protected override async Task FixAllAsync(Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor syntaxEditor, CodeActionOptionsProvider options, CancellationToken cancellationToken)
        {
            var nodesToRemove = new HashSet <SyntaxNode>();

            // Create actions and keep their SpanStart.
            // Execute actions ordered descending by SpanStart to avoid conflicts.
            var actionsToPerform = new List <(int, Action)>();
            var root             = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var documentEditor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);

            var documentsToBeSearched = ImmutableHashSet.Create(document);

            foreach (var diagnostic in diagnostics)
            {
                var token = diagnostic.Location.FindToken(cancellationToken);
                var node  = root.FindNode(diagnostic.Location.SourceSpan);
                if (IsCatchDeclarationIdentifier(token))
                {
                    (int, Action)pair = (token.Parent.SpanStart,
                                         () => syntaxEditor.ReplaceNode(
                                             token.Parent,
                                             token.Parent.ReplaceToken(token, default(SyntaxToken)).WithAdditionalAnnotations(Formatter.Annotation)));
                    actionsToPerform.Add(pair);
                }
                else
                {
                    nodesToRemove.Add(node);
                }

                var symbol            = documentEditor.SemanticModel.GetDeclaredSymbol(node, cancellationToken);
                var referencedSymbols = await SymbolFinder.FindReferencesAsync(symbol, document.Project.Solution, documentsToBeSearched, cancellationToken).ConfigureAwait(false);

                foreach (var referencedSymbol in referencedSymbols)
                {
                    if (referencedSymbol?.Locations != null)
                    {
                        foreach (var location in referencedSymbol.Locations)
                        {
                            var referencedSymbolNode = root.FindNode(location.Location.SourceSpan);
                            if (referencedSymbolNode != null)
                            {
                                var nodeToRemoveOrReplace = GetNodeToRemoveOrReplace(referencedSymbolNode);
                                if (nodeToRemoveOrReplace != null)
                                {
                                    nodesToRemove.Add(nodeToRemoveOrReplace);
                                }
                            }
                        }
                    }
                }
            }

            MergeNodesToRemove(nodesToRemove);
            var blockFacts = document.GetLanguageService <IBlockFactsService>();

            foreach (var node in nodesToRemove)
            {
                actionsToPerform.Add((node.SpanStart, () => RemoveOrReplaceNode(syntaxEditor, node, blockFacts)));
            }

            // Process nodes in reverse order
            // to complete with nested declarations before processing the outer ones.
            foreach (var node in actionsToPerform.OrderByDescending(n => n.Item1))
            {
                node.Item2();
            }
        }
示例#2
0
 public CSharpCodeFixOptionsProvider(AnalyzerConfigOptions options, CodeActionOptionsProvider fallbackOptions, HostLanguageServices languageServices)
 {
     _options          = options;
     _fallbackOptions  = fallbackOptions;
     _languageServices = languageServices;
 }
示例#3
0
 public static Task <ImmutableArray <CodeFixCollection> > GetFixesAsync(this ICodeFixService service, Document document, TextSpan range, CodeActionOptionsProvider fallbackOptions, bool isBlocking, CancellationToken cancellationToken)
 => service.StreamFixesAsync(document, range, fallbackOptions, isBlocking, cancellationToken).ToImmutableArrayAsync(cancellationToken);
