private static async Task <object[]> RunGetDocumentSymbolsAsync(Solution solution, bool hierarchicalSupport)
        {
            var document = solution.Projects.First().Documents.First();
            var request  = new LSP.DocumentSymbolParams
            {
                TextDocument = CreateTextDocumentIdentifier(new Uri(document.FilePath))
            };

            var clientCapabilities = new LSP.ClientCapabilities()
            {
                TextDocument = new LSP.TextDocumentClientCapabilities()
                {
                    DocumentSymbol = new LSP.DocumentSymbolSetting()
                    {
                        HierarchicalDocumentSymbolSupport = hierarchicalSupport
                    }
                }
            };

            return(await GetLanguageServer(solution).GetDocumentSymbolsAsync(solution, request, clientCapabilities, CancellationToken.None));
        }
Beispiel #2
0
        private static async Task <object[]> RunGetDocumentSymbolsAsync(TestLspServer testLspServer, bool hierarchicalSupport)
        {
            var document = testLspServer.GetCurrentSolution().Projects.First().Documents.First();
            var request  = new LSP.DocumentSymbolParams
            {
                TextDocument = CreateTextDocumentIdentifier(new Uri(document.FilePath))
            };

            var clientCapabilities = new LSP.ClientCapabilities()
            {
                TextDocument = new LSP.TextDocumentClientCapabilities()
                {
                    DocumentSymbol = new LSP.DocumentSymbolSetting()
                    {
                        HierarchicalDocumentSymbolSupport = hierarchicalSupport
                    }
                }
            };

            return(await testLspServer.ExecuteRequestAsync <LSP.DocumentSymbolParams, object[]>(LSP.Methods.TextDocumentDocumentSymbolName,
                                                                                                request, clientCapabilities, null, CancellationToken.None));
        }
        private static async Task <LSP.CompletionList> RunGetCompletionsAsync(
            TestLspServer testLspServer,
            LSP.CompletionParams completionParams,
            LSP.ClientCapabilities clientCapabilities)
        {
            var completionList = await testLspServer.ExecuteRequestAsync <LSP.CompletionParams, LSP.CompletionList>(LSP.Methods.TextDocumentCompletionName,
                                                                                                                    completionParams, clientCapabilities, null, CancellationToken.None);

            // Emulate client behavior of promoting "Data" completion list properties onto completion items.
            if (clientCapabilities.HasCompletionListDataCapability() &&
                completionList is VSCompletionList vsCompletionList &&
                vsCompletionList.Data != null)
            {
                foreach (var completionItem in completionList.Items)
                {
                    Assert.Null(completionItem.Data);
                    completionItem.Data = vsCompletionList.Data;
                }
            }

            return(completionList);
        }
        protected async Task <DocumentOutlineTestMocks> CreateMocksAsync(string code)
        {
            var workspace        = TestWorkspace.CreateCSharp(code, composition: s_composition);
            var threadingContext = workspace.GetService <IThreadingContext>();

            var clientCapabilities = new LSP.ClientCapabilities()
            {
                TextDocument = new LSP.TextDocumentClientCapabilities()
                {
                    DocumentSymbol = new LSP.DocumentSymbolSetting()
                    {
                        HierarchicalDocumentSymbolSupport = true
                    }
                }
            };

            var testLspServer = await CreateTestLspServerAsync(workspace, new InitializationOptions { ClientCapabilities = clientCapabilities });

            var languageServiceBrokerMock = new Mock <ILanguageServiceBroker2>(MockBehavior.Strict);

#pragma warning disable CS0618 // Type or member is obsolete
            languageServiceBrokerMock
            .Setup(l => l.RequestAsync(It.IsAny <ITextBuffer>(), It.IsAny <Func <JToken, bool> >(), It.IsAny <string>(), It.IsAny <string>(), It.IsAny <Func <ITextSnapshot, JToken> >(), It.IsAny <CancellationToken>()))
            .Returns <ITextBuffer, Func <JToken, bool>, string, string, Func <ITextSnapshot, JToken>, CancellationToken>(RequestAsync);
#pragma warning restore CS0618 // Type or member is obsolete

            var mocks = new DocumentOutlineTestMocks(languageServiceBrokerMock.Object, threadingContext, workspace, testLspServer);
            return(mocks);

            async Task <ManualInvocationResponse?> RequestAsync(ITextBuffer textBuffer, Func <JToken, bool> capabilitiesFilter, string languageServerName, string method, Func <ITextSnapshot, JToken> parameterFactory, CancellationToken cancellationToken)
            {
                var request  = parameterFactory(textBuffer.CurrentSnapshot).ToObject <RoslynDocumentSymbolParams>();
                var response = await testLspServer.ExecuteRequestAsync <RoslynDocumentSymbolParams, DocumentSymbol[]>(method, request !, cancellationToken);

                return(new ManualInvocationResponse(string.Empty, JToken.FromObject(response !)));
            }
        }
        public async Task <object> HandleRequestAsync(Solution solution, LSP.TextDocumentPositionParams request,
                                                      LSP.ClientCapabilities clientCapabilities, CancellationToken cancellationToken)
        {
            var locations = ArrayBuilder <LSP.Location> .GetInstance();

            var document = solution.GetDocumentFromURI(request.TextDocument.Uri);

            if (document == null)
            {
                return(locations.ToArrayAndFree());
            }

            var findUsagesService = document.Project.LanguageServices.GetService <IFindUsagesService>();
            var position          = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);

            var context = new SimpleFindUsagesContext(cancellationToken);

            await FindImplementationsAsync(findUsagesService, document, position, context).ConfigureAwait(false);

            foreach (var definition in context.GetDefinitions())
            {
                var text = definition.GetClassifiedText();
                foreach (var sourceSpan in context.GetDefinitions().SelectMany(definition => definition.SourceSpans))
                {
                    if (clientCapabilities?.HasVisualStudioLspCapability() == true)
                    {
                        locations.Add(await ProtocolConversions.DocumentSpanToLocationWithTextAsync(sourceSpan, text, cancellationToken).ConfigureAwait(false));
                    }
                    else
                    {
                        locations.Add(await ProtocolConversions.DocumentSpanToLocationAsync(sourceSpan, cancellationToken).ConfigureAwait(false));
                    }
                }
            }

            return(locations.ToArrayAndFree());
        }
