示例#1
0
            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);
                }
            }
示例#2
0
            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));
            }
示例#3
0
        /// <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);
        }
示例#4
0
 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)));
        }
示例#12
0
 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);
                    }
                }
            }
示例#14
0
        /// <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));
        }