コード例 #1
0
ファイル: CodeFixService.cs プロジェクト: singhsarab/roslyn
        private async Task AppendFixesOrSuppressionsAsync(
            Document document,
            TextSpan span,
            IEnumerable <DiagnosticData> diagnosticsWithSameSpan,
            ArrayBuilder <CodeFixCollection> result,
            object fixer,
            Func <Diagnostic, bool> hasFix,
            Func <ImmutableArray <Diagnostic>, Task <ImmutableArray <CodeFix> > > getFixes,
            CancellationToken cancellationToken)
        {
            var allDiagnostics =
                await diagnosticsWithSameSpan.OrderByDescending(d => d.Severity)
                .ToDiagnosticsAsync(document.Project, cancellationToken).ConfigureAwait(false);

            var diagnostics = allDiagnostics.WhereAsArray(hasFix);

            if (diagnostics.Length <= 0)
            {
                // this can happen for suppression case where all diagnostics can't be suppressed
                return;
            }

            var extensionManager = document.Project.Solution.Workspace.Services.GetService <IExtensionManager>();
            var fixes            = await extensionManager.PerformFunctionAsync(fixer,
                                                                               () => getFixes(diagnostics),
                                                                               defaultValue : ImmutableArray <CodeFix> .Empty).ConfigureAwait(false);

            if (fixes.IsDefaultOrEmpty)
            {
                return;
            }

            // If the fix provider supports fix all occurrences, then get the corresponding FixAllProviderInfo and fix all context.
            var fixAllProviderInfo = extensionManager.PerformFunction(fixer, () => ImmutableInterlocked.GetOrAdd(ref _fixAllProviderMap, fixer, FixAllProviderInfo.Create), defaultValue: null);

            FixAllState fixAllState     = null;
            var         supportedScopes = ImmutableArray <FixAllScope> .Empty;

            if (fixAllProviderInfo != null)
            {
                var codeFixProvider = (fixer as CodeFixProvider) ?? new WrapperCodeFixProvider((ISuppressionFixProvider)fixer, diagnostics.Select(d => d.Id));
                fixAllState = CreateFixAllState(
                    fixAllProviderInfo.FixAllProvider,
                    document, fixAllProviderInfo, codeFixProvider, diagnostics,
                    this.GetDocumentDiagnosticsAsync, this.GetProjectDiagnosticsAsync);
                supportedScopes = fixAllProviderInfo.SupportedScopes;
            }

            var codeFix = new CodeFixCollection(
                fixer, span, fixes, fixAllState,
                supportedScopes, diagnostics.First());

            result.Add(codeFix);
        }
コード例 #2
0
ファイル: CodeFixService.cs プロジェクト: tsasioglu/roslyn
        private async Task <List <CodeFixCollection> > AppendFixesOrSuppressionsAsync(
            Document document,
            TextSpan span,
            IEnumerable <Diagnostic> diagnosticsWithSameSpan,
            List <CodeFixCollection> result,
            object fixer,
            Func <Diagnostic, bool> hasFix,
            Func <ImmutableArray <Diagnostic>, Task <IEnumerable <CodeFix> > > getFixes,
            CancellationToken cancellationToken)
        {
            var diagnostics = diagnosticsWithSameSpan.Where(d => hasFix(d)).OrderByDescending(d => d.Severity).ToImmutableArray();

            if (diagnostics.Length <= 0)
            {
                // this can happen for suppression case where all diagnostics can't be suppressed
                return(result);
            }

            var extensionManager = document.Project.Solution.Workspace.Services.GetService <IExtensionManager>();
            var fixes            = await extensionManager.PerformFunctionAsync(fixer, () => getFixes(diagnostics), defaultValue : SpecializedCollections.EmptyEnumerable <CodeFix>()).ConfigureAwait(false);

            if (fixes != null && fixes.Any())
            {
                FixAllCodeActionContext fixAllContext = null;
                var codeFixProvider = fixer as CodeFixProvider;
                if (codeFixProvider != null)
                {
                    // If the codeFixProvider supports fix all occurrences, then get the corresponding FixAllProviderInfo and fix all context.
                    var fixAllProviderInfo = extensionManager.PerformFunction(codeFixProvider, () => ImmutableInterlocked.GetOrAdd(ref _fixAllProviderMap, codeFixProvider, FixAllProviderInfo.Create), defaultValue: null);

                    if (fixAllProviderInfo != null)
                    {
                        fixAllContext = FixAllCodeActionContext.Create(document, fixAllProviderInfo, codeFixProvider, diagnostics, this.GetDocumentDiagnosticsAsync, this.GetProjectDiagnosticsAsync, cancellationToken);
                    }
                }

                result = result ?? new List <CodeFixCollection>();
                var codeFix = new CodeFixCollection(fixer, span, fixes, fixAllContext);
                result.Add(codeFix);
            }

            return(result);
        }