Beispiel #6
0
        private static async Task <T> GetCompletionItemToResolveAsync <T>(
            TestLspServer testLspServer,
            string label,
            LSP.ClientCapabilities clientCapabilities = null) where T : LSP.CompletionItem
        {
            var completionParams = CreateCompletionParams(
                testLspServer.GetLocations("caret").Single(), LSP.VSInternalCompletionInvokeKind.Explicit, "\0", LSP.CompletionTriggerKind.Invoked);

            clientCapabilities ??= new LSP.VSInternalClientCapabilities {
                SupportsVisualStudioExtensions = true
            };
            var completionList = await RunGetCompletionsAsync(testLspServer, completionParams, clientCapabilities);

            if (clientCapabilities.HasCompletionListDataCapability())
            {
                var vsCompletionList = Assert.IsAssignableFrom <VSInternalCompletionList>(completionList);
                Assert.NotNull(vsCompletionList.Data);
            }

            var serverCompletionItem = completionList.Items.FirstOrDefault(item => item.Label == label);
            var clientCompletionItem = ConvertToClientCompletionItem((T)serverCompletionItem);

            return(clientCompletionItem);
        }
            private TestLspServer(TestWorkspace testWorkspace, Dictionary <string, IList <LSP.Location> > locations, LSP.ClientCapabilities clientCapabilities, WellKnownLspServerKinds serverKind)
            {
                TestWorkspace      = testWorkspace;
                ClientCapabilities = clientCapabilities;
                _locations         = locations;

                var(clientStream, serverStream) = FullDuplexStream.CreatePair();
                _languageServer = CreateLanguageServer(serverStream, serverStream, TestWorkspace, serverKind);

                _clientRpc = new JsonRpc(new HeaderDelimitedMessageHandler(clientStream, clientStream, CreateJsonMessageFormatter()))
                {
                    ExceptionStrategy = ExceptionProcessing.ISerializable,
                };

                _clientRpc.StartListening();

                var workspaceWaiter = GetWorkspaceWaiter(testWorkspace);

                Assert.False(workspaceWaiter.HasPendingWork);

                // Clear any LSP solutions that were created when the workspace was initialized.
                // This ensures that the workspace manager starts with a clean slate.
                GetManagerAccessor().ResetLspSolutions();
            }
