Skip to content

Commit e78c8cd

Browse files
authored
Test ast conversion (#7318)
* POC: test ast conversion * Use separate directory for ast mapping tests * Add new test cases
1 parent f37173f commit e78c8cd

File tree

6 files changed

+140
-5
lines changed

6 files changed

+140
-5
lines changed

compiler/syntax/cli/res_cli.ml

+30-5
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ module ResClflags : sig
165165
val jsx_module : string ref
166166
val jsx_mode : string ref
167167
val typechecker : bool ref
168+
val test_ast_conversion : bool ref
168169

169170
val parse : unit -> unit
170171
end = struct
@@ -178,6 +179,7 @@ end = struct
178179
let jsx_mode = ref "automatic"
179180
let file = ref ""
180181
let typechecker = ref false
182+
let test_ast_conversion = ref false
181183

182184
let usage =
183185
"\n\
@@ -215,6 +217,9 @@ end = struct
215217
Arg.Unit (fun () -> typechecker := true),
216218
"Parses the ast as it would be passed to the typechecker and not the \
217219
printer" );
220+
( "-test-ast-conversion",
221+
Arg.Unit (fun () -> test_ast_conversion := true),
222+
"Test the ast conversion" );
218223
]
219224

220225
let parse () = Arg.parse spec (fun f -> file := f) usage
@@ -225,7 +230,7 @@ module CliArgProcessor = struct
225230
[@@unboxed]
226231

227232
let process_file ~is_interface ~width ~recover ~target ~jsx_version
228-
~jsx_module ~jsx_mode ~typechecker filename =
233+
~jsx_module ~jsx_mode ~typechecker ~test_ast_conversion filename =
229234
let len = String.length filename in
230235
let process_interface =
231236
is_interface
@@ -267,8 +272,17 @@ module CliArgProcessor = struct
267272
else exit 1)
268273
else
269274
let parsetree =
270-
Jsx_ppx.rewrite_signature ~jsx_version ~jsx_module ~jsx_mode
271-
parse_result.parsetree
275+
if not test_ast_conversion then parse_result.parsetree
276+
else
277+
let tree0 =
278+
Ast_mapper_to0.default_mapper.signature
279+
Ast_mapper_to0.default_mapper parse_result.parsetree
280+
in
281+
Ast_mapper_from0.default_mapper.signature
282+
Ast_mapper_from0.default_mapper tree0
283+
in
284+
let parsetree =
285+
Jsx_ppx.rewrite_signature ~jsx_version ~jsx_module ~jsx_mode parsetree
272286
in
273287
print_engine.print_interface ~width ~filename
274288
~comments:parse_result.comments parsetree
@@ -282,9 +296,19 @@ module CliArgProcessor = struct
282296
~comments:parse_result.comments parse_result.parsetree
283297
else exit 1)
284298
else
299+
let parsetree =
300+
if not test_ast_conversion then parse_result.parsetree
301+
else
302+
let tree0 =
303+
Ast_mapper_to0.default_mapper.structure
304+
Ast_mapper_to0.default_mapper parse_result.parsetree
305+
in
306+
Ast_mapper_from0.default_mapper.structure
307+
Ast_mapper_from0.default_mapper tree0
308+
in
285309
let parsetree =
286310
Jsx_ppx.rewrite_implementation ~jsx_version ~jsx_module ~jsx_mode
287-
parse_result.parsetree
311+
parsetree
288312
in
289313
print_engine.print_implementation ~width ~filename
290314
~comments:parse_result.comments parsetree
@@ -298,5 +322,6 @@ let () =
298322
~width:!ResClflags.width ~recover:!ResClflags.recover
299323
~target:!ResClflags.print ~jsx_version:!ResClflags.jsx_version
300324
~jsx_module:!ResClflags.jsx_module ~jsx_mode:!ResClflags.jsx_mode
301-
~typechecker:!ResClflags.typechecker !ResClflags.file)
325+
~typechecker:!ResClflags.typechecker !ResClflags.file
326+
~test_ast_conversion:!ResClflags.test_ast_conversion)
302327
[@@raises exit]

scripts/test_syntax.sh

+6
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ while read file; do
4242
$DUNE_BIN_DIR/res_parser $file &> $(exp $file) & maybeWait
4343
done <temp/files.txt
4444