コード例 #3
0
            private void AddCodeActions(
                Workspace workspace, IDictionary<CodeFixGroupKey, IList<SuggestedAction>> map, 
                ArrayBuilder<CodeFixGroupKey> order, CodeFixCollection fixCollection, 
                Func<CodeAction, SuggestedActionSet> getFixAllSuggestedActionSet,
                ImmutableArray<CodeFix> codeFixes)
            {
                foreach (var fix in codeFixes)
                {
                    SuggestedAction suggestedAction;
                    if (fix.Action.NestedCodeActions.Length > 0)
                    {
                        var nestedActions = fix.Action.NestedCodeActions.SelectAsArray(
                            nestedAction => new CodeFixSuggestedAction(
                                _owner, workspace, _subjectBuffer, fix, fixCollection.Provider,
                                nestedAction, getFixAllSuggestedActionSet(nestedAction)));

                        var set = new SuggestedActionSet(
                            nestedActions, SuggestedActionSetPriority.Medium,
                            fix.PrimaryDiagnostic.Location.SourceSpan.ToSpan());

                        suggestedAction = new SuggestedActionWithNestedActions(
                            _owner, workspace, _subjectBuffer, 
                            fixCollection.Provider, fix.Action, set);
                    }
                    else
                    {
                        suggestedAction = new CodeFixSuggestedAction(
                            _owner, workspace, _subjectBuffer, fix, fixCollection.Provider,
                            fix.Action, getFixAllSuggestedActionSet(fix.Action));
                    }

                    AddFix(fix, suggestedAction, map, order);
                }
            }
コード例 #4
0
            private CodeFixCollection FilterOnUIThread(
                CodeFixCollection collection,
                Workspace workspace)
            {
                this.AssertIsForeground();

                var applicableFixes = collection.Fixes.WhereAsArray(f => IsApplicable(f.Action, workspace));
                return applicableFixes.Length == 0
                    ? null
                    : applicableFixes.Length == collection.Fixes.Length
                        ? collection
                        : new CodeFixCollection(collection.Provider, collection.TextSpan, applicableFixes, 
                            collection.FixAllState, 
                            collection.SupportedScopes, collection.FirstDiagnostic);
            }
コード例 #5
0
            private void ProcessFixCollection(
                Workspace workspace, 
                IDictionary<CodeFixGroupKey, IList<SuggestedAction>> map, 
                ArrayBuilder<CodeFixGroupKey> order, 
                bool includeSuppressionFixes, 
                CodeFixCollection fixCollection)
            {
                var fixes = fixCollection.Fixes;
                var fixCount = fixes.Length;

                Func<CodeAction, SuggestedActionSet> getFixAllSuggestedActionSet =
                    codeAction => GetFixAllSuggestedActionSet(
                        codeAction, fixCount, fixCollection.FixAllState,
                        fixCollection.SupportedScopes, fixCollection.FirstDiagnostic,
                        workspace);

                var nonSupressionCodeFixes = fixes.WhereAsArray(f => !(f.Action is TopLevelSuppressionCodeAction));
                var supressionCodeFixes = fixes.WhereAsArray(f => f.Action is TopLevelSuppressionCodeAction);

                AddCodeActions(workspace, map, order, fixCollection, 
                    getFixAllSuggestedActionSet, nonSupressionCodeFixes);

                // Add suppression fixes to the end of a given SuggestedActionSet so that they
                // always show up last in a group.
                if (includeSuppressionFixes)
                {
                    AddCodeActions(workspace, map, order, fixCollection,
                        getFixAllSuggestedActionSet, supressionCodeFixes);
                }
            }
