-
Notifications
You must be signed in to change notification settings - Fork 6
/
CodeAnalyzer.cs
124 lines (102 loc) · 4.36 KB
/
CodeAnalyzer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
namespace Code.Analyzer
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class CodeAnalyzer : DiagnosticAnalyzer
{
public const string DiagnosticId = "CodeAnalyzer";
private BaseAnalyzer[] analyzers = new BaseAnalyzer[]
{
new InterfaceAnalyzer()
};
public CodeAnalyzer()
{
var supportedDiagnostics = new List<DiagnosticDescriptor>();
foreach(var analyzer in analyzers)
{
supportedDiagnostics.AddRange(analyzer.Descriptors);
}
SupportedDiagnostics = ImmutableArray.Create(supportedDiagnostics.ToArray());
}
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; }
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(Execute, SyntaxKind.InterfaceDeclaration);
context.RegisterSyntaxNodeAction(Class, SyntaxKind.ClassDeclaration);
}
private void Execute(SyntaxNodeAnalysisContext context)
{
foreach (var ansyzer in analyzers.Where(_analyzer=>_analyzer.Kind == context.Node.Kind()))
{
ansyzer.Execute(context);
}
}
private void Class(SyntaxNodeAnalysisContext context)
{
var jitAopAttribute = context.Compilation.GetTypeByMetadataName("NCoreCoder.Aop.JitAopAttribute");
if (IsInheritInterface(context) && IsAopActorsAttribute(context))
{
foreach(var method in GetMethods(context))
{
var attri = method.GetAttributes();
if (!method.GetAttributes().Any(
_attribute =>
_attribute.AttributeClass.Equals(jitAopAttribute) ||
_attribute.AttributeClass.AllInterfaces.Any(_attri =>
_attri.Equals(jitAopAttribute)
)
)
)
{
var descriptor = new DiagnosticDescriptor("E001", "实体类", $"{method.Name} 方法建议打上继承自:NCoreCoder.Aop.JitAopAttribute的特性", "Warning", DiagnosticSeverity.Warning, true);
var diagnostic = Diagnostic.Create(descriptor, method.Locations.FirstOrDefault());
context.ReportDiagnostic(diagnostic);
}
}
}
}
private bool IsInheritInterface(SyntaxNodeAnalysisContext context)
{
var classSyntax = context.Node as ClassDeclarationSyntax;
if (classSyntax.BaseList == null)
return false;
var symbol = context.SemanticModel
.GetDeclaredSymbol(classSyntax);
return symbol.AllInterfaces.Any();
}
private bool IsAopActorsAttribute(SyntaxNodeAnalysisContext context)
{
var classSyntax = context.Node as ClassDeclarationSyntax;
var attributeSymbol = context.Compilation.GetTypeByMetadataName("NCoreCoder.Aop.Jit.AopActorsAttribute");
var symbol = context.SemanticModel
.GetDeclaredSymbol(classSyntax);
foreach(var _interface in symbol.AllInterfaces)
{
if (_interface
.GetAttributes()
.FirstOrDefault(_attribute => _attribute.AttributeClass.Equals(attributeSymbol)) is AttributeData attribute && attribute != null)
{
return true;
}
}
return false;
}
private IEnumerable<IMethodSymbol> GetMethods(SyntaxNodeAnalysisContext context)
{
var classSyntax = context.Node as ClassDeclarationSyntax;
var symbol = context.SemanticModel
.GetDeclaredSymbol(classSyntax);
return symbol.GetMembers()
.OfType<IMethodSymbol>()
.Where(_method=>_method.MethodKind != MethodKind.Constructor);
}
}
}