Skip to content

Instantly share code, notes, and snippets.

@TessenR
Created August 26, 2020 00:46
Show Gist options
  • Save TessenR/79782f3bf0319abecc6358cfd6991459 to your computer and use it in GitHub Desktop.
Save TessenR/79782f3bf0319abecc6358cfd6991459 to your computer and use it in GitHub Desktop.
Iterative source generator reusing types from previous iterations
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