Created
August 26, 2020 00:46
-
-
Save TessenR/79782f3bf0319abecc6358cfd6991459 to your computer and use it in GitHub Desktop.
Iterative source generator reusing types from previous iterations
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 System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using Microsoft.CodeAnalysis; | |
using Microsoft.CodeAnalysis.CSharp; | |
using Microsoft.CodeAnalysis.CSharp.Syntax; | |
using Microsoft.CodeAnalysis.Text; | |
[Generator] | |
public class Generator : ISourceGenerator | |
{ | |
private const int myEnoughIsEnough = 10; | |
private const string TypeNamePrefix = "Generated"; | |
public void Initialize(InitializationContext context) | |
{ | |
} | |
public virtual void Execute(SourceGeneratorContext context) | |
{ | |
var compilation = context.Compilation; | |
CSharpParseOptions options = (CSharpParseOptions) ((CSharpCompilation)context.Compilation).SyntaxTrees[0].Options; | |
for (var x = 0; x < myEnoughIsEnough; x++) | |
{ | |
var allGeneratedTypes = new List<INamedTypeSymbol>(); | |
foreach (var syntaxTree in compilation.SyntaxTrees) | |
{ | |
var model = compilation.GetSemanticModel(syntaxTree); | |
var typeSymbols = syntaxTree.GetRoot() | |
.DescendantNodesAndSelf() | |
.OfType<ClassDeclarationSyntax>() | |
.Select(x => model.GetDeclaredSymbol(x)) | |
.Where(x=> x.Name.StartsWith(TypeNamePrefix)); | |
allGeneratedTypes.AddRange(typeSymbols); | |
} | |
var previousType = allGeneratedTypes.OrderByDescending(x => x.Name).FirstOrDefault(); | |
var source = GetSource(previousType, allGeneratedTypes, x); | |
context.AddSource(TypeNamePrefix+x, SourceText.From(source, Encoding.UTF8)); | |
compilation = compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(source, options)); | |
} | |
} | |
public static string GetSource(INamedTypeSymbol? previousType, IReadOnlyList<INamedTypeSymbol> symbols, int x) | |
=> $@" | |
using System; | |
public static class {TypeNamePrefix}{x} | |
{{ | |
public static void Print() | |
{{ | |
Console.WriteLine(""Hello from type number {x}""); | |
Console.WriteLine(""Following types are already added: { string.Join(";", symbols.Select(x=>x.Name)) }""); | |
{(previousType != null ? $"{previousType.Name}.Print();" : "Console.WriteLine(\"Root\");")} | |
}} | |
}}"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment