ClassDeclarationInHotfixAnalyzer.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. using System.Collections.Immutable;
  2. using System.Linq;
  3. using Microsoft.CodeAnalysis;
  4. using Microsoft.CodeAnalysis.CSharp;
  5. using Microsoft.CodeAnalysis.CSharp.Syntax;
  6. using Microsoft.CodeAnalysis.Diagnostics;
  7. namespace ET.Analyzer
  8. {
  9. [DiagnosticAnalyzer(LanguageNames.CSharp)]
  10. public class ClassDeclarationInHotfixAnalyzer: DiagnosticAnalyzer
  11. {
  12. private const string Title = "Hotfix程序集中 只能声明含有BaseAttribute子类特性的类或静态类";
  13. private const string MessageFormat = "Hotfix程序集中 只能声明含有BaseAttribute子类特性的类或静态类 类: {0}";
  14. private const string Description = "Hotfix程序集中 只能声明含有BaseAttribute子类特性的类或静态类.";
  15. private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticIds.ClassDeclarationInHotfixAnalyzerRuleId,
  16. Title,
  17. MessageFormat,
  18. DiagnosticCategories.Hotfix,
  19. DiagnosticSeverity.Error, true, Description);
  20. public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
  21. public override void Initialize(AnalysisContext context)
  22. {
  23. if (!AnalyzerGlobalSetting.EnableAnalyzer)
  24. {
  25. return;
  26. }
  27. context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
  28. context.EnableConcurrentExecution();
  29. context.RegisterCompilationStartAction((analysisContext =>
  30. {
  31. if (analysisContext.Compilation.AssemblyName==AnalyzeAssembly.UnityCodes)
  32. {
  33. analysisContext.RegisterSemanticModelAction((modelAnalysisContext =>
  34. {
  35. if (AnalyzerHelper.IsSemanticModelNeedAnalyze(modelAnalysisContext.SemanticModel,UnityCodesPath.AllHotfix))
  36. {
  37. AnalyzeSemanticModel(modelAnalysisContext);
  38. }
  39. } ));
  40. return;
  41. }
  42. if (AnalyzerHelper.IsAssemblyNeedAnalyze(analysisContext.Compilation.AssemblyName,AnalyzeAssembly.AllHotfix))
  43. {
  44. analysisContext.RegisterSemanticModelAction((this.AnalyzeSemanticModel));
  45. }
  46. } ));
  47. }
  48. private void AnalyzeSemanticModel(SemanticModelAnalysisContext analysisContext)
  49. {
  50. foreach (var classDeclarationSyntax in analysisContext.SemanticModel.SyntaxTree.GetRoot().DescendantNodes<ClassDeclarationSyntax>())
  51. {
  52. var classTypeSymbol = analysisContext.SemanticModel.GetDeclaredSymbol(classDeclarationSyntax);
  53. if (classTypeSymbol!=null)
  54. {
  55. Analyzer(analysisContext, classTypeSymbol);
  56. }
  57. }
  58. }
  59. private void Analyzer(SemanticModelAnalysisContext context, INamedTypeSymbol namedTypeSymbol)
  60. {
  61. if (namedTypeSymbol.IsStatic)
  62. {
  63. return;
  64. }
  65. if (!this.CheckIsTypeOrBaseTypeHasBaseAttributeInherit(namedTypeSymbol))
  66. {
  67. foreach (SyntaxReference? declaringSyntaxReference in namedTypeSymbol.DeclaringSyntaxReferences)
  68. {
  69. Diagnostic diagnostic = Diagnostic.Create(Rule, declaringSyntaxReference.GetSyntax()?.GetLocation(), namedTypeSymbol.Name);
  70. //Diagnostic diagnostic = Diagnostic.Create(Rule, declaringSyntaxReference.GetSyntax()?.GetLocation(), context.SemanticModel.SyntaxTree.FilePath);
  71. context.ReportDiagnostic(diagnostic);
  72. }
  73. }
  74. }
  75. /// <summary>
  76. /// 检查该类或其基类是否有BaseAttribute的子类特性标记
  77. /// </summary>
  78. private bool CheckIsTypeOrBaseTypeHasBaseAttributeInherit(INamedTypeSymbol namedTypeSymbol)
  79. {
  80. INamedTypeSymbol? typeSymbol = namedTypeSymbol;
  81. while (typeSymbol != null)
  82. {
  83. if (typeSymbol.HasBaseAttribute(Definition.BaseAttribute))
  84. {
  85. return true;
  86. }
  87. typeSymbol = typeSymbol.BaseType;
  88. }
  89. return false;
  90. }
  91. }
  92. }