ClassDeclarationInHotfixAnalyzer.cs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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 static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticIds.ClassDeclarationInHotfixAnalyzerRuleId,
  13. Title,
  14. MessageFormat,
  15. DiagnosticCategories.Hotfix,
  16. DiagnosticSeverity.Error, true, Description);
  17. public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
  18. public override void Initialize(AnalysisContext context)
  19. {
  20. if (!AnalyzerGlobalSetting.EnableAnalyzer)
  21. {
  22. return;
  23. }
  24. context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
  25. context.EnableConcurrentExecution();
  26. context.RegisterSymbolAction(this.Analyzer, SymbolKind.NamedType);
  27. }
  28. private void Analyzer(SymbolAnalysisContext context)
  29. {
  30. if (!AnalyzerHelper.IsAssemblyNeedAnalyze(context.Compilation.AssemblyName, AnalyzeAssembly.AllHotfix))
  31. {
  32. return;
  33. }
  34. if (!(context.Symbol is INamedTypeSymbol namedTypeSymbol))
  35. {
  36. return;
  37. }
  38. if (namedTypeSymbol.IsStatic)
  39. {
  40. return;
  41. }
  42. if (!this.CheckIsTypeOrBaseTypeHasBaseAttributeInherit(namedTypeSymbol))
  43. {
  44. foreach (SyntaxReference? declaringSyntaxReference in namedTypeSymbol.DeclaringSyntaxReferences)
  45. {
  46. Diagnostic diagnostic = Diagnostic.Create(Rule, declaringSyntaxReference.GetSyntax()?.GetLocation(), namedTypeSymbol.Name);
  47. context.ReportDiagnostic(diagnostic);
  48. }
  49. }
  50. }
  51. /// <summary>
  52. /// 检查该类或其基类是否有BaseAttribute的子类特性标记
  53. /// </summary>
  54. private bool CheckIsTypeOrBaseTypeHasBaseAttributeInherit(INamedTypeSymbol namedTypeSymbol)
  55. {
  56. INamedTypeSymbol? typeSymbol = namedTypeSymbol;
  57. while (typeSymbol != null)
  58. {
  59. if (typeSymbol.HasBaseAttribute(Definition.BaseAttribute))
  60. {
  61. return true;
  62. }
  63. typeSymbol = typeSymbol.BaseType;
  64. }
  65. return false;
  66. }
  67. }
  68. }