Skip to content

Commit 3c941e9

Browse files
committed
Use GetMethod.Match
1 parent ce9d32b commit 3c941e9

6 files changed

Lines changed: 184 additions & 176 deletions

File tree

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
namespace ReflectionAnalyzers.Tests.Helpers.Reflection
2+
{
3+
using System.Threading;
4+
5+
using Gu.Roslyn.Asserts;
6+
7+
using Microsoft.CodeAnalysis.CSharp;
8+
9+
using NUnit.Framework;
10+
11+
public static class GetMethodTests
12+
{
13+
[TestCase("typeof(System.Array).GetMethod(nameof(System.Array.CreateInstance), new[] { typeof(System.Type), typeof(int) })", "System.Array.CreateInstance(System.Type, int)")]
14+
[TestCase("typeof(System.Array).GetMethod(nameof(System.Array.CreateInstance), BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly, null, new[] { typeof(Type), typeof(int) }, null)", "System.Array.CreateInstance(System.Type, int)")]
15+
[TestCase("typeof(System.Activator).GetMethod(nameof(System.Activator.CreateInstance), new[] { typeof(System.Reflection.TypeInfo) })", "System.Activator.CreateInstance(System.Type)")]
16+
[TestCase("typeof(System.Array).GetMethod(nameof(System.Array.GetValue), new[] { typeof(System.Int32) })", "System.Array.GetValue(int)")]
17+
[TestCase("typeof(System.Array).GetMethod(nameof(System.Array.GetValue), new[] { typeof(System.Int64) })", "System.Array.GetValue(long)")]
18+
public static void Success(string call, string expected)
19+
{
20+
var code = @"
21+
namespace N
22+
{
23+
using System;
24+
using System.Collections.Generic;
25+
using System.Reflection;
26+
27+
public class C
28+
{
29+
public object Get() => typeof(Array).GetMethod(nameof(Array.CreateInstance), new[] { typeof(Type), typeof(int) });
30+
}
31+
}".AssertReplace("typeof(Array).GetMethod(nameof(Array.CreateInstance), new[] { typeof(Type), typeof(int) })", call);
32+
33+
var syntaxTree = CSharpSyntaxTree.ParseText(code);
34+
var compilation = CSharpCompilation.Create("test", new[] { syntaxTree }, Settings.Default.MetadataReferences);
35+
var semanticModel = compilation.GetSemanticModel(syntaxTree);
36+
var invocation = syntaxTree.FindInvocation("GetMethod");
37+
var match = GetMethod.Match(invocation, semanticModel, CancellationToken.None);
38+
Assert.AreEqual(FilterMatch.Single, match?.Member.Match);
39+
Assert.AreEqual(expected, match?.Member.Symbol.ToDisplayString());
40+
Assert.AreEqual(expected, match?.Single.ToDisplayString());
41+
}
42+
43+
[TestCase("typeof(Array).GetMethod(nameof(Array.CreateInstance), new[] { typeof(Type), typeof(string) })")]
44+
[TestCase("typeof(Activator).GetMethod(nameof(Activator.CreateInstance), new[] { typeof(object) })")]
45+
[TestCase("typeof(Activator).GetMethod(nameof(Activator.CreateInstance), new[] { typeof(MemberInfo) })")]
46+
[TestCase("typeof(System.Array).GetMethod(nameof(System.Array.GetValue), new[] { typeof(System.IFormattable) })")]
47+
public static void NoMatch(string call)
48+
{
49+
var code = @"
50+
namespace N
51+
{
52+
using System;
53+
using System.Collections.Generic;
54+
using System.Reflection;
55+
56+
public class C
57+
{
58+
public object Get() => typeof(Array).GetMethod(nameof(Array.CreateInstance), BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly, null, new[] { typeof(Type), typeof(int) }, null);
59+
}
60+
}".AssertReplace("typeof(Array).GetMethod(nameof(Array.CreateInstance), BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly, null, new[] { typeof(Type), typeof(int) }, null)", call);
61+
62+
var syntaxTree = CSharpSyntaxTree.ParseText(code);
63+
var compilation = CSharpCompilation.Create("test", new[] { syntaxTree }, Settings.Default.MetadataReferences);
64+
var semanticModel = compilation.GetSemanticModel(syntaxTree);
65+
var invocation = syntaxTree.FindInvocation("GetMethod");
66+
var match = GetMethod.Match(invocation, semanticModel, CancellationToken.None);
67+
Assert.AreEqual(FilterMatch.WrongTypes, match?.Member.Match);
68+
}
69+
70+
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(IComparable) })", "N.C.M(System.IComparable)")]
71+
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(IConvertible) })", "N.C.M(System.IConvertible)")]
72+
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(IEquatable<int>) })", "N.C.M(System.IEquatable<int>)")]
73+
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(IEquatable<double>) })", "N.C.M(System.IEquatable<double>)")]
74+
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(IComparable<int>) })", "N.C.M(System.IComparable<int>)")]
75+
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(IComparable<double>) })", "N.C.M(System.IComparable<double>)")]
76+
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(int) })", "N.C.M(int)")]
77+
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(double) })", "N.C.M(double)")]
78+
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(IFormattable) })", "N.C.M(System.IFormattable)")]
79+
public static void SuccessWhenInSameType(string call, string expected)
80+
{
81+
var code = @"
82+
namespace N
83+
{
84+
using System;
85+
using System.Collections.Generic;
86+
using System.Reflection;
87+
88+
public class C
89+
{
90+
public object Get => typeof(C).GetMethod(nameof(M), new[] { typeof(int) });
91+
92+
public static void M(IComparable _) { }
93+
94+
public static void M(IConvertible _) { }
95+
96+
public static void M(IEquatable<int> _) { }
97+
98+
public static void M(IEquatable<double> _) { }
99+
100+
public static void M(IComparable<int> _) { }
101+
102+
public static void M(IComparable<double> _) { }
103+
104+
public static void M(int _) { }
105+
106+
public static void M(double _) { }
107+
108+
public static void M(IFormattable _) { }
109+
}
110+
}".AssertReplace("typeof(C).GetMethod(nameof(M), new[] { typeof(int) })", call);
111+
112+
var syntaxTree = CSharpSyntaxTree.ParseText(code);
113+
var compilation = CSharpCompilation.Create("test", new[] { syntaxTree }, Settings.Default.MetadataReferences);
114+
var semanticModel = compilation.GetSemanticModel(syntaxTree);
115+
var invocation = syntaxTree.FindInvocation("GetMethod");
116+
var match = GetMethod.Match(invocation, semanticModel, CancellationToken.None);
117+
Assert.AreEqual(FilterMatch.Single, match?.Member.Match);
118+
Assert.AreEqual(expected, match?.Member.Symbol.ToDisplayString());
119+
Assert.AreEqual(expected, match?.Single.ToDisplayString());
120+
}
121+
122+
[TestCase("typeof(A).GetMethod(\"M\", new[] { typeof(int) })", "N.A.M(int)")]
123+
[TestCase("typeof(B).GetMethod(\"M\", new[] { typeof(int) })", "N.A.M(int)")]
124+
[TestCase("typeof(B).GetMethod(\"M\", new[] { typeof(double) })", "N.B.M(double)")]
125+
public static void WhenInheritance(string call, string expected)
126+
{
127+
var code = @"
128+
namespace N
129+
{
130+
using System;
131+
132+
public class A
133+
{
134+
public void M(int i) { }
135+
}
136+
137+
public class B : A
138+
{
139+
public void M(double i) { }
140+
}
141+
142+
public class C
143+
{
144+
public object Get => typeof(A).GetMethod(""M"", new[] { typeof(int) });
145+
}
146+
}".AssertReplace("typeof(A).GetMethod(\"M\", new[] { typeof(int) })", call);
147+
148+
var syntaxTree = CSharpSyntaxTree.ParseText(code);
149+
var compilation = CSharpCompilation.Create("test", new[] { syntaxTree }, Settings.Default.MetadataReferences);
150+
var semanticModel = compilation.GetSemanticModel(syntaxTree);
151+
var invocation = syntaxTree.FindInvocation("GetMethod");
152+
var match = GetMethod.Match(invocation, semanticModel, CancellationToken.None);
153+
Assert.AreEqual(FilterMatch.Single, match?.Member.Match);
154+
Assert.AreEqual(expected, match?.Member.Symbol.ToDisplayString());
155+
Assert.AreEqual(expected, match?.Single.ToDisplayString());
156+
}
157+
158+
[Test]
159+
public static void MatchWhenWrongFlagsWhenNotVisible()
160+
{
161+
var code = @"
162+
namespace N
163+
{
164+
using System;
165+
using System.Reflection;
166+
using System.Windows.Forms;
167+
168+
class C
169+
{
170+
public object Get => typeof(Control).GetMethod(nameof(Control.CreateControl), BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(bool) }, null);
171+
}
172+
}";
173+
var syntaxTree = CSharpSyntaxTree.ParseText(code);
174+
var compilation = CSharpCompilation.Create("test", new[] { syntaxTree }, Settings.Default.MetadataReferences);
175+
var semanticModel = compilation.GetSemanticModel(syntaxTree);
176+
var invocation = syntaxTree.FindInvocation("GetMethod");
177+
var match = GetMethod.Match(invocation, semanticModel, CancellationToken.None);
178+
Assert.AreEqual(FilterMatch.PotentiallyInvisible, match?.Member.Match);
179+
}
180+
}
181+
}

