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 fixesTask = GetCodeFixesAsync( state, supportsFeatureService, requestedActionCategories, workspace, document, range, addOperationScope, priority, isBlocking: false, cancellationToken); var refactoringsTask = GetRefactoringsAsync( state, supportsFeatureService, requestedActionCategories, GlobalOptions, workspace, document, selection, addOperationScope, priority, isBlocking: false, 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); } }
public static async Task <LatestDiagnosticsForSpanGetter> CreateAsync( DiagnosticIncrementalAnalyzer owner, Document document, TextSpan?range, bool blockForData, Func <string, IDisposable?>?addOperationScope, bool includeSuppressedDiagnostics, CodeActionRequestPriority priority, string?diagnosticId, CancellationToken cancellationToken) { var stateSets = owner._stateManager .GetOrCreateStateSets(document.Project).Where(s => !owner.DiagnosticAnalyzerInfoCache.IsAnalyzerSuppressed(s.Analyzer, document.Project)); // filter to specific diagnostic it is looking for if (diagnosticId != null) { stateSets = stateSets.Where(s => owner.DiagnosticAnalyzerInfoCache.GetDiagnosticDescriptors(s.Analyzer).Any(d => d.Id == diagnosticId)).ToList(); } var compilationWithAnalyzers = await CreateCompilationWithAnalyzersAsync(document.Project, stateSets, includeSuppressedDiagnostics, cancellationToken).ConfigureAwait(false); return(new LatestDiagnosticsForSpanGetter( owner, compilationWithAnalyzers, document, stateSets, diagnosticId, range, blockForData, addOperationScope, includeSuppressedDiagnostics, priority)); }
/// <summary> /// Gets, filters, and orders code fixes. /// </summary> public static async ValueTask <ImmutableArray <UnifiedSuggestedActionSet> > GetFilterAndOrderCodeFixesAsync( Workspace workspace, ICodeFixService codeFixService, Document document, TextSpan selection, CodeActionRequestPriority priority, CodeActionOptionsProvider options, bool isBlocking, Func <string, IDisposable?> addOperationScope, CancellationToken cancellationToken) { // Intentionally switch to a threadpool thread to compute fixes. We do not want to accidentally // run any of this on the UI thread and potentially allow any code to take a dependency on that. var fixes = await Task.Run(() => codeFixService.GetFixesAsync( document, selection, priority, options, isBlocking, addOperationScope, cancellationToken), cancellationToken).ConfigureAwait(false); var filteredFixes = fixes.WhereAsArray(c => c.Fixes.Length > 0); var organizedFixes = await OrganizeFixesAsync(workspace, filteredFixes, cancellationToken).ConfigureAwait(false); return(organizedFixes); }
private LatestDiagnosticsForSpanGetter( DiagnosticIncrementalAnalyzer owner, CompilationWithAnalyzers?compilationWithAnalyzers, Document document, IEnumerable <StateSet> stateSets, Func <string, bool>?shouldIncludeDiagnostic, bool includeCompilerDiagnostics, TextSpan?range, bool blockForData, Func <string, IDisposable?>?addOperationScope, bool includeSuppressedDiagnostics, CodeActionRequestPriority priority) { _owner = owner; _compilationWithAnalyzers = compilationWithAnalyzers; _document = document; _stateSets = stateSets; _shouldIncludeDiagnostic = shouldIncludeDiagnostic; _includeCompilerDiagnostics = includeCompilerDiagnostics; _range = range; _blockForData = blockForData; _addOperationScope = addOperationScope; _includeSuppressedDiagnostics = includeSuppressedDiagnostics; _priority = priority; }
public async Task <bool> TryAppendDiagnosticsForSpanAsync( Document document, TextSpan?range, ArrayBuilder <DiagnosticData> result, Func <string, bool>?shouldIncludeDiagnostic, bool includeSuppressedDiagnostics, CodeActionRequestPriority priority, bool blockForData, Func <string, IDisposable?>?addOperationScope, CancellationToken cancellationToken) { var getter = await LatestDiagnosticsForSpanGetter.CreateAsync( this, document, range, blockForData, addOperationScope, includeSuppressedDiagnostics, priority, shouldIncludeDiagnostic, cancellationToken).ConfigureAwait(false); return(await getter.TryGetAsync(result, cancellationToken).ConfigureAwait(false)); }
public async Task <ImmutableArray <DiagnosticData> > GetDiagnosticsForSpanAsync( Document document, TextSpan?range, Func <string, bool>?shouldIncludeDiagnostic, bool includeSuppressedDiagnostics, CodeActionRequestPriority priority, bool blockForData, Func <string, IDisposable?>?addOperationScope, CancellationToken cancellationToken) { using var _ = ArrayBuilder <DiagnosticData> .GetInstance(out var list); var result = await TryAppendDiagnosticsForSpanAsync( document, range, list, shouldIncludeDiagnostic, includeSuppressedDiagnostics, priority, blockForData, addOperationScope, cancellationToken).ConfigureAwait(false); Debug.Assert(result); return(list.ToImmutable()); }
public Task <ImmutableArray <DiagnosticData> > GetDiagnosticsForSpanAsync( Document document, TextSpan?range, Func <string, bool>?shouldIncludeDiagnostic, bool includeSuppressedDiagnostics, CodeActionRequestPriority priority, Func <string, IDisposable?>?addOperationScope, CancellationToken cancellationToken) { if (_map.TryGetValue(document.Project.Solution.Workspace, out var analyzer)) { // always make sure that analyzer is called on background thread. return(Task.Run(() => analyzer.GetDiagnosticsForSpanAsync( document, range, shouldIncludeDiagnostic, includeSuppressedDiagnostics, priority, blockForData: true, addOperationScope, cancellationToken), cancellationToken)); } return(SpecializedTasks.EmptyImmutableArray <DiagnosticData>()); }
public static async Task <LatestDiagnosticsForSpanGetter> CreateAsync( DiagnosticIncrementalAnalyzer owner, Document document, TextSpan?range, bool blockForData, Func <string, IDisposable?>?addOperationScope, bool includeSuppressedDiagnostics, CodeActionRequestPriority priority, Func <string, bool>?shouldIncludeDiagnostic, CancellationToken cancellationToken) { var stateSets = owner._stateManager .GetOrCreateStateSets(document.Project).Where(s => !owner.DiagnosticAnalyzerInfoCache.IsAnalyzerSuppressed(s.Analyzer, document.Project)); var compilationWithAnalyzers = await GetOrCreateCompilationWithAnalyzersAsync(document.Project, stateSets, includeSuppressedDiagnostics, cancellationToken).ConfigureAwait(false); return(new LatestDiagnosticsForSpanGetter( owner, compilationWithAnalyzers, document, stateSets, shouldIncludeDiagnostic, range, blockForData, addOperationScope, includeSuppressedDiagnostics, priority)); }
public async Task <ImmutableArray <CodeRefactoring> > GetRefactoringsAsync( Document document, TextSpan state, CodeActionRequestPriority priority, CodeActionOptionsProvider options, bool isBlocking, Func <string, IDisposable?> addOperationScope, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.Refactoring_CodeRefactoringService_GetRefactoringsAsync, cancellationToken)) { var extensionManager = document.Project.Solution.Workspace.Services.GetRequiredService <IExtensionManager>(); using var _ = ArrayBuilder <Task <CodeRefactoring?> > .GetInstance(out var tasks); foreach (var provider in GetProviders(document)) { if (priority != CodeActionRequestPriority.None && priority != provider.RequestPriority) { continue; } tasks.Add(Task.Run(() => { var providerName = provider.GetType().Name; RefactoringToMetadataMap.TryGetValue(provider, out var providerMetadata); using (addOperationScope(providerName)) using (RoslynEventSource.LogInformationalBlock(FunctionId.Refactoring_CodeRefactoringService_GetRefactoringsAsync, providerName, cancellationToken)) { return(GetRefactoringFromProviderAsync(document, state, provider, providerMetadata, extensionManager, options, isBlocking, cancellationToken)); } }, cancellationToken)); } var results = await Task.WhenAll(tasks).ConfigureAwait(false); return(results.WhereNotNull().ToImmutableArray()); } }
public static async Task <LatestDiagnosticsForSpanGetter> CreateAsync( DiagnosticIncrementalAnalyzer owner, Document document, TextSpan?range, bool blockForData, Func <string, IDisposable?>?addOperationScope, bool includeSuppressedDiagnostics, CodeActionRequestPriority priority, Func <string, bool>?shouldIncludeDiagnostic, CancellationToken cancellationToken) { var stateSets = owner._stateManager .GetOrCreateStateSets(document.Project).Where(s => DocumentAnalysisExecutor.IsAnalyzerEnabledForProject(s.Analyzer, document.Project, owner.GlobalOptions)); var crashOnAnalyzerException = owner.GlobalOptions.GetOption(InternalDiagnosticsOptions.CrashOnAnalyzerException); var compilationWithAnalyzers = await GetOrCreateCompilationWithAnalyzersAsync(document.Project, stateSets, includeSuppressedDiagnostics, crashOnAnalyzerException, cancellationToken).ConfigureAwait(false); return(new LatestDiagnosticsForSpanGetter( owner, compilationWithAnalyzers, document, stateSets, shouldIncludeDiagnostic, range, blockForData, addOperationScope, includeSuppressedDiagnostics, priority)); }
public Task <(ImmutableArray <DiagnosticData> diagnostics, bool upToDate)> TryGetDiagnosticsForSpanAsync( Document document, TextSpan range, Func <string, bool>?shouldIncludeDiagnostic, bool includeSuppressedDiagnostics = false, CodeActionRequestPriority priority = CodeActionRequestPriority.None, CancellationToken cancellationToken = default) { if (_map.TryGetValue(document.Project.Solution.Workspace, out var analyzer)) { // always make sure that analyzer is called on background thread. return(Task.Run(async() => { using var _ = ArrayBuilder <DiagnosticData> .GetInstance(out var diagnostics); var upToDate = await analyzer.TryAppendDiagnosticsForSpanAsync( document, range, diagnostics, shouldIncludeDiagnostic, includeSuppressedDiagnostics, priority, blockForData: false, addOperationScope: null, cancellationToken).ConfigureAwait(false); return (diagnostics.ToImmutable(), upToDate); }, cancellationToken)); } return(Task.FromResult((ImmutableArray <DiagnosticData> .Empty, upToDate: false))); }
public static Task <ImmutableArray <CodeFixCollection> > GetFixesAsync(this ICodeFixService service, Document document, TextSpan textSpan, CodeActionRequestPriority priority, CodeActionOptionsProvider options, bool isBlocking, Func <string, IDisposable?> addOperationScope, CancellationToken cancellationToken) => service.StreamFixesAsync(document, textSpan, priority, options, isBlocking, addOperationScope, cancellationToken).ToImmutableArrayAsync(cancellationToken);
private async IAsyncEnumerable <SuggestedActionSet> GetCodeFixesAndRefactoringsAsync( ReferenceCountedDisposable <State> state, ISuggestedActionCategorySet requestedActionCategories, Document document, SnapshotSpan range, TextSpan?selection, Func <string, IDisposable?> addOperationScope, CodeActionRequestPriority priority, [EnumeratorCancellation] CancellationToken cancellationToken) { var workspace = document.Project.Solution.Workspace; var supportsFeatureService = workspace.Services.GetRequiredService <ITextBufferSupportsFeatureService>(); var fixesTask = GetCodeFixesAsync( state, supportsFeatureService, requestedActionCategories, workspace, document, range, addOperationScope, priority, isBlocking: false, cancellationToken); var refactoringsTask = GetRefactoringsAsync( state, supportsFeatureService, requestedActionCategories, workspace, document, selection, addOperationScope, priority, isBlocking: false, cancellationToken); if (priority == CodeActionRequestPriority.High) { // in a high pri scenario, return data as soon as possible so that the user can interact with them. // this is especially important for state-machine oriented refactorings (like rename) where the user // should always have access to them effectively synchronously. var firstTask = await Task.WhenAny(fixesTask, refactoringsTask).ConfigureAwait(false); var secondTask = firstTask == fixesTask ? refactoringsTask : fixesTask; var orderedTasks = new[] { firstTask, secondTask }; foreach (var task in orderedTasks) { if (task == fixesTask) { var fixes = await fixesTask.ConfigureAwait(false); foreach (var set in ConvertToSuggestedActionSets(state, selection, fixes, ImmutableArray <UnifiedSuggestedActionSet> .Empty)) { yield return(set); } } else { Contract.ThrowIfFalse(task == refactoringsTask); var refactorings = await refactoringsTask.ConfigureAwait(false); foreach (var set in ConvertToSuggestedActionSets(state, selection, ImmutableArray <UnifiedSuggestedActionSet> .Empty, refactorings)) { yield return(set); } } } } else { var actionsArray = await Task.WhenAll(fixesTask, refactoringsTask).ConfigureAwait(false); foreach (var set in ConvertToSuggestedActionSets(state, selection, fixes: actionsArray[0], refactorings: actionsArray[1])) { yield return(set); } } }
/// <summary> /// Return up to date diagnostics for the given span for the document /// <para> /// This can be expensive since it is force analyzing diagnostics if it doesn't have up-to-date one yet. If /// <paramref name="diagnosticId"/> is not null, it gets diagnostics only for this given <paramref /// name="diagnosticId"/> value. /// </para> /// </summary> public static Task <ImmutableArray <DiagnosticData> > GetDiagnosticsForSpanAsync(this IDiagnosticAnalyzerService service, Document document, TextSpan?range, string?diagnosticId = null, bool includeSuppressedDiagnostics = false, CodeActionRequestPriority priority = CodeActionRequestPriority.None, Func <string, IDisposable?>?addOperationScope = null, CancellationToken cancellationToken = default) { Func <string, bool>?shouldIncludeDiagnostic = diagnosticId != null ? id => id == diagnosticId : null; return(service.GetDiagnosticsForSpanAsync(document, range, shouldIncludeDiagnostic, includeSuppressedDiagnostics, priority, addOperationScope, cancellationToken)); }