ClassDeclarationInHotfixAnalyzer.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. using System.Collections.Immutable;
  2. using Microsoft.CodeAnalysis;
  3. using Microsoft.CodeAnalysis.Diagnostics;
  4. namespace ET.Analyzer
  5. {
  6. [DiagnosticAnalyzer(LanguageNames.CSharp)]
  7. public class ClassDeclarationInHotfixAnalyzer: DiagnosticAnalyzer
  8. {
  9. private const string Title = "Hotfix程序集中 只能声明含有BaseAttribute子类特性的类或静态类";
  10. private const string MessageFormat = "Hotfix程序集中 只能声明含有BaseAttribute子类特性的类或静态类 类: {0}";
  11. private const string Description = "Hotfix程序集中 只能声明含有BaseAttribute子类特性的类或静态类.";
  12. private const string BaseAttribute = "ET.BaseAttribute";
  13. private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticIds.ClassDeclarationInHotfixAnalyzerRuleId,
  14. Title,
  15. MessageFormat,
  16. DiagnosticCategories.Hotfix,
  17. DiagnosticSeverity.Error, true, Description);
  18. public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
  19. public override void Initialize(AnalysisContext context)
  20. {
  21. if (!AnalyzerGlobalSetting.EnableAnalyzer)
  22. {
  23. return;
  24. }
  25. context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
  26. context.EnableConcurrentExecution();
  27. context.RegisterSymbolAction(this.Analyzer, SymbolKind.NamedType);
  28. }
  29. private void Analyzer(SymbolAnalysisContext context)
  30. {
  31. if (!AnalyzerHelper.IsAssemblyNeedAnalyze(context.Compilation.AssemblyName, AnalyzeAssembly.AllHotfix))
  32. {
  33. return;
  34. }
  35. if (!(context.Symbol is INamedTypeSymbol namedTypeSymbol))
  36. {
  37. return;
  38. }
  39. if (namedTypeSymbol.IsStatic)
  40. {
  41. return;
  42. }
  43. if (!this.CheckIsTypeOrBaseTypeHasBaseAttributeInherit(namedTypeSymbol))
  44. {
  45. foreach (SyntaxReference? declaringSyntaxReference in namedTypeSymbol.DeclaringSyntaxReferences)
  46. {
  47. Diagnostic diagnostic = Diagnostic.Create(Rule, declaringSyntaxReference.GetSyntax()?.GetLocation(), namedTypeSymbol.Name);
  48. context.ReportDiagnostic(diagnostic);
  49. }
  50. }
  51. }
  52. /// <summary>
  53. /// 检查该类或其基类是否有BaseAttribute的子类特性标记
  54. /// </summary>
  55. private bool CheckIsTypeOrBaseTypeHasBaseAttributeInherit(INamedTypeSymbol namedTypeSymbol)
  56. {
  57. INamedTypeSymbol? typeSymbol = namedTypeSymbol;
  58. while (typeSymbol != null)
  59. {
  60. if (typeSymbol.HasBaseAttribute(BaseAttribute))
  61. {
  62. return true;
  63. }
  64. typeSymbol = typeSymbol.BaseType;
  65. }
  66. return false;
  67. }
  68. }
  69. }