ReflectionAnalyzers.Tests/Helpers/Reflection/GetXTests.GetMethodOverloadResolution.cs

Lines changed: 0 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -9,147 +9,7 @@ public static partial class GetXTests
99
{
1010
public static class GetMethodOverloadResolution
1111
{
12-
[TestCase("typeof(System.Array).GetMethod(nameof(System.Array.CreateInstance), new[] { typeof(System.Type), typeof(int) })", "System.Array.CreateInstance(System.Type, int)")]
13-
[TestCase("typeof(System.Array).GetMethod(nameof(System.Array.CreateInstance), BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly, null, new[] { typeof(Type), typeof(int) }, null)", "System.Array.CreateInstance(System.Type, int)")]
14-
[TestCase("typeof(System.Activator).GetMethod(nameof(System.Activator.CreateInstance), new[] { typeof(System.Reflection.TypeInfo) })", "System.Activator.CreateInstance(System.Type)")]
15-
[TestCase("typeof(System.Array).GetMethod(nameof(System.Array.GetValue), new[] { typeof(System.Int32) })", "System.Array.GetValue(int)")]
16-
[TestCase("typeof(System.Array).GetMethod(nameof(System.Array.GetValue), new[] { typeof(System.Int64) })", "System.Array.GetValue(long)")]
17-
public static void Success(string call, string expected)
18-
{
19-
var code = @"
20-
namespace N
21-
{
22-
using System;
23-
using System.Collections.Generic;
24-
using System.Reflection;
25-
26-
public class C
27-
{
28-
public object Get() => typeof(Array).GetMethod(nameof(Array.CreateInstance), new[] { typeof(Type), typeof(int) });
29-
}
30-
}".AssertReplace("typeof(Array).GetMethod(nameof(Array.CreateInstance), new[] { typeof(Type), typeof(int) })", call);
31-
32-
var syntaxTree = CSharpSyntaxTree.ParseText(code);
33-
var compilation = CSharpCompilation.Create("test", new[] { syntaxTree }, Settings.Default.MetadataReferences);
34-
var semanticModel = compilation.GetSemanticModel(syntaxTree);
35-
var invocation = syntaxTree.FindInvocation("GetMethod");
36-
Assert.AreEqual(true, GetX.TryMatchGetMethod(invocation, semanticModel, CancellationToken.None, out var reflectedMember, out _, out _, out _));
37-
Assert.AreEqual(FilterMatch.Single, reflectedMember.Match);
38-
Assert.AreEqual(expected, reflectedMember.Symbol.ToDisplayString());
39-
}
40-
41-
[TestCase("typeof(Array).GetMethod(nameof(Array.CreateInstance), new[] { typeof(Type), typeof(string) })")]
42-
[TestCase("typeof(Activator).GetMethod(nameof(Activator.CreateInstance), new[] { typeof(object) })")]
43-
[TestCase("typeof(Activator).GetMethod(nameof(Activator.CreateInstance), new[] { typeof(MemberInfo) })")]
44-
[TestCase("typeof(System.Array).GetMethod(nameof(System.Array.GetValue), new[] { typeof(System.IFormattable) })")]
45-
public static void NoMatch(string call)
46-
{
47-
var code = @"
48-
namespace N
49-
{
50-
using System;
51-
using System.Collections.Generic;
52-
using System.Reflection;
53-
54-
public class C
55-
{
56-
public object Get() => typeof(Array).GetMethod(nameof(Array.CreateInstance), BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly, null, new[] { typeof(Type), typeof(int) }, null);
57-
}
58-
}".AssertReplace("typeof(Array).GetMethod(nameof(Array.CreateInstance), BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly, null, new[] { typeof(Type), typeof(int) }, null)", call);
59-
60-
var syntaxTree = CSharpSyntaxTree.ParseText(code);
61-
var compilation = CSharpCompilation.Create("test", new[] { syntaxTree }, Settings.Default.MetadataReferences);
62-
var semanticModel = compilation.GetSemanticModel(syntaxTree);
63-
var invocation = syntaxTree.FindInvocation("GetMethod");
64-
Assert.AreEqual(true, GetX.TryMatchGetMethod(invocation, semanticModel, CancellationToken.None, out var reflectedMember, out _, out _, out _));
65-
Assert.AreEqual(FilterMatch.WrongTypes, reflectedMember.Match);
66-
}
67-
68-
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(IComparable) })", "N.C.M(System.IComparable)")]
69-
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(IConvertible) })", "N.C.M(System.IConvertible)")]
70-
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(IEquatable<int>) })", "N.C.M(System.IEquatable<int>)")]
71-
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(IEquatable<double>) })", "N.C.M(System.IEquatable<double>)")]
72-
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(IComparable<int>) })", "N.C.M(System.IComparable<int>)")]
73-
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(IComparable<double>) })", "N.C.M(System.IComparable<double>)")]
74-
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(int) })", "N.C.M(int)")]
75-
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(double) })", "N.C.M(double)")]
76-
[TestCase("typeof(C).GetMethod(nameof(M), new[] { typeof(IFormattable) })", "N.C.M(System.IFormattable)")]
77-
public static void SuccessWhenInSameType(string call, string expected)
78-
{
79-
var code = @"
80-
namespace N
81-
{
82-
using System;
83-
using System.Collections.Generic;
84-
using System.Reflection;
85-
86-
public class C
87-
{
88-
public object Get => typeof(C).GetMethod(nameof(M), new[] { typeof(int) });
89-
90-
public static void M(IComparable _) { }
91-
92-
public static void M(IConvertible _) { }
93-
94-
public static void M(IEquatable<int> _) { }
95-
96-
public static void M(IEquatable<double> _) { }
97-
98-
public static void M(IComparable<int> _) { }
99-
100-
public static void M(IComparable<double> _) { }
101-
102-
public static void M(int _) { }
103-
104-
public static void M(double _) { }
105-
106-
public static void M(IFormattable _) { }
107-
}
108-
}".AssertReplace("typeof(C).GetMethod(nameof(M), new[] { typeof(int) })", call);
109-
110-
var syntaxTree = CSharpSyntaxTree.ParseText(code);
111-
var compilation = CSharpCompilation.Create("test", new[] { syntaxTree }, Settings.Default.MetadataReferences);
112-
var semanticModel = compilation.GetSemanticModel(syntaxTree);
113-
var invocation = syntaxTree.FindInvocation("GetMethod");
114-
Assert.AreEqual(true, GetX.TryMatchGetMethod(invocation, semanticModel, CancellationToken.None, out var reflectedMember, out _, out _, out _));
115-
Assert.AreEqual(FilterMatch.Single, reflectedMember.Match);
116-
Assert.AreEqual(expected, reflectedMember.Symbol.ToDisplayString());
117-
}
118-
119-
[TestCase("typeof(A).GetMethod(\"M\", new[] { typeof(int) })", "N.A.M(int)")]
120-
[TestCase("typeof(B).GetMethod(\"M\", new[] { typeof(int) })", "N.A.M(int)")]
121-
[TestCase("typeof(B).GetMethod(\"M\", new[] { typeof(double) })", "N.B.M(double)")]
122-
public static void SuccessWhenInheritance(string call, string expected)
123-
{
124-
var code = @"
125-
namespace N
126-
{
127-
using System;
128-
129-
public class A
130-
{
131-
public void M(int i) { }
132-
}
133-
134-
public class B : A
135-
{
136-
public void M(double i) { }
137-
}
138-
139-
public class C
140-
{
141-
public object Get => typeof(A).GetMethod(""M"", new[] { typeof(int) });
142-
}
143-
}".AssertReplace("typeof(A).GetMethod(\"M\", new[] { typeof(int) })", call);
14412

145-
var syntaxTree = CSharpSyntaxTree.ParseText(code);
146-
var compilation = CSharpCompilation.Create("test", new[] { syntaxTree }, Settings.Default.MetadataReferences);
147-
var semanticModel = compilation.GetSemanticModel(syntaxTree);
148-
var invocation = syntaxTree.FindInvocation("GetMethod");
149-
Assert.AreEqual(true, GetX.TryMatchGetMethod(invocation, semanticModel, CancellationToken.None, out var reflectedMember, out _, out _, out _));
150-
Assert.AreEqual(FilterMatch.Single, reflectedMember.Match);
151-
Assert.AreEqual(expected, reflectedMember.Symbol.ToDisplayString());
152-
}
15313
}
15414
}
15515
}

