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); }
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); }
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); }
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); }
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());
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);