Beispiel #8
0
        private static List <Task <TestResponse> > StartTestRun(
            TestLspServer testLspServer,
            TestRequest[] requests
            )
        {
            var clientCapabilities = new LSP.ClientCapabilities();

            var waitables = new List <Task <TestResponse> >();

            foreach (var request in requests)
            {
                waitables.Add(
                    testLspServer.ExecuteRequestAsync <TestRequest, TestResponse>(
                        request.MethodName,
                        request,
                        clientCapabilities,
                        null,
                        CancellationToken.None
                        )
                    );
            }

            return(waitables);
        }
Beispiel #9
0
 /// <summary>
 /// Answers a signature help request to get signature information at a given cursor position.
 /// https://microsoft.github.io/language-server-protocol/specification#textDocument_signatureHelp
 /// </summary>
 /// <param name="solution">the solution containing the document.</param>
 /// <param name="request">the request document position.</param>
 /// <param name="clientCapabilities">the client capabilities for the request.</param>
 /// <param name="cancellationToken">a cancellation token.</param>
 /// <returns>the signature help at a given location.</returns>
 public Task <LSP.SignatureHelp> GetSignatureHelpAsync(Solution solution, LSP.TextDocumentPositionParams request, LSP.ClientCapabilities clientCapabilities, CancellationToken cancellationToken)
 => ExecuteRequestAsync <LSP.TextDocumentPositionParams, LSP.SignatureHelp>(LSP.Methods.TextDocumentSignatureHelpName, solution, request, clientCapabilities, cancellationToken);
        public override async Task <LSP.CompletionItem[]> HandleRequestAsync(LSP.CompletionParams request, LSP.ClientCapabilities clientCapabilities, string?clientName,
                                                                             CancellationToken cancellationToken)
        {
            var document = SolutionProvider.GetDocument(request.TextDocument, clientName);

            if (document == null)
            {
                return(Array.Empty <LSP.CompletionItem>());
            }

            var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);

            // Filter out snippets as they are not supported in the LSP client
            // https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1139740
            // Filter out unimported types for now as there are two issues with providing them:
            // 1.  LSP client does not currently provide a way to provide detail text on the completion item to show the namespace.
            //     https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1076759
            // 2.  We need to figure out how to provide the text edits along with the completion item or provide them in the resolve request.
            //     https://devdiv.visualstudio.com/DevDiv/_workitems/edit/985860/
            // 3.  LSP client should support completion filters / expanders
            var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

            var completionOptions = documentOptions
                                    .WithChangedOption(CompletionOptions.SnippetsBehavior, SnippetsRule.NeverInclude)
                                    .WithChangedOption(CompletionOptions.ShowItemsFromUnimportedNamespaces, false)
                                    .WithChangedOption(CompletionServiceOptions.IsExpandedCompletion, false);

            var completionService = document.Project.LanguageServices.GetRequiredService <CompletionService>();
            var list = await completionService.GetCompletionsAsync(document, position, options : completionOptions, cancellationToken : cancellationToken).ConfigureAwait(false);

            if (list == null)
            {
                return(Array.Empty <LSP.CompletionItem>());
            }

            var lspVSClientCapability = clientCapabilities?.HasVisualStudioLspCapability() == true;

            return(list.Items.Select(item => CreateLSPCompletionItem(request, item, lspVSClientCapability)).ToArray());
        public Task <object> HandleRequestAsync(Solution solution, LSP.ExecuteCommandParams request, LSP.ClientCapabilities clientCapabilities,
                                                string?clientName, CancellationToken cancellationToken)
        {
            var commandName = request.Command;

            if (string.IsNullOrEmpty(commandName) || !_executeCommandHandlers.TryGetValue(commandName, out var executeCommandHandler))
            {
                throw new ArgumentException(string.Format("Command name ({0}) is invalid", commandName));
            }

            return(executeCommandHandler.Value.HandleRequestAsync(solution, request, clientCapabilities, cancellationToken));
        }
