Skip to content

Commit 4cd9c66

Browse files
zthcristianoc
authored andcommitted
start working on moving through nested pattern paths
1 parent 46a1349 commit 4cd9c66

File tree

4 files changed

+104
-39
lines changed

4 files changed

+104
-39
lines changed

analysis/src/CompletionBackEnd.ml

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -606,10 +606,6 @@ let completionsGetTypeEnv = function
606606

607607
type getCompletionsForContextPathMode = Regular | Pipe
608608

609-
type completionsTypeEnvTyp =
610-
| TypeExpr of Types.type_expr
611-
| ExtractedType of completionType
612-
613609
let completionsGetCompletionType ~full = function
614610
| {Completion.kind = Value typ; env} :: _
615611
| {Completion.kind = ObjLabel typ; env} :: _
@@ -1098,21 +1094,10 @@ and getCompletionsForContextPath ~full ~opens ~rawOpens ~allFiles ~pos ~env
10981094
~scope
10991095
with
11001096
| Some (typ, env) -> (
1101-
let typ =
1102-
match typ with
1103-
| ExtractedType typ -> Some typ
1104-
| TypeExpr typ -> typ |> TypeUtils.extractType ~env ~package
1105-
in
1106-
match typ with
1107-
| None -> []
1108-
| Some typ -> (
1109-
match typ |> TypeUtils.resolveNested ~env ~full ~nested with
1110-
| Some (typ, env, _completionContext) ->
1111-
[
1112-
Completion.create "dummy" ~env
1113-
~kind:(Completion.ExtractedType (typ, `Value));
1114-
]
1115-
| None -> []))
1097+
match typ |> TypeUtils.resolveNestedPatternPath ~env ~full ~nested with
1098+
| Some (typ, env) ->
1099+
[Completion.create "dummy" ~env ~kind:(kindFromInnerType typ)]
1100+
| None -> [])
11161101
| None -> [])
11171102

11181103
let getOpens ~debug ~rawOpens ~package ~env =

analysis/src/TypeUtils.ml

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

352+
let rec resolveNestedPatternPath (typ : innerType) ~env ~full ~nested =
353+
let t =
354+
match typ with
355+
| TypeExpr t -> t |> extractType ~env ~package:full.package
356+
| ExtractedType t -> Some t
357+
in
358+
match nested with
359+
| [] -> None
360+
| [finalPatternPath] -> (
361+
match t with
362+
| None -> None
363+
| Some completionType -> (
364+
match (finalPatternPath, completionType) with
365+
| ( Completable.NFollowRecordField {fieldName},
366+
(TinlineRecord {env; fields} | Trecord {env; fields}) ) -> (
367+
match
368+
fields
369+
|> List.find_opt (fun (field : field) -> field.fname.txt = fieldName)
370+
with
371+
| None -> None
372+
| Some {typ; optional} ->
373+
let typ = if optional then Utils.unwrapIfOption typ else typ in
374+
Some (TypeExpr typ, env))
375+
| _ -> None))
376+
| patternPath :: nested -> (
377+
match t with
378+
| None -> None
379+
| Some completionType -> (
380+
match (patternPath, completionType) with
381+
| ( Completable.NFollowRecordField {fieldName},
382+
(TinlineRecord {env; fields} | Trecord {env; fields}) ) -> (
383+
match
384+
fields
385+
|> List.find_opt (fun (field : field) -> field.fname.txt = fieldName)
386+
with
387+
| None -> None
388+
| Some {typ; optional} ->
389+
let typ = if optional then Utils.unwrapIfOption typ else typ in
390+
typ
391+
|> extractType ~env ~package:full.package
392+
|> Utils.Option.flatMap (fun typ ->
393+
ExtractedType typ
394+
|> resolveNestedPatternPath ~env ~full ~nested))
395+
| _ -> None))
396+
352397
let getArgs ~env (t : Types.type_expr) ~full =
353398
let rec getArgsLoop ~env (t : Types.type_expr) ~full ~currentArgumentPosition
354399
=

analysis/tests/src/CompletionInferValues.res

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,18 +63,25 @@ type someNestedRecord = {someRecord: someRecord}
6363

6464
type someRecordWithNestedStuff = {
6565
things: string,
66+
someInt: int,
6667
srecord: someRecord,
6768
nested: someNestedRecord,
6869
someStuff: bool,
6970
}
7071

7172
type otherNestedRecord = {someRecord: someRecord, someTuple: (someVariant, int)}
7273

73-
// let x: someRecordWithNestedStuff = {things: "", someRecord: {name: "Hello", age: 123}, someStuff: true}; let {srecord} = x; srecord.
74-
// ^com
74+
// let x: someRecordWithNestedStuff = Obj.magic(); let {srecord} = x; srecord.
75+
// ^com
7576

76-
// let x: someRecordWithNestedStuff = {things: "", someRecord: {name: "Hello", age: 123}, someStuff: true}; let {nested: aliased} = x; aliased.
77-
// ^com
77+
// let x: someRecordWithNestedStuff = Obj.magic(); let {nested: aliased} = x; aliased.
78+
// ^com
7879

79-
// let x: someRecordWithNestedStuff = {things: "", someRecord: {name: "Hello", age: 123}, someStuff: true}; let {srecord, nested: {someRecord}} = x; someRecord.
80-
// ^com
80+
// let x: someRecordWithNestedStuff = Obj.magic(); let {srecord, nested: {someRecord}} = x; someRecord.
81+
// ^com
82+
83+
// let x: someRecordWithNestedStuff = Obj.magic(); let {things} = x; things->slic
84+
// ^com
85+
86+
// let x: someRecordWithNestedStuff = Obj.magic(); let {someInt} = x; someInt->toS
87+
// ^com

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

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

223-
Complete src/CompletionInferValues.res 72:135
224-
posCursor:[72:135] posNoWhite:[72:134] Found expr:[72:127->72:135]
225-
Pexp_field [72:127->72:134] _:[81:0->72:135]
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]
226226
Completable: Cpath Value[srecord].""
227227
[{
228228
"label": "name",
229229
"kind": 5,
230230
"tags": [],
231-
"detail": "name: string\n\nsomeRecord",
231+
"detail": "name: string\n\ntype someRecord = {name: string, age: int}",
232232
"documentation": null
233233
}, {
234234
"label": "age",
235235
"kind": 5,
236236
"tags": [],
237-
"detail": "age: int\n\nsomeRecord",
237+
"detail": "age: int\n\ntype someRecord = {name: string, age: int}",
238238
"documentation": null
239239
}]
240240

241-
Complete src/CompletionInferValues.res 75:143
242-
posCursor:[75:143] posNoWhite:[75:142] Found expr:[75:135->75:143]
243-
Pexp_field [75:135->75:142] _:[81:0->75:143]
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]
244244
Completable: Cpath Value[aliased].""
245245
[{
246246
"label": "someRecord",
247247
"kind": 5,
248248
"tags": [],
249-
"detail": "someRecord: someRecord\n\nsomeNestedRecord",
249+
"detail": "someRecord: someRecord\n\ntype someNestedRecord = {someRecord: someRecord}",
250250
"documentation": null
251251
}]
252252

253-
Complete src/CompletionInferValues.res 78:160
254-
posCursor:[78:160] posNoWhite:[78:159] Found expr:[78:149->78:160]
255-
Pexp_field [78:149->78:159] _:[81:0->78:160]
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]
256256
Completable: Cpath Value[someRecord].""
257257
[{
258258
"label": "name",
259259
"kind": 5,
260260
"tags": [],
261-
"detail": "name: string\n\nsomeRecord",
261+
"detail": "name: string\n\ntype someRecord = {name: string, age: int}",
262262
"documentation": null
263263
}, {
264264
"label": "age",
265265
"kind": 5,
266266
"tags": [],
267-
"detail": "age: int\n\nsomeRecord",
267+
"detail": "age: int\n\ntype someRecord = {name: string, age: int}",
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]
273+
Completable: Cpath Value[things]->slic
274+
[{
275+
"label": "Js.String2.sliceToEnd",
276+
"kind": 12,
277+
"tags": [],
278+
"detail": "(t, ~from: int) => t",
279+
"documentation": {"kind": "markdown", "value": "\n`sliceToEnd(str, from:n)` returns the substring of `str` starting at character\n`n` to the end of the string.\n- If `n` is negative, then it is evaluated as `length(str - n)`.\n- If `n` is greater than the length of `str`, then sliceToEnd 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.sliceToEnd(\"abcdefg\", ~from=4) == \"efg\"\nJs.String2.sliceToEnd(\"abcdefg\", ~from=-2) == \"fg\"\nJs.String2.sliceToEnd(\"abcdefg\", ~from=7) == \"\"\n```\n"}
280+
}, {
281+
"label": "Js.String2.slice",
282+
"kind": 12,
283+
"tags": [],
284+
"detail": "(t, ~from: int, ~to_: int) => t",
285+
"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"}
286+
}]
287+
288+
Complete src/CompletionInferValues.res 85:82
289+
posCursor:[85:82] posNoWhite:[85:81] Found expr:[85:70->85: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+

0 commit comments

Comments
 (0)