HotfixProjectFieldDeclarationAnalyzer.cs 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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 (AnalyzerHelper.IsAssemblyNeedAnalyze(analysisContext.Compilation.AssemblyName,AnalyzeAssembly.AllHotfix))
  31. {
  32. analysisContext.RegisterSemanticModelAction((this.AnalyzeSemanticModel));
  33. }
  34. } ));
  35. }
  36. private void AnalyzeSemanticModel(SemanticModelAnalysisContext analysisContext)
  37. {
  38. foreach (var classDeclarationSyntax in analysisContext.SemanticModel.SyntaxTree.GetRoot().DescendantNodes<ClassDeclarationSyntax>())
  39. {
  40. var classTypeSymbol = analysisContext.SemanticModel.GetDeclaredSymbol(classDeclarationSyntax);
  41. if (classTypeSymbol!=null)
  42. {
  43. Analyzer(analysisContext, classTypeSymbol);
  44. }
  45. }
  46. }
  47. private void Analyzer(SemanticModelAnalysisContext context, INamedTypeSymbol namedTypeSymbol)
  48. {
  49. foreach (ISymbol? memberSymbol in namedTypeSymbol.GetMembers())
  50. {
  51. // 筛选出属性成员
  52. if (memberSymbol is IPropertySymbol propertySymbol)
  53. {
  54. ReportDiagnostic(propertySymbol);
  55. continue;
  56. }
  57. // 筛选出非Const字段成员
  58. if (memberSymbol is IFieldSymbol fieldSymbol && !fieldSymbol.IsConst)
  59. {
  60. ReportDiagnostic(fieldSymbol);
  61. }
  62. }
  63. void ReportDiagnostic(ISymbol symbol)
  64. {
  65. foreach (SyntaxReference? declaringSyntaxReference in symbol.DeclaringSyntaxReferences)
  66. {
  67. Diagnostic diagnostic = Diagnostic.Create(Rule, declaringSyntaxReference.GetSyntax()?.GetLocation(), symbol.Name);
  68. context.ReportDiagnostic(diagnostic);
  69. }
  70. }
  71. }
  72. }
  73. }