45+
# printing with ast conversion
46+
find syntax_tests/data/ast-mapping -name "*.res" -o -name "*.resi" -o -name "*.ml" -o -name "*.mli" >temp/files.txt
47+
while read file; do
48+
$DUNE_BIN_DIR/res_parser -test-ast-conversion -jsx-version 4 -jsx-mode "automatic" $file &> $(exp $file) & maybeWait
49+
done <temp/files.txt
50+
4551
# printing with ppx
4652
find syntax_tests/data/ppx/react -name "*.res" -o -name "*.resi" >temp/files.txt
4753
while read file; do
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
let emptyUnary = <input />
2+
3+
let emptyNonunary = <div></div>
4+
5+
let emptyUnaryWithAttributes = <input type_="text" />
6+
7+
let emptyNonunaryWithAttributes = <div className="container"></div>
8+
9+
let elementWithChildren = <div>
10+
<h1>{React.string("Hi")}</h1>
11+
<p>{React.string("Hello")}</p>
12+
</div>
13+
14+
let elementWithChildrenAndAttributes = <div className="container">
15+
<h1>{React.string("Hi")}</h1>
16+
<p>{React.string("Hello")}</p>
17+
</div>
18+
19+
let elementWithConditionalChildren = <div>
20+
{if true {
21+
<h1>{React.string("Hi")}</h1>
22+
} else {
23+
React.null
24+
}}
25+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
let empty = <></>
2+
3+
let fragmentWithBracedExpresssion = <>{React.int(1 + 2)}</>
4+
5+
let fragmentWithJSXElements = <>
6+
<h1>{React.string("Hi")}</h1>
7+
<p>{React.string("Hello")}</p>
8+
</>
9+
10+
let nestedFragments = <>
11+
<h1>{React.string("Hi")}</h1>
12+
<p>{React.string("Hello")}</p>
13+
<>{React.string("Bye")}</>
14+
</>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
let emptyUnary = ReactDOM.jsx("input", {})
2+
3+
let emptyNonunary = ReactDOM.jsx("div", {})
4+
5+
let emptyUnaryWithAttributes = ReactDOM.jsx("input", {type_: "text"})
6+
7+
let emptyNonunaryWithAttributes = ReactDOM.jsx("div", {className: "container"})
8+
9+
let elementWithChildren = ReactDOM.jsxs(
10+
"div",
11+
{
12+
children: React.array([
13+
ReactDOM.jsx("h1", {children: ?ReactDOM.someElement({React.string("Hi")})}),
14+
ReactDOM.jsx("p", {children: ?ReactDOM.someElement({React.string("Hello")})}),
15+
]),
16+
},
17+
)
18+
19+
let elementWithChildrenAndAttributes = ReactDOM.jsxs(
20+
"div",
21+
{
22+
className: "container",
23+
children: React.array([
24+
ReactDOM.jsx("h1", {children: ?ReactDOM.someElement({React.string("Hi")})}),
25+
ReactDOM.jsx("p", {children: ?ReactDOM.someElement({React.string("Hello")})}),
26+
]),
27+
},
28+
)
29+
30+
let elementWithConditionalChildren = ReactDOM.jsx(
31+
"div",
32+
{
33+
children: ?ReactDOM.someElement({
34+
if true {
35+
ReactDOM.jsx("h1", {children: ?ReactDOM.someElement({React.string("Hi")})})
36+
} else {
37+
React.null
38+
}
39+
}),
40+
},
41+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
let empty = React.jsx(React.jsxFragment, {})
2+
3+
let fragmentWithBracedExpresssion = React.jsx(React.jsxFragment, {children: {React.int(1 + 2)}})
4+
5+
let fragmentWithJSXElements = React.jsxs(
6+
React.jsxFragment,
7+
{
8+
children: React.array([
9+
ReactDOM.jsx("h1", {children: ?ReactDOM.someElement({React.string("Hi")})}),
10+
ReactDOM.jsx("p", {children: ?ReactDOM.someElement({React.string("Hello")})}),
11+
]),
12+
},
13+
)
14+
15+
let nestedFragments = React.jsxs(
16+
React.jsxFragment,
17+
{
18+
children: React.array([
19+
ReactDOM.jsx("h1", {children: ?ReactDOM.someElement({React.string("Hi")})}),
20+
ReactDOM.jsx("p", {children: ?ReactDOM.someElement({React.string("Hello")})}),
21+
React.jsx(React.jsxFragment, {children: {React.string("Bye")}}),
22+
]),
23+
},
24+
)

0 commit comments

Comments
 (0)