' 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 System.Composition Imports System.Threading Imports System.Threading.Tasks Imports dnSpy.Roslyn.Internal.QuickInfo Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Shared.Extensions Imports Microsoft.CodeAnalysis.VisualBasic Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Microsoft.CodeAnalysis.VisualBasic.Utilities.IntrinsicOperators Namespace Global.Microsoft.CodeAnalysis.Editor.VisualBasic.QuickInfo Friend Class SemanticQuickInfoProvider Inherits AbstractSemanticQuickInfoProvider Public Sub New() End Sub Protected Overrides Async Function BuildContentAsync(document As Document, token As SyntaxToken, cancellationToken As CancellationToken) As Task(Of QuickInfoContent) Dim vbToken = CType(token, SyntaxToken) Dim parent = vbToken.Parent Dim predefinedCastExpression = TryCast(parent, PredefinedCastExpressionSyntax) If predefinedCastExpression IsNot Nothing AndAlso vbToken = predefinedCastExpression.Keyword Then Dim compilation = Await document.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(False) Dim documentation = New PredefinedCastExpressionDocumentation(predefinedCastExpression.Keyword.Kind, compilation) Return Await BuildContentForIntrinsicOperatorAsync(document, parent, documentation, Glyph.MethodPublic, cancellationToken).ConfigureAwait(False) End If Select Case vbToken.Kind Case SyntaxKind.AddHandlerKeyword If TypeOf parent Is AddRemoveHandlerStatementSyntax Then Return Await BuildContentForIntrinsicOperatorAsync(document, parent, New AddHandlerStatementDocumentation(), Glyph.Keyword, cancellationToken).ConfigureAwait(False) End If Case SyntaxKind.DimKeyword If TypeOf parent Is FieldDeclarationSyntax Then Return Await BuildContentAsync(document, token, DirectCast(parent, FieldDeclarationSyntax).Declarators, cancellationToken).ConfigureAwait(False) ElseIf TypeOf parent Is LocalDeclarationStatementSyntax Then Return Await BuildContentAsync(document, token, DirectCast(parent, LocalDeclarationStatementSyntax).Declarators, cancellationToken).ConfigureAwait(False) End If Case SyntaxKind.CTypeKeyword If TypeOf parent Is CTypeExpressionSyntax Then Return Await BuildContentForIntrinsicOperatorAsync(document, parent, New CTypeCastExpressionDocumentation(), Glyph.MethodPublic, cancellationToken).ConfigureAwait(False) End If Case SyntaxKind.DirectCastKeyword If TypeOf parent Is DirectCastExpressionSyntax Then Return Await BuildContentForIntrinsicOperatorAsync(document, parent, New DirectCastExpressionDocumentation(), Glyph.MethodPublic, cancellationToken).ConfigureAwait(False) End If Case SyntaxKind.GetTypeKeyword If TypeOf parent Is GetTypeExpressionSyntax Then Return Await BuildContentForIntrinsicOperatorAsync(document, parent, New GetTypeExpressionDocumentation(), Glyph.MethodPublic, cancellationToken).ConfigureAwait(False) End If Case SyntaxKind.GetXmlNamespaceKeyword If TypeOf parent Is GetXmlNamespaceExpressionSyntax Then Return Await BuildContentForIntrinsicOperatorAsync(document, parent, New GetXmlNamespaceExpressionDocumentation(), Glyph.MethodPublic, cancellationToken).ConfigureAwait(False) End If Case SyntaxKind.IfKeyword If parent.Kind = SyntaxKind.BinaryConditionalExpression Then Return Await BuildContentForIntrinsicOperatorAsync(document, parent, New BinaryConditionalExpressionDocumentation(), Glyph.MethodPublic, cancellationToken).ConfigureAwait(False) ElseIf parent.Kind = SyntaxKind.TernaryConditionalExpression Then Return Await BuildContentForIntrinsicOperatorAsync(document, parent, New TernaryConditionalExpressionDocumentation(), Glyph.MethodPublic, cancellationToken).ConfigureAwait(False) End If Case SyntaxKind.RemoveHandlerKeyword If TypeOf parent Is AddRemoveHandlerStatementSyntax Then Return Await BuildContentForIntrinsicOperatorAsync(document, parent, New RemoveHandlerStatementDocumentation(), Glyph.Keyword, cancellationToken).ConfigureAwait(False) End If Case SyntaxKind.TryCastKeyword If TypeOf parent Is TryCastExpressionSyntax Then Return Await BuildContentForIntrinsicOperatorAsync(document, parent, New TryCastExpressionDocumentation(), Glyph.MethodPublic, cancellationToken).ConfigureAwait(False) End If Case SyntaxKind.IdentifierToken If SyntaxFacts.GetContextualKeywordKind(token.ToString()) = SyntaxKind.MidKeyword Then If parent.Kind = SyntaxKind.MidExpression Then Return Await BuildContentForIntrinsicOperatorAsync(document, parent, New MidAssignmentDocumentation(), Glyph.MethodPublic, cancellationToken).ConfigureAwait(False) End If End If End Select Return Await MyBase.BuildContentAsync(document, token, cancellationToken).ConfigureAwait(False) End Function Private Overloads Async Function BuildContentAsync(document As Document, token As SyntaxToken, declarators As SeparatedSyntaxList(Of VariableDeclaratorSyntax), cancellationToken As CancellationToken) As Task(Of QuickInfoContent) If declarators.Count = 0 Then Return Nothing End If Dim semantics = Await document.GetSemanticModelForNodeAsync(token.Parent, cancellationToken).ConfigureAwait(False) Dim types = dnSpy.Roslyn.Utilities2.EnumerableExtensions2.WhereNotNull(declarators.SelectMany(Function(d) d.Names).Select( Function(n) Dim symbol = semantics.GetDeclaredSymbol(n, cancellationToken) If symbol Is Nothing Then Return Nothing End If If TypeOf symbol Is ILocalSymbol Then Return DirectCast(symbol, ILocalSymbol).Type ElseIf TypeOf symbol Is IFieldSymbol Then Return DirectCast(symbol, IFieldSymbol).Type Else Return Nothing End If End Function)).Distinct().ToList() If types.Count = 0 Then Return Nothing End If 'If types.Count > 1 Then ' Dim contentBuilder = New List(Of TaggedText) ' contentBuilder.AddText(VBEditorResources.Multiple_Types) ' Return Me.CreateClassifiableDeferredContent(contentBuilder) 'End If Return Await CreateContentAsync(document.Project.Solution.Workspace, token, semantics, types, supportedPlatforms:=Nothing, cancellationToken:=cancellationToken).ConfigureAwait(False) End Function Private Async Function BuildContentForIntrinsicOperatorAsync(document As Document, expression As SyntaxNode, documentation As AbstractIntrinsicOperatorDocumentation, glyph As Glyph, cancellationToken As CancellationToken) As Task(Of QuickInfoContent) Dim builder = New List(Of SymbolDisplayPart) builder.AddRange(documentation.PrefixParts) Dim semanticModel = Await document.GetSemanticModelForNodeAsync(expression, cancellationToken).ConfigureAwait(False) Dim position = expression.SpanStart For i = 0 To documentation.ParameterCount - 1 If i <> 0 Then builder.AddPunctuation(",") builder.AddSpace() End If Dim typeNameToBind = documentation.TryGetTypeNameParameter(expression, i) If typeNameToBind IsNot Nothing Then ' We'll try to bind the type name Dim typeInfo = semanticModel.GetTypeInfo(typeNameToBind, cancellationToken) If typeInfo.Type IsNot Nothing Then builder.AddRange(typeInfo.Type.ToMinimalDisplayParts(semanticModel, position)) Continue For End If End If builder.AddRange(documentation.GetParameterDisplayParts(i)) Next builder.AddRange(documentation.GetSuffix(semanticModel, position, expression, cancellationToken)) Return CreateQuickInfoDisplayDeferredContent( glyph, builder.ToTaggedText(), CreateDocumentationCommentDeferredContent(documentation.DocumentationText), Array.Empty(Of TaggedText), Array.Empty(Of TaggedText), Array.Empty(Of TaggedText), Array.Empty(Of TaggedText)) End Function End Class End Namespace