HotfixProjectFieldDeclarationAnalyzer.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. using System.Collections.Immutable;
  2. using Microsoft.CodeAnalysis;
  3. using Microsoft.CodeAnalysis.CSharp;
  4. using Microsoft.CodeAnalysis.CSharp.Syntax;
  5. using Microsoft.CodeAnalysis.Diagnostics;
  6. namespace ET.Analyzer
  7. {
  8. [DiagnosticAnalyzer(LanguageNames.CSharp)]
  9. public class HotfixProjectFieldDeclarationAnalyzer: DiagnosticAnalyzer
  10. {
  11. private const string Title = "实体字段访问错误";
  12. private const string MessageFormat = "Hotfix程序集中 不允许声明非Const字段 字段: {0}";
  13. private const string Description = "请使用实体类属性或方法访问其他实体字段.";
  14. private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticIds.HotfixProjectFieldDeclarationAnalyzerRuleId,
  15. Title,
  16. MessageFormat,
  17. DiagnosticCategories.Hotfix,
  18. DiagnosticSeverity.Error, true, Description);
  19. public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
  20. public override void Initialize(AnalysisContext context)
  21. {
  22. if (!AnalyzerGlobalSetting.EnableAnalyzer)
  23. {
  24. return;
  25. }
  26. context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
  27. context.EnableConcurrentExecution();
  28. context.RegisterCompilationStartAction((analysisContext =>
  29. {
  30. if (analysisContext.Compilation.AssemblyName==AnalyzeAssembly.UnityCodes)
  31. {
  32. analysisContext.RegisterSemanticModelAction((modelAnalysisContext =>
  33. {
  34. if (AnalyzerHelper.IsSemanticModelNeedAnalyze(modelAnalysisContext.SemanticModel,UnityCodesPath.AllHotfix))
  35. {
  36. AnalyzeSemanticModel(modelAnalysisContext);
  37. }
  38. } ));
  39. return;
  40. }
  41. if (AnalyzerHelper.IsAssemblyNeedAnalyze(analysisContext.Compilation.AssemblyName,AnalyzeAssembly.AllHotfix))
  42. {
  43. analysisContext.RegisterSemanticModelAction((this.AnalyzeSemanticModel));
  44. }
  45. } ));
  46. }
  47. private void AnalyzeSemanticModel(SemanticModelAnalysisContext analysisContext)
  48. {
  49. foreach (var classDeclarationSyntax in analysisContext.SemanticModel.SyntaxTree.GetRoot().DescendantNodes<ClassDeclarationSyntax>())
  50. {
  51. var classTypeSymbol = analysisContext.SemanticModel.GetDeclaredSymbol(classDeclarationSyntax);
  52. if (classTypeSymbol!=null)
  53. {
  54. Analyzer(analysisContext, classTypeSymbol);
  55. }
  56. }
  57. }
  58. private void Analyzer(SemanticModelAnalysisContext context, INamedTypeSymbol namedTypeSymbol)
  59. {
  60. foreach (ISymbol? memberSymbol in namedTypeSymbol.GetMembers())
  61. {
  62. // 筛选出属性成员
  63. if (memberSymbol is IPropertySymbol propertySymbol)
  64. {
  65. ReportDiagnostic(propertySymbol);
  66. continue;
  67. }
  68. // 筛选出非Const字段成员
  69. if (memberSymbol is IFieldSymbol fieldSymbol && !fieldSymbol.IsConst)
  70. {
  71. ReportDiagnostic(fieldSymbol);
  72. }
  73. }
  74. void ReportDiagnostic(ISymbol symbol)
  75. {
  76. foreach (SyntaxReference? declaringSyntaxReference in symbol.DeclaringSyntaxReferences)
  77. {
  78. Diagnostic diagnostic = Diagnostic.Create(Rule, declaringSyntaxReference.GetSyntax()?.GetLocation(), symbol.Name);
  79. context.ReportDiagnostic(diagnostic);
  80. }
  81. }
  82. }
  83. }
  84. }