Beispiel #12
0
 /// <summary>
 /// Answers an implementation request by returning the implementation location(s) of a given symbol.
 /// https://microsoft.github.io/language-server-protocol/specification#textDocument_implementation
 /// </summary>
 /// <param name="solution">the solution containing the request document.</param>
 /// <param name="request">the request document symbol location.</param>
 /// <param name="clientCapabilities">the client capabilities for the request.</param>
 /// <param name="cancellationToken">a cancellation token.</param>
 /// <returns>the location(s) of the implementations of the symbol.</returns>
 public Task <object> FindImplementationsAsync(Solution solution, LSP.TextDocumentPositionParams request, LSP.ClientCapabilities clientCapabilities, CancellationToken cancellationToken)
 => ExecuteRequestAsync <LSP.TextDocumentPositionParams, object>(LSP.Methods.TextDocumentImplementationName, solution, request, clientCapabilities, cancellationToken);
Beispiel #13
0
 /// <summary>
 /// Answers a format document request to format the entire document.
 /// https://microsoft.github.io/language-server-protocol/specification#textDocument_formatting
 /// </summary>
 /// <param name="solution">the solution containing the document.</param>
 /// <param name="request">the request document and formatting options.</param>
 /// <param name="clientCapabilities">the client capabilities for the request.</param>
 /// <param name="cancellationToken">a cancellation token.</param>
 /// <returns>the text edits describing the document modifications.</returns>
 public Task <LSP.TextEdit[]> FormatDocumentAsync(Solution solution, LSP.DocumentFormattingParams request, LSP.ClientCapabilities clientCapabilities, CancellationToken cancellationToken)
 => ExecuteRequestAsync <LSP.DocumentFormattingParams, LSP.TextEdit[]>(LSP.Methods.TextDocumentFormattingName, solution, request, clientCapabilities, cancellationToken);
            internal static async Task <TestLspServer> CreateAsync(TestWorkspace testWorkspace, LSP.ClientCapabilities clientCapabilities, LanguageServerTarget target, Stream clientStream)
            {
                var locations = await GetAnnotatedLocationsAsync(testWorkspace, testWorkspace.CurrentSolution);

                var server = new TestLspServer(testWorkspace, locations, clientCapabilities, target, clientStream);

                await server.ExecuteRequestAsync <LSP.InitializeParams, LSP.InitializeResult>(LSP.Methods.InitializeName, new LSP.InitializeParams
                {
                    Capabilities = clientCapabilities,
                }, CancellationToken.None);

                return(server);
            }
Beispiel #15
0
 /// <summary>
 /// Answers an execute workspace command request by handling the specified command name.
 /// https://microsoft.github.io/language-server-protocol/specification#workspace_executeCommand
 /// </summary>
 /// <param name="solution">the solution relevant to the workspace.</param>
 /// <param name="request">the request command name and arguments.</param>
 /// <param name="clientCapabilities">the client capabilities for the request.</param>
 /// <param name="cancellationToken">a cancellation token.</param>
 /// <returns>any or null.</returns>
 public Task <object> ExecuteWorkspaceCommandAsync(Solution solution, LSP.ExecuteCommandParams request, LSP.ClientCapabilities clientCapabilities, CancellationToken cancellationToken)
 => ExecuteRequestAsync <LSP.ExecuteCommandParams, object>(LSP.Methods.WorkspaceExecuteCommandName, solution, request, clientCapabilities, cancellationToken);
Beispiel #16
0
 public async Task <LSP.TextEdit[]> HandleRequestAsync(Solution solution, LSP.DocumentFormattingParams request, LSP.ClientCapabilities clientCapabilities,
                                                       CancellationToken cancellationToken)
 {
     return(await GetTextEdits(solution, request.TextDocument.Uri, cancellationToken).ConfigureAwait(false));
 }
Beispiel #17
0
 public async Task <LSP.Location[]> HandleRequestAsync(Solution solution, LSP.TextDocumentPositionParams request,
                                                       LSP.ClientCapabilities clientCapabilities, CancellationToken cancellationToken)
 {
     return(await GetDefinitionAsync(solution, request, typeOnly : true, cancellationToken : cancellationToken).ConfigureAwait(false));
 }
