public static async Task <Document> RefactorAsync( Document document, TypeDeclarationSyntax typeDeclaration, CancellationToken cancellationToken) { int position = typeDeclaration.OpenBraceToken.Span.End; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); string propertyName = NameGenerator.Default.EnsureUniqueName(DefaultNames.DebuggerDisplayPropertyName, semanticModel, position); AttributeListSyntax attributeList = AttributeList( Attribute( ParseName("System.Diagnostics.DebuggerDisplayAttribute").WithSimplifierAnnotation(), AttributeArgument(LiteralExpression($"{{{propertyName},nq}}")))); PropertyDeclarationSyntax propertyDeclaration = DebuggerDisplayPropertyDeclaration(propertyName, InvocationExpression(IdentifierName("ToString"))); TypeDeclarationSyntax newTypeDeclaration; if (typeDeclaration is ClassDeclarationSyntax classDeclaration) { newTypeDeclaration = SyntaxRefactorings.AddAttributeLists(classDeclaration, keepDocumentationCommentOnTop: true, attributeList); } else { var structDeclaration = (StructDeclarationSyntax)typeDeclaration; newTypeDeclaration = SyntaxRefactorings.AddAttributeLists(structDeclaration, keepDocumentationCommentOnTop: true, attributeList); } newTypeDeclaration = MemberDeclarationInserter.Default.Insert(newTypeDeclaration, propertyDeclaration); return(await document.ReplaceNodeAsync(typeDeclaration, newTypeDeclaration, cancellationToken).ConfigureAwait(false)); }
public static Task <Document> MergeAsync( Document document, MemberDeclarationSyntax member, AttributeListSyntax[] attributeLists, CancellationToken cancellationToken = default) { SyntaxList <AttributeListSyntax> lists = member.GetAttributeLists(); var newLists = new List <AttributeListSyntax>(lists.Count - attributeLists.Length + 1); int index = lists.IndexOf(attributeLists[0]); for (int i = 0; i < index; i++) { newLists.Add(lists[i]); } newLists.Add(SyntaxRefactorings.JoinAttributes(attributeLists).WithFormatterAnnotation()); for (int i = index + attributeLists.Length; i < lists.Count; i++) { newLists.Add(lists[i]); } return(document.ReplaceNodeAsync( member, member.WithAttributeLists(newLists.ToSyntaxList()), cancellationToken)); }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out TypeDeclarationSyntax typeDeclaration)) { return; } Diagnostic diagnostic = context.Diagnostics[0]; Document document = context.Document; CodeAction codeAction = CodeAction.Create( ModifiersCodeFixRegistrator.GetRemoveModifierTitle(SyntaxKind.PartialKeyword), ct => { TypeDeclarationSyntax newTypeDeclaration = typeDeclaration.ReplaceNodes( typeDeclaration.Members.OfType <MethodDeclarationSyntax>().Where(f => f.Modifiers.Contains(SyntaxKind.PartialKeyword) && f.BodyOrExpressionBody() != null), (f, _) => f.RemoveModifier(SyntaxKind.PartialKeyword)); int count = newTypeDeclaration.Members.Count; for (int i = count - 1; i >= 0; i--) { if (newTypeDeclaration.Members[i] is MethodDeclarationSyntax method && method.Modifiers.Contains(SyntaxKind.PartialKeyword)) { newTypeDeclaration = SyntaxRefactorings.RemoveMember(newTypeDeclaration, method); } }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindToken(root, context.Span.Start, out SyntaxToken token)) { return; } Debug.Assert(token.IsKind(SyntaxKind.UnsafeKeyword), token.Kind().ToString()); if (!token.IsKind(SyntaxKind.UnsafeKeyword)) { return; } Diagnostic diagnostic = context.Diagnostics[0]; SyntaxNode parent = token.Parent; if (parent is UnsafeStatementSyntax unsafeStatement) { CodeAction codeAction = CodeAction.Create( "Remove unsafe context", ct => context.Document.ReplaceNodeAsync(unsafeStatement, SyntaxRefactorings.RemoveUnsafeContext(unsafeStatement), ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } else { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, parent, token); } }
public static Task <Document> RefactorAsync( Document document, LiteralExpressionSyntax literalExpression, CancellationToken cancellationToken = default) { LiteralExpressionSyntax newNode = SyntaxRefactorings.ReplaceStringLiteralWithCharacterLiteral(literalExpression); return(document.ReplaceNodeAsync(literalExpression, newNode, cancellationToken)); }
private static ExpressionSyntax CreateNewExpression( InvocationExpressionSyntax invocationExpression, ExpressionSyntax expression) { InvocationExpressionSyntax newExpression = SyntaxRefactorings.ChangeInvokedMethodName(invocationExpression, "Skip"); newExpression = newExpression.AddArgumentListArguments(Argument(expression)); return(SimpleMemberInvocationExpression(newExpression, IdentifierName("Any"))); }
public static Task <Document> RefactorAsync( Document document, InvocationExpressionSyntax invocationExpression, string newName, CancellationToken cancellationToken) { InvocationExpressionSyntax newInvocationExpression = SyntaxRefactorings.ChangeInvokedMethodName(invocationExpression, newName); return(document.ReplaceNodeAsync(invocationExpression, newInvocationExpression, cancellationToken)); }
public static Task <Document> RefactorAsync( Document document, AttributeListSyntax attributeList, CancellationToken cancellationToken) { return(document.ReplaceNodeAsync( attributeList, SyntaxRefactorings.SplitAttributeList(attributeList).Select(f => f.WithFormatterAnnotation()), 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 override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out WhileStatementSyntax whileStatement)) { return; } Document document = context.Document; Diagnostic diagnostic = context.Diagnostics[0]; switch (diagnostic.Id) { case DiagnosticIdentifiers.AvoidUsageOfWhileStatementToCreateInfiniteLoop: { CodeAction codeAction = CodeAction.Create( "Convert to 'for'", ct => { ForStatementSyntax forStatement = SyntaxRefactorings.ConvertWhileStatementToForStatement(whileStatement) .WithFormatterAnnotation(); return(document.ReplaceNodeAsync(whileStatement, forStatement, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseForStatementInsteadOfWhileStatement: { CodeAction codeAction = CodeAction.Create( "Convert to 'for'", ct => { return(ConvertWhileStatementToForStatementAsync( document, whileStatement, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } }
private static Task <Document> MarkDeclarationAsNonCLSCompliantAsync( Document document, MemberDeclarationSyntax memberDeclaration, CancellationToken cancellationToken) { AttributeListSyntax attributeList = AttributeList( Attribute( ParseName("global::System.CLSCompliantAttribute").WithSimplifierAnnotation(), AttributeArgument(FalseLiteralExpression()))).WithFormatterAnnotation(); MemberDeclarationSyntax newMemberDeclaration = SyntaxRefactorings.AddAttributeLists(memberDeclaration, keepDocumentationCommentOnTop: true, attributeList); return(document.ReplaceNodeAsync(memberDeclaration, newMemberDeclaration, cancellationToken)); }
private static Task <Document> RefactorAsync( Document document, WhileStatementSyntax whileStatement, List <ExpressionStatementSyntax> expressionStatements, CancellationToken cancellationToken) { SeparatedSyntaxList <ExpressionSyntax> initializers = expressionStatements .Select(f => f.Expression.TrimTrivia()) .ToSeparatedSyntaxList(); ForStatementSyntax forStatement = SyntaxRefactorings.ConvertWhileStatementToForStatement(whileStatement, initializers: initializers); return(RefactorAsync(document, whileStatement, forStatement, expressionStatements, cancellationToken)); }
private static InvocationExpressionSyntax GetNewInvocation(InvocationExpressionSyntax invocation) { ArgumentListSyntax argumentList = invocation.ArgumentList; SeparatedSyntaxList <ArgumentSyntax> arguments = argumentList.Arguments; if (arguments.Count == 1) { ArgumentSyntax argument = arguments[0]; arguments = arguments.ReplaceAt(0, argument.WithExpression(CSharpFactory.StringLiteralExpression("").WithTriviaFrom(argument.Expression))); } else { arguments = arguments.RemoveAt(0); } return(SyntaxRefactorings.ChangeInvokedMethodName(invocation, "Fail") .WithArgumentList(argumentList.WithArguments(arguments))); }
private static Task <Document> RefactorAsync( Document document, WhileStatementSyntax whileStatement, List <LocalDeclarationStatementSyntax> localDeclarations, CancellationToken cancellationToken) { IEnumerable <VariableDeclarationSyntax> declarations = localDeclarations .Select(f => f.Declaration); TypeSyntax type = declarations.First().Type.TrimTrivia(); SeparatedSyntaxList <VariableDeclaratorSyntax> variables = declarations .SelectMany(f => f.Variables) .Select(f => f.TrimTrivia()) .ToSeparatedSyntaxList(); VariableDeclarationSyntax declaration = VariableDeclaration(type, variables); ForStatementSyntax forStatement = SyntaxRefactorings.ConvertWhileStatementToForStatement(whileStatement, declaration); return(RefactorAsync(document, whileStatement, forStatement, localDeclarations, cancellationToken)); }
public static async Task <Document> RefactorAsync( Document document, WhileStatementSyntax whileStatement, CancellationToken cancellationToken) { StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(whileStatement); if (statementsInfo.Success) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); int index = FindLocalDeclarationStatementIndex( whileStatement, statementsInfo.Statements, startIndex: 0, count: statementsInfo.IndexOf(whileStatement), mustBeReferencedInsideWhileStatement: true, semanticModel: semanticModel, cancellationToken: cancellationToken); if (index >= 0) { List <LocalDeclarationStatementSyntax> localDeclarations = statementsInfo .Statements .Skip(index) .Take(statementsInfo.IndexOf(whileStatement) - index) .Cast <LocalDeclarationStatementSyntax>() .ToList(); return(await RefactorAsync(document, whileStatement, localDeclarations, cancellationToken).ConfigureAwait(false)); } } return(await document.ReplaceNodeAsync( whileStatement, SyntaxRefactorings.ConvertWhileStatementToForStatement(whileStatement), cancellationToken) .ConfigureAwait(false)); }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out StatementSyntax statement)) { return; } Document document = context.Document; Diagnostic diagnostic = context.Diagnostics[0]; if (statement.IsKind(SyntaxKind.ForStatement)) { var forStatement = (ForStatementSyntax)statement; CodeAction codeAction = CodeAction.Create( "Convert to 'while'", ct => ConvertForToWhileAsync(document, forStatement, ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } else if (statement.IsKind(SyntaxKind.WhileStatement)) { var whileStatement = (WhileStatementSyntax)statement; CodeAction codeAction = CodeAction.Create( "Convert to 'for'", ct => { ForStatementSyntax forStatement = SyntaxRefactorings.ConvertWhileStatementToForStatement(whileStatement) .WithFormatterAnnotation(); return(document.ReplaceNodeAsync(whileStatement, forStatement, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } else if (statement.IsKind(SyntaxKind.DoStatement)) { var doStatement = (DoStatementSyntax)statement; if (document.GetConfigOptions(statement.SyntaxTree).GetInfiniteLoopStyle() == InfiniteLoopStyle.ForStatement) { CodeAction codeAction = CodeAction.Create( "Convert to 'for'", ct => ConvertDoToForAsync(document, doStatement, ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } else { CodeAction codeAction = CodeAction.Create( "Convert to 'while'", ct => ConvertDoToWhileRefactoring.RefactorAsync(document, doStatement, ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } } }
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); }
private static async Task <StatementListInfo> RefactorAsync <TStatement>( Document document, TStatement statement, StatementListInfo statementsInfo, Func <TStatement, TStatement> createNewStatement, int count, bool removeReturnStatement, CancellationToken cancellationToken) where TStatement : StatementSyntax { int statementIndex = statementsInfo.IndexOf(statement); var returnStatement = (ReturnStatementSyntax)statementsInfo[statementIndex + 1]; ExpressionSyntax returnExpression = returnStatement.Expression; ExpressionSyntax newReturnExpression = null; SyntaxTriviaList newTrailingTrivia = default; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); ISymbol symbol = semanticModel.GetSymbol(returnExpression, cancellationToken); if (symbol.Kind == SymbolKind.Local && statementIndex > 0 && statementsInfo[statementIndex - 1] is LocalDeclarationStatementSyntax localDeclarationStatement && !localDeclarationStatement.ContainsDiagnostics && !localDeclarationStatement.SpanOrTrailingTriviaContainsDirectives() && !statement.GetLeadingTrivia().Any(f => f.IsDirective)) { SeparatedSyntaxList <VariableDeclaratorSyntax> declarators = localDeclarationStatement.Declaration.Variables; VariableDeclaratorSyntax declarator = declarators.FirstOrDefault(f => semanticModel.GetDeclaredSymbol(f, cancellationToken)?.Equals(symbol) == true); if (declarator != null) { ExpressionSyntax value = declarator.Initializer?.Value; if (removeReturnStatement || value != null) { IEnumerable <ReferencedSymbol> referencedSymbols = await SymbolFinder.FindReferencesAsync(symbol, document.Solution(), cancellationToken).ConfigureAwait(false); if (referencedSymbols.First().Locations.Count() == count + 1) { newReturnExpression = value; if (declarators.Count == 1) { if (!removeReturnStatement && returnStatement.GetTrailingTrivia().IsEmptyOrWhitespace()) { SyntaxTriviaList trailingTrivia = localDeclarationStatement.GetTrailingTrivia(); if (trailingTrivia .SkipWhile(f => f.IsWhitespaceTrivia()) .FirstOrDefault() .IsKind(SyntaxKind.SingleLineCommentTrivia)) { newTrailingTrivia = trailingTrivia; } } SyntaxRemoveOptions removeOptions = SyntaxRefactorings.GetRemoveOptions(localDeclarationStatement); if (newTrailingTrivia.Any()) { removeOptions &= ~SyntaxRemoveOptions.KeepTrailingTrivia; } statementsInfo = statementsInfo.RemoveNode(localDeclarationStatement, removeOptions); statementIndex--; } else { statementsInfo = statementsInfo.ReplaceNode(localDeclarationStatement, localDeclarationStatement.RemoveNode(declarator, SyntaxRefactorings.GetRemoveOptions(declarator))); } returnStatement = (ReturnStatementSyntax)statementsInfo[statementIndex + 1]; } } } } if (removeReturnStatement) { statementsInfo = statementsInfo.RemoveNode(returnStatement, SyntaxRefactorings.GetRemoveOptions(returnStatement)); } else if (newReturnExpression != null) { ReturnStatementSyntax newReturnStatement = returnStatement.WithExpression(newReturnExpression.WithTriviaFrom(returnExpression)); if (newTrailingTrivia.Any()) { newReturnStatement = newReturnStatement.WithTrailingTrivia(newTrailingTrivia); } statementsInfo = statementsInfo.ReplaceNode(returnStatement, newReturnStatement); } StatementSyntax oldNode = statementsInfo[statementIndex]; TStatement newNode = createNewStatement((TStatement)oldNode).WithFormatterAnnotation(); return(statementsInfo.ReplaceNode(oldNode, newNode)); }
public static void ComputeRefactoring(RefactoringContext context, BinaryExpressionSyntax binaryExpression) { BinaryExpressionInfo info = SyntaxInfo.BinaryExpressionInfo(binaryExpression); if (!info.Success) { return; } if (CanRefactor()) { context.RegisterRefactoring( "Swap operands", ct => { BinaryExpressionSyntax newBinaryExpression = SyntaxRefactorings.SwapBinaryOperands(binaryExpression); newBinaryExpression = newBinaryExpression.WithOperatorToken(newBinaryExpression.OperatorToken.WithNavigationAnnotation()); return(context.Document.ReplaceNodeAsync(binaryExpression, newBinaryExpression, ct)); }, RefactoringDescriptors.SwapBinaryOperands); } bool CanRefactor() { SyntaxKind kind = binaryExpression.Kind(); switch (kind) { case SyntaxKind.LogicalAndExpression: case SyntaxKind.LogicalOrExpression: case SyntaxKind.BitwiseAndExpression: case SyntaxKind.BitwiseOrExpression: case SyntaxKind.ExclusiveOrExpression: case SyntaxKind.AddExpression: case SyntaxKind.MultiplyExpression: { return(!info.Left.IsKind(kind)); } case SyntaxKind.EqualsExpression: case SyntaxKind.NotEqualsExpression: { return(!info.Right.IsKind( SyntaxKind.NullLiteralExpression, SyntaxKind.TrueLiteralExpression, SyntaxKind.FalseLiteralExpression)); } case SyntaxKind.GreaterThanExpression: case SyntaxKind.GreaterThanOrEqualExpression: case SyntaxKind.LessThanExpression: case SyntaxKind.LessThanOrEqualExpression: { return(true); } } return(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; } Document document = context.Document; foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case DiagnosticIdentifiers.SimplifyBooleanComparison: { CodeAction codeAction = CodeAction.Create( "Simplify boolean comparison", cancellationToken => SimplifyBooleanComparisonRefactoring.RefactorAsync(document, binaryExpression, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.CallSkipAndAnyInsteadOfCount: { CodeAction codeAction = CodeAction.Create( "Call 'Skip' and 'Any' instead of 'Count'", cancellationToken => CallSkipAndAnyInsteadOfCountRefactoring.RefactorAsync(document, binaryExpression, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.ConstantValuesShouldBePlacedOnRightSideOfComparisons: { CodeAction codeAction = CodeAction.Create( "Swap operands", cancellationToken => document.ReplaceNodeAsync(binaryExpression, SyntaxRefactorings.SwapBinaryOperands(binaryExpression), cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseStringIsNullOrEmptyMethod: { CodeAction codeAction = CodeAction.Create( "Use 'string.IsNullOrEmpty' method", cancellationToken => UseStringIsNullOrEmptyMethodAsync(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(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(document, binaryExpression, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseStringLengthInsteadOfComparisonWithEmptyString: { CodeAction codeAction = CodeAction.Create( "Use string.Length", cancellationToken => UseStringLengthInsteadOfComparisonWithEmptyStringAsync(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(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; if (CSharpFacts.IsSimpleType(typeSymbol.SpecialType) || typeSymbol.ContainsMember <IMethodSymbol>(WellKnownMemberNames.EqualityOperatorName)) { ExpressionSyntax expression = typeSymbol.GetDefaultValueSyntax(document.GetDefaultSyntaxOptions()); title = $"Replace 'null' with '{expression}'"; } else { title = $"Use EqualityComparer<{SymbolDisplay.ToMinimalDisplayString(typeSymbol, semanticModel, binaryExpression.Right.SpanStart, SymbolDisplayFormats.DisplayName)}>.Default"; } CodeAction codeAction = CodeAction.Create( title, cancellationToken => ValueTypeObjectIsNeverEqualToNullRefactoring.RefactorAsync(document, binaryExpression, typeSymbol, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.JoinStringExpressions: { CodeAction codeAction = CodeAction.Create( "Join string expressions", cancellationToken => JoinStringExpressionsRefactoring.RefactorAsync(document, binaryExpression, context.Span, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseExclusiveOrOperator: { CodeAction codeAction = CodeAction.Create( "Use ^ operator", cancellationToken => UseExclusiveOrOperatorRefactoring.RefactorAsync(document, binaryExpression, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.SimplifyBooleanExpression: { CodeAction codeAction = CodeAction.Create( "Simplify boolean expression", cancellationToken => SimplifyBooleanExpressionRefactoring.RefactorAsync(document, binaryExpression, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseShortCircuitingOperator: { SyntaxToken operatorToken = binaryExpression.OperatorToken; SyntaxKind kind = binaryExpression.Kind(); SyntaxToken newToken = default; if (kind == SyntaxKind.BitwiseAndExpression) { newToken = Token(operatorToken.LeadingTrivia, SyntaxKind.AmpersandAmpersandToken, operatorToken.TrailingTrivia); } else if (kind == SyntaxKind.BitwiseOrExpression) { newToken = Token(operatorToken.LeadingTrivia, SyntaxKind.BarBarToken, operatorToken.TrailingTrivia); } CodeAction codeAction = CodeAction.Create( $"Use '{newToken.ToString()}' operator", ct => { BinaryExpressionSyntax newBinaryExpression = null; if (kind == SyntaxKind.BitwiseAndExpression) { newBinaryExpression = LogicalAndExpression(binaryExpression.Left, newToken, binaryExpression.Right); } else if (kind == SyntaxKind.BitwiseOrExpression) { newBinaryExpression = LogicalOrExpression(binaryExpression.Left, newToken, binaryExpression.Right); } return(document.ReplaceNodeAsync(binaryExpression, newBinaryExpression, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UnnecessaryOperator: { CodeAction codeAction = CodeAction.Create( "Use '==' operator", ct => { SyntaxToken operatorToken = binaryExpression.OperatorToken; BinaryExpressionSyntax newBinaryExpression = EqualsExpression( binaryExpression.Left, Token(operatorToken.LeadingTrivia, SyntaxKind.EqualsEqualsToken, operatorToken.TrailingTrivia), binaryExpression.Right); return(document.ReplaceNodeAsync(binaryExpression, newBinaryExpression, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } } }