This repository was archived by the owner on Jun 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 38
Move React ppx from compiler repo, add tests #124
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
523ff1e
Move React ppx from compiler repo, add tests
jchavarri d24c0df
Fix roundtrip tests, ignore test files with .fixme suffix
jchavarri a3f0b44
Merge branch 'master' into react-ppx
jchavarri 8a7a1bd
add -ppx cmd line arg
jchavarri d3dcd85
rename .react.res to just .res
jchavarri dd2f680
remove unneeded jsx stuff from res_multi_printer
jchavarri e84640a
remove .fixme option and add previously failing test + snapshot
jchavarri 739a1df
don't run roundtrip tests if ppx is defined
jchavarri 23336db
move ppx tests to own folder, remove "none" as default arg value, cle…
jchavarri File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
(* | ||
This is the module that handles turning Reason JSX' agnostic function call into | ||
a ReasonReact-specific function call. Aka, this is a macro, using OCaml's ppx | ||
facilities; https://whitequark.org/blog/2014/04/16/a-guide-to-extension- | ||
points-in-ocaml/ | ||
You wouldn't use this file directly; it's used by ReScript's | ||
bsconfig.json. Specifically, there's a field called `react-jsx` inside the | ||
field `reason`, which enables this ppx through some internal call in bsb | ||
*) | ||
|
||
(* | ||
There are two different transforms that can be selected in this file (v2 and v3): | ||
v2: | ||
transform `[@JSX] div(~props1=a, ~props2=b, ~children=[foo, bar], ())` into | ||
`ReactDOMRe.createElement("div", ~props={"props1": 1, "props2": b}, [|foo, | ||
bar|])`. | ||
transform `[@JSX] div(~props1=a, ~props2=b, ~children=foo, ())` into | ||
`ReactDOMRe.createElementVariadic("div", ~props={"props1": 1, "props2": b}, foo)`. | ||
transform the upper-cased case | ||
`[@JSX] Foo.createElement(~key=a, ~ref=b, ~foo=bar, ~children=[], ())` into | ||
`ReasonReact.element(~key=a, ~ref=b, Foo.make(~foo=bar, [||]))` | ||
transform `[@JSX] [foo]` into | ||
`ReactDOMRe.createElement(ReasonReact.fragment, [|foo|])` | ||
v3: | ||
transform `[@JSX] div(~props1=a, ~props2=b, ~children=[foo, bar], ())` into | ||
`ReactDOMRe.createDOMElementVariadic("div", ReactDOMRe.domProps(~props1=1, ~props2=b), [|foo, bar|])`. | ||
transform the upper-cased case | ||
`[@JSX] Foo.createElement(~key=a, ~ref=b, ~foo=bar, ~children=[], ())` into | ||
`React.createElement(Foo.make, Foo.makeProps(~key=a, ~ref=b, ~foo=bar, ()))` | ||
transform the upper-cased case | ||
`[@JSX] Foo.createElement(~foo=bar, ~children=[foo, bar], ())` into | ||
`React.createElementVariadic(Foo.make, Foo.makeProps(~foo=bar, ~children=React.null, ()), [|foo, bar|])` | ||
transform `[@JSX] [foo]` into | ||
`ReactDOMRe.createElement(ReasonReact.fragment, [|foo|])` | ||
*) | ||
|
||
val rewrite_implementation : Parsetree.structure -> Parsetree.structure | ||
|
||
val rewrite_signature : Parsetree.signature -> Parsetree.signature |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -165,6 +165,7 @@ module ResClflags: sig | |||||||||
val files: string list ref | ||||||||||
val interface: bool ref | ||||||||||
val report: string ref | ||||||||||
val ppx: string ref | ||||||||||
|
||||||||||
val parse: unit -> unit | ||||||||||
end = struct | ||||||||||
|
@@ -178,6 +179,7 @@ end = struct | |||||||||
let origin = ref "" | ||||||||||
let interface = ref false | ||||||||||
let report = ref "pretty" | ||||||||||
let ppx = ref "" | ||||||||||
|
||||||||||
let usage = "Usage:\n rescript <options> <file>\n\n" ^ | ||||||||||
"Examples:\n" ^ | ||||||||||
|
@@ -192,6 +194,7 @@ end = struct | |||||||||
("-print", Arg.String (fun txt -> print := txt), "Print either binary or ns. Default: ns"); | ||||||||||
("-width", Arg.Int (fun w -> width := w), "Specify the line length for the printer (formatter)"); | ||||||||||
("-interface", Arg.Unit (fun () -> interface := true), "Parse as interface"); | ||||||||||
("-ppx", Arg.String (fun txt -> ppx := txt), "Apply a specific built-in ppx before parsing, none or jsx. Default: none"); | ||||||||||
(* ("-report", Arg.String (fun txt -> report := txt), "Stylize errors and messages using color and context. Accepts `Pretty` and `Plain`. Default `Plain`") *) | ||||||||||
] | ||||||||||
|
||||||||||
|
@@ -201,7 +204,7 @@ end | |||||||||
module CliArgProcessor = struct | ||||||||||
type backend = Parser: ('diagnostics) Res_driver.parsingEngine -> backend [@@unboxed] | ||||||||||
|
||||||||||
let processFile ~isInterface ~width ~recover ~origin ~target ~report:_ filename = | ||||||||||
let processFile ~isInterface ~width ~recover ~origin ~target ~report:_ ~ppx filename = | ||||||||||
try | ||||||||||
let len = String.length filename in | ||||||||||
let processInterface = | ||||||||||
|
@@ -243,8 +246,12 @@ module CliArgProcessor = struct | |||||||||
else exit 1 | ||||||||||
end | ||||||||||
else | ||||||||||
let parsetree = match ppx with | ||||||||||
| "jsx" -> Reactjs_jsx_ppx.rewrite_signature parseResult.parsetree | ||||||||||
| _ -> parseResult.parsetree | ||||||||||
in | ||||||||||
printEngine.printInterface | ||||||||||
~width ~filename ~comments:parseResult.comments parseResult.parsetree | ||||||||||
~width ~filename ~comments:parseResult.comments parsetree | ||||||||||
else | ||||||||||
let parseResult = backend.parseImplementation ~forPrinter ~filename in | ||||||||||
if parseResult.invalid then begin | ||||||||||
|
@@ -258,19 +265,23 @@ module CliArgProcessor = struct | |||||||||
else exit 1 | ||||||||||
end | ||||||||||
else | ||||||||||
let parsetree = match ppx with | ||||||||||
| "jsx" -> Reactjs_jsx_ppx.rewrite_implementation parseResult.parsetree | ||||||||||
| _ -> parseResult.parsetree | ||||||||||
in | ||||||||||
printEngine.printImplementation | ||||||||||
~width ~filename ~comments:parseResult.comments parseResult.parsetree | ||||||||||
~width ~filename ~comments:parseResult.comments parsetree | ||||||||||
with | ||||||||||
| Failure txt -> | ||||||||||
prerr_string txt; | ||||||||||
prerr_newline(); | ||||||||||
exit 1 | ||||||||||
| _ -> exit 1 | ||||||||||
[@@raises exit] | ||||||||||
[@@raises Invalid_argument, exit] | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What raises There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The existing react ppx uses that exception to note cases with unexpected situations. I can count at least 19 different places, e.g. Lines 351 to 354 in 23336db
|
||||||||||
end | ||||||||||
|
||||||||||
|
||||||||||
let [@raises exit] () = | ||||||||||
let [@raises Invalid_argument, exit] () = | ||||||||||
if not !Sys.interactive then begin | ||||||||||
ResClflags.parse (); | ||||||||||
match !ResClflags.files with | ||||||||||
|
@@ -282,6 +293,7 @@ let [@raises exit] () = | |||||||||
~target:!ResClflags.print | ||||||||||
~origin:!ResClflags.origin | ||||||||||
~report:!ResClflags.report | ||||||||||
~ppx:!ResClflags.ppx | ||||||||||
"" | ||||||||||
| files -> | ||||||||||
List.iter (fun filename -> | ||||||||||
|
@@ -292,6 +304,7 @@ let [@raises exit] () = | |||||||||
~target:!ResClflags.print | ||||||||||
~origin:!ResClflags.origin | ||||||||||
~report:!ResClflags.report | ||||||||||
~ppx:!ResClflags.ppx | ||||||||||
filename | ||||||||||
) files | ||||||||||
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// test React JSX file | ||
|
||
@react.component | ||
let make = (~msg) => { | ||
<div> {msg->React.string} </div> | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`commentAtTop.res 1`] = ` | ||
"@bs.obj | ||
external makeProps: (~msg: 'msg, ~key: string=?, unit) => {\\"msg\\": 'msg} = \\"\\" // test React JSX file | ||
|
||
let make = | ||
(@warning(\\"-16\\") ~msg) => { | ||
ReactDOMRe.createDOMElementVariadic(\\"div\\", [{msg->React.string}]) | ||
} | ||
let make = { | ||
let \\\\\\"CommentAtTop\\" = (\\\\\\"Props\\": {\\"msg\\": 'msg}) => make(~msg=\\\\\\"Props\\"[\\"msg\\"]) | ||
\\\\\\"CommentAtTop\\" | ||
} | ||
" | ||
`; | ||
|
||
exports[`externalWithCustomName.res 1`] = ` | ||
"module Foo = { | ||
@bs.obj | ||
external componentProps: ( | ||
~a: int, | ||
~b: string, | ||
~key: string=?, | ||
unit, | ||
) => {\\"a\\": int, \\"b\\": string} = \\"\\" | ||
@bs.module(\\"Foo\\") | ||
external component: React.componentLike< | ||
{\\"a\\": int, \\"b\\": string}, | ||
React.element, | ||
> = \\"component\\" | ||
} | ||
|
||
let t = React.createElement( | ||
Foo.component, | ||
Foo.componentProps(~a=1, ~b={\\"1\\"}, ()), | ||
) | ||
" | ||
`; | ||
|
||
exports[`innerModule.res 1`] = ` | ||
"module Bar = { | ||
@bs.obj | ||
external makeProps: ( | ||
~a: 'a, | ||
~b: 'b, | ||
~key: string=?, | ||
unit, | ||
) => {\\"a\\": 'a, \\"b\\": 'b} = \\"\\" | ||
let make = | ||
(@warning(\\"-16\\") ~a, @warning(\\"-16\\") ~b, _) => { | ||
Js.log(\\"This function should be named \`InnerModule.react$Bar\`\\") | ||
ReactDOMRe.createDOMElementVariadic(\\"div\\", []) | ||
} | ||
let make = { | ||
let \\\\\\"InnerModule$Bar\\" = (\\\\\\"Props\\": {\\"a\\": 'a, \\"b\\": 'b}) => | ||
make(~b=\\\\\\"Props\\"[\\"b\\"], ~a=\\\\\\"Props\\"[\\"a\\"], ()) | ||
\\\\\\"InnerModule$Bar\\" | ||
} | ||
@bs.obj | ||
external componentProps: ( | ||
~a: 'a, | ||
~b: 'b, | ||
~key: string=?, | ||
unit, | ||
) => {\\"a\\": 'a, \\"b\\": 'b} = \\"\\" | ||
|
||
let component = | ||
(@warning(\\"-16\\") ~a, @warning(\\"-16\\") ~b, _) => { | ||
Js.log(\\"This function should be named \`InnerModule.react$Bar$component\`\\") | ||
ReactDOMRe.createDOMElementVariadic(\\"div\\", []) | ||
} | ||
let component = { | ||
let \\\\\\"InnerModule$Bar$component\\" = (\\\\\\"Props\\": {\\"a\\": 'a, \\"b\\": 'b}) => | ||
component(~b=\\\\\\"Props\\"[\\"b\\"], ~a=\\\\\\"Props\\"[\\"a\\"], ()) | ||
\\\\\\"InnerModule$Bar$component\\" | ||
} | ||
} | ||
" | ||
`; | ||
|
||
exports[`topLevel.res 1`] = ` | ||
"@bs.obj | ||
external makeProps: ( | ||
~a: 'a, | ||
~b: 'b, | ||
~key: string=?, | ||
unit, | ||
) => {\\"a\\": 'a, \\"b\\": 'b} = \\"\\" | ||
let make = | ||
(@warning(\\"-16\\") ~a, @warning(\\"-16\\") ~b, _) => { | ||
Js.log(\\"This function should be named 'TopLevel.react'\\") | ||
ReactDOMRe.createDOMElementVariadic(\\"div\\", []) | ||
} | ||
let make = { | ||
let \\\\\\"TopLevel\\" = (\\\\\\"Props\\": {\\"a\\": 'a, \\"b\\": 'b}) => | ||
make(~b=\\\\\\"Props\\"[\\"b\\"], ~a=\\\\\\"Props\\"[\\"a\\"], ()) | ||
\\\\\\"TopLevel\\" | ||
} | ||
" | ||
`; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// test React JSX file | ||
|
||
@react.component | ||
let make = (~msg) => { | ||
<div> {msg->React.string} </div> | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module Foo = { | ||
@react.component @bs.module("Foo") | ||
external component: (~a: int, ~b: string, _) => React.element = "component" | ||
} | ||
|
||
let t = <Foo.component a=1 b={"1"} /> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
module Bar = { | ||
@react.component | ||
let make = (~a, ~b, _) => { | ||
Js.log( | ||
"This function should be named `InnerModule.react$Bar`", | ||
) | ||
<div /> | ||
} | ||
@react.component | ||
let component = (~a, ~b, _) => { | ||
Js.log( | ||
"This function should be named `InnerModule.react$Bar$component`", | ||
) | ||
<div /> | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
runPrinter(__dirname, "jsx") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
@react.component | ||
let make = (~a, ~b, _) => { | ||
Js.log("This function should be named 'TopLevel.react'") | ||
<div /> | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we keep this a string and match on the string for now? Does this extra conversion give us something in the end?