Beispiel #18
0
 private static async Task <LSP.Command[]> RunCodeActionsAsync(Solution solution, LSP.Location caret, LSP.ClientCapabilities clientCapabilities = null)
 => await GetLanguageServer(solution).GetCodeActionsAsync(solution, CreateCodeActionParams(caret), clientCapabilities, CancellationToken.None);
        public override async Task <LSP.CompletionItem> HandleRequestAsync(LSP.CompletionItem completionItem, LSP.ClientCapabilities clientCapabilities,
                                                                           string?clientName, CancellationToken cancellationToken)
        {
            CompletionResolveData data;

            if (completionItem.Data is CompletionResolveData)
            {
                data = (CompletionResolveData)completionItem.Data;
            }
            else
            {
                data = ((JToken)completionItem.Data).ToObject <CompletionResolveData>();
            }

            var document = SolutionProvider.GetDocument(data.TextDocument, clientName);

            if (document == null)
            {
                return(completionItem);
            }

            var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(data.Position), cancellationToken).ConfigureAwait(false);

            var completionService = document.Project.LanguageServices.GetRequiredService <CompletionService>();
            var list = await completionService.GetCompletionsAsync(document, position, cancellationToken : cancellationToken).ConfigureAwait(false);

            if (list == null)
            {
                return(completionItem);
            }

            var selectedItem = list.Items.FirstOrDefault(i => i.DisplayText == data.DisplayText);

            if (selectedItem == null)
            {
                return(completionItem);
            }

            var description = await completionService.GetDescriptionAsync(document, selectedItem, cancellationToken).ConfigureAwait(false);

            var lspVSClientCapability = clientCapabilities?.HasVisualStudioLspCapability() == true;

            LSP.CompletionItem resolvedCompletionItem;
            if (lspVSClientCapability)
            {
                resolvedCompletionItem = CloneVSCompletionItem(completionItem);
                ((LSP.VSCompletionItem)resolvedCompletionItem).Description = new ClassifiedTextElement(description.TaggedParts
                                                                                                       .Select(tp => new ClassifiedTextRun(tp.Tag.ToClassificationTypeName(), tp.Text)));
            }
            else
            {
                resolvedCompletionItem = RoslynCompletionItem.From(completionItem);
                ((RoslynCompletionItem)resolvedCompletionItem).Description = description.TaggedParts.Select(
                    tp => new RoslynTaggedText {
                    Tag = tp.Tag, Text = tp.Text
                }).ToArray();
            }

            resolvedCompletionItem.Detail = description.TaggedParts.GetFullText();
            return(resolvedCompletionItem);
        }
Beispiel #20
0
 /// <summary>
 /// Answers a Hover request by returning the quick info at the requested location.
 /// https://microsoft.github.io/language-server-protocol/specification#textDocument_hover
 /// </summary>
 /// <param name="solution">the solution containing any documents in the request.</param>
 /// <param name="request">the hover requesst.</param>
 /// <param name="clientCapabilities">the client capabilities for the request.</param>
 /// <param name="cancellationToken">a cancellation token.</param>
 /// <returns>the Hover using MarkupContent.</returns>
 public Task <LSP.Hover> GetHoverAsync(Solution solution, LSP.TextDocumentPositionParams request, LSP.ClientCapabilities clientCapabilities, CancellationToken cancellationToken)
 => ExecuteRequestAsync <LSP.TextDocumentPositionParams, LSP.Hover>(LSP.Methods.TextDocumentHoverName, solution, request, clientCapabilities, cancellationToken);
Beispiel #21
0
 /// <summary>
 /// Answers a folding range request by returning all folding ranges in a given document.
 /// https://microsoft.github.io/language-server-protocol/specification#textDocument_foldingRange
 /// </summary>
 /// <param name="solution">the solution containing the document.</param>
 /// <param name="request">the request document.</param>
 /// <param name="clientCapabilities">the client capabilities for the request.</param>
 /// <param name="cancellationToken">a cancellation token.</param>
 /// <returns>a list of folding ranges in the document.</returns>
 public Task <LSP.FoldingRange[]> GetFoldingRangeAsync(Solution solution, LSP.FoldingRangeParams request, LSP.ClientCapabilities clientCapabilities, CancellationToken cancellationToken)
 => ExecuteRequestAsync <LSP.FoldingRangeParams, LSP.FoldingRange[]>(LSP.Methods.TextDocumentFoldingRangeName, solution, request, clientCapabilities, cancellationToken);