コード例 #6
0
ファイル: CodeFixService.cs プロジェクト: XieShuquan/roslyn
        private async Task AppendFixesOrSuppressionsAsync(
            Document document,
            TextSpan span,
            IEnumerable<DiagnosticData> diagnosticsWithSameSpan,
            ArrayBuilder<CodeFixCollection> result,
            object fixer,
            Func<Diagnostic, bool> hasFix,
            Func<ImmutableArray<Diagnostic>, Task<ImmutableArray<CodeFix>>> getFixes,
            CancellationToken cancellationToken)
        {
            var allDiagnostics = 
                await diagnosticsWithSameSpan.OrderByDescending(d => d.Severity)
                                             .ToDiagnosticsAsync(document.Project, cancellationToken).ConfigureAwait(false);
            var diagnostics = allDiagnostics.WhereAsArray(hasFix);
            if (diagnostics.Length <= 0)
            {
                // this can happen for suppression case where all diagnostics can't be suppressed
                return;
            }

            var extensionManager = document.Project.Solution.Workspace.Services.GetService<IExtensionManager>();
            var fixes = await extensionManager.PerformFunctionAsync(fixer,
                () => getFixes(diagnostics),
                defaultValue: ImmutableArray<CodeFix>.Empty).ConfigureAwait(false);

            if (fixes.IsDefaultOrEmpty)
            {
                return;
            }

            // If the fix provider supports fix all occurrences, then get the corresponding FixAllProviderInfo and fix all context.
            var fixAllProviderInfo = extensionManager.PerformFunction(fixer, () => ImmutableInterlocked.GetOrAdd(ref _fixAllProviderMap, fixer, FixAllProviderInfo.Create), defaultValue: null);

            FixAllState fixAllState = null;
            var supportedScopes = ImmutableArray<FixAllScope>.Empty;
            if (fixAllProviderInfo != null)
            {
                var codeFixProvider = (fixer as CodeFixProvider) ?? new WrapperCodeFixProvider((ISuppressionFixProvider)fixer, diagnostics.Select(d => d.Id));
                fixAllState = FixAllState.Create(
                    fixAllProviderInfo.FixAllProvider,
                    document, fixAllProviderInfo, codeFixProvider, diagnostics,
                    this.GetDocumentDiagnosticsAsync, this.GetProjectDiagnosticsAsync);
                supportedScopes = fixAllProviderInfo.SupportedScopes;
            }

            var codeFix = new CodeFixCollection(
                fixer, span, fixes, fixAllState,
                supportedScopes, diagnostics.First());
            result.Add(codeFix);
        }
コード例 #7
0
ファイル: CodeFixService.cs プロジェクト: binsys/roslyn
        private async Task<List<CodeFixCollection>> AppendFixesOrSuppressionsAsync(
            Document document,
            TextSpan span,
            IEnumerable<DiagnosticData> diagnosticsWithSameSpan,
            List<CodeFixCollection> result,
            object fixer,
            Func<Diagnostic, bool> hasFix,
            Func<ImmutableArray<Diagnostic>, Task<IEnumerable<CodeFix>>> getFixes,
            CancellationToken cancellationToken)
        {
            var diagnostics = (await diagnosticsWithSameSpan.OrderByDescending(d => d.Severity).ToDiagnosticsAsync(document.Project, cancellationToken).ConfigureAwait(false)).Where(d => hasFix(d)).ToImmutableArray();
            if (diagnostics.Length <= 0)
            {
                // this can happen for suppression case where all diagnostics can't be suppressed
                return result;
            }

            var extensionManager = document.Project.Solution.Workspace.Services.GetService<IExtensionManager>();
            var fixes = await extensionManager.PerformFunctionAsync(fixer, () => getFixes(diagnostics), defaultValue: SpecializedCollections.EmptyEnumerable<CodeFix>()).ConfigureAwait(false);

            if (fixes != null && fixes.Any())
            {
                // If the fix provider supports fix all occurrences, then get the corresponding FixAllProviderInfo and fix all context.
                var fixAllProviderInfo = extensionManager.PerformFunction(fixer, () => ImmutableInterlocked.GetOrAdd(ref _fixAllProviderMap, fixer, FixAllProviderInfo.Create), defaultValue: null);

                FixAllCodeActionContext fixAllContext = null;
                if (fixAllProviderInfo != null)
                {
                    var codeFixProvider = (fixer as CodeFixProvider) ?? new WrapperCodeFixProvider((ISuppressionFixProvider)fixer, diagnostics.Select(d => d.Id));
                    fixAllContext = FixAllCodeActionContext.Create(
                        document, fixAllProviderInfo, codeFixProvider, diagnostics,
                        this.GetDocumentDiagnosticsAsync, this.GetProjectDiagnosticsAsync, cancellationToken);
                }

                result = result ?? new List<CodeFixCollection>();
                var codeFix = new CodeFixCollection(fixer, span, fixes, fixAllContext);
                result.Add(codeFix);
            }

            return result;
        }
