Skip to content

Commit

Permalink
fixing some issues with the recent raw string literal changes from #975
Browse files Browse the repository at this point in the history
… (#1106)

* fixing some issues with the recent raw string literal changes

* Getting this mostly figured out

* Fixing issues with interpolated raw strings

* Fixing issues with interpolated raw strings

* Update InterpolatedStringExpressions.test

* remove using
  • Loading branch information
belav committed Jan 15, 2024
1 parent 3c8022c commit b634ee3
Show file tree
Hide file tree
Showing 11 changed files with 236 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,36 @@ public class ClassName
var s3 = $"x {1:d}";
var trailingComment = $"{someValue /* Comment shouldn't cause new line */}";
}

void RawString()
{
var multiLineRawInterpolated = $"""
this has the wrong indentation but because the interpolation contains new lines we leave it
{(someValue ?
One : Two)
}
""";

var multiLineRawInterpolated = $"""
This is a long message.
It has several lines.
Some are indented
more than others.
Some should start at the first column.
Some have "quoted text" in them.
""";

var multiLineRawInterpolated = $"""
{one}
And {two} And
Just Text
{three}
""";

var multiLineRawInterpolated = $"""
{one}
And {two} And
Just Text
""";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,27 @@ var whatAboutWhiteSpace = """

That last line is six
""";

var whatAboutWhiteSpace = $"""
Four Spaces

That last line is six
""";

CallMethod(
"""
SomeString
"""
);

CallMethod(
"""
TrailingSpaceHere
"""
);

CallMethod(
$"""
TrailingSpaceHere
"""
);
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
var someString = """
Indent based on previous line
""";

var someString = $"""
Indent based on previous line
""";
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
var someString = """
Indent based on previous line
""";

var someString = $"""
Indent based on previous line
""";
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ var whatAboutWhiteSpace = """

That last line is only two
""";

var whatAboutWhiteSpace = $"""
Four Spaces

That last line is only two
""";
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ var whatAboutWhiteSpace = """

That last line is only two
""";

var whatAboutWhiteSpace = $"""
Four Spaces

That last line is only two
""";
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,6 @@ four",
Some have "quoted text" in them.
""";

var multiLineRawInterpolated = $"""
This is a long message.
It has several lines.
Some are indented
more than others.
Some should start at the first column.
Some have "quoted text" in them.
""";

var shortRaw = """Short Raw String""";
var shortRawInterpolated = $"""Short Raw String""";
var longRaw =
Expand Down
61 changes: 61 additions & 0 deletions Src/CSharpier.Tests/SyntaxNodeComparerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,67 @@ public void Usings_With_Directives_Pass_Validation(string content)
result.Should().BeEmpty();
}

[Test]
public void RawStringLiterals_Work_With_Moving_Indentation()
{
var left = """
public class ClassName
{
public void MethodName()
{
CallMethod(
\"\"\"
SomeString
\"\"\"
);
}
}
""";

var right = """
public class ClassName
{
public void MethodName()
{
CallMethod(
\"\"\"
SomeString
\"\"\"
);
}
}
""";

var result = CompareSource(left, right);

result.Should().BeEmpty();
}

[Test]
public void RawStringLiterals_Work_With_Moving_Indentation_2()
{
var left = """"
CallMethod(CallMethod(
"""
SomeString
""", someValue));
"""";
var right = """"
CallMethod(
CallMethod(
"""
SomeString
""",
someValue
)
);
"""";

var result = CompareSource(left, right);

result.Should().BeEmpty();
}

private static void ResultShouldBe(string result, string be)
{
if (Environment.GetEnvironmentVariable("NormalizeLineEndings") != null)
Expand Down
2 changes: 1 addition & 1 deletion Src/CSharpier/SyntaxNodeComparer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ formattedNode is FileScopedNamespaceDeclarationSyntax fsnd
// this validation will fail unless we also get them consistent here
// adding a semi-complicated if check to determine when to do the string replacement
// did not appear to have any performance benefits
if (originalToken.Text.Replace("\r", "") != formattedToken.Text.Replace("\r", ""))
if (originalToken.ValueText.Replace("\r", "") != formattedToken.ValueText.Replace("\r", ""))
{
return NotEqual(
originalToken.RawSyntaxKind() == SyntaxKind.None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ namespace CSharpier.SyntaxPrinter.SyntaxNodePrinters;

internal static class InterpolatedStringExpression
{
internal static readonly string[] lineSeparators = new[] { "\r\n", "\r", "\n" };

public static Doc Print(InterpolatedStringExpressionSyntax node, FormattingContext context)
{
// if any of the expressions in the interpolation contain a newline then don't force this flat
Expand All @@ -15,6 +17,14 @@ public static Doc Print(InterpolatedStringExpressionSyntax node, FormattingConte
);
}

if (
node.StringStartToken.RawSyntaxKind()
== SyntaxKind.InterpolatedMultiLineRawStringStartToken
)
{
return RawString(node, context);
}

var docs = new List<Doc>
{
Token.PrintWithoutLeadingTrivia(node.StringStartToken, context)
Expand All @@ -29,4 +39,58 @@ public static Doc Print(InterpolatedStringExpressionSyntax node, FormattingConte
Doc.ForceFlat(docs)
);
}

private static Doc RawString(InterpolatedStringExpressionSyntax node, FormattingContext context)
{
var lastLineIsIndented =
node.StringEndToken.Text.Replace("\r", string.Empty).Replace("\n", string.Empty)[0]
is '\t'
or ' ';

var contents = new List<Doc>
{
Token.Print(node.StringStartToken, context),
lastLineIsIndented ? Doc.HardLineNoTrim : Doc.LiteralLine
};
foreach (var content in node.Contents)
{
if (content is InterpolationSyntax interpolationSyntax)
{
contents.Add(Interpolation.Print(interpolationSyntax, context));
}
else if (content is InterpolatedStringTextSyntax textSyntax)
{
if (textSyntax.TextToken.ValueText == string.Empty)
{
continue;
}

var lines = textSyntax
.TextToken
.ValueText
.Split(lineSeparators, StringSplitOptions.None);
for (var index = 0; index < lines.Length; index++)
{
var line = lines[index];
contents.Add(line);
if (index == lines.Length - 1)
{
continue;
}
contents.Add(
lastLineIsIndented
? string.IsNullOrEmpty(line)
? Doc.HardLine
: Doc.HardLineNoTrim
: Doc.LiteralLine
);
}
}
}

contents.Add(lastLineIsIndented ? Doc.HardLineNoTrim : Doc.LiteralLine);
contents.Add(Token.Print(node.StringEndToken, context));

return Doc.IndentIf(node.Parent is not ArgumentSyntax, Doc.Concat(contents));
}
}
62 changes: 34 additions & 28 deletions Src/CSharpier/SyntaxPrinter/Token.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public static Doc PrintWithSuffix(
return PrintSyntaxToken(syntaxToken, context, suffixDoc, skipLeadingTrivia);
}

internal static readonly string[] lineSeparators = new[] { "\r\n", "\r", "\n" };

private static Doc PrintSyntaxToken(
SyntaxToken syntaxToken,
FormattingContext context,
Expand Down Expand Up @@ -69,38 +71,42 @@ is InterpolatedStringExpressionSyntax
}
else if (syntaxToken.RawSyntaxKind() is SyntaxKind.MultiLineRawStringLiteralToken)
{
var contents = new List<Doc>();
var lines = syntaxToken.Text.Replace("\r", string.Empty).Split('\n');
var currentIndentation = lines[^1].CalculateCurrentLeadingIndentation(
context.IndentSize
);
if (currentIndentation == 0)
{
contents.Add(Doc.Join(Doc.LiteralLine, lines.Select(o => new StringDoc(o))));
}
else
var linesIncludingQuotes = syntaxToken
.Text
.Split(lineSeparators, StringSplitOptions.None);
var lastLineIsIndented = linesIncludingQuotes[^1][0] is '\t' or ' ';
var contents = new List<Doc>
{
foreach (var line in lines)
{
var indentation = line.CalculateCurrentLeadingIndentation(context.IndentSize);
var numberOfSpacesToAddOrRemove = indentation - currentIndentation;
var modifiedLine =
numberOfSpacesToAddOrRemove > 0
? context.UseTabs
? new string('\t', numberOfSpacesToAddOrRemove / context.IndentSize)
: new string(' ', numberOfSpacesToAddOrRemove)
: string.Empty;
modifiedLine += line.TrimStart();
contents.Add(modifiedLine);
contents.Add(
numberOfSpacesToAddOrRemove > 0 ? Doc.HardLineNoTrim : Doc.HardLine
);
}
linesIncludingQuotes[0],
lastLineIsIndented ? Doc.HardLineNoTrim : Doc.LiteralLine
};

contents.RemoveAt(contents.Count - 1);
var lines = syntaxToken.ValueText.Split(lineSeparators, StringSplitOptions.None);
foreach (var line in lines)
{
contents.Add(line);
contents.Add(
lastLineIsIndented
? string.IsNullOrEmpty(line)
? Doc.HardLine
: Doc.HardLineNoTrim
: Doc.LiteralLine
);
}

docs.Add(Doc.Indent(contents));
contents.Add(linesIncludingQuotes[^1].TrimStart());

docs.Add(
Doc.IndentIf(syntaxToken.Parent?.Parent is not ArgumentSyntax, Doc.Concat(contents))
);
}
else if (
syntaxToken.RawSyntaxKind()
is SyntaxKind.InterpolatedMultiLineRawStringStartToken
or SyntaxKind.InterpolatedRawStringEndToken
)
{
docs.Add(syntaxToken.Text.Trim());
}
else
{
Expand Down

0 comments on commit b634ee3

Please sign in to comment.