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(RefactoringUtility.ChangeInvokedMethodName(invocation, "Fail") .WithArgumentList(argumentList.WithArguments(arguments))); }
private static Task <Document> SimplifyNullChckWithFirstOrDefault( Document document, SyntaxNode node, CancellationToken cancellationToken) { NullCheckExpressionInfo nullCheck = NullCheckExpressionInfo(node, NullCheckStyles.ComparisonToNull | NullCheckStyles.IsNull); var invocation = (InvocationExpressionSyntax)nullCheck.Expression; ExpressionSyntax newNode = RefactoringUtility.ChangeInvokedMethodName(invocation, "Any"); if (node.IsKind(SyntaxKind.EqualsExpression, SyntaxKind.IsPatternExpression)) { newNode = LogicalNotExpression(newNode.TrimTrivia().Parenthesize()); } newNode = newNode.WithTriviaFrom(node); return(document.ReplaceNodeAsync(node, newNode, cancellationToken)); }
private static void Analyze( SyntaxNodeAnalysisContext context, ConditionalExpressionInfo conditionalExpressionInfo, ExpressionSyntax whenNull, ExpressionSyntax whenNotNull, SemanticModel semanticModel, CancellationToken cancellationToken) { ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(whenNotNull, cancellationToken); if (typeSymbol?.IsErrorType() == false && (typeSymbol.IsReferenceType || typeSymbol.IsValueType) && semanticModel.IsDefaultValue(typeSymbol, whenNull, cancellationToken) && !RefactoringUtility.ContainsOutArgumentWithLocal(whenNotNull, semanticModel, cancellationToken) && !conditionalExpressionInfo.ConditionalExpression.IsInExpressionTree(semanticModel, cancellationToken)) { context.ReportDiagnostic( DiagnosticDescriptors.UseConditionalAccessInsteadOfConditionalExpression, conditionalExpressionInfo.ConditionalExpression); } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out InvocationExpressionSyntax invocation)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case DiagnosticIdentifiers.CombineEnumerableWhereMethodChain: { CodeAction codeAction = CodeAction.Create( "Combine 'Where' method chain", cancellationToken => CombineEnumerableWhereMethodChainRefactoring.RefactorAsync(context.Document, invocation, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseCountOrLengthPropertyInsteadOfAnyMethod: { string propertyName = diagnostic.Properties["PropertyName"]; CodeAction codeAction = CodeAction.Create( $"Use '{propertyName}' property instead of calling 'Any'", cancellationToken => UseCountOrLengthPropertyInsteadOfAnyMethodRefactoring.RefactorAsync(context.Document, invocation, propertyName, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseCountOrLengthPropertyInsteadOfCountMethod: { string propertyName = diagnostic.Properties["PropertyName"]; CodeAction codeAction = CodeAction.Create( $"Use '{propertyName}' property instead of calling 'Count'", cancellationToken => UseCountOrLengthPropertyInsteadOfCountMethodRefactoring.RefactorAsync(context.Document, invocation, diagnostic.Properties["PropertyName"], cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseBitwiseOperationInsteadOfCallingHasFlag: { CodeAction codeAction = CodeAction.Create( UseBitwiseOperationInsteadOfCallingHasFlagRefactoring.Title, cancellationToken => UseBitwiseOperationInsteadOfCallingHasFlagRefactoring.RefactorAsync(context.Document, invocation, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.RemoveRedundantToStringCall: { CodeAction codeAction = CodeAction.Create( "Remove redundant 'ToString' call", cancellationToken => context.Document.ReplaceNodeAsync(invocation, RefactoringUtility.RemoveInvocation(invocation).WithFormatterAnnotation(), cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.CallCastInsteadOfSelect: { CodeAction codeAction = CodeAction.Create( "Call 'Cast' instead of 'Select'", cancellationToken => CallCastInsteadOfSelectRefactoring.RefactorAsync(context.Document, invocation, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.RemoveRedundantStringToCharArrayCall: { CodeAction codeAction = CodeAction.Create( "Remove redundant 'ToCharArray' call", cancellationToken => context.Document.ReplaceNodeAsync(invocation, RefactoringUtility.RemoveInvocation(invocation).WithFormatterAnnotation(), cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.CallFindInsteadOfFirstOrDefault: { CodeAction codeAction = CodeAction.Create( "Call 'Find' instead of 'FirstOrDefault'", cancellationToken => CallFindInsteadOfFirstOrDefaultRefactoring.RefactorAsync(context.Document, invocation, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseElementAccessInsteadOfElementAt: { CodeAction codeAction = CodeAction.Create( "Use [] instead of calling 'ElementAt'", cancellationToken => UseElementAccessInsteadOfElementAtRefactoring.RefactorAsync(context.Document, invocation, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseElementAccessInsteadOfFirst: { CodeAction codeAction = CodeAction.Create( "Use [] instead of calling 'First'", cancellationToken => UseElementAccessInsteadOfFirstRefactoring.RefactorAsync(context.Document, invocation, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.CallStringConcatInsteadOfStringJoin: { CodeAction codeAction = CodeAction.Create( "Call 'Concat' instead of 'Join'", cancellationToken => CallStringConcatInsteadOfStringJoinRefactoring.RefactorAsync(context.Document, invocation, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.CallDebugFailInsteadOfDebugAssert: { CodeAction codeAction = CodeAction.Create( "Call 'Fail' instead of 'Assert'", cancellationToken => CallDebugFailInsteadOfDebugAssertRefactoring.RefactorAsync(context.Document, invocation, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.CallExtensionMethodAsInstanceMethod: { CodeAction codeAction = CodeAction.Create( CallExtensionMethodAsInstanceMethodRefactoring.Title, cancellationToken => CallExtensionMethodAsInstanceMethodRefactoring.RefactorAsync(context.Document, invocation, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.CallThenByInsteadOfOrderBy: { SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocation); string oldName = invocationInfo.NameText; string newName = (string.Equals(oldName, "OrderBy", StringComparison.Ordinal)) ? "ThenBy" : "ThenByDescending"; CodeAction codeAction = CodeAction.Create( $"Call '{newName}' instead of '{oldName}'", cancellationToken => CallThenByInsteadOfOrderByRefactoring.RefactorAsync(context.Document, invocation, newName, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } } }
private static async Task <Document> RefactorAsync( Document document, StringConcatenationExpressionInfo concatenationInfo, StatementSyntax statement, CancellationToken cancellationToken) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); string name = NameGenerator.Default.EnsureUniqueLocalName(DefaultNames.StringBuilderVariable, semanticModel, statement.SpanStart, cancellationToken: cancellationToken); IdentifierNameSyntax stringBuilderName = IdentifierName(name); TypeSyntax type = semanticModel.GetTypeByMetadataName(MetadataNames.System_Text_StringBuilder).ToMinimalTypeSyntax(semanticModel, statement.SpanStart); var statements = new List <StatementSyntax>() { LocalDeclarationStatement(VarType(), Identifier(name).WithRenameAnnotation(), ObjectCreationExpression(type, ArgumentList())).WithLeadingTrivia(statement.GetLeadingTrivia()) }; ExpressionSyntax newInvocation = null; foreach (ExpressionSyntax expression in concatenationInfo.Expressions(leftToRight: true)) { if (expression.IsKind(SyntaxKind.InterpolatedStringExpression)) { var interpolatedString = (InterpolatedStringExpressionSyntax)expression; bool isVerbatim = interpolatedString.IsVerbatim(); SyntaxList <InterpolatedStringContentSyntax> contents = interpolatedString.Contents; for (int j = 0; j < contents.Count; j++) { (SyntaxKind contentKind, string methodName, ImmutableArray <ArgumentSyntax> arguments) = RefactoringUtility.ConvertInterpolatedStringToStringBuilderMethod(contents[j], isVerbatim); newInvocation = SimpleMemberInvocationExpression( newInvocation ?? stringBuilderName, IdentifierName(methodName), ArgumentList(arguments.ToSeparatedSyntaxList())); } } else { newInvocation = SimpleMemberInvocationExpression( newInvocation ?? stringBuilderName, IdentifierName("Append"), Argument(expression.WithoutTrivia())); } } statements.Add(ExpressionStatement(newInvocation)); statements.Add(statement .ReplaceNode(concatenationInfo.BinaryExpression, SimpleMemberInvocationExpression(stringBuilderName, IdentifierName("ToString"))) .WithTrailingTrivia(statement.GetTrailingTrivia()) .WithoutLeadingTrivia()); if (statement.IsEmbedded()) { BlockSyntax block = Block(statements).WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(statement, block, cancellationToken).ConfigureAwait(false)); } else { for (int i = 0; i < statements.Count; i++) { statements[i] = statements[i].WithFormatterAnnotation(); } return(await document.ReplaceNodeAsync(statement, statements, cancellationToken).ConfigureAwait(false)); } }
private static InvocationExpressionSyntax ConvertInterpolatedStringExpressionToInvocationExpression( InterpolatedStringExpressionSyntax interpolatedString, SimpleMemberInvocationExpressionInfo invocationInfo, SemanticModel semanticModel) { bool isVerbatim = interpolatedString.IsVerbatim(); bool isAppendLine = string.Equals(invocationInfo.NameText, "AppendLine", StringComparison.Ordinal); InvocationExpressionSyntax invocation = invocationInfo.InvocationExpression; InvocationExpressionSyntax newExpression = null; SyntaxList <InterpolatedStringContentSyntax> contents = interpolatedString.Contents; for (int i = 0; i < contents.Count; i++) { (SyntaxKind contentKind, string methodName, ImmutableArray <ArgumentSyntax> arguments) = RefactoringUtility.ConvertInterpolatedStringToStringBuilderMethod(contents[i], isVerbatim); if (i == contents.Count - 1 && isAppendLine && string.Equals(methodName, "Append", StringComparison.Ordinal) && (contentKind == SyntaxKind.InterpolatedStringText || semanticModel.IsImplicitConversion(((InterpolationSyntax)contents[i]).Expression, semanticModel.Compilation.GetSpecialType(SpecialType.System_String)))) { methodName = "AppendLine"; } if (newExpression == null) { newExpression = invocation .ReplaceNode(invocationInfo.Name, IdentifierName(methodName).WithTriviaFrom(invocationInfo.Name)) .WithArgumentList(invocation.ArgumentList.WithArguments(arguments.ToSeparatedSyntaxList()).WithoutTrailingTrivia()); } else { newExpression = SimpleMemberInvocationExpression( newExpression, IdentifierName(methodName), ArgumentList(arguments.ToSeparatedSyntaxList())); } if (i == contents.Count - 1 && isAppendLine && !string.Equals(methodName, "AppendLine", StringComparison.Ordinal)) { newExpression = SimpleMemberInvocationExpression( newExpression, IdentifierName("AppendLine"), ArgumentList()); } } return(newExpression); }