From cb7881d28fb722eca051f44a10e3d608c437e5c1 Mon Sep 17 00:00:00 2001 From: yuyi Date: Thu, 15 Aug 2024 21:50:29 +0800 Subject: [PATCH] fmt: fix enum/struct_decl/struct_init fields with empty newlines --- vlib/sync/channels.c.v | 3 +- vlib/v/ast/ast.v | 6 ++- vlib/v/fmt/fmt.v | 3 ++ vlib/v/fmt/struct.v | 31 ++++++------- vlib/v/fmt/tests/comments_input.vv | 1 + ... => enum_fields_with_empty_line_1_keep.vv} | 0 .../enum_fields_with_empty_line_2_keep.vv | 19 ++++++++ ...uct_decl_with_newline_and_comments_keep.vv | 17 +++++++ ..._init_with_newline_and_comments_1_keep.vv} | 0 ...t_init_with_newline_and_comments_2_keep.vv | 25 ++++++++++ vlib/v/parser/parser.v | 10 ++-- vlib/v/parser/struct.v | 46 ++++++++----------- 12 files changed, 111 insertions(+), 50 deletions(-) rename vlib/v/fmt/tests/{enum_fields_with_empty_line_keep.vv => enum_fields_with_empty_line_1_keep.vv} (100%) create mode 100644 vlib/v/fmt/tests/enum_fields_with_empty_line_2_keep.vv create mode 100644 vlib/v/fmt/tests/struct_decl_with_newline_and_comments_keep.vv rename vlib/v/fmt/tests/{struct_init_with_newline_and_comments_keep.vv => struct_init_with_newline_and_comments_1_keep.vv} (100%) create mode 100644 vlib/v/fmt/tests/struct_init_with_newline_and_comments_2_keep.vv diff --git a/vlib/sync/channels.c.v b/vlib/sync/channels.c.v index 22b9eb8117b0b6..f3abcbe83cfea6 100644 --- a/vlib/sync/channels.c.v +++ b/vlib/sync/channels.c.v @@ -33,7 +33,8 @@ pub struct Channel { ringbuf &u8 = unsafe { nil } // queue for buffered channels statusbuf &u8 = unsafe { nil } // flags to synchronize write/read in ringbuf objsize u32 -mut: // atomic +mut: + // atomic writesem Semaphore // to wake thread that wanted to write, but buffer was full readsem Semaphore // to wake thread that wanted to read, but buffer was empty writesem_im Semaphore diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index b66d842b1b7cd6..bfffa757ff12fe 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -330,7 +330,9 @@ pub: pos token.Pos type_pos token.Pos option_pos token.Pos + pre_comments []Comment comments []Comment + next_comments []Comment i int has_default_expr bool has_prev_newline bool @@ -457,7 +459,8 @@ pub struct StructInitField { pub: pos token.Pos name_pos token.Pos - comments []Comment + pre_comments []Comment + end_comments []Comment next_comments []Comment has_prev_newline bool pub mut: @@ -1366,6 +1369,7 @@ pub: name string // just `lock`, or `abc`, etc, no matter if the name is a keyword or not. source_name string // The name in the source, for example `@lock`, and `abc`. Note that `lock` is a keyword in V. pos token.Pos + pre_comments []Comment // comment before Enumfield comments []Comment // comment after Enumfield in the same line next_comments []Comment // comments between current EnumField and next EnumField has_expr bool // true, when .expr has a value diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index cefd8c3c34e691..e2b9fba8b8002b 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -1069,6 +1069,9 @@ pub fn (mut f Fmt) enum_decl(node ast.EnumDecl) { if i > 0 && field.has_prev_newline { f.writeln('') } + if field.pre_comments.len > 0 { + f.comments(field.pre_comments, has_nl: true, level: .indent) + } f.write('\t${field.name}') if field.has_expr { f.write(strings.repeat(` `, value_align.max_len(field.pos.line_nr) - field.name.len)) diff --git a/vlib/v/fmt/struct.v b/vlib/v/fmt/struct.v index d52722c0ed116c..df27df2a1033bf 100644 --- a/vlib/v/fmt/struct.v +++ b/vlib/v/fmt/struct.v @@ -78,16 +78,10 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl, is_anon bool) { } else {} } - mut pre_cmts, mut end_cmts, mut next_line_cmts := []ast.Comment{}, []ast.Comment{}, []ast.Comment{} - for cmt in field.comments { - match true { - cmt.pos.pos < field.pos.pos { pre_cmts << cmt } - cmt.pos.line_nr > field.pos.last_line { next_line_cmts << cmt } - else { end_cmts << cmt } - } - } // Handle comments before the field - f.comments_before_field(pre_cmts) + if field.pre_comments.len > 0 { + f.comments(field.pre_comments, level: .indent) + } volatile_prefix := if field.is_volatile { 'volatile ' } else { '' } f.write('\t${volatile_prefix}${field.name} ') f.write(strings.repeat(` `, type_align.max_len(field.pos.line_nr) - field.name.len)) @@ -115,7 +109,7 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl, is_anon bool) { f.single_line_attrs(field.attrs, same_line: true) } // Handle comments at the end of the line - if end_cmts.len > 0 { + if field.comments.len > 0 { if field.has_default_expr { f.write(strings.repeat(` `, comment_align.max_len(field.pos.line_nr) - field.default_expr.str().len - 2)) } else if field.attrs.len > 0 { @@ -124,13 +118,13 @@ pub fn (mut f Fmt) struct_decl(node ast.StructDecl, is_anon bool) { f.write(strings.repeat(` `, comment_align.max_len(field.pos.line_nr) - field_types[i].len)) } f.write(' ') - f.comments(end_cmts, level: .indent) + f.comments(field.comments, level: .indent) } else { f.writeln('') } // Handle comments on the next lines - if next_line_cmts.len > 0 { - f.comments(next_line_cmts, level: .indent) + if field.next_comments.len > 0 { + f.comments(field.next_comments, level: .indent) } } if is_anon || node.end_comments.len > 0 { @@ -279,7 +273,7 @@ pub fn (mut f Fmt) struct_init(node ast.StructInit) { mut comment_align := new_field_align(use_threshold: true) for init_field in node.init_fields { value_align.add_info(init_field.name.len, init_field.pos.line_nr) - if init_field.comments.len > 0 { + if init_field.end_comments.len > 0 { comment_align.add_info(init_field.expr.str().len, init_field.pos.line_nr) } } @@ -287,15 +281,18 @@ pub fn (mut f Fmt) struct_init(node ast.StructInit) { if i > 0 && init_field.has_prev_newline { f.writeln('') } + if init_field.pre_comments.len > 0 { + f.comments(init_field.pre_comments, has_nl: true, level: .keep) + } f.write('${init_field.name}: ') if !single_line_fields { f.write(strings.repeat(` `, value_align.max_len(init_field.pos.line_nr) - init_field.name.len)) } f.expr(init_field.expr) - if init_field.comments.len > 0 { + if init_field.end_comments.len > 0 { f.write(strings.repeat(` `, comment_align.max_len(init_field.pos.line_nr) - init_field.expr.str().len)) f.write(' ') - f.comments(init_field.comments, has_nl: false, level: .indent) + f.comments(init_field.end_comments, has_nl: false, level: .indent) } if single_line_fields { if i < node.init_fields.len - 1 { @@ -305,7 +302,7 @@ pub fn (mut f Fmt) struct_init(node ast.StructInit) { f.writeln('') } f.comments(init_field.next_comments, has_nl: true, level: .keep) - if single_line_fields && (init_field.comments.len > 0 + if single_line_fields && (init_field.end_comments.len > 0 || init_field.next_comments.len > 0 || !expr_is_single_line(init_field.expr) || f.line_len > max_len) { single_line_fields = false diff --git a/vlib/v/fmt/tests/comments_input.vv b/vlib/v/fmt/tests/comments_input.vv index b3dcf84fd01c05..d01211f11793f9 100644 --- a/vlib/v/fmt/tests/comments_input.vv +++ b/vlib/v/fmt/tests/comments_input.vv @@ -1,4 +1,5 @@ import time // foo + /* block comment diff --git a/vlib/v/fmt/tests/enum_fields_with_empty_line_keep.vv b/vlib/v/fmt/tests/enum_fields_with_empty_line_1_keep.vv similarity index 100% rename from vlib/v/fmt/tests/enum_fields_with_empty_line_keep.vv rename to vlib/v/fmt/tests/enum_fields_with_empty_line_1_keep.vv diff --git a/vlib/v/fmt/tests/enum_fields_with_empty_line_2_keep.vv b/vlib/v/fmt/tests/enum_fields_with_empty_line_2_keep.vv new file mode 100644 index 00000000000000..0b34fb6e2ee270 --- /dev/null +++ b/vlib/v/fmt/tests/enum_fields_with_empty_line_2_keep.vv @@ -0,0 +1,19 @@ +enum Info { + aa = 1 // aa + bbb // bbb + + cccc = 5 /* cccc + --- cccc + */ + ddddd = 10 // ddddd + + // before + ee = 20 + fff = 30 + + // before comment1 + // before comment2 + gg +} + +fn main() {} diff --git a/vlib/v/fmt/tests/struct_decl_with_newline_and_comments_keep.vv b/vlib/v/fmt/tests/struct_decl_with_newline_and_comments_keep.vv new file mode 100644 index 00000000000000..0bec8929c663cb --- /dev/null +++ b/vlib/v/fmt/tests/struct_decl_with_newline_and_comments_keep.vv @@ -0,0 +1,17 @@ +module main + +fn main() { +} + +pub struct OperateInfo { // implements IperateInfo +pub mut: + title string // title + + // msg, id + msg string // msg + id string // id + + // other1 + // other2 + other string +} // operate info diff --git a/vlib/v/fmt/tests/struct_init_with_newline_and_comments_keep.vv b/vlib/v/fmt/tests/struct_init_with_newline_and_comments_1_keep.vv similarity index 100% rename from vlib/v/fmt/tests/struct_init_with_newline_and_comments_keep.vv rename to vlib/v/fmt/tests/struct_init_with_newline_and_comments_1_keep.vv diff --git a/vlib/v/fmt/tests/struct_init_with_newline_and_comments_2_keep.vv b/vlib/v/fmt/tests/struct_init_with_newline_and_comments_2_keep.vv new file mode 100644 index 00000000000000..c775c245371278 --- /dev/null +++ b/vlib/v/fmt/tests/struct_init_with_newline_and_comments_2_keep.vv @@ -0,0 +1,25 @@ +module abcde + +pub struct Builder { +pub mut: + // inline before field + buf []u8 + str_calls int + len int + initial_size int = 1 +} + +pub fn new_builder(initial_size int) Builder { + return Builder{ + // buf: make(0, initial_size) + buf: []u8{cap: initial_size} + + // before comment + str_calls: 0 // after str_calls + len: 0 // after len + + // before comment1 + // before comment2 + initial_size: initial_size // final + } +} diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 6f168df2248606..05a4e07d345e8d 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -904,16 +904,16 @@ pub: } fn (mut p Parser) eat_comments(cfg EatCommentsConfig) []ast.Comment { - mut line := p.prev_tok.line_nr + mut line := p.prev_tok.line_nr + p.prev_tok.lit.count('\n') mut comments := []ast.Comment{} for { if p.tok.kind != .comment || (cfg.same_line && p.tok.line_nr > line) - || (cfg.follow_up && (p.tok.line_nr > line + 1 || p.tok.lit.contains('\n'))) { + || (cfg.follow_up && p.tok.line_nr > line + 1) { break } comments << p.comment() if cfg.follow_up { - line = p.prev_tok.line_nr + line = p.prev_tok.line_nr + p.prev_tok.lit.count('\n') } } return comments @@ -4122,6 +4122,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl { mut uses_exprs := false mut enum_attrs := map[string][]ast.Attr{} for p.tok.kind != .eof && p.tok.kind != .rcbr { + pre_comments := p.eat_comments() pos := p.tok.pos() has_prev_newline := p.has_prev_newline() val := p.check_name() @@ -4143,7 +4144,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl { p.attrs = [] } comments := p.eat_comments(same_line: true) - next_comments := p.eat_comments() + next_comments := p.eat_comments(follow_up: true) fields << ast.EnumField{ name: val source_name: source_name(val) @@ -4151,6 +4152,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl { expr: expr has_expr: has_expr has_prev_newline: has_prev_newline + pre_comments: pre_comments comments: comments next_comments: next_comments attrs: attrs diff --git a/vlib/v/parser/struct.v b/vlib/v/parser/struct.v index f1d676778ddd29..d2aa06d4cd5528 100644 --- a/vlib/v/parser/struct.v +++ b/vlib/v/parser/struct.v @@ -101,12 +101,6 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl { mut i := 0 for p.tok.kind != .rcbr { mut comments := []ast.Comment{} - for p.tok.kind == .comment { - comments << p.comment() - if p.tok.kind == .rcbr { - break - } - } if p.tok.kind == .rcbr { end_comments = p.eat_comments(same_line: true) break @@ -168,12 +162,8 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl { is_field_mut = false is_field_global = false } - for p.tok.kind == .comment { - comments << p.comment() - if p.tok.kind == .rcbr { - break - } - } + pre_field_comments := p.eat_comments() + mut next_field_comments := []ast.Comment{} field_start_pos := p.tok.pos() mut is_field_volatile := false mut is_field_deprecated := false @@ -227,12 +217,6 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl { } else { // struct field field_name = p.check_name() - for p.tok.kind == .comment { - comments << p.comment() - if p.tok.kind == .rcbr { - break - } - } p.inside_struct_field_decl = true if p.tok.kind == .key_struct { // Anon structs @@ -269,7 +253,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl { } p.inside_struct_attr_decl = false } - comments << p.eat_comments() + comments << p.eat_comments(same_line: true) mut default_expr := ast.empty_expr mut has_default_expr := false if !is_embed { @@ -283,7 +267,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl { else {} } has_default_expr = true - comments << p.eat_comments() + comments << p.eat_comments(same_line: true) } if p.tok.kind == .at { p.inside_struct_attr_decl = true @@ -295,15 +279,18 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl { } } p.inside_struct_attr_decl = false - comments << p.eat_comments() + comments << p.eat_comments(same_line: true) } + next_field_comments = p.eat_comments(follow_up: true) ast_fields << ast.StructField{ name: field_name typ: typ pos: field_pos type_pos: type_pos option_pos: option_pos + pre_comments: pre_field_comments comments: comments + next_comments: next_field_comments i: i default_expr: default_expr has_default_expr: has_default_expr @@ -324,7 +311,9 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl { pos: field_pos type_pos: type_pos option_pos: option_pos + pre_comments: pre_field_comments comments: comments + next_comments: next_field_comments i: i default_expr: default_expr has_default_expr: has_default_expr @@ -429,7 +418,8 @@ fn (mut p Parser) struct_init(typ_str string, kind ast.StructInitKind, is_option mut expr := ast.empty_expr mut field_pos := token.Pos{} mut first_field_pos := token.Pos{} - mut comments := []ast.Comment{} + mut prev_comments := []ast.Comment{} + mut end_comments := []ast.Comment{} mut nline_comments := []ast.Comment{} is_update_expr := init_fields.len == 0 && p.tok.kind == .ellipsis if no_keys { @@ -437,7 +427,7 @@ fn (mut p Parser) struct_init(typ_str string, kind ast.StructInitKind, is_option expr = p.expr(0) field_pos = expr.pos() first_field_pos = field_pos - comments = p.eat_comments(same_line: true) + end_comments = p.eat_comments(same_line: true) } else if is_update_expr { // struct updating syntax; f2 := Foo{ ...f, name: 'f2' } update_expr_pos = p.tok.pos() @@ -446,12 +436,13 @@ fn (mut p Parser) struct_init(typ_str string, kind ast.StructInitKind, is_option update_expr_comments << p.eat_comments(same_line: true) has_update_expr = true } else { + prev_comments = p.eat_comments() first_field_pos = p.tok.pos() has_prev_newline = p.has_prev_newline() field_name = p.check_name() p.check(.colon) expr = p.expr(0) - comments = p.eat_comments(same_line: true) + end_comments = p.eat_comments(same_line: true) last_field_pos := expr.pos() field_len := if last_field_pos.len > 0 { last_field_pos.pos - first_field_pos.pos + last_field_pos.len @@ -469,15 +460,16 @@ fn (mut p Parser) struct_init(typ_str string, kind ast.StructInitKind, is_option if p.tok.kind == .comma { p.next() } - comments << p.eat_comments(same_line: true) - nline_comments << p.eat_comments() + end_comments << p.eat_comments(same_line: true) + nline_comments << p.eat_comments(follow_up: true) if !is_update_expr { init_fields << ast.StructInitField{ name: field_name expr: expr pos: field_pos name_pos: first_field_pos - comments: comments + pre_comments: prev_comments + end_comments: end_comments next_comments: nline_comments parent_type: typ has_prev_newline: has_prev_newline