Beispiel #22
0
 /// <summary>
 /// Answers a document symbols request by returning a list of symbols in the document.
 /// https://microsoft.github.io/language-server-protocol/specification#textDocument_documentSymbol
 /// </summary>
 /// <param name="solution">the solution containing the document.</param>
 /// <param name="request">the document to get symbols from.</param>
 /// <param name="clientCapabilities">the client capabilities for the request.</param>
 /// <param name="cancellationToken">a cancellation token.</param>
 /// <returns>a list of symbols in the document.</returns>
 public Task <object[]> GetDocumentSymbolsAsync(Solution solution, LSP.DocumentSymbolParams request, LSP.ClientCapabilities clientCapabilities, CancellationToken cancellationToken)
 => ExecuteRequestAsync <LSP.DocumentSymbolParams, object[]>(LSP.Methods.TextDocumentDocumentSymbolName, solution, request, clientCapabilities, cancellationToken);
Beispiel #23
0
 public override LSP.ServerCapabilities GetCapabilities(LSP.ClientCapabilities clientCapabilities) => new();
Beispiel #24
0
 /// <summary>
 /// Answers a workspace symbols request by providing a list of symbols found in a given workspace.
 /// https://microsoft.github.io/language-server-protocol/specification#workspace_symbol
 /// </summary>
 /// <param name="solution">the current solution.</param>
 /// <param name="request">the workspace request with the query to invoke.</param>
 /// <param name="clientCapabilities">the client capabilities for the request.</param>
 /// <param name="cancellationToken">a cancellation token.</param>
 /// <returns>a list of symbols in the workspace.</returns>
 public Task <LSP.SymbolInformation[]> GetWorkspaceSymbolsAsync(Solution solution, LSP.WorkspaceSymbolParams request, LSP.ClientCapabilities clientCapabilities, CancellationToken cancellationToken)
 => ExecuteRequestAsync <LSP.WorkspaceSymbolParams, LSP.SymbolInformation[]>(LSP.Methods.WorkspaceSymbolName, solution, request, clientCapabilities, cancellationToken);
Beispiel #25
0
 public Task <LSP.Location[]> HandleRequestAsync(Solution solution, LSP.TextDocumentPositionParams request,
                                                 LSP.ClientCapabilities clientCapabilities, string?clientName, CancellationToken cancellationToken)
 => GetDefinitionAsync(solution, request, typeOnly: false, clientName, cancellationToken: cancellationToken);
Beispiel #26
0
 /// <summary>
 /// Answers a goto type definition request by returning the location of a given type definition.
 /// https://microsoft.github.io/language-server-protocol/specification#textDocument_typeDefinition
 /// </summary>
 /// <param name="solution">the solution containing the request.</param>
 /// <param name="request">the document position of the type to go to.</param>
 /// <param name="clientCapabilities">the client capabilities for the request.</param>
 /// <param name="cancellationToken">a cancellation token.</param>
 /// <returns>the location of a type definition.</returns>
 public Task <LSP.Location[]> GoToTypeDefinitionAsync(Solution solution, LSP.TextDocumentPositionParams request, LSP.ClientCapabilities clientCapabilities, CancellationToken cancellationToken)
 => ExecuteRequestAsync <LSP.TextDocumentPositionParams, LSP.Location[]>(LSP.Methods.TextDocumentTypeDefinitionName, solution, request, clientCapabilities, cancellationToken);
 private static async Task <object> RunResolveCompletionItemAsync(Solution solution, LSP.CompletionItem completionItem, LSP.ClientCapabilities clientCapabilities = null)
 => await GetLanguageServer(solution).ExecuteRequestAsync <LSP.CompletionItem, LSP.CompletionItem>(LSP.Methods.TextDocumentCompletionResolveName,
                                                                                                   completionItem, clientCapabilities, null, CancellationToken.None);
