TH1/Share/Share.SourceGenerator/Generator/ETGetComponentGenerator.cs
2025-07-17 18:26:28 +08:00

137 lines
3.9 KiB
C#

using System.Collections.Generic;
using System.Linq;
using System.Text;
using ET.Analyzer;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace ET.Generator;
[Generator(LanguageNames.CSharp)]
public class ETGetComponentGenerator : ISourceGenerator
{
public void Initialize(GeneratorInitializationContext context)
{
//context.RegisterForSyntaxNotifications(SyntaxContextReceiver.Create);
}
public void Execute(GeneratorExecutionContext context)
{
if (context.SyntaxContextReceiver is not SyntaxContextReceiver receiver || receiver.ComponentOfDatas.Count==0 )
{
return;
}
foreach (var kv in receiver.ComponentOfDatas)
{
GenerateCSFiles(context, kv.Key,kv.Value);
}
}
private void GenerateCSFiles(GeneratorExecutionContext context,string nameSpace, List<ComponentOfData> componentOfDatas)
{
StringBuilder contenSb = new StringBuilder();
foreach (var componentOfData in componentOfDatas)
{
GenerateGetComponentCode(context, componentOfData, contenSb);
}
string? assemblyName = context.Compilation.AssemblyName?.Replace(".", "_");
string code = $$"""
namespace {{nameSpace}}
{
public static class {{assemblyName}}ETGetComponentExtension
{
{{contenSb}}
}
}
""";
context.AddSource($"ETGetComponentGenerator.{nameSpace}.g.cs", code);
}
private void GenerateGetComponentCode(GeneratorExecutionContext context,ComponentOfData componentOfData,StringBuilder contenSb)
{
string getComponentName = componentOfData.ComponentName;
string parentEntityName = componentOfData.ParentEntityName;
contenSb.AppendLine($$"""
public static {{getComponentName}} Get{{getComponentName}} (this {{parentEntityName}} self)
{
return self.GetComponent<{{getComponentName}}>();
}
""");
}
struct ComponentOfData
{
public string ComponentName;
public string ParentEntityName;
}
class SyntaxContextReceiver: ISyntaxContextReceiver
{
internal static ISyntaxContextReceiver Create()
{
return new SyntaxContextReceiver();
}
public Dictionary<string, List<ComponentOfData>> ComponentOfDatas = new();
public void OnVisitSyntaxNode(GeneratorSyntaxContext context)
{
SyntaxNode node = context.Node;
if (node is not ClassDeclarationSyntax classDeclarationSyntax)
{
return;
}
if (classDeclarationSyntax.AttributeLists.Count==0)
{
return;
}
var classTypeSymbol = context.SemanticModel.GetDeclaredSymbol(classDeclarationSyntax) as INamedTypeSymbol;
if (classTypeSymbol==null)
{
return;
}
// 筛选出含有 ComponentOf标签的
var componentOfAttrData = classTypeSymbol.GetFirstAttribute(Definition.ComponentOfAttribute);
if (componentOfAttrData==null)
{
return;
}
// 忽略无Type参数的
if (componentOfAttrData.ConstructorArguments[0].Value is not INamedTypeSymbol parentEntityTypeSymbol)
{
return;
}
string? nameSpace = classTypeSymbol.GetNameSpace();
if (nameSpace==null)
{
return;
}
if (!ComponentOfDatas.ContainsKey(nameSpace))
{
ComponentOfDatas.Add(nameSpace,new());
}
this.ComponentOfDatas[nameSpace].Add(new ComponentOfData()
{
ComponentName = classTypeSymbol.Name,
ParentEntityName = parentEntityTypeSymbol.Name,
});
}
}
}