diff --git a/CHANGELOG.md b/CHANGELOG.md index 76d7127496..435654f400 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ - Fix I/O error message when trying to extract extra info from non-existing file. https://github.com/rescript-lang/rescript/pull/7656 - Fix fatal error when JSX expression used without configuring JSX in `rescript.json`. https://github.com/rescript-lang/rescript/pull/7656 - Rewatch: Only allow access to `"bs-dev-dependencies"` from `"type": "dev"` source files. https://github.com/rescript-lang/rescript/pull/7650 +- Fix comment attached to array element. https://github.com/rescript-lang/rescript/pull/7672 #### :nail_care: Polish diff --git a/compiler/syntax/src/res_comments_table.ml b/compiler/syntax/src/res_comments_table.ml index 9f65e471d5..59946df5e1 100644 --- a/compiler/syntax/src/res_comments_table.ml +++ b/compiler/syntax/src/res_comments_table.ml @@ -1028,6 +1028,38 @@ and walk_value_binding vb t comments = and walk_expression expr t comments = let open Location in + let walk_apply_expr call_expr arguments t comments = + let before, inside, after = + partition_by_loc comments call_expr.Parsetree.pexp_loc + in + let after = + if is_block_expr call_expr then ( + let after_expr, rest = + partition_adjacent_trailing call_expr.Parsetree.pexp_loc after + in + walk_expression call_expr t (List.concat [before; inside; after_expr]); + rest) + else ( + attach t.leading call_expr.Parsetree.pexp_loc before; + walk_expression call_expr t inside; + after) + in + let after_expr, rest = + partition_adjacent_trailing call_expr.Parsetree.pexp_loc after + in + attach t.trailing call_expr.Parsetree.pexp_loc after_expr; + walk_list + (arguments + |> List.map (fun (lbl, expr) -> + let loc = + match lbl with + | Asttypes.Labelled {loc} | Optional {loc} -> + {loc with loc_end = expr.Parsetree.pexp_loc.loc_end} + | _ -> expr.pexp_loc + in + ExprArgument {expr; loc})) + t rest + in match expr.Parsetree.pexp_desc with | _ when comments = [] -> () | Pexp_constant _ -> @@ -1539,35 +1571,34 @@ and walk_expression expr t comments = } when Res_parsetree_viewer.is_tuple_array key_values -> walk_list [Expression key_values] t comments - | Pexp_apply {funct = call_expr; args = arguments} -> - let before, inside, after = partition_by_loc comments call_expr.pexp_loc in - let after = - if is_block_expr call_expr then ( - let after_expr, rest = - partition_adjacent_trailing call_expr.pexp_loc after + | Pexp_apply {funct = call_expr; args = arguments} -> ( + (* Special handling for Belt.Array.concatMany - treat like an array *) + match call_expr.pexp_desc with + | Pexp_ident + { + txt = + Longident.Ldot + (Longident.Ldot (Longident.Lident "Belt", "Array"), "concatMany"); + } + when List.length arguments = 1 -> ( + match arguments with + | [(_, {pexp_desc = Pexp_array sub_arrays})] -> + (* Collect all individual expressions from sub-arrays *) + let all_exprs = + List.fold_left + (fun acc sub_array -> + match sub_array.Parsetree.pexp_desc with + | Pexp_array exprs -> acc @ exprs + | _ -> acc @ [sub_array]) + [] sub_arrays in - walk_expression call_expr t (List.concat [before; inside; after_expr]); - rest) - else ( - attach t.leading call_expr.pexp_loc before; - walk_expression call_expr t inside; - after) - in - let after_expr, rest = - partition_adjacent_trailing call_expr.pexp_loc after - in - attach t.trailing call_expr.pexp_loc after_expr; - walk_list - (arguments - |> List.map (fun (lbl, expr) -> - let loc = - match lbl with - | Asttypes.Labelled {loc} | Optional {loc} -> - {loc with loc_end = expr.Parsetree.pexp_loc.loc_end} - | _ -> expr.pexp_loc - in - ExprArgument {expr; loc})) - t rest + walk_list (all_exprs |> List.map (fun e -> Expression e)) t comments + | _ -> + (* Fallback to regular apply handling *) + walk_apply_expr call_expr arguments t comments) + | _ -> + (* Regular apply handling *) + walk_apply_expr call_expr arguments t comments) | Pexp_fun _ | Pexp_newtype _ -> ( let _, parameters, return_expr = fun_expr expr in let comments = diff --git a/compiler/syntax/src/res_printer.ml b/compiler/syntax/src/res_printer.ml index 0dc8e49630..f58503e0d2 100644 --- a/compiler/syntax/src/res_printer.ml +++ b/compiler/syntax/src/res_printer.ml @@ -4035,15 +4035,30 @@ and print_binary_expression ~state (expr : Parsetree.expression) cmt_tbl = and print_belt_array_concat_apply ~state sub_lists cmt_tbl = let make_spread_doc comma_before_spread = function | Some expr -> + (* Extract leading comments before dotdotdot *) + let leading_comments_doc = + print_leading_comments Doc.nil cmt_tbl.CommentTable.leading + expr.Parsetree.pexp_loc + in + (* Print expression without leading comments (they're already extracted) *) + let expr_doc = + let doc = print_expression ~state expr cmt_tbl in + match Parens.expr expr with + | Parens.Parenthesized -> add_parens doc + | Braced braces -> print_braces doc expr braces + | Nothing -> doc + in + (* Print trailing comments with the expression *) + let expr_with_trailing_comments = + print_trailing_comments expr_doc cmt_tbl.CommentTable.trailing + expr.Parsetree.pexp_loc + in Doc.concat [ comma_before_spread; + leading_comments_doc; Doc.dotdotdot; - (let doc = print_expression_with_comments ~state expr cmt_tbl in - match Parens.expr expr with - | Parens.Parenthesized -> add_parens doc - | Braced braces -> print_braces doc expr braces - | Nothing -> doc); + expr_with_trailing_comments; ] | None -> Doc.nil in @@ -4054,20 +4069,19 @@ and print_belt_array_concat_apply ~state sub_lists cmt_tbl = | _ -> Doc.concat [Doc.text ","; Doc.line] in let spread_doc = make_spread_doc comma_before_spread spread in - Doc.concat - [ - Doc.join - ~sep:(Doc.concat [Doc.text ","; Doc.line]) - (List.map - (fun expr -> - let doc = print_expression_with_comments ~state expr cmt_tbl in - match Parens.expr expr with - | Parens.Parenthesized -> add_parens doc - | Braced braces -> print_braces doc expr braces - | Nothing -> doc) - expressions); - spread_doc; - ] + let expressions_doc = + Doc.join + ~sep:(Doc.concat [Doc.text ","; Doc.line]) + (List.map + (fun expr -> + let doc = print_expression_with_comments ~state expr cmt_tbl in + match Parens.expr expr with + | Parens.Parenthesized -> add_parens doc + | Braced braces -> print_braces doc expr braces + | Nothing -> doc) + expressions) + in + Doc.concat [expressions_doc; spread_doc] in Doc.group (Doc.concat diff --git a/tests/syntax_tests/data/printer/comments/array.res b/tests/syntax_tests/data/printer/comments/array.res index 8882f172e8..8bb35e20cd 100644 --- a/tests/syntax_tests/data/printer/comments/array.res +++ b/tests/syntax_tests/data/printer/comments/array.res @@ -15,4 +15,40 @@ let _ = ( ->Belt.SortArray.stableSortBy((a, b) => compare(a.createdTime, b.createdTime) ) - )[0] \ No newline at end of file + )[0] + +let _ = [ + // comment 1 + a, + // comment 2 + b, + // comment 3 + c +] + +let _ = [ + // comment 1 + a, + // comment 2 + b, c +] + +let _ = [ + // comment 0 + ...xs, + // comment 1 + a, + // comment 2 + b, c +] + +let _ = [ + // comment 0 + ...xs, + // comment 1 + a, + // comment 2 + ...ys, + // comment 3 + b, c +] diff --git a/tests/syntax_tests/data/printer/comments/expected/array.res.txt b/tests/syntax_tests/data/printer/comments/expected/array.res.txt index 90ed9ed5c8..2b22a80327 100644 --- a/tests/syntax_tests/data/printer/comments/expected/array.res.txt +++ b/tests/syntax_tests/data/printer/comments/expected/array.res.txt @@ -10,3 +10,42 @@ let _ = a[0] // zz // This comment will vanish ->Belt.SortArray.stableSortBy((a, b) => compare(a.createdTime, b.createdTime)) )[0] + +let _ = [ + // comment 1 + a, + // comment 2 + b, + // comment 3 + c, +] + +let _ = [ + // comment 1 + a, + // comment 2 + b, + c, +] + +let _ = [ + // comment 0 + ...xs, + // comment 1 + a, + // comment 2 + b, + c, +] + +let _ = [ + // comment 0 + ...xs, + // comment 1 + a, + // comment 2 + ...ys, + // comment 3 + b, + c, +]