Beispiel #28
0
 /// <summary>
 /// Answers an initialize request by returning the server capabilities.
 /// https://microsoft.github.io/language-server-protocol/specification#initialize
 /// </summary>
 /// <param name="solution">the solution containing the document.</param>
 /// <param name="request">the initialize parameters.</param>
 /// <param name="clientCapabilities">the client capabilities for the request.</param>
 /// <param name="cancellationToken">a cancellation token.</param>
 /// <returns>the server capabilities.</returns>
 public Task <LSP.InitializeResult> InitializeAsync(Solution solution, LSP.InitializeParams request, LSP.ClientCapabilities clientCapabilities, CancellationToken cancellationToken)
 => ExecuteRequestAsync <LSP.InitializeParams, LSP.InitializeResult>(LSP.Methods.InitializeName, solution, request, clientCapabilities, cancellationToken);
Beispiel #29
0
        public override async Task <LSP.VSCodeAction[]> HandleRequestAsync(
            LSP.CodeActionParams request,
            LSP.ClientCapabilities clientCapabilities,
            string?clientName,
            CancellationToken cancellationToken)
        {
            var document = SolutionProvider.GetDocument(request.TextDocument, clientName);

            if (document == null)
            {
                return(Array.Empty <VSCodeAction>());
            }

            var(codeFixCollections, codeRefactorings) = await CodeActionHelpers.GetCodeFixesAndRefactoringsAsync(
                document, _codeFixService, _codeRefactoringService,
                request.Range, cancellationToken).ConfigureAwait(false);

            var codeFixes = codeFixCollections.SelectMany(c => c.Fixes);

            using var _ = ArrayBuilder <VSCodeAction> .GetInstance(out var results);

            // Go through code fixes and code refactorings separately so that we can properly set the CodeActionKind.
            foreach (var codeFix in codeFixes)
            {
                // Filter out code actions with options since they'll show dialogs and we can't remote the UI and the options.
                if (codeFix.Action is CodeActionWithOptions)
                {
                    continue;
                }

                // Temporarily filter out suppress and configure code actions, as we'll later combine them under a top-level
                // code action.
                if (codeFix.Action is AbstractConfigurationActionWithNestedActions)
                {
                    continue;
                }

                results.Add(GenerateVSCodeAction(request, codeFix.Action, CodeActionKind.QuickFix));
            }

            foreach (var(action, _) in codeRefactorings.SelectMany(codeRefactoring => codeRefactoring.CodeActions))
            {
                // Filter out code actions with options since they'll show dialogs and we can't remote the UI and the options.
                if (action is CodeActionWithOptions)
                {
                    continue;
                }

                results.Add(GenerateVSCodeAction(request, action, CodeActionKind.Refactor));
            }

            // Special case (also dealt with specially in local Roslyn):
            // If we have configure/suppress code actions, combine them under one top-level code action.
            var configureSuppressActions = codeFixes.Where(a => a.Action is AbstractConfigurationActionWithNestedActions);

            if (configureSuppressActions.Any())
            {
                results.Add(GenerateVSCodeAction(request, new CodeActionWithNestedActions(
                                                     CodeFixesResources.Suppress_or_Configure_issues,
                                                     configureSuppressActions.Select(a => a.Action).ToImmutableArray(), true), CodeActionKind.QuickFix));
            }

            return(results.ToArray());
Beispiel #30
0
 /// <summary>
 /// Answers a request to resolve a completion item.
 /// https://microsoft.github.io/language-server-protocol/specification#completionItem_resolve
 /// </summary>
 /// <param name="solution">the solution containing the document.</param>
 /// <param name="request">the completion item to resolve.</param>
 /// <param name="clientCapabilities">the client capabilities for the request.</param>
 /// <param name="cancellationToken">a cancellation token.</param>
 /// <returns>a resolved completion item.</returns>
 public Task <LSP.CompletionItem> ResolveCompletionItemAsync(Solution solution, LSP.CompletionItem request, LSP.ClientCapabilities clientCapabilities, CancellationToken cancellationToken)
 => ExecuteRequestAsync <LSP.CompletionItem, LSP.CompletionItem>(LSP.Methods.TextDocumentCompletionResolveName, solution, request, clientCapabilities, cancellationToken);