Skip to content

Commit 9ca7f6d

Browse files
committed
Add support for prop completion for JSX V4
rescript-lang/rescript#5406
1 parent 6f8e6e0 commit 9ca7f6d

File tree

4 files changed

+77
-8
lines changed

4 files changed

+77
-8
lines changed

Diff for: CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
1313
## master
1414

15+
#### :rocket: New Feature
16+
17+
- Add support for prop completion for JSX V4
18+
1519
## v1.6.0
1620

1721
#### :rocket: New Feature

Diff for: analysis/src/CompletionBackEnd.ml

+43-8
Original file line numberDiff line numberDiff line change
@@ -1427,16 +1427,39 @@ let processCompletable ~debug ~package ~scope ~env ~pos ~forHover
14271427
| Cjsx (componentPath, prefix, identsSeen) ->
14281428
let labels =
14291429
match componentPath @ ["make"] |> findTypeOfValue with
1430-
| Some (typ, _env) ->
1431-
let rec getFields (texp : Types.type_expr) =
1430+
| Some (typ, make_env) ->
1431+
let rec getFieldsV3 (texp : Types.type_expr) =
14321432
match texp.desc with
14331433
| Tfield (name, _, t1, t2) ->
1434-
let fields = t2 |> getFields in
1434+
let fields = t2 |> getFieldsV3 in
14351435
if name = "children" then fields else (name, t1) :: fields
1436-
| Tlink te | Tsubst te | Tpoly (te, []) -> te |> getFields
1436+
| Tlink te | Tsubst te | Tpoly (te, []) -> te |> getFieldsV3
14371437
| Tvar None -> []
14381438
| _ -> []
14391439
in
1440+
let getFieldsV4 ~path ~typeArgs =
1441+
match References.digConstructor ~env:make_env ~package path with
1442+
| Some
1443+
( _env,
1444+
{
1445+
item =
1446+
{
1447+
decl =
1448+
{
1449+
type_kind = Type_record (labelDecls, _repr);
1450+
type_params = typeParams;
1451+
};
1452+
};
1453+
} ) ->
1454+
labelDecls
1455+
|> List.map (fun (ld : Types.label_declaration) ->
1456+
let name = Ident.name ld.ld_id in
1457+
let t =
1458+
ld.ld_type |> instantiateType ~typeParams ~typeArgs
1459+
in
1460+
(name, t))
1461+
| _ -> []
1462+
in
14401463
let rec getLabels (t : Types.type_expr) =
14411464
match t.desc with
14421465
| Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> getLabels t1
@@ -1449,9 +1472,14 @@ let processCompletable ~debug ~package ~scope ~env ~pos ~forHover
14491472
},
14501473
_,
14511474
_ ) ->
1452-
getFields tObj
1475+
(* JSX V3 *)
1476+
getFieldsV3 tObj
1477+
| Tarrow (Nolabel, {desc = Tconstr (path, typeArgs, _)}, _, _)
1478+
when Path.last path = "props" ->
1479+
(* JSX V4 *)
1480+
getFieldsV4 ~path ~typeArgs
14531481
| Tconstr
1454-
( path,
1482+
( clPath,
14551483
[
14561484
{
14571485
desc =
@@ -1461,8 +1489,14 @@ let processCompletable ~debug ~package ~scope ~env ~pos ~forHover
14611489
_;
14621490
],
14631491
_ )
1464-
when Path.name path = "React.componentLike" ->
1465-
getFields tObj
1492+
when Path.name clPath = "React.componentLike" ->
1493+
(* JSX V3 external or interface *)
1494+
getFieldsV3 tObj
1495+
| Tconstr (clPath, [{desc = Tconstr (path, typeArgs, _)}; _], _)
1496+
when Path.name clPath = "React.componentLike"
1497+
&& Path.last path = "props" ->
1498+
(* JSX V4 external or interface *)
1499+
getFieldsV4 ~path ~typeArgs
14661500
| _ -> []
14671501
in
14681502
typ |> getLabels
@@ -1480,6 +1514,7 @@ let processCompletable ~debug ~package ~scope ~env ~pos ~forHover
14801514
(labels
14811515
|> List.filter (fun (name, _t) ->
14821516
Utils.startsWith name prefix
1517+
&& name <> "key"
14831518
&& (forHover || not (List.mem name identsSeen)))
14841519
|> List.map mkLabel)
14851520
@ keyLabels

Diff for: analysis/tests/src/JsxV4.res

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
@@jsxConfig({version: 4})
2+
3+
module M4 = {
4+
@react.component
5+
let make = (~first, ~fun="", ~second="") => React.string(first ++ fun ++ second)
6+
}
7+
8+
let _ = <M4 first="abc" />
9+
// ^def
10+
11+
// <M4 first="abc" f
12+
// ^com

Diff for: analysis/tests/src/expected/JsxV4.res.txt

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Definition src/JsxV4.res 7:9
2+
getLocItem #9: heuristic for JSX variadic, e.g. <C> {x} {y} </C>
3+
heuristic for: [React.null, makeProps, make, createElementVariadic], give the loc of `make`
4+
n1:() n2:makeProps n3:make n4:createElement
5+
{"uri": "JsxV4.res", "range": {"start": {"line": 4, "character": 6}, "end": {"line": 4, "character": 10}}}
6+
7+
Complete src/JsxV4.res 10:20
8+
posCursor:[10:20] posNoWhite:[10:19] Found expr:[10:4->10:20]
9+
JSX <M4:[10:4->10:6] first[10:7->10:12]=...[10:13->10:18] f[10:19->10:20]=...[10:19->10:20]> _children:None
10+
Completable: Cjsx([M4], f, [first, f])
11+
[{
12+
"label": "fun",
13+
"kind": 4,
14+
"tags": [],
15+
"detail": "option<string>",
16+
"documentation": null
17+
}]
18+

0 commit comments

Comments
 (0)