-
Notifications
You must be signed in to change notification settings - Fork 446
/
Copy pathHttpApiContext.cs
151 lines (133 loc) · 5.28 KB
/
HttpApiContext.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Linq;
namespace WebApiClientCore.Analyzers
{
/// <summary>
/// 表示HttpApi上下文
/// </summary>
sealed class HttpApiContext
{
private const string IHttpApiTypeName = "WebApiClientCore.IHttpApi";
private const string IApiAttributeTypeName = "WebApiClientCore.IApiAttribute";
private const string UriAttributeTypeName = "WebApiClientCore.Attributes.UriAttribute";
private const string AttributeCtorUsageTypName = "WebApiClientCore.AttributeCtorUsageAttribute";
/// <summary>
/// 获取接口声明语法
/// </summary>
public InterfaceDeclarationSyntax Syntax { get; }
/// <summary>
/// 获取接口
/// </summary>
public INamedTypeSymbol Interface { get; }
/// <summary>
/// 获取声明的Api方法
/// </summary>
public IMethodSymbol[] Methods { get; }
/// <summary>
/// 获取UriAttribute的类型
/// </summary>
public INamedTypeSymbol? UriAttribute { get; }
/// <summary>
/// 获取AttributeCtorUsageAttribute的类型
/// </summary>
public INamedTypeSymbol? AttributeCtorUsageAttribute { get; }
/// <summary>
/// HttpApi上下文
/// </summary>
/// <param name="syntax"></param>
/// <param name="interface"></param>
/// <param name="methods"></param>
/// <param name="uriAttribute"></param>
/// <param name="attributeCtorUsageAttribute"></param>
private HttpApiContext(
InterfaceDeclarationSyntax syntax,
INamedTypeSymbol @interface,
IMethodSymbol[] methods,
INamedTypeSymbol? uriAttribute,
INamedTypeSymbol? attributeCtorUsageAttribute)
{
this.Syntax = syntax;
this.Interface = @interface;
this.Methods = methods;
this.UriAttribute = uriAttribute;
this.AttributeCtorUsageAttribute = attributeCtorUsageAttribute;
}
/// <summary>
/// 尝试解析
/// </summary>
/// <param name="syntaxNodeContext"></param>
/// <param name="context"></param>
/// <returns></returns>
public static bool TryParse(SyntaxNodeAnalysisContext syntaxNodeContext, out HttpApiContext? context)
{
context = null;
var syntax = syntaxNodeContext.Node as InterfaceDeclarationSyntax;
if (syntax == null)
{
return false;
}
var @interface = syntaxNodeContext.Compilation.GetSemanticModel(syntax.SyntaxTree).GetDeclaredSymbol(syntax);
if (@interface == null)
{
return false;
}
var ihttpApi = syntaxNodeContext.Compilation.GetTypeByMetadataName(IHttpApiTypeName);
if (ihttpApi == null)
{
return false;
}
var iapiAttribute = syntaxNodeContext.Compilation.GetTypeByMetadataName(IApiAttributeTypeName);
if (IsHttpApiInterface(@interface, ihttpApi, iapiAttribute) == false)
{
return false;
}
var methods = @interface.GetMembers().OfType<IMethodSymbol>().ToArray();
var uriAttribute = syntaxNodeContext.Compilation.GetTypeByMetadataName(UriAttributeTypeName);
var attributeCtorUsageAttribute = syntaxNodeContext.Compilation.GetTypeByMetadataName(AttributeCtorUsageTypName);
context = new HttpApiContext(syntax, @interface, methods, uriAttribute, attributeCtorUsageAttribute);
return true;
}
/// <summary>
/// 是否为http接口
/// </summary>
/// <param name="interface"></param>
/// <param name="ihttpApi"></param>
/// <param name="iapiAttribute"></param>
/// <returns></returns>
private static bool IsHttpApiInterface(INamedTypeSymbol @interface, INamedTypeSymbol ihttpApi, INamedTypeSymbol? iapiAttribute)
{
if (@interface.AllInterfaces.Contains(ihttpApi))
{
return true;
}
if (iapiAttribute == null)
{
return false;
}
return @interface.AllInterfaces.Append(@interface).Any(i =>
HasAttribute(i, iapiAttribute) || i.GetMembers().OfType<IMethodSymbol>().Any(m =>
HasAttribute(m, iapiAttribute) || m.Parameters.Any(p => HasAttribute(p, iapiAttribute))));
}
/// <summary>
/// 返回是否声明指定的特性
/// </summary>
/// <param name="symbol"></param>
/// <param name="attribute"></param>
/// <returns></returns>
private static bool HasAttribute(ISymbol symbol, INamedTypeSymbol attribute)
{
foreach (var attr in symbol.GetAttributes())
{
var attrClass = attr.AttributeClass;
if (attrClass != null && attrClass.AllInterfaces.Contains(attribute))
{
return true;
}
}
return false;
}
}
}