Skip to content

Commit 91c17b3

Browse files
committed
suggest using jsx fragment where appropriate
1 parent f34ade1 commit 91c17b3

File tree

3 files changed

+53
-4
lines changed

3 files changed

+53
-4
lines changed

compiler/ml/error_message_utils.ml

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -353,11 +353,24 @@ let print_extra_type_clash_help ~extract_concrete_typedecl ~env loc ppf
353353
->
354354
fprintf ppf
355355
"@,@,Dicts are written like: @{<info>dict{\"a\": 1, \"b\": 2}@}@,"
356-
| _, Some ({Types.desc = Tconstr (_p1, _, _)}, {desc = Tconstr (p2, _, _)})
356+
| ( _,
357+
Some
358+
(({Types.desc = Tconstr (_p1, _, _)} as ty), {desc = Tconstr (p2, _, _)})
359+
)
357360
when Path.same Predef.path_unit p2 ->
361+
fprintf ppf "\n\n";
362+
let is_jsx_element =
363+
match Ctype.expand_head env ty with
364+
| {desc = Tconstr (Pdot (Pident {name = "Jsx"}, "element", _), _, _)} ->
365+
true
366+
| _ -> false
367+
in
368+
if is_jsx_element then
369+
fprintf ppf
370+
" - Did you forget to wrap this + adjacent JSX in a JSX fragment \
371+
(@{<info><></>@})?\n";
358372
fprintf ppf
359-
"\n\n\
360-
\ - Did you mean to assign this to a variable?\n\
373+
" - Did you mean to assign this to a variable?\n\
361374
\ - If you don't care about the result of this expression, you can \
362375
assign it to @{<info>_@} via @{<info>let _ = ...@} or pipe it to \
363376
@{<info>ignore@} via @{<info>expression->ignore@}\n\n"
@@ -714,7 +727,7 @@ let type_clash_context_maybe_option ty_expected ty_res =
714727
715728
let type_clash_context_in_statement sexp =
716729
match sexp.Parsetree.pexp_desc with
717-
| Pexp_apply _ -> Some (Statement FunctionCall)
730+
| Pexp_apply {transformed_jsx = false} -> Some (Statement FunctionCall)
718731
| _ -> None
719732
720733
let print_contextual_unification_error ppf t1 t2 =
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
We've found a bug for you!
3+
/.../fixtures/jsx_maybe_missing_fragment.res:18:3-8
4+
5+
16 │
6+
17 │ let x = {
7+
18 │ <> </>
8+
19 │ <> </>
9+
20 │ }
10+
11+
This has type: React.element (defined as Jsx.element)
12+
But it's expected to have type: unit
13+
14+
- Did you forget to wrap this + adjacent JSX in a JSX fragment (<></>)?
15+
- Did you mean to assign this to a variable?
16+
- If you don't care about the result of this expression, you can assign it to _ via let _ = ... or pipe it to ignore via expression->ignore
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
@@config({
2+
flags: ["-bs-jsx", "4"],
3+
})
4+
5+
module React = {
6+
type element = Jsx.element
7+
type componentLike<'props, 'return> = 'props => 'return
8+
type component<'props> = Jsx.component<'props>
9+
10+
@module("react/jsx-runtime")
11+
external jsx: (component<'props>, 'props) => element = "jsx"
12+
13+
type fragmentProps = {children?: element}
14+
@module("react/jsx-runtime") external jsxFragment: component<fragmentProps> = "Fragment"
15+
}
16+
17+
let x = {
18+
<> </>
19+
<> </>
20+
}

0 commit comments

Comments
 (0)