Skip to content

Commit

Permalink
Cleaning up indentation on raw string literals (#977)
Browse files Browse the repository at this point in the history
* This isn't correct, but I wanna see what 3rd party code does

closes #975

* Getting a basic version of this working

* Handling everything except for tabs

* format files

* Fixing issues with tabs + passing options around

* self code review

* more tweaks

* formatting files

---------

Co-authored-by: Lasath Fernando <devel@lasath.org>
  • Loading branch information
belav and shocklateboy92 committed Dec 25, 2023
1 parent 331da7d commit deb6759
Show file tree
Hide file tree
Showing 19 changed files with 196 additions and 35 deletions.
7 changes: 6 additions & 1 deletion Src/CSharpier.Tests/CSharpierIgnoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,12 @@ private string PrintWithoutFormatting(string code)
{
return CSharpierIgnore.PrintWithoutFormatting(
code,
new FormattingContext { LineEnding = Environment.NewLine }
new FormattingContext
{
LineEnding = Environment.NewLine,
IndentSize = 4,
UseTabs = false
}
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
var someString = """
Indent based on previous line
""";

var someString = """
Indent based on previous line
This should stay indented
""";

var doNotIndentIfEndDelimiterIsAtZero = """
Keep This
Where It
Is
""";

var someOneWantsThisMuchIndentation = """
<element attr="content">
<body>
</body>
</element>
""";

var whatAboutWhiteSpace = """
Four Spaces

That last line is six
""";
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var someString = """
Indent based on previous line
""";
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var someString = """
Indent based on previous line
""";
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var someString = """
Indent based on previous line
""";
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var someString = """
Indent based on previous line
""";
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
var someString = """
Indent based on previous line
""";

var someString = """
Indent based on previous line
This should stay indented
""";

var doNotIndentIfEndDelimiterIsAtZero = """
Keep This
Where It
Is
""";

var someOneWantsThisMuchIndentation = """
<element attr="content">
<body>
</body>
</element>
""";

var whatAboutWhiteSpace = """
One Tab

That last line is two tabs
""";
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var whatAboutWhiteSpace = """
Four Spaces

That last line is only two
""";
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var whatAboutWhiteSpace = """
Four Spaces

That last line is only two
""";
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var whatAboutWhiteSpace = """
One Tab

That last line is one tab
""";
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var whatAboutWhiteSpace = """
One Tab

That last line is one tab
""";
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,13 @@ four",
);

var multiLineRaw = """
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.
""";
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 = $"""
This is a long message.
Expand Down
14 changes: 12 additions & 2 deletions Src/CSharpier/CSharpFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,12 @@ bool TryGetCompilationFailure(out CodeFormatterResult compilationResult)
try
{
var lineEnding = PrinterOptions.GetLineEnding(syntaxTree.ToString(), printerOptions);
var formattingContext = new FormattingContext { LineEnding = lineEnding };
var formattingContext = new FormattingContext
{
LineEnding = lineEnding,
IndentSize = printerOptions.TabWidth,
UseTabs = printerOptions.UseTabs,
};
var document = Node.Print(rootNode, formattingContext);
var formattedCode = DocPrinter.DocPrinter.Print(document, printerOptions, lineEnding);
var reorderedModifiers = formattingContext.ReorderedModifiers;
Expand All @@ -119,7 +124,12 @@ bool TryGetCompilationFailure(out CodeFormatterResult compilationResult)
return result;
}

var formattingContext2 = new FormattingContext { LineEnding = lineEnding };
var formattingContext2 = new FormattingContext
{
LineEnding = lineEnding,
IndentSize = printerOptions.TabWidth,
UseTabs = printerOptions.UseTabs,
};
document = Node.Print(
await syntaxTree.GetRootAsync(cancellationToken),
formattingContext2
Expand Down
29 changes: 7 additions & 22 deletions Src/CSharpier/DocPrinter/DocPrinter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,27 +179,8 @@ private void ProcessNextCommand()

private void AppendComment(LeadingComment leadingComment, Indent indent)
{
int CalculateIndentLength(string line)
{
var result = 0;
foreach (var character in line)
{
if (character == ' ')
{
result += 1;
}
else if (character == '\t')
{
result += this.PrinterOptions.TabWidth;
}
else
{
break;
}
}

return result;
}
int CalculateIndentLength(string line) =>
line.CalculateCurrentLeadingIndentation(this.PrinterOptions.TabWidth);

var stringReader = new StringReader(leadingComment.Comment);
var line = stringReader.ReadLine();
Expand Down Expand Up @@ -315,7 +296,11 @@ private void ProcessLine(LineDoc line, PrintMode mode, Indent indent)
{
if (!this.SkipNextNewLine || !this.NewLineNextStringValue)
{
this.Output.TrimTrailingWhitespace();
if (line is not HardLineNoTrim)
{
this.Output.TrimTrailingWhitespace();
}

this.Output.Append(this.EndOfLine).Append(indent.Value);
this.CurrentWidth = indent.Length;
}
Expand Down
2 changes: 2 additions & 0 deletions Src/CSharpier/DocTypes/Doc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public static implicit operator Doc(string value)

public static readonly HardLine HardLine = new();

public static readonly HardLineNoTrim HardLineNoTrim = new();

public static readonly HardLine HardLineSkipBreakIfFirstInGroup = new(false, true);

public static readonly HardLine HardLineIfNoPreviousLine = new(true);
Expand Down
3 changes: 3 additions & 0 deletions Src/CSharpier/DocTypes/HardLineNoTrim.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace CSharpier.DocTypes;

internal class HardLineNoTrim : HardLine { }
11 changes: 10 additions & 1 deletion Src/CSharpier/SyntaxPrinter/FormattingContext.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
namespace CSharpier.SyntaxPrinter;

// TODO rename this to PrintingContext
// TODO and rename PrinterOptions.TabWidth to PrinterOptions.IndentSize
internal class FormattingContext
{
// TODO these go into Options
// context.Options.LineEnding
public required string LineEnding { get; init; }
public required int IndentSize { get; init; }
public required bool UseTabs { get; init; }

// TODO the rest of these go into State
// context.State.PrintingDepth
public int PrintingDepth { get; set; }
public bool NextTriviaNeedsLine { get; set; }
public bool ShouldSkipNextLeadingTrivia { get; set; }
public required string LineEnding { get; init; }

// we need to keep track if we reordered modifiers because when modifiers are moved inside
// of an #if, then we can't compare the before and after disabled text in the source file
Expand Down
38 changes: 36 additions & 2 deletions Src/CSharpier/SyntaxPrinter/Token.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,46 @@ is InterpolatedStringExpressionSyntax
{ RawKind: (int)SyntaxKind.InterpolatedVerbatimStringStartToken }
}
)
|| syntaxToken.RawSyntaxKind() is SyntaxKind.MultiLineRawStringLiteralToken
)
{
var lines = syntaxToken.Text.Replace("\r", string.Empty).Split(new[] { '\n' });
var lines = syntaxToken.Text.Replace("\r", string.Empty).Split('\n');
docs.Add(Doc.Join(Doc.LiteralLine, lines.Select(o => new StringDoc(o))));
}
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
{
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
);
}

contents.RemoveAt(contents.Count - 1);
}

docs.Add(Doc.Indent(contents));
}
else
{
docs.Add(syntaxToken.Text);
Expand Down
27 changes: 27 additions & 0 deletions Src/CSharpier/Utilities/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,31 @@ public static int GetPrintedWidth(this string value)
{
return value.Length;
}

public static int CalculateCurrentLeadingIndentation(this string line, int indentSize)
{
var result = 0;
foreach (var character in line)
{
if (character == ' ')
{
result += 1;
}
// I'm not sure why this converts tabs to the size of an indent
// I'd think this should be based on if UseTabs is true or not
// if using tabs, this should be considered one
// but then how do we convert spaces to tabs?
// this seems to work, and it came from the comments code
else if (character == '\t')
{
result += indentSize;
}
else
{
break;
}
}

return result;
}
}

0 comments on commit deb6759

Please sign in to comment.