Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retain line ending by default. #553

Merged
merged 6 commits into from
Jul 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
20 changes: 18 additions & 2 deletions src/dfmt/formatter.d
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,13 @@ 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);
this.eolString = eolStringFromInput;
}
}
}

Expand Down Expand Up @@ -201,6 +206,17 @@ private:
/// and paren indentation is ignored.line breaks and "[" reset the counter.
int parenDepthOnLine;

string eolStringFromInput() const
{
import std.algorithm : countUntil;

// Intentional wraparound, -1 turns into uint.max when not found:
const firstCR = cast(uint) rawSource.countUntil("\r");
if (firstCR < cast(uint) rawSource.countUntil("\n"))
return firstCR == rawSource.countUntil("\r\n") ? "\r\n" : "\r";
return "\n";
}

void formatStep()
{
import std.range : assumeSorted;
Expand Down Expand Up @@ -376,7 +392,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');
}