Skip to content

Commit 992e66e

Browse files
committed
重构分析器项目
1 parent 6fc5882 commit 992e66e

12 files changed

+552
-396
lines changed

WebApiClient.Analyzers/AttributeCtorAnalyzer.cs

Lines changed: 0 additions & 42 deletions
This file was deleted.

WebApiClient.Analyzers/DiagnosticDescriptors.cs renamed to WebApiClient.Analyzers/Descriptors.cs

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,31 @@ namespace WebApiClient.Analyzers
55
/// <summary>
66
/// 诊断描述器
77
/// </summary>
8-
static class DiagnosticDescriptors
8+
static class Descriptors
99
{
1010
/// <summary>
1111
/// 特性诊断描述器
1212
/// </summary>
1313
public static DiagnosticDescriptor AttributeDescriptor { get; }
14-
= Rule("WA1001", "不匹配的特性构造函数", "不支持特性的此构造函数,请使用其它构造函数");
14+
= Create("WA1001", "不匹配的特性构造函数", "不支持特性的此构造函数,请使用其它构造函数");
1515

1616
/// <summary>
1717
/// 方法返回类型诊断描述器
1818
/// </summary>
1919
public static DiagnosticDescriptor ReturnTypeDescriptor { get; }
20-
= Rule("WA1002", "不支持的返回类型", "返回类型必须为ITask<>或Task<>");
20+
= Create("WA1002", "不支持的返回类型", "返回类型必须为ITask<>或Task<>");
2121

2222
/// <summary>
2323
/// 引用参数诊断描述器
2424
/// </summary>
2525
public static DiagnosticDescriptor RefParameterDescriptor { get; }
26-
= Rule("WA1003", "不支持的ref/out修饰", "参数不支持ref/out等修饰");
26+
= Create("WA1003", "不支持的ref/out修饰", "参数不支持ref/out等修饰");
2727

2828
/// <summary>
2929
/// 非方法声明诊断描述器
3030
/// </summary>
31-
public static DiagnosticDescriptor NotMethodDefindDescriptor { get; }
32-
= Rule("WA1004", "不支持的非方法声明", "不支持的非方法声明,只允许方法的声明");
31+
public static DiagnosticDescriptor NotMethodDefindedDescriptor { get; }
32+
= Create("WA1004", "不支持的非方法声明", "不支持的非方法声明,只允许方法的声明");
3333

3434
/// <summary>
3535
/// 创建诊断描述器
@@ -39,7 +39,7 @@ static class DiagnosticDescriptors
3939
/// <param name="message"></param>
4040
/// <param name="helpLinkUri"></param>
4141
/// <returns></returns>
42-
private static DiagnosticDescriptor Rule(string id, string title, string message, string helpLinkUri = null)
42+
private static DiagnosticDescriptor Create(string id, string title, string message, string helpLinkUri = null)
4343
{
4444
const string category = "Error";
4545
if (string.IsNullOrEmpty(helpLinkUri) == true)
@@ -48,17 +48,5 @@ private static DiagnosticDescriptor Rule(string id, string title, string message
4848
}
4949
return new DiagnosticDescriptor(id, title, message, category, DiagnosticSeverity.Error, true, helpLinkUri: helpLinkUri);
5050
}
51-
52-
/// <summary>
53-
/// 转换为诊断结果
54-
/// </summary>
55-
/// <param name="diagnosticDescriptor"></param>
56-
/// <param name="location"></param>
57-
/// <param name="messageArgs"></param>
58-
/// <returns></returns>
59-
public static Diagnostic ToDiagnostic(this DiagnosticDescriptor diagnosticDescriptor, Location location, params object[] messageArgs)
60-
{
61-
return Diagnostic.Create(diagnosticDescriptor, location, messageArgs);
62-
}
6351
}
6452
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CSharp;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
7+
namespace WebApiClient.Analyzers.Diagnostics
8+
{
9+
/// <summary>
10+
/// 表示特性构造函数诊断器
11+
/// </summary>
12+
class AttributeDiagnostic : HttpApiDiagnostic
13+
{
14+
/// <summary>
15+
/// /// <summary>
16+
/// 获取诊断描述
17+
/// </summary>
18+
/// </summary>
19+
public override DiagnosticDescriptor Descriptor { get; } = Descriptors.AttributeDescriptor;
20+
21+
/// <summary>
22+
/// 特性构造函数诊断器
23+
/// </summary>
24+
/// <param name="context">上下文</param>
25+
public AttributeDiagnostic(HttpApiContext context)
26+
: base(context)
27+
{
28+
}
29+
30+
/// <summary>
31+
/// 返回所有的报告诊断
32+
/// </summary>
33+
/// <returns></returns>
34+
protected override IEnumerable<Diagnostic> GetDiagnostics()
35+
{
36+
var interfaceSymbol = this.Context.SyntaxNodeContext.SemanticModel.GetDeclaredSymbol(this.Context.HttpApiSyntax);
37+
if (interfaceSymbol == null)
38+
{
39+
yield break;
40+
}
41+
42+
var interfaceAttributes = this.GetInterfaceDiagnosticAttributes(interfaceSymbol);
43+
var methodAttributes = this.GetApiMethodSymbols().SelectMany(item => this.GetMethodDiagnosticAttributes(item));
44+
45+
foreach (var item in interfaceAttributes.Concat(methodAttributes))
46+
{
47+
var location = item.ApplicationSyntaxReference.GetSyntax().GetLocation();
48+
yield return this.CreateDiagnostic(location);
49+
}
50+
}
51+
52+
53+
/// <summary>
54+
/// 获取接口已诊断的特性
55+
/// </summary>
56+
/// <param name="interfaceSymbol">类型</param>
57+
/// <returns></returns>
58+
private IEnumerable<AttributeData> GetInterfaceDiagnosticAttributes(ITypeSymbol interfaceSymbol)
59+
{
60+
foreach (var attribuete in interfaceSymbol.GetAttributes())
61+
{
62+
if (this.CtorAttribueIsDefind(attribuete, AttributeTargets.Interface) == false)
63+
{
64+
yield return attribuete;
65+
}
66+
}
67+
}
68+
69+
70+
/// <summary>
71+
/// 获取方法已诊断的特性
72+
/// </summary>
73+
/// <param name="methodSymbol">方法</param>
74+
/// <returns></returns>
75+
private IEnumerable<AttributeData> GetMethodDiagnosticAttributes(IMethodSymbol methodSymbol)
76+
{
77+
foreach (var methodAttribuete in methodSymbol.GetAttributes())
78+
{
79+
if (this.CtorAttribueIsDefind(methodAttribuete, AttributeTargets.Method) == false)
80+
{
81+
yield return methodAttribuete;
82+
}
83+
}
84+
85+
foreach (var parameter in methodSymbol.Parameters)
86+
{
87+
foreach (var parameterAttribute in parameter.GetAttributes())
88+
{
89+
if (this.CtorAttribueIsDefind(parameterAttribute, AttributeTargets.Parameter) == false)
90+
{
91+
yield return parameterAttribute;
92+
}
93+
}
94+
}
95+
}
96+
97+
98+
/// <summary>
99+
/// 获取特性声明的AttributeCtorUsageAtribute是否声明了指定目标
100+
/// </summary>
101+
/// <param name="attributeData"></param>
102+
/// <param name="targets">指定目标</param>
103+
/// <returns></returns>
104+
private bool CtorAttribueIsDefind(AttributeData attributeData, AttributeTargets targets)
105+
{
106+
var ctorAttributes = attributeData.AttributeConstructor?.GetAttributes();
107+
if (ctorAttributes.HasValue == false)
108+
{
109+
return true;
110+
}
111+
112+
var ctorUsageAttribute = ctorAttributes.Value
113+
.FirstOrDefault(item => item.AttributeClass.Equals(this.Context.AttributeCtorUsageAtributeType));
114+
115+
if (ctorUsageAttribute == null)
116+
{
117+
return true;
118+
}
119+
120+
var arg = ctorUsageAttribute.ConstructorArguments.FirstOrDefault();
121+
if (arg.IsNull == true)
122+
{
123+
return true;
124+
}
125+
126+
var ctorTargets = (AttributeTargets)arg.Value;
127+
return ctorTargets.HasFlag(targets);
128+
}
129+
}
130+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CSharp;
3+
using System.Collections.Generic;
4+
5+
namespace WebApiClient.Analyzers.Diagnostics
6+
{
7+
/// <summary>
8+
/// 表示非方法声明诊断器
9+
/// </summary>
10+
class NotMethodDefindedDiagnostic : HttpApiDiagnostic
11+
{
12+
/// <summary>
13+
/// /// <summary>
14+
/// 获取诊断描述
15+
/// </summary>
16+
/// </summary>
17+
public override DiagnosticDescriptor Descriptor { get; } = Descriptors.NotMethodDefindedDescriptor;
18+
19+
/// <summary>
20+
/// 非方法声明诊断器
21+
/// </summary>
22+
/// <param name="context">上下文</param>
23+
public NotMethodDefindedDiagnostic(HttpApiContext context)
24+
: base(context)
25+
{
26+
}
27+
28+
/// <summary>
29+
/// 返回所有的报告诊断
30+
/// </summary>
31+
/// <returns></returns>
32+
protected override IEnumerable<Diagnostic> GetDiagnostics()
33+
{
34+
foreach (var member in this.Context.HttpApiSyntax.Members)
35+
{
36+
if (member.Kind() != SyntaxKind.MethodDeclaration)
37+
{
38+
var location = member.GetLocation();
39+
yield return this.CreateDiagnostic(location);
40+
}
41+
}
42+
}
43+
}
44+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CSharp.Syntax;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
6+
namespace WebApiClient.Analyzers.Diagnostics
7+
{
8+
/// <summary>
9+
/// 表示引用传递参数诊断器
10+
/// </summary>
11+
class RefParameterDiagnostic : HttpApiDiagnostic
12+
{
13+
/// <summary>
14+
/// /// <summary>
15+
/// 获取诊断描述
16+
/// </summary>
17+
/// </summary>
18+
public override DiagnosticDescriptor Descriptor { get; } = Descriptors.RefParameterDescriptor;
19+
20+
/// <summary>
21+
/// 引用传递参数诊断器
22+
/// </summary>
23+
/// <param name="context">上下文</param>
24+
public RefParameterDiagnostic(HttpApiContext context)
25+
: base(context)
26+
{
27+
}
28+
29+
/// <summary>
30+
/// 返回所有的报告诊断
31+
/// </summary>
32+
/// <returns></returns>
33+
protected override IEnumerable<Diagnostic> GetDiagnostics()
34+
{
35+
foreach (var method in this.GetApiMethodSymbols())
36+
{
37+
foreach (var parameter in method.Parameters)
38+
{
39+
if (parameter.RefKind != RefKind.None)
40+
{
41+
var parameterSyntax = parameter.DeclaringSyntaxReferences.First().GetSyntax() as ParameterSyntax;
42+
var location = parameterSyntax.Modifiers.First().GetLocation();
43+
yield return this.CreateDiagnostic(location);
44+
}
45+
}
46+
}
47+
}
48+
49+
}
50+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CSharp.Syntax;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
6+
namespace WebApiClient.Analyzers.Diagnostics
7+
{
8+
/// <summary>
9+
/// 表示返回类型诊断器
10+
/// </summary>
11+
class ReturnTypeDiagnostic : HttpApiDiagnostic
12+
{
13+
/// <summary>
14+
/// /// <summary>
15+
/// 获取诊断描述
16+
/// </summary>
17+
/// </summary>
18+
public override DiagnosticDescriptor Descriptor { get; } = Descriptors.ReturnTypeDescriptor;
19+
20+
/// <summary>
21+
/// 返回类型诊断器
22+
/// </summary>
23+
/// <param name="context">上下文</param>
24+
public ReturnTypeDiagnostic(HttpApiContext context)
25+
: base(context)
26+
{
27+
}
28+
29+
30+
/// <summary>
31+
/// 返回所有的报告诊断
32+
/// </summary>
33+
/// <returns></returns>
34+
protected override IEnumerable<Diagnostic> GetDiagnostics()
35+
{
36+
foreach (var method in this.GetApiMethodSymbols())
37+
{
38+
var name = method.ReturnType.MetadataName;
39+
if (name == "Task`1" || name == "ITask`1")
40+
{
41+
continue;
42+
}
43+
44+
var methodSyntax = method.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax() as MethodDeclarationSyntax;
45+
if (methodSyntax == null)
46+
{
47+
continue;
48+
}
49+
50+
var location = methodSyntax.ReturnType.GetLocation();
51+
yield return this.CreateDiagnostic(location);
52+
}
53+
}
54+
55+
}
56+
}

0 commit comments

Comments
 (0)