Skip to content

Commit

Permalink
Retain line ending by default.
Browse files Browse the repository at this point in the history
If no `--end_of_line` was specified, find the first line ending in the input and use that for the whole output.

All tests include checking for differences in line endings.

Closes #552.
  • Loading branch information
veelo committed Jun 2, 2022
1 parent ed5fc2f commit 5b995f5
Show file tree
Hide file tree
Showing 18 changed files with 69 additions and 41 deletions.
12 changes: 12 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,15 @@ tests/issue0228.d text eol=lf
tests/allman/issue0228.d.ref text eol=crlf
tests/knr/issue0228.d.ref text eol=crlf
tests/otbs/issue0228.d.ref text eol=crlf
tests/issue0552_lf.d text eol=lf
tests/allman/issue0552_lf.d.ref text eol=lf
tests/knr/issue0552_lf.d.ref text eol=lf
tests/otbs/issue0552_lf.d.ref text eol=lf
tests/issue0552_cr.d text eol=cr
tests/allman/issue0552_cr.d.ref text eol=cr
tests/knr/issue0552_cr.d.ref text eol=cr
tests/otbs/issue0552_cr.d.ref text eol=cr
tests/issue0552_crlf.d text eol=crlf
tests/allman/issue0552_crlf.d.ref text eol=crlf
tests/knr/issue0552_crlf.d.ref text eol=crlf
tests/otbs/issue0552_crlf.d.ref text eol=crlf
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ void main(string[] args)
### Standard EditorConfig properties
Property Name | Allowed Values | Description
--------------|----------------|------------
end_of_line | `cr`, `crlf` and **`lf`** | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#end_of_line)
end_of_line | `cr`, `crlf` and `lf` | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#end_of_line) When not set, `dfmt` adopts the first line ending in the input.
insert_final_newline | **`true`** | Not supported. `dfmt` always inserts a final newline.
charset | **`UTF-8`** | Not supported. `dfmt` only works correctly on UTF-8.
indent_style | `tab`, **`space`** | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#indent_style)
Expand Down
2 changes: 1 addition & 1 deletion src/dfmt/config.d
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ struct Config
void initializeWithDefaults()
{
pattern = "*.d";
end_of_line = EOL.lf;
end_of_line = EOL.automatic;
indent_style = IndentStyle.space;
indent_size = 4;
tab_width = 4;
Expand Down
3 changes: 2 additions & 1 deletion src/dfmt/editorconfig.d
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ enum EOL : ubyte
unspecified,
lf,
cr,
crlf
crlf,
automatic
}

mixin template StandardEditorConfigFields()
Expand Down
17 changes: 17 additions & 0 deletions src/dfmt/formatter.d
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,23 @@ struct TokenFormatter(OutputRange)
this.eolString = "\r\n";
else if (eol == eol.unspecified)
assert(false, "config.end_of_line was unspecified");
else
{
import std.algorithm.searching : countUntil;

assert (eol == eol.automatic);
// Intentional wraparound, -1 turns into uint.max when not found:
const firstCR = cast(uint) rawSource.countUntil("\r");
if (firstCR < cast(uint) rawSource.countUntil("\n"))
{
if (firstCR == rawSource.countUntil("\r\n"))
this.eolString = "\r\n";
else
this.eolString = "\r";
}
else
this.eolString = "\n";
}
}
}

Expand Down
1 change: 1 addition & 0 deletions tests/allman/issue0552_cr.d.ref
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// Testing CR line endings.void main(){}
Expand Down
4 changes: 4 additions & 0 deletions tests/allman/issue0552_crlf.d.ref
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/// Testing CRLF line endings.
void main()
{
}
4 changes: 4 additions & 0 deletions tests/allman/issue0552_lf.d.ref
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/// Testing LF line endings.
void main()
{
}
1 change: 1 addition & 0 deletions tests/issue0552_cr.d
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// Testing CR line endings.void main(){}
Expand Down
4 changes: 4 additions & 0 deletions tests/issue0552_crlf.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/// Testing CRLF line endings.
void main()
{
}
4 changes: 4 additions & 0 deletions tests/issue0552_lf.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/// Testing LF line endings.
void main()
{
}
1 change: 1 addition & 0 deletions tests/knr/issue0552_cr.d.ref
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// Testing CR line endings.void main(){}
Expand Down
4 changes: 4 additions & 0 deletions tests/knr/issue0552_crlf.d.ref
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/// Testing CRLF line endings.
void main()
{
}
4 changes: 4 additions & 0 deletions tests/knr/issue0552_lf.d.ref
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/// Testing LF line endings.
void main()
{
}
1 change: 1 addition & 0 deletions tests/otbs/issue0552_cr.d.ref
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// Testing CR line endings.void main() {}
Expand Down
3 changes: 3 additions & 0 deletions tests/otbs/issue0552_crlf.d.ref
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/// Testing CRLF line endings.
void main() {
}
3 changes: 3 additions & 0 deletions tests/otbs/issue0552_lf.d.ref
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/// Testing LF line endings.
void main() {
}
40 changes: 2 additions & 38 deletions tests/test.d
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,10 @@ int main()
if (const result = spawnProcess(dfmtCommand, stdin, File(outFileName, "w")).wait)
return result;

// As long as dfmt defaults to LF line endings (issue #552), we'll have to default to ignore
// the line endings in our verification with the reference.
const keepTerminator = dfmtCommand.any!(a => a.canFind("--end_of_line")).to!(Flag!"keepTerminator");
const outText = outFileName.readText;
const refText = refFileName.readText;
const outLines = outText.splitLines(keepTerminator);
const refLines = refText.splitLines(keepTerminator);
const outLines = outText.splitLines(Yes.keepTerminator);
const refLines = refText.splitLines(Yes.keepTerminator);
foreach (i; 0 .. min(refLines.length, outLines.length))
if (outLines[i] != refLines[i])
{
Expand All @@ -56,26 +53,6 @@ int main()
writefln("%(%s%)", [outLines[refLines.length]]);
return 1;
}

// As long as dfmt defaults to LF line endings (issue #552) we need an explicit trailing newline check.
// because a) splitLines gives the same number of lines regardless whether the last line ends with a newline,
// and b) when line endings are ignored the trailing endline is of course also ignored.
if (outText.endsWithNewline)
{
if (!refText.endsWithNewline)
{
writeln(outFileName, " ends with a newline, but ", refFileName, " does not.");
return 1;
}
}
else
{
if (refText.endsWithNewline)
{
writeln(refFileName, " ends with a newline, but ", outFileName, " does not.");
return 1;
}
}
}

foreach (entry; dirEntries("expected_failures", "*.d", SpanMode.shallow))
Expand All @@ -88,16 +65,3 @@ int main()
writeln("All tests succeeded.");
return 0;
}

bool endsWithNewline(string text) pure
{
// Same criteria as https://dlang.org/phobos/std_string.html#.lineSplitter
return
text.endsWith('\n') ||
text.endsWith('\r') ||
text.endsWith(lineSep) ||
text.endsWith(paraSep) ||
text.endsWith('\u0085') ||
text.endsWith('\v') ||
text.endsWith('\f');
}

0 comments on commit 5b995f5

Please sign in to comment.