Exemplo n.º 1
0
        private IEnumerable <IGrouping <SyntaxNode, Diagnostic> > GetDiagnosticsGroupedByMember(
            ImmutableArray <Diagnostic> diagnostics,
            ISyntaxFactsService syntaxFacts,
            SyntaxNode root,
            out string diagnosticId,
            out UnusedValuePreference preference,
            out bool removeAssignments)
        {
            diagnosticId = diagnostics[0].Id;
            var success = AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.TryGetUnusedValuePreference(diagnostics[0], out preference);

            Debug.Assert(success);
            removeAssignments = AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.GetIsRemovableAssignmentDiagnostic(diagnostics[0]);
#if DEBUG
            foreach (var diagnostic in diagnostics)
            {
                Debug.Assert(diagnosticId == diagnostic.Id);
                Debug.Assert(AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.TryGetUnusedValuePreference(diagnostic, out var diagnosticPreference) &&
                             diagnosticPreference == preference);
                Debug.Assert(removeAssignments == AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.GetIsRemovableAssignmentDiagnostic(diagnostic));
            }
#endif

            return(GetDiagnosticsGroupedByMember(diagnostics, syntaxFacts, root));
        }
Exemplo n.º 2
0
        private static string GetEquivalenceKey(Diagnostic diagnostic)
        {
            if (!AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.TryGetUnusedValuePreference(diagnostic, out var preference))
            {
                return(string.Empty);
            }

            var isRemovableAssignment = AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.GetIsRemovableAssignmentDiagnostic(diagnostic);

            return(GetEquivalenceKey(preference, isRemovableAssignment));
        }
Exemplo n.º 3
0
        public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var diagnostic = context.Diagnostics[0];

            if (!AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.TryGetUnusedValuePreference(diagnostic, out var preference))
            {
                return(Task.CompletedTask);
            }

            var isRemovableAssignment = AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.GetIsRemovableAssignmentDiagnostic(diagnostic);

            string title;

            if (isRemovableAssignment)
            {
                // Recommend removing the redundant constant value assignment.
                title = FeaturesResources.Remove_redundant_assignment;
            }
            else
            {
                // Recommend using discard/unused local for redundant non-constant assignment.
                switch (preference)
                {
                case UnusedValuePreference.DiscardVariable:
                    if (IsForEachIterationVariableDiagnostic(diagnostic, context.Document, context.CancellationToken))
                    {
                        // Do not offer a fix to replace unused foreach iteration variable with discard.
                        // User should probably replace it with a for loop based on the collection length.
                        return(Task.CompletedTask);
                    }

                    title = FeaturesResources.Use_discard_underscore;
                    break;

                case UnusedValuePreference.UnusedLocalVariable:
                    title = FeaturesResources.Use_discarded_local;
                    break;

                default:
                    return(Task.CompletedTask);
                }
            }

            context.RegisterCodeFix(
                new MyCodeAction(
                    title,
                    c => FixAsync(context.Document, diagnostic, c),
                    equivalenceKey: GetEquivalenceKey(preference, isRemovableAssignment)),
                diagnostic);

            return(Task.CompletedTask);
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var diagnostic = context.Diagnostics[0];

            if (!AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.TryGetUnusedValuePreference(diagnostic, out var preference))
            {
                return;
            }

            var isRemovableAssignment = AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.GetIsRemovableAssignmentDiagnostic(diagnostic);

            string title;

            if (isRemovableAssignment)
            {
                // Recommend removing the redundant constant value assignment.
                title = FeaturesResources.Remove_redundant_assignment;
            }
            else
            {
                // Recommend using discard/unused local for redundant non-constant assignment.
                switch (preference)
                {
                case UnusedValuePreference.DiscardVariable:
                    if (IsForEachIterationVariableDiagnostic(diagnostic, context.Document, context.CancellationToken))
                    {
                        // Do not offer a fix to replace unused foreach iteration variable with discard.
                        // User should probably replace it with a for loop based on the collection length.
                        return;
                    }

                    title = FeaturesResources.Use_discard_underscore;

                    // Check if this is compound assignment which is not parented by an expression statement,
                    // for example "return x += M();" OR "=> x ??= new C();"
                    // If so, we will be replacing this compound assignment with the underlying binary operation.
                    // For the above examples, it will be "return x + M();" AND "=> x ?? new C();" respectively.
                    // For these cases, we want to show the title as "Remove redundant assignment" instead of "Use discard _".

                    var syntaxFacts = context.Document.GetLanguageService <ISyntaxFactsService>();
                    var root        = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

                    var node = root.FindNode(context.Span, getInnermostNodeForTie: true);
                    if (syntaxFacts.IsLeftSideOfCompoundAssignment(node) &&
                        !syntaxFacts.IsExpressionStatement(node.Parent))
                    {
                        title = FeaturesResources.Remove_redundant_assignment;
                    }

                    break;

                case UnusedValuePreference.UnusedLocalVariable:
                    title = FeaturesResources.Use_discarded_local;
                    break;

                default:
                    return;
                }
            }

            context.RegisterCodeFix(
                new MyCodeAction(
                    title,
                    c => FixAsync(context.Document, diagnostic, c),
                    equivalenceKey: GetEquivalenceKey(preference, isRemovableAssignment)),
                diagnostic);

            return;
        }