提交 280d6922 编写于 作者: A AlekseyTs

C# SemanticModel.GetSymbolInfo - Properly handle explicit method group conversions.

Fixes #3096.
上级 7c1dd49d
......@@ -3649,6 +3649,31 @@ private static ImmutableArray<MethodSymbol> FilterOverriddenOrHiddenMethods(Immu
}
break;
case BoundKind.Conversion:
// If we are looking for info on "M" in "(Action)M"
// we want to get the symbol that overload resolution chose for M, not the whole method group M.
var conversion = (BoundConversion)boundNodeForSyntacticParent;
var method = conversion.SymbolOpt;
if ((object)method != null)
{
Debug.Assert(conversion.ConversionKind == ConversionKind.MethodGroup);
if (conversion.IsExtensionMethod)
{
method = ReducedExtensionMethodSymbol.Create(method);
}
symbols = ImmutableArray.Create((Symbol)method);
resultKind = conversion.ResultKind;
}
else
{
goto default;
}
break;
case BoundKind.DynamicInvocation:
var dynamicInvocation = (BoundDynamicInvocation)boundNodeForSyntacticParent;
symbols = dynamicInvocation.ApplicableMethods.Cast<MethodSymbol, Symbol>();
......
......@@ -2524,5 +2524,173 @@ static void Main()
CompileAndVerify(source, expectedOutput: "True");
}
[Fact, WorkItem(3096, "https://github.com/dotnet/roslyn/issues/3096")]
public void CastToDelegate_01()
{
var sourceText = @"namespace NS
{
public static class A
{
public delegate void Action();
public static void M()
{
RunAction(A.B<string>.M0);
RunAction((Action)A.B<string>.M1);
}
private static void RunAction(Action action) { }
private class B<T>
{
public static void M0() { }
public static void M1() { }
}
}
}";
var compilation = CreateCompilationWithMscorlib(sourceText, options: TestOptions.DebugDll);
compilation.VerifyDiagnostics();
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var identifierNameM0 = tree
.GetRoot()
.DescendantNodes()
.OfType<IdentifierNameSyntax>()
.First(x => x.Parent.IsKind(SyntaxKind.SimpleMemberAccessExpression) && x.Identifier.ValueText.Equals("M0"));
Assert.Equal("A.B<string>.M0", identifierNameM0.Parent.ToString());
var m0Symbol = model.GetSymbolInfo(identifierNameM0);
Assert.Equal("void NS.A.B<System.String>.M0()", m0Symbol.Symbol.ToTestDisplayString());
Assert.Equal(CandidateReason.None, m0Symbol.CandidateReason);
var identifierNameM1 = tree
.GetRoot()
.DescendantNodes()
.OfType<IdentifierNameSyntax>()
.First(x => x.Parent.IsKind(SyntaxKind.SimpleMemberAccessExpression) && x.Identifier.ValueText.Equals("M1"));
Assert.Equal("A.B<string>.M1", identifierNameM1.Parent.ToString());
var m1Symbol = model.GetSymbolInfo(identifierNameM1);
Assert.Equal("void NS.A.B<System.String>.M1()", m1Symbol.Symbol.ToTestDisplayString());
Assert.Equal(CandidateReason.None, m1Symbol.CandidateReason);
}
[Fact, WorkItem(3096, "https://github.com/dotnet/roslyn/issues/3096")]
public void CastToDelegate_02()
{
var sourceText = @"
class A
{
public delegate void MyDelegate<T>(T a);
public void Test()
{
UseMyDelegate((MyDelegate<int>)MyMethod);
UseMyDelegate((MyDelegate<long>)MyMethod);
UseMyDelegate((MyDelegate<float>)MyMethod);
UseMyDelegate((MyDelegate<double>)MyMethod);
}
private void UseMyDelegate<T>(MyDelegate<T> f) { }
private static void MyMethod(int a) { }
private static void MyMethod(long a) { }
private static void MyMethod(float a) { }
private static void MyMethod(double a) { }
}";
var compilation = CreateCompilationWithMscorlib(sourceText, options: TestOptions.DebugDll);
compilation.VerifyDiagnostics();
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var identifiers = tree
.GetRoot()
.DescendantNodes()
.OfType<IdentifierNameSyntax>()
.Where(x => x.Identifier.ValueText.Equals("MyMethod")).ToArray();
Assert.Equal(4, identifiers.Length);
Assert.Equal("(MyDelegate<int>)MyMethod", identifiers[0].Parent.ToString());
Assert.Equal("void A.MyMethod(System.Int32 a)", model.GetSymbolInfo(identifiers[0]).Symbol.ToTestDisplayString());
Assert.Equal("(MyDelegate<long>)MyMethod", identifiers[1].Parent.ToString());
Assert.Equal("void A.MyMethod(System.Int64 a)", model.GetSymbolInfo(identifiers[1]).Symbol.ToTestDisplayString());
Assert.Equal("(MyDelegate<float>)MyMethod", identifiers[2].Parent.ToString());
Assert.Equal("void A.MyMethod(System.Single a)", model.GetSymbolInfo(identifiers[2]).Symbol.ToTestDisplayString());
Assert.Equal("(MyDelegate<double>)MyMethod", identifiers[3].Parent.ToString());
Assert.Equal("void A.MyMethod(System.Double a)", model.GetSymbolInfo(identifiers[3]).Symbol.ToTestDisplayString());
}
[Fact, WorkItem(3096, "https://github.com/dotnet/roslyn/issues/3096")]
public void CastToDelegate_03()
{
var sourceText = @"namespace NS
{
public static class A
{
public delegate void Action();
public static void M()
{
var b = new A.B<string>();
RunAction(b.M0);
RunAction((Action)b.M1);
}
private static void RunAction(Action action) { }
public class B<T>
{
}
public static void M0<T>(this B<T> x) { }
public static void M1<T>(this B<T> x) { }
}
}";
var compilation = CreateCompilationWithMscorlibAndSystemCore(sourceText, options: TestOptions.DebugDll);
compilation.VerifyDiagnostics();
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var identifierNameM0 = tree
.GetRoot()
.DescendantNodes()
.OfType<IdentifierNameSyntax>()
.First(x => x.Parent.IsKind(SyntaxKind.SimpleMemberAccessExpression) && x.Identifier.ValueText.Equals("M0"));
Assert.Equal("b.M0", identifierNameM0.Parent.ToString());
var m0Symbol = model.GetSymbolInfo(identifierNameM0);
Assert.Equal("void NS.A.B<System.String>.M0<System.String>()", m0Symbol.Symbol.ToTestDisplayString());
Assert.Equal(CandidateReason.None, m0Symbol.CandidateReason);
var identifierNameM1 = tree
.GetRoot()
.DescendantNodes()
.OfType<IdentifierNameSyntax>()
.First(x => x.Parent.IsKind(SyntaxKind.SimpleMemberAccessExpression) && x.Identifier.ValueText.Equals("M1"));
Assert.Equal("b.M1", identifierNameM1.Parent.ToString());
var m1Symbol = model.GetSymbolInfo(identifierNameM1);
Assert.Equal("void NS.A.B<System.String>.M1<System.String>()", m1Symbol.Symbol.ToTestDisplayString());
Assert.Equal(CandidateReason.None, m1Symbol.CandidateReason);
}
}
}
......@@ -1568,6 +1568,11 @@ Module Program
Dim v5 = F2(0) 'BIND13:"F2"
x = C1.C() 'BIND14:"C1.C"
d = CType(addressof C1.B, Func(of byte)) 'BIND15:"C1.B"
d = DirectCast(addressof C1.B, Func(of byte)) 'BIND16:"C1.B"
d = TryCast(addressof C1.B, Func(of byte)) 'BIND17:"C1.B"
End Sub
Function F() As Func(Of Integer, Integer)
......@@ -1589,6 +1594,21 @@ End Module
</file>
</compilation>)
compilation.AssertTheseDiagnostics(<expected>
BC35000: Requested operation is not available because the runtime library function 'Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute..ctor' is not defined.
Module Program
~~~~~~~
BC30454: Expression is not a method.
C1.A 'BIND:"C1.A"
~~~~
BC30545: Property access must assign to the property or use its value.
C1.C 'BIND2:"C1.C"
~~~~
BC42104: Variable 'o' is used before it has been assigned a value. A null reference exception could result at runtime.
Dim c = o.ToString(0) 'BIND7:"o.ToString"
~
</expected>)
Dim model = GetSemanticModel(compilation, "a.vb")
Dim expressionSyntax = CompilationUtils.FindBindingText(Of MemberAccessExpressionSyntax)(compilation, "a.vb", 0)
Dim symbolInfo = model.GetSymbolInfo(expressionSyntax)
......@@ -1691,6 +1711,27 @@ End Module
Assert.Equal("C", symbolInfo.Symbol.Name)
typeInfo = model.GetTypeInfo(expressionSyntax)
Assert.Null(typeInfo.Type)
expressionSyntax = CompilationUtils.FindBindingText(Of MemberAccessExpressionSyntax)(compilation, "a.vb", 15)
symbolInfo = model.GetSymbolInfo(expressionSyntax)
Assert.Equal("Function C1.B() As System.Byte", symbolInfo.Symbol.ToTestDisplayString())
Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason)
typeInfo = model.GetTypeInfo(expressionSyntax)
Assert.Null(typeInfo.Type)
expressionSyntax = CompilationUtils.FindBindingText(Of MemberAccessExpressionSyntax)(compilation, "a.vb", 16)
symbolInfo = model.GetSymbolInfo(expressionSyntax)
Assert.Equal("Function C1.B() As System.Byte", symbolInfo.Symbol.ToTestDisplayString())
Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason)
typeInfo = model.GetTypeInfo(expressionSyntax)
Assert.Null(typeInfo.Type)
expressionSyntax = CompilationUtils.FindBindingText(Of MemberAccessExpressionSyntax)(compilation, "a.vb", 17)
symbolInfo = model.GetSymbolInfo(expressionSyntax)
Assert.Equal("Function C1.B() As System.Byte", symbolInfo.Symbol.ToTestDisplayString())
Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason)
typeInfo = model.GetTypeInfo(expressionSyntax)
Assert.Null(typeInfo.Type)
End Sub
<WorkItem(543572, "DevDiv")>
......
......@@ -2054,7 +2054,7 @@ class C
static void Main()
{
Action<string> g = null;
var h = (Foo<string>) + g;
var h = Foo + g;
}
static void Foo<T>(T y) { }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册