diff --git a/src/Neo.Compiler.CSharp/CompilationEngine.cs b/src/Neo.Compiler.CSharp/CompilationEngine.cs index 222f91b40..9309029a5 100644 --- a/src/Neo.Compiler.CSharp/CompilationEngine.cs +++ b/src/Neo.Compiler.CSharp/CompilationEngine.cs @@ -21,7 +21,6 @@ using System.IO; using System.Linq; using System.Xml.Linq; -using Akka.Util.Internal; using BigInteger = System.Numerics.BigInteger; namespace Neo.Compiler @@ -60,13 +59,44 @@ public List Compile(IEnumerable sourceFiles, IEnumer return CompileProjectContracts(Compilation); } - public List CompileSources(string[] sourceFiles) + public List CompileSources(params string[] sourceFiles) { - List references = new(CommonReferences) - { - MetadataReference.CreateFromFile(typeof(scfx.Neo.SmartContract.Framework.SmartContract).Assembly.Location) - }; - return Compile(sourceFiles, references); + // Generate a dummy csproj + + var version = typeof(scfx.Neo.SmartContract.Framework.SmartContract).Assembly.GetName().Version!.ToString(); + var csproj = $@" + + + + {AppContext.TargetFrameworkName!} + enable + enable + + + + + + + + + + {string.Join(Environment.NewLine, sourceFiles.Select(u => $""))} + + + + + + +"; + + // Write and compile + + var path = Path.GetTempFileName(); + File.WriteAllText(path, csproj); + + try { return CompileProject(path); } + catch { throw; } + finally { File.Delete(path); } } public List CompileProject(string csproj) @@ -176,26 +206,34 @@ static bool IsDerivedFromSmartContract(INamedTypeSymbol classSymbol, string smar public Compilation GetCompilation(string csproj) { + // Restore project + string folder = Path.GetDirectoryName(csproj)!; - string obj = Path.Combine(folder, "obj"); - string binSc = Path.Combine(Path.Combine(folder, "bin"), "sc"); - HashSet sourceFiles = Directory.EnumerateFiles(folder, "*.cs", SearchOption.AllDirectories) - .Where(p => !p.StartsWith(obj) && !p.StartsWith(binSc)) - .GroupBy(Path.GetFileName) - .Select(g => g.First()) - .ToHashSet(StringComparer.OrdinalIgnoreCase); - List references = new(CommonReferences); - CSharpCompilationOptions compilationOptions = new(OutputKind.DynamicallyLinkedLibrary, deterministic: true, nullableContextOptions: Options.Nullable); - XDocument document = XDocument.Load(csproj); - sourceFiles.UnionWith(document.Root!.Elements("ItemGroup").Elements("Compile").Attributes("Include").Select(p => Path.GetFullPath(p.Value, folder))); Process.Start(new ProcessStartInfo { FileName = "dotnet", Arguments = $"restore \"{csproj}\"", WorkingDirectory = folder })!.WaitForExit(); - string assetsPath = Path.Combine(folder, "obj", "project.assets.json"); - JObject assets = (JObject)JToken.Parse(File.ReadAllBytes(assetsPath))!; + + // Get sources + + XDocument document = XDocument.Load(csproj); + var remove = document.Root!.Elements("ItemGroup").Elements("Compile").Attributes("Remove").Select(p => p.Value).ToArray(); + var obj = Path.Combine(folder, "obj"); + var binSc = Path.Combine(Path.Combine(folder, "bin"), "sc"); + var sourceFiles = + remove.Contains("*.cs") ? new HashSet(StringComparer.OrdinalIgnoreCase) : + Directory.EnumerateFiles(folder, "*.cs", SearchOption.AllDirectories) + .Where(p => !p.StartsWith(obj) && !p.StartsWith(binSc)) + .GroupBy(Path.GetFileName) + .Select(g => g.First()) + .ToHashSet(StringComparer.OrdinalIgnoreCase); + sourceFiles.UnionWith(document.Root!.Elements("ItemGroup").Elements("Compile").Attributes("Include").Select(p => Path.GetFullPath(p.Value, folder))); + var assetsPath = Path.Combine(folder, "obj", "project.assets.json"); + var assets = (JObject)JToken.Parse(File.ReadAllBytes(assetsPath))!; + List references = new(CommonReferences); + CSharpCompilationOptions compilationOptions = new(OutputKind.DynamicallyLinkedLibrary, deterministic: true, nullableContextOptions: Options.Nullable); foreach (var (name, package) in ((JObject)assets["targets"]![0]!).Properties) { MetadataReference? reference = GetReference(name, (JObject)package!, assets, folder, Options, compilationOptions);