From 95a9f0e29b6dd7a9e46903271b88e0ef9ab08bd2 Mon Sep 17 00:00:00 2001 From: yuyi Date: Sun, 12 Mar 2023 07:07:13 +0800 Subject: [PATCH] ast, parser, fmt: fix fmt error of infix expr with comments (fix #17560) (#17583) --- vlib/crypto/internal/subtle/aliasing.v | 2 +- vlib/v/ast/ast.v | 3 +++ vlib/v/fmt/fmt.v | 7 +++++++ .../fmt/tests/infix_expr_with_comments_keep.vv | 9 +++++++++ vlib/v/parser/expr.v | 18 ++++++++++++++++++ vlib/v/parser/parser.v | 2 ++ 6 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 vlib/v/fmt/tests/infix_expr_with_comments_keep.vv diff --git a/vlib/crypto/internal/subtle/aliasing.v b/vlib/crypto/internal/subtle/aliasing.v index 90ac938c5e..07a0e91f93 100644 --- a/vlib/crypto/internal/subtle/aliasing.v +++ b/vlib/crypto/internal/subtle/aliasing.v @@ -12,7 +12,7 @@ pub fn any_overlap(x []u8, y []u8) bool { // NOTE: Remember to come back to this (joe-c) return x.len > 0 && y.len > 0 && // &x.data[0] <= &y.data[y.len-1] && // &y.data[0] <= &x.data[x.len-1] - unsafe { &x[0] <= &y[y.len - 1] && &y[0] <= &x[x.len - 1] } + unsafe { &x[0] <= &y[y.len - 1] && &y[0] <= &x[x.len - 1] } } // inexact_overlap reports whether x and y share memory at any non-corresponding diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index c1a0ae180d..9284d99614 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -881,6 +881,9 @@ pub mut: ct_left_value ComptTimeConstValue = empty_comptime_const_expr() ct_right_value_evaled bool ct_right_value ComptTimeConstValue = empty_comptime_const_expr() + // + before_op_comments []Comment + after_op_comments []Comment } // ++, -- diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 010362cebe..86f97d1603 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -2138,6 +2138,9 @@ pub fn (mut f Fmt) infix_expr(node ast.InfixExpr) { start_pos := f.out.len start_len := f.line_len f.expr(node.left) + if node.before_op_comments.len > 0 { + f.comments(node.before_op_comments, iembed: node.before_op_comments[0].is_inline) + } is_one_val_array_init := node.op in [.key_in, .not_in] && node.right is ast.ArrayInit && (node.right as ast.ArrayInit).exprs.len == 1 is_and := node.op == .amp && f.node_str(node.right).starts_with('&') @@ -2150,6 +2153,10 @@ pub fn (mut f Fmt) infix_expr(node ast.InfixExpr) { } else { f.write(' ${node.op.str()} ') } + if node.after_op_comments.len > 0 { + f.comments(node.after_op_comments, iembed: node.after_op_comments[0].is_inline) + f.write(' ') + } if is_one_val_array_init && !f.inside_comptime_if { // `var in [val]` => `var == val` f.expr((node.right as ast.ArrayInit).exprs[0]) diff --git a/vlib/v/fmt/tests/infix_expr_with_comments_keep.vv b/vlib/v/fmt/tests/infix_expr_with_comments_keep.vv new file mode 100644 index 0000000000..a333822b8a --- /dev/null +++ b/vlib/v/fmt/tests/infix_expr_with_comments_keep.vv @@ -0,0 +1,9 @@ +fn main() { + a := 4 // comment1 + + /* comment2 */ 6 + + b := 5 /* comment1 */ + // comment2 + 6 + + c := 4 /* comment1 */ + /* comment2 */ 6 // comment3 +} diff --git a/vlib/v/parser/expr.v b/vlib/v/parser/expr.v index 2d0e88d569..9b7b33ed87 100644 --- a/vlib/v/parser/expr.v +++ b/vlib/v/parser/expr.v @@ -454,6 +454,10 @@ pub fn (mut p Parser) check_expr(precedence int) !ast.Expr { if p.inside_if_cond { p.if_cond_comments << p.eat_comments() } + if p.pref.is_fmt && p.tok.kind == .comment && p.peek_tok.kind.is_infix() && !p.inside_infix + && !(p.peek_tok.kind == .mul && p.peek_tok.pos().line_nr != p.tok.pos().line_nr) { + p.left_comments = p.eat_comments() + } return p.expr_with_left(node, precedence, is_stmt_ident) } @@ -595,6 +599,11 @@ pub fn (mut p Parser) expr_with_left(left ast.Expr, precedence int, is_stmt_iden } fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr { + prev_inside_infix := p.inside_infix + p.inside_infix = true + defer { + p.inside_infix = prev_inside_infix + } op := p.tok.kind if op == .arrow { p.or_is_handled = true @@ -606,6 +615,13 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr { if p.inside_if_cond { p.if_cond_comments << p.eat_comments() } + mut before_op_comments := []ast.Comment{} + if p.pref.is_fmt && p.left_comments.len > 0 { + before_op_comments = p.left_comments.clone() + p.left_comments = [] + } + p.left_comments = [] + after_op_comments := p.eat_comments() mut right := ast.empty_expr prev_expecting_type := p.expecting_type if op in [.key_is, .not_is] { @@ -648,6 +664,8 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr { op: op pos: pos is_stmt: p.is_stmt_ident + before_op_comments: before_op_comments + after_op_comments: after_op_comments or_block: ast.OrExpr{ stmts: or_stmts kind: or_kind diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 839e65b24f..dd9835d5f2 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -48,6 +48,7 @@ mut: inside_str_interp bool inside_array_lit bool inside_in_array bool + inside_infix bool inside_match bool // to separate `match A { }` from `Struct{}` inside_select bool // to allow `ch <- Struct{} {` inside `select` inside_match_case bool // to separate `match_expr { }` from `Struct{}` @@ -93,6 +94,7 @@ mut: anon_struct_decl ast.StructDecl struct_init_generic_types []ast.Type if_cond_comments []ast.Comment + left_comments []ast.Comment script_mode bool script_mode_start_token token.Token pub mut: