Skip to content

Commit 7942923

Browse files
committed
ref/out修饰的参数诊断检测
1 parent 14ad1bf commit 7942923

File tree

3 files changed

+118
-61
lines changed

3 files changed

+118
-61
lines changed

WebApiClient.Analyzers/AttributeCtorAnalyzer.cs

Lines changed: 8 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using Microsoft.CodeAnalysis.CSharp;
33
using Microsoft.CodeAnalysis.Diagnostics;
44
using System.Collections.Immutable;
5-
using System.Linq;
65

76
namespace WebApiClient.Analyzers
87
{
@@ -12,43 +11,18 @@ namespace WebApiClient.Analyzers
1211
[DiagnosticAnalyzer(LanguageNames.CSharp)]
1312
public class AttributeCtorAnalyzer : DiagnosticAnalyzer
1413
{
15-
/// <summary>
16-
/// 特性诊断描述器
17-
/// </summary>
18-
private static readonly DiagnosticDescriptor attributeDescriptor =
19-
Rule("AC1001", "特性构造函数不匹配", "不支持特性的此构造函数,请使用其它构造函数");
20-
21-
/// <summary>
22-
/// 方法返回类型诊断描述器
23-
/// </summary>
24-
private static readonly DiagnosticDescriptor returnTypeDescriptor =
25-
Rule("RT1001", "不支持的返回类型", "返回类型必须为ITask<>或Task<>");
26-
27-
28-
/// <summary>
29-
/// 创建诊断描述器
30-
/// </summary>
31-
/// <param name="id"></param>
32-
/// <param name="title"></param>
33-
/// <param name="message"></param>
34-
/// <param name="helpLinkUri"></param>
35-
/// <returns></returns>
36-
private static DiagnosticDescriptor Rule(string id, string title, string message, string helpLinkUri = null)
37-
{
38-
const string category = "Error";
39-
if (string.IsNullOrEmpty(helpLinkUri) == true)
40-
{
41-
helpLinkUri = "https://github.com/dotnetcore/WebApiClient/wiki/WebApiClient%E5%9F%BA%E7%A1%80";
42-
}
43-
return new DiagnosticDescriptor(id, title, message, category, DiagnosticSeverity.Error, true, helpLinkUri: helpLinkUri);
44-
}
45-
4614
/// <summary>
4715
/// 获取所支持的诊断
4816
/// </summary>
4917
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
5018
{
51-
get => ImmutableArray.Create(attributeDescriptor, returnTypeDescriptor);
19+
get
20+
{
21+
return ImmutableArray.Create(
22+
DiagnosticDescriptors.AttributeDescriptor,
23+
DiagnosticDescriptors.ReturnTypeDescriptor,
24+
DiagnosticDescriptors.RefParameterDescriptor);
25+
}
5226
}
5327

5428
/// <summary>
@@ -60,22 +34,7 @@ public override void Initialize(AnalysisContext context)
6034
context.RegisterSyntaxNodeAction(syntaxNodeContext =>
6135
{
6236
var httpApi = new WebApiClientHtttApi(syntaxNodeContext);
63-
var diagnosticAttributeSyntaxs = httpApi.GetDiagnosticAttributeSyntaxs();
64-
var diagnosticReturnTypeSyntaxs = httpApi.GetDiagnosticReturnTypeSyntaxs();
65-
66-
foreach (var node in diagnosticAttributeSyntaxs)
67-
{
68-
var location = node.GetLocation();
69-
var diagnostic = Diagnostic.Create(attributeDescriptor, location);
70-
syntaxNodeContext.ReportDiagnostic(diagnostic);
71-
}
72-
73-
foreach (var node in diagnosticReturnTypeSyntaxs)
74-
{
75-
var location = node.GetLocation();
76-
var diagnostic = Diagnostic.Create(returnTypeDescriptor, location);
77-
syntaxNodeContext.ReportDiagnostic(diagnostic);
78-
}
37+
httpApi.ReportDiagnostic();
7938
}, SyntaxKind.InterfaceDeclaration);
8039
}
8140
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using Microsoft.CodeAnalysis;
2+
3+
namespace WebApiClient.Analyzers
4+
{
5+
/// <summary>
6+
/// 诊断描述器
7+
/// </summary>
8+
static class DiagnosticDescriptors
9+
{
10+
/// <summary>
11+
/// 特性诊断描述器
12+
/// </summary>
13+
public static DiagnosticDescriptor AttributeDescriptor { get; }
14+
= Rule("AC1001", "特性构造函数不匹配", "不支持特性的此构造函数,请使用其它构造函数");
15+
16+
/// <summary>
17+
/// 方法返回类型诊断描述器
18+
/// </summary>
19+
public static DiagnosticDescriptor ReturnTypeDescriptor { get; }
20+
= Rule("RT1001", "不支持的返回类型", "返回类型必须为ITask<>或Task<>");
21+
22+
/// <summary>
23+
/// 引用参数诊断描述器
24+
/// </summary>
25+
public static DiagnosticDescriptor RefParameterDescriptor { get; }
26+
= Rule("PR1001", "不支持ref/out", "参数不支持ref/out等修饰");
27+
28+
29+
/// <summary>
30+
/// 创建诊断描述器
31+
/// </summary>
32+
/// <param name="id"></param>
33+
/// <param name="title"></param>
34+
/// <param name="message"></param>
35+
/// <param name="helpLinkUri"></param>
36+
/// <returns></returns>
37+
private static DiagnosticDescriptor Rule(string id, string title, string message, string helpLinkUri = null)
38+
{
39+
const string category = "Error";
40+
if (string.IsNullOrEmpty(helpLinkUri) == true)
41+
{
42+
helpLinkUri = "https://github.com/dotnetcore/WebApiClient/wiki/WebApiClient%E5%9F%BA%E7%A1%80";
43+
}
44+
return new DiagnosticDescriptor(id, title, message, category, DiagnosticSeverity.Error, true, helpLinkUri: helpLinkUri);
45+
}
46+
47+
/// <summary>
48+
/// 转换为诊断结果
49+
/// </summary>
50+
/// <param name="diagnosticDescriptor"></param>
51+
/// <param name="location"></param>
52+
/// <param name="messageArgs"></param>
53+
/// <returns></returns>
54+
public static Diagnostic ToDiagnostic(this DiagnosticDescriptor diagnosticDescriptor, Location location, params object[] messageArgs)
55+
{
56+
return Diagnostic.Create(diagnosticDescriptor, location, messageArgs);
57+
}
58+
}
59+
}

WebApiClient.Analyzers/WebApiClientHtttApi.cs

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,38 +67,51 @@ private bool GetIsHtttApiInterface()
6767
return false;
6868
}
6969