コード例 #8
0
ファイル: CodeFixService.cs プロジェクト: JinGuoGe/roslyn
        private async Task<List<CodeFixCollection>> AppendFixesOrSuppressionsAsync(
            Document document,
            TextSpan span,
            IEnumerable<Diagnostic> diagnosticsWithSameSpan,
            List<CodeFixCollection> result,
            object fixer,
            IExtensionManager extensionManager,
            Func<Diagnostic, bool> hasFix,
            Func<ImmutableArray<Diagnostic>, Task<IEnumerable<CodeFix>>> getFixes,
            CancellationToken cancellationToken)
        {
            var diagnostics = diagnosticsWithSameSpan.Where(d => hasFix(d)).OrderByDescending(d => d.Severity).ToImmutableArray();
            if (diagnostics.Length <= 0)
            {
                // this can happen for suppression case where all diagnostics can't be suppressed
                return result;
            }

            var fixes = await extensionManager.PerformFunctionAsync(fixer, () => getFixes(diagnostics)).ConfigureAwait(false);
            if (fixes != null && fixes.Any())
            {
                FixAllCodeActionContext fixAllContext = null;
                var codeFixProvider = fixer as CodeFixProvider;
                if (codeFixProvider != null)
                {
                    // If the codeFixProvider supports fix all occurrences, then get the corresponding FixAllProviderInfo and fix all context.
                    var fixAllProviderInfo = ImmutableInterlocked.GetOrAdd(ref _fixAllProviderMap, codeFixProvider, FixAllProviderInfo.Create);
                    if (fixAllProviderInfo != null)
                    {
                        fixAllContext = new FixAllCodeActionContext(document, fixAllProviderInfo, codeFixProvider, diagnostics, this.GetDocumentDiagnosticsAsync, this.GetProjectDiagnosticsAsync, cancellationToken);
                    }
                }

                result = result ?? new List<CodeFixCollection>();
                var codeFix = new CodeFixCollection(fixer, span, fixes, fixAllContext);
                result.Add(codeFix);
            }

            return result;
        }
