169 lines
6.2 KiB
C#
169 lines
6.2 KiB
C#
using Microsoft.CodeAnalysis;
|
|
using Microsoft.CodeAnalysis.CSharp;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
using ReCodeIt.Models;
|
|
using ReCodeIt.ReMapper;
|
|
using ReCodeIt.Utils;
|
|
using System.Diagnostics;
|
|
|
|
namespace ReCodeIt.CrossCompiler;
|
|
|
|
public class ReCodeItCrossCompiler
|
|
{
|
|
public ReCodeItCrossCompiler()
|
|
{
|
|
Remapper = new(this);
|
|
}
|
|
|
|
private ReCodeItRemapper Remapper { get; }
|
|
public CrossCompilerSettings Settings => DataProvider.Settings.CrossCompiler;
|
|
|
|
public CrossCompilerProjectModel ActiveProject => ProjectManager.ActiveProject;
|
|
|
|
private int _identifiersChanged = 0;
|
|
|
|
public void StartRemap()
|
|
{
|
|
ActiveProject.ChangedTypes.Clear();
|
|
|
|
if (ActiveProject == null)
|
|
{
|
|
Logger.Log("ERROR: No Cross Compiler Project is loaded, create or load one first.", ConsoleColor.Red);
|
|
return;
|
|
}
|
|
|
|
if (ActiveProject.ReCodeItProjectPath == string.Empty)
|
|
{
|
|
Logger.Log("ERROR: No ReCodeIt Project directory is set. (Project Creation Failed)", ConsoleColor.Red);
|
|
return;
|
|
}
|
|
|
|
Remapper.InitializeRemap(
|
|
ActiveProject.RemapModels,
|
|
ActiveProject.OriginalAssemblyPath,
|
|
ActiveProject.RemappedAssemblyPath,
|
|
true);
|
|
|
|
Logger.Log("-----------------------------------------------", ConsoleColor.Green);
|
|
Logger.Log($"Generated Cross Mapped DLL for project {ActiveProject.SolutionName}", ConsoleColor.Green);
|
|
Logger.Log($"Built to: {Path.Combine(ActiveProject.RemappedAssemblyPath, ActiveProject.OriginalAssemblyDllName)}", ConsoleColor.Green);
|
|
Logger.Log($"Changed {ActiveProject.ChangedTypes.Count} types", ConsoleColor.Green);
|
|
Logger.Log($"Original assembly path: {ActiveProject.OriginalAssemblyPath}", ConsoleColor.Green);
|
|
Logger.Log($"Original assembly hash: {ActiveProject.OriginalAssemblyHash}", ConsoleColor.Green);
|
|
Logger.Log($"Original patched assembly path: {ActiveProject.RemappedAssemblyPath}", ConsoleColor.Green);
|
|
//Logger.Log($"Original patched assembly hash: {ActiveProject.RemappedAssemblyHash}", ConsoleColor.Green);
|
|
Logger.Log("-----------------------------------------------", ConsoleColor.Green);
|
|
}
|
|
|
|
public void StartCrossCompile()
|
|
{
|
|
_identifiersChanged = 0;
|
|
|
|
AnalyzeSourceFiles();
|
|
|
|
StartBuild();
|
|
MoveResult();
|
|
}
|
|
|
|
private void AnalyzeSourceFiles()
|
|
{
|
|
foreach (var file in ProjectManager.AllProjectSourceFiles)
|
|
{
|
|
AnalyzeSourcefile(file);
|
|
}
|
|
|
|
var fileName = Path.GetFileName(ActiveProject.OriginalAssemblyPath);
|
|
var outPath = Path.Combine(ActiveProject.RemappedAssemblyPath, fileName);
|
|
|
|
Logger.Log($"Placing original reference into cloned build directory", ConsoleColor.Green);
|
|
File.Copy(ActiveProject.OriginalAssemblyPath, outPath, true);
|
|
}
|
|
|
|
private void AnalyzeSourcefile(string file)
|
|
{
|
|
var source = File.ReadAllText(file);
|
|
var syntaxTree = CSharpSyntaxTree.ParseText(source);
|
|
var root = syntaxTree.GetCompilationUnitRoot();
|
|
|
|
// Get the things we want to change
|
|
var identifiers = root.DescendantNodes()
|
|
.OfType<IdentifierNameSyntax>()
|
|
.Where(id => ActiveProject.ChangedTypes.ContainsKey(id.Identifier.Text));
|
|
|
|
if (!identifiers.Any()) { return; }
|
|
|
|
_identifiersChanged += identifiers.Count();
|
|
|
|
Logger.Log($"changing {_identifiersChanged} identifiers in file {Path.GetFileName(file)}", ConsoleColor.Green);
|
|
|
|
// Do Black Voodoo Magic
|
|
var newRoot = root.ReplaceNodes(identifiers, (oldNode, newNode) =>
|
|
SyntaxFactory.IdentifierName(ActiveProject.ChangedTypes[oldNode.Identifier.Text])
|
|
.WithLeadingTrivia(oldNode.GetLeadingTrivia())
|
|
.WithTrailingTrivia(oldNode.GetTrailingTrivia()));
|
|
|
|
File.WriteAllText(file, newRoot.ToFullString());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Starts the build process for the active project.
|
|
/// </summary>
|
|
private void StartBuild()
|
|
{
|
|
var arguements = $"build {ActiveProject.VisualStudioClonedSolutionPath} " +
|
|
$"/p:Configuration=Debug " +
|
|
$"/p:Platform=\"Any CPU\"";
|
|
|
|
var path = ActiveProject.VisualStudioClonedSolutionDirectory;
|
|
|
|
// clean the project first
|
|
ExecuteDotnetCommand("clean", path);
|
|
|
|
// Restore packages
|
|
ExecuteDotnetCommand("restore", path);
|
|
|
|
// Then build the project
|
|
ExecuteDotnetCommand(arguements, path);
|
|
}
|
|
|
|
private static void ExecuteDotnetCommand(string arguments, string workingDirectory)
|
|
{
|
|
ProcessStartInfo startInfo = new ProcessStartInfo
|
|
{
|
|
FileName = "dotnet",
|
|
Arguments = arguments,
|
|
WorkingDirectory = workingDirectory,
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true,
|
|
UseShellExecute = false,
|
|
CreateNoWindow = true
|
|
};
|
|
|
|
using (Process process = new Process())
|
|
{
|
|
process.StartInfo = startInfo;
|
|
|
|
process.OutputDataReceived += (sender, e) => Logger.Log(e.Data);
|
|
|
|
process.Start();
|
|
process.BeginOutputReadLine();
|
|
process.BeginErrorReadLine();
|
|
process.WaitForExit();
|
|
|
|
int exitCode = process.ExitCode;
|
|
Logger.Log($"dotnet {arguments} exited with code {exitCode}");
|
|
}
|
|
}
|
|
|
|
private void MoveResult()
|
|
{
|
|
Logger.Log("-----------------------------------------------", ConsoleColor.Green);
|
|
Logger.Log($"Successfully Cross Compiled Project {ActiveProject.SolutionName}", ConsoleColor.Green);
|
|
Logger.Log($"Reversed {_identifiersChanged} Remaps", ConsoleColor.Green);
|
|
Logger.Log($"Original assembly path: {ActiveProject.OriginalAssemblyPath}", ConsoleColor.Green);
|
|
Logger.Log($"Original assembly hash: {ActiveProject.OriginalAssemblyHash}", ConsoleColor.Green);
|
|
Logger.Log($"Final build directory: {ActiveProject.BuildDirectory}", ConsoleColor.Green);
|
|
//Logger.Log($"Original patched assembly hash: {ActiveProject.RemappedAssemblyHash}", ConsoleColor.Green);
|
|
Logger.Log("-----------------------------------------------", ConsoleColor.Green);
|
|
}
|
|
} |