diff --git a/verilog/formatting/formatter_test.cc b/verilog/formatting/formatter_test.cc index a7b82dd1b..e2c687c7e 100644 --- a/verilog/formatting/formatter_test.cc +++ b/verilog/formatting/formatter_test.cc @@ -8996,6 +8996,796 @@ static constexpr FormatterTestCase kFormatterTestCases[] = { "assign a = (b) ?\n" " '{c: d[e], f: '1}\n" " : g;\n"}, + + // ----------------------------------------------------------------- + // Comments around `else`. + // Check whether `else` partition is found correctly and that actual code is + // not appended to EOL comments. + + // generate if + + {"module zx;\n" + "if (x) assign z=y;\n" + "// eol-c\n" + "else if (r) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " // eol-c\n" + " else if (r) assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + {"module zx;\n" + "if (x) assign z=y;\n" + "// eol-c\n" + "// eol-c\n" + "else if (r) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " // eol-c\n" + " // eol-c\n" + " else if (r) assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + {"module zx;\n" + "if (x) assign z=y;\n" + "else // eol-c\n" + "if (r) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " else // eol-c\n" + " if (r) assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + {"module zx;\n" + "if (x) assign z=y;\n" + "else\n" + "// eol-c\n" + "if (r) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " else\n" + " // eol-c\n" + " if (r)\n" + " assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + {"module zx;\n" + "if (x) assign z=y;\n" + "// eol-c\n" + "else // eol-c\n" + "if (r) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " // eol-c\n" + " else // eol-c\n" + " if (r) assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + {"module zx;\n" + "if (x) assign z=y;\n" + "else // eol-c\n" + "// eol-c\n" + "if (r) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " else // eol-c\n" + " // eol-c\n" + " if (r)\n" + " assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + {"module zx;\n" + "if (x) assign z=y;\n" + "// eol-c\n" + "else // eol-c\n" + "// eol-c\n" + "if (r) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " // eol-c\n" + " else // eol-c\n" + " // eol-c\n" + " if (r)\n" + " assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + {"module zx;\n" + "if (x) assign z=y;\n" + "// eol-c\n" + "else // eol-c\n" + "// eol-c\n" + "if\n" + "// eol-c\n" + "(r) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " // eol-c\n" + " else // eol-c\n" + " // eol-c\n" + " if\n" + " // eol-c\n" + " (r)\n" + " assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + {"module zx;\n" + "if (x) assign z=y;\n" + "// eol-c\n" + "// eol-c\n" + "else // eol-c\n" + "// eol-c\n" + "// eol-c\n" + "if\n" + "// eol-c\n" + "// eol-c\n" + "(r) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " // eol-c\n" + " // eol-c\n" + " else // eol-c\n" + " // eol-c\n" + " // eol-c\n" + " if\n" + " // eol-c\n" + " // eol-c\n" + " (r)\n" + " assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + + // generate if with function call + + {"module zx;\n" + "if (x) assign z=y;\n" + "// eol-c\n" + "else if (foo(x) == bar(1, 2)) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " // eol-c\n" + " else if (foo(x) == bar(1, 2))\n" + " assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + {"module zx;\n" + "if (x) assign z=y;\n" + "// eol-c\n" + "// eol-c\n" + "else if (foo(x) == bar(1, 2)) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " // eol-c\n" + " // eol-c\n" + " else if (foo(x) == bar(1, 2))\n" + " assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + {"module zx;\n" + "if (x) assign z=y;\n" + "else // eol-c\n" + "if (foo(x) == bar(1, 2)) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " else // eol-c\n" + " if (foo(x) == bar(1, 2)) assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + {"module zx;\n" + "if (x) assign z=y;\n" + "else\n" + "// eol-c\n" + "if (foo(x) == bar(1, 2)) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " else\n" + " // eol-c\n" + " if (foo(\n" + " x\n" + " ) == bar(\n" + " 1, 2\n" + " ))\n" + " assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + {"module zx;\n" + "if (x) assign z=y;\n" + "// eol-c\n" + "else // eol-c\n" + "if (foo(x) == bar(1, 2)) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " // eol-c\n" + " else // eol-c\n" + " if (foo(x) == bar(1, 2)) assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + {"module zx;\n" + "if (x) assign z=y;\n" + "else // eol-c\n" + "// eol-c\n" + "if (foo(x) == bar(1, 2)) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " else // eol-c\n" + " // eol-c\n" + " if (foo(\n" + " x\n" + " ) == bar(\n" + " 1, 2\n" + " ))\n" + " assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + {"module zx;\n" + "if (x) assign z=y;\n" + "// eol-c\n" + "else // eol-c\n" + "// eol-c\n" + "if (foo(x) == bar(1, 2)) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " // eol-c\n" + " else // eol-c\n" + " // eol-c\n" + " if (foo(\n" + " x\n" + " ) == bar(\n" + " 1, 2\n" + " ))\n" + " assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + {"module zx;\n" + "if (x) assign z=y;\n" + "// eol-c\n" + "else // eol-c\n" + "// eol-c\n" + "if\n" + "// eol-c\n" + "(foo(x) == bar(1, 2)) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " // eol-c\n" + " else // eol-c\n" + " // eol-c\n" + " if\n" + " // eol-c\n" + " (foo(\n" + " x\n" + " ) == bar(\n" + " 1, 2\n" + " ))\n" + " assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + {"module zx;\n" + "if (x) assign z=y;\n" + "// eol-c\n" + "// eol-c\n" + "else // eol-c\n" + "// eol-c\n" + "// eol-c\n" + "if\n" + "// eol-c\n" + "// eol-c\n" + "(foo(x) == bar(1, 2)) assign z=w;\n" + "else assign x=y;\n" + "endmodule\n", + "module zx;\n" + " if (x) assign z = y;\n" + " // eol-c\n" + " // eol-c\n" + " else // eol-c\n" + " // eol-c\n" + " // eol-c\n" + " if\n" + " // eol-c\n" + " // eol-c\n" + " (foo(\n" + " x\n" + " ) == bar(\n" + " 1, 2\n" + " ))\n" + " assign z = w;\n" + " else assign x = y;\n" + "endmodule\n"}, + + // else begin + + {"module zx;\n" + "always begin\n" + "if (a) b<=1;\n" + "// eol-c\n" + "else begin b<=2;\n" + "end\n" + "end\n" + "endmodule\n", + "module zx;\n" + " always begin\n" + " if (a) b <= 1;\n" + " // eol-c\n" + " else begin\n" + " b <= 2;\n" + " end\n" + " end\n" + "endmodule\n"}, + {"module zx;\n" + "always begin\n" + "if (a) b<=1;\n" + "// eol-c\n" + "// eol-c\n" + "else begin b<=2;\n" + "end\n" + "end\n" + "endmodule\n", + "module zx;\n" + " always begin\n" + " if (a) b <= 1;\n" + " // eol-c\n" + " // eol-c\n" + " else begin\n" + " b <= 2;\n" + " end\n" + " end\n" + "endmodule\n"}, + {"module zx;\n" + "always begin\n" + "if (a) b<=1;\n" + "else // eol-c\n" + "begin b<=2;\n" + "end\n" + "end\n" + "endmodule\n", + "module zx;\n" + " always begin\n" + " if (a) b <= 1;\n" + " else // eol-c\n" + " begin\n" + " b <= 2;\n" + " end\n" + " end\n" + "endmodule\n"}, + {"module zx;\n" + "always begin\n" + "if (a) b<=1;\n" + "else\n" + "// eol-c\n" + "begin b<=2;\n" + "end\n" + "end\n" + "endmodule\n", + "module zx;\n" + " always begin\n" + " if (a) b <= 1;\n" + " else\n" + " // eol-c\n" + " begin\n" + " b <= 2;\n" + " end\n" + " end\n" + "endmodule\n"}, + {"module zx;\n" + "always begin\n" + "if (a) b<=1;\n" + "// eol-c\n" + "else // eol-c\n" + "begin b<=2;\n" + "end\n" + "end\n" + "endmodule\n", + "module zx;\n" + " always begin\n" + " if (a) b <= 1;\n" + " // eol-c\n" + " else // eol-c\n" + " begin\n" + " b <= 2;\n" + " end\n" + " end\n" + "endmodule\n"}, + {"module zx;\n" + "always begin\n" + "if (a) b<=1;\n" + "else // eol-c\n" + "// eol-c\n" + "begin b<=2;\n" + "end\n" + "end\n" + "endmodule\n", + "module zx;\n" + " always begin\n" + " if (a) b <= 1;\n" + " else // eol-c\n" + " // eol-c\n" + " begin\n" + " b <= 2;\n" + " end\n" + " end\n" + "endmodule\n"}, + + // else if + + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "// eol-c\n" + "else if (set) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " // eol-c\n" + " else if (set) assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "// eol-c\n" + "// eol-c\n" + "else if (set) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " // eol-c\n" + " // eol-c\n" + " else if (set) assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "else // eol-c\n" + "if (set) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " else // eol-c\n" + " if (set) assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "else\n" + "// eol-c\n" + "if (set) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " else\n" + " // eol-c\n" + " if (set)\n" + " assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "// eol-c\n" + "else // eol-c\n" + "if (set) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " // eol-c\n" + " else // eol-c\n" + " if (set) assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "else // eol-c\n" + "// eol-c\n" + "if (set) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " else // eol-c\n" + " // eol-c\n" + " if (set)\n" + " assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "// eol-c\n" + "else // eol-c\n" + "// eol-c\n" + "if (set) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " // eol-c\n" + " else // eol-c\n" + " // eol-c\n" + " if (set)\n" + " assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "// eol-c\n" + "else // eol-c\n" + "// eol-c\n" + "if\n" + "// eol-c\n" + "(set) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " // eol-c\n" + " else // eol-c\n" + " // eol-c\n" + " if\n" + " // eol-c\n" + " (set)\n" + " assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "// eol-c\n" + "// eol-c\n" + "else // eol-c\n" + "// eol-c\n" + "// eol-c\n" + "if\n" + "// eol-c\n" + "// eol-c\n" + "(set) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " // eol-c\n" + " // eol-c\n" + " else // eol-c\n" + " // eol-c\n" + " // eol-c\n" + " if\n" + " // eol-c\n" + " // eol-c\n" + " (set)\n" + " assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + + // else if with function call + + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "// eol-c\n" + "else if (foo(clr, set, 1)) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " // eol-c\n" + " else if (foo(clr, set, 1))\n" + " assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "// eol-c\n" + "// eol-c\n" + "else if (foo(clr, set, 1)) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " // eol-c\n" + " // eol-c\n" + " else if (foo(clr, set, 1))\n" + " assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "else // eol-c\n" + "if (foo(clr, set, 1)) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " else // eol-c\n" + " if (foo(clr, set, 1)) assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "else\n" + "// eol-c\n" + "if (foo(clr, set, 1)) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " else\n" + " // eol-c\n" + " if (foo(\n" + " clr, set, 1\n" + " ))\n" + " assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "// eol-c\n" + "else // eol-c\n" + "if (foo(clr, set, 1)) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " // eol-c\n" + " else // eol-c\n" + " if (foo(clr, set, 1)) assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "else // eol-c\n" + "// eol-c\n" + "if (foo(clr, set, 1)) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " else // eol-c\n" + " // eol-c\n" + " if (foo(\n" + " clr, set, 1\n" + " ))\n" + " assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "// eol-c\n" + "else // eol-c\n" + "// eol-c\n" + "if (foo(clr, set, 1)) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " // eol-c\n" + " else // eol-c\n" + " // eol-c\n" + " if (foo(\n" + " clr, set, 1\n" + " ))\n" + " assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "// eol-c\n" + "else // eol-c\n" + "// eol-c\n" + "if\n" + "// eol-c\n" + "(foo(clr, set, 1)) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " // eol-c\n" + " else // eol-c\n" + " // eol-c\n" + " if\n" + " // eol-c\n" + " (foo(\n" + " clr, set, 1\n" + " ))\n" + " assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + {"module zx;\n" + "always @(clr or set)\n" + "if (clr) assign q=0;\n" + "// eol-c\n" + "// eol-c\n" + "else // eol-c\n" + "// eol-c\n" + "// eol-c\n" + "if\n" + "// eol-c\n" + "// eol-c\n" + "(foo(clr, set, 1)) assign q=1;\n" + "else deassign q;\n" + "endmodule\n", + "module zx;\n" + " always @(clr or set)\n" + " if (clr) assign q = 0;\n" + " // eol-c\n" + " // eol-c\n" + " else // eol-c\n" + " // eol-c\n" + " // eol-c\n" + " if\n" + " // eol-c\n" + " // eol-c\n" + " (foo(\n" + " clr, set, 1\n" + " ))\n" + " assign q = 1;\n" + " else deassign q;\n" + "endmodule\n"}, + + // ----------------------------------------------------------------- }; // Tests that formatter produces expected results, end-to-end. diff --git a/verilog/formatting/tree_unwrapper.cc b/verilog/formatting/tree_unwrapper.cc index 84d17a34b..aa56c97e0 100644 --- a/verilog/formatting/tree_unwrapper.cc +++ b/verilog/formatting/tree_unwrapper.cc @@ -1553,7 +1553,28 @@ static void ReshapeElseClause(const SyntaxTreeNode& node, // Then fuse 'else' and 'begin' partitions together // or fuse the 'else' and 'if' (header) partitions together - auto& else_partition = partition.Children().front(); + auto& children = partition.Children(); + auto else_partition_iter = std::find_if( + children.begin(), children.end(), [](const TokenPartitionTree& n) { + const auto* origin = n.Value().Origin(); + return origin && + origin->Tag() == verible::LeafTag(verilog_tokentype::TK_else); + }); + if (else_partition_iter == children.end()) return; + + auto& else_partition = *else_partition_iter; + auto* next_leaf = else_partition.NextLeaf(); + if (!next_leaf || PartitionIsForcedIntoNewLine(*next_leaf)) return; + + const auto* next_origin = next_leaf->Value().Origin(); + if (!next_origin || + !(next_origin->Tag() == verible::NodeTag(NodeEnum::kBegin) || + next_origin->Tag() == verible::LeafTag(verilog_tokentype::TK_begin) || + next_origin->Tag() == verible::NodeTag(NodeEnum::kIfHeader) || + next_origin->Tag() == verible::NodeTag(NodeEnum::kGenerateIfHeader) || + next_origin->Tag() == verible::LeafTag(verilog_tokentype::TK_if))) + return; + verible::MergeLeafIntoNextLeaf(&else_partition); } @@ -1967,14 +1988,20 @@ void TreeUnwrapper::ReshapeTokenPartitions( // after better handling of function calls inside expressions // e.g. kBinaryExpression, kUnaryPrefixExpression... if (partition.Children().size() > 1) { - auto& if_header_partition = partition.Children()[0]; - const auto original_indentation = - if_header_partition.Value().IndentationSpaces(); - // Adjust indentation recursively - verible::AdjustIndentationRelative(&partition, style.wrap_spaces); - // Restore original indentation in first partition - partition.Value().SetIndentationSpaces(original_indentation); - if_header_partition.Value().SetIndentationSpaces(original_indentation); + auto if_header_partition_iter = std::find_if( + partition.Children().begin(), partition.Children().end(), + [](const TokenPartitionTree& n) { + const auto* origin = n.Value().Origin(); + return origin && origin->Tag() == + verible::LeafTag(verilog_tokentype::TK_if); + }); + if (if_header_partition_iter == partition.Children().end()) break; + + // Adjust indentation of all partitions following if header recursively + for (auto& child : make_range(if_header_partition_iter + 1, + partition.Children().end())) { + verible::AdjustIndentationRelative(&child, style.wrap_spaces); + } } break; }