コード例 #9
0
        private async Task<IEnumerable<Tuple<Diagnostic, CodeFixCollection>>> GetDiagnosticAndFixesAsync(
            IEnumerable<Diagnostic> diagnostics,
            DiagnosticAnalyzer provider,
            CodeFixProvider fixer,
            TestDiagnosticAnalyzerDriver testDriver,
            Document document,
            TextSpan span,
            FixAllScope? scope,
            string fixAllActionId)
        {
            Assert.NotEmpty(diagnostics);
            var result = new List<Tuple<Diagnostic, CodeFixCollection>>();
            if (scope == null)
            {
                // Simple code fix.
                foreach (var diagnostic in diagnostics)
                {
                    var fixes = new List<CodeFix>();
                    var context = new CodeFixContext(document, diagnostic, (a, d) => fixes.Add(new CodeFix(document.Project, a, d)), CancellationToken.None);

                    await fixer.RegisterCodeFixesAsync(context);
                    if (fixes.Any())
                    {
                        var codeFix = new CodeFixCollection(
                            fixer, diagnostic.Location.SourceSpan, fixes,
                            fixAllState: null, supportedScopes: null, firstDiagnostic: null);
                        result.Add(Tuple.Create(diagnostic, codeFix));
                    }
                }
            }
            else
            {
                // Fix all fix.
                var fixAllProvider = fixer.GetFixAllProvider();
                Assert.NotNull(fixAllProvider);

                var fixAllState = GetFixAllState(fixAllProvider, diagnostics, provider, fixer, testDriver, document, scope.Value, fixAllActionId);
                var fixAllContext = fixAllState.CreateFixAllContext(new ProgressTracker(), CancellationToken.None);
                var fixAllFix = await fixAllProvider.GetFixAsync(fixAllContext);
                if (fixAllFix != null)
                {
                    // Same fix applies to each diagnostic in scope.
                    foreach (var diagnostic in diagnostics)
                    {
                        var diagnosticSpan = diagnostic.Location.IsInSource ? diagnostic.Location.SourceSpan : default(TextSpan);
                        var codeFix = new CodeFixCollection(
                            fixAllProvider, diagnosticSpan, ImmutableArray.Create(new CodeFix(document.Project, fixAllFix, diagnostic)),
                            fixAllState: null, supportedScopes: null, firstDiagnostic: null);
                        result.Add(Tuple.Create(diagnostic, codeFix));
                    }
                }
            }

            return result;
        }
コード例 #10
0
 internal CodeFixCollection(Microsoft.CodeAnalysis.CodeFixes.CodeFixCollection inner)
 {
     _inner = inner;
     Fixes  = inner.Fixes.Select(x => x).ToImmutableArray();
 }
        internal override IEnumerable<Tuple<Diagnostic, CodeFixCollection>> GetDiagnosticAndFixes(TestWorkspace workspace, string fixAllActionId)
        {
            var providerAndFixer = CreateDiagnosticProviderAndFixer(workspace);

            var provider = providerAndFixer.Item1;
            Document document;
            TextSpan span;
            string annotation = null;
            if (!TryGetDocumentAndSelectSpan(workspace, out document, out span))
            {
                document = GetDocumentAndAnnotatedSpan(workspace, out annotation, out span);
            }

            var diagnostics = DiagnosticProviderTestUtilities.GetAllDiagnostics(provider, document, span);

            var fixer = providerAndFixer.Item2;
            var ids = new HashSet<string>(fixer.FixableDiagnosticIds);
            var dxs = diagnostics.Where(d => ids.Contains(d.Id)).ToList();

            foreach (var diagnostic in dxs)
            {
                if (annotation == null)
                {
                    var fixes = new List<CodeFix>();
                    var context = new CodeFixContext(document, diagnostic, (a, d) => fixes.Add(new CodeFix(a, d)), CancellationToken.None);
                    fixer.RegisterCodeFixesAsync(context).Wait();
                    if (fixes.Any())
                    {
                        var codeFix = new CodeFixCollection(fixer, diagnostic.Location.SourceSpan, fixes);
                        yield return Tuple.Create(diagnostic, codeFix);
                    }
                }
                else
                {
                    var fixAllProvider = fixer.GetFixAllProvider();
                    Assert.NotNull(fixAllProvider);
                    FixAllScope scope = GetFixAllScope(annotation);

                    Func<Document, ImmutableHashSet<string>, CancellationToken, Task<IEnumerable<Diagnostic>>> getDocumentDiagnosticsAsync =
                        (d, diagIds, c) =>
                        {
                            var root = d.GetSyntaxRootAsync().Result;
                            var diags = DiagnosticProviderTestUtilities.GetDocumentDiagnostics(provider, d, root.FullSpan);
                            diags = diags.Where(diag => diagIds.Contains(diag.Id));
                            return Task.FromResult(diags);
                        };

                    Func<Project, bool, ImmutableHashSet<string>, CancellationToken, Task<IEnumerable<Diagnostic>>> getProjectDiagnosticsAsync =
                        (p, includeAllDocumentDiagnostics, diagIds, c) =>
                        {
                            var diags = includeAllDocumentDiagnostics ?
                                DiagnosticProviderTestUtilities.GetAllDiagnostics(provider, p) :
                                DiagnosticProviderTestUtilities.GetProjectDiagnostics(provider, p);
                            diags = diags.Where(diag => diagIds.Contains(diag.Id));
                            return Task.FromResult(diags);
                        };

                    var fixAllContext = new FixAllContext(document, fixer, scope, fixAllActionId,
                        SpecializedCollections.SingletonEnumerable(diagnostic.Id), getDocumentDiagnosticsAsync, getProjectDiagnosticsAsync, CancellationToken.None);
                    var fixAllFix = fixAllProvider.GetFixAsync(fixAllContext).WaitAndGetResult(CancellationToken.None);
                    if (fixAllFix != null)
                    {
                        var codeFix = new CodeFixCollection(fixAllProvider, diagnostic.Location.SourceSpan, ImmutableArray.Create(new CodeFix(fixAllFix, diagnostic)));
                        yield return Tuple.Create(diagnostic, codeFix);
                    }
                }
            }
        }
