Skip to content

Commit 75d5bd0

Browse files
committed
Revert "去掉 Object 这一套的代码"
This reverts commit 14661fb.
1 parent 506dc95 commit 75d5bd0

File tree

65 files changed

+5981
-3
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+5981
-3
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using dotnetCampus.Ipc.Analyzers.Compiling;
2+
3+
namespace dotnetCampus.Ipc.Analyzers;
4+
5+
[DiagnosticAnalyzer(LanguageNames.CSharp)]
6+
public class AddIpcProxyConfigsAnalyzer : DiagnosticAnalyzer
7+
{
8+
public AddIpcProxyConfigsAnalyzer()
9+
{
10+
SupportedDiagnostics = ImmutableArray.Create(
11+
IPC301_CreateIpcProxy_AddIpcProxyConfigs,
12+
IPC303_CreateIpcProxy_AddIpcProxyConfigs);
13+
}
14+
15+
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; }
16+
17+
public override void Initialize(AnalysisContext context)
18+
{
19+
context.EnableConcurrentExecution();
20+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
21+
22+
context.RegisterSyntaxNodeAction(AnalyzeIpcPublicAttributes, SyntaxKind.SimpleMemberAccessExpression);
23+
}
24+
25+
private void AnalyzeIpcPublicAttributes(SyntaxNodeAnalysisContext context)
26+
{
27+
if (context.Node is MemberAccessExpressionSyntax memberAccessNode
28+
&& IpcProxyInvokingInfo.TryCreateIpcProxyInvokingInfo(
29+
context.SemanticModel,
30+
memberAccessNode,
31+
context.CancellationToken) is { } invokingInfo)
32+
{
33+
if (invokingInfo.ShapeType is null)
34+
{
35+
context.ReportDiagnostic(
36+
Diagnostic.Create(IPC301_CreateIpcProxy_AddIpcProxyConfigs,
37+
memberAccessNode.GetLocation()));
38+
context.ReportDiagnostic(
39+
Diagnostic.Create(IPC303_CreateIpcProxy_AddIpcProxyConfigs,
40+
memberAccessNode.GetLocation()));
41+
}
42+
}
43+
}
44+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using dotnetCampus.Ipc.Analyzers.Compiling;
2+
3+
namespace dotnetCampus.Ipc.Analyzers;
4+
5+
[DiagnosticAnalyzer(LanguageNames.CSharp)]
6+
public class AddIpcShapeAnalyzer : DiagnosticAnalyzer
7+
{
8+
public AddIpcShapeAnalyzer()
9+
{
10+
SupportedDiagnostics = ImmutableArray.Create(IPC302_CreateIpcProxy_AddIpcShape);
11+
}
12+
13+
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; }
14+
15+
public override void Initialize(AnalysisContext context)
16+
{
17+
context.EnableConcurrentExecution();
18+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
19+
20+
context.RegisterSyntaxNodeAction(AnalyzeIpcPublicAttributes, SyntaxKind.SimpleMemberAccessExpression);
21+
}
22+
23+
private void AnalyzeIpcPublicAttributes(SyntaxNodeAnalysisContext context)
24+
{
25+
if (context.Node is MemberAccessExpressionSyntax memberAccessNode
26+
&& IpcProxyInvokingInfo.TryCreateIpcProxyInvokingInfo(
27+
context.SemanticModel,
28+
memberAccessNode,
29+
context.CancellationToken) is { } invokingInfo)
30+
{
31+
if (invokingInfo.ShapeType is null)
32+
{
33+
context.ReportDiagnostic(
34+
Diagnostic.Create(IPC302_CreateIpcProxy_AddIpcShape,
35+
memberAccessNode.GetLocation()));
36+
}
37+
}
38+
}
39+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
using dotnetCampus.Ipc.CodeAnalysis.Models;
2+
using dotnetCampus.Ipc.Generators.Compiling;
3+
4+
namespace dotnetCampus.Ipc.Analyzers.Compiling;
5+
6+
internal static class IpcAttributeHelper
7+
{
8+
public static IEnumerable<(AttributeSyntax attributeNode, IpcPublicAttributeNamedValues namedValues)> TryFindIpcPublicAttributes(
9+
SemanticModel semanticModel, InterfaceDeclarationSyntax typeDeclarationNode)
10+
{
11+
var typeSymbol = semanticModel.GetDeclaredSymbol(typeDeclarationNode);
12+
if (typeSymbol is null)
13+
{
14+
yield break;
15+
}
16+
17+
if (typeDeclarationNode.AttributeLists.SelectMany(x => x.Attributes).FirstOrDefault(x =>
18+
{
19+
string? attributeName = x.Name switch
20+
{
21+
IdentifierNameSyntax identifierName => identifierName.ToString(),
22+
QualifiedNameSyntax qualifiedName => qualifiedName.ChildNodes().OfType<IdentifierNameSyntax>().LastOrDefault()?.ToString(),
23+
_ => null,
24+
};
25+
return attributeName is not null &&
26+
(attributeName.Equals(nameof(IpcPublicAttribute), StringComparison.Ordinal)
27+
|| attributeName.Equals(GetAttributeName(nameof(IpcPublicAttribute)), StringComparison.Ordinal));
28+
}) is { } attributeNode)
29+
{
30+
var namedValues = typeSymbol.GetIpcPublicNamedValues();
31+
yield return (attributeNode, namedValues);
32+
}
33+
}
34+
35+
public static IEnumerable<(AttributeSyntax attributeNode, IpcShapeAttributeNamedValues namedValues)> TryFindIpcShapeAttributes(
36+
SemanticModel semanticModel, ClassDeclarationSyntax typeDeclarationNode)
37+
{
38+
var typeSymbol = semanticModel.GetDeclaredSymbol(typeDeclarationNode);
39+
if (typeSymbol is null)
40+
{
41+
yield break;
42+
}
43+
44+
if (typeDeclarationNode.AttributeLists.SelectMany(x => x.Attributes).FirstOrDefault(x =>
45+
{
46+
string? attributeName = x.Name switch
47+
{
48+
IdentifierNameSyntax identifierName => identifierName.ToString(),
49+
QualifiedNameSyntax qualifiedName => qualifiedName.ChildNodes().OfType<IdentifierNameSyntax>().LastOrDefault()?.ToString(),
50+
_ => null,
51+
};
52+
return attributeName is not null &&
53+
(attributeName.Equals(nameof(IpcShapeAttribute), StringComparison.Ordinal)
54+
|| attributeName.Equals(GetAttributeName(nameof(IpcShapeAttribute)), StringComparison.Ordinal));
55+
}) is { } attributeNode)
56+
{
57+
var namedValues = typeSymbol.GetIpcShapeNamedValues();
58+
yield return (attributeNode, namedValues);
59+
}
60+
}
61+
62+
public static IEnumerable<(AttributeSyntax? attributeNode, IpcPublicAttributeNamedValues namedValues)> TryFindMemberAttributes(
63+
SemanticModel semanticModel, TypeDeclarationSyntax typeDeclarationNode)
64+
{
65+
if (TryFindIpcPublicType(semanticModel, typeDeclarationNode, out var compilation))
66+
{
67+
foreach (var (contractType, member) in compilation.EnumerateMembers())
68+
{
69+
var namedValues = member switch
70+
{
71+
IPropertySymbol propertySymbol => propertySymbol.GetIpcNamedValues(contractType),
72+
IMethodSymbol methodSymbol => methodSymbol.GetIpcNamedValues(null, contractType),
73+
_ => null,
74+
};
75+
if (namedValues is null)
76+
{
77+
continue;
78+
}
79+
80+
var memberNode = typeDeclarationNode.DescendantNodes()
81+
.Where(x => x is PropertyDeclarationSyntax or MethodDeclarationSyntax)
82+
.FirstOrDefault(x => x switch
83+
{
84+
PropertyDeclarationSyntax propertyDeclarationSyntax => SymbolEqualityComparer.Default.Equals(member, semanticModel.GetDeclaredSymbol(propertyDeclarationSyntax)),
85+
MethodDeclarationSyntax methodDeclarationSyntax => SymbolEqualityComparer.Default.Equals(member, semanticModel.GetDeclaredSymbol(methodDeclarationSyntax)),
86+
_ => false,
87+
}) as MemberDeclarationSyntax;
88+
if (memberNode is not null && memberNode.AttributeLists.SelectMany(x => x.Attributes).FirstOrDefault(x =>
89+
{
90+
string? attributeName = x.Name switch
91+
{
92+
IdentifierNameSyntax identifierName => identifierName.ToString(),
93+
QualifiedNameSyntax qualifiedName => qualifiedName.ChildNodes().OfType<IdentifierNameSyntax>().LastOrDefault()?.ToString(),
94+
_ => null,
95+
};
96+
return attributeName is not null &&
97+
(attributeName.Equals(nameof(IpcPropertyAttribute), StringComparison.Ordinal)
98+
|| attributeName.Equals(GetAttributeName(nameof(IpcPropertyAttribute)), StringComparison.Ordinal)
99+
|| attributeName.Equals(nameof(IpcMethodAttribute), StringComparison.Ordinal)
100+
|| attributeName.Equals(GetAttributeName(nameof(IpcMethodAttribute)), StringComparison.Ordinal));
101+
}) is { } attributeNode)
102+
{
103+
yield return (attributeNode, namedValues);
104+
}
105+
else
106+
{
107+
yield return (null, namedValues);
108+
}
109+
}
110+
}
111+
}
112+
113+
private static bool TryFindIpcPublicType(SemanticModel semanticModel, TypeDeclarationSyntax typeDeclarationNode,
114+
[NotNullWhen(true)] out IpcPublicCompilation? publicIpcObjectCompilation)
115+
{
116+
if (semanticModel.GetDeclaredSymbol(typeDeclarationNode) is { } typeDeclarationSymbol
117+
&& typeDeclarationSymbol.GetAttributes().FirstOrDefault(x => string.Equals(
118+
x.AttributeClass?.ToString(),
119+
typeof(IpcPublicAttribute).FullName,
120+
StringComparison.Ordinal)) is { } ipcPublicAttribute)
121+
{
122+
publicIpcObjectCompilation = new(typeDeclarationNode.SyntaxTree, semanticModel, typeDeclarationSymbol);
123+
return true;
124+
}
125+
publicIpcObjectCompilation = null;
126+
return false;
127+
}
128+
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
namespace dotnetCampus.Ipc.Analyzers.Compiling;
2+
3+
/// <summary>
4+
/// 用语法节点和语义模型描述一次方法调用。
5+
/// </summary>
6+
[DebuggerDisplay("{MemberAccessNode.GetLocation()?.SourceSpan.Start,nq}: {MemberAccessNode.ToFullString(),nq}")]
7+
internal struct IpcProxyInvokingInfo
8+
{
9+
private IpcProxyInvokingInfo(SemanticModel semanticModel, MemberAccessExpressionSyntax memberAccessNode,
10+
IMethodSymbol methodSymbol, INamedTypeSymbol contractType)
11+
{
12+
SemanticModel = semanticModel;
13+
MemberAccessNode = memberAccessNode ?? throw new ArgumentNullException(nameof(memberAccessNode));
14+
MethodSymbol = methodSymbol ?? throw new ArgumentNullException(nameof(methodSymbol));
15+
ContractType = contractType ?? throw new ArgumentNullException(nameof(contractType));
16+
ShapeType = null;
17+
}
18+
19+
private IpcProxyInvokingInfo(SemanticModel semanticModel, MemberAccessExpressionSyntax memberAccessNode,
20+
IMethodSymbol methodSymbol, INamedTypeSymbol contractType, INamedTypeSymbol shapeType)
21+
{
22+
SemanticModel = semanticModel;
23+
MemberAccessNode = memberAccessNode ?? throw new ArgumentNullException(nameof(memberAccessNode));
24+
MethodSymbol = methodSymbol ?? throw new ArgumentNullException(nameof(methodSymbol));
25+
ContractType = contractType ?? throw new ArgumentNullException(nameof(contractType));
26+
ShapeType = shapeType ?? throw new ArgumentNullException(nameof(shapeType));
27+
}
28+
29+
/// <summary>
30+
/// 能用来解读本语法节点的语义模型。
31+
/// </summary>
32+
public SemanticModel SemanticModel { get; }
33+
34+
/// <summary>
35+
/// 本次调用这个方法时,调用的这一句语法节点。
36+
/// </summary>
37+
public MemberAccessExpressionSyntax MemberAccessNode { get; }
38+
39+
/// <summary>
40+
/// 本次所调用的方法的语义符号。
41+
/// </summary>
42+
public IMethodSymbol MethodSymbol { get; }
43+
44+
/// <summary>
45+
/// 本次调用的契约类型。
46+
/// </summary>
47+
public INamedTypeSymbol ContractType { get; }
48+
49+
/// <summary>
50+
/// 如果本次调用使用到了 IPC 代理壳,那么此属性是 IPC 代理壳的类型。
51+
/// </summary>
52+
public INamedTypeSymbol? ShapeType { get; }
53+
54+
/// <inheritdoc />
55+
public override int GetHashCode()
56+
{
57+
var hashCode = -25060616;
58+
hashCode = hashCode * -1521134295 + EqualityComparer<SemanticModel>.Default.GetHashCode(SemanticModel);
59+
hashCode = hashCode * -1521134295 + EqualityComparer<MemberAccessExpressionSyntax>.Default.GetHashCode(MemberAccessNode);
60+
hashCode = hashCode * -1521134295 + EqualityComparer<IMethodSymbol>.Default.GetHashCode(MethodSymbol);
61+
return hashCode;
62+
}
63+
64+
public static IpcProxyInvokingInfo? TryCreateIpcProxyInvokingInfo(SemanticModel semanticModel, MemberAccessExpressionSyntax memberAccessNode, CancellationToken cancellationToken)
65+
{
66+
var methodName = memberAccessNode.Name.Identifier.ValueText;
67+
if (methodName != "CreateIpcProxy")
68+
{
69+
// 初筛。
70+
return null;
71+
}
72+
73+
if (semanticModel.GetSymbolInfo(memberAccessNode, cancellationToken).Symbol is IMethodSymbol methodSymbol)
74+
{
75+
// 当前正在调用的方法是一个正常的方法。
76+
if (memberAccessNode.Name is GenericNameSyntax genericNameNode)
77+
{
78+
if (genericNameNode.TypeArgumentList.Arguments.Count == 1)
79+
{
80+
if (genericNameNode.TypeArgumentList.Arguments[0] is TypeSyntax typeArgumentNode
81+
&& semanticModel.GetSymbolInfo(typeArgumentNode, cancellationToken).Symbol is INamedTypeSymbol typeArgumentSymbol)
82+
{
83+
return new(semanticModel, memberAccessNode, methodSymbol, typeArgumentSymbol);
84+
}
85+
}
86+
else if (genericNameNode.TypeArgumentList.Arguments.Count == 2)
87+
{
88+
if (genericNameNode.TypeArgumentList.Arguments[0] is TypeSyntax contractTypeArgumentNode
89+
&& semanticModel.GetSymbolInfo(contractTypeArgumentNode, cancellationToken).Symbol is INamedTypeSymbol contractTypeArgumentSymbol
90+
&& genericNameNode.TypeArgumentList.Arguments[1] is TypeSyntax shapeTypeArgumentNode
91+
&& semanticModel.GetSymbolInfo(shapeTypeArgumentNode, cancellationToken).Symbol is INamedTypeSymbol shapeTypeArgumentSymbol)
92+
{
93+
return new(semanticModel, memberAccessNode, methodSymbol, contractTypeArgumentSymbol, shapeTypeArgumentSymbol);
94+
}
95+
}
96+
}
97+
else
98+
{
99+
// 无法解析。
100+
}
101+
}
102+
else
103+
{
104+
// 当前正在调用的方法无法找到对应的符号(编译不通过)。
105+
}
106+
return null;
107+
}
108+
109+
public static IEqualityComparer<IpcProxyInvokingInfo> ContractTypeEqualityComparer { get; } = new EqualityComparerByContractType();
110+
111+
private sealed class EqualityComparerByContractType : IEqualityComparer<IpcProxyInvokingInfo>
112+
{
113+
public bool Equals(IpcProxyInvokingInfo x, IpcProxyInvokingInfo y)
114+
{
115+
return false;
116+
}
117+
118+
public int GetHashCode(IpcProxyInvokingInfo info)
119+
{
120+
return info.GetHashCode();
121+
}
122+
}
123+
}

0 commit comments

Comments
 (0)