ETGetComponentGenerator.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using System.Text;
  4. using ET.Analyzer;
  5. using Microsoft.CodeAnalysis;
  6. using Microsoft.CodeAnalysis.CSharp.Syntax;
  7. namespace ET.Generator;
  8. [Generator(LanguageNames.CSharp)]
  9. public class ETGetComponentGenerator : ISourceGenerator
  10. {
  11. public void Initialize(GeneratorInitializationContext context)
  12. {
  13. //context.RegisterForSyntaxNotifications(SyntaxContextReceiver.Create);
  14. }
  15. public void Execute(GeneratorExecutionContext context)
  16. {
  17. if (context.SyntaxContextReceiver is not SyntaxContextReceiver receiver || receiver.ComponentOfDatas.Count==0 )
  18. {
  19. return;
  20. }
  21. foreach (var kv in receiver.ComponentOfDatas)
  22. {
  23. GenerateCSFiles(context, kv.Key,kv.Value);
  24. }
  25. }
  26. private void GenerateCSFiles(GeneratorExecutionContext context,string nameSpace, List<ComponentOfData> componentOfDatas)
  27. {
  28. StringBuilder contenSb = new StringBuilder();
  29. foreach (var componentOfData in componentOfDatas)
  30. {
  31. GenerateGetComponentCode(context, componentOfData, contenSb);
  32. }
  33. string? assemblyName = context.Compilation.AssemblyName?.Replace(".", "_");
  34. string code = $$"""
  35. namespace {{nameSpace}}
  36. {
  37. public static class {{assemblyName}}ETGetComponentExtension
  38. {
  39. {{contenSb}}
  40. }
  41. }
  42. """;
  43. context.AddSource($"ETGetComponentGenerator.{nameSpace}.g.cs", code);
  44. }
  45. private void GenerateGetComponentCode(GeneratorExecutionContext context,ComponentOfData componentOfData,StringBuilder contenSb)
  46. {
  47. string getComponentName = componentOfData.ComponentName;
  48. string parentEntityName = componentOfData.ParentEntityName;
  49. contenSb.AppendLine($$"""
  50. public static {{getComponentName}} Get{{getComponentName}} (this {{parentEntityName}} self)
  51. {
  52. return self.GetComponent<{{getComponentName}}>();
  53. }
  54. """);
  55. }
  56. struct ComponentOfData
  57. {
  58. public string ComponentName;
  59. public string ParentEntityName;
  60. }
  61. class SyntaxContextReceiver: ISyntaxContextReceiver
  62. {
  63. internal static ISyntaxContextReceiver Create()
  64. {
  65. return new SyntaxContextReceiver();
  66. }
  67. public Dictionary<string, List<ComponentOfData>> ComponentOfDatas = new();
  68. public void OnVisitSyntaxNode(GeneratorSyntaxContext context)
  69. {
  70. SyntaxNode node = context.Node;
  71. if (node is not ClassDeclarationSyntax classDeclarationSyntax)
  72. {
  73. return;
  74. }
  75. if (classDeclarationSyntax.AttributeLists.Count==0)
  76. {
  77. return;
  78. }
  79. var classTypeSymbol = context.SemanticModel.GetDeclaredSymbol(classDeclarationSyntax) as INamedTypeSymbol;
  80. if (classTypeSymbol==null)
  81. {
  82. return;
  83. }
  84. // 筛选出含有 ComponentOf标签的
  85. var componentOfAttrData = classTypeSymbol.GetFirstAttribute(Definition.ComponentOfAttribute);
  86. if (componentOfAttrData==null)
  87. {
  88. return;
  89. }
  90. // 忽略无Type参数的
  91. if (componentOfAttrData.ConstructorArguments[0].Value is not INamedTypeSymbol parentEntityTypeSymbol)
  92. {
  93. return;
  94. }
  95. string? nameSpace = classTypeSymbol.GetNameSpace();
  96. if (nameSpace==null)
  97. {
  98. return;
  99. }
  100. if (!ComponentOfDatas.ContainsKey(nameSpace))
  101. {
  102. ComponentOfDatas.Add(nameSpace,new());
  103. }
  104. this.ComponentOfDatas[nameSpace].Add(new ComponentOfData()
  105. {
  106. ComponentName = classTypeSymbol.Name,
  107. ParentEntityName = parentEntityTypeSymbol.Name,
  108. });
  109. }
  110. }
  111. }