| File: CodeLens\VisualBasicDisplayInfoService.vb | Web Access |
| Project: src\roslyn\src\Features\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.Features.vbproj (Microsoft.CodeAnalysis.VisualBasic.Features) |
' Licensed to the .NET Foundation under one or more agreements. ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. Imports System.Composition Imports System.Globalization Imports Microsoft.CodeAnalysis.CodeLens Imports Microsoft.CodeAnalysis.Host.Mef Imports Microsoft.CodeAnalysis.VisualBasic.LanguageService Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.CodeLens <ExportLanguageService(GetType(ICodeLensDisplayInfoService), LanguageNames.VisualBasic), [Shared]> Friend NotInheritable Class VisualBasicDisplayInfoService Implements ICodeLensDisplayInfoService Private Shared ReadOnly Format As SymbolDisplayFormat = New SymbolDisplayFormat( SymbolDisplayGlobalNamespaceStyle.Omitted, ' Don't prepend VB namespaces with "Global." SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, ' Show fully qualified names SymbolDisplayGenericsOptions.IncludeTypeParameters, SymbolDisplayMemberOptions.IncludeContainingType Or SymbolDisplayMemberOptions.IncludeParameters, SymbolDisplayDelegateStyle.NameOnly, SymbolDisplayExtensionMethodStyle.StaticMethod, SymbolDisplayParameterOptions.IncludeType, SymbolDisplayPropertyStyle.ShowReadWriteDescriptor, SymbolDisplayLocalOptions.IncludeType, SymbolDisplayKindOptions.None, SymbolDisplayMiscellaneousOptions.UseSpecialTypes) <ImportingConstructor> <Obsolete(MefConstruction.ImportingConstructorMessage, True)> Public Sub New() End Sub ''' <summary> ''' Returns the node that should be displayed ''' </summary> Public Function GetDisplayNode(node As SyntaxNode) As SyntaxNode Implements ICodeLensDisplayInfoService.GetDisplayNode Select Case node.Kind() ' A variable declarator can contain multiple symbols, for example "Private field2, field3 As Integer" ' In that case default to the first field name. Case SyntaxKind.VariableDeclarator Dim variableNode = CType(node, VariableDeclaratorSyntax) Return GetDisplayNode(variableNode.Names.First()) ' A field declaration (global variable) can contain multiple symbols, for example "Private field2, field3 As Integer" ' In that case default to the first field name. Case SyntaxKind.FieldDeclaration Dim fieldNode = CType(node, FieldDeclarationSyntax) Return GetDisplayNode(fieldNode.Declarators.First()) Case SyntaxKind.PredefinedType Return GetDisplayNode(node.Parent) Case SyntaxKind.DocumentationCommentTrivia If node.IsStructuredTrivia Then Dim structuredTriviaSyntax = CType(node, StructuredTriviaSyntax) Return GetDisplayNode(structuredTriviaSyntax.ParentTrivia.Token.Parent) Else Return node End If End Select Return node End Function Private Shared Function SymbolToDisplayString(symbol As ISymbol) As String Return If(symbol Is Nothing, FeaturesResources.paren_Unknown_paren, symbol.ToDisplayString(Format)) End Function Private Shared Function FormatPropertyAccessor(node As SyntaxNode, symbolName As String) As String Dim symbolNameWithNoParams As String = RemoveParameters(symbolName) If node.IsKind(SyntaxKind.GetAccessorBlock) Then symbolName = String.Format(CultureInfo.CurrentCulture, VBFeaturesResources.Property_getter_name, symbolNameWithNoParams) Else Debug.Assert(node.IsKind(SyntaxKind.SetAccessorBlock)) symbolName = String.Format(CultureInfo.CurrentCulture, VBFeaturesResources.Property_setter_name, symbolNameWithNoParams) End If Return symbolName End Function Private Shared Function FormatEventHandler(node As SyntaxNode, symbolName As String) As String ' symbol name looks Like this at this point : Namespace.Class.Event(EventHandler) Dim symbolNameWithNoParams As String = RemoveParameters(symbolName) If node.IsKind(SyntaxKind.AddHandlerAccessorBlock) Then symbolName = String.Format(CultureInfo.CurrentCulture, VBFeaturesResources.Event_add_handler_name, symbolNameWithNoParams) Else Debug.Assert(node.IsKind(SyntaxKind.RemoveHandlerAccessorBlock)) symbolName = String.Format(CultureInfo.CurrentCulture, VBFeaturesResources.Event_remove_handler_name, symbolNameWithNoParams) End If Return symbolName End Function Private Shared Function IsAccessorForDefaultProperty(symbol As ISymbol) As Boolean Dim methodSymbol = TryCast(symbol, IMethodSymbol) ' its really a SourcePropertyAccessorSymbol but it Is Not accessible If methodSymbol IsNot Nothing Then Dim propertySymbol = TryCast(methodSymbol.AssociatedSymbol, IPropertySymbol) If propertySymbol IsNot Nothing Then ' Applying the default modifier to a property allows it to be used Like a C# indexer Return propertySymbol.IsDefault() End If End If Return False End Function Private Shared Function RemoveParameters(symbolName As String) As String Dim openParenIndex As Integer = symbolName.IndexOf("("c) Dim symbolNameWithNoParams As String = symbolName.Substring(0, openParenIndex) Return symbolNameWithNoParams End Function ''' <summary> ''' Gets the DisplayName for the given node. ''' </summary> Public Function GetDisplayName(semanticModel As SemanticModel, node As SyntaxNode) As String Implements ICodeLensDisplayInfoService.GetDisplayName If VisualBasicSyntaxFacts.Instance.IsGlobalAssemblyAttribute(node) Then Return node.ToString() End If Dim symbol As ISymbol = semanticModel.GetDeclaredSymbol(node) Dim symbolName As String Select Case node.Kind() Case SyntaxKind.GetAccessorBlock, SyntaxKind.SetAccessorBlock ' Indexer properties should Not include get And set symbol = semanticModel.GetDeclaredSymbol(node) If IsAccessorForDefaultProperty(symbol) AndAlso node.Parent.IsKind(SyntaxKind.PropertyBlock) Then Return GetDisplayName(semanticModel, node.Parent) Else ' Append "get" Or "set" to property accessors symbolName = SymbolToDisplayString(symbol) symbolName = FormatPropertyAccessor(node, symbolName) End If Case SyntaxKind.AddHandlerAccessorBlock, SyntaxKind.RemoveHandlerAccessorBlock ' Append "add" Or "remove" to event handlers symbolName = SymbolToDisplayString(symbol) symbolName = FormatEventHandler(node, symbolName) Case SyntaxKind.ImportsStatement symbolName = "Imports" Case Else symbolName = SymbolToDisplayString(symbol) End Select Return symbolName End Function End Class End Namespace