ReflectionAnalyzers.Tests/Helpers/Reflection/GetXTests.cs

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

ReflectionAnalyzers/Helpers/Reflection/GetMethod.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ private GetMethod(InvocationExpressionSyntax invocation, IMethodSymbol target, R
2727
this.Types = types;
2828
}
2929

30-
internal IMethodSymbol? SingleMatch => this.Member.Match == FilterMatch.Single ? (IMethodSymbol)this.Member.Symbol! : null;
30+
internal IMethodSymbol? Single => this.Member.Match == FilterMatch.Single ? (IMethodSymbol)this.Member.Symbol! : null;
3131

3232
internal static GetMethod? Match(ExpressionSyntax candidate, SemanticModel semanticModel, CancellationToken cancellationToken)
3333
{

ReflectionAnalyzers/Helpers/Reflection/TypeArguments.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ private static bool TryGetTypeParameters(InvocationExpressionSyntax invocation,
142142
private static bool TryGetMethodParameters(InvocationExpressionSyntax invocation, SemanticModel semanticModel, CancellationToken cancellationToken, [NotNullWhen(true)] out ISymbol? symbol, out ImmutableArray<ITypeParameterSymbol> parameters)
143143
{
144144
if (IsMakeGeneric(invocation, KnownSymbol.MethodInfo.MakeGenericMethod, semanticModel, cancellationToken) &&
145-
GetMethod.Match(invocation.Expression, semanticModel, cancellationToken) is { SingleMatch: { } method })
145+
GetMethod.Match(invocation.Expression, semanticModel, cancellationToken) is { Single: { } method })
146146
{
147147
symbol = method;
148148
parameters = method.TypeParameters;

0 commit comments

Comments
 (0)