Skip to content

Commit e7f4480

Browse files
committed
TryMatchGetConstructor
1 parent 0b8eb2e commit e7f4480

File tree

4 files changed

+74
-8
lines changed

4 files changed

+74
-8
lines changed

ReflectionAnalyzers/Helpers/GetX.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,30 @@ internal static class GetX
1717
public static IReadOnlyList<ITypeSymbol> AnyTypes = new ITypeSymbol[0];
1818
#pragma warning restore CA1825 // Avoid zero-length array allocations.
1919

20+
/// <summary>
21+
/// Check if <paramref name="invocation"/> is a call to Type.GetMethod
22+
/// </summary>
23+
internal static GetXResult? TryMatchGetConstructor(InvocationExpressionSyntax invocation, SyntaxNodeAnalysisContext context, out ITypeSymbol targetType, out ISymbol target, out ArgumentSyntax flagsArg, out BindingFlags effectiveFlags, out ArgumentSyntax typesArg, out IReadOnlyList<ITypeSymbol> types)
24+
{
25+
targetType = null;
26+
target = null;
27+
flagsArg = null;
28+
effectiveFlags = 0;
29+
typesArg = null;
30+
types = null;
31+
if (invocation.ArgumentList != null &&
32+
invocation.TryGetTarget(KnownSymbol.Type.GetConstructor, context.SemanticModel, context.CancellationToken, out var getX) &&
33+
TryGetTargetType(invocation, context, out targetType, out _) &&
34+
IsKnownSignature(invocation, getX) &&
35+
TryGetFlagsOrDefault(invocation, getX, context, out flagsArg, out effectiveFlags) &&
36+
TryGetTypesOrDefault(invocation, getX, context, out typesArg, out types))
37+
{
38+
return TryGetTarget(getX, targetType, ".ctor", effectiveFlags, types, context, out target);
39+
}
40+
41+
return null;
42+
}
43+
2044
/// <summary>
2145
/// Check if <paramref name="invocation"/> is a call to Type.GetEvent
2246
/// </summary>

ReflectionAnalyzers/Helpers/KnownSymbols/TypeType.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ namespace ReflectionAnalyzers
44

55
internal class TypeType : QualifiedType
66
{
7+
internal readonly QualifiedMethod GetConstructor;
78
internal readonly QualifiedMethod GetEvent;
89
internal readonly QualifiedMethod GetField;
910
internal readonly QualifiedMethod GetMember;
@@ -14,6 +15,7 @@ internal class TypeType : QualifiedType
1415
internal TypeType()
1516
: base("System.Type")
1617
{
18+
this.GetConstructor = new QualifiedMethod(this, nameof(this.GetConstructor));
1719
this.GetEvent = new QualifiedMethod(this, nameof(this.GetEvent));
1820
this.GetField = new QualifiedMethod(this, nameof(this.GetField));
1921
this.GetMember = new QualifiedMethod(this, nameof(this.GetMember));

ReflectionAnalyzers/NodeAnalzers/GetXAnalyzer.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -156,18 +156,21 @@ explicitMemberAccess.Expression is TypeOfExpressionSyntax typeOf
156156
}
157157
}
158158

159-
private static GetXResult TryGetX(SyntaxNodeAnalysisContext context, out ITypeSymbol targetType, out ArgumentSyntax nameArg, out string targetName, out ISymbol target, out ArgumentSyntax flagsArg, out BindingFlags flags, out ArgumentSyntax typesArg, out IReadOnlyList<ITypeSymbol> types)
159+
private static GetXResult TryGetX(SyntaxNodeAnalysisContext context, out ITypeSymbol targetType, out ArgumentSyntax nameArg, out string targetName, out ISymbol target, out ArgumentSyntax flagsArg, out BindingFlags effectiveFlags, out ArgumentSyntax typesArg, out IReadOnlyList<ITypeSymbol> types)
160160
{
161+
nameArg = null;
162+
targetName = null;
161163
typesArg = null;
162164
types = null;
163165
if (context.Node is InvocationExpressionSyntax candidate)
164166
{
165-
var result = GetX.TryMatchGetEvent(candidate, context, out targetType, out nameArg, out targetName, out target, out flagsArg, out flags) ??
166-
GetX.TryMatchGetField(candidate, context, out targetType, out nameArg, out targetName, out target, out flagsArg, out flags) ??
167-
GetX.TryMatchGetMember(candidate, context, out targetType, out nameArg, out targetName, out target, out flagsArg, out flags, out typesArg, out types) ??
168-
GetX.TryMatchGetMethod(candidate, context, out targetType, out nameArg, out targetName, out target, out flagsArg, out flags, out typesArg, out types) ??
169-
GetX.TryMatchGetNestedType(candidate, context, out targetType, out nameArg, out targetName, out target, out flagsArg, out flags) ??
170-
GetX.TryMatchGetProperty(candidate, context, out targetType, out nameArg, out targetName, out target, out flagsArg, out flags);
167+
var result = GetX.TryMatchGetConstructor(candidate, context, out targetType, out target, out flagsArg, out effectiveFlags, out typesArg, out types) ??
168+
GetX.TryMatchGetEvent(candidate, context, out targetType, out nameArg, out targetName, out target, out flagsArg, out effectiveFlags) ??
169+
GetX.TryMatchGetField(candidate, context, out targetType, out nameArg, out targetName, out target, out flagsArg, out effectiveFlags) ??
170+
GetX.TryMatchGetMember(candidate, context, out targetType, out nameArg, out targetName, out target, out flagsArg, out effectiveFlags, out typesArg, out types) ??
171+
GetX.TryMatchGetMethod(candidate, context, out targetType, out nameArg, out targetName, out target, out flagsArg, out effectiveFlags, out typesArg, out types) ??
172+
GetX.TryMatchGetNestedType(candidate, context, out targetType, out nameArg, out targetName, out target, out flagsArg, out effectiveFlags) ??
173+
GetX.TryMatchGetProperty(candidate, context, out targetType, out nameArg, out targetName, out target, out flagsArg, out effectiveFlags);
171174
if (result != null)
172175
{
173176
return result.Value;
@@ -179,7 +182,7 @@ private static GetXResult TryGetX(SyntaxNodeAnalysisContext context, out ITypeSy
179182
targetName = null;
180183
target = null;
181184
flagsArg = null;
182-
flags = BindingFlags.Default;
185+
effectiveFlags = BindingFlags.Default;
183186
return GetXResult.Unknown;
184187
}
185188

ValidCode/GetConstructor.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
namespace ValidCode
2+
{
3+
using System;
4+
using System.Reflection;
5+
6+
public class GetConstructor
7+
{
8+
public GetConstructor()
9+
{
10+
_ = typeof(Default).GetConstructor(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, Type.EmptyTypes, null);
11+
_ = typeof(Single).GetConstructor(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, Type.EmptyTypes, null);
12+
_ = typeof(Two).GetConstructor(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, new[] { typeof(int) }, null);
13+
_ = typeof(Two).GetConstructor(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, new[] { typeof(double) }, null);
14+
}
15+
public class Default
16+
{
17+
}
18+
19+
public class Single
20+
{
21+
public Single()
22+
{
23+
}
24+
}
25+
26+
public class Two
27+
{
28+
public Two(int value)
29+
{
30+
}
31+
32+
public Two(double value)
33+
{
34+
}
35+
}
36+
}
37+
}

0 commit comments

Comments
 (0)