private static void Write( ExpressionSyntax expression, ExpressionSyntax nextExpression, SyntaxToken token, string newText, SyntaxNodeTextBuilder builder) { if (FormatConditionalExpressionAnalyzer.IsFixable(expression, token)) { if (!expression.GetTrailingTrivia().IsEmptyOrWhitespace() || !token.LeadingTrivia.IsEmptyOrWhitespace()) { builder.AppendTrailingTrivia(expression); builder.AppendLeadingTrivia(token); } builder.AppendTrailingTrivia(token); builder.AppendLeadingTrivia(nextExpression); builder.Append(newText); builder.AppendSpan(nextExpression); } else { builder.AppendTrailingTrivia(expression); builder.AppendFullSpan(token); builder.AppendLeadingTriviaAndSpan(nextExpression); } }
public static Task <Document> RefactorAsync( Document document, ConditionalExpressionSyntax conditionalExpression, CancellationToken cancellationToken) { ExpressionSyntax condition = conditionalExpression.Condition; ExpressionSyntax whenTrue = conditionalExpression.WhenTrue; ExpressionSyntax whenFalse = conditionalExpression.WhenFalse; SyntaxToken questionToken = conditionalExpression.QuestionToken; SyntaxToken colonToken = conditionalExpression.ColonToken; StringBuilder sb = StringBuilderCache.GetInstance(); var builder = new SyntaxNodeTextBuilder(conditionalExpression, sb); builder.AppendLeadingTrivia(); builder.AppendSpan(condition); Write(condition, whenTrue, questionToken, "? ", builder); Write(whenTrue, whenFalse, colonToken, ": ", builder); builder.AppendTrailingTrivia(); ExpressionSyntax newNode = SyntaxFactory.ParseExpression(StringBuilderCache.GetStringAndFree(sb)); return(document.ReplaceNodeAsync(conditionalExpression, newNode, cancellationToken)); }
private static void Write( ExpressionSyntax expression, ExpressionSyntax nextExpression, SyntaxToken token, string newText, SyntaxNodeTextBuilder builder) { if (IsFixable(expression, token)) { if (expression.GetTrailingTrivia().Any(f => !f.IsWhitespaceOrEndOfLineTrivia()) || token.LeadingTrivia.Any(f => !f.IsWhitespaceOrEndOfLineTrivia())) { builder.AppendTrailingTrivia(expression); builder.AppendLeadingTrivia(token); } builder.AppendTrailingTrivia(token); builder.AppendLeadingTrivia(nextExpression); builder.Append(newText); builder.AppendSpan(nextExpression); } else { builder.AppendTrailingTrivia(expression); builder.AppendFullSpan(token); builder.AppendLeadingTriviaAndSpan(nextExpression); } }
private static Task <Document> RefactorAsync( Document document, InterpolatedStringExpressionSyntax interpolatedString, CancellationToken cancellationToken) { StringBuilder sb = StringBuilderCache.GetInstance(); var b = new SyntaxNodeTextBuilder(interpolatedString, sb); var arguments = new List <ArgumentSyntax>() { null }; if (interpolatedString.IsVerbatim()) { b.Append("@"); } b.Append("\""); int index = 0; foreach (InterpolatedStringContentSyntax content in interpolatedString.Contents) { switch (content.Kind()) { case SyntaxKind.Interpolation: { var interpolation = (InterpolationSyntax)content; b.Append("{"); b.Append(index.ToString(CultureInfo.InvariantCulture)); index++; InterpolationAlignmentClauseSyntax alignmentClause = interpolation.AlignmentClause; if (alignmentClause != null) { b.Append(","); b.AppendSpan(alignmentClause.Value); } InterpolationFormatClauseSyntax formatClause = interpolation.FormatClause; if (formatClause != null) { b.Append(":"); b.AppendSpan(formatClause.FormatStringToken); } b.Append("}"); arguments.Add(Argument(interpolation.Expression)); break; } case SyntaxKind.InterpolatedStringText: { b.AppendSpan(content); break; } } } b.Append("\""); arguments[0] = Argument(ParseExpression(StringBuilderCache.GetStringAndFree(sb))); InvocationExpressionSyntax invocation = SimpleMemberInvocationExpression( CSharpTypeFactory.StringType(), IdentifierName("Format"), ArgumentList(SeparatedList(arguments))); invocation = invocation.WithTriviaFrom(interpolatedString).WithFormatterAnnotation(); return(document.ReplaceNodeAsync(interpolatedString, invocation, cancellationToken)); }
public static async Task <Document> RefactorAsync( Document document, BinaryExpressionSyntax logicalAnd, CancellationToken cancellationToken) { ExpressionSyntax left = logicalAnd.Left; ExpressionSyntax right = logicalAnd.Right.WalkDownParentheses(); if (logicalAnd.Left.IsKind(SyntaxKind.LogicalAndExpression)) { left = ((BinaryExpressionSyntax)logicalAnd.Left).Right; } NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(left, allowedStyles: NullCheckStyles.NotEqualsToNull); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); ExpressionSyntax expression = nullCheck.Expression; bool isNullable = semanticModel.GetTypeSymbol(expression, cancellationToken).IsNullableType(); ExpressionSyntax expression2 = UseConditionalAccessAnalyzer.FindExpressionThatCanBeConditionallyAccessed( expression, right, isNullable: isNullable); var builder = new SyntaxNodeTextBuilder(logicalAnd, StringBuilderCache.GetInstance(logicalAnd.FullSpan.Length)); builder.Append(TextSpan.FromBounds(logicalAnd.FullSpan.Start, left.Span.Start)); builder.AppendSpan(expression); builder.Append("?"); builder.Append(TextSpan.FromBounds(expression2.Span.End, right.Span.End)); switch (right.Kind()) { case SyntaxKind.LogicalOrExpression: case SyntaxKind.LogicalAndExpression: case SyntaxKind.BitwiseOrExpression: case SyntaxKind.BitwiseAndExpression: case SyntaxKind.ExclusiveOrExpression: case SyntaxKind.EqualsExpression: case SyntaxKind.NotEqualsExpression: case SyntaxKind.LessThanExpression: case SyntaxKind.LessThanOrEqualExpression: case SyntaxKind.GreaterThanExpression: case SyntaxKind.GreaterThanOrEqualExpression: case SyntaxKind.IsExpression: case SyntaxKind.AsExpression: case SyntaxKind.IsPatternExpression: { break; } case SyntaxKind.LogicalNotExpression: { builder.Append(" == false"); break; } default: { builder.Append(" == true"); break; } } builder.AppendTrailingTrivia(); string text = StringBuilderCache.GetStringAndFree(builder.StringBuilder); ParenthesizedExpressionSyntax newNode = SyntaxFactory.ParseExpression(text) .WithFormatterAnnotation() .Parenthesize(); return(await document.ReplaceNodeAsync(logicalAnd, newNode, cancellationToken).ConfigureAwait(false)); }
public static async Task <Document> RefactorAsync( Document document, BinaryExpressionSyntax binaryExpression, CancellationToken cancellationToken) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); SyntaxKind kind = binaryExpression.Kind(); (ExpressionSyntax left, ExpressionSyntax right) = UseConditionalAccessAnalyzer.GetFixableExpressions(binaryExpression, kind, semanticModel, cancellationToken); NullCheckStyles allowedStyles = (kind == SyntaxKind.LogicalAndExpression) ? NullCheckStyles.NotEqualsToNull : NullCheckStyles.EqualsToNull; NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(left, allowedStyles: allowedStyles); ExpressionSyntax expression = nullCheck.Expression; bool isNullable = semanticModel.GetTypeSymbol(expression, cancellationToken).IsNullableType(); ExpressionSyntax expression2 = UseConditionalAccessAnalyzer.FindExpressionThatCanBeConditionallyAccessed( expression, right, isNullable: isNullable, semanticModel, cancellationToken); var builder = new SyntaxNodeTextBuilder(binaryExpression, StringBuilderCache.GetInstance(binaryExpression.FullSpan.Length)); builder.Append(TextSpan.FromBounds(binaryExpression.FullSpan.Start, left.SpanStart)); int parenDiff = GetParenTokenDiff(); if (parenDiff > 0) { builder.Append('(', parenDiff); } builder.AppendSpan(expression); builder.Append("?"); builder.Append(TextSpan.FromBounds(expression2.Span.End, right.Span.End)); switch (right.Kind()) { case SyntaxKind.LogicalOrExpression: case SyntaxKind.LogicalAndExpression: case SyntaxKind.BitwiseOrExpression: case SyntaxKind.BitwiseAndExpression: case SyntaxKind.ExclusiveOrExpression: case SyntaxKind.EqualsExpression: case SyntaxKind.NotEqualsExpression: case SyntaxKind.LessThanExpression: case SyntaxKind.LessThanOrEqualExpression: case SyntaxKind.GreaterThanExpression: case SyntaxKind.GreaterThanOrEqualExpression: case SyntaxKind.IsExpression: case SyntaxKind.AsExpression: case SyntaxKind.IsPatternExpression: { break; } case SyntaxKind.LogicalNotExpression: { builder.Append((kind == SyntaxKind.LogicalAndExpression) ? " == false" : " != true"); break; } default: { builder.Append((kind == SyntaxKind.LogicalAndExpression) ? " == true" : " != false"); break; } } if (parenDiff < 0) { builder.Append(')', -parenDiff); } builder.Append(TextSpan.FromBounds(right.Span.End, binaryExpression.FullSpan.End)); string text = StringBuilderCache.GetStringAndFree(builder.StringBuilder); ParenthesizedExpressionSyntax newNode = SyntaxFactory.ParseExpression(text) .WithFormatterAnnotation() .Parenthesize(); return(await document.ReplaceNodeAsync(binaryExpression, newNode, cancellationToken).ConfigureAwait(false)); int GetParenTokenDiff() { int count = 0; foreach (SyntaxToken token in binaryExpression.DescendantTokens(TextSpan.FromBounds(left.SpanStart, expression2.Span.End))) { SyntaxKind tokenKind = token.Kind(); if (tokenKind == SyntaxKind.OpenParenToken) { if (token.IsParentKind(SyntaxKind.ParenthesizedExpression)) { count++; } } else if (tokenKind == SyntaxKind.CloseParenToken) { if (token.IsParentKind(SyntaxKind.ParenthesizedExpression)) { count--; } } } return(count); } }