示例#4
0
        protected override async Task FixAllAsync(
            Document document, ImmutableArray <Diagnostic> diagnostics,
            SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
        {
            // Fix-All for this feature is somewhat complicated.  As Object-Initializers
            // could be arbitrarily nested, we have to make sure that any edits we make
            // to one Object-Initializer are seen by any higher ones.  In order to do this
            // we actually process each object-creation-node, one at a time, rewriting
            // the tree for each node.  In order to do this effectively, we use the '.TrackNodes'
            // feature to keep track of all the object creation nodes as we make edits to
            // the tree.  If we didn't do this, then we wouldn't be able to find the
            // second object-creation-node after we make the edit for the first one.
            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            var originalRoot = editor.OriginalRoot;
            var originalObjectCreationNodes = new Stack <TObjectCreationExpressionSyntax>();

            foreach (var diagnostic in diagnostics)
            {
                var objectCreation = (TObjectCreationExpressionSyntax)originalRoot.FindNode(
                    diagnostic.AdditionalLocations[0].SourceSpan, getInnermostNodeForTie: true);
                originalObjectCreationNodes.Push(objectCreation);
            }

            // We're going to be continually editing this tree.  Track all the nodes we
            // care about so we can find them across each edit.
            document = document.WithSyntaxRoot(originalRoot.TrackNodes(originalObjectCreationNodes));

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var currentRoot = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            while (originalObjectCreationNodes.Count > 0)
            {
                var originalObjectCreation = originalObjectCreationNodes.Pop();
                var objectCreation         = currentRoot.GetCurrentNodes(originalObjectCreation).Single();

                var matches = UseNamedMemberInitializerAnalyzer <TExpressionSyntax, TStatementSyntax, TObjectCreationExpressionSyntax, TMemberAccessExpressionSyntax, TAssignmentStatementSyntax, TVariableDeclaratorSyntax> .Analyze(
                    semanticModel, syntaxFacts, objectCreation, cancellationToken);

                if (matches == null || matches.Value.Length == 0)
                {
                    continue;
                }

                var statement = objectCreation.FirstAncestorOrSelf <TStatementSyntax>();
                Contract.ThrowIfNull(statement);

                var newStatement = GetNewStatement(statement, objectCreation, matches.Value)
                                   .WithAdditionalAnnotations(Formatter.Annotation);

                var subEditor = document.GetSyntaxEditor(currentRoot);

                subEditor.ReplaceNode(statement, newStatement);
                foreach (var match in matches)
                {
                    subEditor.RemoveNode(match.Statement, SyntaxRemoveOptions.KeepUnbalancedDirectives);
                }

                document      = document.WithSyntaxRoot(subEditor.GetChangedRoot());
                semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                currentRoot = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
            }

            editor.ReplaceNode(editor.OriginalRoot, currentRoot);
        }
 public static ValueTask <ExtractMethodGenerationOptions> GetExtractMethodGenerationOptionsAsync(this Document document, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
 => document.GetExtractMethodGenerationOptionsAsync(fallbackOptions.GetExtractMethodGenerationOptions(document.Project.LanguageServices), cancellationToken);
示例#6
0
        protected override async Task FixAllAsync(
            Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CodeActionOptionsProvider options, CancellationToken cancellationToken)
        {
            var methodDeclaration = (MethodDeclarationSyntax)diagnostics[0].AdditionalLocations[0].FindNode(cancellationToken);

            var newDocument = await ConvertToTopLevelStatementsAsync(document, methodDeclaration, cancellationToken).ConfigureAwait(false);

            var newRoot = await newDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            editor.ReplaceNode(editor.OriginalRoot, newRoot);
        }
 protected abstract Task FixOneAsync(
     Document document, Diagnostic diagnostic,
     SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken);
        protected override Task FixAllAsync(Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CodeActionOptionsProvider options, CancellationToken cancellationToken)
        {
            foreach (var diagnostic in diagnostics)
            {
                var node            = editor.OriginalRoot.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true);
                var newDocCommentId = diagnostic.Properties[AbstractRemoveUnnecessaryAttributeSuppressionsDiagnosticAnalyzer.DocCommentIdKey];
                editor.ReplaceNode(node, editor.Generator.LiteralExpression(newDocCommentId).WithTriviaFrom(node));
            }

            return(Task.CompletedTask);
        }
        public async Task <Document> CleanupAsync(
            Document document,
            EnabledDiagnosticOptions enabledDiagnostics,
            IProgressTracker progressTracker,
            CodeActionOptionsProvider fallbackOptions,
            CancellationToken cancellationToken)
        {
            // add one item for the code fixers we get from nuget, we'll do last
            var thirdPartyDiagnosticIdsAndTitles = ImmutableArray <(string diagnosticId, string?title)> .Empty;

            if (enabledDiagnostics.RunThirdPartyFixers)
            {
                thirdPartyDiagnosticIdsAndTitles = await GetThirdPartyDiagnosticIdsAndTitlesAsync(document, cancellationToken).ConfigureAwait(false);

                progressTracker.AddItems(thirdPartyDiagnosticIdsAndTitles.Length);
            }

            // add one item for the 'format' action
            if (enabledDiagnostics.FormatDocument)
            {
                progressTracker.AddItems(1);
            }

            // and one for 'remove/sort usings' if we're going to run that.
            var organizeUsings = enabledDiagnostics.OrganizeUsings.IsRemoveUnusedImportEnabled ||
                                 enabledDiagnostics.OrganizeUsings.IsSortImportsEnabled;

            if (organizeUsings)
            {
                progressTracker.AddItems(1);
            }

            if (enabledDiagnostics.Diagnostics.Any())
            {
                progressTracker.AddItems(enabledDiagnostics.Diagnostics.Length);
            }

            document = await ApplyCodeFixesAsync(
                document, enabledDiagnostics.Diagnostics, progressTracker, fallbackOptions, cancellationToken).ConfigureAwait(false);

            if (enabledDiagnostics.RunThirdPartyFixers)
            {
                document = await ApplyThirdPartyCodeFixesAsync(
                    document, thirdPartyDiagnosticIdsAndTitles, progressTracker, fallbackOptions, cancellationToken).ConfigureAwait(false);
            }

            // do the remove usings after code fix, as code fix might remove some code which can results in unused usings.
            if (organizeUsings)
            {
                progressTracker.Description = this.OrganizeImportsDescription;
                document = await RemoveSortUsingsAsync(
                    document, enabledDiagnostics.OrganizeUsings, fallbackOptions, cancellationToken).ConfigureAwait(false);

                progressTracker.ItemCompleted();
            }

            if (enabledDiagnostics.FormatDocument)
            {
                var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false);

                progressTracker.Description = FeaturesResources.Formatting_document;
                using (Logger.LogBlock(FunctionId.CodeCleanup_Format, cancellationToken))
                {
                    document = await Formatter.FormatAsync(document, formattingOptions, cancellationToken).ConfigureAwait(false);

                    progressTracker.ItemCompleted();
                }
            }

            if (enabledDiagnostics.RunThirdPartyFixers)
            {
                document = await ApplyThirdPartyCodeFixesAsync(
                    document, thirdPartyDiagnosticIdsAndTitles, progressTracker, fallbackOptions, cancellationToken).ConfigureAwait(false);
            }

            return(document);
        }
 protected override Task FixAllAsync(Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
 => WrapFixAsync(
     document,
     diagnostics,
     (d, localFunction, captures) => MakeLocalFunctionStaticCodeFixHelper.MakeLocalFunctionStaticAsync(
         d,
         localFunction,
         captures,
         editor,
         fallbackOptions,
         cancellationToken),
     cancellationToken);
示例#11
0
        private async Task ApplySuppressionFixAsync(IEnumerable <DiagnosticData>?diagnosticsToFix, Func <Project, bool> shouldFixInProject, bool filterStaleDiagnostics, bool isAddSuppression, bool isSuppressionInSource, bool onlyCompilerDiagnostics, bool showPreviewChangesDialog)
        {
            try
            {
                using var token = _listener.BeginAsyncOperation(nameof(ApplySuppressionFix));
                var title             = GetFixTitle(isAddSuppression);
                var waitDialogMessage = GetWaitDialogMessage(isAddSuppression);

                using var context = _uiThreadOperationExecutor.BeginExecute(
                          title,
                          waitDialogMessage,
                          allowCancellation: true,
                          showProgress: true);

                if (diagnosticsToFix == null)
                {
                    return;
                }

                diagnosticsToFix = FilterDiagnostics(diagnosticsToFix, isAddSuppression, isSuppressionInSource, onlyCompilerDiagnostics);
                if (diagnosticsToFix.IsEmpty())
                {
                    return;
                }

                var newSolution = _workspace.CurrentSolution;

                var cancellationToken = context.UserCancellationToken;
                cancellationToken.ThrowIfCancellationRequested();
                var documentDiagnosticsToFixMap = await GetDocumentDiagnosticsToFixAsync(
                    diagnosticsToFix, shouldFixInProject, filterStaleDiagnostics, cancellationToken).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();
                var projectDiagnosticsToFixMap = isSuppressionInSource
                    ? ImmutableDictionary <Project, ImmutableArray <Diagnostic> > .Empty
                    : await GetProjectDiagnosticsToFixAsync(diagnosticsToFix, shouldFixInProject, filterStaleDiagnostics, cancellationToken).ConfigureAwait(false);

                if (documentDiagnosticsToFixMap == null ||
                    projectDiagnosticsToFixMap == null ||
                    (documentDiagnosticsToFixMap.IsEmpty && projectDiagnosticsToFixMap.IsEmpty))
                {
                    // Nothing to fix.
                    return;
                }

                cancellationToken.ThrowIfCancellationRequested();

                // Equivalence key determines what fix will be applied.
                // Make sure we don't include any specific diagnostic ID, as we want all of the given diagnostics (which can have varied ID) to be fixed.
                var equivalenceKey = isAddSuppression
                    ? (isSuppressionInSource ? FeaturesResources.in_Source : FeaturesResources.in_Suppression_File)
                    : FeaturesResources.Remove_Suppression;

                // We have different suppression fixers for every language.
                // So we need to group diagnostics by the containing project language and apply fixes separately.
                var languages = new HashSet <string>(projectDiagnosticsToFixMap.Select(p => p.Key.Language).Concat(documentDiagnosticsToFixMap.Select(kvp => kvp.Key.Project.Language)));

                foreach (var language in languages)
                {
                    // Use the Fix multiple occurrences service to compute a bulk suppression fix for the specified document and project diagnostics,
                    // show a preview changes dialog and then apply the fix to the workspace.

                    cancellationToken.ThrowIfCancellationRequested();

                    var options         = _globalOptions.GetCodeActionOptions(language);
                    var optionsProvider = new CodeActionOptionsProvider(_ => options);

                    var documentDiagnosticsPerLanguage = GetDocumentDiagnosticsMappedToNewSolution(documentDiagnosticsToFixMap, newSolution, language);
                    if (!documentDiagnosticsPerLanguage.IsEmpty)
                    {
                        var suppressionFixer = GetSuppressionFixer(documentDiagnosticsPerLanguage.SelectMany(kvp => kvp.Value), language, _codeFixService);
                        if (suppressionFixer != null)
                        {
                            var suppressionFixAllProvider = suppressionFixer.GetFixAllProvider();
                            newSolution = _fixMultipleOccurencesService.GetFix(
                                documentDiagnosticsPerLanguage,
                                _workspace,
                                suppressionFixer,
                                suppressionFixAllProvider,
                                optionsProvider,
                                equivalenceKey,
                                title,
                                waitDialogMessage,
                                cancellationToken);
                            if (newSolution == null)
                            {
                                // User cancelled or fixer threw an exception, so we just bail out.
                                return;
                            }
                        }
                    }

                    var projectDiagnosticsPerLanguage = GetProjectDiagnosticsMappedToNewSolution(projectDiagnosticsToFixMap, newSolution, language);
                    if (!projectDiagnosticsPerLanguage.IsEmpty)
                    {
                        var suppressionFixer = GetSuppressionFixer(projectDiagnosticsPerLanguage.SelectMany(kvp => kvp.Value), language, _codeFixService);
                        if (suppressionFixer != null)
                        {
                            var suppressionFixAllProvider = suppressionFixer.GetFixAllProvider();
                            newSolution = _fixMultipleOccurencesService.GetFix(
                                projectDiagnosticsPerLanguage,
                                _workspace,
                                suppressionFixer,
                                suppressionFixAllProvider,
                                optionsProvider,
                                equivalenceKey,
                                title,
                                waitDialogMessage,
                                cancellationToken);
                            if (newSolution == null)
                            {
                                return;
                            }
                        }
                    }

                    if (newSolution == _workspace.CurrentSolution)
                    {
                        // No changes.
                        return;
                    }

                    if (showPreviewChangesDialog)
                    {
                        newSolution = FixAllGetFixesService.PreviewChanges(
                            _workspace.CurrentSolution,
                            newSolution,
                            fixAllPreviewChangesTitle: title,
                            fixAllTopLevelHeader: title,
                            languageOpt: languages?.Count == 1 ? languages.Single() : null,
                            workspace: _workspace);
                        if (newSolution == null)
                        {
                            return;
                        }
                    }

                    waitDialogMessage = isAddSuppression ? ServicesVSResources.Applying_suppressions_fix : ServicesVSResources.Applying_remove_suppressions_fix;
                    var operations = ImmutableArray.Create <CodeActionOperation>(new ApplyChangesOperation(newSolution));
                    using var scope = context.AddScope(allowCancellation: true, description: waitDialogMessage);
                    await _editHandlerService.ApplyAsync(
                        _workspace,
                        fromDocument : null,
                        operations : operations,
                        title : title,
                        progressTracker : new UIThreadOperationContextProgressTracker(scope),
                        cancellationToken : cancellationToken).ConfigureAwait(false);

                    // Kick off diagnostic re-analysis for affected projects so that diagnostics gets refreshed.
                    _ = Task.Run(() =>
                    {
                        var reanalyzeDocuments = diagnosticsToFix.Select(d => d.DocumentId).WhereNotNull().Distinct();
                        _diagnosticService.Reanalyze(_workspace, documentIds: reanalyzeDocuments, highPriority: true);
                    });
                }
            }
            catch (OperationCanceledException)
            {
            }
            catch (Exception ex) when(FatalError.ReportAndCatch(ex))
            {
            }
        }
示例#12
0
        protected override async Task FixAllAsync(Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CodeActionOptionsProvider options, CancellationToken cancellationToken)
        {
            var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var syntaxFacts   = document.GetRequiredLanguageService <ISyntaxFactsService>();
            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            foreach (var diagnostic in diagnostics)
            {
                var node = root.FindNode(diagnostic.AdditionalLocations[0].SourceSpan, getInnermostNodeForTie: true);

                editor.ReplaceNode(node, (n, _) =>
                {
                    if (!syntaxFacts.IsBinaryExpression(n))
                    {
                        // This should happen only in error cases.
                        return(n);
                    }

                    syntaxFacts.GetPartsOfBinaryExpression(n, out var left, out var right);
                    if (diagnostic.Properties[RedundantEqualityConstants.RedundantSide] == RedundantEqualityConstants.Right)
                    {
                        return(WithElasticTrailingTrivia(left));
                    }
                    else if (diagnostic.Properties[RedundantEqualityConstants.RedundantSide] == RedundantEqualityConstants.Left)
                    {
                        return(WithElasticTrailingTrivia(right));
                    }

                    return(n);
                });
示例#13
0
        protected override async Task FixAllAsync(Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CodeActionOptionsProvider options, CancellationToken cancellationToken)
        {
            var formattingOptions = await GetOptionsAsync(document, cancellationToken).ConfigureAwait(false);

            var updatedRoot = Formatter.Format(editor.OriginalRoot, SyntaxFormatting, formattingOptions, cancellationToken);

            editor.ReplaceNode(editor.OriginalRoot, updatedRoot);
        }
 public static Task <ImmutableArray <CodeRefactoring> > GetRefactoringsAsync(this ICodeRefactoringService service, Document document, TextSpan state, CodeActionOptionsProvider options, bool isBlocking, CancellationToken cancellationToken)
 => service.GetRefactoringsAsync(document, state, CodeActionRequestPriority.None, options, isBlocking, addOperationScope: _ => null, cancellationToken);
示例#15
0
        protected override Task FixAllAsync(Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CodeActionOptionsProvider options, CancellationToken cancellationToken)
        {
            foreach (var diagnostic in diagnostics)
            {
                var node = editor.OriginalRoot.FindNode(diagnostic.Location.SourceSpan);
                editor.RemoveNode(node);
            }

            return(Task.CompletedTask);
        }
 public AddNewKeywordAction(Document document, SyntaxNode node, CodeActionOptionsProvider fallbackOptions)
 {
     _document        = document;
     _node            = node;
     _fallbackOptions = fallbackOptions;
 }
示例#17
0
        protected override async Task FixAllAsync(Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
        {
            string?    newLine    = null;
            SourceText?sourceText = null;

            foreach (var diagnostic in diagnostics)
            {
                var node = editor.OriginalRoot.FindNode(diagnostic.Location.SourceSpan);
                if (node.IsKind(SyntaxKind.VariableDeclarator) && !(node = node.Parent?.Parent).IsKind(SyntaxKind.EventFieldDeclaration))
                {
                    continue;
                }

#if CODE_STYLE
                var optionSet = document.Project.AnalyzerOptions.GetAnalyzerOptionSet(node.SyntaxTree, cancellationToken);
#else
                var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
#endif
                newLine ??= optionSet.GetOption(FormattingOptions2.NewLine);
                // We can safely assume, that there is no leading doc comment, because that is what CS1591 is telling us.
                // So we create a new /// <inheritdoc/> comment.
                var xmlSpaceAfterTripleSlash = Token(leading: TriviaList(DocumentationCommentExterior("///")), SyntaxKind.XmlTextLiteralToken, text: " ", valueText: " ", trailing: default);
示例#18
0
 public Task <ImmutableArray <CodeFix> > GetFixesAsync(
     Document document, TextSpan span, IEnumerable <Diagnostic> diagnostics, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
 {
     return(GetSuppressionsAsync(document, span, diagnostics, fallbackOptions, skipSuppressMessage: false, skipUnsuppress: false, cancellationToken: cancellationToken));
 }
        /// <summary>
        /// Checks if we should wrap the conditional expression over multiple lines.
        /// </summary>
        private static async Task <bool> MakeMultiLineAsync(
            Document document, SyntaxNode condition, SyntaxNode trueSyntax, SyntaxNode falseSyntax, CodeActionOptionsProvider fallbackOptions,
            CancellationToken cancellationToken)
        {
            var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            if (!sourceText.AreOnSameLine(condition.GetFirstToken(), condition.GetLastToken()) ||
                !sourceText.AreOnSameLine(trueSyntax.GetFirstToken(), trueSyntax.GetLastToken()) ||
                !sourceText.AreOnSameLine(falseSyntax.GetFirstToken(), falseSyntax.GetLastToken()))
            {
                return(true);
            }

            // the option is currently not an editorconfig option, so not available in code style layer
            var wrappingLength =
#if !CODE_STYLE
                fallbackOptions.GetOptions(document.Project.LanguageServices)?.ConditionalExpressionWrappingLength ??
#endif
                CodeActionOptions.DefaultConditionalExpressionWrappingLength;

            if (condition.Span.Length + trueSyntax.Span.Length + falseSyntax.Span.Length > wrappingLength)
            {
                return(true);
            }

            return(false);
        }
示例#20
0
        internal async Task <ImmutableArray <PragmaWarningCodeAction> > GetPragmaSuppressionsAsync(Document document, TextSpan span, IEnumerable <Diagnostic> diagnostics, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
        {
            var codeFixes = await GetSuppressionsAsync(document, span, diagnostics, fallbackOptions, skipSuppressMessage : true, skipUnsuppress : true, cancellationToken : cancellationToken).ConfigureAwait(false);

            return(codeFixes.SelectMany(fix => fix.Action.NestedCodeActions)
                   .OfType <PragmaWarningCodeAction>()
                   .ToImmutableArray());
        }
        public static async Task <Document> FixAllAsync(Document document, ImmutableArray <Diagnostic> diagnostics, CodeActionOptionsProvider codeActionOptionsProvider, CancellationToken cancellationToken)
        {
            var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var editor = new SyntaxEditor(root, document.Project.Solution.Workspace.Services);

            var options = await document.GetCSharpCodeFixOptionsProviderAsync(codeActionOptionsProvider, cancellationToken).ConfigureAwait(false);

            var endOfLineTrivia = SyntaxFactory.ElasticEndOfLine(options.NewLine);

            foreach (var diagnostic in diagnostics)
            {
                FixOne(editor, diagnostic, endOfLineTrivia, cancellationToken);
            }

            return(document.WithSyntaxRoot(editor.GetChangedRoot()));
        }
示例#22
0
        private async Task <ImmutableArray <CodeFix> > GetSuppressionsAsync(
            Document documentOpt, Project project, IEnumerable <Diagnostic> diagnostics, SuppressionTargetInfo suppressionTargetInfo, CodeActionOptionsProvider fallbackOptions, bool skipSuppressMessage, bool skipUnsuppress, CancellationToken cancellationToken)
        {
            // We only care about diagnostics that can be suppressed/unsuppressed.
            diagnostics = diagnostics.Where(IsFixableDiagnostic);
            if (diagnostics.IsEmpty())
            {
                return(ImmutableArray <CodeFix> .Empty);
            }

            INamedTypeSymbol suppressMessageAttribute = null;

            if (!skipSuppressMessage)
            {
                var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

                suppressMessageAttribute = compilation.SuppressMessageAttributeType();
                skipSuppressMessage      = suppressMessageAttribute == null || !suppressMessageAttribute.IsAttribute();
            }

            var lazyFormattingOptions = (SyntaxFormattingOptions)null;
            var result = ArrayBuilder <CodeFix> .GetInstance();

            foreach (var diagnostic in diagnostics)
            {
                if (!diagnostic.IsSuppressed)
                {
                    var nestedActions = ArrayBuilder <NestedSuppressionCodeAction> .GetInstance();

                    if (diagnostic.Location.IsInSource && documentOpt != null)
                    {
                        // pragma warning disable.
                        lazyFormattingOptions ??= await documentOpt.GetSyntaxFormattingOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false);

                        nestedActions.Add(PragmaWarningCodeAction.Create(suppressionTargetInfo, documentOpt, lazyFormattingOptions, diagnostic, this));
                    }

                    // SuppressMessageAttribute suppression is not supported for compiler diagnostics.
                    if (!skipSuppressMessage && SuppressionHelpers.CanBeSuppressedWithAttribute(diagnostic))
                    {
                        // global assembly-level suppress message attribute.
                        nestedActions.Add(new GlobalSuppressMessageCodeAction(
                                              suppressionTargetInfo.TargetSymbol, suppressMessageAttribute, project, diagnostic, this, fallbackOptions));

                        // local suppress message attribute
                        // please note that in order to avoid issues with existing unit tests referencing the code fix
                        // by their index this needs to be the last added to nestedActions
                        if (suppressionTargetInfo.TargetMemberNode != null && suppressionTargetInfo.TargetSymbol.Kind != SymbolKind.Namespace)
                        {
                            nestedActions.Add(new LocalSuppressMessageCodeAction(
                                                  this, suppressionTargetInfo.TargetSymbol, suppressMessageAttribute, suppressionTargetInfo.TargetMemberNode, documentOpt, diagnostic));
                        }
                    }

                    if (nestedActions.Count > 0)
                    {
                        var codeAction = new TopLevelSuppressionCodeAction(
                            diagnostic, nestedActions.ToImmutableAndFree());
                        result.Add(new CodeFix(project, codeAction, diagnostic));
                    }
                }
                else if (!skipUnsuppress)
                {
                    var codeAction = await RemoveSuppressionCodeAction.CreateAsync(suppressionTargetInfo, documentOpt, project, diagnostic, this, fallbackOptions, cancellationToken).ConfigureAwait(false);

                    if (codeAction != null)
                    {
                        result.Add(new CodeFix(project, codeAction, diagnostic));
                    }
                }
            }

            return(result.ToImmutableAndFree());
        }
        protected override async Task FixAllAsync(
            Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
        {
            var fixedDocument = await ConvertToProgramMainAsync(document, cancellationToken).ConfigureAwait(false);

            var fixedRoot = await fixedDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            editor.ReplaceNode(editor.OriginalRoot, fixedRoot);
        }
示例#24
0
        protected override async Task FixAllAsync(
            Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
        {
            var options = await document.GetAnalyzerOptionsProviderAsync(cancellationToken).ConfigureAwait(false);

            var option = GetCodeStyleOption(options);

            if (!_helpers.TryGetOrComputePreferredOrder(option.Value, out var preferredOrder))
            {
                return;
            }

            foreach (var diagnostic in diagnostics)
            {
                var memberDeclaration = diagnostic.Location.FindNode(cancellationToken);

                editor.ReplaceNode(memberDeclaration, (currentNode, _) =>
                {
                    var modifiers        = _syntaxFacts.GetModifiers(currentNode);
                    var orderedModifiers = new SyntaxTokenList(
                        modifiers.OrderBy(CompareModifiers)
                        .Select((t, i) => t.WithTriviaFrom(modifiers[i])));

                    var updatedMemberDeclaration = _syntaxFacts.WithModifiers(currentNode, orderedModifiers);
                    return(updatedMemberDeclaration);
                });
            }

            return;

            // Local functions

            int CompareModifiers(SyntaxToken t1, SyntaxToken t2)
            => GetOrder(t1) - GetOrder(t2);

            int GetOrder(SyntaxToken token)
            => preferredOrder.TryGetValue(token.RawKind, out var value) ? value : int.MaxValue;
        }
示例#25
0
    public static async ValueTask <CSharpCodeFixOptionsProvider> GetCSharpCodeFixOptionsProviderAsync(this Document document, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
    {
        var configOptions = await document.GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false);

        return(new CSharpCodeFixOptionsProvider(configOptions, fallbackOptions, document.Project.GetExtendedLanguageServices()));
    }
示例#26
0
        private async Task <Document> ApplyCodeFixesForSpecificDiagnosticIdsAsync(
            Document document, ImmutableArray <string> diagnosticIds, IProgressTracker progressTracker, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
        {
            foreach (var diagnosticId in diagnosticIds)
            {
                using (Logger.LogBlock(FunctionId.CodeCleanup_ApplyCodeFixesAsync, diagnosticId, cancellationToken))
                {
                    document = await ApplyCodeFixesForSpecificDiagnosticIdAsync(
                        document, diagnosticId, progressTracker, fallbackOptions, cancellationToken).ConfigureAwait(false);
                }
            }

            return(document);
        }
示例#27
0
 public static IAsyncEnumerable <CodeFixCollection> StreamFixesAsync(this ICodeFixService service, Document document, TextSpan range, CodeActionOptionsProvider fallbackOptions, bool isBlocking, CancellationToken cancellationToken)
 => service.StreamFixesAsync(document, range, CodeActionRequestPriority.None, fallbackOptions, isBlocking, addOperationScope: _ => null, cancellationToken);
示例#28
0
        private async Task <Document> ApplyCodeFixesForSpecificDiagnosticIdAsync(Document document, string diagnosticId, IProgressTracker progressTracker, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken)
        {
            var tree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var textSpan = new TextSpan(0, tree.Length);

            var fixCollection = await _codeFixService.GetDocumentFixAllForIdInSpanAsync(
                document, textSpan, diagnosticId, fallbackOptions, cancellationToken).ConfigureAwait(false);

            if (fixCollection == null)
            {
                return(document);
            }

            var fixAllService = document.Project.Solution.Workspace.Services.GetRequiredService <IFixAllGetFixesService>();

            var solution = await fixAllService.GetFixAllChangedSolutionAsync(
                new FixAllContext(fixCollection.FixAllState, progressTracker, cancellationToken)).ConfigureAwait(false);

            return(solution.GetDocument(document.Id) ?? throw new NotSupportedException(FeaturesResources.Removal_of_document_not_supported));
        }
示例#29
0
 public static Task <ImmutableArray <CodeFixCollection> > GetFixesAsync(this ICodeFixService service, Document document, TextSpan textSpan, CodeActionRequestPriority priority, CodeActionOptionsProvider fallbackOptions, bool isBlocking, Func <string, IDisposable?> addOperationScope, CancellationToken cancellationToken)
 => service.StreamFixesAsync(document, textSpan, priority, fallbackOptions, isBlocking, addOperationScope, cancellationToken).ToImmutableArrayAsync(cancellationToken);
        private async Task <CodeRefactoring?> GetRefactoringFromProviderAsync(
            Document document,
            TextSpan state,
            CodeRefactoringProvider provider,
            CodeChangeProviderMetadata?providerMetadata,
            IExtensionManager extensionManager,
            CodeActionOptionsProvider options,
            bool isBlocking,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            if (extensionManager.IsDisabled(provider))
            {
                return(null);
            }

            try
            {
                using var _ = ArrayBuilder <(CodeAction action, TextSpan?applicableToSpan)> .GetInstance(out var actions);

                var context = new CodeRefactoringContext(document, state,

                                                         // TODO: Can we share code between similar lambdas that we pass to this API in BatchFixAllProvider.cs, CodeFixService.cs and CodeRefactoringService.cs?
                                                         (action, applicableToSpan) =>
                {
                    // Serialize access for thread safety - we don't know what thread the refactoring provider will call this delegate from.
                    lock (actions)
                    {
                        // Add the Refactoring Provider Name to the parent CodeAction's CustomTags.
                        // Always add a name even in cases of 3rd party refactorings that do not export
                        // name metadata.
                        action.AddCustomTagAndTelemetryInfo(providerMetadata, provider);

                        actions.Add((action, applicableToSpan));
                    }
                },
                                                         options,
                                                         isBlocking,
                                                         cancellationToken);

                var task = provider.ComputeRefactoringsAsync(context) ?? Task.CompletedTask;
                await task.ConfigureAwait(false);

                if (actions.Count == 0)
                {
                    return(null);
                }

                var fixAllProviderInfo = extensionManager.PerformFunction(
                    provider, () => ImmutableInterlocked.GetOrAdd(ref _fixAllProviderMap, provider, FixAllProviderInfo.Create), defaultValue: null);
                return(new CodeRefactoring(provider, actions.ToImmutable(), fixAllProviderInfo, options));
            }
            catch (OperationCanceledException)
            {
                // We don't want to catch operation canceled exceptions in the catch block
                // below. So catch is here and rethrow it.
                throw;
            }
            catch (Exception e)
            {
                extensionManager.HandleException(provider, e);
            }

            return(null);
        }