Skip to content

Commit 77c1beb

Browse files
authored
Allow to compile a cs files without a project (#958)
* start * Try * Fix
1 parent 194d98c commit 77c1beb

File tree

1 file changed

+58
-20
lines changed

1 file changed

+58
-20
lines changed

src/Neo.Compiler.CSharp/CompilationEngine.cs

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
using System.IO;
2222
using System.Linq;
2323
using System.Xml.Linq;
24-
using Akka.Util.Internal;
2524
using BigInteger = System.Numerics.BigInteger;
2625

2726
namespace Neo.Compiler
@@ -60,13 +59,44 @@ public List<CompilationContext> Compile(IEnumerable<string> sourceFiles, IEnumer
6059
return CompileProjectContracts(Compilation);
6160
}
6261

63-
public List<CompilationContext> CompileSources(string[] sourceFiles)
62+
public List<CompilationContext> CompileSources(params string[] sourceFiles)
6463
{
65-
List<MetadataReference> references = new(CommonReferences)
66-
{
67-
MetadataReference.CreateFromFile(typeof(scfx.Neo.SmartContract.Framework.SmartContract).Assembly.Location)
68-
};
69-
return Compile(sourceFiles, references);
64+
// Generate a dummy csproj
65+
66+
var version = typeof(scfx.Neo.SmartContract.Framework.SmartContract).Assembly.GetName().Version!.ToString();
67+
var csproj = $@"
68+
<Project Sdk=""Microsoft.NET.Sdk"">
69+
70+
<PropertyGroup>
71+
<TargetFramework>{AppContext.TargetFrameworkName!}</TargetFramework>
72+
<ImplicitUsings>enable</ImplicitUsings>
73+
<Nullable>enable</Nullable>
74+
</PropertyGroup>
75+
76+
<!-- Remove all Compile items from compilation -->
77+
<ItemGroup>
78+
<Compile Remove=""*.cs"" />
79+
</ItemGroup>
80+
81+
<!-- Add specific files for compilation -->
82+
<ItemGroup>
83+
{string.Join(Environment.NewLine, sourceFiles.Select(u => $"<Compile Include=\"{Path.GetFullPath(u)}\" />"))}
84+
</ItemGroup>
85+
86+
<ItemGroup>
87+
<PackageReference Include=""Neo.SmartContract.Framework"" Version=""{version}"" />
88+
</ItemGroup>
89+
90+
</Project>";
91+
92+
// Write and compile
93+
94+
var path = Path.GetTempFileName();
95+
File.WriteAllText(path, csproj);
96+
97+
try { return CompileProject(path); }
98+
catch { throw; }
99+
finally { File.Delete(path); }
70100
}
71101

72102
public List<CompilationContext> CompileProject(string csproj)
@@ -176,26 +206,34 @@ static bool IsDerivedFromSmartContract(INamedTypeSymbol classSymbol, string smar
176206

177207
public Compilation GetCompilation(string csproj)
178208
{
209+
// Restore project
210+
179211
string folder = Path.GetDirectoryName(csproj)!;
180-
string obj = Path.Combine(folder, "obj");
181-
string binSc = Path.Combine(Path.Combine(folder, "bin"), "sc");
182-
HashSet<string> sourceFiles = Directory.EnumerateFiles(folder, "*.cs", SearchOption.AllDirectories)
183-
.Where(p => !p.StartsWith(obj) && !p.StartsWith(binSc))
184-
.GroupBy(Path.GetFileName)
185-
.Select(g => g.First())
186-
.ToHashSet(StringComparer.OrdinalIgnoreCase);
187-
List<MetadataReference> references = new(CommonReferences);
188-
CSharpCompilationOptions compilationOptions = new(OutputKind.DynamicallyLinkedLibrary, deterministic: true, nullableContextOptions: Options.Nullable);
189-
XDocument document = XDocument.Load(csproj);
190-
sourceFiles.UnionWith(document.Root!.Elements("ItemGroup").Elements("Compile").Attributes("Include").Select(p => Path.GetFullPath(p.Value, folder)));
191212
Process.Start(new ProcessStartInfo
192213
{
193214
FileName = "dotnet",
194215
Arguments = $"restore \"{csproj}\"",
195216
WorkingDirectory = folder
196217
})!.WaitForExit();
197-
string assetsPath = Path.Combine(folder, "obj", "project.assets.json");
198-
JObject assets = (JObject)JToken.Parse(File.ReadAllBytes(assetsPath))!;
218+
219+
// Get sources
220+
221+
XDocument document = XDocument.Load(csproj);
222+
var remove = document.Root!.Elements("ItemGroup").Elements("Compile").Attributes("Remove").Select(p => p.Value).ToArray();
223+
var obj = Path.Combine(folder, "obj");
224+
var binSc = Path.Combine(Path.Combine(folder, "bin"), "sc");
225+
var sourceFiles =
226+
remove.Contains("*.cs") ? new HashSet<string>(StringComparer.OrdinalIgnoreCase) :
227+
Directory.EnumerateFiles(folder, "*.cs", SearchOption.AllDirectories)
228+
.Where(p => !p.StartsWith(obj) && !p.StartsWith(binSc))
229+
.GroupBy(Path.GetFileName)
230+
.Select(g => g.First())
231+
.ToHashSet(StringComparer.OrdinalIgnoreCase);
232+
sourceFiles.UnionWith(document.Root!.Elements("ItemGroup").Elements("Compile").Attributes("Include").Select(p => Path.GetFullPath(p.Value, folder)));
233+
var assetsPath = Path.Combine(folder, "obj", "project.assets.json");
234+
var assets = (JObject)JToken.Parse(File.ReadAllBytes(assetsPath))!;
235+
List<MetadataReference> references = new(CommonReferences);
236+
CSharpCompilationOptions compilationOptions = new(OutputKind.DynamicallyLinkedLibrary, deterministic: true, nullableContextOptions: Options.Nullable);
199237
foreach (var (name, package) in ((JObject)assets["targets"]![0]!).Properties)
200238
{
201239
MetadataReference? reference = GetReference(name, (JObject)package!, assets, folder, Options, compilationOptions);

0 commit comments

Comments
 (0)