From 78bfcff34a124e811181ce2913f842dfcb01fc29 Mon Sep 17 00:00:00 2001 From: Pedro B S Lisboa Date: Fri, 24 Jan 2025 17:02:22 +0800 Subject: [PATCH 1/2] chore: add _opam to gitignore Signed-off-by: Pedro B S Lisboa --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index fa46a2146..1d3582f45 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ _esybuild _esyinstall _release _export/ + +# opam +_opam/ From f9f8e2b98e86447fe9edcda73e80c2d041abc27d Mon Sep 17 00:00:00 2001 From: Pedro B S Lisboa Date: Fri, 24 Jan 2025 17:02:50 +0800 Subject: [PATCH 2/2] fix: don't punne record fields and jsx prop with attr Signed-off-by: Pedro B S Lisboa --- src/reason-parser/reason_pprint_ast.ml | 73 ++++++++++++++------------ test/jsx.t/input.re | 5 ++ test/jsx.t/run.t | 20 +++++++ test/sequences.t/input.re | 17 ++++++ test/sequences.t/run.t | 18 ++++++- test/typeDeclarations.t/input.re | 8 +++ test/typeDeclarations.t/run.t | 8 +++ 7 files changed, 113 insertions(+), 36 deletions(-) diff --git a/src/reason-parser/reason_pprint_ast.ml b/src/reason-parser/reason_pprint_ast.ml index f5307671b..e30badef2 100644 --- a/src/reason-parser/reason_pprint_ast.ml +++ b/src/reason-parser/reason_pprint_ast.ml @@ -2113,8 +2113,10 @@ let createFormatter () = true | _ -> false - let isPunnedJsxArg lbl ident = - (not (isLongIdentWithDot ident.txt)) && Longident.last_exn ident.txt = lbl + let isPunnedJsxArg lbl ident attr = + (not (isLongIdentWithDot ident.txt)) + && Longident.last_exn ident.txt = lbl + && attr = [] let is_unit_pattern x = match x.ppat_desc with @@ -4330,7 +4332,8 @@ let createFormatter () = PipeFirstTree.flastNode list) into a more convenient structure * that allows us to express the segments: "foo" "f(a, b)" "g(c, d)". * PipeFirstTree.t expresses those segments. * - [{exp = foo; args = []}; {exp = f; args = [a; b]}; {exp = g; args = [c; d]}] + [{exp = foo; args = []}; {exp = f; args = [a; b]}; {exp = g; args = + [c; d]}] *) let rec parse acc = function | PipeFirstTree.Exp e :: PipeFirstTree.Args args :: xs -> @@ -4360,12 +4363,13 @@ let createFormatter () = *) let (flatNodes : PipeFirstTree.flatT) = flatten ~uncurried [] e in (* Turn * [Exp foo; Exp f; Args [a; b]; Exp g; Args [c; d]] * into * - [{exp = foo; args = []}; {exp = f; args = [a; b]}; {exp = g; args = [c; d]}] + [{exp = foo; args = []}; {exp = f; args = [a; b]}; {exp = g; args = + [c; d]}] *) let (pipetree : PipeFirstTree.t) = parse [] flatNodes in (* Turn * - [{exp = foo; args = []}; {exp = f; args = [a; b]}; {exp = g; args = [c; d]}] - * into * [foo; ->f(a, b); ->g(c, d)] + [{exp = foo; args = []}; {exp = f; args = [a; b]}; {exp = g; args = + [c; d]}] * into * [foo; ->f(a, b); ->g(c, d)] *) let pipeSegments = match pipetree with @@ -5233,13 +5237,14 @@ let createFormatter () = processedAttrs (Some [ self#dotdotdotChild expr ]) | (Optional lbl, expression) :: tail -> - let { Reason_attributes.jsxAttrs; _ } = + let { Reason_attributes.jsxAttrs; Reason_attributes.stdAttrs; _ } = Reason_attributes.partitionAttributes expression.pexp_attributes in let value_has_jsx = jsxAttrs != [] in let nextAttr = match expression.pexp_desc with - | Pexp_ident ident when isPunnedJsxArg lbl ident -> + | Pexp_ident ident + when isPunnedJsxArg lbl ident stdAttrs -> makeList ~break:Layout.Never [ atom "?"; atom lbl ] | Pexp_construct _ when value_has_jsx -> label @@ -5254,13 +5259,15 @@ let createFormatter () = in processArguments tail (nextAttr :: processedAttrs) children | (Labelled lbl, expression) :: tail -> - let { Reason_attributes.jsxAttrs; _ } = + let { Reason_attributes.jsxAttrs; Reason_attributes.stdAttrs; _ } = Reason_attributes.partitionAttributes expression.pexp_attributes in let value_has_jsx = jsxAttrs != [] in let nextAttr = match expression.pexp_desc with - | Pexp_ident ident when isPunnedJsxArg lbl ident -> atom lbl + | Pexp_ident ident + when isPunnedJsxArg lbl ident stdAttrs -> + atom lbl | _ when isJSXComponent expression -> label (atom (lbl ^ "=")) @@ -5614,25 +5621,19 @@ let createFormatter () = let everythingButReturnVal = (* Because align_closing is set to false, you get: * * (Brackets[] inserted to show boundaries between open/close of pattern list) * - let[firstThing - * secondThing - * thirdThing] - * * It only wraps to indent four by coincidence: If the "opening" - token was * longer, you'd get: * * - letReallyLong[firstThing - * secondThing - * thirdThing] - * * For curried let bindings, we stick the arrow in the *last* - pattern: * - let[firstThing - * secondThing - * thirdThing =>] - * * But it could have just as easily been the "closing" token - corresponding to * "let". This works because we have - [align_closing = false]. The benefit of * shoving it in the last - pattern, is that we can turn [align_closing = true] * and still - have the arrow stuck to the last pattern (which is usually what - we * want) (See modeTwo below). + let[firstThing * secondThing * thirdThing] * * It only + wraps to indent four by coincidence: If the "opening" token was * + longer, you'd get: * * + letReallyLong[firstThing * secondThing * + thirdThing] * * For curried let bindings, we stick + the arrow in the *last* pattern: * + let[firstThing * secondThing * thirdThing =>] * * But it + could have just as easily been the "closing" token corresponding + to * "let". This works because we have [align_closing = false]. + The benefit of * shoving it in the last pattern, is that we can + turn [align_closing = true] * and still have the arrow stuck to + the last pattern (which is usually what we * want) (See modeTwo + below). *) match partitioning with | None when sweet -> @@ -5824,11 +5825,10 @@ let createFormatter () = it becomes pretty printed as * let x:t =.... In the proposal, it is not impossible - it is only * impossible to preserve unnecessary parenthesis around the let binding. * * The one downside is that - integrating with existing code that uses - [let x = - * (blah:typ)] in standard OCaml will be parsed as a - Pexp_constraint. There * might be some lossiness (beyond parens) that - occurs in the original OCaml * parser. + integrating with existing code that uses [let x = * (blah:typ)] in + standard OCaml will be parsed as a Pexp_constraint. There * might be + some lossiness (beyond parens) that occurs in the original OCaml * + parser. *) method locallyAbstractPolymorphicFunctionBinding @@ -7095,13 +7095,16 @@ let createFormatter () = ; loc_ghost = false } in + let stdAttrs = Reason_attributes.extractStdAttrs e.pexp_attributes in let theRow = match e.pexp_desc, shouldPun, allowPunning with (* record value punning. Turns {foo: foo, bar: 1} into {foo, bar: 1} *) (* also turns {Foo.bar: bar, baz: 1} into {Foo.bar, baz: 1} *) + (* don't turn {bar: [@foo] bar, baz: 1} into {bar, baz: 1} *) (* don't turn {bar: Foo.bar, baz: 1} into {bar, baz: 1}, naturally *) | Pexp_ident { txt = Lident value; _ }, true, true - when Longident.last_exn li.txt = value -> + when Longident.last_exn li.txt = value && stdAttrs = [] + -> makeList (maybeQuoteFirstElem li []) (* Force breaks for nested records or mel.obj sugar * Example: diff --git a/test/jsx.t/input.re b/test/jsx.t/input.re index 3d9de4ce5..b77f48fe7 100644 --- a/test/jsx.t/input.re +++ b/test/jsx.t/input.re @@ -103,6 +103,9 @@ let icon = ; +/* Don't pun for explicitly props with attributes */ +; + /* don't pun explicitly passed optional with module identifier */ ; @@ -131,6 +134,8 @@ let y = [