diff --git a/src/Compilers/VisualBasic/Portable/Compilation/ClsComplianceChecker.vb b/src/Compilers/VisualBasic/Portable/Compilation/ClsComplianceChecker.vb index 0fe55d83e303539319de03b9950209354a5e56b2..f0ebe8c4e2252e72f158593d20432fbd67444d03 100644 --- a/src/Compilers/VisualBasic/Portable/Compilation/ClsComplianceChecker.vb +++ b/src/Compilers/VisualBasic/Portable/Compilation/ClsComplianceChecker.vb @@ -394,7 +394,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Private Sub CheckEventTypeCompliance(symbol As EventSymbol) Dim type = symbol.Type - If type.TypeKind = TypeKind.Delegate AndAlso type.IsImplicitlyDeclared Then + If type.TypeKind = TypeKind.Delegate AndAlso type.IsImplicitlyDeclared AndAlso TryCast(type, NamedTypeSymbol)?.AssociatedSymbol Is symbol Then Debug.Assert(symbol.DelegateReturnType.SpecialType = SpecialType.System_Void) CheckParameterCompliance(symbol.DelegateParameters, symbol.ContainingType) ElseIf ShouldReportNonCompliantType(type, symbol.ContainingType, symbol) Then diff --git a/src/Compilers/VisualBasic/Portable/Compilation/SyntaxTreeSemanticModel.vb b/src/Compilers/VisualBasic/Portable/Compilation/SyntaxTreeSemanticModel.vb index 20ac68f0050025483281dc720243706738ea8980..97c797640ff62e250e7558bed390cccae9da1fb9 100644 --- a/src/Compilers/VisualBasic/Portable/Compilation/SyntaxTreeSemanticModel.vb +++ b/src/Compilers/VisualBasic/Portable/Compilation/SyntaxTreeSemanticModel.vb @@ -1063,7 +1063,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Case SymbolKind.Method Return GetParameterSymbol(DirectCast(symbol, MethodSymbol).Parameters, parameter) Case SymbolKind.Event - Return GetParameterSymbol(DirectCast(symbol, EventSymbol).DelegateParameters, parameter) + Dim eventSymbol As EventSymbol = DirectCast(symbol, EventSymbol) + Dim type = TryCast(eventSymbol.Type, NamedTypeSymbol) + + If type?.AssociatedSymbol Is eventSymbol Then + Return GetParameterSymbol(type.DelegateInvokeMethod.Parameters, parameter) + End If + + Return Nothing + Case SymbolKind.Property Return GetParameterSymbol(DirectCast(symbol, PropertySymbol).Parameters, parameter) Case SymbolKind.NamedType diff --git a/src/Compilers/VisualBasic/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.vb b/src/Compilers/VisualBasic/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.vb index 520b368651683c6db20db03665542207f1a9753a..cdaa54679e2635c92d369a8ee7967eedc437095a 100644 --- a/src/Compilers/VisualBasic/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.vb +++ b/src/Compilers/VisualBasic/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.vb @@ -128,10 +128,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim sourceSymbol = TryCast(symbol, SourceEventSymbol) If sourceSymbol IsNot Nothing AndAlso sourceSymbol.IsTypeInferred Then If format.MemberOptions.IncludesOption(SymbolDisplayMemberOptions.IncludeParameters) Then - Dim invoke = DirectCast(sourceSymbol.Type, SynthesizedEventDelegateSymbol).DelegateInvokeMethod - AddPunctuation(SyntaxKind.OpenParenToken) - AddParametersIfRequired(isExtensionMethod:=False, parameters:=StaticCast(Of IParameterSymbol).From(invoke.Parameters)) + AddParametersIfRequired(isExtensionMethod:=False, parameters:=StaticCast(Of IParameterSymbol).From(sourceSymbol.DelegateParameters)) AddPunctuation(SyntaxKind.CloseParenToken) End If End If diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceEventSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceEventSymbol.vb index 4070cba7cfe5b863aee60b9c611a6f75e700b8ba..5db3c4f1388d98c08f0a231f9092b0c04ef06e0f 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceEventSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceEventSymbol.vb @@ -216,9 +216,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Dim types = _containingType.GetTypeMembers(Me.Name & EVENT_DELEGATE_SUFFIX) Debug.Assert(Not types.IsDefault) - If Not types.IsEmpty Then - type = types(0) - Else + type = Nothing + + For Each candidate In types + If candidate.AssociatedSymbol Is Me Then + type = candidate + Exit For + End If + Next + + If type Is Nothing Then ' if we still do not know the type, get a temporary one (it is not a member of the containing class) type = New SynthesizedEventDelegateSymbol(Me._syntaxRef, _containingType) End If diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceParameterSymbol.vb index 4ccc333f1268ecfe63af07a6e47b93cdb39d47ea..b23374dc627cd88884e2399e3f6665e1bde5c76c 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceParameterSymbol.vb @@ -103,7 +103,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Public NotOverridable Overrides ReadOnly Property IsImplicitlyDeclared As Boolean Get - Return (GetMatchingPropertyParameter() IsNot Nothing) OrElse (Me.ContainingSymbol.IsImplicitlyDeclared) + If Me.ContainingSymbol.IsImplicitlyDeclared Then + + If TryCast(Me.ContainingSymbol, MethodSymbol)?.MethodKind = MethodKind.DelegateInvoke AndAlso + Not Me.ContainingType.AssociatedSymbol?.IsImplicitlyDeclared Then + Return False + End If + + Return True + End If + + Return (GetMatchingPropertyParameter() IsNot Nothing) End Get End Property diff --git a/src/Compilers/VisualBasic/Test/Semantic/Compilation/SemanticModelGetDeclaredSymbolAPITests.vb b/src/Compilers/VisualBasic/Test/Semantic/Compilation/SemanticModelGetDeclaredSymbolAPITests.vb index dedac3b1fd651f2848f6e9de97ac61169c68b46c..63ee30bc17ef93d57591d169fd79a901337efeef 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Compilation/SemanticModelGetDeclaredSymbolAPITests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Compilation/SemanticModelGetDeclaredSymbolAPITests.vb @@ -1324,7 +1324,8 @@ BC30001: Statement is not valid in a namespace. Assert.NotNull(paramSymbol1) Assert.Equal("Percent", paramSymbol1.Name) Assert.Equal("System.Single", paramSymbol1.Type.ToTestDisplayString()) - Assert.Equal("Event N1.Test.Percent(Percent As System.Single)", paramSymbol1.ContainingSymbol.ToTestDisplayString()) + Assert.Equal("Event N1.Test.Percent(Percent As System.Single)", paramSymbol1.ContainingType.AssociatedSymbol.ToTestDisplayString()) + Assert.Equal("Sub N1.Test.PercentEventHandler.Invoke(Percent As System.Single)", paramSymbol1.ContainingSymbol.ToTestDisplayString()) End Sub diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Source/EventTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Source/EventTests.vb index 358b8491a1c2ec92e8bf739770e5dd6ccab6cfc8..8211c00cfdb69c1ffe4b7b22e397450435423623 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Source/EventTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Source/EventTests.vb @@ -2240,5 +2240,168 @@ BC30590: Event 'E' cannot be found. ) End Sub + + + Public Sub SemanticModelOnParameters_01() + Dim compilation = CompilationUtils.CreateCompilationWithMscorlib( + + +, options:=TestOptions.DebugDll) + + compilation.AssertTheseDiagnostics() + + Dim tree = compilation.SyntaxTrees.Single() + Dim x = tree.GetRoot().DescendantNodes().OfType(Of ParameterSyntax)().Single().Identifier + + Dim model = compilation.GetSemanticModel(tree) + Dim xSym = model.GetDeclaredSymbol(x) + Assert.Equal("x As System.Int32", xSym.ToTestDisplayString()) + Assert.False(xSym.IsImplicitlyDeclared) + Assert.Equal("x As Integer", xSym.DeclaringSyntaxReferences.Single().GetSyntax().ToString()) + + Dim e1EventHandler = compilation.GetTypeByMetadataName("A+E1EventHandler").DelegateInvokeMethod + Assert.Same(e1EventHandler.ContainingType, DirectCast(e1EventHandler.ContainingType.AssociatedSymbol, EventSymbol).Type) + Assert.True(e1EventHandler.IsImplicitlyDeclared) + Assert.True(e1EventHandler.ContainingType.IsImplicitlyDeclared) + Assert.Same(e1EventHandler, xSym.ContainingSymbol) + Assert.Same(xSym, e1EventHandler.Parameters.First()) + End Sub + + + + Public Sub SemanticModelOnParameters_02() + Dim compilation = CompilationUtils.CreateCompilationWithMscorlib( + + +, options:=TestOptions.DebugDll) + + compilation.AssertTheseDiagnostics() + + Dim a = compilation.GetTypeByMetadataName("A") + Dim e1 = a.GetMember(Of EventSymbol)("E1") + Assert.Equal("I1.D", e1.Type.ToTestDisplayString()) + + Dim tree = compilation.SyntaxTrees.Single() + Dim x = tree.GetRoot().DescendantNodes().OfType(Of ParameterSyntax)().ElementAt(1).Identifier + + Dim model = compilation.GetSemanticModel(tree) + Dim xSym = model.GetDeclaredSymbol(x) + Assert.Null(xSym) + End Sub + + + + Public Sub SemanticModelOnParameters_03() + Dim compilation = CompilationUtils.CreateCompilationWithMscorlib( + + +, options:=TestOptions.DebugDll) + + compilation.AssertTheseDiagnostics( + +BC30401: 'E1' cannot implement 'E1' because there is no matching event on interface 'I1'. + Public Event E1(x As Integer) Implements I1.E1 + ~~~~~ +) + + Dim a = compilation.GetTypeByMetadataName("A") + Dim e1 = a.GetMember(Of EventSymbol)("E1") + Assert.Equal("Event A.E1(x As System.Int32)", e1.ToTestDisplayString()) + + Assert.Equal("A.E1EventHandler", e1.Type.ToTestDisplayString()) + Assert.True(e1.Type.IsDelegateType()) + Assert.DoesNotContain(e1.Type, a.GetMembers()) + Assert.Same(a, e1.Type.ContainingType) + Assert.True(e1.Type.IsImplicitlyDeclared) + + Dim tree = compilation.SyntaxTrees.Single() + Dim x = tree.GetRoot().DescendantNodes().OfType(Of ParameterSyntax)().Single().Identifier + + Dim model = compilation.GetSemanticModel(tree) + Dim xSym = model.GetDeclaredSymbol(x) + + Assert.Equal("x As System.Int32", xSym.ToTestDisplayString()) + Assert.False(xSym.IsImplicitlyDeclared) + Assert.Equal("x As Integer", xSym.DeclaringSyntaxReferences.Single().GetSyntax().ToString()) + Assert.True(xSym.ContainingSymbol.IsImplicitlyDeclared) + Assert.Same(e1.Type, xSym.ContainingType) + Assert.Same(xSym, xSym.ContainingType.DelegateInvokeMethod.Parameters.First()) + End Sub + + + + Public Sub SemanticModelOnParameters_04() + Dim compilation = CompilationUtils.CreateCompilationWithMscorlib( + + +, options:=TestOptions.DebugDll) + + compilation.AssertTheseDiagnostics( + +BC30401: 'E1' cannot implement 'E1' because there is no matching event on interface 'I1'. + Public Event E1(x As Integer) Implements I1.E1 + ~~~~~ +) + + Dim e1EventHandler = compilation.GetTypeByMetadataName("A+E1EventHandler") + Assert.False(e1EventHandler.IsImplicitlyDeclared) + Assert.Equal("A.E1EventHandler", e1EventHandler.ToTestDisplayString()) + Assert.Null(e1EventHandler.AssociatedSymbol) + + Dim a = compilation.GetTypeByMetadataName("A") + Dim e1 = a.GetMember(Of EventSymbol)("E1") + Assert.Equal("Event A.E1(x As System.Int32)", e1.ToTestDisplayString()) + + Assert.Equal("A.E1EventHandler", e1.Type.ToTestDisplayString()) + Assert.True(e1.Type.IsDelegateType()) + Assert.DoesNotContain(e1.Type, a.GetMembers()) + Assert.Same(a, e1.Type.ContainingType) + Assert.True(e1.Type.IsImplicitlyDeclared) + + Dim tree = compilation.SyntaxTrees.Single() + Dim x = tree.GetRoot().DescendantNodes().OfType(Of ParameterSyntax)().Single().Identifier + + Dim model = compilation.GetSemanticModel(tree) + Dim xSym = model.GetDeclaredSymbol(x) + + Assert.Equal("x As System.Int32", xSym.ToTestDisplayString()) + Assert.False(xSym.IsImplicitlyDeclared) + Assert.Equal("x As Integer", xSym.DeclaringSyntaxReferences.Single().GetSyntax().ToString()) + Assert.True(xSym.ContainingSymbol.IsImplicitlyDeclared) + Assert.Same(e1.Type, xSym.ContainingType) + Assert.Same(xSym, xSym.ContainingType.DelegateInvokeMethod.Parameters.First()) + End Sub + End Class End Namespace diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.EventSymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.EventSymbols.vb index 1202bffd4efda9047e6e1d16c7377fce8488492a..71170eff5094d9f7aa3ac162290d0b4ec9e63896 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.EventSymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.EventSymbols.vb @@ -183,7 +183,7 @@ End Class End Function - + Public Async Function TestEventParameterCascading() As Task Dim input = diff --git a/src/Workspaces/CoreTest/SymbolKeyTests.cs b/src/Workspaces/CoreTest/SymbolKeyTests.cs index 47d0285fe1f3ac8efaba7efbd108c05686d51be0..45528393968b65a058e55a6024abb067b0000838 100644 --- a/src/Workspaces/CoreTest/SymbolKeyTests.cs +++ b/src/Workspaces/CoreTest/SymbolKeyTests.cs @@ -50,7 +50,8 @@ public class B { }; TestRoundTrip(GetDeclaredSymbols(compilation), compilation); } - [Fact(Skip = "https://github.com/dotnet/roslyn/issues/14364")] + [Fact] + [WorkItem(14364, "https://github.com/dotnet/roslyn/issues/14364")] public void TestVBParameterizedEvent() { var source = @"