Skip to content

Commit b5fcd07

Browse files
authored
Add completion for type t values (#924)
* Add completion for type t values * Update snapshots * Add test * Add test for labeled arg as well * Fixes after review
1 parent 3b996bb commit b5fcd07

File tree

4 files changed

+157
-34
lines changed

4 files changed

+157
-34
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
- Latest parser for newest syntax features. https://github.com/rescript-lang/rescript-vscode/pull/917
2222
- Handle completion for DOM/element attributes and attribute values properly when using a generic JSX transform. https://github.com/rescript-lang/rescript-vscode/pull/919
2323
- Highlight tagged template literal functions as functions. https://github.com/rescript-lang/rescript-vscode/pull/920
24+
- Complete for `type t` values when encountering a `type t` in relevant scenarios. https://github.com/rescript-lang/rescript-vscode/pull/924
2425

2526
## 1.38.0
2627

analysis/src/CompletionBackEnd.ml

+45-31
Original file line numberDiff line numberDiff line change
@@ -1257,6 +1257,12 @@ let rec completeTypedValue ?(typeArgContext : typeArgContext option) ~rawOpens
12571257
match t with
12581258
| TtypeT {env; path} ->
12591259
if Debug.verbose () then print_endline "[complete_typed_value]--> TtypeT";
1260+
(* Find all values in the module with type t *)
1261+
let valueWithTypeT t =
1262+
match t.Types.desc with
1263+
| Tconstr (Pident {name = "t"}, [], _) -> true
1264+
| _ -> false
1265+
in
12601266
(* Find all functions in the module that returns type t *)
12611267
let rec fnReturnsTypeT t =
12621268
match t.Types.desc with
@@ -1277,41 +1283,49 @@ let rec completeTypedValue ?(typeArgContext : typeArgContext option) ~rawOpens
12771283
| _ -> false)
12781284
| _ -> false
12791285
in
1280-
let functionsReturningTypeT =
1281-
Hashtbl.create (Hashtbl.length env.exported.values_)
1286+
let getCompletionName exportedValueName =
1287+
let fnNname =
1288+
TypeUtils.getPathRelativeToEnv ~debug:false
1289+
~env:(QueryEnv.fromFile full.file)
1290+
~envFromItem:env (Utils.expandPath path)
1291+
in
1292+
match fnNname with
1293+
| None -> None
1294+
| Some base ->
1295+
let base =
1296+
TypeUtils.removeOpensFromCompletionPath ~rawOpens
1297+
~package:full.package base
1298+
in
1299+
Some ((base |> String.concat ".") ^ "." ^ exportedValueName)
1300+
in
1301+
let getExportedValueCompletion name (declared : Types.type_expr Declared.t)
1302+
=
1303+
let typeExpr = declared.item in
1304+
if valueWithTypeT typeExpr then
1305+
getCompletionName name
1306+
|> Option.map (fun name ->
1307+
createWithSnippet ~name ~insertText:name ~kind:(Value typeExpr)
1308+
~env ())
1309+
else if fnReturnsTypeT typeExpr then
1310+
getCompletionName name
1311+
|> Option.map (fun name ->
1312+
createWithSnippet
1313+
~name:(Printf.sprintf "%s()" name)
1314+
~insertText:(name ^ "($0)") ~kind:(Value typeExpr) ~env ())
1315+
else None
12821316
in
1283-
env.exported.values_
1284-
|> Hashtbl.iter (fun name stamp ->
1285-
match Stamps.findValue env.file.stamps stamp with
1286-
| None -> ()
1287-
| Some {item} -> (
1288-
if fnReturnsTypeT item then
1289-
let fnNname =
1290-
TypeUtils.getPathRelativeToEnv ~debug:false
1291-
~env:(QueryEnv.fromFile full.file)
1292-
~envFromItem:env (Utils.expandPath path)
1293-
in
1294-
1295-
match fnNname with
1296-
| None -> ()
1297-
| Some base ->
1298-
let base =
1299-
TypeUtils.removeOpensFromCompletionPath ~rawOpens
1300-
~package:full.package base
1301-
in
1302-
Hashtbl.add functionsReturningTypeT
1303-
((base |> String.concat ".") ^ "." ^ name)
1304-
item));
1305-
13061317
let completionItems =
13071318
Hashtbl.fold
1308-
(fun fnName typeExpr all ->
1309-
createWithSnippet
1310-
~name:(Printf.sprintf "%s()" fnName)
1311-
~insertText:(fnName ^ "($0)") ~kind:(Value typeExpr) ~env ()
1312-
:: all)
1313-
functionsReturningTypeT []
1319+
(fun name stamp all ->
1320+
match Stamps.findValue env.file.stamps stamp with
1321+
| None -> all
1322+
| Some declaredTypeExpr -> (
1323+
match getExportedValueCompletion name declaredTypeExpr with
1324+
| None -> all
1325+
| Some completion -> completion :: all))
1326+
env.exported.values_ []
13141327
in
1328+
13151329
(* Special casing for things where we want extra things in the completions *)
13161330
let completionItems =
13171331
match path with

analysis/tests/src/CompletionExpressions.res

