EntityMemberDeclarationAnalyzer.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.Immutable;
  4. using System.Linq;
  5. using Microsoft.CodeAnalysis;
  6. using Microsoft.CodeAnalysis.Diagnostics;
  7. namespace ET.Analyzer
  8. {
  9. [DiagnosticAnalyzer(LanguageNames.CSharp)]
  10. public class EntityMemberDeclarationAnalyzer: DiagnosticAnalyzer
  11. {
  12. public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>ImmutableArray.Create(EntityDelegateDeclarationAnalyzerRule.Rule,
  13. EntityFieldDeclarationInEntityAnalyzerRule.Rule, LSEntityFloatMemberAnalyzer.Rule);
  14. public override void Initialize(AnalysisContext context)
  15. {
  16. if (!AnalyzerGlobalSetting.EnableAnalyzer)
  17. {
  18. return;
  19. }
  20. context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
  21. context.EnableConcurrentExecution();
  22. context.RegisterSymbolAction(this.Analyzer, SymbolKind.NamedType);
  23. }
  24. private void Analyzer(SymbolAnalysisContext context)
  25. {
  26. if (!AnalyzerHelper.IsAssemblyNeedAnalyze(context.Compilation.AssemblyName, AnalyzeAssembly.AllModel))
  27. {
  28. return;
  29. }
  30. if (!(context.Symbol is INamedTypeSymbol namedTypeSymbol))
  31. {
  32. return;
  33. }
  34. var baseType = namedTypeSymbol.BaseType?.ToString();
  35. // 筛选出实体类
  36. if (baseType== Definition.EntityType)
  37. {
  38. AnalyzeDelegateMember(context, namedTypeSymbol);
  39. AnalyzeEntityMember(context, namedTypeSymbol);
  40. }else if (baseType == Definition.LSEntityType)
  41. {
  42. AnalyzeDelegateMember(context, namedTypeSymbol);
  43. AnalyzeEntityMember(context, namedTypeSymbol);
  44. AnalyzeFloatMemberInLSEntity(context,namedTypeSymbol);
  45. }
  46. }
  47. /// <summary>
  48. /// 检查委托成员
  49. /// </summary>
  50. private void AnalyzeDelegateMember(SymbolAnalysisContext context,INamedTypeSymbol namedTypeSymbol)
  51. {
  52. foreach (var member in namedTypeSymbol.GetMembers())
  53. {
  54. if (member is IFieldSymbol fieldSymbol && fieldSymbol.Type.BaseType?.ToString()==typeof(MulticastDelegate).FullName)
  55. {
  56. ReportDiagnostic(fieldSymbol,fieldSymbol.Name);
  57. continue;
  58. }
  59. if (member is IPropertySymbol propertySymbol && propertySymbol.Type.BaseType?.ToString()==typeof(MulticastDelegate).FullName)
  60. {
  61. ReportDiagnostic(propertySymbol,propertySymbol.Name);
  62. continue;
  63. }
  64. }
  65. void ReportDiagnostic(ISymbol symbol,string delegateName)
  66. {
  67. foreach (var syntaxReference in symbol.DeclaringSyntaxReferences)
  68. {
  69. var syntax = syntaxReference.GetSyntax();
  70. Diagnostic diagnostic = Diagnostic.Create(EntityDelegateDeclarationAnalyzerRule.Rule, syntax.GetLocation(),namedTypeSymbol.Name,delegateName);
  71. context.ReportDiagnostic(diagnostic);
  72. }
  73. }
  74. }
  75. /// <summary>
  76. /// 检查实体成员
  77. /// </summary>
  78. private void AnalyzeEntityMember(SymbolAnalysisContext context, INamedTypeSymbol namedTypeSymbol)
  79. {
  80. foreach (var member in namedTypeSymbol.GetMembers())
  81. {
  82. if (member is not IFieldSymbol fieldSymbol)
  83. {
  84. continue;
  85. }
  86. // 忽略静态字段 允许单例实体类
  87. if (fieldSymbol.IsStatic)
  88. {
  89. continue;
  90. }
  91. if (fieldSymbol.Type.ToString()is Definition.EntityType or Definition.LSEntityType || fieldSymbol.Type.BaseType?.ToString()is Definition.EntityType or Definition.LSEntityType)
  92. {
  93. var syntaxReference = fieldSymbol.DeclaringSyntaxReferences.FirstOrDefault();
  94. if (syntaxReference==null)
  95. {
  96. continue;
  97. }
  98. Diagnostic diagnostic = Diagnostic.Create(EntityFieldDeclarationInEntityAnalyzerRule.Rule, syntaxReference.GetSyntax().GetLocation(),namedTypeSymbol.Name,fieldSymbol.Name);
  99. context.ReportDiagnostic(diagnostic);
  100. }
  101. }
  102. }
  103. /// <summary>
  104. /// 检查LSEntity中 是否有浮点数字段
  105. /// </summary>
  106. private void AnalyzeFloatMemberInLSEntity(SymbolAnalysisContext context, INamedTypeSymbol namedTypeSymbol)
  107. {
  108. foreach (var member in namedTypeSymbol.GetMembers())
  109. {
  110. INamedTypeSymbol? memberType = null;
  111. if (member is IFieldSymbol fieldSymbol)
  112. {
  113. memberType = fieldSymbol.Type as INamedTypeSymbol;
  114. }
  115. if (member is IPropertySymbol propertySymbol)
  116. {
  117. memberType = propertySymbol.Type as INamedTypeSymbol;
  118. }
  119. if (memberType==null)
  120. {
  121. continue;
  122. }
  123. if (memberType.SpecialType is SpecialType.System_Single or SpecialType.System_Double)
  124. {
  125. var syntaxReference = member.DeclaringSyntaxReferences.FirstOrDefault();
  126. if (syntaxReference==null)
  127. {
  128. continue;
  129. }
  130. Diagnostic diagnostic = Diagnostic.Create(LSEntityFloatMemberAnalyzer.Rule, syntaxReference.GetSyntax().GetLocation(),namedTypeSymbol.Name,member.Name);
  131. context.ReportDiagnostic(diagnostic);
  132. continue;
  133. }
  134. if (memberType.IsGenericType && GenericTypeHasFloatTypeArgs(memberType))
  135. {
  136. var syntaxReference = member.DeclaringSyntaxReferences.FirstOrDefault();
  137. if (syntaxReference==null)
  138. {
  139. continue;
  140. }
  141. Diagnostic diagnostic = Diagnostic.Create(LSEntityFloatMemberAnalyzer.Rule, syntaxReference.GetSyntax().GetLocation(),namedTypeSymbol.Name,member.Name);
  142. context.ReportDiagnostic(diagnostic);
  143. continue;
  144. }
  145. }
  146. }
  147. /// <summary>
  148. /// 泛型类 是否含有浮点数类型参数
  149. /// 对于嵌套泛型参数 递归判断
  150. /// </summary>
  151. private bool GenericTypeHasFloatTypeArgs(INamedTypeSymbol namedTypeSymbol)
  152. {
  153. var typeArgs = namedTypeSymbol.TypeArguments;
  154. foreach (var typeSymbol in typeArgs)
  155. {
  156. if (typeSymbol is not INamedTypeSymbol namedTypeSymbol2)
  157. {
  158. break;
  159. }
  160. if (namedTypeSymbol2.IsGenericType)
  161. {
  162. if (GenericTypeHasFloatTypeArgs(namedTypeSymbol2))
  163. {
  164. return true;
  165. }
  166. }
  167. else
  168. {
  169. if (namedTypeSymbol2.SpecialType is SpecialType.System_Single or SpecialType.System_Double)
  170. {
  171. return true;
  172. }
  173. }
  174. }
  175. return false;
  176. }
  177. }
  178. }