diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-02-22 23:25:12 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-02-22 23:25:12 -0700 |
| commit | 1e3a200ba604c8d19fcc1119d01c2e80f2a8beca (patch) | |
| tree | b4044c94ee618ffb72f33cbafb83e4c482a4d509 /lib/std | |
| parent | 1253903fef07d7fd0435310f474bfe2745b41405 (diff) | |
| download | zig-1e3a200ba604c8d19fcc1119d01c2e80f2a8beca.tar.gz zig-1e3a200ba604c8d19fcc1119d01c2e80f2a8beca.zip | |
zig fmt: array literal with hint
This regresses the test case of `zig fmt` deleting empty line comments.
Two open questions here:
* What should the rules be about deleting empty line comments?
It makes sense usually, but for array initization, empty line
comments cause a line break, affecting the row/column alignment.
Perhaps we should therefore respect all empty line comments?
Or should we special case array initializations?
* If we decide to special case some kinds of line comments to respect
them (which is status quo!), how should that be implemented?
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/zig/parser_test.zig | 416 | ||||
| -rw-r--r-- | lib/std/zig/render.zig | 55 |
2 files changed, 230 insertions, 241 deletions
diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 4aa6d95b30..27e49b4c01 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -1655,112 +1655,110 @@ test "zig fmt: struct literal containing a multiline expression" { ); } -//test "zig fmt: array literal with hint" { -// try testTransform( -// \\const a = []u8{ -// \\ 1, 2, // -// \\ 3, -// \\ 4, -// \\ 5, -// \\ 6, -// \\ 7 }; -// \\const a = []u8{ -// \\ 1, 2, // -// \\ 3, -// \\ 4, -// \\ 5, -// \\ 6, -// \\ 7, 8 }; -// \\const a = []u8{ -// \\ 1, 2, // -// \\ 3, -// \\ 4, -// \\ 5, -// \\ 6, // blah -// \\ 7, 8 }; -// \\const a = []u8{ -// \\ 1, 2, // -// \\ 3, // -// \\ 4, -// \\ 5, -// \\ 6, -// \\ 7 }; -// \\const a = []u8{ -// \\ 1, -// \\ 2, -// \\ 3, 4, // -// \\ 5, 6, // -// \\ 7, 8, // -// \\}; -// , -// \\const a = []u8{ -// \\ 1, 2, -// \\ 3, 4, -// \\ 5, 6, -// \\ 7, -// \\}; -// \\const a = []u8{ -// \\ 1, 2, -// \\ 3, 4, -// \\ 5, 6, -// \\ 7, 8, -// \\}; -// \\const a = []u8{ -// \\ 1, 2, -// \\ 3, 4, -// \\ 5, -// \\ 6, // blah -// \\ 7, -// \\ 8, -// \\}; -// \\const a = []u8{ -// \\ 1, 2, -// \\ 3, // -// \\ 4, -// \\ 5, 6, -// \\ 7, -// \\}; -// \\const a = []u8{ -// \\ 1, -// \\ 2, -// \\ 3, -// \\ 4, -// \\ 5, -// \\ 6, -// \\ 7, -// \\ 8, -// \\}; -// \\ -// ); -//} -// -//test "zig fmt: array literal veritical column alignment" { -// try testTransform( -// \\const a = []u8{ -// \\ 1000, 200, -// \\ 30, 4, -// \\ 50000, 60 -// \\}; -// \\const a = []u8{0, 1, 2, 3, 40, -// \\ 4,5,600,7, -// \\ 80, -// \\ 9, 10, 11, 0, 13, 14, 15}; -// \\ -// , -// \\const a = []u8{ -// \\ 1000, 200, -// \\ 30, 4, -// \\ 50000, 60, -// \\}; -// \\const a = []u8{ -// \\ 0, 1, 2, 3, 40, -// \\ 4, 5, 600, 7, 80, -// \\ 9, 10, 11, 0, 13, -// \\ 14, 15, -// \\}; -// \\ -// ); -//} +test "zig fmt: array literal with hint" { + try testTransform( + \\const a = []u8{ + \\ 1, 2, // + \\ 3, + \\ 4, + \\ 5, + \\ 6, + \\ 7 }; + \\const a = []u8{ + \\ 1, 2, // + \\ 3, + \\ 4, + \\ 5, + \\ 6, + \\ 7, 8 }; + \\const a = []u8{ + \\ 1, 2, // + \\ 3, + \\ 4, + \\ 5, + \\ 6, // blah + \\ 7, 8 }; + \\const a = []u8{ + \\ 1, 2, // + \\ 3, // + \\ 4, + \\ 5, + \\ 6, + \\ 7 }; + \\const a = []u8{ + \\ 1, + \\ 2, + \\ 3, 4, // + \\ 5, 6, // + \\ 7, 8, // + \\}; + , + \\const a = []u8{ + \\ 1, 2, // + \\ 3, 4, + \\ 5, 6, + \\ 7, + \\}; + \\const a = []u8{ + \\ 1, 2, // + \\ 3, 4, + \\ 5, 6, + \\ 7, 8, + \\}; + \\const a = []u8{ + \\ 1, 2, // + \\ 3, 4, + \\ 5, + \\ 6, // blah + \\ 7, + \\ 8, + \\}; + \\const a = []u8{ + \\ 1, 2, // + \\ 3, // + \\ 4, + \\ 5, + \\ 6, + \\ 7, + \\}; + \\const a = []u8{ + \\ 1, + \\ 2, + \\ 3, 4, // + \\ 5, 6, // + \\ 7, 8, // + \\}; + \\ + ); +} + +test "zig fmt: array literal veritical column alignment" { + try testTransform( + \\const a = []u8{ + \\ 1000, 200, + \\ 30, 4, + \\ 50000, 60 + \\}; + \\const a = []u8{0, 1, 2, 3, 40, + \\ 4,5,600,7, + \\ 80, + \\ 9, 10, 11, 0, 13, 14, 15}; + \\ + , + \\const a = []u8{ + \\ 1000, 200, + \\ 30, 4, + \\ 50000, 60, + \\}; + \\const a = []u8{ + \\ 0, 1, 2, 3, 40, + \\ 4, 5, 600, 7, 80, + \\ 9, 10, 11, 0, 13, + \\ 14, 15, + \\}; + \\ + ); +} test "zig fmt: multiline string with backslash at end of line" { try testCanonical( @@ -1949,29 +1947,29 @@ test "zig fmt: slice align" { ); } -//test "zig fmt: add trailing comma to array literal" { -// try testTransform( -// \\comptime { -// \\ return []u16{'m', 's', 'y', 's', '-' // hi -// \\ }; -// \\ return []u16{'m', 's', 'y', 's', -// \\ '-'}; -// \\ return []u16{'m', 's', 'y', 's', '-'}; -// \\} -// , -// \\comptime { -// \\ return []u16{ -// \\ 'm', 's', 'y', 's', '-', // hi -// \\ }; -// \\ return []u16{ -// \\ 'm', 's', 'y', 's', -// \\ '-', -// \\ }; -// \\ return []u16{ 'm', 's', 'y', 's', '-' }; -// \\} -// \\ -// ); -//} +test "zig fmt: add trailing comma to array literal" { + try testTransform( + \\comptime { + \\ return []u16{'m', 's', 'y', 's', '-' // hi + \\ }; + \\ return []u16{'m', 's', 'y', 's', + \\ '-'}; + \\ return []u16{'m', 's', 'y', 's', '-'}; + \\} + , + \\comptime { + \\ return []u16{ + \\ 'm', 's', 'y', 's', '-', // hi + \\ }; + \\ return []u16{ + \\ 'm', 's', 'y', 's', + \\ '-', + \\ }; + \\ return []u16{ 'm', 's', 'y', 's', '-' }; + \\} + \\ + ); +} test "zig fmt: first thing in file is line comment" { try testCanonical( @@ -3406,30 +3404,30 @@ test "zig fmt: comptime block in container" { // ); //} -//test "zig fmt: multiline string in array" { -// try testCanonical( -// \\const Foo = [][]const u8{ -// \\ \\aaa -// \\ , -// \\ \\bbb -// \\}; -// \\ -// \\fn bar() void { -// \\ const Foo = [][]const u8{ -// \\ \\aaa -// \\ , -// \\ \\bbb -// \\ }; -// \\ const Bar = [][]const u8{ // comment here -// \\ \\aaa -// \\ \\ -// \\ , // and another comment can go here -// \\ \\bbb -// \\ }; -// \\} -// \\ -// ); -//} +test "zig fmt: multiline string in array" { + try testCanonical( + \\const Foo = [][]const u8{ + \\ \\aaa + \\ , + \\ \\bbb + \\}; + \\ + \\fn bar() void { + \\ const Foo = [][]const u8{ + \\ \\aaa + \\ , + \\ \\bbb + \\ }; + \\ const Bar = [][]const u8{ // comment here + \\ \\aaa + \\ \\ + \\ , // and another comment can go here + \\ \\bbb + \\ }; + \\} + \\ + ); +} test "zig fmt: if type expr" { try testCanonical( @@ -3449,19 +3447,21 @@ test "zig fmt: file ends with struct field" { ); } -test "zig fmt: comment after empty comment" { - try testTransform( - \\const x = true; // - \\// - \\// - \\//a - \\ - , - \\const x = true; - \\//a - \\ - ); -} +// TODO intentionally change the behavior of this case? +// for array literals we necessarily have meaningful empty comments +//test "zig fmt: comment after empty comment" { +// try testTransform( +// \\const x = true; // +// \\// +// \\// +// \\//a +// \\ +// , +// \\const x = true; +// \\//a +// \\ +// ); +//} //test "zig fmt: line comment in array" { // try testTransform( @@ -3493,7 +3493,7 @@ test "zig fmt: comment after empty comment" { // \\ // ); //} -// + //test "zig fmt: comment after params" { // try testTransform( // \\fn a( @@ -3518,7 +3518,7 @@ test "zig fmt: comment after empty comment" { // \\ // ); //} -// + //test "zig fmt: comment in array initializer/access" { // try testCanonical( // \\test "a" { @@ -3550,7 +3550,7 @@ test "zig fmt: comment after empty comment" { // \\ // ); //} -// + //test "zig fmt: comments at several places in struct init" { // try testTransform( // \\var bar = Bar{ @@ -3899,44 +3899,44 @@ test "zig fmt: regression test for #5722" { ); } -//test "zig fmt: allow trailing line comments to do manual array formatting" { -// try testCanonical( -// \\fn foo() void { -// \\ self.code.appendSliceAssumeCapacity(&[_]u8{ -// \\ 0x55, // push rbp -// \\ 0x48, 0x89, 0xe5, // mov rbp, rsp -// \\ 0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc) -// \\ }); -// \\ -// \\ di_buf.appendAssumeCapacity(&[_]u8{ -// \\ 1, DW.TAG_compile_unit, DW.CHILDREN_no, // header -// \\ DW.AT_stmt_list, DW_FORM_data4, // form value pairs -// \\ DW.AT_low_pc, DW_FORM_addr, -// \\ DW.AT_high_pc, DW_FORM_addr, -// \\ DW.AT_name, DW_FORM_strp, -// \\ DW.AT_comp_dir, DW_FORM_strp, -// \\ DW.AT_producer, DW_FORM_strp, -// \\ DW.AT_language, DW_FORM_data2, -// \\ 0, 0, // sentinel -// \\ }); -// \\ -// \\ self.code.appendSliceAssumeCapacity(&[_]u8{ -// \\ 0x55, // push rbp -// \\ 0x48, 0x89, 0xe5, // mov rbp, rsp -// \\ // How do we handle this? -// \\ //0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc) -// \\ // Here's a blank line, should that be allowed? -// \\ -// \\ 0x48, 0x89, 0xe5, -// \\ 0x33, 0x45, -// \\ // Now the comment breaks a single line -- how do we handle this? -// \\ 0x88, -// \\ }); -// \\} -// \\ -// ); -//} -// +test "zig fmt: allow trailing line comments to do manual array formatting" { + try testCanonical( + \\fn foo() void { + \\ self.code.appendSliceAssumeCapacity(&[_]u8{ + \\ 0x55, // push rbp + \\ 0x48, 0x89, 0xe5, // mov rbp, rsp + \\ 0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc) + \\ }); + \\ + \\ di_buf.appendAssumeCapacity(&[_]u8{ + \\ 1, DW.TAG_compile_unit, DW.CHILDREN_no, // header + \\ DW.AT_stmt_list, DW_FORM_data4, // form value pairs + \\ DW.AT_low_pc, DW_FORM_addr, + \\ DW.AT_high_pc, DW_FORM_addr, + \\ DW.AT_name, DW_FORM_strp, + \\ DW.AT_comp_dir, DW_FORM_strp, + \\ DW.AT_producer, DW_FORM_strp, + \\ DW.AT_language, DW_FORM_data2, + \\ 0, 0, // sentinel + \\ }); + \\ + \\ self.code.appendSliceAssumeCapacity(&[_]u8{ + \\ 0x55, // push rbp + \\ 0x48, 0x89, 0xe5, // mov rbp, rsp + \\ // How do we handle this? + \\ //0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc) + \\ // Here's a blank line, should that be allowed? + \\ + \\ 0x48, 0x89, 0xe5, + \\ 0x33, 0x45, + \\ // Now the comment breaks a single line -- how do we handle this? + \\ 0x88, + \\ }); + \\} + \\ + ); +} + //test "zig fmt: multiline string literals should play nice with array initializers" { // try testCanonical( // \\fn main() void { @@ -3999,7 +3999,7 @@ test "zig fmt: regression test for #5722" { // \\ // ); //} -// + //test "zig fmt: use of comments and Multiline string literals may force the parameters over multiple lines" { // try testCanonical( // \\pub fn makeMemUndefined(qzz: []u8) i1 { diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 9dc35aa9d8..0a1b6c19c0 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -1640,7 +1640,11 @@ fn renderArrayInit( const last_elem = array_init.ast.elements[array_init.ast.elements.len - 1]; const last_elem_token = tree.lastToken(last_elem); const trailing_comma = token_tags[last_elem_token + 1] == .comma; - if (!trailing_comma) { + const rbrace = if (trailing_comma) last_elem_token + 2 else last_elem_token + 1; + assert(token_tags[rbrace] == .r_brace); + const contains_newlines = !tree.tokensOnSameLine(array_init.ast.lbrace, rbrace); + + if (!trailing_comma and !contains_newlines) { // Render all on one line, no trailing comma. if (array_init.ast.elements.len == 1) { // If there is only one element, we don't use spaces @@ -1658,8 +1662,6 @@ fn renderArrayInit( ais.pushIndentNextLine(); try renderToken(ais, tree, array_init.ast.lbrace, .newline); - const rbrace = last_elem_token + 2; - assert(token_tags[rbrace] == .r_brace); var expr_index: usize = 0; while (rowSize(tree, array_init.ast.elements[expr_index..], rbrace)) |row_size| { @@ -1673,28 +1675,31 @@ fn renderArrayInit( defer gpa.free(expr_newlines); mem.set(bool, expr_newlines, false); - const expr_widths = widths[0 .. widths.len - row_size]; - const column_widths = widths[widths.len - row_size ..]; + const expr_widths = widths[0..row_exprs.len]; + const column_widths = widths[row_exprs.len..]; - // Find next row with trailing comment (if any) to end the current section + // Find next row with trailing comment (if any) to end the current section. const section_end = sec_end: { var this_line_first_expr: usize = 0; var this_line_size = rowSize(tree, row_exprs, rbrace); for (row_exprs) |expr, i| { - // Ignore comment on first line of this section - if (i == 0 or tree.tokensOnSameLine(tree.firstToken(row_exprs[0]), tree.lastToken(expr))) continue; - // Track start of line containing comment - if (!tree.tokensOnSameLine(tree.firstToken(row_exprs[this_line_first_expr]), tree.lastToken(expr))) { + // Ignore comment on first line of this section. + if (i == 0) continue; + const expr_last_token = tree.lastToken(expr); + if (tree.tokensOnSameLine(tree.firstToken(row_exprs[0]), expr_last_token)) + continue; + // Track start of line containing comment. + if (!tree.tokensOnSameLine(tree.firstToken(row_exprs[this_line_first_expr]), expr_last_token)) { this_line_first_expr = i; this_line_size = rowSize(tree, row_exprs[this_line_first_expr..], rbrace); } - const maybe_comma = tree.lastToken(expr) + 1; + const maybe_comma = expr_last_token + 1; if (token_tags[maybe_comma] == .comma) { const after_comma_src = tree.source[token_starts[maybe_comma]..token_starts[maybe_comma + 1]]; - const same_line_comment = for (after_comma_src) |byte| switch (byte) { + for (after_comma_src) |byte| switch (byte) { '\n' => break, - '/' => break :sec_end i - this_line_size.? + 1, // Found row ending in comment + '/' => break :sec_end i - this_line_size.? + 1, else => continue, }; } @@ -1754,7 +1759,7 @@ fn renderArrayInit( } } - // Render exprs in current section + // Render exprs in current section. column_counter = 0; var last_col_index: usize = row_size - 1; for (section_exprs) |expr, i| { @@ -1785,19 +1790,12 @@ fn renderArrayInit( try renderToken(ais, tree, comma, .newline); // , try renderExtraNewline(ais, tree, next_expr); } else { - const maybe_comma = tree.lastToken(expr) + 1; - if (token_tags[maybe_comma] == .comma) { - try renderExpression(gpa, ais, tree, expr, .none); // , - try renderToken(ais, tree, maybe_comma, .newline); // , - } else { - try renderExpression(gpa, ais, tree, expr, .comma); // , - } + try renderExpression(gpa, ais, tree, expr, .comma); // , } } - if (expr_index == array_init.ast.elements.len) { + if (expr_index == array_init.ast.elements.len) break; - } } ais.popIndent(); @@ -2175,7 +2173,6 @@ fn renderToken(ais: *Ais, tree: ast.Tree, token_index: ast.TokenIndex, space: Sp /// that end is the last byte before the next token. fn renderComments(ais: *Ais, tree: ast.Tree, start: usize, end: usize) Error!bool { var index: usize = start; - var rendered_empty_comments = false; while (mem.indexOf(u8, tree.source[index..end], "//")) |offset| { const comment_start = index + offset; @@ -2196,11 +2193,6 @@ fn renderComments(ais: *Ais, tree: ast.Tree, start: usize, end: usize) Error!boo // Respect the newline directly before the comment. // Note: This allows an empty line between comments try ais.insertNewline(); - } else if (trimmed_comment.len == 2) { - if (!rendered_empty_comments) { - try ais.writer().writeByte('\n'); - rendered_empty_comments = true; - } } else if (index == start) { // Otherwise if the first comment is on the same line as // the token before it, prefix it with a single space. @@ -2208,10 +2200,7 @@ fn renderComments(ais: *Ais, tree: ast.Tree, start: usize, end: usize) Error!boo } } - if (trimmed_comment.len != 2) { - try ais.writer().print("{s}\n", .{trimmed_comment}); - rendered_empty_comments = false; - } + try ais.writer().print("{s}\n", .{trimmed_comment}); index = 1 + (newline orelse return true); if (ais.disabled_offset) |disabled_offset| { |
