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 2ca0bab
Show file tree
Hide file tree
Showing 19 changed files with 79 additions and 49 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
6 changes: 3 additions & 3 deletions src/dfmt/config.d
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import dfmt.editorconfig;
/// Brace styles
enum BraceStyle
{
unspecified,
_unspecified,
/// $(LINK https://en.wikipedia.org/wiki/Indent_style#Allman_style)
allman,
/// $(LINK https://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS)
Expand All @@ -23,7 +23,7 @@ enum BraceStyle

enum TemplateConstraintStyle
{
unspecified,
_unspecified,
conditional_newline_indent,
conditional_newline,
always_newline,
Expand Down Expand Up @@ -73,7 +73,7 @@ struct Config
void initializeWithDefaults()
{
pattern = "*.d";
end_of_line = EOL.lf;
end_of_line = EOL._default;
indent_style = IndentStyle.space;
indent_size = 4;
tab_width = 4;
Expand Down
9 changes: 5 additions & 4 deletions src/dfmt/editorconfig.d
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,22 @@ private auto commentRe = ctRegex!(`^\s*[#;].*$`);

enum OptionalBoolean : ubyte
{
unspecified = 3,
_unspecified = 3,
t = 1,
f = 0
}

enum IndentStyle : ubyte
{
unspecified,
_unspecified,
tab,
space
}

enum EOL : ubyte
{
unspecified,
_unspecified,
_default,
lf,
cr,
crlf
Expand Down Expand Up @@ -74,7 +75,7 @@ mixin template StandardEditorConfigFields()
static if (N == "pattern")
continue;
else static if (is(T == enum))
*thisN = otherN != T.unspecified ? otherN : *thisN;
*thisN = otherN != T._unspecified ? otherN : *thisN;
else static if (is(T == int))
*thisN = otherN != -1 ? otherN : *thisN;
else static if (is(T == string))
Expand Down
21 changes: 19 additions & 2 deletions src/dfmt/formatter.d
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ struct TokenFormatter(OutputRange)
this(const ubyte[] rawSource, const(Token)[] tokens, immutable short[] depths,
OutputRange output, ASTInformation* astInformation, Config* config)
{
import std.algorithm.searching : countUntil;

this.rawSource = rawSource;
this.tokens = tokens;
this.depths = depths;
Expand All @@ -121,8 +123,23 @@ struct TokenFormatter(OutputRange)
this.eolString = "\n";
else if (eol == eol.crlf)
this.eolString = "\r\n";
else if (eol == eol.unspecified)
else if (eol == eol._unspecified)
assert(false, "config.end_of_line was unspecified");
else
{
assert (eol == eol._default); // Same as input.
// 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 Expand Up @@ -371,7 +388,7 @@ private:
import dfmt.editorconfig : OB = OptionalBoolean;
with (TemplateConstraintStyle) final switch (config.dfmt_template_constraint_style)
{
case unspecified:
case _unspecified:
assert(false, "Config was not validated properly");
case conditional_newline:
immutable l = currentLineLength + betweenParenLength(tokens[index + 1 .. $]);
Expand Down
4 changes: 3 additions & 1 deletion src/dfmt/main.d
Original file line number Diff line number Diff line change
Expand Up @@ -289,12 +289,14 @@ private version (Windows)

template optionsToString(E) if (is(E == enum))
{
import std.algorithm.searching : startsWith;

enum optionsToString = () {

string result = "(";
foreach (s; [__traits(allMembers, E)])
{
if (s != "unspecified")
if (!s.startsWith("_"))
result ~= s ~ "|";
}
result = result[0 .. $ - 1] ~ ")";
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 2ca0bab

Please sign in to comment.