Rewrite to incremental generator

This commit is contained in:
2025-06-28 22:23:50 +03:00
parent acb5a2cf58
commit 999ee66f9c
2 changed files with 61 additions and 44 deletions
+1 -1
View File
@@ -17,7 +17,7 @@
<RepositoryUrl>https://github.com/YaslePoy/mROA</RepositoryUrl> <RepositoryUrl>https://github.com/YaslePoy/mROA</RepositoryUrl>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Version>2.0.4</Version> <Version>2.0.5</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
+60 -43
View File
@@ -22,7 +22,7 @@ namespace mROA.Codegen
/// performance overhead. /// performance overhead.
/// </summary> /// </summary>
[Generator] [Generator]
public class mROAGenerator : ISourceGenerator public class mROAGenerator : IIncrementalGenerator
{ {
private static readonly Predicate<IParameterSymbol> ParameterFilter = private static readonly Predicate<IParameterSymbol> ParameterFilter =
i => i.Type.Name is "CancellationToken" or "RequestContext"; i => i.Type.Name is "CancellationToken" or "RequestContext";
@@ -56,38 +56,38 @@ namespace mROA.Codegen
} }
} }
public void Execute(GeneratorExecutionContext context) // public void Execute(GeneratorExecutionContext context)
{ // {
// return; // // return;
try // try
{ // {
var trees = context.Compilation.SyntaxTrees; // var trees = context.Compilation.SyntaxTrees;
//
// var interfaces = new List<InterfaceDeclarationSyntax>();
// foreach (var tree in trees)
// {
// var node = (CompilationUnitSyntax)tree.GetRoot();
//
// foreach (var member in node.Members)
// if (member is InterfaceDeclarationSyntax ids)
// interfaces.Add(ids);
// else if (member is NamespaceDeclarationSyntax nds)
// foreach (var inside in nds.Members)
//
// if (inside is InterfaceDeclarationSyntax ids2)
// if (ContainsSoiAttribute(ids2.AttributeLists, context, ids2))
// interfaces.Add(ids2);
// }
//
// GenerateCode(context, context.Compilation, interfaces.ToImmutableArray());
// }
// catch (Exception)
// {
// Console.WriteLine("ERROR: Unable to load method repository");
// }
// }
var interfaces = new List<InterfaceDeclarationSyntax>(); private void GenerateCode(SourceProductionContext context, Compilation compilation,
foreach (var tree in trees)
{
var node = (CompilationUnitSyntax)tree.GetRoot();
foreach (var member in node.Members)
if (member is InterfaceDeclarationSyntax ids)
interfaces.Add(ids);
else if (member is NamespaceDeclarationSyntax nds)
foreach (var inside in nds.Members)
if (inside is InterfaceDeclarationSyntax ids2)
if (ContainsSoiAttribute(ids2.AttributeLists, context, ids2))
interfaces.Add(ids2);
}
GenerateCode(context, context.Compilation, interfaces.ToImmutableArray());
}
catch (Exception)
{
Console.WriteLine("ERROR: Unable to load method repository");
}
}
private void GenerateCode(GeneratorExecutionContext context, Compilation compilation,
ImmutableArray<InterfaceDeclarationSyntax> classes) ImmutableArray<InterfaceDeclarationSyntax> classes)
{ {
var totalMethods = new List<IMethodSymbol>(); var totalMethods = new List<IMethodSymbol>();
@@ -196,7 +196,7 @@ namespace mROA.Codegen
} }
private void GenerateEventImplementation(INamedTypeSymbol classSymbol, List<string> invokers, private void GenerateEventImplementation(INamedTypeSymbol classSymbol, List<string> invokers,
GeneratorExecutionContext context) SourceProductionContext context)
{ {
var events = classSymbol.AllInterfaces.Add(classSymbol).SelectMany(i => i.GetMembers()) var events = classSymbol.AllInterfaces.Add(classSymbol).SelectMany(i => i.GetMembers())
.OfType<IEventSymbol>().ToList(); .OfType<IEventSymbol>().ToList();
@@ -610,24 +610,26 @@ namespace mROA.Codegen
return generics.Length == 0 ? "void" : generics[0].ToUnityString(); return generics.Length == 0 ? "void" : generics[0].ToUnityString();
} }
private bool ContainsSoiAttribute(SyntaxList<AttributeListSyntax> attributes, GeneratorExecutionContext context, private static (InterfaceDeclarationSyntax node, bool usefull) ContainsSoiAttribute(
InterfaceDeclarationSyntax interfaceDeclarationSyntax) GeneratorSyntaxContext context)
{ {
foreach (var attributeSyntax in var ids = (InterfaceDeclarationSyntax)context.Node;
attributes.SelectMany(attributeListSyntax => attributeListSyntax.Attributes))
// Go through all attributes of the class.
foreach (AttributeListSyntax attributeListSyntax in ids.AttributeLists)
foreach (AttributeSyntax attributeSyntax in attributeListSyntax.Attributes)
{ {
if (context.Compilation.GetSemanticModel(interfaceDeclarationSyntax.SyntaxTree) if (context.SemanticModel.GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol)
.GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol)
continue; // if we can't get the symbol, ignore it continue; // if we can't get the symbol, ignore it
var attributeName = attributeSymbol.ContainingType.ToDisplayString(); string attributeName = attributeSymbol.ContainingType.ToDisplayString();
// Check the full name of the [Report] attribute. // Check the full name of the [Report] attribute.
if (attributeName == "mROA.Implementation.Attributes.SharedObjectInterfaceAttribute") if (attributeName == $"mROA.Implementation.Attributes.SharedObjectInterfaceAttribute")
return true; return (ids,true);
} }
return false; return (ids ,false);
} }
private List<IMethodSymbol> CollectMembers(INamedTypeSymbol type) private List<IMethodSymbol> CollectMembers(INamedTypeSymbol type)
@@ -638,6 +640,21 @@ namespace mROA.Codegen
methods.RemoveAll(m => m.Name == "Dispose"); methods.RemoveAll(m => m.Name == "Dispose");
return methods.OrderBy(i => i.Name).ToList(); return methods.OrderBy(i => i.Name).ToList();
} }
public void Initialize(IncrementalGeneratorInitializationContext context)
{
_methodRepoTemplate = TemplateReader.FromEmbeddedResource("MethodRepo.cstmpl");
_methodInvokerOriginal =
((InnerTemplateSection)_methodRepoTemplate["syncInvoker"]!).InnerTemplate;
_classTemplateOriginal = TemplateReader.FromEmbeddedResource("Proxy.cstmpl");
_binderTemplate = TemplateReader.FromEmbeddedResource("RemoteTypeBinder.cstmpl");
_interfaceTemplateOriginal = TemplateReader.FromEmbeddedResource("PartialInterface.cstmpl");
var syntaxes = context.SyntaxProvider.CreateSyntaxProvider(
(static (node, _) => node is InterfaceDeclarationSyntax), static (node, _) => ContainsSoiAttribute(node)).Where(i => i.usefull).Select((node, _) => node.node);
context.RegisterSourceOutput(context.CompilationProvider.Combine(syntaxes.Collect()), (productionContext, pair) => GenerateCode(productionContext, pair.Left, pair.Right));
}
} }
public static class CodegenExtentions public static class CodegenExtentions