private async Task <ImmutableArray <CodeActionOperation> > GetCodeFixOperationsAsync( CodeFixProvider provider, Document document, TextSpan span, ImmutableArray <Diagnostic> diagnostics) { var codeFixes = new List <CodeAction>(); var context = OmniSharpCodeFixContextFactory.CreateCodeFixContext( document, span, diagnostics, registerCodeFix: (a, d) => codeFixes.Add(a), CodeActionOptionsFactory.Create(_options), cancellationToken: CancellationToken.None); // Note: We're intentionally not checking CodeFixProvider.FixableDiagnosticIds here. // The problem is that some providers (like Remove Unnecessary Usings) only listen // for custom IDs produced by their associated diagnostic analyzer. Once we have a // proper diagnostic engine in OmniSharp, we may be able remove this. await provider.RegisterCodeFixesAsync(context); var getOperationsTasks = codeFixes .Select(a => a.GetOperationsAsync(CancellationToken.None)); // Wait until all tasks to produce CodeActionOperations finish running in parallel. await Task.WhenAll(getOperationsTasks); return(getOperationsTasks .Select(t => t.Result) .SelectMany(ops => ops) .ToImmutableArray()); }
private async IAsyncEnumerable <SuggestedActionSet> GetCodeFixesAndRefactoringsAsync( ReferenceCountedDisposable <State> state, ISuggestedActionCategorySet requestedActionCategories, Document document, SnapshotSpan range, TextSpan?selection, Func <string, IDisposable?> addOperationScope, CodeActionRequestPriority priority, int currentActionCount, [EnumeratorCancellation] CancellationToken cancellationToken) { var workspace = document.Project.Solution.Workspace; var supportsFeatureService = workspace.Services.GetRequiredService <ITextBufferSupportsFeatureService>(); var options = CodeActionOptionsFactory.GetCodeActionOptions(document.Project, isBlocking: false); var fixesTask = GetCodeFixesAsync( state, supportsFeatureService, requestedActionCategories, workspace, document, range, addOperationScope, priority, options, cancellationToken); var refactoringsTask = GetRefactoringsAsync( state, supportsFeatureService, requestedActionCategories, GlobalOptions, workspace, document, selection, addOperationScope, priority, options, cancellationToken); await Task.WhenAll(fixesTask, refactoringsTask).ConfigureAwait(false); var fixes = await fixesTask.ConfigureAwait(false); var refactorings = await refactoringsTask.ConfigureAwait(false); foreach (var set in ConvertToSuggestedActionSets(state, selection, fixes, refactorings, currentActionCount)) { yield return(set); } }
private async Task AppendFixesAsync(Document document, TextSpan span, IEnumerable <Diagnostic> diagnostics, List <CodeAction> codeActions) { var codeActionOptions = CodeActionOptionsFactory.Create(Options); foreach (var codeFixProvider in GetSortedCodeFixProviders(document)) { var fixableDiagnostics = diagnostics.Where(d => HasFix(codeFixProvider, d.Id)).ToImmutableArray(); if (fixableDiagnostics.Length > 0) { var context = OmniSharpCodeFixContextFactory.CreateCodeFixContext( document, span, fixableDiagnostics, (a, _) => codeActions.Add(a), codeActionOptions, CancellationToken.None); try { await codeFixProvider.RegisterCodeFixesAsync(context); } catch (Exception ex) { this.Logger.LogError(ex, $"Error registering code fixes for {codeFixProvider.GetType().FullName}"); } } } }
private static async Task <CodeRefactoring> GetCodeRefactoringAsync( CodeRefactoringProvider provider, TestWorkspace workspace) { var documentsWithSelections = workspace.Documents.Where(d => !d.IsLinkFile && d.SelectedSpans.Count == 1); Debug.Assert(documentsWithSelections.Count() == 1, "One document must have a single span annotation"); var span = documentsWithSelections.Single().SelectedSpans.Single(); var actions = ArrayBuilder <(CodeAction, TextSpan?)> .GetInstance(); var document = workspace.CurrentSolution.GetDocument(documentsWithSelections.Single().Id); var options = CodeActionOptionsFactory.GetCodeActionOptions(document.Project, isBlocking: false); var context = new CodeRefactoringContext(document, span, (a, t) => actions.Add((a, t)), options, CancellationToken.None); await provider.ComputeRefactoringsAsync(context); var result = actions.Count > 0 ? new CodeRefactoring(provider, actions.ToImmutable()) : null; actions.Free(); return(result); }
private ImmutableArray <SuggestedActionSet>?GetSuggestedActions( ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, IUIThreadOperationContext?operationContext, CancellationToken cancellationToken) { AssertIsForeground(); using var state = _state.TryAddReference(); if (state is null) { return(null); } if (state.Target.Workspace == null) { return(null); } using (operationContext?.AddScope(allowCancellation: true, description: EditorFeaturesResources.Gathering_Suggestions_Waiting_for_the_solution_to_fully_load)) { // This needs to run under threading context otherwise, we can deadlock on VS var statusService = state.Target.Workspace.Services.GetRequiredService <IWorkspaceStatusService>(); ThreadingContext.JoinableTaskFactory.Run(() => statusService.WaitUntilFullyLoadedAsync(cancellationToken)); } using (Logger.LogBlock(FunctionId.SuggestedActions_GetSuggestedActions, cancellationToken)) { var document = range.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { // this is here to fail test and see why it is failed. Trace.WriteLine("given range is not current"); return(null); } var workspace = document.Project.Solution.Workspace; var supportsFeatureService = workspace.Services.GetRequiredService <ITextBufferSupportsFeatureService>(); var selection = TryGetCodeRefactoringSelection(state, range); Func <string, IDisposable?> addOperationScope = description => operationContext?.AddScope(allowCancellation: true, string.Format(EditorFeaturesResources.Gathering_Suggestions_0, description)); var options = CodeActionOptionsFactory.GetCodeActionOptions(document.Project, isBlocking: true); // We convert the code fixes and refactorings to UnifiedSuggestedActionSets instead of // SuggestedActionSets so that we can share logic between local Roslyn and LSP. var fixesTask = GetCodeFixesAsync( state, supportsFeatureService, requestedActionCategories, workspace, document, range, addOperationScope, CodeActionRequestPriority.None, options, cancellationToken); var refactoringsTask = GetRefactoringsAsync( state, supportsFeatureService, requestedActionCategories, GlobalOptions, workspace, document, selection, addOperationScope, CodeActionRequestPriority.None, options, cancellationToken); Task.WhenAll(fixesTask, refactoringsTask).WaitAndGetResult(cancellationToken); return(ConvertToSuggestedActionSets( state, selection, fixesTask.WaitAndGetResult(cancellationToken), refactoringsTask.WaitAndGetResult(cancellationToken), currentActionCount: 0)); } }