private static bool CanReplaceInterpolationWithStringLiteralInnerText(SeparatedSyntaxList <ArgumentSyntax> arguments, bool isVerbatim) { bool result = false; for (int i = 1; i < arguments.Count; i++) { ExpressionSyntax expression = arguments[i].Expression; StringLiteralExpressionInfo info = SyntaxInfo.StringLiteralExpressionInfo(expression); if (info.Success) { if (isVerbatim == info.IsVerbatim && info.Expression.GetLeadingTrivia().IsEmptyOrWhitespace() && info.Expression.GetTrailingTrivia().IsEmptyOrWhitespace()) { result = true; } else { return(false); } } } return(result); }
public static void AnalyzeInterpolation(SyntaxNodeAnalysisContext context) { var interpolation = (InterpolationSyntax)context.Node; if (interpolation.AlignmentClause != null) { return; } if (interpolation.FormatClause != null) { return; } StringLiteralExpressionInfo stringLiteralInfo = SyntaxInfo.StringLiteralExpressionInfo(interpolation.Expression); if (!stringLiteralInfo.Success) { return; } if (!(interpolation.Parent is InterpolatedStringExpressionSyntax interpolatedString)) { return; } if (interpolatedString.StringStartToken.ValueText.Contains("@") != stringLiteralInfo.IsVerbatim) { return; } DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UnnecessaryInterpolation, interpolation); }
public void Append(LiteralExpressionSyntax stringLiteral) { if (stringLiteral == null) { return; } if (!stringLiteral.IsKind(SyntaxKind.StringLiteralExpression)) { throw new ArgumentException("", nameof(stringLiteral)); } StringLiteralExpressionInfo literalInfo = SyntaxInfo.StringLiteralExpressionInfo(stringLiteral); bool isVerbatim = literalInfo.IsVerbatim; if (IsVerbatim == isVerbatim) { string text = literalInfo.Text; int length = text.Length; if (length == 0) { return; } int startIndex = StringBuilder.Length; if (isVerbatim) { StringBuilder.Append(text, 2, length - 3); } else { StringBuilder.Append(text, 1, length - 2); } if (IsInterpolated) { StringBuilder.Replace("{", "{{", startIndex); StringBuilder.Replace("}", "}}", startIndex); } } else { Append(literalInfo.ValueText); } }
private static int GetStartIndex(StringLiteralExpressionInfo info, TextSpan span) { int spanStart = info.Expression.SpanStart; int index = span.Start - spanStart; string text = info.Text; if (info.IsVerbatim) { if (index > 1 && StringLiteralParser.CanExtractSpan(text, 2, text.Length - 3, span.Offset(-spanStart), isVerbatim: true, isInterpolatedText: false)) { return(index); } } else if (index > 0 && StringLiteralParser.CanExtractSpan(text, 1, text.Length - 2, span.Offset(-spanStart), isVerbatim: false, isInterpolatedText: false)) { return(index); } return(-1); }
private static void AnalyzeAddExpression(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; if (node.ContainsDiagnostics) { return; } if (node.SpanContainsDirectives()) { return; } if (node.IsParentKind(SyntaxKind.AddExpression)) { return; } var addExpression = (BinaryExpressionSyntax)node; ExpressionSyntax firstExpression = null; ExpressionSyntax lastExpression = null; bool isLiteral = false; bool isVerbatim = false; foreach (ExpressionSyntax expression in addExpression.AsChain().Reverse()) { context.CancellationToken.ThrowIfCancellationRequested(); switch (expression.Kind()) { case SyntaxKind.StringLiteralExpression: { StringLiteralExpressionInfo stringLiteral = SyntaxInfo.StringLiteralExpressionInfo(expression); bool isVerbatim2 = stringLiteral.IsVerbatim; if (firstExpression == null) { firstExpression = expression; isLiteral = true; isVerbatim = isVerbatim2; } else if (!isLiteral || isVerbatim != isVerbatim2 || (!isVerbatim && !CheckHexadecimalEscapeSequence(stringLiteral))) { if (lastExpression != null) { Analyze(context, firstExpression, lastExpression, isVerbatim); } firstExpression = null; lastExpression = null; } else { lastExpression = expression; } break; } case SyntaxKind.InterpolatedStringExpression: { var interpolatedString = ((InterpolatedStringExpressionSyntax)expression); bool isVerbatim2 = interpolatedString.IsVerbatim(); if (firstExpression == null) { firstExpression = expression; isLiteral = false; isVerbatim = isVerbatim2; } else if (isLiteral || isVerbatim != isVerbatim2 || (!isVerbatim && !CheckHexadecimalEscapeSequence(interpolatedString))) { if (lastExpression != null) { Analyze(context, firstExpression, lastExpression, isVerbatim); } firstExpression = null; lastExpression = null; } else { lastExpression = expression; } break; } default: { if (lastExpression != null) { Analyze(context, firstExpression, lastExpression, isVerbatim); } firstExpression = null; lastExpression = null; break; } } } if (lastExpression != null) { Analyze(context, firstExpression, lastExpression, isVerbatim); } }
private static InterpolatedStringExpressionSyntax ReplaceInterpolationWithStringLiteralInnerText( SeparatedSyntaxList <ArgumentSyntax> arguments, InterpolatedStringExpressionSyntax interpolatedString, string text) { StringBuilder sb = StringBuilderCache.GetInstance(); int pos = 0; SyntaxList <InterpolatedStringContentSyntax> contents = interpolatedString.Contents; for (int i = 0; i < contents.Count; i++) { if (contents[i].Kind() != SyntaxKind.Interpolation) { continue; } var interpolation = (InterpolationSyntax)contents[i]; ExpressionSyntax expression = interpolation.Expression; if (expression?.Kind() != SyntaxKind.NumericLiteralExpression) { continue; } var index = (int)((LiteralExpressionSyntax)expression).Token.Value; if (index < 0) { continue; } if (index >= arguments.Count) { continue; } ExpressionSyntax argumentExpression = arguments[index + 1].Expression; StringLiteralExpressionInfo stringLiteral = SyntaxInfo.StringLiteralExpressionInfo(argumentExpression); if (!stringLiteral.Success) { continue; } sb.Append(text, pos, interpolation.SpanStart - pos); int startIndex = sb.Length; sb.Append(stringLiteral.InnerText); sb.Replace("{", "{{", startIndex); sb.Replace("}", "}}", startIndex); pos = interpolation.Span.End; } sb.Append(text, pos, text.Length - pos); return((InterpolatedStringExpressionSyntax)ParseExpression(StringBuilderCache.GetStringAndFree(sb))); }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, LiteralExpressionSyntax literalExpression) { StringLiteralExpressionInfo info = SyntaxInfo.StringLiteralExpressionInfo(literalExpression); Debug.Assert(info.Success); if (!info.Success) { return; } if (context.IsRefactoringEnabled(RefactoringIdentifiers.InsertStringInterpolation) && context.SupportsCSharp6 && context.Span.End < literalExpression.Span.End) { int startIndex = GetStartIndex(info, context.Span); if (startIndex != -1) { context.RegisterRefactoring( "Insert interpolation", cancellationToken => { return(ReplaceWithInterpolatedStringAsync( context.Document, literalExpression, startIndex, context.Span.Length, addNameOf: false, cancellationToken: cancellationToken)); }); if (!context.Span.IsEmpty) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); string name = StringLiteralParser.Parse(literalExpression.Token.Text, startIndex, context.Span.Length, info.IsVerbatim, isInterpolatedText: false); foreach (ISymbol symbol in semanticModel.LookupSymbols(literalExpression.SpanStart)) { if (string.Equals(name, symbol.MetadataName, StringComparison.Ordinal)) { context.RegisterRefactoring( "Insert interpolation with nameof", cancellationToken => { return(ReplaceWithInterpolatedStringAsync( context.Document, literalExpression, startIndex, context.Span.Length, addNameOf: true, cancellationToken: cancellationToken)); }); break; } } } } } if (context.Span.IsBetweenSpans(literalExpression)) { if (info.IsVerbatim) { if (info.ContainsEscapeSequence) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceVerbatimStringLiteralWithRegularStringLiteral)) { context.RegisterRefactoring( "Replace verbatim string literal with regular string literal", ct => ReplaceWithRegularStringLiteralAsync(context.Document, literalExpression, ct)); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceVerbatimStringLiteralWithRegularStringLiterals) && info.ContainsLinefeed) { context.RegisterRefactoring( "Replace verbatim string literal with regular string literals", ct => ReplaceWithRegularStringLiteralsAsync(context.Document, literalExpression, ct)); } } } else if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceRegularStringLiteralWithVerbatimStringLiteral) && info.ContainsEscapeSequence) { context.RegisterRefactoring( "Replace regular string literal with verbatim string literal", ct => ReplaceWithVerbatimStringLiteralAsync(context.Document, literalExpression, ct)); } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.UseStringEmptyInsteadOfEmptyStringLiteral) && CanReplaceWithStringEmpty(literalExpression)) { context.RegisterRefactoring( "Replace \"\" with 'string.Empty'", ct => ReplaceWithStringEmptyAsync(context.Document, literalExpression, ct)); } }