Skip to content

Commit b277f33

Browse files
zthcristianoc
authored andcommitted
follow tuples
1 parent 4cd9c66 commit b277f33

File tree

3 files changed

+59
-26
lines changed

3 files changed

+59
-26
lines changed

analysis/src/TypeUtils.ml

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,15 @@ let rec resolveNested (typ : completionType) ~env ~full ~nested =
349349
typ |> resolveNested ~env ~full ~nested)
350350
| _ -> None)
351351

352+
let findTypeOfRecordField fields ~fieldName =
353+
match
354+
fields |> List.find_opt (fun (field : field) -> field.fname.txt = fieldName)
355+
with
356+
| None -> None
357+
| Some {typ; optional} ->
358+
let typ = if optional then Utils.unwrapIfOption typ else typ in
359+
Some typ
360+
352361
let rec resolveNestedPatternPath (typ : innerType) ~env ~full ~nested =
353362
let t =
354363
match typ with
@@ -364,14 +373,13 @@ let rec resolveNestedPatternPath (typ : innerType) ~env ~full ~nested =
364373
match (finalPatternPath, completionType) with
365374
| ( Completable.NFollowRecordField {fieldName},
366375
(TinlineRecord {env; fields} | Trecord {env; fields}) ) -> (
367-
match
368-
fields
369-
|> List.find_opt (fun (field : field) -> field.fname.txt = fieldName)
370-
with
376+
match fields |> findTypeOfRecordField ~fieldName with
377+
| None -> None
378+
| Some typ -> Some (TypeExpr typ, env))
379+
| NTupleItem {itemNum}, Tuple (env, tupleItems, _) -> (
380+
match List.nth_opt tupleItems itemNum with
371381
| None -> None
372-
| Some {typ; optional} ->
373-
let typ = if optional then Utils.unwrapIfOption typ else typ in
374-
Some (TypeExpr typ, env))
382+
| Some typ -> Some (TypeExpr typ, env))
375383
| _ -> None))
376384
| patternPath :: nested -> (
377385
match t with
@@ -380,13 +388,18 @@ let rec resolveNestedPatternPath (typ : innerType) ~env ~full ~nested =
380388
match (patternPath, completionType) with
381389
| ( Completable.NFollowRecordField {fieldName},
382390
(TinlineRecord {env; fields} | Trecord {env; fields}) ) -> (
383-
match
384-
fields
385-
|> List.find_opt (fun (field : field) -> field.fname.txt = fieldName)
386-
with
391+
match fields |> findTypeOfRecordField ~fieldName with
392+
| None -> None
393+
| Some typ ->
394+
typ
395+
|> extractType ~env ~package:full.package
396+
|> Utils.Option.flatMap (fun typ ->
397+
ExtractedType typ
398+
|> resolveNestedPatternPath ~env ~full ~nested))
399+
| NTupleItem {itemNum}, Tuple (env, tupleItems, _) -> (
400+
match List.nth_opt tupleItems itemNum with
387401
| None -> None
388-
| Some {typ; optional} ->
389-
let typ = if optional then Utils.unwrapIfOption typ else typ in
402+
| Some typ ->
390403
typ
391404
|> extractType ~env ~package:full.package
392405
|> Utils.Option.flatMap (fun typ ->

analysis/tests/src/CompletionInferValues.res

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,26 @@ type someRecordWithNestedStuff = {
7171

7272
type otherNestedRecord = {someRecord: someRecord, someTuple: (someVariant, int)}
7373

74+
// Destructure record
7475
// let x: someRecordWithNestedStuff = Obj.magic(); let {srecord} = x; srecord.
7576
// ^com
7677

78+
// Follow aliased
7779
// let x: someRecordWithNestedStuff = Obj.magic(); let {nested: aliased} = x; aliased.
7880
// ^com
7981

82+
// Follow nested record
8083
// let x: someRecordWithNestedStuff = Obj.magic(); let {srecord, nested: {someRecord}} = x; someRecord.
8184
// ^com
8285

86+
// Destructure string
8387
// let x: someRecordWithNestedStuff = Obj.magic(); let {things} = x; things->slic
8488
// ^com
8589

90+
// Destructure int
8691
// let x: someRecordWithNestedStuff = Obj.magic(); let {someInt} = x; someInt->toS
8792
// ^com
93+
94+
// Follow tuples
95+
// let x: otherNestedRecord = Obj.magic(); let {someTuple} = x; let (_, someInt) = someTuple; someInt->toS
96+
// ^com

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

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,9 @@ Completable: Cpath Value[x].""
220220
"documentation": null
221221
}]
222222

223-
Complete src/CompletionInferValues.res 73:78
224-
posCursor:[73:78] posNoWhite:[73:77] Found expr:[73:70->73:78]
225-
Pexp_field [73:70->73:77] _:[88:0->73:78]
223+
Complete src/CompletionInferValues.res 74:78
224+
posCursor:[74:78] posNoWhite:[74:77] Found expr:[74:70->74:78]
225+
Pexp_field [74:70->74:77] _:[97:0->74:78]
226226
Completable: Cpath Value[srecord].""
227227
[{
228228
"label": "name",
@@ -238,9 +238,9 @@ Completable: Cpath Value[srecord].""
238238
"documentation": null
239239
}]
240240

241-
Complete src/CompletionInferValues.res 76:86
242-
posCursor:[76:86] posNoWhite:[76:85] Found expr:[76:78->76:86]
243-
Pexp_field [76:78->76:85] _:[88:0->76:86]
241+
Complete src/CompletionInferValues.res 78:86
242+
posCursor:[78:86] posNoWhite:[78:85] Found expr:[78:78->78:86]
243+
Pexp_field [78:78->78:85] _:[97:0->78:86]
244244
Completable: Cpath Value[aliased].""
245245
[{
246246
"label": "someRecord",
@@ -250,9 +250,9 @@ Completable: Cpath Value[aliased].""
250250
"documentation": null
251251
}]
252252

253-
Complete src/CompletionInferValues.res 79:103
254-
posCursor:[79:103] posNoWhite:[79:102] Found expr:[79:92->79:103]
255-
Pexp_field [79:92->79:102] _:[88:0->79:103]
253+
Complete src/CompletionInferValues.res 82:103
254+
posCursor:[82:103] posNoWhite:[82:102] Found expr:[82:92->82:103]
255+
Pexp_field [82:92->82:102] _:[97:0->82:103]
256256
Completable: Cpath Value[someRecord].""
257257
[{
258258
"label": "name",
@@ -268,8 +268,8 @@ Completable: Cpath Value[someRecord].""
268268
"documentation": null
269269
}]
270270

271-
Complete src/CompletionInferValues.res 82:81
272-
posCursor:[82:81] posNoWhite:[82:80] Found expr:[82:69->82:81]
271+
Complete src/CompletionInferValues.res 86:81
272+
posCursor:[86:81] posNoWhite:[86:80] Found expr:[86:69->86:81]
273273
Completable: Cpath Value[things]->slic
274274
[{
275275
"label": "Js.String2.sliceToEnd",
@@ -285,8 +285,19 @@ Completable: Cpath Value[things]->slic
285285
"documentation": {"kind": "markdown", "value": "\n`slice(str, from:n1, to_:n2)` returns the substring of `str` starting at\ncharacter `n1` up to but not including `n2`.\n- If either `n1` or `n2` is negative, then it is evaluated as `length(str - n1)` or `length(str - n2)`.\n- If `n2` is greater than the length of `str`, then it is treated as `length(str)`.\n- If `n1` is greater than `n2`, slice returns the empty string.\n\nSee [`String.slice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice) on MDN.\n\n```res example\nJs.String2.slice(\"abcdefg\", ~from=2, ~to_=5) == \"cde\"\nJs.String2.slice(\"abcdefg\", ~from=2, ~to_=9) == \"cdefg\"\nJs.String2.slice(\"abcdefg\", ~from=-4, ~to_=-2) == \"de\"\nJs.String2.slice(\"abcdefg\", ~from=5, ~to_=1) == \"\"\n```\n"}
286286
}]
287287

288-
Complete src/CompletionInferValues.res 85:82
289-
posCursor:[85:82] posNoWhite:[85:81] Found expr:[85:70->85:82]
288+
Complete src/CompletionInferValues.res 90:82
289+
posCursor:[90:82] posNoWhite:[90:81] Found expr:[90:70->90:82]
290+
Completable: Cpath Value[someInt]->toS
291+
[{
292+
"label": "Belt.Int.toString",
293+
"kind": 12,
294+
"tags": [],
295+
"detail": "int => string",
296+
"documentation": {"kind": "markdown", "value": "\n Converts a given `int` to a `string`. Uses the JavaScript `String` constructor under the hood.\n\n ```res example\n Js.log(Belt.Int.toString(1) === \"1\") /* true */\n ```\n"}
297+
}]
298+
299+
Complete src/CompletionInferValues.res 94:106
300+
posCursor:[94:106] posNoWhite:[94:105] Found expr:[94:94->94:106]
290301
Completable: Cpath Value[someInt]->toS
291302
[{
292303
"label": "Belt.Int.toString",

0 commit comments

Comments
 (0)