Skip to content

Commit

Permalink
fix: don't punne record fields and jsx prop with attr
Browse files Browse the repository at this point in the history
Signed-off-by: Pedro B S Lisboa <[email protected]>
  • Loading branch information
pedrobslisboa committed Jan 30, 2025
1 parent 78bfcff commit ac648b7
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 12 deletions.
32 changes: 21 additions & 11 deletions src/reason-parser/reason_pprint_ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 ->
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -5233,13 +5237,14 @@ let createFormatter () =
processedAttrs
(Some [ self#dotdotdotChild expr ])
| (Optional lbl, expression) :: tail ->
let { Reason_attributes.jsxAttrs; _ } =
let { Reason_attributes.jsxAttrs; 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
Expand All @@ -5254,13 +5259,15 @@ let createFormatter () =
in
processArguments tail (nextAttr :: processedAttrs) children
| (Labelled lbl, expression) :: tail ->
let { Reason_attributes.jsxAttrs; _ } =
let { Reason_attributes.jsxAttrs; 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 ^ "="))
Expand Down Expand Up @@ -7095,13 +7102,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:
Expand Down
5 changes: 5 additions & 0 deletions test/jsx.t/input.re
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ let icon = <Icon
/* punning for explicitly passed optional */
<Foo bar=?bar />;

/* Don't pun for explicitly props with attributes */
<Foo bar=?{[@browser_only]bar} />;

/* don't pun explicitly passed optional with module identifier */
<Foo bar=?Baz.bar />;

Expand Down Expand Up @@ -131,6 +134,8 @@ let y = [<Button onClick=handleStaleClick />, <Button onClick=handleStaleClick /
<Description term=([@JSX] Text.createElement(~text="Age", ()))> child </Description>;

<Description term={<Text superLongPunnedProp anotherSuperLongOneCrazyLongThingHere text="Age" />}> child </Description>;
<Description term={<Text noPunnedProp={[@attribute] noPunnedProp} superLongPunnedProp anotherSuperLongOneCrazyLongThingHere text="Age" />}> child </Description>;
<Description term={<Text noPunned={[@attribute] noPunnedProp} />}> child </Description>;

<Foo bar={<Baz superLongPunnedProp anotherSuperLongOneCrazyLongThingHere/>}/>;

Expand Down
20 changes: 20 additions & 0 deletions test/jsx.t/run.t
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ Format JSX
/* punning for explicitly passed optional */
<Foo ?bar />;

/* Don't pun for explicitly props with attributes */
<Foo bar=?{[@browser_only] bar} />;

/* don't pun explicitly passed optional with module identifier */
<Foo bar=?Baz.bar />;

Expand Down Expand Up @@ -200,6 +203,23 @@ Format JSX
}>
child
</Description>;
<Description
term={
<Text
noPunnedProp={[@attribute] noPunnedProp}
superLongPunnedProp
anotherSuperLongOneCrazyLongThingHere
text="Age"
/>
}>
child
</Description>;
<Description
term={
<Text noPunned={[@attribute] noPunnedProp} />
}>
child
</Description>;
<Foo
bar={
Expand Down
17 changes: 17 additions & 0 deletions test/sequences.t/input.re
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,20 @@ let thirdFieldPunned = {
c
};
let singlePunAcceptedIfExtended = {...firstFieldPunned, a};

/* non-punned */
let firstFieldNonPun = {
a: [@with_attribute] a,
b,
c
};
let secondFieldNonPun = {
a,
b: [@with_attribute] b,
c
};
let thirdFieldNonPun = {
a,
b,
c: [@with_attribute] c,
};
18 changes: 17 additions & 1 deletion test/sequences.t/run.t
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,23 @@ Print the formatted file
...firstFieldPunned,
a,
};


/* non-punned */
let firstFieldNonPun = {
a: [@with_attribute] a,
b,
c,
};
let secondFieldNonPun = {
a,
b: [@with_attribute] b,
c,
};
let thirdFieldNonPun = {
a,
b,
c: [@with_attribute] c,
};
Type-check basics
$ ocamlc -c -pp 'refmt --print binary' -intf-suffix .rei -impl formatted.re

Expand Down
8 changes: 8 additions & 0 deletions test/typeDeclarations.t/input.re
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,18 @@ type foo = option([@foo]string, [@bar](int => string => int));
/* https://github.com/facebook/reason/issues/2073 */
type a = array({. "someStringKeyThatCausesLineToBreak": string });

/* Inline type record non punned field */
type b = {
punned: [@with_attribute] punned
};

/* Breakline record non punned field */
type c = {
a: string,
b: string,
punned: [@with_attribute] punned
};

type%x foo = int;

type%x foo += Int;
8 changes: 8 additions & 0 deletions test/typeDeclarations.t/run.t
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,16 @@ Format type declarations
"someStringKeyThatCausesLineToBreak": string,
});

/* Inline type record non punned field */
type b = {punned: [@with_attribute] punned};

/* Breakline record non punned field */
type c = {
a: string,
b: string,
punned: [@with_attribute] punned,
};

type%x foo = int;

type%x foo +=
Expand Down

0 comments on commit ac648b7

Please sign in to comment.