Skip to content

Commit c79b033

Browse files
authored
Suggest using JSX fragment where appropriate (#7714)
* suggest using jsx fragment where appropriate * changelog * update message
1 parent f34ade1 commit c79b033

File tree

4 files changed

+62
-9
lines changed

4 files changed

+62
-9
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
1313
# 12.0.0-beta.4 (Unreleased)
1414

15+
#### :nail_care: Polish
16+
17+
- Apply heuristic to suggest using JSX fragments where we guess that might be what the user wanted. https://github.com/rescript-lang/rescript/pull/7714
18+
1519
# 12.0.0-beta.3
1620

1721
#### :boom: Breaking Change
@@ -50,7 +54,6 @@
5054
- Remove all leftovers of `pinned-dependencies` handling. https://github.com/rescript-lang/rescript/pull/7686
5155
- Add `rust-version` field to Rewatch's `Cargo.toml`. https://github.com/rescript-lang/rescript/pull/7701
5256

53-
5457
# 12.0.0-beta.2
5558

5659
#### :boom: Breaking Change

compiler/ml/error_message_utils.ml

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -353,14 +353,29 @@ 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 ->
358-
fprintf ppf
359-
"\n\n\
360-
\ - Did you mean to assign this to a variable?\n\
361-
\ - If you don't care about the result of this expression, you can \
362-
assign it to @{<info>_@} via @{<info>let _ = ...@} or pipe it to \
363-
@{<info>ignore@} via @{<info>expression->ignore@}\n\n"
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\
372+
\ - Did you mean to assign this to a variable?\n\n"
373+
else
374+
fprintf ppf
375+
" - Did you mean to assign this to a variable?\n\
376+
\ - If you don't care about the result of this expression, you can \
377+
assign it to @{<info>_@} via @{<info>let _ = ...@} or pipe it to \
378+
@{<info>ignore@} via @{<info>expression->ignore@}\n\n"
364379
| _, Some ({desc = Tobject _}, ({Types.desc = Tconstr _} as t1))
365380
when is_record_type ~extract_concrete_typedecl ~env t1 ->
366381
fprintf ppf
@@ -714,7 +729,7 @@ let type_clash_context_maybe_option ty_expected ty_res =
714729
715730
let type_clash_context_in_statement sexp =
716731
match sexp.Parsetree.pexp_desc with
717-
| Pexp_apply _ -> Some (Statement FunctionCall)
732+
| Pexp_apply {transformed_jsx = false} -> Some (Statement FunctionCall)
718733
| _ -> None
719734
720735
let print_contextual_unification_error ppf t1 t2 =
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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?
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)