コード例 #12
0
        internal IEnumerable<Tuple<Diagnostic, CodeFixCollection>> GetDiagnosticAndFixes(
            IEnumerable<Diagnostic> diagnostics,
            DiagnosticAnalyzer provider,
            CodeFixProvider fixer,
            TestDiagnosticAnalyzerDriver testDriver,
            Document document,
            TextSpan span,
            string annotation,
            string fixAllActionId)
        {
            foreach (var diagnostic in diagnostics)
            {
                if (annotation == null)
                {
                    var fixes = new List<CodeFix>();
                    var context = new CodeFixContext(document, diagnostic, (a, d) => fixes.Add(new CodeFix(document.Project, a, d)), CancellationToken.None);

                    fixer.RegisterCodeFixesAsync(context).Wait();
                    if (fixes.Any())
                    {
                        var codeFix = new CodeFixCollection(fixer, diagnostic.Location.SourceSpan, fixes);
                        yield return Tuple.Create(diagnostic, codeFix);
                    }
                }
                else
                {
                    var fixAllProvider = fixer.GetFixAllProvider();
                    Assert.NotNull(fixAllProvider);
                    FixAllScope scope = GetFixAllScope(annotation);

                    Func<Document, ImmutableHashSet<string>, CancellationToken, Task<IEnumerable<Diagnostic>>> getDocumentDiagnosticsAsync =
                        (d, diagIds, c) =>
                        {
                            var root = d.GetSyntaxRootAsync().Result;
                            var diags = testDriver.GetDocumentDiagnostics(provider, d, root.FullSpan);
                            diags = diags.Where(diag => diagIds.Contains(diag.Id));
                            return Task.FromResult(diags);
                        };

                    Func<Project, bool, ImmutableHashSet<string>, CancellationToken, Task<IEnumerable<Diagnostic>>> getProjectDiagnosticsAsync =
                        (p, includeAllDocumentDiagnostics, diagIds, c) =>
                        {
                            var diags = includeAllDocumentDiagnostics ?
                                testDriver.GetAllDiagnostics(provider, p) :
                                testDriver.GetProjectDiagnostics(provider, p);
                            diags = diags.Where(diag => diagIds.Contains(diag.Id));
                            return Task.FromResult(diags);
                        };

                    var diagnosticIds = ImmutableHashSet.Create(diagnostic.Id);
                    var fixAllDiagnosticProvider = new FixAllCodeActionContext.FixAllDiagnosticProvider(diagnosticIds, getDocumentDiagnosticsAsync, getProjectDiagnosticsAsync);
                    var fixAllContext = diagnostic.Location.IsInSource ?
                        new FixAllContext(document, fixer, scope, fixAllActionId, diagnosticIds, fixAllDiagnosticProvider, CancellationToken.None) :
                        new FixAllContext(document.Project, fixer, scope, fixAllActionId, diagnosticIds, fixAllDiagnosticProvider, CancellationToken.None);
                    var fixAllFix = fixAllProvider.GetFixAsync(fixAllContext).WaitAndGetResult(CancellationToken.None);
                    if (fixAllFix != null)
                    {
                        var diagnosticSpan = diagnostic.Location.IsInSource ? diagnostic.Location.SourceSpan : default(TextSpan);
                        var codeFix = new CodeFixCollection(fixAllProvider, diagnosticSpan, ImmutableArray.Create(new CodeFix(document.Project, fixAllFix, diagnostic)));
                        yield return Tuple.Create(diagnostic, codeFix);
                    }
                }
            }
        }
