コード例 #1
0
        public static async Task <Document> RefactorAsync(
            Document document,
            BinaryExpressionSyntax binaryExpression,
            ITypeSymbol typeSymbol,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            ExpressionSyntax right = binaryExpression.Right;

            ExpressionSyntax newNode = null;

            if (typeSymbol.IsPredefinedValueType() ||
                typeSymbol.ExistsMethod(WellKnownMemberNames.EqualityOperatorName))
            {
                newNode = typeSymbol.ToDefaultValueSyntax(semanticModel, right.SpanStart)
                          .WithTriviaFrom(right)
                          .WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(right, newNode, cancellationToken).ConfigureAwait(false));
            }
            else
            {
                INamedTypeSymbol equalityComparerSymbol = semanticModel
                                                          .GetTypeByMetadataName(MetadataNames.System_Collections_Generic_EqualityComparer_T)
                                                          .Construct(typeSymbol);

                newNode = InvocationExpression(
                    SimpleMemberAccessExpression(
                        SimpleMemberAccessExpression(equalityComparerSymbol.ToMinimalTypeSyntax(semanticModel, binaryExpression.SpanStart), IdentifierName("Default")), IdentifierName("Equals")),
                    ArgumentList(
                        Argument(binaryExpression.Left.WithoutTrivia()),
                        Argument(DefaultExpression(typeSymbol.ToMinimalTypeSyntax(semanticModel, right.SpanStart)))));

                if (binaryExpression.IsKind(SyntaxKind.NotEqualsExpression))
                {
                    newNode = LogicalNotExpression(newNode);
                }

                newNode = newNode
                          .WithTriviaFrom(binaryExpression)
                          .WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(binaryExpression, newNode, cancellationToken).ConfigureAwait(false));
            }
        }
コード例 #2
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out BinaryExpressionSyntax binaryExpression))
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case DiagnosticIdentifiers.SimplifyBooleanComparison:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Simplify boolean comparison",
                        cancellationToken => SimplifyBooleanComparisonRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);

                    break;
                }

                case DiagnosticIdentifiers.UseAnyMethodInsteadOfCountMethod:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Call 'Any' instead of 'Count'",
                        cancellationToken => CallAnyInsteadOfCountRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case DiagnosticIdentifiers.AvoidNullLiteralExpressionOnLeftSideOfBinaryExpression:
                {
                    CodeAction codeAction = CodeAction.Create(
                        $"Swap '{binaryExpression.Left}' and '{binaryExpression.Right}'",
                        cancellationToken => SwapExpressionsInBinaryExpressionRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case DiagnosticIdentifiers.UseStringIsNullOrEmptyMethod:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Use 'string.IsNullOrEmpty' method",
                        cancellationToken => UseStringIsNullOrEmptyMethodRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case DiagnosticIdentifiers.SimplifyCoalesceExpression:
                {
                    ExpressionSyntax expression = binaryExpression.Left;

                    if (expression == null ||
                        !context.Span.Contains(expression.Span))
                    {
                        expression = binaryExpression.Right;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Simplify coalesce expression",
                        cancellationToken => SimplifyCoalesceExpressionRefactoring.RefactorAsync(context.Document, binaryExpression, expression, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case DiagnosticIdentifiers.RemoveRedundantAsOperator:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Remove redundant 'as' operator",
                        cancellationToken => RemoveRedundantAsOperatorRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case DiagnosticIdentifiers.UseStringLengthInsteadOfComparisonWithEmptyString:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Use string.Length",
                        cancellationToken => UseStringLengthInsteadOfComparisonWithEmptyStringRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case DiagnosticIdentifiers.UnconstrainedTypeParameterCheckedForNull:
                {
                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(binaryExpression.Left, context.CancellationToken);

                    CodeAction codeAction = CodeAction.Create(
                        $"Use EqualityComparer<{typeSymbol.Name}>.Default",
                        cancellationToken => UnconstrainedTypeParameterCheckedForNullRefactoring.RefactorAsync(context.Document, binaryExpression, typeSymbol, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case DiagnosticIdentifiers.ValueTypeObjectIsNeverEqualToNull:
                {
                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(binaryExpression.Left, context.CancellationToken);

                    string title = null;

                    if (typeSymbol.IsPredefinedValueType() ||
                        typeSymbol.ExistsMethod(WellKnownMemberNames.EqualityOperatorName))
                    {
                        ExpressionSyntax expression = typeSymbol.ToDefaultValueSyntax(semanticModel, binaryExpression.Right.SpanStart);

                        title = $"Replace 'null' with '{expression}'";
                    }
                    else
                    {
                        title = $"Use EqualityComparer<{SymbolDisplay.GetMinimalString(typeSymbol, semanticModel, binaryExpression.Right.SpanStart)}>.Default";
                    }

                    CodeAction codeAction = CodeAction.Create(
                        title,
                        cancellationToken => ValueTypeObjectIsNeverEqualToNullRefactoring.RefactorAsync(context.Document, binaryExpression, typeSymbol, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case DiagnosticIdentifiers.UseIsOperatorInsteadOfAsOperator:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Use is operator",
                        cancellationToken => UseIsOperatorInsteadOfAsOperatorRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case DiagnosticIdentifiers.JoinStringExpressions:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Join string expressions",
                        cancellationToken => JoinStringExpressionsRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case DiagnosticIdentifiers.UseExclusiveOrOperator:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Use ^ operator",
                        cancellationToken => UseExclusiveOrOperatorRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case DiagnosticIdentifiers.SimplifyBooleanExpression:
                {
                    CodeAction codeAction = CodeAction.Create(
                        "Simplify boolean expression",
                        cancellationToken => SimplifyBooleanExpressionRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }
                }
            }
        }