diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..43d013f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,2 @@ +language: d +script: make test diff --git a/src/dfmt.d b/src/dfmt.d index 83bd5dc..14a55d9 100644 --- a/src/dfmt.d +++ b/src/dfmt.d @@ -159,7 +159,7 @@ private: const i = index; if (i > 0) { - if (tokens[i-1].line < tokens[i].line) + if (tokens[i-1].line < current.line) { if (tokens[i-1].type != tok!"comment" && tokens[i-1].type != tok!"{") @@ -171,6 +171,11 @@ private: writeToken(); if (i >= tokens.length-1) newline(); + else if (tokens[i+1].line-1 > tokens[i].line) + { + newline(); + newline(); + } else if (tokens[i+1].line > tokens[i].line) newline(); else if (tokens[i+1].type != tok!"{") @@ -192,6 +197,8 @@ private: { writeToken(); tempIndent = 0; + if (current.type == tok!"comment") + break; if (!(t == tok!"import" && current.type == tok!"import")) write("\n"); newline(); @@ -226,7 +233,8 @@ private: else if (current.type == tok!"return") { writeToken(); - write(" "); + if (current.type != tok!";") + write(" "); } else if (current.type == tok!"switch") formatSwitch(); @@ -310,17 +318,6 @@ private: case tok!"(": writeParens(true); break; - case tok!":": - if (!assumeSorted(astInformation.ternaryColonLocations) - .equalRange(current.index).empty) - { - write(" "); - writeToken(); - write(" "); - } - else - writeToken(); - break; case tok!"@": case tok!"!": case tok!"...": @@ -330,6 +327,10 @@ private: case tok!"$": writeToken(); break; + case tok!":": + write(" : "); + index += 1; + break; case tok!"]": writeToken(); if (current.type == tok!"identifier") @@ -340,6 +341,8 @@ private: writeToken(); if (current.type != tok!"comment") newline(); + if (peekImplementation(tok!"class",0)) + newline(); break; case tok!"{": writeBraces(); @@ -538,7 +541,8 @@ private: else if (current.type == tok!")") { if (peekIs(tok!"identifier") || (index + 1 < tokens.length - && isKeyword(tokens[index + 1].type))) + && (isKeyword(tokens[index+1].type) + || tokens[index+1].type == tok!"@"))) { writeToken(); if (space_afterwards) @@ -807,9 +811,6 @@ struct ASTInformation /// Locations of unary operators size_t[] unaryLocations; - - /// Locations of ':' operators in ternary expressions - size_t[] ternaryColonLocations; } /// Collects information from the AST that is useful for the formatter @@ -882,13 +883,6 @@ final class FormatVisitor : ASTVisitor unary.accept(this); } - override void visit(const TernaryExpression ternary) - { - if (ternary.colon.type != tok!"") - astInformation.ternaryColonLocations ~= ternary.colon.index; - ternary.accept(this); - } - private: ASTInformation* astInformation; alias visit = ASTVisitor.visit; diff --git a/tests/DeclSpacing.d b/tests/DeclSpacing.d new file mode 100644 index 0000000..a3af881 --- /dev/null +++ b/tests/DeclSpacing.d @@ -0,0 +1,6 @@ +import std.stdio; +class Foo {} +import std.conv; +void main() {return;} +const baz = 11; +class Foo2:Foo {} diff --git a/tests/DeclSpacing.d.ref b/tests/DeclSpacing.d.ref new file mode 100644 index 0000000..7383c47 --- /dev/null +++ b/tests/DeclSpacing.d.ref @@ -0,0 +1,18 @@ +import std.stdio; + +class Foo +{ +} + +import std.conv; + +void main() +{ + return; +} + +const baz = 11; + +class Foo2 : Foo +{ +} diff --git a/tests/catchExceptionNested.d b/tests/catchExceptionNested.d new file mode 100644 index 0000000..bddfd10 --- /dev/null +++ b/tests/catchExceptionNested.d @@ -0,0 +1,31 @@ +class U0 : Exception { + this() @safe pure nothrow { super("U0 error message"); } +} + +class U1 : Exception { + this() @safe pure nothrow { super("U1 error message"); } +} + +void foo() { + import std.stdio; + + foreach (immutable i; 0 .. 2) { + try { + i.bar; + } catch (U0) { + "Function foo caught exception U0".writeln; + } + } +} + +void bar(in int i) @safe pure { + i.baz; +} + +void baz(in int i) @safe pure { + throw i ? new U1 : new U0; +} + +void main() { + foo; +} diff --git a/tests/catchExceptionNested.d.ref b/tests/catchExceptionNested.d.ref new file mode 100644 index 0000000..22d8d26 --- /dev/null +++ b/tests/catchExceptionNested.d.ref @@ -0,0 +1,49 @@ +class U0 : Exception +{ + this() @safe pure nothrow + { + super("U0 error message"); + } + +} + +class U1 : Exception +{ + this() @safe pure nothrow + { + super("U1 error message"); + } + +} + +void foo() +{ + import std.stdio; + + foreach (immutable i; 0 .. 2) + { + try + { + i.bar; + } + catch(U0) + { + "Function foo caught exception U0".writeln; + } + } +} + +void bar(in int i) @safe pure +{ + i.baz; +} + +void baz(in int i) @safe pure +{ + throw i ? new U1 : new U0; +} + +void main() +{ + foo; +} diff --git a/tests/heronian.d b/tests/heronian.d deleted file mode 100644 index ffe6334..0000000 --- a/tests/heronian.d +++ /dev/null @@ -1,45 +0,0 @@ -import std.stdio, std.math, std.range, std.algorithm, std.numeric, std.traits, std.typecons; - -double hero(in uint a, in uint b, in uint c) pure nothrow @safe @nogc { - immutable s = (a + b + c) / 2.0; - immutable a2 = s * (s - a) * (s - b) * (s - c); - return (a2 > 0) ? a2.sqrt : 0.0; -} - -bool isHeronian(in uint a, in uint b, in uint c) pure nothrow @safe @nogc { - immutable h = hero(a, b, c); - return h > 0 && h.floor == h.ceil; -} - -T gcd3(T)(in T x, in T y, in T z) pure nothrow @safe @nogc { - return gcd(gcd(x, y), z); -} - -void main() /*@safe*/ { - enum uint maxSide = 200; - - // Sort by increasing area, perimeter, then sides. - //auto h = cartesianProduct!3(iota(1, maxSide + 1)) - auto r = iota(1, maxSide + 1); - const h = cartesianProduct(r, r, r) - //.filter!({a, b, c} => ... - .filter!(t => t[0] <= t[1] && t[1] <= t[2] && - t[0] + t[1] > t[2] && - t[].gcd3 == 1 && t[].isHeronian) - .array - .schwartzSort!(t => tuple(t[].hero, t[].only.sum, t.reverse)) - .release; - - static void showTriangles(R)(R ts) @safe { - "Area Perimeter Sides".writeln; - foreach (immutable t; ts) - writefln("%3s %8d %3dx%dx%d", t[].hero, t[].only.sum, t[]); - } - - writefln("Primitive Heronian triangles with sides up to %d: %d", maxSide, h.length); - "\nFirst ten when ordered by increasing area, then perimeter,then maximum sides:".writeln; - showTriangles(h.take(10)); - - "\nAll with area 210 subject to the previous ordering:".writeln; - showTriangles(h.filter!(t => t[].hero == 210)); -} diff --git a/tests/heronian.d.ref b/tests/heronian.d.ref deleted file mode 100644 index 14d84c9..0000000 --- a/tests/heronian.d.ref +++ /dev/null @@ -1,48 +0,0 @@ -import std.stdio, std.math, std.range, std.algorithm, std.numeric, std.traits, - std.typecons; - -double hero(in uint a, in uint b, in uint c) pure nothrow @safe @nogc -{ - immutable s = (a + b + c) / 2.0; - immutable a2 = s * (s - a) * (s - b) * (s - c); - return (a2 > 0) ? a2.sqrt : 0.0; -} - -bool isHeronian(in uint a, in uint b, in uint c) pure nothrow @safe @nogc -{ - immutable h = hero(a, b, c); - return h > 0 && h.floor == h.ceil; -} - -T gcd3(T)(in T x, in T y, in T z) pure nothrow @safe @nogc -{ - return gcd(gcd(x, y), z); -} - -void main() /*@safe*/ -{ - enum uint maxSide = 200; - // Sort by increasing area, perimeter, then sides. - //auto h = cartesianProduct!3(iota(1, maxSide + 1)) - auto r = iota(1, maxSide + 1); - const h = cartesianProduct(r, r, r) - //.filter!({a, b, c} => ... - .filter!(t => t[0] <= t[1] && t[1] <= t[2] && t[0] + t[1] > t[2] && - t[].gcd3 == 1 && t[].isHeronian) - .array.schwartzSort!(t => tuple(t[].hero, t[].only.sum, t.reverse)) - .release; - - static void showTriangles(R)(R ts) @safe - { - "Area Perimeter Sides".writeln; - foreach (immutable t; ts) - writefln("%3s %8d %3dx%dx%d", t[].hero, t[].only.sum, t[]); - } - - writefln("Primitive Heronian triangles with sides up to %d: %d", maxSide, h.length); - "\nFirst ten when ordered by increasing area, then perimeter,then maximum sides:" - .writeln; - showTriangles(h.take(10)); - "\nAll with area 210 subject to the previous ordering:".writeln; - showTriangles(h.filter!(t => t[].hero == 210)); -} diff --git a/tests/swap.d b/tests/swap.d new file mode 100644 index 0000000..d5ee7d3 --- /dev/null +++ b/tests/swap.d @@ -0,0 +1,24 @@ +import std.algorithm: swap; // from Phobos standard library + +// The D solution uses templates and it's similar to the C++ one: +void mySwap(T)(ref T left, ref T right) { + auto temp = left; + left = right; + right = temp; +} + +void main() { + import std.stdio; + + int[] a = [10, 20]; + writeln(a); + + // The std.algorithm standard library module + // contains a generic swap: + swap(a[0], a[1]); + writeln(a); + + // Using mySwap: + mySwap(a[0], a[1]); + writeln(a); +} diff --git a/tests/swap.d.ref b/tests/swap.d.ref new file mode 100644 index 0000000..a5176e3 --- /dev/null +++ b/tests/swap.d.ref @@ -0,0 +1,24 @@ +import std.algorithm : swap; // from Phobos standard library + +// The D solution uses templates and it's similar to the C++ one: +void mySwap(T)(ref T left, ref T right) +{ + auto temp = left; + left = right; + right = temp; +} + +void main() +{ + import std.stdio; + + int[] a = [10, 20]; + writeln(a); + // The std.algorithm standard library module + // contains a generic swap: + swap(a[0], a[1]); + writeln(a); + // Using mySwap: + mySwap(a[0], a[1]); + writeln(a); +} diff --git a/tests/test.sh b/tests/test.sh index ea46ff2..463159f 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -4,5 +4,5 @@ set -e for source in *.d do ../bin/dfmt "${source}" >"${source}.out" - diff -u "${source}.ref" "${source}.out" || echo "fail ${source}" + diff -u "${source}.ref" "${source}.out" done