public static async Task <Document> RefactorAsync( Document document, BinaryExpressionSyntax binaryExpression, CancellationToken cancellationToken) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); StringConcatenationExpressionInfo concatenationInfo = SyntaxInfo.StringConcatenationExpressionInfo(binaryExpression, semanticModel, cancellationToken); StringConcatenationAnalysis analysis = concatenationInfo.Analyze(); ExpressionSyntax newNode; if (analysis.ContainsStringLiteral) { if (analysis.ContainsVerbatimExpression && concatenationInfo.ContainsMultiLineExpression()) { newNode = concatenationInfo.ToMultiLineStringLiteralExpression(); } else { newNode = concatenationInfo.ToStringLiteralExpression(); } } else { newNode = concatenationInfo.ToInterpolatedStringExpression(); } newNode = newNode.WithTriviaFrom(binaryExpression); return(await document.ReplaceNodeAsync(binaryExpression, newNode, cancellationToken).ConfigureAwait(false)); }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, SyntaxToken token) { if (context.IsAnyRefactoringEnabled( RefactoringDescriptors.JoinStringExpressions, RefactoringDescriptors.UseStringBuilderInsteadOfConcatenation) && context.Span.IsEmptyAndContainedInSpan(token) && token.IsParentKind(SyntaxKind.AddExpression)) { var addExpression = (BinaryExpressionSyntax)token.Parent; while (addExpression.IsParentKind(SyntaxKind.AddExpression)) { addExpression = (BinaryExpressionSyntax)addExpression.Parent; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); StringConcatenationExpressionInfo concatenationInfo = SyntaxInfo.StringConcatenationExpressionInfo(addExpression, semanticModel, context.CancellationToken); if (concatenationInfo.Success) { if (context.IsRefactoringEnabled(RefactoringDescriptors.JoinStringExpressions)) { JoinStringExpressionsRefactoring.ComputeRefactoring(context, concatenationInfo); } if (context.IsRefactoringEnabled(RefactoringDescriptors.UseStringBuilderInsteadOfConcatenation)) { UseStringBuilderInsteadOfConcatenationRefactoring.ComputeRefactoring(context, concatenationInfo); } } } }
public static void AnalyzeAddExpression(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; if (node.ContainsDiagnostics) { return; } if (node.SpanContainsDirectives()) { return; } var addExpression = (BinaryExpressionSyntax)node; StringConcatenationExpressionInfo concatenationInfo = SyntaxInfo.StringConcatenationExpressionInfo(addExpression, context.SemanticModel, context.CancellationToken); if (concatenationInfo.Success && !concatenationInfo.ContainsNonSpecificExpression && (concatenationInfo.ContainsLiteralExpression ^ concatenationInfo.ContainsInterpolatedStringExpression) && (concatenationInfo.ContainsRegular ^ concatenationInfo.ContainsVerbatim) && (concatenationInfo.ContainsVerbatim || addExpression.IsSingleLine(includeExteriorTrivia: false, cancellationToken: context.CancellationToken))) { context.ReportDiagnostic(DiagnosticDescriptors.JoinStringExpressions, addExpression); } }
public static async Task <Document> RefactorAsync( Document document, BinaryExpressionSyntax binaryExpression, CancellationToken cancellationToken) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); StringConcatenationExpressionInfo concatenationInfo = SyntaxInfo.StringConcatenationExpressionInfo(binaryExpression, semanticModel, cancellationToken); if (concatenationInfo.Success) { ExpressionSyntax newNode = null; if (concatenationInfo.ContainsLiteralExpression) { if (concatenationInfo.ContainsVerbatim && ContainsMultiLine(concatenationInfo, cancellationToken)) { newNode = concatenationInfo.ToMultilineStringLiteral(); } else { newNode = concatenationInfo.ToStringLiteral(); } } else { newNode = concatenationInfo.ToInterpolatedString(); } newNode = newNode.WithTriviaFrom(binaryExpression); return(await document.ReplaceNodeAsync(binaryExpression, newNode, cancellationToken).ConfigureAwait(false)); } Debug.Fail(binaryExpression.ToString()); return(document); }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, BinaryExpressionSyntax binaryExpression) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.NegateOperator)) { SyntaxToken operatorToken = binaryExpression.OperatorToken; if (operatorToken.Span.Contains(context.Span) && NegateOperatorRefactoring.CanBeNegated(operatorToken)) { context.RegisterRefactoring( "Negate operator", cancellationToken => NegateOperatorRefactoring.RefactorAsync(context.Document, operatorToken, cancellationToken)); } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.FormatBinaryExpression)) { FormatBinaryExpressionRefactoring.ComputeRefactorings(context, binaryExpression); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.NegateBinaryExpression)) { NegateBinaryExpressionRefactoring.ComputeRefactoring(context, binaryExpression); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.ExpandCoalesceExpression) && binaryExpression.OperatorToken.Span.Contains(context.Span)) { ExpandCoalesceExpressionRefactoring.ComputeRefactoring(context, binaryExpression); } if (context.IsAnyRefactoringEnabled( RefactoringIdentifiers.JoinStringExpressions, RefactoringIdentifiers.UseStringBuilderInsteadOfConcatenation) && context.Span.IsBetweenSpans(binaryExpression) && binaryExpression.IsKind(SyntaxKind.AddExpression)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); StringConcatenationExpressionInfo concatenationInfo = SyntaxInfo.StringConcatenationExpressionInfo(binaryExpression, semanticModel, context.CancellationToken); if (concatenationInfo.Success) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.JoinStringExpressions)) { JoinStringExpressionsRefactoring.ComputeRefactoring(context, concatenationInfo); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.UseStringBuilderInsteadOfConcatenation)) { UseStringBuilderInsteadOfConcatenationRefactoring.ComputeRefactoring(context, concatenationInfo); } } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.SwapExpressionsInBinaryExpression) && context.Span.IsBetweenSpans(binaryExpression)) { SwapExpressionsInBinaryExpressionRefactoring.ComputeRefactoring(context, binaryExpression); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceAsWithCast) && context.Span.IsEmptyAndContainedInSpanOrBetweenSpans(binaryExpression)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (ReplaceAsWithCastRefactoring.CanRefactor(binaryExpression, semanticModel, context.CancellationToken)) { context.RegisterRefactoring( "Replace as with cast", cancellationToken => ReplaceAsWithCastRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken)); } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.NegateIsExpression)) { NegateIsExpressionRefactoring.ComputeRefactoring(context, binaryExpression); } if (context.Span.IsContainedInSpanOrBetweenSpans(binaryExpression.OperatorToken)) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceEqualsExpressionWithStringEquals)) { await ReplaceEqualsExpressionWithStringEqualsRefactoring.ComputeRefactoringAsync(context, binaryExpression).ConfigureAwait(false); } if (context.IsAnyRefactoringEnabled( RefactoringIdentifiers.ReplaceEqualsExpressionWithStringIsNullOrEmpty, RefactoringIdentifiers.ReplaceEqualsExpressionWithStringIsNullOrWhiteSpace)) { await ReplaceEqualsExpressionRefactoring.ComputeRefactoringsAsync(context, binaryExpression).ConfigureAwait(false); } } if (!context.Span.IsBetweenSpans(binaryExpression) && context.IsAnyRefactoringEnabled( RefactoringIdentifiers.ExtractExpressionFromCondition, RefactoringIdentifiers.JoinStringExpressions)) { BinaryExpressionSelection binaryExpressionSelection = BinaryExpressionSelection.Create(binaryExpression, context.Span); if (binaryExpressionSelection.Expressions.Length > 1) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.ExtractExpressionFromCondition)) { ExtractConditionRefactoring.ComputeRefactoring(context, binaryExpressionSelection); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.JoinStringExpressions) && binaryExpression.IsKind(SyntaxKind.AddExpression)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); StringConcatenationExpressionInfo concatenation = SyntaxInfo.StringConcatenationExpressionInfo(binaryExpressionSelection, semanticModel, context.CancellationToken); if (concatenation.Success) { JoinStringExpressionsRefactoring.ComputeRefactoring(context, concatenation); } } } } }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, BinaryExpressionSyntax binaryExpression) { SyntaxToken operatorToken = binaryExpression.OperatorToken; if (context.IsRefactoringEnabled(RefactoringIdentifiers.InvertOperator) && context.Span.IsEmptyAndContainedInSpanOrBetweenSpans(operatorToken) && InvertOperatorRefactoring.CanBeInverted(operatorToken)) { context.RegisterRefactoring( "Invert operator", cancellationToken => InvertOperatorRefactoring.RefactorAsync(context.Document, operatorToken, cancellationToken), RefactoringIdentifiers.InvertOperator); } if (context.Span.IsEmptyAndContainedInSpan(operatorToken)) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.InvertBinaryExpression)) { InvertBinaryExpressionRefactoring.ComputeRefactoring(context, binaryExpression); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.SwapBinaryOperands)) { SwapBinaryOperandsRefactoring.ComputeRefactoring(context, binaryExpression); } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.FormatBinaryExpression)) { FormatBinaryExpressionRefactoring.ComputeRefactorings(context, binaryExpression); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.ExpandCoalesceExpression) && operatorToken.Span.Contains(context.Span)) { ExpandCoalesceExpressionRefactoring.ComputeRefactoring(context, binaryExpression); } if (context.IsAnyRefactoringEnabled( RefactoringIdentifiers.ExtractExpressionFromCondition, RefactoringIdentifiers.JoinStringExpressions, RefactoringIdentifiers.UseStringBuilderInsteadOfConcatenation) && !context.Span.IsEmpty && binaryExpression.IsKind(SyntaxKind.AddExpression, SyntaxKind.LogicalAndExpression, SyntaxKind.LogicalOrExpression)) { ExpressionChain chain = binaryExpression.AsChain(context.Span); ExpressionChain.Enumerator en = chain.GetEnumerator(); if (en.MoveNext() && en.MoveNext()) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.ExtractExpressionFromCondition)) { ExtractConditionRefactoring.ComputeRefactoring(context, chain); } if (binaryExpression.IsKind(SyntaxKind.AddExpression)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); StringConcatenationExpressionInfo concatenationInfo = SyntaxInfo.StringConcatenationExpressionInfo(chain, semanticModel, context.CancellationToken); if (concatenationInfo.Success) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.JoinStringExpressions)) { JoinStringExpressionsRefactoring.ComputeRefactoring(context, concatenationInfo); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.UseStringBuilderInsteadOfConcatenation)) { UseStringBuilderInsteadOfConcatenationRefactoring.ComputeRefactoring(context, concatenationInfo); } } } } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceAsWithCast) && context.Span.IsEmptyAndContainedInSpanOrBetweenSpans(binaryExpression)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (ReplaceAsWithCastAnalysis.IsFixable(binaryExpression, semanticModel, context.CancellationToken)) { context.RegisterRefactoring( ReplaceAsWithCastRefactoring.Title, cancellationToken => ReplaceAsWithCastRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken), RefactoringIdentifiers.ReplaceAsWithCast); } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.InvertIsExpression)) { InvertIsExpressionRefactoring.ComputeRefactoring(context, binaryExpression); } if (context.Span.IsContainedInSpanOrBetweenSpans(operatorToken)) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceEqualsExpressionWithStringEquals)) { await ReplaceEqualsExpressionWithStringEqualsRefactoring.ComputeRefactoringAsync(context, binaryExpression).ConfigureAwait(false); } if (context.IsAnyRefactoringEnabled( RefactoringIdentifiers.ReplaceEqualsExpressionWithStringIsNullOrEmpty, RefactoringIdentifiers.ReplaceEqualsExpressionWithStringIsNullOrWhiteSpace)) { await ReplaceEqualsExpressionRefactoring.ComputeRefactoringsAsync(context, binaryExpression).ConfigureAwait(false); } } }
public static void Analyze(SyntaxNodeAnalysisContext context, MemberInvocationExpressionInfo invocationInfo) { INamedTypeSymbol stringBuilderSymbol = context.GetTypeByMetadataName(MetadataNames.System_Text_StringBuilder); if (stringBuilderSymbol != null) { InvocationExpressionSyntax invocationExpression = invocationInfo.InvocationExpression; if (context.SemanticModel.TryGetMethodInfo(invocationExpression, out MethodInfo methodInfo, context.CancellationToken) && !methodInfo.IsExtensionMethod && methodInfo.ContainingType?.Equals(stringBuilderSymbol) == true) { ImmutableArray <IParameterSymbol> parameters = methodInfo.Parameters; SeparatedSyntaxList <ArgumentSyntax> arguments = invocationInfo.Arguments; if (parameters.Length == 1 && arguments.Count == 1 && methodInfo.IsName("Append", "AppendLine")) { ArgumentSyntax argument = arguments.First(); ExpressionSyntax expression = argument.Expression; SyntaxKind expressionKind = expression.Kind(); switch (expressionKind) { case SyntaxKind.InterpolatedStringExpression: { context.ReportDiagnostic(DiagnosticDescriptors.OptimizeStringBuilderAppendCall, argument, methodInfo.Name); return; } case SyntaxKind.AddExpression: { StringConcatenationExpressionInfo concatenationInfo = SyntaxInfo.StringConcatenationExpressionInfo((BinaryExpressionSyntax)expression, context.SemanticModel, context.CancellationToken); if (concatenationInfo.Success) { context.ReportDiagnostic(DiagnosticDescriptors.OptimizeStringBuilderAppendCall, argument, methodInfo.Name); return; } break; } default: { if (expressionKind == SyntaxKind.InvocationExpression && IsFixable((InvocationExpressionSyntax)expression, context.SemanticModel, context.CancellationToken)) { context.ReportDiagnostic(DiagnosticDescriptors.OptimizeStringBuilderAppendCall, argument, methodInfo.Name); return; } if (methodInfo.IsName("Append") && parameters.Length == 1 && parameters[0].Type.IsObject() && context.SemanticModel.GetTypeSymbol(argument.Expression, context.CancellationToken).IsValueType) { context.ReportDiagnostic(DiagnosticDescriptors.AvoidBoxingOfValueType, argument); return; } break; } } } else if (parameters.Length > 1 && methodInfo.IsName("Insert") && methodInfo.HasParameters(SpecialType.System_Int32, SpecialType.System_Object) && context.SemanticModel .GetTypeSymbol(arguments[1].Expression, context.CancellationToken) .IsValueType) { context.ReportDiagnostic(DiagnosticDescriptors.AvoidBoxingOfValueType, arguments[1]); } } } }