Exemplo n.º 1
0
        public async Task <object> HandleRequestAsync(LSP.ExecuteCommandParams request, RequestContext context, CancellationToken cancellationToken)
        {
            var runRequest = ((JToken)request.Arguments.Single()).ToObject <CodeActionResolveData>();
            var document   = _solutionProvider.GetDocument(runRequest.TextDocument);

            Contract.ThrowIfNull(document);

            var codeActions = await CodeActionHelpers.GetCodeActionsAsync(
                _codeActionsCache, document, runRequest.Range, _codeFixService, _codeRefactoringService, cancellationToken).ConfigureAwait(false);

            var actionToRun = CodeActionHelpers.GetCodeActionToResolve(runRequest.UniqueIdentifier, codeActions);

            Contract.ThrowIfNull(actionToRun);

            var operations = await actionToRun.GetOperationsAsync(cancellationToken).ConfigureAwait(false);

            // TODO - This UI thread dependency should be removed.
            // https://github.com/dotnet/roslyn/projects/45#card-20619668
            await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

            foreach (var operation in operations)
            {
                operation.Apply(document.Project.Solution.Workspace, cancellationToken);
            }

            return(true);
        }
Exemplo n.º 2
0
        public async Task <LSP.VSCodeAction[]> HandleRequestAsync(
            LSP.CodeActionParams request,
            RequestContext context,
            CancellationToken cancellationToken
            )
        {
            var document = context.Document;

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

            var codeActions = await CodeActionHelpers
                              .GetVSCodeActionsAsync(
                request,
                _codeActionsCache,
                document,
                _codeFixService,
                _codeRefactoringService,
                cancellationToken
                )
                              .ConfigureAwait(false);

            return(codeActions);
        }
Exemplo n.º 3
0
        public async Task <LSP.CodeAction[]> HandleRequestAsync(LSP.CodeActionParams request, RequestContext context, CancellationToken cancellationToken)
        {
            var document = context.Document;

            Contract.ThrowIfNull(document);

            var codeActions = await CodeActionHelpers.GetVSCodeActionsAsync(
                request, _codeActionsCache, document, _codeFixService, _codeRefactoringService, cancellationToken).ConfigureAwait(false);

            return(codeActions);
        }
Exemplo n.º 4
0
        public override async Task <LSP.VSCodeAction[]> HandleRequestAsync(LSP.CodeActionParams request, RequestContext context, CancellationToken cancellationToken)
        {
            var document = SolutionProvider.GetDocument(request.TextDocument, context.ClientName);

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

            var codeActions = await CodeActionHelpers.GetVSCodeActionsAsync(
                request, document, _codeFixService, _codeRefactoringService, _threadingContext,
                request.Range, cancellationToken).ConfigureAwait(false);

            return(codeActions);
        }
Exemplo n.º 5
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());
Exemplo n.º 6
0
        public override async Task <LSP.VSCodeAction> HandleRequestAsync(LSP.VSCodeAction codeAction, RequestContext context, CancellationToken cancellationToken)
        {
            var data     = ((JToken)codeAction.Data).ToObject <CodeActionResolveData>();
            var document = SolutionProvider.GetDocument(data.TextDocument, context.ClientName);

            Contract.ThrowIfNull(document);

            var codeActions = await CodeActionHelpers.GetCodeActionsAsync(
                document,
                _codeFixService,
                _codeRefactoringService,
                _threadingContext,
                data.Range,
                cancellationToken).ConfigureAwait(false);

            var codeActionToResolve = CodeActionHelpers.GetCodeActionToResolve(
                data.UniqueIdentifier, codeActions);

            Contract.ThrowIfNull(codeActionToResolve);

            var operations = await codeActionToResolve.GetOperationsAsync(cancellationToken).ConfigureAwait(false);

            if (operations.IsEmpty)
            {
                return(codeAction);
            }

            // If we have all non-ApplyChangesOperations, set up to run as command on the server
            // instead of using WorkspaceEdits.
            if (operations.All(operation => !(operation is ApplyChangesOperation)))
            {
                codeAction.Command = SetCommand(codeAction.Title, data);
                return(codeAction);
            }

            // TO-DO: We currently must execute code actions which add new documents on the server as commands,
            // since there is no LSP support for adding documents yet. In the future, we should move these actions
            // to execute on the client.
            // https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1147293/

            // Add workspace edits
            var applyChangesOperations = operations.OfType <ApplyChangesOperation>();

            if (applyChangesOperations.Any())
            {
                using var _ = ArrayBuilder <TextDocumentEdit> .GetInstance(out var textDocumentEdits);

                foreach (var applyChangesOperation in applyChangesOperations)
                {
                    var solution       = document.Project.Solution;
                    var changes        = applyChangesOperation.ChangedSolution.GetChanges(solution);
                    var projectChanges = changes.GetProjectChanges();

                    // TO-DO: If the change involves adding or removing a document, execute via command instead of WorkspaceEdit
                    // until adding/removing documents is supported in LSP: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1147293/
                    // After support is added, remove the below if-statement and add code to support adding/removing documents.
                    var addedDocuments = projectChanges.SelectMany(
                        pc => pc.GetAddedDocuments().Concat(pc.GetAddedAdditionalDocuments().Concat(pc.GetAddedAnalyzerConfigDocuments())));
                    var removedDocuments = projectChanges.SelectMany(
                        pc => pc.GetRemovedDocuments().Concat(pc.GetRemovedAdditionalDocuments().Concat(pc.GetRemovedAnalyzerConfigDocuments())));
                    if (addedDocuments.Any() || removedDocuments.Any())
                    {
                        codeAction.Command = SetCommand(codeAction.Title, data);
                        return(codeAction);
                    }

                    // TO-DO: If the change involves adding or removing a project reference, execute via command instead of
                    // WorkspaceEdit until adding/removing project references is supported in LSP:
                    // https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1166040
                    var projectReferences = projectChanges.SelectMany(
                        pc => pc.GetAddedProjectReferences().Concat(pc.GetRemovedProjectReferences()));
                    if (projectReferences.Any())
                    {
                        codeAction.Command = SetCommand(codeAction.Title, data);
                        return(codeAction);
                    }

                    var changedDocuments = projectChanges.SelectMany(pc => pc.GetChangedDocuments());
                    var changedAnalyzerConfigDocuments = projectChanges.SelectMany(pc => pc.GetChangedAnalyzerConfigDocuments());
                    var changedAdditionalDocuments     = projectChanges.SelectMany(pc => pc.GetChangedAdditionalDocuments());

                    // Changed documents
                    await AddTextDocumentEdits(
                        textDocumentEdits, applyChangesOperation, solution, changedDocuments,
                        applyChangesOperation.ChangedSolution.GetDocument, solution.GetDocument,
                        cancellationToken).ConfigureAwait(false);

                    // Changed analyzer config documents
                    await AddTextDocumentEdits(
                        textDocumentEdits, applyChangesOperation, solution, changedAnalyzerConfigDocuments,
                        applyChangesOperation.ChangedSolution.GetAnalyzerConfigDocument, solution.GetAnalyzerConfigDocument,
                        cancellationToken).ConfigureAwait(false);

                    // Changed additional documents
                    await AddTextDocumentEdits(
                        textDocumentEdits, applyChangesOperation, solution, changedAdditionalDocuments,
                        applyChangesOperation.ChangedSolution.GetAdditionalDocument, solution.GetAdditionalDocument,
                        cancellationToken).ConfigureAwait(false);
                }

                codeAction.Edit = new LSP.WorkspaceEdit {
                    DocumentChanges = textDocumentEdits.ToArray()
                };
            }

            return(codeAction);