Created
December 12, 2020 00:10
-
-
Save chsienki/334ec398079988fab97bfd7029cf6736 to your computer and use it in GitHub Desktop.
Debuggable runtime generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<OutputType>Exe</OutputType> | |
<TargetFramework>netcoreapp3.1</TargetFramework> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="Microsoft.CodeAnalysis" Version="3.8.0" /> | |
</ItemGroup> | |
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.CodeAnalysis; | |
using Microsoft.CodeAnalysis.CSharp; | |
using Microsoft.CodeAnalysis.Text; | |
using System; | |
using System.IO; | |
using System.Runtime.InteropServices; | |
using System.Text; | |
namespace ConsoleApp18 | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var source = @" | |
public static class Program { | |
public static void Main(string[] args) { | |
GeneratedClass.DoThing(); | |
} | |
} | |
"; | |
var generatorSource = @" | |
public class GeneratedClass { | |
public static void DoThing(){ | |
System.Console.WriteLine(""thing""); | |
} | |
} | |
"; | |
var corLib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location); | |
var console = MetadataReference.CreateFromFile(typeof(Console).Assembly.Location); | |
var runtime = MetadataReference.CreateFromFile(Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "System.Runtime.dll")); | |
SyntaxTree programTree = CSharpSyntaxTree.ParseText(SourceText.From(source, Encoding.UTF8), new CSharpParseOptions(LanguageVersion.Latest), "program.cs"); | |
CSharpCompilation compilation = CSharpCompilation.Create(Guid.NewGuid().ToString(), new[] { programTree }, new[] { corLib, console, runtime }, new CSharpCompilationOptions(OutputKind.ConsoleApplication)); | |
SingleFileTestGenerator testGenerator = new SingleFileTestGenerator(generatorSource); | |
GeneratorDriver driver = CSharpGeneratorDriver.Create(new[] { testGenerator }); | |
driver = driver.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out _); | |
var diagnostics = outputCompilation.GetDiagnostics(); | |
var generatorTree = driver.GetRunResult().GeneratedTrees[0]; | |
EmbeddedText et = EmbeddedText.FromSource(generatorTree.FilePath, generatorTree.GetText()); | |
EmbeddedText et2 = EmbeddedText.FromSource(programTree.FilePath, programTree.GetText()); | |
var assemblyStream = new MemoryStream(); | |
var symbolsStream = new MemoryStream(); | |
var result = outputCompilation.Emit(assemblyStream, symbolsStream, embeddedTexts: new[] { et, et2 }); | |
var assemblyBytes = assemblyStream.GetBuffer(); | |
var symbolsBytes = symbolsStream.GetBuffer(); | |
var asm = System.Reflection.Assembly.Load(assemblyBytes, symbolsBytes); | |
asm.EntryPoint.Invoke(null, new object[] { new string[0] }); | |
} | |
} | |
internal class SingleFileTestGenerator : ISourceGenerator | |
{ | |
private readonly string _content; | |
private readonly string _hintName; | |
public SingleFileTestGenerator(string content, string hintName = "generatedFile") | |
{ | |
_content = content; | |
_hintName = hintName; | |
} | |
public void Execute(GeneratorExecutionContext context) | |
{ | |
context.AddSource(this._hintName, SourceText.From(_content, Encoding.UTF8)); | |
} | |
public void Initialize(GeneratorInitializationContext context) | |
{ | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment