diff --git a/src/VisualStudio/Core/Impl/CodeModel/MethodXml/AbstractMethodXmlBuilder.cs b/src/VisualStudio/Core/Impl/CodeModel/MethodXml/AbstractMethodXmlBuilder.cs index fb44161ae8cf18a3e1fb131bd72b13abfddbb288..998a31f3479bed5eb67a8c8b33abf4da0de5cd83 100644 --- a/src/VisualStudio/Core/Impl/CodeModel/MethodXml/AbstractMethodXmlBuilder.cs +++ b/src/VisualStudio/Core/Impl/CodeModel/MethodXml/AbstractMethodXmlBuilder.cs @@ -33,6 +33,7 @@ internal abstract partial class AbstractMethodXmlBuilder private const string NameRefElementName = "NameRef"; private const string NewArrayElementName = "NewArray"; private const string NewClassElementName = "NewClass"; + private const string NewDelegateElementName = "NewDelegate"; private const string NullElementName = "Null"; private const string NumberElementName = "Number"; private const string ParenthesesElementName = "Parentheses"; @@ -42,7 +43,10 @@ internal abstract partial class AbstractMethodXmlBuilder private const string TypeElementName = "Type"; private const string BinaryOperatorAttributeName = "binaryoperator"; + private const string FullNameAttributeName = "fullname"; + private const string ImplicitAttributeName = "implicit"; private const string LineAttributeName = "line"; + private const string NameAttributeName = "name"; private const string RankAttributeName = "rank"; private const string TypeAttributeName = "type"; private const string VariableKindAttributeName = "variablekind"; @@ -182,11 +186,41 @@ private AttributeInfo BinaryOperatorAttribute(BinaryOperatorKind kind) return new AttributeInfo(BinaryOperatorAttributeName, GetBinaryOperatorKindText(kind)); } + private AttributeInfo FullNameAttribute(string name) + { + if (string.IsNullOrWhiteSpace(name)) + { + return AttributeInfo.Empty; + } + + return new AttributeInfo(FullNameAttributeName, name); + } + + private AttributeInfo ImplicitAttribute(bool? @implicit) + { + if (@implicit == null) + { + return AttributeInfo.Empty; + } + + return new AttributeInfo(ImplicitAttributeName, @implicit.Value ? "yes" : "no"); + } + private AttributeInfo LineNumberAttribute(int lineNumber) { return new AttributeInfo(LineAttributeName, lineNumber.ToString()); } + private AttributeInfo NameAttribute(string name) + { + if (string.IsNullOrWhiteSpace(name)) + { + return AttributeInfo.Empty; + } + + return new AttributeInfo(NameAttributeName, name); + } + private AttributeInfo RankAttribute(int rank) { return new AttributeInfo(RankAttributeName, rank.ToString()); @@ -307,9 +341,9 @@ protected IDisposable NameTag() return Tag(NameElementName); } - protected IDisposable NameRefTag(VariableKind kind) + protected IDisposable NameRefTag(VariableKind kind, string name = null, string fullName = null) { - return Tag(NameRefElementName, VariableKindAttribute(kind)); + return Tag(NameRefElementName, VariableKindAttribute(kind), NameAttribute(name), FullNameAttribute(fullName)); } protected IDisposable NewArrayTag() @@ -322,6 +356,11 @@ protected IDisposable NewClassTag() return Tag(NewClassElementName); } + protected IDisposable NewDelegateTag(string name) + { + return Tag(NewDelegateElementName, NameAttribute(name)); + } + protected void NullTag() { AppendLeafTag(NullElementName); @@ -352,9 +391,9 @@ protected void ThisReferenceTag() AppendLeafTag(ThisReferenceElementName); } - protected IDisposable TypeTag() + protected IDisposable TypeTag(bool? @implicit = null) { - return Tag(TypeElementName); + return Tag(TypeElementName, ImplicitAttribute(@implicit)); } protected void LineBreak() @@ -427,21 +466,25 @@ protected void GenerateName(string name) } } - protected void GenerateType(ITypeSymbol type) + protected void GenerateType(ITypeSymbol type, bool? @implicit = null, bool assemblyQualify = false) { if (type.TypeKind == TypeKind.Array) { var arrayType = (IArrayTypeSymbol)type; using (var tag = ArrayTypeTag(arrayType.Rank)) { - GenerateType(arrayType.ElementType); + GenerateType(arrayType.ElementType, @implicit, assemblyQualify); } } else { - using (TypeTag()) + using (TypeTag(@implicit)) { - EncodedText(GetTypeName(type)); + var typeName = assemblyQualify + ? GetTypeName(type) + ", " + type.ContainingAssembly.ToDisplayString() + : GetTypeName(type); + + EncodedText(typeName); } } } diff --git a/src/VisualStudio/Core/Test/CodeModel/MethodXML/MethodXMLTests_VBLocalDeclarations.vb b/src/VisualStudio/Core/Test/CodeModel/MethodXML/MethodXMLTests_VBLocalDeclarations.vb index d2ca9d513874381abd04764d98e846687119d3b4..dc8bcad189dd7a0b042c4a618a8c086097052bc2 100644 --- a/src/VisualStudio/Core/Test/CodeModel/MethodXML/MethodXMLTests_VBLocalDeclarations.vb +++ b/src/VisualStudio/Core/Test/CodeModel/MethodXML/MethodXMLTests_VBLocalDeclarations.vb @@ -1,7 +1,6 @@ ' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. Imports Roslyn.Test.Utilities -Imports Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel.MethodXML Partial Public Class MethodXMLTests diff --git a/src/VisualStudio/Core/Test/CodeModel/MethodXML/MethodXMLTests_VBStatements.vb b/src/VisualStudio/Core/Test/CodeModel/MethodXML/MethodXMLTests_VBStatements.vb new file mode 100644 index 0000000000000000000000000000000000000000..13d41c2d9d5514d025e2d1d693ce29d381f0dc43 --- /dev/null +++ b/src/VisualStudio/Core/Test/CodeModel/MethodXML/MethodXMLTests_VBStatements.vb @@ -0,0 +1,679 @@ +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +Imports Roslyn.Test.Utilities + +Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.CodeModel.MethodXML + Partial Public Class MethodXMLTests + + + Public Sub VBStatements_AddHandler1() + Dim definition = + + + + +Imports System + +Class C + Event E As EventHandler + + Sub Handler(sender As Object, e As EventArgs) + End Sub + + $$Sub M() + AddHandler E, AddressOf Handler + End Sub +End Class + + + + + Dim expected = + + + + + + + + + + + + N.C, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + System.EventHandler, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + N.C, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + + + + + + Test(definition, expected) + End Sub + + + Public Sub VBStatements_AddHandler2() + Dim definition = + + + + +Imports System + +Class B + Event E As EventHandler +End Class + +Class C + Dim b As New B + + Sub Handler(sender As Object, e As EventArgs) + End Sub + + $$Sub M() + AddHandler b.E, AddressOf Handler + End Sub +End Class + + + + + Dim expected = + + + + + + + + + + + + + + + + N.B, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + System.EventHandler, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + N.C, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + + + + + + Test(definition, expected) + End Sub + + + Public Sub VBStatements_AddHandler3() + Dim definition = + + + + +Imports System + +Class B + Event E As EventHandler + + Sub Handler(sender As Object, e As EventArgs) + End Sub +End Class + +Class C + Dim b As New B + + $$Sub M() + AddHandler b.E, AddressOf b.Handler + End Sub +End Class + + + + + Dim expected = + + + + + + + + + + + + + + + + N.B, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + System.EventHandler, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + + + N.B, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + + + + + + Test(definition, expected) + End Sub + + + Public Sub VBStatements_AddHandler4() + Dim definition = + + + + +Imports System + +Class A + Event E As EventHandler +End Class + +Class B + Property A As New A + + Sub Handler(sender As Object, e As EventArgs) + End Sub +End Class + +Class C + Dim b As New B + + $$Sub M() + AddHandler b.A.E, AddressOf b.Handler + End Sub +End Class + + + + + Dim expected = + + + + + + + + + + + + + + + + + + + + N.A, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + System.EventHandler, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + + + N.B, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + + + + + + Test(definition, expected) + End Sub + + + Public Sub VBStatements_AddHandler5() + Dim definition = + + + + +Imports System + +Class A + Sub Handler(sender As Object, e As EventArgs) + End Sub +End Class + +Class B + Property A As New A + + Event E As EventHandler +End Class + +Class C + Dim b As New B + + $$Sub M() + AddHandler b.E, AddressOf b.A.Handler + End Sub +End Class + + + + + Dim expected = + + + + + + + + + + + + + + + + N.B, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + System.EventHandler, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + + + + + + + N.A, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + + + + + + Test(definition, expected) + End Sub + + + Public Sub VBStatements_RemoveHandler1() + Dim definition = + + + + +Imports System + +Class C + Event E As EventHandler + + Sub Handler(sender As Object, e As EventArgs) + End Sub + + $$Sub M() + RemoveHandler E, AddressOf Handler + End Sub +End Class + + + + + Dim expected = + + + + + + + + + + + + N.C, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + System.EventHandler, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + N.C, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + + + + + + Test(definition, expected) + End Sub + + + Public Sub VBStatements_RemoveHandler2() + Dim definition = + + + + +Imports System + +Class B + Event E As EventHandler +End Class + +Class C + Dim b As New B + + Sub Handler(sender As Object, e As EventArgs) + End Sub + + $$Sub M() + RemoveHandler b.E, AddressOf Handler + End Sub +End Class + + + + + Dim expected = + + + + + + + + + + + + + + + + N.B, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + System.EventHandler, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + N.C, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + + + + + + Test(definition, expected) + End Sub + + + Public Sub VBStatements_RemoveHandler3() + Dim definition = + + + + +Imports System + +Class B + Event E As EventHandler + + Sub Handler(sender As Object, e As EventArgs) + End Sub +End Class + +Class C + Dim b As New B + + $$Sub M() + RemoveHandler b.E, AddressOf b.Handler + End Sub +End Class + + + + + Dim expected = + + + + + + + + + + + + + + + + N.B, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + System.EventHandler, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + + + N.B, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + + + + + + Test(definition, expected) + End Sub + + + Public Sub VBStatements_RemoveHandler4() + Dim definition = + + + + +Imports System + +Class A + Event E As EventHandler +End Class + +Class B + Property A As New A + + Sub Handler(sender As Object, e As EventArgs) + End Sub +End Class + +Class C + Dim b As New B + + $$Sub M() + RemoveHandler b.A.E, AddressOf b.Handler + End Sub +End Class + + + + + Dim expected = + + + + + + + + + + + + + + + + + + + + N.A, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + System.EventHandler, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + + + N.B, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + + + + + + Test(definition, expected) + End Sub + + + Public Sub VBStatements_RemoveHandler5() + Dim definition = + + + + +Imports System + +Class A + Sub Handler(sender As Object, e As EventArgs) + End Sub +End Class + +Class B + Property A As New A + + Event E As EventHandler +End Class + +Class C + Dim b As New B + + $$Sub M() + RemoveHandler b.E, AddressOf b.A.Handler + End Sub +End Class + + + + + Dim expected = + + + + + + + + + + + + + + + + N.B, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + System.EventHandler, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + + + + + + + N.A, Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + + + + + + + Test(definition, expected) + End Sub + + End Class +End Namespace \ No newline at end of file diff --git a/src/VisualStudio/Core/Test/ServicesVisualStudioTest.vbproj b/src/VisualStudio/Core/Test/ServicesVisualStudioTest.vbproj index cbcb9b369e59a4b1fa01cc0a02d8894080e2992c..f69cd3f6ac1f3174b0a738a0e6af9a81c02c1dd3 100644 --- a/src/VisualStudio/Core/Test/ServicesVisualStudioTest.vbproj +++ b/src/VisualStudio/Core/Test/ServicesVisualStudioTest.vbproj @@ -300,6 +300,7 @@ + diff --git a/src/VisualStudio/VisualBasic/Impl/CodeModel/MethodXML/MethodXmlBuilder.vb b/src/VisualStudio/VisualBasic/Impl/CodeModel/MethodXML/MethodXmlBuilder.vb index 8cb1996bd982566f4ef11908ad747e82958d512a..de8a7399955907d16f8d3bdb2b026162c8b76b74 100644 --- a/src/VisualStudio/VisualBasic/Impl/CodeModel/MethodXML/MethodXmlBuilder.vb +++ b/src/VisualStudio/VisualBasic/Impl/CodeModel/MethodXML/MethodXmlBuilder.vb @@ -2,10 +2,8 @@ Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Shared.Extensions -Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic Imports Microsoft.CodeAnalysis.VisualBasic.Extensions -Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel.MethodXml @@ -13,6 +11,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel.MethodXm Friend Class MethodXmlBuilder Inherits AbstractMethodXmlBuilder + Private Shared ReadOnly s_fullNameFormat As New SymbolDisplayFormat( + typeQualificationStyle:=SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, + memberOptions:=SymbolDisplayMemberOptions.None) + Private Sub New(symbol As IMethodSymbol, semanticModel As SemanticModel) MyBase.New(symbol, semanticModel) End Sub @@ -38,6 +40,9 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel.MethodXm success = TryGenerateCall(DirectCast(statement, CallStatementSyntax)) Case SyntaxKind.ExpressionStatement success = TryGenerateExpressionStatement(DirectCast(statement, ExpressionStatementSyntax)) + Case SyntaxKind.AddHandlerStatement, + SyntaxKind.RemoveHandlerStatement + success = TryGenerateAddOrRemoveHandlerStatement(DirectCast(statement, AddRemoveHandlerStatementSyntax)) End Select If Not success Then @@ -110,13 +115,54 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel.MethodXm End Using End Function - Private Function TryGenerateExpression(expression As ExpressionSyntax) As Boolean + Private Function TryGenerateAddOrRemoveHandlerStatement(addHandlerStatement As AddRemoveHandlerStatementSyntax) As Boolean + ' AddHandler statements are represented as invocations of an event's add_* method. + ' RemoveHandler statements are represented as invocations of an event's remove_* method. + + Dim eventExpression = addHandlerStatement.EventExpression + Dim eventSymbol = TryCast(SemanticModel.GetSymbolInfo(eventExpression).Symbol, IEventSymbol) + + Dim eventAccessor As IMethodSymbol + If addHandlerStatement.Kind() = SyntaxKind.AddHandlerStatement Then + eventAccessor = eventSymbol?.AddMethod + ElseIf addHandlerStatement.Kind() = SyntaxKind.RemoveHandlerStatement + eventAccessor = eventSymbol?.RemoveMethod + Else + eventAccessor = Nothing + End If + + If eventAccessor Is Nothing Then + Return False + End If + + Using ExpressionStatementTag(GetLineNumber(addHandlerStatement)) + Using ExpressionTag() + Using MethodCallTag() + If Not TryGenerateExpression(eventExpression, eventAccessor, generateAttributes:=True) Then + Return False + End If + + GenerateType(eventSymbol.ContainingType, implicit:=True, assemblyQualify:=True) + + Using ArgumentTag() + If Not TryGenerateExpression(addHandlerStatement.DelegateExpression, generateAttributes:=True) Then + Return False + End If + End Using + + Return True + End Using + End Using + End Using + End Function + + Private Function TryGenerateExpression(expression As ExpressionSyntax, Optional symbolOpt As ISymbol = Nothing, Optional generateAttributes As Boolean = False) As Boolean Using ExpressionTag() - Return TryGenerateExpressionSansTag(expression) + Return TryGenerateExpressionSansTag(expression, symbolOpt, generateAttributes) End Using End Function - Private Function TryGenerateExpressionSansTag(expression As ExpressionSyntax) As Boolean + Private Function TryGenerateExpressionSansTag(expression As ExpressionSyntax, Optional symbolOpt As ISymbol = Nothing, Optional generateAttributes As Boolean = False) As Boolean Select Case expression.Kind Case SyntaxKind.CharacterLiteralExpression, SyntaxKind.UnaryMinusExpression, @@ -149,10 +195,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel.MethodXm Return TryGenerateNewClass(DirectCast(expression, ObjectCreationExpressionSyntax)) Case SyntaxKind.SimpleMemberAccessExpression - Return TryGenerateNameRef(DirectCast(expression, MemberAccessExpressionSyntax)) + Return TryGenerateNameRef(DirectCast(expression, MemberAccessExpressionSyntax), symbolOpt, generateAttributes) Case SyntaxKind.IdentifierName - Return TryGenerateNameRef(DirectCast(expression, IdentifierNameSyntax)) + Return TryGenerateNameRef(DirectCast(expression, IdentifierNameSyntax), symbolOpt, generateAttributes) Case SyntaxKind.InvocationExpression Return TryGenerateMethodCall(DirectCast(expression, InvocationExpressionSyntax)) @@ -169,6 +215,9 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel.MethodXm Case SyntaxKind.MeExpression GenerateThisReference() Return True + + Case SyntaxKind.AddressOfExpression + Return TryGenerateAddressOfExpression(DirectCast(expression, UnaryExpressionSyntax)) End Select Return False @@ -278,16 +327,36 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel.MethodXm Return kind End Function - Private Function TryGenerateNameRef(memberAccessExpression As MemberAccessExpressionSyntax) As Boolean - Dim symbol = SemanticModel.GetSymbolInfo(memberAccessExpression).Symbol + Private Shared Function GetFullNameText(symbol As ISymbol) As String + If symbol Is Nothing Then + Return Nothing + End If + + If symbol.IsAccessor() Then + Return Nothing + End If + + Return symbol.ContainingSymbol.ToDisplayString(s_fullNameFormat) & "." & symbol.Name + End Function + + Private Function TryGenerateNameRef( + memberAccess As MemberAccessExpressionSyntax, + Optional symbolOpt As ISymbol = Nothing, + Optional generateAttributes As Boolean = False + ) As Boolean + + symbolOpt = If(symbolOpt, SemanticModel.GetSymbolInfo(memberAccess).Symbol) - ' No null check for 'symbol' here. If 'symbol' unknown, we'll - ' generate an "unknown" name ref. + ' Note: There's no null check for 'symbolOpt' here. If 'symbolOpt' is Nothing, we'll generate an "unknown" name ref. + Dim varKind As VariableKind = GetVariableKind(symbolOpt) - Dim kind As VariableKind = GetVariableKind(symbol) + Dim name = If(symbolOpt IsNot Nothing, symbolOpt.Name, memberAccess.Name.Identifier.ValueText) + Dim nameAttribute = If(generateAttributes, name, Nothing) + Dim fullNameAttribute = If(generateAttributes, GetFullNameText(symbolOpt), Nothing) - Using NameRefTag(kind) - Dim leftHandSymbol = SemanticModel.GetSymbolInfo(memberAccessExpression.GetExpressionOfMemberAccessExpression()).Symbol + Using NameRefTag(varKind, nameAttribute, fullNameAttribute) + + Dim leftHandSymbol = SemanticModel.GetSymbolInfo(memberAccess.GetExpressionOfMemberAccessExpression()).Symbol If leftHandSymbol IsNot Nothing Then If leftHandSymbol.Kind = SymbolKind.Alias Then leftHandSymbol = DirectCast(leftHandSymbol, IAliasSymbol).Target @@ -296,10 +365,9 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel.MethodXm ' This can occur if a module member is referenced without the module name. In that case, ' we'll go ahead and try to use the module name name. If leftHandSymbol.Kind = SymbolKind.Namespace AndAlso - symbol.ContainingType IsNot Nothing AndAlso - symbol.ContainingType.TypeKind = TypeKind.Module Then + symbolOpt?.ContainingType?.TypeKind = TypeKind.Module Then - leftHandSymbol = symbol.ContainingType + leftHandSymbol = symbolOpt.ContainingType End If End If @@ -311,50 +379,65 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel.MethodXm GenerateType(DirectCast(leftHandSymbol, ITypeSymbol)) End Using End Using - ElseIf Not TryGenerateExpression(memberAccessExpression.GetExpressionOfMemberAccessExpression()) Then + ElseIf Not TryGenerateExpression(memberAccess.GetExpressionOfMemberAccessExpression(), generateAttributes:=generateAttributes) Then Return False End If - GenerateName(memberAccessExpression.Name.Identifier.ValueText) + If Not generateAttributes Then + GenerateName(name) + End If End Using Return True End Function - Private Function TryGenerateNameRef(identifierName As IdentifierNameSyntax) As Boolean - Dim symbol = SemanticModel.GetSymbolInfo(identifierName).Symbol + Private Function TryGenerateNameRef( + identifierName As IdentifierNameSyntax, + Optional symbolOpt As ISymbol = Nothing, + Optional generateAttributes As Boolean = False + ) As Boolean - ' No null check for 'symbol' here. If 'symbol' unknown, we'll - ' generate an "unknown" name ref. + symbolOpt = If(symbolOpt, SemanticModel.GetSymbolInfo(identifierName).Symbol) - Dim varKind = GetVariableKind(symbol) + ' Note: There's no null check for 'symbolOpt' here. If 'symbolOpt' is Nothing, we'll generate an "unknown" name ref. + Dim varKind = GetVariableKind(symbolOpt) - Using NameRefTag(varKind) - If symbol IsNot Nothing AndAlso varKind <> VariableKind.Local Then - ' This is a little tricky -- if our method symbol's containing type inherits from - ' or is the same as the identifier symbol's containing type, we'll go ahead and - ' generate a . Otherwise, because this is an identifier, we assume - ' that it is a Shared member or an imported type (for example, a Module) and generate - ' an - If Me.Symbol.ContainingType.InheritsFromOrEquals(symbol.ContainingType) Then - Using ExpressionTag() - GenerateThisReference() - End Using - Else - Using ExpressionTag() - Using LiteralTag() - GenerateType(symbol.ContainingType) - End Using - End Using - End If + Dim name = If(symbolOpt IsNot Nothing, symbolOpt.Name, identifierName.Identifier.ValueText) + Dim nameAttribute = If(generateAttributes, name, Nothing) + Dim fullNameAttribute = If(generateAttributes, GetFullNameText(symbolOpt), Nothing) + + Using NameRefTag(varKind, nameAttribute, fullNameAttribute) + If symbolOpt IsNot Nothing AndAlso varKind <> VariableKind.Local Then + GenerateLastNameRef(symbolOpt) End If - GenerateName(identifierName.ToString()) + If Not generateAttributes Then + GenerateName(name) + End If End Using Return True End Function + Private Sub GenerateLastNameRef(symbol As ISymbol) + ' This is a little tricky -- if our method symbol's containing type inherits from + ' or is the same as the identifier symbol's containing type, we'll go ahead and + ' generate a . Otherwise, because this is an identifier, we assume + ' that it is a Shared member or an imported type (for example, a Module) and generate + ' an + If Me.Symbol.ContainingType.InheritsFromOrEquals(symbol.ContainingType) Then + Using ExpressionTag() + GenerateThisReference() + End Using + Else + Using ExpressionTag() + Using LiteralTag() + GenerateType(symbol.ContainingType) + End Using + End Using + End If + End Sub + Private Function TryGenerateMethodCall(invocationExpression As InvocationExpressionSyntax) As Boolean Using MethodCallTag() If Not TryGenerateExpression(invocationExpression.Expression) Then @@ -558,8 +641,41 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.CodeModel.MethodXm Return True End Function + Private Function TryGenerateAddressOfExpression(expression As UnaryExpressionSyntax) As Boolean + Debug.Assert(expression.Kind() = SyntaxKind.AddressOfExpression) + + Dim delegateExpression = expression.Operand + + Dim delegateSymbol = TryCast(SemanticModel.GetSymbolInfo(delegateExpression).Symbol, IMethodSymbol) + If delegateSymbol Is Nothing Then + Return False + End If + + Dim eventType = SemanticModel.GetTypeInfo(expression).Type + If eventType Is Nothing Then + Return False + End If + + Using NewDelegateTag(delegateSymbol.Name) + GenerateType(eventType, implicit:=True, assemblyQualify:=True) + + If delegateExpression.Kind() = SyntaxKind.IdentifierName Then + GenerateLastNameRef(delegateSymbol) + ElseIf delegateExpression.Kind() = SyntaxKind.SimpleMemberAccessExpression + Dim memberAccess = DirectCast(delegateExpression, MemberAccessExpressionSyntax) + If Not TryGenerateExpression(memberAccess.GetExpressionOfMemberAccessExpression(), generateAttributes:=True) Then + Return False + End If + End If + + GenerateType(delegateSymbol.ContainingType, implicit:=True, assemblyQualify:=True) + + Return True + End Using + End Function + Public Shared Function Generate(methodBlock As MethodBlockBaseSyntax, semanticModel As SemanticModel) As String - Dim symbol = DirectCast(semanticModel.GetDeclaredSymbol(methodBlock), IMethodSymbol) + Dim symbol = semanticModel.GetDeclaredSymbol(methodBlock) Dim builder = New MethodXmlBuilder(symbol, semanticModel) builder.GenerateStatementBlock(methodBlock.Statements)