70+
/// <summary>
71+
/// 报告所有诊断
72+
/// </summary>
73+
public void ReportDiagnostic()
74+
{
75+
this.ReportDiagnosticOfAttributes();
76+
this.ReportDiagnosticOfReturnTypes();
77+
this.ReportDiagnosticOfRefParameters();
78+
}
7079

7180
/// <summary>
72-
/// 获取诊断的特性
81+
/// 报告特性诊断
7382
/// </summary>
74-
/// <returns></returns>
75-
public IEnumerable<SyntaxNode> GetDiagnosticAttributeSyntaxs()
83+
public void ReportDiagnosticOfAttributes()
7684
{
7785
if (this.IsHtttApiInterface == false)
7886
{
79-
return Enumerable.Empty<SyntaxNode>();
87+
return;
8088
}
8189

8290
var interfaceSymbol = this.syntaxNodeContext.SemanticModel.GetDeclaredSymbol(this.interfaceDeclaration);
8391
if (interfaceSymbol == null)
8492
{
85-
return Enumerable.Empty<SyntaxNode>();
93+
return;
8694
}
8795

8896
var interfaceAttributes = this.GetInterfaceDiagnosticAttributes(interfaceSymbol);
8997
var methodAttributes = this.GetHttpApiMethodSymbols().SelectMany(item => this.GetMethodDiagnosticAttributes(item));
90-
return interfaceAttributes.Concat(methodAttributes).Select(item => item.ApplicationSyntaxReference.GetSyntax());
98+
99+
foreach (var item in interfaceAttributes.Concat(methodAttributes))
100+
{
101+
var location = item.ApplicationSyntaxReference.GetSyntax().GetLocation();
102+
var diagnostic = DiagnosticDescriptors.AttributeDescriptor.ToDiagnostic(location);
103+
this.syntaxNodeContext.ReportDiagnostic(diagnostic);
104+
}
91105
}
92106

93107
/// <summary>
94-
/// 获取诊断的接口返回类型
108+
/// 报告返回类型诊断
95109
/// </summary>
96-
/// <returns></returns>
97-
public IEnumerable<SyntaxNode> GetDiagnosticReturnTypeSyntaxs()
110+
public void ReportDiagnosticOfReturnTypes()
98111
{
99112
if (this.IsHtttApiInterface == false)
100113
{
101-
yield break;
114+
return;
102115
}
103116

104117
foreach (var method in this.GetHttpApiMethodSymbols())
@@ -109,7 +122,34 @@ public IEnumerable<SyntaxNode> GetDiagnosticReturnTypeSyntaxs()
109122
var methodSyntax = method.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax() as MethodDeclarationSyntax;
110123
if (methodSyntax != null)
111124
{
112-
yield return methodSyntax.ReturnType;
125+
var location = methodSyntax.ReturnType.GetLocation();
126+
var diagnostic = DiagnosticDescriptors.ReturnTypeDescriptor.ToDiagnostic(location);
127+
this.syntaxNodeContext.ReportDiagnostic(diagnostic);
128+
}
129+
}
130+
}
131+
}
132+
133+
/// <summary>
134+
/// 报告引用参数诊断
135+
/// </summary>
136+
public void ReportDiagnosticOfRefParameters()
137+
{
138+
if (this.IsHtttApiInterface == false)
139+
{
140+
return;
141+
}
142+
143+
foreach (var method in this.GetHttpApiMethodSymbols())
144+
{
145+
foreach (var parameter in method.Parameters)
146+
{
147+
if (parameter.RefKind != RefKind.None)
148+
{
149+
var parameterSyntax = parameter.DeclaringSyntaxReferences.First().GetSyntax() as ParameterSyntax;
150+
var location = parameterSyntax.Modifiers.First().GetLocation();
151+
var diagnostic = DiagnosticDescriptors.RefParameterDescriptor.ToDiagnostic(location);
152+
this.syntaxNodeContext.ReportDiagnostic(diagnostic);
113153
}
114154
}
115155
}
@@ -136,7 +176,6 @@ private IEnumerable<IMethodSymbol> GetHttpApiMethodSymbols()
136176
}
137177
}
138178

139-
140179
/// <summary>
141180
/// 获取接口已诊断的特性
142181
/// </summary>

0 commit comments

Comments
 (0)