From a86bf3254aeea70112ae2e4a2570b19b832934ff Mon Sep 17 00:00:00 2001 From: Lukas Neubert Date: Sat, 20 Feb 2021 15:05:05 +0100 Subject: [PATCH] fmt: keep empty line between if statement and comment (#8846) --- vlib/v/fmt/comments.v | 15 +++++++++++---- vlib/v/fmt/fmt.v | 19 +++++++++++-------- vlib/v/fmt/tests/comments_expected.vv | 14 ++++++++++++++ vlib/v/fmt/tests/comments_input.vv | 16 ++++++++++++++++ vlib/v/fmt/tests/comments_keep.vv | 15 ++++++++++++--- 5 files changed, 64 insertions(+), 15 deletions(-) diff --git a/vlib/v/fmt/comments.v b/vlib/v/fmt/comments.v index b57c715bf7..da77004df7 100644 --- a/vlib/v/fmt/comments.v +++ b/vlib/v/fmt/comments.v @@ -15,11 +15,13 @@ enum CommentsLevel { // - inline: single-line comments will be on the same line as the last statement // - iembed: a /* ... */ embedded comment; used in expressions; // comments the whole line // - level: either .keep (don't indent), or .indent (increment indentation) +// - prev_line: the line number of the previous token struct CommentsOptions { - has_nl bool = true - inline bool - level CommentsLevel - iembed bool + has_nl bool = true + inline bool + level CommentsLevel + iembed bool + prev_line int = -1 } pub fn (mut f Fmt) comment(node ast.Comment, options CommentsOptions) { @@ -79,14 +81,19 @@ pub fn (mut f Fmt) comment(node ast.Comment, options CommentsOptions) { } pub fn (mut f Fmt) comments(comments []ast.Comment, options CommentsOptions) { + mut prev_line := options.prev_line for i, c in comments { if !f.out.last_n(1)[0].is_space() { f.write(' ') } + if options.prev_line > -1 && c.pos.line_nr > prev_line + 1 { + f.writeln('') + } f.comment(c, options) if !options.iembed && (i < comments.len - 1 || options.has_nl) { f.writeln('') } + prev_line = c.pos.last_line } } diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index a368c789bc..362d9aaf55 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -102,7 +102,7 @@ pub fn (mut f Fmt) write(s string) { } pub fn (mut f Fmt) writeln(s string) { - if f.indent > 0 && f.empty_line { + if f.indent > 0 && f.empty_line && s.len > 0 { f.write_indent() } f.out.writeln(s) @@ -1657,10 +1657,10 @@ pub fn (mut f Fmt) wrap_infix(start_pos int, start_len int, ignore_paren bool) { pub fn (mut f Fmt) if_expr(node ast.IfExpr) { dollar := if node.is_comptime { '$' } else { '' } - mut single_line := node.branches.len == 2 && node.has_else + mut is_ternary := node.branches.len == 2 && node.has_else && branch_is_single_line(node.branches[0]) && branch_is_single_line(node.branches[1]) && (node.is_expr || f.is_assign || f.is_struct_init || f.single_line_fields) - f.single_line_if = single_line + f.single_line_if = is_ternary start_pos := f.out.len start_len := f.line_len for { @@ -1693,20 +1693,20 @@ pub fn (mut f Fmt) if_expr(node ast.IfExpr) { } } f.write('{') - if single_line { + if is_ternary { f.write(' ') } else { f.writeln('') } f.stmts(branch.stmts) - if single_line { + if is_ternary { f.write(' ') } } // When a single line if is really long, write it again as multiline, // except it is part of an InfixExpr. - if single_line && f.line_len > fmt.max_len.last() && !f.buffering { - single_line = false + if is_ternary && f.line_len > fmt.max_len.last() && !f.buffering { + is_ternary = false f.single_line_if = false f.out.go_back_to(start_pos) f.line_len = start_len @@ -1719,7 +1719,10 @@ pub fn (mut f Fmt) if_expr(node ast.IfExpr) { f.single_line_if = false if node.post_comments.len > 0 { f.writeln('') - f.comments(node.post_comments, has_nl: false) + f.comments(node.post_comments, + has_nl: false + prev_line: node.branches.last().body_pos.last_line + ) } } diff --git a/vlib/v/fmt/tests/comments_expected.vv b/vlib/v/fmt/tests/comments_expected.vv index 692275012e..c046e1f7af 100644 --- a/vlib/v/fmt/tests/comments_expected.vv +++ b/vlib/v/fmt/tests/comments_expected.vv @@ -82,3 +82,17 @@ fn linebreaks_in_block_comments() { eggs */ } + +fn between_if_branches() { + if spam { + } + // remove the empty line above + else if eggs { + } + + if spam2 { + } + // remove the empty line below + else { + } +} diff --git a/vlib/v/fmt/tests/comments_input.vv b/vlib/v/fmt/tests/comments_input.vv index 3078f64587..1c752c2f61 100644 --- a/vlib/v/fmt/tests/comments_input.vv +++ b/vlib/v/fmt/tests/comments_input.vv @@ -65,3 +65,19 @@ fn linebreaks_in_block_comments() { spaces make no difference there eggs */ } + +fn between_if_branches() { + if spam { + } + + // remove the empty line above + else if eggs { + } + + if spam2 { + } + // remove the empty line below + + else { + } +} diff --git a/vlib/v/fmt/tests/comments_keep.vv b/vlib/v/fmt/tests/comments_keep.vv index ac4fee3bde..b923ee34e7 100644 --- a/vlib/v/fmt/tests/comments_keep.vv +++ b/vlib/v/fmt/tests/comments_keep.vv @@ -20,9 +20,6 @@ fn main() { u := User{ name: 'Peter' } - if true { - } - // some comment after an if without else n := sizeof(User) // else // else { @@ -60,3 +57,15 @@ fn linebreaks_in_block_comments() { no problem *****/ } + +fn ifs_comments_and_empty_lines() { + if true { + } + // some comment after an if without else + if false { + } + + // this is parsed as post_comment of the if but does not really belong there + // thereore keep the empty line + something_else() +}