提交 d3da6e81 编写于 作者: A Artur Spychaj

Add completions for #r REPL command

上级 d5a4b8f1
......@@ -56,8 +56,8 @@
</PropertyGroup>
<ItemGroup>
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.VisualBasic.EditorFeatures" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.VisualBasic.InteractiveEditorFeatures" />
<InternalsVisibleTo Include="Microsoft.VisualStudio.LanguageServices.VisualBasic" />
<InternalsVisibleTo Include="Roslyn.VisualBasic.InteractiveEditorFeatures" />
<InternalsVisibleToTest Include="Roslyn.Services.Editor.CSharp.UnitTests" />
<InternalsVisibleToTest Include="Roslyn.Services.Editor.UnitTests" />
<InternalsVisibleToTest Include="Roslyn.Services.Editor.UnitTests2" />
......
......@@ -84,6 +84,7 @@
<DocumentationFile>Microsoft.CodeAnalysis.VisualBasic.EditorFeatures.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Compile Include="Interactive\FileSystem\ReferenceDirectiveCompletionProvider.vb" />
<Compile Include="Interactive\VisualBasicInteractiveEvaluator.vb" />
<Compile Include="Interactive\VisualBasicReplServiceProvider.vb" />
<Compile Include="VBInteractiveEditorResources.Designer.vb">
......@@ -153,6 +154,9 @@
<PublicAPI Include="PublicAPI.Shipped.txt" />
<PublicAPI Include="PublicAPI.Unshipped.txt" />
</ItemGroup>
<ItemGroup>
<Compile Include="Interactive\CompletionProviders\ReplCommandCompletionProvider.vb" />
</ItemGroup>
<ImportGroup Label="Targets">
<Import Project="..\..\..\..\build\Targets\VSL.Imports.targets" />
</ImportGroup>
......
' 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.Threading
Imports System.Threading.Tasks
Imports Microsoft.CodeAnalysis.Completion
Imports Microsoft.CodeAnalysis.VisualBasic.Completion.Providers
Imports Microsoft.CodeAnalysis.Editor.Implementation.Interactive
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.VisualStudio.InteractiveWindow
Imports Microsoft.VisualStudio.Text.Editor
Imports Microsoft.VisualStudio.Utilities
Imports Microsoft.VisualStudio.InteractiveWindow.Commands
Namespace Microsoft.CodeAnalysis.Editor.CSharp.Completion.CompletionProviders
<ExportCompletionProvider("ReplCommandCompletionProvider", LanguageNames.VisualBasic)>
<TextViewRole(PredefinedInteractiveTextViewRoles.InteractiveTextViewRole)>
<Order(Before:=PredefinedCompletionProviderNames.Keyword)>
Friend Class ReplCommandCompletionProvider
Inherits CompletionListProvider
Private Async Function GetTextChangeSpanAsync(document As Document, position As Integer, cancellationToken As CancellationToken) As Task(Of TextSpan)
Dim text = Await document.GetTextAsync(cancellationToken).ConfigureAwait(False)
Return CompletionUtilities.GetTextChangeSpan(text, position)
End Function
Public Overrides Function IsTriggerCharacter(text As SourceText, characterPosition As Integer, options As OptionSet) As Boolean
Return CompletionUtilities.IsTriggerAfterSpaceOrStartOfWordCharacter(text, characterPosition, options)
End Function
Public Overrides Async Function ProduceCompletionListAsync(context As CompletionListContext) As Task
Dim document = context.Document
Dim position = context.Position
Dim cancellationToken = context.CancellationToken
' the provider might be invoked in non-interactive context:
Dim ws As Workspace = Nothing
If Workspace.TryGetWorkspace(document.GetTextAsync(cancellationToken).WaitAndGetResult(cancellationToken).Container, ws) Then
Dim workspace As InteractiveWorkspace = TryCast(ws, InteractiveWorkspace)
If workspace IsNot Nothing Then
Dim window = workspace.Engine.CurrentWindow
Dim tree = Await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(False)
Dim shouldComplete = tree.IsBeforeFirstToken(position, cancellationToken) AndAlso tree.IsPreProcessorKeywordContext(position, cancellationToken)
If shouldComplete Then
Dim filterSpan = Await Me.GetTextChangeSpanAsync(document, position, cancellationToken).ConfigureAwait(False)
Dim commands As IInteractiveWindowCommands = window.GetInteractiveCommands()
If commands IsNot Nothing Then
For Each commandItem In commands.GetCommands()
For Each commandName In commandItem.Names
' In VB the completion needs to include the # sign.
Dim completion = "#" + commandName
context.AddItem(New CompletionItem(Me, completion, filterSpan, Function(c) Task.FromResult(commandItem.Description.ToSymbolDisplayParts()), glyph:=Glyph.Intrinsic))
Next
Next
End If
End If
End If
End If
End Function
End Class
End Namespace
\ No newline at end of file
' 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.Threading
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Editor.Completion.FileSystem
Imports Microsoft.VisualStudio.InteractiveWindow
Imports Microsoft.VisualStudio.Text.Editor
Namespace Microsoft.CodeAnalysis.Editor.CSharp.Completion.CompletionProviders
<ExportCompletionProvider("ReferenceDirectiveCompletionProvider", LanguageNames.VisualBasic)>
<TextViewRole(PredefinedInteractiveTextViewRoles.InteractiveTextViewRole)>
Friend Class ReferenceDirectiveCompletionProvider : Inherits AbstractReferenceDirectiveCompletionProvider
Protected Overrides Function TryGetStringLiteralToken(tree As SyntaxTree, position As Integer, ByRef stringLiteral As SyntaxToken, cancellationToken As CancellationToken) As Boolean
If tree.IsEntirelyWithinStringLiteral(position, cancellationToken) Then
Dim token = tree.FindTokenOnLeftOfPosition(position, cancellationToken, includeDirectives:=True, includeDocumentationComments:=True)
' Verifies that the string literal under caret is the path token.
If token.IsKind(SyntaxKind.StringLiteralToken) AndAlso token.Parent.IsKind(SyntaxKind.ReferenceDirectiveTrivia) Then
stringLiteral = token
Return True
End If
End If
stringLiteral = Nothing
Return False
End Function
End Class
End Namespace
\ No newline at end of file
......@@ -47,7 +47,7 @@
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.VisualBasic.EditorFeatures" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.VisualBasic.Features" />
<InternalsVisibleTo Include="Microsoft.VisualStudio.LanguageServices.VisualBasic" />
<InternalsVisibleTo Include="Roslyn.VisualBasic.InteractiveEditorFeatures" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.VisualBasic.InteractiveEditorFeatures" />
<InternalsVisibleTo Include="Roslyn.VisualStudio.VisualBasic.Repl" />
<InternalsVisibleToTest Include="Roslyn.Hosting.Diagnostics" />
<InternalsVisibleToTest Include="Roslyn.Services.Editor.UnitTests" />
......
......@@ -32,6 +32,33 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery
Return token
End Function
<Extension()>
Public Function IsPreProcessorKeywordContext(syntaxTree As SyntaxTree, position As Integer, cancellationToken As CancellationToken) As Boolean
Return IsPreProcessorKeywordContext(
syntaxTree, position,
syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken, includeDirectives:=True),
cancellationToken)
End Function
<Extension()>
Public Function IsPreProcessorKeywordContext(syntaxTree As SyntaxTree, position As Integer, preProcessorTokenOnLeftOfPosition As SyntaxToken, cancellationToken As CancellationToken) As Boolean
' cases:
' #|
' #d|
' # |
' # d|
' note comments are Not allowed between the # And item.
Dim token = preProcessorTokenOnLeftOfPosition
token = token.GetPreviousTokenIfTouchingWord(position)
If token.IsKind(SyntaxKind.HashToken) Then
Return True
End If
Return False
End Function
<Extension()>
Public Function IsNamespaceContext(syntaxTree As SyntaxTree, position As Integer, token As SyntaxToken, cancellationToken As CancellationToken, Optional semanticModelOpt As SemanticModel = Nothing) As Boolean
Return syntaxTree.IsTypeContext(position, token, cancellationToken, semanticModelOpt)
......
......@@ -84,6 +84,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
Return False
End Function
<Extension()>
Public Function IsEntirelyWithinStringLiteral(syntaxTree As SyntaxTree, position As Integer, cancellationToken As CancellationToken) As Boolean
Dim token = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken, includeDirectives:=True, includeDocumentationComments:=True)
If token.IsKind(SyntaxKind.StringLiteralToken) Then
Return token.SpanStart < position AndAlso position < token.Span.End OrElse AtEndOfIncompleteStringOrCharLiteral(token, position, """")
End If
Return False
End Function
<Extension()>
Public Function IsEntirelyWithinStringOrCharOrNumericLiteral(syntaxTree As SyntaxTree, position As Integer, cancellationToken As CancellationToken) As Boolean
Dim token = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken, includeDirectives:=True, includeDocumentationComments:=True)
......@@ -98,13 +109,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
Return True
End If
Dim lastChar = If(token.IsKind(SyntaxKind.CharacterLiteralToken), "'", """")
Return AtEndOfIncompleteStringOrCharLiteral(token, position, lastChar)
End Function
Private Function AtEndOfIncompleteStringOrCharLiteral(token As SyntaxToken, position As Integer, lastChar As String) As Boolean
' Check if it's a token that was started, but not ended
Dim startLength = 1
If token.IsKind(SyntaxKind.CharacterLiteralToken) Then
startLength = 2
End If
Dim lastChar = If(token.IsKind(SyntaxKind.CharacterLiteralToken), "'", """")
Return _
position = token.Span.End AndAlso
(token.Span.Length = startLength OrElse
......@@ -138,6 +154,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
Return False
End Function
<Extension()>
Public Function IsBeforeFirstToken(syntaxTree As SyntaxTree, position As Integer, cancellationToken As CancellationToken) As Boolean
Dim firstToken = syntaxTree.GetRoot(cancellationToken).GetFirstToken(includeZeroWidth:=True, includeSkipped:=True)
Return position <= firstToken.SpanStart
End Function
<Extension()>
Public Function IsInSkippedText(syntaxTree As SyntaxTree, position As Integer, cancellationToken As CancellationToken) As Boolean
Dim trivia = syntaxTree.FindTriviaToLeft(position, cancellationToken)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册