+36
Original file line numberDiff line numberDiff line change
@@ -321,3 +321,39 @@ let mkStuff = (r: Js.Re.t) => {
321321

322322
// mkStuff()
323323
// ^com
324+
325+
module Money: {
326+
type t
327+
328+
let zero: t
329+
330+
let nonTType: string
331+
332+
let make: unit => t
333+
334+
let fromInt: int => t
335+
336+
let plus: (t, t) => t
337+
} = {
338+
type t = string
339+
340+
let zero: t = "0"
341+
342+
let nonTType = "0"
343+
344+
let make = (): t => zero
345+
346+
let fromInt = (int): t => int->Js.Int.toString
347+
348+
let plus = (m1, _) => m1
349+
}
350+
351+
let tArgCompletionTestFn = (tVal: Money.t) => ()
352+
353+
// tArgCompletionTestFn()
354+
// ^com
355+
356+
let labeledTArgCompletionTestFn = (~tVal: Money.t) => ()
357+
358+
// labeledTArgCompletionTestFn(~tVal=)
359+
// ^com

analysis/tests/src/expected/CompletionExpressions.res.txt

+75-3
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,14 @@ Path mkStuff
13141314
"documentation": null,
13151315
"insertText": "%re(\"/$0/g\")",
13161316
"insertTextFormat": 2
1317+
}, {
1318+
"label": "Js.Re.fromString()",
1319+
"kind": 12,
1320+
"tags": [],
1321+
"detail": "string => t",
1322+
"documentation": null,
1323+
"insertText": "Js.Re.fromString($0)",
1324+
"insertTextFormat": 2
13171325
}, {
13181326
"label": "Js.Re.fromStringWithFlags()",
13191327
"kind": 12,
@@ -1322,13 +1330,77 @@ Path mkStuff
13221330
"documentation": null,
13231331
"insertText": "Js.Re.fromStringWithFlags($0)",
13241332
"insertTextFormat": 2
1333+
}]
1334+
1335+
Complete src/CompletionExpressions.res 352:24
1336+
posCursor:[352:24] posNoWhite:[352:23] Found expr:[352:3->352:25]
1337+
Pexp_apply ...[352:3->352:23] (...[352:24->352:25])
1338+
Completable: Cexpression CArgument Value[tArgCompletionTestFn]($0)
1339+
Raw opens: 1 CompletionSupport.place holder
1340+
Package opens Pervasives.JsxModules.place holder
1341+
Resolved opens 2 pervasives CompletionSupport.res
1342+
ContextPath CArgument Value[tArgCompletionTestFn]($0)
1343+
ContextPath Value[tArgCompletionTestFn]
1344+
Path tArgCompletionTestFn
1345+
[{
1346+
"label": "Money.fromInt()",
1347+
"kind": 12,
1348+
"tags": [],
1349+
"detail": "int => t",
1350+
"documentation": null,
1351+
"insertText": "Money.fromInt($0)",
1352+
"insertTextFormat": 2
13251353
}, {
1326-
"label": "Js.Re.fromString()",
1354+
"label": "Money.make()",
13271355
"kind": 12,
13281356
"tags": [],
1329-
"detail": "string => t",
1357+
"detail": "unit => t",
13301358
"documentation": null,
1331-
"insertText": "Js.Re.fromString($0)",
1359+
"insertText": "Money.make($0)",
1360+
"insertTextFormat": 2
1361+
}, {
1362+
"label": "Money.zero",
1363+
"kind": 12,
1364+
"tags": [],
1365+
"detail": "t",
1366+
"documentation": null,
1367+
"insertText": "Money.zero",
1368+
"insertTextFormat": 2
1369+
}]
1370+
1371+
Complete src/CompletionExpressions.res 357:37
1372+
posCursor:[357:37] posNoWhite:[357:36] Found expr:[357:3->357:38]
1373+
Pexp_apply ...[357:3->357:30] (~tVal357:32->357:36=...__ghost__[0:-1->0:-1])
1374+
Completable: Cexpression CArgument Value[labeledTArgCompletionTestFn](~tVal)
1375+
Raw opens: 1 CompletionSupport.place holder
1376+
Package opens Pervasives.JsxModules.place holder
1377+
Resolved opens 2 pervasives CompletionSupport.res
1378+
ContextPath CArgument Value[labeledTArgCompletionTestFn](~tVal)
1379+
ContextPath Value[labeledTArgCompletionTestFn]
1380+
Path labeledTArgCompletionTestFn
1381+
[{
1382+
"label": "Money.fromInt()",
1383+
"kind": 12,
1384+
"tags": [],
1385+
"detail": "int => t",
1386+
"documentation": null,
1387+
"insertText": "Money.fromInt($0)",
1388+
"insertTextFormat": 2
1389+
}, {
1390+
"label": "Money.make()",
1391+
"kind": 12,
1392+
"tags": [],
1393+
"detail": "unit => t",
1394+
"documentation": null,
1395+
"insertText": "Money.make($0)",
1396+
"insertTextFormat": 2
1397+
}, {
1398+
"label": "Money.zero",
1399+
"kind": 12,
1400+
"tags": [],
1401+
"detail": "t",
1402+
"documentation": null,
1403+
"insertText": "Money.zero",
13321404
"insertTextFormat": 2
13331405
}]
13341406

0 commit comments

Comments
 (0)