diff --git a/HISTORY.md b/HISTORY.md index 9144831a0..fd45cb33e 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,6 +1,7 @@ ## 3.9 (unreleased) - Fix missing patterns around contraint pattern (a pattern with a type annotation). +- Fix top level extension printing ## 3.8.2 diff --git a/formatTest/unit_tests/expected_output/extensions.re b/formatTest/unit_tests/expected_output/extensions.re index 3660f1e6b..a6d5d84d8 100644 --- a/formatTest/unit_tests/expected_output/extensions.re +++ b/formatTest/unit_tests/expected_output/extensions.re @@ -350,6 +350,8 @@ let () = { something_else(); }; +let f = [%bs.raw x => x]; + [%bs.raw x => x]; let work = () => { diff --git a/formatTest/unit_tests/input/extensions.re b/formatTest/unit_tests/input/extensions.re index 218f02e37..8024f3c36 100644 --- a/formatTest/unit_tests/input/extensions.re +++ b/formatTest/unit_tests/input/extensions.re @@ -348,6 +348,8 @@ let () = { something_else(); }; +let f = [%bs.raw x => x]; + [%bs.raw x => x]; let work = () => { diff --git a/src/reason-parser/reason_pprint_ast.ml b/src/reason-parser/reason_pprint_ast.ml index 06fe241b1..18b03f196 100644 --- a/src/reason-parser/reason_pprint_ast.ml +++ b/src/reason-parser/reason_pprint_ast.ml @@ -7576,29 +7576,42 @@ let printer = object(self:'self) | Pmod_constraint _ | Pmod_structure _ -> self#simple_module_expr x - method structure structureItems = + (* We don't have any way to know if an extension is placed at the top level by the parsetree + while there's a difference syntactically (% for structure_items/expressons and %% for top_level). + This small fn detects this particular case (structure > structure_item > extension > value) and + prints with double % *) + let structure_item item = + match item.pstr_desc with + | Pstr_extension ((extension, PStr [item]), attrs) -> + begin match item.pstr_desc with + (* In case of a value, the extension gets inlined `let%private a = 1` *) + | Pstr_value (rf, vb_list) -> self#bindings ~extension (rf, vb_list) + | _ -> self#attach_std_item_attrs attrs (self#payload "%%" extension (PStr [item])) + end + | _ -> self#structure_item item + in match structureItems with | [] -> atom "" - | first::_ as structureItems -> + | first :: _ as structureItems -> let last = match (List.rev structureItems) with | last::_ -> last | [] -> assert false in let loc_start = first.pstr_loc.loc_start in let loc_end = last.pstr_loc.loc_end in let items = groupAndPrint - ~xf:self#structure_item + ~xf:structure_item ~getLoc:(fun x -> x.pstr_loc) ~comments:self#comments structureItems in source_map ~loc:{loc_start; loc_end; loc_ghost = false} (makeList - ~postSpace:true - ~break:Always_rec - ~indent:0 - ~inline:(true, false) - ~sep:(SepFinal (";", ";")) - items) + ~postSpace:true + ~break:Always_rec + ~indent:0 + ~inline:(true, false) + ~sep:(SepFinal (";", ";")) + items) (* How do modules become parsed? diff --git a/test/extensions.t/input.re b/test/extensions.t/input.re index 218f02e37..2bbeab3c2 100644 --- a/test/extensions.t/input.re +++ b/test/extensions.t/input.re @@ -348,16 +348,29 @@ let () = { something_else(); }; -[%bs.raw x => x]; - let work = () => { open Syntax; let%bind name = x; name; }; -/** header */ -[%raw "console.log(42)"]; +/* Extensions can have % or %% at the top-level */ + +[%bs.raw x => x]; + +[%%bs.raw x => x]; + +[%%randomExtension "with string payload"]; + +[%%randomExtension { with_obj: 33 }]; + +[%randomExtension { with_obj: 33 }]; + +/** with a comment on top */ +[%%raw "console.log(42)"]; + +/* extensions live under expresions with only one % */ +let f = [%bs.raw x => x]; /* https://github.com/facebook/reason/issues/2032 */ let predicate = diff --git a/test/extensions.t/run.t b/test/extensions.t/run.t index 735b93f2b..17f1f283f 100644 --- a/test/extensions.t/run.t +++ b/test/extensions.t/run.t @@ -352,16 +352,29 @@ Format extensions something_else(); }; - [%bs.raw x => x]; - let work = () => { open Syntax; let%bind name = x; name; }; - /** header */ - [%raw "console.log(42)"]; + /* Extensions can have % or %% at the top-level */ + + [%bs.raw x => x]; + + [%%bs.raw x => x]; + + [%%randomExtension "with string payload"]; + + [%%randomExtension {with_obj: 33}]; + + [%randomExtension {with_obj: 33}]; + + /** with a comment on top */ + [%%raw "console.log(42)"]; + + /* extensions live under expresions with only one % */ + let f = [%bs.raw x => x]; /* https://github.com/facebook/reason/issues/2032 */ let predicate =