コード例 #13
0
            private CodeFixCollection FilterOnUIThread(CodeFixCollection collection, Workspace workspace)
            {
                this.AssertIsForeground();

                var applicableFixes = collection.Fixes.Where(f => IsApplicable(f.Action, workspace)).ToList();
                return applicableFixes.Count == 0
                    ? null
                    : applicableFixes.Count == collection.Fixes.Length
                        ? collection
                        : new CodeFixCollection(collection.Provider, collection.TextSpan, applicableFixes, collection.FixAllContext);
            }
コード例 #14
0
ファイル: CodeFixService.cs プロジェクト: wenming2014/roslyn
        private async Task AppendFixesOrConfigurationsAsync<TCodeFixProvider>(
            Document document,
            TextSpan fixesSpan,
            IEnumerable<DiagnosticData> diagnosticsWithSameSpan,
            bool fixAllForInSpan,
            ArrayBuilder<CodeFixCollection> result,
            TCodeFixProvider fixer,
            Func<Diagnostic, bool> hasFix,
            Func<ImmutableArray<Diagnostic>, Task<ImmutableArray<CodeFix>>> getFixes,
            CancellationToken cancellationToken)
            where TCodeFixProvider : notnull
        {
            var allDiagnostics =
                await diagnosticsWithSameSpan.OrderByDescending(d => d.Severity)
                                             .ToDiagnosticsAsync(document.Project, cancellationToken).ConfigureAwait(false);
            var diagnostics = allDiagnostics.WhereAsArray(hasFix);
            if (diagnostics.Length <= 0)
            {
                // this can happen for suppression case where all diagnostics can't be suppressed
                return;
            }

            var extensionManager = document.Project.Solution.Workspace.Services.GetRequiredService<IExtensionManager>();
            var fixes = await extensionManager.PerformFunctionAsync(fixer,
                 () => getFixes(diagnostics),
                defaultValue: ImmutableArray<CodeFix>.Empty).ConfigureAwait(false);

            if (fixes.IsDefaultOrEmpty)
            {
                return;
            }

            // If the fix provider supports fix all occurrences, then get the corresponding FixAllProviderInfo and fix all context.
            var fixAllProviderInfo = extensionManager.PerformFunction<FixAllProviderInfo?>(fixer, () => ImmutableInterlocked.GetOrAdd(ref _fixAllProviderMap, fixer, FixAllProviderInfo.Create), defaultValue: null);

            FixAllState? fixAllState = null;
            var supportedScopes = ImmutableArray<FixAllScope>.Empty;
            if (fixAllProviderInfo != null)
            {
                var codeFixProvider = (fixer as CodeFixProvider) ?? new WrapperCodeFixProvider((IConfigurationFixProvider)fixer, diagnostics.Select(d => d.Id));

                var diagnosticIds = diagnostics.Where(fixAllProviderInfo.CanBeFixed)
                                          .Select(d => d.Id)
                                          .ToImmutableHashSet();

                var diagnosticProvider = fixAllForInSpan
                    ? new FixAllPredefinedDiagnosticProvider(allDiagnostics)
                    : (FixAllContext.DiagnosticProvider)new FixAllDiagnosticProvider(this, diagnosticIds);

                fixAllState = new FixAllState(
                    fixAllProvider: fixAllProviderInfo.FixAllProvider,
                    document: document,
                    codeFixProvider: codeFixProvider,
                    scope: FixAllScope.Document,
                    codeActionEquivalenceKey: null,
                    diagnosticIds: diagnosticIds,
                    fixAllDiagnosticProvider: diagnosticProvider);

                supportedScopes = fixAllProviderInfo.SupportedScopes;
            }

            var codeFix = new CodeFixCollection(
                fixer, fixesSpan, fixes, fixAllState,
                supportedScopes, diagnostics.First());
            result.Add(codeFix);
        }