private static Task <Document> RefactorAsync( Document document, ExpressionSyntax expression, ISymbol symbol, Optional <object> optional, SemanticModel semanticModel, CancellationToken cancellationToken) { LiteralExpressionSyntax literalExpression = (optional.HasValue) ? LiteralExpression(optional.Value) : GetLiteralExpression(symbol, semanticModel, cancellationToken); SyntaxNode oldNode = expression; if (oldNode.IsParentKind(SyntaxKind.SimpleMemberAccessExpression)) { var memberAccessExpression = (MemberAccessExpressionSyntax)oldNode.Parent; if (memberAccessExpression.Name == expression) { oldNode = memberAccessExpression; } } return(document.ReplaceNodeAsync(oldNode, literalExpression.WithTriviaFrom(expression).Parenthesize(), cancellationToken)); }
private static Task <Document> RefactorAsync( Document document, LiteralExpressionSyntax literalExpression, LiteralExpressionSyntax newLiteralExpression, CancellationToken cancellationToken) { newLiteralExpression = newLiteralExpression.WithTriviaFrom(literalExpression); return(document.ReplaceNodeAsync(literalExpression, newLiteralExpression, cancellationToken)); }
private static ExpressionSyntax GetNewNode(PrefixUnaryExpressionSyntax logicalNot) { ExpressionSyntax operand = logicalNot.Operand; ExpressionSyntax expression = operand.WalkDownParentheses(); switch (expression.Kind()) { case SyntaxKind.TrueLiteralExpression: case SyntaxKind.FalseLiteralExpression: { LiteralExpressionSyntax newNode = BooleanLiteralExpression(expression.Kind() == SyntaxKind.FalseLiteralExpression); newNode = newNode.WithTriviaFrom(expression); return(operand.ReplaceNode(expression, newNode)); } case SyntaxKind.LogicalNotExpression: { return(((PrefixUnaryExpressionSyntax)expression).Operand); } case SyntaxKind.EqualsExpression: { var equalsExpression = (BinaryExpressionSyntax)expression; BinaryExpressionSyntax notEqualsExpression = NotEqualsExpression( equalsExpression.Left, SyntaxFactory.Token(SyntaxKind.ExclamationEqualsToken).WithTriviaFrom(equalsExpression.OperatorToken), equalsExpression.Right); return(operand.ReplaceNode(equalsExpression, notEqualsExpression)); } case SyntaxKind.InvocationExpression: { var invocationExpression = (InvocationExpressionSyntax)expression; var memberAccessExpression = (MemberAccessExpressionSyntax)invocationExpression.Expression; ExpressionSyntax lambdaExpression = invocationExpression.ArgumentList.Arguments.First().Expression.WalkDownParentheses(); SingleParameterLambdaExpressionInfo lambdaInfo = SyntaxInfo.SingleParameterLambdaExpressionInfo(lambdaExpression); var logicalNot2 = (PrefixUnaryExpressionSyntax)SimplifyLogicalNegationAnalyzer.GetReturnExpression(lambdaInfo.Body).WalkDownParentheses(); InvocationExpressionSyntax newNode = invocationExpression.ReplaceNode(logicalNot2, logicalNot2.Operand.WithTriviaFrom(logicalNot2)); return(SyntaxRefactorings.ChangeInvokedMethodName(newNode, (memberAccessExpression.Name.Identifier.ValueText == "All") ? "Any" : "All")); } } return(null); }
public static Task <Document> RefactorAsync( Document document, LiteralExpressionSyntax literalExpression, CancellationToken cancellationToken = default(CancellationToken)) { LiteralExpressionSyntax newNode = (literalExpression.IsKind(SyntaxKind.TrueLiteralExpression)) ? FalseLiteralExpression() : TrueLiteralExpression(); newNode = newNode.WithTriviaFrom(literalExpression); return(document.ReplaceNodeAsync(literalExpression, newNode, cancellationToken)); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out ExpressionSyntax expression)) { return; } Document document = context.Document; foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case DiagnosticIdentifiers.ExpressionIsAlwaysEqualToTrueOrFalse: { if (expression.IsKind( SyntaxKind.LessThanExpression, SyntaxKind.LessThanOrEqualExpression, SyntaxKind.GreaterThanExpression, SyntaxKind.GreaterThanOrEqualExpression)) { var binaryExpression = (BinaryExpressionSyntax)expression; LiteralExpressionSyntax newNode = CSharpFactory.BooleanLiteralExpression(binaryExpression.IsKind(SyntaxKind.GreaterThanOrEqualExpression, SyntaxKind.LessThanOrEqualExpression)); CodeAction codeAction = CodeAction.Create( $"Replace expression with '{newNode}'", ct => document.ReplaceNodeAsync(binaryExpression, newNode.WithTriviaFrom(binaryExpression), ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } else { CodeAction codeAction = CodeAction.Create( "Remove null check", ct => RemoveUnnecessaryNullCheckAsync(document, expression, ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } break; } } } }
public static async Task <Document> ToStringLiteralAsync( Document document, StringExpressionChain chain, bool multiline, CancellationToken cancellationToken = default(CancellationToken)) { BinaryExpressionSyntax binaryExpression = chain.OriginalExpression; LiteralExpressionSyntax newNode = (multiline) ? chain.ToMultilineStringLiteral() : chain.ToStringLiteral(); newNode = newNode .WithTriviaFrom(binaryExpression) .WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(binaryExpression, newNode, cancellationToken).ConfigureAwait(false)); }
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.CallAnyInsteadOfCount: { 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 (CSharpFacts.IsSimpleType(typeSymbol.SpecialType) || typeSymbol.ContainsMember <IMethodSymbol>(WellKnownMemberNames.EqualityOperatorName)) { ExpressionSyntax expression = typeSymbol.GetDefaultValueSyntax(semanticModel, binaryExpression.Right.SpanStart); title = $"Replace 'null' with '{expression}'"; } else { title = $"Use EqualityComparer<{SymbolDisplay.ToMinimalDisplayString(typeSymbol, semanticModel, binaryExpression.Right.SpanStart, SymbolDisplayFormats.Default)}>.Default"; } CodeAction codeAction = CodeAction.Create( title, cancellationToken => ValueTypeObjectIsNeverEqualToNullRefactoring.RefactorAsync(context.Document, binaryExpression, typeSymbol, 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; } case DiagnosticIdentifiers.ExpressionIsAlwaysEqualToTrueOrFalse: { LiteralExpressionSyntax newNode = BooleanLiteralExpression(binaryExpression.IsKind(SyntaxKind.GreaterThanOrEqualExpression, SyntaxKind.LessThanOrEqualExpression)); CodeAction codeAction = CodeAction.Create( $"Replace expression with '{newNode}'", cancellationToken => context.Document.ReplaceNodeAsync(binaryExpression, newNode.WithTriviaFrom(binaryExpression), cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out ExpressionSyntax expression)) { return; } Document document = context.Document; foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case DiagnosticIdentifiers.ExpressionIsAlwaysEqualToTrueOrFalse: { if (expression.IsKind( SyntaxKind.LessThanExpression, SyntaxKind.LessThanOrEqualExpression, SyntaxKind.GreaterThanExpression, SyntaxKind.GreaterThanOrEqualExpression)) { var binaryExpression = (BinaryExpressionSyntax)expression; LiteralExpressionSyntax newNode = BooleanLiteralExpression(binaryExpression.IsKind(SyntaxKind.GreaterThanOrEqualExpression, SyntaxKind.LessThanOrEqualExpression)); CodeAction codeAction = CodeAction.Create( $"Replace expression with '{newNode}'", ct => document.ReplaceNodeAsync(binaryExpression, newNode.WithTriviaFrom(binaryExpression), ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } else if (diagnostic.Properties.TryGetValue("DoubleNaN", out string leftOrRight)) { var binaryExpression = (BinaryExpressionSyntax)expression; CodeAction codeAction = CodeAction.Create( $"Call 'IsNaN'", ct => { ExpressionSyntax newExpression = SimpleMemberInvocationExpression( CSharpTypeFactory.DoubleType(), IdentifierName("IsNaN"), Argument((leftOrRight == "Left") ? binaryExpression.Left.WithoutLeadingTrivia() : binaryExpression.Right.WithoutTrailingTrivia())); if (binaryExpression.IsKind(SyntaxKind.NotEqualsExpression)) { newExpression = LogicalNotExpression(newExpression); } newExpression = newExpression.Parenthesize().WithTriviaFrom(binaryExpression); return(document.ReplaceNodeAsync(binaryExpression, newExpression, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } { CodeAction codeAction = CodeAction.Create( "Remove null check", ct => RemoveUnnecessaryNullCheckAsync(document, expression, ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } break; } } } }
private static ExpressionSyntax GetNewNode(PrefixUnaryExpressionSyntax logicalNot, Document document) { ExpressionSyntax operand = logicalNot.Operand; ExpressionSyntax expression = operand.WalkDownParentheses(); switch (expression.Kind()) { case SyntaxKind.TrueLiteralExpression: case SyntaxKind.FalseLiteralExpression: { LiteralExpressionSyntax newNode = BooleanLiteralExpression(expression.Kind() == SyntaxKind.FalseLiteralExpression); newNode = newNode.WithTriviaFrom(expression); return(operand.ReplaceNode(expression, newNode)); } case SyntaxKind.LogicalNotExpression: { return(((PrefixUnaryExpressionSyntax)expression).Operand); } case SyntaxKind.EqualsExpression: case SyntaxKind.NotEqualsExpression: case SyntaxKind.LessThanExpression: case SyntaxKind.LessThanOrEqualExpression: case SyntaxKind.GreaterThanExpression: case SyntaxKind.GreaterThanOrEqualExpression: { BinaryExpressionSyntax newExpression = SyntaxLogicalInverter.GetInstance(document).InvertBinaryExpression((BinaryExpressionSyntax)expression); return(operand.ReplaceNode(expression, newExpression)); } case SyntaxKind.InvocationExpression: { var invocationExpression = (InvocationExpressionSyntax)expression; var memberAccessExpression = (MemberAccessExpressionSyntax)invocationExpression.Expression; ExpressionSyntax lambdaExpression = invocationExpression.ArgumentList.Arguments[0].Expression.WalkDownParentheses(); SingleParameterLambdaExpressionInfo lambdaInfo = SyntaxInfo.SingleParameterLambdaExpressionInfo(lambdaExpression); var logicalNot2 = (PrefixUnaryExpressionSyntax)SimplifyLogicalNegationAnalyzer.GetReturnExpression(lambdaInfo.Body).WalkDownParentheses(); InvocationExpressionSyntax newNode = invocationExpression.ReplaceNode(logicalNot2, logicalNot2.Operand.WithTriviaFrom(logicalNot2)); return(SyntaxRefactorings.ChangeInvokedMethodName(newNode, (memberAccessExpression.Name.Identifier.ValueText == "All") ? "Any" : "All")); } case SyntaxKind.IsPatternExpression: { var isPatternExpression = (IsPatternExpressionSyntax)expression; var pattern = (ConstantPatternSyntax)isPatternExpression.Pattern; UnaryPatternSyntax newPattern = NotPattern(pattern.WithoutTrivia()).WithTriviaFrom(pattern); return(isPatternExpression.WithPattern(newPattern) .PrependToLeadingTrivia(logicalNot.GetLeadingTrivia()) .AppendToTrailingTrivia(logicalNot.GetTrailingTrivia())); } } return(null); }