public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); BinaryExpressionSyntax binaryExpression = root .FindNode(context.Span, getInnermostNodeForTie: true)? .FirstAncestorOrSelf <BinaryExpressionSyntax>(); if (binaryExpression == null) { 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), diagnostic.Id + EquivalenceKeySuffix); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseAnyMethodInsteadOfCountMethod: { CodeAction codeAction = CodeAction.Create( "Call 'Any' instead of 'Count'", cancellationToken => UseAnyMethodInsteadOfCountMethodRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken), diagnostic.Id + EquivalenceKeySuffix); 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), diagnostic.Id + EquivalenceKeySuffix); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseStringIsNullOrEmptyMethod: { CodeAction codeAction = CodeAction.Create( "Use 'string.IsNullOrEmpty' method", cancellationToken => UseStringIsNullOrEmptyMethodRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken), diagnostic.Id + EquivalenceKeySuffix); 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), diagnostic.Id + EquivalenceKeySuffix); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.RemoveRedundantAsOperator: { CodeAction codeAction = CodeAction.Create( "Remove redundant 'as' operator", cancellationToken => RemoveRedundantAsOperatorRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken), diagnostic.Id + EquivalenceKeySuffix); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseConditionalAccess: { CodeAction codeAction = CodeAction.Create( "Use conditional access", cancellationToken => UseConditionalAccessRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken), diagnostic.Id + EquivalenceKeySuffix); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseStringLengthInsteadOfComparisonWithEmptyString: { CodeAction codeAction = CodeAction.Create( "Use string.Length", cancellationToken => UseStringLengthInsteadOfComparisonWithEmptyStringRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken), diagnostic.Id + EquivalenceKeySuffix); context.RegisterCodeFix(codeAction, diagnostic); break; } } } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); BinaryExpressionSyntax binaryExpression = root .FindNode(context.Span, getInnermostNodeForTie: true)? .FirstAncestorOrSelf <BinaryExpressionSyntax>(); if (binaryExpression == null) { 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), diagnostic.Id + EquivalenceKeySuffix); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseAnyMethodInsteadOfCountMethod: { CodeAction codeAction = CodeAction.Create( "Call 'Any' instead of 'Count'", cancellationToken => UseAnyMethodInsteadOfCountMethodRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken), diagnostic.Id + EquivalenceKeySuffix); 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), diagnostic.Id + EquivalenceKeySuffix); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseStringIsNullOrEmptyMethod: { CodeAction codeAction = CodeAction.Create( "Use 'string.IsNullOrEmpty' method", cancellationToken => UseStringIsNullOrEmptyMethodRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken), diagnostic.Id + EquivalenceKeySuffix); 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), diagnostic.Id + EquivalenceKeySuffix); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.RemoveRedundantAsOperator: { CodeAction codeAction = CodeAction.Create( "Remove redundant 'as' operator", cancellationToken => RemoveRedundantAsOperatorRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken), diagnostic.Id + EquivalenceKeySuffix); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseStringLengthInsteadOfComparisonWithEmptyString: { CodeAction codeAction = CodeAction.Create( "Use string.Length", cancellationToken => UseStringLengthInsteadOfComparisonWithEmptyStringRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken), diagnostic.Id + EquivalenceKeySuffix); 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), diagnostic.Id + EquivalenceKeySuffix); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.ValueTypeCheckedForNull: { 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 => ValueTypeCheckedForNullRefactoring.RefactorAsync(context.Document, binaryExpression, typeSymbol, cancellationToken), diagnostic.Id + EquivalenceKeySuffix); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseIsOperatorInsteadOfAsOperator: { CodeAction codeAction = CodeAction.Create( "Use is operator", cancellationToken => UseIsOperatorInsteadOfAsOperatorRefactoring. RefactorAsync(context.Document, binaryExpression, cancellationToken), diagnostic.Id + EquivalenceKeySuffix); context.RegisterCodeFix(codeAction, diagnostic); break; } } } }