From 7db9012ac063f156983d9161c9832429ac70671e Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 14 Jul 2022 21:56:13 +0200 Subject: [PATCH 01/80] add base test case for completing jsx prop and labelled argument --- analysis/tests/src/TypeContextCompletion.res | 22 +++++++++++++++++++ .../expected/TypeContextCompletion.res.txt | 9 ++++++++ 2 files changed, 31 insertions(+) create mode 100644 analysis/tests/src/TypeContextCompletion.res create mode 100644 analysis/tests/src/expected/TypeContextCompletion.res.txt diff --git a/analysis/tests/src/TypeContextCompletion.res b/analysis/tests/src/TypeContextCompletion.res new file mode 100644 index 000000000..cd4eecdac --- /dev/null +++ b/analysis/tests/src/TypeContextCompletion.res @@ -0,0 +1,22 @@ +type someVariant = One | Two | Three | Four + +let someVariantToString = (~someVariant) => + switch someVariant { + | One => "One" + | Two => "Two" + | Three => "Three" + | Four => "Four" + } + +// let someVariantToString(~someVariant= +// ^com + +module SomeComponent = { + @react.component + let make = (~whatever) => { + someVariantToString(~someVariant=whatever)->React.string + } +} + +// let jsx = 18:1] +[] + +Complete src/TypeContextCompletion.res 20:37 +posCursor:[20:37] posNoWhite:[20:36] Found expr:[20:14->20:37] +JSX 20:27] whatever[20:28->20:36]=...__ghost__[0:-1->0:-1]> _children:None +[] + From 4362bdf50de24af755ff3c64db83d623eda7c49d Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 14 Jul 2022 22:11:38 +0200 Subject: [PATCH 02/80] commit the rest of the updated test result files --- analysis/tests/src/expected/Completion.res.txt | 6 ++++++ analysis/tests/src/expected/Dce.res.txt | 2 +- analysis/tests/src/expected/Debug.res.txt | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index a32963ef6..3543634f4 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -1403,6 +1403,12 @@ Completable: Cpath Value[T] "tags": [], "detail": "file module", "documentation": null + }, { + "label": "TypeContextCompletion", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null }, { "label": "TypeDefinition", "kind": 9, diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index 308ef678c..c4c5eda20 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:235 +issues:241 diff --git a/analysis/tests/src/expected/Debug.res.txt b/analysis/tests/src/expected/Debug.res.txt index ff23fed2d..b609e3ed4 100644 --- a/analysis/tests/src/expected/Debug.res.txt +++ b/analysis/tests/src/expected/Debug.res.txt @@ -4,7 +4,7 @@ Dependencies: @rescript/react Source directories: ./node_modules/@rescript/react/src ./node_modules/@rescript/react/src/legacy Source files: ./node_modules/@rescript/react/src/React.res ./node_modules/@rescript/react/src/ReactDOM.res ./node_modules/@rescript/react/src/ReactDOMServer.res ./node_modules/@rescript/react/src/ReactDOMStyle.res ./node_modules/@rescript/react/src/ReactEvent.res ./node_modules/@rescript/react/src/ReactEvent.resi ./node_modules/@rescript/react/src/ReactTestUtils.res ./node_modules/@rescript/react/src/ReactTestUtils.resi ./node_modules/@rescript/react/src/RescriptReactErrorBoundary.res ./node_modules/@rescript/react/src/RescriptReactErrorBoundary.resi ./node_modules/@rescript/react/src/RescriptReactRouter.res ./node_modules/@rescript/react/src/RescriptReactRouter.resi ./node_modules/@rescript/react/src/legacy/ReactDOMRe.res ./node_modules/@rescript/react/src/legacy/ReasonReact.res Source directories: ./src ./src/expected -Source files: ./src/Auto.res ./src/CompletePrioritize1.res ./src/CompletePrioritize2.res ./src/Completion.res ./src/Component.res ./src/Component.resi ./src/CreateInterface.res ./src/Cross.res ./src/Dce.res ./src/Debug.res ./src/Definition.res ./src/DefinitionWithInterface.res ./src/DefinitionWithInterface.resi ./src/Div.res ./src/DocumentSymbol.res ./src/Fragment.res ./src/Highlight.res ./src/Hover.res ./src/Jsx.res ./src/Jsx.resi ./src/LongIdentTest.res ./src/Object.res ./src/Patterns.res ./src/RecModules.res ./src/RecordCompletion.res ./src/RecoveryOnProp.res ./src/References.res ./src/ReferencesWithInterface.res ./src/ReferencesWithInterface.resi ./src/Rename.res ./src/RenameWithInterface.res ./src/RenameWithInterface.resi ./src/TableclothMap.ml ./src/TableclothMap.mli ./src/TypeDefinition.res ./src/Xform.res +Source files: ./src/Auto.res ./src/CompletePrioritize1.res ./src/CompletePrioritize2.res ./src/Completion.res ./src/Component.res ./src/Component.resi ./src/CreateInterface.res ./src/Cross.res ./src/Dce.res ./src/Debug.res ./src/Definition.res ./src/DefinitionWithInterface.res ./src/DefinitionWithInterface.resi ./src/Div.res ./src/DocumentSymbol.res ./src/Fragment.res ./src/Highlight.res ./src/Hover.res ./src/Jsx.res ./src/Jsx.resi ./src/LongIdentTest.res ./src/Object.res ./src/Patterns.res ./src/RecModules.res ./src/RecordCompletion.res ./src/RecoveryOnProp.res ./src/References.res ./src/ReferencesWithInterface.res ./src/ReferencesWithInterface.resi ./src/Rename.res ./src/RenameWithInterface.res ./src/RenameWithInterface.resi ./src/TableclothMap.ml ./src/TableclothMap.mli ./src/TypeContextCompletion.res ./src/TypeDefinition.res ./src/Xform.res Impl cmt:./lib/bs/src/Auto.cmt res:./src/Auto.res Impl cmt:./lib/bs/src/CompletePrioritize1.cmt res:./src/CompletePrioritize1.res Impl cmt:./lib/bs/src/CompletePrioritize2.cmt res:./src/CompletePrioritize2.res @@ -33,6 +33,7 @@ IntfAndImpl cmti:./lib/bs/src/ReferencesWithInterface.cmti resi:./src/References Impl cmt:./lib/bs/src/Rename.cmt res:./src/Rename.res IntfAndImpl cmti:./lib/bs/src/RenameWithInterface.cmti resi:./src/RenameWithInterface.resi cmt:./lib/bs/src/RenameWithInterface.cmt res:./src/RenameWithInterface.res IntfAndImpl cmti:./lib/bs/src/TableclothMap.cmti resi:./src/TableclothMap.mli cmt:./lib/bs/src/TableclothMap.cmt res:./src/TableclothMap.ml +Impl cmt:./lib/bs/src/TypeContextCompletion.cmt res:./src/TypeContextCompletion.res Impl cmt:./lib/bs/src/TypeDefinition.cmt res:./src/TypeDefinition.res Impl cmt:./lib/bs/src/Xform.cmt res:./src/Xform.res Dependency dirs: ./node_modules/@rescript/react/lib/bs/src ./node_modules/@rescript/react/lib/bs/src/legacy From 87508b3887b85eee4c8320ae6ca943c60fcecc81 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 14 Jul 2022 22:12:54 +0200 Subject: [PATCH 03/80] fix accidentally broken completion example --- analysis/tests/src/TypeContextCompletion.res | 4 ++-- analysis/tests/src/expected/TypeContextCompletion.res.txt | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/analysis/tests/src/TypeContextCompletion.res b/analysis/tests/src/TypeContextCompletion.res index cd4eecdac..ced9a9d04 100644 --- a/analysis/tests/src/TypeContextCompletion.res +++ b/analysis/tests/src/TypeContextCompletion.res @@ -8,8 +8,8 @@ let someVariantToString = (~someVariant) => | Four => "Four" } -// let someVariantToString(~someVariant= -// ^com +// let x = someVariantToString(~someVariant= +// ^com module SomeComponent = { @react.component diff --git a/analysis/tests/src/expected/TypeContextCompletion.res.txt b/analysis/tests/src/expected/TypeContextCompletion.res.txt index 0426f5b0e..cf3b1b3fe 100644 --- a/analysis/tests/src/expected/TypeContextCompletion.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion.res.txt @@ -1,5 +1,8 @@ -Complete src/TypeContextCompletion.res 10:40 -posCursor:[10:40] posNoWhite:[10:39] Found expr:[10:26->18:1] +Complete src/TypeContextCompletion.res 10:44 +posCursor:[10:44] posNoWhite:[10:43] Found expr:[10:11->18:1] +Pexp_apply ...[10:11->10:30] (~someVariant10:32->10:43=...[13:0->17:3]) +Completable: CnamedArg(Value[someVariantToString], "", [someVariant]) +Found type for function (~someVariant: someVariant) => string [] Complete src/TypeContextCompletion.res 20:37 From 5ed8bb42b6d7c85ad056c6c4b1ad0675a8937d0b Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Fri, 15 Jul 2022 21:24:31 +0200 Subject: [PATCH 04/80] identify typed context for labelled argument assignments --- analysis/src/CompletionBackEnd.ml | 1 + analysis/src/CompletionFrontEnd.ml | 14 ++++++-- analysis/src/SharedTypes.ml | 2 ++ analysis/tests/src/TypeContextCompletion.res | 6 ++++ .../expected/TypeContextCompletion.res.txt | 34 +++++++++++++++---- 5 files changed, 48 insertions(+), 9 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 387abd6b8..bed40cf75 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1337,6 +1337,7 @@ let processCompletable ~debug ~package ~scope ~env ~pos ~forHover in match completable with | Cnone -> [] + | CtypedContext _contextPath -> [] | Cpath contextPath -> contextPath |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 2bb5ab2de..ab8cb1d5b 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -137,7 +137,8 @@ type label = labelled option type arg = {label: label; exp: Parsetree.expression} let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor - ~(contextPath : Completable.contextPath) ~posAfterFunExpr = + ~(contextPath : Completable.contextPath) ~posAfterFunExpr ~charBeforeCursor + ~debug = let allNames = List.fold_right (fun arg allLabels -> @@ -149,11 +150,19 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor let rec loop args = match args with | {label = Some labelled; exp} :: rest -> + (* Figure out if we're completing the labelled argument name, or assigning to the labelled argument *) if labelled.posStart <= posBeforeCursor && posBeforeCursor < labelled.posEnd + && charBeforeCursor <> Some '=' + (* We need to account for empty assignments being parsed as regular labelled arguments without an assignment *) then Some (Completable.CnamedArg (contextPath, labelled.name, allNames)) - else if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then None + else if + exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor + || charBeforeCursor = Some '=' + then ( + if debug then Printf.printf "found typed context \n"; + Some (Completable.CtypedContext contextPath)) else loop rest | {label = None; exp} :: rest -> if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then None @@ -592,6 +601,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | Some contextPath -> findNamedArgCompletable ~contextPath ~args ~endPos:(Loc.end_ expr.pexp_loc) ~posBeforeCursor + ~charBeforeCursor ~debug ~posAfterFunExpr:(Loc.end_ funExpr.pexp_loc) | None -> None in diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 314f7670b..53cd2e10b 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -433,6 +433,7 @@ module Completable = struct | Cpath of contextPath | Cjsx of string list * string * string list (** E.g. (["M", "Comp"], "id", ["id1", "id2"]) for "Cnone" | Cjsx (sl1, s, sl2) -> "Cjsx(" ^ (sl1 |> list) ^ ", " ^ str s ^ ", " ^ (sl2 |> list) ^ ")" + | CtypedContext cp -> "CtypedContext(" ^ (cp |> contextPathToString) ^ ")" end diff --git a/analysis/tests/src/TypeContextCompletion.res b/analysis/tests/src/TypeContextCompletion.res index ced9a9d04..632d9a51e 100644 --- a/analysis/tests/src/TypeContextCompletion.res +++ b/analysis/tests/src/TypeContextCompletion.res @@ -8,9 +8,15 @@ let someVariantToString = (~someVariant) => | Four => "Four" } +// let x = someVariantToString(~someVaria +// ^com + // let x = someVariantToString(~someVariant= // ^com +// let x = someVariantToString(~someVariant=T +// ^com + module SomeComponent = { @react.component let make = (~whatever) => { diff --git a/analysis/tests/src/expected/TypeContextCompletion.res.txt b/analysis/tests/src/expected/TypeContextCompletion.res.txt index cf3b1b3fe..b24dbe969 100644 --- a/analysis/tests/src/expected/TypeContextCompletion.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion.res.txt @@ -1,12 +1,32 @@ -Complete src/TypeContextCompletion.res 10:44 -posCursor:[10:44] posNoWhite:[10:43] Found expr:[10:11->18:1] -Pexp_apply ...[10:11->10:30] (~someVariant10:32->10:43=...[13:0->17:3]) -Completable: CnamedArg(Value[someVariantToString], "", [someVariant]) +Complete src/TypeContextCompletion.res 10:41 +posCursor:[10:41] posNoWhite:[10:40] Found expr:[10:11->24:1] +Pexp_apply ...[10:11->10:30] (~someVaria10:32->10:41=...[10:32->10:41], ...[19:0->23:3]) +Completable: CnamedArg(Value[someVariantToString], someVaria, [someVaria]) Found type for function (~someVariant: someVariant) => string +[{ + "label": "someVariant", + "kind": 4, + "tags": [], + "detail": "someVariant", + "documentation": null + }] + +Complete src/TypeContextCompletion.res 13:44 +posCursor:[13:44] posNoWhite:[13:43] Found expr:[13:11->24:1] +Pexp_apply ...[13:11->13:30] (~someVariant13:32->13:43=...[19:0->23:3]) +found typed context +Completable: CtypedContext(Value[someVariantToString]) +[] + +Complete src/TypeContextCompletion.res 16:45 +posCursor:[16:45] posNoWhite:[16:44] Found expr:[16:11->24:1] +Pexp_apply ...[16:11->16:30] (~someVariant16:32->16:43=...[16:44->16:45], ...[19:0->23:3]) +found typed context +Completable: CtypedContext(Value[someVariantToString]) [] -Complete src/TypeContextCompletion.res 20:37 -posCursor:[20:37] posNoWhite:[20:36] Found expr:[20:14->20:37] -JSX 20:27] whatever[20:28->20:36]=...__ghost__[0:-1->0:-1]> _children:None +Complete src/TypeContextCompletion.res 26:37 +posCursor:[26:37] posNoWhite:[26:36] Found expr:[26:14->26:37] +JSX 26:27] whatever[26:28->26:36]=...__ghost__[0:-1->0:-1]> _children:None [] From d121e735c15ac5dda6b491f4b93b8614b89054a4 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sat, 16 Jul 2022 21:07:28 +0200 Subject: [PATCH 05/80] remove special handling of equality char --- analysis/src/CompletionFrontEnd.ml | 13 ++------ analysis/tests/src/TypeContextCompletion.res | 15 +++++---- .../expected/TypeContextCompletion.res.txt | 31 ++++++++++++------- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index ab8cb1d5b..d178bdfb3 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -137,8 +137,7 @@ type label = labelled option type arg = {label: label; exp: Parsetree.expression} let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor - ~(contextPath : Completable.contextPath) ~posAfterFunExpr ~charBeforeCursor - ~debug = + ~(contextPath : Completable.contextPath) ~posAfterFunExpr ~debug = let allNames = List.fold_right (fun arg allLabels -> @@ -154,13 +153,8 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor if labelled.posStart <= posBeforeCursor && posBeforeCursor < labelled.posEnd - && charBeforeCursor <> Some '=' - (* We need to account for empty assignments being parsed as regular labelled arguments without an assignment *) then Some (Completable.CnamedArg (contextPath, labelled.name, allNames)) - else if - exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor - || charBeforeCursor = Some '=' - then ( + else if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then ( if debug then Printf.printf "found typed context \n"; Some (Completable.CtypedContext contextPath)) else loop rest @@ -600,8 +594,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = match exprToContextPath funExpr with | Some contextPath -> findNamedArgCompletable ~contextPath ~args - ~endPos:(Loc.end_ expr.pexp_loc) ~posBeforeCursor - ~charBeforeCursor ~debug + ~endPos:(Loc.end_ expr.pexp_loc) ~posBeforeCursor ~debug ~posAfterFunExpr:(Loc.end_ funExpr.pexp_loc) | None -> None in diff --git a/analysis/tests/src/TypeContextCompletion.res b/analysis/tests/src/TypeContextCompletion.res index 632d9a51e..34d284e09 100644 --- a/analysis/tests/src/TypeContextCompletion.res +++ b/analysis/tests/src/TypeContextCompletion.res @@ -8,6 +8,13 @@ let someVariantToString = (~someVariant) => | Four => "Four" } +module SomeComponent = { + @react.component + let make = (~whatever) => { + someVariantToString(~someVariant=whatever)->React.string + } +} + // let x = someVariantToString(~someVaria // ^com @@ -17,12 +24,8 @@ let someVariantToString = (~someVariant) => // let x = someVariantToString(~someVariant=T // ^com -module SomeComponent = { - @react.component - let make = (~whatever) => { - someVariantToString(~someVariant=whatever)->React.string - } -} +// let x = someVariantToString(~someVariant=t +// ^com // let jsx = 24:1] -Pexp_apply ...[10:11->10:30] (~someVaria10:32->10:41=...[10:32->10:41], ...[19:0->23:3]) +Complete src/TypeContextCompletion.res 17:41 +posCursor:[17:41] posNoWhite:[17:40] Found expr:[17:11->17:41] +Pexp_apply ...[17:11->17:30] (~someVaria17:32->17:41=...[17:32->17:41]) Completable: CnamedArg(Value[someVariantToString], someVaria, [someVaria]) Found type for function (~someVariant: someVariant) => string [{ @@ -11,22 +11,29 @@ Found type for function (~someVariant: someVariant) => string "documentation": null }] -Complete src/TypeContextCompletion.res 13:44 -posCursor:[13:44] posNoWhite:[13:43] Found expr:[13:11->24:1] -Pexp_apply ...[13:11->13:30] (~someVariant13:32->13:43=...[19:0->23:3]) +Complete src/TypeContextCompletion.res 20:44 +posCursor:[20:44] posNoWhite:[20:43] Found expr:[20:11->20:44] +Pexp_apply ...[20:11->20:30] (~someVariant20:32->20:43=...__ghost__[0:-1->0:-1]) +Completable: CnamedArg(Value[someVariantToString], "", [someVariant]) +Found type for function (~someVariant: someVariant) => string +[] + +Complete src/TypeContextCompletion.res 23:45 +posCursor:[23:45] posNoWhite:[23:44] Found expr:[23:11->23:45] +Pexp_apply ...[23:11->23:30] (~someVariant23:32->23:43=...[23:44->23:45]) found typed context Completable: CtypedContext(Value[someVariantToString]) [] -Complete src/TypeContextCompletion.res 16:45 -posCursor:[16:45] posNoWhite:[16:44] Found expr:[16:11->24:1] -Pexp_apply ...[16:11->16:30] (~someVariant16:32->16:43=...[16:44->16:45], ...[19:0->23:3]) +Complete src/TypeContextCompletion.res 26:45 +posCursor:[26:45] posNoWhite:[26:44] Found expr:[26:11->26:45] +Pexp_apply ...[26:11->26:30] (~someVariant26:32->26:43=...[26:44->26:45]) found typed context Completable: CtypedContext(Value[someVariantToString]) [] -Complete src/TypeContextCompletion.res 26:37 -posCursor:[26:37] posNoWhite:[26:36] Found expr:[26:14->26:37] -JSX 26:27] whatever[26:28->26:36]=...__ghost__[0:-1->0:-1]> _children:None +Complete src/TypeContextCompletion.res 29:37 +posCursor:[29:37] posNoWhite:[29:36] Found expr:[29:14->29:37] +JSX 29:27] whatever[29:28->29:36]=...__ghost__[0:-1->0:-1]> _children:None [] From 57e7cce27264526bc7576ca6b7c2de1a298b1391 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sat, 16 Jul 2022 21:35:07 +0200 Subject: [PATCH 06/80] use trick from JSX prop completion to identify empty assignment of labelled argument --- analysis/src/CompletionFrontEnd.ml | 5 +++++ analysis/tests/src/TypeContextCompletion.res | 3 +++ .../expected/TypeContextCompletion.res.txt | 21 ++++++++++++------- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index d178bdfb3..cf8850902 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -157,6 +157,11 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor else if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then ( if debug then Printf.printf "found typed context \n"; Some (Completable.CtypedContext contextPath)) + else if exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then ( + (* Expr assigned presumably is "rescript.exprhole" after parser recovery. + Assume this is an empty expression. *) + if debug then Printf.printf "found typed context \n"; + Some (Completable.CtypedContext contextPath)) else loop rest | {label = None; exp} :: rest -> if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then None diff --git a/analysis/tests/src/TypeContextCompletion.res b/analysis/tests/src/TypeContextCompletion.res index 34d284e09..d9c525290 100644 --- a/analysis/tests/src/TypeContextCompletion.res +++ b/analysis/tests/src/TypeContextCompletion.res @@ -21,6 +21,9 @@ module SomeComponent = { // let x = someVariantToString(~someVariant= // ^com +// let x = someVariantToString(~someVariant= +// ^com + // let x = someVariantToString(~someVariant=T // ^com diff --git a/analysis/tests/src/expected/TypeContextCompletion.res.txt b/analysis/tests/src/expected/TypeContextCompletion.res.txt index 4eecb75b9..8105decdc 100644 --- a/analysis/tests/src/expected/TypeContextCompletion.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion.res.txt @@ -14,13 +14,13 @@ Found type for function (~someVariant: someVariant) => string Complete src/TypeContextCompletion.res 20:44 posCursor:[20:44] posNoWhite:[20:43] Found expr:[20:11->20:44] Pexp_apply ...[20:11->20:30] (~someVariant20:32->20:43=...__ghost__[0:-1->0:-1]) -Completable: CnamedArg(Value[someVariantToString], "", [someVariant]) -Found type for function (~someVariant: someVariant) => string +found typed context +Completable: CtypedContext(Value[someVariantToString]) [] Complete src/TypeContextCompletion.res 23:45 -posCursor:[23:45] posNoWhite:[23:44] Found expr:[23:11->23:45] -Pexp_apply ...[23:11->23:30] (~someVariant23:32->23:43=...[23:44->23:45]) +posCursor:[23:45] posNoWhite:[23:43] Found expr:[23:11->23:44] +Pexp_apply ...[23:11->23:30] (~someVariant23:32->23:43=...__ghost__[0:-1->0:-1]) found typed context Completable: CtypedContext(Value[someVariantToString]) [] @@ -32,8 +32,15 @@ found typed context Completable: CtypedContext(Value[someVariantToString]) [] -Complete src/TypeContextCompletion.res 29:37 -posCursor:[29:37] posNoWhite:[29:36] Found expr:[29:14->29:37] -JSX 29:27] whatever[29:28->29:36]=...__ghost__[0:-1->0:-1]> _children:None +Complete src/TypeContextCompletion.res 29:45 +posCursor:[29:45] posNoWhite:[29:44] Found expr:[29:11->29:45] +Pexp_apply ...[29:11->29:30] (~someVariant29:32->29:43=...[29:44->29:45]) +found typed context +Completable: CtypedContext(Value[someVariantToString]) +[] + +Complete src/TypeContextCompletion.res 32:37 +posCursor:[32:37] posNoWhite:[32:36] Found expr:[32:14->32:37] +JSX 32:27] whatever[32:28->32:36]=...__ghost__[0:-1->0:-1]> _children:None [] From b1252070fdfe7c292ea3051fee574f3de22fae8e Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 17 Jul 2022 12:24:34 +0200 Subject: [PATCH 07/80] crude implementation of completing variant constructors --- analysis/src/CompletionBackEnd.ml | 72 ++++++- analysis/src/CompletionFrontEnd.ml | 4 +- analysis/src/SharedTypes.ml | 16 +- analysis/tests/src/TypeContextCompletion.res | 3 +- analysis/tests/src/expected/Dce.res.txt | 2 +- .../expected/TypeContextCompletion.res.txt | 200 +++++++++++++++--- 6 files changed, 264 insertions(+), 33 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index bed40cf75..4ab734b42 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -992,6 +992,18 @@ let rec extractRecordType ~env ~package (t : Types.type_expr) = | _ -> None) | _ -> None +let rec extractVariantType ~env ~package (t : Types.type_expr) = + match t.desc with + | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> extractVariantType ~env ~package t1 + | Tconstr (path, _, _) -> ( + match References.digConstructor ~env ~package path with + | Some (env, ({item = {kind = Variant constructors}} as typ)) -> + Some (env, constructors, typ) + | Some (env, {item = {decl = {type_manifest = Some t1}}}) -> + extractVariantType ~env ~package t1 + | _ -> None) + | _ -> None + let rec extractObjectType ~env ~package (t : Types.type_expr) = match t.desc with | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> extractObjectType ~env ~package t1 @@ -1337,7 +1349,6 @@ let processCompletable ~debug ~package ~scope ~env ~pos ~forHover in match completable with | Cnone -> [] - | CtypedContext _contextPath -> [] | Cpath contextPath -> contextPath |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos @@ -1687,3 +1698,62 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i Utils.startsWith name prefix && (forHover || not (List.mem name identsSeen))) |> List.map mkLabel + | CtypedContext (cp, typedContext) -> ( + match typedContext with + | NamedArg argName -> ( + (* TODO: Should probably share this with the branch handling CnamedArg... *) + let labels = + match + cp + |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles + ~pos ~env ~exact:true ~scope + |> completionsGetTypeEnv + with + | Some (typ, _env) -> + let rec getLabels ~env (t : Types.type_expr) = + match t.desc with + | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> getLabels ~env t1 + | Tarrow ((Labelled l | Optional l), tArg, tRet, _) -> + (l, tArg) :: getLabels ~env tRet + | Tarrow (Nolabel, _, tRet, _) -> getLabels ~env tRet + | Tconstr (path, _, _) -> ( + match References.digConstructor ~env ~package path with + | Some (env, {item = {decl = {type_manifest = Some t1}}}) -> + getLabels ~env t1 + | _ -> []) + | _ -> [] + in + typ |> getLabels ~env + | None -> [] + in + let targetLabel = + labels |> List.find_opt (fun (name, _t) -> name = argName) + in + match targetLabel with + | None -> [] + | Some (_, typeExpr) -> ( + match extractVariantType ~env ~package typeExpr with + | None -> + if debug then Printf.printf "Could not extract variant type\n"; + [] + | Some (_env, constructors, _typ) -> + if debug then + Printf.printf "Found variant type for NamedArg typed context %s\n" + (typeExpr |> Shared.typeToString); + + (* TODO: Account for existing prefix (e.g what the user has already started typing, if anything)? + According to the LS protocol the client can perform that filtering by itself in the simplest cases. + Investigate if doing it ourselves here would be more robust. *) + (* TODO: Investigate completing seen identifiers _with the correct type_ here too. If completing + variant someVariant, and there's a someVariable of type someVariant, add that to the completion list. *) + constructors + |> List.map (fun constructor -> + (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? + Eg. Some($1) as completion item. *) + Completion.create + ~name: + (constructor.Constructor.cname.txt + ^ if constructor.args |> List.length > 0 then "(_)" else "" + ) + ~kind:(Constructor (constructor, "")) + ~env)))) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index cf8850902..25380db2c 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -156,12 +156,12 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor then Some (Completable.CnamedArg (contextPath, labelled.name, allNames)) else if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then ( if debug then Printf.printf "found typed context \n"; - Some (Completable.CtypedContext contextPath)) + Some (Completable.CtypedContext (contextPath, NamedArg labelled.name))) else if exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then ( (* Expr assigned presumably is "rescript.exprhole" after parser recovery. Assume this is an empty expression. *) if debug then Printf.printf "found typed context \n"; - Some (Completable.CtypedContext contextPath)) + Some (Completable.CtypedContext (contextPath, NamedArg labelled.name))) else loop rest | {label = None; exp} :: rest -> if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then None diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 53cd2e10b..f73c2d8ff 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -425,6 +425,12 @@ module Completable = struct | CPObj of contextPath * string | CPPipe of contextPath * string + type typedContext = NamedArg of string + + let typedContextToString typedContext = + match typedContext with + | NamedArg argName -> "NamedArg(" ^ argName ^ ")" + type t = | Cdecorator of string (** e.g. @module *) | CnamedArg of contextPath * string * string list @@ -433,7 +439,8 @@ module Completable = struct | Cpath of contextPath | Cjsx of string list * string * string list (** E.g. (["M", "Comp"], "id", ["id1", "id2"]) for "Cnone" | Cjsx (sl1, s, sl2) -> "Cjsx(" ^ (sl1 |> list) ^ ", " ^ str s ^ ", " ^ (sl2 |> list) ^ ")" - | CtypedContext cp -> "CtypedContext(" ^ (cp |> contextPathToString) ^ ")" + | CtypedContext (cp, typedContext) -> + "CtypedContext(" + ^ (cp |> contextPathToString) + ^ ", " + ^ (typedContext |> typedContextToString) + ^ ")" end diff --git a/analysis/tests/src/TypeContextCompletion.res b/analysis/tests/src/TypeContextCompletion.res index d9c525290..15e52f9e4 100644 --- a/analysis/tests/src/TypeContextCompletion.res +++ b/analysis/tests/src/TypeContextCompletion.res @@ -1,4 +1,4 @@ -type someVariant = One | Two | Three | Four +type someVariant = One | Two | Three | Four | Five(int) | Six(option) let someVariantToString = (~someVariant) => switch someVariant { @@ -6,6 +6,7 @@ let someVariantToString = (~someVariant) => | Two => "Two" | Three => "Three" | Four => "Four" + | _ => "-" } module SomeComponent = { diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index c4c5eda20..441bb5807 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:241 +issues:243 diff --git a/analysis/tests/src/expected/TypeContextCompletion.res.txt b/analysis/tests/src/expected/TypeContextCompletion.res.txt index 8105decdc..3c5b665ef 100644 --- a/analysis/tests/src/expected/TypeContextCompletion.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion.res.txt @@ -1,6 +1,6 @@ -Complete src/TypeContextCompletion.res 17:41 -posCursor:[17:41] posNoWhite:[17:40] Found expr:[17:11->17:41] -Pexp_apply ...[17:11->17:30] (~someVaria17:32->17:41=...[17:32->17:41]) +Complete src/TypeContextCompletion.res 18:41 +posCursor:[18:41] posNoWhite:[18:40] Found expr:[18:11->18:41] +Pexp_apply ...[18:11->18:30] (~someVaria18:32->18:41=...[18:32->18:41]) Completable: CnamedArg(Value[someVariantToString], someVaria, [someVaria]) Found type for function (~someVariant: someVariant) => string [{ @@ -11,36 +11,184 @@ Found type for function (~someVariant: someVariant) => string "documentation": null }] -Complete src/TypeContextCompletion.res 20:44 -posCursor:[20:44] posNoWhite:[20:43] Found expr:[20:11->20:44] -Pexp_apply ...[20:11->20:30] (~someVariant20:32->20:43=...__ghost__[0:-1->0:-1]) +Complete src/TypeContextCompletion.res 21:44 +posCursor:[21:44] posNoWhite:[21:43] Found expr:[21:11->21:44] +Pexp_apply ...[21:11->21:30] (~someVariant21:32->21:43=...__ghost__[0:-1->0:-1]) found typed context -Completable: CtypedContext(Value[someVariantToString]) -[] +Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) +Found variant type for NamedArg typed context someVariant +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\n", + "documentation": null + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\n", + "documentation": null + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\n", + "documentation": null + }, { + "label": "Six(_)", + "kind": 4, + "tags": [], + "detail": "Six(option)\n\n", + "documentation": null + }] -Complete src/TypeContextCompletion.res 23:45 -posCursor:[23:45] posNoWhite:[23:43] Found expr:[23:11->23:44] -Pexp_apply ...[23:11->23:30] (~someVariant23:32->23:43=...__ghost__[0:-1->0:-1]) +Complete src/TypeContextCompletion.res 24:45 +posCursor:[24:45] posNoWhite:[24:43] Found expr:[24:11->24:44] +Pexp_apply ...[24:11->24:30] (~someVariant24:32->24:43=...__ghost__[0:-1->0:-1]) found typed context -Completable: CtypedContext(Value[someVariantToString]) -[] +Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) +Found variant type for NamedArg typed context someVariant +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\n", + "documentation": null + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\n", + "documentation": null + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\n", + "documentation": null + }, { + "label": "Six(_)", + "kind": 4, + "tags": [], + "detail": "Six(option)\n\n", + "documentation": null + }] -Complete src/TypeContextCompletion.res 26:45 -posCursor:[26:45] posNoWhite:[26:44] Found expr:[26:11->26:45] -Pexp_apply ...[26:11->26:30] (~someVariant26:32->26:43=...[26:44->26:45]) +Complete src/TypeContextCompletion.res 27:45 +posCursor:[27:45] posNoWhite:[27:44] Found expr:[27:11->27:45] +Pexp_apply ...[27:11->27:30] (~someVariant27:32->27:43=...[27:44->27:45]) found typed context -Completable: CtypedContext(Value[someVariantToString]) -[] +Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) +Found variant type for NamedArg typed context someVariant +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\n", + "documentation": null + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\n", + "documentation": null + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\n", + "documentation": null + }, { + "label": "Six(_)", + "kind": 4, + "tags": [], + "detail": "Six(option)\n\n", + "documentation": null + }] -Complete src/TypeContextCompletion.res 29:45 -posCursor:[29:45] posNoWhite:[29:44] Found expr:[29:11->29:45] -Pexp_apply ...[29:11->29:30] (~someVariant29:32->29:43=...[29:44->29:45]) +Complete src/TypeContextCompletion.res 30:45 +posCursor:[30:45] posNoWhite:[30:44] Found expr:[30:11->30:45] +Pexp_apply ...[30:11->30:30] (~someVariant30:32->30:43=...[30:44->30:45]) found typed context -Completable: CtypedContext(Value[someVariantToString]) -[] +Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) +Found variant type for NamedArg typed context someVariant +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\n", + "documentation": null + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\n", + "documentation": null + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\n", + "documentation": null + }, { + "label": "Six(_)", + "kind": 4, + "tags": [], + "detail": "Six(option)\n\n", + "documentation": null + }] -Complete src/TypeContextCompletion.res 32:37 -posCursor:[32:37] posNoWhite:[32:36] Found expr:[32:14->32:37] -JSX 32:27] whatever[32:28->32:36]=...__ghost__[0:-1->0:-1]> _children:None +Complete src/TypeContextCompletion.res 33:37 +posCursor:[33:37] posNoWhite:[33:36] Found expr:[33:14->33:37] +JSX 33:27] whatever[33:28->33:36]=...__ghost__[0:-1->0:-1]> _children:None [] From 431ab48b8bffd57d15f4113b3b49d7eb2140deb9 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 17 Jul 2022 20:37:42 +0200 Subject: [PATCH 08/80] rename and specialize test file so that it will only contain tests for labelled argument completion --- ...peContextCompletion_LabelledArguments.res} | 10 - .../tests/src/expected/Completion.res.txt | 2 +- analysis/tests/src/expected/Debug.res.txt | 4 +- ...ontextCompletion_LabelledArguments.res.txt | 189 ++++++++++++++++++ 4 files changed, 192 insertions(+), 13 deletions(-) rename analysis/tests/src/{TypeContextCompletion.res => TypeContextCompletion_LabelledArguments.res} (76%) create mode 100644 analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt diff --git a/analysis/tests/src/TypeContextCompletion.res b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res similarity index 76% rename from analysis/tests/src/TypeContextCompletion.res rename to analysis/tests/src/TypeContextCompletion_LabelledArguments.res index 15e52f9e4..a9e5c5a06 100644 --- a/analysis/tests/src/TypeContextCompletion.res +++ b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res @@ -9,13 +9,6 @@ let someVariantToString = (~someVariant) => | _ => "-" } -module SomeComponent = { - @react.component - let make = (~whatever) => { - someVariantToString(~someVariant=whatever)->React.string - } -} - // let x = someVariantToString(~someVaria // ^com @@ -30,6 +23,3 @@ module SomeComponent = { // let x = someVariantToString(~someVariant=t // ^com - -// let jsx = 11:41] +Pexp_apply ...[11:11->11:30] (~someVaria11:32->11:41=...[11:32->11:41]) +Completable: CnamedArg(Value[someVariantToString], someVaria, [someVaria]) +Found type for function (~someVariant: someVariant) => string +[{ + "label": "someVariant", + "kind": 4, + "tags": [], + "detail": "someVariant", + "documentation": null + }] + +Complete src/TypeContextCompletion_LabelledArguments.res 14:44 +posCursor:[14:44] posNoWhite:[14:43] Found expr:[14:11->14:44] +Pexp_apply ...[14:11->14:30] (~someVariant14:32->14:43=...__ghost__[0:-1->0:-1]) +found typed context +Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) +Found variant type for NamedArg typed context someVariant +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\n", + "documentation": null + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\n", + "documentation": null + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\n", + "documentation": null + }, { + "label": "Six(_)", + "kind": 4, + "tags": [], + "detail": "Six(option)\n\n", + "documentation": null + }] + +Complete src/TypeContextCompletion_LabelledArguments.res 17:45 +posCursor:[17:45] posNoWhite:[17:43] Found expr:[17:11->17:44] +Pexp_apply ...[17:11->17:30] (~someVariant17:32->17:43=...__ghost__[0:-1->0:-1]) +found typed context +Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) +Found variant type for NamedArg typed context someVariant +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\n", + "documentation": null + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\n", + "documentation": null + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\n", + "documentation": null + }, { + "label": "Six(_)", + "kind": 4, + "tags": [], + "detail": "Six(option)\n\n", + "documentation": null + }] + +Complete src/TypeContextCompletion_LabelledArguments.res 20:45 +posCursor:[20:45] posNoWhite:[20:44] Found expr:[20:11->20:45] +Pexp_apply ...[20:11->20:30] (~someVariant20:32->20:43=...[20:44->20:45]) +found typed context +Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) +Found variant type for NamedArg typed context someVariant +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\n", + "documentation": null + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\n", + "documentation": null + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\n", + "documentation": null + }, { + "label": "Six(_)", + "kind": 4, + "tags": [], + "detail": "Six(option)\n\n", + "documentation": null + }] + +Complete src/TypeContextCompletion_LabelledArguments.res 23:45 +posCursor:[23:45] posNoWhite:[23:44] Found expr:[23:11->23:45] +Pexp_apply ...[23:11->23:30] (~someVariant23:32->23:43=...[23:44->23:45]) +found typed context +Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) +Found variant type for NamedArg typed context someVariant +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\n", + "documentation": null + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\n", + "documentation": null + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\n", + "documentation": null + }, { + "label": "Six(_)", + "kind": 4, + "tags": [], + "detail": "Six(option)\n\n", + "documentation": null + }] + From bdd2e111fb1e372f0204bf97dcf90aa02e1b63f2 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 17 Jul 2022 20:47:37 +0200 Subject: [PATCH 09/80] generalize completion so it theoretically can handle more than variants --- analysis/src/CompletionBackEnd.ml | 60 ++++++++++++++++--------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 4ab734b42..a18bcaa92 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -992,15 +992,14 @@ let rec extractRecordType ~env ~package (t : Types.type_expr) = | _ -> None) | _ -> None -let rec extractVariantType ~env ~package (t : Types.type_expr) = +let rec extractType ~env ~package (t : Types.type_expr) = match t.desc with - | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> extractVariantType ~env ~package t1 + | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> extractType ~env ~package t1 | Tconstr (path, _, _) -> ( match References.digConstructor ~env ~package path with - | Some (env, ({item = {kind = Variant constructors}} as typ)) -> - Some (env, constructors, typ) | Some (env, {item = {decl = {type_manifest = Some t1}}}) -> - extractVariantType ~env ~package t1 + extractType ~env ~package t1 + | Some (env, typ) -> Some (env, typ) | _ -> None) | _ -> None @@ -1732,28 +1731,33 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i match targetLabel with | None -> [] | Some (_, typeExpr) -> ( - match extractVariantType ~env ~package typeExpr with + match extractType ~env ~package typeExpr with | None -> - if debug then Printf.printf "Could not extract variant type\n"; - [] - | Some (_env, constructors, _typ) -> if debug then - Printf.printf "Found variant type for NamedArg typed context %s\n" - (typeExpr |> Shared.typeToString); - - (* TODO: Account for existing prefix (e.g what the user has already started typing, if anything)? - According to the LS protocol the client can perform that filtering by itself in the simplest cases. - Investigate if doing it ourselves here would be more robust. *) - (* TODO: Investigate completing seen identifiers _with the correct type_ here too. If completing - variant someVariant, and there's a someVariable of type someVariant, add that to the completion list. *) - constructors - |> List.map (fun constructor -> - (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? - Eg. Some($1) as completion item. *) - Completion.create - ~name: - (constructor.Constructor.cname.txt - ^ if constructor.args |> List.length > 0 then "(_)" else "" - ) - ~kind:(Constructor (constructor, "")) - ~env)))) + Printf.printf + "Could not extract type for labelled argument completion\n"; + [] + | Some (_env, {item}) -> ( + match item.kind with + | Variant constructors -> + if debug then + Printf.printf "Found variant type for NamedArg typed context %s\n" + (typeExpr |> Shared.typeToString); + (* TODO: Account for existing prefix (e.g what the user has already started typing, if anything)? + According to the LS protocol the client can perform that filtering by itself in the simplest cases. + Investigate if doing it ourselves here would be more robust. *) + (* TODO: Investigate completing seen identifiers _with the correct type_ here too. If completing + variant someVariant, and there's a someVariable of type someVariant, add that to the completion list. *) + constructors + |> List.map (fun constructor -> + (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? + Eg. Some($1) as completion item. *) + Completion.create + ~name: + (constructor.Constructor.cname.txt + ^ + if constructor.args |> List.length > 0 then "(_)" else "" + ) + ~kind:(Constructor (constructor, "")) + ~env) + | _ -> [])))) From bea78fe4421f32b1a1bf7e8a9621ee9077c2c45d Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 17 Jul 2022 20:48:50 +0200 Subject: [PATCH 10/80] add assigned identifier to test file --- ...ypeContextCompletion_LabelledArguments.res | 2 ++ analysis/tests/src/expected/Dce.res.txt | 2 +- ...ontextCompletion_LabelledArguments.res.txt | 30 +++++++++---------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/analysis/tests/src/TypeContextCompletion_LabelledArguments.res b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res index a9e5c5a06..7349d6893 100644 --- a/analysis/tests/src/TypeContextCompletion_LabelledArguments.res +++ b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res @@ -1,5 +1,7 @@ type someVariant = One | Two | Three | Four | Five(int) | Six(option) +let someValue = Two + let someVariantToString = (~someVariant) => switch someVariant { | One => "One" diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index 441bb5807..adb61de68 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:243 +issues:242 diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index f459c50be..b2825a0ed 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -1,6 +1,6 @@ -Complete src/TypeContextCompletion_LabelledArguments.res 11:41 -posCursor:[11:41] posNoWhite:[11:40] Found expr:[11:11->11:41] -Pexp_apply ...[11:11->11:30] (~someVaria11:32->11:41=...[11:32->11:41]) +Complete src/TypeContextCompletion_LabelledArguments.res 13:41 +posCursor:[13:41] posNoWhite:[13:40] Found expr:[13:11->13:41] +Pexp_apply ...[13:11->13:30] (~someVaria13:32->13:41=...[13:32->13:41]) Completable: CnamedArg(Value[someVariantToString], someVaria, [someVaria]) Found type for function (~someVariant: someVariant) => string [{ @@ -11,9 +11,9 @@ Found type for function (~someVariant: someVariant) => string "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 14:44 -posCursor:[14:44] posNoWhite:[14:43] Found expr:[14:11->14:44] -Pexp_apply ...[14:11->14:30] (~someVariant14:32->14:43=...__ghost__[0:-1->0:-1]) +Complete src/TypeContextCompletion_LabelledArguments.res 16:44 +posCursor:[16:44] posNoWhite:[16:43] Found expr:[16:11->16:44] +Pexp_apply ...[16:11->16:30] (~someVariant16:32->16:43=...__ghost__[0:-1->0:-1]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant @@ -55,9 +55,9 @@ Found variant type for NamedArg typed context someVariant "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 17:45 -posCursor:[17:45] posNoWhite:[17:43] Found expr:[17:11->17:44] -Pexp_apply ...[17:11->17:30] (~someVariant17:32->17:43=...__ghost__[0:-1->0:-1]) +Complete src/TypeContextCompletion_LabelledArguments.res 19:45 +posCursor:[19:45] posNoWhite:[19:43] Found expr:[19:11->19:44] +Pexp_apply ...[19:11->19:30] (~someVariant19:32->19:43=...__ghost__[0:-1->0:-1]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant @@ -99,9 +99,9 @@ Found variant type for NamedArg typed context someVariant "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 20:45 -posCursor:[20:45] posNoWhite:[20:44] Found expr:[20:11->20:45] -Pexp_apply ...[20:11->20:30] (~someVariant20:32->20:43=...[20:44->20:45]) +Complete src/TypeContextCompletion_LabelledArguments.res 22:45 +posCursor:[22:45] posNoWhite:[22:44] Found expr:[22:11->22:45] +Pexp_apply ...[22:11->22:30] (~someVariant22:32->22:43=...[22:44->22:45]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant @@ -143,9 +143,9 @@ Found variant type for NamedArg typed context someVariant "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 23:45 -posCursor:[23:45] posNoWhite:[23:44] Found expr:[23:11->23:45] -Pexp_apply ...[23:11->23:30] (~someVariant23:32->23:43=...[23:44->23:45]) +Complete src/TypeContextCompletion_LabelledArguments.res 25:45 +posCursor:[25:45] posNoWhite:[25:44] Found expr:[25:11->25:45] +Pexp_apply ...[25:11->25:30] (~someVariant25:32->25:43=...[25:44->25:45]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant From 5ebe602d5821d8bcccb37b479467477ff35df7c8 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 17 Jul 2022 20:50:58 +0200 Subject: [PATCH 11/80] add more args to test function in test file --- ...ypeContextCompletion_LabelledArguments.res | 5 ++- ...ontextCompletion_LabelledArguments.res.txt | 36 ++++++++++--------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/analysis/tests/src/TypeContextCompletion_LabelledArguments.res b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res index 7349d6893..146873fde 100644 --- a/analysis/tests/src/TypeContextCompletion_LabelledArguments.res +++ b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res @@ -2,7 +2,9 @@ type someVariant = One | Two | Three | Four | Five(int) | Six(option) let someValue = Two -let someVariantToString = (~someVariant) => +let someVariantToString = (~someVariant, ~anotherThing: string, ~thirdThing: option) => { + ignore(anotherThing) + ignore(thirdThing) switch someVariant { | One => "One" | Two => "Two" @@ -10,6 +12,7 @@ let someVariantToString = (~someVariant) => | Four => "Four" | _ => "-" } +} // let x = someVariantToString(~someVaria // ^com diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index b2825a0ed..d809873d7 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -1,8 +1,12 @@ -Complete src/TypeContextCompletion_LabelledArguments.res 13:41 -posCursor:[13:41] posNoWhite:[13:40] Found expr:[13:11->13:41] -Pexp_apply ...[13:11->13:30] (~someVaria13:32->13:41=...[13:32->13:41]) +Complete src/TypeContextCompletion_LabelledArguments.res 16:41 +posCursor:[16:41] posNoWhite:[16:40] Found expr:[16:11->16:41] +Pexp_apply ...[16:11->16:30] (~someVaria16:32->16:41=...[16:32->16:41]) Completable: CnamedArg(Value[someVariantToString], someVaria, [someVaria]) -Found type for function (~someVariant: someVariant) => string +Found type for function ( + ~someVariant: someVariant, + ~anotherThing: string, + ~thirdThing: option, +) => string [{ "label": "someVariant", "kind": 4, @@ -11,9 +15,9 @@ Found type for function (~someVariant: someVariant) => string "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 16:44 -posCursor:[16:44] posNoWhite:[16:43] Found expr:[16:11->16:44] -Pexp_apply ...[16:11->16:30] (~someVariant16:32->16:43=...__ghost__[0:-1->0:-1]) +Complete src/TypeContextCompletion_LabelledArguments.res 19:44 +posCursor:[19:44] posNoWhite:[19:43] Found expr:[19:11->19:44] +Pexp_apply ...[19:11->19:30] (~someVariant19:32->19:43=...__ghost__[0:-1->0:-1]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant @@ -55,9 +59,9 @@ Found variant type for NamedArg typed context someVariant "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 19:45 -posCursor:[19:45] posNoWhite:[19:43] Found expr:[19:11->19:44] -Pexp_apply ...[19:11->19:30] (~someVariant19:32->19:43=...__ghost__[0:-1->0:-1]) +Complete src/TypeContextCompletion_LabelledArguments.res 22:45 +posCursor:[22:45] posNoWhite:[22:43] Found expr:[22:11->22:44] +Pexp_apply ...[22:11->22:30] (~someVariant22:32->22:43=...__ghost__[0:-1->0:-1]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant @@ -99,9 +103,9 @@ Found variant type for NamedArg typed context someVariant "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 22:45 -posCursor:[22:45] posNoWhite:[22:44] Found expr:[22:11->22:45] -Pexp_apply ...[22:11->22:30] (~someVariant22:32->22:43=...[22:44->22:45]) +Complete src/TypeContextCompletion_LabelledArguments.res 25:45 +posCursor:[25:45] posNoWhite:[25:44] Found expr:[25:11->25:45] +Pexp_apply ...[25:11->25:30] (~someVariant25:32->25:43=...[25:44->25:45]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant @@ -143,9 +147,9 @@ Found variant type for NamedArg typed context someVariant "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 25:45 -posCursor:[25:45] posNoWhite:[25:44] Found expr:[25:11->25:45] -Pexp_apply ...[25:11->25:30] (~someVariant25:32->25:43=...[25:44->25:45]) +Complete src/TypeContextCompletion_LabelledArguments.res 28:45 +posCursor:[28:45] posNoWhite:[28:44] Found expr:[28:11->28:45] +Pexp_apply ...[28:11->28:30] (~someVariant28:32->28:43=...[28:44->28:45]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant From b85c4aecfa9216f5e6db8386c1f0a95fb2c93c5b Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 17 Jul 2022 21:09:25 +0200 Subject: [PATCH 12/80] filter completed variant constructors on what the user has already written --- analysis/src/CompletionBackEnd.ml | 7 +-- analysis/src/CompletionFrontEnd.ml | 20 +++++- analysis/src/SharedTypes.ml | 11 +++- ...ontextCompletion_LabelledArguments.res.txt | 62 +------------------ 4 files changed, 31 insertions(+), 69 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index a18bcaa92..4815d2b8b 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1699,7 +1699,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i |> List.map mkLabel | CtypedContext (cp, typedContext) -> ( match typedContext with - | NamedArg argName -> ( + | NamedArg {name = argName; prefix} -> ( (* TODO: Should probably share this with the branch handling CnamedArg... *) let labels = match @@ -1743,12 +1743,11 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i if debug then Printf.printf "Found variant type for NamedArg typed context %s\n" (typeExpr |> Shared.typeToString); - (* TODO: Account for existing prefix (e.g what the user has already started typing, if anything)? - According to the LS protocol the client can perform that filtering by itself in the simplest cases. - Investigate if doing it ourselves here would be more robust. *) (* TODO: Investigate completing seen identifiers _with the correct type_ here too. If completing variant someVariant, and there's a someVariable of type someVariant, add that to the completion list. *) constructors + |> List.filter (fun constructor -> + Utils.startsWith constructor.Constructor.cname.txt prefix) |> List.map (fun constructor -> (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? Eg. Some($1) as completion item. *) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 25380db2c..90cfcb39b 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -136,6 +136,14 @@ type labelled = { type label = labelled option type arg = {label: label; exp: Parsetree.expression} +let getPrefixFromExpr exp = + match exp.Parsetree.pexp_desc with + | Pexp_ident {txt} -> txt |> Longident.last + | Pexp_construct ({txt}, _) -> txt |> Longident.last + | Pexp_variant (label, _) -> label + | Pexp_field (_, {txt}) -> txt |> Longident.last + | _ -> "" + let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor ~(contextPath : Completable.contextPath) ~posAfterFunExpr ~debug = let allNames = @@ -156,12 +164,20 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor then Some (Completable.CnamedArg (contextPath, labelled.name, allNames)) else if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then ( if debug then Printf.printf "found typed context \n"; - Some (Completable.CtypedContext (contextPath, NamedArg labelled.name))) + Some + (Completable.CtypedContext + ( contextPath, + NamedArg {name = labelled.name; prefix = getPrefixFromExpr exp} + ))) else if exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then ( (* Expr assigned presumably is "rescript.exprhole" after parser recovery. Assume this is an empty expression. *) if debug then Printf.printf "found typed context \n"; - Some (Completable.CtypedContext (contextPath, NamedArg labelled.name))) + Some + (Completable.CtypedContext + ( contextPath, + NamedArg {name = labelled.name; prefix = getPrefixFromExpr exp} + ))) else loop rest | {label = None; exp} :: rest -> if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then None diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index f73c2d8ff..081df2e8f 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -425,11 +425,18 @@ module Completable = struct | CPObj of contextPath * string | CPPipe of contextPath * string - type typedContext = NamedArg of string + type namedArg = { + (* What the user has already started writing, if anything *) + prefix: string; + (* Name of the argument *) + name: string; + } + + type typedContext = NamedArg of namedArg let typedContextToString typedContext = match typedContext with - | NamedArg argName -> "NamedArg(" ^ argName ^ ")" + | NamedArg {name} -> "NamedArg(" ^ name ^ ")" type t = | Cdecorator of string (** e.g. @module *) diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index d809873d7..d9816c008 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -110,12 +110,6 @@ found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant [{ - "label": "One", - "kind": 4, - "tags": [], - "detail": "One\n\n", - "documentation": null - }, { "label": "Two", "kind": 4, "tags": [], @@ -127,24 +121,6 @@ Found variant type for NamedArg typed context someVariant "tags": [], "detail": "Three\n\n", "documentation": null - }, { - "label": "Four", - "kind": 4, - "tags": [], - "detail": "Four\n\n", - "documentation": null - }, { - "label": "Five(_)", - "kind": 4, - "tags": [], - "detail": "Five(int)\n\n", - "documentation": null - }, { - "label": "Six(_)", - "kind": 4, - "tags": [], - "detail": "Six(option)\n\n", - "documentation": null }] Complete src/TypeContextCompletion_LabelledArguments.res 28:45 @@ -153,41 +129,5 @@ Pexp_apply ...[28:11->28:30] (~someVariant28:32->28:43=...[28:44->28:45]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant -[{ - "label": "One", - "kind": 4, - "tags": [], - "detail": "One\n\n", - "documentation": null - }, { - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\n", - "documentation": null - }, { - "label": "Three", - "kind": 4, - "tags": [], - "detail": "Three\n\n", - "documentation": null - }, { - "label": "Four", - "kind": 4, - "tags": [], - "detail": "Four\n\n", - "documentation": null - }, { - "label": "Five(_)", - "kind": 4, - "tags": [], - "detail": "Five(int)\n\n", - "documentation": null - }, { - "label": "Six(_)", - "kind": 4, - "tags": [], - "detail": "Six(option)\n\n", - "documentation": null - }] +[] From dd8333e736e6c201adaf015d1610507a92a3df77 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 17 Jul 2022 21:19:14 +0200 Subject: [PATCH 13/80] add example completing variant from other file --- ...ypeContextCompletion_LabelledArguments.res | 9 +++- ...ontextCompletion_LabelledArguments.res.txt | 52 +++++++++++++------ 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/analysis/tests/src/TypeContextCompletion_LabelledArguments.res b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res index 146873fde..0deb3e7d4 100644 --- a/analysis/tests/src/TypeContextCompletion_LabelledArguments.res +++ b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res @@ -2,7 +2,11 @@ type someVariant = One | Two | Three | Four | Five(int) | Six(option) let someValue = Two -let someVariantToString = (~someVariant, ~anotherThing: string, ~thirdThing: option) => { +let someVariantToString = ( + ~someVariant, + ~anotherThing: TypeDefinition.variant, + ~thirdThing: option, +) => { ignore(anotherThing) ignore(thirdThing) switch someVariant { @@ -28,3 +32,6 @@ let someVariantToString = (~someVariant, ~anotherThing: string, ~thirdThing: opt // let x = someVariantToString(~someVariant=t // ^com + +// let x = someVariantToString(~anotherThing= +// ^com diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index d9816c008..0b4ed00b4 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -1,10 +1,10 @@ -Complete src/TypeContextCompletion_LabelledArguments.res 16:41 -posCursor:[16:41] posNoWhite:[16:40] Found expr:[16:11->16:41] -Pexp_apply ...[16:11->16:30] (~someVaria16:32->16:41=...[16:32->16:41]) +Complete src/TypeContextCompletion_LabelledArguments.res 20:41 +posCursor:[20:41] posNoWhite:[20:40] Found expr:[20:11->20:41] +Pexp_apply ...[20:11->20:30] (~someVaria20:32->20:41=...[20:32->20:41]) Completable: CnamedArg(Value[someVariantToString], someVaria, [someVaria]) Found type for function ( ~someVariant: someVariant, - ~anotherThing: string, + ~anotherThing: TypeDefinition.variant, ~thirdThing: option, ) => string [{ @@ -15,9 +15,9 @@ Found type for function ( "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 19:44 -posCursor:[19:44] posNoWhite:[19:43] Found expr:[19:11->19:44] -Pexp_apply ...[19:11->19:30] (~someVariant19:32->19:43=...__ghost__[0:-1->0:-1]) +Complete src/TypeContextCompletion_LabelledArguments.res 23:44 +posCursor:[23:44] posNoWhite:[23:43] Found expr:[23:11->23:44] +Pexp_apply ...[23:11->23:30] (~someVariant23:32->23:43=...__ghost__[0:-1->0:-1]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant @@ -59,9 +59,9 @@ Found variant type for NamedArg typed context someVariant "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 22:45 -posCursor:[22:45] posNoWhite:[22:43] Found expr:[22:11->22:44] -Pexp_apply ...[22:11->22:30] (~someVariant22:32->22:43=...__ghost__[0:-1->0:-1]) +Complete src/TypeContextCompletion_LabelledArguments.res 26:45 +posCursor:[26:45] posNoWhite:[26:43] Found expr:[26:11->26:44] +Pexp_apply ...[26:11->26:30] (~someVariant26:32->26:43=...__ghost__[0:-1->0:-1]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant @@ -103,9 +103,9 @@ Found variant type for NamedArg typed context someVariant "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 25:45 -posCursor:[25:45] posNoWhite:[25:44] Found expr:[25:11->25:45] -Pexp_apply ...[25:11->25:30] (~someVariant25:32->25:43=...[25:44->25:45]) +Complete src/TypeContextCompletion_LabelledArguments.res 29:45 +posCursor:[29:45] posNoWhite:[29:44] Found expr:[29:11->29:45] +Pexp_apply ...[29:11->29:30] (~someVariant29:32->29:43=...[29:44->29:45]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant @@ -123,11 +123,31 @@ Found variant type for NamedArg typed context someVariant "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 28:45 -posCursor:[28:45] posNoWhite:[28:44] Found expr:[28:11->28:45] -Pexp_apply ...[28:11->28:30] (~someVariant28:32->28:43=...[28:44->28:45]) +Complete src/TypeContextCompletion_LabelledArguments.res 32:45 +posCursor:[32:45] posNoWhite:[32:44] Found expr:[32:11->32:45] +Pexp_apply ...[32:11->32:30] (~someVariant32:32->32:43=...[32:44->32:45]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant [] +Complete src/TypeContextCompletion_LabelledArguments.res 35:45 +posCursor:[35:45] posNoWhite:[35:44] Found expr:[35:11->35:45] +Pexp_apply ...[35:11->35:30] (~anotherThing35:32->35:44=...__ghost__[0:-1->0:-1]) +found typed context +Completable: CtypedContext(Value[someVariantToString], NamedArg(anotherThing)) +Found variant type for NamedArg typed context TypeDefinition.variant +[{ + "label": "Foo", + "kind": 4, + "tags": [], + "detail": "Foo\n\n", + "documentation": null + }, { + "label": "Bar", + "kind": 4, + "tags": [], + "detail": "Bar\n\n", + "documentation": null + }] + From ffa06f417329040f43fc05b916d918103c9ed94b Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 17 Jul 2022 23:05:12 +0200 Subject: [PATCH 14/80] complete polyvariants in addition to regular variants --- analysis/src/CompletionBackEnd.ml | 60 ++++++- analysis/src/SharedTypes.ml | 5 +- ...ypeContextCompletion_LabelledArguments.res | 18 +- ...ontextCompletion_LabelledArguments.res.txt | 158 +++++++++++++++--- 4 files changed, 212 insertions(+), 29 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 4815d2b8b..42d7228ba 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -711,6 +711,16 @@ let detail name (kind : Completion.kind) = | FileModule _ -> "file module" | Field ({typ}, s) -> name ^ ": " ^ (typ |> Shared.typeToString) ^ "\n\n" ^ s | Constructor (c, s) -> showConstructor c ^ "\n\n" ^ s + | PolyvariantConstructor {name; payload} -> ( + "#" ^ name + ^ + (* TODO: I get the feeling there's a more clever way to do this printing... + Multiple arguments (tuples) already print with parenthesis, but regular args don't. So account for that. *) + match payload with + | None -> "" + | Some ({desc = Types.Ttuple _} as typeExpr) -> + typeExpr |> Shared.typeToString + | Some typeExpr -> "(" ^ (typeExpr |> Shared.typeToString) ^ ")") let findAllCompletions ~(env : QueryEnv.t) ~prefix ~exact ~namesUsed ~(completionContext : Completable.completionContext) = @@ -992,6 +1002,11 @@ let rec extractRecordType ~env ~package (t : Types.type_expr) = | _ -> None) | _ -> None +type extractedType = + | Declared of QueryEnv.t * Type.t Declared.t + (* Polyvariants seem to be "inlined" in the type system, so we extract what we need from them here. *) + | Polyvariant of QueryEnv.t * SharedTypes.polyVariantConstructor list + let rec extractType ~env ~package (t : Types.type_expr) = match t.desc with | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> extractType ~env ~package t1 @@ -999,8 +1014,23 @@ let rec extractType ~env ~package (t : Types.type_expr) = match References.digConstructor ~env ~package path with | Some (env, {item = {decl = {type_manifest = Some t1}}}) -> extractType ~env ~package t1 - | Some (env, typ) -> Some (env, typ) + | Some (env, typ) -> Some (Declared (env, typ)) | _ -> None) + | Tvariant {row_fields} -> + (* Polyvariants seem "inlined" into the type system, so we extract just + what we need for completion from that definition here. *) + let constructors = + row_fields + |> List.map (fun (label, field) -> + { + name = label; + payload = + (match field with + | Types.Rpresent maybeTypeExpr -> maybeTypeExpr + | _ -> None); + }) + in + Some (Polyvariant (env, constructors)) | _ -> None let rec extractObjectType ~env ~package (t : Types.type_expr) = @@ -1737,7 +1767,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i Printf.printf "Could not extract type for labelled argument completion\n"; [] - | Some (_env, {item}) -> ( + | Some (Declared (_env, {item})) -> ( match item.kind with | Variant constructors -> if debug then @@ -1748,15 +1778,35 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i constructors |> List.filter (fun constructor -> Utils.startsWith constructor.Constructor.cname.txt prefix) - |> List.map (fun constructor -> + |> List.map (fun (constructor : Constructor.t) -> (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? Eg. Some($1) as completion item. *) Completion.create ~name: - (constructor.Constructor.cname.txt + (constructor.cname.txt ^ if constructor.args |> List.length > 0 then "(_)" else "" ) ~kind:(Constructor (constructor, "")) ~env) - | _ -> [])))) + | _ -> []) + | Some (Polyvariant (_env, constructors)) -> + if debug then + Printf.printf + "Found polyvariant type for NamedArg typed context: %s\n" + (typeExpr |> Shared.typeToString); + (* TODO: Investigate completing seen identifiers _with the correct type_ here too. Unsure if that's possible though + for polyvariants, if things aren't referred to by typename, but rather the full inlined type definition.. *) + constructors + |> List.filter (fun constructor -> + Utils.startsWith constructor.name prefix) + |> List.map (fun constructor -> + (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? + Eg. Some($1) as completion item. *) + Completion.create + ~name: + ("#" ^ constructor.name + ^ + if constructor.payload |> Option.is_some then "(_)" else "" + ) + ~kind:(PolyvariantConstructor constructor) ~env)))) diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 081df2e8f..72ddae61d 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -216,6 +216,8 @@ module QueryEnv = struct let fromFile file = {file; exported = file.structure.exported} end +type polyVariantConstructor = {name: string; payload: Types.type_expr option} + module Completion = struct type kind = | Module of Module.t @@ -224,6 +226,7 @@ module Completion = struct | Label of string | Type of Type.t | Constructor of Constructor.t * string + | PolyvariantConstructor of polyVariantConstructor | Field of field * string | FileModule of string @@ -244,7 +247,7 @@ module Completion = struct match kind with | Module _ -> 9 | FileModule _ -> 9 - | Constructor (_, _) -> 4 + | PolyvariantConstructor _ | Constructor (_, _) -> 4 | ObjLabel _ -> 4 | Label _ -> 4 | Field (_, _) -> 5 diff --git a/analysis/tests/src/TypeContextCompletion_LabelledArguments.res b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res index 0deb3e7d4..420e0bca3 100644 --- a/analysis/tests/src/TypeContextCompletion_LabelledArguments.res +++ b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res @@ -1,11 +1,13 @@ -type someVariant = One | Two | Three | Four | Five(int) | Six(option) +type someVariant = One | Two | Three | Four | Five(int) | Six(option, int) + +type otherVariant = [#one | #two | #three | #four | #five(int) | #six(option, int)] let someValue = Two let someVariantToString = ( ~someVariant, ~anotherThing: TypeDefinition.variant, - ~thirdThing: option, + ~thirdThing: otherVariant, ) => { ignore(anotherThing) ignore(thirdThing) @@ -35,3 +37,15 @@ let someVariantToString = ( // let x = someVariantToString(~anotherThing= // ^com + +// let x = someVariantToString(~thirdThing= +// ^com + +// let x = someVariantToString(~thirdThing= +// ^com + +// let x = someVariantToString(~thirdThing=#t +// ^com + +// let x = someVariantToString(~thirdThing=#T +// ^com diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index 0b4ed00b4..53da10dd6 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -1,11 +1,11 @@ -Complete src/TypeContextCompletion_LabelledArguments.res 20:41 -posCursor:[20:41] posNoWhite:[20:40] Found expr:[20:11->20:41] -Pexp_apply ...[20:11->20:30] (~someVaria20:32->20:41=...[20:32->20:41]) +Complete src/TypeContextCompletion_LabelledArguments.res 22:41 +posCursor:[22:41] posNoWhite:[22:40] Found expr:[22:11->22:41] +Pexp_apply ...[22:11->22:30] (~someVaria22:32->22:41=...[22:32->22:41]) Completable: CnamedArg(Value[someVariantToString], someVaria, [someVaria]) Found type for function ( ~someVariant: someVariant, ~anotherThing: TypeDefinition.variant, - ~thirdThing: option, + ~thirdThing: otherVariant, ) => string [{ "label": "someVariant", @@ -15,9 +15,9 @@ Found type for function ( "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 23:44 -posCursor:[23:44] posNoWhite:[23:43] Found expr:[23:11->23:44] -Pexp_apply ...[23:11->23:30] (~someVariant23:32->23:43=...__ghost__[0:-1->0:-1]) +Complete src/TypeContextCompletion_LabelledArguments.res 25:44 +posCursor:[25:44] posNoWhite:[25:43] Found expr:[25:11->25:44] +Pexp_apply ...[25:11->25:30] (~someVariant25:32->25:43=...__ghost__[0:-1->0:-1]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant @@ -55,13 +55,13 @@ Found variant type for NamedArg typed context someVariant "label": "Six(_)", "kind": 4, "tags": [], - "detail": "Six(option)\n\n", + "detail": "Six(option, int)\n\n", "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 26:45 -posCursor:[26:45] posNoWhite:[26:43] Found expr:[26:11->26:44] -Pexp_apply ...[26:11->26:30] (~someVariant26:32->26:43=...__ghost__[0:-1->0:-1]) +Complete src/TypeContextCompletion_LabelledArguments.res 28:45 +posCursor:[28:45] posNoWhite:[28:43] Found expr:[28:11->28:44] +Pexp_apply ...[28:11->28:30] (~someVariant28:32->28:43=...__ghost__[0:-1->0:-1]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant @@ -99,13 +99,13 @@ Found variant type for NamedArg typed context someVariant "label": "Six(_)", "kind": 4, "tags": [], - "detail": "Six(option)\n\n", + "detail": "Six(option, int)\n\n", "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 29:45 -posCursor:[29:45] posNoWhite:[29:44] Found expr:[29:11->29:45] -Pexp_apply ...[29:11->29:30] (~someVariant29:32->29:43=...[29:44->29:45]) +Complete src/TypeContextCompletion_LabelledArguments.res 31:45 +posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:11->31:45] +Pexp_apply ...[31:11->31:30] (~someVariant31:32->31:43=...[31:44->31:45]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant @@ -123,17 +123,17 @@ Found variant type for NamedArg typed context someVariant "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 32:45 -posCursor:[32:45] posNoWhite:[32:44] Found expr:[32:11->32:45] -Pexp_apply ...[32:11->32:30] (~someVariant32:32->32:43=...[32:44->32:45]) +Complete src/TypeContextCompletion_LabelledArguments.res 34:45 +posCursor:[34:45] posNoWhite:[34:44] Found expr:[34:11->34:45] +Pexp_apply ...[34:11->34:30] (~someVariant34:32->34:43=...[34:44->34:45]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) Found variant type for NamedArg typed context someVariant [] -Complete src/TypeContextCompletion_LabelledArguments.res 35:45 -posCursor:[35:45] posNoWhite:[35:44] Found expr:[35:11->35:45] -Pexp_apply ...[35:11->35:30] (~anotherThing35:32->35:44=...__ghost__[0:-1->0:-1]) +Complete src/TypeContextCompletion_LabelledArguments.res 37:45 +posCursor:[37:45] posNoWhite:[37:44] Found expr:[37:11->37:45] +Pexp_apply ...[37:11->37:30] (~anotherThing37:32->37:44=...__ghost__[0:-1->0:-1]) found typed context Completable: CtypedContext(Value[someVariantToString], NamedArg(anotherThing)) Found variant type for NamedArg typed context TypeDefinition.variant @@ -151,3 +151,119 @@ Found variant type for NamedArg typed context TypeDefinition.variant "documentation": null }] +Complete src/TypeContextCompletion_LabelledArguments.res 40:43 +posCursor:[40:43] posNoWhite:[40:42] Found expr:[40:11->40:43] +Pexp_apply ...[40:11->40:30] (~thirdThing40:32->40:42=...__ghost__[0:-1->0:-1]) +found typed context +Completable: CtypedContext(Value[someVariantToString], NamedArg(thirdThing)) +Found polyvariant type for NamedArg typed context: otherVariant +[{ + "label": "#one", + "kind": 4, + "tags": [], + "detail": "#one", + "documentation": null + }, { + "label": "#six(_)", + "kind": 4, + "tags": [], + "detail": "#six(option, int)", + "documentation": null + }, { + "label": "#three", + "kind": 4, + "tags": [], + "detail": "#three", + "documentation": null + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two", + "documentation": null + }, { + "label": "#five(_)", + "kind": 4, + "tags": [], + "detail": "#five(int)", + "documentation": null + }, { + "label": "#four", + "kind": 4, + "tags": [], + "detail": "#four", + "documentation": null + }] + +Complete src/TypeContextCompletion_LabelledArguments.res 43:44 +posCursor:[43:44] posNoWhite:[43:42] Found expr:[43:11->43:43] +Pexp_apply ...[43:11->43:30] (~thirdThing43:32->43:42=...__ghost__[0:-1->0:-1]) +found typed context +Completable: CtypedContext(Value[someVariantToString], NamedArg(thirdThing)) +Found polyvariant type for NamedArg typed context: otherVariant +[{ + "label": "#one", + "kind": 4, + "tags": [], + "detail": "#one", + "documentation": null + }, { + "label": "#six(_)", + "kind": 4, + "tags": [], + "detail": "#six(option, int)", + "documentation": null + }, { + "label": "#three", + "kind": 4, + "tags": [], + "detail": "#three", + "documentation": null + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two", + "documentation": null + }, { + "label": "#five(_)", + "kind": 4, + "tags": [], + "detail": "#five(int)", + "documentation": null + }, { + "label": "#four", + "kind": 4, + "tags": [], + "detail": "#four", + "documentation": null + }] + +Complete src/TypeContextCompletion_LabelledArguments.res 46:45 +posCursor:[46:45] posNoWhite:[46:44] Found expr:[46:11->46:45] +Pexp_apply ...[46:11->46:30] (~thirdThing46:32->46:42=...[46:43->46:45]) +found typed context +Completable: CtypedContext(Value[someVariantToString], NamedArg(thirdThing)) +Found polyvariant type for NamedArg typed context: otherVariant +[{ + "label": "#three", + "kind": 4, + "tags": [], + "detail": "#three", + "documentation": null + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two", + "documentation": null + }] + +Complete src/TypeContextCompletion_LabelledArguments.res 49:45 +posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:11->49:45] +Pexp_apply ...[49:11->49:30] (~thirdThing49:32->49:42=...[49:43->49:45]) +found typed context +Completable: CtypedContext(Value[someVariantToString], NamedArg(thirdThing)) +Found polyvariant type for NamedArg typed context: otherVariant +[] + From 37e4f9b39ddbe7bc995ac725958e65a7c1b8959b Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 18 Jul 2022 18:18:55 +0200 Subject: [PATCH 15/80] clarifications and touch ups after pr comments --- analysis/src/CompletionBackEnd.ml | 9 +++------ analysis/src/CompletionFrontEnd.ml | 4 ++-- analysis/src/SharedTypes.ml | 17 ++++++++--------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 42d7228ba..1af8e4bdb 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -714,8 +714,6 @@ let detail name (kind : Completion.kind) = | PolyvariantConstructor {name; payload} -> ( "#" ^ name ^ - (* TODO: I get the feeling there's a more clever way to do this printing... - Multiple arguments (tuples) already print with parenthesis, but regular args don't. So account for that. *) match payload with | None -> "" | Some ({desc = Types.Ttuple _} as typeExpr) -> @@ -1004,7 +1002,6 @@ let rec extractRecordType ~env ~package (t : Types.type_expr) = type extractedType = | Declared of QueryEnv.t * Type.t Declared.t - (* Polyvariants seem to be "inlined" in the type system, so we extract what we need from them here. *) | Polyvariant of QueryEnv.t * SharedTypes.polyVariantConstructor list let rec extractType ~env ~package (t : Types.type_expr) = @@ -1017,7 +1014,7 @@ let rec extractType ~env ~package (t : Types.type_expr) = | Some (env, typ) -> Some (Declared (env, typ)) | _ -> None) | Tvariant {row_fields} -> - (* Polyvariants seem "inlined" into the type system, so we extract just + (* Since polyvariants are strutural, they're "inlined". So, we extract just what we need for completion from that definition here. *) let constructors = row_fields @@ -1729,7 +1726,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i |> List.map mkLabel | CtypedContext (cp, typedContext) -> ( match typedContext with - | NamedArg {name = argName; prefix} -> ( + | NamedArg {label; prefix} -> ( (* TODO: Should probably share this with the branch handling CnamedArg... *) let labels = match @@ -1756,7 +1753,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i | None -> [] in let targetLabel = - labels |> List.find_opt (fun (name, _t) -> name = argName) + labels |> List.find_opt (fun (name, _t) -> name = label) in match targetLabel with | None -> [] diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 90cfcb39b..823f2c0b7 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -167,7 +167,7 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor Some (Completable.CtypedContext ( contextPath, - NamedArg {name = labelled.name; prefix = getPrefixFromExpr exp} + NamedArg {label = labelled.name; prefix = getPrefixFromExpr exp} ))) else if exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then ( (* Expr assigned presumably is "rescript.exprhole" after parser recovery. @@ -176,7 +176,7 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor Some (Completable.CtypedContext ( contextPath, - NamedArg {name = labelled.name; prefix = getPrefixFromExpr exp} + NamedArg {label = labelled.name; prefix = getPrefixFromExpr exp} ))) else loop rest | {label = None; exp} :: rest -> diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 72ddae61d..cacadcffa 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -428,18 +428,17 @@ module Completable = struct | CPObj of contextPath * string | CPPipe of contextPath * string - type namedArg = { - (* What the user has already started writing, if anything *) - prefix: string; - (* Name of the argument *) - name: string; - } - - type typedContext = NamedArg of namedArg + type typedContext = + | NamedArg of { + (* What the user has already started writing, if anything *) + prefix: string; + (* Name of the argument *) + label: string; + } let typedContextToString typedContext = match typedContext with - | NamedArg {name} -> "NamedArg(" ^ name ^ ")" + | NamedArg {label} -> "NamedArg(" ^ label ^ ")" type t = | Cdecorator of string (** e.g. @module *) From c2e2adfe8736764cad819017d58b130fcd4e11fb Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 18 Jul 2022 18:31:47 +0200 Subject: [PATCH 16/80] add dedicated example file for JSX completions --- .../tests/src/TypeContextCompletion_Jsx.res | 45 ++++++++ .../tests/src/expected/Completion.res.txt | 6 ++ analysis/tests/src/expected/Dce.res.txt | 2 +- analysis/tests/src/expected/Debug.res.txt | 3 +- .../TypeContextCompletion_Jsx.res.txt | 101 ++++++++++++++++++ 5 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 analysis/tests/src/TypeContextCompletion_Jsx.res create mode 100644 analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt diff --git a/analysis/tests/src/TypeContextCompletion_Jsx.res b/analysis/tests/src/TypeContextCompletion_Jsx.res new file mode 100644 index 000000000..b872cc63e --- /dev/null +++ b/analysis/tests/src/TypeContextCompletion_Jsx.res @@ -0,0 +1,45 @@ +type someVariant = One | Two | Three | Four | Five(int) | Six(option, int) + +type otherVariant = [#one | #two | #three | #four | #five(int) | #six(option, int)] + +let someValue = Two + +module SomeComponent = { + @react.component + let make = (~someVariant, ~anotherThing: TypeDefinition.variant, ~thirdThing: otherVariant) => { + ignore(someVariant) + ignore(anotherThing) + ignore(thirdThing) + React.null + } +} + +// let x = 16:35] +JSX 16:25] someVaria[16:26->16:35]=...[16:26->16:35]> _children:None +Completable: Cjsx([SomeComponent], someVaria, [someVaria]) +[{ + "label": "someVariant", + "kind": 4, + "tags": [], + "detail": "'someVariant", + "documentation": null + }] + +Complete src/TypeContextCompletion_Jsx.res 19:38 +posCursor:[19:38] posNoWhite:[19:37] Found expr:[19:12->19:38] +JSX 19:25] someVariant[19:26->19:37]=...__ghost__[0:-1->0:-1]> _children:None +[] + +Complete src/TypeContextCompletion_Jsx.res 22:39 +posCursor:[22:39] posNoWhite:[22:37] Found expr:[22:12->22:38] +JSX 22:25] someVariant[22:26->22:37]=...__ghost__[0:-1->0:-1]> _children:None +[] + +Complete src/TypeContextCompletion_Jsx.res 25:39 +posCursor:[25:39] posNoWhite:[25:38] Found expr:[25:12->25:39] +JSX 25:25] someVariant[25:26->25:37]=...[25:38->25:39]> _children:None +posCursor:[25:39] posNoWhite:[25:38] Found expr:[25:38->25:39] +Pexp_construct T:[25:38->25:39] None +Completable: Cpath Value[T] +[{ + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "TableclothMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_Jsx", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_LabelledArguments", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeDefinition", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }] + +Complete src/TypeContextCompletion_Jsx.res 28:39 +posCursor:[28:39] posNoWhite:[28:38] Found expr:[28:12->28:39] +JSX 28:25] someVariant[28:26->28:37]=...[28:38->28:39]> _children:None +posCursor:[28:39] posNoWhite:[28:38] Found expr:[28:38->28:39] +Pexp_ident t:[28:38->28:39] +Completable: Cpath Value[t] +[] + +Complete src/TypeContextCompletion_Jsx.res 31:39 +posCursor:[31:39] posNoWhite:[31:38] Found expr:[31:12->31:39] +JSX 31:25] anotherThing[31:26->31:38]=...__ghost__[0:-1->0:-1]> _children:None +[] + +Complete src/TypeContextCompletion_Jsx.res 34:37 +posCursor:[34:37] posNoWhite:[34:36] Found expr:[34:12->34:37] +JSX 34:25] thirdThing[34:26->34:36]=...__ghost__[0:-1->0:-1]> _children:None +[] + +Complete src/TypeContextCompletion_Jsx.res 37:38 +posCursor:[37:38] posNoWhite:[37:36] Found expr:[37:12->37:37] +JSX 37:25] thirdThing[37:26->37:36]=...__ghost__[0:-1->0:-1]> _children:None +[] + +Complete src/TypeContextCompletion_Jsx.res 40:39 +posCursor:[40:39] posNoWhite:[40:38] Found expr:[40:12->40:39] +JSX 40:25] thirdThing[40:26->40:36]=...[40:37->40:39]> _children:None +posCursor:[40:39] posNoWhite:[40:38] Found expr:[40:37->40:39] +[] + +Complete src/TypeContextCompletion_Jsx.res 43:39 +posCursor:[43:39] posNoWhite:[43:38] Found expr:[43:12->43:39] +JSX 43:25] thirdThing[43:26->43:36]=...[43:37->43:39]> _children:None +posCursor:[43:39] posNoWhite:[43:38] Found expr:[43:37->43:39] +[] + From d1d86e841411e50e1c803a9df28c91036d52fea3 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 18 Jul 2022 20:07:51 +0200 Subject: [PATCH 17/80] inline contextPath into NamedArg to pave way for JsxProp, that will not explicitly need the contextPAth --- analysis/src/CompletionBackEnd.ml | 6 +- analysis/src/CompletionFrontEnd.ml | 18 +++-- analysis/src/SharedTypes.ml | 71 +++++++++---------- ...ontextCompletion_LabelledArguments.res.txt | 18 ++--- 4 files changed, 59 insertions(+), 54 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 1af8e4bdb..043c9d28b 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1724,13 +1724,13 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i Utils.startsWith name prefix && (forHover || not (List.mem name identsSeen))) |> List.map mkLabel - | CtypedContext (cp, typedContext) -> ( + | CtypedContext typedContext -> ( match typedContext with - | NamedArg {label; prefix} -> ( + | NamedArg {label; prefix; contextPath} -> ( (* TODO: Should probably share this with the branch handling CnamedArg... *) let labels = match - cp + contextPath |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos ~env ~exact:true ~scope |> completionsGetTypeEnv diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 823f2c0b7..c6dac0dc4 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -166,18 +166,24 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor if debug then Printf.printf "found typed context \n"; Some (Completable.CtypedContext - ( contextPath, - NamedArg {label = labelled.name; prefix = getPrefixFromExpr exp} - ))) + (NamedArg + { + contextPath; + label = labelled.name; + prefix = getPrefixFromExpr exp; + }))) else if exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then ( (* Expr assigned presumably is "rescript.exprhole" after parser recovery. Assume this is an empty expression. *) if debug then Printf.printf "found typed context \n"; Some (Completable.CtypedContext - ( contextPath, - NamedArg {label = labelled.name; prefix = getPrefixFromExpr exp} - ))) + (NamedArg + { + contextPath; + label = labelled.name; + prefix = getPrefixFromExpr exp; + }))) else loop rest | {label = None; exp} :: rest -> if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then None diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index cacadcffa..873170033 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -430,15 +430,45 @@ module Completable = struct type typedContext = | NamedArg of { + (* The context path where the completion was found *) + contextPath: contextPath; (* What the user has already started writing, if anything *) prefix: string; (* Name of the argument *) label: string; } + let str s = if s = "" then "\"\"" else s + let list l = "[" ^ (l |> List.map str |> String.concat ", ") ^ "]" + + let completionContextToString = function + | Value -> "Value" + | Type -> "Type" + | Module -> "Module" + | Field -> "Field" + + let rec contextPathToString = function + | CPString -> "string" + | CPApply (cp, labels) -> + contextPathToString cp ^ "(" + ^ (labels + |> List.map (function + | Asttypes.Nolabel -> "Nolabel" + | Labelled s -> "~" ^ s + | Optional s -> "?" ^ s) + |> String.concat ", ") + ^ ")" + | CPArray -> "array" + | CPId (sl, completionContext) -> + completionContextToString completionContext ^ list sl + | CPField (cp, s) -> contextPathToString cp ^ "." ^ str s + | CPObj (cp, s) -> contextPathToString cp ^ "[\"" ^ s ^ "\"]" + | CPPipe (cp, s) -> contextPathToString cp ^ "->" ^ s + let typedContextToString typedContext = match typedContext with - | NamedArg {label} -> "NamedArg(" ^ label ^ ")" + | NamedArg {label; contextPath} -> + "NamedArg(" ^ label ^ ", " ^ (contextPath |> contextPathToString) ^ ")" type t = | Cdecorator of string (** e.g. @module *) @@ -448,37 +478,10 @@ module Completable = struct | Cpath of contextPath | Cjsx of string list * string * string list (** E.g. (["M", "Comp"], "id", ["id1", "id2"]) for List.map str |> String.concat ", ") ^ "]" in - let completionContextToString = function - | Value -> "Value" - | Type -> "Type" - | Module -> "Module" - | Field -> "Field" - in - let rec contextPathToString = function - | CPString -> "string" - | CPApply (cp, labels) -> - contextPathToString cp ^ "(" - ^ (labels - |> List.map (function - | Asttypes.Nolabel -> "Nolabel" - | Labelled s -> "~" ^ s - | Optional s -> "?" ^ s) - |> String.concat ", ") - ^ ")" - | CPArray -> "array" - | CPId (sl, completionContext) -> - completionContextToString completionContext ^ list sl - | CPField (cp, s) -> contextPathToString cp ^ "." ^ str s - | CPObj (cp, s) -> contextPathToString cp ^ "[\"" ^ s ^ "\"]" - | CPPipe (cp, s) -> contextPathToString cp ^ "->" ^ s - in - function + let toString = function | Cpath cp -> "Cpath " ^ contextPathToString cp | Cdecorator s -> "Cdecorator(" ^ str s ^ ")" | CnamedArg (cp, s, sl2) -> @@ -488,10 +491,6 @@ module Completable = struct | Cnone -> "Cnone" | Cjsx (sl1, s, sl2) -> "Cjsx(" ^ (sl1 |> list) ^ ", " ^ str s ^ ", " ^ (sl2 |> list) ^ ")" - | CtypedContext (cp, typedContext) -> - "CtypedContext(" - ^ (cp |> contextPathToString) - ^ ", " - ^ (typedContext |> typedContextToString) - ^ ")" + | CtypedContext typedContext -> + "CtypedContext(" ^ (typedContext |> typedContextToString) ^ ")" end diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index 53da10dd6..c363a1122 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -19,7 +19,7 @@ Complete src/TypeContextCompletion_LabelledArguments.res 25:44 posCursor:[25:44] posNoWhite:[25:43] Found expr:[25:11->25:44] Pexp_apply ...[25:11->25:30] (~someVariant25:32->25:43=...__ghost__[0:-1->0:-1]) found typed context -Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) +Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])) Found variant type for NamedArg typed context someVariant [{ "label": "One", @@ -63,7 +63,7 @@ Complete src/TypeContextCompletion_LabelledArguments.res 28:45 posCursor:[28:45] posNoWhite:[28:43] Found expr:[28:11->28:44] Pexp_apply ...[28:11->28:30] (~someVariant28:32->28:43=...__ghost__[0:-1->0:-1]) found typed context -Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) +Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])) Found variant type for NamedArg typed context someVariant [{ "label": "One", @@ -107,7 +107,7 @@ Complete src/TypeContextCompletion_LabelledArguments.res 31:45 posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:11->31:45] Pexp_apply ...[31:11->31:30] (~someVariant31:32->31:43=...[31:44->31:45]) found typed context -Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) +Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])) Found variant type for NamedArg typed context someVariant [{ "label": "Two", @@ -127,7 +127,7 @@ Complete src/TypeContextCompletion_LabelledArguments.res 34:45 posCursor:[34:45] posNoWhite:[34:44] Found expr:[34:11->34:45] Pexp_apply ...[34:11->34:30] (~someVariant34:32->34:43=...[34:44->34:45]) found typed context -Completable: CtypedContext(Value[someVariantToString], NamedArg(someVariant)) +Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])) Found variant type for NamedArg typed context someVariant [] @@ -135,7 +135,7 @@ Complete src/TypeContextCompletion_LabelledArguments.res 37:45 posCursor:[37:45] posNoWhite:[37:44] Found expr:[37:11->37:45] Pexp_apply ...[37:11->37:30] (~anotherThing37:32->37:44=...__ghost__[0:-1->0:-1]) found typed context -Completable: CtypedContext(Value[someVariantToString], NamedArg(anotherThing)) +Completable: CtypedContext(NamedArg(anotherThing, Value[someVariantToString])) Found variant type for NamedArg typed context TypeDefinition.variant [{ "label": "Foo", @@ -155,7 +155,7 @@ Complete src/TypeContextCompletion_LabelledArguments.res 40:43 posCursor:[40:43] posNoWhite:[40:42] Found expr:[40:11->40:43] Pexp_apply ...[40:11->40:30] (~thirdThing40:32->40:42=...__ghost__[0:-1->0:-1]) found typed context -Completable: CtypedContext(Value[someVariantToString], NamedArg(thirdThing)) +Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString])) Found polyvariant type for NamedArg typed context: otherVariant [{ "label": "#one", @@ -199,7 +199,7 @@ Complete src/TypeContextCompletion_LabelledArguments.res 43:44 posCursor:[43:44] posNoWhite:[43:42] Found expr:[43:11->43:43] Pexp_apply ...[43:11->43:30] (~thirdThing43:32->43:42=...__ghost__[0:-1->0:-1]) found typed context -Completable: CtypedContext(Value[someVariantToString], NamedArg(thirdThing)) +Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString])) Found polyvariant type for NamedArg typed context: otherVariant [{ "label": "#one", @@ -243,7 +243,7 @@ Complete src/TypeContextCompletion_LabelledArguments.res 46:45 posCursor:[46:45] posNoWhite:[46:44] Found expr:[46:11->46:45] Pexp_apply ...[46:11->46:30] (~thirdThing46:32->46:42=...[46:43->46:45]) found typed context -Completable: CtypedContext(Value[someVariantToString], NamedArg(thirdThing)) +Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString])) Found polyvariant type for NamedArg typed context: otherVariant [{ "label": "#three", @@ -263,7 +263,7 @@ Complete src/TypeContextCompletion_LabelledArguments.res 49:45 posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:11->49:45] Pexp_apply ...[49:11->49:30] (~thirdThing49:32->49:42=...[49:43->49:45]) found typed context -Completable: CtypedContext(Value[someVariantToString], NamedArg(thirdThing)) +Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString])) Found polyvariant type for NamedArg typed context: otherVariant [] From 90ccf19fcef8061d5da662c1729b26e014d55516 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 19 Jul 2022 20:44:13 +0200 Subject: [PATCH 18/80] add jsx example completing across files --- analysis/tests/src/Jsx.res | 3 +++ analysis/tests/src/expected/Jsx.res.txt | 30 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/analysis/tests/src/Jsx.res b/analysis/tests/src/Jsx.res index b49174d22..6b9e7f46c 100644 --- a/analysis/tests/src/Jsx.res +++ b/analysis/tests/src/Jsx.res @@ -168,3 +168,6 @@ let _ = { <> {<> } // ^hov } + +// let _ = +// ^com \ No newline at end of file diff --git a/analysis/tests/src/expected/Jsx.res.txt b/analysis/tests/src/expected/Jsx.res.txt index 041c8d867..6bec2fedd 100644 --- a/analysis/tests/src/expected/Jsx.res.txt +++ b/analysis/tests/src/expected/Jsx.res.txt @@ -431,3 +431,33 @@ JSX 167:14] age[167:15->167:18]=...[167:19->167:21]> _children:16 Completable: Cjsx([Comp], age, [age]) {"contents": "```rescript\nint\n```"} +Complete src/Jsx.res 171:30 +posCursor:[171:30] posNoWhite:[171:28] Found expr:[171:12->171:33] +JSX 171:29] > _children:171:31 +Completable: Cjsx([Completion, O, Comp], "", []) +[{ + "label": "first", + "kind": 4, + "tags": [], + "detail": "option", + "documentation": null + }, { + "label": "second", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null + }, { + "label": "zoo", + "kind": 4, + "tags": [], + "detail": "option", + "documentation": null + }, { + "label": "key", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null + }] + From d54b5624a2ef47932055a6621b0823f84aa69749 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 18 Jul 2022 22:43:55 +0200 Subject: [PATCH 19/80] basic JSX prop completion via type --- analysis/src/CompletionBackEnd.ml | 210 +++++++------ analysis/src/CompletionFrontEnd.ml | 104 ++++--- analysis/src/SharedTypes.ml | 20 +- analysis/src/Utils.ml | 39 +++ .../tests/src/TypeContextCompletion_Jsx.res | 6 +- ...ypeContextCompletion_LabelledArguments.res | 5 +- .../TypeContextCompletion_Jsx.res.txt | 283 ++++++++++++++---- ...ontextCompletion_LabelledArguments.res.txt | 74 +++-- 8 files changed, 513 insertions(+), 228 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 043c9d28b..2fc43e6ca 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1362,17 +1362,106 @@ let getOpens ~rawOpens ~package ~env = (* Last open takes priority *) List.rev resolvedOpens -let processCompletable ~debug ~package ~scope ~env ~pos ~forHover - (completable : Completable.t) = - let rawOpens = Scope.getRawOpens scope in - let opens = getOpens ~rawOpens ~package ~env in - let allFiles = FileSet.union package.projectFiles package.dependenciesFiles in +(* Takes a context and a component path (SomeModule.SomeComponent) and extracts all labels *) +let getLabelsForComponent ~package ~opens ~allFiles ~pos ~env ~scope + componentPath = let findTypeOfValue path = path |> getCompletionsForPath ~completionContext:Value ~exact:true ~package ~opens ~allFiles ~pos ~env ~scope |> completionsGetTypeEnv in + + match componentPath @ ["make"] |> findTypeOfValue with + | Some (typ, _env) -> + let rec getFields (texp : Types.type_expr) = + match texp.desc with + | Tfield (name, _, t1, t2) -> + let fields = t2 |> getFields in + if name = "children" then fields else (name, t1) :: fields + | Tlink te | Tsubst te | Tpoly (te, []) -> te |> getFields + | Tvar None -> [] + | _ -> [] + in + let rec getLabels (t : Types.type_expr) = + match t.desc with + | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> getLabels t1 + | Tarrow + ( Nolabel, + { + desc = + ( Tconstr (* Js.t *) (_, [{desc = Tobject (tObj, _)}], _) + | Tobject (tObj, _) ); + }, + _, + _ ) -> + getFields tObj + | Tconstr + ( path, + [ + { + desc = + ( Tconstr (* Js.t *) (_, [{desc = Tobject (tObj, _)}], _) + | Tobject (tObj, _) ); + }; + _; + ], + _ ) + when Path.name path = "React.componentLike" -> + getFields tObj + | _ -> [] + in + typ |> getLabels + | None -> [] + +(* This completes a type expression. Intended to be shared logic that can extract completions from a context, as soon as that the type is identified. *) +let completeTypeExpr ~env ~package ~debug ~prefix (typeExpr : Types.type_expr) = + match extractType ~env ~package typeExpr with + | None -> + if debug then Printf.printf "Could not extract type\n"; + [] + | Some (Declared (_env, {item})) -> ( + match item.kind with + | Variant constructors -> + if debug then + Printf.printf "Found variant type %s\n" (typeExpr |> Shared.typeToString); + (* TODO: Investigate completing seen identifiers _with the correct type_ here too. If completing + variant someVariant, and there's a someVariable of type someVariant, add that to the completion list. *) + constructors + |> List.filter (fun constructor -> + Utils.startsWith constructor.Constructor.cname.txt prefix) + |> List.map (fun (constructor : Constructor.t) -> + (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? + Eg. Some($1) as completion item. *) + Completion.create + ~name: + (constructor.cname.txt + ^ if constructor.args |> List.length > 0 then "(_)" else "") + ~kind:(Constructor (constructor, "")) + ~env) + | _ -> []) + | Some (Polyvariant (_env, constructors)) -> + if debug then + Printf.printf "Found polyvariant type %s\n" + (typeExpr |> Shared.typeToString); + (* TODO: Investigate completing seen identifiers _with the correct type_ here too. Unsure if that's possible though + for polyvariants, if things aren't referred to by typename, but rather the full inlined type definition.. *) + constructors + |> List.filter (fun constructor -> Utils.startsWith constructor.name prefix) + |> List.map (fun constructor -> + (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? + Eg. Some($1) as completion item. *) + Completion.create + ~name: + ("#" ^ constructor.name + ^ if constructor.payload |> Option.is_some then "(_)" else "") + ~kind:(PolyvariantConstructor constructor) ~env) + +let processCompletable ~debug ~package ~scope ~env ~pos ~forHover + (completable : Completable.t) = + let rawOpens = Scope.getRawOpens scope in + let opens = getOpens ~rawOpens ~package ~env in + let allFiles = FileSet.union package.projectFiles package.dependenciesFiles in match completable with | Cnone -> [] | Cpath contextPath -> @@ -1394,47 +1483,8 @@ let processCompletable ~debug ~package ~scope ~env ~pos ~forHover @ keyLabels | Cjsx (componentPath, prefix, identsSeen) -> let labels = - match componentPath @ ["make"] |> findTypeOfValue with - | Some (typ, _env) -> - let rec getFields (texp : Types.type_expr) = - match texp.desc with - | Tfield (name, _, t1, t2) -> - let fields = t2 |> getFields in - if name = "children" then fields else (name, t1) :: fields - | Tlink te | Tsubst te | Tpoly (te, []) -> te |> getFields - | Tvar None -> [] - | _ -> [] - in - let rec getLabels (t : Types.type_expr) = - match t.desc with - | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> getLabels t1 - | Tarrow - ( Nolabel, - { - desc = - ( Tconstr (* Js.t *) (_, [{desc = Tobject (tObj, _)}], _) - | Tobject (tObj, _) ); - }, - _, - _ ) -> - getFields tObj - | Tconstr - ( path, - [ - { - desc = - ( Tconstr (* Js.t *) (_, [{desc = Tobject (tObj, _)}], _) - | Tobject (tObj, _) ); - }; - _; - ], - _ ) - when Path.name path = "React.componentLike" -> - getFields tObj - | _ -> [] - in - typ |> getLabels - | None -> [] + componentPath + |> getLabelsForComponent ~package ~opens ~allFiles ~pos ~env ~scope in let mkLabel_ name typString = Completion.create ~name ~kind:(Label typString) ~env @@ -1757,53 +1807,21 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i in match targetLabel with | None -> [] - | Some (_, typeExpr) -> ( - match extractType ~env ~package typeExpr with - | None -> - if debug then - Printf.printf - "Could not extract type for labelled argument completion\n"; - [] - | Some (Declared (_env, {item})) -> ( - match item.kind with - | Variant constructors -> - if debug then - Printf.printf "Found variant type for NamedArg typed context %s\n" - (typeExpr |> Shared.typeToString); - (* TODO: Investigate completing seen identifiers _with the correct type_ here too. If completing - variant someVariant, and there's a someVariable of type someVariant, add that to the completion list. *) - constructors - |> List.filter (fun constructor -> - Utils.startsWith constructor.Constructor.cname.txt prefix) - |> List.map (fun (constructor : Constructor.t) -> - (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? - Eg. Some($1) as completion item. *) - Completion.create - ~name: - (constructor.cname.txt - ^ - if constructor.args |> List.length > 0 then "(_)" else "" - ) - ~kind:(Constructor (constructor, "")) - ~env) - | _ -> []) - | Some (Polyvariant (_env, constructors)) -> - if debug then - Printf.printf - "Found polyvariant type for NamedArg typed context: %s\n" - (typeExpr |> Shared.typeToString); - (* TODO: Investigate completing seen identifiers _with the correct type_ here too. Unsure if that's possible though - for polyvariants, if things aren't referred to by typename, but rather the full inlined type definition.. *) - constructors - |> List.filter (fun constructor -> - Utils.startsWith constructor.name prefix) - |> List.map (fun constructor -> - (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? - Eg. Some($1) as completion item. *) - Completion.create - ~name: - ("#" ^ constructor.name - ^ - if constructor.payload |> Option.is_some then "(_)" else "" - ) - ~kind:(PolyvariantConstructor constructor) ~env)))) + | Some (_, typeExpr) -> + completeTypeExpr ~env ~package ~debug ~prefix typeExpr) + | JsxProp {componentPath; propName; prefix} -> ( + (* TODO: Reintroduce these + potentially filter on type if possible...? *) + let _completionsFromContext = + Completable.CPId (prefix, Module) + |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos + ~env ~exact:forHover ~scope + in + match + componentPath + |> getLabelsForComponent ~package ~opens ~allFiles ~pos ~env ~scope + |> List.find_opt (fun (label, _typeExpr) -> label = propName) + with + | None -> [] + | Some (_label, typeExpr) -> + completeTypeExpr ~env ~package ~debug ~prefix:(List.hd prefix) typeExpr) + ) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index c6dac0dc4..873a46b1a 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -27,6 +27,38 @@ let positionToOffset text (line, character) = if bol + character <= String.length text then Some (bol + character) else None +let getIdentFromExpr exp = + match exp.Parsetree.pexp_desc with + | Pexp_ident {txt} -> txt + | Pexp_construct ({txt}, _) -> txt + | Pexp_variant (label, _) -> Lident label + | Pexp_field (_, {txt}) -> txt + | _ -> Lident "" + +let getPrefixFromExpr exp = getIdentFromExpr exp |> Longident.last + +let rec exprToContextPath (e : Parsetree.expression) = + match e.pexp_desc with + | Pexp_constant (Pconst_string _) -> Some Completable.CPString + | Pexp_array _ -> Some CPArray + | Pexp_ident {txt} -> Some (CPId (Utils.flattenLongIdent txt, Value)) + | Pexp_field (e1, {txt = Lident name}) -> ( + match exprToContextPath e1 with + | Some contextPath -> Some (CPField (contextPath, name)) + | _ -> None) + | Pexp_field (_, {txt = Ldot (lid, name)}) -> + (* Case x.M.field ignore the x part *) + Some (CPField (CPId (Utils.flattenLongIdent lid, Module), name)) + | Pexp_send (e1, {txt}) -> ( + match exprToContextPath e1 with + | None -> None + | Some contexPath -> Some (CPObj (contexPath, txt))) + | Pexp_apply (e1, args) -> ( + match exprToContextPath e1 with + | None -> None + | Some contexPath -> Some (CPApply (contexPath, args |> List.map fst))) + | _ -> None + type prop = { name: string; posStart: int * int; @@ -40,8 +72,16 @@ type jsxProps = { childrenStart: (int * int) option; } +(* Checks if an expression is elgible for typed context completion. *) +let isElgibleForTypedContextCompletion exp = + match exp.Parsetree.pexp_desc with + | Pexp_variant _ | Pexp_field _ | Pexp_construct _ + | Pexp_extension ({txt = "rescript.exprhole"}, _) -> + true + | _ -> false + let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName - = + ~debug = let allLabels = List.fold_right (fun prop allLabels -> prop.name :: allLabels) @@ -64,11 +104,35 @@ let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName None else if prop.exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then (* Cursor on expr assigned *) - None + if isElgibleForTypedContextCompletion prop.exp then ( + if debug then Printf.printf "Found typed context\n"; + let typedContext = + Completable.JsxProp + { + componentPath = + Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; + propName = prop.name; + prefix = getIdentFromExpr prop.exp |> Utils.flattenLongIdent; + } + in + Some (CtypedContext typedContext)) + else None else if prop.exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then (* Expr assigned presumably is "rescript.exprhole" after parser recovery. - To be on the safe side, don't do label completion. *) - None + Complete for the value. *) + if isElgibleForTypedContextCompletion prop.exp then ( + if debug then Printf.printf "Found typed context\n"; + let typedContext = + Completable.JsxProp + { + componentPath = + Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; + propName = prop.name; + prefix = getIdentFromExpr prop.exp |> Utils.flattenLongIdent; + } + in + Some (CtypedContext typedContext)) + else None else loop rest | [] -> let beforeChildrenStart = @@ -136,14 +200,6 @@ type labelled = { type label = labelled option type arg = {label: label; exp: Parsetree.expression} -let getPrefixFromExpr exp = - match exp.Parsetree.pexp_desc with - | Pexp_ident {txt} -> txt |> Longident.last - | Pexp_construct ({txt}, _) -> txt |> Longident.last - | Pexp_variant (label, _) -> label - | Pexp_field (_, {txt}) -> txt |> Longident.last - | _ -> "" - let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor ~(contextPath : Completable.contextPath) ~posAfterFunExpr ~debug = let allNames = @@ -226,28 +282,6 @@ let extractExpApplyArgs ~args = in args |> processArgs ~acc:[] -let rec exprToContextPath (e : Parsetree.expression) = - match e.pexp_desc with - | Pexp_constant (Pconst_string _) -> Some Completable.CPString - | Pexp_array _ -> Some CPArray - | Pexp_ident {txt} -> Some (CPId (Utils.flattenLongIdent txt, Value)) - | Pexp_field (e1, {txt = Lident name}) -> ( - match exprToContextPath e1 with - | Some contextPath -> Some (CPField (contextPath, name)) - | _ -> None) - | Pexp_field (_, {txt = Ldot (lid, name)}) -> - (* Case x.M.field ignore the x part *) - Some (CPField (CPId (Utils.flattenLongIdent lid, Module), name)) - | Pexp_send (e1, {txt}) -> ( - match exprToContextPath e1 with - | None -> None - | Some contexPath -> Some (CPObj (contexPath, txt))) - | Pexp_apply (e1, args) -> ( - match exprToContextPath e1 with - | None -> None - | Some contexPath -> Some (CPApply (contexPath, args |> List.map fst))) - | _ -> None - let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = let offsetNoWhite = skipWhite text (offset - 1) in let posNoWhite = @@ -572,7 +606,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | Some childrenPosStart -> Pos.toString childrenPosStart); let jsxCompletable = findJsxPropsCompletable ~jsxProps ~endPos:(Loc.end_ expr.pexp_loc) - ~posBeforeCursor ~posAfterCompName:(Loc.end_ compName.loc) + ~posBeforeCursor ~posAfterCompName:(Loc.end_ compName.loc) ~debug in if jsxCompletable <> None then setResultOpt jsxCompletable else if compName.loc |> Loc.hasPos ~pos:posBeforeCursor then diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 873170033..f7daf0ed5 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -429,6 +429,7 @@ module Completable = struct | CPPipe of contextPath * string type typedContext = + (* A labelled argument assignment, eg. someFunc(~someArg=) *) | NamedArg of { (* The context path where the completion was found *) contextPath: contextPath; @@ -437,9 +438,19 @@ module Completable = struct (* Name of the argument *) label: string; } + (* A JSX prop assignment, eg. *) + | JsxProp of { + (* Path to the target component *) + componentPath: string list; + (* The target prop name *) + propName: string; + (* What the user has already started writing, if anything *) + prefix: string list; + } let str s = if s = "" then "\"\"" else s let list l = "[" ^ (l |> List.map str |> String.concat ", ") ^ "]" + let ident l = l |> List.map str |> String.concat "." let completionContextToString = function | Value -> "Value" @@ -467,8 +478,13 @@ module Completable = struct let typedContextToString typedContext = match typedContext with - | NamedArg {label; contextPath} -> - "NamedArg(" ^ label ^ ", " ^ (contextPath |> contextPathToString) ^ ")" + | NamedArg {label; contextPath; prefix} -> + "NamedArg(" ^ label ^ ", " + ^ (contextPath |> contextPathToString) + ^ ")=" ^ prefix + | JsxProp {propName; componentPath; prefix} -> + "JsxProp(<" ^ (componentPath |> ident) ^ " " ^ propName ^ "=" + ^ (prefix |> ident) ^ " />)" type t = | Cdecorator of string (** e.g. @module *) diff --git a/analysis/src/Utils.ml b/analysis/src/Utils.ml index c785d54f1..7d8ed8e7d 100644 --- a/analysis/src/Utils.ml +++ b/analysis/src/Utils.ml @@ -71,3 +71,42 @@ let flattenLongIdent ?(jsx = false) ?(cutAtOffset = None) lid = in let path, _ = loop lid in List.rev path + +let identifyPexp pexp = + match pexp with + | Parsetree.Pexp_ident _ -> "Pexp_ident" + | Pexp_constant _ -> "Pexp_constant" + | Pexp_let _ -> "Pexp_let" + | Pexp_function _ -> "Pexp_function" + | Pexp_fun _ -> "Pexp_fun" + | Pexp_apply _ -> "Pexp_apply" + | Pexp_match _ -> "Pexp_match" + | Pexp_try _ -> "Pexp_try" + | Pexp_tuple _ -> "Pexp_tuple" + | Pexp_construct _ -> "Pexp_construct" + | Pexp_variant _ -> "Pexp_variant" + | Pexp_record _ -> "Pexp_record" + | Pexp_field _ -> "Pexp_field" + | Pexp_setfield _ -> "Pexp_setfield" + | Pexp_array _ -> "Pexp_array" + | Pexp_ifthenelse _ -> "Pexp_ifthenelse" + | Pexp_sequence _ -> "Pexp_sequence" + | Pexp_while _ -> "Pexp_while" + | Pexp_for _ -> "Pexp_for" + | Pexp_constraint _ -> "Pexp_constraint" + | Pexp_coerce _ -> "Pexp_coerce" + | Pexp_send _ -> "Pexp_send" + | Pexp_new _ -> "Pexp_new" + | Pexp_setinstvar _ -> "Pexp_setinstvar" + | Pexp_override _ -> "Pexp_override" + | Pexp_letmodule _ -> "Pexp_letmodule" + | Pexp_letexception _ -> "Pexp_letexception" + | Pexp_assert _ -> "Pexp_assert" + | Pexp_lazy _ -> "Pexp_lazy" + | Pexp_poly _ -> "Pexp_poly" + | Pexp_object _ -> "Pexp_object" + | Pexp_newtype _ -> "Pexp_newtype" + | Pexp_pack _ -> "Pexp_pack" + | Pexp_extension _ -> "Pexp_extension" + | Pexp_open _ -> "Pexp_open" + | Pexp_unreachable -> "Pexp_unreachable" \ No newline at end of file diff --git a/analysis/tests/src/TypeContextCompletion_Jsx.res b/analysis/tests/src/TypeContextCompletion_Jsx.res index b872cc63e..8a9fff01c 100644 --- a/analysis/tests/src/TypeContextCompletion_Jsx.res +++ b/analysis/tests/src/TypeContextCompletion_Jsx.res @@ -6,7 +6,11 @@ let someValue = Two module SomeComponent = { @react.component - let make = (~someVariant, ~anotherThing: TypeDefinition.variant, ~thirdThing: otherVariant) => { + let make = ( + ~someVariant: someVariant, + ~anotherThing: TypeDefinition.variant, + ~thirdThing: otherVariant, + ) => { ignore(someVariant) ignore(anotherThing) ignore(thirdThing) diff --git a/analysis/tests/src/TypeContextCompletion_LabelledArguments.res b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res index 420e0bca3..e85808361 100644 --- a/analysis/tests/src/TypeContextCompletion_LabelledArguments.res +++ b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res @@ -2,7 +2,7 @@ type someVariant = One | Two | Three | Four | Five(int) | Six(option, in type otherVariant = [#one | #two | #three | #four | #five(int) | #six(option, int)] -let someValue = Two +let thisIsAValue = Two let someVariantToString = ( ~someVariant, @@ -35,6 +35,9 @@ let someVariantToString = ( // let x = someVariantToString(~someVariant=t // ^com +// let x = someVariantToString(~someVariant=TypeDefinition. +// ^com + // let x = someVariantToString(~anotherThing= // ^com diff --git a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt index 4aef7c4bb..13e536aa8 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt @@ -1,101 +1,264 @@ -Complete src/TypeContextCompletion_Jsx.res 16:35 -posCursor:[16:35] posNoWhite:[16:34] Found expr:[16:12->16:35] -JSX 16:25] someVaria[16:26->16:35]=...[16:26->16:35]> _children:None +Complete src/TypeContextCompletion_Jsx.res 20:35 +posCursor:[20:35] posNoWhite:[20:34] Found expr:[20:12->20:35] +JSX 20:25] someVaria[20:26->20:35]=...[20:26->20:35]> _children:None Completable: Cjsx([SomeComponent], someVaria, [someVaria]) [{ "label": "someVariant", "kind": 4, "tags": [], - "detail": "'someVariant", + "detail": "someVariant", "documentation": null }] -Complete src/TypeContextCompletion_Jsx.res 19:38 -posCursor:[19:38] posNoWhite:[19:37] Found expr:[19:12->19:38] -JSX 19:25] someVariant[19:26->19:37]=...__ghost__[0:-1->0:-1]> _children:None -[] - -Complete src/TypeContextCompletion_Jsx.res 22:39 -posCursor:[22:39] posNoWhite:[22:37] Found expr:[22:12->22:38] -JSX 22:25] someVariant[22:26->22:37]=...__ghost__[0:-1->0:-1]> _children:None -[] - -Complete src/TypeContextCompletion_Jsx.res 25:39 -posCursor:[25:39] posNoWhite:[25:38] Found expr:[25:12->25:39] -JSX 25:25] someVariant[25:26->25:37]=...[25:38->25:39]> _children:None -posCursor:[25:39] posNoWhite:[25:38] Found expr:[25:38->25:39] -Pexp_construct T:[25:38->25:39] None -Completable: Cpath Value[T] +Complete src/TypeContextCompletion_Jsx.res 23:38 +posCursor:[23:38] posNoWhite:[23:37] Found expr:[23:12->23:38] +JSX 23:25] someVariant[23:26->23:37]=...__ghost__[0:-1->0:-1]> _children:None +Found typed context +Completable: CtypedContext(JsxProp()) +Found variant type someVariant [{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { "label": "Three", "kind": 4, "tags": [], - "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "detail": "Three\n\n", + "documentation": null + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\n", + "documentation": null + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\n", + "documentation": null + }, { + "label": "Six(_)", + "kind": 4, + "tags": [], + "detail": "Six(option, int)\n\n", + "documentation": null + }] + +Complete src/TypeContextCompletion_Jsx.res 26:39 +posCursor:[26:39] posNoWhite:[26:37] Found expr:[26:12->26:38] +JSX 26:25] someVariant[26:26->26:37]=...__ghost__[0:-1->0:-1]> _children:None +Found typed context +Completable: CtypedContext(JsxProp()) +Found variant type someVariant +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", "documentation": null }, { "label": "Two", "kind": 4, "tags": [], - "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\n", "documentation": null }, { - "label": "TableclothMap", - "kind": 9, + "label": "Four", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Four\n\n", "documentation": null }, { - "label": "TypeContextCompletion_Jsx", - "kind": 9, + "label": "Five(_)", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Five(int)\n\n", "documentation": null }, { - "label": "TypeContextCompletion_LabelledArguments", - "kind": 9, + "label": "Six(_)", + "kind": 4, + "tags": [], + "detail": "Six(option, int)\n\n", + "documentation": null + }] + +Complete src/TypeContextCompletion_Jsx.res 29:39 +posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:12->29:39] +JSX 29:25] someVariant[29:26->29:37]=...[29:38->29:39]> _children:None +Found typed context +Completable: CtypedContext(JsxProp()) +Found variant type someVariant +[{ + "label": "Two", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Two\n\n", "documentation": null }, { - "label": "TypeDefinition", - "kind": 9, + "label": "Three", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Three\n\n", "documentation": null }] -Complete src/TypeContextCompletion_Jsx.res 28:39 -posCursor:[28:39] posNoWhite:[28:38] Found expr:[28:12->28:39] -JSX 28:25] someVariant[28:26->28:37]=...[28:38->28:39]> _children:None -posCursor:[28:39] posNoWhite:[28:38] Found expr:[28:38->28:39] -Pexp_ident t:[28:38->28:39] +Complete src/TypeContextCompletion_Jsx.res 32:39 +posCursor:[32:39] posNoWhite:[32:38] Found expr:[32:12->32:39] +JSX 32:25] someVariant[32:26->32:37]=...[32:38->32:39]> _children:None +posCursor:[32:39] posNoWhite:[32:38] Found expr:[32:38->32:39] +Pexp_ident t:[32:38->32:39] Completable: Cpath Value[t] [] -Complete src/TypeContextCompletion_Jsx.res 31:39 -posCursor:[31:39] posNoWhite:[31:38] Found expr:[31:12->31:39] -JSX 31:25] anotherThing[31:26->31:38]=...__ghost__[0:-1->0:-1]> _children:None -[] +Complete src/TypeContextCompletion_Jsx.res 35:39 +posCursor:[35:39] posNoWhite:[35:38] Found expr:[35:12->35:39] +JSX 35:25] anotherThing[35:26->35:38]=...__ghost__[0:-1->0:-1]> _children:None +Found typed context +Completable: CtypedContext(JsxProp()) +Found variant type TypeDefinition.variant +[{ + "label": "Foo", + "kind": 4, + "tags": [], + "detail": "Foo\n\n", + "documentation": null + }, { + "label": "Bar", + "kind": 4, + "tags": [], + "detail": "Bar\n\n", + "documentation": null + }] -Complete src/TypeContextCompletion_Jsx.res 34:37 -posCursor:[34:37] posNoWhite:[34:36] Found expr:[34:12->34:37] -JSX 34:25] thirdThing[34:26->34:36]=...__ghost__[0:-1->0:-1]> _children:None -[] +Complete src/TypeContextCompletion_Jsx.res 38:37 +posCursor:[38:37] posNoWhite:[38:36] Found expr:[38:12->38:37] +JSX 38:25] thirdThing[38:26->38:36]=...__ghost__[0:-1->0:-1]> _children:None +Found typed context +Completable: CtypedContext(JsxProp()) +Found polyvariant type otherVariant +[{ + "label": "#one", + "kind": 4, + "tags": [], + "detail": "#one", + "documentation": null + }, { + "label": "#six(_)", + "kind": 4, + "tags": [], + "detail": "#six(option, int)", + "documentation": null + }, { + "label": "#three", + "kind": 4, + "tags": [], + "detail": "#three", + "documentation": null + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two", + "documentation": null + }, { + "label": "#five(_)", + "kind": 4, + "tags": [], + "detail": "#five(int)", + "documentation": null + }, { + "label": "#four", + "kind": 4, + "tags": [], + "detail": "#four", + "documentation": null + }] -Complete src/TypeContextCompletion_Jsx.res 37:38 -posCursor:[37:38] posNoWhite:[37:36] Found expr:[37:12->37:37] -JSX 37:25] thirdThing[37:26->37:36]=...__ghost__[0:-1->0:-1]> _children:None -[] +Complete src/TypeContextCompletion_Jsx.res 41:38 +posCursor:[41:38] posNoWhite:[41:36] Found expr:[41:12->41:37] +JSX 41:25] thirdThing[41:26->41:36]=...__ghost__[0:-1->0:-1]> _children:None +Found typed context +Completable: CtypedContext(JsxProp()) +Found polyvariant type otherVariant +[{ + "label": "#one", + "kind": 4, + "tags": [], + "detail": "#one", + "documentation": null + }, { + "label": "#six(_)", + "kind": 4, + "tags": [], + "detail": "#six(option, int)", + "documentation": null + }, { + "label": "#three", + "kind": 4, + "tags": [], + "detail": "#three", + "documentation": null + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two", + "documentation": null + }, { + "label": "#five(_)", + "kind": 4, + "tags": [], + "detail": "#five(int)", + "documentation": null + }, { + "label": "#four", + "kind": 4, + "tags": [], + "detail": "#four", + "documentation": null + }] -Complete src/TypeContextCompletion_Jsx.res 40:39 -posCursor:[40:39] posNoWhite:[40:38] Found expr:[40:12->40:39] -JSX 40:25] thirdThing[40:26->40:36]=...[40:37->40:39]> _children:None -posCursor:[40:39] posNoWhite:[40:38] Found expr:[40:37->40:39] -[] +Complete src/TypeContextCompletion_Jsx.res 44:39 +posCursor:[44:39] posNoWhite:[44:38] Found expr:[44:12->44:39] +JSX 44:25] thirdThing[44:26->44:36]=...[44:37->44:39]> _children:None +Found typed context +Completable: CtypedContext(JsxProp()) +Found polyvariant type otherVariant +[{ + "label": "#three", + "kind": 4, + "tags": [], + "detail": "#three", + "documentation": null + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two", + "documentation": null + }] -Complete src/TypeContextCompletion_Jsx.res 43:39 -posCursor:[43:39] posNoWhite:[43:38] Found expr:[43:12->43:39] -JSX 43:25] thirdThing[43:26->43:36]=...[43:37->43:39]> _children:None -posCursor:[43:39] posNoWhite:[43:38] Found expr:[43:37->43:39] +Complete src/TypeContextCompletion_Jsx.res 47:39 +posCursor:[47:39] posNoWhite:[47:38] Found expr:[47:12->47:39] +JSX 47:25] thirdThing[47:26->47:36]=...[47:37->47:39]> _children:None +Found typed context +Completable: CtypedContext(JsxProp()) +Found polyvariant type otherVariant [] diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index c363a1122..7118e0755 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -19,8 +19,8 @@ Complete src/TypeContextCompletion_LabelledArguments.res 25:44 posCursor:[25:44] posNoWhite:[25:43] Found expr:[25:11->25:44] Pexp_apply ...[25:11->25:30] (~someVariant25:32->25:43=...__ghost__[0:-1->0:-1]) found typed context -Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])) -Found variant type for NamedArg typed context someVariant +Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])=) +Found variant type someVariant [{ "label": "One", "kind": 4, @@ -63,8 +63,8 @@ Complete src/TypeContextCompletion_LabelledArguments.res 28:45 posCursor:[28:45] posNoWhite:[28:43] Found expr:[28:11->28:44] Pexp_apply ...[28:11->28:30] (~someVariant28:32->28:43=...__ghost__[0:-1->0:-1]) found typed context -Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])) -Found variant type for NamedArg typed context someVariant +Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])=) +Found variant type someVariant [{ "label": "One", "kind": 4, @@ -107,8 +107,8 @@ Complete src/TypeContextCompletion_LabelledArguments.res 31:45 posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:11->31:45] Pexp_apply ...[31:11->31:30] (~someVariant31:32->31:43=...[31:44->31:45]) found typed context -Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])) -Found variant type for NamedArg typed context someVariant +Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])=T) +Found variant type someVariant [{ "label": "Two", "kind": 4, @@ -127,16 +127,24 @@ Complete src/TypeContextCompletion_LabelledArguments.res 34:45 posCursor:[34:45] posNoWhite:[34:44] Found expr:[34:11->34:45] Pexp_apply ...[34:11->34:30] (~someVariant34:32->34:43=...[34:44->34:45]) found typed context -Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])) -Found variant type for NamedArg typed context someVariant +Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])=t) +Found variant type someVariant [] -Complete src/TypeContextCompletion_LabelledArguments.res 37:45 -posCursor:[37:45] posNoWhite:[37:44] Found expr:[37:11->37:45] -Pexp_apply ...[37:11->37:30] (~anotherThing37:32->37:44=...__ghost__[0:-1->0:-1]) +Complete src/TypeContextCompletion_LabelledArguments.res 37:59 +posCursor:[37:59] posNoWhite:[37:58] Found expr:[37:11->37:59] +Pexp_apply ...[37:11->37:30] (~someVariant37:32->37:43=...[37:44->37:59]) found typed context -Completable: CtypedContext(NamedArg(anotherThing, Value[someVariantToString])) -Found variant type for NamedArg typed context TypeDefinition.variant +Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])=_) +Found variant type someVariant +[] + +Complete src/TypeContextCompletion_LabelledArguments.res 40:45 +posCursor:[40:45] posNoWhite:[40:44] Found expr:[40:11->40:45] +Pexp_apply ...[40:11->40:30] (~anotherThing40:32->40:44=...__ghost__[0:-1->0:-1]) +found typed context +Completable: CtypedContext(NamedArg(anotherThing, Value[someVariantToString])=) +Found variant type TypeDefinition.variant [{ "label": "Foo", "kind": 4, @@ -151,12 +159,12 @@ Found variant type for NamedArg typed context TypeDefinition.variant "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 40:43 -posCursor:[40:43] posNoWhite:[40:42] Found expr:[40:11->40:43] -Pexp_apply ...[40:11->40:30] (~thirdThing40:32->40:42=...__ghost__[0:-1->0:-1]) +Complete src/TypeContextCompletion_LabelledArguments.res 43:43 +posCursor:[43:43] posNoWhite:[43:42] Found expr:[43:11->43:43] +Pexp_apply ...[43:11->43:30] (~thirdThing43:32->43:42=...__ghost__[0:-1->0:-1]) found typed context -Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString])) -Found polyvariant type for NamedArg typed context: otherVariant +Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString])=) +Found polyvariant type otherVariant [{ "label": "#one", "kind": 4, @@ -195,12 +203,12 @@ Found polyvariant type for NamedArg typed context: otherVariant "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 43:44 -posCursor:[43:44] posNoWhite:[43:42] Found expr:[43:11->43:43] -Pexp_apply ...[43:11->43:30] (~thirdThing43:32->43:42=...__ghost__[0:-1->0:-1]) +Complete src/TypeContextCompletion_LabelledArguments.res 46:44 +posCursor:[46:44] posNoWhite:[46:42] Found expr:[46:11->46:43] +Pexp_apply ...[46:11->46:30] (~thirdThing46:32->46:42=...__ghost__[0:-1->0:-1]) found typed context -Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString])) -Found polyvariant type for NamedArg typed context: otherVariant +Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString])=) +Found polyvariant type otherVariant [{ "label": "#one", "kind": 4, @@ -239,12 +247,12 @@ Found polyvariant type for NamedArg typed context: otherVariant "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 46:45 -posCursor:[46:45] posNoWhite:[46:44] Found expr:[46:11->46:45] -Pexp_apply ...[46:11->46:30] (~thirdThing46:32->46:42=...[46:43->46:45]) +Complete src/TypeContextCompletion_LabelledArguments.res 49:45 +posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:11->49:45] +Pexp_apply ...[49:11->49:30] (~thirdThing49:32->49:42=...[49:43->49:45]) found typed context -Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString])) -Found polyvariant type for NamedArg typed context: otherVariant +Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString])=t) +Found polyvariant type otherVariant [{ "label": "#three", "kind": 4, @@ -259,11 +267,11 @@ Found polyvariant type for NamedArg typed context: otherVariant "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 49:45 -posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:11->49:45] -Pexp_apply ...[49:11->49:30] (~thirdThing49:32->49:42=...[49:43->49:45]) +Complete src/TypeContextCompletion_LabelledArguments.res 52:45 +posCursor:[52:45] posNoWhite:[52:44] Found expr:[52:11->52:45] +Pexp_apply ...[52:11->52:30] (~thirdThing52:32->52:42=...[52:43->52:45]) found typed context -Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString])) -Found polyvariant type for NamedArg typed context: otherVariant +Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString])=T) +Found polyvariant type otherVariant [] From 2b29291a1390ce7615e14cbd85f5574c7b632d1d Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 19 Jul 2022 21:04:35 +0200 Subject: [PATCH 20/80] add completions from context in addition to the explicit type based completions --- analysis/src/CompletionBackEnd.ml | 12 +- .../TypeContextCompletion_Jsx.res.txt | 5588 ++++++++++++++++- 2 files changed, 5477 insertions(+), 123 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 2fc43e6ca..80a49383b 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1810,9 +1810,11 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i | Some (_, typeExpr) -> completeTypeExpr ~env ~package ~debug ~prefix typeExpr) | JsxProp {componentPath; propName; prefix} -> ( - (* TODO: Reintroduce these + potentially filter on type if possible...? *) - let _completionsFromContext = - Completable.CPId (prefix, Module) + (* TODO: Variant constructors seem to re-appear here. + Wondering if we can get rid of "randomly" completing constructors in scope. Or at least de-duping somehow. *) + (* These are the regular completions for context. Identifiers, modules, etc. *) + let completionsFromContext = + Completable.CPId (prefix, Value) |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos ~env ~exact:forHover ~scope in @@ -1823,5 +1825,5 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i with | None -> [] | Some (_label, typeExpr) -> - completeTypeExpr ~env ~package ~debug ~prefix:(List.hd prefix) typeExpr) - ) + completeTypeExpr ~env ~package ~debug ~prefix:(List.hd prefix) typeExpr + @ completionsFromContext)) diff --git a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt index 13e536aa8..4122025c1 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt @@ -52,185 +52,5501 @@ Found variant type someVariant "tags": [], "detail": "Six(option, int)\n\n", "documentation": null - }] - -Complete src/TypeContextCompletion_Jsx.res 26:39 -posCursor:[26:39] posNoWhite:[26:37] Found expr:[26:12->26:38] -JSX 26:25] someVariant[26:26->26:37]=...__ghost__[0:-1->0:-1]> _children:None -Found typed context -Completable: CtypedContext(JsxProp()) -Found variant type someVariant -[{ + }, { + "label": "someValue", + "kind": 12, + "tags": [], + "detail": "someVariant", + "documentation": null + }, { + "label": "Six", + "kind": 4, + "tags": [], + "detail": "Six(option, int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Five", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { "label": "One", "kind": 4, "tags": [], - "detail": "One\n\n", + "detail": "One\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "SomeComponent", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null + }, { + "label": "Arg", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ArrayLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Auto", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Float", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSet", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Id", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Int", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_List", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Map", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapDict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableQueue", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSet", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableStack", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Option", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Range", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Result", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Set", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetDict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArray", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArrayInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArrayString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalAVLset", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalAVLtree", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalBuckets", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalBucketsType", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetBuckets", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internals", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Buffer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Bytes", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "BytesLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Callback", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CamlinternalLazy", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CamlinternalMod", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Char", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CompletePrioritize1", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CompletePrioritize2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Completion", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Complex", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Component", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CreateInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Cross", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dce", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Debug", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Definition", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "DefinitionWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Digest", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Div", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "DocumentSymbol", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom_storage", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom_storage2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Filename", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Fragment", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Genlex", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Hashtbl", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "HashtblLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Highlight", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Hover", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Int32", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Int64", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_OO", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_array2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_bigint", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_cast", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_console", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_date", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_dict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_exn", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_float", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_global", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_int", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_json", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_list", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_mapperRt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_math", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_null", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_null_undefined", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_obj", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_option", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_promise", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_re", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_result", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_string", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_string2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_typed_array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_typed_array2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_types", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_undefined", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_vector", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Jsx", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Lazy", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Lexing", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "List", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ListLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "LongIdentTest", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Map", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "MapLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "MoreLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_buffer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_child_process", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_fs", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_module", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_path", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_process", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Obj", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Object", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Parsing", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Patterns", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Pervasives", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Printexc", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Queue", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Random", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "React", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOM", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMRe", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMServer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMStyle", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactEvent", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactTestUtils", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReasonReact", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecModules", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecordCompletion", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecoveryOnProp", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "References", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReferencesWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Rename", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RenameWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RescriptReactErrorBoundary", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RescriptReactRouter", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Set", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "SetLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Sort", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Stack", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "StdLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Stream", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "String", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "StringLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Sys", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TableclothMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_Jsx", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_LabelledArguments", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeDefinition", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Uchar", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Xform", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }] + +Complete src/TypeContextCompletion_Jsx.res 26:39 +posCursor:[26:39] posNoWhite:[26:37] Found expr:[26:12->26:38] +JSX 26:25] someVariant[26:26->26:37]=...__ghost__[0:-1->0:-1]> _children:None +Found typed context +Completable: CtypedContext(JsxProp()) +Found variant type someVariant +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\n", + "documentation": null + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\n", + "documentation": null + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\n", + "documentation": null + }, { + "label": "Six(_)", + "kind": 4, + "tags": [], + "detail": "Six(option, int)\n\n", + "documentation": null + }, { + "label": "someValue", + "kind": 12, + "tags": [], + "detail": "someVariant", + "documentation": null + }, { + "label": "Six", + "kind": 4, + "tags": [], + "detail": "Six(option, int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Five", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "SomeComponent", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null + }, { + "label": "Arg", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ArrayLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Auto", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Float", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSet", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Id", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Int", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_List", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Map", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapDict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableQueue", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSet", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableStack", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Option", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Range", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Result", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Set", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetDict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArray", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArrayInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArrayString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalAVLset", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalAVLtree", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalBuckets", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalBucketsType", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetBuckets", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internals", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Buffer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Bytes", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "BytesLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Callback", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CamlinternalLazy", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CamlinternalMod", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Char", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CompletePrioritize1", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CompletePrioritize2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Completion", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Complex", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Component", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CreateInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Cross", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dce", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Debug", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Definition", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "DefinitionWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Digest", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Div", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "DocumentSymbol", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom_storage", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom_storage2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Filename", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Fragment", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Genlex", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Hashtbl", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "HashtblLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Highlight", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Hover", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Int32", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Int64", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_OO", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_array2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_bigint", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_cast", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_console", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_date", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_dict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_exn", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_float", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_global", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_int", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_json", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_list", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_mapperRt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_math", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_null", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_null_undefined", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_obj", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_option", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_promise", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_re", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_result", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_string", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_string2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_typed_array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_typed_array2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_types", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_undefined", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_vector", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Jsx", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Lazy", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Lexing", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "List", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ListLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "LongIdentTest", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Map", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "MapLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "MoreLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_buffer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_child_process", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_fs", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_module", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_path", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_process", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Obj", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Object", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Parsing", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Patterns", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Pervasives", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Printexc", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Queue", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Random", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "React", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOM", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMRe", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMServer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMStyle", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactEvent", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactTestUtils", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReasonReact", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecModules", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecordCompletion", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecoveryOnProp", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "References", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReferencesWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Rename", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RenameWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RescriptReactErrorBoundary", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RescriptReactRouter", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Set", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "SetLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Sort", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Stack", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "StdLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Stream", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "String", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "StringLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Sys", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TableclothMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_Jsx", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_LabelledArguments", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeDefinition", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Uchar", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Xform", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }] + +Complete src/TypeContextCompletion_Jsx.res 29:39 +posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:12->29:39] +JSX 29:25] someVariant[29:26->29:37]=...[29:38->29:39]> _children:None +Found typed context +Completable: CtypedContext(JsxProp()) +Found variant type someVariant +[{ + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\n", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "TableclothMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_Jsx", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_LabelledArguments", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeDefinition", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }] + +Complete src/TypeContextCompletion_Jsx.res 32:39 +posCursor:[32:39] posNoWhite:[32:38] Found expr:[32:12->32:39] +JSX 32:25] someVariant[32:26->32:37]=...[32:38->32:39]> _children:None +posCursor:[32:39] posNoWhite:[32:38] Found expr:[32:38->32:39] +Pexp_ident t:[32:38->32:39] +Completable: Cpath Value[t] +[] + +Complete src/TypeContextCompletion_Jsx.res 35:39 +posCursor:[35:39] posNoWhite:[35:38] Found expr:[35:12->35:39] +JSX 35:25] anotherThing[35:26->35:38]=...__ghost__[0:-1->0:-1]> _children:None +Found typed context +Completable: CtypedContext(JsxProp()) +Found variant type TypeDefinition.variant +[{ + "label": "Foo", + "kind": 4, + "tags": [], + "detail": "Foo\n\n", + "documentation": null + }, { + "label": "Bar", + "kind": 4, + "tags": [], + "detail": "Bar\n\n", + "documentation": null + }, { + "label": "someValue", + "kind": 12, + "tags": [], + "detail": "someVariant", + "documentation": null + }, { + "label": "Six", + "kind": 4, + "tags": [], + "detail": "Six(option, int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Five", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "SomeComponent", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null + }, { + "label": "Arg", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ArrayLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Auto", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Float", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSet", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Id", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Int", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_List", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Map", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapDict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableQueue", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSet", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableStack", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Option", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Range", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Result", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Set", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetDict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArray", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArrayInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArrayString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalAVLset", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalAVLtree", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalBuckets", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalBucketsType", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetBuckets", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internals", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Buffer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Bytes", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "BytesLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Callback", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CamlinternalLazy", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CamlinternalMod", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Char", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CompletePrioritize1", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CompletePrioritize2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Completion", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Complex", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Component", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CreateInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Cross", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dce", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Debug", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Definition", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "DefinitionWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Digest", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Div", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "DocumentSymbol", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom_storage", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom_storage2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Filename", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Fragment", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Genlex", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Hashtbl", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "HashtblLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Highlight", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Hover", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Int32", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Int64", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_OO", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_array2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_bigint", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_cast", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_console", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_date", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_dict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_exn", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_float", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_global", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_int", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_json", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_list", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_mapperRt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_math", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_null", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_null_undefined", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_obj", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_option", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_promise", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_re", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_result", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_string", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_string2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_typed_array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_typed_array2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_types", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_undefined", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_vector", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Jsx", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Lazy", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Lexing", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "List", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ListLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "LongIdentTest", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Map", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "MapLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "MoreLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_buffer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_child_process", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_fs", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_module", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_path", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_process", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Obj", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Object", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Parsing", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Patterns", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Pervasives", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Printexc", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Queue", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Random", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "React", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOM", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMRe", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMServer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMStyle", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactEvent", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactTestUtils", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReasonReact", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecModules", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecordCompletion", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecoveryOnProp", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "References", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReferencesWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Rename", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RenameWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RescriptReactErrorBoundary", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RescriptReactRouter", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Set", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "SetLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Sort", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Stack", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "StdLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Stream", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "String", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "StringLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Sys", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TableclothMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_Jsx", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_LabelledArguments", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeDefinition", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Uchar", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Xform", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }] + +Complete src/TypeContextCompletion_Jsx.res 38:37 +posCursor:[38:37] posNoWhite:[38:36] Found expr:[38:12->38:37] +JSX 38:25] thirdThing[38:26->38:36]=...__ghost__[0:-1->0:-1]> _children:None +Found typed context +Completable: CtypedContext(JsxProp()) +Found polyvariant type otherVariant +[{ + "label": "#one", + "kind": 4, + "tags": [], + "detail": "#one", + "documentation": null + }, { + "label": "#six(_)", + "kind": 4, + "tags": [], + "detail": "#six(option, int)", + "documentation": null + }, { + "label": "#three", + "kind": 4, + "tags": [], + "detail": "#three", + "documentation": null + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two", + "documentation": null + }, { + "label": "#five(_)", + "kind": 4, + "tags": [], + "detail": "#five(int)", + "documentation": null + }, { + "label": "#four", + "kind": 4, + "tags": [], + "detail": "#four", + "documentation": null + }, { + "label": "someValue", + "kind": 12, + "tags": [], + "detail": "someVariant", + "documentation": null + }, { + "label": "Six", + "kind": 4, + "tags": [], + "detail": "Six(option, int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Five", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "SomeComponent", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null + }, { + "label": "Arg", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ArrayLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Auto", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Float", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSet", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Id", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Int", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_List", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Map", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapDict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableQueue", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSet", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableStack", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Option", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Range", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Result", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Set", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetDict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArray", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArrayInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArrayString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalAVLset", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalAVLtree", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalBuckets", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalBucketsType", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetBuckets", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internals", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Buffer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Bytes", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "BytesLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Callback", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CamlinternalLazy", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CamlinternalMod", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Char", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CompletePrioritize1", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CompletePrioritize2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Completion", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Complex", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Component", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CreateInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Cross", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dce", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Debug", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Definition", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "DefinitionWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Digest", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Div", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "DocumentSymbol", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom_storage", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom_storage2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Filename", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Fragment", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Genlex", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Hashtbl", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "HashtblLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Highlight", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Hover", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Int32", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Int64", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_OO", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_array2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_bigint", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_cast", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_console", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_date", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_dict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_exn", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_float", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_global", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_int", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_json", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_list", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_mapperRt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_math", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_null", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_null_undefined", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_obj", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_option", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_promise", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_re", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_result", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_string", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_string2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_typed_array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_typed_array2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_types", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_undefined", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_vector", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Jsx", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Lazy", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Lexing", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "List", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ListLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "LongIdentTest", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Map", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "MapLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "MoreLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_buffer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_child_process", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_fs", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_module", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_path", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_process", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Obj", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Object", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Parsing", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Patterns", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Pervasives", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Printexc", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Queue", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Random", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "React", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOM", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMRe", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMServer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMStyle", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactEvent", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactTestUtils", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReasonReact", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecModules", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecordCompletion", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecoveryOnProp", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "References", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReferencesWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Rename", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RenameWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RescriptReactErrorBoundary", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RescriptReactRouter", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Set", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "SetLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Sort", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Stack", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "StdLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Stream", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "String", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "StringLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Sys", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TableclothMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_Jsx", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_LabelledArguments", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeDefinition", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Uchar", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Xform", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }] + +Complete src/TypeContextCompletion_Jsx.res 41:38 +posCursor:[41:38] posNoWhite:[41:36] Found expr:[41:12->41:37] +JSX 41:25] thirdThing[41:26->41:36]=...__ghost__[0:-1->0:-1]> _children:None +Found typed context +Completable: CtypedContext(JsxProp()) +Found polyvariant type otherVariant +[{ + "label": "#one", + "kind": 4, + "tags": [], + "detail": "#one", + "documentation": null + }, { + "label": "#six(_)", + "kind": 4, + "tags": [], + "detail": "#six(option, int)", + "documentation": null + }, { + "label": "#three", + "kind": 4, + "tags": [], + "detail": "#three", + "documentation": null + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two", + "documentation": null + }, { + "label": "#five(_)", + "kind": 4, + "tags": [], + "detail": "#five(int)", + "documentation": null + }, { + "label": "#four", + "kind": 4, + "tags": [], + "detail": "#four", + "documentation": null + }, { + "label": "someValue", + "kind": 12, + "tags": [], + "detail": "someVariant", + "documentation": null + }, { + "label": "Six", + "kind": 4, + "tags": [], + "detail": "Six(option, int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Five", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "SomeComponent", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null + }, { + "label": "Arg", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ArrayLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Auto", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Float", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSet", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Id", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Int", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_List", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Map", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapDict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableQueue", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSet", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableStack", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Option", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Range", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Result", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Set", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetDict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArray", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArrayInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArrayString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalAVLset", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalAVLtree", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalBuckets", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalBucketsType", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetBuckets", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internals", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Buffer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Bytes", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "BytesLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Callback", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CamlinternalLazy", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CamlinternalMod", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Char", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CompletePrioritize1", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CompletePrioritize2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Completion", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Complex", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Component", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CreateInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Cross", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dce", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Debug", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Definition", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "DefinitionWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Digest", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Div", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "DocumentSymbol", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom_storage", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom_storage2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Filename", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Fragment", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Genlex", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Hashtbl", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "HashtblLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Highlight", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Hover", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Int32", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Int64", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_OO", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_array2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_bigint", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_cast", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_console", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_date", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_dict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_exn", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_float", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_global", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_int", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_json", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_list", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_mapperRt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_math", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_null", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_null_undefined", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_obj", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_option", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_promise", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_re", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_result", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_string", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_string2", + "kind": 9, + "tags": [], + "detail": "file module", "documentation": null }, { - "label": "Two", - "kind": 4, + "label": "Js_typed_array", + "kind": 9, "tags": [], - "detail": "Two\n\n", + "detail": "file module", "documentation": null }, { - "label": "Three", - "kind": 4, + "label": "Js_typed_array2", + "kind": 9, "tags": [], - "detail": "Three\n\n", + "detail": "file module", "documentation": null }, { - "label": "Four", - "kind": 4, + "label": "Js_types", + "kind": 9, "tags": [], - "detail": "Four\n\n", + "detail": "file module", "documentation": null }, { - "label": "Five(_)", - "kind": 4, + "label": "Js_undefined", + "kind": 9, "tags": [], - "detail": "Five(int)\n\n", + "detail": "file module", "documentation": null }, { - "label": "Six(_)", - "kind": 4, + "label": "Js_vector", + "kind": 9, "tags": [], - "detail": "Six(option, int)\n\n", + "detail": "file module", "documentation": null - }] - -Complete src/TypeContextCompletion_Jsx.res 29:39 -posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:12->29:39] -JSX 29:25] someVariant[29:26->29:37]=...[29:38->29:39]> _children:None -Found typed context -Completable: CtypedContext(JsxProp()) -Found variant type someVariant -[{ - "label": "Two", - "kind": 4, + }, { + "label": "Jsx", + "kind": 9, "tags": [], - "detail": "Two\n\n", + "detail": "file module", "documentation": null }, { - "label": "Three", - "kind": 4, + "label": "Lazy", + "kind": 9, "tags": [], - "detail": "Three\n\n", + "detail": "file module", "documentation": null - }] - -Complete src/TypeContextCompletion_Jsx.res 32:39 -posCursor:[32:39] posNoWhite:[32:38] Found expr:[32:12->32:39] -JSX 32:25] someVariant[32:26->32:37]=...[32:38->32:39]> _children:None -posCursor:[32:39] posNoWhite:[32:38] Found expr:[32:38->32:39] -Pexp_ident t:[32:38->32:39] -Completable: Cpath Value[t] -[] - -Complete src/TypeContextCompletion_Jsx.res 35:39 -posCursor:[35:39] posNoWhite:[35:38] Found expr:[35:12->35:39] -JSX 35:25] anotherThing[35:26->35:38]=...__ghost__[0:-1->0:-1]> _children:None -Found typed context -Completable: CtypedContext(JsxProp()) -Found variant type TypeDefinition.variant -[{ - "label": "Foo", - "kind": 4, + }, { + "label": "Lexing", + "kind": 9, "tags": [], - "detail": "Foo\n\n", + "detail": "file module", "documentation": null }, { - "label": "Bar", - "kind": 4, + "label": "List", + "kind": 9, "tags": [], - "detail": "Bar\n\n", + "detail": "file module", "documentation": null - }] - -Complete src/TypeContextCompletion_Jsx.res 38:37 -posCursor:[38:37] posNoWhite:[38:36] Found expr:[38:12->38:37] -JSX 38:25] thirdThing[38:26->38:36]=...__ghost__[0:-1->0:-1]> _children:None -Found typed context -Completable: CtypedContext(JsxProp()) -Found polyvariant type otherVariant -[{ - "label": "#one", - "kind": 4, + }, { + "label": "ListLabels", + "kind": 9, "tags": [], - "detail": "#one", + "detail": "file module", "documentation": null }, { - "label": "#six(_)", - "kind": 4, + "label": "LongIdentTest", + "kind": 9, "tags": [], - "detail": "#six(option, int)", + "detail": "file module", "documentation": null }, { - "label": "#three", - "kind": 4, + "label": "Map", + "kind": 9, "tags": [], - "detail": "#three", + "detail": "file module", "documentation": null }, { - "label": "#two", - "kind": 4, + "label": "MapLabels", + "kind": 9, "tags": [], - "detail": "#two", + "detail": "file module", "documentation": null }, { - "label": "#five(_)", - "kind": 4, + "label": "MoreLabels", + "kind": 9, "tags": [], - "detail": "#five(int)", + "detail": "file module", "documentation": null }, { - "label": "#four", - "kind": 4, + "label": "Node", + "kind": 9, "tags": [], - "detail": "#four", + "detail": "file module", "documentation": null - }] - -Complete src/TypeContextCompletion_Jsx.res 41:38 -posCursor:[41:38] posNoWhite:[41:36] Found expr:[41:12->41:37] -JSX 41:25] thirdThing[41:26->41:36]=...__ghost__[0:-1->0:-1]> _children:None -Found typed context -Completable: CtypedContext(JsxProp()) -Found polyvariant type otherVariant -[{ - "label": "#one", - "kind": 4, + }, { + "label": "Node_buffer", + "kind": 9, "tags": [], - "detail": "#one", + "detail": "file module", "documentation": null }, { - "label": "#six(_)", - "kind": 4, + "label": "Node_child_process", + "kind": 9, "tags": [], - "detail": "#six(option, int)", + "detail": "file module", "documentation": null }, { - "label": "#three", - "kind": 4, + "label": "Node_fs", + "kind": 9, "tags": [], - "detail": "#three", + "detail": "file module", "documentation": null }, { - "label": "#two", - "kind": 4, + "label": "Node_module", + "kind": 9, "tags": [], - "detail": "#two", + "detail": "file module", "documentation": null }, { - "label": "#five(_)", - "kind": 4, + "label": "Node_path", + "kind": 9, "tags": [], - "detail": "#five(int)", + "detail": "file module", "documentation": null }, { - "label": "#four", - "kind": 4, + "label": "Node_process", + "kind": 9, "tags": [], - "detail": "#four", + "detail": "file module", + "documentation": null + }, { + "label": "Obj", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Object", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Parsing", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Patterns", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Pervasives", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Printexc", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Queue", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Random", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "React", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOM", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMRe", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMServer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMStyle", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactEvent", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactTestUtils", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReasonReact", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecModules", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecordCompletion", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecoveryOnProp", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "References", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReferencesWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Rename", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RenameWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RescriptReactErrorBoundary", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RescriptReactRouter", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Set", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "SetLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Sort", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Stack", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "StdLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Stream", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "String", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "StringLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Sys", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TableclothMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_Jsx", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_LabelledArguments", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeDefinition", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Uchar", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Xform", + "kind": 9, + "tags": [], + "detail": "file module", "documentation": null }] @@ -260,5 +5576,41 @@ JSX 47:25] thirdThing[47:26->47:36]=...[47:37->47:39]> _c Found typed context Completable: CtypedContext(JsxProp()) Found polyvariant type otherVariant -[] +[{ + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "documentation": null + }, { + "label": "TableclothMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_Jsx", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_LabelledArguments", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeDefinition", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }] From 27532b0f99d2b36dbca5c982e8f60aa19de0641a Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 19 Jul 2022 21:10:47 +0200 Subject: [PATCH 21/80] bring contextual completions to labelled arguments as well --- analysis/src/CompletionBackEnd.ml | 12 +++- ...ontextCompletion_LabelledArguments.res.txt | 66 ++++++++++++++++++- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 80a49383b..87d80e6c9 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1808,7 +1808,17 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i match targetLabel with | None -> [] | Some (_, typeExpr) -> - completeTypeExpr ~env ~package ~debug ~prefix typeExpr) + (* TODO: Wonder if we can filter the values returned here on type... + Maybe that'd be confusing for the user though, if items in scope don't appear. + We should at a minimum be able to sort values according to type and the proximity + of them in the scope. *) + let completionsFromContext = + contextPath + |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles + ~pos ~env ~exact:forHover ~scope + in + completeTypeExpr ~env ~package ~debug ~prefix typeExpr + @ completionsFromContext) | JsxProp {componentPath; propName; prefix} -> ( (* TODO: Variant constructors seem to re-appear here. Wondering if we can get rid of "randomly" completing constructors in scope. Or at least de-duping somehow. *) diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index 7118e0755..8b7c98589 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -57,6 +57,12 @@ Found variant type someVariant "tags": [], "detail": "Six(option, int)\n\n", "documentation": null + }, { + "label": "someVariantToString", + "kind": 12, + "tags": [], + "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", + "documentation": null }] Complete src/TypeContextCompletion_LabelledArguments.res 28:45 @@ -101,6 +107,12 @@ Found variant type someVariant "tags": [], "detail": "Six(option, int)\n\n", "documentation": null + }, { + "label": "someVariantToString", + "kind": 12, + "tags": [], + "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", + "documentation": null }] Complete src/TypeContextCompletion_LabelledArguments.res 31:45 @@ -121,6 +133,12 @@ Found variant type someVariant "tags": [], "detail": "Three\n\n", "documentation": null + }, { + "label": "someVariantToString", + "kind": 12, + "tags": [], + "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", + "documentation": null }] Complete src/TypeContextCompletion_LabelledArguments.res 34:45 @@ -129,7 +147,13 @@ Pexp_apply ...[34:11->34:30] (~someVariant34:32->34:43=...[34:44->34:45]) found typed context Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])=t) Found variant type someVariant -[] +[{ + "label": "someVariantToString", + "kind": 12, + "tags": [], + "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", + "documentation": null + }] Complete src/TypeContextCompletion_LabelledArguments.res 37:59 posCursor:[37:59] posNoWhite:[37:58] Found expr:[37:11->37:59] @@ -137,7 +161,13 @@ Pexp_apply ...[37:11->37:30] (~someVariant37:32->37:43=...[37:44->37:59]) found typed context Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])=_) Found variant type someVariant -[] +[{ + "label": "someVariantToString", + "kind": 12, + "tags": [], + "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", + "documentation": null + }] Complete src/TypeContextCompletion_LabelledArguments.res 40:45 posCursor:[40:45] posNoWhite:[40:44] Found expr:[40:11->40:45] @@ -157,6 +187,12 @@ Found variant type TypeDefinition.variant "tags": [], "detail": "Bar\n\n", "documentation": null + }, { + "label": "someVariantToString", + "kind": 12, + "tags": [], + "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", + "documentation": null }] Complete src/TypeContextCompletion_LabelledArguments.res 43:43 @@ -201,6 +237,12 @@ Found polyvariant type otherVariant "tags": [], "detail": "#four", "documentation": null + }, { + "label": "someVariantToString", + "kind": 12, + "tags": [], + "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", + "documentation": null }] Complete src/TypeContextCompletion_LabelledArguments.res 46:44 @@ -245,6 +287,12 @@ Found polyvariant type otherVariant "tags": [], "detail": "#four", "documentation": null + }, { + "label": "someVariantToString", + "kind": 12, + "tags": [], + "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", + "documentation": null }] Complete src/TypeContextCompletion_LabelledArguments.res 49:45 @@ -265,6 +313,12 @@ Found polyvariant type otherVariant "tags": [], "detail": "#two", "documentation": null + }, { + "label": "someVariantToString", + "kind": 12, + "tags": [], + "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", + "documentation": null }] Complete src/TypeContextCompletion_LabelledArguments.res 52:45 @@ -273,5 +327,11 @@ Pexp_apply ...[52:11->52:30] (~thirdThing52:32->52:42=...[52:43->52:45]) found typed context Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString])=T) Found polyvariant type otherVariant -[] +[{ + "label": "someVariantToString", + "kind": 12, + "tags": [], + "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", + "documentation": null + }] From e87ad5aa5d93bbf8dcf265e312466904d57255b0 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 19 Jul 2022 21:13:09 +0200 Subject: [PATCH 22/80] remove redundant comment# --- analysis/src/CompletionBackEnd.ml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 87d80e6c9..7b37fff37 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1425,8 +1425,6 @@ let completeTypeExpr ~env ~package ~debug ~prefix (typeExpr : Types.type_expr) = | Variant constructors -> if debug then Printf.printf "Found variant type %s\n" (typeExpr |> Shared.typeToString); - (* TODO: Investigate completing seen identifiers _with the correct type_ here too. If completing - variant someVariant, and there's a someVariable of type someVariant, add that to the completion list. *) constructors |> List.filter (fun constructor -> Utils.startsWith constructor.Constructor.cname.txt prefix) @@ -1444,8 +1442,6 @@ let completeTypeExpr ~env ~package ~debug ~prefix (typeExpr : Types.type_expr) = if debug then Printf.printf "Found polyvariant type %s\n" (typeExpr |> Shared.typeToString); - (* TODO: Investigate completing seen identifiers _with the correct type_ here too. Unsure if that's possible though - for polyvariants, if things aren't referred to by typename, but rather the full inlined type definition.. *) constructors |> List.filter (fun constructor -> Utils.startsWith constructor.name prefix) |> List.map (fun constructor -> From b260d383943bf9071a3cde284c65d8d9ac91dce0 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Wed, 27 Jul 2022 12:52:44 +0200 Subject: [PATCH 23/80] take a step back and remove typed completions for now. focus on identifying the correct typed contexts first --- .vscode/settings.json | 4 + analysis/src/CompletionFrontEnd.ml | 72 +- .../tests/src/expected/Completion.res.txt | 2 + analysis/tests/src/expected/Jsx.res.txt | 3 + .../tests/src/expected/RecoveryOnProp.res.txt | 1 + .../TypeContextCompletion_Jsx.res.txt | 5676 +---------------- ...ontextCompletion_LabelledArguments.res.txt | 313 +- 7 files changed, 177 insertions(+), 5894 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index a0dfd585e..a7024256f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,5 +5,9 @@ "typescript.preferences.quoteStyle": "single", "editor.codeActionsOnSave": { "source.fixAll.eslint": true + }, + "ocaml.sandbox": { + "kind": "opam", + "switch": "4.12.1" } } \ No newline at end of file diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 873a46b1a..367b60f60 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -102,37 +102,37 @@ let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName && posBeforeCursor < Loc.start prop.exp.pexp_loc then (* Cursor between the prop name and expr assigned *) None - else if prop.exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then + else if prop.exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then ( (* Cursor on expr assigned *) - if isElgibleForTypedContextCompletion prop.exp then ( - if debug then Printf.printf "Found typed context\n"; - let typedContext = - Completable.JsxProp - { - componentPath = - Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; - propName = prop.name; - prefix = getIdentFromExpr prop.exp |> Utils.flattenLongIdent; - } - in - Some (CtypedContext typedContext)) - else None - else if prop.exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then + if debug then + Printf.printf "found typed context: jsxProp %s\n" prop.name; + let _typedContext = + Completable.JsxProp + { + componentPath = + Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; + propName = prop.name; + prefix = getIdentFromExpr prop.exp |> Utils.flattenLongIdent; + } + in + (* Some (CtypedContext typedContext)) *) + None) + else if prop.exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then ( (* Expr assigned presumably is "rescript.exprhole" after parser recovery. Complete for the value. *) - if isElgibleForTypedContextCompletion prop.exp then ( - if debug then Printf.printf "Found typed context\n"; - let typedContext = - Completable.JsxProp - { - componentPath = - Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; - propName = prop.name; - prefix = getIdentFromExpr prop.exp |> Utils.flattenLongIdent; - } - in - Some (CtypedContext typedContext)) - else None + if debug then + Printf.printf "found typed context: jsxProp %s\n" prop.name; + let _typedContext = + Completable.JsxProp + { + componentPath = + Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; + propName = prop.name; + prefix = getIdentFromExpr prop.exp |> Utils.flattenLongIdent; + } + in + (* Some (CtypedContext typedContext)) *) + None) else loop rest | [] -> let beforeChildrenStart = @@ -219,27 +219,31 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor && posBeforeCursor < labelled.posEnd then Some (Completable.CnamedArg (contextPath, labelled.name, allNames)) else if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then ( - if debug then Printf.printf "found typed context \n"; - Some + if debug then + Printf.printf "found typed context: named arg %s \n" labelled.name; + (*Some (Completable.CtypedContext (NamedArg { contextPath; label = labelled.name; prefix = getPrefixFromExpr exp; - }))) + }))) *) + None) else if exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then ( (* Expr assigned presumably is "rescript.exprhole" after parser recovery. Assume this is an empty expression. *) - if debug then Printf.printf "found typed context \n"; - Some + if debug then + Printf.printf "found typed context: named arg %s \n" labelled.name; + (*Some (Completable.CtypedContext (NamedArg { contextPath; label = labelled.name; prefix = getPrefixFromExpr exp; - }))) + })))*) + None) else loop rest | {label = None; exp} :: rest -> if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then None diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index 8ab9911d1..0dfa7d659 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -463,6 +463,7 @@ Completable: Cpath Value[Js, Dict, u] Complete src/Completion.res 59:30 posCursor:[59:30] posNoWhite:[59:29] Found expr:[59:15->59:30] JSX 59:21] second[59:22->59:28]=...[59:29->59:30]> _children:None +found typed context: jsxProp second posCursor:[59:30] posNoWhite:[59:29] Found expr:[59:29->59:30] Pexp_ident z:[59:29->59:30] Completable: Cpath Value[z] @@ -1305,6 +1306,7 @@ Found type for function (~a: int) => int Complete src/Completion.res 336:26 posCursor:[336:26] posNoWhite:[336:25] Found expr:[333:3->346:23] JSX 333:6] onClick[334:4->334:11]=...[334:13->346:23]> _children:None +found typed context: jsxProp onClick posCursor:[336:26] posNoWhite:[336:25] Found expr:[334:13->346:23] posCursor:[336:26] posNoWhite:[336:25] Found expr:[334:13->338:6] posCursor:[336:26] posNoWhite:[336:25] Found expr:[335:6->338:5] diff --git a/analysis/tests/src/expected/Jsx.res.txt b/analysis/tests/src/expected/Jsx.res.txt index 6bec2fedd..b7091ea73 100644 --- a/analysis/tests/src/expected/Jsx.res.txt +++ b/analysis/tests/src/expected/Jsx.res.txt @@ -6,6 +6,7 @@ the type is not great but jump to definition works Complete src/Jsx.res 8:15 posCursor:[8:15] posNoWhite:[8:14] Found expr:[8:4->8:15] JSX 8:5] second[8:6->8:12]=...[8:13->8:15]> _children:None +found typed context: jsxProp second posCursor:[8:15] posNoWhite:[8:14] Found expr:[8:13->8:15] Pexp_ident fi:[8:13->8:15] Completable: Cpath Value[fi] @@ -354,6 +355,7 @@ Completable: Cpath Module[DefineSomeFields].th Complete src/Jsx.res 122:20 posCursor:[122:20] posNoWhite:[122:19] Found expr:[121:3->125:4] JSX 121:6] x[122:5->122:6]=...[122:7->122:20] name[124:4->124:8]=...[124:9->124:11]> _children:125:2 +found typed context: jsxProp x posCursor:[122:20] posNoWhite:[122:19] Found expr:[122:7->122:20] Pexp_ident Outer.Inner.h:[122:7->122:20] Completable: Cpath Value[Outer, Inner, h] @@ -368,6 +370,7 @@ Completable: Cpath Value[Outer, Inner, h] Complete src/Jsx.res 129:19 posCursor:[129:19] posNoWhite:[129:18] Found expr:[128:3->131:9] JSX 128:6] x[129:5->129:6]=...[129:7->131:8]> _children:None +found typed context: jsxProp x posCursor:[129:19] posNoWhite:[129:18] Found expr:[129:7->131:8] Pexp_ident Outer.Inner.:[129:7->131:8] Completable: Cpath Value[Outer, Inner, ""] diff --git a/analysis/tests/src/expected/RecoveryOnProp.res.txt b/analysis/tests/src/expected/RecoveryOnProp.res.txt index fe509d768..eb1d6d422 100644 --- a/analysis/tests/src/expected/RecoveryOnProp.res.txt +++ b/analysis/tests/src/expected/RecoveryOnProp.res.txt @@ -1,6 +1,7 @@ Complete src/RecoveryOnProp.res 6:26 posCursor:[6:26] posNoWhite:[6:25] Found expr:[3:3->11:8] JSX 3:6] onClick[4:4->4:11]=...[4:13->0:-1]> _children:None +found typed context: jsxProp onClick posCursor:[6:26] posNoWhite:[6:25] Found expr:[4:13->8:6] posCursor:[6:26] posNoWhite:[6:25] Found expr:[5:6->8:5] posCursor:[6:26] posNoWhite:[6:25] Found expr:[6:16->8:5] diff --git a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt index dccf0634e..49f6224bf 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt @@ -13,5629 +13,22 @@ Completable: Cjsx([SomeComponent], someVaria, [someVaria]) Complete src/TypeContextCompletion_Jsx.res 23:38 posCursor:[23:38] posNoWhite:[23:37] Found expr:[23:12->23:38] JSX 23:25] someVariant[23:26->23:37]=...__ghost__[0:-1->0:-1]> _children:None -Found typed context -Completable: CtypedContext(JsxProp()) -Found variant type someVariant -[{ - "label": "One", - "kind": 4, - "tags": [], - "detail": "One\n\n", - "documentation": null - }, { - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\n", - "documentation": null - }, { - "label": "Three", - "kind": 4, - "tags": [], - "detail": "Three\n\n", - "documentation": null - }, { - "label": "Four", - "kind": 4, - "tags": [], - "detail": "Four\n\n", - "documentation": null - }, { - "label": "Five(_)", - "kind": 4, - "tags": [], - "detail": "Five(int)\n\n", - "documentation": null - }, { - "label": "Six(_)", - "kind": 4, - "tags": [], - "detail": "Six(option, int)\n\n", - "documentation": null - }, { - "label": "someValue", - "kind": 12, - "tags": [], - "detail": "someVariant", - "documentation": null - }, { - "label": "Six", - "kind": 4, - "tags": [], - "detail": "Six(option, int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Five", - "kind": 4, - "tags": [], - "detail": "Five(int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Four", - "kind": 4, - "tags": [], - "detail": "Four\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Three", - "kind": 4, - "tags": [], - "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "One", - "kind": 4, - "tags": [], - "detail": "One\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "SomeComponent", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null - }, { - "label": "Arg", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ArrayLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Auto", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Float", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSet", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Id", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Int", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_List", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Map", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapDict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableQueue", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSet", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableStack", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Option", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Range", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Result", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Set", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetDict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArray", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArrayInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArrayString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalAVLset", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalAVLtree", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalBuckets", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalBucketsType", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetBuckets", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internals", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Buffer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Bytes", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "BytesLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Callback", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CamlinternalLazy", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CamlinternalMod", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Char", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CodeLens", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CompletePrioritize1", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CompletePrioritize2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Completion", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Complex", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Component", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CreateInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Cross", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dce", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Debug", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Definition", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "DefinitionWithInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Digest", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Div", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "DocumentSymbol", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dom", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dom_storage", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dom_storage2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Filename", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Fragment", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Genlex", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Hashtbl", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "HashtblLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Highlight", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Hover", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "InlayHint", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Int32", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Int64", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_OO", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_array2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_bigint", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_cast", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_console", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_date", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_dict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_exn", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_float", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_global", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_int", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_json", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_list", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_mapperRt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_math", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_null", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_null_undefined", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_obj", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_option", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_promise", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_re", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_result", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_string", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_string2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_typed_array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_typed_array2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_types", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_undefined", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_vector", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Jsx", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Lazy", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Lexing", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "List", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ListLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "LongIdentTest", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Map", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "MapLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "MoreLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_buffer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_child_process", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_fs", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_module", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_path", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_process", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Obj", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Object", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Parsing", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Patterns", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Pervasives", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Printexc", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Queue", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Random", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "React", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOM", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMRe", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMServer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMStyle", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactEvent", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactTestUtils", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReasonReact", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecModules", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecordCompletion", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecoveryOnProp", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "References", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReferencesWithInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Rename", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RenameWithInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RescriptReactErrorBoundary", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RescriptReactRouter", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Set", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "SetLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Sort", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Stack", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "StdLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Stream", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "String", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "StringLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Sys", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TableclothMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_Jsx", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_LabelledArguments", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeDefinition", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Uchar", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Xform", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }] - -Complete src/TypeContextCompletion_Jsx.res 26:39 -posCursor:[26:39] posNoWhite:[26:37] Found expr:[26:12->26:38] -JSX 26:25] someVariant[26:26->26:37]=...__ghost__[0:-1->0:-1]> _children:None -Found typed context -Completable: CtypedContext(JsxProp()) -Found variant type someVariant -[{ - "label": "One", - "kind": 4, - "tags": [], - "detail": "One\n\n", - "documentation": null - }, { - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\n", - "documentation": null - }, { - "label": "Three", - "kind": 4, - "tags": [], - "detail": "Three\n\n", - "documentation": null - }, { - "label": "Four", - "kind": 4, - "tags": [], - "detail": "Four\n\n", - "documentation": null - }, { - "label": "Five(_)", - "kind": 4, - "tags": [], - "detail": "Five(int)\n\n", - "documentation": null - }, { - "label": "Six(_)", - "kind": 4, - "tags": [], - "detail": "Six(option, int)\n\n", - "documentation": null - }, { - "label": "someValue", - "kind": 12, - "tags": [], - "detail": "someVariant", - "documentation": null - }, { - "label": "Six", - "kind": 4, - "tags": [], - "detail": "Six(option, int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Five", - "kind": 4, - "tags": [], - "detail": "Five(int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Four", - "kind": 4, - "tags": [], - "detail": "Four\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Three", - "kind": 4, - "tags": [], - "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "One", - "kind": 4, - "tags": [], - "detail": "One\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "SomeComponent", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null - }, { - "label": "Arg", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ArrayLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Auto", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Float", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSet", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Id", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Int", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_List", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Map", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapDict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableQueue", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSet", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableStack", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Option", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Range", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Result", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Set", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetDict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArray", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArrayInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArrayString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalAVLset", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalAVLtree", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalBuckets", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalBucketsType", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetBuckets", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internals", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Buffer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Bytes", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "BytesLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Callback", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CamlinternalLazy", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CamlinternalMod", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Char", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CodeLens", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CompletePrioritize1", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CompletePrioritize2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Completion", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Complex", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Component", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CreateInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Cross", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dce", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Debug", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Definition", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "DefinitionWithInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Digest", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Div", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "DocumentSymbol", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dom", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dom_storage", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dom_storage2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Filename", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Fragment", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Genlex", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Hashtbl", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "HashtblLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Highlight", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Hover", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "InlayHint", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Int32", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Int64", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_OO", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_array2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_bigint", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_cast", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_console", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_date", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_dict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_exn", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_float", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_global", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_int", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_json", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_list", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_mapperRt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_math", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_null", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_null_undefined", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_obj", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_option", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_promise", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_re", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_result", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_string", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_string2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_typed_array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_typed_array2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_types", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_undefined", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_vector", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Jsx", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Lazy", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Lexing", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "List", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ListLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "LongIdentTest", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Map", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "MapLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "MoreLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_buffer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_child_process", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_fs", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_module", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_path", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_process", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Obj", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Object", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Parsing", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Patterns", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Pervasives", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Printexc", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Queue", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Random", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "React", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOM", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMRe", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMServer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMStyle", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactEvent", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactTestUtils", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReasonReact", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecModules", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecordCompletion", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecoveryOnProp", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "References", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReferencesWithInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Rename", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RenameWithInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RescriptReactErrorBoundary", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RescriptReactRouter", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Set", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "SetLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Sort", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Stack", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "StdLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Stream", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "String", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "StringLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Sys", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TableclothMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_Jsx", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_LabelledArguments", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeDefinition", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Uchar", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Xform", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }] - -Complete src/TypeContextCompletion_Jsx.res 29:39 -posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:12->29:39] -JSX 29:25] someVariant[29:26->29:37]=...[29:38->29:39]> _children:None -Found typed context -Completable: CtypedContext(JsxProp()) -Found variant type someVariant -[{ - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\n", - "documentation": null - }, { - "label": "Three", - "kind": 4, - "tags": [], - "detail": "Three\n\n", - "documentation": null - }, { - "label": "Three", - "kind": 4, - "tags": [], - "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "TableclothMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_Jsx", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_LabelledArguments", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeDefinition", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }] - -Complete src/TypeContextCompletion_Jsx.res 32:39 -posCursor:[32:39] posNoWhite:[32:38] Found expr:[32:12->32:39] -JSX 32:25] someVariant[32:26->32:37]=...[32:38->32:39]> _children:None -posCursor:[32:39] posNoWhite:[32:38] Found expr:[32:38->32:39] -Pexp_ident t:[32:38->32:39] -Completable: Cpath Value[t] -[] - -Complete src/TypeContextCompletion_Jsx.res 35:39 -posCursor:[35:39] posNoWhite:[35:38] Found expr:[35:12->35:39] -JSX 35:25] anotherThing[35:26->35:38]=...__ghost__[0:-1->0:-1]> _children:None -Found typed context -Completable: CtypedContext(JsxProp()) -Found variant type TypeDefinition.variant -[{ - "label": "Foo", - "kind": 4, - "tags": [], - "detail": "Foo\n\n", - "documentation": null - }, { - "label": "Bar", - "kind": 4, - "tags": [], - "detail": "Bar\n\n", - "documentation": null - }, { - "label": "someValue", - "kind": 12, - "tags": [], - "detail": "someVariant", - "documentation": null - }, { - "label": "Six", - "kind": 4, - "tags": [], - "detail": "Six(option, int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Five", - "kind": 4, - "tags": [], - "detail": "Five(int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Four", - "kind": 4, - "tags": [], - "detail": "Four\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Three", - "kind": 4, - "tags": [], - "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "One", - "kind": 4, - "tags": [], - "detail": "One\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "SomeComponent", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null - }, { - "label": "Arg", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ArrayLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Auto", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Float", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSet", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Id", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Int", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_List", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Map", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapDict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableQueue", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSet", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableStack", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Option", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Range", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Result", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Set", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetDict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArray", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArrayInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArrayString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalAVLset", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalAVLtree", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalBuckets", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalBucketsType", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetBuckets", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internals", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Buffer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Bytes", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "BytesLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Callback", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CamlinternalLazy", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CamlinternalMod", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Char", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CodeLens", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CompletePrioritize1", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CompletePrioritize2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Completion", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Complex", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Component", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CreateInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Cross", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dce", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Debug", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Definition", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "DefinitionWithInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Digest", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Div", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "DocumentSymbol", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dom", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dom_storage", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dom_storage2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Filename", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Fragment", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Genlex", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Hashtbl", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "HashtblLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Highlight", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Hover", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "InlayHint", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Int32", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Int64", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_OO", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_array2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_bigint", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_cast", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_console", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_date", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_dict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_exn", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_float", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_global", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_int", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_json", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_list", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_mapperRt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_math", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_null", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_null_undefined", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_obj", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_option", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_promise", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_re", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_result", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_string", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_string2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_typed_array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_typed_array2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_types", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_undefined", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_vector", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Jsx", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Lazy", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Lexing", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "List", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ListLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "LongIdentTest", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Map", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "MapLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "MoreLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_buffer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_child_process", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_fs", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_module", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_path", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_process", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Obj", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Object", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Parsing", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Patterns", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Pervasives", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Printexc", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Queue", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Random", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "React", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOM", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMRe", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMServer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMStyle", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactEvent", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactTestUtils", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReasonReact", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecModules", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecordCompletion", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecoveryOnProp", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "References", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReferencesWithInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Rename", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RenameWithInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RescriptReactErrorBoundary", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RescriptReactRouter", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Set", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "SetLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Sort", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Stack", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "StdLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Stream", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "String", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "StringLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Sys", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TableclothMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_Jsx", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_LabelledArguments", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeDefinition", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Uchar", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Xform", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }] - -Complete src/TypeContextCompletion_Jsx.res 38:37 -posCursor:[38:37] posNoWhite:[38:36] Found expr:[38:12->38:37] -JSX 38:25] thirdThing[38:26->38:36]=...__ghost__[0:-1->0:-1]> _children:None -Found typed context -Completable: CtypedContext(JsxProp()) -Found polyvariant type otherVariant -[{ - "label": "#one", - "kind": 4, - "tags": [], - "detail": "#one", - "documentation": null - }, { - "label": "#six(_)", - "kind": 4, - "tags": [], - "detail": "#six(option, int)", - "documentation": null - }, { - "label": "#three", - "kind": 4, - "tags": [], - "detail": "#three", - "documentation": null - }, { - "label": "#two", - "kind": 4, - "tags": [], - "detail": "#two", - "documentation": null - }, { - "label": "#five(_)", - "kind": 4, - "tags": [], - "detail": "#five(int)", - "documentation": null - }, { - "label": "#four", - "kind": 4, - "tags": [], - "detail": "#four", - "documentation": null - }, { - "label": "someValue", - "kind": 12, - "tags": [], - "detail": "someVariant", - "documentation": null - }, { - "label": "Six", - "kind": 4, - "tags": [], - "detail": "Six(option, int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Five", - "kind": 4, - "tags": [], - "detail": "Five(int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Four", - "kind": 4, - "tags": [], - "detail": "Four\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Three", - "kind": 4, - "tags": [], - "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "One", - "kind": 4, - "tags": [], - "detail": "One\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "SomeComponent", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null - }, { - "label": "Arg", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ArrayLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Auto", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Float", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSet", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Id", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Int", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_List", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Map", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapDict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableQueue", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSet", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableStack", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Option", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Range", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Result", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Set", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetDict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArray", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArrayInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArrayString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalAVLset", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalAVLtree", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalBuckets", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalBucketsType", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetBuckets", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internals", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Buffer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Bytes", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "BytesLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Callback", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CamlinternalLazy", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CamlinternalMod", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Char", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CodeLens", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CompletePrioritize1", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CompletePrioritize2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Completion", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Complex", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Component", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CreateInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Cross", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dce", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Debug", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Definition", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "DefinitionWithInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Digest", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Div", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "DocumentSymbol", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dom", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dom_storage", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dom_storage2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Filename", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Fragment", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Genlex", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Hashtbl", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "HashtblLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Highlight", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Hover", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "InlayHint", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Int32", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Int64", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_OO", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_array2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_bigint", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_cast", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_console", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_date", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_dict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_exn", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_float", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_global", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_int", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_json", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_list", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_mapperRt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_math", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_null", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_null_undefined", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_obj", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_option", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_promise", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_re", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_result", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_string", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_string2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_typed_array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_typed_array2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_types", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_undefined", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_vector", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Jsx", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Lazy", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Lexing", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "List", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ListLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "LongIdentTest", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Map", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "MapLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "MoreLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_buffer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_child_process", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_fs", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_module", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_path", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_process", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Obj", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Object", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Parsing", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Patterns", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Pervasives", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Printexc", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Queue", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Random", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "React", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOM", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMRe", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMServer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMStyle", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactEvent", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactTestUtils", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReasonReact", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecModules", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecordCompletion", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecoveryOnProp", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "References", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReferencesWithInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Rename", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RenameWithInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RescriptReactErrorBoundary", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RescriptReactRouter", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Set", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "SetLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Sort", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Stack", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "StdLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Stream", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "String", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "StringLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Sys", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TableclothMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_Jsx", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_LabelledArguments", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeDefinition", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Uchar", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Xform", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }] - -Complete src/TypeContextCompletion_Jsx.res 41:38 -posCursor:[41:38] posNoWhite:[41:36] Found expr:[41:12->41:37] -JSX 41:25] thirdThing[41:26->41:36]=...__ghost__[0:-1->0:-1]> _children:None -Found typed context -Completable: CtypedContext(JsxProp()) -Found polyvariant type otherVariant -[{ - "label": "#one", - "kind": 4, - "tags": [], - "detail": "#one", - "documentation": null - }, { - "label": "#six(_)", - "kind": 4, - "tags": [], - "detail": "#six(option, int)", - "documentation": null - }, { - "label": "#three", - "kind": 4, - "tags": [], - "detail": "#three", - "documentation": null - }, { - "label": "#two", - "kind": 4, - "tags": [], - "detail": "#two", - "documentation": null - }, { - "label": "#five(_)", - "kind": 4, - "tags": [], - "detail": "#five(int)", - "documentation": null - }, { - "label": "#four", - "kind": 4, - "tags": [], - "detail": "#four", - "documentation": null - }, { - "label": "someValue", - "kind": 12, - "tags": [], - "detail": "someVariant", - "documentation": null - }, { - "label": "Six", - "kind": 4, - "tags": [], - "detail": "Six(option, int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Five", - "kind": 4, - "tags": [], - "detail": "Five(int)\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Four", - "kind": 4, - "tags": [], - "detail": "Four\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Three", - "kind": 4, - "tags": [], - "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "One", - "kind": 4, - "tags": [], - "detail": "One\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", - "documentation": null - }, { - "label": "SomeComponent", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null - }, { - "label": "Arg", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ArrayLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Auto", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Float", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSet", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Id", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Int", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_List", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Map", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapDict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableQueue", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSet", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableStack", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Option", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Range", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Result", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Set", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetDict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArray", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArrayInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArrayString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalAVLset", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalAVLtree", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalBuckets", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalBucketsType", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetBuckets", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internals", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Buffer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Bytes", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "BytesLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Callback", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CamlinternalLazy", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CamlinternalMod", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Char", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CodeLens", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CompletePrioritize1", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CompletePrioritize2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Completion", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Complex", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Component", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CreateInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Cross", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dce", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Debug", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Definition", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "DefinitionWithInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Digest", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Div", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "DocumentSymbol", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dom", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dom_storage", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Dom_storage2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Filename", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Fragment", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Genlex", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Hashtbl", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "HashtblLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Highlight", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Hover", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "InlayHint", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Int32", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Int64", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_OO", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_array2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_bigint", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_cast", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_console", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_date", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_dict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_exn", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_float", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_global", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_int", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_json", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_list", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_mapperRt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_math", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_null", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_null_undefined", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_obj", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_option", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_promise", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_re", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_result", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_string", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_string2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_typed_array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_typed_array2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_types", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_undefined", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_vector", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Jsx", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Lazy", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Lexing", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "List", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ListLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "LongIdentTest", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Map", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "MapLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "MoreLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_buffer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_child_process", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_fs", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_module", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_path", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_process", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Obj", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Object", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Parsing", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Patterns", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Pervasives", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Printexc", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Queue", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Random", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "React", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOM", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMRe", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMServer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMStyle", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactEvent", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactTestUtils", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReasonReact", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecModules", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecordCompletion", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecoveryOnProp", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "References", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReferencesWithInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Rename", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RenameWithInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RescriptReactErrorBoundary", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RescriptReactRouter", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Set", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "SetLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Sort", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Stack", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "StdLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Stream", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "String", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "StringLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Sys", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TableclothMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_Jsx", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_LabelledArguments", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeDefinition", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Uchar", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Xform", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }] +found typed context: jsxProp someVariant +[] -Complete src/TypeContextCompletion_Jsx.res 44:39 -posCursor:[44:39] posNoWhite:[44:38] Found expr:[44:12->44:39] -JSX 44:25] thirdThing[44:26->44:36]=...[44:37->44:39]> _children:None -Found typed context -Completable: CtypedContext(JsxProp()) -Found polyvariant type otherVariant -[{ - "label": "#three", - "kind": 4, - "tags": [], - "detail": "#three", - "documentation": null - }, { - "label": "#two", - "kind": 4, - "tags": [], - "detail": "#two", - "documentation": null - }] +Complete src/TypeContextCompletion_Jsx.res 26:39 +posCursor:[26:39] posNoWhite:[26:37] Found expr:[26:12->26:38] +JSX 26:25] someVariant[26:26->26:37]=...__ghost__[0:-1->0:-1]> _children:None +found typed context: jsxProp someVariant +[] -Complete src/TypeContextCompletion_Jsx.res 47:39 -posCursor:[47:39] posNoWhite:[47:38] Found expr:[47:12->47:39] -JSX 47:25] thirdThing[47:26->47:36]=...[47:37->47:39]> _children:None -Found typed context -Completable: CtypedContext(JsxProp()) -Found polyvariant type otherVariant +Complete src/TypeContextCompletion_Jsx.res 29:39 +posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:12->29:39] +JSX 29:25] someVariant[29:26->29:37]=...[29:38->29:39]> _children:None +found typed context: jsxProp someVariant +posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:38->29:39] +Pexp_construct T:[29:38->29:39] None +Completable: Cpath Value[T] [{ "label": "Three", "kind": 4, @@ -5674,3 +67,44 @@ Found polyvariant type otherVariant "documentation": null }] +Complete src/TypeContextCompletion_Jsx.res 32:39 +posCursor:[32:39] posNoWhite:[32:38] Found expr:[32:12->32:39] +JSX 32:25] someVariant[32:26->32:37]=...[32:38->32:39]> _children:None +found typed context: jsxProp someVariant +posCursor:[32:39] posNoWhite:[32:38] Found expr:[32:38->32:39] +Pexp_ident t:[32:38->32:39] +Completable: Cpath Value[t] +[] + +Complete src/TypeContextCompletion_Jsx.res 35:39 +posCursor:[35:39] posNoWhite:[35:38] Found expr:[35:12->35:39] +JSX 35:25] anotherThing[35:26->35:38]=...__ghost__[0:-1->0:-1]> _children:None +found typed context: jsxProp anotherThing +[] + +Complete src/TypeContextCompletion_Jsx.res 38:37 +posCursor:[38:37] posNoWhite:[38:36] Found expr:[38:12->38:37] +JSX 38:25] thirdThing[38:26->38:36]=...__ghost__[0:-1->0:-1]> _children:None +found typed context: jsxProp thirdThing +[] + +Complete src/TypeContextCompletion_Jsx.res 41:38 +posCursor:[41:38] posNoWhite:[41:36] Found expr:[41:12->41:37] +JSX 41:25] thirdThing[41:26->41:36]=...__ghost__[0:-1->0:-1]> _children:None +found typed context: jsxProp thirdThing +[] + +Complete src/TypeContextCompletion_Jsx.res 44:39 +posCursor:[44:39] posNoWhite:[44:38] Found expr:[44:12->44:39] +JSX 44:25] thirdThing[44:26->44:36]=...[44:37->44:39]> _children:None +found typed context: jsxProp thirdThing +posCursor:[44:39] posNoWhite:[44:38] Found expr:[44:37->44:39] +[] + +Complete src/TypeContextCompletion_Jsx.res 47:39 +posCursor:[47:39] posNoWhite:[47:38] Found expr:[47:12->47:39] +JSX 47:25] thirdThing[47:26->47:36]=...[47:37->47:39]> _children:None +found typed context: jsxProp thirdThing +posCursor:[47:39] posNoWhite:[47:38] Found expr:[47:37->47:39] +[] + diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index 8b7c98589..2508db47e 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -18,320 +18,155 @@ Found type for function ( Complete src/TypeContextCompletion_LabelledArguments.res 25:44 posCursor:[25:44] posNoWhite:[25:43] Found expr:[25:11->25:44] Pexp_apply ...[25:11->25:30] (~someVariant25:32->25:43=...__ghost__[0:-1->0:-1]) -found typed context -Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])=) -Found variant type someVariant -[{ - "label": "One", - "kind": 4, - "tags": [], - "detail": "One\n\n", - "documentation": null - }, { - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\n", - "documentation": null - }, { - "label": "Three", - "kind": 4, - "tags": [], - "detail": "Three\n\n", - "documentation": null - }, { - "label": "Four", - "kind": 4, - "tags": [], - "detail": "Four\n\n", - "documentation": null - }, { - "label": "Five(_)", - "kind": 4, - "tags": [], - "detail": "Five(int)\n\n", - "documentation": null - }, { - "label": "Six(_)", - "kind": 4, - "tags": [], - "detail": "Six(option, int)\n\n", - "documentation": null - }, { - "label": "someVariantToString", - "kind": 12, - "tags": [], - "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", - "documentation": null - }] +found typed context: named arg someVariant +[] Complete src/TypeContextCompletion_LabelledArguments.res 28:45 posCursor:[28:45] posNoWhite:[28:43] Found expr:[28:11->28:44] Pexp_apply ...[28:11->28:30] (~someVariant28:32->28:43=...__ghost__[0:-1->0:-1]) -found typed context -Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])=) -Found variant type someVariant +found typed context: named arg someVariant +[] + +Complete src/TypeContextCompletion_LabelledArguments.res 31:45 +posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:11->31:45] +Pexp_apply ...[31:11->31:30] (~someVariant31:32->31:43=...[31:44->31:45]) +found typed context: named arg someVariant +posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:44->31:45] +Pexp_construct T:[31:44->31:45] None +Completable: Cpath Value[T] [{ - "label": "One", - "kind": 4, - "tags": [], - "detail": "One\n\n", - "documentation": null - }, { - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\n", - "documentation": null - }, { "label": "Three", "kind": 4, "tags": [], - "detail": "Three\n\n", + "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", "documentation": null }, { - "label": "Four", + "label": "Two", "kind": 4, "tags": [], - "detail": "Four\n\n", + "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", "documentation": null }, { - "label": "Five(_)", - "kind": 4, + "label": "TableclothMap", + "kind": 9, "tags": [], - "detail": "Five(int)\n\n", + "detail": "file module", "documentation": null }, { - "label": "Six(_)", - "kind": 4, + "label": "TypeContextCompletion_Jsx", + "kind": 9, "tags": [], - "detail": "Six(option, int)\n\n", + "detail": "file module", "documentation": null }, { - "label": "someVariantToString", - "kind": 12, - "tags": [], - "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", - "documentation": null - }] - -Complete src/TypeContextCompletion_LabelledArguments.res 31:45 -posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:11->31:45] -Pexp_apply ...[31:11->31:30] (~someVariant31:32->31:43=...[31:44->31:45]) -found typed context -Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])=T) -Found variant type someVariant -[{ - "label": "Two", - "kind": 4, + "label": "TypeContextCompletion_LabelledArguments", + "kind": 9, "tags": [], - "detail": "Two\n\n", + "detail": "file module", "documentation": null }, { - "label": "Three", - "kind": 4, - "tags": [], - "detail": "Three\n\n", - "documentation": null - }, { - "label": "someVariantToString", - "kind": 12, + "label": "TypeDefinition", + "kind": 9, "tags": [], - "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", + "detail": "file module", "documentation": null }] Complete src/TypeContextCompletion_LabelledArguments.res 34:45 posCursor:[34:45] posNoWhite:[34:44] Found expr:[34:11->34:45] Pexp_apply ...[34:11->34:30] (~someVariant34:32->34:43=...[34:44->34:45]) -found typed context -Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])=t) -Found variant type someVariant +found typed context: named arg someVariant +posCursor:[34:45] posNoWhite:[34:44] Found expr:[34:44->34:45] +Pexp_ident t:[34:44->34:45] +Completable: Cpath Value[t] [{ - "label": "someVariantToString", + "label": "thisIsAValue", "kind": 12, "tags": [], - "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", + "detail": "someVariant", "documentation": null }] Complete src/TypeContextCompletion_LabelledArguments.res 37:59 posCursor:[37:59] posNoWhite:[37:58] Found expr:[37:11->37:59] Pexp_apply ...[37:11->37:30] (~someVariant37:32->37:43=...[37:44->37:59]) -found typed context -Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString])=_) -Found variant type someVariant +found typed context: named arg someVariant +posCursor:[37:59] posNoWhite:[37:58] Found expr:[37:44->37:59] +Pexp_ident TypeDefinition.:[37:44->37:59] +Completable: Cpath Value[TypeDefinition, ""] [{ - "label": "someVariantToString", + "label": "g", "kind": 12, "tags": [], - "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", - "documentation": null - }] - -Complete src/TypeContextCompletion_LabelledArguments.res 40:45 -posCursor:[40:45] posNoWhite:[40:44] Found expr:[40:11->40:45] -Pexp_apply ...[40:11->40:30] (~anotherThing40:32->40:44=...__ghost__[0:-1->0:-1]) -found typed context -Completable: CtypedContext(NamedArg(anotherThing, Value[someVariantToString])=) -Found variant type TypeDefinition.variant -[{ - "label": "Foo", - "kind": 4, - "tags": [], - "detail": "Foo\n\n", - "documentation": null - }, { - "label": "Bar", - "kind": 4, - "tags": [], - "detail": "Bar\n\n", + "detail": "variant => string", "documentation": null }, { - "label": "someVariantToString", + "label": "x", "kind": 12, "tags": [], - "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", - "documentation": null - }] - -Complete src/TypeContextCompletion_LabelledArguments.res 43:43 -posCursor:[43:43] posNoWhite:[43:42] Found expr:[43:11->43:43] -Pexp_apply ...[43:11->43:30] (~thirdThing43:32->43:42=...__ghost__[0:-1->0:-1]) -found typed context -Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString])=) -Found polyvariant type otherVariant -[{ - "label": "#one", - "kind": 4, - "tags": [], - "detail": "#one", + "detail": "variant", "documentation": null }, { - "label": "#six(_)", - "kind": 4, + "label": "y", + "kind": 12, "tags": [], - "detail": "#six(option, int)", + "detail": "record", "documentation": null }, { - "label": "#three", - "kind": 4, + "label": "obj", + "kind": 12, "tags": [], - "detail": "#three", + "detail": "obj", "documentation": null }, { - "label": "#two", - "kind": 4, + "label": "f", + "kind": 12, "tags": [], - "detail": "#two", + "detail": "record => string", "documentation": null }, { - "label": "#five(_)", + "label": "Foo", "kind": 4, "tags": [], - "detail": "#five(int)", + "detail": "Foo\n\ntype variant = Foo | Bar", "documentation": null }, { - "label": "#four", + "label": "Bar", "kind": 4, "tags": [], - "detail": "#four", - "documentation": null - }, { - "label": "someVariantToString", - "kind": 12, - "tags": [], - "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", + "detail": "Bar\n\ntype variant = Foo | Bar", "documentation": null }] +Complete src/TypeContextCompletion_LabelledArguments.res 40:45 +posCursor:[40:45] posNoWhite:[40:44] Found expr:[40:11->40:45] +Pexp_apply ...[40:11->40:30] (~anotherThing40:32->40:44=...__ghost__[0:-1->0:-1]) +found typed context: named arg anotherThing +[] + +Complete src/TypeContextCompletion_LabelledArguments.res 43:43 +posCursor:[43:43] posNoWhite:[43:42] Found expr:[43:11->43:43] +Pexp_apply ...[43:11->43:30] (~thirdThing43:32->43:42=...__ghost__[0:-1->0:-1]) +found typed context: named arg thirdThing +[] + Complete src/TypeContextCompletion_LabelledArguments.res 46:44 posCursor:[46:44] posNoWhite:[46:42] Found expr:[46:11->46:43] Pexp_apply ...[46:11->46:30] (~thirdThing46:32->46:42=...__ghost__[0:-1->0:-1]) -found typed context -Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString])=) -Found polyvariant type otherVariant -[{ - "label": "#one", - "kind": 4, - "tags": [], - "detail": "#one", - "documentation": null - }, { - "label": "#six(_)", - "kind": 4, - "tags": [], - "detail": "#six(option, int)", - "documentation": null - }, { - "label": "#three", - "kind": 4, - "tags": [], - "detail": "#three", - "documentation": null - }, { - "label": "#two", - "kind": 4, - "tags": [], - "detail": "#two", - "documentation": null - }, { - "label": "#five(_)", - "kind": 4, - "tags": [], - "detail": "#five(int)", - "documentation": null - }, { - "label": "#four", - "kind": 4, - "tags": [], - "detail": "#four", - "documentation": null - }, { - "label": "someVariantToString", - "kind": 12, - "tags": [], - "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", - "documentation": null - }] +found typed context: named arg thirdThing +[] Complete src/TypeContextCompletion_LabelledArguments.res 49:45 posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:11->49:45] Pexp_apply ...[49:11->49:30] (~thirdThing49:32->49:42=...[49:43->49:45]) -found typed context -Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString])=t) -Found polyvariant type otherVariant -[{ - "label": "#three", - "kind": 4, - "tags": [], - "detail": "#three", - "documentation": null - }, { - "label": "#two", - "kind": 4, - "tags": [], - "detail": "#two", - "documentation": null - }, { - "label": "someVariantToString", - "kind": 12, - "tags": [], - "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", - "documentation": null - }] +found typed context: named arg thirdThing +posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:43->49:45] +[] Complete src/TypeContextCompletion_LabelledArguments.res 52:45 posCursor:[52:45] posNoWhite:[52:44] Found expr:[52:11->52:45] Pexp_apply ...[52:11->52:30] (~thirdThing52:32->52:42=...[52:43->52:45]) -found typed context -Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString])=T) -Found polyvariant type otherVariant -[{ - "label": "someVariantToString", - "kind": 12, - "tags": [], - "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", - "documentation": null - }] +found typed context: named arg thirdThing +posCursor:[52:45] posNoWhite:[52:44] Found expr:[52:43->52:45] +[] From 54e596ced9ea9ff8b72a4946f44262ce37eb24e9 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sat, 30 Jul 2022 18:24:25 +0200 Subject: [PATCH 24/80] add some completion cases for records --- .../tests/src/TypeContextCompletion_Records.res | 17 +++++++++++++++++ analysis/tests/src/expected/Completion.res.txt | 6 ++++++ analysis/tests/src/expected/Dce.res.txt | 2 +- analysis/tests/src/expected/Debug.res.txt | 3 ++- .../expected/TypeContextCompletion_Jsx.res.txt | 6 ++++++ ...eContextCompletion_LabelledArguments.res.txt | 6 ++++++ .../TypeContextCompletion_Records.res.txt | 17 +++++++++++++++++ 7 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 analysis/tests/src/TypeContextCompletion_Records.res create mode 100644 analysis/tests/src/expected/TypeContextCompletion_Records.res.txt diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res new file mode 100644 index 000000000..36a466146 --- /dev/null +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -0,0 +1,17 @@ +type someRecord = {somethingElse: int, whatIsThis: bool} + +type anotherRecord = {something: someRecord, anotherThing: option, thirdThing: string} + +let someVal = { + something: {somethingElse: 123, whatIsThis: false}, + anotherThing: None, + thirdThing: "test", +} + +// let value: anotherRecord = { +// anotherThing: None, +// some +// ^com + +// let {another} = someVal +// ^com diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index 0dfa7d659..a40137f91 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -1417,6 +1417,12 @@ Completable: Cpath Value[T] "tags": [], "detail": "file module", "documentation": null + }, { + "label": "TypeContextCompletion_Records", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null }, { "label": "TypeDefinition", "kind": 9, diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index 07008ce61..94f21c652 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:264 +issues:271 diff --git a/analysis/tests/src/expected/Debug.res.txt b/analysis/tests/src/expected/Debug.res.txt index e8bb2875b..10f7b2f27 100644 --- a/analysis/tests/src/expected/Debug.res.txt +++ b/analysis/tests/src/expected/Debug.res.txt @@ -4,7 +4,7 @@ Dependencies: @rescript/react Source directories: ./node_modules/@rescript/react/src ./node_modules/@rescript/react/src/legacy Source files: ./node_modules/@rescript/react/src/React.res ./node_modules/@rescript/react/src/ReactDOM.res ./node_modules/@rescript/react/src/ReactDOMServer.res ./node_modules/@rescript/react/src/ReactDOMStyle.res ./node_modules/@rescript/react/src/ReactEvent.res ./node_modules/@rescript/react/src/ReactEvent.resi ./node_modules/@rescript/react/src/ReactTestUtils.res ./node_modules/@rescript/react/src/ReactTestUtils.resi ./node_modules/@rescript/react/src/RescriptReactErrorBoundary.res ./node_modules/@rescript/react/src/RescriptReactErrorBoundary.resi ./node_modules/@rescript/react/src/RescriptReactRouter.res ./node_modules/@rescript/react/src/RescriptReactRouter.resi ./node_modules/@rescript/react/src/legacy/ReactDOMRe.res ./node_modules/@rescript/react/src/legacy/ReasonReact.res Source directories: ./src ./src/expected -Source files: ./src/Auto.res ./src/CodeLens.res ./src/CompletePrioritize1.res ./src/CompletePrioritize2.res ./src/Completion.res ./src/Component.res ./src/Component.resi ./src/CreateInterface.res ./src/Cross.res ./src/Dce.res ./src/Debug.res ./src/Definition.res ./src/DefinitionWithInterface.res ./src/DefinitionWithInterface.resi ./src/Div.res ./src/DocumentSymbol.res ./src/Fragment.res ./src/Highlight.res ./src/Hover.res ./src/InlayHint.res ./src/Jsx.res ./src/Jsx.resi ./src/LongIdentTest.res ./src/Object.res ./src/Patterns.res ./src/RecModules.res ./src/RecordCompletion.res ./src/RecoveryOnProp.res ./src/References.res ./src/ReferencesWithInterface.res ./src/ReferencesWithInterface.resi ./src/Rename.res ./src/RenameWithInterface.res ./src/RenameWithInterface.resi ./src/TableclothMap.ml ./src/TableclothMap.mli ./src/TypeContextCompletion_Jsx.res ./src/TypeContextCompletion_LabelledArguments.res ./src/TypeDefinition.res ./src/Xform.res +Source files: ./src/Auto.res ./src/CodeLens.res ./src/CompletePrioritize1.res ./src/CompletePrioritize2.res ./src/Completion.res ./src/Component.res ./src/Component.resi ./src/CreateInterface.res ./src/Cross.res ./src/Dce.res ./src/Debug.res ./src/Definition.res ./src/DefinitionWithInterface.res ./src/DefinitionWithInterface.resi ./src/Div.res ./src/DocumentSymbol.res ./src/Fragment.res ./src/Highlight.res ./src/Hover.res ./src/InlayHint.res ./src/Jsx.res ./src/Jsx.resi ./src/LongIdentTest.res ./src/Object.res ./src/Patterns.res ./src/RecModules.res ./src/RecordCompletion.res ./src/RecoveryOnProp.res ./src/References.res ./src/ReferencesWithInterface.res ./src/ReferencesWithInterface.resi ./src/Rename.res ./src/RenameWithInterface.res ./src/RenameWithInterface.resi ./src/TableclothMap.ml ./src/TableclothMap.mli ./src/TypeContextCompletion_Jsx.res ./src/TypeContextCompletion_LabelledArguments.res ./src/TypeContextCompletion_Records.res ./src/TypeDefinition.res ./src/Xform.res Impl cmt:./lib/bs/src/Auto.cmt res:./src/Auto.res Impl cmt:./lib/bs/src/CodeLens.cmt res:./src/CodeLens.res Impl cmt:./lib/bs/src/CompletePrioritize1.cmt res:./src/CompletePrioritize1.res @@ -37,6 +37,7 @@ IntfAndImpl cmti:./lib/bs/src/RenameWithInterface.cmti resi:./src/RenameWithInte IntfAndImpl cmti:./lib/bs/src/TableclothMap.cmti resi:./src/TableclothMap.mli cmt:./lib/bs/src/TableclothMap.cmt res:./src/TableclothMap.ml Impl cmt:./lib/bs/src/TypeContextCompletion_Jsx.cmt res:./src/TypeContextCompletion_Jsx.res Impl cmt:./lib/bs/src/TypeContextCompletion_LabelledArguments.cmt res:./src/TypeContextCompletion_LabelledArguments.res +Impl cmt:./lib/bs/src/TypeContextCompletion_Records.cmt res:./src/TypeContextCompletion_Records.res Impl cmt:./lib/bs/src/TypeDefinition.cmt res:./src/TypeDefinition.res Impl cmt:./lib/bs/src/Xform.cmt res:./src/Xform.res Dependency dirs: ./node_modules/@rescript/react/lib/bs/src ./node_modules/@rescript/react/lib/bs/src/legacy diff --git a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt index 49f6224bf..a7b6ffd7c 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt @@ -59,6 +59,12 @@ Completable: Cpath Value[T] "tags": [], "detail": "file module", "documentation": null + }, { + "label": "TypeContextCompletion_Records", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null }, { "label": "TypeDefinition", "kind": 9, diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index 2508db47e..92d9e6374 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -64,6 +64,12 @@ Completable: Cpath Value[T] "tags": [], "detail": "file module", "documentation": null + }, { + "label": "TypeContextCompletion_Records", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null }, { "label": "TypeDefinition", "kind": 9, diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt new file mode 100644 index 000000000..6a959b83a --- /dev/null +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -0,0 +1,17 @@ +Complete src/TypeContextCompletion_Records.res 12:9 +posCursor:[12:9] posNoWhite:[12:8] Found expr:[12:5->12:9] +Pexp_ident some:[12:5->12:9] +Completable: Cpath Value[some] +[{ + "label": "someVal", + "kind": 12, + "tags": [], + "detail": "anotherRecord", + "documentation": null + }] + +Complete src/TypeContextCompletion_Records.res 15:15 +posCursor:[15:15] posNoWhite:[15:14] Found pattern:[15:7->15:16] +posCursor:[15:15] posNoWhite:[15:14] Found pattern:[15:8->15:15] +[] + From 8c49fa5b397f62aa9ab14262a76f7a9b3138999a Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sat, 30 Jul 2022 23:45:32 +0200 Subject: [PATCH 25/80] refactor to continuously setting the typed context we're currently looking for --- analysis/src/CompletionFrontEnd.ml | 128 ++++++++++++++++++++--------- 1 file changed, 89 insertions(+), 39 deletions(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 367b60f60..667bbd5cc 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -81,7 +81,7 @@ let isElgibleForTypedContextCompletion exp = | _ -> false let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName - ~debug = + ~setCurrentlyLookingForTypeOpt = let allLabels = List.fold_right (fun prop allLabels -> prop.name :: allLabels) @@ -104,34 +104,28 @@ let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName None else if prop.exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then ( (* Cursor on expr assigned *) - if debug then - Printf.printf "found typed context: jsxProp %s\n" prop.name; - let _typedContext = - Completable.JsxProp - { - componentPath = - Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; - propName = prop.name; - prefix = getIdentFromExpr prop.exp |> Utils.flattenLongIdent; - } - in - (* Some (CtypedContext typedContext)) *) + setCurrentlyLookingForTypeOpt + (Some + (Completable.JsxProp + { + componentPath = + Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; + propName = prop.name; + prefix = getIdentFromExpr prop.exp |> Utils.flattenLongIdent; + })); None) else if prop.exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then ( (* Expr assigned presumably is "rescript.exprhole" after parser recovery. Complete for the value. *) - if debug then - Printf.printf "found typed context: jsxProp %s\n" prop.name; - let _typedContext = - Completable.JsxProp - { - componentPath = - Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; - propName = prop.name; - prefix = getIdentFromExpr prop.exp |> Utils.flattenLongIdent; - } - in - (* Some (CtypedContext typedContext)) *) + setCurrentlyLookingForTypeOpt + (Some + (Completable.JsxProp + { + componentPath = + Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; + propName = prop.name; + prefix = getIdentFromExpr prop.exp |> Utils.flattenLongIdent; + })); None) else loop rest | [] -> @@ -201,7 +195,8 @@ type label = labelled option type arg = {label: label; exp: Parsetree.expression} let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor - ~(contextPath : Completable.contextPath) ~posAfterFunExpr ~debug = + ~(contextPath : Completable.contextPath) ~posAfterFunExpr + ~setCurrentlyLookingForTypeOpt = let allNames = List.fold_right (fun arg allLabels -> @@ -219,30 +214,26 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor && posBeforeCursor < labelled.posEnd then Some (Completable.CnamedArg (contextPath, labelled.name, allNames)) else if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then ( - if debug then - Printf.printf "found typed context: named arg %s \n" labelled.name; - (*Some - (Completable.CtypedContext - (NamedArg + setCurrentlyLookingForTypeOpt + (Some + (Completable.NamedArg { contextPath; label = labelled.name; prefix = getPrefixFromExpr exp; - }))) *) + })); None) else if exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then ( (* Expr assigned presumably is "rescript.exprhole" after parser recovery. Assume this is an empty expression. *) - if debug then - Printf.printf "found typed context: named arg %s \n" labelled.name; - (*Some - (Completable.CtypedContext + setCurrentlyLookingForTypeOpt + (Some (NamedArg { contextPath; label = labelled.name; prefix = getPrefixFromExpr exp; - })))*) + })); None) else loop rest | {label = None; exp} :: rest -> @@ -332,6 +323,20 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | Some x -> result := Some (x, !scope) in let setResult x = setResultOpt (Some x) in + let currentlyLookingForType = ref None in + let setCurrentlyLookingForTypeOpt x = + if !currentlyLookingForType = None then + match x with + | None -> if debug then Printf.printf "Typed context, unsetting\n" + | Some x -> + if debug then + Printf.printf "Typed context, found %s\n" + (match x with + | Completable.JsxProp {propName} -> "jsxProp: " ^ propName + | NamedArg {label} -> "namedArg: " ^ label + | RecordField _ -> "recordField"); + currentlyLookingForType := Some x + in let scopeValueDescription (vd : Parsetree.value_description) = scope := !scope |> Scope.addValue ~name:vd.pval_name.txt ~loc:vd.pval_name.loc @@ -416,6 +421,49 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | Pstr_primitive vd -> scopeValueDescription vd | Pstr_value (recFlag, bindings) -> if recFlag = Recursive then bindings |> List.iter scopeValueBinding; + + (* Check for: let {destructuringSomething} = someIdentifier *) + (* Ensure cursor is inside of record pattern. *) + (* TODO: Function calls, tuples, etc... *) + (match bindings with + | [ + { + pvb_pat = {ppat_desc = Ppat_record (fields, _); ppat_loc}; + pvb_expr = {pexp_desc = Pexp_ident _} as expr; + }; + ] + when ppat_loc |> Loc.hasPos ~pos:posNoWhite && !result = None -> ( + (* The thing being typed currently, if anything *) + let prefix = + match + fields + |> List.filter_map (fun (_loc, {Parsetree.ppat_desc; ppat_loc}) -> + match ppat_desc with + | Ppat_var {txt} + when ppat_loc |> Loc.hasPos ~pos:posBeforeCursor -> + Some txt + | _ -> None) + with + | [prefix] -> prefix + | _ -> "" + in + (* Find all fields already selected in the pattern *) + let alreadySelectedFields = + fields + |> List.filter_map (fun (_loc, {Parsetree.ppat_desc}) -> + match ppat_desc with + | Ppat_var {txt} -> Some txt + | _ -> None) + in + match exprToContextPath expr with + | None -> () + | Some contextPath -> + setResultOpt + (Some + (Completable.CtypedContext + (RecordField {contextPath; prefix; alreadySelectedFields})))) + | _ -> ()); + bindings |> List.iter (fun vb -> iterator.value_binding iterator vb); if recFlag = Nonrecursive then bindings |> List.iter scopeValueBinding; processed := true @@ -610,7 +658,8 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | Some childrenPosStart -> Pos.toString childrenPosStart); let jsxCompletable = findJsxPropsCompletable ~jsxProps ~endPos:(Loc.end_ expr.pexp_loc) - ~posBeforeCursor ~posAfterCompName:(Loc.end_ compName.loc) ~debug + ~posBeforeCursor ~posAfterCompName:(Loc.end_ compName.loc) + ~setCurrentlyLookingForTypeOpt in if jsxCompletable <> None then setResultOpt jsxCompletable else if compName.loc |> Loc.hasPos ~pos:posBeforeCursor then @@ -659,8 +708,9 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = match exprToContextPath funExpr with | Some contextPath -> findNamedArgCompletable ~contextPath ~args - ~endPos:(Loc.end_ expr.pexp_loc) ~posBeforeCursor ~debug + ~endPos:(Loc.end_ expr.pexp_loc) ~posBeforeCursor ~posAfterFunExpr:(Loc.end_ funExpr.pexp_loc) + ~setCurrentlyLookingForTypeOpt | None -> None in From c8f112a499c439bf9ae7406691f50b38fd18d8ed Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sat, 30 Jul 2022 23:47:56 +0200 Subject: [PATCH 26/80] fix + debug util --- analysis/src/CompletionFrontEnd.ml | 4 ++-- analysis/src/Utils.ml | 23 ++++++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 667bbd5cc..c9892f40d 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -330,9 +330,9 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | None -> if debug then Printf.printf "Typed context, unsetting\n" | Some x -> if debug then - Printf.printf "Typed context, found %s\n" + Printf.printf "found typed context: %s\n" (match x with - | Completable.JsxProp {propName} -> "jsxProp: " ^ propName + | Completable.JsxProp {propName} -> "jsxProp " ^ propName | NamedArg {label} -> "namedArg: " ^ label | RecordField _ -> "recordField"); currentlyLookingForType := Some x diff --git a/analysis/src/Utils.ml b/analysis/src/Utils.ml index 7d8ed8e7d..3c31dfbf0 100644 --- a/analysis/src/Utils.ml +++ b/analysis/src/Utils.ml @@ -109,4 +109,25 @@ let identifyPexp pexp = | Pexp_pack _ -> "Pexp_pack" | Pexp_extension _ -> "Pexp_extension" | Pexp_open _ -> "Pexp_open" - | Pexp_unreachable -> "Pexp_unreachable" \ No newline at end of file + | Pexp_unreachable -> "Pexp_unreachable" + +let identifyPpat pat = + match pat with + | Parsetree.Ppat_any -> "Ppat_any" + | Ppat_var _ -> "Ppat_var" + | Ppat_alias _ -> "Ppat_alias" + | Ppat_constant _ -> "Ppat_constant" + | Ppat_interval _ -> "Ppat_interval" + | Ppat_tuple _ -> "Ppat_tuple" + | Ppat_construct _ -> "Ppat_construct" + | Ppat_variant _ -> "Ppat_variant" + | Ppat_record _ -> "Ppat_record" + | Ppat_array _ -> "Ppat_array" + | Ppat_or _ -> "Ppat_or" + | Ppat_constraint _ -> "Ppat_constraint" + | Ppat_type _ -> "Ppat_type" + | Ppat_lazy _ -> "Ppat_lazy" + | Ppat_unpack _ -> "Ppat_unpack" + | Ppat_exception _ -> "Ppat_exception" + | Ppat_extension _ -> "Ppat_extension" + | Ppat_open _ -> "Ppat_open" From 49e45d87fb03535e9df1678dfd6cac3450adbb4d Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sat, 30 Jul 2022 23:48:40 +0200 Subject: [PATCH 27/80] identify and complete for record fields when destructuring --- analysis/src/CompletionBackEnd.ml | 33 +++++++++++- analysis/src/SharedTypes.ml | 11 ++++ .../src/TypeContextCompletion_Records.res | 12 +++-- ...ontextCompletion_LabelledArguments.res.txt | 20 +++---- .../TypeContextCompletion_Records.res.txt | 52 +++++++++++++++---- 5 files changed, 101 insertions(+), 27 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 7b37fff37..f6b21e585 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1832,4 +1832,35 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i | None -> [] | Some (_label, typeExpr) -> completeTypeExpr ~env ~package ~debug ~prefix:(List.hd prefix) typeExpr - @ completionsFromContext)) + @ completionsFromContext) + | RecordField {contextPath; alreadySelectedFields; prefix} -> ( + match + contextPath + |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos + ~env ~exact:true ~scope + |> completionsGetTypeEnv + with + | Some (typ, env) -> ( + match typ |> extractRecordType ~env ~package with + | Some (env, fields, typDecl) -> + (* Get rid of all fields already selected. *) + fields + |> List.filter (fun field -> + not + (alreadySelectedFields + |> List.exists (fun fieldName -> fieldName = field.fname.txt) + )) + |> Utils.filterMap (fun (field : field) -> + if + prefix = "" || checkName field.fname.txt ~prefix ~exact:false + then + Some + (Completion.create ~name:field.fname.txt ~env + ~kind: + (Completion.Field + ( field, + typDecl.item.decl + |> Shared.declToString typDecl.name.txt ))) + else None) + | None -> []) + | None -> [])) diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index f7daf0ed5..8dbe8980e 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -447,6 +447,11 @@ module Completable = struct (* What the user has already started writing, if anything *) prefix: string list; } + | RecordField of { + contextPath: contextPath; + alreadySelectedFields: string list; + prefix: string; + } let str s = if s = "" then "\"\"" else s let list l = "[" ^ (l |> List.map str |> String.concat ", ") ^ "]" @@ -485,6 +490,12 @@ module Completable = struct | JsxProp {propName; componentPath; prefix} -> "JsxProp(<" ^ (componentPath |> ident) ^ " " ^ propName ^ "=" ^ (prefix |> ident) ^ " />)" + | RecordField {contextPath; alreadySelectedFields; prefix} -> + "RecordField(" + ^ (contextPath |> contextPathToString) + ^ ", " + ^ (alreadySelectedFields |> list) + ^ ", " ^ str prefix ^ ")" type t = | Cdecorator of string (** e.g. @module *) diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index 36a466146..4c1891554 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -8,10 +8,12 @@ let someVal = { thirdThing: "test", } -// let value: anotherRecord = { -// anotherThing: None, -// some -// ^com - +// Simple destructuring // let {another} = someVal // ^com + +// let {anotherThing, s} = someVal +// ^com + +// let {} = someVal +// ^com diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index 92d9e6374..3fde038bd 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -18,19 +18,19 @@ Found type for function ( Complete src/TypeContextCompletion_LabelledArguments.res 25:44 posCursor:[25:44] posNoWhite:[25:43] Found expr:[25:11->25:44] Pexp_apply ...[25:11->25:30] (~someVariant25:32->25:43=...__ghost__[0:-1->0:-1]) -found typed context: named arg someVariant +found typed context: namedArg: someVariant [] Complete src/TypeContextCompletion_LabelledArguments.res 28:45 posCursor:[28:45] posNoWhite:[28:43] Found expr:[28:11->28:44] Pexp_apply ...[28:11->28:30] (~someVariant28:32->28:43=...__ghost__[0:-1->0:-1]) -found typed context: named arg someVariant +found typed context: namedArg: someVariant [] Complete src/TypeContextCompletion_LabelledArguments.res 31:45 posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:11->31:45] Pexp_apply ...[31:11->31:30] (~someVariant31:32->31:43=...[31:44->31:45]) -found typed context: named arg someVariant +found typed context: namedArg: someVariant posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:44->31:45] Pexp_construct T:[31:44->31:45] None Completable: Cpath Value[T] @@ -81,7 +81,7 @@ Completable: Cpath Value[T] Complete src/TypeContextCompletion_LabelledArguments.res 34:45 posCursor:[34:45] posNoWhite:[34:44] Found expr:[34:11->34:45] Pexp_apply ...[34:11->34:30] (~someVariant34:32->34:43=...[34:44->34:45]) -found typed context: named arg someVariant +found typed context: namedArg: someVariant posCursor:[34:45] posNoWhite:[34:44] Found expr:[34:44->34:45] Pexp_ident t:[34:44->34:45] Completable: Cpath Value[t] @@ -96,7 +96,7 @@ Completable: Cpath Value[t] Complete src/TypeContextCompletion_LabelledArguments.res 37:59 posCursor:[37:59] posNoWhite:[37:58] Found expr:[37:11->37:59] Pexp_apply ...[37:11->37:30] (~someVariant37:32->37:43=...[37:44->37:59]) -found typed context: named arg someVariant +found typed context: namedArg: someVariant posCursor:[37:59] posNoWhite:[37:58] Found expr:[37:44->37:59] Pexp_ident TypeDefinition.:[37:44->37:59] Completable: Cpath Value[TypeDefinition, ""] @@ -147,32 +147,32 @@ Completable: Cpath Value[TypeDefinition, ""] Complete src/TypeContextCompletion_LabelledArguments.res 40:45 posCursor:[40:45] posNoWhite:[40:44] Found expr:[40:11->40:45] Pexp_apply ...[40:11->40:30] (~anotherThing40:32->40:44=...__ghost__[0:-1->0:-1]) -found typed context: named arg anotherThing +found typed context: namedArg: anotherThing [] Complete src/TypeContextCompletion_LabelledArguments.res 43:43 posCursor:[43:43] posNoWhite:[43:42] Found expr:[43:11->43:43] Pexp_apply ...[43:11->43:30] (~thirdThing43:32->43:42=...__ghost__[0:-1->0:-1]) -found typed context: named arg thirdThing +found typed context: namedArg: thirdThing [] Complete src/TypeContextCompletion_LabelledArguments.res 46:44 posCursor:[46:44] posNoWhite:[46:42] Found expr:[46:11->46:43] Pexp_apply ...[46:11->46:30] (~thirdThing46:32->46:42=...__ghost__[0:-1->0:-1]) -found typed context: named arg thirdThing +found typed context: namedArg: thirdThing [] Complete src/TypeContextCompletion_LabelledArguments.res 49:45 posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:11->49:45] Pexp_apply ...[49:11->49:30] (~thirdThing49:32->49:42=...[49:43->49:45]) -found typed context: named arg thirdThing +found typed context: namedArg: thirdThing posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:43->49:45] [] Complete src/TypeContextCompletion_LabelledArguments.res 52:45 posCursor:[52:45] posNoWhite:[52:44] Found expr:[52:11->52:45] Pexp_apply ...[52:11->52:30] (~thirdThing52:32->52:42=...[52:43->52:45]) -found typed context: named arg thirdThing +found typed context: namedArg: thirdThing posCursor:[52:45] posNoWhite:[52:44] Found expr:[52:43->52:45] [] diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 6a959b83a..f3effaeac 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -1,17 +1,47 @@ -Complete src/TypeContextCompletion_Records.res 12:9 -posCursor:[12:9] posNoWhite:[12:8] Found expr:[12:5->12:9] -Pexp_ident some:[12:5->12:9] -Completable: Cpath Value[some] +Complete src/TypeContextCompletion_Records.res 11:15 +posCursor:[11:15] posNoWhite:[11:14] Found pattern:[11:7->11:16] +posCursor:[11:15] posNoWhite:[11:14] Found pattern:[11:8->11:15] +Completable: CtypedContext(RecordField(Value[someVal], [another], another)) [{ - "label": "someVal", - "kind": 12, + "label": "anotherThing", + "kind": 5, "tags": [], - "detail": "anotherRecord", + "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null }] -Complete src/TypeContextCompletion_Records.res 15:15 -posCursor:[15:15] posNoWhite:[15:14] Found pattern:[15:7->15:16] -posCursor:[15:15] posNoWhite:[15:14] Found pattern:[15:8->15:15] -[] +Complete src/TypeContextCompletion_Records.res 14:23 +posCursor:[14:23] posNoWhite:[14:22] Found pattern:[14:7->14:24] +posCursor:[14:23] posNoWhite:[14:22] Found pattern:[14:22->14:23] +Completable: CtypedContext(RecordField(Value[someVal], [anotherThing, s], s)) +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }] + +Complete src/TypeContextCompletion_Records.res 17:8 +posCursor:[17:8] posNoWhite:[17:7] Found pattern:[17:7->17:9] +Completable: CtypedContext(RecordField(Value[someVal], [], "")) +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { + "label": "anotherThing", + "kind": 5, + "tags": [], + "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { + "label": "thirdThing", + "kind": 5, + "tags": [], + "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }] From 7c8a1ad54355eb71a179b4f4f15f1a3800a1fa86 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sat, 30 Jul 2022 23:59:13 +0200 Subject: [PATCH 28/80] allow any expr, which makes fn returns also work --- analysis/src/CompletionFrontEnd.ml | 4 ++-- .../src/TypeContextCompletion_Records.res | 9 ++++++++ analysis/tests/src/expected/Dce.res.txt | 2 +- .../TypeContextCompletion_Records.res.txt | 23 +++++++++++++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index c9892f40d..652fd62aa 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -424,12 +424,12 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = (* Check for: let {destructuringSomething} = someIdentifier *) (* Ensure cursor is inside of record pattern. *) - (* TODO: Function calls, tuples, etc... *) + (* TODO: Tuples, etc... *) (match bindings with | [ { pvb_pat = {ppat_desc = Ppat_record (fields, _); ppat_loc}; - pvb_expr = {pexp_desc = Pexp_ident _} as expr; + pvb_expr = expr; }; ] when ppat_loc |> Loc.hasPos ~pos:posNoWhite && !result = None -> ( diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index 4c1891554..80d7ea7f1 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -17,3 +17,12 @@ let someVal = { // let {} = someVal // ^com + +let getSomeVal = (~irrelevant: int) => { + ignore(irrelevant) + someVal +} + +// Via function +// let {} = getSomeVal(~irrelevant=123) +// ^com diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index 94f21c652..1c3c94997 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:271 +issues:272 diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index f3effaeac..431b7fab3 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -45,3 +45,26 @@ Completable: CtypedContext(RecordField(Value[someVal], [], "")) "documentation": null }] +Complete src/TypeContextCompletion_Records.res 26:8 +posCursor:[26:8] posNoWhite:[26:7] Found pattern:[26:7->26:9] +Completable: CtypedContext(RecordField(Value[getSomeVal](~irrelevant), [], "")) +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { + "label": "anotherThing", + "kind": 5, + "tags": [], + "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { + "label": "thirdThing", + "kind": 5, + "tags": [], + "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }] + From b34c35d12ce501bd81eb1c66149dd8bbb450da9e Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 31 Jul 2022 20:03:08 +0200 Subject: [PATCH 29/80] basic, slightly buggy completion for nested record fields --- analysis/src/CompletionBackEnd.ml | 37 ++++++++- analysis/src/CompletionFrontEnd.ml | 61 ++++++++++---- analysis/src/SharedTypes.ml | 36 +++++++-- .../src/TypeContextCompletion_Records.res | 15 +++- analysis/tests/src/expected/Dce.res.txt | 2 +- .../TypeContextCompletion_Records.res.txt | 79 +++++++++++++++---- 6 files changed, 191 insertions(+), 39 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index f6b21e585..f2133a297 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1833,9 +1833,15 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i | Some (_label, typeExpr) -> completeTypeExpr ~env ~package ~debug ~prefix:(List.hd prefix) typeExpr @ completionsFromContext) - | RecordField {contextPath; alreadySelectedFields; prefix} -> ( + | RecordField + { + typeSourceContextPath; + nestedContextPath; + alreadySelectedFields; + prefix; + } -> ( match - contextPath + typeSourceContextPath |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos ~env ~exact:true ~scope |> completionsGetTypeEnv @@ -1843,6 +1849,33 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i | Some (typ, env) -> ( match typ |> extractRecordType ~env ~package with | Some (env, fields, typDecl) -> + let rec digToTargetRecord ~nestedContextPath ~env ~targetRecord fields + = + match nestedContextPath with + | [] -> + (* Nothing left to dig, return whatever we have *) + targetRecord + | Completable.RField fieldName :: nestedContextPath -> + fields + |> List.find_map (fun (field : field) -> + if field.fname.txt = fieldName then + match field.typ |> extractRecordType ~env ~package with + | None -> targetRecord + | Some (env, fields, _typDecl) -> + fields + |> digToTargetRecord ~nestedContextPath ~env + ~targetRecord:(Some fields) + else None) + in + + let fields = + match + fields + |> digToTargetRecord ~nestedContextPath ~targetRecord:None ~env + with + | None -> fields + | Some f -> f + in (* Get rid of all fields already selected. *) fields |> List.filter (fun field -> diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 652fd62aa..1ae52c0c2 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -277,6 +277,11 @@ let extractExpApplyArgs ~args = in args |> processArgs ~acc:[] +let getSimpleFieldName txt = + match txt with + | Longident.Lident fieldName -> fieldName + | _ -> "" + let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = let offsetNoWhite = skipWhite text (offset - 1) in let posNoWhite = @@ -425,6 +430,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = (* Check for: let {destructuringSomething} = someIdentifier *) (* Ensure cursor is inside of record pattern. *) (* TODO: Tuples, etc... *) + (* TODO: Handle let {SomeModule.recordField} = ...*) (match bindings with | [ { @@ -433,20 +439,41 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = }; ] when ppat_loc |> Loc.hasPos ~pos:posNoWhite && !result = None -> ( - (* The thing being typed currently, if anything *) - let prefix = - match + (* The contextPath is what we'll use to look up the root record type for this completion. + Depending on if the destructure is nested or not, we may or may not use that directly.*) + let contextPath = exprToContextPath expr in + let prefix, nestedContextPath = + let prefix = ref "" in + let rec findNestedContextPath ~path fields = fields - |> List.filter_map (fun (_loc, {Parsetree.ppat_desc; ppat_loc}) -> - match ppat_desc with - | Ppat_var {txt} - when ppat_loc |> Loc.hasPos ~pos:posBeforeCursor -> - Some txt - | _ -> None) - with - | [prefix] -> prefix - | _ -> "" + |> List.find_map + (fun ({Location.txt}, {Parsetree.ppat_loc; ppat_desc}) -> + if ppat_loc |> Loc.hasPos ~pos:posBeforeCursor then + match ppat_desc with + | Ppat_record (fields, _) -> + if List.length fields = 0 then + Some + ([Completable.RField (getSimpleFieldName txt)] @ path) + else + fields + |> findNestedContextPath + ~path: + ([Completable.RField (getSimpleFieldName txt)] + @ path) + | Ppat_var {txt} -> + prefix := txt; + Some path + | _ -> Some path + else if ppat_loc |> Loc.end_ = (Location.none |> Loc.end_) + then Some path + else None) + in + + match fields |> findNestedContextPath ~path:[] with + | None -> (!prefix, []) + | Some nestedContextPath -> (!prefix, nestedContextPath) in + (* Find all fields already selected in the pattern *) let alreadySelectedFields = fields @@ -455,13 +482,19 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | Ppat_var {txt} -> Some txt | _ -> None) in - match exprToContextPath expr with + match contextPath with | None -> () | Some contextPath -> setResultOpt (Some (Completable.CtypedContext - (RecordField {contextPath; prefix; alreadySelectedFields})))) + (RecordField + { + nestedContextPath = nestedContextPath |> List.rev; + typeSourceContextPath = contextPath; + prefix; + alreadySelectedFields; + })))) | _ -> ()); bindings |> List.iter (fun vb -> iterator.value_binding iterator vb); diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 8dbe8980e..721488e51 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -428,6 +428,9 @@ module Completable = struct | CPObj of contextPath * string | CPPipe of contextPath * string + (* TODO: Can extend to tuples, objects, etc *) + type recordFieldContextPathItem = RField of string + type typedContext = (* A labelled argument assignment, eg. someFunc(~someArg=) *) | NamedArg of { @@ -448,8 +451,14 @@ module Completable = struct prefix: string list; } | RecordField of { - contextPath: contextPath; + (* This is what you'll use to lookup the type to start from when completing *) + typeSourceContextPath: contextPath; + (* This dedicated context path should be used to look up the actual type to complete. + It'll be populated if the type to complete is nested inside of the source record. If it's empty, you should use the source record directly. *) + nestedContextPath: recordFieldContextPathItem list; + (* These are the fields already selected, if any. Filter these away from any completion. *) alreadySelectedFields: string list; + (* This is what the user has started typing already, if anything. Filter results based on this if it's not empty. *) prefix: string; } @@ -457,6 +466,13 @@ module Completable = struct let list l = "[" ^ (l |> List.map str |> String.concat ", ") ^ "]" let ident l = l |> List.map str |> String.concat "." + let recordFieldContextPathToString pathItems = + pathItems + |> List.map (fun item -> + match item with + | RField fieldName -> fieldName) + |> list + let completionContextToString = function | Value -> "Value" | Type -> "Type" @@ -490,12 +506,20 @@ module Completable = struct | JsxProp {propName; componentPath; prefix} -> "JsxProp(<" ^ (componentPath |> ident) ^ " " ^ propName ^ "=" ^ (prefix |> ident) ^ " />)" - | RecordField {contextPath; alreadySelectedFields; prefix} -> - "RecordField(" - ^ (contextPath |> contextPathToString) - ^ ", " + | RecordField + { + typeSourceContextPath; + nestedContextPath; + alreadySelectedFields; + prefix; + } -> + "RecordField(contextPath:" + ^ (typeSourceContextPath |> contextPathToString) + ^ ", nestedContextPath:" + ^ (nestedContextPath |> recordFieldContextPathToString) + ^ ", alreadySelectedFields:" ^ (alreadySelectedFields |> list) - ^ ", " ^ str prefix ^ ")" + ^ ", prefix:" ^ str prefix ^ ")" type t = | Cdecorator of string (** e.g. @module *) diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index 80d7ea7f1..bfea1d56b 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -1,9 +1,10 @@ -type someRecord = {somethingElse: int, whatIsThis: bool} +type anotherLevel = {level: int} +type someRecord = {somethingElse: int, whatIsThis: bool, anotherLevel: anotherLevel} type anotherRecord = {something: someRecord, anotherThing: option, thirdThing: string} let someVal = { - something: {somethingElse: 123, whatIsThis: false}, + something: {somethingElse: 123, whatIsThis: false, anotherLevel: {level: 123}}, anotherThing: None, thirdThing: "test", } @@ -26,3 +27,13 @@ let getSomeVal = (~irrelevant: int) => { // Via function // let {} = getSomeVal(~irrelevant=123) // ^com + +// Nested destructuring +// let {something: {}} = someVal +// ^com + +// let {something: {whatIsThis, anotherLevel: {}}} = someVal +// ^com + +// let {something: {whatIsThis, anotherLevel: {l}}} = someVal +// ^com diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index 1c3c94997..c4bb3af64 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:272 +issues:274 diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 431b7fab3..743850fe2 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -1,7 +1,7 @@ -Complete src/TypeContextCompletion_Records.res 11:15 -posCursor:[11:15] posNoWhite:[11:14] Found pattern:[11:7->11:16] -posCursor:[11:15] posNoWhite:[11:14] Found pattern:[11:8->11:15] -Completable: CtypedContext(RecordField(Value[someVal], [another], another)) +Complete src/TypeContextCompletion_Records.res 12:15 +posCursor:[12:15] posNoWhite:[12:14] Found pattern:[12:7->12:16] +posCursor:[12:15] posNoWhite:[12:14] Found pattern:[12:8->12:15] +Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[], alreadySelectedFields:[another], prefix:another)) [{ "label": "anotherThing", "kind": 5, @@ -10,10 +10,10 @@ Completable: CtypedContext(RecordField(Value[someVal], [another], another)) "documentation": null }] -Complete src/TypeContextCompletion_Records.res 14:23 -posCursor:[14:23] posNoWhite:[14:22] Found pattern:[14:7->14:24] -posCursor:[14:23] posNoWhite:[14:22] Found pattern:[14:22->14:23] -Completable: CtypedContext(RecordField(Value[someVal], [anotherThing, s], s)) +Complete src/TypeContextCompletion_Records.res 15:23 +posCursor:[15:23] posNoWhite:[15:22] Found pattern:[15:7->15:24] +posCursor:[15:23] posNoWhite:[15:22] Found pattern:[15:22->15:23] +Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[], alreadySelectedFields:[anotherThing, s], prefix:s)) [{ "label": "something", "kind": 5, @@ -22,9 +22,9 @@ Completable: CtypedContext(RecordField(Value[someVal], [anotherThing, s], s)) "documentation": null }] -Complete src/TypeContextCompletion_Records.res 17:8 -posCursor:[17:8] posNoWhite:[17:7] Found pattern:[17:7->17:9] -Completable: CtypedContext(RecordField(Value[someVal], [], "")) +Complete src/TypeContextCompletion_Records.res 18:8 +posCursor:[18:8] posNoWhite:[18:7] Found pattern:[18:7->18:9] +Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[], alreadySelectedFields:[], prefix:"")) [{ "label": "something", "kind": 5, @@ -45,9 +45,9 @@ Completable: CtypedContext(RecordField(Value[someVal], [], "")) "documentation": null }] -Complete src/TypeContextCompletion_Records.res 26:8 -posCursor:[26:8] posNoWhite:[26:7] Found pattern:[26:7->26:9] -Completable: CtypedContext(RecordField(Value[getSomeVal](~irrelevant), [], "")) +Complete src/TypeContextCompletion_Records.res 27:8 +posCursor:[27:8] posNoWhite:[27:7] Found pattern:[27:7->27:9] +Completable: CtypedContext(RecordField(contextPath:Value[getSomeVal](~irrelevant), nestedContextPath:[], alreadySelectedFields:[], prefix:"")) [{ "label": "something", "kind": 5, @@ -68,3 +68,54 @@ Completable: CtypedContext(RecordField(Value[getSomeVal](~irrelevant), [], "")) "documentation": null }] +Complete src/TypeContextCompletion_Records.res 31:20 +posCursor:[31:20] posNoWhite:[31:19] Found pattern:[31:7->31:22] +posCursor:[31:20] posNoWhite:[31:19] Found pattern:[31:19->31:21] +Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something], alreadySelectedFields:[], prefix:"")) +[{ + "label": "somethingElse", + "kind": 5, + "tags": [], + "detail": "somethingElse: int\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { + "label": "whatIsThis", + "kind": 5, + "tags": [], + "detail": "whatIsThis: bool\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { + "label": "anotherLevel", + "kind": 5, + "tags": [], + "detail": "anotherLevel: anotherLevel\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }] + +Complete src/TypeContextCompletion_Records.res 34:47 +posCursor:[34:47] posNoWhite:[34:46] Found pattern:[34:7->34:50] +posCursor:[34:47] posNoWhite:[34:46] Found pattern:[34:19->34:49] +posCursor:[34:47] posNoWhite:[34:46] Found pattern:[34:46->34:48] +Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something, anotherLevel], alreadySelectedFields:[], prefix:"")) +[{ + "label": "level", + "kind": 5, + "tags": [], + "detail": "level: int\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }] + +Complete src/TypeContextCompletion_Records.res 37:48 +posCursor:[37:48] posNoWhite:[37:47] Found pattern:[37:7->37:51] +posCursor:[37:48] posNoWhite:[37:47] Found pattern:[37:19->37:50] +posCursor:[37:48] posNoWhite:[37:47] Found pattern:[37:46->37:49] +posCursor:[37:48] posNoWhite:[37:47] Found pattern:[37:47->37:48] +Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something, anotherLevel], alreadySelectedFields:[], prefix:l)) +[{ + "label": "level", + "kind": 5, + "tags": [], + "detail": "level: int\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }] + From 7b1b8cd773ad6f9229b8fc557d5a169655630846 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 1 Aug 2022 09:23:03 +0200 Subject: [PATCH 30/80] do not complete if we cant find the cursor inside of nested pattern --- analysis/src/CompletionFrontEnd.ml | 20 +++++---- .../TypeContextCompletion_Records.res.txt | 42 +------------------ 2 files changed, 13 insertions(+), 49 deletions(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 1ae52c0c2..df00b7948 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -438,7 +438,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = pvb_expr = expr; }; ] - when ppat_loc |> Loc.hasPos ~pos:posNoWhite && !result = None -> ( + when ppat_loc |> Loc.hasPos ~pos:posBeforeCursor && !result = None -> ( (* The contextPath is what we'll use to look up the root record type for this completion. Depending on if the destructure is nested or not, we may or may not use that directly.*) let contextPath = exprToContextPath expr in @@ -466,15 +466,17 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | _ -> Some path else if ppat_loc |> Loc.end_ = (Location.none |> Loc.end_) then Some path - else None) + else + match charBeforeCursor with + | Some ',' -> Some path + | _ -> None) in - match fields |> findNestedContextPath ~path:[] with - | None -> (!prefix, []) - | Some nestedContextPath -> (!prefix, nestedContextPath) + (!prefix, fields |> findNestedContextPath ~path:[]) in (* Find all fields already selected in the pattern *) + (* TODO: This obviously extracts from the wrong thing... *) let alreadySelectedFields = fields |> List.filter_map (fun (_loc, {Parsetree.ppat_desc}) -> @@ -482,9 +484,8 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | Ppat_var {txt} -> Some txt | _ -> None) in - match contextPath with - | None -> () - | Some contextPath -> + match (contextPath, nestedContextPath) with + | Some contextPath, Some nestedContextPath -> setResultOpt (Some (Completable.CtypedContext @@ -494,7 +495,8 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = typeSourceContextPath = contextPath; prefix; alreadySelectedFields; - })))) + }))) + | _ -> ()) | _ -> ()); bindings |> List.iter (fun vb -> iterator.value_binding iterator vb); diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 743850fe2..a65c1aef0 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -24,49 +24,11 @@ Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContext Complete src/TypeContextCompletion_Records.res 18:8 posCursor:[18:8] posNoWhite:[18:7] Found pattern:[18:7->18:9] -Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[], alreadySelectedFields:[], prefix:"")) -[{ - "label": "something", - "kind": 5, - "tags": [], - "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }, { - "label": "anotherThing", - "kind": 5, - "tags": [], - "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }, { - "label": "thirdThing", - "kind": 5, - "tags": [], - "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }] +[] Complete src/TypeContextCompletion_Records.res 27:8 posCursor:[27:8] posNoWhite:[27:7] Found pattern:[27:7->27:9] -Completable: CtypedContext(RecordField(contextPath:Value[getSomeVal](~irrelevant), nestedContextPath:[], alreadySelectedFields:[], prefix:"")) -[{ - "label": "something", - "kind": 5, - "tags": [], - "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }, { - "label": "anotherThing", - "kind": 5, - "tags": [], - "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }, { - "label": "thirdThing", - "kind": 5, - "tags": [], - "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }] +[] Complete src/TypeContextCompletion_Records.res 31:20 posCursor:[31:20] posNoWhite:[31:19] Found pattern:[31:7->31:22] From f79f21bbfa7e2ad1e6aa58aa62ecb4d5f9b69c74 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 1 Aug 2022 09:25:38 +0200 Subject: [PATCH 31/80] add more broken test cases --- .../src/TypeContextCompletion_Records.res | 6 ++++ .../TypeContextCompletion_Records.res.txt | 29 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index bfea1d56b..d479c2d65 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -37,3 +37,9 @@ let getSomeVal = (~irrelevant: int) => { // let {something: {whatIsThis, anotherLevel: {l}}} = someVal // ^com + +// let {something: {whatIsThis, anotherLevel, }} = someVal +// ^com + +// let {something: {whatIsThis, ,anotherLevel}} = someVal +// ^com diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index a65c1aef0..51b0204f5 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -81,3 +81,32 @@ Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContext "documentation": null }] +Complete src/TypeContextCompletion_Records.res 40:47 +posCursor:[40:47] posNoWhite:[40:44] Found pattern:[40:7->40:49] +posCursor:[40:47] posNoWhite:[40:44] Found pattern:[40:19->40:48] +[] + +Complete src/TypeContextCompletion_Records.res 43:31 +posCursor:[43:31] posNoWhite:[43:30] Found pattern:[43:7->43:47] +posCursor:[43:31] posNoWhite:[43:30] Found pattern:[43:19->43:46] +Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something], alreadySelectedFields:[], prefix:"")) +[{ + "label": "somethingElse", + "kind": 5, + "tags": [], + "detail": "somethingElse: int\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { + "label": "whatIsThis", + "kind": 5, + "tags": [], + "detail": "whatIsThis: bool\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { + "label": "anotherLevel", + "kind": 5, + "tags": [], + "detail": "anotherLevel: anotherLevel\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }] + From 0df2b0c6cf12a40e5e669c972a5f2ee530c83c13 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 1 Aug 2022 09:40:19 +0200 Subject: [PATCH 32/80] ensure completing from empty root records work as expected --- analysis/src/CompletionFrontEnd.ml | 16 +++---- .../TypeContextCompletion_Records.res.txt | 42 ++++++++++++++++++- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index df00b7948..6776e773e 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -432,13 +432,8 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = (* TODO: Tuples, etc... *) (* TODO: Handle let {SomeModule.recordField} = ...*) (match bindings with - | [ - { - pvb_pat = {ppat_desc = Ppat_record (fields, _); ppat_loc}; - pvb_expr = expr; - }; - ] - when ppat_loc |> Loc.hasPos ~pos:posBeforeCursor && !result = None -> ( + | [{pvb_pat = {ppat_desc = Ppat_record (fields, _)}; pvb_expr = expr}] + when !result = None -> ( (* The contextPath is what we'll use to look up the root record type for this completion. Depending on if the destructure is nested or not, we may or may not use that directly.*) let contextPath = exprToContextPath expr in @@ -472,7 +467,12 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | _ -> None) in - (!prefix, fields |> findNestedContextPath ~path:[]) + ( !prefix, + match List.length fields with + | 0 -> + (* A record with 0 fields is still valid to complete from *) + Some [] + | _ -> fields |> findNestedContextPath ~path:[] ) in (* Find all fields already selected in the pattern *) diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 51b0204f5..00488d7f2 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -24,11 +24,49 @@ Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContext Complete src/TypeContextCompletion_Records.res 18:8 posCursor:[18:8] posNoWhite:[18:7] Found pattern:[18:7->18:9] -[] +Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[], alreadySelectedFields:[], prefix:"")) +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { + "label": "anotherThing", + "kind": 5, + "tags": [], + "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { + "label": "thirdThing", + "kind": 5, + "tags": [], + "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }] Complete src/TypeContextCompletion_Records.res 27:8 posCursor:[27:8] posNoWhite:[27:7] Found pattern:[27:7->27:9] -[] +Completable: CtypedContext(RecordField(contextPath:Value[getSomeVal](~irrelevant), nestedContextPath:[], alreadySelectedFields:[], prefix:"")) +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { + "label": "anotherThing", + "kind": 5, + "tags": [], + "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { + "label": "thirdThing", + "kind": 5, + "tags": [], + "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }] Complete src/TypeContextCompletion_Records.res 31:20 posCursor:[31:20] posNoWhite:[31:19] Found pattern:[31:7->31:22] From 33cd6452ffaf78f3e050150d57c4d77682d4ae91 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 1 Aug 2022 21:05:37 +0200 Subject: [PATCH 33/80] look for ',' as first char before cursor to trigger completion in cases where the parser discards things we'd need to trigger completion --- analysis/src/CompletionBackEnd.ml | 2 +- analysis/src/CompletionFrontEnd.ml | 41 ++++++++++++++++--- analysis/src/SharedTypes.ml | 4 +- .../TypeContextCompletion_Records.res.txt | 21 +++++++++- 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index f2133a297..c4dd99446 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1855,7 +1855,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i | [] -> (* Nothing left to dig, return whatever we have *) targetRecord - | Completable.RField fieldName :: nestedContextPath -> + | Completable.RField {fieldName} :: nestedContextPath -> fields |> List.find_map (fun (field : field) -> if field.fname.txt = fieldName then diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 6776e773e..7e14404c5 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -288,6 +288,15 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = let line, col = posCursor in (line, max 0 col - offset + offsetNoWhite) in + (* Identifies the first character before the cursor that's not white space. + Should be used very sparingly, but can be used to drive completion triggering + in scenarios where the parser eats things we'd need to complete. + Example: let {whatever, }, char is ','. *) + let firstCharBeforeCursorNoWhite = + if offsetNoWhite < String.length text && offsetNoWhite >= 0 then + Some text.[offsetNoWhite] + else None + in let posBeforeCursor = (fst posCursor, max 0 (snd posCursor - 1)) in let charBeforeCursor, blankAfterCursor = match positionToOffset text posCursor with @@ -440,29 +449,49 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = let prefix, nestedContextPath = let prefix = ref "" in let rec findNestedContextPath ~path fields = + (* This will descend through the record, following where the cursor is located, + to pull out a nested context we can use to figure out what type + we should complete from. *) fields |> List.find_map (fun ({Location.txt}, {Parsetree.ppat_loc; ppat_desc}) -> if ppat_loc |> Loc.hasPos ~pos:posBeforeCursor then + (* Covers when we're still inside the cursor position - continue descending + and build the nested context appropriately. *) match ppat_desc with | Ppat_record (fields, _) -> if List.length fields = 0 then + (* Empty records are fine to complete from *) Some - ([Completable.RField (getSimpleFieldName txt)] @ path) + ([ + Completable.RField + {fieldName = getSimpleFieldName txt}; + ] + @ path) else fields |> findNestedContextPath ~path: - ([Completable.RField (getSimpleFieldName txt)] + ([ + Completable.RField + {fieldName = getSimpleFieldName txt}; + ] @ path) | Ppat_var {txt} -> + (* Whenever we encounter a var, that means we've hit an identifier the user has started typing. + We can then use that as the prefix hint for what to filter completions on. *) prefix := txt; Some path - | _ -> Some path + | _ -> + (* This can be extended to understand more nested contexts, like tuples, etc. *) + Some path else if ppat_loc |> Loc.end_ = (Location.none |> Loc.end_) - then Some path + then + (* This means that an empty location was found, which typically means that the parser has made + recovery here. Complete wherever we are. *) + Some path else - match charBeforeCursor with + match firstCharBeforeCursorNoWhite with | Some ',' -> Some path | _ -> None) in @@ -470,7 +499,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = ( !prefix, match List.length fields with | 0 -> - (* A record with 0 fields is still valid to complete from *) + (* A root record with 0 fields, `let {} = someVar`, is still valid to complete from. But it has no nested context. *) Some [] | _ -> fields |> findNestedContextPath ~path:[] ) in diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 721488e51..047378510 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -429,7 +429,7 @@ module Completable = struct | CPPipe of contextPath * string (* TODO: Can extend to tuples, objects, etc *) - type recordFieldContextPathItem = RField of string + type recordFieldContextPathItem = RField of {fieldName: string} type typedContext = (* A labelled argument assignment, eg. someFunc(~someArg=) *) @@ -470,7 +470,7 @@ module Completable = struct pathItems |> List.map (fun item -> match item with - | RField fieldName -> fieldName) + | RField {fieldName} -> fieldName) |> list let completionContextToString = function diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 00488d7f2..d51a1a87d 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -122,7 +122,26 @@ Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContext Complete src/TypeContextCompletion_Records.res 40:47 posCursor:[40:47] posNoWhite:[40:44] Found pattern:[40:7->40:49] posCursor:[40:47] posNoWhite:[40:44] Found pattern:[40:19->40:48] -[] +Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something], alreadySelectedFields:[], prefix:"")) +[{ + "label": "somethingElse", + "kind": 5, + "tags": [], + "detail": "somethingElse: int\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { + "label": "whatIsThis", + "kind": 5, + "tags": [], + "detail": "whatIsThis: bool\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { + "label": "anotherLevel", + "kind": 5, + "tags": [], + "detail": "anotherLevel: anotherLevel\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }] Complete src/TypeContextCompletion_Records.res 43:31 posCursor:[43:31] posNoWhite:[43:30] Found pattern:[43:7->43:47] From f21a06e8a7ec4a7177915aca3d3c422778e15f4c Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 1 Aug 2022 21:15:53 +0200 Subject: [PATCH 34/80] refactor --- analysis/src/CompletionBackEnd.ml | 12 +++------ analysis/src/CompletionFrontEnd.ml | 26 +++++++++---------- analysis/src/SharedTypes.ml | 18 ++++--------- .../TypeContextCompletion_Records.res.txt | 18 ++++++------- 4 files changed, 31 insertions(+), 43 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index c4dd99446..5e7c02c01 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1833,13 +1833,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i | Some (_label, typeExpr) -> completeTypeExpr ~env ~package ~debug ~prefix:(List.hd prefix) typeExpr @ completionsFromContext) - | RecordField - { - typeSourceContextPath; - nestedContextPath; - alreadySelectedFields; - prefix; - } -> ( + | RecordField {typeSourceContextPath; nestedContextPath; prefix} -> ( match typeSourceContextPath |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos @@ -1876,11 +1870,13 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i | None -> fields | Some f -> f in + (* TODO: This is broken right now, awaiting a refactor *) + let alreadySeenFields = [] in (* Get rid of all fields already selected. *) fields |> List.filter (fun field -> not - (alreadySelectedFields + (alreadySeenFields |> List.exists (fun fieldName -> fieldName = field.fname.txt) )) |> Utils.filterMap (fun (field : field) -> diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 7e14404c5..ea2abfd27 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -277,9 +277,10 @@ let extractExpApplyArgs ~args = in args |> processArgs ~acc:[] -let getSimpleFieldName txt = +let rec getSimpleFieldName txt = match txt with | Longident.Lident fieldName -> fieldName + | Ldot (t, _) -> getSimpleFieldName t | _ -> "" let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = @@ -465,7 +466,10 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = Some ([ Completable.RField - {fieldName = getSimpleFieldName txt}; + { + fieldName = getSimpleFieldName txt; + alreadySeenFields = []; + }; ] @ path) else @@ -474,7 +478,13 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = ~path: ([ Completable.RField - {fieldName = getSimpleFieldName txt}; + { + fieldName = getSimpleFieldName txt; + alreadySeenFields = + fields + |> List.map (fun ({Location.txt}, _) -> + getSimpleFieldName txt); + }; ] @ path) | Ppat_var {txt} -> @@ -504,15 +514,6 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | _ -> fields |> findNestedContextPath ~path:[] ) in - (* Find all fields already selected in the pattern *) - (* TODO: This obviously extracts from the wrong thing... *) - let alreadySelectedFields = - fields - |> List.filter_map (fun (_loc, {Parsetree.ppat_desc}) -> - match ppat_desc with - | Ppat_var {txt} -> Some txt - | _ -> None) - in match (contextPath, nestedContextPath) with | Some contextPath, Some nestedContextPath -> setResultOpt @@ -523,7 +524,6 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = nestedContextPath = nestedContextPath |> List.rev; typeSourceContextPath = contextPath; prefix; - alreadySelectedFields; }))) | _ -> ()) | _ -> ()); diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 047378510..33345e2ce 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -429,7 +429,8 @@ module Completable = struct | CPPipe of contextPath * string (* TODO: Can extend to tuples, objects, etc *) - type recordFieldContextPathItem = RField of {fieldName: string} + type recordFieldContextPathItem = + | RField of {fieldName: string; alreadySeenFields: string list} type typedContext = (* A labelled argument assignment, eg. someFunc(~someArg=) *) @@ -456,8 +457,6 @@ module Completable = struct (* This dedicated context path should be used to look up the actual type to complete. It'll be populated if the type to complete is nested inside of the source record. If it's empty, you should use the source record directly. *) nestedContextPath: recordFieldContextPathItem list; - (* These are the fields already selected, if any. Filter these away from any completion. *) - alreadySelectedFields: string list; (* This is what the user has started typing already, if anything. Filter results based on this if it's not empty. *) prefix: string; } @@ -470,7 +469,8 @@ module Completable = struct pathItems |> List.map (fun item -> match item with - | RField {fieldName} -> fieldName) + | RField {fieldName; alreadySeenFields} -> + fieldName ^ ":" ^ list alreadySeenFields) |> list let completionContextToString = function @@ -506,19 +506,11 @@ module Completable = struct | JsxProp {propName; componentPath; prefix} -> "JsxProp(<" ^ (componentPath |> ident) ^ " " ^ propName ^ "=" ^ (prefix |> ident) ^ " />)" - | RecordField - { - typeSourceContextPath; - nestedContextPath; - alreadySelectedFields; - prefix; - } -> + | RecordField {typeSourceContextPath; nestedContextPath; prefix} -> "RecordField(contextPath:" ^ (typeSourceContextPath |> contextPathToString) ^ ", nestedContextPath:" ^ (nestedContextPath |> recordFieldContextPathToString) - ^ ", alreadySelectedFields:" - ^ (alreadySelectedFields |> list) ^ ", prefix:" ^ str prefix ^ ")" type t = diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index d51a1a87d..e2ca2a6a6 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -1,7 +1,7 @@ Complete src/TypeContextCompletion_Records.res 12:15 posCursor:[12:15] posNoWhite:[12:14] Found pattern:[12:7->12:16] posCursor:[12:15] posNoWhite:[12:14] Found pattern:[12:8->12:15] -Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[], alreadySelectedFields:[another], prefix:another)) +Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[], prefix:another)) [{ "label": "anotherThing", "kind": 5, @@ -13,7 +13,7 @@ Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContext Complete src/TypeContextCompletion_Records.res 15:23 posCursor:[15:23] posNoWhite:[15:22] Found pattern:[15:7->15:24] posCursor:[15:23] posNoWhite:[15:22] Found pattern:[15:22->15:23] -Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[], alreadySelectedFields:[anotherThing, s], prefix:s)) +Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[], prefix:s)) [{ "label": "something", "kind": 5, @@ -24,7 +24,7 @@ Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContext Complete src/TypeContextCompletion_Records.res 18:8 posCursor:[18:8] posNoWhite:[18:7] Found pattern:[18:7->18:9] -Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[], alreadySelectedFields:[], prefix:"")) +Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[], prefix:"")) [{ "label": "something", "kind": 5, @@ -47,7 +47,7 @@ Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContext Complete src/TypeContextCompletion_Records.res 27:8 posCursor:[27:8] posNoWhite:[27:7] Found pattern:[27:7->27:9] -Completable: CtypedContext(RecordField(contextPath:Value[getSomeVal](~irrelevant), nestedContextPath:[], alreadySelectedFields:[], prefix:"")) +Completable: CtypedContext(RecordField(contextPath:Value[getSomeVal](~irrelevant), nestedContextPath:[], prefix:"")) [{ "label": "something", "kind": 5, @@ -71,7 +71,7 @@ Completable: CtypedContext(RecordField(contextPath:Value[getSomeVal](~irrelevant Complete src/TypeContextCompletion_Records.res 31:20 posCursor:[31:20] posNoWhite:[31:19] Found pattern:[31:7->31:22] posCursor:[31:20] posNoWhite:[31:19] Found pattern:[31:19->31:21] -Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something], alreadySelectedFields:[], prefix:"")) +Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something:[]], prefix:"")) [{ "label": "somethingElse", "kind": 5, @@ -96,7 +96,7 @@ Complete src/TypeContextCompletion_Records.res 34:47 posCursor:[34:47] posNoWhite:[34:46] Found pattern:[34:7->34:50] posCursor:[34:47] posNoWhite:[34:46] Found pattern:[34:19->34:49] posCursor:[34:47] posNoWhite:[34:46] Found pattern:[34:46->34:48] -Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something, anotherLevel], alreadySelectedFields:[], prefix:"")) +Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something:[whatIsThis, anotherLevel], anotherLevel:[]], prefix:"")) [{ "label": "level", "kind": 5, @@ -110,7 +110,7 @@ posCursor:[37:48] posNoWhite:[37:47] Found pattern:[37:7->37:51] posCursor:[37:48] posNoWhite:[37:47] Found pattern:[37:19->37:50] posCursor:[37:48] posNoWhite:[37:47] Found pattern:[37:46->37:49] posCursor:[37:48] posNoWhite:[37:47] Found pattern:[37:47->37:48] -Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something, anotherLevel], alreadySelectedFields:[], prefix:l)) +Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something:[whatIsThis, anotherLevel], anotherLevel:[l]], prefix:l)) [{ "label": "level", "kind": 5, @@ -122,7 +122,7 @@ Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContext Complete src/TypeContextCompletion_Records.res 40:47 posCursor:[40:47] posNoWhite:[40:44] Found pattern:[40:7->40:49] posCursor:[40:47] posNoWhite:[40:44] Found pattern:[40:19->40:48] -Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something], alreadySelectedFields:[], prefix:"")) +Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something:[whatIsThis, anotherLevel]], prefix:"")) [{ "label": "somethingElse", "kind": 5, @@ -146,7 +146,7 @@ Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContext Complete src/TypeContextCompletion_Records.res 43:31 posCursor:[43:31] posNoWhite:[43:30] Found pattern:[43:7->43:47] posCursor:[43:31] posNoWhite:[43:30] Found pattern:[43:19->43:46] -Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something], alreadySelectedFields:[], prefix:"")) +Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something:[whatIsThis, anotherLevel]], prefix:"")) [{ "label": "somethingElse", "kind": 5, From 44698e4f55fcbe191bb3c653e015b7c7d9e31eff Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 2 Aug 2022 18:16:33 +0200 Subject: [PATCH 35/80] refactor completion to use new way of recursively digging to the target type --- analysis/src/CompletionBackEnd.ml | 85 ++++++++++--------- .../TypeContextCompletion_Records.res.txt | 22 ++--- 2 files changed, 54 insertions(+), 53 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 5e7c02c01..159d91feb 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1362,6 +1362,44 @@ let getOpens ~rawOpens ~package ~env = (* Last open takes priority *) List.rev resolvedOpens +(* Temporary while I figure things out *) +type completable = + | CRecord of { + fields: field list; + decl: Types.type_declaration; + name: string Location.loc; + } + +let typeExprToCompletable typ ~env ~package = + match typ |> extractType ~env ~package with + | Some (Declared (_, {name; item = {kind = Record fields; decl}})) -> + Some (CRecord {fields; decl; name}) + | _ -> None + +let findTypeInContext (typ : Types.type_expr) ~env ~nestedContextPath ~package = + let rec digToType (currentType : Types.type_expr) ~env ~nestedContextPath + ~package = + (* Check the current context path item *) + match nestedContextPath with + | [] -> + (* If there's no context path, complete the current type *) + typeExprToCompletable currentType ~env ~package + | targetItem :: nestedContextPath -> ( + match (targetItem, currentType |> extractType ~env ~package) with + | ( Completable.RField {fieldName}, + Some (Declared (_, {item = {kind = Record fields}})) ) -> ( + match + fields |> List.find_opt (fun field -> field.fname.txt = fieldName) + with + | None -> None + | Some targetField -> + if List.length nestedContextPath > 0 then + targetField.typ |> digToType ~env ~nestedContextPath ~package + else typeExprToCompletable targetField.typ ~env ~package) + | _ -> None) + in + typ |> digToType ~env ~nestedContextPath ~package + (* Takes a context and a component path (SomeModule.SomeComponent) and extracts all labels *) let getLabelsForComponent ~package ~opens ~allFiles ~pos ~env ~scope componentPath = @@ -1841,44 +1879,10 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i |> completionsGetTypeEnv with | Some (typ, env) -> ( - match typ |> extractRecordType ~env ~package with - | Some (env, fields, typDecl) -> - let rec digToTargetRecord ~nestedContextPath ~env ~targetRecord fields - = - match nestedContextPath with - | [] -> - (* Nothing left to dig, return whatever we have *) - targetRecord - | Completable.RField {fieldName} :: nestedContextPath -> - fields - |> List.find_map (fun (field : field) -> - if field.fname.txt = fieldName then - match field.typ |> extractRecordType ~env ~package with - | None -> targetRecord - | Some (env, fields, _typDecl) -> - fields - |> digToTargetRecord ~nestedContextPath ~env - ~targetRecord:(Some fields) - else None) - in - - let fields = - match - fields - |> digToTargetRecord ~nestedContextPath ~targetRecord:None ~env - with - | None -> fields - | Some f -> f - in - (* TODO: This is broken right now, awaiting a refactor *) - let alreadySeenFields = [] in - (* Get rid of all fields already selected. *) + match typ |> findTypeInContext ~env ~nestedContextPath ~package with + | None -> [] + | Some (CRecord {fields; decl; name}) -> fields - |> List.filter (fun field -> - not - (alreadySeenFields - |> List.exists (fun fieldName -> fieldName = field.fname.txt) - )) |> Utils.filterMap (fun (field : field) -> if prefix = "" || checkName field.fname.txt ~prefix ~exact:false @@ -1887,9 +1891,6 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i (Completion.create ~name:field.fname.txt ~env ~kind: (Completion.Field - ( field, - typDecl.item.decl - |> Shared.declToString typDecl.name.txt ))) - else None) - | None -> []) + (field, decl |> Shared.declToString name.txt))) + else None)) | None -> [])) diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index e2ca2a6a6..8c71c371b 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -76,19 +76,19 @@ Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContext "label": "somethingElse", "kind": 5, "tags": [], - "detail": "somethingElse: int\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null }, { "label": "whatIsThis", "kind": 5, "tags": [], - "detail": "whatIsThis: bool\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "detail": "whatIsThis: bool\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null }, { "label": "anotherLevel", "kind": 5, "tags": [], - "detail": "anotherLevel: anotherLevel\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "detail": "anotherLevel: anotherLevel\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null }] @@ -101,7 +101,7 @@ Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContext "label": "level", "kind": 5, "tags": [], - "detail": "level: int\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "detail": "level: int\n\ntype anotherLevel = {level: int}", "documentation": null }] @@ -115,7 +115,7 @@ Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContext "label": "level", "kind": 5, "tags": [], - "detail": "level: int\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "detail": "level: int\n\ntype anotherLevel = {level: int}", "documentation": null }] @@ -127,19 +127,19 @@ Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContext "label": "somethingElse", "kind": 5, "tags": [], - "detail": "somethingElse: int\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null }, { "label": "whatIsThis", "kind": 5, "tags": [], - "detail": "whatIsThis: bool\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "detail": "whatIsThis: bool\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null }, { "label": "anotherLevel", "kind": 5, "tags": [], - "detail": "anotherLevel: anotherLevel\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "detail": "anotherLevel: anotherLevel\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null }] @@ -151,19 +151,19 @@ Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContext "label": "somethingElse", "kind": 5, "tags": [], - "detail": "somethingElse: int\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null }, { "label": "whatIsThis", "kind": 5, "tags": [], - "detail": "whatIsThis: bool\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "detail": "whatIsThis: bool\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null }, { "label": "anotherLevel", "kind": 5, "tags": [], - "detail": "anotherLevel: anotherLevel\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "detail": "anotherLevel: anotherLevel\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null }] From 48b7bec2f662ceb8087306d81478d0abee1070b5 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 2 Aug 2022 20:50:01 +0200 Subject: [PATCH 36/80] start refactoring the typed context --- analysis/src/CompletionBackEnd.ml | 164 ++++++++++++++--------------- analysis/src/CompletionFrontEnd.ml | 10 +- analysis/src/SharedTypes.ml | 52 +++++++-- 3 files changed, 130 insertions(+), 96 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 159d91feb..e16e6571a 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1491,6 +1491,61 @@ let completeTypeExpr ~env ~package ~debug ~prefix (typeExpr : Types.type_expr) = ^ if constructor.payload |> Option.is_some then "(_)" else "") ~kind:(PolyvariantConstructor constructor) ~env) +let findSourceType sourceType ~package ~opens ~rawOpens ~allFiles ~env ~scope + ~pos = + match sourceType with + | Completable.HowToRetrieveSourceType.NamedArg {label; prefix; contextPath} + -> ( + (* TODO: Should probably share this with the branch handling CnamedArg... *) + let labels = + match + contextPath + |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos + ~env ~exact:true ~scope + |> completionsGetTypeEnv + with + | Some (typ, _env) -> + let rec getLabels ~env (t : Types.type_expr) = + match t.desc with + | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> getLabels ~env t1 + | Tarrow ((Labelled l | Optional l), tArg, tRet, _) -> + (l, tArg) :: getLabels ~env tRet + | Tarrow (Nolabel, _, tRet, _) -> getLabels ~env tRet + | Tconstr (path, _, _) -> ( + match References.digConstructor ~env ~package path with + | Some (env, {item = {decl = {type_manifest = Some t1}}}) -> + getLabels ~env t1 + | _ -> []) + | _ -> [] + in + typ |> getLabels ~env + | None -> [] + in + let targetLabel = + labels |> List.find_opt (fun (name, _t) -> name = label) + in + match targetLabel with + | Some (_, typeExpr) -> Some typeExpr + | _ -> None) + | JsxProp {componentPath; propName; prefix} -> ( + match + componentPath + |> getLabelsForComponent ~package ~opens ~allFiles ~pos ~env ~scope + |> List.find_opt (fun (label, _typeExpr) -> label = propName) + with + | None -> None + | Some (_label, typeExpr) -> Some typeExpr) + | CtxPath typeSourceContextPath -> ( + match + typeSourceContextPath + |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos + ~env ~exact:true ~scope + |> completionsGetTypeEnv + with + | Some (typ, _env) -> Some typ + | None -> None) + | _ -> None + let processCompletable ~debug ~package ~scope ~env ~pos ~forHover (completable : Completable.t) = let rawOpens = Scope.getRawOpens scope in @@ -1808,89 +1863,30 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i Utils.startsWith name prefix && (forHover || not (List.mem name identsSeen))) |> List.map mkLabel - | CtypedContext typedContext -> ( - match typedContext with - | NamedArg {label; prefix; contextPath} -> ( - (* TODO: Should probably share this with the branch handling CnamedArg... *) - let labels = - match - contextPath - |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles - ~pos ~env ~exact:true ~scope - |> completionsGetTypeEnv - with - | Some (typ, _env) -> - let rec getLabels ~env (t : Types.type_expr) = - match t.desc with - | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> getLabels ~env t1 - | Tarrow ((Labelled l | Optional l), tArg, tRet, _) -> - (l, tArg) :: getLabels ~env tRet - | Tarrow (Nolabel, _, tRet, _) -> getLabels ~env tRet - | Tconstr (path, _, _) -> ( - match References.digConstructor ~env ~package path with - | Some (env, {item = {decl = {type_manifest = Some t1}}}) -> - getLabels ~env t1 - | _ -> []) - | _ -> [] - in - typ |> getLabels ~env - | None -> [] - in - let targetLabel = - labels |> List.find_opt (fun (name, _t) -> name = label) - in - match targetLabel with + | CtypedContext {howToRetrieveSourceType; patternPath} -> ( + let prefix = "" in + let sourceType = + findSourceType howToRetrieveSourceType ~package ~opens ~rawOpens ~allFiles + ~env ~pos ~scope + in + let nestedContextPath = + match patternPath with | None -> [] - | Some (_, typeExpr) -> - (* TODO: Wonder if we can filter the values returned here on type... - Maybe that'd be confusing for the user though, if items in scope don't appear. - We should at a minimum be able to sort values according to type and the proximity - of them in the scope. *) - let completionsFromContext = - contextPath - |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles - ~pos ~env ~exact:forHover ~scope - in - completeTypeExpr ~env ~package ~debug ~prefix typeExpr - @ completionsFromContext) - | JsxProp {componentPath; propName; prefix} -> ( - (* TODO: Variant constructors seem to re-appear here. - Wondering if we can get rid of "randomly" completing constructors in scope. Or at least de-duping somehow. *) - (* These are the regular completions for context. Identifiers, modules, etc. *) - let completionsFromContext = - Completable.CPId (prefix, Value) - |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos - ~env ~exact:forHover ~scope - in - match - componentPath - |> getLabelsForComponent ~package ~opens ~allFiles ~pos ~env ~scope - |> List.find_opt (fun (label, _typeExpr) -> label = propName) - with + | Some patternPath -> patternPath + in + match sourceType with + | None -> [] + | Some typ -> ( + match typ |> findTypeInContext ~env ~nestedContextPath ~package with | None -> [] - | Some (_label, typeExpr) -> - completeTypeExpr ~env ~package ~debug ~prefix:(List.hd prefix) typeExpr - @ completionsFromContext) - | RecordField {typeSourceContextPath; nestedContextPath; prefix} -> ( - match - typeSourceContextPath - |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos - ~env ~exact:true ~scope - |> completionsGetTypeEnv - with - | Some (typ, env) -> ( - match typ |> findTypeInContext ~env ~nestedContextPath ~package with - | None -> [] - | Some (CRecord {fields; decl; name}) -> - fields - |> Utils.filterMap (fun (field : field) -> - if - prefix = "" || checkName field.fname.txt ~prefix ~exact:false - then - Some - (Completion.create ~name:field.fname.txt ~env - ~kind: - (Completion.Field - (field, decl |> Shared.declToString name.txt))) - else None)) - | None -> [])) + | Some (CRecord {fields; decl; name}) -> + fields + |> Utils.filterMap (fun (field : field) -> + if prefix = "" || checkName field.fname.txt ~prefix ~exact:false + then + Some + (Completion.create ~name:field.fname.txt ~env + ~kind: + (Completion.Field + (field, decl |> Shared.declToString name.txt))) + else None))) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index ea2abfd27..95c27191a 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -519,12 +519,10 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = setResultOpt (Some (Completable.CtypedContext - (RecordField - { - nestedContextPath = nestedContextPath |> List.rev; - typeSourceContextPath = contextPath; - prefix; - }))) + { + howToRetrieveSourceType = CtxPath contextPath; + patternPath = Some (nestedContextPath |> List.rev); + })) | _ -> ()) | _ -> ()); diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 33345e2ce..3dac25ebe 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -429,7 +429,7 @@ module Completable = struct | CPPipe of contextPath * string (* TODO: Can extend to tuples, objects, etc *) - type recordFieldContextPathItem = + type patternPathItem = | RField of {fieldName: string; alreadySeenFields: string list} type typedContext = @@ -456,7 +456,7 @@ module Completable = struct typeSourceContextPath: contextPath; (* This dedicated context path should be used to look up the actual type to complete. It'll be populated if the type to complete is nested inside of the source record. If it's empty, you should use the source record directly. *) - nestedContextPath: recordFieldContextPathItem list; + nestedContextPath: patternPathItem list; (* This is what the user has started typing already, if anything. Filter results based on this if it's not empty. *) prefix: string; } @@ -513,6 +513,40 @@ module Completable = struct ^ (nestedContextPath |> recordFieldContextPathToString) ^ ", prefix:" ^ str prefix ^ ")" + module HowToRetrieveSourceType = struct + (* Temporary while I figure things. Pretty sure this should be integrated into contextPath when this is all finished *) + type howToRetrieveSourceType = + | CtxPath of contextPath + (* A JSX prop assignment, eg. *) + | JsxProp of { + (* Path to the target component *) + componentPath: string list; + (* The target prop name *) + propName: string; + (* What the user has already started writing, if anything *) + prefix: string list; + } + | NamedArg of { + (* The context path where the completion was found *) + contextPath: contextPath; + (* What the user has already started writing, if anything *) + prefix: string; + (* Name of the argument *) + label: string; + } + + let howToRetrieveSourceTypeToString howToRetrieveSourceType = + match howToRetrieveSourceType with + | CtxPath contextPath -> contextPath |> contextPathToString + | JsxProp {propName; componentPath; prefix} -> + "JsxProp(<" ^ (componentPath |> ident) ^ " " ^ propName ^ "=" + ^ (prefix |> ident) ^ " />)" + | NamedArg {label; contextPath; prefix} -> + "NamedArg(" ^ label ^ ", " + ^ (contextPath |> contextPathToString) + ^ ")=" ^ prefix + end + type t = | Cdecorator of string (** e.g. @module *) | CnamedArg of contextPath * string * string list @@ -521,8 +555,11 @@ module Completable = struct | Cpath of contextPath | Cjsx of string list * string * string list (** E.g. (["M", "Comp"], "id", ["id1", "id2"]) for "Cpath " ^ contextPathToString cp @@ -534,6 +571,9 @@ module Completable = struct | Cnone -> "Cnone" | Cjsx (sl1, s, sl2) -> "Cjsx(" ^ (sl1 |> list) ^ ", " ^ str s ^ ", " ^ (sl2 |> list) ^ ")" - | CtypedContext typedContext -> - "CtypedContext(" ^ (typedContext |> typedContextToString) ^ ")" + | CtypedContext {howToRetrieveSourceType} -> + "CtypedContext(" + ^ (howToRetrieveSourceType + |> HowToRetrieveSourceType.howToRetrieveSourceTypeToString) + ^ ")" end From 295be6b8db6c0608a6ad986c4cad21d5880fe0ba Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 2 Aug 2022 20:50:32 +0200 Subject: [PATCH 37/80] add another label to the record so we can test prefix etc in a better way --- .../src/TypeContextCompletion_Records.res | 8 +- analysis/tests/src/expected/Dce.res.txt | 2 +- .../TypeContextCompletion_Records.res.txt | 114 ++++++++++++------ 3 files changed, 82 insertions(+), 42 deletions(-) diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index d479c2d65..be07215f4 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -1,10 +1,14 @@ -type anotherLevel = {level: int} +type anotherLevel = {level: int, someOtherArg: bool} type someRecord = {somethingElse: int, whatIsThis: bool, anotherLevel: anotherLevel} type anotherRecord = {something: someRecord, anotherThing: option, thirdThing: string} let someVal = { - something: {somethingElse: 123, whatIsThis: false, anotherLevel: {level: 123}}, + something: { + somethingElse: 123, + whatIsThis: false, + anotherLevel: {level: 123, someOtherArg: true}, + }, anotherThing: None, thirdThing: "test", } diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index c4bb3af64..472868779 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:274 +issues:275 diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 8c71c371b..c882a062f 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -1,30 +1,54 @@ -Complete src/TypeContextCompletion_Records.res 12:15 -posCursor:[12:15] posNoWhite:[12:14] Found pattern:[12:7->12:16] -posCursor:[12:15] posNoWhite:[12:14] Found pattern:[12:8->12:15] -Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[], prefix:another)) +Complete src/TypeContextCompletion_Records.res 16:15 +posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:7->16:16] +posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:8->16:15] +Completable: CtypedContext(Value[someVal]) [{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { "label": "anotherThing", "kind": 5, "tags": [], "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null + }, { + "label": "thirdThing", + "kind": 5, + "tags": [], + "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null }] -Complete src/TypeContextCompletion_Records.res 15:23 -posCursor:[15:23] posNoWhite:[15:22] Found pattern:[15:7->15:24] -posCursor:[15:23] posNoWhite:[15:22] Found pattern:[15:22->15:23] -Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[], prefix:s)) +Complete src/TypeContextCompletion_Records.res 19:23 +posCursor:[19:23] posNoWhite:[19:22] Found pattern:[19:7->19:24] +posCursor:[19:23] posNoWhite:[19:22] Found pattern:[19:22->19:23] +Completable: CtypedContext(Value[someVal]) [{ "label": "something", "kind": 5, "tags": [], "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null + }, { + "label": "anotherThing", + "kind": 5, + "tags": [], + "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { + "label": "thirdThing", + "kind": 5, + "tags": [], + "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null }] -Complete src/TypeContextCompletion_Records.res 18:8 -posCursor:[18:8] posNoWhite:[18:7] Found pattern:[18:7->18:9] -Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[], prefix:"")) +Complete src/TypeContextCompletion_Records.res 22:8 +posCursor:[22:8] posNoWhite:[22:7] Found pattern:[22:7->22:9] +Completable: CtypedContext(Value[someVal]) [{ "label": "something", "kind": 5, @@ -45,9 +69,9 @@ Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContext "documentation": null }] -Complete src/TypeContextCompletion_Records.res 27:8 -posCursor:[27:8] posNoWhite:[27:7] Found pattern:[27:7->27:9] -Completable: CtypedContext(RecordField(contextPath:Value[getSomeVal](~irrelevant), nestedContextPath:[], prefix:"")) +Complete src/TypeContextCompletion_Records.res 31:8 +posCursor:[31:8] posNoWhite:[31:7] Found pattern:[31:7->31:9] +Completable: CtypedContext(Value[getSomeVal](~irrelevant)) [{ "label": "something", "kind": 5, @@ -68,10 +92,10 @@ Completable: CtypedContext(RecordField(contextPath:Value[getSomeVal](~irrelevant "documentation": null }] -Complete src/TypeContextCompletion_Records.res 31:20 -posCursor:[31:20] posNoWhite:[31:19] Found pattern:[31:7->31:22] -posCursor:[31:20] posNoWhite:[31:19] Found pattern:[31:19->31:21] -Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something:[]], prefix:"")) +Complete src/TypeContextCompletion_Records.res 35:20 +posCursor:[35:20] posNoWhite:[35:19] Found pattern:[35:7->35:22] +posCursor:[35:20] posNoWhite:[35:19] Found pattern:[35:19->35:21] +Completable: CtypedContext(Value[someVal]) [{ "label": "somethingElse", "kind": 5, @@ -92,37 +116,49 @@ Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContext "documentation": null }] -Complete src/TypeContextCompletion_Records.res 34:47 -posCursor:[34:47] posNoWhite:[34:46] Found pattern:[34:7->34:50] -posCursor:[34:47] posNoWhite:[34:46] Found pattern:[34:19->34:49] -posCursor:[34:47] posNoWhite:[34:46] Found pattern:[34:46->34:48] -Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something:[whatIsThis, anotherLevel], anotherLevel:[]], prefix:"")) +Complete src/TypeContextCompletion_Records.res 38:47 +posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:7->38:50] +posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:19->38:49] +posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:46->38:48] +Completable: CtypedContext(Value[someVal]) [{ "label": "level", "kind": 5, "tags": [], - "detail": "level: int\n\ntype anotherLevel = {level: int}", + "detail": "level: int\n\ntype anotherLevel = {level: int, someOtherArg: bool}", + "documentation": null + }, { + "label": "someOtherArg", + "kind": 5, + "tags": [], + "detail": "someOtherArg: bool\n\ntype anotherLevel = {level: int, someOtherArg: bool}", "documentation": null }] -Complete src/TypeContextCompletion_Records.res 37:48 -posCursor:[37:48] posNoWhite:[37:47] Found pattern:[37:7->37:51] -posCursor:[37:48] posNoWhite:[37:47] Found pattern:[37:19->37:50] -posCursor:[37:48] posNoWhite:[37:47] Found pattern:[37:46->37:49] -posCursor:[37:48] posNoWhite:[37:47] Found pattern:[37:47->37:48] -Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something:[whatIsThis, anotherLevel], anotherLevel:[l]], prefix:l)) +Complete src/TypeContextCompletion_Records.res 41:48 +posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:7->41:51] +posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:19->41:50] +posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:46->41:49] +posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:47->41:48] +Completable: CtypedContext(Value[someVal]) [{ "label": "level", "kind": 5, "tags": [], - "detail": "level: int\n\ntype anotherLevel = {level: int}", + "detail": "level: int\n\ntype anotherLevel = {level: int, someOtherArg: bool}", + "documentation": null + }, { + "label": "someOtherArg", + "kind": 5, + "tags": [], + "detail": "someOtherArg: bool\n\ntype anotherLevel = {level: int, someOtherArg: bool}", "documentation": null }] -Complete src/TypeContextCompletion_Records.res 40:47 -posCursor:[40:47] posNoWhite:[40:44] Found pattern:[40:7->40:49] -posCursor:[40:47] posNoWhite:[40:44] Found pattern:[40:19->40:48] -Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something:[whatIsThis, anotherLevel]], prefix:"")) +Complete src/TypeContextCompletion_Records.res 44:47 +posCursor:[44:47] posNoWhite:[44:44] Found pattern:[44:7->44:49] +posCursor:[44:47] posNoWhite:[44:44] Found pattern:[44:19->44:48] +Completable: CtypedContext(Value[someVal]) [{ "label": "somethingElse", "kind": 5, @@ -143,10 +179,10 @@ Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContext "documentation": null }] -Complete src/TypeContextCompletion_Records.res 43:31 -posCursor:[43:31] posNoWhite:[43:30] Found pattern:[43:7->43:47] -posCursor:[43:31] posNoWhite:[43:30] Found pattern:[43:19->43:46] -Completable: CtypedContext(RecordField(contextPath:Value[someVal], nestedContextPath:[something:[whatIsThis, anotherLevel]], prefix:"")) +Complete src/TypeContextCompletion_Records.res 47:31 +posCursor:[47:31] posNoWhite:[47:30] Found pattern:[47:7->47:47] +posCursor:[47:31] posNoWhite:[47:30] Found pattern:[47:19->47:46] +Completable: CtypedContext(Value[someVal]) [{ "label": "somethingElse", "kind": 5, From 5a2097eec91d22f63cfc5099da3c00dcc10eecf7 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 2 Aug 2022 21:09:38 +0200 Subject: [PATCH 38/80] bring back prefix and seen record fields filtering for destructuring records --- analysis/src/CompletionBackEnd.ml | 24 +++- analysis/src/CompletionFrontEnd.ml | 26 ++-- analysis/src/SharedTypes.ml | 113 +++++------------- .../TypeContextCompletion_Records.res.txt | 54 --------- 4 files changed, 58 insertions(+), 159 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index e16e6571a..8ecbeb111 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1494,8 +1494,7 @@ let completeTypeExpr ~env ~package ~debug ~prefix (typeExpr : Types.type_expr) = let findSourceType sourceType ~package ~opens ~rawOpens ~allFiles ~env ~scope ~pos = match sourceType with - | Completable.HowToRetrieveSourceType.NamedArg {label; prefix; contextPath} - -> ( + | Completable.NamedArg {label; contextPath} -> ( (* TODO: Should probably share this with the branch handling CnamedArg... *) let labels = match @@ -1527,7 +1526,7 @@ let findSourceType sourceType ~package ~opens ~rawOpens ~allFiles ~env ~scope match targetLabel with | Some (_, typeExpr) -> Some typeExpr | _ -> None) - | JsxProp {componentPath; propName; prefix} -> ( + | JsxProp {componentPath; propName} -> ( match componentPath |> getLabelsForComponent ~package ~opens ~allFiles ~pos ~env ~scope @@ -1544,7 +1543,6 @@ let findSourceType sourceType ~package ~opens ~rawOpens ~allFiles ~env ~scope with | Some (typ, _env) -> Some typ | None -> None) - | _ -> None let processCompletable ~debug ~package ~scope ~env ~pos ~forHover (completable : Completable.t) = @@ -1863,8 +1861,8 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i Utils.startsWith name prefix && (forHover || not (List.mem name identsSeen))) |> List.map mkLabel - | CtypedContext {howToRetrieveSourceType; patternPath} -> ( - let prefix = "" in + | CtypedContext + {howToRetrieveSourceType; patternPath; prefix; alreadySeenIdents} -> ( let sourceType = findSourceType howToRetrieveSourceType ~package ~opens ~rawOpens ~allFiles ~env ~pos ~scope @@ -1880,7 +1878,21 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i match typ |> findTypeInContext ~env ~nestedContextPath ~package with | None -> [] | Some (CRecord {fields; decl; name}) -> + let prefix = + match prefix with + | None -> "" + | Some prefix -> prefix + in + let alreadyTypedRecordFields = + match alreadySeenIdents with + | None -> [] + | Some recordFieldNames -> recordFieldNames + in fields + |> List.filter (fun (field : field) -> + not + (alreadyTypedRecordFields + |> List.exists (fun fieldName -> fieldName = field.fname.txt))) |> Utils.filterMap (fun (field : field) -> if prefix = "" || checkName field.fname.txt ~prefix ~exact:false then diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 95c27191a..554a01f16 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -111,7 +111,6 @@ let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName componentPath = Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; propName = prop.name; - prefix = getIdentFromExpr prop.exp |> Utils.flattenLongIdent; })); None) else if prop.exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then ( @@ -124,7 +123,6 @@ let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName componentPath = Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; propName = prop.name; - prefix = getIdentFromExpr prop.exp |> Utils.flattenLongIdent; })); None) else loop rest @@ -215,25 +213,13 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor then Some (Completable.CnamedArg (contextPath, labelled.name, allNames)) else if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then ( setCurrentlyLookingForTypeOpt - (Some - (Completable.NamedArg - { - contextPath; - label = labelled.name; - prefix = getPrefixFromExpr exp; - })); + (Some (Completable.NamedArg {contextPath; label = labelled.name})); None) else if exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then ( (* Expr assigned presumably is "rescript.exprhole" after parser recovery. Assume this is an empty expression. *) setCurrentlyLookingForTypeOpt - (Some - (NamedArg - { - contextPath; - label = labelled.name; - prefix = getPrefixFromExpr exp; - })); + (Some (NamedArg {contextPath; label = labelled.name})); None) else loop rest | {label = None; exp} :: rest -> @@ -349,7 +335,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = (match x with | Completable.JsxProp {propName} -> "jsxProp " ^ propName | NamedArg {label} -> "namedArg: " ^ label - | RecordField _ -> "recordField"); + | CtxPath _ -> "ctxPath"); currentlyLookingForType := Some x in let scopeValueDescription (vd : Parsetree.value_description) = @@ -522,6 +508,12 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = { howToRetrieveSourceType = CtxPath contextPath; patternPath = Some (nestedContextPath |> List.rev); + prefix = Some prefix; + alreadySeenIdents = + (match nestedContextPath with + | RField {alreadySeenFields} :: _rest -> + Some alreadySeenFields + | _ -> None); })) | _ -> ()) | _ -> ()); diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 3dac25ebe..e5b440cfb 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -432,35 +432,6 @@ module Completable = struct type patternPathItem = | RField of {fieldName: string; alreadySeenFields: string list} - type typedContext = - (* A labelled argument assignment, eg. someFunc(~someArg=) *) - | NamedArg of { - (* The context path where the completion was found *) - contextPath: contextPath; - (* What the user has already started writing, if anything *) - prefix: string; - (* Name of the argument *) - label: string; - } - (* A JSX prop assignment, eg. *) - | JsxProp of { - (* Path to the target component *) - componentPath: string list; - (* The target prop name *) - propName: string; - (* What the user has already started writing, if anything *) - prefix: string list; - } - | RecordField of { - (* This is what you'll use to lookup the type to start from when completing *) - typeSourceContextPath: contextPath; - (* This dedicated context path should be used to look up the actual type to complete. - It'll be populated if the type to complete is nested inside of the source record. If it's empty, you should use the source record directly. *) - nestedContextPath: patternPathItem list; - (* This is what the user has started typing already, if anything. Filter results based on this if it's not empty. *) - prefix: string; - } - let str s = if s = "" then "\"\"" else s let list l = "[" ^ (l |> List.map str |> String.concat ", ") ^ "]" let ident l = l |> List.map str |> String.concat "." @@ -497,55 +468,30 @@ module Completable = struct | CPObj (cp, s) -> contextPathToString cp ^ "[\"" ^ s ^ "\"]" | CPPipe (cp, s) -> contextPathToString cp ^ "->" ^ s - let typedContextToString typedContext = - match typedContext with - | NamedArg {label; contextPath; prefix} -> - "NamedArg(" ^ label ^ ", " - ^ (contextPath |> contextPathToString) - ^ ")=" ^ prefix - | JsxProp {propName; componentPath; prefix} -> - "JsxProp(<" ^ (componentPath |> ident) ^ " " ^ propName ^ "=" - ^ (prefix |> ident) ^ " />)" - | RecordField {typeSourceContextPath; nestedContextPath; prefix} -> - "RecordField(contextPath:" - ^ (typeSourceContextPath |> contextPathToString) - ^ ", nestedContextPath:" - ^ (nestedContextPath |> recordFieldContextPathToString) - ^ ", prefix:" ^ str prefix ^ ")" - - module HowToRetrieveSourceType = struct - (* Temporary while I figure things. Pretty sure this should be integrated into contextPath when this is all finished *) - type howToRetrieveSourceType = - | CtxPath of contextPath - (* A JSX prop assignment, eg. *) - | JsxProp of { - (* Path to the target component *) - componentPath: string list; - (* The target prop name *) - propName: string; - (* What the user has already started writing, if anything *) - prefix: string list; - } - | NamedArg of { - (* The context path where the completion was found *) - contextPath: contextPath; - (* What the user has already started writing, if anything *) - prefix: string; - (* Name of the argument *) - label: string; - } - - let howToRetrieveSourceTypeToString howToRetrieveSourceType = - match howToRetrieveSourceType with - | CtxPath contextPath -> contextPath |> contextPathToString - | JsxProp {propName; componentPath; prefix} -> - "JsxProp(<" ^ (componentPath |> ident) ^ " " ^ propName ^ "=" - ^ (prefix |> ident) ^ " />)" - | NamedArg {label; contextPath; prefix} -> - "NamedArg(" ^ label ^ ", " - ^ (contextPath |> contextPathToString) - ^ ")=" ^ prefix - end + (* Temporary while I figure things. Pretty sure this should be integrated into contextPath when this is all finished *) + type howToRetrieveSourceType = + | CtxPath of contextPath + (* A JSX prop assignment, eg. *) + | JsxProp of { + (* Path to the target component *) + componentPath: string list; + (* The target prop name *) + propName: string; + } + | NamedArg of { + (* The context path where the completion was found *) + contextPath: contextPath; + (* Name of the argument *) + label: string; + } + + let howToRetrieveSourceTypeToString howToRetrieveSourceType = + match howToRetrieveSourceType with + | CtxPath contextPath -> contextPath |> contextPathToString + | JsxProp {propName; componentPath} -> + "JsxProp(<" ^ (componentPath |> ident) ^ " " ^ propName ^ "=" ^ " />)" + | NamedArg {label; contextPath} -> + "NamedArg(" ^ label ^ ", " ^ (contextPath |> contextPathToString) ^ ")" type t = | Cdecorator of string (** e.g. @module *) @@ -556,9 +502,13 @@ module Completable = struct | Cjsx of string list * string * string list (** E.g. (["M", "Comp"], "id", ["id1", "id2"]) for list) ^ ", " ^ str s ^ ", " ^ (sl2 |> list) ^ ")" | CtypedContext {howToRetrieveSourceType} -> "CtypedContext(" - ^ (howToRetrieveSourceType - |> HowToRetrieveSourceType.howToRetrieveSourceTypeToString) + ^ (howToRetrieveSourceType |> howToRetrieveSourceTypeToString) ^ ")" end diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index c882a062f..0775358ca 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -3,23 +3,11 @@ posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:7->16:16] posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:8->16:15] Completable: CtypedContext(Value[someVal]) [{ - "label": "something", - "kind": 5, - "tags": [], - "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }, { "label": "anotherThing", "kind": 5, "tags": [], "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null - }, { - "label": "thirdThing", - "kind": 5, - "tags": [], - "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null }] Complete src/TypeContextCompletion_Records.res 19:23 @@ -32,18 +20,6 @@ Completable: CtypedContext(Value[someVal]) "tags": [], "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null - }, { - "label": "anotherThing", - "kind": 5, - "tags": [], - "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }, { - "label": "thirdThing", - "kind": 5, - "tags": [], - "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null }] Complete src/TypeContextCompletion_Records.res 22:8 @@ -147,12 +123,6 @@ Completable: CtypedContext(Value[someVal]) "tags": [], "detail": "level: int\n\ntype anotherLevel = {level: int, someOtherArg: bool}", "documentation": null - }, { - "label": "someOtherArg", - "kind": 5, - "tags": [], - "detail": "someOtherArg: bool\n\ntype anotherLevel = {level: int, someOtherArg: bool}", - "documentation": null }] Complete src/TypeContextCompletion_Records.res 44:47 @@ -165,18 +135,6 @@ Completable: CtypedContext(Value[someVal]) "tags": [], "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null - }, { - "label": "whatIsThis", - "kind": 5, - "tags": [], - "detail": "whatIsThis: bool\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", - "documentation": null - }, { - "label": "anotherLevel", - "kind": 5, - "tags": [], - "detail": "anotherLevel: anotherLevel\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", - "documentation": null }] Complete src/TypeContextCompletion_Records.res 47:31 @@ -189,17 +147,5 @@ Completable: CtypedContext(Value[someVal]) "tags": [], "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null - }, { - "label": "whatIsThis", - "kind": 5, - "tags": [], - "detail": "whatIsThis: bool\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", - "documentation": null - }, { - "label": "anotherLevel", - "kind": 5, - "tags": [], - "detail": "anotherLevel: anotherLevel\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", - "documentation": null }] From da23ca8524e15852954f28863370d3bc909a3f73 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 2 Aug 2022 21:13:17 +0200 Subject: [PATCH 39/80] change test message some --- analysis/src/CompletionFrontEnd.ml | 7 ++++--- .../tests/src/expected/Completion.res.txt | 4 ++-- analysis/tests/src/expected/Jsx.res.txt | 6 +++--- .../tests/src/expected/RecoveryOnProp.res.txt | 2 +- .../TypeContextCompletion_Jsx.res.txt | 18 ++++++++--------- ...ontextCompletion_LabelledArguments.res.txt | 20 +++++++++---------- 6 files changed, 29 insertions(+), 28 deletions(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 554a01f16..84e003cb8 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -333,9 +333,10 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = if debug then Printf.printf "found typed context: %s\n" (match x with - | Completable.JsxProp {propName} -> "jsxProp " ^ propName - | NamedArg {label} -> "namedArg: " ^ label - | CtxPath _ -> "ctxPath"); + | Completable.JsxProp {propName} -> "jsxProp:" ^ propName + | NamedArg {label} -> "namedArg:" ^ label + | CtxPath contextPath -> + "ctxPath:" ^ Completable.contextPathToString contextPath); currentlyLookingForType := Some x in let scopeValueDescription (vd : Parsetree.value_description) = diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index a40137f91..7286c6e81 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -463,7 +463,7 @@ Completable: Cpath Value[Js, Dict, u] Complete src/Completion.res 59:30 posCursor:[59:30] posNoWhite:[59:29] Found expr:[59:15->59:30] JSX 59:21] second[59:22->59:28]=...[59:29->59:30]> _children:None -found typed context: jsxProp second +found typed context: jsxProp:second posCursor:[59:30] posNoWhite:[59:29] Found expr:[59:29->59:30] Pexp_ident z:[59:29->59:30] Completable: Cpath Value[z] @@ -1306,7 +1306,7 @@ Found type for function (~a: int) => int Complete src/Completion.res 336:26 posCursor:[336:26] posNoWhite:[336:25] Found expr:[333:3->346:23] JSX 333:6] onClick[334:4->334:11]=...[334:13->346:23]> _children:None -found typed context: jsxProp onClick +found typed context: jsxProp:onClick posCursor:[336:26] posNoWhite:[336:25] Found expr:[334:13->346:23] posCursor:[336:26] posNoWhite:[336:25] Found expr:[334:13->338:6] posCursor:[336:26] posNoWhite:[336:25] Found expr:[335:6->338:5] diff --git a/analysis/tests/src/expected/Jsx.res.txt b/analysis/tests/src/expected/Jsx.res.txt index b7091ea73..a07c60015 100644 --- a/analysis/tests/src/expected/Jsx.res.txt +++ b/analysis/tests/src/expected/Jsx.res.txt @@ -6,7 +6,7 @@ the type is not great but jump to definition works Complete src/Jsx.res 8:15 posCursor:[8:15] posNoWhite:[8:14] Found expr:[8:4->8:15] JSX 8:5] second[8:6->8:12]=...[8:13->8:15]> _children:None -found typed context: jsxProp second +found typed context: jsxProp:second posCursor:[8:15] posNoWhite:[8:14] Found expr:[8:13->8:15] Pexp_ident fi:[8:13->8:15] Completable: Cpath Value[fi] @@ -355,7 +355,7 @@ Completable: Cpath Module[DefineSomeFields].th Complete src/Jsx.res 122:20 posCursor:[122:20] posNoWhite:[122:19] Found expr:[121:3->125:4] JSX 121:6] x[122:5->122:6]=...[122:7->122:20] name[124:4->124:8]=...[124:9->124:11]> _children:125:2 -found typed context: jsxProp x +found typed context: jsxProp:x posCursor:[122:20] posNoWhite:[122:19] Found expr:[122:7->122:20] Pexp_ident Outer.Inner.h:[122:7->122:20] Completable: Cpath Value[Outer, Inner, h] @@ -370,7 +370,7 @@ Completable: Cpath Value[Outer, Inner, h] Complete src/Jsx.res 129:19 posCursor:[129:19] posNoWhite:[129:18] Found expr:[128:3->131:9] JSX 128:6] x[129:5->129:6]=...[129:7->131:8]> _children:None -found typed context: jsxProp x +found typed context: jsxProp:x posCursor:[129:19] posNoWhite:[129:18] Found expr:[129:7->131:8] Pexp_ident Outer.Inner.:[129:7->131:8] Completable: Cpath Value[Outer, Inner, ""] diff --git a/analysis/tests/src/expected/RecoveryOnProp.res.txt b/analysis/tests/src/expected/RecoveryOnProp.res.txt index eb1d6d422..336f4212e 100644 --- a/analysis/tests/src/expected/RecoveryOnProp.res.txt +++ b/analysis/tests/src/expected/RecoveryOnProp.res.txt @@ -1,7 +1,7 @@ Complete src/RecoveryOnProp.res 6:26 posCursor:[6:26] posNoWhite:[6:25] Found expr:[3:3->11:8] JSX 3:6] onClick[4:4->4:11]=...[4:13->0:-1]> _children:None -found typed context: jsxProp onClick +found typed context: jsxProp:onClick posCursor:[6:26] posNoWhite:[6:25] Found expr:[4:13->8:6] posCursor:[6:26] posNoWhite:[6:25] Found expr:[5:6->8:5] posCursor:[6:26] posNoWhite:[6:25] Found expr:[6:16->8:5] diff --git a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt index a7b6ffd7c..1d03efe77 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt @@ -13,19 +13,19 @@ Completable: Cjsx([SomeComponent], someVaria, [someVaria]) Complete src/TypeContextCompletion_Jsx.res 23:38 posCursor:[23:38] posNoWhite:[23:37] Found expr:[23:12->23:38] JSX 23:25] someVariant[23:26->23:37]=...__ghost__[0:-1->0:-1]> _children:None -found typed context: jsxProp someVariant +found typed context: jsxProp:someVariant [] Complete src/TypeContextCompletion_Jsx.res 26:39 posCursor:[26:39] posNoWhite:[26:37] Found expr:[26:12->26:38] JSX 26:25] someVariant[26:26->26:37]=...__ghost__[0:-1->0:-1]> _children:None -found typed context: jsxProp someVariant +found typed context: jsxProp:someVariant [] Complete src/TypeContextCompletion_Jsx.res 29:39 posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:12->29:39] JSX 29:25] someVariant[29:26->29:37]=...[29:38->29:39]> _children:None -found typed context: jsxProp someVariant +found typed context: jsxProp:someVariant posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:38->29:39] Pexp_construct T:[29:38->29:39] None Completable: Cpath Value[T] @@ -76,7 +76,7 @@ Completable: Cpath Value[T] Complete src/TypeContextCompletion_Jsx.res 32:39 posCursor:[32:39] posNoWhite:[32:38] Found expr:[32:12->32:39] JSX 32:25] someVariant[32:26->32:37]=...[32:38->32:39]> _children:None -found typed context: jsxProp someVariant +found typed context: jsxProp:someVariant posCursor:[32:39] posNoWhite:[32:38] Found expr:[32:38->32:39] Pexp_ident t:[32:38->32:39] Completable: Cpath Value[t] @@ -85,32 +85,32 @@ Completable: Cpath Value[t] Complete src/TypeContextCompletion_Jsx.res 35:39 posCursor:[35:39] posNoWhite:[35:38] Found expr:[35:12->35:39] JSX 35:25] anotherThing[35:26->35:38]=...__ghost__[0:-1->0:-1]> _children:None -found typed context: jsxProp anotherThing +found typed context: jsxProp:anotherThing [] Complete src/TypeContextCompletion_Jsx.res 38:37 posCursor:[38:37] posNoWhite:[38:36] Found expr:[38:12->38:37] JSX 38:25] thirdThing[38:26->38:36]=...__ghost__[0:-1->0:-1]> _children:None -found typed context: jsxProp thirdThing +found typed context: jsxProp:thirdThing [] Complete src/TypeContextCompletion_Jsx.res 41:38 posCursor:[41:38] posNoWhite:[41:36] Found expr:[41:12->41:37] JSX 41:25] thirdThing[41:26->41:36]=...__ghost__[0:-1->0:-1]> _children:None -found typed context: jsxProp thirdThing +found typed context: jsxProp:thirdThing [] Complete src/TypeContextCompletion_Jsx.res 44:39 posCursor:[44:39] posNoWhite:[44:38] Found expr:[44:12->44:39] JSX 44:25] thirdThing[44:26->44:36]=...[44:37->44:39]> _children:None -found typed context: jsxProp thirdThing +found typed context: jsxProp:thirdThing posCursor:[44:39] posNoWhite:[44:38] Found expr:[44:37->44:39] [] Complete src/TypeContextCompletion_Jsx.res 47:39 posCursor:[47:39] posNoWhite:[47:38] Found expr:[47:12->47:39] JSX 47:25] thirdThing[47:26->47:36]=...[47:37->47:39]> _children:None -found typed context: jsxProp thirdThing +found typed context: jsxProp:thirdThing posCursor:[47:39] posNoWhite:[47:38] Found expr:[47:37->47:39] [] diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index 3fde038bd..8864c68d1 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -18,19 +18,19 @@ Found type for function ( Complete src/TypeContextCompletion_LabelledArguments.res 25:44 posCursor:[25:44] posNoWhite:[25:43] Found expr:[25:11->25:44] Pexp_apply ...[25:11->25:30] (~someVariant25:32->25:43=...__ghost__[0:-1->0:-1]) -found typed context: namedArg: someVariant +found typed context: namedArg:someVariant [] Complete src/TypeContextCompletion_LabelledArguments.res 28:45 posCursor:[28:45] posNoWhite:[28:43] Found expr:[28:11->28:44] Pexp_apply ...[28:11->28:30] (~someVariant28:32->28:43=...__ghost__[0:-1->0:-1]) -found typed context: namedArg: someVariant +found typed context: namedArg:someVariant [] Complete src/TypeContextCompletion_LabelledArguments.res 31:45 posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:11->31:45] Pexp_apply ...[31:11->31:30] (~someVariant31:32->31:43=...[31:44->31:45]) -found typed context: namedArg: someVariant +found typed context: namedArg:someVariant posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:44->31:45] Pexp_construct T:[31:44->31:45] None Completable: Cpath Value[T] @@ -81,7 +81,7 @@ Completable: Cpath Value[T] Complete src/TypeContextCompletion_LabelledArguments.res 34:45 posCursor:[34:45] posNoWhite:[34:44] Found expr:[34:11->34:45] Pexp_apply ...[34:11->34:30] (~someVariant34:32->34:43=...[34:44->34:45]) -found typed context: namedArg: someVariant +found typed context: namedArg:someVariant posCursor:[34:45] posNoWhite:[34:44] Found expr:[34:44->34:45] Pexp_ident t:[34:44->34:45] Completable: Cpath Value[t] @@ -96,7 +96,7 @@ Completable: Cpath Value[t] Complete src/TypeContextCompletion_LabelledArguments.res 37:59 posCursor:[37:59] posNoWhite:[37:58] Found expr:[37:11->37:59] Pexp_apply ...[37:11->37:30] (~someVariant37:32->37:43=...[37:44->37:59]) -found typed context: namedArg: someVariant +found typed context: namedArg:someVariant posCursor:[37:59] posNoWhite:[37:58] Found expr:[37:44->37:59] Pexp_ident TypeDefinition.:[37:44->37:59] Completable: Cpath Value[TypeDefinition, ""] @@ -147,32 +147,32 @@ Completable: Cpath Value[TypeDefinition, ""] Complete src/TypeContextCompletion_LabelledArguments.res 40:45 posCursor:[40:45] posNoWhite:[40:44] Found expr:[40:11->40:45] Pexp_apply ...[40:11->40:30] (~anotherThing40:32->40:44=...__ghost__[0:-1->0:-1]) -found typed context: namedArg: anotherThing +found typed context: namedArg:anotherThing [] Complete src/TypeContextCompletion_LabelledArguments.res 43:43 posCursor:[43:43] posNoWhite:[43:42] Found expr:[43:11->43:43] Pexp_apply ...[43:11->43:30] (~thirdThing43:32->43:42=...__ghost__[0:-1->0:-1]) -found typed context: namedArg: thirdThing +found typed context: namedArg:thirdThing [] Complete src/TypeContextCompletion_LabelledArguments.res 46:44 posCursor:[46:44] posNoWhite:[46:42] Found expr:[46:11->46:43] Pexp_apply ...[46:11->46:30] (~thirdThing46:32->46:42=...__ghost__[0:-1->0:-1]) -found typed context: namedArg: thirdThing +found typed context: namedArg:thirdThing [] Complete src/TypeContextCompletion_LabelledArguments.res 49:45 posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:11->49:45] Pexp_apply ...[49:11->49:30] (~thirdThing49:32->49:42=...[49:43->49:45]) -found typed context: namedArg: thirdThing +found typed context: namedArg:thirdThing posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:43->49:45] [] Complete src/TypeContextCompletion_LabelledArguments.res 52:45 posCursor:[52:45] posNoWhite:[52:44] Found expr:[52:11->52:45] Pexp_apply ...[52:11->52:30] (~thirdThing52:32->52:42=...[52:43->52:45]) -found typed context: namedArg: thirdThing +found typed context: namedArg:thirdThing posCursor:[52:45] posNoWhite:[52:44] Found expr:[52:43->52:45] [] From 39a35ecabb819cb8b7599dd8a829f2e5842432ea Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 4 Aug 2022 18:09:04 +0200 Subject: [PATCH 40/80] more completion exploration --- analysis/src/CompletionBackEnd.ml | 108 ++++++- analysis/src/CompletionFrontEnd.ml | 96 ++++-- analysis/src/SharedTypes.ml | 22 +- analysis/tests/src/Completion.res | 2 +- .../tests/src/expected/Completion.res.txt | 11 +- analysis/tests/src/expected/Jsx.res.txt | 25 +- .../TypeContextCompletion_Jsx.res.txt | 269 ++++++++++++++-- ...ontextCompletion_LabelledArguments.res.txt | 291 ++++++++++++++---- .../TypeContextCompletion_Records.res.txt | 18 +- 9 files changed, 677 insertions(+), 165 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 8ecbeb111..d505a4d09 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -897,6 +897,40 @@ let getItemsFromOpens ~opens ~localTables ~prefix ~exact ~completionContext = completionsFromThisOpen @ results) [] +let findLocalCompletionsForTypeExpr ~(localTables : LocalTables.t) ~env ~prefix + ~exact ~opens ~scope typeExpr = + let _targetId = typeExpr.Types.id in + localTables |> LocalTables.populateValues ~env; + localTables |> LocalTables.populateModules ~env; + scope + |> Scope.iterValuesBeforeFirstOpen + (processLocalValue ~prefix ~exact ~env ~localTables); + scope + |> Scope.iterModulesBeforeFirstOpen + (processLocalModule ~prefix ~exact ~env ~localTables); + + let valuesFromOpens = + getItemsFromOpens ~opens ~localTables ~prefix ~exact + ~completionContext:Value + in + + scope + |> Scope.iterValuesAfterFirstOpen + (processLocalValue ~prefix ~exact ~env ~localTables); + scope + |> Scope.iterModulesAfterFirstOpen + (processLocalModule ~prefix ~exact ~env ~localTables); + List.rev_append localTables.resultRev valuesFromOpens +(* TODO: Re-enable/make this work - filtering by type |> List.filter (fun completion -> + match completion.Completion.kind with + | Module _ -> true + | Value {id} when id = targetId -> true + | Value {id} -> + Printf.printf "compared %s with id %i to target %i\n" completion.name + id targetId; + false + | _ -> false) *) + let findLocalCompletionsForValuesAndConstructors ~(localTables : LocalTables.t) ~env ~prefix ~exact ~opens ~scope = localTables |> LocalTables.populateValues ~env; @@ -988,6 +1022,14 @@ let findLocalCompletionsWithOpens ~pos ~(env : QueryEnv.t) ~prefix ~exact ~opens (* There's no local completion for fields *) [] +let findLocalCompletionsForTypeExprL ~(env : QueryEnv.t) ~prefix ~exact ~opens + ~scope typeExpr = + (* TODO: handle arbitrary interleaving of opens and local bindings correctly *) + let localTables = LocalTables.create () in + typeExpr + |> findLocalCompletionsForTypeExpr ~localTables ~env ~exact ~opens ~scope + ~prefix + let rec extractRecordType ~env ~package (t : Types.type_expr) = match t.desc with | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> extractRecordType ~env ~package t1 @@ -1369,11 +1411,16 @@ type completable = decl: Types.type_declaration; name: string Location.loc; } + | CVariant of {constructors: Constructor.t list} + | CPolyVariant of {constructors: polyVariantConstructor list} let typeExprToCompletable typ ~env ~package = match typ |> extractType ~env ~package with | Some (Declared (_, {name; item = {kind = Record fields; decl}})) -> Some (CRecord {fields; decl; name}) + | Some (Declared (_, {item = {kind = Variant constructors}})) -> + Some (CVariant {constructors}) + | Some (Polyvariant (_, constructors)) -> Some (CPolyVariant {constructors}) | _ -> None let findTypeInContext (typ : Types.type_expr) ~env ~nestedContextPath ~package = @@ -1498,12 +1545,14 @@ let findSourceType sourceType ~package ~opens ~rawOpens ~allFiles ~env ~scope (* TODO: Should probably share this with the branch handling CnamedArg... *) let labels = match + (* This just hijacks getCompletionsForContextPath and completionsGetTypeEnv because they + already kind of do what I need. Should break this out to its own, dedicated thing later. *) contextPath |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos ~env ~exact:true ~scope |> completionsGetTypeEnv with - | Some (typ, _env) -> + | Some (typ, env) -> let rec getLabels ~env (t : Types.type_expr) = match t.desc with | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> getLabels ~env t1 @@ -1862,7 +1911,13 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i && (forHover || not (List.mem name identsSeen))) |> List.map mkLabel | CtypedContext - {howToRetrieveSourceType; patternPath; prefix; alreadySeenIdents} -> ( + {howToRetrieveSourceType; patternPath; meta = {prefix; alreadySeenIdents}} + -> ( + let prefix = + match prefix with + | None -> "" + | Some prefix -> prefix + in let sourceType = findSourceType howToRetrieveSourceType ~package ~opens ~rawOpens ~allFiles ~env ~pos ~scope @@ -1877,12 +1932,51 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i | Some typ -> ( match typ |> findTypeInContext ~env ~nestedContextPath ~package with | None -> [] - | Some (CRecord {fields; decl; name}) -> - let prefix = - match prefix with - | None -> "" - | Some prefix -> prefix + | Some (CPolyVariant {constructors}) -> + let constructorCompletions = + constructors + |> List.filter (fun constructor -> + Utils.startsWith constructor.name prefix) + |> List.map (fun constructor -> + (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? + Eg. Some($1) as completion item. *) + Completion.create + ~name: + ("#" ^ constructor.name + ^ + if constructor.payload |> Option.is_some then "(_)" else "" + ) + ~kind:(PolyvariantConstructor constructor) ~env) in + let localCompletions = + typ + |> findLocalCompletionsForTypeExprL ~env ~prefix ~exact:false ~opens + ~scope + in + constructorCompletions @ localCompletions + | Some (CVariant {constructors}) -> + let constructorCompletions = + constructors + |> List.filter (fun constructor -> + Utils.startsWith constructor.Constructor.cname.txt prefix) + |> List.map (fun (constructor : Constructor.t) -> + (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? + Eg. Some($1) as completion item. *) + Completion.create + ~name: + (constructor.cname.txt + ^ if constructor.args |> List.length > 0 then "(_)" else "" + ) + ~kind:(Constructor (constructor, "")) + ~env) + in + let localCompletions = + typ + |> findLocalCompletionsForTypeExprL ~env ~prefix ~exact:false ~opens + ~scope + in + constructorCompletions @ localCompletions + | Some (CRecord {fields; decl; name}) -> let alreadyTypedRecordFields = match alreadySeenIdents with | None -> [] diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 84e003cb8..fed12f93f 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -72,16 +72,8 @@ type jsxProps = { childrenStart: (int * int) option; } -(* Checks if an expression is elgible for typed context completion. *) -let isElgibleForTypedContextCompletion exp = - match exp.Parsetree.pexp_desc with - | Pexp_variant _ | Pexp_field _ | Pexp_construct _ - | Pexp_extension ({txt = "rescript.exprhole"}, _) -> - true - | _ -> false - let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName - ~setCurrentlyLookingForTypeOpt = + ~setCurrentlyLookingForTypeOpt ~setTypedContextMeta = let allLabels = List.fold_right (fun prop allLabels -> prop.name :: allLabels) @@ -112,6 +104,11 @@ let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; propName = prop.name; })); + setTypedContextMeta + { + Completable.prefix = Some (getPrefixFromExpr prop.exp); + alreadySeenIdents = None; + }; None) else if prop.exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then ( (* Expr assigned presumably is "rescript.exprhole" after parser recovery. @@ -124,6 +121,11 @@ let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; propName = prop.name; })); + setTypedContextMeta + { + Completable.prefix = Some (getPrefixFromExpr prop.exp); + alreadySeenIdents = None; + }; None) else loop rest | [] -> @@ -194,7 +196,7 @@ type arg = {label: label; exp: Parsetree.expression} let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor ~(contextPath : Completable.contextPath) ~posAfterFunExpr - ~setCurrentlyLookingForTypeOpt = + ~setCurrentlyLookingForTypeOpt ~setTypedContextMeta = let allNames = List.fold_right (fun arg allLabels -> @@ -214,12 +216,22 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor else if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then ( setCurrentlyLookingForTypeOpt (Some (Completable.NamedArg {contextPath; label = labelled.name})); + setTypedContextMeta + { + Completable.prefix = Some (getPrefixFromExpr exp); + alreadySeenIdents = None; + }; None) else if exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then ( (* Expr assigned presumably is "rescript.exprhole" after parser recovery. Assume this is an empty expression. *) setCurrentlyLookingForTypeOpt (Some (NamedArg {contextPath; label = labelled.name})); + setTypedContextMeta + { + Completable.prefix = Some (getPrefixFromExpr exp); + alreadySeenIdents = None; + }; None) else loop rest | {label = None; exp} :: rest -> @@ -324,6 +336,10 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | Some x -> result := Some (x, !scope) in let setResult x = setResultOpt (Some x) in + let typedContextMeta = + ref {Completable.prefix = None; alreadySeenIdents = None} + in + let setTypedContextMeta newValue = typedContextMeta := newValue in let currentlyLookingForType = ref None in let setCurrentlyLookingForTypeOpt x = if !currentlyLookingForType = None then @@ -509,12 +525,15 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = { howToRetrieveSourceType = CtxPath contextPath; patternPath = Some (nestedContextPath |> List.rev); - prefix = Some prefix; - alreadySeenIdents = - (match nestedContextPath with - | RField {alreadySeenFields} :: _rest -> - Some alreadySeenFields - | _ -> None); + meta = + { + prefix = Some prefix; + alreadySeenIdents = + (match nestedContextPath with + | RField {alreadySeenFields} :: _rest -> + Some alreadySeenFields + | _ -> None); + }; })) | _ -> ()) | _ -> ()); @@ -644,15 +663,24 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = setFound (); match expr.pexp_desc with | Pexp_constant _ -> setResult Cnone - | Pexp_ident lid -> + | Pexp_ident lid -> ( let lidPath = flattenLidCheckDot lid in if debug then Printf.printf "Pexp_ident %s:%s\n" (lidPath |> String.concat ".") (Loc.toString lid.loc); if lid.loc |> Loc.hasPos ~pos:posBeforeCursor then - setResult (Cpath (CPId (lidPath, Value))) - | Pexp_construct (lid, eOpt) -> + match !currentlyLookingForType with + | Some lookingForType -> + setResult + (CtypedContext + { + howToRetrieveSourceType = lookingForType; + patternPath = None; + meta = !typedContextMeta; + }) + | _ -> setResult (Cpath (CPId (lidPath, Value)))) + | Pexp_construct (lid, eOpt) -> ( let lidPath = flattenLidCheckDot lid in if debug then Printf.printf "Pexp_construct %s:%s %s\n" @@ -664,7 +692,17 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = if eOpt = None && (not lid.loc.loc_ghost) && lid.loc |> Loc.hasPos ~pos:posBeforeCursor - then setResult (Cpath (CPId (lidPath, Value))) + then + match !currentlyLookingForType with + | Some lookingForType -> + setResult + (CtypedContext + { + howToRetrieveSourceType = lookingForType; + patternPath = None; + meta = !typedContextMeta; + }) + | _ -> setResult (Cpath (CPId (lidPath, Value)))) | Pexp_field (e, fieldName) -> ( if debug then Printf.printf "Pexp_field %s %s:%s\n" (Loc.toString e.pexp_loc) @@ -714,7 +752,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = let jsxCompletable = findJsxPropsCompletable ~jsxProps ~endPos:(Loc.end_ expr.pexp_loc) ~posBeforeCursor ~posAfterCompName:(Loc.end_ compName.loc) - ~setCurrentlyLookingForTypeOpt + ~setCurrentlyLookingForTypeOpt ~setTypedContextMeta in if jsxCompletable <> None then setResultOpt jsxCompletable else if compName.loc |> Loc.hasPos ~pos:posBeforeCursor then @@ -765,7 +803,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = findNamedArgCompletable ~contextPath ~args ~endPos:(Loc.end_ expr.pexp_loc) ~posBeforeCursor ~posAfterFunExpr:(Loc.end_ funExpr.pexp_loc) - ~setCurrentlyLookingForTypeOpt + ~setCurrentlyLookingForTypeOpt ~setTypedContextMeta | None -> None in @@ -948,6 +986,20 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = scope := !lastScopeBeforeCursor; setResult (Cpath (CPId ([""], Value)))); if !found = false then if debug then Printf.printf "XXX Not found!\n"; + + (* If nothing explicitly matched for completion, but we're still looking for a type + somewhere where the cursor is - complete for that. *) + (match (!result, !currentlyLookingForType) with + | None, Some lookingForType -> + scope := !lastScopeBeforeCursor; + setResult + (Completable.CtypedContext + { + howToRetrieveSourceType = lookingForType; + patternPath = None; + meta = !typedContextMeta; + }) + | _ -> ()); !result) else if Filename.check_suffix path ".resi" then ( let parser = Res_driver.parsingEngine.parseInterface ~forPrinter:false in diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index e5b440cfb..3a95c9ca2 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -493,6 +493,14 @@ module Completable = struct | NamedArg {label; contextPath} -> "NamedArg(" ^ label ^ ", " ^ (contextPath |> contextPathToString) ^ ")" + type typedContextMeta = { + (* What the user has already started writing, if anything. *) + prefix: string option; + (* Record fields already written by the user, etc. + This is contextual of course, but putting it here in the general type to simplify things. *) + alreadySeenIdents: string list option; + } + type t = | Cdecorator of string (** e.g. @module *) | CnamedArg of contextPath * string * string list @@ -504,11 +512,7 @@ module Completable = struct | CtypedContext of { howToRetrieveSourceType: howToRetrieveSourceType; patternPath: patternPathItem list option; - (* What the user has already started writing, if anything. *) - prefix: string option; - (* Record fields already written by the user, etc. - This is contextual of course, but putting it here in the general type to simplify things. *) - alreadySeenIdents: string list option; + meta: typedContextMeta; } let toString = function @@ -521,8 +525,12 @@ module Completable = struct | Cnone -> "Cnone" | Cjsx (sl1, s, sl2) -> "Cjsx(" ^ (sl1 |> list) ^ ", " ^ str s ^ ", " ^ (sl2 |> list) ^ ")" - | CtypedContext {howToRetrieveSourceType} -> + | CtypedContext {howToRetrieveSourceType; meta = {prefix}} -> ( "CtypedContext(" ^ (howToRetrieveSourceType |> howToRetrieveSourceTypeToString) - ^ ")" + ^ ")=" + ^ + match prefix with + | None -> "" + | Some prefix -> str prefix) end diff --git a/analysis/tests/src/Completion.res b/analysis/tests/src/Completion.res index 4f3f46c04..4ad191100 100644 --- a/analysis/tests/src/Completion.res +++ b/analysis/tests/src/Completion.res @@ -51,7 +51,7 @@ let fa: ForAuto.t = 34 module O = { module Comp = { @react.component - let make = (~first="", ~zoo=3, ~second) => React.string(first ++ second ++ string_of_int(zoo)) + let make = (~first="", ~zoo=3, ~second) => React.string(first ++ string_of_int(second) ++ string_of_int(zoo)) } } diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index 7286c6e81..602772eda 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -466,14 +466,9 @@ JSX 59:21] second[59:22->59:28]=...[59:29->59:30]> _children:Non found typed context: jsxProp:second posCursor:[59:30] posNoWhite:[59:29] Found expr:[59:29->59:30] Pexp_ident z:[59:29->59:30] -Completable: Cpath Value[z] -[{ - "label": "zzz", - "kind": 12, - "tags": [], - "detail": "int", - "documentation": null - }] +Completable: CtypedContext(JsxProp())=z +could not extract type +[] Complete src/Completion.res 62:23 posCursor:[62:23] posNoWhite:[62:22] Found expr:[62:15->62:23] diff --git a/analysis/tests/src/expected/Jsx.res.txt b/analysis/tests/src/expected/Jsx.res.txt index a07c60015..9bbac1c73 100644 --- a/analysis/tests/src/expected/Jsx.res.txt +++ b/analysis/tests/src/expected/Jsx.res.txt @@ -9,7 +9,8 @@ JSX 8:5] second[8:6->8:12]=...[8:13->8:15]> _children:None found typed context: jsxProp:second posCursor:[8:15] posNoWhite:[8:14] Found expr:[8:13->8:15] Pexp_ident fi:[8:13->8:15] -Completable: Cpath Value[fi] +Completable: CtypedContext(JsxProp())=fi +could not extract type [] Complete src/Jsx.res 11:20 @@ -358,14 +359,8 @@ JSX 121:6] x[122:5->122:6]=...[122:7->122:20] name[124:4->124:8]=.. found typed context: jsxProp:x posCursor:[122:20] posNoWhite:[122:19] Found expr:[122:7->122:20] Pexp_ident Outer.Inner.h:[122:7->122:20] -Completable: Cpath Value[Outer, Inner, h] -[{ - "label": "hello", - "kind": 12, - "tags": [], - "detail": "int", - "documentation": null - }] +Completable: CtypedContext(JsxProp(
))=h +[] Complete src/Jsx.res 129:19 posCursor:[129:19] posNoWhite:[129:18] Found expr:[128:3->131:9] @@ -373,14 +368,8 @@ JSX 128:6] x[129:5->129:6]=...[129:7->131:8]> _children:None found typed context: jsxProp:x posCursor:[129:19] posNoWhite:[129:18] Found expr:[129:7->131:8] Pexp_ident Outer.Inner.:[129:7->131:8] -Completable: Cpath Value[Outer, Inner, ""] -[{ - "label": "hello", - "kind": 12, - "tags": [], - "detail": "int", - "documentation": null - }] +Completable: CtypedContext(JsxProp(
))=name +[] Complete src/Jsx.res 136:7 posCursor:[136:7] posNoWhite:[136:6] Found expr:[135:3->138:9] @@ -448,7 +437,7 @@ Completable: Cjsx([Completion, O, Comp], "", []) "label": "second", "kind": 4, "tags": [], - "detail": "string", + "detail": "int", "documentation": null }, { "label": "zoo", diff --git a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt index 1d03efe77..eb71f79d4 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt @@ -14,62 +14,130 @@ Complete src/TypeContextCompletion_Jsx.res 23:38 posCursor:[23:38] posNoWhite:[23:37] Found expr:[23:12->23:38] JSX 23:25] someVariant[23:26->23:37]=...__ghost__[0:-1->0:-1]> _children:None found typed context: jsxProp:someVariant -[] +Completable: CtypedContext(JsxProp())="" +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\n", + "documentation": null + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\n", + "documentation": null + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\n", + "documentation": null + }, { + "label": "Six(_)", + "kind": 4, + "tags": [], + "detail": "Six(option, int)\n\n", + "documentation": null + }, { + "label": "someValue", + "kind": 12, + "tags": [], + "detail": "someVariant", + "documentation": null + }, { + "label": "SomeComponent", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null + }] Complete src/TypeContextCompletion_Jsx.res 26:39 posCursor:[26:39] posNoWhite:[26:37] Found expr:[26:12->26:38] JSX 26:25] someVariant[26:26->26:37]=...__ghost__[0:-1->0:-1]> _children:None found typed context: jsxProp:someVariant -[] - -Complete src/TypeContextCompletion_Jsx.res 29:39 -posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:12->29:39] -JSX 29:25] someVariant[29:26->29:37]=...[29:38->29:39]> _children:None -found typed context: jsxProp:someVariant -posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:38->29:39] -Pexp_construct T:[29:38->29:39] None -Completable: Cpath Value[T] +Completable: CtypedContext(JsxProp())="" [{ - "label": "Three", + "label": "One", "kind": 4, "tags": [], - "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "detail": "One\n\n", "documentation": null }, { "label": "Two", "kind": 4, "tags": [], - "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "detail": "Two\n\n", "documentation": null }, { - "label": "TableclothMap", - "kind": 9, + "label": "Three", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Three\n\n", "documentation": null }, { - "label": "TypeContextCompletion_Jsx", - "kind": 9, + "label": "Four", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Four\n\n", "documentation": null }, { - "label": "TypeContextCompletion_LabelledArguments", - "kind": 9, + "label": "Five(_)", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Five(int)\n\n", "documentation": null }, { - "label": "TypeContextCompletion_Records", - "kind": 9, + "label": "Six(_)", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Six(option, int)\n\n", "documentation": null }, { - "label": "TypeDefinition", + "label": "someValue", + "kind": 12, + "tags": [], + "detail": "someVariant", + "documentation": null + }, { + "label": "SomeComponent", "kind": 9, "tags": [], - "detail": "file module", + "detail": "module", + "documentation": null + }] + +Complete src/TypeContextCompletion_Jsx.res 29:39 +posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:12->29:39] +JSX 29:25] someVariant[29:26->29:37]=...[29:38->29:39]> _children:None +found typed context: jsxProp:someVariant +posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:38->29:39] +Pexp_construct T:[29:38->29:39] None +Completable: CtypedContext(JsxProp())=T +[{ + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\n", "documentation": null }] @@ -79,38 +147,175 @@ JSX 32:25] someVariant[32:26->32:37]=...[32:38->32:39]> _ found typed context: jsxProp:someVariant posCursor:[32:39] posNoWhite:[32:38] Found expr:[32:38->32:39] Pexp_ident t:[32:38->32:39] -Completable: Cpath Value[t] +Completable: CtypedContext(JsxProp())=t [] Complete src/TypeContextCompletion_Jsx.res 35:39 posCursor:[35:39] posNoWhite:[35:38] Found expr:[35:12->35:39] JSX 35:25] anotherThing[35:26->35:38]=...__ghost__[0:-1->0:-1]> _children:None found typed context: jsxProp:anotherThing -[] +Completable: CtypedContext(JsxProp())="" +[{ + "label": "Foo", + "kind": 4, + "tags": [], + "detail": "Foo\n\n", + "documentation": null + }, { + "label": "Bar", + "kind": 4, + "tags": [], + "detail": "Bar\n\n", + "documentation": null + }, { + "label": "someValue", + "kind": 12, + "tags": [], + "detail": "someVariant", + "documentation": null + }, { + "label": "SomeComponent", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null + }] Complete src/TypeContextCompletion_Jsx.res 38:37 posCursor:[38:37] posNoWhite:[38:36] Found expr:[38:12->38:37] JSX 38:25] thirdThing[38:26->38:36]=...__ghost__[0:-1->0:-1]> _children:None found typed context: jsxProp:thirdThing -[] +Completable: CtypedContext(JsxProp())="" +[{ + "label": "#one", + "kind": 4, + "tags": [], + "detail": "#one", + "documentation": null + }, { + "label": "#six(_)", + "kind": 4, + "tags": [], + "detail": "#six(option, int)", + "documentation": null + }, { + "label": "#three", + "kind": 4, + "tags": [], + "detail": "#three", + "documentation": null + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two", + "documentation": null + }, { + "label": "#five(_)", + "kind": 4, + "tags": [], + "detail": "#five(int)", + "documentation": null + }, { + "label": "#four", + "kind": 4, + "tags": [], + "detail": "#four", + "documentation": null + }, { + "label": "someValue", + "kind": 12, + "tags": [], + "detail": "someVariant", + "documentation": null + }, { + "label": "SomeComponent", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null + }] Complete src/TypeContextCompletion_Jsx.res 41:38 posCursor:[41:38] posNoWhite:[41:36] Found expr:[41:12->41:37] JSX 41:25] thirdThing[41:26->41:36]=...__ghost__[0:-1->0:-1]> _children:None found typed context: jsxProp:thirdThing -[] +Completable: CtypedContext(JsxProp())="" +[{ + "label": "#one", + "kind": 4, + "tags": [], + "detail": "#one", + "documentation": null + }, { + "label": "#six(_)", + "kind": 4, + "tags": [], + "detail": "#six(option, int)", + "documentation": null + }, { + "label": "#three", + "kind": 4, + "tags": [], + "detail": "#three", + "documentation": null + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two", + "documentation": null + }, { + "label": "#five(_)", + "kind": 4, + "tags": [], + "detail": "#five(int)", + "documentation": null + }, { + "label": "#four", + "kind": 4, + "tags": [], + "detail": "#four", + "documentation": null + }, { + "label": "someValue", + "kind": 12, + "tags": [], + "detail": "someVariant", + "documentation": null + }, { + "label": "SomeComponent", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null + }] Complete src/TypeContextCompletion_Jsx.res 44:39 posCursor:[44:39] posNoWhite:[44:38] Found expr:[44:12->44:39] JSX 44:25] thirdThing[44:26->44:36]=...[44:37->44:39]> _children:None found typed context: jsxProp:thirdThing posCursor:[44:39] posNoWhite:[44:38] Found expr:[44:37->44:39] -[] +Completable: CtypedContext(JsxProp())=t +[{ + "label": "#three", + "kind": 4, + "tags": [], + "detail": "#three", + "documentation": null + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two", + "documentation": null + }] Complete src/TypeContextCompletion_Jsx.res 47:39 posCursor:[47:39] posNoWhite:[47:38] Found expr:[47:12->47:39] JSX 47:25] thirdThing[47:26->47:36]=...[47:37->47:39]> _children:None found typed context: jsxProp:thirdThing posCursor:[47:39] posNoWhite:[47:38] Found expr:[47:37->47:39] +Completable: CtypedContext(JsxProp())=T [] diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index 8864c68d1..7a6f8f2b7 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -19,62 +19,130 @@ Complete src/TypeContextCompletion_LabelledArguments.res 25:44 posCursor:[25:44] posNoWhite:[25:43] Found expr:[25:11->25:44] Pexp_apply ...[25:11->25:30] (~someVariant25:32->25:43=...__ghost__[0:-1->0:-1]) found typed context: namedArg:someVariant -[] +Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))="" +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\n", + "documentation": null + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\n", + "documentation": null + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\n", + "documentation": null + }, { + "label": "Six(_)", + "kind": 4, + "tags": [], + "detail": "Six(option, int)\n\n", + "documentation": null + }, { + "label": "someVariantToString", + "kind": 12, + "tags": [], + "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", + "documentation": null + }, { + "label": "thisIsAValue", + "kind": 12, + "tags": [], + "detail": "someVariant", + "documentation": null + }] Complete src/TypeContextCompletion_LabelledArguments.res 28:45 posCursor:[28:45] posNoWhite:[28:43] Found expr:[28:11->28:44] Pexp_apply ...[28:11->28:30] (~someVariant28:32->28:43=...__ghost__[0:-1->0:-1]) found typed context: namedArg:someVariant -[] - -Complete src/TypeContextCompletion_LabelledArguments.res 31:45 -posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:11->31:45] -Pexp_apply ...[31:11->31:30] (~someVariant31:32->31:43=...[31:44->31:45]) -found typed context: namedArg:someVariant -posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:44->31:45] -Pexp_construct T:[31:44->31:45] None -Completable: Cpath Value[T] +Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))="" [{ - "label": "Three", + "label": "One", "kind": 4, "tags": [], - "detail": "Three\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "detail": "One\n\n", "documentation": null }, { "label": "Two", "kind": 4, "tags": [], - "detail": "Two\n\ntype someVariant =\n | One\n | Two\n | Three\n | Four\n | Five(int)\n | Six(option, int)", + "detail": "Two\n\n", "documentation": null }, { - "label": "TableclothMap", - "kind": 9, + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\n", + "documentation": null + }, { + "label": "Four", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Four\n\n", "documentation": null }, { - "label": "TypeContextCompletion_Jsx", - "kind": 9, + "label": "Five(_)", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Five(int)\n\n", "documentation": null }, { - "label": "TypeContextCompletion_LabelledArguments", - "kind": 9, + "label": "Six(_)", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Six(option, int)\n\n", "documentation": null }, { - "label": "TypeContextCompletion_Records", - "kind": 9, + "label": "someVariantToString", + "kind": 12, "tags": [], - "detail": "file module", + "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", "documentation": null }, { - "label": "TypeDefinition", - "kind": 9, + "label": "thisIsAValue", + "kind": 12, "tags": [], - "detail": "file module", + "detail": "someVariant", + "documentation": null + }] + +Complete src/TypeContextCompletion_LabelledArguments.res 31:45 +posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:11->31:45] +Pexp_apply ...[31:11->31:30] (~someVariant31:32->31:43=...[31:44->31:45]) +found typed context: namedArg:someVariant +posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:44->31:45] +Pexp_construct T:[31:44->31:45] None +Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))=T +[{ + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\n", "documentation": null }] @@ -84,7 +152,7 @@ Pexp_apply ...[34:11->34:30] (~someVariant34:32->34:43=...[34:44->34:45]) found typed context: namedArg:someVariant posCursor:[34:45] posNoWhite:[34:44] Found expr:[34:44->34:45] Pexp_ident t:[34:44->34:45] -Completable: Cpath Value[t] +Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))=t [{ "label": "thisIsAValue", "kind": 12, @@ -99,80 +167,181 @@ Pexp_apply ...[37:11->37:30] (~someVariant37:32->37:43=...[37:44->37:59]) found typed context: namedArg:someVariant posCursor:[37:59] posNoWhite:[37:58] Found expr:[37:44->37:59] Pexp_ident TypeDefinition.:[37:44->37:59] -Completable: Cpath Value[TypeDefinition, ""] +Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))=_ +[] + +Complete src/TypeContextCompletion_LabelledArguments.res 40:45 +posCursor:[40:45] posNoWhite:[40:44] Found expr:[40:11->40:45] +Pexp_apply ...[40:11->40:30] (~anotherThing40:32->40:44=...__ghost__[0:-1->0:-1]) +found typed context: namedArg:anotherThing +Completable: CtypedContext(NamedArg(anotherThing, Value[someVariantToString]))="" [{ - "label": "g", - "kind": 12, + "label": "Foo", + "kind": 4, "tags": [], - "detail": "variant => string", + "detail": "Foo\n\n", "documentation": null }, { - "label": "x", - "kind": 12, + "label": "Bar", + "kind": 4, "tags": [], - "detail": "variant", + "detail": "Bar\n\n", "documentation": null }, { - "label": "y", + "label": "someVariantToString", "kind": 12, "tags": [], - "detail": "record", + "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", "documentation": null }, { - "label": "obj", + "label": "thisIsAValue", "kind": 12, "tags": [], - "detail": "obj", + "detail": "someVariant", + "documentation": null + }] + +Complete src/TypeContextCompletion_LabelledArguments.res 43:43 +posCursor:[43:43] posNoWhite:[43:42] Found expr:[43:11->43:43] +Pexp_apply ...[43:11->43:30] (~thirdThing43:32->43:42=...__ghost__[0:-1->0:-1]) +found typed context: namedArg:thirdThing +Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))="" +[{ + "label": "#one", + "kind": 4, + "tags": [], + "detail": "#one", "documentation": null }, { - "label": "f", - "kind": 12, + "label": "#six(_)", + "kind": 4, "tags": [], - "detail": "record => string", + "detail": "#six(option, int)", "documentation": null }, { - "label": "Foo", + "label": "#three", "kind": 4, "tags": [], - "detail": "Foo\n\ntype variant = Foo | Bar", + "detail": "#three", "documentation": null }, { - "label": "Bar", + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two", + "documentation": null + }, { + "label": "#five(_)", + "kind": 4, + "tags": [], + "detail": "#five(int)", + "documentation": null + }, { + "label": "#four", "kind": 4, "tags": [], - "detail": "Bar\n\ntype variant = Foo | Bar", + "detail": "#four", + "documentation": null + }, { + "label": "someVariantToString", + "kind": 12, + "tags": [], + "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", + "documentation": null + }, { + "label": "thisIsAValue", + "kind": 12, + "tags": [], + "detail": "someVariant", "documentation": null }] -Complete src/TypeContextCompletion_LabelledArguments.res 40:45 -posCursor:[40:45] posNoWhite:[40:44] Found expr:[40:11->40:45] -Pexp_apply ...[40:11->40:30] (~anotherThing40:32->40:44=...__ghost__[0:-1->0:-1]) -found typed context: namedArg:anotherThing -[] - -Complete src/TypeContextCompletion_LabelledArguments.res 43:43 -posCursor:[43:43] posNoWhite:[43:42] Found expr:[43:11->43:43] -Pexp_apply ...[43:11->43:30] (~thirdThing43:32->43:42=...__ghost__[0:-1->0:-1]) -found typed context: namedArg:thirdThing -[] - Complete src/TypeContextCompletion_LabelledArguments.res 46:44 posCursor:[46:44] posNoWhite:[46:42] Found expr:[46:11->46:43] Pexp_apply ...[46:11->46:30] (~thirdThing46:32->46:42=...__ghost__[0:-1->0:-1]) found typed context: namedArg:thirdThing -[] +Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))="" +[{ + "label": "#one", + "kind": 4, + "tags": [], + "detail": "#one", + "documentation": null + }, { + "label": "#six(_)", + "kind": 4, + "tags": [], + "detail": "#six(option, int)", + "documentation": null + }, { + "label": "#three", + "kind": 4, + "tags": [], + "detail": "#three", + "documentation": null + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two", + "documentation": null + }, { + "label": "#five(_)", + "kind": 4, + "tags": [], + "detail": "#five(int)", + "documentation": null + }, { + "label": "#four", + "kind": 4, + "tags": [], + "detail": "#four", + "documentation": null + }, { + "label": "someVariantToString", + "kind": 12, + "tags": [], + "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", + "documentation": null + }, { + "label": "thisIsAValue", + "kind": 12, + "tags": [], + "detail": "someVariant", + "documentation": null + }] Complete src/TypeContextCompletion_LabelledArguments.res 49:45 posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:11->49:45] Pexp_apply ...[49:11->49:30] (~thirdThing49:32->49:42=...[49:43->49:45]) found typed context: namedArg:thirdThing posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:43->49:45] -[] +Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))=t +[{ + "label": "#three", + "kind": 4, + "tags": [], + "detail": "#three", + "documentation": null + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two", + "documentation": null + }, { + "label": "thisIsAValue", + "kind": 12, + "tags": [], + "detail": "someVariant", + "documentation": null + }] Complete src/TypeContextCompletion_LabelledArguments.res 52:45 posCursor:[52:45] posNoWhite:[52:44] Found expr:[52:11->52:45] Pexp_apply ...[52:11->52:30] (~thirdThing52:32->52:42=...[52:43->52:45]) found typed context: namedArg:thirdThing posCursor:[52:45] posNoWhite:[52:44] Found expr:[52:43->52:45] +Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))=T [] diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 0775358ca..1d6cc2a43 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -1,7 +1,7 @@ Complete src/TypeContextCompletion_Records.res 16:15 posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:7->16:16] posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:8->16:15] -Completable: CtypedContext(Value[someVal]) +Completable: CtypedContext(Value[someVal])=another [{ "label": "anotherThing", "kind": 5, @@ -13,7 +13,7 @@ Completable: CtypedContext(Value[someVal]) Complete src/TypeContextCompletion_Records.res 19:23 posCursor:[19:23] posNoWhite:[19:22] Found pattern:[19:7->19:24] posCursor:[19:23] posNoWhite:[19:22] Found pattern:[19:22->19:23] -Completable: CtypedContext(Value[someVal]) +Completable: CtypedContext(Value[someVal])=s [{ "label": "something", "kind": 5, @@ -24,7 +24,7 @@ Completable: CtypedContext(Value[someVal]) Complete src/TypeContextCompletion_Records.res 22:8 posCursor:[22:8] posNoWhite:[22:7] Found pattern:[22:7->22:9] -Completable: CtypedContext(Value[someVal]) +Completable: CtypedContext(Value[someVal])="" [{ "label": "something", "kind": 5, @@ -47,7 +47,7 @@ Completable: CtypedContext(Value[someVal]) Complete src/TypeContextCompletion_Records.res 31:8 posCursor:[31:8] posNoWhite:[31:7] Found pattern:[31:7->31:9] -Completable: CtypedContext(Value[getSomeVal](~irrelevant)) +Completable: CtypedContext(Value[getSomeVal](~irrelevant))="" [{ "label": "something", "kind": 5, @@ -71,7 +71,7 @@ Completable: CtypedContext(Value[getSomeVal](~irrelevant)) Complete src/TypeContextCompletion_Records.res 35:20 posCursor:[35:20] posNoWhite:[35:19] Found pattern:[35:7->35:22] posCursor:[35:20] posNoWhite:[35:19] Found pattern:[35:19->35:21] -Completable: CtypedContext(Value[someVal]) +Completable: CtypedContext(Value[someVal])="" [{ "label": "somethingElse", "kind": 5, @@ -96,7 +96,7 @@ Complete src/TypeContextCompletion_Records.res 38:47 posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:7->38:50] posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:19->38:49] posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:46->38:48] -Completable: CtypedContext(Value[someVal]) +Completable: CtypedContext(Value[someVal])="" [{ "label": "level", "kind": 5, @@ -116,7 +116,7 @@ posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:7->41:51] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:19->41:50] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:46->41:49] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:47->41:48] -Completable: CtypedContext(Value[someVal]) +Completable: CtypedContext(Value[someVal])=l [{ "label": "level", "kind": 5, @@ -128,7 +128,7 @@ Completable: CtypedContext(Value[someVal]) Complete src/TypeContextCompletion_Records.res 44:47 posCursor:[44:47] posNoWhite:[44:44] Found pattern:[44:7->44:49] posCursor:[44:47] posNoWhite:[44:44] Found pattern:[44:19->44:48] -Completable: CtypedContext(Value[someVal]) +Completable: CtypedContext(Value[someVal])="" [{ "label": "somethingElse", "kind": 5, @@ -140,7 +140,7 @@ Completable: CtypedContext(Value[someVal]) Complete src/TypeContextCompletion_Records.res 47:31 posCursor:[47:31] posNoWhite:[47:30] Found pattern:[47:7->47:47] posCursor:[47:31] posNoWhite:[47:30] Found pattern:[47:19->47:46] -Completable: CtypedContext(Value[someVal]) +Completable: CtypedContext(Value[someVal])="" [{ "label": "somethingElse", "kind": 5, From f9515d13a6a78b176c59e4b4a5bf28807f8d6d44 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 4 Aug 2022 20:03:12 +0200 Subject: [PATCH 41/80] cleanup and comments on where I'm at right now --- analysis/src/CompletionBackEnd.ml | 64 ++++++------------- analysis/src/CompletionFrontEnd.ml | 7 +- analysis/src/SharedTypes.ml | 1 + .../tests/src/expected/Completion.res.txt | 1 - analysis/tests/src/expected/Jsx.res.txt | 1 - 5 files changed, 25 insertions(+), 49 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index d505a4d09..4e8b2a0bd 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -897,6 +897,10 @@ let getItemsFromOpens ~opens ~localTables ~prefix ~exact ~completionContext = completionsFromThisOpen @ results) [] +(* This is a dedicated function for finding local completions for a specific type expr (as in filtered to match only the type expr). + Filtering is commented out for now though, since the strategy I used did not work out. + The idea here is that _values_ can be filtered on the type, but we still need to complete for modules just like we normally do, + to support using values from other modules. *) let findLocalCompletionsForTypeExpr ~(localTables : LocalTables.t) ~env ~prefix ~exact ~opens ~scope typeExpr = let _targetId = typeExpr.Types.id in @@ -1022,8 +1026,8 @@ let findLocalCompletionsWithOpens ~pos ~(env : QueryEnv.t) ~prefix ~exact ~opens (* There's no local completion for fields *) [] -let findLocalCompletionsForTypeExprL ~(env : QueryEnv.t) ~prefix ~exact ~opens - ~scope typeExpr = +let findLocalCompletionsForTypeExprWithOpens ~(env : QueryEnv.t) ~prefix ~exact + ~opens ~scope typeExpr = (* TODO: handle arbitrary interleaving of opens and local bindings correctly *) let localTables = LocalTables.create () in typeExpr @@ -1042,10 +1046,12 @@ let rec extractRecordType ~env ~package (t : Types.type_expr) = | _ -> None) | _ -> None +(* Had to add another type level here to cover that polyvariants are inlined into to the type system. Mostly a temporary solution. *) type extractedType = | Declared of QueryEnv.t * Type.t Declared.t | Polyvariant of QueryEnv.t * SharedTypes.polyVariantConstructor list +(* This is a more general extraction function for pulling out the type of a type_expr. We already have other similar functions, but they are all specialized on something (variants, records, etc). *) let rec extractType ~env ~package (t : Types.type_expr) = match t.desc with | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> extractType ~env ~package t1 @@ -1404,7 +1410,7 @@ let getOpens ~rawOpens ~package ~env = (* Last open takes priority *) List.rev resolvedOpens -(* Temporary while I figure things out *) +(* Temporary while I figure things out. This should be merged with the completable we already have. *) type completable = | CRecord of { fields: field list; @@ -1423,6 +1429,9 @@ let typeExprToCompletable typ ~env ~package = | Some (Polyvariant (_, constructors)) -> Some (CPolyVariant {constructors}) | _ -> None +(* Takes a type_expr and figures out what completable it corresponds to, if any. If the target type is nested somewhere inside of the type_expr, + nestedContextPath will be populated with instructions on how to reach that part. This is primarily used in patterns, + where the cursor can be deep into the pattern. *) let findTypeInContext (typ : Types.type_expr) ~env ~nestedContextPath ~package = let rec digToType (currentType : Types.type_expr) ~env ~nestedContextPath ~package = @@ -1499,45 +1508,8 @@ let getLabelsForComponent ~package ~opens ~allFiles ~pos ~env ~scope typ |> getLabels | None -> [] -(* This completes a type expression. Intended to be shared logic that can extract completions from a context, as soon as that the type is identified. *) -let completeTypeExpr ~env ~package ~debug ~prefix (typeExpr : Types.type_expr) = - match extractType ~env ~package typeExpr with - | None -> - if debug then Printf.printf "Could not extract type\n"; - [] - | Some (Declared (_env, {item})) -> ( - match item.kind with - | Variant constructors -> - if debug then - Printf.printf "Found variant type %s\n" (typeExpr |> Shared.typeToString); - constructors - |> List.filter (fun constructor -> - Utils.startsWith constructor.Constructor.cname.txt prefix) - |> List.map (fun (constructor : Constructor.t) -> - (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? - Eg. Some($1) as completion item. *) - Completion.create - ~name: - (constructor.cname.txt - ^ if constructor.args |> List.length > 0 then "(_)" else "") - ~kind:(Constructor (constructor, "")) - ~env) - | _ -> []) - | Some (Polyvariant (_env, constructors)) -> - if debug then - Printf.printf "Found polyvariant type %s\n" - (typeExpr |> Shared.typeToString); - constructors - |> List.filter (fun constructor -> Utils.startsWith constructor.name prefix) - |> List.map (fun constructor -> - (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? - Eg. Some($1) as completion item. *) - Completion.create - ~name: - ("#" ^ constructor.name - ^ if constructor.payload |> Option.is_some then "(_)" else "") - ~kind:(PolyvariantConstructor constructor) ~env) - +(* This pulls out the type we want to do type based completion based on, using an instruction. + This instruction can be "the type that the jsx prop X wants in component Y". *) let findSourceType sourceType ~package ~opens ~rawOpens ~allFiles ~env ~scope ~pos = match sourceType with @@ -1950,8 +1922,8 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i in let localCompletions = typ - |> findLocalCompletionsForTypeExprL ~env ~prefix ~exact:false ~opens - ~scope + |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix ~exact:false + ~opens ~scope in constructorCompletions @ localCompletions | Some (CVariant {constructors}) -> @@ -1972,8 +1944,8 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i in let localCompletions = typ - |> findLocalCompletionsForTypeExprL ~env ~prefix ~exact:false ~opens - ~scope + |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix ~exact:false + ~opens ~scope in constructorCompletions @ localCompletions | Some (CRecord {fields; decl; name}) -> diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index fed12f93f..eef4ca6bf 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -35,8 +35,10 @@ let getIdentFromExpr exp = | Pexp_field (_, {txt}) -> txt | _ -> Lident "" +(* This is probably wrong and we should likely use the full Longident instead for the prefix. *) let getPrefixFromExpr exp = getIdentFromExpr exp |> Longident.last +(* Extracted for reuse. *) let rec exprToContextPath (e : Parsetree.expression) = match e.pexp_desc with | Pexp_constant (Pconst_string _) -> Some Completable.CPString @@ -440,6 +442,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | Pstr_value (recFlag, bindings) -> if recFlag = Recursive then bindings |> List.iter scopeValueBinding; + (* This is an experiment and should most likely not live here in its final form. *) (* Check for: let {destructuringSomething} = someIdentifier *) (* Ensure cursor is inside of record pattern. *) (* TODO: Tuples, etc... *) @@ -988,7 +991,9 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = if !found = false then if debug then Printf.printf "XXX Not found!\n"; (* If nothing explicitly matched for completion, but we're still looking for a type - somewhere where the cursor is - complete for that. *) + somewhere where the cursor is - complete for that. + This is an experiment as is likely wrong/will trigger completion of the type + based value in a bunch of scenarios when it shouldn't. *) (match (!result, !currentlyLookingForType) with | None, Some lookingForType -> scope := !lastScopeBeforeCursor; diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 3a95c9ca2..780d99159 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -428,6 +428,7 @@ module Completable = struct | CPObj of contextPath * string | CPPipe of contextPath * string + (* How to move through a nested type context, like from a root record to the type of one of its fields, and beyond. *) (* TODO: Can extend to tuples, objects, etc *) type patternPathItem = | RField of {fieldName: string; alreadySeenFields: string list} diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index 602772eda..b6f288000 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -467,7 +467,6 @@ found typed context: jsxProp:second posCursor:[59:30] posNoWhite:[59:29] Found expr:[59:29->59:30] Pexp_ident z:[59:29->59:30] Completable: CtypedContext(JsxProp())=z -could not extract type [] Complete src/Completion.res 62:23 diff --git a/analysis/tests/src/expected/Jsx.res.txt b/analysis/tests/src/expected/Jsx.res.txt index 9bbac1c73..55562b1c6 100644 --- a/analysis/tests/src/expected/Jsx.res.txt +++ b/analysis/tests/src/expected/Jsx.res.txt @@ -10,7 +10,6 @@ found typed context: jsxProp:second posCursor:[8:15] posNoWhite:[8:14] Found expr:[8:13->8:15] Pexp_ident fi:[8:13->8:15] Completable: CtypedContext(JsxProp())=fi -could not extract type [] Complete src/Jsx.res 11:20 From a268d24d4bf7979349d5f9bb5cc80fccb81aa2a3 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 9 Aug 2022 14:10:31 +0200 Subject: [PATCH 42/80] narrow the places where type based completion is invoked --- analysis/src/CompletionFrontEnd.ml | 194 ++++++++---------- .../tests/src/expected/Completion.res.txt | 12 +- analysis/tests/src/expected/Jsx.res.txt | 25 ++- .../tests/src/expected/RecoveryOnProp.res.txt | 1 - .../TypeContextCompletion_Jsx.res.txt | 15 +- ...ontextCompletion_LabelledArguments.res.txt | 62 ++++-- 6 files changed, 154 insertions(+), 155 deletions(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index eef4ca6bf..0db849abe 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -35,6 +35,13 @@ let getIdentFromExpr exp = | Pexp_field (_, {txt}) -> txt | _ -> Lident "" +let canDoTypedCompletionOnExpr exp = + match exp.Parsetree.pexp_desc with + | Pexp_construct _ | Pexp_variant _ + | Pexp_extension ({txt = "rescript.exprhole"}, _) -> + true + | _ -> false + (* This is probably wrong and we should likely use the full Longident instead for the prefix. *) let getPrefixFromExpr exp = getIdentFromExpr exp |> Longident.last @@ -75,7 +82,7 @@ type jsxProps = { } let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName - ~setCurrentlyLookingForTypeOpt ~setTypedContextMeta = + = let allLabels = List.fold_right (fun prop allLabels -> prop.name :: allLabels) @@ -96,39 +103,49 @@ let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName && posBeforeCursor < Loc.start prop.exp.pexp_loc then (* Cursor between the prop name and expr assigned *) None - else if prop.exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then ( + else if prop.exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then (* Cursor on expr assigned *) - setCurrentlyLookingForTypeOpt - (Some - (Completable.JsxProp - { - componentPath = - Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; - propName = prop.name; - })); - setTypedContextMeta - { - Completable.prefix = Some (getPrefixFromExpr prop.exp); - alreadySeenIdents = None; - }; - None) - else if prop.exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then ( + if canDoTypedCompletionOnExpr prop.exp then + Some + (Completable.CtypedContext + { + howToRetrieveSourceType = + JsxProp + { + componentPath = + Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; + propName = prop.name; + }; + patternPath = None; + meta = + { + prefix = Some (getPrefixFromExpr prop.exp); + alreadySeenIdents = None; + }; + }) + else None + else if prop.exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then (* Expr assigned presumably is "rescript.exprhole" after parser recovery. Complete for the value. *) - setCurrentlyLookingForTypeOpt - (Some - (Completable.JsxProp - { - componentPath = - Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; - propName = prop.name; - })); - setTypedContextMeta - { - Completable.prefix = Some (getPrefixFromExpr prop.exp); - alreadySeenIdents = None; - }; - None) + if canDoTypedCompletionOnExpr prop.exp then + Some + (Completable.CtypedContext + { + howToRetrieveSourceType = + JsxProp + { + componentPath = + Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; + propName = prop.name; + }; + patternPath = None; + meta = + { + prefix = Some (getPrefixFromExpr prop.exp); + alreadySeenIdents = None; + }; + }) + else None else loop rest | [] -> let beforeChildrenStart = @@ -197,8 +214,7 @@ type label = labelled option type arg = {label: label; exp: Parsetree.expression} let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor - ~(contextPath : Completable.contextPath) ~posAfterFunExpr - ~setCurrentlyLookingForTypeOpt ~setTypedContextMeta = + ~(contextPath : Completable.contextPath) ~posAfterFunExpr = let allNames = List.fold_right (fun arg allLabels -> @@ -215,26 +231,38 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor labelled.posStart <= posBeforeCursor && posBeforeCursor < labelled.posEnd then Some (Completable.CnamedArg (contextPath, labelled.name, allNames)) - else if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then ( - setCurrentlyLookingForTypeOpt - (Some (Completable.NamedArg {contextPath; label = labelled.name})); - setTypedContextMeta - { - Completable.prefix = Some (getPrefixFromExpr exp); - alreadySeenIdents = None; - }; - None) - else if exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then ( + else if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then + if canDoTypedCompletionOnExpr exp then + Some + (Completable.CtypedContext + { + howToRetrieveSourceType = + Completable.NamedArg {contextPath; label = labelled.name}; + patternPath = None; + meta = + { + prefix = Some (getPrefixFromExpr exp); + alreadySeenIdents = None; + }; + }) + else None + else if exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then (* Expr assigned presumably is "rescript.exprhole" after parser recovery. Assume this is an empty expression. *) - setCurrentlyLookingForTypeOpt - (Some (NamedArg {contextPath; label = labelled.name})); - setTypedContextMeta - { - Completable.prefix = Some (getPrefixFromExpr exp); - alreadySeenIdents = None; - }; - None) + if canDoTypedCompletionOnExpr exp then + Some + (Completable.CtypedContext + { + howToRetrieveSourceType = + NamedArg {contextPath; label = labelled.name}; + patternPath = None; + meta = + { + prefix = Some (getPrefixFromExpr exp); + alreadySeenIdents = None; + }; + }) + else None else loop rest | {label = None; exp} :: rest -> if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then None @@ -338,25 +366,6 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | Some x -> result := Some (x, !scope) in let setResult x = setResultOpt (Some x) in - let typedContextMeta = - ref {Completable.prefix = None; alreadySeenIdents = None} - in - let setTypedContextMeta newValue = typedContextMeta := newValue in - let currentlyLookingForType = ref None in - let setCurrentlyLookingForTypeOpt x = - if !currentlyLookingForType = None then - match x with - | None -> if debug then Printf.printf "Typed context, unsetting\n" - | Some x -> - if debug then - Printf.printf "found typed context: %s\n" - (match x with - | Completable.JsxProp {propName} -> "jsxProp:" ^ propName - | NamedArg {label} -> "namedArg:" ^ label - | CtxPath contextPath -> - "ctxPath:" ^ Completable.contextPathToString contextPath); - currentlyLookingForType := Some x - in let scopeValueDescription (vd : Parsetree.value_description) = scope := !scope |> Scope.addValue ~name:vd.pval_name.txt ~loc:vd.pval_name.loc @@ -666,24 +675,15 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = setFound (); match expr.pexp_desc with | Pexp_constant _ -> setResult Cnone - | Pexp_ident lid -> ( + | Pexp_ident lid -> let lidPath = flattenLidCheckDot lid in if debug then Printf.printf "Pexp_ident %s:%s\n" (lidPath |> String.concat ".") (Loc.toString lid.loc); if lid.loc |> Loc.hasPos ~pos:posBeforeCursor then - match !currentlyLookingForType with - | Some lookingForType -> - setResult - (CtypedContext - { - howToRetrieveSourceType = lookingForType; - patternPath = None; - meta = !typedContextMeta; - }) - | _ -> setResult (Cpath (CPId (lidPath, Value)))) - | Pexp_construct (lid, eOpt) -> ( + setResult (Cpath (CPId (lidPath, Value))) + | Pexp_construct (lid, eOpt) -> let lidPath = flattenLidCheckDot lid in if debug then Printf.printf "Pexp_construct %s:%s %s\n" @@ -695,17 +695,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = if eOpt = None && (not lid.loc.loc_ghost) && lid.loc |> Loc.hasPos ~pos:posBeforeCursor - then - match !currentlyLookingForType with - | Some lookingForType -> - setResult - (CtypedContext - { - howToRetrieveSourceType = lookingForType; - patternPath = None; - meta = !typedContextMeta; - }) - | _ -> setResult (Cpath (CPId (lidPath, Value)))) + then setResult (Cpath (CPId (lidPath, Value))) | Pexp_field (e, fieldName) -> ( if debug then Printf.printf "Pexp_field %s %s:%s\n" (Loc.toString e.pexp_loc) @@ -755,7 +745,6 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = let jsxCompletable = findJsxPropsCompletable ~jsxProps ~endPos:(Loc.end_ expr.pexp_loc) ~posBeforeCursor ~posAfterCompName:(Loc.end_ compName.loc) - ~setCurrentlyLookingForTypeOpt ~setTypedContextMeta in if jsxCompletable <> None then setResultOpt jsxCompletable else if compName.loc |> Loc.hasPos ~pos:posBeforeCursor then @@ -806,7 +795,6 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = findNamedArgCompletable ~contextPath ~args ~endPos:(Loc.end_ expr.pexp_loc) ~posBeforeCursor ~posAfterFunExpr:(Loc.end_ funExpr.pexp_loc) - ~setCurrentlyLookingForTypeOpt ~setTypedContextMeta | None -> None in @@ -989,22 +977,6 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = scope := !lastScopeBeforeCursor; setResult (Cpath (CPId ([""], Value)))); if !found = false then if debug then Printf.printf "XXX Not found!\n"; - - (* If nothing explicitly matched for completion, but we're still looking for a type - somewhere where the cursor is - complete for that. - This is an experiment as is likely wrong/will trigger completion of the type - based value in a bunch of scenarios when it shouldn't. *) - (match (!result, !currentlyLookingForType) with - | None, Some lookingForType -> - scope := !lastScopeBeforeCursor; - setResult - (Completable.CtypedContext - { - howToRetrieveSourceType = lookingForType; - patternPath = None; - meta = !typedContextMeta; - }) - | _ -> ()); !result) else if Filename.check_suffix path ".resi" then ( let parser = Res_driver.parsingEngine.parseInterface ~forPrinter:false in diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index b6f288000..12dcf751e 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -463,11 +463,16 @@ Completable: Cpath Value[Js, Dict, u] Complete src/Completion.res 59:30 posCursor:[59:30] posNoWhite:[59:29] Found expr:[59:15->59:30] JSX 59:21] second[59:22->59:28]=...[59:29->59:30]> _children:None -found typed context: jsxProp:second posCursor:[59:30] posNoWhite:[59:29] Found expr:[59:29->59:30] Pexp_ident z:[59:29->59:30] -Completable: CtypedContext(JsxProp())=z -[] +Completable: Cpath Value[z] +[{ + "label": "zzz", + "kind": 12, + "tags": [], + "detail": "int", + "documentation": null + }] Complete src/Completion.res 62:23 posCursor:[62:23] posNoWhite:[62:22] Found expr:[62:15->62:23] @@ -1300,7 +1305,6 @@ Found type for function (~a: int) => int Complete src/Completion.res 336:26 posCursor:[336:26] posNoWhite:[336:25] Found expr:[333:3->346:23] JSX 333:6] onClick[334:4->334:11]=...[334:13->346:23]> _children:None -found typed context: jsxProp:onClick posCursor:[336:26] posNoWhite:[336:25] Found expr:[334:13->346:23] posCursor:[336:26] posNoWhite:[336:25] Found expr:[334:13->338:6] posCursor:[336:26] posNoWhite:[336:25] Found expr:[335:6->338:5] diff --git a/analysis/tests/src/expected/Jsx.res.txt b/analysis/tests/src/expected/Jsx.res.txt index 55562b1c6..8e2f1569c 100644 --- a/analysis/tests/src/expected/Jsx.res.txt +++ b/analysis/tests/src/expected/Jsx.res.txt @@ -6,10 +6,9 @@ the type is not great but jump to definition works Complete src/Jsx.res 8:15 posCursor:[8:15] posNoWhite:[8:14] Found expr:[8:4->8:15] JSX 8:5] second[8:6->8:12]=...[8:13->8:15]> _children:None -found typed context: jsxProp:second posCursor:[8:15] posNoWhite:[8:14] Found expr:[8:13->8:15] Pexp_ident fi:[8:13->8:15] -Completable: CtypedContext(JsxProp())=fi +Completable: Cpath Value[fi] [] Complete src/Jsx.res 11:20 @@ -355,20 +354,30 @@ Completable: Cpath Module[DefineSomeFields].th Complete src/Jsx.res 122:20 posCursor:[122:20] posNoWhite:[122:19] Found expr:[121:3->125:4] JSX 121:6] x[122:5->122:6]=...[122:7->122:20] name[124:4->124:8]=...[124:9->124:11]> _children:125:2 -found typed context: jsxProp:x posCursor:[122:20] posNoWhite:[122:19] Found expr:[122:7->122:20] Pexp_ident Outer.Inner.h:[122:7->122:20] -Completable: CtypedContext(JsxProp(
))=h -[] +Completable: Cpath Value[Outer, Inner, h] +[{ + "label": "hello", + "kind": 12, + "tags": [], + "detail": "int", + "documentation": null + }] Complete src/Jsx.res 129:19 posCursor:[129:19] posNoWhite:[129:18] Found expr:[128:3->131:9] JSX 128:6] x[129:5->129:6]=...[129:7->131:8]> _children:None -found typed context: jsxProp:x posCursor:[129:19] posNoWhite:[129:18] Found expr:[129:7->131:8] Pexp_ident Outer.Inner.:[129:7->131:8] -Completable: CtypedContext(JsxProp(
))=name -[] +Completable: Cpath Value[Outer, Inner, ""] +[{ + "label": "hello", + "kind": 12, + "tags": [], + "detail": "int", + "documentation": null + }] Complete src/Jsx.res 136:7 posCursor:[136:7] posNoWhite:[136:6] Found expr:[135:3->138:9] diff --git a/analysis/tests/src/expected/RecoveryOnProp.res.txt b/analysis/tests/src/expected/RecoveryOnProp.res.txt index 336f4212e..fe509d768 100644 --- a/analysis/tests/src/expected/RecoveryOnProp.res.txt +++ b/analysis/tests/src/expected/RecoveryOnProp.res.txt @@ -1,7 +1,6 @@ Complete src/RecoveryOnProp.res 6:26 posCursor:[6:26] posNoWhite:[6:25] Found expr:[3:3->11:8] JSX 3:6] onClick[4:4->4:11]=...[4:13->0:-1]> _children:None -found typed context: jsxProp:onClick posCursor:[6:26] posNoWhite:[6:25] Found expr:[4:13->8:6] posCursor:[6:26] posNoWhite:[6:25] Found expr:[5:6->8:5] posCursor:[6:26] posNoWhite:[6:25] Found expr:[6:16->8:5] diff --git a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt index eb71f79d4..2dc03adb0 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt @@ -13,7 +13,6 @@ Completable: Cjsx([SomeComponent], someVaria, [someVaria]) Complete src/TypeContextCompletion_Jsx.res 23:38 posCursor:[23:38] posNoWhite:[23:37] Found expr:[23:12->23:38] JSX 23:25] someVariant[23:26->23:37]=...__ghost__[0:-1->0:-1]> _children:None -found typed context: jsxProp:someVariant Completable: CtypedContext(JsxProp())="" [{ "label": "One", @@ -68,7 +67,6 @@ Completable: CtypedContext(JsxProp())="" Complete src/TypeContextCompletion_Jsx.res 26:39 posCursor:[26:39] posNoWhite:[26:37] Found expr:[26:12->26:38] JSX 26:25] someVariant[26:26->26:37]=...__ghost__[0:-1->0:-1]> _children:None -found typed context: jsxProp:someVariant Completable: CtypedContext(JsxProp())="" [{ "label": "One", @@ -123,9 +121,6 @@ Completable: CtypedContext(JsxProp())="" Complete src/TypeContextCompletion_Jsx.res 29:39 posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:12->29:39] JSX 29:25] someVariant[29:26->29:37]=...[29:38->29:39]> _children:None -found typed context: jsxProp:someVariant -posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:38->29:39] -Pexp_construct T:[29:38->29:39] None Completable: CtypedContext(JsxProp())=T [{ "label": "Two", @@ -144,16 +139,14 @@ Completable: CtypedContext(JsxProp())=T Complete src/TypeContextCompletion_Jsx.res 32:39 posCursor:[32:39] posNoWhite:[32:38] Found expr:[32:12->32:39] JSX 32:25] someVariant[32:26->32:37]=...[32:38->32:39]> _children:None -found typed context: jsxProp:someVariant posCursor:[32:39] posNoWhite:[32:38] Found expr:[32:38->32:39] Pexp_ident t:[32:38->32:39] -Completable: CtypedContext(JsxProp())=t +Completable: Cpath Value[t] [] Complete src/TypeContextCompletion_Jsx.res 35:39 posCursor:[35:39] posNoWhite:[35:38] Found expr:[35:12->35:39] JSX 35:25] anotherThing[35:26->35:38]=...__ghost__[0:-1->0:-1]> _children:None -found typed context: jsxProp:anotherThing Completable: CtypedContext(JsxProp())="" [{ "label": "Foo", @@ -184,7 +177,6 @@ Completable: CtypedContext(JsxProp())="" Complete src/TypeContextCompletion_Jsx.res 38:37 posCursor:[38:37] posNoWhite:[38:36] Found expr:[38:12->38:37] JSX 38:25] thirdThing[38:26->38:36]=...__ghost__[0:-1->0:-1]> _children:None -found typed context: jsxProp:thirdThing Completable: CtypedContext(JsxProp())="" [{ "label": "#one", @@ -239,7 +231,6 @@ Completable: CtypedContext(JsxProp())="" Complete src/TypeContextCompletion_Jsx.res 41:38 posCursor:[41:38] posNoWhite:[41:36] Found expr:[41:12->41:37] JSX 41:25] thirdThing[41:26->41:36]=...__ghost__[0:-1->0:-1]> _children:None -found typed context: jsxProp:thirdThing Completable: CtypedContext(JsxProp())="" [{ "label": "#one", @@ -294,8 +285,6 @@ Completable: CtypedContext(JsxProp())="" Complete src/TypeContextCompletion_Jsx.res 44:39 posCursor:[44:39] posNoWhite:[44:38] Found expr:[44:12->44:39] JSX 44:25] thirdThing[44:26->44:36]=...[44:37->44:39]> _children:None -found typed context: jsxProp:thirdThing -posCursor:[44:39] posNoWhite:[44:38] Found expr:[44:37->44:39] Completable: CtypedContext(JsxProp())=t [{ "label": "#three", @@ -314,8 +303,6 @@ Completable: CtypedContext(JsxProp())=t Complete src/TypeContextCompletion_Jsx.res 47:39 posCursor:[47:39] posNoWhite:[47:38] Found expr:[47:12->47:39] JSX 47:25] thirdThing[47:26->47:36]=...[47:37->47:39]> _children:None -found typed context: jsxProp:thirdThing -posCursor:[47:39] posNoWhite:[47:38] Found expr:[47:37->47:39] Completable: CtypedContext(JsxProp())=T [] diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index 7a6f8f2b7..2e2582bf8 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -18,7 +18,6 @@ Found type for function ( Complete src/TypeContextCompletion_LabelledArguments.res 25:44 posCursor:[25:44] posNoWhite:[25:43] Found expr:[25:11->25:44] Pexp_apply ...[25:11->25:30] (~someVariant25:32->25:43=...__ghost__[0:-1->0:-1]) -found typed context: namedArg:someVariant Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))="" [{ "label": "One", @@ -73,7 +72,6 @@ Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))="" Complete src/TypeContextCompletion_LabelledArguments.res 28:45 posCursor:[28:45] posNoWhite:[28:43] Found expr:[28:11->28:44] Pexp_apply ...[28:11->28:30] (~someVariant28:32->28:43=...__ghost__[0:-1->0:-1]) -found typed context: namedArg:someVariant Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))="" [{ "label": "One", @@ -128,9 +126,6 @@ Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))="" Complete src/TypeContextCompletion_LabelledArguments.res 31:45 posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:11->31:45] Pexp_apply ...[31:11->31:30] (~someVariant31:32->31:43=...[31:44->31:45]) -found typed context: namedArg:someVariant -posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:44->31:45] -Pexp_construct T:[31:44->31:45] None Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))=T [{ "label": "Two", @@ -149,10 +144,9 @@ Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))=T Complete src/TypeContextCompletion_LabelledArguments.res 34:45 posCursor:[34:45] posNoWhite:[34:44] Found expr:[34:11->34:45] Pexp_apply ...[34:11->34:30] (~someVariant34:32->34:43=...[34:44->34:45]) -found typed context: namedArg:someVariant posCursor:[34:45] posNoWhite:[34:44] Found expr:[34:44->34:45] Pexp_ident t:[34:44->34:45] -Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))=t +Completable: Cpath Value[t] [{ "label": "thisIsAValue", "kind": 12, @@ -164,16 +158,56 @@ Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))=t Complete src/TypeContextCompletion_LabelledArguments.res 37:59 posCursor:[37:59] posNoWhite:[37:58] Found expr:[37:11->37:59] Pexp_apply ...[37:11->37:30] (~someVariant37:32->37:43=...[37:44->37:59]) -found typed context: namedArg:someVariant posCursor:[37:59] posNoWhite:[37:58] Found expr:[37:44->37:59] Pexp_ident TypeDefinition.:[37:44->37:59] -Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))=_ -[] +Completable: Cpath Value[TypeDefinition, ""] +[{ + "label": "g", + "kind": 12, + "tags": [], + "detail": "variant => string", + "documentation": null + }, { + "label": "x", + "kind": 12, + "tags": [], + "detail": "variant", + "documentation": null + }, { + "label": "y", + "kind": 12, + "tags": [], + "detail": "record", + "documentation": null + }, { + "label": "obj", + "kind": 12, + "tags": [], + "detail": "obj", + "documentation": null + }, { + "label": "f", + "kind": 12, + "tags": [], + "detail": "record => string", + "documentation": null + }, { + "label": "Foo", + "kind": 4, + "tags": [], + "detail": "Foo\n\ntype variant = Foo | Bar", + "documentation": null + }, { + "label": "Bar", + "kind": 4, + "tags": [], + "detail": "Bar\n\ntype variant = Foo | Bar", + "documentation": null + }] Complete src/TypeContextCompletion_LabelledArguments.res 40:45 posCursor:[40:45] posNoWhite:[40:44] Found expr:[40:11->40:45] Pexp_apply ...[40:11->40:30] (~anotherThing40:32->40:44=...__ghost__[0:-1->0:-1]) -found typed context: namedArg:anotherThing Completable: CtypedContext(NamedArg(anotherThing, Value[someVariantToString]))="" [{ "label": "Foo", @@ -204,7 +238,6 @@ Completable: CtypedContext(NamedArg(anotherThing, Value[someVariantToString]))=" Complete src/TypeContextCompletion_LabelledArguments.res 43:43 posCursor:[43:43] posNoWhite:[43:42] Found expr:[43:11->43:43] Pexp_apply ...[43:11->43:30] (~thirdThing43:32->43:42=...__ghost__[0:-1->0:-1]) -found typed context: namedArg:thirdThing Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))="" [{ "label": "#one", @@ -259,7 +292,6 @@ Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))="" Complete src/TypeContextCompletion_LabelledArguments.res 46:44 posCursor:[46:44] posNoWhite:[46:42] Found expr:[46:11->46:43] Pexp_apply ...[46:11->46:30] (~thirdThing46:32->46:42=...__ghost__[0:-1->0:-1]) -found typed context: namedArg:thirdThing Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))="" [{ "label": "#one", @@ -314,8 +346,6 @@ Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))="" Complete src/TypeContextCompletion_LabelledArguments.res 49:45 posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:11->49:45] Pexp_apply ...[49:11->49:30] (~thirdThing49:32->49:42=...[49:43->49:45]) -found typed context: namedArg:thirdThing -posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:43->49:45] Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))=t [{ "label": "#three", @@ -340,8 +370,6 @@ Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))=t Complete src/TypeContextCompletion_LabelledArguments.res 52:45 posCursor:[52:45] posNoWhite:[52:44] Found expr:[52:11->52:45] Pexp_apply ...[52:11->52:30] (~thirdThing52:32->52:42=...[52:43->52:45]) -found typed context: namedArg:thirdThing -posCursor:[52:45] posNoWhite:[52:44] Found expr:[52:43->52:45] Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))=T [] From 9f511cd108273a526c0969effb313a2f11647ff7 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 9 Aug 2022 15:02:46 +0200 Subject: [PATCH 43/80] complete record field destructuring in switch patterns --- analysis/src/CompletionFrontEnd.ml | 208 ++++++++++-------- .../src/TypeContextCompletion_Records.res | 9 + .../TypeContextCompletion_Records.res.txt | 50 +++++ 3 files changed, 179 insertions(+), 88 deletions(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 0db849abe..e0ae427c0 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -311,6 +311,101 @@ let rec getSimpleFieldName txt = | Ldot (t, _) -> getSimpleFieldName t | _ -> "" +let rec findNestedContextPath ~path ~posBeforeCursor ~prefix + ~firstCharBeforeCursorNoWhite fields = + (* This will descend through the record, following where the cursor is located, + to pull out a nested context we can use to figure out what type + we should complete from. *) + fields + |> List.find_map (fun ({Location.txt}, {Parsetree.ppat_loc; ppat_desc}) -> + if ppat_loc |> Loc.hasPos ~pos:posBeforeCursor then + (* Covers when we're still inside the cursor position - continue descending + and build the nested context appropriately. *) + match ppat_desc with + | Ppat_record (fields, _) -> + if List.length fields = 0 then + (* Empty records are fine to complete from *) + Some + ([ + Completable.RField + { + fieldName = getSimpleFieldName txt; + alreadySeenFields = []; + }; + ] + @ path) + else + fields + |> findNestedContextPath ~posBeforeCursor ~prefix + ~firstCharBeforeCursorNoWhite + ~path: + ([ + Completable.RField + { + fieldName = getSimpleFieldName txt; + alreadySeenFields = + fields + |> List.map (fun ({Location.txt}, _) -> + getSimpleFieldName txt); + }; + ] + @ path) + | Ppat_var {txt} -> + (* Whenever we encounter a var, that means we've hit an identifier the user has started typing. + We can then use that as the prefix hint for what to filter completions on. *) + prefix := txt; + Some path + | _ -> + (* This can be extended to understand more nested contexts, like tuples, etc. *) + Some path + else if ppat_loc |> Loc.end_ = (Location.none |> Loc.end_) then + (* This means that an empty location was found, which typically means that the parser has made + recovery here. Complete wherever we are. *) + Some path + else + match firstCharBeforeCursorNoWhite with + | Some ',' -> Some path + | _ -> None) + +let findPrefixAndNestedContextPath fields ~posBeforeCursor + ~firstCharBeforeCursorNoWhite = + let prefix = ref "" in + + ( !prefix, + match List.length fields with + | 0 -> + (* A root record with 0 fields, `let {} = someVar`, is still valid to complete from. But it has no nested context. *) + Some [] + | _ -> + fields + |> findNestedContextPath ~path:[] ~posBeforeCursor ~prefix + ~firstCharBeforeCursorNoWhite ) + +let completeRecordDestructure fields ~contextPath ~posBeforeCursor + ~firstCharBeforeCursorNoWhite = + let prefix, nestedContextPath = + fields + |> findPrefixAndNestedContextPath ~posBeforeCursor + ~firstCharBeforeCursorNoWhite + in + match (contextPath, nestedContextPath) with + | Some contextPath, Some nestedContextPath -> + Some + (Completable.CtypedContext + { + howToRetrieveSourceType = CtxPath contextPath; + patternPath = Some (nestedContextPath |> List.rev); + meta = + { + prefix = Some prefix; + alreadySeenIdents = + (match nestedContextPath with + | RField {alreadySeenFields} :: _rest -> Some alreadySeenFields + | _ -> None); + }; + }) + | _ -> None + let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = let offsetNoWhite = skipWhite text (offset - 1) in let posNoWhite = @@ -458,98 +553,15 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = (* TODO: Handle let {SomeModule.recordField} = ...*) (match bindings with | [{pvb_pat = {ppat_desc = Ppat_record (fields, _)}; pvb_expr = expr}] - when !result = None -> ( + when !result = None -> (* The contextPath is what we'll use to look up the root record type for this completion. Depending on if the destructure is nested or not, we may or may not use that directly.*) let contextPath = exprToContextPath expr in - let prefix, nestedContextPath = - let prefix = ref "" in - let rec findNestedContextPath ~path fields = - (* This will descend through the record, following where the cursor is located, - to pull out a nested context we can use to figure out what type - we should complete from. *) - fields - |> List.find_map - (fun ({Location.txt}, {Parsetree.ppat_loc; ppat_desc}) -> - if ppat_loc |> Loc.hasPos ~pos:posBeforeCursor then - (* Covers when we're still inside the cursor position - continue descending - and build the nested context appropriately. *) - match ppat_desc with - | Ppat_record (fields, _) -> - if List.length fields = 0 then - (* Empty records are fine to complete from *) - Some - ([ - Completable.RField - { - fieldName = getSimpleFieldName txt; - alreadySeenFields = []; - }; - ] - @ path) - else - fields - |> findNestedContextPath - ~path: - ([ - Completable.RField - { - fieldName = getSimpleFieldName txt; - alreadySeenFields = - fields - |> List.map (fun ({Location.txt}, _) -> - getSimpleFieldName txt); - }; - ] - @ path) - | Ppat_var {txt} -> - (* Whenever we encounter a var, that means we've hit an identifier the user has started typing. - We can then use that as the prefix hint for what to filter completions on. *) - prefix := txt; - Some path - | _ -> - (* This can be extended to understand more nested contexts, like tuples, etc. *) - Some path - else if ppat_loc |> Loc.end_ = (Location.none |> Loc.end_) - then - (* This means that an empty location was found, which typically means that the parser has made - recovery here. Complete wherever we are. *) - Some path - else - match firstCharBeforeCursorNoWhite with - | Some ',' -> Some path - | _ -> None) - in - - ( !prefix, - match List.length fields with - | 0 -> - (* A root record with 0 fields, `let {} = someVar`, is still valid to complete from. But it has no nested context. *) - Some [] - | _ -> fields |> findNestedContextPath ~path:[] ) - in - - match (contextPath, nestedContextPath) with - | Some contextPath, Some nestedContextPath -> - setResultOpt - (Some - (Completable.CtypedContext - { - howToRetrieveSourceType = CtxPath contextPath; - patternPath = Some (nestedContextPath |> List.rev); - meta = - { - prefix = Some prefix; - alreadySeenIdents = - (match nestedContextPath with - | RField {alreadySeenFields} :: _rest -> - Some alreadySeenFields - | _ -> None); - }; - })) - | _ -> ()) + setResultOpt + (fields + |> completeRecordDestructure ~contextPath ~posBeforeCursor + ~firstCharBeforeCursorNoWhite) | _ -> ()); - bindings |> List.iter (fun vb -> iterator.value_binding iterator vb); if recFlag = Nonrecursive then bindings |> List.iter scopeValueBinding; processed := true @@ -858,6 +870,26 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = iterator.expr iterator e; scope := oldScope; processed := true + | Pexp_match (expr, cases) -> + (* Completes switch case destructuring *) + let rec findCaseWithCursor cases = + match cases with + | case :: cases -> ( + match case with + | { + Parsetree.pc_lhs = + {ppat_loc; ppat_desc = Ppat_record (fields, _)}; + } + when ppat_loc |> Loc.hasPos ~pos:posBeforeCursor -> + let contextPath = exprToContextPath expr in + setResultOpt + (fields + |> completeRecordDestructure ~contextPath ~posBeforeCursor + ~firstCharBeforeCursorNoWhite) + | _ -> findCaseWithCursor cases) + | [] -> () + in + findCaseWithCursor cases | _ -> ()); if not !processed then Ast_iterator.default_iterator.expr iterator expr in diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index be07215f4..65a925c22 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -47,3 +47,12 @@ let getSomeVal = (~irrelevant: int) => { // let {something: {whatIsThis, ,anotherLevel}} = someVal // ^com + +// switch someVal { | {thirdThing: "123", som} => () } +// ^com + +// switch someVal { | {thirdThing: "1234"} => () | {} => () } +// ^com + +// switch someVal { | {thirdThing: "1234"} => () | {something: {whatIsThis, anotherLevel, }} => () } +// ^com diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 1d6cc2a43..d3befabd3 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -149,3 +149,53 @@ Completable: CtypedContext(Value[someVal])="" "documentation": null }] +Complete src/TypeContextCompletion_Records.res 50:44 +posCursor:[50:44] posNoWhite:[50:43] Found expr:[50:3->50:54] +posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:22->50:46] +posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:42->50:45] +Completable: CtypedContext(Value[someVal])=som +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }] + +Complete src/TypeContextCompletion_Records.res 53:52 +posCursor:[53:52] posNoWhite:[53:51] Found expr:[53:3->53:61] +posCursor:[53:52] posNoWhite:[53:51] Found pattern:[53:51->53:53] +Completable: CtypedContext(Value[someVal])="" +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { + "label": "anotherThing", + "kind": 5, + "tags": [], + "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }, { + "label": "thirdThing", + "kind": 5, + "tags": [], + "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }] + +Complete src/TypeContextCompletion_Records.res 56:89 +posCursor:[56:89] posNoWhite:[56:88] Found expr:[56:3->56:100] +posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:51->56:92] +posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:63->56:91] +Completable: CtypedContext(Value[someVal])="" +[{ + "label": "somethingElse", + "kind": 5, + "tags": [], + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null + }] + From ef427d2302ddb5415199b6080b827c9d37152813 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 9 Aug 2022 15:03:01 +0200 Subject: [PATCH 44/80] comment --- analysis/src/CompletionFrontEnd.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index e0ae427c0..990c69fec 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -871,7 +871,8 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = scope := oldScope; processed := true | Pexp_match (expr, cases) -> - (* Completes switch case destructuring *) + (* Completes switch case destructuring + Example: switch someIdentifier { | {completeRecordFieldsHere} => ...}*) let rec findCaseWithCursor cases = match cases with | case :: cases -> ( From 555110f52d9560026550fe99cdaf13a97b1d406b Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Wed, 10 Aug 2022 08:53:25 +0200 Subject: [PATCH 45/80] wip --- analysis/src/CompletionBackEnd.ml | 32 ++- analysis/src/CompletionFrontEnd.ml | 254 +++++++++++++----- analysis/src/SharedTypes.ml | 36 ++- analysis/src/Utils.ml | 16 ++ .../src/TypeContextCompletion_Records.res | 28 ++ analysis/tests/src/expected/Dce.res.txt | 2 +- .../TypeContextCompletion_Jsx.res.txt | 4 + ...ontextCompletion_LabelledArguments.res.txt | 4 + .../TypeContextCompletion_Records.res.txt | 189 +++++++++---- 9 files changed, 426 insertions(+), 139 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 4e8b2a0bd..4b7aad1de 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1050,17 +1050,22 @@ let rec extractRecordType ~env ~package (t : Types.type_expr) = type extractedType = | Declared of QueryEnv.t * Type.t Declared.t | Polyvariant of QueryEnv.t * SharedTypes.polyVariantConstructor list + | Tuple of QueryEnv.t * Types.type_expr list + | Toption of QueryEnv.t * Types.type_expr (* This is a more general extraction function for pulling out the type of a type_expr. We already have other similar functions, but they are all specialized on something (variants, records, etc). *) let rec extractType ~env ~package (t : Types.type_expr) = match t.desc with | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> extractType ~env ~package t1 + | Tconstr (Path.Pident {name = "option"}, [payloadTypeExpr], _) -> + (* Handle option *) + Some (Toption (env, payloadTypeExpr)) | Tconstr (path, _, _) -> ( match References.digConstructor ~env ~package path with | Some (env, {item = {decl = {type_manifest = Some t1}}}) -> extractType ~env ~package t1 | Some (env, typ) -> Some (Declared (env, typ)) - | _ -> None) + | None -> None) | Tvariant {row_fields} -> (* Since polyvariants are strutural, they're "inlined". So, we extract just what we need for completion from that definition here. *) @@ -1076,6 +1081,7 @@ let rec extractType ~env ~package (t : Types.type_expr) = }) in Some (Polyvariant (env, constructors)) + | Ttuple expressions -> Some (Tuple (env, expressions)) | _ -> None let rec extractObjectType ~env ~package (t : Types.type_expr) = @@ -1452,6 +1458,29 @@ let findTypeInContext (typ : Types.type_expr) ~env ~nestedContextPath ~package = if List.length nestedContextPath > 0 then targetField.typ |> digToType ~env ~nestedContextPath ~package else typeExprToCompletable targetField.typ ~env ~package) + | ( Variant {name}, + Some (Declared (_, {item = {kind = Variant constructors}})) ) -> ( + match + constructors + |> List.find_opt (fun constructor -> + constructor.Constructor.cname.txt = name) + with + | Some _ -> Some (CVariant {constructors}) + | None -> None) + | Polyvariant {name}, Some (Polyvariant (_, constructors)) -> ( + match + constructors + |> List.find_opt (fun constructor -> constructor.name = name) + with + | Some _ -> Some (CPolyVariant {constructors}) + | None -> None) + | PTuple {itemNumber}, Some (Tuple (_, exprs)) -> ( + match List.nth_opt exprs itemNumber with + | None -> None + | Some typeExpr -> + typeExpr |> digToType ~env ~nestedContextPath ~package) + | Variant {name = "Some"}, Some (Toption (_, typeExpr)) -> + typeExpr |> digToType ~env ~nestedContextPath ~package | _ -> None) in typ |> digToType ~env ~nestedContextPath ~package @@ -1927,6 +1956,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i in constructorCompletions @ localCompletions | Some (CVariant {constructors}) -> + if debug then Printf.printf "found variant: %s\n" prefix; let constructorCompletions = constructors |> List.filter (fun constructor -> diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 990c69fec..1cfc358b0 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -312,81 +312,193 @@ let rec getSimpleFieldName txt = | _ -> "" let rec findNestedContextPath ~path ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite fields = - (* This will descend through the record, following where the cursor is located, - to pull out a nested context we can use to figure out what type - we should complete from. *) - fields - |> List.find_map (fun ({Location.txt}, {Parsetree.ppat_loc; ppat_desc}) -> - if ppat_loc |> Loc.hasPos ~pos:posBeforeCursor then - (* Covers when we're still inside the cursor position - continue descending - and build the nested context appropriately. *) - match ppat_desc with - | Ppat_record (fields, _) -> - if List.length fields = 0 then - (* Empty records are fine to complete from *) - Some - ([ - Completable.RField - { - fieldName = getSimpleFieldName txt; - alreadySeenFields = []; - }; - ] - @ path) - else - fields + ~firstCharBeforeCursorNoWhite pattern = + match pattern.Parsetree.ppat_desc with + | Ppat_record (fields, _) -> + (* This will descend through the record, following where the cursor is located, + to pull out a nested context we can use to figure out what type + we should complete from. *) + fields + |> List.find_map + (fun ({Location.txt}, ({Parsetree.ppat_loc; ppat_desc} as pat)) -> + if ppat_loc |> Loc.hasPos ~pos:posBeforeCursor then + (* Covers when we're still inside the cursor position - continue descending + and build the nested context appropriately. *) + match ppat_desc with + | Ppat_record (fields, _) -> + if List.length fields = 0 then + (* Empty records are fine to complete from *) + Some + ([ + Completable.RField + { + fieldName = getSimpleFieldName txt; + alreadySeenFields = []; + }; + ] + @ path) + else + pat + |> findNestedContextPath ~posBeforeCursor ~prefix + ~firstCharBeforeCursorNoWhite + ~path: + ([ + Completable.RField + { + fieldName = getSimpleFieldName txt; + alreadySeenFields = + fields + |> List.map (fun ({Location.txt}, _) -> + getSimpleFieldName txt); + }; + ] + @ path) + | Ppat_var {txt} -> + (* Whenever we encounter a var, that means we've hit an identifier the user has started typing. + We can then use that as the prefix hint for what to filter completions on. *) + prefix := txt; + Some path + | Ppat_construct ({txt}, None) -> + let name = getSimpleFieldName txt in + prefix := name; + Some ([Completable.Variant {name}] @ path) + | Ppat_construct ({txt}, Some pat) -> + let name = getSimpleFieldName txt in + pat |> findNestedContextPath ~posBeforeCursor ~prefix ~firstCharBeforeCursorNoWhite - ~path: - ([ - Completable.RField - { - fieldName = getSimpleFieldName txt; - alreadySeenFields = - fields - |> List.map (fun ({Location.txt}, _) -> - getSimpleFieldName txt); - }; - ] - @ path) - | Ppat_var {txt} -> - (* Whenever we encounter a var, that means we've hit an identifier the user has started typing. - We can then use that as the prefix hint for what to filter completions on. *) - prefix := txt; - Some path - | _ -> - (* This can be extended to understand more nested contexts, like tuples, etc. *) + ~path:([Completable.Variant {name}] @ path) + | _ -> + (* This can be extended to understand more nested contexts, like tuples, etc. *) + None + else if ppat_loc |> Loc.end_ = (Location.none |> Loc.end_) then + (* This means that an empty location was found, which typically means that the parser has made + recovery here. Complete wherever we are. *) Some path - else if ppat_loc |> Loc.end_ = (Location.none |> Loc.end_) then - (* This means that an empty location was found, which typically means that the parser has made - recovery here. Complete wherever we are. *) - Some path - else - match firstCharBeforeCursorNoWhite with - | Some ',' -> Some path - | _ -> None) + else + match firstCharBeforeCursorNoWhite with + | Some ',' -> Some path + | _ -> None) + | _ -> None + +let rec whatevs pattern ~path ~posBeforeCursor ~prefix + ~firstCharBeforeCursorNoWhite = + match + pattern.Parsetree.ppat_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + with + | NoCursor | EmptyLoc -> None + | HasCursor -> ( + match pattern.ppat_desc with + | Ppat_construct ({txt = Lident "()"}, None) -> + (* A constructor without a payload mean we've reached an end. *) + prefix := ""; + Some path + | Ppat_construct ({txt}, None) -> + (* A constructor without a payload mean we've reached an end. *) + prefix := getSimpleFieldName txt; + Some path + | Ppat_construct ({txt}, Some constructorPayload) -> + constructorPayload + |> whatevs + ~path:([Completable.Variant {name = getSimpleFieldName txt}] @ path) + ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~prefix + | Ppat_variant (label, None) -> + (* A constructor without a payload mean we've reached an end. *) + prefix := label; + Some path + | Ppat_variant (label, Some constructorPayload) -> + constructorPayload + |> whatevs + ~path:([Completable.Variant {name = label}] @ path) + ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~prefix + | Ppat_tuple patterns -> ( + let tupleItemNum = ref 0 in + let patternWithCursor = + patterns + |> List.find_map (fun pat -> + let currentItemNum = !tupleItemNum in + tupleItemNum := !tupleItemNum + 1; + match + pat.Parsetree.ppat_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + with + | HasCursor | EmptyLoc -> Some (currentItemNum, pat) + | NoCursor -> None) + in + match patternWithCursor with + | None -> None + | Some (tupleItemNum, pat) -> + pat + |> whatevs ~posBeforeCursor ~prefix ~firstCharBeforeCursorNoWhite + ~path:([Completable.PTuple {itemNumber = tupleItemNum}] @ path)) + | Ppat_record (fields, _) when List.length fields = 0 -> Some path + | Ppat_record (fields, _) -> ( + let fieldWithCursor = + fields + |> List.find_map (fun (loc, pat) -> + match + pat.Parsetree.ppat_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + with + | NoCursor -> None + | HasCursor | EmptyLoc -> Some (loc, pat)) + in + match fieldWithCursor with + | None -> None + | Some (loc, pat) -> + let fieldName = getSimpleFieldName loc.txt in + pat + |> whatevs ~posBeforeCursor ~prefix ~firstCharBeforeCursorNoWhite + ~path: + ([ + Completable.RField + { + fieldName; + alreadySeenFields = + fields + |> List.map (fun ({Location.txt}, _) -> + getSimpleFieldName txt) + |> List.filter (fun name -> name <> fieldName); + }; + ] + @ path)) + | Ppat_var {txt} -> + prefix := txt; + Some path + | _ -> None) -let findPrefixAndNestedContextPath fields ~posBeforeCursor +let findPrefixAndNestedContextPath pattern ~posBeforeCursor ~firstCharBeforeCursorNoWhite = let prefix = ref "" in - ( !prefix, - match List.length fields with - | 0 -> + let nestedContextPath = + match pattern.Parsetree.ppat_desc with + | Ppat_record (fields, _) when List.length fields = 0 -> (* A root record with 0 fields, `let {} = someVar`, is still valid to complete from. But it has no nested context. *) Some [] | _ -> - fields - |> findNestedContextPath ~path:[] ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite ) + pattern + |> whatevs ~path:[] ~posBeforeCursor ~prefix ~firstCharBeforeCursorNoWhite + in -let completeRecordDestructure fields ~contextPath ~posBeforeCursor + (!prefix, nestedContextPath) + +let completePattern pattern ~contextPath ~posBeforeCursor ~firstCharBeforeCursorNoWhite = - let prefix, nestedContextPath = - fields - |> findPrefixAndNestedContextPath ~posBeforeCursor - ~firstCharBeforeCursorNoWhite + let prefix = ref "" in + let nestedContextPath = + match pattern.Parsetree.ppat_desc with + | Ppat_record (fields, _) -> ( + match List.length fields with + | 0 -> + (* A root record with 0 fields, `let {} = someVar`, is still valid to complete from. But it has no nested context. *) + Some [] + | _ -> + pattern + |> whatevs ~path:[] ~posBeforeCursor ~prefix + ~firstCharBeforeCursorNoWhite) + | _ -> None in match (contextPath, nestedContextPath) with | Some contextPath, Some nestedContextPath -> @@ -397,7 +509,7 @@ let completeRecordDestructure fields ~contextPath ~posBeforeCursor patternPath = Some (nestedContextPath |> List.rev); meta = { - prefix = Some prefix; + prefix = Some !prefix; alreadySeenIdents = (match nestedContextPath with | RField {alreadySeenFields} :: _rest -> Some alreadySeenFields @@ -552,14 +664,13 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = (* TODO: Tuples, etc... *) (* TODO: Handle let {SomeModule.recordField} = ...*) (match bindings with - | [{pvb_pat = {ppat_desc = Ppat_record (fields, _)}; pvb_expr = expr}] - when !result = None -> + | [{pvb_pat; pvb_expr = expr}] when !result = None -> (* The contextPath is what we'll use to look up the root record type for this completion. Depending on if the destructure is nested or not, we may or may not use that directly.*) let contextPath = exprToContextPath expr in setResultOpt - (fields - |> completeRecordDestructure ~contextPath ~posBeforeCursor + (pvb_pat + |> completePattern ~contextPath ~posBeforeCursor ~firstCharBeforeCursorNoWhite) | _ -> ()); bindings |> List.iter (fun vb -> iterator.value_binding iterator vb); @@ -878,14 +989,13 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | case :: cases -> ( match case with | { - Parsetree.pc_lhs = - {ppat_loc; ppat_desc = Ppat_record (fields, _)}; + Parsetree.pc_lhs = {ppat_loc; ppat_desc = Ppat_record _} as pat; } when ppat_loc |> Loc.hasPos ~pos:posBeforeCursor -> let contextPath = exprToContextPath expr in setResultOpt - (fields - |> completeRecordDestructure ~contextPath ~posBeforeCursor + (pat + |> completePattern ~contextPath ~posBeforeCursor ~firstCharBeforeCursorNoWhite) | _ -> findCaseWithCursor cases) | [] -> () diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 780d99159..ce47ccf77 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -432,18 +432,24 @@ module Completable = struct (* TODO: Can extend to tuples, objects, etc *) type patternPathItem = | RField of {fieldName: string; alreadySeenFields: string list} + | Variant of {name: string} + | Polyvariant of {name: string} + | PTuple of {itemNumber: int} let str s = if s = "" then "\"\"" else s let list l = "[" ^ (l |> List.map str |> String.concat ", ") ^ "]" let ident l = l |> List.map str |> String.concat "." + let pathItemToString item = + match item with + | RField {fieldName; alreadySeenFields} -> + "RecordField:" ^ fieldName ^ ":" ^ list alreadySeenFields + | Variant {name} -> "Variant:" ^ name + | Polyvariant {name} -> "Polyvariant:" ^ name + | PTuple {itemNumber} -> "Tuple:" ^ string_of_int itemNumber + let recordFieldContextPathToString pathItems = - pathItems - |> List.map (fun item -> - match item with - | RField {fieldName; alreadySeenFields} -> - fieldName ^ ":" ^ list alreadySeenFields) - |> list + pathItems |> List.map (fun item -> pathItemToString item) |> list let completionContextToString = function | Value -> "Value" @@ -526,12 +532,26 @@ module Completable = struct | Cnone -> "Cnone" | Cjsx (sl1, s, sl2) -> "Cjsx(" ^ (sl1 |> list) ^ ", " ^ str s ^ ", " ^ (sl2 |> list) ^ ")" - | CtypedContext {howToRetrieveSourceType; meta = {prefix}} -> ( - "CtypedContext(" + | CtypedContext {howToRetrieveSourceType; meta = {prefix}; patternPath} -> ( + ("CtypedContext(" ^ (howToRetrieveSourceType |> howToRetrieveSourceTypeToString) ^ ")=" ^ match prefix with | None -> "" | Some prefix -> str prefix) + ^ + match patternPath with + | None -> "" + | Some patternPath -> + " pattern: " ^ (patternPath |> recordFieldContextPathToString)) end + +module CursorPosition = struct + type t = NoCursor | HasCursor | EmptyLoc + + let classifyLoc loc ~pos = + if loc |> Loc.hasPos ~pos then HasCursor + else if loc |> Loc.end_ = (Location.none |> Loc.end_) then EmptyLoc + else NoCursor +end \ No newline at end of file diff --git a/analysis/src/Utils.ml b/analysis/src/Utils.ml index 3c31dfbf0..ff4299c7b 100644 --- a/analysis/src/Utils.ml +++ b/analysis/src/Utils.ml @@ -131,3 +131,19 @@ let identifyPpat pat = | Ppat_exception _ -> "Ppat_exception" | Ppat_extension _ -> "Ppat_extension" | Ppat_open _ -> "Ppat_open" + +let identifyType type_desc = + match type_desc with + | Types.Tvar _ -> "Tvar" + | Tarrow _ -> "Tarrow" + | Ttuple _ -> "Ttuple" + | Tconstr _ -> "Tconstr" + | Tobject _ -> "Tobject" + | Tfield _ -> "Tfield" + | Tnil -> "Tnil" + | Tlink _ -> "Tlink" + | Tsubst _ -> "Tsubst" + | Tvariant _ -> "Tvariant" + | Tunivar _ -> "Tunivar" + | Tpoly _ -> "Tpoly" + | Tpackage _ -> "Tpackage" diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index 65a925c22..58942af83 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -56,3 +56,31 @@ let getSomeVal = (~irrelevant: int) => { // switch someVal { | {thirdThing: "1234"} => () | {something: {whatIsThis, anotherLevel, }} => () } // ^com + +type someOtherVariant = TwentyFive | SixtyTwo +type rec someVariant = One | Two | Three(int) | Four(someOtherVariant) + +type someRecordWithVariant = { + other: someRecord, + something: someVariant, + otherThing: option, + thirdStuff: (someRecord, someVariant, option, int), +} + +let someOtherValue: someRecordWithVariant = { + other: someVal.something, + something: Two, + otherThing: None, + thirdStuff: (someVal.something, One, None, 1), +} +// switch someOtherValue { | {something: T} => () } +// ^com + +// switch someOtherValue { | {otherThing: Some(T)} => () } +// ^com + +// switch someOtherValue { | {thirdStuff: (_, T)} => () } +// ^com + +// switch someOtherValue { | {thirdStuff: (_, Four())} => () } +// ^com diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index 472868779..8d1e7f441 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:275 +issues:282 diff --git a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt index 2dc03adb0..31c75b95f 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt @@ -14,6 +14,7 @@ Complete src/TypeContextCompletion_Jsx.res 23:38 posCursor:[23:38] posNoWhite:[23:37] Found expr:[23:12->23:38] JSX 23:25] someVariant[23:26->23:37]=...__ghost__[0:-1->0:-1]> _children:None Completable: CtypedContext(JsxProp())="" +found variant: [{ "label": "One", "kind": 4, @@ -68,6 +69,7 @@ Complete src/TypeContextCompletion_Jsx.res 26:39 posCursor:[26:39] posNoWhite:[26:37] Found expr:[26:12->26:38] JSX 26:25] someVariant[26:26->26:37]=...__ghost__[0:-1->0:-1]> _children:None Completable: CtypedContext(JsxProp())="" +found variant: [{ "label": "One", "kind": 4, @@ -122,6 +124,7 @@ Complete src/TypeContextCompletion_Jsx.res 29:39 posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:12->29:39] JSX 29:25] someVariant[29:26->29:37]=...[29:38->29:39]> _children:None Completable: CtypedContext(JsxProp())=T +found variant: T [{ "label": "Two", "kind": 4, @@ -148,6 +151,7 @@ Complete src/TypeContextCompletion_Jsx.res 35:39 posCursor:[35:39] posNoWhite:[35:38] Found expr:[35:12->35:39] JSX 35:25] anotherThing[35:26->35:38]=...__ghost__[0:-1->0:-1]> _children:None Completable: CtypedContext(JsxProp())="" +found variant: [{ "label": "Foo", "kind": 4, diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index 2e2582bf8..b9d93edb2 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -19,6 +19,7 @@ Complete src/TypeContextCompletion_LabelledArguments.res 25:44 posCursor:[25:44] posNoWhite:[25:43] Found expr:[25:11->25:44] Pexp_apply ...[25:11->25:30] (~someVariant25:32->25:43=...__ghost__[0:-1->0:-1]) Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))="" +found variant: [{ "label": "One", "kind": 4, @@ -73,6 +74,7 @@ Complete src/TypeContextCompletion_LabelledArguments.res 28:45 posCursor:[28:45] posNoWhite:[28:43] Found expr:[28:11->28:44] Pexp_apply ...[28:11->28:30] (~someVariant28:32->28:43=...__ghost__[0:-1->0:-1]) Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))="" +found variant: [{ "label": "One", "kind": 4, @@ -127,6 +129,7 @@ Complete src/TypeContextCompletion_LabelledArguments.res 31:45 posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:11->31:45] Pexp_apply ...[31:11->31:30] (~someVariant31:32->31:43=...[31:44->31:45]) Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))=T +found variant: T [{ "label": "Two", "kind": 4, @@ -209,6 +212,7 @@ Complete src/TypeContextCompletion_LabelledArguments.res 40:45 posCursor:[40:45] posNoWhite:[40:44] Found expr:[40:11->40:45] Pexp_apply ...[40:11->40:30] (~anotherThing40:32->40:44=...__ghost__[0:-1->0:-1]) Completable: CtypedContext(NamedArg(anotherThing, Value[someVariantToString]))="" +found variant: [{ "label": "Foo", "kind": 4, diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index d3befabd3..260bd8954 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -1,30 +1,18 @@ Complete src/TypeContextCompletion_Records.res 16:15 posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:7->16:16] posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:8->16:15] -Completable: CtypedContext(Value[someVal])=another -[{ - "label": "anotherThing", - "kind": 5, - "tags": [], - "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }] +Completable: CtypedContext(Value[someVal])=another pattern: [RecordField:another:[]] +[] Complete src/TypeContextCompletion_Records.res 19:23 posCursor:[19:23] posNoWhite:[19:22] Found pattern:[19:7->19:24] posCursor:[19:23] posNoWhite:[19:22] Found pattern:[19:22->19:23] -Completable: CtypedContext(Value[someVal])=s -[{ - "label": "something", - "kind": 5, - "tags": [], - "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }] +Completable: CtypedContext(Value[someVal])=s pattern: [RecordField:s:[anotherThing]] +[] Complete src/TypeContextCompletion_Records.res 22:8 posCursor:[22:8] posNoWhite:[22:7] Found pattern:[22:7->22:9] -Completable: CtypedContext(Value[someVal])="" +Completable: CtypedContext(Value[someVal])="" pattern: [] [{ "label": "something", "kind": 5, @@ -47,7 +35,7 @@ Completable: CtypedContext(Value[someVal])="" Complete src/TypeContextCompletion_Records.res 31:8 posCursor:[31:8] posNoWhite:[31:7] Found pattern:[31:7->31:9] -Completable: CtypedContext(Value[getSomeVal](~irrelevant))="" +Completable: CtypedContext(Value[getSomeVal](~irrelevant))="" pattern: [] [{ "label": "something", "kind": 5, @@ -71,7 +59,7 @@ Completable: CtypedContext(Value[getSomeVal](~irrelevant))="" Complete src/TypeContextCompletion_Records.res 35:20 posCursor:[35:20] posNoWhite:[35:19] Found pattern:[35:7->35:22] posCursor:[35:20] posNoWhite:[35:19] Found pattern:[35:19->35:21] -Completable: CtypedContext(Value[someVal])="" +Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something:[]] [{ "label": "somethingElse", "kind": 5, @@ -96,7 +84,7 @@ Complete src/TypeContextCompletion_Records.res 38:47 posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:7->38:50] posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:19->38:49] posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:46->38:48] -Completable: CtypedContext(Value[someVal])="" +Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something:[], RecordField:anotherLevel:[whatIsThis]] [{ "label": "level", "kind": 5, @@ -116,56 +104,30 @@ posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:7->41:51] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:19->41:50] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:46->41:49] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:47->41:48] -Completable: CtypedContext(Value[someVal])=l -[{ - "label": "level", - "kind": 5, - "tags": [], - "detail": "level: int\n\ntype anotherLevel = {level: int, someOtherArg: bool}", - "documentation": null - }] +Completable: CtypedContext(Value[someVal])=l pattern: [RecordField:something:[], RecordField:anotherLevel:[whatIsThis], RecordField:l:[]] +[] Complete src/TypeContextCompletion_Records.res 44:47 posCursor:[44:47] posNoWhite:[44:44] Found pattern:[44:7->44:49] posCursor:[44:47] posNoWhite:[44:44] Found pattern:[44:19->44:48] -Completable: CtypedContext(Value[someVal])="" -[{ - "label": "somethingElse", - "kind": 5, - "tags": [], - "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", - "documentation": null - }] +[] Complete src/TypeContextCompletion_Records.res 47:31 posCursor:[47:31] posNoWhite:[47:30] Found pattern:[47:7->47:47] posCursor:[47:31] posNoWhite:[47:30] Found pattern:[47:19->47:46] -Completable: CtypedContext(Value[someVal])="" -[{ - "label": "somethingElse", - "kind": 5, - "tags": [], - "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", - "documentation": null - }] +[] Complete src/TypeContextCompletion_Records.res 50:44 posCursor:[50:44] posNoWhite:[50:43] Found expr:[50:3->50:54] posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:22->50:46] posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:42->50:45] -Completable: CtypedContext(Value[someVal])=som -[{ - "label": "something", - "kind": 5, - "tags": [], - "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }] +Completable: CtypedContext(Value[someVal])=som pattern: [RecordField:som:[thirdThing]] +[] Complete src/TypeContextCompletion_Records.res 53:52 posCursor:[53:52] posNoWhite:[53:51] Found expr:[53:3->53:61] posCursor:[53:52] posNoWhite:[53:51] Found pattern:[53:51->53:53] -Completable: CtypedContext(Value[someVal])="" +Completable: CtypedContext(Value[someVal])="" pattern: [] [{ "label": "something", "kind": 5, @@ -190,12 +152,125 @@ Complete src/TypeContextCompletion_Records.res 56:89 posCursor:[56:89] posNoWhite:[56:88] Found expr:[56:3->56:100] posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:51->56:92] posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:63->56:91] -Completable: CtypedContext(Value[someVal])="" +[] + +Complete src/TypeContextCompletion_Records.res 75:42 +posCursor:[75:42] posNoWhite:[75:41] Found expr:[75:3->75:51] +posCursor:[75:42] posNoWhite:[75:41] Found pattern:[75:29->75:43] +posCursor:[75:42] posNoWhite:[75:41] Found pattern:[75:41->75:42] +Ppat_construct T:[75:41->75:42] +Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:something:[]] +found variant: T [{ - "label": "somethingElse", - "kind": 5, + "label": "Two", + "kind": 4, "tags": [], - "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three(_)", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null + }] + +Complete src/TypeContextCompletion_Records.res 78:48 +posCursor:[78:48] posNoWhite:[78:47] Found expr:[78:3->78:58] +posCursor:[78:48] posNoWhite:[78:47] Found pattern:[78:29->78:50] +posCursor:[78:48] posNoWhite:[78:47] Found pattern:[78:42->78:49] +Ppat_construct Some:[78:42->78:46] +posCursor:[78:48] posNoWhite:[78:47] Found pattern:[78:47->78:48] +Ppat_construct T:[78:47->78:48] +Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:otherThing:[], Variant:Some] +found variant: T +[{ + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three(_)", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null + }] + +Complete src/TypeContextCompletion_Records.res 81:47 +posCursor:[81:47] posNoWhite:[81:46] Found expr:[81:3->81:57] +posCursor:[81:47] posNoWhite:[81:46] Found pattern:[81:29->81:49] +posCursor:[81:47] posNoWhite:[81:46] Found pattern:[81:42->81:48] +posCursor:[81:47] posNoWhite:[81:46] Found pattern:[81:46->81:47] +Ppat_construct T:[81:46->81:47] +Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:thirdStuff:[], Tuple:1] +found variant: T +[{ + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three(_)", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null + }] + +Complete src/TypeContextCompletion_Records.res 84:51 +posCursor:[84:51] posNoWhite:[84:50] Found expr:[84:3->84:62] +posCursor:[84:51] posNoWhite:[84:50] Found pattern:[84:29->84:54] +posCursor:[84:51] posNoWhite:[84:50] Found pattern:[84:42->84:53] +posCursor:[84:51] posNoWhite:[84:50] Found pattern:[84:46->84:52] +Ppat_construct Four:[84:46->84:50] +posCursor:[84:51] posNoWhite:[84:50] Found pattern:[84:50->84:52] +Ppat_construct ():[84:50->84:52] +Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:thirdStuff:[], Tuple:1, Variant:Four] +found variant: +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Three(_)", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null + }, { + "label": "Four(_)", + "kind": 4, + "tags": [], + "detail": "Four(someOtherVariant)\n\n", + "documentation": null + }, { + "label": "someOtherValue", + "kind": 12, + "tags": [], + "detail": "someRecordWithVariant", + "documentation": null + }, { + "label": "getSomeVal", + "kind": 12, + "tags": [], + "detail": "(~irrelevant: int) => anotherRecord", + "documentation": null + }, { + "label": "someVal", + "kind": 12, + "tags": [], + "detail": "anotherRecord", "documentation": null }] From cf8b472cbe1e357048f0f3155662465e6f2484b0 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Wed, 10 Aug 2022 13:28:49 +0200 Subject: [PATCH 46/80] more work on nested completion in patterns --- analysis/src/CompletionBackEnd.ml | 37 +++++- analysis/src/CompletionFrontEnd.ml | 125 +++++++----------- analysis/src/SharedTypes.ml | 24 +++- .../src/TypeContextCompletion_Records.res | 11 +- analysis/tests/src/expected/Dce.res.txt | 2 +- .../TypeContextCompletion_Records.res.txt | 114 ++++++++++------ 6 files changed, 176 insertions(+), 137 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 4b7aad1de..f9ce3a565 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1078,6 +1078,14 @@ let rec extractType ~env ~package (t : Types.type_expr) = (match field with | Types.Rpresent maybeTypeExpr -> maybeTypeExpr | _ -> None); + args = + (* Multiple arguments are represented as a Ttuple, while a single argument is just the type expression itself. *) + (match field with + | Types.Rpresent (Some typeExpr) -> ( + match typeExpr.desc with + | Ttuple args -> args + | _ -> [typeExpr]) + | _ -> []); }) in Some (Polyvariant (env, constructors)) @@ -1458,21 +1466,38 @@ let findTypeInContext (typ : Types.type_expr) ~env ~nestedContextPath ~package = if List.length nestedContextPath > 0 then targetField.typ |> digToType ~env ~nestedContextPath ~package else typeExprToCompletable targetField.typ ~env ~package) - | ( Variant {name}, + | ( Variant {name; payloadNum}, Some (Declared (_, {item = {kind = Variant constructors}})) ) -> ( match constructors |> List.find_opt (fun constructor -> constructor.Constructor.cname.txt = name) with - | Some _ -> Some (CVariant {constructors}) + | Some constructor -> ( + (* payloadNum tells us whether there's also a payload we should descend into. *) + match payloadNum with + | None -> Some (CVariant {constructors}) + | Some argNum -> ( + (* If we find the argument/payload requested, descend into that *) + match List.nth_opt constructor.args argNum with + | None -> None + | Some (argType, _) -> + argType |> digToType ~env ~nestedContextPath ~package)) | None -> None) - | Polyvariant {name}, Some (Polyvariant (_, constructors)) -> ( + | Polyvariant {name; payloadNum}, Some (Polyvariant (_, constructors)) + -> ( match constructors |> List.find_opt (fun constructor -> constructor.name = name) with - | Some _ -> Some (CPolyVariant {constructors}) + | Some constructor -> ( + match payloadNum with + | None -> Some (CPolyVariant {constructors}) + | Some argNum -> ( + match List.nth_opt constructor.args argNum with + | None -> None + | Some argType -> + argType |> digToType ~env ~nestedContextPath ~package)) | None -> None) | PTuple {itemNumber}, Some (Tuple (_, exprs)) -> ( match List.nth_opt exprs itemNumber with @@ -1920,8 +1945,8 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i | Some prefix -> prefix in let sourceType = - findSourceType howToRetrieveSourceType ~package ~opens ~rawOpens ~allFiles - ~env ~pos ~scope + howToRetrieveSourceType + |> findSourceType ~package ~opens ~rawOpens ~allFiles ~env ~pos ~scope in let nestedContextPath = match patternPath with diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 1cfc358b0..5e6e1eea5 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -311,75 +311,19 @@ let rec getSimpleFieldName txt = | Ldot (t, _) -> getSimpleFieldName t | _ -> "" -let rec findNestedContextPath ~path ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite pattern = - match pattern.Parsetree.ppat_desc with - | Ppat_record (fields, _) -> - (* This will descend through the record, following where the cursor is located, - to pull out a nested context we can use to figure out what type - we should complete from. *) - fields - |> List.find_map - (fun ({Location.txt}, ({Parsetree.ppat_loc; ppat_desc} as pat)) -> - if ppat_loc |> Loc.hasPos ~pos:posBeforeCursor then - (* Covers when we're still inside the cursor position - continue descending - and build the nested context appropriately. *) - match ppat_desc with - | Ppat_record (fields, _) -> - if List.length fields = 0 then - (* Empty records are fine to complete from *) - Some - ([ - Completable.RField - { - fieldName = getSimpleFieldName txt; - alreadySeenFields = []; - }; - ] - @ path) - else - pat - |> findNestedContextPath ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite - ~path: - ([ - Completable.RField - { - fieldName = getSimpleFieldName txt; - alreadySeenFields = - fields - |> List.map (fun ({Location.txt}, _) -> - getSimpleFieldName txt); - }; - ] - @ path) - | Ppat_var {txt} -> - (* Whenever we encounter a var, that means we've hit an identifier the user has started typing. - We can then use that as the prefix hint for what to filter completions on. *) - prefix := txt; - Some path - | Ppat_construct ({txt}, None) -> - let name = getSimpleFieldName txt in - prefix := name; - Some ([Completable.Variant {name}] @ path) - | Ppat_construct ({txt}, Some pat) -> - let name = getSimpleFieldName txt in - pat - |> findNestedContextPath ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite - ~path:([Completable.Variant {name}] @ path) - | _ -> - (* This can be extended to understand more nested contexts, like tuples, etc. *) - None - else if ppat_loc |> Loc.end_ = (Location.none |> Loc.end_) then - (* This means that an empty location was found, which typically means that the parser has made - recovery here. Complete wherever we are. *) - Some path - else - match firstCharBeforeCursorNoWhite with - | Some ',' -> Some path - | _ -> None) - | _ -> None +(* Variants can have payloads. We need to figure out which of the payloads we're in, so we can find the type at that position as we try to do completion. + We also need to continue descending into the pattern of the argument under the cursor to find any inner type. *) +let findVariantPayloadItemNumWithCursor pat ~pos = + match pat.Parsetree.ppat_desc with + | Ppat_tuple patterns -> + let res = ref None in + patterns + |> List.iteri (fun index pat -> + match pat.Parsetree.ppat_loc |> CursorPosition.classifyLoc ~pos with + | HasCursor -> res := Some (index, pat) + | _ -> ()); + !res + | _ -> Some (0, pat) let rec whatevs pattern ~path ~posBeforeCursor ~prefix ~firstCharBeforeCursorNoWhite = @@ -391,27 +335,48 @@ let rec whatevs pattern ~path ~posBeforeCursor ~prefix | HasCursor -> ( match pattern.ppat_desc with | Ppat_construct ({txt = Lident "()"}, None) -> - (* A constructor without a payload mean we've reached an end. *) + (* A constructor without a payload mean we've reached an end. The parser parses SomeVariant() like above. *) prefix := ""; Some path | Ppat_construct ({txt}, None) -> (* A constructor without a payload mean we've reached an end. *) prefix := getSimpleFieldName txt; Some path - | Ppat_construct ({txt}, Some constructorPayload) -> - constructorPayload - |> whatevs - ~path:([Completable.Variant {name = getSimpleFieldName txt}] @ path) - ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~prefix + | Ppat_construct ({txt}, Some constructorPayload) -> ( + match + findVariantPayloadItemNumWithCursor constructorPayload + ~pos:posBeforeCursor + with + | None -> None + | Some (index, pat) -> + pat + |> whatevs + ~path: + ([ + Completable.Variant + {name = getSimpleFieldName txt; payloadNum = Some index}; + ] + @ path) + ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~prefix) | Ppat_variant (label, None) -> (* A constructor without a payload mean we've reached an end. *) prefix := label; Some path - | Ppat_variant (label, Some constructorPayload) -> - constructorPayload - |> whatevs - ~path:([Completable.Variant {name = label}] @ path) - ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~prefix + | Ppat_variant (label, Some constructorPayload) -> ( + match + findVariantPayloadItemNumWithCursor constructorPayload + ~pos:posBeforeCursor + with + | None -> None + | Some (index, pat) -> + pat + |> whatevs + ~path: + ([ + Completable.Polyvariant {name = label; payloadNum = Some index}; + ] + @ path) + ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~prefix) | Ppat_tuple patterns -> ( let tupleItemNum = ref 0 in let patternWithCursor = diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index ce47ccf77..b6cb470b5 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -216,7 +216,11 @@ module QueryEnv = struct let fromFile file = {file; exported = file.structure.exported} end -type polyVariantConstructor = {name: string; payload: Types.type_expr option} +type polyVariantConstructor = { + name: string; + payload: Types.type_expr option; + args: Types.type_expr list; +} module Completion = struct type kind = @@ -432,8 +436,8 @@ module Completable = struct (* TODO: Can extend to tuples, objects, etc *) type patternPathItem = | RField of {fieldName: string; alreadySeenFields: string list} - | Variant of {name: string} - | Polyvariant of {name: string} + | Variant of {name: string; payloadNum: int option} + | Polyvariant of {name: string; payloadNum: int option} | PTuple of {itemNumber: int} let str s = if s = "" then "\"\"" else s @@ -444,8 +448,18 @@ module Completable = struct match item with | RField {fieldName; alreadySeenFields} -> "RecordField:" ^ fieldName ^ ":" ^ list alreadySeenFields - | Variant {name} -> "Variant:" ^ name - | Polyvariant {name} -> "Polyvariant:" ^ name + | Variant {name; payloadNum} -> ( + "Variant:" ^ name + ^ + match payloadNum with + | None -> "" + | Some payloadNum -> "(" ^ string_of_int payloadNum ^ ")") + | Polyvariant {name; payloadNum} -> ( + "Polyvariant:" ^ name + ^ + match payloadNum with + | None -> "" + | Some payloadNum -> "(" ^ string_of_int payloadNum ^ ")") | PTuple {itemNumber} -> "Tuple:" ^ string_of_int itemNumber let recordFieldContextPathToString pathItems = diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index 58942af83..9a1af6ef6 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -58,13 +58,15 @@ let getSomeVal = (~irrelevant: int) => { // ^com type someOtherVariant = TwentyFive | SixtyTwo -type rec someVariant = One | Two | Three(int) | Four(someOtherVariant) +type rec someVariant = + One | Two | Three(int) | Four(someOtherVariant) | Five(someOtherVariant, someVariant) type someRecordWithVariant = { other: someRecord, something: someVariant, otherThing: option, thirdStuff: (someRecord, someVariant, option, int), + fourthStuff: (option<[#WithPayload(someVariant)]>, someVariant), } let someOtherValue: someRecordWithVariant = { @@ -72,6 +74,7 @@ let someOtherValue: someRecordWithVariant = { something: Two, otherThing: None, thirdStuff: (someVal.something, One, None, 1), + fourthStuff: (None, One), } // switch someOtherValue { | {something: T} => () } // ^com @@ -84,3 +87,9 @@ let someOtherValue: someRecordWithVariant = { // switch someOtherValue { | {thirdStuff: (_, Four())} => () } // ^com + +// switch someOtherValue { | {thirdStuff: (_, Five(_, O))} => () } +// ^com + +// switch someOtherValue { | {fourthStuff: (Some(#WithPayload(O)), _)} => () } +// ^com diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index 8d1e7f441..052abba9a 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:282 +issues:284 diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 260bd8954..c2a744ce3 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -154,11 +154,11 @@ posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:51->56:92] posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:63->56:91] [] -Complete src/TypeContextCompletion_Records.res 75:42 -posCursor:[75:42] posNoWhite:[75:41] Found expr:[75:3->75:51] -posCursor:[75:42] posNoWhite:[75:41] Found pattern:[75:29->75:43] -posCursor:[75:42] posNoWhite:[75:41] Found pattern:[75:41->75:42] -Ppat_construct T:[75:41->75:42] +Complete src/TypeContextCompletion_Records.res 78:42 +posCursor:[78:42] posNoWhite:[78:41] Found expr:[78:3->78:51] +posCursor:[78:42] posNoWhite:[78:41] Found pattern:[78:29->78:43] +posCursor:[78:42] posNoWhite:[78:41] Found pattern:[78:41->78:42] +Ppat_construct T:[78:41->78:42] Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:something:[]] found variant: T [{ @@ -175,14 +175,14 @@ found variant: T "documentation": null }] -Complete src/TypeContextCompletion_Records.res 78:48 -posCursor:[78:48] posNoWhite:[78:47] Found expr:[78:3->78:58] -posCursor:[78:48] posNoWhite:[78:47] Found pattern:[78:29->78:50] -posCursor:[78:48] posNoWhite:[78:47] Found pattern:[78:42->78:49] -Ppat_construct Some:[78:42->78:46] -posCursor:[78:48] posNoWhite:[78:47] Found pattern:[78:47->78:48] -Ppat_construct T:[78:47->78:48] -Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:otherThing:[], Variant:Some] +Complete src/TypeContextCompletion_Records.res 81:48 +posCursor:[81:48] posNoWhite:[81:47] Found expr:[81:3->81:58] +posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:29->81:50] +posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:42->81:49] +Ppat_construct Some:[81:42->81:46] +posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:47->81:48] +Ppat_construct T:[81:47->81:48] +Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:otherThing:[], Variant:Some(0)] found variant: T [{ "label": "Two", @@ -198,12 +198,12 @@ found variant: T "documentation": null }] -Complete src/TypeContextCompletion_Records.res 81:47 -posCursor:[81:47] posNoWhite:[81:46] Found expr:[81:3->81:57] -posCursor:[81:47] posNoWhite:[81:46] Found pattern:[81:29->81:49] -posCursor:[81:47] posNoWhite:[81:46] Found pattern:[81:42->81:48] -posCursor:[81:47] posNoWhite:[81:46] Found pattern:[81:46->81:47] -Ppat_construct T:[81:46->81:47] +Complete src/TypeContextCompletion_Records.res 84:47 +posCursor:[84:47] posNoWhite:[84:46] Found expr:[84:3->84:57] +posCursor:[84:47] posNoWhite:[84:46] Found pattern:[84:29->84:49] +posCursor:[84:47] posNoWhite:[84:46] Found pattern:[84:42->84:48] +posCursor:[84:47] posNoWhite:[84:46] Found pattern:[84:46->84:47] +Ppat_construct T:[84:46->84:47] Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:thirdStuff:[], Tuple:1] found variant: T [{ @@ -220,39 +220,27 @@ found variant: T "documentation": null }] -Complete src/TypeContextCompletion_Records.res 84:51 -posCursor:[84:51] posNoWhite:[84:50] Found expr:[84:3->84:62] -posCursor:[84:51] posNoWhite:[84:50] Found pattern:[84:29->84:54] -posCursor:[84:51] posNoWhite:[84:50] Found pattern:[84:42->84:53] -posCursor:[84:51] posNoWhite:[84:50] Found pattern:[84:46->84:52] -Ppat_construct Four:[84:46->84:50] -posCursor:[84:51] posNoWhite:[84:50] Found pattern:[84:50->84:52] -Ppat_construct ():[84:50->84:52] -Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:thirdStuff:[], Tuple:1, Variant:Four] +Complete src/TypeContextCompletion_Records.res 87:51 +posCursor:[87:51] posNoWhite:[87:50] Found expr:[87:3->87:62] +posCursor:[87:51] posNoWhite:[87:50] Found pattern:[87:29->87:54] +posCursor:[87:51] posNoWhite:[87:50] Found pattern:[87:42->87:53] +posCursor:[87:51] posNoWhite:[87:50] Found pattern:[87:46->87:52] +Ppat_construct Four:[87:46->87:50] +posCursor:[87:51] posNoWhite:[87:50] Found pattern:[87:50->87:52] +Ppat_construct ():[87:50->87:52] +Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:thirdStuff:[], Tuple:1, Variant:Four(0)] found variant: [{ - "label": "One", + "label": "TwentyFive", "kind": 4, "tags": [], - "detail": "One\n\n", + "detail": "TwentyFive\n\n", "documentation": null }, { - "label": "Two", + "label": "SixtyTwo", "kind": 4, "tags": [], - "detail": "Two\n\n", - "documentation": null - }, { - "label": "Three(_)", - "kind": 4, - "tags": [], - "detail": "Three(int)\n\n", - "documentation": null - }, { - "label": "Four(_)", - "kind": 4, - "tags": [], - "detail": "Four(someOtherVariant)\n\n", + "detail": "SixtyTwo\n\n", "documentation": null }, { "label": "someOtherValue", @@ -274,3 +262,41 @@ found variant: "documentation": null }] +Complete src/TypeContextCompletion_Records.res 90:55 +posCursor:[90:55] posNoWhite:[90:54] Found expr:[90:3->90:66] +posCursor:[90:55] posNoWhite:[90:54] Found pattern:[90:29->90:58] +posCursor:[90:55] posNoWhite:[90:54] Found pattern:[90:42->90:57] +posCursor:[90:55] posNoWhite:[90:54] Found pattern:[90:46->90:56] +Ppat_construct Five:[90:46->90:50] +posCursor:[90:55] posNoWhite:[90:54] Found pattern:[90:50->90:57] +posCursor:[90:55] posNoWhite:[90:54] Found pattern:[90:54->90:55] +Ppat_construct O:[90:54->90:55] +Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:thirdStuff:[], Tuple:1, Variant:Five(1)] +found variant: O +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null + }] + +Complete src/TypeContextCompletion_Records.res 93:63 +posCursor:[93:63] posNoWhite:[93:62] Found expr:[93:3->93:78] +posCursor:[93:63] posNoWhite:[93:62] Found pattern:[93:29->93:70] +posCursor:[93:63] posNoWhite:[93:62] Found pattern:[93:43->93:69] +posCursor:[93:63] posNoWhite:[93:62] Found pattern:[93:44->93:65] +Ppat_construct Some:[93:44->93:48] +posCursor:[93:63] posNoWhite:[93:62] Found pattern:[93:49->93:64] +posCursor:[93:63] posNoWhite:[93:62] Found pattern:[93:62->93:63] +Ppat_construct O:[93:62->93:63] +Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:fourthStuff:[], Tuple:0, Variant:Some(0), Polyvariant:WithPayload(0)] +found variant: O +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null + }] + From 3a6a6e50b4d14efe2af554898aa78092d653c17b Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 11 Aug 2022 09:18:03 +0200 Subject: [PATCH 47/80] pick up already seen idents for constructors/record fields --- analysis/src/CompletionBackEnd.ml | 22 +-- analysis/src/CompletionFrontEnd.ml | 131 ++++++++++-------- analysis/src/SharedTypes.ml | 28 ++-- .../src/TypeContextCompletion_Records.res | 7 +- .../TypeContextCompletion_Records.res.txt | 61 +++++--- 5 files changed, 152 insertions(+), 97 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index f9ce3a565..1bed19269 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1058,7 +1058,7 @@ let rec extractType ~env ~package (t : Types.type_expr) = match t.desc with | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> extractType ~env ~package t1 | Tconstr (Path.Pident {name = "option"}, [payloadTypeExpr], _) -> - (* Handle option *) + (* Handle option. TODO: Look up how the compiler does this and copy that behavior. *) Some (Toption (env, payloadTypeExpr)) | Tconstr (path, _, _) -> ( match References.digConstructor ~env ~package path with @@ -1466,12 +1466,12 @@ let findTypeInContext (typ : Types.type_expr) ~env ~nestedContextPath ~package = if List.length nestedContextPath > 0 then targetField.typ |> digToType ~env ~nestedContextPath ~package else typeExprToCompletable targetField.typ ~env ~package) - | ( Variant {name; payloadNum}, + | ( Variant {constructorName; payloadNum}, Some (Declared (_, {item = {kind = Variant constructors}})) ) -> ( match constructors |> List.find_opt (fun constructor -> - constructor.Constructor.cname.txt = name) + constructor.Constructor.cname.txt = constructorName) with | Some constructor -> ( (* payloadNum tells us whether there's also a payload we should descend into. *) @@ -1504,7 +1504,7 @@ let findTypeInContext (typ : Types.type_expr) ~env ~nestedContextPath ~package = | None -> None | Some typeExpr -> typeExpr |> digToType ~env ~nestedContextPath ~package) - | Variant {name = "Some"}, Some (Toption (_, typeExpr)) -> + | Variant {constructorName = "Some"}, Some (Toption (_, typeExpr)) -> typeExpr |> digToType ~env ~nestedContextPath ~package | _ -> None) in @@ -1985,7 +1985,12 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i let constructorCompletions = constructors |> List.filter (fun constructor -> - Utils.startsWith constructor.Constructor.cname.txt prefix) + Utils.startsWith constructor.Constructor.cname.txt prefix + && not + (alreadySeenIdents + |> List.exists (fun alreadySeenConstructorName -> + alreadySeenConstructorName + = constructor.Constructor.cname.txt))) |> List.map (fun (constructor : Constructor.t) -> (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? Eg. Some($1) as completion item. *) @@ -2004,15 +2009,10 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i in constructorCompletions @ localCompletions | Some (CRecord {fields; decl; name}) -> - let alreadyTypedRecordFields = - match alreadySeenIdents with - | None -> [] - | Some recordFieldNames -> recordFieldNames - in fields |> List.filter (fun (field : field) -> not - (alreadyTypedRecordFields + (alreadySeenIdents |> List.exists (fun fieldName -> fieldName = field.fname.txt))) |> Utils.filterMap (fun (field : field) -> if prefix = "" || checkName field.fname.txt ~prefix ~exact:false diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 5e6e1eea5..22ac9320d 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -120,7 +120,7 @@ let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName meta = { prefix = Some (getPrefixFromExpr prop.exp); - alreadySeenIdents = None; + alreadySeenIdents = []; }; }) else None @@ -142,7 +142,7 @@ let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName meta = { prefix = Some (getPrefixFromExpr prop.exp); - alreadySeenIdents = None; + alreadySeenIdents = []; }; }) else None @@ -242,7 +242,7 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor meta = { prefix = Some (getPrefixFromExpr exp); - alreadySeenIdents = None; + alreadySeenIdents = []; }; }) else None @@ -259,7 +259,7 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor meta = { prefix = Some (getPrefixFromExpr exp); - alreadySeenIdents = None; + alreadySeenIdents = []; }; }) else None @@ -318,15 +318,35 @@ let findVariantPayloadItemNumWithCursor pat ~pos = | Ppat_tuple patterns -> let res = ref None in patterns - |> List.iteri (fun index pat -> + |> List.iteri (fun index tuplePat -> match pat.Parsetree.ppat_loc |> CursorPosition.classifyLoc ~pos with - | HasCursor -> res := Some (index, pat) + | HasCursor -> res := Some (index, tuplePat) | _ -> ()); !res | _ -> Some (0, pat) -let rec whatevs pattern ~path ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite = +let identFromPat pat = + match pat.Parsetree.ppat_desc with + | Ppat_var loc -> Some loc.txt + | Ppat_construct (loc, _) -> Some (getSimpleFieldName loc.txt) + | Ppat_variant (label, _) -> Some label + | _ -> None + +let findAlreadySeenIdents pat = + match pat.Parsetree.ppat_desc with + | Ppat_or (pat1, pat2) -> + let rec findAllOrBranches pat ~branches = + match pat.Parsetree.ppat_desc with + | Ppat_or (pat1, pat2) -> + pat1 |> findAllOrBranches ~branches:([pat2] @ branches) + | _ -> [pat] @ branches + in + let branches = pat1 |> findAllOrBranches ~branches:[pat2] in + branches |> List.filter_map (fun branchPat -> identFromPat branchPat) + | _ -> [] + +let rec findCompletableInPattern pattern ~path ~posBeforeCursor ~prefix + ~firstCharBeforeCursorNoWhite ~seenIdents = match pattern.Parsetree.ppat_loc |> CursorPosition.classifyLoc ~pos:posBeforeCursor @@ -349,15 +369,19 @@ let rec whatevs pattern ~path ~posBeforeCursor ~prefix with | None -> None | Some (index, pat) -> + seenIdents := findAlreadySeenIdents pat; pat - |> whatevs + |> findCompletableInPattern ~path: ([ Completable.Variant - {name = getSimpleFieldName txt; payloadNum = Some index}; + { + constructorName = getSimpleFieldName txt; + payloadNum = Some index; + }; ] @ path) - ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~prefix) + ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~prefix ~seenIdents) | Ppat_variant (label, None) -> (* A constructor without a payload mean we've reached an end. *) prefix := label; @@ -369,14 +393,15 @@ let rec whatevs pattern ~path ~posBeforeCursor ~prefix with | None -> None | Some (index, pat) -> + seenIdents := findAlreadySeenIdents pat; pat - |> whatevs + |> findCompletableInPattern ~path: ([ Completable.Polyvariant {name = label; payloadNum = Some index}; ] @ path) - ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~prefix) + ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~prefix ~seenIdents) | Ppat_tuple patterns -> ( let tupleItemNum = ref 0 in let patternWithCursor = @@ -394,8 +419,10 @@ let rec whatevs pattern ~path ~posBeforeCursor ~prefix match patternWithCursor with | None -> None | Some (tupleItemNum, pat) -> + seenIdents := []; pat - |> whatevs ~posBeforeCursor ~prefix ~firstCharBeforeCursorNoWhite + |> findCompletableInPattern ~posBeforeCursor ~prefix + ~firstCharBeforeCursorNoWhite ~seenIdents ~path:([Completable.PTuple {itemNumber = tupleItemNum}] @ path)) | Ppat_record (fields, _) when List.length fields = 0 -> Some path | Ppat_record (fields, _) -> ( @@ -413,46 +440,49 @@ let rec whatevs pattern ~path ~posBeforeCursor ~prefix | None -> None | Some (loc, pat) -> let fieldName = getSimpleFieldName loc.txt in + seenIdents := + fields + |> List.map (fun ({Location.txt}, _) -> getSimpleFieldName txt) + |> List.filter (fun name -> name <> fieldName); pat - |> whatevs ~posBeforeCursor ~prefix ~firstCharBeforeCursorNoWhite - ~path: - ([ - Completable.RField - { - fieldName; - alreadySeenFields = - fields - |> List.map (fun ({Location.txt}, _) -> - getSimpleFieldName txt) - |> List.filter (fun name -> name <> fieldName); - }; - ] - @ path)) + |> findCompletableInPattern ~posBeforeCursor ~prefix + ~firstCharBeforeCursorNoWhite ~seenIdents + ~path:([Completable.RField {fieldName}] @ path)) | Ppat_var {txt} -> prefix := txt; Some path + | Ppat_or (pat1, pat2) -> ( + let rec findAllOrBranches pat ~branches = + match pat.Parsetree.ppat_desc with + | Ppat_or (pat1, pat2) -> + pat1 |> findAllOrBranches ~branches:([pat2] @ branches) + | _ -> [pat] @ branches + in + let branches = pat1 |> findAllOrBranches ~branches:[pat2] in + let branchAtCursor = + branches + |> List.find_opt (fun pat -> + match + pat.Parsetree.ppat_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + with + | HasCursor -> true + | EmptyLoc | NoCursor -> false) + in + match branchAtCursor with + | None -> None + | Some pat -> + pat + |> findCompletableInPattern ~posBeforeCursor ~prefix + ~firstCharBeforeCursorNoWhite ~path ~seenIdents) | _ -> None) -let findPrefixAndNestedContextPath pattern ~posBeforeCursor - ~firstCharBeforeCursorNoWhite = - let prefix = ref "" in - - let nestedContextPath = - match pattern.Parsetree.ppat_desc with - | Ppat_record (fields, _) when List.length fields = 0 -> - (* A root record with 0 fields, `let {} = someVar`, is still valid to complete from. But it has no nested context. *) - Some [] - | _ -> - pattern - |> whatevs ~path:[] ~posBeforeCursor ~prefix ~firstCharBeforeCursorNoWhite - in - - (!prefix, nestedContextPath) - let completePattern pattern ~contextPath ~posBeforeCursor ~firstCharBeforeCursorNoWhite = let prefix = ref "" in + let seenIdents = ref [] in let nestedContextPath = + (* TODO: This special casing should probably be cleaned up somehow... *) match pattern.Parsetree.ppat_desc with | Ppat_record (fields, _) -> ( match List.length fields with @@ -461,8 +491,8 @@ let completePattern pattern ~contextPath ~posBeforeCursor Some [] | _ -> pattern - |> whatevs ~path:[] ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite) + |> findCompletableInPattern ~path:[] ~posBeforeCursor ~prefix + ~firstCharBeforeCursorNoWhite ~seenIdents) | _ -> None in match (contextPath, nestedContextPath) with @@ -472,14 +502,7 @@ let completePattern pattern ~contextPath ~posBeforeCursor { howToRetrieveSourceType = CtxPath contextPath; patternPath = Some (nestedContextPath |> List.rev); - meta = - { - prefix = Some !prefix; - alreadySeenIdents = - (match nestedContextPath with - | RField {alreadySeenFields} :: _rest -> Some alreadySeenFields - | _ -> None); - }; + meta = {prefix = Some !prefix; alreadySeenIdents = !seenIdents}; }) | _ -> None diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index b6cb470b5..6aeb802a2 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -435,8 +435,8 @@ module Completable = struct (* How to move through a nested type context, like from a root record to the type of one of its fields, and beyond. *) (* TODO: Can extend to tuples, objects, etc *) type patternPathItem = - | RField of {fieldName: string; alreadySeenFields: string list} - | Variant of {name: string; payloadNum: int option} + | RField of {fieldName: string} + | Variant of {constructorName: string; payloadNum: int option} | Polyvariant of {name: string; payloadNum: int option} | PTuple of {itemNumber: int} @@ -446,10 +446,9 @@ module Completable = struct let pathItemToString item = match item with - | RField {fieldName; alreadySeenFields} -> - "RecordField:" ^ fieldName ^ ":" ^ list alreadySeenFields - | Variant {name; payloadNum} -> ( - "Variant:" ^ name + | RField {fieldName} -> "RecordField:" ^ fieldName + | Variant {constructorName; payloadNum} -> ( + "Variant:" ^ constructorName ^ match payloadNum with | None -> "" @@ -462,7 +461,7 @@ module Completable = struct | Some payloadNum -> "(" ^ string_of_int payloadNum ^ ")") | PTuple {itemNumber} -> "Tuple:" ^ string_of_int itemNumber - let recordFieldContextPathToString pathItems = + let patternContextPathToString pathItems = pathItems |> List.map (fun item -> pathItemToString item) |> list let completionContextToString = function @@ -519,7 +518,8 @@ module Completable = struct prefix: string option; (* Record fields already written by the user, etc. This is contextual of course, but putting it here in the general type to simplify things. *) - alreadySeenIdents: string list option; + (* TODO: Clarify that this is only for patterns (?). If so, move it to something more obvious. *) + alreadySeenIdents: string list; } type t = @@ -530,6 +530,7 @@ module Completable = struct | Cpath of contextPath | Cjsx of string list * string * string list (** E.g. (["M", "Comp"], "id", ["id1", "id2"]) for "Cnone" | Cjsx (sl1, s, sl2) -> "Cjsx(" ^ (sl1 |> list) ^ ", " ^ str s ^ ", " ^ (sl2 |> list) ^ ")" - | CtypedContext {howToRetrieveSourceType; meta = {prefix}; patternPath} -> ( + | CtypedContext + { + howToRetrieveSourceType; + meta = {prefix; alreadySeenIdents}; + patternPath; + } -> ( ("CtypedContext(" ^ (howToRetrieveSourceType |> howToRetrieveSourceTypeToString) ^ ")=" @@ -558,7 +564,9 @@ module Completable = struct match patternPath with | None -> "" | Some patternPath -> - " pattern: " ^ (patternPath |> recordFieldContextPathToString)) + " pattern: " + ^ (patternPath |> patternContextPathToString) + ^ " seenIdents: " ^ list alreadySeenIdents) end module CursorPosition = struct diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index 9a1af6ef6..37b4328e0 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -76,8 +76,8 @@ let someOtherValue: someRecordWithVariant = { thirdStuff: (someVal.something, One, None, 1), fourthStuff: (None, One), } -// switch someOtherValue { | {something: T} => () } -// ^com +// switch someOtherValue { | {something: Two | T} => () } +// ^com // switch someOtherValue { | {otherThing: Some(T)} => () } // ^com @@ -93,3 +93,6 @@ let someOtherValue: someRecordWithVariant = { // switch someOtherValue { | {fourthStuff: (Some(#WithPayload(O)), _)} => () } // ^com + +// switch someOtherValue { | {thirdStuff: (_, Five(_, One | Two | T))} => () } +// ^com diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index c2a744ce3..f4a4f9daf 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -1,18 +1,18 @@ Complete src/TypeContextCompletion_Records.res 16:15 posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:7->16:16] posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:8->16:15] -Completable: CtypedContext(Value[someVal])=another pattern: [RecordField:another:[]] +Completable: CtypedContext(Value[someVal])=another pattern: [RecordField:another] seenIdents: [] [] Complete src/TypeContextCompletion_Records.res 19:23 posCursor:[19:23] posNoWhite:[19:22] Found pattern:[19:7->19:24] posCursor:[19:23] posNoWhite:[19:22] Found pattern:[19:22->19:23] -Completable: CtypedContext(Value[someVal])=s pattern: [RecordField:s:[anotherThing]] +Completable: CtypedContext(Value[someVal])=s pattern: [RecordField:s] seenIdents: [anotherThing] [] Complete src/TypeContextCompletion_Records.res 22:8 posCursor:[22:8] posNoWhite:[22:7] Found pattern:[22:7->22:9] -Completable: CtypedContext(Value[someVal])="" pattern: [] +Completable: CtypedContext(Value[someVal])="" pattern: [] seenIdents: [] [{ "label": "something", "kind": 5, @@ -35,7 +35,7 @@ Completable: CtypedContext(Value[someVal])="" pattern: [] Complete src/TypeContextCompletion_Records.res 31:8 posCursor:[31:8] posNoWhite:[31:7] Found pattern:[31:7->31:9] -Completable: CtypedContext(Value[getSomeVal](~irrelevant))="" pattern: [] +Completable: CtypedContext(Value[getSomeVal](~irrelevant))="" pattern: [] seenIdents: [] [{ "label": "something", "kind": 5, @@ -59,7 +59,7 @@ Completable: CtypedContext(Value[getSomeVal](~irrelevant))="" pattern: [] Complete src/TypeContextCompletion_Records.res 35:20 posCursor:[35:20] posNoWhite:[35:19] Found pattern:[35:7->35:22] posCursor:[35:20] posNoWhite:[35:19] Found pattern:[35:19->35:21] -Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something:[]] +Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something] seenIdents: [] [{ "label": "somethingElse", "kind": 5, @@ -84,7 +84,7 @@ Complete src/TypeContextCompletion_Records.res 38:47 posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:7->38:50] posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:19->38:49] posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:46->38:48] -Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something:[], RecordField:anotherLevel:[whatIsThis]] +Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something, RecordField:anotherLevel] seenIdents: [whatIsThis] [{ "label": "level", "kind": 5, @@ -104,7 +104,7 @@ posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:7->41:51] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:19->41:50] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:46->41:49] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:47->41:48] -Completable: CtypedContext(Value[someVal])=l pattern: [RecordField:something:[], RecordField:anotherLevel:[whatIsThis], RecordField:l:[]] +Completable: CtypedContext(Value[someVal])=l pattern: [RecordField:something, RecordField:anotherLevel, RecordField:l] seenIdents: [] [] Complete src/TypeContextCompletion_Records.res 44:47 @@ -121,13 +121,13 @@ Complete src/TypeContextCompletion_Records.res 50:44 posCursor:[50:44] posNoWhite:[50:43] Found expr:[50:3->50:54] posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:22->50:46] posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:42->50:45] -Completable: CtypedContext(Value[someVal])=som pattern: [RecordField:som:[thirdThing]] +Completable: CtypedContext(Value[someVal])=som pattern: [RecordField:som] seenIdents: [thirdThing] [] Complete src/TypeContextCompletion_Records.res 53:52 posCursor:[53:52] posNoWhite:[53:51] Found expr:[53:3->53:61] posCursor:[53:52] posNoWhite:[53:51] Found pattern:[53:51->53:53] -Completable: CtypedContext(Value[someVal])="" pattern: [] +Completable: CtypedContext(Value[someVal])="" pattern: [] seenIdents: [] [{ "label": "something", "kind": 5, @@ -154,12 +154,13 @@ posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:51->56:92] posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:63->56:91] [] -Complete src/TypeContextCompletion_Records.res 78:42 -posCursor:[78:42] posNoWhite:[78:41] Found expr:[78:3->78:51] -posCursor:[78:42] posNoWhite:[78:41] Found pattern:[78:29->78:43] -posCursor:[78:42] posNoWhite:[78:41] Found pattern:[78:41->78:42] -Ppat_construct T:[78:41->78:42] -Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:something:[]] +Complete src/TypeContextCompletion_Records.res 78:48 +posCursor:[78:48] posNoWhite:[78:47] Found expr:[78:3->78:57] +posCursor:[78:48] posNoWhite:[78:47] Found pattern:[78:29->78:49] +posCursor:[78:48] posNoWhite:[78:47] Found pattern:[78:41->78:48] +posCursor:[78:48] posNoWhite:[78:47] Found pattern:[78:47->78:48] +Ppat_construct T:[78:47->78:48] +Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:something] seenIdents: [] found variant: T [{ "label": "Two", @@ -182,7 +183,7 @@ posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:42->81:49] Ppat_construct Some:[81:42->81:46] posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:47->81:48] Ppat_construct T:[81:47->81:48] -Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:otherThing:[], Variant:Some(0)] +Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:otherThing, Variant:Some(0)] seenIdents: [] found variant: T [{ "label": "Two", @@ -204,7 +205,7 @@ posCursor:[84:47] posNoWhite:[84:46] Found pattern:[84:29->84:49] posCursor:[84:47] posNoWhite:[84:46] Found pattern:[84:42->84:48] posCursor:[84:47] posNoWhite:[84:46] Found pattern:[84:46->84:47] Ppat_construct T:[84:46->84:47] -Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:thirdStuff:[], Tuple:1] +Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:thirdStuff, Tuple:1] seenIdents: [] found variant: T [{ "label": "Two", @@ -228,7 +229,7 @@ posCursor:[87:51] posNoWhite:[87:50] Found pattern:[87:46->87:52] Ppat_construct Four:[87:46->87:50] posCursor:[87:51] posNoWhite:[87:50] Found pattern:[87:50->87:52] Ppat_construct ():[87:50->87:52] -Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:thirdStuff:[], Tuple:1, Variant:Four(0)] +Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)] seenIdents: [] found variant: [{ "label": "TwentyFive", @@ -271,7 +272,7 @@ Ppat_construct Five:[90:46->90:50] posCursor:[90:55] posNoWhite:[90:54] Found pattern:[90:50->90:57] posCursor:[90:55] posNoWhite:[90:54] Found pattern:[90:54->90:55] Ppat_construct O:[90:54->90:55] -Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:thirdStuff:[], Tuple:1, Variant:Five(1)] +Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)] seenIdents: [] found variant: O [{ "label": "One", @@ -290,7 +291,7 @@ Ppat_construct Some:[93:44->93:48] posCursor:[93:63] posNoWhite:[93:62] Found pattern:[93:49->93:64] posCursor:[93:63] posNoWhite:[93:62] Found pattern:[93:62->93:63] Ppat_construct O:[93:62->93:63] -Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:fourthStuff:[], Tuple:0, Variant:Some(0), Polyvariant:WithPayload(0)] +Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:fourthStuff, Tuple:0, Variant:Some(0), Polyvariant:WithPayload(0)] seenIdents: [] found variant: O [{ "label": "One", @@ -300,3 +301,23 @@ found variant: O "documentation": null }] +Complete src/TypeContextCompletion_Records.res 96:67 +posCursor:[96:67] posNoWhite:[96:66] Found expr:[96:3->96:78] +posCursor:[96:67] posNoWhite:[96:66] Found pattern:[96:29->96:70] +posCursor:[96:67] posNoWhite:[96:66] Found pattern:[96:42->96:69] +posCursor:[96:67] posNoWhite:[96:66] Found pattern:[96:46->96:68] +Ppat_construct Five:[96:46->96:50] +posCursor:[96:67] posNoWhite:[96:66] Found pattern:[96:50->96:69] +posCursor:[96:67] posNoWhite:[96:66] Found pattern:[96:54->96:67] +posCursor:[96:67] posNoWhite:[96:66] Found pattern:[96:66->96:67] +Ppat_construct T:[96:66->96:67] +Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)] seenIdents: [One, Two, T] +found variant: T +[{ + "label": "Three(_)", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null + }] + From 339417c9664a2740dd4b77a78dbdba6f1b276069 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 11 Aug 2022 10:20:24 +0200 Subject: [PATCH 48/80] basic completion of options --- analysis/src/CompletionBackEnd.ml | 75 +++++++- analysis/src/SharedTypes.ml | 4 +- .../src/TypeContextCompletion_Records.res | 8 + analysis/tests/src/expected/Dce.res.txt | 2 +- .../TypeContextCompletion_Jsx.res.txt | 4 - ...ontextCompletion_LabelledArguments.res.txt | 4 - .../TypeContextCompletion_Records.res.txt | 181 ++++++++++++------ 7 files changed, 204 insertions(+), 74 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 1bed19269..44150a0b7 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -711,6 +711,8 @@ let detail name (kind : Completion.kind) = | FileModule _ -> "file module" | Field ({typ}, s) -> name ^ ": " ^ (typ |> Shared.typeToString) ^ "\n\n" ^ s | Constructor (c, s) -> showConstructor c ^ "\n\n" ^ s + | OptionNone -> "None\n\n" + | OptionSome -> "Some(_)\n\n" | PolyvariantConstructor {name; payload} -> ( "#" ^ name ^ @@ -1433,14 +1435,19 @@ type completable = } | CVariant of {constructors: Constructor.t list} | CPolyVariant of {constructors: polyVariantConstructor list} + | COptional of completable -let typeExprToCompletable typ ~env ~package = +let rec typeExprToCompletable typ ~env ~package = match typ |> extractType ~env ~package with | Some (Declared (_, {name; item = {kind = Record fields; decl}})) -> Some (CRecord {fields; decl; name}) | Some (Declared (_, {item = {kind = Variant constructors}})) -> Some (CVariant {constructors}) | Some (Polyvariant (_, constructors)) -> Some (CPolyVariant {constructors}) + | Some (Toption (env, typ)) -> ( + match typ |> typeExprToCompletable ~env ~package with + | None -> None + | Some typ -> Some (COptional typ)) | _ -> None (* Takes a type_expr and figures out what completable it corresponds to, if any. If the target type is nested somewhere inside of the type_expr, @@ -1958,6 +1965,71 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i | Some typ -> ( match typ |> findTypeInContext ~env ~nestedContextPath ~package with | None -> [] + | Some (COptional completable) -> ( + match completable with + | CVariant {constructors} -> + (* TOOD: Unify with other variant completion handler *) + let constructorCompletions = + constructors + |> List.filter (fun constructor -> + Utils.startsWith + ("Some(" ^ constructor.Constructor.cname.txt ^ ")") + prefix + && not + (alreadySeenIdents + |> List.exists (fun alreadySeenConstructorName -> + alreadySeenConstructorName + = constructor.Constructor.cname.txt))) + |> List.map (fun (constructor : Constructor.t) -> + (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? + Eg. Some($1) as completion item. *) + Completion.create + ~name: + ("Some(" ^ constructor.cname.txt + ^ + if constructor.args |> List.length > 0 then "(_))" + else ")") + ~kind:(Constructor (constructor, "")) + ~env) + in + (* TODO: Patterns should not include local completions *) + let localCompletions = + typ + |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix + ~exact:false ~opens ~scope + in + [Completion.create ~name:"None" ~kind:OptionNone ~env] + @ constructorCompletions @ localCompletions + | CPolyVariant {constructors} -> + (* TOOD: Unify with other variant completion handler *) + let constructorCompletions = + constructors + |> List.filter (fun constructor -> + Utils.startsWith ("Some(#" ^ constructor.name ^ ")") prefix) + |> List.map (fun constructor -> + (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? + Eg. Some($1) as completion item. *) + Completion.create + ~name: + ("Some(#" ^ constructor.name + ^ + if constructor.payload |> Option.is_some then "(_))" + else ")") + ~kind:(PolyvariantConstructor constructor) ~env) + in + (* TODO: Patterns should not include local completions *) + let localCompletions = + typ + |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix + ~exact:false ~opens ~scope + in + [Completion.create ~name:"None" ~kind:OptionNone ~env] + @ constructorCompletions @ localCompletions + | _ -> + [ + Completion.create ~name:"None" ~kind:OptionNone ~env; + Completion.create ~name:"Some(_)" ~kind:OptionSome ~env; + ]) | Some (CPolyVariant {constructors}) -> let constructorCompletions = constructors @@ -1981,7 +2053,6 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i in constructorCompletions @ localCompletions | Some (CVariant {constructors}) -> - if debug then Printf.printf "found variant: %s\n" prefix; let constructorCompletions = constructors |> List.filter (fun constructor -> diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 6aeb802a2..87ac76ecb 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -233,6 +233,8 @@ module Completion = struct | PolyvariantConstructor of polyVariantConstructor | Field of field * string | FileModule of string + | OptionNone + | OptionSome type t = { name: string; @@ -251,7 +253,7 @@ module Completion = struct match kind with | Module _ -> 9 | FileModule _ -> 9 - | PolyvariantConstructor _ | Constructor (_, _) -> 4 + | PolyvariantConstructor _ | Constructor _ | OptionNone | OptionSome -> 4 | ObjLabel _ -> 4 | Label _ -> 4 | Field (_, _) -> 5 diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index 37b4328e0..fa6adc0f4 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -63,6 +63,7 @@ type rec someVariant = type someRecordWithVariant = { other: someRecord, + other2: option, something: someVariant, otherThing: option, thirdStuff: (someRecord, someVariant, option, int), @@ -71,6 +72,7 @@ type someRecordWithVariant = { let someOtherValue: someRecordWithVariant = { other: someVal.something, + other2: None, something: Two, otherThing: None, thirdStuff: (someVal.something, One, None, 1), @@ -96,3 +98,9 @@ let someOtherValue: someRecordWithVariant = { // switch someOtherValue { | {thirdStuff: (_, Five(_, One | Two | T))} => () } // ^com + +// switch someOtherValue { | {otherThing: S} => () } +// ^com + +// switch someOtherValue { | {other2: S} => () } +// ^com diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index 052abba9a..3dde901c5 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:284 +issues:285 diff --git a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt index 31c75b95f..2dc03adb0 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt @@ -14,7 +14,6 @@ Complete src/TypeContextCompletion_Jsx.res 23:38 posCursor:[23:38] posNoWhite:[23:37] Found expr:[23:12->23:38] JSX 23:25] someVariant[23:26->23:37]=...__ghost__[0:-1->0:-1]> _children:None Completable: CtypedContext(JsxProp())="" -found variant: [{ "label": "One", "kind": 4, @@ -69,7 +68,6 @@ Complete src/TypeContextCompletion_Jsx.res 26:39 posCursor:[26:39] posNoWhite:[26:37] Found expr:[26:12->26:38] JSX 26:25] someVariant[26:26->26:37]=...__ghost__[0:-1->0:-1]> _children:None Completable: CtypedContext(JsxProp())="" -found variant: [{ "label": "One", "kind": 4, @@ -124,7 +122,6 @@ Complete src/TypeContextCompletion_Jsx.res 29:39 posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:12->29:39] JSX 29:25] someVariant[29:26->29:37]=...[29:38->29:39]> _children:None Completable: CtypedContext(JsxProp())=T -found variant: T [{ "label": "Two", "kind": 4, @@ -151,7 +148,6 @@ Complete src/TypeContextCompletion_Jsx.res 35:39 posCursor:[35:39] posNoWhite:[35:38] Found expr:[35:12->35:39] JSX 35:25] anotherThing[35:26->35:38]=...__ghost__[0:-1->0:-1]> _children:None Completable: CtypedContext(JsxProp())="" -found variant: [{ "label": "Foo", "kind": 4, diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index b9d93edb2..2e2582bf8 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -19,7 +19,6 @@ Complete src/TypeContextCompletion_LabelledArguments.res 25:44 posCursor:[25:44] posNoWhite:[25:43] Found expr:[25:11->25:44] Pexp_apply ...[25:11->25:30] (~someVariant25:32->25:43=...__ghost__[0:-1->0:-1]) Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))="" -found variant: [{ "label": "One", "kind": 4, @@ -74,7 +73,6 @@ Complete src/TypeContextCompletion_LabelledArguments.res 28:45 posCursor:[28:45] posNoWhite:[28:43] Found expr:[28:11->28:44] Pexp_apply ...[28:11->28:30] (~someVariant28:32->28:43=...__ghost__[0:-1->0:-1]) Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))="" -found variant: [{ "label": "One", "kind": 4, @@ -129,7 +127,6 @@ Complete src/TypeContextCompletion_LabelledArguments.res 31:45 posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:11->31:45] Pexp_apply ...[31:11->31:30] (~someVariant31:32->31:43=...[31:44->31:45]) Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))=T -found variant: T [{ "label": "Two", "kind": 4, @@ -212,7 +209,6 @@ Complete src/TypeContextCompletion_LabelledArguments.res 40:45 posCursor:[40:45] posNoWhite:[40:44] Found expr:[40:11->40:45] Pexp_apply ...[40:11->40:30] (~anotherThing40:32->40:44=...__ghost__[0:-1->0:-1]) Completable: CtypedContext(NamedArg(anotherThing, Value[someVariantToString]))="" -found variant: [{ "label": "Foo", "kind": 4, diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index f4a4f9daf..c0ff430c3 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -154,14 +154,13 @@ posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:51->56:92] posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:63->56:91] [] -Complete src/TypeContextCompletion_Records.res 78:48 -posCursor:[78:48] posNoWhite:[78:47] Found expr:[78:3->78:57] -posCursor:[78:48] posNoWhite:[78:47] Found pattern:[78:29->78:49] -posCursor:[78:48] posNoWhite:[78:47] Found pattern:[78:41->78:48] -posCursor:[78:48] posNoWhite:[78:47] Found pattern:[78:47->78:48] -Ppat_construct T:[78:47->78:48] +Complete src/TypeContextCompletion_Records.res 80:48 +posCursor:[80:48] posNoWhite:[80:47] Found expr:[80:3->80:57] +posCursor:[80:48] posNoWhite:[80:47] Found pattern:[80:29->80:49] +posCursor:[80:48] posNoWhite:[80:47] Found pattern:[80:41->80:48] +posCursor:[80:48] posNoWhite:[80:47] Found pattern:[80:47->80:48] +Ppat_construct T:[80:47->80:48] Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:something] seenIdents: [] -found variant: T [{ "label": "Two", "kind": 4, @@ -176,15 +175,14 @@ found variant: T "documentation": null }] -Complete src/TypeContextCompletion_Records.res 81:48 -posCursor:[81:48] posNoWhite:[81:47] Found expr:[81:3->81:58] -posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:29->81:50] -posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:42->81:49] -Ppat_construct Some:[81:42->81:46] -posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:47->81:48] -Ppat_construct T:[81:47->81:48] +Complete src/TypeContextCompletion_Records.res 83:48 +posCursor:[83:48] posNoWhite:[83:47] Found expr:[83:3->83:58] +posCursor:[83:48] posNoWhite:[83:47] Found pattern:[83:29->83:50] +posCursor:[83:48] posNoWhite:[83:47] Found pattern:[83:42->83:49] +Ppat_construct Some:[83:42->83:46] +posCursor:[83:48] posNoWhite:[83:47] Found pattern:[83:47->83:48] +Ppat_construct T:[83:47->83:48] Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:otherThing, Variant:Some(0)] seenIdents: [] -found variant: T [{ "label": "Two", "kind": 4, @@ -199,14 +197,13 @@ found variant: T "documentation": null }] -Complete src/TypeContextCompletion_Records.res 84:47 -posCursor:[84:47] posNoWhite:[84:46] Found expr:[84:3->84:57] -posCursor:[84:47] posNoWhite:[84:46] Found pattern:[84:29->84:49] -posCursor:[84:47] posNoWhite:[84:46] Found pattern:[84:42->84:48] -posCursor:[84:47] posNoWhite:[84:46] Found pattern:[84:46->84:47] -Ppat_construct T:[84:46->84:47] +Complete src/TypeContextCompletion_Records.res 86:47 +posCursor:[86:47] posNoWhite:[86:46] Found expr:[86:3->86:57] +posCursor:[86:47] posNoWhite:[86:46] Found pattern:[86:29->86:49] +posCursor:[86:47] posNoWhite:[86:46] Found pattern:[86:42->86:48] +posCursor:[86:47] posNoWhite:[86:46] Found pattern:[86:46->86:47] +Ppat_construct T:[86:46->86:47] Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:thirdStuff, Tuple:1] seenIdents: [] -found variant: T [{ "label": "Two", "kind": 4, @@ -221,16 +218,15 @@ found variant: T "documentation": null }] -Complete src/TypeContextCompletion_Records.res 87:51 -posCursor:[87:51] posNoWhite:[87:50] Found expr:[87:3->87:62] -posCursor:[87:51] posNoWhite:[87:50] Found pattern:[87:29->87:54] -posCursor:[87:51] posNoWhite:[87:50] Found pattern:[87:42->87:53] -posCursor:[87:51] posNoWhite:[87:50] Found pattern:[87:46->87:52] -Ppat_construct Four:[87:46->87:50] -posCursor:[87:51] posNoWhite:[87:50] Found pattern:[87:50->87:52] -Ppat_construct ():[87:50->87:52] +Complete src/TypeContextCompletion_Records.res 89:51 +posCursor:[89:51] posNoWhite:[89:50] Found expr:[89:3->89:62] +posCursor:[89:51] posNoWhite:[89:50] Found pattern:[89:29->89:54] +posCursor:[89:51] posNoWhite:[89:50] Found pattern:[89:42->89:53] +posCursor:[89:51] posNoWhite:[89:50] Found pattern:[89:46->89:52] +Ppat_construct Four:[89:46->89:50] +posCursor:[89:51] posNoWhite:[89:50] Found pattern:[89:50->89:52] +Ppat_construct ():[89:50->89:52] Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)] seenIdents: [] -found variant: [{ "label": "TwentyFive", "kind": 4, @@ -263,17 +259,16 @@ found variant: "documentation": null }] -Complete src/TypeContextCompletion_Records.res 90:55 -posCursor:[90:55] posNoWhite:[90:54] Found expr:[90:3->90:66] -posCursor:[90:55] posNoWhite:[90:54] Found pattern:[90:29->90:58] -posCursor:[90:55] posNoWhite:[90:54] Found pattern:[90:42->90:57] -posCursor:[90:55] posNoWhite:[90:54] Found pattern:[90:46->90:56] -Ppat_construct Five:[90:46->90:50] -posCursor:[90:55] posNoWhite:[90:54] Found pattern:[90:50->90:57] -posCursor:[90:55] posNoWhite:[90:54] Found pattern:[90:54->90:55] -Ppat_construct O:[90:54->90:55] +Complete src/TypeContextCompletion_Records.res 92:55 +posCursor:[92:55] posNoWhite:[92:54] Found expr:[92:3->92:66] +posCursor:[92:55] posNoWhite:[92:54] Found pattern:[92:29->92:58] +posCursor:[92:55] posNoWhite:[92:54] Found pattern:[92:42->92:57] +posCursor:[92:55] posNoWhite:[92:54] Found pattern:[92:46->92:56] +Ppat_construct Five:[92:46->92:50] +posCursor:[92:55] posNoWhite:[92:54] Found pattern:[92:50->92:57] +posCursor:[92:55] posNoWhite:[92:54] Found pattern:[92:54->92:55] +Ppat_construct O:[92:54->92:55] Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)] seenIdents: [] -found variant: O [{ "label": "One", "kind": 4, @@ -282,17 +277,16 @@ found variant: O "documentation": null }] -Complete src/TypeContextCompletion_Records.res 93:63 -posCursor:[93:63] posNoWhite:[93:62] Found expr:[93:3->93:78] -posCursor:[93:63] posNoWhite:[93:62] Found pattern:[93:29->93:70] -posCursor:[93:63] posNoWhite:[93:62] Found pattern:[93:43->93:69] -posCursor:[93:63] posNoWhite:[93:62] Found pattern:[93:44->93:65] -Ppat_construct Some:[93:44->93:48] -posCursor:[93:63] posNoWhite:[93:62] Found pattern:[93:49->93:64] -posCursor:[93:63] posNoWhite:[93:62] Found pattern:[93:62->93:63] -Ppat_construct O:[93:62->93:63] +Complete src/TypeContextCompletion_Records.res 95:63 +posCursor:[95:63] posNoWhite:[95:62] Found expr:[95:3->95:78] +posCursor:[95:63] posNoWhite:[95:62] Found pattern:[95:29->95:70] +posCursor:[95:63] posNoWhite:[95:62] Found pattern:[95:43->95:69] +posCursor:[95:63] posNoWhite:[95:62] Found pattern:[95:44->95:65] +Ppat_construct Some:[95:44->95:48] +posCursor:[95:63] posNoWhite:[95:62] Found pattern:[95:49->95:64] +posCursor:[95:63] posNoWhite:[95:62] Found pattern:[95:62->95:63] +Ppat_construct O:[95:62->95:63] Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:fourthStuff, Tuple:0, Variant:Some(0), Polyvariant:WithPayload(0)] seenIdents: [] -found variant: O [{ "label": "One", "kind": 4, @@ -301,18 +295,17 @@ found variant: O "documentation": null }] -Complete src/TypeContextCompletion_Records.res 96:67 -posCursor:[96:67] posNoWhite:[96:66] Found expr:[96:3->96:78] -posCursor:[96:67] posNoWhite:[96:66] Found pattern:[96:29->96:70] -posCursor:[96:67] posNoWhite:[96:66] Found pattern:[96:42->96:69] -posCursor:[96:67] posNoWhite:[96:66] Found pattern:[96:46->96:68] -Ppat_construct Five:[96:46->96:50] -posCursor:[96:67] posNoWhite:[96:66] Found pattern:[96:50->96:69] -posCursor:[96:67] posNoWhite:[96:66] Found pattern:[96:54->96:67] -posCursor:[96:67] posNoWhite:[96:66] Found pattern:[96:66->96:67] -Ppat_construct T:[96:66->96:67] +Complete src/TypeContextCompletion_Records.res 98:67 +posCursor:[98:67] posNoWhite:[98:66] Found expr:[98:3->98:78] +posCursor:[98:67] posNoWhite:[98:66] Found pattern:[98:29->98:70] +posCursor:[98:67] posNoWhite:[98:66] Found pattern:[98:42->98:69] +posCursor:[98:67] posNoWhite:[98:66] Found pattern:[98:46->98:68] +Ppat_construct Five:[98:46->98:50] +posCursor:[98:67] posNoWhite:[98:66] Found pattern:[98:50->98:69] +posCursor:[98:67] posNoWhite:[98:66] Found pattern:[98:54->98:67] +posCursor:[98:67] posNoWhite:[98:66] Found pattern:[98:66->98:67] +Ppat_construct T:[98:66->98:67] Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)] seenIdents: [One, Two, T] -found variant: T [{ "label": "Three(_)", "kind": 4, @@ -321,3 +314,67 @@ found variant: T "documentation": null }] +Complete src/TypeContextCompletion_Records.res 101:43 +posCursor:[101:43] posNoWhite:[101:42] Found expr:[101:3->101:52] +posCursor:[101:43] posNoWhite:[101:42] Found pattern:[101:29->101:44] +posCursor:[101:43] posNoWhite:[101:42] Found pattern:[101:42->101:43] +Ppat_construct S:[101:42->101:43] +Completable: CtypedContext(Value[someOtherValue])=S pattern: [RecordField:otherThing] seenIdents: [] +[{ + "label": "None", + "kind": 4, + "tags": [], + "detail": "None\n\n", + "documentation": null + }, { + "label": "Some(One)", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null + }, { + "label": "Some(Two)", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null + }, { + "label": "Some(Three(_))", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null + }, { + "label": "Some(Four(_))", + "kind": 4, + "tags": [], + "detail": "Four(someOtherVariant)\n\n", + "documentation": null + }, { + "label": "Some(Five(_))", + "kind": 4, + "tags": [], + "detail": "Five(someOtherVariant, someVariant)\n\n", + "documentation": null + }] + +Complete src/TypeContextCompletion_Records.res 104:39 +posCursor:[104:39] posNoWhite:[104:38] Found expr:[104:3->104:48] +posCursor:[104:39] posNoWhite:[104:38] Found pattern:[104:29->104:40] +posCursor:[104:39] posNoWhite:[104:38] Found pattern:[104:38->104:39] +Ppat_construct S:[104:38->104:39] +Completable: CtypedContext(Value[someOtherValue])=S pattern: [RecordField:other2] seenIdents: [] +[{ + "label": "None", + "kind": 4, + "tags": [], + "detail": "None\n\n", + "documentation": null + }, { + "label": "Some(_)", + "kind": 4, + "tags": [], + "detail": "Some(_)\n\n", + "documentation": null + }] + From 928e84ef2876482ace278b754ac702f8188b73c1 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 11 Aug 2022 10:35:38 +0200 Subject: [PATCH 49/80] complete empty | patterns --- analysis/src/CompletionFrontEnd.ml | 10 +++++- .../src/TypeContextCompletion_Records.res | 3 ++ .../TypeContextCompletion_Records.res.txt | 33 +++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 22ac9320d..ec38ae11d 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -351,7 +351,15 @@ let rec findCompletableInPattern pattern ~path ~posBeforeCursor ~prefix pattern.Parsetree.ppat_loc |> CursorPosition.classifyLoc ~pos:posBeforeCursor with - | NoCursor | EmptyLoc -> None + | NoCursor -> None + | EmptyLoc -> ( + (* An empty location means the parser likely recovered from parsing an erronous pattern. + If we have at least one entry in the path list already, we know that we've at least + found _some_ context. We check that context and the char before the cursor to figure + out if we should complete for that path. *) + match (path, firstCharBeforeCursorNoWhite) with + | (Completable.Variant _ | Polyvariant _) :: _, Some '|' -> Some path + | _ -> None) | HasCursor -> ( match pattern.ppat_desc with | Ppat_construct ({txt = Lident "()"}, None) -> diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index fa6adc0f4..e02fea461 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -104,3 +104,6 @@ let someOtherValue: someRecordWithVariant = { // switch someOtherValue { | {other2: S} => () } // ^com + +// switch someOtherValue { | {thirdStuff: (_, Four(TwentyFive | ))} => () } +// ^com diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index c0ff430c3..9f0ad6da2 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -378,3 +378,36 @@ Completable: CtypedContext(Value[someOtherValue])=S pattern: [RecordField:other2 "documentation": null }] +Complete src/TypeContextCompletion_Records.res 107:64 +posCursor:[107:64] posNoWhite:[107:62] Found expr:[107:3->107:75] +posCursor:[107:64] posNoWhite:[107:62] Found pattern:[107:29->107:67] +posCursor:[107:64] posNoWhite:[107:62] Found pattern:[107:42->107:66] +posCursor:[107:64] posNoWhite:[107:62] Found pattern:[107:46->107:65] +Ppat_construct Four:[107:46->107:50] +Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)] seenIdents: [TwentyFive] +[{ + "label": "SixtyTwo", + "kind": 4, + "tags": [], + "detail": "SixtyTwo\n\n", + "documentation": null + }, { + "label": "someOtherValue", + "kind": 12, + "tags": [], + "detail": "someRecordWithVariant", + "documentation": null + }, { + "label": "getSomeVal", + "kind": 12, + "tags": [], + "detail": "(~irrelevant: int) => anotherRecord", + "documentation": null + }, { + "label": "someVal", + "kind": 12, + "tags": [], + "detail": "anotherRecord", + "documentation": null + }] + From d134b8b3daab5596982239e5e81a5b4a6f1d22bc Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 11 Aug 2022 10:51:35 +0200 Subject: [PATCH 50/80] fix only descending to record field if valid --- analysis/src/CompletionFrontEnd.ml | 9 ++++- .../src/TypeContextCompletion_Records.res | 4 ++ .../TypeContextCompletion_Records.res.txt | 40 +++++++++++++++---- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index ec38ae11d..3d47784c7 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -452,10 +452,15 @@ let rec findCompletableInPattern pattern ~path ~posBeforeCursor ~prefix fields |> List.map (fun ({Location.txt}, _) -> getSimpleFieldName txt) |> List.filter (fun name -> name <> fieldName); + (* let {whatever} = something <- parsed as a Ppat_var, in which case we don't want to consider this descending into a record field. *) + let newPath = + match pat.ppat_desc with + | Ppat_var _ -> path + | _ -> [Completable.RField {fieldName}] @ path + in pat |> findCompletableInPattern ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite ~seenIdents - ~path:([Completable.RField {fieldName}] @ path)) + ~firstCharBeforeCursorNoWhite ~seenIdents ~path:newPath) | Ppat_var {txt} -> prefix := txt; Some path diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index e02fea461..9e254e8de 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -42,9 +42,11 @@ let getSomeVal = (~irrelevant: int) => { // let {something: {whatIsThis, anotherLevel: {l}}} = someVal // ^com +// TODO: Broken - does not account for , // let {something: {whatIsThis, anotherLevel, }} = someVal // ^com +// TODO: Broken - does not account for , // let {something: {whatIsThis, ,anotherLevel}} = someVal // ^com @@ -54,6 +56,7 @@ let getSomeVal = (~irrelevant: int) => { // switch someVal { | {thirdThing: "1234"} => () | {} => () } // ^com +// TODO: Broken - does not account for , // switch someVal { | {thirdThing: "1234"} => () | {something: {whatIsThis, anotherLevel, }} => () } // ^com @@ -78,6 +81,7 @@ let someOtherValue: someRecordWithVariant = { thirdStuff: (someVal.something, One, None, 1), fourthStuff: (None, One), } +// TODO: Broken - does not filter idents // switch someOtherValue { | {something: Two | T} => () } // ^com diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 9f0ad6da2..843fc217c 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -1,14 +1,26 @@ Complete src/TypeContextCompletion_Records.res 16:15 posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:7->16:16] posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:8->16:15] -Completable: CtypedContext(Value[someVal])=another pattern: [RecordField:another] seenIdents: [] -[] +Completable: CtypedContext(Value[someVal])=another pattern: [] seenIdents: [] +[{ + "label": "anotherThing", + "kind": 5, + "tags": [], + "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }] Complete src/TypeContextCompletion_Records.res 19:23 posCursor:[19:23] posNoWhite:[19:22] Found pattern:[19:7->19:24] posCursor:[19:23] posNoWhite:[19:22] Found pattern:[19:22->19:23] -Completable: CtypedContext(Value[someVal])=s pattern: [RecordField:s] seenIdents: [anotherThing] -[] +Completable: CtypedContext(Value[someVal])=s pattern: [] seenIdents: [anotherThing] +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }] Complete src/TypeContextCompletion_Records.res 22:8 posCursor:[22:8] posNoWhite:[22:7] Found pattern:[22:7->22:9] @@ -104,8 +116,14 @@ posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:7->41:51] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:19->41:50] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:46->41:49] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:47->41:48] -Completable: CtypedContext(Value[someVal])=l pattern: [RecordField:something, RecordField:anotherLevel, RecordField:l] seenIdents: [] -[] +Completable: CtypedContext(Value[someVal])=l pattern: [RecordField:something, RecordField:anotherLevel] seenIdents: [] +[{ + "label": "level", + "kind": 5, + "tags": [], + "detail": "level: int\n\ntype anotherLevel = {level: int, someOtherArg: bool}", + "documentation": null + }] Complete src/TypeContextCompletion_Records.res 44:47 posCursor:[44:47] posNoWhite:[44:44] Found pattern:[44:7->44:49] @@ -121,8 +139,14 @@ Complete src/TypeContextCompletion_Records.res 50:44 posCursor:[50:44] posNoWhite:[50:43] Found expr:[50:3->50:54] posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:22->50:46] posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:42->50:45] -Completable: CtypedContext(Value[someVal])=som pattern: [RecordField:som] seenIdents: [thirdThing] -[] +Completable: CtypedContext(Value[someVal])=som pattern: [] seenIdents: [thirdThing] +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null + }] Complete src/TypeContextCompletion_Records.res 53:52 posCursor:[53:52] posNoWhite:[53:51] Found expr:[53:3->53:61] From 0d06fc6d373f65d747f60cc9f0f6dfde920034ee Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 11 Aug 2022 10:53:53 +0200 Subject: [PATCH 51/80] more filtering of idents --- analysis/src/CompletionFrontEnd.ml | 1 + .../src/TypeContextCompletion_Records.res | 2 +- .../TypeContextCompletion_Records.res.txt | 184 +++++++++--------- 3 files changed, 91 insertions(+), 96 deletions(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 3d47784c7..80fd1da97 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -465,6 +465,7 @@ let rec findCompletableInPattern pattern ~path ~posBeforeCursor ~prefix prefix := txt; Some path | Ppat_or (pat1, pat2) -> ( + seenIdents := findAlreadySeenIdents pattern; let rec findAllOrBranches pat ~branches = match pat.Parsetree.ppat_desc with | Ppat_or (pat1, pat2) -> diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index 9e254e8de..9a8870380 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -81,7 +81,7 @@ let someOtherValue: someRecordWithVariant = { thirdStuff: (someVal.something, One, None, 1), fourthStuff: (None, One), } -// TODO: Broken - does not filter idents + // switch someOtherValue { | {something: Two | T} => () } // ^com diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 843fc217c..ca12a0b68 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -125,20 +125,20 @@ Completable: CtypedContext(Value[someVal])=l pattern: [RecordField:something, Re "documentation": null }] -Complete src/TypeContextCompletion_Records.res 44:47 -posCursor:[44:47] posNoWhite:[44:44] Found pattern:[44:7->44:49] -posCursor:[44:47] posNoWhite:[44:44] Found pattern:[44:19->44:48] +Complete src/TypeContextCompletion_Records.res 45:47 +posCursor:[45:47] posNoWhite:[45:44] Found pattern:[45:7->45:49] +posCursor:[45:47] posNoWhite:[45:44] Found pattern:[45:19->45:48] [] -Complete src/TypeContextCompletion_Records.res 47:31 -posCursor:[47:31] posNoWhite:[47:30] Found pattern:[47:7->47:47] -posCursor:[47:31] posNoWhite:[47:30] Found pattern:[47:19->47:46] +Complete src/TypeContextCompletion_Records.res 49:31 +posCursor:[49:31] posNoWhite:[49:30] Found pattern:[49:7->49:47] +posCursor:[49:31] posNoWhite:[49:30] Found pattern:[49:19->49:46] [] -Complete src/TypeContextCompletion_Records.res 50:44 -posCursor:[50:44] posNoWhite:[50:43] Found expr:[50:3->50:54] -posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:22->50:46] -posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:42->50:45] +Complete src/TypeContextCompletion_Records.res 52:44 +posCursor:[52:44] posNoWhite:[52:43] Found expr:[52:3->52:54] +posCursor:[52:44] posNoWhite:[52:43] Found pattern:[52:22->52:46] +posCursor:[52:44] posNoWhite:[52:43] Found pattern:[52:42->52:45] Completable: CtypedContext(Value[someVal])=som pattern: [] seenIdents: [thirdThing] [{ "label": "something", @@ -148,9 +148,9 @@ Completable: CtypedContext(Value[someVal])=som pattern: [] seenIdents: [thirdThi "documentation": null }] -Complete src/TypeContextCompletion_Records.res 53:52 -posCursor:[53:52] posNoWhite:[53:51] Found expr:[53:3->53:61] -posCursor:[53:52] posNoWhite:[53:51] Found pattern:[53:51->53:53] +Complete src/TypeContextCompletion_Records.res 55:52 +posCursor:[55:52] posNoWhite:[55:51] Found expr:[55:3->55:61] +posCursor:[55:52] posNoWhite:[55:51] Found pattern:[55:51->55:53] Completable: CtypedContext(Value[someVal])="" pattern: [] seenIdents: [] [{ "label": "something", @@ -172,26 +172,20 @@ Completable: CtypedContext(Value[someVal])="" pattern: [] seenIdents: [] "documentation": null }] -Complete src/TypeContextCompletion_Records.res 56:89 -posCursor:[56:89] posNoWhite:[56:88] Found expr:[56:3->56:100] -posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:51->56:92] -posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:63->56:91] +Complete src/TypeContextCompletion_Records.res 59:89 +posCursor:[59:89] posNoWhite:[59:88] Found expr:[59:3->59:100] +posCursor:[59:89] posNoWhite:[59:88] Found pattern:[59:51->59:92] +posCursor:[59:89] posNoWhite:[59:88] Found pattern:[59:63->59:91] [] -Complete src/TypeContextCompletion_Records.res 80:48 -posCursor:[80:48] posNoWhite:[80:47] Found expr:[80:3->80:57] -posCursor:[80:48] posNoWhite:[80:47] Found pattern:[80:29->80:49] -posCursor:[80:48] posNoWhite:[80:47] Found pattern:[80:41->80:48] -posCursor:[80:48] posNoWhite:[80:47] Found pattern:[80:47->80:48] -Ppat_construct T:[80:47->80:48] -Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:something] seenIdents: [] +Complete src/TypeContextCompletion_Records.res 84:48 +posCursor:[84:48] posNoWhite:[84:47] Found expr:[84:3->84:57] +posCursor:[84:48] posNoWhite:[84:47] Found pattern:[84:29->84:49] +posCursor:[84:48] posNoWhite:[84:47] Found pattern:[84:41->84:48] +posCursor:[84:48] posNoWhite:[84:47] Found pattern:[84:47->84:48] +Ppat_construct T:[84:47->84:48] +Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:something] seenIdents: [Two, T] [{ - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\n", - "documentation": null - }, { "label": "Three(_)", "kind": 4, "tags": [], @@ -199,13 +193,13 @@ Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:someth "documentation": null }] -Complete src/TypeContextCompletion_Records.res 83:48 -posCursor:[83:48] posNoWhite:[83:47] Found expr:[83:3->83:58] -posCursor:[83:48] posNoWhite:[83:47] Found pattern:[83:29->83:50] -posCursor:[83:48] posNoWhite:[83:47] Found pattern:[83:42->83:49] -Ppat_construct Some:[83:42->83:46] -posCursor:[83:48] posNoWhite:[83:47] Found pattern:[83:47->83:48] -Ppat_construct T:[83:47->83:48] +Complete src/TypeContextCompletion_Records.res 87:48 +posCursor:[87:48] posNoWhite:[87:47] Found expr:[87:3->87:58] +posCursor:[87:48] posNoWhite:[87:47] Found pattern:[87:29->87:50] +posCursor:[87:48] posNoWhite:[87:47] Found pattern:[87:42->87:49] +Ppat_construct Some:[87:42->87:46] +posCursor:[87:48] posNoWhite:[87:47] Found pattern:[87:47->87:48] +Ppat_construct T:[87:47->87:48] Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:otherThing, Variant:Some(0)] seenIdents: [] [{ "label": "Two", @@ -221,12 +215,12 @@ Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:otherT "documentation": null }] -Complete src/TypeContextCompletion_Records.res 86:47 -posCursor:[86:47] posNoWhite:[86:46] Found expr:[86:3->86:57] -posCursor:[86:47] posNoWhite:[86:46] Found pattern:[86:29->86:49] -posCursor:[86:47] posNoWhite:[86:46] Found pattern:[86:42->86:48] -posCursor:[86:47] posNoWhite:[86:46] Found pattern:[86:46->86:47] -Ppat_construct T:[86:46->86:47] +Complete src/TypeContextCompletion_Records.res 90:47 +posCursor:[90:47] posNoWhite:[90:46] Found expr:[90:3->90:57] +posCursor:[90:47] posNoWhite:[90:46] Found pattern:[90:29->90:49] +posCursor:[90:47] posNoWhite:[90:46] Found pattern:[90:42->90:48] +posCursor:[90:47] posNoWhite:[90:46] Found pattern:[90:46->90:47] +Ppat_construct T:[90:46->90:47] Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:thirdStuff, Tuple:1] seenIdents: [] [{ "label": "Two", @@ -242,14 +236,14 @@ Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:thirdS "documentation": null }] -Complete src/TypeContextCompletion_Records.res 89:51 -posCursor:[89:51] posNoWhite:[89:50] Found expr:[89:3->89:62] -posCursor:[89:51] posNoWhite:[89:50] Found pattern:[89:29->89:54] -posCursor:[89:51] posNoWhite:[89:50] Found pattern:[89:42->89:53] -posCursor:[89:51] posNoWhite:[89:50] Found pattern:[89:46->89:52] -Ppat_construct Four:[89:46->89:50] -posCursor:[89:51] posNoWhite:[89:50] Found pattern:[89:50->89:52] -Ppat_construct ():[89:50->89:52] +Complete src/TypeContextCompletion_Records.res 93:51 +posCursor:[93:51] posNoWhite:[93:50] Found expr:[93:3->93:62] +posCursor:[93:51] posNoWhite:[93:50] Found pattern:[93:29->93:54] +posCursor:[93:51] posNoWhite:[93:50] Found pattern:[93:42->93:53] +posCursor:[93:51] posNoWhite:[93:50] Found pattern:[93:46->93:52] +Ppat_construct Four:[93:46->93:50] +posCursor:[93:51] posNoWhite:[93:50] Found pattern:[93:50->93:52] +Ppat_construct ():[93:50->93:52] Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)] seenIdents: [] [{ "label": "TwentyFive", @@ -283,15 +277,15 @@ Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:third "documentation": null }] -Complete src/TypeContextCompletion_Records.res 92:55 -posCursor:[92:55] posNoWhite:[92:54] Found expr:[92:3->92:66] -posCursor:[92:55] posNoWhite:[92:54] Found pattern:[92:29->92:58] -posCursor:[92:55] posNoWhite:[92:54] Found pattern:[92:42->92:57] -posCursor:[92:55] posNoWhite:[92:54] Found pattern:[92:46->92:56] -Ppat_construct Five:[92:46->92:50] -posCursor:[92:55] posNoWhite:[92:54] Found pattern:[92:50->92:57] -posCursor:[92:55] posNoWhite:[92:54] Found pattern:[92:54->92:55] -Ppat_construct O:[92:54->92:55] +Complete src/TypeContextCompletion_Records.res 96:55 +posCursor:[96:55] posNoWhite:[96:54] Found expr:[96:3->96:66] +posCursor:[96:55] posNoWhite:[96:54] Found pattern:[96:29->96:58] +posCursor:[96:55] posNoWhite:[96:54] Found pattern:[96:42->96:57] +posCursor:[96:55] posNoWhite:[96:54] Found pattern:[96:46->96:56] +Ppat_construct Five:[96:46->96:50] +posCursor:[96:55] posNoWhite:[96:54] Found pattern:[96:50->96:57] +posCursor:[96:55] posNoWhite:[96:54] Found pattern:[96:54->96:55] +Ppat_construct O:[96:54->96:55] Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)] seenIdents: [] [{ "label": "One", @@ -301,15 +295,15 @@ Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:thirdS "documentation": null }] -Complete src/TypeContextCompletion_Records.res 95:63 -posCursor:[95:63] posNoWhite:[95:62] Found expr:[95:3->95:78] -posCursor:[95:63] posNoWhite:[95:62] Found pattern:[95:29->95:70] -posCursor:[95:63] posNoWhite:[95:62] Found pattern:[95:43->95:69] -posCursor:[95:63] posNoWhite:[95:62] Found pattern:[95:44->95:65] -Ppat_construct Some:[95:44->95:48] -posCursor:[95:63] posNoWhite:[95:62] Found pattern:[95:49->95:64] -posCursor:[95:63] posNoWhite:[95:62] Found pattern:[95:62->95:63] -Ppat_construct O:[95:62->95:63] +Complete src/TypeContextCompletion_Records.res 99:63 +posCursor:[99:63] posNoWhite:[99:62] Found expr:[99:3->99:78] +posCursor:[99:63] posNoWhite:[99:62] Found pattern:[99:29->99:70] +posCursor:[99:63] posNoWhite:[99:62] Found pattern:[99:43->99:69] +posCursor:[99:63] posNoWhite:[99:62] Found pattern:[99:44->99:65] +Ppat_construct Some:[99:44->99:48] +posCursor:[99:63] posNoWhite:[99:62] Found pattern:[99:49->99:64] +posCursor:[99:63] posNoWhite:[99:62] Found pattern:[99:62->99:63] +Ppat_construct O:[99:62->99:63] Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:fourthStuff, Tuple:0, Variant:Some(0), Polyvariant:WithPayload(0)] seenIdents: [] [{ "label": "One", @@ -319,16 +313,16 @@ Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:fourth "documentation": null }] -Complete src/TypeContextCompletion_Records.res 98:67 -posCursor:[98:67] posNoWhite:[98:66] Found expr:[98:3->98:78] -posCursor:[98:67] posNoWhite:[98:66] Found pattern:[98:29->98:70] -posCursor:[98:67] posNoWhite:[98:66] Found pattern:[98:42->98:69] -posCursor:[98:67] posNoWhite:[98:66] Found pattern:[98:46->98:68] -Ppat_construct Five:[98:46->98:50] -posCursor:[98:67] posNoWhite:[98:66] Found pattern:[98:50->98:69] -posCursor:[98:67] posNoWhite:[98:66] Found pattern:[98:54->98:67] -posCursor:[98:67] posNoWhite:[98:66] Found pattern:[98:66->98:67] -Ppat_construct T:[98:66->98:67] +Complete src/TypeContextCompletion_Records.res 102:67 +posCursor:[102:67] posNoWhite:[102:66] Found expr:[102:3->102:78] +posCursor:[102:67] posNoWhite:[102:66] Found pattern:[102:29->102:70] +posCursor:[102:67] posNoWhite:[102:66] Found pattern:[102:42->102:69] +posCursor:[102:67] posNoWhite:[102:66] Found pattern:[102:46->102:68] +Ppat_construct Five:[102:46->102:50] +posCursor:[102:67] posNoWhite:[102:66] Found pattern:[102:50->102:69] +posCursor:[102:67] posNoWhite:[102:66] Found pattern:[102:54->102:67] +posCursor:[102:67] posNoWhite:[102:66] Found pattern:[102:66->102:67] +Ppat_construct T:[102:66->102:67] Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)] seenIdents: [One, Two, T] [{ "label": "Three(_)", @@ -338,11 +332,11 @@ Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:thirdS "documentation": null }] -Complete src/TypeContextCompletion_Records.res 101:43 -posCursor:[101:43] posNoWhite:[101:42] Found expr:[101:3->101:52] -posCursor:[101:43] posNoWhite:[101:42] Found pattern:[101:29->101:44] -posCursor:[101:43] posNoWhite:[101:42] Found pattern:[101:42->101:43] -Ppat_construct S:[101:42->101:43] +Complete src/TypeContextCompletion_Records.res 105:43 +posCursor:[105:43] posNoWhite:[105:42] Found expr:[105:3->105:52] +posCursor:[105:43] posNoWhite:[105:42] Found pattern:[105:29->105:44] +posCursor:[105:43] posNoWhite:[105:42] Found pattern:[105:42->105:43] +Ppat_construct S:[105:42->105:43] Completable: CtypedContext(Value[someOtherValue])=S pattern: [RecordField:otherThing] seenIdents: [] [{ "label": "None", @@ -382,11 +376,11 @@ Completable: CtypedContext(Value[someOtherValue])=S pattern: [RecordField:otherT "documentation": null }] -Complete src/TypeContextCompletion_Records.res 104:39 -posCursor:[104:39] posNoWhite:[104:38] Found expr:[104:3->104:48] -posCursor:[104:39] posNoWhite:[104:38] Found pattern:[104:29->104:40] -posCursor:[104:39] posNoWhite:[104:38] Found pattern:[104:38->104:39] -Ppat_construct S:[104:38->104:39] +Complete src/TypeContextCompletion_Records.res 108:39 +posCursor:[108:39] posNoWhite:[108:38] Found expr:[108:3->108:48] +posCursor:[108:39] posNoWhite:[108:38] Found pattern:[108:29->108:40] +posCursor:[108:39] posNoWhite:[108:38] Found pattern:[108:38->108:39] +Ppat_construct S:[108:38->108:39] Completable: CtypedContext(Value[someOtherValue])=S pattern: [RecordField:other2] seenIdents: [] [{ "label": "None", @@ -402,12 +396,12 @@ Completable: CtypedContext(Value[someOtherValue])=S pattern: [RecordField:other2 "documentation": null }] -Complete src/TypeContextCompletion_Records.res 107:64 -posCursor:[107:64] posNoWhite:[107:62] Found expr:[107:3->107:75] -posCursor:[107:64] posNoWhite:[107:62] Found pattern:[107:29->107:67] -posCursor:[107:64] posNoWhite:[107:62] Found pattern:[107:42->107:66] -posCursor:[107:64] posNoWhite:[107:62] Found pattern:[107:46->107:65] -Ppat_construct Four:[107:46->107:50] +Complete src/TypeContextCompletion_Records.res 111:64 +posCursor:[111:64] posNoWhite:[111:62] Found expr:[111:3->111:75] +posCursor:[111:64] posNoWhite:[111:62] Found pattern:[111:29->111:67] +posCursor:[111:64] posNoWhite:[111:62] Found pattern:[111:42->111:66] +posCursor:[111:64] posNoWhite:[111:62] Found pattern:[111:46->111:65] +Ppat_construct Four:[111:46->111:50] Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)] seenIdents: [TwentyFive] [{ "label": "SixtyTwo", From d2ef230b26e8ce0a11c01e8a29ec3791c4218bab Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 11 Aug 2022 11:03:47 +0200 Subject: [PATCH 52/80] fix record completion of empty , --- analysis/src/CompletionFrontEnd.ml | 20 +- .../src/TypeContextCompletion_Records.res | 3 - .../TypeContextCompletion_Records.res.txt | 203 ++++++++++-------- 3 files changed, 124 insertions(+), 102 deletions(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 80fd1da97..aaad62bd5 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -434,24 +434,28 @@ let rec findCompletableInPattern pattern ~path ~posBeforeCursor ~prefix ~path:([Completable.PTuple {itemNumber = tupleItemNum}] @ path)) | Ppat_record (fields, _) when List.length fields = 0 -> Some path | Ppat_record (fields, _) -> ( + let seenFields = + fields |> List.map (fun ({Location.txt}, _) -> getSimpleFieldName txt) + in let fieldWithCursor = fields - |> List.find_map (fun (loc, pat) -> + |> List.find_map (fun (loc, fieldPat) -> match - pat.Parsetree.ppat_loc + fieldPat.Parsetree.ppat_loc |> CursorPosition.classifyLoc ~pos:posBeforeCursor with | NoCursor -> None - | HasCursor | EmptyLoc -> Some (loc, pat)) + | HasCursor | EmptyLoc -> Some (loc, fieldPat)) in match fieldWithCursor with - | None -> None + | None -> + if firstCharBeforeCursorNoWhite = Some ',' then ( + seenIdents := seenFields; + Some path) + else None | Some (loc, pat) -> let fieldName = getSimpleFieldName loc.txt in - seenIdents := - fields - |> List.map (fun ({Location.txt}, _) -> getSimpleFieldName txt) - |> List.filter (fun name -> name <> fieldName); + seenIdents := seenFields |> List.filter (fun name -> name <> fieldName); (* let {whatever} = something <- parsed as a Ppat_var, in which case we don't want to consider this descending into a record field. *) let newPath = match pat.ppat_desc with diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index 9a8870380..a9cc6d14e 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -42,11 +42,9 @@ let getSomeVal = (~irrelevant: int) => { // let {something: {whatIsThis, anotherLevel: {l}}} = someVal // ^com -// TODO: Broken - does not account for , // let {something: {whatIsThis, anotherLevel, }} = someVal // ^com -// TODO: Broken - does not account for , // let {something: {whatIsThis, ,anotherLevel}} = someVal // ^com @@ -56,7 +54,6 @@ let getSomeVal = (~irrelevant: int) => { // switch someVal { | {thirdThing: "1234"} => () | {} => () } // ^com -// TODO: Broken - does not account for , // switch someVal { | {thirdThing: "1234"} => () | {something: {whatIsThis, anotherLevel, }} => () } // ^com diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index ca12a0b68..f7d154fa1 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -125,20 +125,34 @@ Completable: CtypedContext(Value[someVal])=l pattern: [RecordField:something, Re "documentation": null }] -Complete src/TypeContextCompletion_Records.res 45:47 -posCursor:[45:47] posNoWhite:[45:44] Found pattern:[45:7->45:49] -posCursor:[45:47] posNoWhite:[45:44] Found pattern:[45:19->45:48] -[] +Complete src/TypeContextCompletion_Records.res 44:47 +posCursor:[44:47] posNoWhite:[44:44] Found pattern:[44:7->44:49] +posCursor:[44:47] posNoWhite:[44:44] Found pattern:[44:19->44:48] +Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something] seenIdents: [whatIsThis, anotherLevel] +[{ + "label": "somethingElse", + "kind": 5, + "tags": [], + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null + }] -Complete src/TypeContextCompletion_Records.res 49:31 -posCursor:[49:31] posNoWhite:[49:30] Found pattern:[49:7->49:47] -posCursor:[49:31] posNoWhite:[49:30] Found pattern:[49:19->49:46] -[] +Complete src/TypeContextCompletion_Records.res 47:31 +posCursor:[47:31] posNoWhite:[47:30] Found pattern:[47:7->47:47] +posCursor:[47:31] posNoWhite:[47:30] Found pattern:[47:19->47:46] +Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something] seenIdents: [whatIsThis, anotherLevel] +[{ + "label": "somethingElse", + "kind": 5, + "tags": [], + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null + }] -Complete src/TypeContextCompletion_Records.res 52:44 -posCursor:[52:44] posNoWhite:[52:43] Found expr:[52:3->52:54] -posCursor:[52:44] posNoWhite:[52:43] Found pattern:[52:22->52:46] -posCursor:[52:44] posNoWhite:[52:43] Found pattern:[52:42->52:45] +Complete src/TypeContextCompletion_Records.res 50:44 +posCursor:[50:44] posNoWhite:[50:43] Found expr:[50:3->50:54] +posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:22->50:46] +posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:42->50:45] Completable: CtypedContext(Value[someVal])=som pattern: [] seenIdents: [thirdThing] [{ "label": "something", @@ -148,9 +162,9 @@ Completable: CtypedContext(Value[someVal])=som pattern: [] seenIdents: [thirdThi "documentation": null }] -Complete src/TypeContextCompletion_Records.res 55:52 -posCursor:[55:52] posNoWhite:[55:51] Found expr:[55:3->55:61] -posCursor:[55:52] posNoWhite:[55:51] Found pattern:[55:51->55:53] +Complete src/TypeContextCompletion_Records.res 53:52 +posCursor:[53:52] posNoWhite:[53:51] Found expr:[53:3->53:61] +posCursor:[53:52] posNoWhite:[53:51] Found pattern:[53:51->53:53] Completable: CtypedContext(Value[someVal])="" pattern: [] seenIdents: [] [{ "label": "something", @@ -172,18 +186,25 @@ Completable: CtypedContext(Value[someVal])="" pattern: [] seenIdents: [] "documentation": null }] -Complete src/TypeContextCompletion_Records.res 59:89 -posCursor:[59:89] posNoWhite:[59:88] Found expr:[59:3->59:100] -posCursor:[59:89] posNoWhite:[59:88] Found pattern:[59:51->59:92] -posCursor:[59:89] posNoWhite:[59:88] Found pattern:[59:63->59:91] -[] +Complete src/TypeContextCompletion_Records.res 56:89 +posCursor:[56:89] posNoWhite:[56:88] Found expr:[56:3->56:100] +posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:51->56:92] +posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:63->56:91] +Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something] seenIdents: [whatIsThis, anotherLevel] +[{ + "label": "somethingElse", + "kind": 5, + "tags": [], + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null + }] -Complete src/TypeContextCompletion_Records.res 84:48 -posCursor:[84:48] posNoWhite:[84:47] Found expr:[84:3->84:57] -posCursor:[84:48] posNoWhite:[84:47] Found pattern:[84:29->84:49] -posCursor:[84:48] posNoWhite:[84:47] Found pattern:[84:41->84:48] -posCursor:[84:48] posNoWhite:[84:47] Found pattern:[84:47->84:48] -Ppat_construct T:[84:47->84:48] +Complete src/TypeContextCompletion_Records.res 81:48 +posCursor:[81:48] posNoWhite:[81:47] Found expr:[81:3->81:57] +posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:29->81:49] +posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:41->81:48] +posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:47->81:48] +Ppat_construct T:[81:47->81:48] Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:something] seenIdents: [Two, T] [{ "label": "Three(_)", @@ -193,13 +214,13 @@ Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:someth "documentation": null }] -Complete src/TypeContextCompletion_Records.res 87:48 -posCursor:[87:48] posNoWhite:[87:47] Found expr:[87:3->87:58] -posCursor:[87:48] posNoWhite:[87:47] Found pattern:[87:29->87:50] -posCursor:[87:48] posNoWhite:[87:47] Found pattern:[87:42->87:49] -Ppat_construct Some:[87:42->87:46] -posCursor:[87:48] posNoWhite:[87:47] Found pattern:[87:47->87:48] -Ppat_construct T:[87:47->87:48] +Complete src/TypeContextCompletion_Records.res 84:48 +posCursor:[84:48] posNoWhite:[84:47] Found expr:[84:3->84:58] +posCursor:[84:48] posNoWhite:[84:47] Found pattern:[84:29->84:50] +posCursor:[84:48] posNoWhite:[84:47] Found pattern:[84:42->84:49] +Ppat_construct Some:[84:42->84:46] +posCursor:[84:48] posNoWhite:[84:47] Found pattern:[84:47->84:48] +Ppat_construct T:[84:47->84:48] Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:otherThing, Variant:Some(0)] seenIdents: [] [{ "label": "Two", @@ -215,12 +236,12 @@ Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:otherT "documentation": null }] -Complete src/TypeContextCompletion_Records.res 90:47 -posCursor:[90:47] posNoWhite:[90:46] Found expr:[90:3->90:57] -posCursor:[90:47] posNoWhite:[90:46] Found pattern:[90:29->90:49] -posCursor:[90:47] posNoWhite:[90:46] Found pattern:[90:42->90:48] -posCursor:[90:47] posNoWhite:[90:46] Found pattern:[90:46->90:47] -Ppat_construct T:[90:46->90:47] +Complete src/TypeContextCompletion_Records.res 87:47 +posCursor:[87:47] posNoWhite:[87:46] Found expr:[87:3->87:57] +posCursor:[87:47] posNoWhite:[87:46] Found pattern:[87:29->87:49] +posCursor:[87:47] posNoWhite:[87:46] Found pattern:[87:42->87:48] +posCursor:[87:47] posNoWhite:[87:46] Found pattern:[87:46->87:47] +Ppat_construct T:[87:46->87:47] Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:thirdStuff, Tuple:1] seenIdents: [] [{ "label": "Two", @@ -236,14 +257,14 @@ Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:thirdS "documentation": null }] -Complete src/TypeContextCompletion_Records.res 93:51 -posCursor:[93:51] posNoWhite:[93:50] Found expr:[93:3->93:62] -posCursor:[93:51] posNoWhite:[93:50] Found pattern:[93:29->93:54] -posCursor:[93:51] posNoWhite:[93:50] Found pattern:[93:42->93:53] -posCursor:[93:51] posNoWhite:[93:50] Found pattern:[93:46->93:52] -Ppat_construct Four:[93:46->93:50] -posCursor:[93:51] posNoWhite:[93:50] Found pattern:[93:50->93:52] -Ppat_construct ():[93:50->93:52] +Complete src/TypeContextCompletion_Records.res 90:51 +posCursor:[90:51] posNoWhite:[90:50] Found expr:[90:3->90:62] +posCursor:[90:51] posNoWhite:[90:50] Found pattern:[90:29->90:54] +posCursor:[90:51] posNoWhite:[90:50] Found pattern:[90:42->90:53] +posCursor:[90:51] posNoWhite:[90:50] Found pattern:[90:46->90:52] +Ppat_construct Four:[90:46->90:50] +posCursor:[90:51] posNoWhite:[90:50] Found pattern:[90:50->90:52] +Ppat_construct ():[90:50->90:52] Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)] seenIdents: [] [{ "label": "TwentyFive", @@ -277,15 +298,15 @@ Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:third "documentation": null }] -Complete src/TypeContextCompletion_Records.res 96:55 -posCursor:[96:55] posNoWhite:[96:54] Found expr:[96:3->96:66] -posCursor:[96:55] posNoWhite:[96:54] Found pattern:[96:29->96:58] -posCursor:[96:55] posNoWhite:[96:54] Found pattern:[96:42->96:57] -posCursor:[96:55] posNoWhite:[96:54] Found pattern:[96:46->96:56] -Ppat_construct Five:[96:46->96:50] -posCursor:[96:55] posNoWhite:[96:54] Found pattern:[96:50->96:57] -posCursor:[96:55] posNoWhite:[96:54] Found pattern:[96:54->96:55] -Ppat_construct O:[96:54->96:55] +Complete src/TypeContextCompletion_Records.res 93:55 +posCursor:[93:55] posNoWhite:[93:54] Found expr:[93:3->93:66] +posCursor:[93:55] posNoWhite:[93:54] Found pattern:[93:29->93:58] +posCursor:[93:55] posNoWhite:[93:54] Found pattern:[93:42->93:57] +posCursor:[93:55] posNoWhite:[93:54] Found pattern:[93:46->93:56] +Ppat_construct Five:[93:46->93:50] +posCursor:[93:55] posNoWhite:[93:54] Found pattern:[93:50->93:57] +posCursor:[93:55] posNoWhite:[93:54] Found pattern:[93:54->93:55] +Ppat_construct O:[93:54->93:55] Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)] seenIdents: [] [{ "label": "One", @@ -295,15 +316,15 @@ Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:thirdS "documentation": null }] -Complete src/TypeContextCompletion_Records.res 99:63 -posCursor:[99:63] posNoWhite:[99:62] Found expr:[99:3->99:78] -posCursor:[99:63] posNoWhite:[99:62] Found pattern:[99:29->99:70] -posCursor:[99:63] posNoWhite:[99:62] Found pattern:[99:43->99:69] -posCursor:[99:63] posNoWhite:[99:62] Found pattern:[99:44->99:65] -Ppat_construct Some:[99:44->99:48] -posCursor:[99:63] posNoWhite:[99:62] Found pattern:[99:49->99:64] -posCursor:[99:63] posNoWhite:[99:62] Found pattern:[99:62->99:63] -Ppat_construct O:[99:62->99:63] +Complete src/TypeContextCompletion_Records.res 96:63 +posCursor:[96:63] posNoWhite:[96:62] Found expr:[96:3->96:78] +posCursor:[96:63] posNoWhite:[96:62] Found pattern:[96:29->96:70] +posCursor:[96:63] posNoWhite:[96:62] Found pattern:[96:43->96:69] +posCursor:[96:63] posNoWhite:[96:62] Found pattern:[96:44->96:65] +Ppat_construct Some:[96:44->96:48] +posCursor:[96:63] posNoWhite:[96:62] Found pattern:[96:49->96:64] +posCursor:[96:63] posNoWhite:[96:62] Found pattern:[96:62->96:63] +Ppat_construct O:[96:62->96:63] Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:fourthStuff, Tuple:0, Variant:Some(0), Polyvariant:WithPayload(0)] seenIdents: [] [{ "label": "One", @@ -313,16 +334,16 @@ Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:fourth "documentation": null }] -Complete src/TypeContextCompletion_Records.res 102:67 -posCursor:[102:67] posNoWhite:[102:66] Found expr:[102:3->102:78] -posCursor:[102:67] posNoWhite:[102:66] Found pattern:[102:29->102:70] -posCursor:[102:67] posNoWhite:[102:66] Found pattern:[102:42->102:69] -posCursor:[102:67] posNoWhite:[102:66] Found pattern:[102:46->102:68] -Ppat_construct Five:[102:46->102:50] -posCursor:[102:67] posNoWhite:[102:66] Found pattern:[102:50->102:69] -posCursor:[102:67] posNoWhite:[102:66] Found pattern:[102:54->102:67] -posCursor:[102:67] posNoWhite:[102:66] Found pattern:[102:66->102:67] -Ppat_construct T:[102:66->102:67] +Complete src/TypeContextCompletion_Records.res 99:67 +posCursor:[99:67] posNoWhite:[99:66] Found expr:[99:3->99:78] +posCursor:[99:67] posNoWhite:[99:66] Found pattern:[99:29->99:70] +posCursor:[99:67] posNoWhite:[99:66] Found pattern:[99:42->99:69] +posCursor:[99:67] posNoWhite:[99:66] Found pattern:[99:46->99:68] +Ppat_construct Five:[99:46->99:50] +posCursor:[99:67] posNoWhite:[99:66] Found pattern:[99:50->99:69] +posCursor:[99:67] posNoWhite:[99:66] Found pattern:[99:54->99:67] +posCursor:[99:67] posNoWhite:[99:66] Found pattern:[99:66->99:67] +Ppat_construct T:[99:66->99:67] Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)] seenIdents: [One, Two, T] [{ "label": "Three(_)", @@ -332,11 +353,11 @@ Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:thirdS "documentation": null }] -Complete src/TypeContextCompletion_Records.res 105:43 -posCursor:[105:43] posNoWhite:[105:42] Found expr:[105:3->105:52] -posCursor:[105:43] posNoWhite:[105:42] Found pattern:[105:29->105:44] -posCursor:[105:43] posNoWhite:[105:42] Found pattern:[105:42->105:43] -Ppat_construct S:[105:42->105:43] +Complete src/TypeContextCompletion_Records.res 102:43 +posCursor:[102:43] posNoWhite:[102:42] Found expr:[102:3->102:52] +posCursor:[102:43] posNoWhite:[102:42] Found pattern:[102:29->102:44] +posCursor:[102:43] posNoWhite:[102:42] Found pattern:[102:42->102:43] +Ppat_construct S:[102:42->102:43] Completable: CtypedContext(Value[someOtherValue])=S pattern: [RecordField:otherThing] seenIdents: [] [{ "label": "None", @@ -376,11 +397,11 @@ Completable: CtypedContext(Value[someOtherValue])=S pattern: [RecordField:otherT "documentation": null }] -Complete src/TypeContextCompletion_Records.res 108:39 -posCursor:[108:39] posNoWhite:[108:38] Found expr:[108:3->108:48] -posCursor:[108:39] posNoWhite:[108:38] Found pattern:[108:29->108:40] -posCursor:[108:39] posNoWhite:[108:38] Found pattern:[108:38->108:39] -Ppat_construct S:[108:38->108:39] +Complete src/TypeContextCompletion_Records.res 105:39 +posCursor:[105:39] posNoWhite:[105:38] Found expr:[105:3->105:48] +posCursor:[105:39] posNoWhite:[105:38] Found pattern:[105:29->105:40] +posCursor:[105:39] posNoWhite:[105:38] Found pattern:[105:38->105:39] +Ppat_construct S:[105:38->105:39] Completable: CtypedContext(Value[someOtherValue])=S pattern: [RecordField:other2] seenIdents: [] [{ "label": "None", @@ -396,12 +417,12 @@ Completable: CtypedContext(Value[someOtherValue])=S pattern: [RecordField:other2 "documentation": null }] -Complete src/TypeContextCompletion_Records.res 111:64 -posCursor:[111:64] posNoWhite:[111:62] Found expr:[111:3->111:75] -posCursor:[111:64] posNoWhite:[111:62] Found pattern:[111:29->111:67] -posCursor:[111:64] posNoWhite:[111:62] Found pattern:[111:42->111:66] -posCursor:[111:64] posNoWhite:[111:62] Found pattern:[111:46->111:65] -Ppat_construct Four:[111:46->111:50] +Complete src/TypeContextCompletion_Records.res 108:64 +posCursor:[108:64] posNoWhite:[108:62] Found expr:[108:3->108:75] +posCursor:[108:64] posNoWhite:[108:62] Found pattern:[108:29->108:67] +posCursor:[108:64] posNoWhite:[108:62] Found pattern:[108:42->108:66] +posCursor:[108:64] posNoWhite:[108:62] Found pattern:[108:46->108:65] +Ppat_construct Four:[108:46->108:50] Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)] seenIdents: [TwentyFive] [{ "label": "SixtyTwo", From 013680ee5f61cea35c378fb54f4d873741768b0f Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 11 Aug 2022 11:11:00 +0200 Subject: [PATCH 53/80] temp disable local completions + constructor completions in general scope, to make testing a bit easier/reduce false positives --- analysis/src/CompletionBackEnd.ml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 44150a0b7..b9d9b7cfd 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -940,14 +940,14 @@ let findLocalCompletionsForTypeExpr ~(localTables : LocalTables.t) ~env ~prefix let findLocalCompletionsForValuesAndConstructors ~(localTables : LocalTables.t) ~env ~prefix ~exact ~opens ~scope = localTables |> LocalTables.populateValues ~env; - localTables |> LocalTables.populateConstructors ~env; + (*localTables |> LocalTables.populateConstructors ~env;*) localTables |> LocalTables.populateModules ~env; scope |> Scope.iterValuesBeforeFirstOpen (processLocalValue ~prefix ~exact ~env ~localTables); - scope - |> Scope.iterConstructorsBeforeFirstOpen - (processLocalConstructor ~prefix ~exact ~env ~localTables); + (*scope + |> Scope.iterConstructorsBeforeFirstOpen + (processLocalConstructor ~prefix ~exact ~env ~localTables);*) scope |> Scope.iterModulesBeforeFirstOpen (processLocalModule ~prefix ~exact ~env ~localTables); @@ -960,9 +960,9 @@ let findLocalCompletionsForValuesAndConstructors ~(localTables : LocalTables.t) scope |> Scope.iterValuesAfterFirstOpen (processLocalValue ~prefix ~exact ~env ~localTables); - scope - |> Scope.iterConstructorsAfterFirstOpen - (processLocalConstructor ~prefix ~exact ~env ~localTables); + (*scope + |> Scope.iterConstructorsAfterFirstOpen + (processLocalConstructor ~prefix ~exact ~env ~localTables);*) scope |> Scope.iterModulesAfterFirstOpen (processLocalModule ~prefix ~exact ~env ~localTables); @@ -1993,13 +1993,13 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i ~env) in (* TODO: Patterns should not include local completions *) - let localCompletions = + let _localCompletions = typ |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix ~exact:false ~opens ~scope in [Completion.create ~name:"None" ~kind:OptionNone ~env] - @ constructorCompletions @ localCompletions + @ constructorCompletions | CPolyVariant {constructors} -> (* TOOD: Unify with other variant completion handler *) let constructorCompletions = @@ -2018,13 +2018,13 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i ~kind:(PolyvariantConstructor constructor) ~env) in (* TODO: Patterns should not include local completions *) - let localCompletions = + let _localCompletions = typ |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix ~exact:false ~opens ~scope in [Completion.create ~name:"None" ~kind:OptionNone ~env] - @ constructorCompletions @ localCompletions + @ constructorCompletions | _ -> [ Completion.create ~name:"None" ~kind:OptionNone ~env; @@ -2046,12 +2046,12 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i ) ~kind:(PolyvariantConstructor constructor) ~env) in - let localCompletions = + let _localCompletions = typ |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix ~exact:false ~opens ~scope in - constructorCompletions @ localCompletions + constructorCompletions | Some (CVariant {constructors}) -> let constructorCompletions = constructors @@ -2073,12 +2073,12 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i ~kind:(Constructor (constructor, "")) ~env) in - let localCompletions = + let _localCompletions = typ |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix ~exact:false ~opens ~scope in - constructorCompletions @ localCompletions + constructorCompletions | Some (CRecord {fields; decl; name}) -> fields |> List.filter (fun (field : field) -> From 303eb5759f181bbd04968f2c1b8ad1653a5463f2 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 11 Aug 2022 11:11:59 +0200 Subject: [PATCH 54/80] commit test output from last commit --- .../tests/src/expected/Completion.res.txt | 26 +------- .../TypeContextCompletion_Jsx.res.txt | 60 ----------------- ...ontextCompletion_LabelledArguments.res.txt | 66 ------------------- .../TypeContextCompletion_Records.res.txt | 36 ---------- 4 files changed, 1 insertion(+), 187 deletions(-) diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index 12dcf751e..cfe09d7bf 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -796,13 +796,7 @@ Complete src/Completion.res 179:13 posCursor:[179:13] posNoWhite:[179:12] Found expr:[179:11->179:13] Pexp_construct As:[179:11->179:13] None Completable: Cpath Value[As] -[{ - "label": "Asterix", - "kind": 4, - "tags": [], - "detail": "Asterix\n\ntype z = Allo | Asterix | Baba", - "documentation": null - }] +[] Complete src/Completion.res 182:17 Pmod_ident For:[182:14->182:17] @@ -1011,12 +1005,6 @@ Complete src/Completion.res 268:21 Ptype_variant unary SomeLocal:[268:12->268:21] Completable: Cpath Value[SomeLocal] [{ - "label": "SomeLocalVariantItem", - "kind": 4, - "tags": [], - "detail": "SomeLocalVariantItem\n\ntype someLocalVariant = SomeLocalVariantItem", - "documentation": null - }, { "label": "SomeLocalModule", "kind": 9, "tags": [], @@ -1386,18 +1374,6 @@ posCursor:[362:8] posNoWhite:[362:7] Found pattern:[362:7->362:8] Ppat_construct T:[362:7->362:8] Completable: Cpath Value[T] [{ - "label": "That", - "kind": 4, - "tags": [], - "detail": "That\n\ntype v = This | That", - "documentation": null - }, { - "label": "This", - "kind": 4, - "tags": [], - "detail": "This\n\ntype v = This | That", - "documentation": null - }, { "label": "TableclothMap", "kind": 9, "tags": [], diff --git a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt index 2dc03adb0..47d8fff36 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt @@ -50,18 +50,6 @@ Completable: CtypedContext(JsxProp())="" "tags": [], "detail": "Six(option, int)\n\n", "documentation": null - }, { - "label": "someValue", - "kind": 12, - "tags": [], - "detail": "someVariant", - "documentation": null - }, { - "label": "SomeComponent", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null }] Complete src/TypeContextCompletion_Jsx.res 26:39 @@ -104,18 +92,6 @@ Completable: CtypedContext(JsxProp())="" "tags": [], "detail": "Six(option, int)\n\n", "documentation": null - }, { - "label": "someValue", - "kind": 12, - "tags": [], - "detail": "someVariant", - "documentation": null - }, { - "label": "SomeComponent", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null }] Complete src/TypeContextCompletion_Jsx.res 29:39 @@ -160,18 +136,6 @@ Completable: CtypedContext(JsxProp())="" "tags": [], "detail": "Bar\n\n", "documentation": null - }, { - "label": "someValue", - "kind": 12, - "tags": [], - "detail": "someVariant", - "documentation": null - }, { - "label": "SomeComponent", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null }] Complete src/TypeContextCompletion_Jsx.res 38:37 @@ -214,18 +178,6 @@ Completable: CtypedContext(JsxProp())="" "tags": [], "detail": "#four", "documentation": null - }, { - "label": "someValue", - "kind": 12, - "tags": [], - "detail": "someVariant", - "documentation": null - }, { - "label": "SomeComponent", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null }] Complete src/TypeContextCompletion_Jsx.res 41:38 @@ -268,18 +220,6 @@ Completable: CtypedContext(JsxProp())="" "tags": [], "detail": "#four", "documentation": null - }, { - "label": "someValue", - "kind": 12, - "tags": [], - "detail": "someVariant", - "documentation": null - }, { - "label": "SomeComponent", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null }] Complete src/TypeContextCompletion_Jsx.res 44:39 diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index 2e2582bf8..147857e10 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -55,18 +55,6 @@ Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))="" "tags": [], "detail": "Six(option, int)\n\n", "documentation": null - }, { - "label": "someVariantToString", - "kind": 12, - "tags": [], - "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", - "documentation": null - }, { - "label": "thisIsAValue", - "kind": 12, - "tags": [], - "detail": "someVariant", - "documentation": null }] Complete src/TypeContextCompletion_LabelledArguments.res 28:45 @@ -109,18 +97,6 @@ Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))="" "tags": [], "detail": "Six(option, int)\n\n", "documentation": null - }, { - "label": "someVariantToString", - "kind": 12, - "tags": [], - "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", - "documentation": null - }, { - "label": "thisIsAValue", - "kind": 12, - "tags": [], - "detail": "someVariant", - "documentation": null }] Complete src/TypeContextCompletion_LabelledArguments.res 31:45 @@ -221,18 +197,6 @@ Completable: CtypedContext(NamedArg(anotherThing, Value[someVariantToString]))=" "tags": [], "detail": "Bar\n\n", "documentation": null - }, { - "label": "someVariantToString", - "kind": 12, - "tags": [], - "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", - "documentation": null - }, { - "label": "thisIsAValue", - "kind": 12, - "tags": [], - "detail": "someVariant", - "documentation": null }] Complete src/TypeContextCompletion_LabelledArguments.res 43:43 @@ -275,18 +239,6 @@ Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))="" "tags": [], "detail": "#four", "documentation": null - }, { - "label": "someVariantToString", - "kind": 12, - "tags": [], - "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", - "documentation": null - }, { - "label": "thisIsAValue", - "kind": 12, - "tags": [], - "detail": "someVariant", - "documentation": null }] Complete src/TypeContextCompletion_LabelledArguments.res 46:44 @@ -329,18 +281,6 @@ Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))="" "tags": [], "detail": "#four", "documentation": null - }, { - "label": "someVariantToString", - "kind": 12, - "tags": [], - "detail": "(\n ~someVariant: someVariant,\n ~anotherThing: TypeDefinition.variant,\n ~thirdThing: otherVariant,\n) => string", - "documentation": null - }, { - "label": "thisIsAValue", - "kind": 12, - "tags": [], - "detail": "someVariant", - "documentation": null }] Complete src/TypeContextCompletion_LabelledArguments.res 49:45 @@ -359,12 +299,6 @@ Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))=t "tags": [], "detail": "#two", "documentation": null - }, { - "label": "thisIsAValue", - "kind": 12, - "tags": [], - "detail": "someVariant", - "documentation": null }] Complete src/TypeContextCompletion_LabelledArguments.res 52:45 diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index f7d154fa1..3e8b9b6ba 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -278,24 +278,6 @@ Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:third "tags": [], "detail": "SixtyTwo\n\n", "documentation": null - }, { - "label": "someOtherValue", - "kind": 12, - "tags": [], - "detail": "someRecordWithVariant", - "documentation": null - }, { - "label": "getSomeVal", - "kind": 12, - "tags": [], - "detail": "(~irrelevant: int) => anotherRecord", - "documentation": null - }, { - "label": "someVal", - "kind": 12, - "tags": [], - "detail": "anotherRecord", - "documentation": null }] Complete src/TypeContextCompletion_Records.res 93:55 @@ -430,23 +412,5 @@ Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:third "tags": [], "detail": "SixtyTwo\n\n", "documentation": null - }, { - "label": "someOtherValue", - "kind": 12, - "tags": [], - "detail": "someRecordWithVariant", - "documentation": null - }, { - "label": "getSomeVal", - "kind": 12, - "tags": [], - "detail": "(~irrelevant: int) => anotherRecord", - "documentation": null - }, { - "label": "someVal", - "kind": 12, - "tags": [], - "detail": "anotherRecord", - "documentation": null }] From 858be8fcc2f0180d5f60637a3123c7b8f36ed074 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 11 Aug 2022 11:20:02 +0200 Subject: [PATCH 55/80] handle completing empty patterns in records --- analysis/src/CompletionFrontEnd.ml | 5 +++++ .../src/TypeContextCompletion_Records.res | 3 +++ .../TypeContextCompletion_Records.res.txt | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index aaad62bd5..be83b6d44 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -358,7 +358,12 @@ let rec findCompletableInPattern pattern ~path ~posBeforeCursor ~prefix found _some_ context. We check that context and the char before the cursor to figure out if we should complete for that path. *) match (path, firstCharBeforeCursorNoWhite) with + (* Handles: One | Two | *) | (Completable.Variant _ | Polyvariant _) :: _, Some '|' -> Some path + (* Handles: {someField: } *) + | RField _ :: _, Some ':' -> + (* TODO: This should handle when the last path item is a record field, at which point we'll also need to insert the record syntax when completing, or we yield broken syntax. *) + Some path | _ -> None) | HasCursor -> ( match pattern.ppat_desc with diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index a9cc6d14e..a1a9330bf 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -108,3 +108,6 @@ let someOtherValue: someRecordWithVariant = { // switch someOtherValue { | {thirdStuff: (_, Four(TwentyFive | ))} => () } // ^com + +// switch someOtherValue { | {other2: } => () } +// ^com diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 3e8b9b6ba..94389300d 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -414,3 +414,21 @@ Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:third "documentation": null }] +Complete src/TypeContextCompletion_Records.res 111:38 +posCursor:[111:38] posNoWhite:[111:36] Found expr:[111:3->111:47] +posCursor:[111:38] posNoWhite:[111:36] Found pattern:[111:29->111:39] +Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:other2] seenIdents: [] +[{ + "label": "None", + "kind": 4, + "tags": [], + "detail": "None\n\n", + "documentation": null + }, { + "label": "Some(_)", + "kind": 4, + "tags": [], + "detail": "Some(_)\n\n", + "documentation": null + }] + From d5ced339f377877aeead215d1cb915c1a935ba1f Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 11 Aug 2022 15:58:52 +0200 Subject: [PATCH 56/80] complete booleans --- analysis/src/CompletionBackEnd.ml | 16 + analysis/src/CompletionFrontEnd.ml | 7 +- analysis/src/SharedTypes.ml | 3 +- .../src/TypeContextCompletion_Records.res | 10 + .../TypeContextCompletion_Records.res.txt | 1084 +++++++++++++++++ 5 files changed, 1117 insertions(+), 3 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index b9d9b7cfd..abaf38026 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -713,6 +713,7 @@ let detail name (kind : Completion.kind) = | Constructor (c, s) -> showConstructor c ^ "\n\n" ^ s | OptionNone -> "None\n\n" | OptionSome -> "Some(_)\n\n" + | Bool -> "boolean\n\n" | PolyvariantConstructor {name; payload} -> ( "#" ^ name ^ @@ -1054,6 +1055,7 @@ type extractedType = | Polyvariant of QueryEnv.t * SharedTypes.polyVariantConstructor list | Tuple of QueryEnv.t * Types.type_expr list | Toption of QueryEnv.t * Types.type_expr + | Tbool of QueryEnv.t (* This is a more general extraction function for pulling out the type of a type_expr. We already have other similar functions, but they are all specialized on something (variants, records, etc). *) let rec extractType ~env ~package (t : Types.type_expr) = @@ -1062,6 +1064,9 @@ let rec extractType ~env ~package (t : Types.type_expr) = | Tconstr (Path.Pident {name = "option"}, [payloadTypeExpr], _) -> (* Handle option. TODO: Look up how the compiler does this and copy that behavior. *) Some (Toption (env, payloadTypeExpr)) + | Tconstr (Path.Pident {name = "bool"}, [], _) -> + (* Handle bool. TODO: Look up how the compiler does this and copy that behavior. *) + Some (Tbool env) | Tconstr (path, _, _) -> ( match References.digConstructor ~env ~package path with | Some (env, {item = {decl = {type_manifest = Some t1}}}) -> @@ -1436,6 +1441,7 @@ type completable = | CVariant of {constructors: Constructor.t list} | CPolyVariant of {constructors: polyVariantConstructor list} | COptional of completable + | CBool let rec typeExprToCompletable typ ~env ~package = match typ |> extractType ~env ~package with @@ -1444,6 +1450,7 @@ let rec typeExprToCompletable typ ~env ~package = | Some (Declared (_, {item = {kind = Variant constructors}})) -> Some (CVariant {constructors}) | Some (Polyvariant (_, constructors)) -> Some (CPolyVariant {constructors}) + | Some (Tbool _) -> Some CBool | Some (Toption (env, typ)) -> ( match typ |> typeExprToCompletable ~env ~package with | None -> None @@ -1965,6 +1972,15 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i | Some typ -> ( match typ |> findTypeInContext ~env ~nestedContextPath ~package with | None -> [] + | Some CBool -> + ["false"; "true"] + |> List.filter (fun boolEntry -> + Utils.startsWith boolEntry prefix + && not + (alreadySeenIdents + |> List.exists (fun seenIdent -> seenIdent = boolEntry))) + |> List.map (fun boolEntry -> + Completion.create ~name:boolEntry ~kind:Bool ~env) | Some (COptional completable) -> ( match completable with | CVariant {constructors} -> diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index be83b6d44..afbbc2924 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -461,10 +461,13 @@ let rec findCompletableInPattern pattern ~path ~posBeforeCursor ~prefix | Some (loc, pat) -> let fieldName = getSimpleFieldName loc.txt in seenIdents := seenFields |> List.filter (fun name -> name <> fieldName); - (* let {whatever} = something <- parsed as a Ppat_var, in which case we don't want to consider this descending into a record field. *) + let newPath = match pat.ppat_desc with - | Ppat_var _ -> path + | Ppat_var {txt} when txt = fieldName -> + (* let {something} = whatever <- shorthand for let {something:something}, which is just an alias, + so we don't want to consider it entering the record field. *) + path | _ -> [Completable.RField {fieldName}] @ path in pat diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 87ac76ecb..7789ce11c 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -235,6 +235,7 @@ module Completion = struct | FileModule of string | OptionNone | OptionSome + | Bool type t = { name: string; @@ -258,7 +259,7 @@ module Completion = struct | Label _ -> 4 | Field (_, _) -> 5 | Type _ -> 22 - | Value _ -> 12 + | Value _ | Bool -> 12 end module Env = struct diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index a1a9330bf..9a5434e01 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -111,3 +111,13 @@ let someOtherValue: someRecordWithVariant = { // switch someOtherValue { | {other2: } => () } // ^com + +// TODO: Broken +// switch someVal { | {something: {whatIsThis: false | } } => () } +// ^com + +// switch someVal { | {something: {whatIsThis: } } => () } +// ^com + +// switch someVal { | {something: {whatIsThis: fa } } => () } +// ^com diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 94389300d..a30c223ad 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -432,3 +432,1087 @@ Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:other "documentation": null }] +Complete src/TypeContextCompletion_Records.res 115:55 +posCursor:[115:55] posNoWhite:[115:53] Found expr:[115:3->115:67] +posCursor:[115:55] posNoWhite:[115:53] Found pattern:[115:22->115:59] +posCursor:[115:55] posNoWhite:[115:53] Found pattern:[115:34->115:59] +Completable: Cpath Value[""] +[{ + "label": "someOtherValue", + "kind": 12, + "tags": [], + "detail": "someRecordWithVariant", + "documentation": null + }, { + "label": "getSomeVal", + "kind": 12, + "tags": [], + "detail": "(~irrelevant: int) => anotherRecord", + "documentation": null + }, { + "label": "someVal", + "kind": 12, + "tags": [], + "detail": "anotherRecord", + "documentation": null + }, { + "label": "Arg", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ArrayLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Auto", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Float", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSet", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Id", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Int", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_List", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Map", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapDict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableQueue", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSet", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableStack", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Option", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Range", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Result", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Set", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetDict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArray", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArrayInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArrayString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalAVLset", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalAVLtree", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalBuckets", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalBucketsType", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetBuckets", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internals", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Buffer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Bytes", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "BytesLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Callback", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CamlinternalLazy", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CamlinternalMod", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Char", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CodeLens", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CompletePrioritize1", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CompletePrioritize2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Completion", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Complex", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Component", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CreateInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Cross", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dce", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Debug", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Definition", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "DefinitionWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Digest", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Div", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "DocumentSymbol", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom_storage", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom_storage2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Filename", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Fragment", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Genlex", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Hashtbl", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "HashtblLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Highlight", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Hover", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "InlayHint", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Int32", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Int64", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_OO", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_array2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_bigint", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_cast", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_console", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_date", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_dict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_exn", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_float", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_global", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_int", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_json", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_list", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_mapperRt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_math", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_null", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_null_undefined", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_obj", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_option", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_promise", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_re", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_result", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_string", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_string2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_typed_array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_typed_array2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_types", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_undefined", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_vector", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Jsx", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Lazy", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Lexing", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "List", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ListLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "LongIdentTest", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Map", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "MapLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "MoreLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_buffer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_child_process", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_fs", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_module", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_path", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_process", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Obj", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Object", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Parsing", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Patterns", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Pervasives", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Printexc", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Queue", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Random", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "React", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOM", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMRe", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMServer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMStyle", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactEvent", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactTestUtils", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReasonReact", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecModules", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecordCompletion", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecoveryOnProp", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "References", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReferencesWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Rename", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RenameWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RescriptReactErrorBoundary", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RescriptReactRouter", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Set", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "SetLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Sort", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Stack", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "StdLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Stream", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "String", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "StringLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Sys", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TableclothMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_Jsx", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_LabelledArguments", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_Records", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeDefinition", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Uchar", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Xform", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }] + +Complete src/TypeContextCompletion_Records.res 118:46 +posCursor:[118:46] posNoWhite:[118:45] Found expr:[118:3->118:58] +posCursor:[118:46] posNoWhite:[118:45] Found pattern:[118:22->118:50] +posCursor:[118:46] posNoWhite:[118:45] Found pattern:[118:34->118:50] +Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something, RecordField:whatIsThis] seenIdents: [] +[{ + "label": "false", + "kind": 12, + "tags": [], + "detail": "boolean\n\n", + "documentation": null + }, { + "label": "true", + "kind": 12, + "tags": [], + "detail": "boolean\n\n", + "documentation": null + }] + +Complete src/TypeContextCompletion_Records.res 121:49 +posCursor:[121:49] posNoWhite:[121:48] Found expr:[121:3->121:62] +posCursor:[121:49] posNoWhite:[121:48] Found pattern:[121:22->121:54] +posCursor:[121:49] posNoWhite:[121:48] Found pattern:[121:34->121:52] +posCursor:[121:49] posNoWhite:[121:48] Found pattern:[121:47->121:49] +Completable: CtypedContext(Value[someVal])=fa pattern: [RecordField:something, RecordField:whatIsThis] seenIdents: [] +[{ + "label": "false", + "kind": 12, + "tags": [], + "detail": "boolean\n\n", + "documentation": null + }] + From 167976974bd7bcbb9ea1736bb47786bc582ea0db Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sat, 13 Aug 2022 11:46:11 +0200 Subject: [PATCH 57/80] more work, plugging holes etc --- analysis/src/CompletionBackEnd.ml | 14 +- analysis/src/CompletionFrontEnd.ml | 79 +- analysis/src/SharedTypes.ml | 7 +- .../src/TypeContextCompletion_Records.res | 25 +- .../tests/src/expected/Completion.res.txt | 44 +- analysis/tests/src/expected/Dce.res.txt | 2 +- .../TypeContextCompletion_Records.res.txt | 1142 ++--------------- 7 files changed, 220 insertions(+), 1093 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index abaf38026..acccf3e89 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1470,16 +1470,24 @@ let findTypeInContext (typ : Types.type_expr) ~env ~nestedContextPath ~package = typeExprToCompletable currentType ~env ~package | targetItem :: nestedContextPath -> ( match (targetItem, currentType |> extractType ~env ~package) with - | ( Completable.RField {fieldName}, + | ( Completable.RField {fieldName; emptyContext}, Some (Declared (_, {item = {kind = Record fields}})) ) -> ( match fields |> List.find_opt (fun field -> field.fname.txt = fieldName) with | None -> None - | Some targetField -> + | Some targetField -> ( if List.length nestedContextPath > 0 then targetField.typ |> digToType ~env ~nestedContextPath ~package - else typeExprToCompletable targetField.typ ~env ~package) + else + (* emptyContext means this record field was found without braces/parens (like `{someField: }`). + In these cases, we can complete for variants etc, but we can't complete for tuples or record fields, + since they'd require preceding characters (parens for tuple, brace for record) to be valid patterns. *) + match + (emptyContext, typeExprToCompletable targetField.typ ~env ~package) + with + | true, Some (CRecord _) -> None + | _, completable -> completable)) | ( Variant {constructorName; payloadNum}, Some (Declared (_, {item = {kind = Variant constructors}})) ) -> ( match diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index afbbc2924..38810cb9d 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -358,12 +358,14 @@ let rec findCompletableInPattern pattern ~path ~posBeforeCursor ~prefix found _some_ context. We check that context and the char before the cursor to figure out if we should complete for that path. *) match (path, firstCharBeforeCursorNoWhite) with + | Completable.RField rfield :: rest, Some ':' -> + (* We're setting "emptyContext" here, because this record field was found without + braces or parens leading, which affects what we can complete if a type is found. *) + Some ([Completable.RField {rfield with emptyContext = true}] @ rest) (* Handles: One | Two | *) - | (Completable.Variant _ | Polyvariant _) :: _, Some '|' -> Some path - (* Handles: {someField: } *) - | RField _ :: _, Some ':' -> - (* TODO: This should handle when the last path item is a record field, at which point we'll also need to insert the record syntax when completing, or we yield broken syntax. *) - Some path + | _ :: _, Some '|' -> + seenIdents := findAlreadySeenIdents pattern; + Some path (* Handles: {someField: } *) | _ -> None) | HasCursor -> ( match pattern.ppat_desc with @@ -468,7 +470,7 @@ let rec findCompletableInPattern pattern ~path ~posBeforeCursor ~prefix (* let {something} = whatever <- shorthand for let {something:something}, which is just an alias, so we don't want to consider it entering the record field. *) path - | _ -> [Completable.RField {fieldName}] @ path + | _ -> [Completable.RField {fieldName; emptyContext = false}] @ path in pat |> findCompletableInPattern ~posBeforeCursor ~prefix @@ -504,23 +506,15 @@ let rec findCompletableInPattern pattern ~path ~posBeforeCursor ~prefix | _ -> None) let completePattern pattern ~contextPath ~posBeforeCursor - ~firstCharBeforeCursorNoWhite = + ~firstCharBeforeCursorNoWhite ~seenIdents = let prefix = ref "" in - let seenIdents = ref [] in + let seenIdents = ref seenIdents in let nestedContextPath = - (* TODO: This special casing should probably be cleaned up somehow... *) - match pattern.Parsetree.ppat_desc with - | Ppat_record (fields, _) -> ( - match List.length fields with - | 0 -> - (* A root record with 0 fields, `let {} = someVar`, is still valid to complete from. But it has no nested context. *) - Some [] - | _ -> - pattern - |> findCompletableInPattern ~path:[] ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite ~seenIdents) - | _ -> None + pattern + |> findCompletableInPattern ~path:[] ~posBeforeCursor ~prefix + ~firstCharBeforeCursorNoWhite ~seenIdents in + match (contextPath, nestedContextPath) with | Some contextPath, Some nestedContextPath -> Some @@ -685,7 +679,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = setResultOpt (pvb_pat |> completePattern ~contextPath ~posBeforeCursor - ~firstCharBeforeCursorNoWhite) + ~firstCharBeforeCursorNoWhite ~seenIdents:[]) | _ -> ()); bindings |> List.iter (fun vb -> iterator.value_binding iterator vb); if recFlag = Nonrecursive then bindings |> List.iter scopeValueBinding; @@ -998,21 +992,50 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | Pexp_match (expr, cases) -> (* Completes switch case destructuring Example: switch someIdentifier { | {completeRecordFieldsHere} => ...}*) + let rec findIdentsFromCases cases ~seenIdents = + match cases with + | [] -> seenIdents + | case :: cases -> + findIdentsFromCases cases + ~seenIdents: + (findAlreadySeenIdents case.Parsetree.pc_lhs @ seenIdents) + in let rec findCaseWithCursor cases = match cases with - | case :: cases -> ( + | case :: nextCases -> ( match case with - | { - Parsetree.pc_lhs = {ppat_loc; ppat_desc = Ppat_record _} as pat; - } + | {Parsetree.pc_lhs = {ppat_loc} as pat} when ppat_loc |> Loc.hasPos ~pos:posBeforeCursor -> let contextPath = exprToContextPath expr in setResultOpt (pat |> completePattern ~contextPath ~posBeforeCursor - ~firstCharBeforeCursorNoWhite) - | _ -> findCaseWithCursor cases) - | [] -> () + ~firstCharBeforeCursorNoWhite + ~seenIdents:(findIdentsFromCases cases ~seenIdents:[])) + | _ -> findCaseWithCursor nextCases) + | [] -> ( + (* In case there are no cases, like in `switch whatever { | `, complete for the *) + match + expr.pexp_loc |> CursorPosition.classifyLoc ~pos:posBeforeCursor + with + | NoCursor | EmptyLoc -> ( + match + (exprToContextPath expr, firstCharBeforeCursorNoWhite) + with + | ( Some contextPath, + Some '|' + (* This helps ensuring we're actually in the switch, and completing for a case *) + ) -> + setResultOpt + (Some + (Completable.CtypedContext + { + howToRetrieveSourceType = CtxPath contextPath; + patternPath = None; + meta = {prefix = Some ""; alreadySeenIdents = []}; + })) + | _ -> ()) + | HasCursor -> ()) in findCaseWithCursor cases | _ -> ()); diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 7789ce11c..10542fca7 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -436,9 +436,8 @@ module Completable = struct | CPPipe of contextPath * string (* How to move through a nested type context, like from a root record to the type of one of its fields, and beyond. *) - (* TODO: Can extend to tuples, objects, etc *) type patternPathItem = - | RField of {fieldName: string} + | RField of {fieldName: string; emptyContext: bool} | Variant of {constructorName: string; payloadNum: int option} | Polyvariant of {name: string; payloadNum: int option} | PTuple of {itemNumber: int} @@ -449,7 +448,9 @@ module Completable = struct let pathItemToString item = match item with - | RField {fieldName} -> "RecordField:" ^ fieldName + | RField {fieldName; emptyContext} -> + "RecordField:" ^ fieldName + ^ if emptyContext then "(empty context)" else "" | Variant {constructorName; payloadNum} -> ( "Variant:" ^ constructorName ^ diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index 9a5434e01..f34730a76 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -112,7 +112,6 @@ let someOtherValue: someRecordWithVariant = { // switch someOtherValue { | {other2: } => () } // ^com -// TODO: Broken // switch someVal { | {something: {whatIsThis: false | } } => () } // ^com @@ -121,3 +120,27 @@ let someOtherValue: someRecordWithVariant = { // switch someVal { | {something: {whatIsThis: fa } } => () } // ^com + +let x = Some(One) + +// switch x { | } +// ^com + +// switch x { +// ^com + +let y = One + +// switch y { | } +// ^com + +// switch y { | One | Two | Three | } +// ^com + +// Should not complete because the record has no braces +// switch someVal { | {something: } => () } +// ^com + +// Should complete because the record has braces +// switch someVal { | {something: {} } => () } +// ^com diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index cfe09d7bf..a1224d44b 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -1372,38 +1372,8 @@ posCursor:[362:8] posNoWhite:[362:7] Found expr:[361:2->365:3] posCursor:[362:8] posNoWhite:[362:7] Found pattern:[362:7->364:5] posCursor:[362:8] posNoWhite:[362:7] Found pattern:[362:7->362:8] Ppat_construct T:[362:7->362:8] -Completable: Cpath Value[T] -[{ - "label": "TableclothMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_Jsx", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_LabelledArguments", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_Records", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeDefinition", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }] +Completable: CtypedContext(Value[x])=T pattern: [] seenIdents: [T] +[] Complete src/Completion.res 373:21 posCursor:[373:21] posNoWhite:[373:20] Found expr:[371:8->376:3] @@ -1411,14 +1381,8 @@ posCursor:[373:21] posNoWhite:[373:20] Found expr:[372:2->376:3] posCursor:[373:21] posNoWhite:[373:20] Found pattern:[373:7->375:5] posCursor:[373:21] posNoWhite:[373:20] Found pattern:[373:7->373:21] Ppat_construct AndThatOther.T:[373:7->373:21] -Completable: Cpath Value[AndThatOther, T] -[{ - "label": "ThatOther", - "kind": 4, - "tags": [], - "detail": "ThatOther\n\ntype v = And | ThatOther", - "documentation": null - }] +Completable: CtypedContext(Value[x])=AndThatOther pattern: [] seenIdents: [AndThatOther] +[] Complete src/Completion.res 378:24 posCursor:[378:24] posNoWhite:[378:23] Found expr:[378:12->378:26] diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index 3dde901c5..863caa829 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:285 +issues:287 diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index a30c223ad..c1238c841 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -417,7 +417,7 @@ Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:third Complete src/TypeContextCompletion_Records.res 111:38 posCursor:[111:38] posNoWhite:[111:36] Found expr:[111:3->111:47] posCursor:[111:38] posNoWhite:[111:36] Found pattern:[111:29->111:39] -Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:other2] seenIdents: [] +Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:other2(empty context)] seenIdents: [] [{ "label": "None", "kind": 4, @@ -432,1087 +432,195 @@ Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:other "documentation": null }] -Complete src/TypeContextCompletion_Records.res 115:55 -posCursor:[115:55] posNoWhite:[115:53] Found expr:[115:3->115:67] -posCursor:[115:55] posNoWhite:[115:53] Found pattern:[115:22->115:59] -posCursor:[115:55] posNoWhite:[115:53] Found pattern:[115:34->115:59] -Completable: Cpath Value[""] +Complete src/TypeContextCompletion_Records.res 114:55 +posCursor:[114:55] posNoWhite:[114:53] Found expr:[114:3->114:67] +posCursor:[114:55] posNoWhite:[114:53] Found pattern:[114:22->114:59] +posCursor:[114:55] posNoWhite:[114:53] Found pattern:[114:34->114:59] +Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something, RecordField:whatIsThis] seenIdents: [false] [{ - "label": "someOtherValue", + "label": "true", "kind": 12, "tags": [], - "detail": "someRecordWithVariant", + "detail": "boolean\n\n", "documentation": null - }, { - "label": "getSomeVal", + }] + +Complete src/TypeContextCompletion_Records.res 117:46 +posCursor:[117:46] posNoWhite:[117:45] Found expr:[117:3->117:58] +posCursor:[117:46] posNoWhite:[117:45] Found pattern:[117:22->117:50] +posCursor:[117:46] posNoWhite:[117:45] Found pattern:[117:34->117:50] +Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something, RecordField:whatIsThis(empty context)] seenIdents: [] +[{ + "label": "false", "kind": 12, "tags": [], - "detail": "(~irrelevant: int) => anotherRecord", + "detail": "boolean\n\n", "documentation": null }, { - "label": "someVal", + "label": "true", "kind": 12, "tags": [], - "detail": "anotherRecord", - "documentation": null - }, { - "label": "Arg", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ArrayLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Auto", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Float", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSet", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_HashSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Id", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Int", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_List", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Map", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapDict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableQueue", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSet", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_MutableStack", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Option", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Range", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Result", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_Set", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetDict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArray", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArrayInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_SortArrayString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalAVLset", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalAVLtree", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalBuckets", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalBucketsType", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalMapInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalMapString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetBuckets", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetInt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internalSetString", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Belt_internals", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Buffer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Bytes", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "BytesLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Callback", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CamlinternalLazy", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "CamlinternalMod", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Char", - "kind": 9, - "tags": [], - "detail": "file module", + "detail": "boolean\n\n", "documentation": null - }, { - "label": "CodeLens", - "kind": 9, + }] + +Complete src/TypeContextCompletion_Records.res 120:49 +posCursor:[120:49] posNoWhite:[120:48] Found expr:[120:3->120:62] +posCursor:[120:49] posNoWhite:[120:48] Found pattern:[120:22->120:54] +posCursor:[120:49] posNoWhite:[120:48] Found pattern:[120:34->120:52] +posCursor:[120:49] posNoWhite:[120:48] Found pattern:[120:47->120:49] +Completable: CtypedContext(Value[someVal])=fa pattern: [RecordField:something, RecordField:whatIsThis] seenIdents: [] +[{ + "label": "false", + "kind": 12, "tags": [], - "detail": "file module", + "detail": "boolean\n\n", "documentation": null - }, { - "label": "CompletePrioritize1", - "kind": 9, + }] + +Complete src/TypeContextCompletion_Records.res 125:15 +posCursor:[125:15] posNoWhite:[125:14] Found expr:[125:3->131:11] +Completable: CtypedContext(Value[x])="" +[{ + "label": "None", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "None\n\n", "documentation": null }, { - "label": "CompletePrioritize2", - "kind": 9, + "label": "Some(One)", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "One\n\n", "documentation": null }, { - "label": "Completion", - "kind": 9, + "label": "Some(Two)", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Two\n\n", "documentation": null }, { - "label": "Complex", - "kind": 9, + "label": "Some(Three(_))", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Three(int)\n\n", "documentation": null }, { - "label": "Component", - "kind": 9, + "label": "Some(Four(_))", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Four(someOtherVariant)\n\n", "documentation": null }, { - "label": "CreateInterface", - "kind": 9, + "label": "Some(Five(_))", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null - }, { - "label": "Cross", - "kind": 9, + }] + +Complete src/TypeContextCompletion_Records.res 128:14 +posCursor:[128:14] posNoWhite:[128:12] Found expr:[128:3->128:13] +[] + +Complete src/TypeContextCompletion_Records.res 133:15 +posCursor:[133:15] posNoWhite:[133:14] Found expr:[133:3->133:17] +Completable: CtypedContext(Value[y])="" +[{ + "label": "One", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "One\n\n", "documentation": null }, { - "label": "Dce", - "kind": 9, + "label": "Two", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Two\n\n", "documentation": null }, { - "label": "Debug", - "kind": 9, + "label": "Three(_)", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Three(int)\n\n", "documentation": null }, { - "label": "Definition", - "kind": 9, + "label": "Four(_)", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Four(someOtherVariant)\n\n", "documentation": null }, { - "label": "DefinitionWithInterface", - "kind": 9, + "label": "Five(_)", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null - }, { - "label": "Digest", - "kind": 9, + }] + +Complete src/TypeContextCompletion_Records.res 136:36 +posCursor:[136:36] posNoWhite:[136:34] Found expr:[136:3->136:38] +Completable: CtypedContext(Value[y])="" +[{ + "label": "One", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "One\n\n", "documentation": null }, { - "label": "Div", - "kind": 9, + "label": "Two", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Two\n\n", "documentation": null }, { - "label": "DocumentSymbol", - "kind": 9, + "label": "Three(_)", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Three(int)\n\n", "documentation": null }, { - "label": "Dom", - "kind": 9, + "label": "Four(_)", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Four(someOtherVariant)\n\n", "documentation": null }, { - "label": "Dom_storage", - "kind": 9, + "label": "Five(_)", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null - }, { - "label": "Dom_storage2", - "kind": 9, + }] + +Complete src/TypeContextCompletion_Records.res 140:33 +posCursor:[140:33] posNoWhite:[140:32] Found expr:[140:3->140:44] +posCursor:[140:33] posNoWhite:[140:32] Found pattern:[140:22->140:36] +Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something(empty context)] seenIdents: [] +[] + +Complete src/TypeContextCompletion_Records.res 144:35 +posCursor:[144:35] posNoWhite:[144:34] Found expr:[144:3->144:46] +posCursor:[144:35] posNoWhite:[144:34] Found pattern:[144:22->144:38] +posCursor:[144:35] posNoWhite:[144:34] Found pattern:[144:34->144:36] +Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something] seenIdents: [] +[{ + "label": "somethingElse", + "kind": 5, "tags": [], - "detail": "file module", + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null }, { - "label": "Filename", - "kind": 9, + "label": "whatIsThis", + "kind": 5, "tags": [], - "detail": "file module", + "detail": "whatIsThis: bool\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null }, { - "label": "Fragment", - "kind": 9, + "label": "anotherLevel", + "kind": 5, "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Genlex", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Hashtbl", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "HashtblLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Highlight", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Hover", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "InlayHint", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Int32", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Int64", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_OO", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_array2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_bigint", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_cast", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_console", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_date", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_dict", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_exn", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_float", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_global", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_int", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_json", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_list", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_mapperRt", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_math", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_null", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_null_undefined", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_obj", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_option", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_promise", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_re", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_result", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_string", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_string2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_typed_array", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_typed_array2", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_types", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_undefined", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Js_vector", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Jsx", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Lazy", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Lexing", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "List", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ListLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "LongIdentTest", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Map", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "MapLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "MoreLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_buffer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_child_process", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_fs", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_module", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_path", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Node_process", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Obj", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Object", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Parsing", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Patterns", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Pervasives", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Printexc", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Queue", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Random", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "React", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOM", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMRe", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMServer", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactDOMStyle", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactEvent", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReactTestUtils", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReasonReact", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecModules", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecordCompletion", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RecoveryOnProp", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "References", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "ReferencesWithInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Rename", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RenameWithInterface", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RescriptReactErrorBoundary", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "RescriptReactRouter", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Set", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "SetLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Sort", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Stack", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "StdLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Stream", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "String", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "StringLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Sys", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TableclothMap", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_Jsx", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_LabelledArguments", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeContextCompletion_Records", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "TypeDefinition", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Uchar", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }, { - "label": "Xform", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null - }] - -Complete src/TypeContextCompletion_Records.res 118:46 -posCursor:[118:46] posNoWhite:[118:45] Found expr:[118:3->118:58] -posCursor:[118:46] posNoWhite:[118:45] Found pattern:[118:22->118:50] -posCursor:[118:46] posNoWhite:[118:45] Found pattern:[118:34->118:50] -Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something, RecordField:whatIsThis] seenIdents: [] -[{ - "label": "false", - "kind": 12, - "tags": [], - "detail": "boolean\n\n", - "documentation": null - }, { - "label": "true", - "kind": 12, - "tags": [], - "detail": "boolean\n\n", - "documentation": null - }] - -Complete src/TypeContextCompletion_Records.res 121:49 -posCursor:[121:49] posNoWhite:[121:48] Found expr:[121:3->121:62] -posCursor:[121:49] posNoWhite:[121:48] Found pattern:[121:22->121:54] -posCursor:[121:49] posNoWhite:[121:48] Found pattern:[121:34->121:52] -posCursor:[121:49] posNoWhite:[121:48] Found pattern:[121:47->121:49] -Completable: CtypedContext(Value[someVal])=fa pattern: [RecordField:something, RecordField:whatIsThis] seenIdents: [] -[{ - "label": "false", - "kind": 12, - "tags": [], - "detail": "boolean\n\n", + "detail": "anotherLevel: anotherLevel\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null }] From f262a50dc47561538431e70d62ec2e6ec16afb53 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sat, 13 Aug 2022 18:45:44 +0200 Subject: [PATCH 58/80] complete patterns in arguments of fns passed to named arguments --- analysis/src/CompletionBackEnd.ml | 32 +- analysis/src/CompletionFrontEnd.ml | 552 ++++++++++-------- analysis/src/SharedTypes.ml | 22 +- ...ypeContextCompletion_LabelledArguments.res | 12 + analysis/tests/src/expected/Dce.res.txt | 2 +- ...ontextCompletion_LabelledArguments.res.txt | 14 + 6 files changed, 381 insertions(+), 253 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index acccf3e89..d7d90925e 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1586,8 +1586,8 @@ let getLabelsForComponent ~package ~opens ~allFiles ~pos ~env ~scope (* This pulls out the type we want to do type based completion based on, using an instruction. This instruction can be "the type that the jsx prop X wants in component Y". *) -let findSourceType sourceType ~package ~opens ~rawOpens ~allFiles ~env ~scope - ~pos = +let rec findSourceType sourceType ~package ~opens ~rawOpens ~allFiles ~env + ~scope ~pos = match sourceType with | Completable.NamedArg {label; contextPath} -> ( (* TODO: Should probably share this with the branch handling CnamedArg... *) @@ -1640,6 +1640,34 @@ let findSourceType sourceType ~package ~opens ~rawOpens ~allFiles ~env ~scope with | Some (typ, _env) -> Some typ | None -> None) + | FunctionArgument {howToFindFunctionType; arg} -> ( + match + howToFindFunctionType + |> findSourceType ~package ~opens ~rawOpens ~allFiles ~env ~scope ~pos + with + | Some typ -> ( + let labels, _ = typ |> extractFunctionType ~env ~package in + match arg with + | Unlabelled argNum -> + let idx = ref 0 in + labels + |> List.find_map (fun (label, typExpr) -> + match label with + | Asttypes.Nolabel -> + if argNum = !idx then Some typExpr + else ( + idx := !idx + 1; + None) + | _ -> None) + | Labelled lookingForLabel -> + labels + |> List.find_map (fun (label, typExpr) -> + match label with + | (Asttypes.Labelled labelName | Optional labelName) + when labelName = lookingForLabel -> + Some typExpr + | _ -> None)) + | _ -> None) let processCompletable ~debug ~package ~scope ~env ~pos ~forHover (completable : Completable.t) = diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 38810cb9d..8a53136c5 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -42,6 +42,227 @@ let canDoTypedCompletionOnExpr exp = true | _ -> false +let rec getSimpleFieldName txt = + match txt with + | Longident.Lident fieldName -> fieldName + | Ldot (t, _) -> getSimpleFieldName t + | _ -> "" + +(* Variants can have payloads. We need to figure out which of the payloads we're in, so we can find the type at that position as we try to do completion. + We also need to continue descending into the pattern of the argument under the cursor to find any inner type. *) +let findVariantPayloadItemNumWithCursor pat ~pos = + match pat.Parsetree.ppat_desc with + | Ppat_tuple patterns -> + let res = ref None in + patterns + |> List.iteri (fun index tuplePat -> + match pat.Parsetree.ppat_loc |> CursorPosition.classifyLoc ~pos with + | HasCursor -> res := Some (index, tuplePat) + | _ -> ()); + !res + | _ -> Some (0, pat) + +let identFromPat pat = + match pat.Parsetree.ppat_desc with + | Ppat_var loc -> Some loc.txt + | Ppat_construct (loc, _) -> Some (getSimpleFieldName loc.txt) + | Ppat_variant (label, _) -> Some label + | _ -> None + +let findAlreadySeenIdents pat = + match pat.Parsetree.ppat_desc with + | Ppat_or (pat1, pat2) -> + let rec findAllOrBranches pat ~branches = + match pat.Parsetree.ppat_desc with + | Ppat_or (pat1, pat2) -> + pat1 |> findAllOrBranches ~branches:([pat2] @ branches) + | _ -> [pat] @ branches + in + let branches = pat1 |> findAllOrBranches ~branches:[pat2] in + branches |> List.filter_map (fun branchPat -> identFromPat branchPat) + | _ -> [] + +let rec findCompletableInPattern pattern ~path ~posBeforeCursor ~prefix + ~firstCharBeforeCursorNoWhite ~seenIdents = + match + pattern.Parsetree.ppat_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + with + | NoCursor -> None + | EmptyLoc -> ( + (* An empty location means the parser likely recovered from parsing an erronous pattern. + If we have at least one entry in the path list already, we know that we've at least + found _some_ context. We check that context and the char before the cursor to figure + out if we should complete for that path. *) + match (path, firstCharBeforeCursorNoWhite) with + | Completable.RField rfield :: rest, Some ':' -> + (* We're setting "emptyContext" here, because this record field was found without + braces or parens leading, which affects what we can complete if a type is found. *) + Some ([Completable.RField {rfield with emptyContext = true}] @ rest) + (* Handles: One | Two | *) + | _ :: _, Some '|' -> + seenIdents := findAlreadySeenIdents pattern; + Some path (* Handles: {someField: } *) + | _ -> None) + | HasCursor -> ( + match pattern.ppat_desc with + | Ppat_construct ({txt = Lident "()"}, None) -> + (* A constructor without a payload mean we've reached an end. The parser parses SomeVariant() like above. *) + prefix := ""; + Some path + | Ppat_construct ({txt}, None) -> + (* A constructor without a payload mean we've reached an end. *) + prefix := getSimpleFieldName txt; + Some path + | Ppat_construct ({txt}, Some constructorPayload) -> ( + match + findVariantPayloadItemNumWithCursor constructorPayload + ~pos:posBeforeCursor + with + | None -> None + | Some (index, pat) -> + seenIdents := findAlreadySeenIdents pat; + pat + |> findCompletableInPattern + ~path: + ([ + Completable.Variant + { + constructorName = getSimpleFieldName txt; + payloadNum = Some index; + }; + ] + @ path) + ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~prefix ~seenIdents) + | Ppat_variant (label, None) -> + (* A constructor without a payload mean we've reached an end. *) + prefix := label; + Some path + | Ppat_variant (label, Some constructorPayload) -> ( + match + findVariantPayloadItemNumWithCursor constructorPayload + ~pos:posBeforeCursor + with + | None -> None + | Some (index, pat) -> + seenIdents := findAlreadySeenIdents pat; + pat + |> findCompletableInPattern + ~path: + ([ + Completable.Polyvariant {name = label; payloadNum = Some index}; + ] + @ path) + ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~prefix ~seenIdents) + | Ppat_tuple patterns -> ( + let tupleItemNum = ref 0 in + let patternWithCursor = + patterns + |> List.find_map (fun pat -> + let currentItemNum = !tupleItemNum in + tupleItemNum := !tupleItemNum + 1; + match + pat.Parsetree.ppat_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + with + | HasCursor | EmptyLoc -> Some (currentItemNum, pat) + | NoCursor -> None) + in + match patternWithCursor with + | None -> None + | Some (tupleItemNum, pat) -> + seenIdents := []; + pat + |> findCompletableInPattern ~posBeforeCursor ~prefix + ~firstCharBeforeCursorNoWhite ~seenIdents + ~path:([Completable.PTuple {itemNumber = tupleItemNum}] @ path)) + | Ppat_record (fields, _) when List.length fields = 0 -> Some path + | Ppat_record (fields, _) -> ( + let seenFields = + fields |> List.map (fun ({Location.txt}, _) -> getSimpleFieldName txt) + in + let fieldWithCursor = + fields + |> List.find_map (fun (loc, fieldPat) -> + match + fieldPat.Parsetree.ppat_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + with + | NoCursor -> None + | HasCursor | EmptyLoc -> Some (loc, fieldPat)) + in + match fieldWithCursor with + | None -> + if firstCharBeforeCursorNoWhite = Some ',' then ( + seenIdents := seenFields; + Some path) + else None + | Some (loc, pat) -> + let fieldName = getSimpleFieldName loc.txt in + seenIdents := seenFields |> List.filter (fun name -> name <> fieldName); + + let newPath = + match pat.ppat_desc with + | Ppat_var {txt} when txt = fieldName -> + (* let {something} = whatever <- shorthand for let {something:something}, which is just an alias, + so we don't want to consider it entering the record field. *) + path + | _ -> [Completable.RField {fieldName; emptyContext = false}] @ path + in + pat + |> findCompletableInPattern ~posBeforeCursor ~prefix + ~firstCharBeforeCursorNoWhite ~seenIdents ~path:newPath) + | Ppat_var {txt} -> + prefix := txt; + Some path + | Ppat_or (pat1, pat2) -> ( + seenIdents := findAlreadySeenIdents pattern; + let rec findAllOrBranches pat ~branches = + match pat.Parsetree.ppat_desc with + | Ppat_or (pat1, pat2) -> + pat1 |> findAllOrBranches ~branches:([pat2] @ branches) + | _ -> [pat] @ branches + in + let branches = pat1 |> findAllOrBranches ~branches:[pat2] in + let branchAtCursor = + branches + |> List.find_opt (fun pat -> + match + pat.Parsetree.ppat_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + with + | HasCursor -> true + | EmptyLoc | NoCursor -> false) + in + match branchAtCursor with + | None -> None + | Some pat -> + pat + |> findCompletableInPattern ~posBeforeCursor ~prefix + ~firstCharBeforeCursorNoWhite ~path ~seenIdents) + | _ -> None) + +let completePattern pattern ~howToRetrieveSourceType ~posBeforeCursor + ~firstCharBeforeCursorNoWhite ~seenIdents = + let prefix = ref "" in + let seenIdents = ref seenIdents in + let nestedContextPath = + pattern + |> findCompletableInPattern ~path:[] ~posBeforeCursor ~prefix + ~firstCharBeforeCursorNoWhite ~seenIdents + in + + match nestedContextPath with + | Some nestedContextPath -> + Some + (Completable.CtypedContext + { + howToRetrieveSourceType; + patternPath = Some (nestedContextPath |> List.rev); + meta = {prefix = Some !prefix; alreadySeenIdents = !seenIdents}; + }) + | _ -> None + (* This is probably wrong and we should likely use the full Longident instead for the prefix. *) let getPrefixFromExpr exp = getIdentFromExpr exp |> Longident.last @@ -214,7 +435,8 @@ type label = labelled option type arg = {label: label; exp: Parsetree.expression} let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor - ~(contextPath : Completable.contextPath) ~posAfterFunExpr = + ~(contextPath : Completable.contextPath) ~posAfterFunExpr + ~firstCharBeforeCursorNoWhite = let allNames = List.fold_right (fun arg allLabels -> @@ -232,20 +454,66 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor && posBeforeCursor < labelled.posEnd then Some (Completable.CnamedArg (contextPath, labelled.name, allNames)) else if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then - if canDoTypedCompletionOnExpr exp then - Some - (Completable.CtypedContext - { - howToRetrieveSourceType = - Completable.NamedArg {contextPath; label = labelled.name}; - patternPath = None; - meta = - { - prefix = Some (getPrefixFromExpr exp); - alreadySeenIdents = []; - }; - }) - else None + (* Ok, were completing in the expression. Inspect what the expression is. *) + (* TODO: Apply the same thing to JSX *) + let howToRetrieveTheTypeForThisArg = + Completable.NamedArg {contextPath; label = labelled.name} + in + match exp.pexp_desc with + | Pexp_fun _ -> ( + (* If this is a function expression, there might be function argument patterns we can + complete (like the record destructuring in `someFunc(~someArg=({}) => {...})`) *) + let idx = ref 0 in + let rec findTargetArg exp = + match exp.Parsetree.pexp_desc with + | Pexp_fun (label, _, fnArgPattern, nextFunExpr) -> ( + let currentUnlabelledArgIdx = !idx in + (match label with + | Nolabel -> idx := !idx + 1 + | _ -> ()); + (* Check if the cursor is inside this args pattern. *) + match + ( fnArgPattern.ppat_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor, + label ) + with + | (EmptyLoc | HasCursor), Nolabel -> + Some + (Completable.Unlabelled currentUnlabelledArgIdx, fnArgPattern) + | (EmptyLoc | HasCursor), (Labelled label | Optional label) -> + Some (Completable.Labelled label, fnArgPattern) + | NoCursor, _ -> findTargetArg nextFunExpr) + | _ -> None + in + match findTargetArg exp with + | None -> None + | Some (arg, argPattern) -> + let completable = + argPattern + |> completePattern + ~howToRetrieveSourceType: + (Completable.FunctionArgument + { + howToFindFunctionType = howToRetrieveTheTypeForThisArg; + arg; + }) + ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~seenIdents:[] + in + completable) + | _ -> + if canDoTypedCompletionOnExpr exp then + Some + (Completable.CtypedContext + { + howToRetrieveSourceType = howToRetrieveTheTypeForThisArg; + patternPath = None; + meta = + { + prefix = Some (getPrefixFromExpr exp); + alreadySeenIdents = []; + }; + }) + else None else if exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then (* Expr assigned presumably is "rescript.exprhole" after parser recovery. Assume this is an empty expression. *) @@ -305,227 +573,6 @@ let extractExpApplyArgs ~args = in args |> processArgs ~acc:[] -let rec getSimpleFieldName txt = - match txt with - | Longident.Lident fieldName -> fieldName - | Ldot (t, _) -> getSimpleFieldName t - | _ -> "" - -(* Variants can have payloads. We need to figure out which of the payloads we're in, so we can find the type at that position as we try to do completion. - We also need to continue descending into the pattern of the argument under the cursor to find any inner type. *) -let findVariantPayloadItemNumWithCursor pat ~pos = - match pat.Parsetree.ppat_desc with - | Ppat_tuple patterns -> - let res = ref None in - patterns - |> List.iteri (fun index tuplePat -> - match pat.Parsetree.ppat_loc |> CursorPosition.classifyLoc ~pos with - | HasCursor -> res := Some (index, tuplePat) - | _ -> ()); - !res - | _ -> Some (0, pat) - -let identFromPat pat = - match pat.Parsetree.ppat_desc with - | Ppat_var loc -> Some loc.txt - | Ppat_construct (loc, _) -> Some (getSimpleFieldName loc.txt) - | Ppat_variant (label, _) -> Some label - | _ -> None - -let findAlreadySeenIdents pat = - match pat.Parsetree.ppat_desc with - | Ppat_or (pat1, pat2) -> - let rec findAllOrBranches pat ~branches = - match pat.Parsetree.ppat_desc with - | Ppat_or (pat1, pat2) -> - pat1 |> findAllOrBranches ~branches:([pat2] @ branches) - | _ -> [pat] @ branches - in - let branches = pat1 |> findAllOrBranches ~branches:[pat2] in - branches |> List.filter_map (fun branchPat -> identFromPat branchPat) - | _ -> [] - -let rec findCompletableInPattern pattern ~path ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite ~seenIdents = - match - pattern.Parsetree.ppat_loc - |> CursorPosition.classifyLoc ~pos:posBeforeCursor - with - | NoCursor -> None - | EmptyLoc -> ( - (* An empty location means the parser likely recovered from parsing an erronous pattern. - If we have at least one entry in the path list already, we know that we've at least - found _some_ context. We check that context and the char before the cursor to figure - out if we should complete for that path. *) - match (path, firstCharBeforeCursorNoWhite) with - | Completable.RField rfield :: rest, Some ':' -> - (* We're setting "emptyContext" here, because this record field was found without - braces or parens leading, which affects what we can complete if a type is found. *) - Some ([Completable.RField {rfield with emptyContext = true}] @ rest) - (* Handles: One | Two | *) - | _ :: _, Some '|' -> - seenIdents := findAlreadySeenIdents pattern; - Some path (* Handles: {someField: } *) - | _ -> None) - | HasCursor -> ( - match pattern.ppat_desc with - | Ppat_construct ({txt = Lident "()"}, None) -> - (* A constructor without a payload mean we've reached an end. The parser parses SomeVariant() like above. *) - prefix := ""; - Some path - | Ppat_construct ({txt}, None) -> - (* A constructor without a payload mean we've reached an end. *) - prefix := getSimpleFieldName txt; - Some path - | Ppat_construct ({txt}, Some constructorPayload) -> ( - match - findVariantPayloadItemNumWithCursor constructorPayload - ~pos:posBeforeCursor - with - | None -> None - | Some (index, pat) -> - seenIdents := findAlreadySeenIdents pat; - pat - |> findCompletableInPattern - ~path: - ([ - Completable.Variant - { - constructorName = getSimpleFieldName txt; - payloadNum = Some index; - }; - ] - @ path) - ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~prefix ~seenIdents) - | Ppat_variant (label, None) -> - (* A constructor without a payload mean we've reached an end. *) - prefix := label; - Some path - | Ppat_variant (label, Some constructorPayload) -> ( - match - findVariantPayloadItemNumWithCursor constructorPayload - ~pos:posBeforeCursor - with - | None -> None - | Some (index, pat) -> - seenIdents := findAlreadySeenIdents pat; - pat - |> findCompletableInPattern - ~path: - ([ - Completable.Polyvariant {name = label; payloadNum = Some index}; - ] - @ path) - ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~prefix ~seenIdents) - | Ppat_tuple patterns -> ( - let tupleItemNum = ref 0 in - let patternWithCursor = - patterns - |> List.find_map (fun pat -> - let currentItemNum = !tupleItemNum in - tupleItemNum := !tupleItemNum + 1; - match - pat.Parsetree.ppat_loc - |> CursorPosition.classifyLoc ~pos:posBeforeCursor - with - | HasCursor | EmptyLoc -> Some (currentItemNum, pat) - | NoCursor -> None) - in - match patternWithCursor with - | None -> None - | Some (tupleItemNum, pat) -> - seenIdents := []; - pat - |> findCompletableInPattern ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite ~seenIdents - ~path:([Completable.PTuple {itemNumber = tupleItemNum}] @ path)) - | Ppat_record (fields, _) when List.length fields = 0 -> Some path - | Ppat_record (fields, _) -> ( - let seenFields = - fields |> List.map (fun ({Location.txt}, _) -> getSimpleFieldName txt) - in - let fieldWithCursor = - fields - |> List.find_map (fun (loc, fieldPat) -> - match - fieldPat.Parsetree.ppat_loc - |> CursorPosition.classifyLoc ~pos:posBeforeCursor - with - | NoCursor -> None - | HasCursor | EmptyLoc -> Some (loc, fieldPat)) - in - match fieldWithCursor with - | None -> - if firstCharBeforeCursorNoWhite = Some ',' then ( - seenIdents := seenFields; - Some path) - else None - | Some (loc, pat) -> - let fieldName = getSimpleFieldName loc.txt in - seenIdents := seenFields |> List.filter (fun name -> name <> fieldName); - - let newPath = - match pat.ppat_desc with - | Ppat_var {txt} when txt = fieldName -> - (* let {something} = whatever <- shorthand for let {something:something}, which is just an alias, - so we don't want to consider it entering the record field. *) - path - | _ -> [Completable.RField {fieldName; emptyContext = false}] @ path - in - pat - |> findCompletableInPattern ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite ~seenIdents ~path:newPath) - | Ppat_var {txt} -> - prefix := txt; - Some path - | Ppat_or (pat1, pat2) -> ( - seenIdents := findAlreadySeenIdents pattern; - let rec findAllOrBranches pat ~branches = - match pat.Parsetree.ppat_desc with - | Ppat_or (pat1, pat2) -> - pat1 |> findAllOrBranches ~branches:([pat2] @ branches) - | _ -> [pat] @ branches - in - let branches = pat1 |> findAllOrBranches ~branches:[pat2] in - let branchAtCursor = - branches - |> List.find_opt (fun pat -> - match - pat.Parsetree.ppat_loc - |> CursorPosition.classifyLoc ~pos:posBeforeCursor - with - | HasCursor -> true - | EmptyLoc | NoCursor -> false) - in - match branchAtCursor with - | None -> None - | Some pat -> - pat - |> findCompletableInPattern ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite ~path ~seenIdents) - | _ -> None) - -let completePattern pattern ~contextPath ~posBeforeCursor - ~firstCharBeforeCursorNoWhite ~seenIdents = - let prefix = ref "" in - let seenIdents = ref seenIdents in - let nestedContextPath = - pattern - |> findCompletableInPattern ~path:[] ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite ~seenIdents - in - - match (contextPath, nestedContextPath) with - | Some contextPath, Some nestedContextPath -> - Some - (Completable.CtypedContext - { - howToRetrieveSourceType = CtxPath contextPath; - patternPath = Some (nestedContextPath |> List.rev); - meta = {prefix = Some !prefix; alreadySeenIdents = !seenIdents}; - }) - | _ -> None - let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = let offsetNoWhite = skipWhite text (offset - 1) in let posNoWhite = @@ -672,14 +719,16 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = (* TODO: Tuples, etc... *) (* TODO: Handle let {SomeModule.recordField} = ...*) (match bindings with - | [{pvb_pat; pvb_expr = expr}] when !result = None -> + | [{pvb_pat; pvb_expr = expr}] when !result = None -> ( (* The contextPath is what we'll use to look up the root record type for this completion. Depending on if the destructure is nested or not, we may or may not use that directly.*) - let contextPath = exprToContextPath expr in - setResultOpt - (pvb_pat - |> completePattern ~contextPath ~posBeforeCursor - ~firstCharBeforeCursorNoWhite ~seenIdents:[]) + match exprToContextPath expr with + | None -> () + | Some contextPath -> + setResultOpt + (pvb_pat + |> completePattern ~howToRetrieveSourceType:(CtxPath contextPath) + ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~seenIdents:[])) | _ -> ()); bindings |> List.iter (fun vb -> iterator.value_binding iterator vb); if recFlag = Nonrecursive then bindings |> List.iter scopeValueBinding; @@ -925,6 +974,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | Some contextPath -> findNamedArgCompletable ~contextPath ~args ~endPos:(Loc.end_ expr.pexp_loc) ~posBeforeCursor + ~firstCharBeforeCursorNoWhite ~posAfterFunExpr:(Loc.end_ funExpr.pexp_loc) | None -> None in @@ -1005,13 +1055,17 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | case :: nextCases -> ( match case with | {Parsetree.pc_lhs = {ppat_loc} as pat} - when ppat_loc |> Loc.hasPos ~pos:posBeforeCursor -> - let contextPath = exprToContextPath expr in - setResultOpt - (pat - |> completePattern ~contextPath ~posBeforeCursor - ~firstCharBeforeCursorNoWhite - ~seenIdents:(findIdentsFromCases cases ~seenIdents:[])) + when ppat_loc |> Loc.hasPos ~pos:posBeforeCursor -> ( + match exprToContextPath expr with + | None -> () + | Some contextPath -> + setResultOpt + (pat + |> completePattern + ~howToRetrieveSourceType:(CtxPath contextPath) + ~posBeforeCursor ~firstCharBeforeCursorNoWhite + ~seenIdents:(findIdentsFromCases cases ~seenIdents:[]) + )) | _ -> findCaseWithCursor nextCases) | [] -> ( (* In case there are no cases, like in `switch whatever { | `, complete for the *) diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 10542fca7..bf571f694 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -492,6 +492,13 @@ module Completable = struct | CPObj (cp, s) -> contextPathToString cp ^ "[\"" ^ s ^ "\"]" | CPPipe (cp, s) -> contextPathToString cp ^ "->" ^ s + type functionArgument = Labelled of string | Unlabelled of int + + let functionArgumentToString arg = + match arg with + | Labelled name -> "~" ^ name + | Unlabelled argNum -> "unlabelled(" ^ string_of_int argNum ^ ")" + (* Temporary while I figure things. Pretty sure this should be integrated into contextPath when this is all finished *) type howToRetrieveSourceType = | CtxPath of contextPath @@ -508,14 +515,27 @@ module Completable = struct (* Name of the argument *) label: string; } + (* An argument to a function, like when completing in: someFunc(~someArg=({^com}) => {...})*) + | FunctionArgument of { + (* How to find the type of the function with the argument. *) + howToFindFunctionType: howToRetrieveSourceType; + (* Where the argument itself is located. *) + arg: functionArgument; + } - let howToRetrieveSourceTypeToString howToRetrieveSourceType = + let rec howToRetrieveSourceTypeToString howToRetrieveSourceType = match howToRetrieveSourceType with | CtxPath contextPath -> contextPath |> contextPathToString | JsxProp {propName; componentPath} -> "JsxProp(<" ^ (componentPath |> ident) ^ " " ^ propName ^ "=" ^ " />)" | NamedArg {label; contextPath} -> "NamedArg(" ^ label ^ ", " ^ (contextPath |> contextPathToString) ^ ")" + | FunctionArgument {howToFindFunctionType; arg} -> + "FunctionArgument(fnSource:" + ^ howToRetrieveSourceTypeToString howToFindFunctionType + ^ ", arg:" + ^ (arg |> functionArgumentToString) + ^ ")" type typedContextMeta = { (* What the user has already started writing, if anything. *) diff --git a/analysis/tests/src/TypeContextCompletion_LabelledArguments.res b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res index e85808361..c3322dff7 100644 --- a/analysis/tests/src/TypeContextCompletion_LabelledArguments.res +++ b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res @@ -52,3 +52,15 @@ let someVariantToString = ( // let x = someVariantToString(~thirdThing=#T // ^com + +type someRecord = { + age: int, + name: string, +} + +let doStuff = (~doThing: someRecord => unit) => { + ignore(doThing({age: 123, name: "hello"})) +} + +// let _ = doStuff(~doThing=({age, n}) => {()}) +// ^com diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index 863caa829..256fadee8 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:287 +issues:290 diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index 147857e10..bc8e4c8db 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -307,3 +307,17 @@ Pexp_apply ...[52:11->52:30] (~thirdThing52:32->52:42=...[52:43->52:45]) Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))=T [] +Complete src/TypeContextCompletion_LabelledArguments.res 64:36 +posCursor:[64:36] posNoWhite:[64:35] Found expr:[64:11->64:47] +Pexp_apply ...[64:11->64:18] (~doThing64:20->64:27=...[64:28->64:46]) +posCursor:[64:36] posNoWhite:[64:35] Found pattern:[64:29->64:37] +posCursor:[64:36] posNoWhite:[64:35] Found pattern:[64:35->64:36] +Completable: CtypedContext(FunctionArgument(fnSource:NamedArg(doThing, Value[doStuff]), arg:unlabelled(0)))=n pattern: [] seenIdents: [age] +[{ + "label": "name", + "kind": 5, + "tags": [], + "detail": "name: string\n\ntype someRecord = {age: int, name: string}", + "documentation": null + }] + From 28dddca75b3aefe9d627847676f6f0b9b4c0152f Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 14 Aug 2022 14:06:18 +0200 Subject: [PATCH 59/80] rename --- analysis/src/CompletionBackEnd.ml | 8 +-- analysis/src/CompletionFrontEnd.ml | 25 ++++---- analysis/src/SharedTypes.ml | 20 +++--- .../tests/src/expected/Completion.res.txt | 4 +- .../TypeContextCompletion_Jsx.res.txt | 16 ++--- ...ontextCompletion_LabelledArguments.res.txt | 18 +++--- .../TypeContextCompletion_Records.res.txt | 62 +++++++++---------- 7 files changed, 72 insertions(+), 81 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index d7d90925e..5def8951e 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1986,7 +1986,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i Utils.startsWith name prefix && (forHover || not (List.mem name identsSeen))) |> List.map mkLabel - | CtypedContext + | CtypedContextPattern {howToRetrieveSourceType; patternPath; meta = {prefix; alreadySeenIdents}} -> ( let prefix = @@ -1998,11 +1998,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i howToRetrieveSourceType |> findSourceType ~package ~opens ~rawOpens ~allFiles ~env ~pos ~scope in - let nestedContextPath = - match patternPath with - | None -> [] - | Some patternPath -> patternPath - in + let nestedContextPath = patternPath in match sourceType with | None -> [] | Some typ -> ( diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 8a53136c5..195fd041d 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -251,14 +251,13 @@ let completePattern pattern ~howToRetrieveSourceType ~posBeforeCursor |> findCompletableInPattern ~path:[] ~posBeforeCursor ~prefix ~firstCharBeforeCursorNoWhite ~seenIdents in - match nestedContextPath with | Some nestedContextPath -> Some - (Completable.CtypedContext + (Completable.CtypedContextPattern { howToRetrieveSourceType; - patternPath = Some (nestedContextPath |> List.rev); + patternPath = nestedContextPath |> List.rev; meta = {prefix = Some !prefix; alreadySeenIdents = !seenIdents}; }) | _ -> None @@ -328,7 +327,7 @@ let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName (* Cursor on expr assigned *) if canDoTypedCompletionOnExpr prop.exp then Some - (Completable.CtypedContext + (Completable.CtypedContextPattern { howToRetrieveSourceType = JsxProp @@ -337,7 +336,7 @@ let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; propName = prop.name; }; - patternPath = None; + patternPath = []; meta = { prefix = Some (getPrefixFromExpr prop.exp); @@ -350,7 +349,7 @@ let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName Complete for the value. *) if canDoTypedCompletionOnExpr prop.exp then Some - (Completable.CtypedContext + (Completable.CtypedContextPattern { howToRetrieveSourceType = JsxProp @@ -359,7 +358,7 @@ let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; propName = prop.name; }; - patternPath = None; + patternPath = []; meta = { prefix = Some (getPrefixFromExpr prop.exp); @@ -503,10 +502,10 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor | _ -> if canDoTypedCompletionOnExpr exp then Some - (Completable.CtypedContext + (Completable.CtypedContextPattern { howToRetrieveSourceType = howToRetrieveTheTypeForThisArg; - patternPath = None; + patternPath = []; meta = { prefix = Some (getPrefixFromExpr exp); @@ -519,11 +518,11 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor Assume this is an empty expression. *) if canDoTypedCompletionOnExpr exp then Some - (Completable.CtypedContext + (Completable.CtypedContextPattern { howToRetrieveSourceType = NamedArg {contextPath; label = labelled.name}; - patternPath = None; + patternPath = []; meta = { prefix = Some (getPrefixFromExpr exp); @@ -1082,10 +1081,10 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = ) -> setResultOpt (Some - (Completable.CtypedContext + (Completable.CtypedContextPattern { howToRetrieveSourceType = CtxPath contextPath; - patternPath = None; + patternPath = []; meta = {prefix = Some ""; alreadySeenIdents = []}; })) | _ -> ()) diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index bf571f694..e6f5d8d74 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -555,9 +555,9 @@ module Completable = struct | Cjsx of string list * string * string list (** E.g. (["M", "Comp"], "id", ["id1", "id2"]) for "Cnone" | Cjsx (sl1, s, sl2) -> "Cjsx(" ^ (sl1 |> list) ^ ", " ^ str s ^ ", " ^ (sl2 |> list) ^ ")" - | CtypedContext + | CtypedContextPattern { howToRetrieveSourceType; meta = {prefix; alreadySeenIdents}; patternPath; - } -> ( - ("CtypedContext(" + } -> + ("CtypedContextPattern(" ^ (howToRetrieveSourceType |> howToRetrieveSourceTypeToString) ^ ")=" ^ match prefix with | None -> "" | Some prefix -> str prefix) - ^ - match patternPath with - | None -> "" - | Some patternPath -> - " pattern: " - ^ (patternPath |> patternContextPathToString) - ^ " seenIdents: " ^ list alreadySeenIdents) + ^ " pattern: " + ^ (patternPath |> patternContextPathToString) + ^ " seenIdents: " ^ list alreadySeenIdents end module CursorPosition = struct diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index a1224d44b..13cbcb971 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -1372,7 +1372,7 @@ posCursor:[362:8] posNoWhite:[362:7] Found expr:[361:2->365:3] posCursor:[362:8] posNoWhite:[362:7] Found pattern:[362:7->364:5] posCursor:[362:8] posNoWhite:[362:7] Found pattern:[362:7->362:8] Ppat_construct T:[362:7->362:8] -Completable: CtypedContext(Value[x])=T pattern: [] seenIdents: [T] +Completable: CtypedContextPattern(Value[x])=T pattern: [] seenIdents: [T] [] Complete src/Completion.res 373:21 @@ -1381,7 +1381,7 @@ posCursor:[373:21] posNoWhite:[373:20] Found expr:[372:2->376:3] posCursor:[373:21] posNoWhite:[373:20] Found pattern:[373:7->375:5] posCursor:[373:21] posNoWhite:[373:20] Found pattern:[373:7->373:21] Ppat_construct AndThatOther.T:[373:7->373:21] -Completable: CtypedContext(Value[x])=AndThatOther pattern: [] seenIdents: [AndThatOther] +Completable: CtypedContextPattern(Value[x])=AndThatOther pattern: [] seenIdents: [AndThatOther] [] Complete src/Completion.res 378:24 diff --git a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt index 47d8fff36..793282c36 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt @@ -13,7 +13,7 @@ Completable: Cjsx([SomeComponent], someVaria, [someVaria]) Complete src/TypeContextCompletion_Jsx.res 23:38 posCursor:[23:38] posNoWhite:[23:37] Found expr:[23:12->23:38] JSX 23:25] someVariant[23:26->23:37]=...__ghost__[0:-1->0:-1]> _children:None -Completable: CtypedContext(JsxProp())="" +Completable: CtypedContextPattern(JsxProp())="" pattern: [] seenIdents: [] [{ "label": "One", "kind": 4, @@ -55,7 +55,7 @@ Completable: CtypedContext(JsxProp())="" Complete src/TypeContextCompletion_Jsx.res 26:39 posCursor:[26:39] posNoWhite:[26:37] Found expr:[26:12->26:38] JSX 26:25] someVariant[26:26->26:37]=...__ghost__[0:-1->0:-1]> _children:None -Completable: CtypedContext(JsxProp())="" +Completable: CtypedContextPattern(JsxProp())="" pattern: [] seenIdents: [] [{ "label": "One", "kind": 4, @@ -97,7 +97,7 @@ Completable: CtypedContext(JsxProp())="" Complete src/TypeContextCompletion_Jsx.res 29:39 posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:12->29:39] JSX 29:25] someVariant[29:26->29:37]=...[29:38->29:39]> _children:None -Completable: CtypedContext(JsxProp())=T +Completable: CtypedContextPattern(JsxProp())=T pattern: [] seenIdents: [] [{ "label": "Two", "kind": 4, @@ -123,7 +123,7 @@ Completable: Cpath Value[t] Complete src/TypeContextCompletion_Jsx.res 35:39 posCursor:[35:39] posNoWhite:[35:38] Found expr:[35:12->35:39] JSX 35:25] anotherThing[35:26->35:38]=...__ghost__[0:-1->0:-1]> _children:None -Completable: CtypedContext(JsxProp())="" +Completable: CtypedContextPattern(JsxProp())="" pattern: [] seenIdents: [] [{ "label": "Foo", "kind": 4, @@ -141,7 +141,7 @@ Completable: CtypedContext(JsxProp())="" Complete src/TypeContextCompletion_Jsx.res 38:37 posCursor:[38:37] posNoWhite:[38:36] Found expr:[38:12->38:37] JSX 38:25] thirdThing[38:26->38:36]=...__ghost__[0:-1->0:-1]> _children:None -Completable: CtypedContext(JsxProp())="" +Completable: CtypedContextPattern(JsxProp())="" pattern: [] seenIdents: [] [{ "label": "#one", "kind": 4, @@ -183,7 +183,7 @@ Completable: CtypedContext(JsxProp())="" Complete src/TypeContextCompletion_Jsx.res 41:38 posCursor:[41:38] posNoWhite:[41:36] Found expr:[41:12->41:37] JSX 41:25] thirdThing[41:26->41:36]=...__ghost__[0:-1->0:-1]> _children:None -Completable: CtypedContext(JsxProp())="" +Completable: CtypedContextPattern(JsxProp())="" pattern: [] seenIdents: [] [{ "label": "#one", "kind": 4, @@ -225,7 +225,7 @@ Completable: CtypedContext(JsxProp())="" Complete src/TypeContextCompletion_Jsx.res 44:39 posCursor:[44:39] posNoWhite:[44:38] Found expr:[44:12->44:39] JSX 44:25] thirdThing[44:26->44:36]=...[44:37->44:39]> _children:None -Completable: CtypedContext(JsxProp())=t +Completable: CtypedContextPattern(JsxProp())=t pattern: [] seenIdents: [] [{ "label": "#three", "kind": 4, @@ -243,6 +243,6 @@ Completable: CtypedContext(JsxProp())=t Complete src/TypeContextCompletion_Jsx.res 47:39 posCursor:[47:39] posNoWhite:[47:38] Found expr:[47:12->47:39] JSX 47:25] thirdThing[47:26->47:36]=...[47:37->47:39]> _children:None -Completable: CtypedContext(JsxProp())=T +Completable: CtypedContextPattern(JsxProp())=T pattern: [] seenIdents: [] [] diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index bc8e4c8db..44246da5c 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -18,7 +18,7 @@ Found type for function ( Complete src/TypeContextCompletion_LabelledArguments.res 25:44 posCursor:[25:44] posNoWhite:[25:43] Found expr:[25:11->25:44] Pexp_apply ...[25:11->25:30] (~someVariant25:32->25:43=...__ghost__[0:-1->0:-1]) -Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))="" +Completable: CtypedContextPattern(NamedArg(someVariant, Value[someVariantToString]))="" pattern: [] seenIdents: [] [{ "label": "One", "kind": 4, @@ -60,7 +60,7 @@ Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))="" Complete src/TypeContextCompletion_LabelledArguments.res 28:45 posCursor:[28:45] posNoWhite:[28:43] Found expr:[28:11->28:44] Pexp_apply ...[28:11->28:30] (~someVariant28:32->28:43=...__ghost__[0:-1->0:-1]) -Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))="" +Completable: CtypedContextPattern(NamedArg(someVariant, Value[someVariantToString]))="" pattern: [] seenIdents: [] [{ "label": "One", "kind": 4, @@ -102,7 +102,7 @@ Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))="" Complete src/TypeContextCompletion_LabelledArguments.res 31:45 posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:11->31:45] Pexp_apply ...[31:11->31:30] (~someVariant31:32->31:43=...[31:44->31:45]) -Completable: CtypedContext(NamedArg(someVariant, Value[someVariantToString]))=T +Completable: CtypedContextPattern(NamedArg(someVariant, Value[someVariantToString]))=T pattern: [] seenIdents: [] [{ "label": "Two", "kind": 4, @@ -184,7 +184,7 @@ Completable: Cpath Value[TypeDefinition, ""] Complete src/TypeContextCompletion_LabelledArguments.res 40:45 posCursor:[40:45] posNoWhite:[40:44] Found expr:[40:11->40:45] Pexp_apply ...[40:11->40:30] (~anotherThing40:32->40:44=...__ghost__[0:-1->0:-1]) -Completable: CtypedContext(NamedArg(anotherThing, Value[someVariantToString]))="" +Completable: CtypedContextPattern(NamedArg(anotherThing, Value[someVariantToString]))="" pattern: [] seenIdents: [] [{ "label": "Foo", "kind": 4, @@ -202,7 +202,7 @@ Completable: CtypedContext(NamedArg(anotherThing, Value[someVariantToString]))=" Complete src/TypeContextCompletion_LabelledArguments.res 43:43 posCursor:[43:43] posNoWhite:[43:42] Found expr:[43:11->43:43] Pexp_apply ...[43:11->43:30] (~thirdThing43:32->43:42=...__ghost__[0:-1->0:-1]) -Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))="" +Completable: CtypedContextPattern(NamedArg(thirdThing, Value[someVariantToString]))="" pattern: [] seenIdents: [] [{ "label": "#one", "kind": 4, @@ -244,7 +244,7 @@ Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))="" Complete src/TypeContextCompletion_LabelledArguments.res 46:44 posCursor:[46:44] posNoWhite:[46:42] Found expr:[46:11->46:43] Pexp_apply ...[46:11->46:30] (~thirdThing46:32->46:42=...__ghost__[0:-1->0:-1]) -Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))="" +Completable: CtypedContextPattern(NamedArg(thirdThing, Value[someVariantToString]))="" pattern: [] seenIdents: [] [{ "label": "#one", "kind": 4, @@ -286,7 +286,7 @@ Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))="" Complete src/TypeContextCompletion_LabelledArguments.res 49:45 posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:11->49:45] Pexp_apply ...[49:11->49:30] (~thirdThing49:32->49:42=...[49:43->49:45]) -Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))=t +Completable: CtypedContextPattern(NamedArg(thirdThing, Value[someVariantToString]))=t pattern: [] seenIdents: [] [{ "label": "#three", "kind": 4, @@ -304,7 +304,7 @@ Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))=t Complete src/TypeContextCompletion_LabelledArguments.res 52:45 posCursor:[52:45] posNoWhite:[52:44] Found expr:[52:11->52:45] Pexp_apply ...[52:11->52:30] (~thirdThing52:32->52:42=...[52:43->52:45]) -Completable: CtypedContext(NamedArg(thirdThing, Value[someVariantToString]))=T +Completable: CtypedContextPattern(NamedArg(thirdThing, Value[someVariantToString]))=T pattern: [] seenIdents: [] [] Complete src/TypeContextCompletion_LabelledArguments.res 64:36 @@ -312,7 +312,7 @@ posCursor:[64:36] posNoWhite:[64:35] Found expr:[64:11->64:47] Pexp_apply ...[64:11->64:18] (~doThing64:20->64:27=...[64:28->64:46]) posCursor:[64:36] posNoWhite:[64:35] Found pattern:[64:29->64:37] posCursor:[64:36] posNoWhite:[64:35] Found pattern:[64:35->64:36] -Completable: CtypedContext(FunctionArgument(fnSource:NamedArg(doThing, Value[doStuff]), arg:unlabelled(0)))=n pattern: [] seenIdents: [age] +Completable: CtypedContextPattern(FunctionArgument(fnSource:NamedArg(doThing, Value[doStuff]), arg:unlabelled(0)))=n pattern: [] seenIdents: [age] [{ "label": "name", "kind": 5, diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index c1238c841..72f208e7d 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -1,7 +1,7 @@ Complete src/TypeContextCompletion_Records.res 16:15 posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:7->16:16] posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:8->16:15] -Completable: CtypedContext(Value[someVal])=another pattern: [] seenIdents: [] +Completable: CtypedContextPattern(Value[someVal])=another pattern: [] seenIdents: [] [{ "label": "anotherThing", "kind": 5, @@ -13,7 +13,7 @@ Completable: CtypedContext(Value[someVal])=another pattern: [] seenIdents: [] Complete src/TypeContextCompletion_Records.res 19:23 posCursor:[19:23] posNoWhite:[19:22] Found pattern:[19:7->19:24] posCursor:[19:23] posNoWhite:[19:22] Found pattern:[19:22->19:23] -Completable: CtypedContext(Value[someVal])=s pattern: [] seenIdents: [anotherThing] +Completable: CtypedContextPattern(Value[someVal])=s pattern: [] seenIdents: [anotherThing] [{ "label": "something", "kind": 5, @@ -24,7 +24,7 @@ Completable: CtypedContext(Value[someVal])=s pattern: [] seenIdents: [anotherThi Complete src/TypeContextCompletion_Records.res 22:8 posCursor:[22:8] posNoWhite:[22:7] Found pattern:[22:7->22:9] -Completable: CtypedContext(Value[someVal])="" pattern: [] seenIdents: [] +Completable: CtypedContextPattern(Value[someVal])="" pattern: [] seenIdents: [] [{ "label": "something", "kind": 5, @@ -47,7 +47,7 @@ Completable: CtypedContext(Value[someVal])="" pattern: [] seenIdents: [] Complete src/TypeContextCompletion_Records.res 31:8 posCursor:[31:8] posNoWhite:[31:7] Found pattern:[31:7->31:9] -Completable: CtypedContext(Value[getSomeVal](~irrelevant))="" pattern: [] seenIdents: [] +Completable: CtypedContextPattern(Value[getSomeVal](~irrelevant))="" pattern: [] seenIdents: [] [{ "label": "something", "kind": 5, @@ -71,7 +71,7 @@ Completable: CtypedContext(Value[getSomeVal](~irrelevant))="" pattern: [] seenId Complete src/TypeContextCompletion_Records.res 35:20 posCursor:[35:20] posNoWhite:[35:19] Found pattern:[35:7->35:22] posCursor:[35:20] posNoWhite:[35:19] Found pattern:[35:19->35:21] -Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something] seenIdents: [] +Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something] seenIdents: [] [{ "label": "somethingElse", "kind": 5, @@ -96,7 +96,7 @@ Complete src/TypeContextCompletion_Records.res 38:47 posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:7->38:50] posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:19->38:49] posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:46->38:48] -Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something, RecordField:anotherLevel] seenIdents: [whatIsThis] +Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something, RecordField:anotherLevel] seenIdents: [whatIsThis] [{ "label": "level", "kind": 5, @@ -116,7 +116,7 @@ posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:7->41:51] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:19->41:50] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:46->41:49] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:47->41:48] -Completable: CtypedContext(Value[someVal])=l pattern: [RecordField:something, RecordField:anotherLevel] seenIdents: [] +Completable: CtypedContextPattern(Value[someVal])=l pattern: [RecordField:something, RecordField:anotherLevel] seenIdents: [] [{ "label": "level", "kind": 5, @@ -128,7 +128,7 @@ Completable: CtypedContext(Value[someVal])=l pattern: [RecordField:something, Re Complete src/TypeContextCompletion_Records.res 44:47 posCursor:[44:47] posNoWhite:[44:44] Found pattern:[44:7->44:49] posCursor:[44:47] posNoWhite:[44:44] Found pattern:[44:19->44:48] -Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something] seenIdents: [whatIsThis, anotherLevel] +Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something] seenIdents: [whatIsThis, anotherLevel] [{ "label": "somethingElse", "kind": 5, @@ -140,7 +140,7 @@ Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something] s Complete src/TypeContextCompletion_Records.res 47:31 posCursor:[47:31] posNoWhite:[47:30] Found pattern:[47:7->47:47] posCursor:[47:31] posNoWhite:[47:30] Found pattern:[47:19->47:46] -Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something] seenIdents: [whatIsThis, anotherLevel] +Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something] seenIdents: [whatIsThis, anotherLevel] [{ "label": "somethingElse", "kind": 5, @@ -153,7 +153,7 @@ Complete src/TypeContextCompletion_Records.res 50:44 posCursor:[50:44] posNoWhite:[50:43] Found expr:[50:3->50:54] posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:22->50:46] posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:42->50:45] -Completable: CtypedContext(Value[someVal])=som pattern: [] seenIdents: [thirdThing] +Completable: CtypedContextPattern(Value[someVal])=som pattern: [] seenIdents: [thirdThing] [{ "label": "something", "kind": 5, @@ -165,7 +165,7 @@ Completable: CtypedContext(Value[someVal])=som pattern: [] seenIdents: [thirdThi Complete src/TypeContextCompletion_Records.res 53:52 posCursor:[53:52] posNoWhite:[53:51] Found expr:[53:3->53:61] posCursor:[53:52] posNoWhite:[53:51] Found pattern:[53:51->53:53] -Completable: CtypedContext(Value[someVal])="" pattern: [] seenIdents: [] +Completable: CtypedContextPattern(Value[someVal])="" pattern: [] seenIdents: [] [{ "label": "something", "kind": 5, @@ -190,7 +190,7 @@ Complete src/TypeContextCompletion_Records.res 56:89 posCursor:[56:89] posNoWhite:[56:88] Found expr:[56:3->56:100] posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:51->56:92] posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:63->56:91] -Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something] seenIdents: [whatIsThis, anotherLevel] +Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something] seenIdents: [whatIsThis, anotherLevel] [{ "label": "somethingElse", "kind": 5, @@ -205,7 +205,7 @@ posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:29->81:49] posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:41->81:48] posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:47->81:48] Ppat_construct T:[81:47->81:48] -Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:something] seenIdents: [Two, T] +Completable: CtypedContextPattern(Value[someOtherValue])=T pattern: [RecordField:something] seenIdents: [Two, T] [{ "label": "Three(_)", "kind": 4, @@ -221,7 +221,7 @@ posCursor:[84:48] posNoWhite:[84:47] Found pattern:[84:42->84:49] Ppat_construct Some:[84:42->84:46] posCursor:[84:48] posNoWhite:[84:47] Found pattern:[84:47->84:48] Ppat_construct T:[84:47->84:48] -Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:otherThing, Variant:Some(0)] seenIdents: [] +Completable: CtypedContextPattern(Value[someOtherValue])=T pattern: [RecordField:otherThing, Variant:Some(0)] seenIdents: [] [{ "label": "Two", "kind": 4, @@ -242,7 +242,7 @@ posCursor:[87:47] posNoWhite:[87:46] Found pattern:[87:29->87:49] posCursor:[87:47] posNoWhite:[87:46] Found pattern:[87:42->87:48] posCursor:[87:47] posNoWhite:[87:46] Found pattern:[87:46->87:47] Ppat_construct T:[87:46->87:47] -Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:thirdStuff, Tuple:1] seenIdents: [] +Completable: CtypedContextPattern(Value[someOtherValue])=T pattern: [RecordField:thirdStuff, Tuple:1] seenIdents: [] [{ "label": "Two", "kind": 4, @@ -265,7 +265,7 @@ posCursor:[90:51] posNoWhite:[90:50] Found pattern:[90:46->90:52] Ppat_construct Four:[90:46->90:50] posCursor:[90:51] posNoWhite:[90:50] Found pattern:[90:50->90:52] Ppat_construct ():[90:50->90:52] -Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)] seenIdents: [] +Completable: CtypedContextPattern(Value[someOtherValue])="" pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)] seenIdents: [] [{ "label": "TwentyFive", "kind": 4, @@ -289,7 +289,7 @@ Ppat_construct Five:[93:46->93:50] posCursor:[93:55] posNoWhite:[93:54] Found pattern:[93:50->93:57] posCursor:[93:55] posNoWhite:[93:54] Found pattern:[93:54->93:55] Ppat_construct O:[93:54->93:55] -Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)] seenIdents: [] +Completable: CtypedContextPattern(Value[someOtherValue])=O pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)] seenIdents: [] [{ "label": "One", "kind": 4, @@ -307,7 +307,7 @@ Ppat_construct Some:[96:44->96:48] posCursor:[96:63] posNoWhite:[96:62] Found pattern:[96:49->96:64] posCursor:[96:63] posNoWhite:[96:62] Found pattern:[96:62->96:63] Ppat_construct O:[96:62->96:63] -Completable: CtypedContext(Value[someOtherValue])=O pattern: [RecordField:fourthStuff, Tuple:0, Variant:Some(0), Polyvariant:WithPayload(0)] seenIdents: [] +Completable: CtypedContextPattern(Value[someOtherValue])=O pattern: [RecordField:fourthStuff, Tuple:0, Variant:Some(0), Polyvariant:WithPayload(0)] seenIdents: [] [{ "label": "One", "kind": 4, @@ -326,7 +326,7 @@ posCursor:[99:67] posNoWhite:[99:66] Found pattern:[99:50->99:69] posCursor:[99:67] posNoWhite:[99:66] Found pattern:[99:54->99:67] posCursor:[99:67] posNoWhite:[99:66] Found pattern:[99:66->99:67] Ppat_construct T:[99:66->99:67] -Completable: CtypedContext(Value[someOtherValue])=T pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)] seenIdents: [One, Two, T] +Completable: CtypedContextPattern(Value[someOtherValue])=T pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)] seenIdents: [One, Two, T] [{ "label": "Three(_)", "kind": 4, @@ -340,7 +340,7 @@ posCursor:[102:43] posNoWhite:[102:42] Found expr:[102:3->102:52] posCursor:[102:43] posNoWhite:[102:42] Found pattern:[102:29->102:44] posCursor:[102:43] posNoWhite:[102:42] Found pattern:[102:42->102:43] Ppat_construct S:[102:42->102:43] -Completable: CtypedContext(Value[someOtherValue])=S pattern: [RecordField:otherThing] seenIdents: [] +Completable: CtypedContextPattern(Value[someOtherValue])=S pattern: [RecordField:otherThing] seenIdents: [] [{ "label": "None", "kind": 4, @@ -384,7 +384,7 @@ posCursor:[105:39] posNoWhite:[105:38] Found expr:[105:3->105:48] posCursor:[105:39] posNoWhite:[105:38] Found pattern:[105:29->105:40] posCursor:[105:39] posNoWhite:[105:38] Found pattern:[105:38->105:39] Ppat_construct S:[105:38->105:39] -Completable: CtypedContext(Value[someOtherValue])=S pattern: [RecordField:other2] seenIdents: [] +Completable: CtypedContextPattern(Value[someOtherValue])=S pattern: [RecordField:other2] seenIdents: [] [{ "label": "None", "kind": 4, @@ -405,7 +405,7 @@ posCursor:[108:64] posNoWhite:[108:62] Found pattern:[108:29->108:67] posCursor:[108:64] posNoWhite:[108:62] Found pattern:[108:42->108:66] posCursor:[108:64] posNoWhite:[108:62] Found pattern:[108:46->108:65] Ppat_construct Four:[108:46->108:50] -Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)] seenIdents: [TwentyFive] +Completable: CtypedContextPattern(Value[someOtherValue])="" pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)] seenIdents: [TwentyFive] [{ "label": "SixtyTwo", "kind": 4, @@ -417,7 +417,7 @@ Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:third Complete src/TypeContextCompletion_Records.res 111:38 posCursor:[111:38] posNoWhite:[111:36] Found expr:[111:3->111:47] posCursor:[111:38] posNoWhite:[111:36] Found pattern:[111:29->111:39] -Completable: CtypedContext(Value[someOtherValue])="" pattern: [RecordField:other2(empty context)] seenIdents: [] +Completable: CtypedContextPattern(Value[someOtherValue])="" pattern: [RecordField:other2(empty context)] seenIdents: [] [{ "label": "None", "kind": 4, @@ -436,7 +436,7 @@ Complete src/TypeContextCompletion_Records.res 114:55 posCursor:[114:55] posNoWhite:[114:53] Found expr:[114:3->114:67] posCursor:[114:55] posNoWhite:[114:53] Found pattern:[114:22->114:59] posCursor:[114:55] posNoWhite:[114:53] Found pattern:[114:34->114:59] -Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something, RecordField:whatIsThis] seenIdents: [false] +Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something, RecordField:whatIsThis] seenIdents: [false] [{ "label": "true", "kind": 12, @@ -449,7 +449,7 @@ Complete src/TypeContextCompletion_Records.res 117:46 posCursor:[117:46] posNoWhite:[117:45] Found expr:[117:3->117:58] posCursor:[117:46] posNoWhite:[117:45] Found pattern:[117:22->117:50] posCursor:[117:46] posNoWhite:[117:45] Found pattern:[117:34->117:50] -Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something, RecordField:whatIsThis(empty context)] seenIdents: [] +Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something, RecordField:whatIsThis(empty context)] seenIdents: [] [{ "label": "false", "kind": 12, @@ -469,7 +469,7 @@ posCursor:[120:49] posNoWhite:[120:48] Found expr:[120:3->120:62] posCursor:[120:49] posNoWhite:[120:48] Found pattern:[120:22->120:54] posCursor:[120:49] posNoWhite:[120:48] Found pattern:[120:34->120:52] posCursor:[120:49] posNoWhite:[120:48] Found pattern:[120:47->120:49] -Completable: CtypedContext(Value[someVal])=fa pattern: [RecordField:something, RecordField:whatIsThis] seenIdents: [] +Completable: CtypedContextPattern(Value[someVal])=fa pattern: [RecordField:something, RecordField:whatIsThis] seenIdents: [] [{ "label": "false", "kind": 12, @@ -480,7 +480,7 @@ Completable: CtypedContext(Value[someVal])=fa pattern: [RecordField:something, R Complete src/TypeContextCompletion_Records.res 125:15 posCursor:[125:15] posNoWhite:[125:14] Found expr:[125:3->131:11] -Completable: CtypedContext(Value[x])="" +Completable: CtypedContextPattern(Value[x])="" pattern: [] seenIdents: [] [{ "label": "None", "kind": 4, @@ -525,7 +525,7 @@ posCursor:[128:14] posNoWhite:[128:12] Found expr:[128:3->128:13] Complete src/TypeContextCompletion_Records.res 133:15 posCursor:[133:15] posNoWhite:[133:14] Found expr:[133:3->133:17] -Completable: CtypedContext(Value[y])="" +Completable: CtypedContextPattern(Value[y])="" pattern: [] seenIdents: [] [{ "label": "One", "kind": 4, @@ -560,7 +560,7 @@ Completable: CtypedContext(Value[y])="" Complete src/TypeContextCompletion_Records.res 136:36 posCursor:[136:36] posNoWhite:[136:34] Found expr:[136:3->136:38] -Completable: CtypedContext(Value[y])="" +Completable: CtypedContextPattern(Value[y])="" pattern: [] seenIdents: [] [{ "label": "One", "kind": 4, @@ -596,14 +596,14 @@ Completable: CtypedContext(Value[y])="" Complete src/TypeContextCompletion_Records.res 140:33 posCursor:[140:33] posNoWhite:[140:32] Found expr:[140:3->140:44] posCursor:[140:33] posNoWhite:[140:32] Found pattern:[140:22->140:36] -Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something(empty context)] seenIdents: [] +Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something(empty context)] seenIdents: [] [] Complete src/TypeContextCompletion_Records.res 144:35 posCursor:[144:35] posNoWhite:[144:34] Found expr:[144:3->144:46] posCursor:[144:35] posNoWhite:[144:34] Found pattern:[144:22->144:38] posCursor:[144:35] posNoWhite:[144:34] Found pattern:[144:34->144:36] -Completable: CtypedContext(Value[someVal])="" pattern: [RecordField:something] seenIdents: [] +Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something] seenIdents: [] [{ "label": "somethingElse", "kind": 5, From 8a98793bd8477511048dfec4e4d5c84c5d46aee4 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 15 Aug 2022 11:22:57 +0200 Subject: [PATCH 60/80] add debug tool and start setting up spec for typed context completion --- analysis/src/Commands.ml | 16 +- analysis/src/DumpAst.ml | 273 ++++++ analysis/src/SharedTypes.ml | 11 + .../tests/src/TypedContextCompletionSpec.res | 218 +++++ analysis/tests/src/expected/Dce.res.txt | 2 +- analysis/tests/src/expected/Debug.res.txt | 3 +- .../TypedContextCompletionSpec.res.txt | 904 ++++++++++++++++++ 7 files changed, 1422 insertions(+), 5 deletions(-) create mode 100644 analysis/src/DumpAst.ml create mode 100644 analysis/tests/src/TypedContextCompletionSpec.res create mode 100644 analysis/tests/src/expected/TypedContextCompletionSpec.res.txt diff --git a/analysis/src/Commands.ml b/analysis/src/Commands.ml index ad9ad4a89..42f1489dc 100644 --- a/analysis/src/Commands.ml +++ b/analysis/src/Commands.ml @@ -390,14 +390,24 @@ let test ~path = (Protocol.stringifyRange range) indent indent newText))) | "dia" -> diagnosticSyntax ~path - | "hin" -> ( + | "hin" -> let line_start = 0 in let line_end = 6 in - print_endline ("Inlay Hint " ^ path ^ " " ^ string_of_int line_start ^ ":" ^ string_of_int line_end); - inlayhint ~path ~pos:(line_start, line_end) ~maxLength:"25" ~debug:false) + print_endline + ("Inlay Hint " ^ path ^ " " ^ string_of_int line_start ^ ":" + ^ string_of_int line_end); + inlayhint ~path ~pos:(line_start, line_end) ~maxLength:"25" + ~debug:false | "cle" -> print_endline ("Code Lens " ^ path); codeLens ~path ~debug:false + | "ast" -> + print_endline + ("Dump AST " ^ path ^ " " ^ string_of_int line ^ ":" + ^ string_of_int col); + let currentFile = createCurrentFile () in + DumpAst.dump ~pos:(line, col) ~currentFile; + Sys.remove currentFile | _ -> ()); print_newline ()) in diff --git a/analysis/src/DumpAst.ml b/analysis/src/DumpAst.ml new file mode 100644 index 000000000..858334d33 --- /dev/null +++ b/analysis/src/DumpAst.ml @@ -0,0 +1,273 @@ +open SharedTypes +(* This is intended to be a debug tool. It's by no means complete. Rather, you're encouraged to extend this with printing whatever types you need printing. *) + +let emptyLocDenom = "" +let hasCursorDenom = "<*>" +let noCursorDenom = "" + +let printLocDenominator loc ~pos = + match loc |> CursorPosition.classifyLoc ~pos with + | EmptyLoc -> emptyLocDenom + | HasCursor -> hasCursorDenom + | NoCursor -> noCursorDenom + +let printLocDenominatorLoc loc ~pos = + match loc |> CursorPosition.classifyLocationLoc ~pos with + | CursorPosition.EmptyLoc -> emptyLocDenom + | HasCursor -> hasCursorDenom + | NoCursor -> noCursorDenom + +let printLocDenominatorPos pos ~posStart ~posEnd = + match CursorPosition.classifyPositions pos ~posStart ~posEnd with + | CursorPosition.EmptyLoc -> emptyLocDenom + | HasCursor -> hasCursorDenom + | NoCursor -> noCursorDenom + +let addIndentation indentation = + let rec indent str indentation = + if indentation < 1 then str else indent (str ^ " ") (indentation - 1) + in + indent "" indentation + +let printConstant const = + match const with + | Parsetree.Pconst_integer (s, _) -> "Pconst_integer(" ^ s ^ ")" + | Pconst_char c -> "Pconst_char(" ^ String.make 1 c ^ ")" + | Pconst_string (s, delim) -> + let delim = + match delim with + | None -> "" + | Some delim -> delim ^ " " + in + "Pconst_string(" ^ delim ^ s ^ delim ^ ")" + | Pconst_float (s, _) -> "Pconst_float(" ^ s ^ ")" + +let printCoreType typ ~pos = + (typ.Parsetree.ptyp_loc |> printLocDenominator ~pos) + ^ + match typ.ptyp_desc with + | Ptyp_any -> "Ptyp_any" + | Ptyp_var name -> "Ptyp_var(" ^ Completable.str name ^ ")" + | Ptyp_constr (loc, _types) -> + "Ptyp_constr(" + ^ (loc |> printLocDenominatorLoc ~pos) + ^ (Utils.flattenLongIdent loc.txt |> Completable.ident |> Completable.str) + ^ ")" + | _ -> "" + +let rec printPattern pattern ~pos ~indentation = + (pattern.Parsetree.ppat_loc |> printLocDenominator ~pos) + ^ + match pattern.Parsetree.ppat_desc with + | Ppat_or (pat1, pat2) -> + "Ppat_or(\n" + ^ addIndentation (indentation + 1) + ^ printPattern pat1 ~pos ~indentation:(indentation + 2) + ^ ",\n" + ^ addIndentation (indentation + 1) + ^ printPattern pat2 ~pos ~indentation:(indentation + 2) + ^ "\n" ^ addIndentation indentation ^ ")" + | Ppat_extension (({txt} as loc), _) -> + "Ppat_extension(%" ^ (loc |> printLocDenominatorLoc ~pos) ^ txt ^ ")" + | Ppat_var ({txt} as loc) -> + "Ppat_var(" ^ (loc |> printLocDenominatorLoc ~pos) ^ txt ^ ")" + | Ppat_constant const -> "Ppat_constant(" ^ printConstant const ^ ")" + | Ppat_construct (({txt} as loc), maybePat) -> + "Ppat_construct(" + ^ (loc |> printLocDenominatorLoc ~pos) + ^ (Utils.flattenLongIdent txt |> Completable.ident |> Completable.str) + ^ (match maybePat with + | None -> "" + | Some pat -> "," ^ printPattern pat ~pos ~indentation) + ^ ")" + | Ppat_variant (label, maybePat) -> + "Ppat_variant(" ^ Completable.str label + ^ (match maybePat with + | None -> "" + | Some pat -> "," ^ printPattern pat ~pos ~indentation) + ^ ")" + | Ppat_record (fields, _) -> + "Ppat_record(\n" + ^ addIndentation (indentation + 1) + ^ "fields:\n" + ^ (fields + |> List.map (fun ((Location.{txt} as loc), pat) -> + addIndentation (indentation + 2) + ^ (loc |> printLocDenominatorLoc ~pos) + ^ (Utils.flattenLongIdent txt |> Completable.ident + |> Completable.str) + ^ ": " + ^ printPattern pat ~pos ~indentation:(indentation + 2)) + |> String.concat "\n") + ^ "\n" ^ addIndentation indentation ^ ")" + | Ppat_tuple patterns -> + "Ppat_tuple(\n" + ^ (patterns + |> List.map (fun pattern -> + addIndentation (indentation + 2) + ^ (pattern |> printPattern ~pos ~indentation:(indentation + 2))) + |> String.concat ",\n") + ^ "\n" ^ addIndentation indentation ^ ")" + | Ppat_any -> "Ppat_any" + | Ppat_constraint (pattern, typ) -> + "Ppat_constraint(\n" + ^ addIndentation (indentation + 1) + ^ printCoreType typ ~pos ^ ",\n" + ^ addIndentation (indentation + 1) + ^ (pattern |> printPattern ~pos ~indentation:(indentation + 1)) + ^ "\n" ^ addIndentation indentation ^ ")" + | v -> Printf.sprintf "" (Utils.identifyPpat v) + +and printCase case ~pos ~indentation ~caseNum = + addIndentation indentation + ^ Printf.sprintf "case %i:\n" caseNum + ^ addIndentation (indentation + 1) + ^ "pattern" + ^ (case.Parsetree.pc_lhs.ppat_loc |> printLocDenominator ~pos) + ^ ":\n" + ^ addIndentation (indentation + 2) + ^ printPattern case.Parsetree.pc_lhs ~pos ~indentation + ^ "\n" + ^ addIndentation (indentation + 1) + ^ "expr" + ^ (case.Parsetree.pc_rhs.pexp_loc |> printLocDenominator ~pos) + ^ ":\n" + ^ printExprItem case.pc_rhs ~pos ~indentation:(indentation + 2) + +and printExprItem expr ~pos ~indentation = + addIndentation indentation + ^ (expr.Parsetree.pexp_loc |> printLocDenominator ~pos) + ^ + match expr.Parsetree.pexp_desc with + | Pexp_match (matchExpr, cases) -> + "Pexp_match(" + ^ printExprItem matchExpr ~pos ~indentation:0 + ^ ")\n" + ^ (cases + |> List.mapi (fun caseNum case -> + printCase case ~pos ~caseNum:(caseNum + 1) + ~indentation:(indentation + 1)) + |> String.concat "\n") + | Pexp_ident {txt} -> + "Pexp_ident:" ^ (Utils.flattenLongIdent txt |> SharedTypes.Completable.ident) + | Pexp_apply (expr, args) -> + let printLabel labelled ~pos = + match labelled with + | None -> "" + | Some labelled -> + printLocDenominatorPos pos + ~posStart:labelled.CompletionFrontEnd.posStart ~posEnd:labelled.posEnd + ^ "~" + ^ if labelled.opt then "?" else "" ^ labelled.name + in + let args = CompletionFrontEnd.extractExpApplyArgs ~args in + "Pexp_apply(\n" + ^ addIndentation (indentation + 1) + ^ "expr:\n" + ^ printExprItem expr ~pos ~indentation:(indentation + 2) + ^ "\n" + ^ addIndentation (indentation + 1) + ^ "args:\n" + ^ (args + |> List.map (fun arg -> + addIndentation (indentation + 2) + ^ printLabel arg.CompletionFrontEnd.label ~pos + ^ "=\n" + ^ printExprItem arg.exp ~pos ~indentation:(indentation + 3)) + |> String.concat ",\n") + ^ "\n" ^ addIndentation indentation ^ ")" + | Pexp_constant constant -> "Pexp_constant(" ^ printConstant constant ^ ")" + | Pexp_construct (({txt} as loc), maybeExpr) -> + "Pexp_construct(" + ^ (loc |> printLocDenominatorLoc ~pos) + ^ (Utils.flattenLongIdent txt |> Completable.ident |> Completable.str) + ^ (match maybeExpr with + | None -> "" + | Some expr -> ", " ^ printExprItem expr ~pos ~indentation) + ^ ")" + | Pexp_variant (label, maybeExpr) -> + "Pexp_variant(" ^ Completable.str label + ^ (match maybeExpr with + | None -> "" + | Some expr -> "," ^ printExprItem expr ~pos ~indentation) + ^ ")" + | Pexp_fun (arg, _maybeDefaultArgExpr, pattern, nextExpr) -> + "Pexp_fun(\n" + ^ addIndentation (indentation + 1) + ^ "arg: " + ^ (match arg with + | Nolabel -> "Nolabel" + | Labelled name -> "Labelled(" ^ name ^ ")" + | Optional name -> "Optional(" ^ name ^ ")") + ^ ",\n" + ^ addIndentation (indentation + 1) + ^ "pattern: " + ^ printPattern pattern ~pos ~indentation:(indentation + 2) + ^ ",\n" + ^ addIndentation (indentation + 1) + ^ "next expr:\n" + ^ printExprItem nextExpr ~pos ~indentation:(indentation + 2) + ^ "\n" ^ addIndentation indentation ^ ")" + | Pexp_extension (({txt} as loc), _) -> + "Pexp_extension(%" ^ (loc |> printLocDenominatorLoc ~pos) ^ txt ^ ")" + | v -> Printf.sprintf "" (Utils.identifyPexp v) + +let printValueBinding value ~pos ~indentation = + "value pattern" + ^ printLocDenominator value.Parsetree.pvb_loc ~pos + ^ ":\n" + ^ addIndentation (indentation + 1) + ^ (value.pvb_pat |> printPattern ~pos ~indentation:(indentation + 1)) + ^ "\n" ^ addIndentation indentation ^ "expr:\n" + ^ printExprItem value.pvb_expr ~pos ~indentation:(indentation + 1) + +let printStructItem structItem ~pos ~source = + match structItem.Parsetree.pstr_loc |> CursorPosition.classifyLoc ~pos with + | HasCursor -> ( + let startOffset = + match + CompletionFrontEnd.positionToOffset source + (structItem.pstr_loc |> Loc.start) + with + | None -> 0 + | Some offset -> offset + in + let endOffset = + (* Include the next line of the source since that will hold the ast comment pointing to the position. + Caveat: this only works for single line sources with a comment on the next line. Will need to be + adapted if that's not the only use case.*) + let line, _col = structItem.pstr_loc |> Loc.end_ in + match CompletionFrontEnd.positionToOffset source (line + 2, 0) with + | None -> 0 + | Some offset -> offset + in + print_endline + ("\nSource:\n// " + ^ String.sub source startOffset (endOffset - startOffset) + ^ "\n"); + match structItem.pstr_desc with + | Pstr_eval (expr, _attributes) -> + "Pstr_eval(\n" ^ printExprItem expr ~pos ~indentation:1 ^ "\n)" + | Pstr_value (recFlag, values) -> + "Pstr_value(\n" + ^ (match recFlag with + | Recursive -> " rec,\n" + | Nonrecursive -> "") + ^ (values + |> List.map (fun value -> + addIndentation 1 ^ printValueBinding value ~pos ~indentation:1) + |> String.concat ",\n") + ^ "\n)" + | _ -> "") + | _ -> "" + +let dump ~currentFile ~pos = + let {Res_driver.parsetree = structure; source} = + Res_driver.parsingEngine.parseImplementation ~forPrinter:true + ~filename:currentFile + in + + print_endline + (structure + |> List.map (fun structItem -> printStructItem structItem ~pos ~source) + |> String.concat "") diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index e6f5d8d74..b5e96f4fa 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -596,4 +596,15 @@ module CursorPosition = struct if loc |> Loc.hasPos ~pos then HasCursor else if loc |> Loc.end_ = (Location.none |> Loc.end_) then EmptyLoc else NoCursor + + let classifyLocationLoc (loc : 'a Location.loc) ~pos = + if Loc.start loc.Location.loc <= pos && pos <= Loc.end_ loc.loc then + HasCursor + else if loc.loc |> Loc.end_ = (Location.none |> Loc.end_) then EmptyLoc + else NoCursor + + let classifyPositions pos ~posStart ~posEnd = + if posStart <= pos && pos <= posEnd then HasCursor + else if posEnd = (Location.none |> Loc.end_) then EmptyLoc + else NoCursor end \ No newline at end of file diff --git a/analysis/tests/src/TypedContextCompletionSpec.res b/analysis/tests/src/TypedContextCompletionSpec.res new file mode 100644 index 000000000..f3880aabe --- /dev/null +++ b/analysis/tests/src/TypedContextCompletionSpec.res @@ -0,0 +1,218 @@ +type anotherLevel = {level: int, someOtherArg: bool} +type someRecord = {somethingElse: int, whatIsThis: bool, anotherLevel: anotherLevel} + +type anotherRecord = {something: someRecord, anotherThing: option, thirdThing: string} + +let someVal = { + something: { + somethingElse: 123, + whatIsThis: false, + anotherLevel: {level: 123, someOtherArg: true}, + }, + anotherThing: None, + thirdThing: "test", +} + +let getSomeVal = (~irrelevant: int) => { + ignore(irrelevant) + someVal +} + +type someOtherVariant = TwentyFive | SixtyTwo +type rec someVariant = + One | Two | Three(int) | Four(someOtherVariant) | Five(someOtherVariant, someVariant) + +type someRecordWithVariant = { + other: someRecord, + other2: option, + something: someVariant, + otherThing: option, + thirdStuff: (someRecord, someVariant, option, int), + fourthStuff: (option<[#WithPayload(someVariant)]>, someVariant), +} + +let someOtherValue: someRecordWithVariant = { + other: someVal.something, + other2: None, + something: Two, + otherThing: None, + thirdStuff: (someVal.something, One, None, 1), + fourthStuff: (None, One), +} + +let x = Some(One) + +let y = One + +// --- Labelled arguments start --- + +// Should complete the labelled argument name +// let x = someVariantToString(~someVaria +// ^ast + +// Should complete the value for the someVariant arg +// let x = someVariantToString(~someVariant= +// ^ast + +// Same as above but with additional space +// let x = someVariantToString(~someVariant= +// ^^ast + +// Complete for variant T +// let x = someVariantToString(~someVariant=T +// ^ast + +// Complete for identifier t +// let x = someVariantToString(~someVariant=t +// ^ast + +// Complete for things in TypeDefinition. Factor in type? +// let x = someVariantToString(~someVariant=TypeDefinition. +// ^ast + +// Complete for arg anotherThing's type +// let x = someVariantToString(~anotherThing= +// ^ast + +// Complete for thirdThing's type +// let x = someVariantToString(~thirdThing= +// ^ast + +// Complete for polyvariant #t +// let x = someVariantToString(~thirdThing=#t +// ^ast + +// Complete for polyvariant #t +// let x = someVariantToString(~thirdThing=#T +// ^ast + +// --- Labelled arguments end --- + +// --- Record destructuring start --- + +// Complete for destructured record field starting with n +// let _ = doStuff(~doThing=({age, n}) => {()}) +// ^ast + +// Complete for record field another +// let {another} = someVal +// ^ast + +// Complete for record field s +// let {anotherThing, s} = someVal +// ^ast + +// Complete for record fields of someVal +// let {} = someVal +// ^ast + +// Complete for record fields of fn invocation +// let {} = getSomeVal(~irrelevant=123) +// ^ast + +// Complete for record fields on record field something +// let {something: {}} = someVal +// ^ast + +// Complete for record fields of type for anotherLevel +// let {something: {whatIsThis, anotherLevel: {}}} = someVal +// ^ast + +// Complete for record fields of type for anotherLevel, with prefix "l" +// let {something: {whatIsThis, anotherLevel: {l}}} = someVal +// ^ast + +// Complete for record fields of type for something, with seen idents whatIsThis, anotherLevel +// let {something: {whatIsThis, anotherLevel, }} = someVal +// ^ast + +// Complete for record fields of type for something, with seen idents whatIsThis, anotherLevel +// let {something: {whatIsThis, ,anotherLevel}} = someVal +// ^ast + +// --- Record destructuring end --- + +// --- Pattern matching start --- + +// Complete for record field som in root record +// switch someVal { | {thirdThing: "123", som} => () } +// ^ast + +// Complete for any record field in root record +// switch someVal { | {thirdThing: "1234"} => () | {} => () } +// ^ast + +// Complete for record field in type of root record->something +// switch someVal { | {thirdThing: "1234"} => () | {something: {whatIsThis, anotherLevel, }} => () } +// ^ast + +// Complete for variant starting with T in rfield something of root record +// switch someOtherValue { | {something: Two | T} => () } +// ^ast + +// switch someOtherValue { | {otherThing: Some(T)} => () } +// ^ast + +// switch someOtherValue { | {thirdStuff: (_, T)} => () } +// ^ast + +// switch someOtherValue { | {thirdStuff: (_, Four())} => () } +// ^ast + +// switch someOtherValue { | {thirdStuff: (_, Five(_, O))} => () } +// ^ast + +// switch someOtherValue { | {fourthStuff: (Some(#WithPayload(O)), _)} => () } +// ^ast + +// switch someOtherValue { | {thirdStuff: (_, Five(_, One | Two | T))} => () } +// ^ast + +// switch someOtherValue { | {otherThing: S} => () } +// ^ast + +// switch someOtherValue { | {other2: S} => () } +// ^ast + +// switch someOtherValue { | {thirdStuff: (_, Four(TwentyFive | ))} => () } +// ^ast + +// switch someOtherValue { | {other2: } => () } +// ^ast + +// switch someVal { | {something: {whatIsThis: false | } } => () } +// ^ast + +// switch someVal { | {something: {whatIsThis: } } => () } +// ^ast + +// switch someVal { | {something: {whatIsThis: fa } } => () } +// ^ast + +// Complete for root type of x +// switch x { | } +// ^ast + +// Incomplete switch, no completion +// switch x { +// ^ast + +// switch y { | } +// ^ast + +// switch y { | One | Two | Three | } +// ^ast + +// Should not complete because the record has no braces +// switch someVal { | {something: } => () } +// ^ast + +// Should not complete because the record has no braces +// switch someVal { | => () } +// ^ast + +// Should complete because the record has braces +// switch someVal { | {something: {} } => () } +// ^ast + +// --- Pattern matching end --- diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index 256fadee8..cf91af19b 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:290 +issues:313 diff --git a/analysis/tests/src/expected/Debug.res.txt b/analysis/tests/src/expected/Debug.res.txt index 10f7b2f27..78437d8c0 100644 --- a/analysis/tests/src/expected/Debug.res.txt +++ b/analysis/tests/src/expected/Debug.res.txt @@ -4,7 +4,7 @@ Dependencies: @rescript/react Source directories: ./node_modules/@rescript/react/src ./node_modules/@rescript/react/src/legacy Source files: ./node_modules/@rescript/react/src/React.res ./node_modules/@rescript/react/src/ReactDOM.res ./node_modules/@rescript/react/src/ReactDOMServer.res ./node_modules/@rescript/react/src/ReactDOMStyle.res ./node_modules/@rescript/react/src/ReactEvent.res ./node_modules/@rescript/react/src/ReactEvent.resi ./node_modules/@rescript/react/src/ReactTestUtils.res ./node_modules/@rescript/react/src/ReactTestUtils.resi ./node_modules/@rescript/react/src/RescriptReactErrorBoundary.res ./node_modules/@rescript/react/src/RescriptReactErrorBoundary.resi ./node_modules/@rescript/react/src/RescriptReactRouter.res ./node_modules/@rescript/react/src/RescriptReactRouter.resi ./node_modules/@rescript/react/src/legacy/ReactDOMRe.res ./node_modules/@rescript/react/src/legacy/ReasonReact.res Source directories: ./src ./src/expected -Source files: ./src/Auto.res ./src/CodeLens.res ./src/CompletePrioritize1.res ./src/CompletePrioritize2.res ./src/Completion.res ./src/Component.res ./src/Component.resi ./src/CreateInterface.res ./src/Cross.res ./src/Dce.res ./src/Debug.res ./src/Definition.res ./src/DefinitionWithInterface.res ./src/DefinitionWithInterface.resi ./src/Div.res ./src/DocumentSymbol.res ./src/Fragment.res ./src/Highlight.res ./src/Hover.res ./src/InlayHint.res ./src/Jsx.res ./src/Jsx.resi ./src/LongIdentTest.res ./src/Object.res ./src/Patterns.res ./src/RecModules.res ./src/RecordCompletion.res ./src/RecoveryOnProp.res ./src/References.res ./src/ReferencesWithInterface.res ./src/ReferencesWithInterface.resi ./src/Rename.res ./src/RenameWithInterface.res ./src/RenameWithInterface.resi ./src/TableclothMap.ml ./src/TableclothMap.mli ./src/TypeContextCompletion_Jsx.res ./src/TypeContextCompletion_LabelledArguments.res ./src/TypeContextCompletion_Records.res ./src/TypeDefinition.res ./src/Xform.res +Source files: ./src/Auto.res ./src/CodeLens.res ./src/CompletePrioritize1.res ./src/CompletePrioritize2.res ./src/Completion.res ./src/Component.res ./src/Component.resi ./src/CreateInterface.res ./src/Cross.res ./src/Dce.res ./src/Debug.res ./src/Definition.res ./src/DefinitionWithInterface.res ./src/DefinitionWithInterface.resi ./src/Div.res ./src/DocumentSymbol.res ./src/Fragment.res ./src/Highlight.res ./src/Hover.res ./src/InlayHint.res ./src/Jsx.res ./src/Jsx.resi ./src/LongIdentTest.res ./src/Object.res ./src/Patterns.res ./src/RecModules.res ./src/RecordCompletion.res ./src/RecoveryOnProp.res ./src/References.res ./src/ReferencesWithInterface.res ./src/ReferencesWithInterface.resi ./src/Rename.res ./src/RenameWithInterface.res ./src/RenameWithInterface.resi ./src/TableclothMap.ml ./src/TableclothMap.mli ./src/TypeContextCompletion_Jsx.res ./src/TypeContextCompletion_LabelledArguments.res ./src/TypeContextCompletion_Records.res ./src/TypeDefinition.res ./src/TypedContextCompletionSpec.res ./src/Xform.res Impl cmt:./lib/bs/src/Auto.cmt res:./src/Auto.res Impl cmt:./lib/bs/src/CodeLens.cmt res:./src/CodeLens.res Impl cmt:./lib/bs/src/CompletePrioritize1.cmt res:./src/CompletePrioritize1.res @@ -39,6 +39,7 @@ Impl cmt:./lib/bs/src/TypeContextCompletion_Jsx.cmt res:./src/TypeContextComplet Impl cmt:./lib/bs/src/TypeContextCompletion_LabelledArguments.cmt res:./src/TypeContextCompletion_LabelledArguments.res Impl cmt:./lib/bs/src/TypeContextCompletion_Records.cmt res:./src/TypeContextCompletion_Records.res Impl cmt:./lib/bs/src/TypeDefinition.cmt res:./src/TypeDefinition.res +Impl cmt:./lib/bs/src/TypedContextCompletionSpec.cmt res:./src/TypedContextCompletionSpec.res Impl cmt:./lib/bs/src/Xform.cmt res:./src/Xform.res Dependency dirs: ./node_modules/@rescript/react/lib/bs/src ./node_modules/@rescript/react/lib/bs/src/legacy Opens from bsconfig: diff --git a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt new file mode 100644 index 000000000..f91790281 --- /dev/null +++ b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt @@ -0,0 +1,904 @@ +Dump AST src/TypedContextCompletionSpec.res 49:40 + +Source: +// let x = someVariantToString(~someVaria +// ^ast + + +Pstr_value( + value pattern<*>: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + <*>~someVaria= + <*>Pexp_ident:someVaria + ) +) + +Dump AST src/TypedContextCompletionSpec.res 53:43 + +Source: +// let x = someVariantToString(~someVariant= +// ^ast + + +Pstr_value( + value pattern<*>: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + <*>~someVariant= + Pexp_extension(%rescript.exprhole) + ) +) + + +Dump AST src/TypedContextCompletionSpec.res 61:44 + +Source: +// let x = someVariantToString(~someVariant=T +// ^ast + + +Pstr_value( + value pattern<*>: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + ~someVariant= + <*>Pexp_construct(<*>T) + ) +) + +Dump AST src/TypedContextCompletionSpec.res 65:44 + +Source: +// let x = someVariantToString(~someVariant=t +// ^ast + + +Pstr_value( + value pattern<*>: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + ~someVariant= + <*>Pexp_ident:t + ) +) + +Dump AST src/TypedContextCompletionSpec.res 69:58 + +Source: +// let x = someVariantToString(~someVariant=TypeDefinition. +// ^ast + + +Pstr_value( + value pattern<*>: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + ~someVariant= + <*>Pexp_ident:TypeDefinition."" + ) +) + +Dump AST src/TypedContextCompletionSpec.res 73:44 + +Source: +// let x = someVariantToString(~anotherThing= +// ^ast + + +Pstr_value( + value pattern<*>: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + <*>~anotherThing= + Pexp_extension(%rescript.exprhole) + ) +) + +Dump AST src/TypedContextCompletionSpec.res 77:42 + +Source: +// let x = someVariantToString(~thirdThing= +// ^ast + + +Pstr_value( + value pattern<*>: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + <*>~thirdThing= + Pexp_extension(%rescript.exprhole) + ) +) + +Dump AST src/TypedContextCompletionSpec.res 81:44 + +Source: +// let x = someVariantToString(~thirdThing=#t +// ^ast + + +Pstr_value( + value pattern<*>: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + ~thirdThing= + <*>Pexp_variant(t) + ) +) + +Dump AST src/TypedContextCompletionSpec.res 85:44 + +Source: +// let x = someVariantToString(~thirdThing=#T +// ^ast + + +Pstr_value( + value pattern<*>: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + ~thirdThing= + <*>Pexp_variant(T) + ) +) + +Dump AST src/TypedContextCompletionSpec.res 93:36 + +Source: +// let _ = doStuff(~doThing=({age, n}) => {()}) +// ^ast + + +Pstr_value( + value pattern<*>: + Ppat_any + expr: + <*>Pexp_apply( + expr: + Pexp_ident:doStuff + args: + ~doThing= + <*>Pexp_fun( + arg: Nolabel, + pattern: <*>Ppat_record( + fields: + age: Ppat_var(age) + <*>n: Ppat_var(<*>n) + ), + next expr: + Pexp_construct(()) + ) + ) +) + +Dump AST src/TypedContextCompletionSpec.res 97:15 + +Source: +// let {another} = someVal +// ^ast + + +Pstr_value( + value pattern<*>: + <*>Ppat_record( + fields: + <*>another: Ppat_var(<*>another) + ) + expr: + Pexp_ident:someVal +) + +Dump AST src/TypedContextCompletionSpec.res 101:23 + +Source: +// let {anotherThing, s} = someVal +// ^ast + + +Pstr_value( + value pattern<*>: + <*>Ppat_record( + fields: + anotherThing: Ppat_var(anotherThing) + <*>s: Ppat_var(<*>s) + ) + expr: + Pexp_ident:someVal +) + +Dump AST src/TypedContextCompletionSpec.res 105:8 + +Source: +// let {} = someVal +// ^ast + + +Pstr_value( + value pattern<*>: + <*>Ppat_record( + fields: + + ) + expr: + Pexp_ident:someVal +) + +Dump AST src/TypedContextCompletionSpec.res 109:8 + +Source: +// let {} = getSomeVal(~irrelevant=123) +// ^ast + + +Pstr_value( + value pattern<*>: + <*>Ppat_record( + fields: + + ) + expr: + Pexp_apply( + expr: + Pexp_ident:getSomeVal + args: + ~irrelevant= + Pexp_constant(Pconst_integer(123)) + ) +) + +Dump AST src/TypedContextCompletionSpec.res 113:20 + +Source: +// let {something: {}} = someVal +// ^ast + + +Pstr_value( + value pattern<*>: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + + ) + ) + expr: + Pexp_ident:someVal +) + +Dump AST src/TypedContextCompletionSpec.res 117:47 + +Source: +// let {something: {whatIsThis, anotherLevel: {}}} = someVal +// ^ast + + +Pstr_value( + value pattern<*>: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + whatIsThis: Ppat_var(whatIsThis) + anotherLevel: <*>Ppat_record( + fields: + + ) + ) + ) + expr: + Pexp_ident:someVal +) + +Dump AST src/TypedContextCompletionSpec.res 121:48 + +Source: +// let {something: {whatIsThis, anotherLevel: {l}}} = someVal +// ^ast + + +Pstr_value( + value pattern<*>: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + whatIsThis: Ppat_var(whatIsThis) + anotherLevel: <*>Ppat_record( + fields: + <*>l: Ppat_var(<*>l) + ) + ) + ) + expr: + Pexp_ident:someVal +) + +Dump AST src/TypedContextCompletionSpec.res 125:47 + +Source: +// let {something: {whatIsThis, anotherLevel, }} = someVal +// ^ast + + +Pstr_value( + value pattern<*>: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + whatIsThis: Ppat_var(whatIsThis) + anotherLevel: Ppat_var(anotherLevel) + ) + ) + expr: + Pexp_ident:someVal +) + +Dump AST src/TypedContextCompletionSpec.res 129:31 + +Source: +// let {something: {whatIsThis, ,anotherLevel}} = someVal +// ^ast + + +Pstr_value( + value pattern<*>: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + whatIsThis: Ppat_var(whatIsThis) + anotherLevel: Ppat_var(anotherLevel) + ) + ) + expr: + Pexp_ident:someVal +) + +Dump AST src/TypedContextCompletionSpec.res 137:44 + +Source: +// switch someVal { | {thirdThing: "123", som} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + thirdThing: Ppat_constant(Pconst_string(123)) + <*>som: <*>Ppat_var(<*>som) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 141:52 + +Source: +// switch someVal { | {thirdThing: "1234"} => () | {} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern: + Ppat_record( + fields: + thirdThing: Ppat_constant(Pconst_string(1234)) + ) + expr: + Pexp_construct(()) + case 2: + pattern<*>: + <*>Ppat_record( + fields: + + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 145:89 + +Source: +// switch someVal { | {thirdThing: "1234"} => () | {something: {whatIsThis, anotherLevel, }} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern: + Ppat_record( + fields: + thirdThing: Ppat_constant(Pconst_string(1234)) + ) + expr: + Pexp_construct(()) + case 2: + pattern<*>: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + whatIsThis: Ppat_var(whatIsThis) + anotherLevel: Ppat_var(anotherLevel) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 149:48 + +Source: +// switch someOtherValue { | {something: Two | T} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + something: Ppat_or( + Ppat_construct(Two), + Ppat_construct(<*>T) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 152:48 + +Source: +// switch someOtherValue { | {otherThing: Some(T)} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + otherThing: <*>Ppat_construct(Some,Ppat_construct(<*>T)) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 155:47 + +Source: +// switch someOtherValue { | {thirdStuff: (_, T)} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + thirdStuff: <*>Ppat_tuple( + Ppat_any, + Ppat_construct(<*>T) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 158:51 + +Source: +// switch someOtherValue { | {thirdStuff: (_, Four())} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + thirdStuff: <*>Ppat_tuple( + Ppat_any, + <*>Ppat_construct(Four,<*>Ppat_construct(<*>())) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 161:55 + +Source: +// switch someOtherValue { | {thirdStuff: (_, Five(_, O))} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + thirdStuff: <*>Ppat_tuple( + Ppat_any, + <*>Ppat_construct(Five,<*>Ppat_tuple( + Ppat_any, + Ppat_construct(<*>O) + )) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 164:63 + +Source: +// switch someOtherValue { | {fourthStuff: (Some(#WithPayload(O)), _)} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + fourthStuff: <*>Ppat_tuple( + <*>Ppat_construct(Some,<*>Ppat_variant(WithPayload,Ppat_construct(<*>O))), + Ppat_any + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 167:67 + +Source: +// switch someOtherValue { | {thirdStuff: (_, Five(_, One | Two | T))} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + thirdStuff: <*>Ppat_tuple( + Ppat_any, + <*>Ppat_construct(Five,<*>Ppat_tuple( + Ppat_any, + Ppat_or( + Ppat_or( + Ppat_construct(One), + Ppat_construct(Two) + ), + Ppat_construct(<*>T) + ) + )) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 170:43 + +Source: +// switch someOtherValue { | {otherThing: S} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + otherThing: Ppat_construct(<*>S) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 173:39 + +Source: +// switch someOtherValue { | {other2: S} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + other2: Ppat_construct(<*>S) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 176:64 + +Source: +// switch someOtherValue { | {thirdStuff: (_, Four(TwentyFive | ))} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + thirdStuff: <*>Ppat_tuple( + Ppat_any, + <*>Ppat_construct(Four,Ppat_or( + Ppat_construct(TwentyFive), + Ppat_extension(%rescript.patternhole) + )) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 179:38 + +Source: +// switch someOtherValue { | {other2: } => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + other2: Ppat_extension(%rescript.patternhole) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 182:55 + +Source: +// switch someVal { | {something: {whatIsThis: false | } } => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + whatIsThis: Ppat_or( + Ppat_construct(false), + Ppat_extension(%rescript.patternhole) + ) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 185:46 + +Source: +// switch someVal { | {something: {whatIsThis: } } => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + whatIsThis: Ppat_extension(%rescript.patternhole) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 188:49 + +Source: +// switch someVal { | {something: {whatIsThis: fa } } => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + whatIsThis: Ppat_var(<*>fa) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 192:15 + +Source: +// switch x { | } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:x) + case 1: + pattern: + Ppat_extension(%rescript.patternhole) + expr: + Pexp_extension(%rescript.exprhole) +) + +Dump AST src/TypedContextCompletionSpec.res 196:14 + + +Dump AST src/TypedContextCompletionSpec.res 199:15 + +Source: +// switch y { | } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:y) + case 1: + pattern: + Ppat_extension(%rescript.patternhole) + expr: + Pexp_extension(%rescript.exprhole) +) + +Dump AST src/TypedContextCompletionSpec.res 202:36 + +Source: +// switch y { | One | Two | Three | } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:y) + case 1: + pattern: + Ppat_or( + Ppat_or( + Ppat_or( + Ppat_construct(One), + Ppat_construct(Two) + ), + Ppat_construct(Three) + ), + Ppat_extension(%rescript.patternhole) + ) + expr: + Pexp_extension(%rescript.exprhole) +) + +Dump AST src/TypedContextCompletionSpec.res 206:33 + +Source: +// switch someVal { | {something: } => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + something: Ppat_extension(%rescript.patternhole) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 210:22 + +Source: +// switch someVal { | => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern: + Ppat_construct(()) + expr: + Pexp_extension(%rescript.exprhole) +) + +Dump AST src/TypedContextCompletionSpec.res 214:35 + +Source: +// switch someVal { | {something: {} } => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + + ) + ) + expr: + Pexp_construct(()) +) + From 5647a1ecd86b8aec6171603b84de1f3d2488086f Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 15 Aug 2022 22:09:45 +0200 Subject: [PATCH 61/80] start moving to rewrite of finding pattern completable --- analysis/src/CompletionBackEnd.ml | 15 +- analysis/src/CompletionFrontEnd.ml | 438 +++- analysis/src/DumpAst.ml | 6 +- analysis/src/SharedTypes.ml | 51 +- .../tests/src/TypedContextCompletionSpec.res | 101 +- .../tests/src/expected/Completion.res.txt | 4 +- .../TypeContextCompletion_Records.res.txt | 509 +--- .../TypedContextCompletionSpec.res.spec.txt | 965 ++++++++ .../TypedContextCompletionSpec.res.txt | 2115 +++++++++++------ 9 files changed, 2906 insertions(+), 1298 deletions(-) create mode 100644 analysis/tests/src/expected/TypedContextCompletionSpec.res.spec.txt diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 5def8951e..8a218ccbc 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1470,24 +1470,16 @@ let findTypeInContext (typ : Types.type_expr) ~env ~nestedContextPath ~package = typeExprToCompletable currentType ~env ~package | targetItem :: nestedContextPath -> ( match (targetItem, currentType |> extractType ~env ~package) with - | ( Completable.RField {fieldName; emptyContext}, + | ( Completable.RField {fieldName}, Some (Declared (_, {item = {kind = Record fields}})) ) -> ( match fields |> List.find_opt (fun field -> field.fname.txt = fieldName) with | None -> None - | Some targetField -> ( + | Some targetField -> if List.length nestedContextPath > 0 then targetField.typ |> digToType ~env ~nestedContextPath ~package - else - (* emptyContext means this record field was found without braces/parens (like `{someField: }`). - In these cases, we can complete for variants etc, but we can't complete for tuples or record fields, - since they'd require preceding characters (parens for tuple, brace for record) to be valid patterns. *) - match - (emptyContext, typeExprToCompletable targetField.typ ~env ~package) - with - | true, Some (CRecord _) -> None - | _, completable -> completable)) + else typeExprToCompletable targetField.typ ~env ~package) | ( Variant {constructorName; payloadNum}, Some (Declared (_, {item = {kind = Variant constructors}})) ) -> ( match @@ -2142,3 +2134,4 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i (Completion.Field (field, decl |> Shared.declToString name.txt))) else None))) + | CtypedPattern _ -> [] diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 195fd041d..cf8c5ab4f 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -69,6 +69,33 @@ let identFromPat pat = | Ppat_variant (label, _) -> Some label | _ -> None +let rec identListFromPat pat = + match pat.Parsetree.ppat_desc with + | Ppat_var loc -> [loc.txt] + (* Allow moving one level into variants, just to be able to complete Some(One) etc successfully *) + (* E.g. Some(One)*) + | Ppat_construct (loc, Some {ppat_desc = Ppat_construct (innerLoc, _)}) -> + [getSimpleFieldName loc.txt ^ "(" ^ getSimpleFieldName innerLoc.txt ^ ")"] + (* E.g. Some(#One)*) + | Ppat_construct (loc, Some {ppat_desc = Ppat_variant (innerLabel, _)}) -> + [getSimpleFieldName loc.txt ^ "(" ^ innerLabel ^ ")"] + (* E.g. #Whatever(One)*) + | Ppat_variant (label, Some {ppat_desc = Ppat_construct (innerLoc, _)}) -> + [label ^ "(" ^ getSimpleFieldName innerLoc.txt ^ ")"] + (* E.g. #Whatever(#One)*) + | Ppat_variant (label, Some {ppat_desc = Ppat_variant (innerLabel, _)}) -> + [label ^ "(" ^ innerLabel ^ ")"] + | Ppat_construct (loc, _) -> [getSimpleFieldName loc.txt] + | Ppat_variant (label, _) -> [label] + | Ppat_or (pat1, pat2) -> identListFromPat pat1 @ identListFromPat pat2 + | _ -> [] + +let rec findAllOrBranches pat ~branches = + match pat.Parsetree.ppat_desc with + | Ppat_or (pat1, pat2) -> + pat1 |> findAllOrBranches ~branches:([pat2] @ branches) + | _ -> [pat] @ branches + let findAlreadySeenIdents pat = match pat.Parsetree.ppat_desc with | Ppat_or (pat1, pat2) -> @@ -95,10 +122,6 @@ let rec findCompletableInPattern pattern ~path ~posBeforeCursor ~prefix found _some_ context. We check that context and the char before the cursor to figure out if we should complete for that path. *) match (path, firstCharBeforeCursorNoWhite) with - | Completable.RField rfield :: rest, Some ':' -> - (* We're setting "emptyContext" here, because this record field was found without - braces or parens leading, which affects what we can complete if a type is found. *) - Some ([Completable.RField {rfield with emptyContext = true}] @ rest) (* Handles: One | Two | *) | _ :: _, Some '|' -> seenIdents := findAlreadySeenIdents pattern; @@ -207,7 +230,7 @@ let rec findCompletableInPattern pattern ~path ~posBeforeCursor ~prefix (* let {something} = whatever <- shorthand for let {something:something}, which is just an alias, so we don't want to consider it entering the record field. *) path - | _ -> [Completable.RField {fieldName; emptyContext = false}] @ path + | _ -> [Completable.RField {fieldName}] @ path in pat |> findCompletableInPattern ~posBeforeCursor ~prefix @@ -217,12 +240,7 @@ let rec findCompletableInPattern pattern ~path ~posBeforeCursor ~prefix Some path | Ppat_or (pat1, pat2) -> ( seenIdents := findAlreadySeenIdents pattern; - let rec findAllOrBranches pat ~branches = - match pat.Parsetree.ppat_desc with - | Ppat_or (pat1, pat2) -> - pat1 |> findAllOrBranches ~branches:([pat2] @ branches) - | _ -> [pat] @ branches - in + let branches = pat1 |> findAllOrBranches ~branches:[pat2] in let branchAtCursor = branches @@ -572,6 +590,285 @@ let extractExpApplyArgs ~args = in args |> processArgs ~acc:[] +type findContextInPatternRes = { + lookingToComplete: Completable.lookingToComplete; + patternPath: Completable.patternPathItem list; + prefix: string; + alreadySeenIdents: string list; +} + +let rec findTupleItemWithCursor items ~index ~pos = + match items with + | [] -> None + | item :: rest -> + if CursorPosition.classifyLoc item.Parsetree.ppat_loc ~pos = HasCursor then + Some (Some item, index) + else findTupleItemWithCursor rest ~index:(index + 1) ~pos + +let rec findContextInPattern pattern ~pos ~patternPath ~debug + ~seenIdentsFromParent = + match pattern.Parsetree.ppat_desc with + | Ppat_extension ({txt = "rescript.patternhole"}, _) -> + (* This is printed when the parser has made recovery. + E.g. `| Something => () | ` *) + Some + { + (* We're completing vars as variants for now, since bool (which is a variant) is the only thing + I can think of that needs completion here. *) + lookingToComplete = CNoContext; + patternPath; + prefix = ""; + alreadySeenIdents = seenIdentsFromParent; + } + | Ppat_var loc when CursorPosition.classifyLoc loc.loc ~pos = HasCursor -> + (* E.g. something: someVar *) + Some + { + (* We're completing vars as variants for now, since bool (which is a variant) is the only thing + I can think of that needs completion here. *) + lookingToComplete = CVariant; + patternPath; + prefix = loc.txt; + alreadySeenIdents = []; + } + (* Variants etc *) + | Ppat_construct ({txt}, Some payload) + when CursorPosition.classifyLoc payload.ppat_loc ~pos = HasCursor -> + (* When there's a variant with a payload, and the cursor is in the pattern. Some(S) for example. *) + let payloadNum = + match payload.ppat_desc with + | Ppat_tuple items -> + (* Find the tuple item that has the cursor, so we can add that as payload num for the variant.*) + findTupleItemWithCursor items ~index:0 ~pos + | _ -> Some (None, 0) + in + let patternToContinueFrom = + match payloadNum with + | Some (Some pat, _) -> pat + | _ -> payload + in + findContextInPattern patternToContinueFrom ~pos ~debug + ~seenIdentsFromParent:[] + ~patternPath: + ([ + Completable.Variant + { + constructorName = getSimpleFieldName txt; + payloadNum = + (match payloadNum with + | Some (_, payloadNum) -> Some payloadNum + | _ -> None); + }; + ] + @ patternPath) + | Ppat_variant (constructorName, Some pat) + when CursorPosition.classifyLoc pat.ppat_loc ~pos = HasCursor -> ( + (* When there's a polyvariant with a payload, and the cursor is in the pattern. Some(S) for example. *) + match pat.ppat_desc with + | Ppat_tuple _ -> + (* Continue down here too, but let us discover the tuple in the next step. *) + findContextInPattern pat ~pos ~patternPath ~debug ~seenIdentsFromParent:[] + | _ -> + findContextInPattern pat ~pos ~debug ~seenIdentsFromParent:[] + ~patternPath: + ([Completable.Variant {constructorName; payloadNum = Some 0}] + @ patternPath)) + | Ppat_construct ({txt}, None) -> ( + (* Payload-less variant *) + match CursorPosition.classifyLoc pattern.ppat_loc ~pos with + | HasCursor -> + Some + { + lookingToComplete = CVariant; + patternPath; + prefix = getSimpleFieldName txt; + alreadySeenIdents = seenIdentsFromParent; + } + | NoCursor -> None + | EmptyLoc -> None) + | Ppat_variant (label, None) -> ( + (* Payload-less polyvariant *) + match CursorPosition.classifyLoc pattern.ppat_loc ~pos with + | HasCursor -> + Some + { + lookingToComplete = CPolyvariant; + patternPath; + prefix = label; + alreadySeenIdents = seenIdentsFromParent; + } + | NoCursor -> None + | EmptyLoc -> None) + | Ppat_construct + ( {txt}, + Some {ppat_loc; ppat_desc = Ppat_construct ({txt = Lident "()"}, _)} ) + -> ( + (* A variant like SomeVariant(). Interpret as completing the payload of the variant *) + match CursorPosition.classifyLoc ppat_loc ~pos with + | HasCursor -> + Some + { + lookingToComplete = CNoContext; + patternPath = + [ + Completable.Variant + {constructorName = getSimpleFieldName txt; payloadNum = Some 0}; + ] + @ patternPath; + prefix = ""; + alreadySeenIdents = []; + } + | NoCursor -> None + | EmptyLoc -> None) + | Ppat_variant + ( label, + Some {ppat_loc; ppat_desc = Ppat_construct ({txt = Lident "()"}, _)} ) + -> ( + (* A polyvariant like #SomeVariant(). Interpret as completing the payload of the variant *) + match CursorPosition.classifyLoc ppat_loc ~pos with + | HasCursor -> + Some + { + lookingToComplete = CNoContext; + patternPath = + [Completable.Polyvariant {name = label; payloadNum = Some 0}] + @ patternPath; + prefix = ""; + alreadySeenIdents = []; + } + | NoCursor -> None + | EmptyLoc -> None) + (* Records *) + | Ppat_record ([], _) -> + (* No fields mean we're in an empty record body. We can complete for that. *) + Some + { + lookingToComplete = CRecordField; + patternPath; + prefix = ""; + alreadySeenIdents = []; + } + | Ppat_record (fields, _) -> + let seenFields = + fields |> List.map (fun ({Location.txt}, _) -> getSimpleFieldName txt) + in + let fieldWithCursorExists = + fields + |> List.exists (fun (_, fieldPat) -> + CursorPosition.classifyLoc fieldPat.Parsetree.ppat_loc ~pos + = HasCursor) + in + fields + |> List.find_map (fun (loc, fieldPat) -> + match + CursorPosition.classifyLoc fieldPat.Parsetree.ppat_loc ~pos + with + | HasCursor -> ( + (* handle `{something}`, which is parsed as `{something: something}` because of punning *) + match (loc, fieldPat.Parsetree.ppat_desc) with + | ( {Location.txt = Longident.Lident fieldName}, + Ppat_var {txt = varName} ) + when fieldName = varName -> + Some + { + lookingToComplete = CRecordField; + patternPath; + prefix = varName; + alreadySeenIdents = seenFields; + } + | _ -> + (* We can continue down into anything else *) + findContextInPattern fieldPat ~pos ~debug + ~seenIdentsFromParent:[] + ~patternPath: + ([ + Completable.RField {fieldName = getSimpleFieldName loc.txt}; + ] + @ patternPath)) + | NoCursor -> None + | EmptyLoc -> + if + (* We only care about empty locations if there's no field with the cursor *) + fieldWithCursorExists + then None + else + findContextInPattern fieldPat ~pos ~debug + ~seenIdentsFromParent:[] + ~patternPath: + ([ + Completable.RField {fieldName = getSimpleFieldName loc.txt}; + ] + @ patternPath)) + | Ppat_tuple items -> ( + match findTupleItemWithCursor items ~pos ~index:0 with + | Some (Some tuplePatternWithCursor, itemNumber) -> + findContextInPattern tuplePatternWithCursor ~pos ~debug + ~seenIdentsFromParent:[] + ~patternPath:([Completable.PTuple {itemNumber}] @ patternPath) + | None -> + (* TODO: No tuple item had the cursor, but we might still be able to complete + for the next tuple item. We just need to figure out where in the pattern + we are. E.g. `(_, , A)` is parsed the same as `(_, A, )` or `(_, A, ,)`. + Figuring out exactly which tuple item we're in is problematic because of that. *) + None + | _ -> None) + | Ppat_or (pat1, pat2) -> ( + (* There's a few things that can happen as we're looking for or patterns. + a. First off, we can find an or pattern with the cursor, in which case we should try to descend into it. + E.g. `One | Two | Three({someField: s})` + b. Secondly, if there's no pattern with the cursor, there might be a or pattern with parser recovery in it. + That means the user has written an empty or pattern, in which case we should complete for the current type. + E.g. `One | Two | ` *) + let branches = + pat1 + |> findAllOrBranches ~branches:[pat2] + |> List.filter (fun pat -> + match pat.Parsetree.ppat_desc with + | Ppat_or _ -> false + | _ -> true) + in + let branchAtCursor = + branches + |> List.find_opt (fun pat -> + pat.Parsetree.ppat_loc + |> CursorPosition.classifyLoc ~pos + = HasCursor) + in + let identsFromBranches = + branches + |> List.map (fun branch -> branch |> identListFromPat) + |> List.flatten + in + match branchAtCursor with + | None -> ( + let branchWithEmptyLoc = + branches + |> List.find_opt (fun pat -> + pat.Parsetree.ppat_loc + |> CursorPosition.classifyLoc ~pos + = EmptyLoc) + in + (* If we found no branch with the cursor, look for one with an empty loc + that's a patternhole (error recovery done by the parser). *) + match branchWithEmptyLoc with + | Some {ppat_desc = Ppat_extension ({txt = "rescript.patternhole"}, _)} -> + Some + { + lookingToComplete = CNoContext; + patternPath; + prefix = ""; + alreadySeenIdents = identsFromBranches; + } + | _ -> None) + | Some pattern -> + pattern + |> findContextInPattern ~pos ~patternPath ~debug + ~seenIdentsFromParent:identsFromBranches) + | _v -> + (* if debug then + Printf.printf "warning: unhandled pattern %s\n" (Utils.identifyPpat v);*) + None + let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = let offsetNoWhite = skipWhite text (offset - 1) in let posNoWhite = @@ -715,7 +1012,6 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = (* This is an experiment and should most likely not live here in its final form. *) (* Check for: let {destructuringSomething} = someIdentifier *) (* Ensure cursor is inside of record pattern. *) - (* TODO: Tuples, etc... *) (* TODO: Handle let {SomeModule.recordField} = ...*) (match bindings with | [{pvb_pat; pvb_expr = expr}] when !result = None -> ( @@ -723,11 +1019,32 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = Depending on if the destructure is nested or not, we may or may not use that directly.*) match exprToContextPath expr with | None -> () - | Some contextPath -> + | Some contextPath when false -> setResultOpt (pvb_pat |> completePattern ~howToRetrieveSourceType:(CtxPath contextPath) - ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~seenIdents:[])) + ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~seenIdents:[]) + | Some contextPath -> ( + match + findContextInPattern pvb_pat ~pos:posBeforeCursor ~patternPath:[] + ~seenIdentsFromParent:[] ~debug + with + | None -> () + | Some res -> + setResultOpt + (Some + (CtypedPattern + { + howToRetrieveSourceType = CtxPath contextPath; + patternPath = res.patternPath |> List.rev; + patternType = Destructure; + lookingToComplete = res.lookingToComplete; + meta = + { + prefix = Some res.prefix; + alreadySeenIdents = res.alreadySeenIdents; + }; + })))) | _ -> ()); bindings |> List.iter (fun vb -> iterator.value_binding iterator vb); if recFlag = Nonrecursive then bindings |> List.iter scopeValueBinding; @@ -1038,59 +1355,60 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = iterator.expr iterator e; scope := oldScope; processed := true - | Pexp_match (expr, cases) -> + | Pexp_match (expr, cases) -> ( (* Completes switch case destructuring Example: switch someIdentifier { | {completeRecordFieldsHere} => ...}*) - let rec findIdentsFromCases cases ~seenIdents = + let rec findCaseWithCursor cases ~typ ~identsFromCases = match cases with - | [] -> seenIdents - | case :: cases -> - findIdentsFromCases cases - ~seenIdents: - (findAlreadySeenIdents case.Parsetree.pc_lhs @ seenIdents) + | case :: nextCases -> + if + case.Parsetree.pc_lhs.ppat_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + = typ + then + case.pc_lhs + |> findContextInPattern ~pos:posBeforeCursor ~patternPath:[] + ~debug ~seenIdentsFromParent:identsFromCases + else findCaseWithCursor nextCases ~typ ~identsFromCases + | [] -> None in - let rec findCaseWithCursor cases = - match cases with - | case :: nextCases -> ( - match case with - | {Parsetree.pc_lhs = {ppat_loc} as pat} - when ppat_loc |> Loc.hasPos ~pos:posBeforeCursor -> ( - match exprToContextPath expr with - | None -> () - | Some contextPath -> - setResultOpt - (pat - |> completePattern - ~howToRetrieveSourceType:(CtxPath contextPath) - ~posBeforeCursor ~firstCharBeforeCursorNoWhite - ~seenIdents:(findIdentsFromCases cases ~seenIdents:[]) - )) - | _ -> findCaseWithCursor nextCases) - | [] -> ( - (* In case there are no cases, like in `switch whatever { | `, complete for the *) + match exprToContextPath expr with + | None -> () + | Some contextPath -> ( + (* Collect all of the seen idents from the cases themselves. *) + let identsFromCases = + cases + |> List.map (fun case -> + case.Parsetree.pc_lhs |> identListFromPat) + |> List.flatten + in + (* First, look for a case with the cursor. *) + let res = match - expr.pexp_loc |> CursorPosition.classifyLoc ~pos:posBeforeCursor + findCaseWithCursor cases ~typ:HasCursor ~identsFromCases with - | NoCursor | EmptyLoc -> ( - match - (exprToContextPath expr, firstCharBeforeCursorNoWhite) - with - | ( Some contextPath, - Some '|' - (* This helps ensuring we're actually in the switch, and completing for a case *) - ) -> - setResultOpt - (Some - (Completable.CtypedContextPattern + | None -> + (* If there's no case with the cursor, look for a case with a broken loc. That means parser recovery has happened somewhere. *) + findCaseWithCursor cases ~typ:EmptyLoc ~identsFromCases + | v -> v + in + match res with + | None -> () + | Some res -> + setResultOpt + (Some + (CtypedPattern + { + howToRetrieveSourceType = CtxPath contextPath; + patternPath = res.patternPath |> List.rev; + patternType = Switch; + lookingToComplete = res.lookingToComplete; + meta = { - howToRetrieveSourceType = CtxPath contextPath; - patternPath = []; - meta = {prefix = Some ""; alreadySeenIdents = []}; - })) - | _ -> ()) - | HasCursor -> ()) - in - findCaseWithCursor cases + prefix = Some res.prefix; + alreadySeenIdents = res.alreadySeenIdents; + }; + })))) | _ -> ()); if not !processed then Ast_iterator.default_iterator.expr iterator expr in diff --git a/analysis/src/DumpAst.ml b/analysis/src/DumpAst.ml index 858334d33..3a0a388b2 100644 --- a/analysis/src/DumpAst.ml +++ b/analysis/src/DumpAst.ml @@ -213,11 +213,9 @@ and printExprItem expr ~pos ~indentation = | v -> Printf.sprintf "" (Utils.identifyPexp v) let printValueBinding value ~pos ~indentation = - "value pattern" - ^ printLocDenominator value.Parsetree.pvb_loc ~pos - ^ ":\n" + "value" ^ ":\n" ^ addIndentation (indentation + 1) - ^ (value.pvb_pat |> printPattern ~pos ~indentation:(indentation + 1)) + ^ (value.Parsetree.pvb_pat |> printPattern ~pos ~indentation:(indentation + 1)) ^ "\n" ^ addIndentation indentation ^ "expr:\n" ^ printExprItem value.pvb_expr ~pos ~indentation:(indentation + 1) diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index b5e96f4fa..94389f04c 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -437,7 +437,7 @@ module Completable = struct (* How to move through a nested type context, like from a root record to the type of one of its fields, and beyond. *) type patternPathItem = - | RField of {fieldName: string; emptyContext: bool} + | RField of {fieldName: string} | Variant of {constructorName: string; payloadNum: int option} | Polyvariant of {name: string; payloadNum: int option} | PTuple of {itemNumber: int} @@ -448,9 +448,7 @@ module Completable = struct let pathItemToString item = match item with - | RField {fieldName; emptyContext} -> - "RecordField:" ^ fieldName - ^ if emptyContext then "(empty context)" else "" + | RField {fieldName} -> "RecordField:" ^ fieldName | Variant {constructorName; payloadNum} -> ( "Variant:" ^ constructorName ^ @@ -492,6 +490,22 @@ module Completable = struct | CPObj (cp, s) -> contextPathToString cp ^ "[\"" ^ s ^ "\"]" | CPPipe (cp, s) -> contextPathToString cp ^ "->" ^ s + type lookingToComplete = CRecordField | CVariant | CPolyvariant | CNoContext + + let lookingToCompleteToString l = + match l with + | CRecordField -> "CRecordField" + | CVariant -> "CVariant" + | CPolyvariant -> "CPolyvariant" + | CNoContext -> "CNoContext" + + type patternCompletionType = Destructure | Switch + + let patternCompletionTypeToString p = + match p with + | Destructure -> "Destructure" + | Switch -> "Switch" + type functionArgument = Labelled of string | Unlabelled of int let functionArgumentToString arg = @@ -560,6 +574,13 @@ module Completable = struct patternPath: patternPathItem list; meta: typedContextMeta; } + | CtypedPattern of { + howToRetrieveSourceType: howToRetrieveSourceType; + patternPath: patternPathItem list; + patternType: patternCompletionType; + lookingToComplete: lookingToComplete; + meta: typedContextMeta; + } let toString = function | Cpath cp -> "Cpath " ^ contextPathToString cp @@ -587,6 +608,28 @@ module Completable = struct ^ " pattern: " ^ (patternPath |> patternContextPathToString) ^ " seenIdents: " ^ list alreadySeenIdents + | CtypedPattern + { + howToRetrieveSourceType; + meta = {prefix; alreadySeenIdents}; + patternPath; + lookingToComplete; + patternType; + } -> + ("CtypedPattern(sourceType:" + ^ (howToRetrieveSourceType |> howToRetrieveSourceTypeToString) + ^ ", lookingToComplete:" + ^ lookingToCompleteToString lookingToComplete + ^ ", patternType:" + ^ patternCompletionTypeToString patternType + ^ ", prefix:" + ^ + match prefix with + | None -> "" + | Some prefix -> str prefix) + ^ ", pattern: " + ^ (patternPath |> patternContextPathToString) + ^ ", seenIdents: " ^ list alreadySeenIdents ^ ")" end module CursorPosition = struct diff --git a/analysis/tests/src/TypedContextCompletionSpec.res b/analysis/tests/src/TypedContextCompletionSpec.res index f3880aabe..3c655ba1e 100644 --- a/analysis/tests/src/TypedContextCompletionSpec.res +++ b/analysis/tests/src/TypedContextCompletionSpec.res @@ -92,43 +92,43 @@ let y = One // Complete for destructured record field starting with n // let _ = doStuff(~doThing=({age, n}) => {()}) -// ^ast +// ^com // Complete for record field another // let {another} = someVal -// ^ast +// ^com // Complete for record field s // let {anotherThing, s} = someVal -// ^ast +// ^com // Complete for record fields of someVal // let {} = someVal -// ^ast +// ^com // Complete for record fields of fn invocation // let {} = getSomeVal(~irrelevant=123) -// ^ast +// ^com // Complete for record fields on record field something // let {something: {}} = someVal -// ^ast +// ^com // Complete for record fields of type for anotherLevel // let {something: {whatIsThis, anotherLevel: {}}} = someVal -// ^ast +// ^com // Complete for record fields of type for anotherLevel, with prefix "l" // let {something: {whatIsThis, anotherLevel: {l}}} = someVal -// ^ast +// ^com // Complete for record fields of type for something, with seen idents whatIsThis, anotherLevel // let {something: {whatIsThis, anotherLevel, }} = someVal -// ^ast +// ^com // Complete for record fields of type for something, with seen idents whatIsThis, anotherLevel // let {something: {whatIsThis, ,anotherLevel}} = someVal -// ^ast +// ^com // --- Record destructuring end --- @@ -136,83 +136,114 @@ let y = One // Complete for record field som in root record // switch someVal { | {thirdThing: "123", som} => () } -// ^ast +// ^com // Complete for any record field in root record // switch someVal { | {thirdThing: "1234"} => () | {} => () } -// ^ast +// ^com // Complete for record field in type of root record->something // switch someVal { | {thirdThing: "1234"} => () | {something: {whatIsThis, anotherLevel, }} => () } -// ^ast +// ^com // Complete for variant starting with T in rfield something of root record // switch someOtherValue { | {something: Two | T} => () } -// ^ast +// ^com // switch someOtherValue { | {otherThing: Some(T)} => () } -// ^ast +// ^com // switch someOtherValue { | {thirdStuff: (_, T)} => () } -// ^ast +// ^com // switch someOtherValue { | {thirdStuff: (_, Four())} => () } -// ^ast +// ^com // switch someOtherValue { | {thirdStuff: (_, Five(_, O))} => () } -// ^ast +// ^com // switch someOtherValue { | {fourthStuff: (Some(#WithPayload(O)), _)} => () } -// ^ast +// ^com // switch someOtherValue { | {thirdStuff: (_, Five(_, One | Two | T))} => () } -// ^ast +// ^com // switch someOtherValue { | {otherThing: S} => () } -// ^ast +// ^com // switch someOtherValue { | {other2: S} => () } -// ^ast +// ^com // switch someOtherValue { | {thirdStuff: (_, Four(TwentyFive | ))} => () } -// ^ast +// ^com // switch someOtherValue { | {other2: } => () } -// ^ast +// ^com // switch someVal { | {something: {whatIsThis: false | } } => () } -// ^ast +// ^com // switch someVal { | {something: {whatIsThis: } } => () } -// ^ast +// ^com // switch someVal { | {something: {whatIsThis: fa } } => () } -// ^ast +// ^com // Complete for root type of x // switch x { | } -// ^ast +// ^com // Incomplete switch, no completion // switch x { -// ^ast +// ^com // switch y { | } -// ^ast +// ^com // switch y { | One | Two | Three | } -// ^ast +// ^com // Should not complete because the record has no braces // switch someVal { | {something: } => () } -// ^ast +// ^com // Should not complete because the record has no braces // switch someVal { | => () } -// ^ast +// ^com + +// No path, looking for record field +// switch someVal { | {} => () } +// ^com // Should complete because the record has braces -// switch someVal { | {something: {} } => () } -// ^ast +// switch someVal { | {something} => () } +// ^com + +// switch someVal { | {something: {}} => () } +// ^com + +// Should not complete because the record has no braces +// switch someVal { | {something: {el: } } => () } +// ^com + +// switch someOtherValue { | {other2: #S()} => () } +// ^com + +// switch someOtherValue { | {thirdStuff: Some(_, {something: t})} => () } +// ^com + +// switch someOtherValue { | {thirdStuff: (_, {something: t})} => () } +// ^com + +// Mixing matches in branches is still picked up as seen idents +// switch y { | One | Two => () | Three => () | T } +// ^com + +// switch someVal { | {something: {whatIsThis: false | } } => () } +// ^com + +// Mixing matches in branches is still picked up as seen idents +// switch y { | One | Two => () | Three => () | } +// ^com // --- Pattern matching end --- diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index 13cbcb971..07db5bc9c 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -1372,7 +1372,7 @@ posCursor:[362:8] posNoWhite:[362:7] Found expr:[361:2->365:3] posCursor:[362:8] posNoWhite:[362:7] Found pattern:[362:7->364:5] posCursor:[362:8] posNoWhite:[362:7] Found pattern:[362:7->362:8] Ppat_construct T:[362:7->362:8] -Completable: CtypedContextPattern(Value[x])=T pattern: [] seenIdents: [T] +Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [], seenIdents: [T]) [] Complete src/Completion.res 373:21 @@ -1381,7 +1381,7 @@ posCursor:[373:21] posNoWhite:[373:20] Found expr:[372:2->376:3] posCursor:[373:21] posNoWhite:[373:20] Found pattern:[373:7->375:5] posCursor:[373:21] posNoWhite:[373:20] Found pattern:[373:7->373:21] Ppat_construct AndThatOther.T:[373:7->373:21] -Completable: CtypedContextPattern(Value[x])=AndThatOther pattern: [] seenIdents: [AndThatOther] +Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CVariant, patternType:Switch, prefix:AndThatOther, pattern: [], seenIdents: [AndThatOther]) [] Complete src/Completion.res 378:24 diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 72f208e7d..9737d00a3 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -1,203 +1,74 @@ Complete src/TypeContextCompletion_Records.res 16:15 posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:7->16:16] posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:8->16:15] -Completable: CtypedContextPattern(Value[someVal])=another pattern: [] seenIdents: [] -[{ - "label": "anotherThing", - "kind": 5, - "tags": [], - "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:another, pattern: [], seenIdents: [another]) +[] Complete src/TypeContextCompletion_Records.res 19:23 posCursor:[19:23] posNoWhite:[19:22] Found pattern:[19:7->19:24] posCursor:[19:23] posNoWhite:[19:22] Found pattern:[19:22->19:23] -Completable: CtypedContextPattern(Value[someVal])=s pattern: [] seenIdents: [anotherThing] -[{ - "label": "something", - "kind": 5, - "tags": [], - "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:s, pattern: [], seenIdents: [anotherThing, s]) +[] Complete src/TypeContextCompletion_Records.res 22:8 posCursor:[22:8] posNoWhite:[22:7] Found pattern:[22:7->22:9] -Completable: CtypedContextPattern(Value[someVal])="" pattern: [] seenIdents: [] -[{ - "label": "something", - "kind": 5, - "tags": [], - "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }, { - "label": "anotherThing", - "kind": 5, - "tags": [], - "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }, { - "label": "thirdThing", - "kind": 5, - "tags": [], - "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/TypeContextCompletion_Records.res 31:8 posCursor:[31:8] posNoWhite:[31:7] Found pattern:[31:7->31:9] -Completable: CtypedContextPattern(Value[getSomeVal](~irrelevant))="" pattern: [] seenIdents: [] -[{ - "label": "something", - "kind": 5, - "tags": [], - "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }, { - "label": "anotherThing", - "kind": 5, - "tags": [], - "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }, { - "label": "thirdThing", - "kind": 5, - "tags": [], - "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[getSomeVal](~irrelevant), lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/TypeContextCompletion_Records.res 35:20 posCursor:[35:20] posNoWhite:[35:19] Found pattern:[35:7->35:22] posCursor:[35:20] posNoWhite:[35:19] Found pattern:[35:19->35:21] -Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something] seenIdents: [] -[{ - "label": "somethingElse", - "kind": 5, - "tags": [], - "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", - "documentation": null - }, { - "label": "whatIsThis", - "kind": 5, - "tags": [], - "detail": "whatIsThis: bool\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", - "documentation": null - }, { - "label": "anotherLevel", - "kind": 5, - "tags": [], - "detail": "anotherLevel: anotherLevel\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [RecordField:something], seenIdents: []) +[] Complete src/TypeContextCompletion_Records.res 38:47 posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:7->38:50] posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:19->38:49] posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:46->38:48] -Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something, RecordField:anotherLevel] seenIdents: [whatIsThis] -[{ - "label": "level", - "kind": 5, - "tags": [], - "detail": "level: int\n\ntype anotherLevel = {level: int, someOtherArg: bool}", - "documentation": null - }, { - "label": "someOtherArg", - "kind": 5, - "tags": [], - "detail": "someOtherArg: bool\n\ntype anotherLevel = {level: int, someOtherArg: bool}", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [RecordField:something, RecordField:anotherLevel], seenIdents: []) +[] Complete src/TypeContextCompletion_Records.res 41:48 posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:7->41:51] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:19->41:50] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:46->41:49] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:47->41:48] -Completable: CtypedContextPattern(Value[someVal])=l pattern: [RecordField:something, RecordField:anotherLevel] seenIdents: [] -[{ - "label": "level", - "kind": 5, - "tags": [], - "detail": "level: int\n\ntype anotherLevel = {level: int, someOtherArg: bool}", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:l, pattern: [RecordField:something, RecordField:anotherLevel], seenIdents: [l]) +[] Complete src/TypeContextCompletion_Records.res 44:47 posCursor:[44:47] posNoWhite:[44:44] Found pattern:[44:7->44:49] posCursor:[44:47] posNoWhite:[44:44] Found pattern:[44:19->44:48] -Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something] seenIdents: [whatIsThis, anotherLevel] -[{ - "label": "somethingElse", - "kind": 5, - "tags": [], - "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", - "documentation": null - }] +[] Complete src/TypeContextCompletion_Records.res 47:31 posCursor:[47:31] posNoWhite:[47:30] Found pattern:[47:7->47:47] posCursor:[47:31] posNoWhite:[47:30] Found pattern:[47:19->47:46] -Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something] seenIdents: [whatIsThis, anotherLevel] -[{ - "label": "somethingElse", - "kind": 5, - "tags": [], - "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", - "documentation": null - }] +[] Complete src/TypeContextCompletion_Records.res 50:44 posCursor:[50:44] posNoWhite:[50:43] Found expr:[50:3->50:54] posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:22->50:46] posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:42->50:45] -Completable: CtypedContextPattern(Value[someVal])=som pattern: [] seenIdents: [thirdThing] -[{ - "label": "something", - "kind": 5, - "tags": [], - "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Switch, prefix:som, pattern: [], seenIdents: [thirdThing, som]) +[] Complete src/TypeContextCompletion_Records.res 53:52 posCursor:[53:52] posNoWhite:[53:51] Found expr:[53:3->53:61] posCursor:[53:52] posNoWhite:[53:51] Found pattern:[53:51->53:53] -Completable: CtypedContextPattern(Value[someVal])="" pattern: [] seenIdents: [] -[{ - "label": "something", - "kind": 5, - "tags": [], - "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }, { - "label": "anotherThing", - "kind": 5, - "tags": [], - "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }, { - "label": "thirdThing", - "kind": 5, - "tags": [], - "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Switch, prefix:"", pattern: [], seenIdents: []) +[] Complete src/TypeContextCompletion_Records.res 56:89 posCursor:[56:89] posNoWhite:[56:88] Found expr:[56:3->56:100] posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:51->56:92] posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:63->56:91] -Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something] seenIdents: [whatIsThis, anotherLevel] -[{ - "label": "somethingElse", - "kind": 5, - "tags": [], - "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", - "documentation": null - }] +[] Complete src/TypeContextCompletion_Records.res 81:48 posCursor:[81:48] posNoWhite:[81:47] Found expr:[81:3->81:57] @@ -205,14 +76,8 @@ posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:29->81:49] posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:41->81:48] posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:47->81:48] Ppat_construct T:[81:47->81:48] -Completable: CtypedContextPattern(Value[someOtherValue])=T pattern: [RecordField:something] seenIdents: [Two, T] -[{ - "label": "Three(_)", - "kind": 4, - "tags": [], - "detail": "Three(int)\n\n", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [RecordField:something], seenIdents: [Two, T]) +[] Complete src/TypeContextCompletion_Records.res 84:48 posCursor:[84:48] posNoWhite:[84:47] Found expr:[84:3->84:58] @@ -221,20 +86,8 @@ posCursor:[84:48] posNoWhite:[84:47] Found pattern:[84:42->84:49] Ppat_construct Some:[84:42->84:46] posCursor:[84:48] posNoWhite:[84:47] Found pattern:[84:47->84:48] Ppat_construct T:[84:47->84:48] -Completable: CtypedContextPattern(Value[someOtherValue])=T pattern: [RecordField:otherThing, Variant:Some(0)] seenIdents: [] -[{ - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\n", - "documentation": null - }, { - "label": "Three(_)", - "kind": 4, - "tags": [], - "detail": "Three(int)\n\n", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [RecordField:otherThing, Variant:Some(0)], seenIdents: []) +[] Complete src/TypeContextCompletion_Records.res 87:47 posCursor:[87:47] posNoWhite:[87:46] Found expr:[87:3->87:57] @@ -242,20 +95,8 @@ posCursor:[87:47] posNoWhite:[87:46] Found pattern:[87:29->87:49] posCursor:[87:47] posNoWhite:[87:46] Found pattern:[87:42->87:48] posCursor:[87:47] posNoWhite:[87:46] Found pattern:[87:46->87:47] Ppat_construct T:[87:46->87:47] -Completable: CtypedContextPattern(Value[someOtherValue])=T pattern: [RecordField:thirdStuff, Tuple:1] seenIdents: [] -[{ - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\n", - "documentation": null - }, { - "label": "Three(_)", - "kind": 4, - "tags": [], - "detail": "Three(int)\n\n", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [RecordField:thirdStuff, Tuple:1], seenIdents: []) +[] Complete src/TypeContextCompletion_Records.res 90:51 posCursor:[90:51] posNoWhite:[90:50] Found expr:[90:3->90:62] @@ -265,20 +106,8 @@ posCursor:[90:51] posNoWhite:[90:50] Found pattern:[90:46->90:52] Ppat_construct Four:[90:46->90:50] posCursor:[90:51] posNoWhite:[90:50] Found pattern:[90:50->90:52] Ppat_construct ():[90:50->90:52] -Completable: CtypedContextPattern(Value[someOtherValue])="" pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)] seenIdents: [] -[{ - "label": "TwentyFive", - "kind": 4, - "tags": [], - "detail": "TwentyFive\n\n", - "documentation": null - }, { - "label": "SixtyTwo", - "kind": 4, - "tags": [], - "detail": "SixtyTwo\n\n", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:(), pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)], seenIdents: []) +[] Complete src/TypeContextCompletion_Records.res 93:55 posCursor:[93:55] posNoWhite:[93:54] Found expr:[93:3->93:66] @@ -289,14 +118,8 @@ Ppat_construct Five:[93:46->93:50] posCursor:[93:55] posNoWhite:[93:54] Found pattern:[93:50->93:57] posCursor:[93:55] posNoWhite:[93:54] Found pattern:[93:54->93:55] Ppat_construct O:[93:54->93:55] -Completable: CtypedContextPattern(Value[someOtherValue])=O pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)] seenIdents: [] -[{ - "label": "One", - "kind": 4, - "tags": [], - "detail": "One\n\n", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:O, pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)], seenIdents: []) +[] Complete src/TypeContextCompletion_Records.res 96:63 posCursor:[96:63] posNoWhite:[96:62] Found expr:[96:3->96:78] @@ -307,14 +130,8 @@ Ppat_construct Some:[96:44->96:48] posCursor:[96:63] posNoWhite:[96:62] Found pattern:[96:49->96:64] posCursor:[96:63] posNoWhite:[96:62] Found pattern:[96:62->96:63] Ppat_construct O:[96:62->96:63] -Completable: CtypedContextPattern(Value[someOtherValue])=O pattern: [RecordField:fourthStuff, Tuple:0, Variant:Some(0), Polyvariant:WithPayload(0)] seenIdents: [] -[{ - "label": "One", - "kind": 4, - "tags": [], - "detail": "One\n\n", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:O, pattern: [RecordField:fourthStuff, Tuple:0, Variant:Some(0), Variant:WithPayload(0)], seenIdents: []) +[] Complete src/TypeContextCompletion_Records.res 99:67 posCursor:[99:67] posNoWhite:[99:66] Found expr:[99:3->99:78] @@ -326,78 +143,24 @@ posCursor:[99:67] posNoWhite:[99:66] Found pattern:[99:50->99:69] posCursor:[99:67] posNoWhite:[99:66] Found pattern:[99:54->99:67] posCursor:[99:67] posNoWhite:[99:66] Found pattern:[99:66->99:67] Ppat_construct T:[99:66->99:67] -Completable: CtypedContextPattern(Value[someOtherValue])=T pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)] seenIdents: [One, Two, T] -[{ - "label": "Three(_)", - "kind": 4, - "tags": [], - "detail": "Three(int)\n\n", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)], seenIdents: [One, Two, T]) +[] Complete src/TypeContextCompletion_Records.res 102:43 posCursor:[102:43] posNoWhite:[102:42] Found expr:[102:3->102:52] posCursor:[102:43] posNoWhite:[102:42] Found pattern:[102:29->102:44] posCursor:[102:43] posNoWhite:[102:42] Found pattern:[102:42->102:43] Ppat_construct S:[102:42->102:43] -Completable: CtypedContextPattern(Value[someOtherValue])=S pattern: [RecordField:otherThing] seenIdents: [] -[{ - "label": "None", - "kind": 4, - "tags": [], - "detail": "None\n\n", - "documentation": null - }, { - "label": "Some(One)", - "kind": 4, - "tags": [], - "detail": "One\n\n", - "documentation": null - }, { - "label": "Some(Two)", - "kind": 4, - "tags": [], - "detail": "Two\n\n", - "documentation": null - }, { - "label": "Some(Three(_))", - "kind": 4, - "tags": [], - "detail": "Three(int)\n\n", - "documentation": null - }, { - "label": "Some(Four(_))", - "kind": 4, - "tags": [], - "detail": "Four(someOtherVariant)\n\n", - "documentation": null - }, { - "label": "Some(Five(_))", - "kind": 4, - "tags": [], - "detail": "Five(someOtherVariant, someVariant)\n\n", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:S, pattern: [RecordField:otherThing], seenIdents: []) +[] Complete src/TypeContextCompletion_Records.res 105:39 posCursor:[105:39] posNoWhite:[105:38] Found expr:[105:3->105:48] posCursor:[105:39] posNoWhite:[105:38] Found pattern:[105:29->105:40] posCursor:[105:39] posNoWhite:[105:38] Found pattern:[105:38->105:39] Ppat_construct S:[105:38->105:39] -Completable: CtypedContextPattern(Value[someOtherValue])=S pattern: [RecordField:other2] seenIdents: [] -[{ - "label": "None", - "kind": 4, - "tags": [], - "detail": "None\n\n", - "documentation": null - }, { - "label": "Some(_)", - "kind": 4, - "tags": [], - "detail": "Some(_)\n\n", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:S, pattern: [RecordField:other2], seenIdents: []) +[] Complete src/TypeContextCompletion_Records.res 108:64 posCursor:[108:64] posNoWhite:[108:62] Found expr:[108:3->108:75] @@ -405,119 +168,41 @@ posCursor:[108:64] posNoWhite:[108:62] Found pattern:[108:29->108:67] posCursor:[108:64] posNoWhite:[108:62] Found pattern:[108:42->108:66] posCursor:[108:64] posNoWhite:[108:62] Found pattern:[108:46->108:65] Ppat_construct Four:[108:46->108:50] -Completable: CtypedContextPattern(Value[someOtherValue])="" pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)] seenIdents: [TwentyFive] -[{ - "label": "SixtyTwo", - "kind": 4, - "tags": [], - "detail": "SixtyTwo\n\n", - "documentation": null - }] +Completable: Cpath Value[Four] +[] Complete src/TypeContextCompletion_Records.res 111:38 posCursor:[111:38] posNoWhite:[111:36] Found expr:[111:3->111:47] posCursor:[111:38] posNoWhite:[111:36] Found pattern:[111:29->111:39] -Completable: CtypedContextPattern(Value[someOtherValue])="" pattern: [RecordField:other2(empty context)] seenIdents: [] -[{ - "label": "None", - "kind": 4, - "tags": [], - "detail": "None\n\n", - "documentation": null - }, { - "label": "Some(_)", - "kind": 4, - "tags": [], - "detail": "Some(_)\n\n", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:other2], seenIdents: []) +[] Complete src/TypeContextCompletion_Records.res 114:55 posCursor:[114:55] posNoWhite:[114:53] Found expr:[114:3->114:67] posCursor:[114:55] posNoWhite:[114:53] Found pattern:[114:22->114:59] posCursor:[114:55] posNoWhite:[114:53] Found pattern:[114:34->114:59] -Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something, RecordField:whatIsThis] seenIdents: [false] -[{ - "label": "true", - "kind": 12, - "tags": [], - "detail": "boolean\n\n", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:something, RecordField:whatIsThis], seenIdents: [false]) +[] Complete src/TypeContextCompletion_Records.res 117:46 posCursor:[117:46] posNoWhite:[117:45] Found expr:[117:3->117:58] posCursor:[117:46] posNoWhite:[117:45] Found pattern:[117:22->117:50] posCursor:[117:46] posNoWhite:[117:45] Found pattern:[117:34->117:50] -Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something, RecordField:whatIsThis(empty context)] seenIdents: [] -[{ - "label": "false", - "kind": 12, - "tags": [], - "detail": "boolean\n\n", - "documentation": null - }, { - "label": "true", - "kind": 12, - "tags": [], - "detail": "boolean\n\n", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:something, RecordField:whatIsThis], seenIdents: []) +[] Complete src/TypeContextCompletion_Records.res 120:49 posCursor:[120:49] posNoWhite:[120:48] Found expr:[120:3->120:62] posCursor:[120:49] posNoWhite:[120:48] Found pattern:[120:22->120:54] posCursor:[120:49] posNoWhite:[120:48] Found pattern:[120:34->120:52] posCursor:[120:49] posNoWhite:[120:48] Found pattern:[120:47->120:49] -Completable: CtypedContextPattern(Value[someVal])=fa pattern: [RecordField:something, RecordField:whatIsThis] seenIdents: [] -[{ - "label": "false", - "kind": 12, - "tags": [], - "detail": "boolean\n\n", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CVariant, patternType:Switch, prefix:fa, pattern: [RecordField:something, RecordField:whatIsThis], seenIdents: []) +[] Complete src/TypeContextCompletion_Records.res 125:15 posCursor:[125:15] posNoWhite:[125:14] Found expr:[125:3->131:11] -Completable: CtypedContextPattern(Value[x])="" pattern: [] seenIdents: [] -[{ - "label": "None", - "kind": 4, - "tags": [], - "detail": "None\n\n", - "documentation": null - }, { - "label": "Some(One)", - "kind": 4, - "tags": [], - "detail": "One\n\n", - "documentation": null - }, { - "label": "Some(Two)", - "kind": 4, - "tags": [], - "detail": "Two\n\n", - "documentation": null - }, { - "label": "Some(Three(_))", - "kind": 4, - "tags": [], - "detail": "Three(int)\n\n", - "documentation": null - }, { - "label": "Some(Four(_))", - "kind": 4, - "tags": [], - "detail": "Four(someOtherVariant)\n\n", - "documentation": null - }, { - "label": "Some(Five(_))", - "kind": 4, - "tags": [], - "detail": "Five(someOtherVariant, someVariant)\n\n", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [], seenIdents: []) +[] Complete src/TypeContextCompletion_Records.res 128:14 posCursor:[128:14] posNoWhite:[128:12] Found expr:[128:3->128:13] @@ -525,102 +210,24 @@ posCursor:[128:14] posNoWhite:[128:12] Found expr:[128:3->128:13] Complete src/TypeContextCompletion_Records.res 133:15 posCursor:[133:15] posNoWhite:[133:14] Found expr:[133:3->133:17] -Completable: CtypedContextPattern(Value[y])="" pattern: [] seenIdents: [] -[{ - "label": "One", - "kind": 4, - "tags": [], - "detail": "One\n\n", - "documentation": null - }, { - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\n", - "documentation": null - }, { - "label": "Three(_)", - "kind": 4, - "tags": [], - "detail": "Three(int)\n\n", - "documentation": null - }, { - "label": "Four(_)", - "kind": 4, - "tags": [], - "detail": "Four(someOtherVariant)\n\n", - "documentation": null - }, { - "label": "Five(_)", - "kind": 4, - "tags": [], - "detail": "Five(someOtherVariant, someVariant)\n\n", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [], seenIdents: []) +[] Complete src/TypeContextCompletion_Records.res 136:36 posCursor:[136:36] posNoWhite:[136:34] Found expr:[136:3->136:38] -Completable: CtypedContextPattern(Value[y])="" pattern: [] seenIdents: [] -[{ - "label": "One", - "kind": 4, - "tags": [], - "detail": "One\n\n", - "documentation": null - }, { - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\n", - "documentation": null - }, { - "label": "Three(_)", - "kind": 4, - "tags": [], - "detail": "Three(int)\n\n", - "documentation": null - }, { - "label": "Four(_)", - "kind": 4, - "tags": [], - "detail": "Four(someOtherVariant)\n\n", - "documentation": null - }, { - "label": "Five(_)", - "kind": 4, - "tags": [], - "detail": "Five(someOtherVariant, someVariant)\n\n", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [], seenIdents: [One, Two, Three]) +[] Complete src/TypeContextCompletion_Records.res 140:33 posCursor:[140:33] posNoWhite:[140:32] Found expr:[140:3->140:44] posCursor:[140:33] posNoWhite:[140:32] Found pattern:[140:22->140:36] -Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something(empty context)] seenIdents: [] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:something], seenIdents: []) [] Complete src/TypeContextCompletion_Records.res 144:35 posCursor:[144:35] posNoWhite:[144:34] Found expr:[144:3->144:46] posCursor:[144:35] posNoWhite:[144:34] Found pattern:[144:22->144:38] posCursor:[144:35] posNoWhite:[144:34] Found pattern:[144:34->144:36] -Completable: CtypedContextPattern(Value[someVal])="" pattern: [RecordField:something] seenIdents: [] -[{ - "label": "somethingElse", - "kind": 5, - "tags": [], - "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", - "documentation": null - }, { - "label": "whatIsThis", - "kind": 5, - "tags": [], - "detail": "whatIsThis: bool\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", - "documentation": null - }, { - "label": "anotherLevel", - "kind": 5, - "tags": [], - "detail": "anotherLevel: anotherLevel\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", - "documentation": null - }] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Switch, prefix:"", pattern: [RecordField:something], seenIdents: []) +[] diff --git a/analysis/tests/src/expected/TypedContextCompletionSpec.res.spec.txt b/analysis/tests/src/expected/TypedContextCompletionSpec.res.spec.txt new file mode 100644 index 000000000..e960e25e8 --- /dev/null +++ b/analysis/tests/src/expected/TypedContextCompletionSpec.res.spec.txt @@ -0,0 +1,965 @@ +Dump AST src/TypedContextCompletionSpec.res 49:40 + +Source: +// let x = someVariantToString(~someVaria +// ^ast + + +Pstr_value( + value: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + <*>~someVaria= + <*>Pexp_ident:someVaria + ) +) + +Dump AST src/TypedContextCompletionSpec.res 53:43 + +// Find source: exp -> labelled arg +// Looking for: no context +Source: +// let x = someVariantToString(~someVariant= +// ^ast + + +Pstr_value( + value: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + <*>~someVariant= + Pexp_extension(%rescript.exprhole) + ) +) + + +// Find source: exp -> labelled arg +// Looking for: variant +Dump AST src/TypedContextCompletionSpec.res 61:44 + +Source: +// let x = someVariantToString(~someVariant=T +// ^ast + + +Pstr_value( + value: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + ~someVariant= + <*>Pexp_construct(<*>T) + ) +) + +// Find source: exp -> labelled arg +// Looking for: variant/ident? +Dump AST src/TypedContextCompletionSpec.res 65:44 + +Source: +// let x = someVariantToString(~someVariant=t +// ^ast + + +Pstr_value( + value: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + ~someVariant= + <*>Pexp_ident:t + ) +) + +// Find source: exp -> labelled arg +// Looking for: TypeDefinition. -> anything +Dump AST src/TypedContextCompletionSpec.res 69:58 + +Source: +// let x = someVariantToString(~someVariant=TypeDefinition. +// ^ast + + +Pstr_value( + value: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + ~someVariant= + <*>Pexp_ident:TypeDefinition."" + ) +) + +// Find source: exp -> labelled arg +// Looking for: no context +Dump AST src/TypedContextCompletionSpec.res 73:44 + +Source: +// let x = someVariantToString(~anotherThing= +// ^ast + + +Pstr_value( + value: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + <*>~anotherThing= + Pexp_extension(%rescript.exprhole) + ) +) + +// Find source: exp -> labelled arg +// Looking for: no context +Dump AST src/TypedContextCompletionSpec.res 77:42 + +Source: +// let x = someVariantToString(~thirdThing= +// ^ast + + +Pstr_value( + value: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + <*>~thirdThing= + Pexp_extension(%rescript.exprhole) + ) +) + +// Find source: exp -> labelled arg +// Looking for: polyvariant +Dump AST src/TypedContextCompletionSpec.res 81:44 + +Source: +// let x = someVariantToString(~thirdThing=#t +// ^ast + + +Pstr_value( + value: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + ~thirdThing= + <*>Pexp_variant(t) + ) +) + +// Find source: exp -> labelled arg +// Looking for: polyvariant +Dump AST src/TypedContextCompletionSpec.res 85:44 + +Source: +// let x = someVariantToString(~thirdThing=#T +// ^ast + + +Pstr_value( + value: + Ppat_var(x) + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someVariantToString + args: + ~thirdThing= + <*>Pexp_variant(T) + ) +) + +// Find source: exp -> labelled arg -> fn argument unlabelled 0 +// Looking for: record field +Dump AST src/TypedContextCompletionSpec.res 93:36 + +Source: +// let _ = doStuff(~doThing=({age, n}) => {()}) +// ^ast + + +Pstr_value( + value: + Ppat_any + expr: + <*>Pexp_apply( + expr: + Pexp_ident:doStuff + args: + ~doThing= + <*>Pexp_fun( + arg: Nolabel, + pattern: <*>Ppat_record( + fields: + age: Ppat_var(age) + <*>n: Ppat_var(<*>n) + ), + next expr: + Pexp_construct(()) + ) + ) +) + +// Find source: exp +// Looking for: record field +Dump AST src/TypedContextCompletionSpec.res 97:15 + +Source: +// let {another} = someVal +// ^ast + + +Pstr_value( + value: + <*>Ppat_record( + fields: + <*>another: Ppat_var(<*>another) + ) + expr: + Pexp_ident:someVal +) + +// Find source: exp +// Looking for: record field +Dump AST src/TypedContextCompletionSpec.res 101:23 + +Source: +// let {anotherThing, s} = someVal +// ^ast + + +Pstr_value( + value: + <*>Ppat_record( + fields: + anotherThing: Ppat_var(anotherThing) + <*>s: Ppat_var(<*>s) + ) + expr: + Pexp_ident:someVal +) + +Dump AST src/TypedContextCompletionSpec.res 105:8 + +// Find source: exp +// Looking for: record field +Source: +// let {} = someVal +// ^ast + + +Pstr_value( + value: + <*>Ppat_record( + fields: + + ) + expr: + Pexp_ident:someVal +) + +// Find source: exp +// Looking for: record field +Dump AST src/TypedContextCompletionSpec.res 109:8 + +Source: +// let {} = getSomeVal(~irrelevant=123) +// ^ast + + +Pstr_value( + value: + <*>Ppat_record( + fields: + + ) + expr: + Pexp_apply( + expr: + Pexp_ident:getSomeVal + args: + ~irrelevant= + Pexp_constant(Pconst_integer(123)) + ) +) + +Dump AST src/TypedContextCompletionSpec.res 113:20 + +// Find source: exp + pat[rfield something] +// Looking for: record field +Source: +// let {something: {}} = someVal +// ^ast + + +Pstr_value( + value: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + + ) + ) + expr: + Pexp_ident:someVal +) + +// Find source: exp + pat[rfield something, rfield anotherLevel] +// Looking for: record field +Dump AST src/TypedContextCompletionSpec.res 117:47 + +Source: +// let {something: {whatIsThis, anotherLevel: {}}} = someVal +// ^ast + + +Pstr_value( + value: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + whatIsThis: Ppat_var(whatIsThis) + anotherLevel: <*>Ppat_record( + fields: + + ) + ) + ) + expr: + Pexp_ident:someVal +) + +Dump AST src/TypedContextCompletionSpec.res 121:48 + +// Find source: exp + pat[rfield something, rfield anotherLevel] +// Looking for: record field +Source: +// let {something: {whatIsThis, anotherLevel: {l}}} = someVal +// ^ast + + +Pstr_value( + value: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + whatIsThis: Ppat_var(whatIsThis) + anotherLevel: <*>Ppat_record( + fields: + <*>l: Ppat_var(<*>l) + ) + ) + ) + expr: + Pexp_ident:someVal +) + +Dump AST src/TypedContextCompletionSpec.res 125:47 + +// Find source: exp + pat[rfield something] +// Looking for: record field +Source: +// let {something: {whatIsThis, anotherLevel, }} = someVal +// ^ast + + +Pstr_value( + value: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + whatIsThis: Ppat_var(whatIsThis) + anotherLevel: Ppat_var(anotherLevel) + ) + ) + expr: + Pexp_ident:someVal +) + +Dump AST src/TypedContextCompletionSpec.res 129:31 + +// Find source: exp + pat[rfield something] +// Looking for: record field + +Source: +// let {something: {whatIsThis, ,anotherLevel}} = someVal +// ^ast + + +Pstr_value( + value: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + whatIsThis: Ppat_var(whatIsThis) + anotherLevel: Ppat_var(anotherLevel) + ) + ) + expr: + Pexp_ident:someVal +) + +Dump AST src/TypedContextCompletionSpec.res 137:44 +// Find source: exp +// Looking for: record field som +Source: +// switch someVal { | {thirdThing: "123", som} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + thirdThing: Ppat_constant(Pconst_string(123)) + <*>som: <*>Ppat_var(<*>som) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 141:52 + +// Find source: exp +// Looking for: record field som + +Source: +// switch someVal { | {thirdThing: "1234"} => () | {} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern: + Ppat_record( + fields: + thirdThing: Ppat_constant(Pconst_string(1234)) + ) + expr: + Pexp_construct(()) + case 2: + pattern<*>: + <*>Ppat_record( + fields: + + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 145:89 + +// Find source: exp + pat[rfield something] +// Looking for: record field + +Source: +// switch someVal { | {thirdThing: "1234"} => () | {something: {whatIsThis, anotherLevel, }} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern: + Ppat_record( + fields: + thirdThing: Ppat_constant(Pconst_string(1234)) + ) + expr: + Pexp_construct(()) + case 2: + pattern<*>: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + whatIsThis: Ppat_var(whatIsThis) + anotherLevel: Ppat_var(anotherLevel) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 149:48 + +// Find source: exp + pat[rfield something] +// Looking for: variant + +Source: +// switch someOtherValue { | {something: Two | T} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + something: Ppat_or( + Ppat_construct(Two), + Ppat_construct(<*>T) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 152:48 + +// Find source: exp + pat[rfield otherThing, variant Some(0)] +// Looking for: variant + +Source: +// switch someOtherValue { | {otherThing: Some(T)} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + otherThing: <*>Ppat_construct(Some,Ppat_construct(<*>T)) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 155:47 + +// Find source: exp + pat[rfield thirdStuff, tuple(1)] +// Looking for: variant + +Source: +// switch someOtherValue { | {thirdStuff: (_, T)} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + thirdStuff: <*>Ppat_tuple( + Ppat_any, + Ppat_construct(<*>T) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 158:51 + +// Find source: exp + pat[rfield thirdStuff, tuple(1), variant Four(0)] +// Looking for: no context + +Source: +// switch someOtherValue { | {thirdStuff: (_, Four())} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + thirdStuff: <*>Ppat_tuple( + Ppat_any, + <*>Ppat_construct(Four,<*>Ppat_construct(<*>())) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 161:55 + +// Find source: exp + pat[rfield thirdStuff, tuple(2), variant Five(1)] +// Looking for: variant + +Source: +// switch someOtherValue { | {thirdStuff: (_, Five(_, O))} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + thirdStuff: <*>Ppat_tuple( + Ppat_any, + <*>Ppat_construct(Five,<*>Ppat_tuple( + Ppat_any, + Ppat_construct(<*>O) + )) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 164:63 +// Find source: exp + pat[rfield thirdStuff, tuple(2), variant Five(1)] +// Looking for: variant + +Source: +// switch someOtherValue { | {fourthStuff: (Some(#WithPayload(O)), _)} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + fourthStuff: <*>Ppat_tuple( + <*>Ppat_construct(Some,<*>Ppat_variant(WithPayload,Ppat_construct(<*>O))), + Ppat_any + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 167:67 + +Source: +// switch someOtherValue { | {thirdStuff: (_, Five(_, One | Two | T))} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + thirdStuff: <*>Ppat_tuple( + Ppat_any, + <*>Ppat_construct(Five,<*>Ppat_tuple( + Ppat_any, + Ppat_or( + Ppat_or( + Ppat_construct(One), + Ppat_construct(Two) + ), + Ppat_construct(<*>T) + ) + )) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 170:43 + +Source: +// switch someOtherValue { | {otherThing: S} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + otherThing: Ppat_construct(<*>S) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 173:39 + +Source: +// switch someOtherValue { | {other2: S} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + other2: Ppat_construct(<*>S) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 176:64 + +Source: +// switch someOtherValue { | {thirdStuff: (_, Four(TwentyFive | ))} => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + thirdStuff: <*>Ppat_tuple( + Ppat_any, + <*>Ppat_construct(Four,Ppat_or( + Ppat_construct(TwentyFive), + Ppat_extension(%rescript.patternhole) + )) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 179:38 + +Source: +// switch someOtherValue { | {other2: } => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someOtherValue) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + other2: Ppat_extension(%rescript.patternhole) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 182:55 + +Source: +// switch someVal { | {something: {whatIsThis: false | } } => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + whatIsThis: Ppat_or( + Ppat_construct(false), + Ppat_extension(%rescript.patternhole) + ) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 185:46 + +Source: +// switch someVal { | {something: {whatIsThis: } } => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + whatIsThis: Ppat_extension(%rescript.patternhole) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 188:49 + +Source: +// switch someVal { | {something: {whatIsThis: fa } } => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + whatIsThis: Ppat_var(<*>fa) + ) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 192:15 + +Source: +// switch x { | } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:x) + case 1: + pattern: + Ppat_extension(%rescript.patternhole) + expr: + Pexp_extension(%rescript.exprhole) +) + +Dump AST src/TypedContextCompletionSpec.res 196:14 + + +Dump AST src/TypedContextCompletionSpec.res 199:15 + +Source: +// switch y { | } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:y) + case 1: + pattern: + Ppat_extension(%rescript.patternhole) + expr: + Pexp_extension(%rescript.exprhole) +) + +Dump AST src/TypedContextCompletionSpec.res 202:36 + +Source: +// switch y { | One | Two | Three | } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:y) + case 1: + pattern: + Ppat_or( + Ppat_or( + Ppat_or( + Ppat_construct(One), + Ppat_construct(Two) + ), + Ppat_construct(Three) + ), + Ppat_extension(%rescript.patternhole) + ) + expr: + Pexp_extension(%rescript.exprhole) +) + +Dump AST src/TypedContextCompletionSpec.res 206:33 + +Source: +// switch someVal { | {something: } => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + something: Ppat_extension(%rescript.patternhole) + ) + expr: + Pexp_construct(()) +) + +Dump AST src/TypedContextCompletionSpec.res 210:22 + +Source: +// switch someVal { | => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern: + Ppat_construct(()) + expr: + Pexp_extension(%rescript.exprhole) +) + +Dump AST src/TypedContextCompletionSpec.res 214:35 + +Source: +// switch someVal { | {something: {} } => () } +// ^ast + + +Pstr_eval( + <*>Pexp_match(Pexp_ident:someVal) + case 1: + pattern<*>: + <*>Ppat_record( + fields: + something: <*>Ppat_record( + fields: + + ) + ) + expr: + Pexp_construct(()) +) + diff --git a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt index f91790281..4909241e3 100644 --- a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt +++ b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt @@ -6,7 +6,7 @@ Source: Pstr_value( - value pattern<*>: + value: Ppat_var(x) expr: <*>Pexp_apply( @@ -26,7 +26,7 @@ Source: Pstr_value( - value pattern<*>: + value: Ppat_var(x) expr: <*>Pexp_apply( @@ -47,7 +47,7 @@ Source: Pstr_value( - value pattern<*>: + value: Ppat_var(x) expr: <*>Pexp_apply( @@ -67,7 +67,7 @@ Source: Pstr_value( - value pattern<*>: + value: Ppat_var(x) expr: <*>Pexp_apply( @@ -87,7 +87,7 @@ Source: Pstr_value( - value pattern<*>: + value: Ppat_var(x) expr: <*>Pexp_apply( @@ -107,7 +107,7 @@ Source: Pstr_value( - value pattern<*>: + value: Ppat_var(x) expr: <*>Pexp_apply( @@ -127,7 +127,7 @@ Source: Pstr_value( - value pattern<*>: + value: Ppat_var(x) expr: <*>Pexp_apply( @@ -147,7 +147,7 @@ Source: Pstr_value( - value pattern<*>: + value: Ppat_var(x) expr: <*>Pexp_apply( @@ -167,7 +167,7 @@ Source: Pstr_value( - value pattern<*>: + value: Ppat_var(x) expr: <*>Pexp_apply( @@ -179,726 +179,1379 @@ Pstr_value( ) ) -Dump AST src/TypedContextCompletionSpec.res 93:36 - -Source: -// let _ = doStuff(~doThing=({age, n}) => {()}) -// ^ast - - -Pstr_value( - value pattern<*>: - Ppat_any - expr: - <*>Pexp_apply( - expr: - Pexp_ident:doStuff - args: - ~doThing= - <*>Pexp_fun( - arg: Nolabel, - pattern: <*>Ppat_record( - fields: - age: Ppat_var(age) - <*>n: Ppat_var(<*>n) - ), - next expr: - Pexp_construct(()) - ) - ) -) - -Dump AST src/TypedContextCompletionSpec.res 97:15 - -Source: -// let {another} = someVal -// ^ast - - -Pstr_value( - value pattern<*>: - <*>Ppat_record( - fields: - <*>another: Ppat_var(<*>another) - ) - expr: - Pexp_ident:someVal -) - -Dump AST src/TypedContextCompletionSpec.res 101:23 - -Source: -// let {anotherThing, s} = someVal -// ^ast - - -Pstr_value( - value pattern<*>: - <*>Ppat_record( - fields: - anotherThing: Ppat_var(anotherThing) - <*>s: Ppat_var(<*>s) - ) - expr: - Pexp_ident:someVal -) - -Dump AST src/TypedContextCompletionSpec.res 105:8 - -Source: -// let {} = someVal -// ^ast - - -Pstr_value( - value pattern<*>: - <*>Ppat_record( - fields: - - ) - expr: - Pexp_ident:someVal -) - -Dump AST src/TypedContextCompletionSpec.res 109:8 - -Source: -// let {} = getSomeVal(~irrelevant=123) -// ^ast - - -Pstr_value( - value pattern<*>: - <*>Ppat_record( - fields: - - ) - expr: - Pexp_apply( - expr: - Pexp_ident:getSomeVal - args: - ~irrelevant= - Pexp_constant(Pconst_integer(123)) - ) -) - -Dump AST src/TypedContextCompletionSpec.res 113:20 - -Source: -// let {something: {}} = someVal -// ^ast - - -Pstr_value( - value pattern<*>: - <*>Ppat_record( - fields: - something: <*>Ppat_record( - fields: - - ) - ) - expr: - Pexp_ident:someVal -) - -Dump AST src/TypedContextCompletionSpec.res 117:47 - -Source: -// let {something: {whatIsThis, anotherLevel: {}}} = someVal -// ^ast - - -Pstr_value( - value pattern<*>: - <*>Ppat_record( - fields: - something: <*>Ppat_record( - fields: - whatIsThis: Ppat_var(whatIsThis) - anotherLevel: <*>Ppat_record( - fields: - - ) - ) - ) - expr: - Pexp_ident:someVal -) - -Dump AST src/TypedContextCompletionSpec.res 121:48 - -Source: -// let {something: {whatIsThis, anotherLevel: {l}}} = someVal -// ^ast - - -Pstr_value( - value pattern<*>: - <*>Ppat_record( - fields: - something: <*>Ppat_record( - fields: - whatIsThis: Ppat_var(whatIsThis) - anotherLevel: <*>Ppat_record( - fields: - <*>l: Ppat_var(<*>l) - ) - ) - ) - expr: - Pexp_ident:someVal -) - -Dump AST src/TypedContextCompletionSpec.res 125:47 - -Source: -// let {something: {whatIsThis, anotherLevel, }} = someVal -// ^ast - - -Pstr_value( - value pattern<*>: - <*>Ppat_record( - fields: - something: <*>Ppat_record( - fields: - whatIsThis: Ppat_var(whatIsThis) - anotherLevel: Ppat_var(anotherLevel) - ) - ) - expr: - Pexp_ident:someVal -) - -Dump AST src/TypedContextCompletionSpec.res 129:31 - -Source: -// let {something: {whatIsThis, ,anotherLevel}} = someVal -// ^ast - - -Pstr_value( - value pattern<*>: - <*>Ppat_record( - fields: - something: <*>Ppat_record( - fields: - whatIsThis: Ppat_var(whatIsThis) - anotherLevel: Ppat_var(anotherLevel) - ) - ) - expr: - Pexp_ident:someVal -) - -Dump AST src/TypedContextCompletionSpec.res 137:44 - -Source: -// switch someVal { | {thirdThing: "123", som} => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someVal) - case 1: - pattern<*>: - <*>Ppat_record( - fields: - thirdThing: Ppat_constant(Pconst_string(123)) - <*>som: <*>Ppat_var(<*>som) - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 141:52 - -Source: -// switch someVal { | {thirdThing: "1234"} => () | {} => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someVal) - case 1: - pattern: - Ppat_record( - fields: - thirdThing: Ppat_constant(Pconst_string(1234)) - ) - expr: - Pexp_construct(()) - case 2: - pattern<*>: - <*>Ppat_record( - fields: - - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 145:89 - -Source: -// switch someVal { | {thirdThing: "1234"} => () | {something: {whatIsThis, anotherLevel, }} => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someVal) - case 1: - pattern: - Ppat_record( - fields: - thirdThing: Ppat_constant(Pconst_string(1234)) - ) - expr: - Pexp_construct(()) - case 2: - pattern<*>: - <*>Ppat_record( - fields: - something: <*>Ppat_record( - fields: - whatIsThis: Ppat_var(whatIsThis) - anotherLevel: Ppat_var(anotherLevel) - ) - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 149:48 - -Source: -// switch someOtherValue { | {something: Two | T} => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someOtherValue) - case 1: - pattern<*>: - <*>Ppat_record( - fields: - something: Ppat_or( - Ppat_construct(Two), - Ppat_construct(<*>T) - ) - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 152:48 - -Source: -// switch someOtherValue { | {otherThing: Some(T)} => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someOtherValue) - case 1: - pattern<*>: - <*>Ppat_record( - fields: - otherThing: <*>Ppat_construct(Some,Ppat_construct(<*>T)) - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 155:47 - -Source: -// switch someOtherValue { | {thirdStuff: (_, T)} => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someOtherValue) - case 1: - pattern<*>: - <*>Ppat_record( - fields: - thirdStuff: <*>Ppat_tuple( - Ppat_any, - Ppat_construct(<*>T) - ) - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 158:51 - -Source: -// switch someOtherValue { | {thirdStuff: (_, Four())} => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someOtherValue) - case 1: - pattern<*>: - <*>Ppat_record( - fields: - thirdStuff: <*>Ppat_tuple( - Ppat_any, - <*>Ppat_construct(Four,<*>Ppat_construct(<*>())) - ) - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 161:55 - -Source: -// switch someOtherValue { | {thirdStuff: (_, Five(_, O))} => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someOtherValue) - case 1: - pattern<*>: - <*>Ppat_record( - fields: - thirdStuff: <*>Ppat_tuple( - Ppat_any, - <*>Ppat_construct(Five,<*>Ppat_tuple( - Ppat_any, - Ppat_construct(<*>O) - )) - ) - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 164:63 - -Source: -// switch someOtherValue { | {fourthStuff: (Some(#WithPayload(O)), _)} => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someOtherValue) - case 1: - pattern<*>: - <*>Ppat_record( - fields: - fourthStuff: <*>Ppat_tuple( - <*>Ppat_construct(Some,<*>Ppat_variant(WithPayload,Ppat_construct(<*>O))), - Ppat_any - ) - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 167:67 - -Source: -// switch someOtherValue { | {thirdStuff: (_, Five(_, One | Two | T))} => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someOtherValue) - case 1: - pattern<*>: - <*>Ppat_record( - fields: - thirdStuff: <*>Ppat_tuple( - Ppat_any, - <*>Ppat_construct(Five,<*>Ppat_tuple( - Ppat_any, - Ppat_or( - Ppat_or( - Ppat_construct(One), - Ppat_construct(Two) - ), - Ppat_construct(<*>T) - ) - )) - ) - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 170:43 - -Source: -// switch someOtherValue { | {otherThing: S} => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someOtherValue) - case 1: - pattern<*>: - <*>Ppat_record( - fields: - otherThing: Ppat_construct(<*>S) - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 173:39 - -Source: -// switch someOtherValue { | {other2: S} => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someOtherValue) - case 1: - pattern<*>: - <*>Ppat_record( - fields: - other2: Ppat_construct(<*>S) - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 176:64 - -Source: -// switch someOtherValue { | {thirdStuff: (_, Four(TwentyFive | ))} => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someOtherValue) - case 1: - pattern<*>: - <*>Ppat_record( - fields: - thirdStuff: <*>Ppat_tuple( - Ppat_any, - <*>Ppat_construct(Four,Ppat_or( - Ppat_construct(TwentyFive), - Ppat_extension(%rescript.patternhole) - )) - ) - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 179:38 - -Source: -// switch someOtherValue { | {other2: } => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someOtherValue) - case 1: - pattern<*>: - <*>Ppat_record( - fields: - other2: Ppat_extension(%rescript.patternhole) - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 182:55 - -Source: -// switch someVal { | {something: {whatIsThis: false | } } => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someVal) - case 1: - pattern<*>: - <*>Ppat_record( - fields: - something: <*>Ppat_record( - fields: - whatIsThis: Ppat_or( - Ppat_construct(false), - Ppat_extension(%rescript.patternhole) - ) - ) - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 185:46 - -Source: -// switch someVal { | {something: {whatIsThis: } } => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someVal) - case 1: - pattern<*>: - <*>Ppat_record( - fields: - something: <*>Ppat_record( - fields: - whatIsThis: Ppat_extension(%rescript.patternhole) - ) - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 188:49 - -Source: -// switch someVal { | {something: {whatIsThis: fa } } => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someVal) - case 1: - pattern<*>: - <*>Ppat_record( - fields: - something: <*>Ppat_record( - fields: - whatIsThis: Ppat_var(<*>fa) - ) - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 192:15 - -Source: -// switch x { | } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:x) - case 1: - pattern: - Ppat_extension(%rescript.patternhole) - expr: - Pexp_extension(%rescript.exprhole) -) - -Dump AST src/TypedContextCompletionSpec.res 196:14 - - -Dump AST src/TypedContextCompletionSpec.res 199:15 - -Source: -// switch y { | } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:y) - case 1: - pattern: - Ppat_extension(%rescript.patternhole) - expr: - Pexp_extension(%rescript.exprhole) -) - -Dump AST src/TypedContextCompletionSpec.res 202:36 - -Source: -// switch y { | One | Two | Three | } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:y) - case 1: - pattern: - Ppat_or( - Ppat_or( - Ppat_or( - Ppat_construct(One), - Ppat_construct(Two) - ), - Ppat_construct(Three) - ), - Ppat_extension(%rescript.patternhole) - ) - expr: - Pexp_extension(%rescript.exprhole) -) - -Dump AST src/TypedContextCompletionSpec.res 206:33 - -Source: -// switch someVal { | {something: } => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someVal) - case 1: - pattern<*>: - <*>Ppat_record( - fields: - something: Ppat_extension(%rescript.patternhole) - ) - expr: - Pexp_construct(()) -) - -Dump AST src/TypedContextCompletionSpec.res 210:22 - -Source: -// switch someVal { | => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someVal) - case 1: - pattern: - Ppat_construct(()) - expr: - Pexp_extension(%rescript.exprhole) -) - -Dump AST src/TypedContextCompletionSpec.res 214:35 - -Source: -// switch someVal { | {something: {} } => () } -// ^ast - - -Pstr_eval( - <*>Pexp_match(Pexp_ident:someVal) - case 1: - pattern<*>: - <*>Ppat_record( - fields: - something: <*>Ppat_record( - fields: - - ) - ) - expr: - Pexp_construct(()) -) +Complete src/TypedContextCompletionSpec.res 93:36 +posCursor:[93:36] posNoWhite:[93:35] Found expr:[93:11->93:47] +Pexp_apply ...[93:11->93:18] (~doThing93:20->93:27=...[93:28->93:46]) +posCursor:[93:36] posNoWhite:[93:35] Found pattern:[93:29->93:37] +posCursor:[93:36] posNoWhite:[93:35] Found pattern:[93:35->93:36] +Completable: CtypedContextPattern(FunctionArgument(fnSource:NamedArg(doThing, Value[doStuff]), arg:unlabelled(0)))=n pattern: [] seenIdents: [age] +[] + +Complete src/TypedContextCompletionSpec.res 97:15 +posCursor:[97:15] posNoWhite:[97:14] Found pattern:[97:7->97:16] +posCursor:[97:15] posNoWhite:[97:14] Found pattern:[97:8->97:15] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:another, pattern: [], seenIdents: [another]) +[] + +Complete src/TypedContextCompletionSpec.res 101:23 +posCursor:[101:23] posNoWhite:[101:22] Found pattern:[101:7->101:24] +posCursor:[101:23] posNoWhite:[101:22] Found pattern:[101:22->101:23] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:s, pattern: [], seenIdents: [anotherThing, s]) +[] + +Complete src/TypedContextCompletionSpec.res 105:8 +posCursor:[105:8] posNoWhite:[105:7] Found pattern:[105:7->105:9] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 109:8 +posCursor:[109:8] posNoWhite:[109:7] Found pattern:[109:7->109:9] +Completable: CtypedPattern(sourceType:Value[getSomeVal](~irrelevant), lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 113:20 +posCursor:[113:20] posNoWhite:[113:19] Found pattern:[113:7->113:22] +posCursor:[113:20] posNoWhite:[113:19] Found pattern:[113:19->113:21] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [RecordField:something], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 117:47 +posCursor:[117:47] posNoWhite:[117:46] Found pattern:[117:7->117:50] +posCursor:[117:47] posNoWhite:[117:46] Found pattern:[117:19->117:49] +posCursor:[117:47] posNoWhite:[117:46] Found pattern:[117:46->117:48] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [RecordField:something, RecordField:anotherLevel], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 121:48 +posCursor:[121:48] posNoWhite:[121:47] Found pattern:[121:7->121:51] +posCursor:[121:48] posNoWhite:[121:47] Found pattern:[121:19->121:50] +posCursor:[121:48] posNoWhite:[121:47] Found pattern:[121:46->121:49] +posCursor:[121:48] posNoWhite:[121:47] Found pattern:[121:47->121:48] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:l, pattern: [RecordField:something, RecordField:anotherLevel], seenIdents: [l]) +[] + +Complete src/TypedContextCompletionSpec.res 125:47 +posCursor:[125:47] posNoWhite:[125:44] Found pattern:[125:7->125:49] +posCursor:[125:47] posNoWhite:[125:44] Found pattern:[125:19->125:48] +[] + +Complete src/TypedContextCompletionSpec.res 129:31 +posCursor:[129:31] posNoWhite:[129:30] Found pattern:[129:7->129:47] +posCursor:[129:31] posNoWhite:[129:30] Found pattern:[129:19->129:46] +[] + +Complete src/TypedContextCompletionSpec.res 137:44 +posCursor:[137:44] posNoWhite:[137:43] Found expr:[137:3->137:54] +posCursor:[137:44] posNoWhite:[137:43] Found pattern:[137:22->137:46] +posCursor:[137:44] posNoWhite:[137:43] Found pattern:[137:42->137:45] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Switch, prefix:som, pattern: [], seenIdents: [thirdThing, som]) +[] + +Complete src/TypedContextCompletionSpec.res 141:52 +posCursor:[141:52] posNoWhite:[141:51] Found expr:[141:3->141:61] +posCursor:[141:52] posNoWhite:[141:51] Found pattern:[141:51->141:53] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Switch, prefix:"", pattern: [], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 145:89 +posCursor:[145:89] posNoWhite:[145:88] Found expr:[145:3->145:100] +posCursor:[145:89] posNoWhite:[145:88] Found pattern:[145:51->145:92] +posCursor:[145:89] posNoWhite:[145:88] Found pattern:[145:63->145:91] +[] + +Complete src/TypedContextCompletionSpec.res 149:48 +posCursor:[149:48] posNoWhite:[149:47] Found expr:[149:3->149:57] +posCursor:[149:48] posNoWhite:[149:47] Found pattern:[149:29->149:49] +posCursor:[149:48] posNoWhite:[149:47] Found pattern:[149:41->149:48] +posCursor:[149:48] posNoWhite:[149:47] Found pattern:[149:47->149:48] +Ppat_construct T:[149:47->149:48] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [RecordField:something], seenIdents: [Two, T]) +[] + +Complete src/TypedContextCompletionSpec.res 152:48 +posCursor:[152:48] posNoWhite:[152:47] Found expr:[152:3->152:58] +posCursor:[152:48] posNoWhite:[152:47] Found pattern:[152:29->152:50] +posCursor:[152:48] posNoWhite:[152:47] Found pattern:[152:42->152:49] +Ppat_construct Some:[152:42->152:46] +posCursor:[152:48] posNoWhite:[152:47] Found pattern:[152:47->152:48] +Ppat_construct T:[152:47->152:48] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [RecordField:otherThing, Variant:Some(0)], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 155:47 +posCursor:[155:47] posNoWhite:[155:46] Found expr:[155:3->155:57] +posCursor:[155:47] posNoWhite:[155:46] Found pattern:[155:29->155:49] +posCursor:[155:47] posNoWhite:[155:46] Found pattern:[155:42->155:48] +posCursor:[155:47] posNoWhite:[155:46] Found pattern:[155:46->155:47] +Ppat_construct T:[155:46->155:47] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [RecordField:thirdStuff, Tuple:1], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 158:51 +posCursor:[158:51] posNoWhite:[158:50] Found expr:[158:3->158:62] +posCursor:[158:51] posNoWhite:[158:50] Found pattern:[158:29->158:54] +posCursor:[158:51] posNoWhite:[158:50] Found pattern:[158:42->158:53] +posCursor:[158:51] posNoWhite:[158:50] Found pattern:[158:46->158:52] +Ppat_construct Four:[158:46->158:50] +posCursor:[158:51] posNoWhite:[158:50] Found pattern:[158:50->158:52] +Ppat_construct ():[158:50->158:52] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:(), pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 161:55 +posCursor:[161:55] posNoWhite:[161:54] Found expr:[161:3->161:66] +posCursor:[161:55] posNoWhite:[161:54] Found pattern:[161:29->161:58] +posCursor:[161:55] posNoWhite:[161:54] Found pattern:[161:42->161:57] +posCursor:[161:55] posNoWhite:[161:54] Found pattern:[161:46->161:56] +Ppat_construct Five:[161:46->161:50] +posCursor:[161:55] posNoWhite:[161:54] Found pattern:[161:50->161:57] +posCursor:[161:55] posNoWhite:[161:54] Found pattern:[161:54->161:55] +Ppat_construct O:[161:54->161:55] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:O, pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 164:63 +posCursor:[164:63] posNoWhite:[164:62] Found expr:[164:3->164:78] +posCursor:[164:63] posNoWhite:[164:62] Found pattern:[164:29->164:70] +posCursor:[164:63] posNoWhite:[164:62] Found pattern:[164:43->164:69] +posCursor:[164:63] posNoWhite:[164:62] Found pattern:[164:44->164:65] +Ppat_construct Some:[164:44->164:48] +posCursor:[164:63] posNoWhite:[164:62] Found pattern:[164:49->164:64] +posCursor:[164:63] posNoWhite:[164:62] Found pattern:[164:62->164:63] +Ppat_construct O:[164:62->164:63] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:O, pattern: [RecordField:fourthStuff, Tuple:0, Variant:Some(0), Variant:WithPayload(0)], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 167:67 +posCursor:[167:67] posNoWhite:[167:66] Found expr:[167:3->167:78] +posCursor:[167:67] posNoWhite:[167:66] Found pattern:[167:29->167:70] +posCursor:[167:67] posNoWhite:[167:66] Found pattern:[167:42->167:69] +posCursor:[167:67] posNoWhite:[167:66] Found pattern:[167:46->167:68] +Ppat_construct Five:[167:46->167:50] +posCursor:[167:67] posNoWhite:[167:66] Found pattern:[167:50->167:69] +posCursor:[167:67] posNoWhite:[167:66] Found pattern:[167:54->167:67] +posCursor:[167:67] posNoWhite:[167:66] Found pattern:[167:66->167:67] +Ppat_construct T:[167:66->167:67] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)], seenIdents: [One, Two, T]) +[] + +Complete src/TypedContextCompletionSpec.res 170:43 +posCursor:[170:43] posNoWhite:[170:42] Found expr:[170:3->170:52] +posCursor:[170:43] posNoWhite:[170:42] Found pattern:[170:29->170:44] +posCursor:[170:43] posNoWhite:[170:42] Found pattern:[170:42->170:43] +Ppat_construct S:[170:42->170:43] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:S, pattern: [RecordField:otherThing], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 173:39 +posCursor:[173:39] posNoWhite:[173:38] Found expr:[173:3->173:48] +posCursor:[173:39] posNoWhite:[173:38] Found pattern:[173:29->173:40] +posCursor:[173:39] posNoWhite:[173:38] Found pattern:[173:38->173:39] +Ppat_construct S:[173:38->173:39] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:S, pattern: [RecordField:other2], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 176:64 +posCursor:[176:64] posNoWhite:[176:62] Found expr:[176:3->176:75] +posCursor:[176:64] posNoWhite:[176:62] Found pattern:[176:29->176:67] +posCursor:[176:64] posNoWhite:[176:62] Found pattern:[176:42->176:66] +posCursor:[176:64] posNoWhite:[176:62] Found pattern:[176:46->176:65] +Ppat_construct Four:[176:46->176:50] +Completable: Cpath Value[Four] +[] + +Complete src/TypedContextCompletionSpec.res 179:38 +posCursor:[179:38] posNoWhite:[179:36] Found expr:[179:3->179:47] +posCursor:[179:38] posNoWhite:[179:36] Found pattern:[179:29->179:39] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:other2], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 182:55 +posCursor:[182:55] posNoWhite:[182:53] Found expr:[182:3->182:67] +posCursor:[182:55] posNoWhite:[182:53] Found pattern:[182:22->182:59] +posCursor:[182:55] posNoWhite:[182:53] Found pattern:[182:34->182:59] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:something, RecordField:whatIsThis], seenIdents: [false]) +[] + +Complete src/TypedContextCompletionSpec.res 185:46 +posCursor:[185:46] posNoWhite:[185:45] Found expr:[185:3->185:58] +posCursor:[185:46] posNoWhite:[185:45] Found pattern:[185:22->185:50] +posCursor:[185:46] posNoWhite:[185:45] Found pattern:[185:34->185:50] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:something, RecordField:whatIsThis], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 188:49 +posCursor:[188:49] posNoWhite:[188:48] Found expr:[188:3->188:62] +posCursor:[188:49] posNoWhite:[188:48] Found pattern:[188:22->188:54] +posCursor:[188:49] posNoWhite:[188:48] Found pattern:[188:34->188:52] +posCursor:[188:49] posNoWhite:[188:48] Found pattern:[188:47->188:49] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CVariant, patternType:Switch, prefix:fa, pattern: [RecordField:something, RecordField:whatIsThis], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 192:15 +posCursor:[192:15] posNoWhite:[192:14] Found expr:[192:3->192:17] +Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 196:14 +posCursor:[196:14] posNoWhite:[196:12] Found expr:[196:3->196:13] +[] + +Complete src/TypedContextCompletionSpec.res 199:15 +posCursor:[199:15] posNoWhite:[199:14] Found expr:[199:3->199:17] +Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 202:36 +posCursor:[202:36] posNoWhite:[202:34] Found expr:[202:3->202:38] +Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [], seenIdents: [One, Two, Three]) +[] + +Complete src/TypedContextCompletionSpec.res 206:33 +posCursor:[206:33] posNoWhite:[206:32] Found expr:[206:3->206:44] +posCursor:[206:33] posNoWhite:[206:32] Found pattern:[206:22->206:36] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:something], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 210:22 +posCursor:[210:22] posNoWhite:[210:20] Found expr:[210:3->210:30] +Completable: Cpath Value[""] +[{ + "label": "y", + "kind": 12, + "tags": [], + "detail": "someVariant", + "documentation": null + }, { + "label": "x", + "kind": 12, + "tags": [], + "detail": "option", + "documentation": null + }, { + "label": "someOtherValue", + "kind": 12, + "tags": [], + "detail": "someRecordWithVariant", + "documentation": null + }, { + "label": "getSomeVal", + "kind": 12, + "tags": [], + "detail": "(~irrelevant: int) => anotherRecord", + "documentation": null + }, { + "label": "someVal", + "kind": 12, + "tags": [], + "detail": "anotherRecord", + "documentation": null + }, { + "label": "Arg", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ArrayLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Auto", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Float", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSet", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_HashSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Id", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Int", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_List", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Map", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapDict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableQueue", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSet", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_MutableStack", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Option", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Range", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Result", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_Set", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetDict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArray", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArrayInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_SortArrayString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalAVLset", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalAVLtree", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalBuckets", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalBucketsType", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalMapInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalMapString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetBuckets", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetInt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internalSetString", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Belt_internals", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Buffer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Bytes", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "BytesLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Callback", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CamlinternalLazy", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CamlinternalMod", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Char", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CodeLens", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CompletePrioritize1", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CompletePrioritize2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Completion", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Complex", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Component", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "CreateInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Cross", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dce", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Debug", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Definition", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "DefinitionWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Digest", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Div", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "DocumentSymbol", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom_storage", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Dom_storage2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Filename", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Fragment", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Genlex", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Hashtbl", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "HashtblLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Highlight", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Hover", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "InlayHint", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Int32", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Int64", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_OO", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_array2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_bigint", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_cast", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_console", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_date", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_dict", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_exn", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_float", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_global", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_int", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_json", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_list", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_mapperRt", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_math", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_null", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_null_undefined", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_obj", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_option", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_promise", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_re", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_result", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_string", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_string2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_typed_array", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_typed_array2", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_types", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_undefined", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Js_vector", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Jsx", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Lazy", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Lexing", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "List", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ListLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "LongIdentTest", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Map", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "MapLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "MoreLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_buffer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_child_process", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_fs", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_module", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_path", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Node_process", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Obj", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Object", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Parsing", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Patterns", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Pervasives", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Printexc", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Queue", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Random", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "React", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOM", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMRe", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMServer", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactDOMStyle", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactEvent", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReactTestUtils", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReasonReact", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecModules", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecordCompletion", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RecoveryOnProp", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "References", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "ReferencesWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Rename", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RenameWithInterface", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RescriptReactErrorBoundary", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "RescriptReactRouter", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Set", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "SetLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Sort", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Stack", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "StdLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Stream", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "String", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "StringLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Sys", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TableclothMap", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_Jsx", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_LabelledArguments", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeContextCompletion_Records", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypeDefinition", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "TypedContextCompletionSpec", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Uchar", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }, { + "label": "Xform", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null + }] + +Complete src/TypedContextCompletionSpec.res 214:23 +posCursor:[214:23] posNoWhite:[214:22] Found expr:[214:3->214:32] +posCursor:[214:23] posNoWhite:[214:22] Found pattern:[214:22->214:24] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Switch, prefix:"", pattern: [], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 218:31 +posCursor:[218:31] posNoWhite:[218:30] Found expr:[218:3->218:41] +posCursor:[218:31] posNoWhite:[218:30] Found pattern:[218:22->218:33] +posCursor:[218:31] posNoWhite:[218:30] Found pattern:[218:23->218:32] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Switch, prefix:something, pattern: [], seenIdents: [something]) +[] + +Complete src/TypedContextCompletionSpec.res 221:35 +posCursor:[221:35] posNoWhite:[221:34] Found expr:[221:3->221:45] +posCursor:[221:35] posNoWhite:[221:34] Found pattern:[221:22->221:37] +posCursor:[221:35] posNoWhite:[221:34] Found pattern:[221:34->221:36] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Switch, prefix:"", pattern: [RecordField:something], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 225:38 +posCursor:[225:38] posNoWhite:[225:37] Found expr:[225:3->225:50] +posCursor:[225:38] posNoWhite:[225:37] Found pattern:[225:22->225:42] +posCursor:[225:38] posNoWhite:[225:37] Found pattern:[225:34->225:42] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:something, RecordField:el], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 228:41 +posCursor:[228:41] posNoWhite:[228:40] Found expr:[228:3->228:51] +posCursor:[228:41] posNoWhite:[228:40] Found pattern:[228:29->228:43] +posCursor:[228:41] posNoWhite:[228:40] Found pattern:[228:38->228:42] +posCursor:[228:41] posNoWhite:[228:40] Found pattern:[228:40->228:41] +Ppat_construct ():[228:40->228:41] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:(), pattern: [RecordField:other2, Variant:S(0)], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 231:63 +posCursor:[231:63] posNoWhite:[231:62] Found expr:[231:3->231:74] +posCursor:[231:63] posNoWhite:[231:62] Found pattern:[231:29->231:66] +posCursor:[231:63] posNoWhite:[231:62] Found pattern:[231:42->231:65] +Ppat_construct Some:[231:42->231:46] +posCursor:[231:63] posNoWhite:[231:62] Found pattern:[231:46->231:66] +posCursor:[231:63] posNoWhite:[231:62] Found pattern:[231:50->231:64] +posCursor:[231:63] posNoWhite:[231:62] Found pattern:[231:62->231:63] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:t, pattern: [RecordField:thirdStuff, Variant:Some(1), RecordField:something], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 234:59 +posCursor:[234:59] posNoWhite:[234:58] Found expr:[234:3->234:70] +posCursor:[234:59] posNoWhite:[234:58] Found pattern:[234:29->234:62] +posCursor:[234:59] posNoWhite:[234:58] Found pattern:[234:42->234:61] +posCursor:[234:59] posNoWhite:[234:58] Found pattern:[234:46->234:60] +posCursor:[234:59] posNoWhite:[234:58] Found pattern:[234:58->234:59] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:t, pattern: [RecordField:thirdStuff, Tuple:1, RecordField:something], seenIdents: []) +[] + +Complete src/TypedContextCompletionSpec.res 238:49 +posCursor:[238:49] posNoWhite:[238:48] Found expr:[238:3->238:52] +posCursor:[238:49] posNoWhite:[238:48] Found pattern:[238:48->238:49] +Ppat_construct T:[238:48->238:49] +Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [], seenIdents: [One, Two, Three, T]) +[] + +Complete src/TypedContextCompletionSpec.res 241:55 +posCursor:[241:55] posNoWhite:[241:53] Found expr:[241:3->241:67] +posCursor:[241:55] posNoWhite:[241:53] Found pattern:[241:22->241:59] +posCursor:[241:55] posNoWhite:[241:53] Found pattern:[241:34->241:59] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:something, RecordField:whatIsThis], seenIdents: [false]) +[] + +Complete src/TypedContextCompletionSpec.res 245:49 +posCursor:[245:49] posNoWhite:[245:46] Found expr:[245:3->245:51] +Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [], seenIdents: [One, Two, Three]) +[] From 2c1b7215144981aa55df345bcd04929436433100 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 16 Aug 2022 11:00:03 +0200 Subject: [PATCH 62/80] hook up completion backend with new pattern completion stuff --- analysis/src/CompletionBackEnd.ml | 178 ++- analysis/src/CompletionFrontEnd.ml | 127 +- analysis/src/DumpAst.ml | 24 +- analysis/src/Protocol.ml | 7 +- analysis/src/SharedTypes.ml | 13 +- .../src/expected/CompletePrioritize1.res.txt | 3 +- .../src/expected/CompletePrioritize2.res.txt | 6 +- .../tests/src/expected/Completion.res.txt | 486 +++++--- analysis/tests/src/expected/Debug.res.txt | 6 +- analysis/tests/src/expected/Div.res.txt | 3 +- analysis/tests/src/expected/Jsx.res.txt | 108 +- analysis/tests/src/expected/Jsx.resi.txt | 6 +- .../src/expected/RecordCompletion.res.txt | 18 +- .../tests/src/expected/RecoveryOnProp.res.txt | 6 +- .../TypeContextCompletion_Jsx.res.txt | 93 +- ...ontextCompletion_LabelledArguments.res.txt | 120 +- .../TypeContextCompletion_Records.res.txt | 472 +++++++- .../TypedContextCompletionSpec.res.txt | 1069 +++++++++++++---- 18 files changed, 2153 insertions(+), 592 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 8a218ccbc..6a2504b4c 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1157,7 +1157,7 @@ let getCompletionsForPath ~package ~opens ~allFiles ~pos ~exact ~scope findAllCompletions ~env ~prefix ~exact ~namesUsed ~completionContext | None -> []) -let mkItem ~name ~kind ~detail ~deprecated ~docstring = +let mkItem ~name ~sortText ~kind ~detail ~deprecated ~docstring = let docContent = (match deprecated with | None -> "" @@ -1181,10 +1181,11 @@ let mkItem ~name ~kind ~detail ~deprecated ~docstring = documentation = (if docContent = "" then None else Some {kind = "markdown"; value = docContent}); + sortText; } -let completionToItem {Completion.name; deprecated; docstring; kind} = - mkItem ~name +let completionToItem {Completion.name; deprecated; docstring; kind; sortText} = + mkItem ~name ~sortText ~kind:(Completion.kindToInt kind) ~deprecated ~detail:(detail name kind) ~docstring @@ -1978,6 +1979,176 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i Utils.startsWith name prefix && (forHover || not (List.mem name identsSeen))) |> List.map mkLabel + | CtypedPattern + { + howToRetrieveSourceType; + patternPath; + patternType; + lookingToComplete; + meta = {prefix; alreadySeenIdents}; + } -> ( + let prefix = + match prefix with + | None -> "" + | Some prefix -> prefix + in + let sourceType = + howToRetrieveSourceType + |> findSourceType ~package ~opens ~rawOpens ~allFiles ~env ~pos ~scope + in + match sourceType with + | None -> [] + | Some typ -> ( + match + ( typ |> findTypeInContext ~env ~nestedContextPath:patternPath ~package, + lookingToComplete ) + with + | None, _ -> [] + | Some CBool, _ -> + (* Completing booleans - doesn't matter what we're looking to complete, since there's only one thing to complete (the bool values themselves). *) + ["false"; "true"] + |> List.filter (fun boolEntry -> + Utils.startsWith boolEntry prefix + && not + (alreadySeenIdents + |> List.exists (fun seenIdent -> seenIdent = boolEntry))) + |> List.map (fun boolEntry -> + Completion.create ~name:boolEntry ~kind:Bool ~env) + | Some (COptional completable), _lookingToComplete -> ( + (* TODO: Account for lookingToComplete? *) + match completable with + | CVariant {constructors} -> + (* TOOD: Unify with other variant completion handler *) + let constructorCompletions = + constructors + |> List.filter (fun constructor -> + Utils.startsWith + ("Some(" ^ constructor.Constructor.cname.txt ^ ")") + prefix + && not + (alreadySeenIdents + |> List.exists (fun alreadySeenConstructorName -> + alreadySeenConstructorName + = constructor.Constructor.cname.txt))) + |> List.map (fun (constructor : Constructor.t) -> + (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? + Eg. Some($1) as completion item. *) + Completion.create + ~name: + ("Some(" ^ constructor.cname.txt + ^ + if constructor.args |> List.length > 0 then "(_))" + else ")") + ~kind:(Constructor (constructor, "")) + ~env) + in + (* TODO: Patterns should not include local completions *) + let _localCompletions = + typ + |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix + ~exact:false ~opens ~scope + in + [Completion.create ~name:"None" ~kind:OptionNone ~env] + @ constructorCompletions + | CPolyVariant {constructors} -> + (* TOOD: Unify with other variant completion handler *) + let constructorCompletions = + constructors + |> List.filter (fun constructor -> + Utils.startsWith ("Some(#" ^ constructor.name ^ ")") prefix) + |> List.map (fun constructor -> + (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? + Eg. Some($1) as completion item. *) + Completion.create + ~name: + ("Some(#" ^ constructor.name + ^ + if constructor.payload |> Option.is_some then "(_))" + else ")") + ~kind:(PolyvariantConstructor constructor) ~env) + in + (* TODO: Patterns should not include local completions *) + let _localCompletions = + typ + |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix + ~exact:false ~opens ~scope + in + [Completion.create ~name:"None" ~kind:OptionNone ~env] + @ constructorCompletions + | _ -> + [ + Completion.create ~name:"None" ~kind:OptionNone ~env; + Completion.create ~name:"Some(_)" ~kind:OptionSome ~env; + ]) + | Some (CPolyVariant {constructors}), _ -> + let constructorCompletions = + constructors + |> List.filter (fun constructor -> + Utils.startsWith constructor.name prefix) + |> List.map (fun constructor -> + (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? + Eg. Some($1) as completion item. *) + Completion.create + ~name: + ("#" ^ constructor.name + ^ + if constructor.payload |> Option.is_some then "(_)" else "" + ) + ~kind:(PolyvariantConstructor constructor) ~env) + in + let _localCompletions = + typ + |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix ~exact:false + ~opens ~scope + in + constructorCompletions + | Some (CVariant {constructors}), _ -> + let constructorCompletions = + constructors + |> List.filter (fun constructor -> + Utils.startsWith constructor.Constructor.cname.txt prefix + && not + (alreadySeenIdents + |> List.exists (fun alreadySeenConstructorName -> + alreadySeenConstructorName + = constructor.Constructor.cname.txt))) + |> List.map (fun (constructor : Constructor.t) -> + (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? + Eg. Some($1) as completion item. *) + Completion.create + ~name: + (constructor.cname.txt + ^ if constructor.args |> List.length > 0 then "(_)" else "" + ) + ~kind:(Constructor (constructor, "")) + ~env) + in + let _localCompletions = + typ + |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix ~exact:false + ~opens ~scope + in + constructorCompletions + | Some (CRecord {fields; decl; name}), CRecordField -> + fields + |> List.filter (fun (field : field) -> + not + (alreadySeenIdents + |> List.exists (fun fieldName -> fieldName = field.fname.txt))) + |> Utils.filterMap (fun (field : field) -> + if prefix = "" || checkName field.fname.txt ~prefix ~exact:false + then + Some + (Completion.create ~name:field.fname.txt ~env + ~kind: + (Completion.Field + (field, decl |> Shared.declToString name.txt))) + else None) + | Some (CRecord _), _ -> + [ + Completion.createWithSortText ~name:"{}" ~env ~sortText:"a" + ~kind:(Completion.Label "Empty record"); + ])) | CtypedContextPattern {howToRetrieveSourceType; patternPath; meta = {prefix; alreadySeenIdents}} -> ( @@ -2134,4 +2305,3 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i (Completion.Field (field, decl |> Shared.declToString name.txt))) else None))) - | CtypedPattern _ -> [] diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index cf8c5ab4f..f83d6143f 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -606,7 +606,7 @@ let rec findTupleItemWithCursor items ~index ~pos = else findTupleItemWithCursor rest ~index:(index + 1) ~pos let rec findContextInPattern pattern ~pos ~patternPath ~debug - ~seenIdentsFromParent = + ~seenIdentsFromParent ~firstCharBeforeCursorNoWhite = match pattern.Parsetree.ppat_desc with | Ppat_extension ({txt = "rescript.patternhole"}, _) -> (* This is printed when the parser has made recovery. @@ -648,7 +648,7 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug | _ -> payload in findContextInPattern patternToContinueFrom ~pos ~debug - ~seenIdentsFromParent:[] + ~firstCharBeforeCursorNoWhite ~seenIdentsFromParent:[] ~patternPath: ([ Completable.Variant @@ -667,9 +667,11 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug match pat.ppat_desc with | Ppat_tuple _ -> (* Continue down here too, but let us discover the tuple in the next step. *) - findContextInPattern pat ~pos ~patternPath ~debug ~seenIdentsFromParent:[] + findContextInPattern pat ~firstCharBeforeCursorNoWhite ~pos ~patternPath + ~debug ~seenIdentsFromParent:[] | _ -> - findContextInPattern pat ~pos ~debug ~seenIdentsFromParent:[] + findContextInPattern pat ~firstCharBeforeCursorNoWhite ~pos ~debug + ~seenIdentsFromParent:[] ~patternPath: ([Completable.Variant {constructorName; payloadNum = Some 0}] @ patternPath)) @@ -748,7 +750,7 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug prefix = ""; alreadySeenIdents = []; } - | Ppat_record (fields, _) -> + | Ppat_record (fields, _) -> ( let seenFields = fields |> List.map (fun ({Location.txt}, _) -> getSimpleFieldName txt) in @@ -758,52 +760,72 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug CursorPosition.classifyLoc fieldPat.Parsetree.ppat_loc ~pos = HasCursor) in - fields - |> List.find_map (fun (loc, fieldPat) -> - match - CursorPosition.classifyLoc fieldPat.Parsetree.ppat_loc ~pos - with - | HasCursor -> ( - (* handle `{something}`, which is parsed as `{something: something}` because of punning *) - match (loc, fieldPat.Parsetree.ppat_desc) with - | ( {Location.txt = Longident.Lident fieldName}, - Ppat_var {txt = varName} ) - when fieldName = varName -> - Some - { - lookingToComplete = CRecordField; - patternPath; - prefix = varName; - alreadySeenIdents = seenFields; - } - | _ -> - (* We can continue down into anything else *) - findContextInPattern fieldPat ~pos ~debug - ~seenIdentsFromParent:[] - ~patternPath: - ([ - Completable.RField {fieldName = getSimpleFieldName loc.txt}; - ] - @ patternPath)) - | NoCursor -> None - | EmptyLoc -> - if - (* We only care about empty locations if there's no field with the cursor *) - fieldWithCursorExists - then None - else - findContextInPattern fieldPat ~pos ~debug - ~seenIdentsFromParent:[] - ~patternPath: - ([ - Completable.RField {fieldName = getSimpleFieldName loc.txt}; - ] - @ patternPath)) + let completableFromField = + fields + |> List.find_map (fun (loc, fieldPat) -> + match + CursorPosition.classifyLoc fieldPat.Parsetree.ppat_loc ~pos + with + | HasCursor -> ( + (* handle `{something}`, which is parsed as `{something: something}` because of punning *) + match (loc, fieldPat.Parsetree.ppat_desc) with + | ( {Location.txt = Longident.Lident fieldName}, + Ppat_var {txt = varName} ) + when fieldName = varName -> + Some + { + lookingToComplete = CRecordField; + patternPath; + prefix = varName; + alreadySeenIdents = seenFields; + } + | _ -> + (* We can continue down into anything else *) + findContextInPattern fieldPat ~pos + ~firstCharBeforeCursorNoWhite ~debug ~seenIdentsFromParent:[] + ~patternPath: + ([ + Completable.RField + {fieldName = getSimpleFieldName loc.txt}; + ] + @ patternPath)) + | NoCursor -> None + | EmptyLoc -> + if + (* We only care about empty locations if there's no field with the cursor *) + fieldWithCursorExists + then None + else + findContextInPattern fieldPat ~pos ~debug + ~firstCharBeforeCursorNoWhite ~seenIdentsFromParent:[] + ~patternPath: + ([ + Completable.RField + {fieldName = getSimpleFieldName loc.txt}; + ] + @ patternPath)) + in + match + (completableFromField, fieldWithCursorExists, firstCharBeforeCursorNoWhite) + with + | None, false, Some ',' -> + (* If there's no field with the cursor, and we found no completable, and the first char before the + cursor is ',' we can assume that this is a pattern like `{someField, }`. + The parser discards any unecessary commas, so we can't leverage the parser to figure out that + we're looking to complete for a new field. *) + Some + { + lookingToComplete = CRecordField; + patternPath; + prefix = ""; + alreadySeenIdents = seenFields; + } + | completableFromField, _, _ -> completableFromField) | Ppat_tuple items -> ( match findTupleItemWithCursor items ~pos ~index:0 with | Some (Some tuplePatternWithCursor, itemNumber) -> findContextInPattern tuplePatternWithCursor ~pos ~debug - ~seenIdentsFromParent:[] + ~seenIdentsFromParent:[] ~firstCharBeforeCursorNoWhite ~patternPath:([Completable.PTuple {itemNumber}] @ patternPath) | None -> (* TODO: No tuple item had the cursor, but we might still be able to complete @@ -863,6 +885,7 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug | Some pattern -> pattern |> findContextInPattern ~pos ~patternPath ~debug + ~firstCharBeforeCursorNoWhite ~seenIdentsFromParent:identsFromBranches) | _v -> (* if debug then @@ -1026,8 +1049,9 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~seenIdents:[]) | Some contextPath -> ( match - findContextInPattern pvb_pat ~pos:posBeforeCursor ~patternPath:[] - ~seenIdentsFromParent:[] ~debug + findContextInPattern pvb_pat ~firstCharBeforeCursorNoWhite + ~pos:posBeforeCursor ~patternPath:[] ~seenIdentsFromParent:[] + ~debug with | None -> () | Some res -> @@ -1367,8 +1391,9 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = = typ then case.pc_lhs - |> findContextInPattern ~pos:posBeforeCursor ~patternPath:[] - ~debug ~seenIdentsFromParent:identsFromCases + |> findContextInPattern ~firstCharBeforeCursorNoWhite + ~pos:posBeforeCursor ~patternPath:[] ~debug + ~seenIdentsFromParent:identsFromCases else findCaseWithCursor nextCases ~typ ~identsFromCases | [] -> None in diff --git a/analysis/src/DumpAst.ml b/analysis/src/DumpAst.ml index 3a0a388b2..adf3be23c 100644 --- a/analysis/src/DumpAst.ml +++ b/analysis/src/DumpAst.ml @@ -29,6 +29,16 @@ let addIndentation indentation = in indent "" indentation +let printAttributes attributes = + match List.length attributes with + | 0 -> "" + | _ -> + "[" + ^ (attributes + |> List.map (fun ({Location.txt}, _payload) -> "@" ^ txt) + |> String.concat ",") + ^ "]" + let printConstant const = match const with | Parsetree.Pconst_integer (s, _) -> "Pconst_integer(" ^ s ^ ")" @@ -43,7 +53,8 @@ let printConstant const = | Pconst_float (s, _) -> "Pconst_float(" ^ s ^ ")" let printCoreType typ ~pos = - (typ.Parsetree.ptyp_loc |> printLocDenominator ~pos) + printAttributes typ.Parsetree.ptyp_attributes + ^ (typ.ptyp_loc |> printLocDenominator ~pos) ^ match typ.ptyp_desc with | Ptyp_any -> "Ptyp_any" @@ -56,7 +67,8 @@ let printCoreType typ ~pos = | _ -> "" let rec printPattern pattern ~pos ~indentation = - (pattern.Parsetree.ppat_loc |> printLocDenominator ~pos) + printAttributes pattern.Parsetree.ppat_attributes + ^ (pattern.ppat_loc |> printLocDenominator ~pos) ^ match pattern.Parsetree.ppat_desc with | Ppat_or (pat1, pat2) -> @@ -136,7 +148,8 @@ and printCase case ~pos ~indentation ~caseNum = and printExprItem expr ~pos ~indentation = addIndentation indentation - ^ (expr.Parsetree.pexp_loc |> printLocDenominator ~pos) + ^ printAttributes expr.Parsetree.pexp_attributes + ^ (expr.pexp_loc |> printLocDenominator ~pos) ^ match expr.Parsetree.pexp_desc with | Pexp_match (matchExpr, cases) -> @@ -213,9 +226,10 @@ and printExprItem expr ~pos ~indentation = | v -> Printf.sprintf "" (Utils.identifyPexp v) let printValueBinding value ~pos ~indentation = - "value" ^ ":\n" + printAttributes value.Parsetree.pvb_attributes + ^ "value" ^ ":\n" ^ addIndentation (indentation + 1) - ^ (value.Parsetree.pvb_pat |> printPattern ~pos ~indentation:(indentation + 1)) + ^ (value.pvb_pat |> printPattern ~pos ~indentation:(indentation + 1)) ^ "\n" ^ addIndentation indentation ^ "expr:\n" ^ printExprItem value.pvb_expr ~pos ~indentation:(indentation + 1) diff --git a/analysis/src/Protocol.ml b/analysis/src/Protocol.ml index a1440aa85..04fdb7b3f 100644 --- a/analysis/src/Protocol.ml +++ b/analysis/src/Protocol.ml @@ -21,6 +21,7 @@ type completionItem = { kind: int; tags: int list; detail: string; + sortText: string option; documentation: markupContent option; } @@ -71,7 +72,8 @@ let stringifyCompletionItem c = "kind": %i, "tags": %s, "detail": "%s", - "documentation": %s + "documentation": %s, + "sortText": %s }|} (Json.escape c.label) c.kind (c.tags |> List.map string_of_int |> array) @@ -79,6 +81,9 @@ let stringifyCompletionItem c = (match c.documentation with | None -> null | Some doc -> stringifyMarkupContent doc) + (match c.sortText with + | None -> null + | Some sortText -> Printf.sprintf "\"%s\"" (Json.escape sortText)) let stringifyHover s = Printf.sprintf {|{"contents": "%s"}|} (Json.escape s) diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 94389f04c..e9ef3d8ea 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -239,6 +239,7 @@ module Completion = struct type t = { name: string; + sortText: string option; env: QueryEnv.t; deprecated: string option; docstring: string list; @@ -246,7 +247,17 @@ module Completion = struct } let create ~name ~kind ~env = - {name; env; deprecated = None; docstring = []; kind} + {name; env; deprecated = None; docstring = []; kind; sortText = None} + + let createWithSortText ~name ~kind ~env ~sortText = + { + name; + env; + deprecated = None; + docstring = []; + kind; + sortText = Some sortText; + } (* https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion *) (* https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#completionItemKind *) diff --git a/analysis/tests/src/expected/CompletePrioritize1.res.txt b/analysis/tests/src/expected/CompletePrioritize1.res.txt index 3f5485410..c1ec4a7cc 100644 --- a/analysis/tests/src/expected/CompletePrioritize1.res.txt +++ b/analysis/tests/src/expected/CompletePrioritize1.res.txt @@ -6,6 +6,7 @@ Completable: Cpath Value[a]-> "kind": 12, "tags": [], "detail": "float => float", - "documentation": null + "documentation": null, + "sortText": null }] diff --git a/analysis/tests/src/expected/CompletePrioritize2.res.txt b/analysis/tests/src/expected/CompletePrioritize2.res.txt index b3b9674e1..8c8cbef44 100644 --- a/analysis/tests/src/expected/CompletePrioritize2.res.txt +++ b/analysis/tests/src/expected/CompletePrioritize2.res.txt @@ -6,7 +6,8 @@ Completable: Cpath Value[ax]-> "kind": 12, "tags": [], "detail": "t => int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/CompletePrioritize2.res 12:5 @@ -18,6 +19,7 @@ Completable: Cpath Value[ax] "kind": 12, "tags": [], "detail": "Test.t", - "documentation": null + "documentation": null, + "sortText": null }] diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index 07db5bc9c..71d2a3de5 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -7,67 +7,78 @@ Completable: Cpath Value[MyList, m] "kind": 12, "tags": [], "detail": "(t<'a>, 'a => 'b) => t<'b>", - "documentation": {"kind": "markdown", "value": "\n Equivalent to:\n\n ```res\n map(someList, f)->reverse\n ```\n\n ```res example\n list{3, 4, 5}->Belt.List.mapReverse(x => x * x) /* list{25, 16, 9} */\n ```\n"} + "documentation": {"kind": "markdown", "value": "\n Equivalent to:\n\n ```res\n map(someList, f)->reverse\n ```\n\n ```res example\n list{3, 4, 5}->Belt.List.mapReverse(x => x * x) /* list{25, 16, 9} */\n ```\n"}, + "sortText": null }, { "label": "makeBy", "kind": 12, "tags": [], "detail": "(int, int => 'a) => t<'a>", - "documentation": {"kind": "markdown", "value": "\nReturn a list of length `numItems` with element `i` initialized with `f(i)`.\nReturns an empty list if `numItems` is negative.\n\n```res example\nBelt.List.makeBy(5, i => i) // list{0, 1, 2, 3, 4}\n\nBelt.List.makeBy(5, i => i * i) // list{0, 1, 4, 9, 16}\n```\n"} + "documentation": {"kind": "markdown", "value": "\nReturn a list of length `numItems` with element `i` initialized with `f(i)`.\nReturns an empty list if `numItems` is negative.\n\n```res example\nBelt.List.makeBy(5, i => i) // list{0, 1, 2, 3, 4}\n\nBelt.List.makeBy(5, i => i * i) // list{0, 1, 4, 9, 16}\n```\n"}, + "sortText": null }, { "label": "make", "kind": 12, "tags": [], "detail": "(int, 'a) => t<'a>", - "documentation": {"kind": "markdown", "value": "\n Returns a list of length `numItems` with each element filled with value `v`. Returns an empty list if `numItems` is negative.\n\n ```res example\n Belt.List.make(3, 1) // list{1, 1, 1}\n ```\n"} + "documentation": {"kind": "markdown", "value": "\n Returns a list of length `numItems` with each element filled with value `v`. Returns an empty list if `numItems` is negative.\n\n ```res example\n Belt.List.make(3, 1) // list{1, 1, 1}\n ```\n"}, + "sortText": null }, { "label": "mapReverse2U", "kind": 12, "tags": [], "detail": "(t<'a>, t<'b>, (. 'a, 'b) => 'c) => t<'c>", - "documentation": {"kind": "markdown", "value": " Uncurried version of [mapReverse2](#mapReverse2). "} + "documentation": {"kind": "markdown", "value": " Uncurried version of [mapReverse2](#mapReverse2). "}, + "sortText": null }, { "label": "map", "kind": 12, "tags": [], "detail": "(t<'a>, 'a => 'b) => t<'b>", - "documentation": {"kind": "markdown", "value": "\n Returns a new list with `f` applied to each element of `someList`.\n\n ```res example\n list{1, 2}->Belt.List.map(x => x + 1) // list{3, 4}\n ```\n"} + "documentation": {"kind": "markdown", "value": "\n Returns a new list with `f` applied to each element of `someList`.\n\n ```res example\n list{1, 2}->Belt.List.map(x => x + 1) // list{3, 4}\n ```\n"}, + "sortText": null }, { "label": "mapWithIndexU", "kind": 12, "tags": [], "detail": "(t<'a>, (. int, 'a) => 'b) => t<'b>", - "documentation": {"kind": "markdown", "value": " Uncurried version of [mapWithIndex](#mapWithIndex). "} + "documentation": {"kind": "markdown", "value": " Uncurried version of [mapWithIndex](#mapWithIndex). "}, + "sortText": null }, { "label": "mapU", "kind": 12, "tags": [], "detail": "(t<'a>, (. 'a) => 'b) => t<'b>", - "documentation": {"kind": "markdown", "value": " Uncurried version of [map](#map). "} + "documentation": {"kind": "markdown", "value": " Uncurried version of [map](#map). "}, + "sortText": null }, { "label": "makeByU", "kind": 12, "tags": [], "detail": "(int, (. int) => 'a) => t<'a>", - "documentation": {"kind": "markdown", "value": " Uncurried version of [makeBy](#makeBy) "} + "documentation": {"kind": "markdown", "value": " Uncurried version of [makeBy](#makeBy) "}, + "sortText": null }, { "label": "mapReverse2", "kind": 12, "tags": [], "detail": "(t<'a>, t<'b>, ('a, 'b) => 'c) => t<'c>", - "documentation": {"kind": "markdown", "value": "\n Equivalent to: `zipBy(xs, ys, f)->reverse`\n\n ```res example\n\n Belt.List.mapReverse2(list{1, 2, 3}, list{1, 2}, (a, b) => a + b) // list{4, 2}\n ```\n"} + "documentation": {"kind": "markdown", "value": "\n Equivalent to: `zipBy(xs, ys, f)->reverse`\n\n ```res example\n\n Belt.List.mapReverse2(list{1, 2, 3}, list{1, 2}, (a, b) => a + b) // list{4, 2}\n ```\n"}, + "sortText": null }, { "label": "mapWithIndex", "kind": 12, "tags": [], "detail": "(t<'a>, (int, 'a) => 'b) => t<'b>", - "documentation": {"kind": "markdown", "value": "\n Applies `f` to each element of `someList`.\n Function `f` takes two arguments: the index starting from 0 and the element from `someList`, in that order.\n\n ```res example\n list{1, 2, 3}->Belt.List.mapWithIndex((index, x) => index + x) // list{1, 3, 5}\n ```\n"} + "documentation": {"kind": "markdown", "value": "\n Applies `f` to each element of `someList`.\n Function `f` takes two arguments: the index starting from 0 and the element from `someList`, in that order.\n\n ```res example\n list{1, 2, 3}->Belt.List.mapWithIndex((index, x) => index + x) // list{1, 3, 5}\n ```\n"}, + "sortText": null }, { "label": "mapReverseU", "kind": 12, "tags": [], "detail": "(t<'a>, (. 'a) => 'b) => t<'b>", - "documentation": {"kind": "markdown", "value": " Uncurried version of [mapReverse](#mapReverse). "} + "documentation": {"kind": "markdown", "value": " Uncurried version of [mapReverse](#mapReverse). "}, + "sortText": null }] Complete src/Completion.res 3:9 @@ -79,217 +90,253 @@ Completable: Cpath Value[Array, ""] "kind": 12, "tags": [], "detail": "(('a, 'b) => 'a, 'a, array<'b>) => 'a", - "documentation": {"kind": "markdown", "value": " [Array.fold_left f x a] computes\n [f (... (f (f x a.(0)) a.(1)) ...) a.(n-1)],\n where [n] is the length of the array [a]. "} + "documentation": {"kind": "markdown", "value": " [Array.fold_left f x a] computes\n [f (... (f (f x a.(0)) a.(1)) ...) a.(n-1)],\n where [n] is the length of the array [a]. "}, + "sortText": null }, { "label": "concat", "kind": 12, "tags": [], "detail": "list> => array<'a>", - "documentation": {"kind": "markdown", "value": " Same as {!Array.append}, but concatenates a list of arrays. "} + "documentation": {"kind": "markdown", "value": " Same as {!Array.append}, but concatenates a list of arrays. "}, + "sortText": null }, { "label": "mapi", "kind": 12, "tags": [], "detail": "((int, 'a) => 'b, array<'a>) => array<'b>", - "documentation": {"kind": "markdown", "value": " Same as {!Array.map}, but the\n function is applied to the index of the element as first argument,\n and the element itself as second argument. "} + "documentation": {"kind": "markdown", "value": " Same as {!Array.map}, but the\n function is applied to the index of the element as first argument,\n and the element itself as second argument. "}, + "sortText": null }, { "label": "exists", "kind": 12, "tags": [], "detail": "('a => bool, array<'a>) => bool", - "documentation": {"kind": "markdown", "value": " [Array.exists p [|a1; ...; an|]] checks if at least one element of\n the array satisfies the predicate [p]. That is, it returns\n [(p a1) || (p a2) || ... || (p an)].\n @since 4.03.0 "} + "documentation": {"kind": "markdown", "value": " [Array.exists p [|a1; ...; an|]] checks if at least one element of\n the array satisfies the predicate [p]. That is, it returns\n [(p a1) || (p a2) || ... || (p an)].\n @since 4.03.0 "}, + "sortText": null }, { "label": "for_all", "kind": 12, "tags": [], "detail": "('a => bool, array<'a>) => bool", - "documentation": {"kind": "markdown", "value": " [Array.for_all p [|a1; ...; an|]] checks if all elements of the array\n satisfy the predicate [p]. That is, it returns\n [(p a1) && (p a2) && ... && (p an)].\n @since 4.03.0 "} + "documentation": {"kind": "markdown", "value": " [Array.for_all p [|a1; ...; an|]] checks if all elements of the array\n satisfy the predicate [p]. That is, it returns\n [(p a1) && (p a2) && ... && (p an)].\n @since 4.03.0 "}, + "sortText": null }, { "label": "copy", "kind": 12, "tags": [], "detail": "array<'a> => array<'a>", - "documentation": {"kind": "markdown", "value": " [Array.copy a] returns a copy of [a], that is, a fresh array\n containing the same elements as [a]. "} + "documentation": {"kind": "markdown", "value": " [Array.copy a] returns a copy of [a], that is, a fresh array\n containing the same elements as [a]. "}, + "sortText": null }, { "label": "iter2", "kind": 12, "tags": [], "detail": "(('a, 'b) => unit, array<'a>, array<'b>) => unit", - "documentation": {"kind": "markdown", "value": " [Array.iter2 f a b] applies function [f] to all the elements of [a]\n and [b].\n Raise [Invalid_argument] if the arrays are not the same size.\n @since 4.03.0 "} + "documentation": {"kind": "markdown", "value": " [Array.iter2 f a b] applies function [f] to all the elements of [a]\n and [b].\n Raise [Invalid_argument] if the arrays are not the same size.\n @since 4.03.0 "}, + "sortText": null }, { "label": "to_list", "kind": 12, "tags": [], "detail": "array<'a> => list<'a>", - "documentation": {"kind": "markdown", "value": " [Array.to_list a] returns the list of all the elements of [a]. "} + "documentation": {"kind": "markdown", "value": " [Array.to_list a] returns the list of all the elements of [a]. "}, + "sortText": null }, { "label": "stable_sort", "kind": 12, "tags": [], "detail": "(('a, 'a) => int, array<'a>) => unit", - "documentation": {"kind": "markdown", "value": " Same as {!Array.sort}, but the sorting algorithm is stable (i.e.\n elements that compare equal are kept in their original order) and\n not guaranteed to run in constant heap space.\n\n The current implementation uses Merge Sort. It uses [n/2]\n words of heap space, where [n] is the length of the array.\n It is usually faster than the current implementation of {!Array.sort}.\n"} + "documentation": {"kind": "markdown", "value": " Same as {!Array.sort}, but the sorting algorithm is stable (i.e.\n elements that compare equal are kept in their original order) and\n not guaranteed to run in constant heap space.\n\n The current implementation uses Merge Sort. It uses [n/2]\n words of heap space, where [n] is the length of the array.\n It is usually faster than the current implementation of {!Array.sort}.\n"}, + "sortText": null }, { "label": "iteri", "kind": 12, "tags": [], "detail": "((int, 'a) => unit, array<'a>) => unit", - "documentation": {"kind": "markdown", "value": " Same as {!Array.iter}, but the\n function is applied with the index of the element as first argument,\n and the element itself as second argument. "} + "documentation": {"kind": "markdown", "value": " Same as {!Array.iter}, but the\n function is applied with the index of the element as first argument,\n and the element itself as second argument. "}, + "sortText": null }, { "label": "memq", "kind": 12, "tags": [], "detail": "('a, array<'a>) => bool", - "documentation": {"kind": "markdown", "value": " Same as {!Array.mem}, but uses physical equality instead of structural\n equality to compare array elements.\n @since 4.03.0 "} + "documentation": {"kind": "markdown", "value": " Same as {!Array.mem}, but uses physical equality instead of structural\n equality to compare array elements.\n @since 4.03.0 "}, + "sortText": null }, { "label": "map2", "kind": 12, "tags": [], "detail": "(('a, 'b) => 'c, array<'a>, array<'b>) => array<'c>", - "documentation": {"kind": "markdown", "value": " [Array.map2 f a b] applies function [f] to all the elements of [a]\n and [b], and builds an array with the results returned by [f]:\n [[| f a.(0) b.(0); ...; f a.(Array.length a - 1) b.(Array.length b - 1)|]].\n Raise [Invalid_argument] if the arrays are not the same size.\n @since 4.03.0 "} + "documentation": {"kind": "markdown", "value": " [Array.map2 f a b] applies function [f] to all the elements of [a]\n and [b], and builds an array with the results returned by [f]:\n [[| f a.(0) b.(0); ...; f a.(Array.length a - 1) b.(Array.length b - 1)|]].\n Raise [Invalid_argument] if the arrays are not the same size.\n @since 4.03.0 "}, + "sortText": null }, { "label": "set", "kind": 12, "tags": [], "detail": "(array<'a>, int, 'a) => unit", - "documentation": {"kind": "markdown", "value": " [Array.set a n x] modifies array [a] in place, replacing\n element number [n] with [x].\n You can also write [a.(n) <- x] instead of [Array.set a n x].\n\n Raise [Invalid_argument \"index out of bounds\"]\n if [n] is outside the range 0 to [Array.length a - 1]. "} + "documentation": {"kind": "markdown", "value": " [Array.set a n x] modifies array [a] in place, replacing\n element number [n] with [x].\n You can also write [a.(n) <- x] instead of [Array.set a n x].\n\n Raise [Invalid_argument \"index out of bounds\"]\n if [n] is outside the range 0 to [Array.length a - 1]. "}, + "sortText": null }, { "label": "make", "kind": 12, "tags": [], "detail": "(int, 'a) => array<'a>", - "documentation": {"kind": "markdown", "value": " [Array.make n x] returns a fresh array of length [n],\n initialized with [x].\n All the elements of this new array are initially\n physically equal to [x] (in the sense of the [==] predicate).\n Consequently, if [x] is mutable, it is shared among all elements\n of the array, and modifying [x] through one of the array entries\n will modify all other entries at the same time.\n\n Raise [Invalid_argument] if [n < 0] or [n > Sys.max_array_length].\n If the value of [x] is a floating-point number, then the maximum\n size is only [Sys.max_array_length / 2]."} + "documentation": {"kind": "markdown", "value": " [Array.make n x] returns a fresh array of length [n],\n initialized with [x].\n All the elements of this new array are initially\n physically equal to [x] (in the sense of the [==] predicate).\n Consequently, if [x] is mutable, it is shared among all elements\n of the array, and modifying [x] through one of the array entries\n will modify all other entries at the same time.\n\n Raise [Invalid_argument] if [n < 0] or [n > Sys.max_array_length].\n If the value of [x] is a floating-point number, then the maximum\n size is only [Sys.max_array_length / 2]."}, + "sortText": null }, { "label": "make_float", "kind": 12, "tags": [], "detail": "int => array", - "documentation": {"kind": "markdown", "value": " @deprecated [Array.make_float] is an alias for {!Array.create_float}. "} + "documentation": {"kind": "markdown", "value": " @deprecated [Array.make_float] is an alias for {!Array.create_float}. "}, + "sortText": null }, { "label": "fold_right", "kind": 12, "tags": [], "detail": "(('b, 'a) => 'a, array<'b>, 'a) => 'a", - "documentation": {"kind": "markdown", "value": " [Array.fold_right f a x] computes\n [f a.(0) (f a.(1) ( ... (f a.(n-1) x) ...))],\n where [n] is the length of the array [a]. "} + "documentation": {"kind": "markdown", "value": " [Array.fold_right f a x] computes\n [f a.(0) (f a.(1) ( ... (f a.(n-1) x) ...))],\n where [n] is the length of the array [a]. "}, + "sortText": null }, { "label": "sort", "kind": 12, "tags": [], "detail": "(('a, 'a) => int, array<'a>) => unit", - "documentation": {"kind": "markdown", "value": " Sort an array in increasing order according to a comparison\n function. The comparison function must return 0 if its arguments\n compare as equal, a positive integer if the first is greater,\n and a negative integer if the first is smaller (see below for a\n complete specification). For example, {!Pervasives.compare} is\n a suitable comparison function, provided there are no floating-point\n NaN values in the data. After calling [Array.sort], the\n array is sorted in place in increasing order.\n [Array.sort] is guaranteed to run in constant heap space\n and (at most) logarithmic stack space.\n\n The current implementation uses Heap Sort. It runs in constant\n stack space.\n\n Specification of the comparison function:\n Let [a] be the array and [cmp] the comparison function. The following\n must be true for all x, y, z in a :\n- [cmp x y] > 0 if and only if [cmp y x] < 0\n- if [cmp x y] >= 0 and [cmp y z] >= 0 then [cmp x z] >= 0\n\n When [Array.sort] returns, [a] contains the same elements as before,\n reordered in such a way that for all i and j valid indices of [a] :\n- [cmp a.(i) a.(j)] >= 0 if and only if i >= j\n"} + "documentation": {"kind": "markdown", "value": " Sort an array in increasing order according to a comparison\n function. The comparison function must return 0 if its arguments\n compare as equal, a positive integer if the first is greater,\n and a negative integer if the first is smaller (see below for a\n complete specification). For example, {!Pervasives.compare} is\n a suitable comparison function, provided there are no floating-point\n NaN values in the data. After calling [Array.sort], the\n array is sorted in place in increasing order.\n [Array.sort] is guaranteed to run in constant heap space\n and (at most) logarithmic stack space.\n\n The current implementation uses Heap Sort. It runs in constant\n stack space.\n\n Specification of the comparison function:\n Let [a] be the array and [cmp] the comparison function. The following\n must be true for all x, y, z in a :\n- [cmp x y] > 0 if and only if [cmp y x] < 0\n- if [cmp x y] >= 0 and [cmp y z] >= 0 then [cmp x z] >= 0\n\n When [Array.sort] returns, [a] contains the same elements as before,\n reordered in such a way that for all i and j valid indices of [a] :\n- [cmp a.(i) a.(j)] >= 0 if and only if i >= j\n"}, + "sortText": null }, { "label": "length", "kind": 12, "tags": [], "detail": "array<'a> => int", - "documentation": {"kind": "markdown", "value": " Return the length (number of elements) of the given array. "} + "documentation": {"kind": "markdown", "value": " Return the length (number of elements) of the given array. "}, + "sortText": null }, { "label": "sub", "kind": 12, "tags": [], "detail": "(array<'a>, int, int) => array<'a>", - "documentation": {"kind": "markdown", "value": " [Array.sub a start len] returns a fresh array of length [len],\n containing the elements number [start] to [start + len - 1]\n of array [a].\n\n Raise [Invalid_argument \"Array.sub\"] if [start] and [len] do not\n designate a valid subarray of [a]; that is, if\n [start < 0], or [len < 0], or [start + len > Array.length a]. "} + "documentation": {"kind": "markdown", "value": " [Array.sub a start len] returns a fresh array of length [len],\n containing the elements number [start] to [start + len - 1]\n of array [a].\n\n Raise [Invalid_argument \"Array.sub\"] if [start] and [len] do not\n designate a valid subarray of [a]; that is, if\n [start < 0], or [len < 0], or [start + len > Array.length a]. "}, + "sortText": null }, { "label": "of_list", "kind": 12, "tags": [], "detail": "list<'a> => array<'a>", - "documentation": {"kind": "markdown", "value": " [Array.of_list l] returns a fresh array containing the elements\n of [l]. "} + "documentation": {"kind": "markdown", "value": " [Array.of_list l] returns a fresh array containing the elements\n of [l]. "}, + "sortText": null }, { "label": "iter", "kind": 12, "tags": [], "detail": "('a => unit, array<'a>) => unit", - "documentation": {"kind": "markdown", "value": " [Array.iter f a] applies function [f] in turn to all\n the elements of [a]. It is equivalent to\n [f a.(0); f a.(1); ...; f a.(Array.length a - 1); ()]. "} + "documentation": {"kind": "markdown", "value": " [Array.iter f a] applies function [f] in turn to all\n the elements of [a]. It is equivalent to\n [f a.(0); f a.(1); ...; f a.(Array.length a - 1); ()]. "}, + "sortText": null }, { "label": "map", "kind": 12, "tags": [], "detail": "('a => 'b, array<'a>) => array<'b>", - "documentation": {"kind": "markdown", "value": " [Array.map f a] applies function [f] to all the elements of [a],\n and builds an array with the results returned by [f]:\n [[| f a.(0); f a.(1); ...; f a.(Array.length a - 1) |]]. "} + "documentation": {"kind": "markdown", "value": " [Array.map f a] applies function [f] to all the elements of [a],\n and builds an array with the results returned by [f]:\n [[| f a.(0); f a.(1); ...; f a.(Array.length a - 1) |]]. "}, + "sortText": null }, { "label": "unsafe_get", "kind": 12, "tags": [], "detail": "(array<'a>, int) => 'a", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "make_matrix", "kind": 12, "tags": [], "detail": "(int, int, 'a) => array>", - "documentation": {"kind": "markdown", "value": " [Array.make_matrix dimx dimy e] returns a two-dimensional array\n (an array of arrays) with first dimension [dimx] and\n second dimension [dimy]. All the elements of this new matrix\n are initially physically equal to [e].\n The element ([x,y]) of a matrix [m] is accessed\n with the notation [m.(x).(y)].\n\n Raise [Invalid_argument] if [dimx] or [dimy] is negative or\n greater than {!Sys.max_array_length}.\n If the value of [e] is a floating-point number, then the maximum\n size is only [Sys.max_array_length / 2]. "} + "documentation": {"kind": "markdown", "value": " [Array.make_matrix dimx dimy e] returns a two-dimensional array\n (an array of arrays) with first dimension [dimx] and\n second dimension [dimy]. All the elements of this new matrix\n are initially physically equal to [e].\n The element ([x,y]) of a matrix [m] is accessed\n with the notation [m.(x).(y)].\n\n Raise [Invalid_argument] if [dimx] or [dimy] is negative or\n greater than {!Sys.max_array_length}.\n If the value of [e] is a floating-point number, then the maximum\n size is only [Sys.max_array_length / 2]. "}, + "sortText": null }, { "label": "mem", "kind": 12, "tags": [], "detail": "('a, array<'a>) => bool", - "documentation": {"kind": "markdown", "value": " [mem a l] is true if and only if [a] is equal\n to an element of [l].\n @since 4.03.0 "} + "documentation": {"kind": "markdown", "value": " [mem a l] is true if and only if [a] is equal\n to an element of [l].\n @since 4.03.0 "}, + "sortText": null }, { "label": "get", "kind": 12, "tags": [], "detail": "(array<'a>, int) => 'a", - "documentation": {"kind": "markdown", "value": " [Array.get a n] returns the element number [n] of array [a].\n The first element has number 0.\n The last element has number [Array.length a - 1].\n You can also write [a.(n)] instead of [Array.get a n].\n\n Raise [Invalid_argument \"index out of bounds\"]\n if [n] is outside the range 0 to [(Array.length a - 1)]. "} + "documentation": {"kind": "markdown", "value": " [Array.get a n] returns the element number [n] of array [a].\n The first element has number 0.\n The last element has number [Array.length a - 1].\n You can also write [a.(n)] instead of [Array.get a n].\n\n Raise [Invalid_argument \"index out of bounds\"]\n if [n] is outside the range 0 to [(Array.length a - 1)]. "}, + "sortText": null }, { "label": "append", "kind": 12, "tags": [], "detail": "(array<'a>, array<'a>) => array<'a>", - "documentation": {"kind": "markdown", "value": " [Array.append v1 v2] returns a fresh array containing the\n concatenation of the arrays [v1] and [v2]. "} + "documentation": {"kind": "markdown", "value": " [Array.append v1 v2] returns a fresh array containing the\n concatenation of the arrays [v1] and [v2]. "}, + "sortText": null }, { "label": "unsafe_set", "kind": 12, "tags": [], "detail": "(array<'a>, int, 'a) => unit", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "create_matrix", "kind": 12, "tags": [], "detail": "(int, int, 'a) => array>", - "documentation": {"kind": "markdown", "value": " @deprecated [Array.create_matrix] is an alias for {!Array.make_matrix}. "} + "documentation": {"kind": "markdown", "value": " @deprecated [Array.create_matrix] is an alias for {!Array.make_matrix}. "}, + "sortText": null }, { "label": "create_float", "kind": 12, "tags": [], "detail": "int => array", - "documentation": {"kind": "markdown", "value": " [Array.create_float n] returns a fresh float array of length [n],\n with uninitialized data.\n @since 4.03 "} + "documentation": {"kind": "markdown", "value": " [Array.create_float n] returns a fresh float array of length [n],\n with uninitialized data.\n @since 4.03 "}, + "sortText": null }, { "label": "create", "kind": 12, "tags": [], "detail": "(int, 'a) => array<'a>", - "documentation": {"kind": "markdown", "value": " @deprecated [Array.create] is an alias for {!Array.make}. "} + "documentation": {"kind": "markdown", "value": " @deprecated [Array.create] is an alias for {!Array.make}. "}, + "sortText": null }, { "label": "init", "kind": 12, "tags": [], "detail": "(int, int => 'a) => array<'a>", - "documentation": {"kind": "markdown", "value": " [Array.init n f] returns a fresh array of length [n],\n with element number [i] initialized to the result of [f i].\n In other terms, [Array.init n f] tabulates the results of [f]\n applied to the integers [0] to [n-1].\n\n Raise [Invalid_argument] if [n < 0] or [n > Sys.max_array_length].\n If the return type of [f] is [float], then the maximum\n size is only [Sys.max_array_length / 2]."} + "documentation": {"kind": "markdown", "value": " [Array.init n f] returns a fresh array of length [n],\n with element number [i] initialized to the result of [f i].\n In other terms, [Array.init n f] tabulates the results of [f]\n applied to the integers [0] to [n-1].\n\n Raise [Invalid_argument] if [n < 0] or [n > Sys.max_array_length].\n If the return type of [f] is [float], then the maximum\n size is only [Sys.max_array_length / 2]."}, + "sortText": null }, { "label": "fast_sort", "kind": 12, "tags": [], "detail": "(('a, 'a) => int, array<'a>) => unit", - "documentation": {"kind": "markdown", "value": " Same as {!Array.sort} or {!Array.stable_sort}, whichever is faster\n on typical input.\n"} + "documentation": {"kind": "markdown", "value": " Same as {!Array.sort} or {!Array.stable_sort}, whichever is faster\n on typical input.\n"}, + "sortText": null }, { "label": "fill", "kind": 12, "tags": [], "detail": "(array<'a>, int, int, 'a) => unit", - "documentation": {"kind": "markdown", "value": " [Array.fill a ofs len x] modifies the array [a] in place,\n storing [x] in elements number [ofs] to [ofs + len - 1].\n\n Raise [Invalid_argument \"Array.fill\"] if [ofs] and [len] do not\n designate a valid subarray of [a]. "} + "documentation": {"kind": "markdown", "value": " [Array.fill a ofs len x] modifies the array [a] in place,\n storing [x] in elements number [ofs] to [ofs + len - 1].\n\n Raise [Invalid_argument \"Array.fill\"] if [ofs] and [len] do not\n designate a valid subarray of [a]. "}, + "sortText": null }, { "label": "blit", "kind": 12, "tags": [], "detail": "(array<'a>, int, array<'a>, int, int) => unit", - "documentation": {"kind": "markdown", "value": " [Array.blit v1 o1 v2 o2 len] copies [len] elements\n from array [v1], starting at element number [o1], to array [v2],\n starting at element number [o2]. It works correctly even if\n [v1] and [v2] are the same array, and the source and\n destination chunks overlap.\n\n Raise [Invalid_argument \"Array.blit\"] if [o1] and [len] do not\n designate a valid subarray of [v1], or if [o2] and [len] do not\n designate a valid subarray of [v2]. "} + "documentation": {"kind": "markdown", "value": " [Array.blit v1 o1 v2 o2 len] copies [len] elements\n from array [v1], starting at element number [o1], to array [v2],\n starting at element number [o2]. It works correctly even if\n [v1] and [v2] are the same array, and the source and\n destination chunks overlap.\n\n Raise [Invalid_argument \"Array.blit\"] if [o1] and [len] do not\n designate a valid subarray of [v1], or if [o2] and [len] do not\n designate a valid subarray of [v2]. "}, + "sortText": null }, { "label": "Floatarray", "kind": 9, "tags": [], "detail": "module", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 5:10 @@ -301,49 +348,57 @@ Completable: Cpath Value[Array, m] "kind": 12, "tags": [], "detail": "((int, 'a) => 'b, array<'a>) => array<'b>", - "documentation": {"kind": "markdown", "value": " Same as {!Array.map}, but the\n function is applied to the index of the element as first argument,\n and the element itself as second argument. "} + "documentation": {"kind": "markdown", "value": " Same as {!Array.map}, but the\n function is applied to the index of the element as first argument,\n and the element itself as second argument. "}, + "sortText": null }, { "label": "memq", "kind": 12, "tags": [], "detail": "('a, array<'a>) => bool", - "documentation": {"kind": "markdown", "value": " Same as {!Array.mem}, but uses physical equality instead of structural\n equality to compare array elements.\n @since 4.03.0 "} + "documentation": {"kind": "markdown", "value": " Same as {!Array.mem}, but uses physical equality instead of structural\n equality to compare array elements.\n @since 4.03.0 "}, + "sortText": null }, { "label": "map2", "kind": 12, "tags": [], "detail": "(('a, 'b) => 'c, array<'a>, array<'b>) => array<'c>", - "documentation": {"kind": "markdown", "value": " [Array.map2 f a b] applies function [f] to all the elements of [a]\n and [b], and builds an array with the results returned by [f]:\n [[| f a.(0) b.(0); ...; f a.(Array.length a - 1) b.(Array.length b - 1)|]].\n Raise [Invalid_argument] if the arrays are not the same size.\n @since 4.03.0 "} + "documentation": {"kind": "markdown", "value": " [Array.map2 f a b] applies function [f] to all the elements of [a]\n and [b], and builds an array with the results returned by [f]:\n [[| f a.(0) b.(0); ...; f a.(Array.length a - 1) b.(Array.length b - 1)|]].\n Raise [Invalid_argument] if the arrays are not the same size.\n @since 4.03.0 "}, + "sortText": null }, { "label": "make", "kind": 12, "tags": [], "detail": "(int, 'a) => array<'a>", - "documentation": {"kind": "markdown", "value": " [Array.make n x] returns a fresh array of length [n],\n initialized with [x].\n All the elements of this new array are initially\n physically equal to [x] (in the sense of the [==] predicate).\n Consequently, if [x] is mutable, it is shared among all elements\n of the array, and modifying [x] through one of the array entries\n will modify all other entries at the same time.\n\n Raise [Invalid_argument] if [n < 0] or [n > Sys.max_array_length].\n If the value of [x] is a floating-point number, then the maximum\n size is only [Sys.max_array_length / 2]."} + "documentation": {"kind": "markdown", "value": " [Array.make n x] returns a fresh array of length [n],\n initialized with [x].\n All the elements of this new array are initially\n physically equal to [x] (in the sense of the [==] predicate).\n Consequently, if [x] is mutable, it is shared among all elements\n of the array, and modifying [x] through one of the array entries\n will modify all other entries at the same time.\n\n Raise [Invalid_argument] if [n < 0] or [n > Sys.max_array_length].\n If the value of [x] is a floating-point number, then the maximum\n size is only [Sys.max_array_length / 2]."}, + "sortText": null }, { "label": "make_float", "kind": 12, "tags": [], "detail": "int => array", - "documentation": {"kind": "markdown", "value": " @deprecated [Array.make_float] is an alias for {!Array.create_float}. "} + "documentation": {"kind": "markdown", "value": " @deprecated [Array.make_float] is an alias for {!Array.create_float}. "}, + "sortText": null }, { "label": "map", "kind": 12, "tags": [], "detail": "('a => 'b, array<'a>) => array<'b>", - "documentation": {"kind": "markdown", "value": " [Array.map f a] applies function [f] to all the elements of [a],\n and builds an array with the results returned by [f]:\n [[| f a.(0); f a.(1); ...; f a.(Array.length a - 1) |]]. "} + "documentation": {"kind": "markdown", "value": " [Array.map f a] applies function [f] to all the elements of [a],\n and builds an array with the results returned by [f]:\n [[| f a.(0); f a.(1); ...; f a.(Array.length a - 1) |]]. "}, + "sortText": null }, { "label": "make_matrix", "kind": 12, "tags": [], "detail": "(int, int, 'a) => array>", - "documentation": {"kind": "markdown", "value": " [Array.make_matrix dimx dimy e] returns a two-dimensional array\n (an array of arrays) with first dimension [dimx] and\n second dimension [dimy]. All the elements of this new matrix\n are initially physically equal to [e].\n The element ([x,y]) of a matrix [m] is accessed\n with the notation [m.(x).(y)].\n\n Raise [Invalid_argument] if [dimx] or [dimy] is negative or\n greater than {!Sys.max_array_length}.\n If the value of [e] is a floating-point number, then the maximum\n size is only [Sys.max_array_length / 2]. "} + "documentation": {"kind": "markdown", "value": " [Array.make_matrix dimx dimy e] returns a two-dimensional array\n (an array of arrays) with first dimension [dimx] and\n second dimension [dimy]. All the elements of this new matrix\n are initially physically equal to [e].\n The element ([x,y]) of a matrix [m] is accessed\n with the notation [m.(x).(y)].\n\n Raise [Invalid_argument] if [dimx] or [dimy] is negative or\n greater than {!Sys.max_array_length}.\n If the value of [e] is a floating-point number, then the maximum\n size is only [Sys.max_array_length / 2]. "}, + "sortText": null }, { "label": "mem", "kind": 12, "tags": [], "detail": "('a, array<'a>) => bool", - "documentation": {"kind": "markdown", "value": " [mem a l] is true if and only if [a] is equal\n to an element of [l].\n @since 4.03.0 "} + "documentation": {"kind": "markdown", "value": " [mem a l] is true if and only if [a] is equal\n to an element of [l].\n @since 4.03.0 "}, + "sortText": null }] Complete src/Completion.res 15:17 @@ -355,7 +410,8 @@ Completable: Cpath Value[Dep, c] "kind": 12, "tags": [1], "detail": "int => int", - "documentation": {"kind": "markdown", "value": "Deprecated: Use customDouble instead\n\nSome doc comment"} + "documentation": {"kind": "markdown", "value": "Deprecated: Use customDouble instead\n\nSome doc comment"}, + "sortText": null }] Complete src/Completion.res 23:20 @@ -368,13 +424,15 @@ Found type for function (~age: int, ~name: string) => string "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "name", "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 26:13 @@ -385,13 +443,15 @@ Completable: Cpath array->m "kind": 12, "tags": [], "detail": "(t<'a>, ('a, int) => 'b) => t<'b>", - "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The function acceps two arguments: an item from the array and its\nindex number. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\n// multiply each item in array by its position\nlet product = (item, index) => item * index\nJs.Array2.mapi([10, 11, 12], product) == [0, 11, 24]\n```\n"} + "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The function acceps two arguments: an item from the array and its\nindex number. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\n// multiply each item in array by its position\nlet product = (item, index) => item * index\nJs.Array2.mapi([10, 11, 12], product) == [0, 11, 24]\n```\n"}, + "sortText": null }, { "label": "Js.Array2.map", "kind": 12, "tags": [], "detail": "(t<'a>, 'a => 'b) => t<'b>", - "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\nJs.Array2.map([12, 4, 8], x => x * x) == [144, 16, 64]\nJs.Array2.map([\"animal\", \"vegetable\", \"mineral\"], Js.String.length) == [6, 9, 7]\n```\n"} + "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\nJs.Array2.map([12, 4, 8], x => x * x) == [144, 16, 64]\nJs.Array2.map([\"animal\", \"vegetable\", \"mineral\"], Js.String.length) == [6, 9, 7]\n```\n"}, + "sortText": null }] Complete src/Completion.res 29:13 @@ -402,7 +462,8 @@ Completable: Cpath string->toU "kind": 12, "tags": [], "detail": "t => t", - "documentation": {"kind": "markdown", "value": "\n`toUpperCase(str)` converts `str` to upper case using the locale-insensitive\ncase mappings in the Unicode Character Database. Notice that the conversion can\nexpand the number of letters in the result; for example the German ß\ncapitalizes to two Ses in a row.\n\nSee [`String.toUpperCase`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase)\non MDN.\n\n```res example\nJs.String2.toUpperCase(\"abc\") == \"ABC\"\nJs.String2.toUpperCase(`Straße`) == `STRASSE`\nJs.String2.toUpperCase(`πς`) == `ΠΣ`\n```\n"} + "documentation": {"kind": "markdown", "value": "\n`toUpperCase(str)` converts `str` to upper case using the locale-insensitive\ncase mappings in the Unicode Character Database. Notice that the conversion can\nexpand the number of letters in the result; for example the German ß\ncapitalizes to two Ses in a row.\n\nSee [`String.toUpperCase`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase)\non MDN.\n\n```res example\nJs.String2.toUpperCase(\"abc\") == \"ABC\"\nJs.String2.toUpperCase(`Straße`) == `STRASSE`\nJs.String2.toUpperCase(`πς`) == `ΠΣ`\n```\n"}, + "sortText": null }] Complete src/Completion.res 34:8 @@ -413,13 +474,15 @@ Completable: Cpath Value[op]->e "kind": 12, "tags": [], "detail": "(option<'a>, option<'b>, (. 'a, 'b) => bool) => bool", - "documentation": {"kind": "markdown", "value": "\n Uncurried version of `eq`\n"} + "documentation": {"kind": "markdown", "value": "\n Uncurried version of `eq`\n"}, + "sortText": null }, { "label": "Belt.Option.eq", "kind": 12, "tags": [], "detail": "(option<'a>, option<'b>, ('a, 'b) => bool) => bool", - "documentation": {"kind": "markdown", "value": "\n Evaluates two optional values for equality with respect to a predicate\n function. If both `optValue1` and `optValue2` are `None`, returns `true`.\n If one of the arguments is `Some(value)` and the other is `None`, returns\n `false`.\n\n If arguments are `Some(value1)` and `Some(value2)`, returns the result of\n `predicate(value1, value2)`; the predicate function must return a bool.\n\n ```res example\n let clockEqual = (a, b) => mod(a, 12) == mod(b, 12)\n\n open Belt.Option\n\n eq(Some(3), Some(15), clockEqual) /* true */\n\n eq(Some(3), None, clockEqual) /* false */\n\n eq(None, Some(3), clockEqual) /* false */\n\n eq(None, None, clockEqual) /* true */\n ```\n"} + "documentation": {"kind": "markdown", "value": "\n Evaluates two optional values for equality with respect to a predicate\n function. If both `optValue1` and `optValue2` are `None`, returns `true`.\n If one of the arguments is `Some(value)` and the other is `None`, returns\n `false`.\n\n If arguments are `Some(value1)` and `Some(value2)`, returns the result of\n `predicate(value1, value2)`; the predicate function must return a bool.\n\n ```res example\n let clockEqual = (a, b) => mod(a, 12) == mod(b, 12)\n\n open Belt.Option\n\n eq(Some(3), Some(15), clockEqual) /* true */\n\n eq(Some(3), None, clockEqual) /* false */\n\n eq(None, Some(3), clockEqual) /* false */\n\n eq(None, None, clockEqual) /* true */\n ```\n"}, + "sortText": null }] Complete src/Completion.res 44:7 @@ -432,13 +495,15 @@ Completable: Cpath Value[fa]-> "kind": 12, "tags": [], "detail": "(t, int) => t", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "ForAuto.abd", "kind": 12, "tags": [], "detail": "(t, int) => t", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 47:21 @@ -451,13 +516,15 @@ Completable: Cpath Value[Js, Dict, u] "kind": 12, "tags": [], "detail": "(t<'a>, key) => 'a", - "documentation": {"kind": "markdown", "value": "\n`Js.Dict.unsafeGet(key)` returns the value if the key exists, otherwise an `undefined` value is returned. Use this only when you are sure the key exists (i.e. when having used the `keys()` function to check that the key is valid).\n\n```res example\nJs.Dict.unsafeGet(ages, \"Fred\") == 49\nJs.Dict.unsafeGet(ages, \"Paul\") // returns undefined\n```\n"} + "documentation": {"kind": "markdown", "value": "\n`Js.Dict.unsafeGet(key)` returns the value if the key exists, otherwise an `undefined` value is returned. Use this only when you are sure the key exists (i.e. when having used the `keys()` function to check that the key is valid).\n\n```res example\nJs.Dict.unsafeGet(ages, \"Fred\") == 49\nJs.Dict.unsafeGet(ages, \"Paul\") // returns undefined\n```\n"}, + "sortText": null }, { "label": "unsafeDeleteKey", "kind": 12, "tags": [], "detail": "(. t, string) => unit", - "documentation": {"kind": "markdown", "value": " Experimental internal function "} + "documentation": {"kind": "markdown", "value": " Experimental internal function "}, + "sortText": null }] Complete src/Completion.res 59:30 @@ -471,7 +538,8 @@ Completable: Cpath Value[z] "kind": 12, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 62:23 @@ -483,7 +551,8 @@ Completable: Cjsx([O, Comp], z, [z]) "kind": 4, "tags": [], "detail": "option", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 65:8 @@ -494,7 +563,8 @@ Completable: Cdecorator(reac) "kind": 4, "tags": [], "detail": "", - "documentation": {"kind": "markdown", "value": "The `@react.component` decorator is used to annotate functions that are RescriptReact components.\n\nYou will need this decorator whenever you want to use a ReScript / React component in ReScript JSX expressions.\n\nNote: The `@react.component` decorator requires the react-jsx config to be set in your `bsconfig.json` to enable the required React transformations.\n\n[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#react-component-decorator)."} + "documentation": {"kind": "markdown", "value": "The `@react.component` decorator is used to annotate functions that are RescriptReact components.\n\nYou will need this decorator whenever you want to use a ReScript / React component in ReScript JSX expressions.\n\nNote: The `@react.component` decorator requires the react-jsx config to be set in your `bsconfig.json` to enable the required React transformations.\n\n[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#react-component-decorator)."}, + "sortText": null }] Complete src/Completion.res 68:10 @@ -507,7 +577,8 @@ Completable: Cdecorator(react.) "kind": 4, "tags": [], "detail": "", - "documentation": {"kind": "markdown", "value": "The `@react.component` decorator is used to annotate functions that are RescriptReact components.\n\nYou will need this decorator whenever you want to use a ReScript / React component in ReScript JSX expressions.\n\nNote: The `@react.component` decorator requires the react-jsx config to be set in your `bsconfig.json` to enable the required React transformations.\n\n[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#react-component-decorator)."} + "documentation": {"kind": "markdown", "value": "The `@react.component` decorator is used to annotate functions that are RescriptReact components.\n\nYou will need this decorator whenever you want to use a ReScript / React component in ReScript JSX expressions.\n\nNote: The `@react.component` decorator requires the react-jsx config to be set in your `bsconfig.json` to enable the required React transformations.\n\n[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#react-component-decorator)."}, + "sortText": null }] Complete src/Completion.res 71:27 @@ -520,7 +591,8 @@ Found type for function (~age: int, ~name: string) => string "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 74:26 @@ -533,7 +605,8 @@ Found type for function (~age: int, ~name: string) => string "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 77:32 @@ -546,7 +619,8 @@ Found type for function (~age: int, ~name: string) => string "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 82:5 @@ -565,7 +639,8 @@ Completable: Cpath Value[someObj]["a"] "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 95:24 @@ -577,13 +652,15 @@ Completable: Cpath Value[nestedObj]["x"]["y"][""] "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "name", "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 99:7 @@ -595,7 +672,8 @@ Completable: Cpath Value[o]["a"] "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 104:17 @@ -607,13 +685,15 @@ Completable: Cpath Value[no]["x"]["y"][""] "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "age", "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 110:5 @@ -625,13 +705,15 @@ Completable: Cpath Value[r]."" "kind": 5, "tags": [], "detail": "x: int\n\ntype r = {x: int, y: string}", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "y", "kind": 5, "tags": [], "detail": "y: string\n\ntype r = {x: int, y: string}", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 113:24 @@ -643,13 +725,15 @@ Completable: Cpath Value[Object, Rec, recordVal]."" "kind": 5, "tags": [], "detail": "xx: int\n\ntype recordt = {xx: int, ss: string}", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "ss", "kind": 5, "tags": [], "detail": "ss: string\n\ntype recordt = {xx: int, ss: string}", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 120:7 @@ -663,7 +747,8 @@ Completable: Cpath Value[my] "kind": 12, "tags": [], "detail": "(int, int) => int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 125:18 @@ -675,13 +760,15 @@ Completable: Cpath Value[Object, object][""] "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "age", "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 151:6 @@ -693,7 +780,8 @@ Completable: Cpath Module[O, ""] "kind": 9, "tags": [], "detail": "module", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 157:8 @@ -705,13 +793,15 @@ Completable: Cpath Value[q].aa."" "kind": 5, "tags": [], "detail": "x: int\n\ntype aa = {x: int, name: string}", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "name", "kind": 5, "tags": [], "detail": "name: string\n\ntype aa = {x: int, name: string}", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 159:9 @@ -723,7 +813,8 @@ Completable: Cpath Value[q].aa.n "kind": 5, "tags": [], "detail": "name: string\n\ntype aa = {x: int, name: string}", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 162:6 @@ -735,13 +826,15 @@ Completable: Cpath Value[Lis] "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "ListLabels", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 169:16 @@ -753,7 +846,8 @@ Completable: Cpath Module[WithChildren] "kind": 9, "tags": [], "detail": "module", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 172:16 @@ -765,19 +859,22 @@ Completable: Cpath Type[Js, n] "kind": 22, "tags": [], "detail": "type null_undefined<'a> = nullable<'a>", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "nullable", "kind": 22, "tags": [], "detail": "type nullable<+'a>", - "documentation": {"kind": "markdown", "value": "\n A value of this type can be undefined, null or 'a. This type is equivalent to Js.Null_undefined.t.\n"} + "documentation": {"kind": "markdown", "value": "\n A value of this type can be undefined, null or 'a. This type is equivalent to Js.Null_undefined.t.\n"}, + "sortText": null }, { "label": "null", "kind": 22, "tags": [], "detail": "type null<+'a>", - "documentation": {"kind": "markdown", "value": "\n Nullable value of this type can be either null or 'a. This type is equivalent to Js.Null.t.\n"} + "documentation": {"kind": "markdown", "value": "\n Nullable value of this type can be either null or 'a. This type is equivalent to Js.Null.t.\n"}, + "sortText": null }] Complete src/Completion.res 174:20 @@ -789,7 +886,8 @@ Completable: Cpath Type[ForAuto, ""] "kind": 22, "tags": [], "detail": "type t = int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 179:13 @@ -806,7 +904,8 @@ Completable: Cpath Module[For] "kind": 9, "tags": [], "detail": "module", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 190:11 @@ -818,7 +917,8 @@ Completable: Cpath Value[Private, ""] "kind": 12, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 202:6 @@ -836,7 +936,8 @@ Completable: Cpath Value[sha] "kind": 12, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 208:6 @@ -848,7 +949,8 @@ Completable: Cpath Value[sha] "kind": 12, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 221:22 @@ -860,13 +962,15 @@ Completable: Cpath Value[FAO, forAutoObject][""] "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "forAutoLabel", "kind": 4, "tags": [], "detail": "FAR.forAutoRecord", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 224:37 @@ -878,13 +982,15 @@ Completable: Cpath Value[FAO, forAutoObject]["forAutoLabel"]."" "kind": 5, "tags": [], "detail": "forAuto: ForAuto.t\n\ntype forAutoRecord = {\n forAuto: ForAuto.t,\n something: option,\n}", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "something", "kind": 5, "tags": [], "detail": "something: option\n\ntype forAutoRecord = {\n forAuto: ForAuto.t,\n something: option,\n}", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 227:46 @@ -895,13 +1001,15 @@ Completable: Cpath Value[FAO, forAutoObject]["forAutoLabel"].forAuto-> "kind": 12, "tags": [], "detail": "(t, int) => t", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "ForAuto.abd", "kind": 12, "tags": [], "detail": "(t, int) => t", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 230:55 @@ -914,13 +1022,15 @@ Completable: Cpath Value[ForAuto, a] "kind": 12, "tags": [], "detail": "(t, int) => t", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "abd", "kind": 12, "tags": [], "detail": "(t, int) => t", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 234:34 @@ -936,7 +1046,8 @@ Completable: Cpath Value[na] "kind": 12, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 237:17 @@ -956,13 +1067,15 @@ Completable: Cpath Value[_z]."" "kind": 5, "tags": [], "detail": "x: int\n\ntype r = {x: int, y: string}", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "y", "kind": 5, "tags": [], "detail": "y: string\n\ntype r = {x: int, y: string}", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 254:17 @@ -974,7 +1087,8 @@ Completable: Cpath Value[SomeLo] "kind": 9, "tags": [], "detail": "module", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 256:29 @@ -986,7 +1100,8 @@ Completable: Cpath Type[SomeLocalModule, ""] "kind": 22, "tags": [], "detail": "type zz = int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 261:33 @@ -998,7 +1113,8 @@ Completable: Cpath Type[SomeLocalModule, ""] "kind": 22, "tags": [], "detail": "type zz = int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 268:21 @@ -1009,7 +1125,8 @@ Completable: Cpath Value[SomeLocal] "kind": 9, "tags": [], "detail": "module", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 271:20 @@ -1022,7 +1139,8 @@ Completable: Cpath Type[SomeLocal] "kind": 9, "tags": [], "detail": "module", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 275:15 @@ -1036,7 +1154,8 @@ Completable: Cpath Value[_w] "kind": 12, "tags": [], "detail": "'a", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 281:22 @@ -1048,13 +1167,15 @@ Completable: Cpath Type[s] "kind": 22, "tags": [], "detail": "type someType = {hello: string}", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "someLocalVariant", "kind": 22, "tags": [], "detail": "type someLocalVariant = SomeLocalVariantItem", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 291:30 @@ -1067,7 +1188,8 @@ Found type for function (~name: string) => unit "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 296:11 @@ -1079,13 +1201,15 @@ Completable: Cpath Value[retAA](Nolabel)."" "kind": 5, "tags": [], "detail": "x: int\n\ntype aa = {x: int, name: string}", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "name", "kind": 5, "tags": [], "detail": "name: string\n\ntype aa = {x: int, name: string}", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 301:13 @@ -1105,25 +1229,29 @@ Found type for function ( "kind": 4, "tags": [], "detail": "option", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "a", "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "b", "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "opt2", "kind": 4, "tags": [], "detail": "option", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 304:15 @@ -1136,19 +1264,22 @@ Found type for function (~a: int, ~b: int, ~opt2: int=?, unit) => int "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "b", "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "opt2", "kind": 4, "tags": [], "detail": "option", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 307:17 @@ -1161,19 +1292,22 @@ Found type for function (~a: int, ~b: int, ~opt2: int=?, unit) => int "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "b", "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "opt2", "kind": 4, "tags": [], "detail": "option", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 310:21 @@ -1186,13 +1320,15 @@ Found type for function (~a: int, ~b: int) => int "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "b", "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 313:23 @@ -1205,13 +1341,15 @@ Found type for function (~a: int, ~opt2: int=?, unit) => int "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "opt2", "kind": 4, "tags": [], "detail": "option", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 316:16 @@ -1224,25 +1362,29 @@ Found type for function (~opt1: int=?, ~a: int, ~b: int, unit, unit, ~c: int) => "kind": 4, "tags": [], "detail": "option", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "a", "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "b", "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "c", "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 323:17 @@ -1255,13 +1397,15 @@ Found type for function (~b: int) => callback "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "a", "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 326:21 @@ -1274,7 +1418,8 @@ Found type for function (~b: int) => int "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 329:21 @@ -1287,7 +1432,8 @@ Found type for function (~a: int) => int "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 336:26 @@ -1306,13 +1452,15 @@ Completable: Cpath Type[Res] "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "RescriptReactRouter", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 343:57 @@ -1326,7 +1474,8 @@ Completable: Cpath Value[this] "kind": 12, "tags": [], "detail": "\\\"Type Not Known\"", - "documentation": null + "documentation": null, + "sortText": null }] Hover src/Completion.res 346:14 @@ -1397,13 +1546,15 @@ Completable: Cpath Value[ForAuto, ""] "kind": 12, "tags": [], "detail": "(t, int) => t", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "abd", "kind": 12, "tags": [], "detail": "(t, int) => t", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 381:38 @@ -1419,13 +1570,15 @@ Completable: Cpath Value[FAO, forAutoObject][""] "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "forAutoLabel", "kind": 4, "tags": [], "detail": "FAR.forAutoRecord", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 384:24 @@ -1441,13 +1594,15 @@ Completable: Cpath Value[funRecord]."" "kind": 5, "tags": [], "detail": "someFun: (~name: string) => unit\n\ntype funRecord = {\n someFun: (~name: string) => unit,\n stuff: string,\n}", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "stuff", "kind": 5, "tags": [], "detail": "stuff: string\n\ntype funRecord = {\n someFun: (~name: string) => unit,\n stuff: string,\n}", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 389:12 @@ -1461,13 +1616,15 @@ Completable: Cpath array->ma "kind": 12, "tags": [], "detail": "(t<'a>, ('a, int) => 'b) => t<'b>", - "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The function acceps two arguments: an item from the array and its\nindex number. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\n// multiply each item in array by its position\nlet product = (item, index) => item * index\nJs.Array2.mapi([10, 11, 12], product) == [0, 11, 24]\n```\n"} + "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The function acceps two arguments: an item from the array and its\nindex number. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\n// multiply each item in array by its position\nlet product = (item, index) => item * index\nJs.Array2.mapi([10, 11, 12], product) == [0, 11, 24]\n```\n"}, + "sortText": null }, { "label": "Array2.map", "kind": 12, "tags": [], "detail": "(t<'a>, 'a => 'b) => t<'b>", - "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\nJs.Array2.map([12, 4, 8], x => x * x) == [144, 16, 64]\nJs.Array2.map([\"animal\", \"vegetable\", \"mineral\"], Js.String.length) == [6, 9, 7]\n```\n"} + "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\nJs.Array2.map([12, 4, 8], x => x * x) == [144, 16, 64]\nJs.Array2.map([\"animal\", \"vegetable\", \"mineral\"], Js.String.length) == [6, 9, 7]\n```\n"}, + "sortText": null }] Complete src/Completion.res 397:14 @@ -1483,7 +1640,8 @@ Completable: Cpath Value[red] "kind": 12, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 402:25 @@ -1499,7 +1657,8 @@ Completable: Cpath Value[red] "kind": 12, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Completion.res 405:22 @@ -1515,18 +1674,21 @@ Completable: Cpath Value[r] "kind": 12, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "retAA", "kind": 12, "tags": [], "detail": "unit => aa", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "r", "kind": 12, "tags": [], "detail": "rAlias", - "documentation": null + "documentation": null, + "sortText": null }] diff --git a/analysis/tests/src/expected/Debug.res.txt b/analysis/tests/src/expected/Debug.res.txt index 78437d8c0..6da6f3fc0 100644 --- a/analysis/tests/src/expected/Debug.res.txt +++ b/analysis/tests/src/expected/Debug.res.txt @@ -88,13 +88,15 @@ findAllCompletions uri:js.ml "kind": 12, "tags": [], "detail": "('a, nullable<'a>) => bool", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "eqNull", "kind": 12, "tags": [], "detail": "('a, null<'a>) => bool", - "documentation": null + "documentation": null, + "sortText": null }] diff --git a/analysis/tests/src/expected/Div.res.txt b/analysis/tests/src/expected/Div.res.txt index aeb25d150..cc82a7263 100644 --- a/analysis/tests/src/expected/Div.res.txt +++ b/analysis/tests/src/expected/Div.res.txt @@ -11,6 +11,7 @@ Completable: Cjsx([div], dangerous, [dangerous]) "kind": 4, "tags": [], "detail": "{\"__html\": string}", - "documentation": null + "documentation": null, + "sortText": null }] diff --git a/analysis/tests/src/expected/Jsx.res.txt b/analysis/tests/src/expected/Jsx.res.txt index 8e2f1569c..6d5a9e9c0 100644 --- a/analysis/tests/src/expected/Jsx.res.txt +++ b/analysis/tests/src/expected/Jsx.res.txt @@ -20,13 +20,15 @@ Completable: Cjsx([M], f, [second, f]) "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "fun", "kind": 4, "tags": [], "detail": "option", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 14:13 @@ -38,25 +40,29 @@ Completable: Cpath Module[M] "kind": 9, "tags": [], "detail": "module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Map", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "MapLabels", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "MoreLabels", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 22:19 @@ -68,7 +74,8 @@ Completable: Cjsx([M], k, [prop, k]) "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 25:17 @@ -80,7 +87,8 @@ Completable: Cjsx([M], k, [prop, k]) "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 28:21 @@ -92,7 +100,8 @@ Completable: Cjsx([M], k, [prop, k]) "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 31:24 @@ -104,7 +113,8 @@ Completable: Cjsx([M], k, [prop, k]) "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 34:18 @@ -116,7 +126,8 @@ Completable: Cjsx([M], k, [prop, k]) "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 37:16 @@ -128,7 +139,8 @@ Completable: Cjsx([M], k, [prop, k]) "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 40:17 @@ -140,7 +152,8 @@ Completable: Cjsx([M], k, [prop, k]) "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 43:18 @@ -152,7 +165,8 @@ Completable: Cjsx([M], k, [prop, k]) "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 46:16 @@ -164,7 +178,8 @@ Completable: Cjsx([M], k, [prop, k]) "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 49:27 @@ -176,7 +191,8 @@ Completable: Cjsx([M], k, [prop, k]) "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 52:38 @@ -188,7 +204,8 @@ Completable: Cjsx([M], k, [prop, k]) "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 55:25 @@ -200,7 +217,8 @@ Completable: Cjsx([M], k, [prop, k]) "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Definition src/Jsx.res 58:11 @@ -217,7 +235,8 @@ Completable: Cjsx([Ext], al, [al]) "kind": 4, "tags": [], "detail": "option", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 71:11 @@ -235,7 +254,8 @@ Completable: Cjsx([M], k, [first, k]) "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 77:23 @@ -247,7 +267,8 @@ Completable: Cjsx([M], k, [first, k]) "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 80:6 @@ -270,7 +291,8 @@ Completable: Cpath Module[WithChildren] "kind": 9, "tags": [], "detail": "module", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 91:18 @@ -282,7 +304,8 @@ Completable: Cjsx([WithChildren], n, [n]) "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 94:18 @@ -295,7 +318,8 @@ Completable: Cpath Type[React, e] "kind": 22, "tags": [], "detail": "type element", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 96:20 @@ -308,7 +332,8 @@ Completable: Cpath Type[ReactDOMR] "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 102:21 @@ -328,7 +353,8 @@ Completable: Cpath Value[DefineSomeFields, ""] "kind": 12, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 108:36 @@ -342,13 +368,15 @@ Completable: Cpath Module[DefineSomeFields].th "kind": 5, "tags": [], "detail": "thisField: int\n\ntype r = {thisField: int, thatField: string}", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "thatField", "kind": 5, "tags": [], "detail": "thatField: string\n\ntype r = {thisField: int, thatField: string}", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 122:20 @@ -362,7 +390,8 @@ Completable: Cpath Value[Outer, Inner, h] "kind": 12, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 129:19 @@ -376,7 +405,8 @@ Completable: Cpath Value[Outer, Inner, ""] "kind": 12, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 136:7 @@ -393,7 +423,8 @@ Completable: Cpath Module[Nested, Co] "kind": 9, "tags": [], "detail": "module", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.res 153:19 @@ -405,7 +436,8 @@ Completable: Cpath Module[Nested, ""] "kind": 9, "tags": [], "detail": "module", - "documentation": null + "documentation": null, + "sortText": null }] Hover src/Jsx.res 162:12 @@ -440,24 +472,28 @@ Completable: Cjsx([Completion, O, Comp], "", []) "kind": 4, "tags": [], "detail": "option", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "second", "kind": 4, "tags": [], "detail": "int", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "zoo", "kind": 4, "tags": [], "detail": "option", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "key", "kind": 4, "tags": [], "detail": "string", - "documentation": null + "documentation": null, + "sortText": null }] diff --git a/analysis/tests/src/expected/Jsx.resi.txt b/analysis/tests/src/expected/Jsx.resi.txt index b0b987154..670c65be9 100644 --- a/analysis/tests/src/expected/Jsx.resi.txt +++ b/analysis/tests/src/expected/Jsx.resi.txt @@ -15,7 +15,8 @@ Completable: Cpath Type[React, e] "kind": 22, "tags": [], "detail": "type element", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/Jsx.resi 10:18 @@ -27,6 +28,7 @@ Completable: Cpath Type[React, e] "kind": 22, "tags": [], "detail": "type element", - "documentation": null + "documentation": null, + "sortText": null }] diff --git a/analysis/tests/src/expected/RecordCompletion.res.txt b/analysis/tests/src/expected/RecordCompletion.res.txt index d5d0b47dc..12a3f7ce5 100644 --- a/analysis/tests/src/expected/RecordCompletion.res.txt +++ b/analysis/tests/src/expected/RecordCompletion.res.txt @@ -6,13 +6,15 @@ Completable: Cpath Value[t].n->m "kind": 12, "tags": [], "detail": "(t<'a>, ('a, int) => 'b) => t<'b>", - "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The function acceps two arguments: an item from the array and its\nindex number. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\n// multiply each item in array by its position\nlet product = (item, index) => item * index\nJs.Array2.mapi([10, 11, 12], product) == [0, 11, 24]\n```\n"} + "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The function acceps two arguments: an item from the array and its\nindex number. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\n// multiply each item in array by its position\nlet product = (item, index) => item * index\nJs.Array2.mapi([10, 11, 12], product) == [0, 11, 24]\n```\n"}, + "sortText": null }, { "label": "Js.Array2.map", "kind": 12, "tags": [], "detail": "(t<'a>, 'a => 'b) => t<'b>", - "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\nJs.Array2.map([12, 4, 8], x => x * x) == [144, 16, 64]\nJs.Array2.map([\"animal\", \"vegetable\", \"mineral\"], Js.String.length) == [6, 9, 7]\n```\n"} + "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\nJs.Array2.map([12, 4, 8], x => x * x) == [144, 16, 64]\nJs.Array2.map([\"animal\", \"vegetable\", \"mineral\"], Js.String.length) == [6, 9, 7]\n```\n"}, + "sortText": null }] Complete src/RecordCompletion.res 11:13 @@ -23,13 +25,15 @@ Completable: Cpath Value[t2].n2.n->m "kind": 12, "tags": [], "detail": "(t<'a>, ('a, int) => 'b) => t<'b>", - "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The function acceps two arguments: an item from the array and its\nindex number. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\n// multiply each item in array by its position\nlet product = (item, index) => item * index\nJs.Array2.mapi([10, 11, 12], product) == [0, 11, 24]\n```\n"} + "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The function acceps two arguments: an item from the array and its\nindex number. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\n// multiply each item in array by its position\nlet product = (item, index) => item * index\nJs.Array2.mapi([10, 11, 12], product) == [0, 11, 24]\n```\n"}, + "sortText": null }, { "label": "Js.Array2.map", "kind": 12, "tags": [], "detail": "(t<'a>, 'a => 'b) => t<'b>", - "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\nJs.Array2.map([12, 4, 8], x => x * x) == [144, 16, 64]\nJs.Array2.map([\"animal\", \"vegetable\", \"mineral\"], Js.String.length) == [6, 9, 7]\n```\n"} + "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\nJs.Array2.map([12, 4, 8], x => x * x) == [144, 16, 64]\nJs.Array2.map([\"animal\", \"vegetable\", \"mineral\"], Js.String.length) == [6, 9, 7]\n```\n"}, + "sortText": null }] Complete src/RecordCompletion.res 19:7 @@ -41,7 +45,8 @@ Completable: Cpath Module[R]."" "kind": 5, "tags": [], "detail": "name: string\n\ntype t = {name: string}", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/RecordCompletion.res 22:7 @@ -53,6 +58,7 @@ Completable: Cpath Module[R]."" "kind": 5, "tags": [], "detail": "name: string\n\ntype t = {name: string}", - "documentation": null + "documentation": null, + "sortText": null }] diff --git a/analysis/tests/src/expected/RecoveryOnProp.res.txt b/analysis/tests/src/expected/RecoveryOnProp.res.txt index fe509d768..8b3dcf599 100644 --- a/analysis/tests/src/expected/RecoveryOnProp.res.txt +++ b/analysis/tests/src/expected/RecoveryOnProp.res.txt @@ -13,12 +13,14 @@ Completable: Cpath Type[Res] "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "RescriptReactRouter", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }] diff --git a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt index 793282c36..44948b045 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt @@ -7,7 +7,8 @@ Completable: Cjsx([SomeComponent], someVaria, [someVaria]) "kind": 4, "tags": [], "detail": "someVariant", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_Jsx.res 23:38 @@ -19,37 +20,43 @@ Completable: CtypedContextPattern(JsxProp())="" pa "kind": 4, "tags": [], "detail": "One\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Two", "kind": 4, "tags": [], "detail": "Two\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Three", "kind": 4, "tags": [], "detail": "Three\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Four", "kind": 4, "tags": [], "detail": "Four\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Five(_)", "kind": 4, "tags": [], "detail": "Five(int)\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Six(_)", "kind": 4, "tags": [], "detail": "Six(option, int)\n\n", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_Jsx.res 26:39 @@ -61,37 +68,43 @@ Completable: CtypedContextPattern(JsxProp())="" pa "kind": 4, "tags": [], "detail": "One\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Two", "kind": 4, "tags": [], "detail": "Two\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Three", "kind": 4, "tags": [], "detail": "Three\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Four", "kind": 4, "tags": [], "detail": "Four\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Five(_)", "kind": 4, "tags": [], "detail": "Five(int)\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Six(_)", "kind": 4, "tags": [], "detail": "Six(option, int)\n\n", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_Jsx.res 29:39 @@ -103,13 +116,15 @@ Completable: CtypedContextPattern(JsxProp())=T pat "kind": 4, "tags": [], "detail": "Two\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Three", "kind": 4, "tags": [], "detail": "Three\n\n", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_Jsx.res 32:39 @@ -129,13 +144,15 @@ Completable: CtypedContextPattern(JsxProp())="" p "kind": 4, "tags": [], "detail": "Foo\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Bar", "kind": 4, "tags": [], "detail": "Bar\n\n", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_Jsx.res 38:37 @@ -147,37 +164,43 @@ Completable: CtypedContextPattern(JsxProp())="" pat "kind": 4, "tags": [], "detail": "#one", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#six(_)", "kind": 4, "tags": [], "detail": "#six(option, int)", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#three", "kind": 4, "tags": [], "detail": "#three", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#two", "kind": 4, "tags": [], "detail": "#two", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#five(_)", "kind": 4, "tags": [], "detail": "#five(int)", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#four", "kind": 4, "tags": [], "detail": "#four", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_Jsx.res 41:38 @@ -189,37 +212,43 @@ Completable: CtypedContextPattern(JsxProp())="" pat "kind": 4, "tags": [], "detail": "#one", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#six(_)", "kind": 4, "tags": [], "detail": "#six(option, int)", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#three", "kind": 4, "tags": [], "detail": "#three", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#two", "kind": 4, "tags": [], "detail": "#two", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#five(_)", "kind": 4, "tags": [], "detail": "#five(int)", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#four", "kind": 4, "tags": [], "detail": "#four", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_Jsx.res 44:39 @@ -231,13 +260,15 @@ Completable: CtypedContextPattern(JsxProp())=t patt "kind": 4, "tags": [], "detail": "#three", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#two", "kind": 4, "tags": [], "detail": "#two", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_Jsx.res 47:39 diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index 44246da5c..f2c344832 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -12,7 +12,8 @@ Found type for function ( "kind": 4, "tags": [], "detail": "someVariant", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_LabelledArguments.res 25:44 @@ -24,37 +25,43 @@ Completable: CtypedContextPattern(NamedArg(someVariant, Value[someVariantToStrin "kind": 4, "tags": [], "detail": "One\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Two", "kind": 4, "tags": [], "detail": "Two\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Three", "kind": 4, "tags": [], "detail": "Three\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Four", "kind": 4, "tags": [], "detail": "Four\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Five(_)", "kind": 4, "tags": [], "detail": "Five(int)\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Six(_)", "kind": 4, "tags": [], "detail": "Six(option, int)\n\n", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_LabelledArguments.res 28:45 @@ -66,37 +73,43 @@ Completable: CtypedContextPattern(NamedArg(someVariant, Value[someVariantToStrin "kind": 4, "tags": [], "detail": "One\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Two", "kind": 4, "tags": [], "detail": "Two\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Three", "kind": 4, "tags": [], "detail": "Three\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Four", "kind": 4, "tags": [], "detail": "Four\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Five(_)", "kind": 4, "tags": [], "detail": "Five(int)\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Six(_)", "kind": 4, "tags": [], "detail": "Six(option, int)\n\n", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_LabelledArguments.res 31:45 @@ -108,13 +121,15 @@ Completable: CtypedContextPattern(NamedArg(someVariant, Value[someVariantToStrin "kind": 4, "tags": [], "detail": "Two\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Three", "kind": 4, "tags": [], "detail": "Three\n\n", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_LabelledArguments.res 34:45 @@ -128,7 +143,8 @@ Completable: Cpath Value[t] "kind": 12, "tags": [], "detail": "someVariant", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_LabelledArguments.res 37:59 @@ -142,43 +158,50 @@ Completable: Cpath Value[TypeDefinition, ""] "kind": 12, "tags": [], "detail": "variant => string", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "x", "kind": 12, "tags": [], "detail": "variant", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "y", "kind": 12, "tags": [], "detail": "record", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "obj", "kind": 12, "tags": [], "detail": "obj", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "f", "kind": 12, "tags": [], "detail": "record => string", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Foo", "kind": 4, "tags": [], "detail": "Foo\n\ntype variant = Foo | Bar", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Bar", "kind": 4, "tags": [], "detail": "Bar\n\ntype variant = Foo | Bar", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_LabelledArguments.res 40:45 @@ -190,13 +213,15 @@ Completable: CtypedContextPattern(NamedArg(anotherThing, Value[someVariantToStri "kind": 4, "tags": [], "detail": "Foo\n\n", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Bar", "kind": 4, "tags": [], "detail": "Bar\n\n", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_LabelledArguments.res 43:43 @@ -208,37 +233,43 @@ Completable: CtypedContextPattern(NamedArg(thirdThing, Value[someVariantToString "kind": 4, "tags": [], "detail": "#one", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#six(_)", "kind": 4, "tags": [], "detail": "#six(option, int)", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#three", "kind": 4, "tags": [], "detail": "#three", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#two", "kind": 4, "tags": [], "detail": "#two", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#five(_)", "kind": 4, "tags": [], "detail": "#five(int)", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#four", "kind": 4, "tags": [], "detail": "#four", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_LabelledArguments.res 46:44 @@ -250,37 +281,43 @@ Completable: CtypedContextPattern(NamedArg(thirdThing, Value[someVariantToString "kind": 4, "tags": [], "detail": "#one", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#six(_)", "kind": 4, "tags": [], "detail": "#six(option, int)", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#three", "kind": 4, "tags": [], "detail": "#three", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#two", "kind": 4, "tags": [], "detail": "#two", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#five(_)", "kind": 4, "tags": [], "detail": "#five(int)", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#four", "kind": 4, "tags": [], "detail": "#four", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_LabelledArguments.res 49:45 @@ -292,13 +329,15 @@ Completable: CtypedContextPattern(NamedArg(thirdThing, Value[someVariantToString "kind": 4, "tags": [], "detail": "#three", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "#two", "kind": 4, "tags": [], "detail": "#two", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypeContextCompletion_LabelledArguments.res 52:45 @@ -318,6 +357,7 @@ Completable: CtypedContextPattern(FunctionArgument(fnSource:NamedArg(doThing, Va "kind": 5, "tags": [], "detail": "name: string\n\ntype someRecord = {age: int, name: string}", - "documentation": null + "documentation": null, + "sortText": null }] diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 9737d00a3..71b9e5b7d 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -2,36 +2,127 @@ Complete src/TypeContextCompletion_Records.res 16:15 posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:7->16:16] posCursor:[16:15] posNoWhite:[16:14] Found pattern:[16:8->16:15] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:another, pattern: [], seenIdents: [another]) -[] +[{ + "label": "anotherThing", + "kind": 5, + "tags": [], + "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 19:23 posCursor:[19:23] posNoWhite:[19:22] Found pattern:[19:7->19:24] posCursor:[19:23] posNoWhite:[19:22] Found pattern:[19:22->19:23] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:s, pattern: [], seenIdents: [anotherThing, s]) -[] +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 22:8 posCursor:[22:8] posNoWhite:[22:7] Found pattern:[22:7->22:9] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }, { + "label": "anotherThing", + "kind": 5, + "tags": [], + "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }, { + "label": "thirdThing", + "kind": 5, + "tags": [], + "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 31:8 posCursor:[31:8] posNoWhite:[31:7] Found pattern:[31:7->31:9] Completable: CtypedPattern(sourceType:Value[getSomeVal](~irrelevant), lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }, { + "label": "anotherThing", + "kind": 5, + "tags": [], + "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }, { + "label": "thirdThing", + "kind": 5, + "tags": [], + "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 35:20 posCursor:[35:20] posNoWhite:[35:19] Found pattern:[35:7->35:22] posCursor:[35:20] posNoWhite:[35:19] Found pattern:[35:19->35:21] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [RecordField:something], seenIdents: []) -[] +[{ + "label": "somethingElse", + "kind": 5, + "tags": [], + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }, { + "label": "whatIsThis", + "kind": 5, + "tags": [], + "detail": "whatIsThis: bool\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }, { + "label": "anotherLevel", + "kind": 5, + "tags": [], + "detail": "anotherLevel: anotherLevel\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 38:47 posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:7->38:50] posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:19->38:49] posCursor:[38:47] posNoWhite:[38:46] Found pattern:[38:46->38:48] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [RecordField:something, RecordField:anotherLevel], seenIdents: []) -[] +[{ + "label": "level", + "kind": 5, + "tags": [], + "detail": "level: int\n\ntype anotherLevel = {level: int, someOtherArg: bool}", + "documentation": null, + "sortText": null + }, { + "label": "someOtherArg", + "kind": 5, + "tags": [], + "detail": "someOtherArg: bool\n\ntype anotherLevel = {level: int, someOtherArg: bool}", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 41:48 posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:7->41:51] @@ -39,36 +130,95 @@ posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:19->41:50] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:46->41:49] posCursor:[41:48] posNoWhite:[41:47] Found pattern:[41:47->41:48] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:l, pattern: [RecordField:something, RecordField:anotherLevel], seenIdents: [l]) -[] +[{ + "label": "level", + "kind": 5, + "tags": [], + "detail": "level: int\n\ntype anotherLevel = {level: int, someOtherArg: bool}", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 44:47 posCursor:[44:47] posNoWhite:[44:44] Found pattern:[44:7->44:49] posCursor:[44:47] posNoWhite:[44:44] Found pattern:[44:19->44:48] -[] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [RecordField:something], seenIdents: [whatIsThis, anotherLevel]) +[{ + "label": "somethingElse", + "kind": 5, + "tags": [], + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 47:31 posCursor:[47:31] posNoWhite:[47:30] Found pattern:[47:7->47:47] posCursor:[47:31] posNoWhite:[47:30] Found pattern:[47:19->47:46] -[] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [RecordField:something], seenIdents: [whatIsThis, anotherLevel]) +[{ + "label": "somethingElse", + "kind": 5, + "tags": [], + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 50:44 posCursor:[50:44] posNoWhite:[50:43] Found expr:[50:3->50:54] posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:22->50:46] posCursor:[50:44] posNoWhite:[50:43] Found pattern:[50:42->50:45] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Switch, prefix:som, pattern: [], seenIdents: [thirdThing, som]) -[] +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 53:52 posCursor:[53:52] posNoWhite:[53:51] Found expr:[53:3->53:61] posCursor:[53:52] posNoWhite:[53:51] Found pattern:[53:51->53:53] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Switch, prefix:"", pattern: [], seenIdents: []) -[] +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }, { + "label": "anotherThing", + "kind": 5, + "tags": [], + "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }, { + "label": "thirdThing", + "kind": 5, + "tags": [], + "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 56:89 posCursor:[56:89] posNoWhite:[56:88] Found expr:[56:3->56:100] posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:51->56:92] posCursor:[56:89] posNoWhite:[56:88] Found pattern:[56:63->56:91] -[] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Switch, prefix:"", pattern: [RecordField:something], seenIdents: [whatIsThis, anotherLevel]) +[{ + "label": "somethingElse", + "kind": 5, + "tags": [], + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 81:48 posCursor:[81:48] posNoWhite:[81:47] Found expr:[81:3->81:57] @@ -77,7 +227,14 @@ posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:41->81:48] posCursor:[81:48] posNoWhite:[81:47] Found pattern:[81:47->81:48] Ppat_construct T:[81:47->81:48] Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [RecordField:something], seenIdents: [Two, T]) -[] +[{ + "label": "Three(_)", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 84:48 posCursor:[84:48] posNoWhite:[84:47] Found expr:[84:3->84:58] @@ -87,7 +244,21 @@ Ppat_construct Some:[84:42->84:46] posCursor:[84:48] posNoWhite:[84:47] Found pattern:[84:47->84:48] Ppat_construct T:[84:47->84:48] Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [RecordField:otherThing, Variant:Some(0)], seenIdents: []) -[] +[{ + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Three(_)", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 87:47 posCursor:[87:47] posNoWhite:[87:46] Found expr:[87:3->87:57] @@ -96,7 +267,21 @@ posCursor:[87:47] posNoWhite:[87:46] Found pattern:[87:42->87:48] posCursor:[87:47] posNoWhite:[87:46] Found pattern:[87:46->87:47] Ppat_construct T:[87:46->87:47] Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [RecordField:thirdStuff, Tuple:1], seenIdents: []) -[] +[{ + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Three(_)", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 90:51 posCursor:[90:51] posNoWhite:[90:50] Found expr:[90:3->90:62] @@ -119,7 +304,14 @@ posCursor:[93:55] posNoWhite:[93:54] Found pattern:[93:50->93:57] posCursor:[93:55] posNoWhite:[93:54] Found pattern:[93:54->93:55] Ppat_construct O:[93:54->93:55] Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:O, pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)], seenIdents: []) -[] +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 96:63 posCursor:[96:63] posNoWhite:[96:62] Found expr:[96:3->96:78] @@ -144,7 +336,14 @@ posCursor:[99:67] posNoWhite:[99:66] Found pattern:[99:54->99:67] posCursor:[99:67] posNoWhite:[99:66] Found pattern:[99:66->99:67] Ppat_construct T:[99:66->99:67] Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)], seenIdents: [One, Two, T]) -[] +[{ + "label": "Three(_)", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 102:43 posCursor:[102:43] posNoWhite:[102:42] Found expr:[102:3->102:52] @@ -152,7 +351,49 @@ posCursor:[102:43] posNoWhite:[102:42] Found pattern:[102:29->102:44] posCursor:[102:43] posNoWhite:[102:42] Found pattern:[102:42->102:43] Ppat_construct S:[102:42->102:43] Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:S, pattern: [RecordField:otherThing], seenIdents: []) -[] +[{ + "label": "None", + "kind": 4, + "tags": [], + "detail": "None\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(One)", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(Two)", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(Three(_))", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(Four(_))", + "kind": 4, + "tags": [], + "detail": "Four(someOtherVariant)\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(Five(_))", + "kind": 4, + "tags": [], + "detail": "Five(someOtherVariant, someVariant)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 105:39 posCursor:[105:39] posNoWhite:[105:38] Found expr:[105:3->105:48] @@ -160,7 +401,21 @@ posCursor:[105:39] posNoWhite:[105:38] Found pattern:[105:29->105:40] posCursor:[105:39] posNoWhite:[105:38] Found pattern:[105:38->105:39] Ppat_construct S:[105:38->105:39] Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:S, pattern: [RecordField:other2], seenIdents: []) -[] +[{ + "label": "None", + "kind": 4, + "tags": [], + "detail": "None\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(_)", + "kind": 4, + "tags": [], + "detail": "Some(_)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 108:64 posCursor:[108:64] posNoWhite:[108:62] Found expr:[108:3->108:75] @@ -175,21 +430,56 @@ Complete src/TypeContextCompletion_Records.res 111:38 posCursor:[111:38] posNoWhite:[111:36] Found expr:[111:3->111:47] posCursor:[111:38] posNoWhite:[111:36] Found pattern:[111:29->111:39] Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:other2], seenIdents: []) -[] +[{ + "label": "None", + "kind": 4, + "tags": [], + "detail": "None\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(_)", + "kind": 4, + "tags": [], + "detail": "Some(_)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 114:55 posCursor:[114:55] posNoWhite:[114:53] Found expr:[114:3->114:67] posCursor:[114:55] posNoWhite:[114:53] Found pattern:[114:22->114:59] posCursor:[114:55] posNoWhite:[114:53] Found pattern:[114:34->114:59] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:something, RecordField:whatIsThis], seenIdents: [false]) -[] +[{ + "label": "true", + "kind": 12, + "tags": [], + "detail": "boolean\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 117:46 posCursor:[117:46] posNoWhite:[117:45] Found expr:[117:3->117:58] posCursor:[117:46] posNoWhite:[117:45] Found pattern:[117:22->117:50] posCursor:[117:46] posNoWhite:[117:45] Found pattern:[117:34->117:50] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:something, RecordField:whatIsThis], seenIdents: []) -[] +[{ + "label": "false", + "kind": 12, + "tags": [], + "detail": "boolean\n\n", + "documentation": null, + "sortText": null + }, { + "label": "true", + "kind": 12, + "tags": [], + "detail": "boolean\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 120:49 posCursor:[120:49] posNoWhite:[120:48] Found expr:[120:3->120:62] @@ -197,12 +487,61 @@ posCursor:[120:49] posNoWhite:[120:48] Found pattern:[120:22->120:54] posCursor:[120:49] posNoWhite:[120:48] Found pattern:[120:34->120:52] posCursor:[120:49] posNoWhite:[120:48] Found pattern:[120:47->120:49] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CVariant, patternType:Switch, prefix:fa, pattern: [RecordField:something, RecordField:whatIsThis], seenIdents: []) -[] +[{ + "label": "false", + "kind": 12, + "tags": [], + "detail": "boolean\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 125:15 posCursor:[125:15] posNoWhite:[125:14] Found expr:[125:3->131:11] Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [], seenIdents: []) -[] +[{ + "label": "None", + "kind": 4, + "tags": [], + "detail": "None\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(One)", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(Two)", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(Three(_))", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(Four(_))", + "kind": 4, + "tags": [], + "detail": "Four(someOtherVariant)\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(Five(_))", + "kind": 4, + "tags": [], + "detail": "Five(someOtherVariant, someVariant)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 128:14 posCursor:[128:14] posNoWhite:[128:12] Found expr:[128:3->128:13] @@ -211,23 +550,100 @@ posCursor:[128:14] posNoWhite:[128:12] Found expr:[128:3->128:13] Complete src/TypeContextCompletion_Records.res 133:15 posCursor:[133:15] posNoWhite:[133:14] Found expr:[133:3->133:17] Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [], seenIdents: []) -[] +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Three(_)", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Four(_)", + "kind": 4, + "tags": [], + "detail": "Four(someOtherVariant)\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(someOtherVariant, someVariant)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 136:36 posCursor:[136:36] posNoWhite:[136:34] Found expr:[136:3->136:38] Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [], seenIdents: [One, Two, Three]) -[] +[{ + "label": "Four(_)", + "kind": 4, + "tags": [], + "detail": "Four(someOtherVariant)\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(someOtherVariant, someVariant)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypeContextCompletion_Records.res 140:33 posCursor:[140:33] posNoWhite:[140:32] Found expr:[140:3->140:44] posCursor:[140:33] posNoWhite:[140:32] Found pattern:[140:22->140:36] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:something], seenIdents: []) -[] +[{ + "label": "{}", + "kind": 4, + "tags": [], + "detail": "Empty record", + "documentation": null, + "sortText": "a" + }] Complete src/TypeContextCompletion_Records.res 144:35 posCursor:[144:35] posNoWhite:[144:34] Found expr:[144:3->144:46] posCursor:[144:35] posNoWhite:[144:34] Found pattern:[144:22->144:38] posCursor:[144:35] posNoWhite:[144:34] Found pattern:[144:34->144:36] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Switch, prefix:"", pattern: [RecordField:something], seenIdents: []) -[] +[{ + "label": "somethingElse", + "kind": 5, + "tags": [], + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }, { + "label": "whatIsThis", + "kind": 5, + "tags": [], + "detail": "whatIsThis: bool\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }, { + "label": "anotherLevel", + "kind": 5, + "tags": [], + "detail": "anotherLevel: anotherLevel\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }] diff --git a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt index 4909241e3..30beade22 100644 --- a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt +++ b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt @@ -14,7 +14,7 @@ Pstr_value( Pexp_ident:someVariantToString args: <*>~someVaria= - <*>Pexp_ident:someVaria + [@ns.namedArgLoc]<*>Pexp_ident:someVaria ) ) @@ -34,7 +34,7 @@ Pstr_value( Pexp_ident:someVariantToString args: <*>~someVariant= - Pexp_extension(%rescript.exprhole) + [@ns.namedArgLoc]Pexp_extension(%rescript.exprhole) ) ) @@ -55,7 +55,7 @@ Pstr_value( Pexp_ident:someVariantToString args: ~someVariant= - <*>Pexp_construct(<*>T) + [@ns.namedArgLoc]<*>Pexp_construct(<*>T) ) ) @@ -75,7 +75,7 @@ Pstr_value( Pexp_ident:someVariantToString args: ~someVariant= - <*>Pexp_ident:t + [@ns.namedArgLoc]<*>Pexp_ident:t ) ) @@ -95,7 +95,7 @@ Pstr_value( Pexp_ident:someVariantToString args: ~someVariant= - <*>Pexp_ident:TypeDefinition."" + [@ns.namedArgLoc]<*>Pexp_ident:TypeDefinition."" ) ) @@ -115,7 +115,7 @@ Pstr_value( Pexp_ident:someVariantToString args: <*>~anotherThing= - Pexp_extension(%rescript.exprhole) + [@ns.namedArgLoc]Pexp_extension(%rescript.exprhole) ) ) @@ -135,7 +135,7 @@ Pstr_value( Pexp_ident:someVariantToString args: <*>~thirdThing= - Pexp_extension(%rescript.exprhole) + [@ns.namedArgLoc]Pexp_extension(%rescript.exprhole) ) ) @@ -155,7 +155,7 @@ Pstr_value( Pexp_ident:someVariantToString args: ~thirdThing= - <*>Pexp_variant(t) + [@ns.namedArgLoc]<*>Pexp_variant(t) ) ) @@ -175,7 +175,7 @@ Pstr_value( Pexp_ident:someVariantToString args: ~thirdThing= - <*>Pexp_variant(T) + [@ns.namedArgLoc]<*>Pexp_variant(T) ) ) @@ -191,36 +191,127 @@ Complete src/TypedContextCompletionSpec.res 97:15 posCursor:[97:15] posNoWhite:[97:14] Found pattern:[97:7->97:16] posCursor:[97:15] posNoWhite:[97:14] Found pattern:[97:8->97:15] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:another, pattern: [], seenIdents: [another]) -[] +[{ + "label": "anotherThing", + "kind": 5, + "tags": [], + "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 101:23 posCursor:[101:23] posNoWhite:[101:22] Found pattern:[101:7->101:24] posCursor:[101:23] posNoWhite:[101:22] Found pattern:[101:22->101:23] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:s, pattern: [], seenIdents: [anotherThing, s]) -[] +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 105:8 posCursor:[105:8] posNoWhite:[105:7] Found pattern:[105:7->105:9] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }, { + "label": "anotherThing", + "kind": 5, + "tags": [], + "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }, { + "label": "thirdThing", + "kind": 5, + "tags": [], + "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 109:8 posCursor:[109:8] posNoWhite:[109:7] Found pattern:[109:7->109:9] Completable: CtypedPattern(sourceType:Value[getSomeVal](~irrelevant), lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }, { + "label": "anotherThing", + "kind": 5, + "tags": [], + "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }, { + "label": "thirdThing", + "kind": 5, + "tags": [], + "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 113:20 posCursor:[113:20] posNoWhite:[113:19] Found pattern:[113:7->113:22] posCursor:[113:20] posNoWhite:[113:19] Found pattern:[113:19->113:21] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [RecordField:something], seenIdents: []) -[] +[{ + "label": "somethingElse", + "kind": 5, + "tags": [], + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }, { + "label": "whatIsThis", + "kind": 5, + "tags": [], + "detail": "whatIsThis: bool\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }, { + "label": "anotherLevel", + "kind": 5, + "tags": [], + "detail": "anotherLevel: anotherLevel\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 117:47 posCursor:[117:47] posNoWhite:[117:46] Found pattern:[117:7->117:50] posCursor:[117:47] posNoWhite:[117:46] Found pattern:[117:19->117:49] posCursor:[117:47] posNoWhite:[117:46] Found pattern:[117:46->117:48] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [RecordField:something, RecordField:anotherLevel], seenIdents: []) -[] +[{ + "label": "level", + "kind": 5, + "tags": [], + "detail": "level: int\n\ntype anotherLevel = {level: int, someOtherArg: bool}", + "documentation": null, + "sortText": null + }, { + "label": "someOtherArg", + "kind": 5, + "tags": [], + "detail": "someOtherArg: bool\n\ntype anotherLevel = {level: int, someOtherArg: bool}", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 121:48 posCursor:[121:48] posNoWhite:[121:47] Found pattern:[121:7->121:51] @@ -228,36 +319,95 @@ posCursor:[121:48] posNoWhite:[121:47] Found pattern:[121:19->121:50] posCursor:[121:48] posNoWhite:[121:47] Found pattern:[121:46->121:49] posCursor:[121:48] posNoWhite:[121:47] Found pattern:[121:47->121:48] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:l, pattern: [RecordField:something, RecordField:anotherLevel], seenIdents: [l]) -[] +[{ + "label": "level", + "kind": 5, + "tags": [], + "detail": "level: int\n\ntype anotherLevel = {level: int, someOtherArg: bool}", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 125:47 posCursor:[125:47] posNoWhite:[125:44] Found pattern:[125:7->125:49] posCursor:[125:47] posNoWhite:[125:44] Found pattern:[125:19->125:48] -[] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [RecordField:something], seenIdents: [whatIsThis, anotherLevel]) +[{ + "label": "somethingElse", + "kind": 5, + "tags": [], + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 129:31 posCursor:[129:31] posNoWhite:[129:30] Found pattern:[129:7->129:47] posCursor:[129:31] posNoWhite:[129:30] Found pattern:[129:19->129:46] -[] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Destructure, prefix:"", pattern: [RecordField:something], seenIdents: [whatIsThis, anotherLevel]) +[{ + "label": "somethingElse", + "kind": 5, + "tags": [], + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 137:44 posCursor:[137:44] posNoWhite:[137:43] Found expr:[137:3->137:54] posCursor:[137:44] posNoWhite:[137:43] Found pattern:[137:22->137:46] posCursor:[137:44] posNoWhite:[137:43] Found pattern:[137:42->137:45] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Switch, prefix:som, pattern: [], seenIdents: [thirdThing, som]) -[] +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 141:52 posCursor:[141:52] posNoWhite:[141:51] Found expr:[141:3->141:61] posCursor:[141:52] posNoWhite:[141:51] Found pattern:[141:51->141:53] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Switch, prefix:"", pattern: [], seenIdents: []) -[] +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }, { + "label": "anotherThing", + "kind": 5, + "tags": [], + "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }, { + "label": "thirdThing", + "kind": 5, + "tags": [], + "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 145:89 posCursor:[145:89] posNoWhite:[145:88] Found expr:[145:3->145:100] posCursor:[145:89] posNoWhite:[145:88] Found pattern:[145:51->145:92] posCursor:[145:89] posNoWhite:[145:88] Found pattern:[145:63->145:91] -[] +Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Switch, prefix:"", pattern: [RecordField:something], seenIdents: [whatIsThis, anotherLevel]) +[{ + "label": "somethingElse", + "kind": 5, + "tags": [], + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 149:48 posCursor:[149:48] posNoWhite:[149:47] Found expr:[149:3->149:57] @@ -266,7 +416,14 @@ posCursor:[149:48] posNoWhite:[149:47] Found pattern:[149:41->149:48] posCursor:[149:48] posNoWhite:[149:47] Found pattern:[149:47->149:48] Ppat_construct T:[149:47->149:48] Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [RecordField:something], seenIdents: [Two, T]) -[] +[{ + "label": "Three(_)", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 152:48 posCursor:[152:48] posNoWhite:[152:47] Found expr:[152:3->152:58] @@ -276,7 +433,21 @@ Ppat_construct Some:[152:42->152:46] posCursor:[152:48] posNoWhite:[152:47] Found pattern:[152:47->152:48] Ppat_construct T:[152:47->152:48] Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [RecordField:otherThing, Variant:Some(0)], seenIdents: []) -[] +[{ + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Three(_)", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 155:47 posCursor:[155:47] posNoWhite:[155:46] Found expr:[155:3->155:57] @@ -285,7 +456,21 @@ posCursor:[155:47] posNoWhite:[155:46] Found pattern:[155:42->155:48] posCursor:[155:47] posNoWhite:[155:46] Found pattern:[155:46->155:47] Ppat_construct T:[155:46->155:47] Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [RecordField:thirdStuff, Tuple:1], seenIdents: []) -[] +[{ + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Three(_)", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 158:51 posCursor:[158:51] posNoWhite:[158:50] Found expr:[158:3->158:62] @@ -308,7 +493,14 @@ posCursor:[161:55] posNoWhite:[161:54] Found pattern:[161:50->161:57] posCursor:[161:55] posNoWhite:[161:54] Found pattern:[161:54->161:55] Ppat_construct O:[161:54->161:55] Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:O, pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)], seenIdents: []) -[] +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 164:63 posCursor:[164:63] posNoWhite:[164:62] Found expr:[164:3->164:78] @@ -333,7 +525,14 @@ posCursor:[167:67] posNoWhite:[167:66] Found pattern:[167:54->167:67] posCursor:[167:67] posNoWhite:[167:66] Found pattern:[167:66->167:67] Ppat_construct T:[167:66->167:67] Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [RecordField:thirdStuff, Tuple:1, Variant:Five(1)], seenIdents: [One, Two, T]) -[] +[{ + "label": "Three(_)", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 170:43 posCursor:[170:43] posNoWhite:[170:42] Found expr:[170:3->170:52] @@ -341,7 +540,49 @@ posCursor:[170:43] posNoWhite:[170:42] Found pattern:[170:29->170:44] posCursor:[170:43] posNoWhite:[170:42] Found pattern:[170:42->170:43] Ppat_construct S:[170:42->170:43] Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:S, pattern: [RecordField:otherThing], seenIdents: []) -[] +[{ + "label": "None", + "kind": 4, + "tags": [], + "detail": "None\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(One)", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(Two)", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(Three(_))", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(Four(_))", + "kind": 4, + "tags": [], + "detail": "Four(someOtherVariant)\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(Five(_))", + "kind": 4, + "tags": [], + "detail": "Five(someOtherVariant, someVariant)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 173:39 posCursor:[173:39] posNoWhite:[173:38] Found expr:[173:3->173:48] @@ -349,7 +590,21 @@ posCursor:[173:39] posNoWhite:[173:38] Found pattern:[173:29->173:40] posCursor:[173:39] posNoWhite:[173:38] Found pattern:[173:38->173:39] Ppat_construct S:[173:38->173:39] Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:S, pattern: [RecordField:other2], seenIdents: []) -[] +[{ + "label": "None", + "kind": 4, + "tags": [], + "detail": "None\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(_)", + "kind": 4, + "tags": [], + "detail": "Some(_)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 176:64 posCursor:[176:64] posNoWhite:[176:62] Found expr:[176:3->176:75] @@ -364,21 +619,56 @@ Complete src/TypedContextCompletionSpec.res 179:38 posCursor:[179:38] posNoWhite:[179:36] Found expr:[179:3->179:47] posCursor:[179:38] posNoWhite:[179:36] Found pattern:[179:29->179:39] Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:other2], seenIdents: []) -[] +[{ + "label": "None", + "kind": 4, + "tags": [], + "detail": "None\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(_)", + "kind": 4, + "tags": [], + "detail": "Some(_)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 182:55 posCursor:[182:55] posNoWhite:[182:53] Found expr:[182:3->182:67] posCursor:[182:55] posNoWhite:[182:53] Found pattern:[182:22->182:59] posCursor:[182:55] posNoWhite:[182:53] Found pattern:[182:34->182:59] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:something, RecordField:whatIsThis], seenIdents: [false]) -[] +[{ + "label": "true", + "kind": 12, + "tags": [], + "detail": "boolean\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 185:46 posCursor:[185:46] posNoWhite:[185:45] Found expr:[185:3->185:58] posCursor:[185:46] posNoWhite:[185:45] Found pattern:[185:22->185:50] posCursor:[185:46] posNoWhite:[185:45] Found pattern:[185:34->185:50] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:something, RecordField:whatIsThis], seenIdents: []) -[] +[{ + "label": "false", + "kind": 12, + "tags": [], + "detail": "boolean\n\n", + "documentation": null, + "sortText": null + }, { + "label": "true", + "kind": 12, + "tags": [], + "detail": "boolean\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 188:49 posCursor:[188:49] posNoWhite:[188:48] Found expr:[188:3->188:62] @@ -386,12 +676,61 @@ posCursor:[188:49] posNoWhite:[188:48] Found pattern:[188:22->188:54] posCursor:[188:49] posNoWhite:[188:48] Found pattern:[188:34->188:52] posCursor:[188:49] posNoWhite:[188:48] Found pattern:[188:47->188:49] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CVariant, patternType:Switch, prefix:fa, pattern: [RecordField:something, RecordField:whatIsThis], seenIdents: []) -[] +[{ + "label": "false", + "kind": 12, + "tags": [], + "detail": "boolean\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 192:15 posCursor:[192:15] posNoWhite:[192:14] Found expr:[192:3->192:17] Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [], seenIdents: []) -[] +[{ + "label": "None", + "kind": 4, + "tags": [], + "detail": "None\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(One)", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(Two)", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(Three(_))", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(Four(_))", + "kind": 4, + "tags": [], + "detail": "Four(someOtherVariant)\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Some(Five(_))", + "kind": 4, + "tags": [], + "detail": "Five(someOtherVariant, someVariant)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 196:14 posCursor:[196:14] posNoWhite:[196:12] Found expr:[196:3->196:13] @@ -400,18 +739,74 @@ posCursor:[196:14] posNoWhite:[196:12] Found expr:[196:3->196:13] Complete src/TypedContextCompletionSpec.res 199:15 posCursor:[199:15] posNoWhite:[199:14] Found expr:[199:3->199:17] Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [], seenIdents: []) -[] +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Three(_)", + "kind": 4, + "tags": [], + "detail": "Three(int)\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Four(_)", + "kind": 4, + "tags": [], + "detail": "Four(someOtherVariant)\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(someOtherVariant, someVariant)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 202:36 posCursor:[202:36] posNoWhite:[202:34] Found expr:[202:3->202:38] Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [], seenIdents: [One, Two, Three]) -[] +[{ + "label": "Four(_)", + "kind": 4, + "tags": [], + "detail": "Four(someOtherVariant)\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(someOtherVariant, someVariant)\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 206:33 posCursor:[206:33] posNoWhite:[206:32] Found expr:[206:3->206:44] posCursor:[206:33] posNoWhite:[206:32] Found pattern:[206:22->206:36] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:something], seenIdents: []) -[] +[{ + "label": "{}", + "kind": 4, + "tags": [], + "detail": "Empty record", + "documentation": null, + "sortText": "a" + }] Complete src/TypedContextCompletionSpec.res 210:22 posCursor:[210:22] posNoWhite:[210:20] Found expr:[210:3->210:30] @@ -421,1070 +816,1268 @@ Completable: Cpath Value[""] "kind": 12, "tags": [], "detail": "someVariant", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "x", "kind": 12, "tags": [], "detail": "option", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "someOtherValue", "kind": 12, "tags": [], "detail": "someRecordWithVariant", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "getSomeVal", "kind": 12, "tags": [], "detail": "(~irrelevant: int) => anotherRecord", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "someVal", "kind": 12, "tags": [], "detail": "anotherRecord", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Arg", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Array", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "ArrayLabels", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Auto", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_Array", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_Float", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_HashMap", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_HashMapInt", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_HashMapString", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_HashSet", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_HashSetInt", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_HashSetString", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_Id", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_Int", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_List", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_Map", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_MapDict", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_MapInt", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_MapString", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_MutableMap", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_MutableMapInt", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_MutableMapString", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_MutableQueue", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_MutableSet", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_MutableSetInt", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_MutableSetString", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_MutableStack", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_Option", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_Range", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_Result", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_Set", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_SetDict", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_SetInt", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_SetString", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_SortArray", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_SortArrayInt", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_SortArrayString", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_internalAVLset", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_internalAVLtree", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_internalBuckets", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_internalBucketsType", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_internalMapInt", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_internalMapString", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_internalSetBuckets", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_internalSetInt", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_internalSetString", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Belt_internals", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Buffer", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Bytes", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "BytesLabels", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Callback", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "CamlinternalLazy", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "CamlinternalMod", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Char", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "CodeLens", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "CompletePrioritize1", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "CompletePrioritize2", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Completion", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Complex", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Component", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "CreateInterface", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Cross", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Dce", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Debug", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Definition", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "DefinitionWithInterface", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Digest", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Div", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "DocumentSymbol", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Dom", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Dom_storage", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Dom_storage2", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Filename", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Fragment", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Genlex", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Hashtbl", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "HashtblLabels", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Highlight", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Hover", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "InlayHint", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Int32", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Int64", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_OO", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_array", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_array2", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_bigint", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_cast", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_console", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_date", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_dict", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_exn", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_float", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_global", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_int", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_json", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_list", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_mapperRt", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_math", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_null", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_null_undefined", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_obj", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_option", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_promise", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_re", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_result", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_string", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_string2", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_typed_array", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_typed_array2", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_types", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_undefined", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Js_vector", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Jsx", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Lazy", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Lexing", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "List", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "ListLabels", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "LongIdentTest", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Map", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "MapLabels", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "MoreLabels", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Node", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Node_buffer", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Node_child_process", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Node_fs", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Node_module", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Node_path", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Node_process", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Obj", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Object", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Parsing", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Patterns", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Pervasives", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Printexc", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Queue", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Random", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "React", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "ReactDOM", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "ReactDOMRe", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "ReactDOMServer", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "ReactDOMStyle", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "ReactEvent", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "ReactTestUtils", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "ReasonReact", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "RecModules", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "RecordCompletion", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "RecoveryOnProp", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "References", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "ReferencesWithInterface", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Rename", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "RenameWithInterface", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "RescriptReactErrorBoundary", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "RescriptReactRouter", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Set", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "SetLabels", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Sort", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Stack", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "StdLabels", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Stream", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "String", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "StringLabels", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Sys", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "TableclothMap", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "TypeContextCompletion_Jsx", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "TypeContextCompletion_LabelledArguments", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "TypeContextCompletion_Records", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "TypeDefinition", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "TypedContextCompletionSpec", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Uchar", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }, { "label": "Xform", "kind": 9, "tags": [], "detail": "file module", - "documentation": null + "documentation": null, + "sortText": null }] Complete src/TypedContextCompletionSpec.res 214:23 posCursor:[214:23] posNoWhite:[214:22] Found expr:[214:3->214:32] posCursor:[214:23] posNoWhite:[214:22] Found pattern:[214:22->214:24] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Switch, prefix:"", pattern: [], seenIdents: []) -[] +[{ + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }, { + "label": "anotherThing", + "kind": 5, + "tags": [], + "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }, { + "label": "thirdThing", + "kind": 5, + "tags": [], + "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 218:31 posCursor:[218:31] posNoWhite:[218:30] Found expr:[218:3->218:41] @@ -1498,7 +2091,28 @@ posCursor:[221:35] posNoWhite:[221:34] Found expr:[221:3->221:45] posCursor:[221:35] posNoWhite:[221:34] Found pattern:[221:22->221:37] posCursor:[221:35] posNoWhite:[221:34] Found pattern:[221:34->221:36] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordField, patternType:Switch, prefix:"", pattern: [RecordField:something], seenIdents: []) -[] +[{ + "label": "somethingElse", + "kind": 5, + "tags": [], + "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }, { + "label": "whatIsThis", + "kind": 5, + "tags": [], + "detail": "whatIsThis: bool\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }, { + "label": "anotherLevel", + "kind": 5, + "tags": [], + "detail": "anotherLevel: anotherLevel\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 225:38 posCursor:[225:38] posNoWhite:[225:37] Found expr:[225:3->225:50] @@ -1548,10 +2162,31 @@ posCursor:[241:55] posNoWhite:[241:53] Found expr:[241:3->241:67] posCursor:[241:55] posNoWhite:[241:53] Found pattern:[241:22->241:59] posCursor:[241:55] posNoWhite:[241:53] Found pattern:[241:34->241:59] Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:something, RecordField:whatIsThis], seenIdents: [false]) -[] +[{ + "label": "true", + "kind": 12, + "tags": [], + "detail": "boolean\n\n", + "documentation": null, + "sortText": null + }] Complete src/TypedContextCompletionSpec.res 245:49 posCursor:[245:49] posNoWhite:[245:46] Found expr:[245:3->245:51] Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [], seenIdents: [One, Two, Three]) -[] +[{ + "label": "Four(_)", + "kind": 4, + "tags": [], + "detail": "Four(someOtherVariant)\n\n", + "documentation": null, + "sortText": null + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(someOtherVariant, someVariant)\n\n", + "documentation": null, + "sortText": null + }] From 5d69adbd3d25c4b5c485e190e7b1e6ca17497b82 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 16 Aug 2022 11:08:21 +0200 Subject: [PATCH 63/80] complete clean up of the old way of doing pattern completion --- analysis/src/CompletionBackEnd.ml | 156 --------- analysis/src/CompletionFrontEnd.ml | 303 +----------------- analysis/src/SharedTypes.ml | 22 -- .../TypeContextCompletion_Jsx.res.txt | 237 ++------------ ...ontextCompletion_LabelledArguments.res.txt | 248 ++------------ .../TypedContextCompletionSpec.res.txt | 2 +- 6 files changed, 80 insertions(+), 888 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 6a2504b4c..1bd7c2a7d 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -2149,159 +2149,3 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i Completion.createWithSortText ~name:"{}" ~env ~sortText:"a" ~kind:(Completion.Label "Empty record"); ])) - | CtypedContextPattern - {howToRetrieveSourceType; patternPath; meta = {prefix; alreadySeenIdents}} - -> ( - let prefix = - match prefix with - | None -> "" - | Some prefix -> prefix - in - let sourceType = - howToRetrieveSourceType - |> findSourceType ~package ~opens ~rawOpens ~allFiles ~env ~pos ~scope - in - let nestedContextPath = patternPath in - match sourceType with - | None -> [] - | Some typ -> ( - match typ |> findTypeInContext ~env ~nestedContextPath ~package with - | None -> [] - | Some CBool -> - ["false"; "true"] - |> List.filter (fun boolEntry -> - Utils.startsWith boolEntry prefix - && not - (alreadySeenIdents - |> List.exists (fun seenIdent -> seenIdent = boolEntry))) - |> List.map (fun boolEntry -> - Completion.create ~name:boolEntry ~kind:Bool ~env) - | Some (COptional completable) -> ( - match completable with - | CVariant {constructors} -> - (* TOOD: Unify with other variant completion handler *) - let constructorCompletions = - constructors - |> List.filter (fun constructor -> - Utils.startsWith - ("Some(" ^ constructor.Constructor.cname.txt ^ ")") - prefix - && not - (alreadySeenIdents - |> List.exists (fun alreadySeenConstructorName -> - alreadySeenConstructorName - = constructor.Constructor.cname.txt))) - |> List.map (fun (constructor : Constructor.t) -> - (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? - Eg. Some($1) as completion item. *) - Completion.create - ~name: - ("Some(" ^ constructor.cname.txt - ^ - if constructor.args |> List.length > 0 then "(_))" - else ")") - ~kind:(Constructor (constructor, "")) - ~env) - in - (* TODO: Patterns should not include local completions *) - let _localCompletions = - typ - |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix - ~exact:false ~opens ~scope - in - [Completion.create ~name:"None" ~kind:OptionNone ~env] - @ constructorCompletions - | CPolyVariant {constructors} -> - (* TOOD: Unify with other variant completion handler *) - let constructorCompletions = - constructors - |> List.filter (fun constructor -> - Utils.startsWith ("Some(#" ^ constructor.name ^ ")") prefix) - |> List.map (fun constructor -> - (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? - Eg. Some($1) as completion item. *) - Completion.create - ~name: - ("Some(#" ^ constructor.name - ^ - if constructor.payload |> Option.is_some then "(_))" - else ")") - ~kind:(PolyvariantConstructor constructor) ~env) - in - (* TODO: Patterns should not include local completions *) - let _localCompletions = - typ - |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix - ~exact:false ~opens ~scope - in - [Completion.create ~name:"None" ~kind:OptionNone ~env] - @ constructorCompletions - | _ -> - [ - Completion.create ~name:"None" ~kind:OptionNone ~env; - Completion.create ~name:"Some(_)" ~kind:OptionSome ~env; - ]) - | Some (CPolyVariant {constructors}) -> - let constructorCompletions = - constructors - |> List.filter (fun constructor -> - Utils.startsWith constructor.name prefix) - |> List.map (fun constructor -> - (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? - Eg. Some($1) as completion item. *) - Completion.create - ~name: - ("#" ^ constructor.name - ^ - if constructor.payload |> Option.is_some then "(_)" else "" - ) - ~kind:(PolyvariantConstructor constructor) ~env) - in - let _localCompletions = - typ - |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix ~exact:false - ~opens ~scope - in - constructorCompletions - | Some (CVariant {constructors}) -> - let constructorCompletions = - constructors - |> List.filter (fun constructor -> - Utils.startsWith constructor.Constructor.cname.txt prefix - && not - (alreadySeenIdents - |> List.exists (fun alreadySeenConstructorName -> - alreadySeenConstructorName - = constructor.Constructor.cname.txt))) - |> List.map (fun (constructor : Constructor.t) -> - (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? - Eg. Some($1) as completion item. *) - Completion.create - ~name: - (constructor.cname.txt - ^ if constructor.args |> List.length > 0 then "(_)" else "" - ) - ~kind:(Constructor (constructor, "")) - ~env) - in - let _localCompletions = - typ - |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix ~exact:false - ~opens ~scope - in - constructorCompletions - | Some (CRecord {fields; decl; name}) -> - fields - |> List.filter (fun (field : field) -> - not - (alreadySeenIdents - |> List.exists (fun fieldName -> fieldName = field.fname.txt))) - |> Utils.filterMap (fun (field : field) -> - if prefix = "" || checkName field.fname.txt ~prefix ~exact:false - then - Some - (Completion.create ~name:field.fname.txt ~env - ~kind: - (Completion.Field - (field, decl |> Shared.declToString name.txt))) - else None))) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index f83d6143f..d767b5c1e 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -27,21 +27,6 @@ let positionToOffset text (line, character) = if bol + character <= String.length text then Some (bol + character) else None -let getIdentFromExpr exp = - match exp.Parsetree.pexp_desc with - | Pexp_ident {txt} -> txt - | Pexp_construct ({txt}, _) -> txt - | Pexp_variant (label, _) -> Lident label - | Pexp_field (_, {txt}) -> txt - | _ -> Lident "" - -let canDoTypedCompletionOnExpr exp = - match exp.Parsetree.pexp_desc with - | Pexp_construct _ | Pexp_variant _ - | Pexp_extension ({txt = "rescript.exprhole"}, _) -> - true - | _ -> false - let rec getSimpleFieldName txt = match txt with | Longident.Lident fieldName -> fieldName @@ -96,193 +81,6 @@ let rec findAllOrBranches pat ~branches = pat1 |> findAllOrBranches ~branches:([pat2] @ branches) | _ -> [pat] @ branches -let findAlreadySeenIdents pat = - match pat.Parsetree.ppat_desc with - | Ppat_or (pat1, pat2) -> - let rec findAllOrBranches pat ~branches = - match pat.Parsetree.ppat_desc with - | Ppat_or (pat1, pat2) -> - pat1 |> findAllOrBranches ~branches:([pat2] @ branches) - | _ -> [pat] @ branches - in - let branches = pat1 |> findAllOrBranches ~branches:[pat2] in - branches |> List.filter_map (fun branchPat -> identFromPat branchPat) - | _ -> [] - -let rec findCompletableInPattern pattern ~path ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite ~seenIdents = - match - pattern.Parsetree.ppat_loc - |> CursorPosition.classifyLoc ~pos:posBeforeCursor - with - | NoCursor -> None - | EmptyLoc -> ( - (* An empty location means the parser likely recovered from parsing an erronous pattern. - If we have at least one entry in the path list already, we know that we've at least - found _some_ context. We check that context and the char before the cursor to figure - out if we should complete for that path. *) - match (path, firstCharBeforeCursorNoWhite) with - (* Handles: One | Two | *) - | _ :: _, Some '|' -> - seenIdents := findAlreadySeenIdents pattern; - Some path (* Handles: {someField: } *) - | _ -> None) - | HasCursor -> ( - match pattern.ppat_desc with - | Ppat_construct ({txt = Lident "()"}, None) -> - (* A constructor without a payload mean we've reached an end. The parser parses SomeVariant() like above. *) - prefix := ""; - Some path - | Ppat_construct ({txt}, None) -> - (* A constructor without a payload mean we've reached an end. *) - prefix := getSimpleFieldName txt; - Some path - | Ppat_construct ({txt}, Some constructorPayload) -> ( - match - findVariantPayloadItemNumWithCursor constructorPayload - ~pos:posBeforeCursor - with - | None -> None - | Some (index, pat) -> - seenIdents := findAlreadySeenIdents pat; - pat - |> findCompletableInPattern - ~path: - ([ - Completable.Variant - { - constructorName = getSimpleFieldName txt; - payloadNum = Some index; - }; - ] - @ path) - ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~prefix ~seenIdents) - | Ppat_variant (label, None) -> - (* A constructor without a payload mean we've reached an end. *) - prefix := label; - Some path - | Ppat_variant (label, Some constructorPayload) -> ( - match - findVariantPayloadItemNumWithCursor constructorPayload - ~pos:posBeforeCursor - with - | None -> None - | Some (index, pat) -> - seenIdents := findAlreadySeenIdents pat; - pat - |> findCompletableInPattern - ~path: - ([ - Completable.Polyvariant {name = label; payloadNum = Some index}; - ] - @ path) - ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~prefix ~seenIdents) - | Ppat_tuple patterns -> ( - let tupleItemNum = ref 0 in - let patternWithCursor = - patterns - |> List.find_map (fun pat -> - let currentItemNum = !tupleItemNum in - tupleItemNum := !tupleItemNum + 1; - match - pat.Parsetree.ppat_loc - |> CursorPosition.classifyLoc ~pos:posBeforeCursor - with - | HasCursor | EmptyLoc -> Some (currentItemNum, pat) - | NoCursor -> None) - in - match patternWithCursor with - | None -> None - | Some (tupleItemNum, pat) -> - seenIdents := []; - pat - |> findCompletableInPattern ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite ~seenIdents - ~path:([Completable.PTuple {itemNumber = tupleItemNum}] @ path)) - | Ppat_record (fields, _) when List.length fields = 0 -> Some path - | Ppat_record (fields, _) -> ( - let seenFields = - fields |> List.map (fun ({Location.txt}, _) -> getSimpleFieldName txt) - in - let fieldWithCursor = - fields - |> List.find_map (fun (loc, fieldPat) -> - match - fieldPat.Parsetree.ppat_loc - |> CursorPosition.classifyLoc ~pos:posBeforeCursor - with - | NoCursor -> None - | HasCursor | EmptyLoc -> Some (loc, fieldPat)) - in - match fieldWithCursor with - | None -> - if firstCharBeforeCursorNoWhite = Some ',' then ( - seenIdents := seenFields; - Some path) - else None - | Some (loc, pat) -> - let fieldName = getSimpleFieldName loc.txt in - seenIdents := seenFields |> List.filter (fun name -> name <> fieldName); - - let newPath = - match pat.ppat_desc with - | Ppat_var {txt} when txt = fieldName -> - (* let {something} = whatever <- shorthand for let {something:something}, which is just an alias, - so we don't want to consider it entering the record field. *) - path - | _ -> [Completable.RField {fieldName}] @ path - in - pat - |> findCompletableInPattern ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite ~seenIdents ~path:newPath) - | Ppat_var {txt} -> - prefix := txt; - Some path - | Ppat_or (pat1, pat2) -> ( - seenIdents := findAlreadySeenIdents pattern; - - let branches = pat1 |> findAllOrBranches ~branches:[pat2] in - let branchAtCursor = - branches - |> List.find_opt (fun pat -> - match - pat.Parsetree.ppat_loc - |> CursorPosition.classifyLoc ~pos:posBeforeCursor - with - | HasCursor -> true - | EmptyLoc | NoCursor -> false) - in - match branchAtCursor with - | None -> None - | Some pat -> - pat - |> findCompletableInPattern ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite ~path ~seenIdents) - | _ -> None) - -let completePattern pattern ~howToRetrieveSourceType ~posBeforeCursor - ~firstCharBeforeCursorNoWhite ~seenIdents = - let prefix = ref "" in - let seenIdents = ref seenIdents in - let nestedContextPath = - pattern - |> findCompletableInPattern ~path:[] ~posBeforeCursor ~prefix - ~firstCharBeforeCursorNoWhite ~seenIdents - in - match nestedContextPath with - | Some nestedContextPath -> - Some - (Completable.CtypedContextPattern - { - howToRetrieveSourceType; - patternPath = nestedContextPath |> List.rev; - meta = {prefix = Some !prefix; alreadySeenIdents = !seenIdents}; - }) - | _ -> None - -(* This is probably wrong and we should likely use the full Longident instead for the prefix. *) -let getPrefixFromExpr exp = getIdentFromExpr exp |> Longident.last - (* Extracted for reuse. *) let rec exprToContextPath (e : Parsetree.expression) = match e.pexp_desc with @@ -343,47 +141,13 @@ let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName None else if prop.exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then (* Cursor on expr assigned *) - if canDoTypedCompletionOnExpr prop.exp then - Some - (Completable.CtypedContextPattern - { - howToRetrieveSourceType = - JsxProp - { - componentPath = - Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; - propName = prop.name; - }; - patternPath = []; - meta = - { - prefix = Some (getPrefixFromExpr prop.exp); - alreadySeenIdents = []; - }; - }) - else None + (* TODO: Add expr completion *) + None else if prop.exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then (* Expr assigned presumably is "rescript.exprhole" after parser recovery. Complete for the value. *) - if canDoTypedCompletionOnExpr prop.exp then - Some - (Completable.CtypedContextPattern - { - howToRetrieveSourceType = - JsxProp - { - componentPath = - Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt; - propName = prop.name; - }; - patternPath = []; - meta = - { - prefix = Some (getPrefixFromExpr prop.exp); - alreadySeenIdents = []; - }; - }) - else None + (* TODO: Add expr completion *) + None else loop rest | [] -> let beforeChildrenStart = @@ -452,8 +216,7 @@ type label = labelled option type arg = {label: label; exp: Parsetree.expression} let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor - ~(contextPath : Completable.contextPath) ~posAfterFunExpr - ~firstCharBeforeCursorNoWhite = + ~(contextPath : Completable.contextPath) ~posAfterFunExpr = let allNames = List.fold_right (fun arg allLabels -> @@ -473,9 +236,6 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor else if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then (* Ok, were completing in the expression. Inspect what the expression is. *) (* TODO: Apply the same thing to JSX *) - let howToRetrieveTheTypeForThisArg = - Completable.NamedArg {contextPath; label = labelled.name} - in match exp.pexp_desc with | Pexp_fun _ -> ( (* If this is a function expression, there might be function argument patterns we can @@ -504,50 +264,15 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor in match findTargetArg exp with | None -> None - | Some (arg, argPattern) -> - let completable = - argPattern - |> completePattern - ~howToRetrieveSourceType: - (Completable.FunctionArgument - { - howToFindFunctionType = howToRetrieveTheTypeForThisArg; - arg; - }) - ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~seenIdents:[] - in - completable) + | Some (_arg, _argPattern) -> (* TODO: Add expr completion *) None) | _ -> - if canDoTypedCompletionOnExpr exp then - Some - (Completable.CtypedContextPattern - { - howToRetrieveSourceType = howToRetrieveTheTypeForThisArg; - patternPath = []; - meta = - { - prefix = Some (getPrefixFromExpr exp); - alreadySeenIdents = []; - }; - }) - else None + (* TODO: Add expr completion *) + None else if exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then (* Expr assigned presumably is "rescript.exprhole" after parser recovery. Assume this is an empty expression. *) - if canDoTypedCompletionOnExpr exp then - Some - (Completable.CtypedContextPattern - { - howToRetrieveSourceType = - NamedArg {contextPath; label = labelled.name}; - patternPath = []; - meta = - { - prefix = Some (getPrefixFromExpr exp); - alreadySeenIdents = []; - }; - }) - else None + (* TODO: Add expr completion *) + None else loop rest | {label = None; exp} :: rest -> if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then None @@ -1042,11 +767,6 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = Depending on if the destructure is nested or not, we may or may not use that directly.*) match exprToContextPath expr with | None -> () - | Some contextPath when false -> - setResultOpt - (pvb_pat - |> completePattern ~howToRetrieveSourceType:(CtxPath contextPath) - ~posBeforeCursor ~firstCharBeforeCursorNoWhite ~seenIdents:[]) | Some contextPath -> ( match findContextInPattern pvb_pat ~firstCharBeforeCursorNoWhite @@ -1057,7 +777,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | Some res -> setResultOpt (Some - (CtypedPattern + (Completable.CtypedPattern { howToRetrieveSourceType = CtxPath contextPath; patternPath = res.patternPath |> List.rev; @@ -1314,7 +1034,6 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | Some contextPath -> findNamedArgCompletable ~contextPath ~args ~endPos:(Loc.end_ expr.pexp_loc) ~posBeforeCursor - ~firstCharBeforeCursorNoWhite ~posAfterFunExpr:(Loc.end_ funExpr.pexp_loc) | None -> None in diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index e9ef3d8ea..8de9c945c 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -579,12 +579,6 @@ module Completable = struct | Cpath of contextPath | Cjsx of string list * string * string list (** E.g. (["M", "Comp"], "id", ["id1", "id2"]) for "Cnone" | Cjsx (sl1, s, sl2) -> "Cjsx(" ^ (sl1 |> list) ^ ", " ^ str s ^ ", " ^ (sl2 |> list) ^ ")" - | CtypedContextPattern - { - howToRetrieveSourceType; - meta = {prefix; alreadySeenIdents}; - patternPath; - } -> - ("CtypedContextPattern(" - ^ (howToRetrieveSourceType |> howToRetrieveSourceTypeToString) - ^ ")=" - ^ - match prefix with - | None -> "" - | Some prefix -> str prefix) - ^ " pattern: " - ^ (patternPath |> patternContextPathToString) - ^ " seenIdents: " ^ list alreadySeenIdents | CtypedPattern { howToRetrieveSourceType; diff --git a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt index 44948b045..9b99934c1 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt @@ -14,115 +14,59 @@ Completable: Cjsx([SomeComponent], someVaria, [someVaria]) Complete src/TypeContextCompletion_Jsx.res 23:38 posCursor:[23:38] posNoWhite:[23:37] Found expr:[23:12->23:38] JSX 23:25] someVariant[23:26->23:37]=...__ghost__[0:-1->0:-1]> _children:None -Completable: CtypedContextPattern(JsxProp())="" pattern: [] seenIdents: [] -[{ - "label": "One", - "kind": 4, - "tags": [], - "detail": "One\n\n", - "documentation": null, - "sortText": null - }, { - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\n", - "documentation": null, - "sortText": null - }, { - "label": "Three", - "kind": 4, - "tags": [], - "detail": "Three\n\n", - "documentation": null, - "sortText": null - }, { - "label": "Four", - "kind": 4, - "tags": [], - "detail": "Four\n\n", - "documentation": null, - "sortText": null - }, { - "label": "Five(_)", - "kind": 4, - "tags": [], - "detail": "Five(int)\n\n", - "documentation": null, - "sortText": null - }, { - "label": "Six(_)", - "kind": 4, - "tags": [], - "detail": "Six(option, int)\n\n", - "documentation": null, - "sortText": null - }] +[] Complete src/TypeContextCompletion_Jsx.res 26:39 posCursor:[26:39] posNoWhite:[26:37] Found expr:[26:12->26:38] JSX 26:25] someVariant[26:26->26:37]=...__ghost__[0:-1->0:-1]> _children:None -Completable: CtypedContextPattern(JsxProp())="" pattern: [] seenIdents: [] +[] + +Complete src/TypeContextCompletion_Jsx.res 29:39 +posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:12->29:39] +JSX 29:25] someVariant[29:26->29:37]=...[29:38->29:39]> _children:None +posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:38->29:39] +Pexp_construct T:[29:38->29:39] None +Completable: Cpath Value[T] [{ - "label": "One", - "kind": 4, + "label": "TableclothMap", + "kind": 9, "tags": [], - "detail": "One\n\n", + "detail": "file module", "documentation": null, "sortText": null }, { - "label": "Two", - "kind": 4, + "label": "TypeContextCompletion_Jsx", + "kind": 9, "tags": [], - "detail": "Two\n\n", + "detail": "file module", "documentation": null, "sortText": null }, { - "label": "Three", - "kind": 4, + "label": "TypeContextCompletion_LabelledArguments", + "kind": 9, "tags": [], - "detail": "Three\n\n", + "detail": "file module", "documentation": null, "sortText": null }, { - "label": "Four", - "kind": 4, - "tags": [], - "detail": "Four\n\n", - "documentation": null, - "sortText": null - }, { - "label": "Five(_)", - "kind": 4, + "label": "TypeContextCompletion_Records", + "kind": 9, "tags": [], - "detail": "Five(int)\n\n", + "detail": "file module", "documentation": null, "sortText": null }, { - "label": "Six(_)", - "kind": 4, - "tags": [], - "detail": "Six(option, int)\n\n", - "documentation": null, - "sortText": null - }] - -Complete src/TypeContextCompletion_Jsx.res 29:39 -posCursor:[29:39] posNoWhite:[29:38] Found expr:[29:12->29:39] -JSX 29:25] someVariant[29:26->29:37]=...[29:38->29:39]> _children:None -Completable: CtypedContextPattern(JsxProp())=T pattern: [] seenIdents: [] -[{ - "label": "Two", - "kind": 4, + "label": "TypeDefinition", + "kind": 9, "tags": [], - "detail": "Two\n\n", + "detail": "file module", "documentation": null, "sortText": null }, { - "label": "Three", - "kind": 4, + "label": "TypedContextCompletionSpec", + "kind": 9, "tags": [], - "detail": "Three\n\n", + "detail": "file module", "documentation": null, "sortText": null }] @@ -138,142 +82,27 @@ Completable: Cpath Value[t] Complete src/TypeContextCompletion_Jsx.res 35:39 posCursor:[35:39] posNoWhite:[35:38] Found expr:[35:12->35:39] JSX 35:25] anotherThing[35:26->35:38]=...__ghost__[0:-1->0:-1]> _children:None -Completable: CtypedContextPattern(JsxProp())="" pattern: [] seenIdents: [] -[{ - "label": "Foo", - "kind": 4, - "tags": [], - "detail": "Foo\n\n", - "documentation": null, - "sortText": null - }, { - "label": "Bar", - "kind": 4, - "tags": [], - "detail": "Bar\n\n", - "documentation": null, - "sortText": null - }] +[] Complete src/TypeContextCompletion_Jsx.res 38:37 posCursor:[38:37] posNoWhite:[38:36] Found expr:[38:12->38:37] JSX 38:25] thirdThing[38:26->38:36]=...__ghost__[0:-1->0:-1]> _children:None -Completable: CtypedContextPattern(JsxProp())="" pattern: [] seenIdents: [] -[{ - "label": "#one", - "kind": 4, - "tags": [], - "detail": "#one", - "documentation": null, - "sortText": null - }, { - "label": "#six(_)", - "kind": 4, - "tags": [], - "detail": "#six(option, int)", - "documentation": null, - "sortText": null - }, { - "label": "#three", - "kind": 4, - "tags": [], - "detail": "#three", - "documentation": null, - "sortText": null - }, { - "label": "#two", - "kind": 4, - "tags": [], - "detail": "#two", - "documentation": null, - "sortText": null - }, { - "label": "#five(_)", - "kind": 4, - "tags": [], - "detail": "#five(int)", - "documentation": null, - "sortText": null - }, { - "label": "#four", - "kind": 4, - "tags": [], - "detail": "#four", - "documentation": null, - "sortText": null - }] +[] Complete src/TypeContextCompletion_Jsx.res 41:38 posCursor:[41:38] posNoWhite:[41:36] Found expr:[41:12->41:37] JSX 41:25] thirdThing[41:26->41:36]=...__ghost__[0:-1->0:-1]> _children:None -Completable: CtypedContextPattern(JsxProp())="" pattern: [] seenIdents: [] -[{ - "label": "#one", - "kind": 4, - "tags": [], - "detail": "#one", - "documentation": null, - "sortText": null - }, { - "label": "#six(_)", - "kind": 4, - "tags": [], - "detail": "#six(option, int)", - "documentation": null, - "sortText": null - }, { - "label": "#three", - "kind": 4, - "tags": [], - "detail": "#three", - "documentation": null, - "sortText": null - }, { - "label": "#two", - "kind": 4, - "tags": [], - "detail": "#two", - "documentation": null, - "sortText": null - }, { - "label": "#five(_)", - "kind": 4, - "tags": [], - "detail": "#five(int)", - "documentation": null, - "sortText": null - }, { - "label": "#four", - "kind": 4, - "tags": [], - "detail": "#four", - "documentation": null, - "sortText": null - }] +[] Complete src/TypeContextCompletion_Jsx.res 44:39 posCursor:[44:39] posNoWhite:[44:38] Found expr:[44:12->44:39] JSX 44:25] thirdThing[44:26->44:36]=...[44:37->44:39]> _children:None -Completable: CtypedContextPattern(JsxProp())=t pattern: [] seenIdents: [] -[{ - "label": "#three", - "kind": 4, - "tags": [], - "detail": "#three", - "documentation": null, - "sortText": null - }, { - "label": "#two", - "kind": 4, - "tags": [], - "detail": "#two", - "documentation": null, - "sortText": null - }] +posCursor:[44:39] posNoWhite:[44:38] Found expr:[44:37->44:39] +[] Complete src/TypeContextCompletion_Jsx.res 47:39 posCursor:[47:39] posNoWhite:[47:38] Found expr:[47:12->47:39] JSX 47:25] thirdThing[47:26->47:36]=...[47:37->47:39]> _children:None -Completable: CtypedContextPattern(JsxProp())=T pattern: [] seenIdents: [] +posCursor:[47:39] posNoWhite:[47:38] Found expr:[47:37->47:39] [] diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index f2c344832..ef0446702 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -19,115 +19,59 @@ Found type for function ( Complete src/TypeContextCompletion_LabelledArguments.res 25:44 posCursor:[25:44] posNoWhite:[25:43] Found expr:[25:11->25:44] Pexp_apply ...[25:11->25:30] (~someVariant25:32->25:43=...__ghost__[0:-1->0:-1]) -Completable: CtypedContextPattern(NamedArg(someVariant, Value[someVariantToString]))="" pattern: [] seenIdents: [] -[{ - "label": "One", - "kind": 4, - "tags": [], - "detail": "One\n\n", - "documentation": null, - "sortText": null - }, { - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\n", - "documentation": null, - "sortText": null - }, { - "label": "Three", - "kind": 4, - "tags": [], - "detail": "Three\n\n", - "documentation": null, - "sortText": null - }, { - "label": "Four", - "kind": 4, - "tags": [], - "detail": "Four\n\n", - "documentation": null, - "sortText": null - }, { - "label": "Five(_)", - "kind": 4, - "tags": [], - "detail": "Five(int)\n\n", - "documentation": null, - "sortText": null - }, { - "label": "Six(_)", - "kind": 4, - "tags": [], - "detail": "Six(option, int)\n\n", - "documentation": null, - "sortText": null - }] +[] Complete src/TypeContextCompletion_LabelledArguments.res 28:45 posCursor:[28:45] posNoWhite:[28:43] Found expr:[28:11->28:44] Pexp_apply ...[28:11->28:30] (~someVariant28:32->28:43=...__ghost__[0:-1->0:-1]) -Completable: CtypedContextPattern(NamedArg(someVariant, Value[someVariantToString]))="" pattern: [] seenIdents: [] +[] + +Complete src/TypeContextCompletion_LabelledArguments.res 31:45 +posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:11->31:45] +Pexp_apply ...[31:11->31:30] (~someVariant31:32->31:43=...[31:44->31:45]) +posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:44->31:45] +Pexp_construct T:[31:44->31:45] None +Completable: Cpath Value[T] [{ - "label": "One", - "kind": 4, + "label": "TableclothMap", + "kind": 9, "tags": [], - "detail": "One\n\n", + "detail": "file module", "documentation": null, "sortText": null }, { - "label": "Two", - "kind": 4, + "label": "TypeContextCompletion_Jsx", + "kind": 9, "tags": [], - "detail": "Two\n\n", + "detail": "file module", "documentation": null, "sortText": null }, { - "label": "Three", - "kind": 4, + "label": "TypeContextCompletion_LabelledArguments", + "kind": 9, "tags": [], - "detail": "Three\n\n", + "detail": "file module", "documentation": null, "sortText": null }, { - "label": "Four", - "kind": 4, + "label": "TypeContextCompletion_Records", + "kind": 9, "tags": [], - "detail": "Four\n\n", + "detail": "file module", "documentation": null, "sortText": null }, { - "label": "Five(_)", - "kind": 4, + "label": "TypeDefinition", + "kind": 9, "tags": [], - "detail": "Five(int)\n\n", + "detail": "file module", "documentation": null, "sortText": null }, { - "label": "Six(_)", - "kind": 4, - "tags": [], - "detail": "Six(option, int)\n\n", - "documentation": null, - "sortText": null - }] - -Complete src/TypeContextCompletion_LabelledArguments.res 31:45 -posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:11->31:45] -Pexp_apply ...[31:11->31:30] (~someVariant31:32->31:43=...[31:44->31:45]) -Completable: CtypedContextPattern(NamedArg(someVariant, Value[someVariantToString]))=T pattern: [] seenIdents: [] -[{ - "label": "Two", - "kind": 4, - "tags": [], - "detail": "Two\n\n", - "documentation": null, - "sortText": null - }, { - "label": "Three", - "kind": 4, + "label": "TypedContextCompletionSpec", + "kind": 9, "tags": [], - "detail": "Three\n\n", + "detail": "file module", "documentation": null, "sortText": null }] @@ -207,157 +151,35 @@ Completable: Cpath Value[TypeDefinition, ""] Complete src/TypeContextCompletion_LabelledArguments.res 40:45 posCursor:[40:45] posNoWhite:[40:44] Found expr:[40:11->40:45] Pexp_apply ...[40:11->40:30] (~anotherThing40:32->40:44=...__ghost__[0:-1->0:-1]) -Completable: CtypedContextPattern(NamedArg(anotherThing, Value[someVariantToString]))="" pattern: [] seenIdents: [] -[{ - "label": "Foo", - "kind": 4, - "tags": [], - "detail": "Foo\n\n", - "documentation": null, - "sortText": null - }, { - "label": "Bar", - "kind": 4, - "tags": [], - "detail": "Bar\n\n", - "documentation": null, - "sortText": null - }] +[] Complete src/TypeContextCompletion_LabelledArguments.res 43:43 posCursor:[43:43] posNoWhite:[43:42] Found expr:[43:11->43:43] Pexp_apply ...[43:11->43:30] (~thirdThing43:32->43:42=...__ghost__[0:-1->0:-1]) -Completable: CtypedContextPattern(NamedArg(thirdThing, Value[someVariantToString]))="" pattern: [] seenIdents: [] -[{ - "label": "#one", - "kind": 4, - "tags": [], - "detail": "#one", - "documentation": null, - "sortText": null - }, { - "label": "#six(_)", - "kind": 4, - "tags": [], - "detail": "#six(option, int)", - "documentation": null, - "sortText": null - }, { - "label": "#three", - "kind": 4, - "tags": [], - "detail": "#three", - "documentation": null, - "sortText": null - }, { - "label": "#two", - "kind": 4, - "tags": [], - "detail": "#two", - "documentation": null, - "sortText": null - }, { - "label": "#five(_)", - "kind": 4, - "tags": [], - "detail": "#five(int)", - "documentation": null, - "sortText": null - }, { - "label": "#four", - "kind": 4, - "tags": [], - "detail": "#four", - "documentation": null, - "sortText": null - }] +[] Complete src/TypeContextCompletion_LabelledArguments.res 46:44 posCursor:[46:44] posNoWhite:[46:42] Found expr:[46:11->46:43] Pexp_apply ...[46:11->46:30] (~thirdThing46:32->46:42=...__ghost__[0:-1->0:-1]) -Completable: CtypedContextPattern(NamedArg(thirdThing, Value[someVariantToString]))="" pattern: [] seenIdents: [] -[{ - "label": "#one", - "kind": 4, - "tags": [], - "detail": "#one", - "documentation": null, - "sortText": null - }, { - "label": "#six(_)", - "kind": 4, - "tags": [], - "detail": "#six(option, int)", - "documentation": null, - "sortText": null - }, { - "label": "#three", - "kind": 4, - "tags": [], - "detail": "#three", - "documentation": null, - "sortText": null - }, { - "label": "#two", - "kind": 4, - "tags": [], - "detail": "#two", - "documentation": null, - "sortText": null - }, { - "label": "#five(_)", - "kind": 4, - "tags": [], - "detail": "#five(int)", - "documentation": null, - "sortText": null - }, { - "label": "#four", - "kind": 4, - "tags": [], - "detail": "#four", - "documentation": null, - "sortText": null - }] +[] Complete src/TypeContextCompletion_LabelledArguments.res 49:45 posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:11->49:45] Pexp_apply ...[49:11->49:30] (~thirdThing49:32->49:42=...[49:43->49:45]) -Completable: CtypedContextPattern(NamedArg(thirdThing, Value[someVariantToString]))=t pattern: [] seenIdents: [] -[{ - "label": "#three", - "kind": 4, - "tags": [], - "detail": "#three", - "documentation": null, - "sortText": null - }, { - "label": "#two", - "kind": 4, - "tags": [], - "detail": "#two", - "documentation": null, - "sortText": null - }] +posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:43->49:45] +[] Complete src/TypeContextCompletion_LabelledArguments.res 52:45 posCursor:[52:45] posNoWhite:[52:44] Found expr:[52:11->52:45] Pexp_apply ...[52:11->52:30] (~thirdThing52:32->52:42=...[52:43->52:45]) -Completable: CtypedContextPattern(NamedArg(thirdThing, Value[someVariantToString]))=T pattern: [] seenIdents: [] +posCursor:[52:45] posNoWhite:[52:44] Found expr:[52:43->52:45] [] Complete src/TypeContextCompletion_LabelledArguments.res 64:36 posCursor:[64:36] posNoWhite:[64:35] Found expr:[64:11->64:47] Pexp_apply ...[64:11->64:18] (~doThing64:20->64:27=...[64:28->64:46]) +posCursor:[64:36] posNoWhite:[64:35] Found expr:[64:28->64:46] posCursor:[64:36] posNoWhite:[64:35] Found pattern:[64:29->64:37] posCursor:[64:36] posNoWhite:[64:35] Found pattern:[64:35->64:36] -Completable: CtypedContextPattern(FunctionArgument(fnSource:NamedArg(doThing, Value[doStuff]), arg:unlabelled(0)))=n pattern: [] seenIdents: [age] -[{ - "label": "name", - "kind": 5, - "tags": [], - "detail": "name: string\n\ntype someRecord = {age: int, name: string}", - "documentation": null, - "sortText": null - }] +[] diff --git a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt index 30beade22..7a6ed1a05 100644 --- a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt +++ b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt @@ -182,9 +182,9 @@ Pstr_value( Complete src/TypedContextCompletionSpec.res 93:36 posCursor:[93:36] posNoWhite:[93:35] Found expr:[93:11->93:47] Pexp_apply ...[93:11->93:18] (~doThing93:20->93:27=...[93:28->93:46]) +posCursor:[93:36] posNoWhite:[93:35] Found expr:[93:28->93:46] posCursor:[93:36] posNoWhite:[93:35] Found pattern:[93:29->93:37] posCursor:[93:36] posNoWhite:[93:35] Found pattern:[93:35->93:36] -Completable: CtypedContextPattern(FunctionArgument(fnSource:NamedArg(doThing, Value[doStuff]), arg:unlabelled(0)))=n pattern: [] seenIdents: [age] [] Complete src/TypedContextCompletionSpec.res 97:15 From f06111956e8ff3a13f37989ba2f2f0c81dc48e32 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 16 Aug 2022 11:13:59 +0200 Subject: [PATCH 64/80] simplify --- analysis/src/CompletionBackEnd.ml | 8 ++------ analysis/src/CompletionFrontEnd.ml | 14 ++++---------- analysis/src/SharedTypes.ml | 24 ++++++++---------------- 3 files changed, 14 insertions(+), 32 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 1bd7c2a7d..958c11ac7 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1985,13 +1985,9 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i patternPath; patternType; lookingToComplete; - meta = {prefix; alreadySeenIdents}; + prefix; + alreadySeenIdents; } -> ( - let prefix = - match prefix with - | None -> "" - | Some prefix -> prefix - in let sourceType = howToRetrieveSourceType |> findSourceType ~package ~opens ~rawOpens ~allFiles ~env ~pos ~scope diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index d767b5c1e..92b59cbcf 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -783,11 +783,8 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = patternPath = res.patternPath |> List.rev; patternType = Destructure; lookingToComplete = res.lookingToComplete; - meta = - { - prefix = Some res.prefix; - alreadySeenIdents = res.alreadySeenIdents; - }; + prefix = res.prefix; + alreadySeenIdents = res.alreadySeenIdents; })))) | _ -> ()); bindings |> List.iter (fun vb -> iterator.value_binding iterator vb); @@ -1147,11 +1144,8 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = patternPath = res.patternPath |> List.rev; patternType = Switch; lookingToComplete = res.lookingToComplete; - meta = - { - prefix = Some res.prefix; - alreadySeenIdents = res.alreadySeenIdents; - }; + prefix = res.prefix; + alreadySeenIdents = res.alreadySeenIdents; })))) | _ -> ()); if not !processed then Ast_iterator.default_iterator.expr iterator expr diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 8de9c945c..245c4d2e7 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -562,15 +562,6 @@ module Completable = struct ^ (arg |> functionArgumentToString) ^ ")" - type typedContextMeta = { - (* What the user has already started writing, if anything. *) - prefix: string option; - (* Record fields already written by the user, etc. - This is contextual of course, but putting it here in the general type to simplify things. *) - (* TODO: Clarify that this is only for patterns (?). If so, move it to something more obvious. *) - alreadySeenIdents: string list; - } - type t = | Cdecorator of string (** e.g. @module *) | CnamedArg of contextPath * string * string list @@ -584,7 +575,11 @@ module Completable = struct patternPath: patternPathItem list; patternType: patternCompletionType; lookingToComplete: lookingToComplete; - meta: typedContextMeta; + (* What the user has already started writing, if anything. *) + prefix: string; + (* Record fields already written by the user, etc. + This is contextual of course, but putting it here in the general type to simplify things. *) + alreadySeenIdents: string list; } let toString = function @@ -600,7 +595,8 @@ module Completable = struct | CtypedPattern { howToRetrieveSourceType; - meta = {prefix; alreadySeenIdents}; + prefix; + alreadySeenIdents; patternPath; lookingToComplete; patternType; @@ -611,11 +607,7 @@ module Completable = struct ^ lookingToCompleteToString lookingToComplete ^ ", patternType:" ^ patternCompletionTypeToString patternType - ^ ", prefix:" - ^ - match prefix with - | None -> "" - | Some prefix -> str prefix) + ^ ", prefix:" ^ str prefix) ^ ", pattern: " ^ (patternPath |> patternContextPathToString) ^ ", seenIdents: " ^ list alreadySeenIdents ^ ")" From 82796f98e270cd4d22b2d9ff6f83c693d3c33847 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 16 Aug 2022 12:31:47 +0200 Subject: [PATCH 65/80] complete empty tuples --- analysis/src/CompletionBackEnd.ml | 17 ++++++++++++++++ .../tests/src/TypedContextCompletionSpec.res | 3 +++ .../TypedContextCompletionSpec.res.txt | 20 +++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 958c11ac7..6c5e0afd0 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1050,6 +1050,7 @@ let rec extractRecordType ~env ~package (t : Types.type_expr) = | _ -> None (* Had to add another type level here to cover that polyvariants are inlined into to the type system. Mostly a temporary solution. *) +(* TODO: This has overlap with Declared, which is confusing. *) type extractedType = | Declared of QueryEnv.t * Type.t Declared.t | Polyvariant of QueryEnv.t * SharedTypes.polyVariantConstructor list @@ -1442,6 +1443,7 @@ type completable = | CVariant of {constructors: Constructor.t list} | CPolyVariant of {constructors: polyVariantConstructor list} | COptional of completable + | CTuple of {types: Types.type_expr list} | CBool let rec typeExprToCompletable typ ~env ~package = @@ -1456,6 +1458,8 @@ let rec typeExprToCompletable typ ~env ~package = match typ |> typeExprToCompletable ~env ~package with | None -> None | Some typ -> Some (COptional typ)) + | Some (Declared (_, {item = {kind = Abstract _}})) -> None + | Some (Tuple (_, types)) -> Some (CTuple {types}) | _ -> None (* Takes a type_expr and figures out what completable it corresponds to, if any. If the target type is nested somewhere inside of the type_expr, @@ -2000,6 +2004,19 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i lookingToComplete ) with | None, _ -> [] + + | Some (CTuple {types}), _ -> + (* Completing a tuple itself, like `{someFieldWithTuple: }` *) + [ + Completion.createWithSortText + ~name: + ("(" + ^ (types |> List.map (fun _t -> "_") |> String.concat ", ") + ^ ")") + ~env ~sortText:"a" ~kind:(Completion.Label "Full tuple match"); + Completion.createWithSortText ~name:"()" ~env ~sortText:"b" + ~kind:(Completion.Label "Empty tuple match for single element"); + ] | Some CBool, _ -> (* Completing booleans - doesn't matter what we're looking to complete, since there's only one thing to complete (the bool values themselves). *) ["false"; "true"] diff --git a/analysis/tests/src/TypedContextCompletionSpec.res b/analysis/tests/src/TypedContextCompletionSpec.res index 3c655ba1e..c781e5457 100644 --- a/analysis/tests/src/TypedContextCompletionSpec.res +++ b/analysis/tests/src/TypedContextCompletionSpec.res @@ -246,4 +246,7 @@ let y = One // switch y { | One | Two => () | Three => () | } // ^com +// switch someOtherValue { | {thirdStuff: } => () | } +// ^com + // --- Pattern matching end --- diff --git a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt index 7a6ed1a05..154bfb59f 100644 --- a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt +++ b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt @@ -2190,3 +2190,23 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "sortText": null }] +Complete src/TypedContextCompletionSpec.res 248:41 +posCursor:[248:41] posNoWhite:[248:40] Found expr:[248:3->248:55] +posCursor:[248:41] posNoWhite:[248:40] Found pattern:[248:29->248:43] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:thirdStuff], seenIdents: []) +[{ + "label": "(_, _, _, _)", + "kind": 4, + "tags": [], + "detail": "Full tuple match", + "documentation": null, + "sortText": "a" + }, { + "label": "()", + "kind": 4, + "tags": [], + "detail": "Empty tuple match for single element", + "documentation": null, + "sortText": "b" + }] + From 6a0a884c13c66ed9a369ea10b374f8fa80bc4722 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 16 Aug 2022 15:02:29 +0200 Subject: [PATCH 66/80] introduce snippets --- analysis/src/Cli.ml | 11 +- analysis/src/Commands.ml | 10 +- analysis/src/CompletionBackEnd.ml | 133 +- analysis/src/CompletionFrontEnd.ml | 10 + analysis/src/Protocol.ml | 21 +- analysis/src/SharedTypes.ml | 11 +- .../src/TypeContextCompletion_Records.res | 3 + .../src/expected/CompletePrioritize1.res.txt | 4 +- .../src/expected/CompletePrioritize2.res.txt | 25 +- .../tests/src/expected/Completion.res.txt | 1380 +++++------------ analysis/tests/src/expected/Cross.res.txt | 5 +- analysis/tests/src/expected/Debug.res.txt | 42 +- analysis/tests/src/expected/Div.res.txt | 4 +- analysis/tests/src/expected/Hover.res.txt | 4 +- analysis/tests/src/expected/Jsx.res.txt | 504 ++---- analysis/tests/src/expected/Jsx.resi.txt | 8 +- .../src/expected/RecordCompletion.res.txt | 24 +- .../tests/src/expected/RecoveryOnProp.res.txt | 23 +- .../TypeContextCompletion_Jsx.res.txt | 28 +- ...ontextCompletion_LabelledArguments.res.txt | 64 +- .../TypeContextCompletion_Records.res.txt | 262 +++- .../TypedContextCompletionSpec.res.txt | 980 +++++++++--- server/src/server.ts | 23 +- 23 files changed, 1718 insertions(+), 1861 deletions(-) diff --git a/analysis/src/Cli.ml b/analysis/src/Cli.ml index 90b82b1c8..3e71a6acf 100644 --- a/analysis/src/Cli.ml +++ b/analysis/src/Cli.ml @@ -3,7 +3,7 @@ let help = **Private CLI For rescript-vscode usage only** API examples: - ./rescript-editor-analysis.exe completion src/MyFile.res 0 4 currentContent.res + ./rescript-editor-analysis.exe completion src/MyFile.res 0 4 currentContent.res true ./rescript-editor-analysis.exe definition src/MyFile.res 9 3 ./rescript-editor-analysis.exe typeDefinition src/MyFile.res 9 3 ./rescript-editor-analysis.exe documentSymbol src/Foo.res @@ -24,8 +24,9 @@ https://microsoft.github.io/language-server-protocol/specification#position Options: completion: compute autocomplete for MyFile.res at line 0 and column 4, where MyFile.res is being edited and the editor content is in file current.res. + The final boolean indicates whether the completion should return snippets or not. - ./rescript-editor-analysis.exe completion src/MyFile.res 0 4 current.res + ./rescript-editor-analysis.exe completion src/MyFile.res 0 4 current.res true definition: get definition for item in MyFile.res at line 10 column 2: @@ -82,10 +83,14 @@ Options: let main () = match Array.to_list Sys.argv with - | [_; "completion"; path; line; col; currentFile] -> + | [_; "completion"; path; line; col; currentFile; supportsSnippets] -> Commands.completion ~debug:false ~path ~pos:(int_of_string line, int_of_string col) ~currentFile + ~supportsSnippets: + (match supportsSnippets with + | "true" -> true + | _ -> false) | [_; "definition"; path; line; col] -> Commands.definition ~path ~pos:(int_of_string line, int_of_string col) diff --git a/analysis/src/Commands.ml b/analysis/src/Commands.ml index 42f1489dc..82ce646e7 100644 --- a/analysis/src/Commands.ml +++ b/analysis/src/Commands.ml @@ -21,10 +21,18 @@ let getCompletions ~debug ~path ~pos ~currentFile ~forHover = |> CompletionBackEnd.processCompletable ~debug ~package ~pos ~scope ~env ~forHover)) -let completion ~debug ~path ~pos ~currentFile = +let completion ~debug ~path ~pos ~currentFile ~supportsSnippets = print_endline (getCompletions ~debug ~path ~pos ~currentFile ~forHover:false |> List.map CompletionBackEnd.completionToItem + |> List.map (fun completionItem -> + if supportsSnippets then completionItem + else + { + completionItem with + Protocol.insertText = None; + insertTextFormat = None; + }) |> List.map Protocol.stringifyCompletionItem |> Protocol.array) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 6c5e0afd0..3fa3b7e6f 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -558,7 +558,8 @@ let completionForExporteds iterExported getDeclared ~prefix ~exact ~env res := { (Completion.create ~name:declared.name.txt ~env - ~kind:(transformContents declared.item)) + ~kind:(transformContents declared.item) + ()) with deprecated = declared.deprecated; docstring = declared.docstring; @@ -600,7 +601,8 @@ let completionsForExportedConstructors ~(env : QueryEnv.t) ~prefix ~exact (Completion.create ~name ~env ~kind: (Completion.Constructor - (c, t.item.decl |> Shared.declToString t.name.txt))) + (c, t.item.decl |> Shared.declToString t.name.txt)) + ()) else None)) @ !res | _ -> ()); @@ -622,7 +624,8 @@ let completionForExportedFields ~(env : QueryEnv.t) ~prefix ~exact ~namesUsed = (Completion.create ~name ~env ~kind: (Completion.Field - (f, t.item.decl |> Shared.declToString t.name.txt))) + (f, t.item.decl |> Shared.declToString t.name.txt)) + ()) else None)) @ !res | _ -> ()); @@ -801,7 +804,7 @@ let processLocalValue name loc ~prefix ~exact ~env localTables.resultRev <- { (Completion.create ~name:declared.name.txt ~env - ~kind:(Value declared.item)) + ~kind:(Value declared.item) ()) with deprecated = declared.deprecated; docstring = declared.docstring; @@ -818,6 +821,7 @@ let processLocalValue name loc ~prefix ~exact ~env (Ctype.newconstr (Path.Pident (Ident.create "Type Not Known")) [])) + () :: localTables.resultRev let processLocalConstructor name loc ~prefix ~exact ~env @@ -836,7 +840,8 @@ let processLocalConstructor name loc ~prefix ~exact ~env (Constructor ( declared.item, snd declared.item.typeDecl - |> Shared.declToString (fst declared.item.typeDecl) ))) + |> Shared.declToString (fst declared.item.typeDecl) )) + ()) with deprecated = declared.deprecated; docstring = declared.docstring; @@ -857,7 +862,7 @@ let processLocalType name loc ~prefix ~exact ~env ~(localTables : LocalTables.t) localTables.resultRev <- { (Completion.create ~name:declared.name.txt ~env - ~kind:(Type declared.item)) + ~kind:(Type declared.item) ()) with deprecated = declared.deprecated; docstring = declared.docstring; @@ -878,7 +883,7 @@ let processLocalModule name loc ~prefix ~exact ~env localTables.resultRev <- { (Completion.create ~name:declared.name.txt ~env - ~kind:(Module declared.item)) + ~kind:(Module declared.item) ()) with deprecated = declared.deprecated; docstring = declared.docstring; @@ -1145,7 +1150,7 @@ let getCompletionsForPath ~package ~opens ~allFiles ~pos ~exact ~scope then Some (Completion.create ~name ~env - ~kind:(Completion.FileModule name)) + ~kind:(Completion.FileModule name) ()) else None) in localCompletionsWithOpens @ fileModules @@ -1158,7 +1163,8 @@ let getCompletionsForPath ~package ~opens ~allFiles ~pos ~exact ~scope findAllCompletions ~env ~prefix ~exact ~namesUsed ~completionContext | None -> []) -let mkItem ~name ~sortText ~kind ~detail ~deprecated ~docstring = +let mkItem ~name ~sortText ~insertText ~insertTextFormat ~kind ~detail + ~deprecated ~docstring = let docContent = (match deprecated with | None -> "" @@ -1183,10 +1189,21 @@ let mkItem ~name ~sortText ~kind ~detail ~deprecated ~docstring = (if docContent = "" then None else Some {kind = "markdown"; value = docContent}); sortText; + insertText; + insertTextFormat; } -let completionToItem {Completion.name; deprecated; docstring; kind; sortText} = - mkItem ~name ~sortText +let completionToItem + { + Completion.name; + deprecated; + docstring; + kind; + sortText; + insertText; + insertTextFormat; + } = + mkItem ~name ~sortText ~insertText ~insertTextFormat ~kind:(Completion.kindToInt kind) ~deprecated ~detail:(detail name kind) ~docstring @@ -1204,14 +1221,16 @@ let rec getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos Completion.create ~name:"string" ~env ~kind: (Completion.Value - (Ctype.newconstr (Path.Pident (Ident.create "string")) [])); + (Ctype.newconstr (Path.Pident (Ident.create "string")) [])) + (); ] | CPArray -> [ Completion.create ~name:"array" ~env ~kind: (Completion.Value - (Ctype.newconstr (Path.Pident (Ident.create "array")) [])); + (Ctype.newconstr (Path.Pident (Ident.create "array")) [])) + (); ] | CPId (path, completionContext) -> path @@ -1255,7 +1274,10 @@ let rec getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos | args, tRet when args <> [] -> let args = processApply args labels in let retType = reconstructFunctionType args tRet in - [Completion.create ~name:"dummy" ~env ~kind:(Completion.Value retType)] + [ + Completion.create ~name:"dummy" ~env ~kind:(Completion.Value retType) + (); + ] | _ -> []) | None -> []) | CPField (CPId (path, Module), fieldName) -> @@ -1282,7 +1304,8 @@ let rec getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos (Completion.Field ( field, typDecl.item.decl - |> Shared.declToString typDecl.name.txt ))) + |> Shared.declToString typDecl.name.txt )) + ()) else None) | None -> []) | None -> []) @@ -1310,7 +1333,7 @@ let rec getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos if checkName field ~prefix:label ~exact then Some (Completion.create ~name:field ~env - ~kind:(Completion.ObjLabel typ)) + ~kind:(Completion.ObjLabel typ) ()) else None) | None -> []) | None -> []) @@ -1679,7 +1702,7 @@ let processCompletable ~debug ~package ~scope ~env ~pos ~forHover ~env ~exact:forHover ~scope | Cjsx ([id], prefix, identsSeen) when String.uncapitalize_ascii id = id -> let mkLabel (name, typString) = - Completion.create ~name ~kind:(Label typString) ~env + Completion.create ~name ~kind:(Label typString) ~env () in let keyLabels = if Utils.startsWith "key" prefix then [mkLabel ("key", "string")] else [] @@ -1696,7 +1719,7 @@ let processCompletable ~debug ~package ~scope ~env ~pos ~forHover |> getLabelsForComponent ~package ~opens ~allFiles ~pos ~env ~scope in let mkLabel_ name typString = - Completion.create ~name ~kind:(Label typString) ~env + Completion.create ~name ~kind:(Label typString) ~env () in let mkLabel (name, typ) = mkLabel_ name (typ |> Shared.typeToString) in let keyLabels = @@ -1712,7 +1735,7 @@ let processCompletable ~debug ~package ~scope ~env ~pos ~forHover @ keyLabels | Cdecorator prefix -> let mkDecorator (name, docstring) = - {(Completion.create ~name ~kind:(Label "") ~env) with docstring} + {(Completion.create ~name ~kind:(Label "") ~env ()) with docstring} in [ ( "as", @@ -1976,7 +1999,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i | None -> [] in let mkLabel (name, typ) = - Completion.create ~name ~kind:(Label (typ |> Shared.typeToString)) ~env + Completion.create ~name ~kind:(Label (typ |> Shared.typeToString)) ~env () in labels |> List.filter (fun (name, _t) -> @@ -1987,11 +2010,11 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i { howToRetrieveSourceType; patternPath; - patternType; lookingToComplete; prefix; alreadySeenIdents; } -> ( + let prefix = if prefix = "_" then "" else prefix in let sourceType = howToRetrieveSourceType |> findSourceType ~package ~opens ~rawOpens ~allFiles ~env ~pos ~scope @@ -2004,18 +2027,26 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i lookingToComplete ) with | None, _ -> [] - | Some (CTuple {types}), _ -> (* Completing a tuple itself, like `{someFieldWithTuple: }` *) [ - Completion.createWithSortText + Completion.create ~name: ("(" ^ (types |> List.map (fun _t -> "_") |> String.concat ", ") ^ ")") - ~env ~sortText:"a" ~kind:(Completion.Label "Full tuple match"); - Completion.createWithSortText ~name:"()" ~env ~sortText:"b" - ~kind:(Completion.Label "Empty tuple match for single element"); + ~insertText: + ("(" + ^ (types + |> List.mapi (fun index _t -> + Printf.sprintf "${%i:_}" (index + 1)) + |> String.concat ", ") + ^ ")") + ~insertTextFormat:Snippet ~env ~sortText:"a" + ~kind:(Completion.Label "Full tuple match") (); + Completion.create ~name:"()" ~env ~sortText:"b" ~insertText:"($1)" + ~insertTextFormat:Snippet + ~kind:(Completion.Label "Empty tuple match for single element") (); ] | Some CBool, _ -> (* Completing booleans - doesn't matter what we're looking to complete, since there's only one thing to complete (the bool values themselves). *) @@ -2026,7 +2057,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i (alreadySeenIdents |> List.exists (fun seenIdent -> seenIdent = boolEntry))) |> List.map (fun boolEntry -> - Completion.create ~name:boolEntry ~kind:Bool ~env) + Completion.create ~name:boolEntry ~kind:Bool ~env ()) | Some (COptional completable), _lookingToComplete -> ( (* TODO: Account for lookingToComplete? *) match completable with @@ -2052,8 +2083,14 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i ^ if constructor.args |> List.length > 0 then "(_))" else ")") + ~insertText: + ("Some(" ^ constructor.cname.txt + ^ + if constructor.args |> List.length > 0 then "(${1:_}))" + else ")") + ~insertTextFormat:Snippet ~kind:(Constructor (constructor, "")) - ~env) + ~env ()) in (* TODO: Patterns should not include local completions *) let _localCompletions = @@ -2061,7 +2098,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix ~exact:false ~opens ~scope in - [Completion.create ~name:"None" ~kind:OptionNone ~env] + [Completion.create ~name:"None" ~kind:OptionNone ~env ()] @ constructorCompletions | CPolyVariant {constructors} -> (* TOOD: Unify with other variant completion handler *) @@ -2078,7 +2115,13 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i ^ if constructor.payload |> Option.is_some then "(_))" else ")") - ~kind:(PolyvariantConstructor constructor) ~env) + ~insertTextFormat:Snippet + ~insertText: + ("Some(#" ^ constructor.name + ^ + if constructor.payload |> Option.is_some then "(${1:_}))" + else ")") + ~kind:(PolyvariantConstructor constructor) ~env ()) in (* TODO: Patterns should not include local completions *) let _localCompletions = @@ -2086,12 +2129,13 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix ~exact:false ~opens ~scope in - [Completion.create ~name:"None" ~kind:OptionNone ~env] + [Completion.create ~name:"None" ~kind:OptionNone ~env ()] @ constructorCompletions | _ -> [ - Completion.create ~name:"None" ~kind:OptionNone ~env; - Completion.create ~name:"Some(_)" ~kind:OptionSome ~env; + Completion.create ~name:"None" ~kind:OptionNone ~env (); + Completion.create ~name:"Some(_)" ~insertText:"Some(${1:_})" + ~insertTextFormat:Snippet ~kind:OptionSome ~env (); ]) | Some (CPolyVariant {constructors}), _ -> let constructorCompletions = @@ -2107,7 +2151,13 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i ^ if constructor.payload |> Option.is_some then "(_)" else "" ) - ~kind:(PolyvariantConstructor constructor) ~env) + ~insertText: + ("#" ^ constructor.name + ^ + if constructor.payload |> Option.is_some then "(${1:_})" + else "") + ~insertTextFormat:Snippet + ~kind:(PolyvariantConstructor constructor) ~env ()) in let _localCompletions = typ @@ -2133,8 +2183,14 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i (constructor.cname.txt ^ if constructor.args |> List.length > 0 then "(_)" else "" ) + ~insertTextFormat:Snippet + ~insertText: + (constructor.cname.txt + ^ + if constructor.args |> List.length > 0 then "(${1:_})" + else "") ~kind:(Constructor (constructor, "")) - ~env) + ~env ()) in let _localCompletions = typ @@ -2155,10 +2211,11 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i (Completion.create ~name:field.fname.txt ~env ~kind: (Completion.Field - (field, decl |> Shared.declToString name.txt))) + (field, decl |> Shared.declToString name.txt)) + ()) else None) | Some (CRecord _), _ -> [ - Completion.createWithSortText ~name:"{}" ~env ~sortText:"a" - ~kind:(Completion.Label "Empty record"); + Completion.create ~name:"{}" ~insertText:"{${1}}" ~insertTextFormat:Snippet ~env ~sortText:"a" + ~kind:(Completion.Label "Empty record") (); ])) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 92b59cbcf..38011a30c 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -333,6 +333,16 @@ let rec findTupleItemWithCursor items ~index ~pos = let rec findContextInPattern pattern ~pos ~patternPath ~debug ~seenIdentsFromParent ~firstCharBeforeCursorNoWhite = match pattern.Parsetree.ppat_desc with + | Ppat_any -> + (* E.g. something: _ *) + (* We hijack the any pattern some here, and interpret that as an "empty" completion. *) + Some + { + lookingToComplete = CNoContext; + patternPath; + prefix = ""; + alreadySeenIdents = seenIdentsFromParent; + } | Ppat_extension ({txt = "rescript.patternhole"}, _) -> (* This is printed when the parser has made recovery. E.g. `| Something => () | ` *) diff --git a/analysis/src/Protocol.ml b/analysis/src/Protocol.ml index 04fdb7b3f..82b13026f 100644 --- a/analysis/src/Protocol.ml +++ b/analysis/src/Protocol.ml @@ -16,12 +16,22 @@ type inlayHint = { paddingRight: bool; } +(* https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#insertTextFormat *) +type insertTextFormat = PlainText | Snippet + +let insertTextFormatToInt f = + match f with + | PlainText -> 1 + | Snippet -> 2 + type completionItem = { label: string; kind: int; tags: int list; detail: string; sortText: string option; + insertTextFormat: insertTextFormat option; + insertText: string option; documentation: markupContent option; } @@ -73,7 +83,9 @@ let stringifyCompletionItem c = "tags": %s, "detail": "%s", "documentation": %s, - "sortText": %s + "sortText": %s, + "insertText": %s, + "insertTextFormat": %s }|} (Json.escape c.label) c.kind (c.tags |> List.map string_of_int |> array) @@ -84,6 +96,13 @@ let stringifyCompletionItem c = (match c.sortText with | None -> null | Some sortText -> Printf.sprintf "\"%s\"" (Json.escape sortText)) + (match c.insertText with + | None -> null + | Some insertText -> Printf.sprintf "\"%s\"" (Json.escape insertText)) + (match c.insertTextFormat with + | None -> null + | Some insertTextFormat -> + Printf.sprintf "%i" (insertTextFormatToInt insertTextFormat)) let stringifyHover s = Printf.sprintf {|{"contents": "%s"}|} (Json.escape s) diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 245c4d2e7..69a2a3bb6 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -240,23 +240,24 @@ module Completion = struct type t = { name: string; sortText: string option; + insertText: string option; + insertTextFormat: Protocol.insertTextFormat option; env: QueryEnv.t; deprecated: string option; docstring: string list; kind: kind; } - let create ~name ~kind ~env = - {name; env; deprecated = None; docstring = []; kind; sortText = None} - - let createWithSortText ~name ~kind ~env ~sortText = + let create ~name ?sortText ?insertText ?insertTextFormat ~kind ~env () = { name; env; deprecated = None; docstring = []; kind; - sortText = Some sortText; + sortText; + insertText; + insertTextFormat; } (* https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion *) diff --git a/analysis/tests/src/TypeContextCompletion_Records.res b/analysis/tests/src/TypeContextCompletion_Records.res index f34730a76..2bbf711db 100644 --- a/analysis/tests/src/TypeContextCompletion_Records.res +++ b/analysis/tests/src/TypeContextCompletion_Records.res @@ -144,3 +144,6 @@ let y = One // Should complete because the record has braces // switch someVal { | {something: {} } => () } // ^com + +// switch someOtherValue { | {fourthStuff: (_, _)} => () } +// ^com diff --git a/analysis/tests/src/expected/CompletePrioritize1.res.txt b/analysis/tests/src/expected/CompletePrioritize1.res.txt index c1ec4a7cc..eced522e2 100644 --- a/analysis/tests/src/expected/CompletePrioritize1.res.txt +++ b/analysis/tests/src/expected/CompletePrioritize1.res.txt @@ -7,6 +7,8 @@ Completable: Cpath Value[a]-> "tags": [], "detail": "float => float", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] diff --git a/analysis/tests/src/expected/CompletePrioritize2.res.txt b/analysis/tests/src/expected/CompletePrioritize2.res.txt index 8c8cbef44..7d62533c1 100644 --- a/analysis/tests/src/expected/CompletePrioritize2.res.txt +++ b/analysis/tests/src/expected/CompletePrioritize2.res.txt @@ -1,25 +1,10 @@ Complete src/CompletePrioritize2.res 9:7 posCursor:[9:7] posNoWhite:[9:6] Found expr:[9:3->0:-1] -Completable: Cpath Value[ax]-> -[{ - "label": "Test.add", - "kind": 12, - "tags": [], - "detail": "t => int", - "documentation": null, - "sortText": null - }] +Completable: CtypedPattern(sourceType:Value[ax], lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/CompletePrioritize2.res 12:5 -posCursor:[12:5] posNoWhite:[12:4] Found expr:[12:3->12:5] -Pexp_ident ax:[12:3->12:5] -Completable: Cpath Value[ax] -[{ - "label": "ax", - "kind": 12, - "tags": [], - "detail": "Test.t", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[ax], lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index 71d2a3de5..69fb03e35 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -8,77 +8,99 @@ Completable: Cpath Value[MyList, m] "tags": [], "detail": "(t<'a>, 'a => 'b) => t<'b>", "documentation": {"kind": "markdown", "value": "\n Equivalent to:\n\n ```res\n map(someList, f)->reverse\n ```\n\n ```res example\n list{3, 4, 5}->Belt.List.mapReverse(x => x * x) /* list{25, 16, 9} */\n ```\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "makeBy", "kind": 12, "tags": [], "detail": "(int, int => 'a) => t<'a>", "documentation": {"kind": "markdown", "value": "\nReturn a list of length `numItems` with element `i` initialized with `f(i)`.\nReturns an empty list if `numItems` is negative.\n\n```res example\nBelt.List.makeBy(5, i => i) // list{0, 1, 2, 3, 4}\n\nBelt.List.makeBy(5, i => i * i) // list{0, 1, 4, 9, 16}\n```\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "make", "kind": 12, "tags": [], "detail": "(int, 'a) => t<'a>", "documentation": {"kind": "markdown", "value": "\n Returns a list of length `numItems` with each element filled with value `v`. Returns an empty list if `numItems` is negative.\n\n ```res example\n Belt.List.make(3, 1) // list{1, 1, 1}\n ```\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "mapReverse2U", "kind": 12, "tags": [], "detail": "(t<'a>, t<'b>, (. 'a, 'b) => 'c) => t<'c>", "documentation": {"kind": "markdown", "value": " Uncurried version of [mapReverse2](#mapReverse2). "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "map", "kind": 12, "tags": [], "detail": "(t<'a>, 'a => 'b) => t<'b>", "documentation": {"kind": "markdown", "value": "\n Returns a new list with `f` applied to each element of `someList`.\n\n ```res example\n list{1, 2}->Belt.List.map(x => x + 1) // list{3, 4}\n ```\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "mapWithIndexU", "kind": 12, "tags": [], "detail": "(t<'a>, (. int, 'a) => 'b) => t<'b>", "documentation": {"kind": "markdown", "value": " Uncurried version of [mapWithIndex](#mapWithIndex). "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "mapU", "kind": 12, "tags": [], "detail": "(t<'a>, (. 'a) => 'b) => t<'b>", "documentation": {"kind": "markdown", "value": " Uncurried version of [map](#map). "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "makeByU", "kind": 12, "tags": [], "detail": "(int, (. int) => 'a) => t<'a>", "documentation": {"kind": "markdown", "value": " Uncurried version of [makeBy](#makeBy) "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "mapReverse2", "kind": 12, "tags": [], "detail": "(t<'a>, t<'b>, ('a, 'b) => 'c) => t<'c>", "documentation": {"kind": "markdown", "value": "\n Equivalent to: `zipBy(xs, ys, f)->reverse`\n\n ```res example\n\n Belt.List.mapReverse2(list{1, 2, 3}, list{1, 2}, (a, b) => a + b) // list{4, 2}\n ```\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "mapWithIndex", "kind": 12, "tags": [], "detail": "(t<'a>, (int, 'a) => 'b) => t<'b>", "documentation": {"kind": "markdown", "value": "\n Applies `f` to each element of `someList`.\n Function `f` takes two arguments: the index starting from 0 and the element from `someList`, in that order.\n\n ```res example\n list{1, 2, 3}->Belt.List.mapWithIndex((index, x) => index + x) // list{1, 3, 5}\n ```\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "mapReverseU", "kind": 12, "tags": [], "detail": "(t<'a>, (. 'a) => 'b) => t<'b>", "documentation": {"kind": "markdown", "value": " Uncurried version of [mapReverse](#mapReverse). "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/Completion.res 3:9 @@ -91,252 +113,324 @@ Completable: Cpath Value[Array, ""] "tags": [], "detail": "(('a, 'b) => 'a, 'a, array<'b>) => 'a", "documentation": {"kind": "markdown", "value": " [Array.fold_left f x a] computes\n [f (... (f (f x a.(0)) a.(1)) ...) a.(n-1)],\n where [n] is the length of the array [a]. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "concat", "kind": 12, "tags": [], "detail": "list> => array<'a>", "documentation": {"kind": "markdown", "value": " Same as {!Array.append}, but concatenates a list of arrays. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "mapi", "kind": 12, "tags": [], "detail": "((int, 'a) => 'b, array<'a>) => array<'b>", "documentation": {"kind": "markdown", "value": " Same as {!Array.map}, but the\n function is applied to the index of the element as first argument,\n and the element itself as second argument. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "exists", "kind": 12, "tags": [], "detail": "('a => bool, array<'a>) => bool", "documentation": {"kind": "markdown", "value": " [Array.exists p [|a1; ...; an|]] checks if at least one element of\n the array satisfies the predicate [p]. That is, it returns\n [(p a1) || (p a2) || ... || (p an)].\n @since 4.03.0 "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "for_all", "kind": 12, "tags": [], "detail": "('a => bool, array<'a>) => bool", "documentation": {"kind": "markdown", "value": " [Array.for_all p [|a1; ...; an|]] checks if all elements of the array\n satisfy the predicate [p]. That is, it returns\n [(p a1) && (p a2) && ... && (p an)].\n @since 4.03.0 "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "copy", "kind": 12, "tags": [], "detail": "array<'a> => array<'a>", "documentation": {"kind": "markdown", "value": " [Array.copy a] returns a copy of [a], that is, a fresh array\n containing the same elements as [a]. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "iter2", "kind": 12, "tags": [], "detail": "(('a, 'b) => unit, array<'a>, array<'b>) => unit", "documentation": {"kind": "markdown", "value": " [Array.iter2 f a b] applies function [f] to all the elements of [a]\n and [b].\n Raise [Invalid_argument] if the arrays are not the same size.\n @since 4.03.0 "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "to_list", "kind": 12, "tags": [], "detail": "array<'a> => list<'a>", "documentation": {"kind": "markdown", "value": " [Array.to_list a] returns the list of all the elements of [a]. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "stable_sort", "kind": 12, "tags": [], "detail": "(('a, 'a) => int, array<'a>) => unit", "documentation": {"kind": "markdown", "value": " Same as {!Array.sort}, but the sorting algorithm is stable (i.e.\n elements that compare equal are kept in their original order) and\n not guaranteed to run in constant heap space.\n\n The current implementation uses Merge Sort. It uses [n/2]\n words of heap space, where [n] is the length of the array.\n It is usually faster than the current implementation of {!Array.sort}.\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "iteri", "kind": 12, "tags": [], "detail": "((int, 'a) => unit, array<'a>) => unit", "documentation": {"kind": "markdown", "value": " Same as {!Array.iter}, but the\n function is applied with the index of the element as first argument,\n and the element itself as second argument. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "memq", "kind": 12, "tags": [], "detail": "('a, array<'a>) => bool", "documentation": {"kind": "markdown", "value": " Same as {!Array.mem}, but uses physical equality instead of structural\n equality to compare array elements.\n @since 4.03.0 "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "map2", "kind": 12, "tags": [], "detail": "(('a, 'b) => 'c, array<'a>, array<'b>) => array<'c>", "documentation": {"kind": "markdown", "value": " [Array.map2 f a b] applies function [f] to all the elements of [a]\n and [b], and builds an array with the results returned by [f]:\n [[| f a.(0) b.(0); ...; f a.(Array.length a - 1) b.(Array.length b - 1)|]].\n Raise [Invalid_argument] if the arrays are not the same size.\n @since 4.03.0 "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "set", "kind": 12, "tags": [], "detail": "(array<'a>, int, 'a) => unit", "documentation": {"kind": "markdown", "value": " [Array.set a n x] modifies array [a] in place, replacing\n element number [n] with [x].\n You can also write [a.(n) <- x] instead of [Array.set a n x].\n\n Raise [Invalid_argument \"index out of bounds\"]\n if [n] is outside the range 0 to [Array.length a - 1]. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "make", "kind": 12, "tags": [], "detail": "(int, 'a) => array<'a>", "documentation": {"kind": "markdown", "value": " [Array.make n x] returns a fresh array of length [n],\n initialized with [x].\n All the elements of this new array are initially\n physically equal to [x] (in the sense of the [==] predicate).\n Consequently, if [x] is mutable, it is shared among all elements\n of the array, and modifying [x] through one of the array entries\n will modify all other entries at the same time.\n\n Raise [Invalid_argument] if [n < 0] or [n > Sys.max_array_length].\n If the value of [x] is a floating-point number, then the maximum\n size is only [Sys.max_array_length / 2]."}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "make_float", "kind": 12, "tags": [], "detail": "int => array", "documentation": {"kind": "markdown", "value": " @deprecated [Array.make_float] is an alias for {!Array.create_float}. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "fold_right", "kind": 12, "tags": [], "detail": "(('b, 'a) => 'a, array<'b>, 'a) => 'a", "documentation": {"kind": "markdown", "value": " [Array.fold_right f a x] computes\n [f a.(0) (f a.(1) ( ... (f a.(n-1) x) ...))],\n where [n] is the length of the array [a]. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "sort", "kind": 12, "tags": [], "detail": "(('a, 'a) => int, array<'a>) => unit", "documentation": {"kind": "markdown", "value": " Sort an array in increasing order according to a comparison\n function. The comparison function must return 0 if its arguments\n compare as equal, a positive integer if the first is greater,\n and a negative integer if the first is smaller (see below for a\n complete specification). For example, {!Pervasives.compare} is\n a suitable comparison function, provided there are no floating-point\n NaN values in the data. After calling [Array.sort], the\n array is sorted in place in increasing order.\n [Array.sort] is guaranteed to run in constant heap space\n and (at most) logarithmic stack space.\n\n The current implementation uses Heap Sort. It runs in constant\n stack space.\n\n Specification of the comparison function:\n Let [a] be the array and [cmp] the comparison function. The following\n must be true for all x, y, z in a :\n- [cmp x y] > 0 if and only if [cmp y x] < 0\n- if [cmp x y] >= 0 and [cmp y z] >= 0 then [cmp x z] >= 0\n\n When [Array.sort] returns, [a] contains the same elements as before,\n reordered in such a way that for all i and j valid indices of [a] :\n- [cmp a.(i) a.(j)] >= 0 if and only if i >= j\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "length", "kind": 12, "tags": [], "detail": "array<'a> => int", "documentation": {"kind": "markdown", "value": " Return the length (number of elements) of the given array. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "sub", "kind": 12, "tags": [], "detail": "(array<'a>, int, int) => array<'a>", "documentation": {"kind": "markdown", "value": " [Array.sub a start len] returns a fresh array of length [len],\n containing the elements number [start] to [start + len - 1]\n of array [a].\n\n Raise [Invalid_argument \"Array.sub\"] if [start] and [len] do not\n designate a valid subarray of [a]; that is, if\n [start < 0], or [len < 0], or [start + len > Array.length a]. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "of_list", "kind": 12, "tags": [], "detail": "list<'a> => array<'a>", "documentation": {"kind": "markdown", "value": " [Array.of_list l] returns a fresh array containing the elements\n of [l]. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "iter", "kind": 12, "tags": [], "detail": "('a => unit, array<'a>) => unit", "documentation": {"kind": "markdown", "value": " [Array.iter f a] applies function [f] in turn to all\n the elements of [a]. It is equivalent to\n [f a.(0); f a.(1); ...; f a.(Array.length a - 1); ()]. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "map", "kind": 12, "tags": [], "detail": "('a => 'b, array<'a>) => array<'b>", "documentation": {"kind": "markdown", "value": " [Array.map f a] applies function [f] to all the elements of [a],\n and builds an array with the results returned by [f]:\n [[| f a.(0); f a.(1); ...; f a.(Array.length a - 1) |]]. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "unsafe_get", "kind": 12, "tags": [], "detail": "(array<'a>, int) => 'a", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "make_matrix", "kind": 12, "tags": [], "detail": "(int, int, 'a) => array>", "documentation": {"kind": "markdown", "value": " [Array.make_matrix dimx dimy e] returns a two-dimensional array\n (an array of arrays) with first dimension [dimx] and\n second dimension [dimy]. All the elements of this new matrix\n are initially physically equal to [e].\n The element ([x,y]) of a matrix [m] is accessed\n with the notation [m.(x).(y)].\n\n Raise [Invalid_argument] if [dimx] or [dimy] is negative or\n greater than {!Sys.max_array_length}.\n If the value of [e] is a floating-point number, then the maximum\n size is only [Sys.max_array_length / 2]. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "mem", "kind": 12, "tags": [], "detail": "('a, array<'a>) => bool", "documentation": {"kind": "markdown", "value": " [mem a l] is true if and only if [a] is equal\n to an element of [l].\n @since 4.03.0 "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "get", "kind": 12, "tags": [], "detail": "(array<'a>, int) => 'a", "documentation": {"kind": "markdown", "value": " [Array.get a n] returns the element number [n] of array [a].\n The first element has number 0.\n The last element has number [Array.length a - 1].\n You can also write [a.(n)] instead of [Array.get a n].\n\n Raise [Invalid_argument \"index out of bounds\"]\n if [n] is outside the range 0 to [(Array.length a - 1)]. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "append", "kind": 12, "tags": [], "detail": "(array<'a>, array<'a>) => array<'a>", "documentation": {"kind": "markdown", "value": " [Array.append v1 v2] returns a fresh array containing the\n concatenation of the arrays [v1] and [v2]. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "unsafe_set", "kind": 12, "tags": [], "detail": "(array<'a>, int, 'a) => unit", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "create_matrix", "kind": 12, "tags": [], "detail": "(int, int, 'a) => array>", "documentation": {"kind": "markdown", "value": " @deprecated [Array.create_matrix] is an alias for {!Array.make_matrix}. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "create_float", "kind": 12, "tags": [], "detail": "int => array", "documentation": {"kind": "markdown", "value": " [Array.create_float n] returns a fresh float array of length [n],\n with uninitialized data.\n @since 4.03 "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "create", "kind": 12, "tags": [], "detail": "(int, 'a) => array<'a>", "documentation": {"kind": "markdown", "value": " @deprecated [Array.create] is an alias for {!Array.make}. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "init", "kind": 12, "tags": [], "detail": "(int, int => 'a) => array<'a>", "documentation": {"kind": "markdown", "value": " [Array.init n f] returns a fresh array of length [n],\n with element number [i] initialized to the result of [f i].\n In other terms, [Array.init n f] tabulates the results of [f]\n applied to the integers [0] to [n-1].\n\n Raise [Invalid_argument] if [n < 0] or [n > Sys.max_array_length].\n If the return type of [f] is [float], then the maximum\n size is only [Sys.max_array_length / 2]."}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "fast_sort", "kind": 12, "tags": [], "detail": "(('a, 'a) => int, array<'a>) => unit", "documentation": {"kind": "markdown", "value": " Same as {!Array.sort} or {!Array.stable_sort}, whichever is faster\n on typical input.\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "fill", "kind": 12, "tags": [], "detail": "(array<'a>, int, int, 'a) => unit", "documentation": {"kind": "markdown", "value": " [Array.fill a ofs len x] modifies the array [a] in place,\n storing [x] in elements number [ofs] to [ofs + len - 1].\n\n Raise [Invalid_argument \"Array.fill\"] if [ofs] and [len] do not\n designate a valid subarray of [a]. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "blit", "kind": 12, "tags": [], "detail": "(array<'a>, int, array<'a>, int, int) => unit", "documentation": {"kind": "markdown", "value": " [Array.blit v1 o1 v2 o2 len] copies [len] elements\n from array [v1], starting at element number [o1], to array [v2],\n starting at element number [o2]. It works correctly even if\n [v1] and [v2] are the same array, and the source and\n destination chunks overlap.\n\n Raise [Invalid_argument \"Array.blit\"] if [o1] and [len] do not\n designate a valid subarray of [v1], or if [o2] and [len] do not\n designate a valid subarray of [v2]. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Floatarray", "kind": 9, "tags": [], "detail": "module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/Completion.res 5:10 @@ -349,56 +443,72 @@ Completable: Cpath Value[Array, m] "tags": [], "detail": "((int, 'a) => 'b, array<'a>) => array<'b>", "documentation": {"kind": "markdown", "value": " Same as {!Array.map}, but the\n function is applied to the index of the element as first argument,\n and the element itself as second argument. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "memq", "kind": 12, "tags": [], "detail": "('a, array<'a>) => bool", "documentation": {"kind": "markdown", "value": " Same as {!Array.mem}, but uses physical equality instead of structural\n equality to compare array elements.\n @since 4.03.0 "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "map2", "kind": 12, "tags": [], "detail": "(('a, 'b) => 'c, array<'a>, array<'b>) => array<'c>", "documentation": {"kind": "markdown", "value": " [Array.map2 f a b] applies function [f] to all the elements of [a]\n and [b], and builds an array with the results returned by [f]:\n [[| f a.(0) b.(0); ...; f a.(Array.length a - 1) b.(Array.length b - 1)|]].\n Raise [Invalid_argument] if the arrays are not the same size.\n @since 4.03.0 "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "make", "kind": 12, "tags": [], "detail": "(int, 'a) => array<'a>", "documentation": {"kind": "markdown", "value": " [Array.make n x] returns a fresh array of length [n],\n initialized with [x].\n All the elements of this new array are initially\n physically equal to [x] (in the sense of the [==] predicate).\n Consequently, if [x] is mutable, it is shared among all elements\n of the array, and modifying [x] through one of the array entries\n will modify all other entries at the same time.\n\n Raise [Invalid_argument] if [n < 0] or [n > Sys.max_array_length].\n If the value of [x] is a floating-point number, then the maximum\n size is only [Sys.max_array_length / 2]."}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "make_float", "kind": 12, "tags": [], "detail": "int => array", "documentation": {"kind": "markdown", "value": " @deprecated [Array.make_float] is an alias for {!Array.create_float}. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "map", "kind": 12, "tags": [], "detail": "('a => 'b, array<'a>) => array<'b>", "documentation": {"kind": "markdown", "value": " [Array.map f a] applies function [f] to all the elements of [a],\n and builds an array with the results returned by [f]:\n [[| f a.(0); f a.(1); ...; f a.(Array.length a - 1) |]]. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "make_matrix", "kind": 12, "tags": [], "detail": "(int, int, 'a) => array>", "documentation": {"kind": "markdown", "value": " [Array.make_matrix dimx dimy e] returns a two-dimensional array\n (an array of arrays) with first dimension [dimx] and\n second dimension [dimy]. All the elements of this new matrix\n are initially physically equal to [e].\n The element ([x,y]) of a matrix [m] is accessed\n with the notation [m.(x).(y)].\n\n Raise [Invalid_argument] if [dimx] or [dimy] is negative or\n greater than {!Sys.max_array_length}.\n If the value of [e] is a floating-point number, then the maximum\n size is only [Sys.max_array_length / 2]. "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "mem", "kind": 12, "tags": [], "detail": "('a, array<'a>) => bool", "documentation": {"kind": "markdown", "value": " [mem a l] is true if and only if [a] is equal\n to an element of [l].\n @since 4.03.0 "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/Completion.res 15:17 @@ -411,7 +521,9 @@ Completable: Cpath Value[Dep, c] "tags": [1], "detail": "int => int", "documentation": {"kind": "markdown", "value": "Deprecated: Use customDouble instead\n\nSome doc comment"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/Completion.res 23:20 @@ -425,14 +537,18 @@ Found type for function (~age: int, ~name: string) => string "tags": [], "detail": "int", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "name", "kind": 4, "tags": [], "detail": "string", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/Completion.res 26:13 @@ -444,14 +560,18 @@ Completable: Cpath array->m "tags": [], "detail": "(t<'a>, ('a, int) => 'b) => t<'b>", "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The function acceps two arguments: an item from the array and its\nindex number. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\n// multiply each item in array by its position\nlet product = (item, index) => item * index\nJs.Array2.mapi([10, 11, 12], product) == [0, 11, 24]\n```\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js.Array2.map", "kind": 12, "tags": [], "detail": "(t<'a>, 'a => 'b) => t<'b>", "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\nJs.Array2.map([12, 4, 8], x => x * x) == [144, 16, 64]\nJs.Array2.map([\"animal\", \"vegetable\", \"mineral\"], Js.String.length) == [6, 9, 7]\n```\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/Completion.res 29:13 @@ -463,7 +583,9 @@ Completable: Cpath string->toU "tags": [], "detail": "t => t", "documentation": {"kind": "markdown", "value": "\n`toUpperCase(str)` converts `str` to upper case using the locale-insensitive\ncase mappings in the Unicode Character Database. Notice that the conversion can\nexpand the number of letters in the result; for example the German ß\ncapitalizes to two Ses in a row.\n\nSee [`String.toUpperCase`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase)\non MDN.\n\n```res example\nJs.String2.toUpperCase(\"abc\") == \"ABC\"\nJs.String2.toUpperCase(`Straße`) == `STRASSE`\nJs.String2.toUpperCase(`πς`) == `ΠΣ`\n```\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/Completion.res 34:8 @@ -475,14 +597,18 @@ Completable: Cpath Value[op]->e "tags": [], "detail": "(option<'a>, option<'b>, (. 'a, 'b) => bool) => bool", "documentation": {"kind": "markdown", "value": "\n Uncurried version of `eq`\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt.Option.eq", "kind": 12, "tags": [], "detail": "(option<'a>, option<'b>, ('a, 'b) => bool) => bool", "documentation": {"kind": "markdown", "value": "\n Evaluates two optional values for equality with respect to a predicate\n function. If both `optValue1` and `optValue2` are `None`, returns `true`.\n If one of the arguments is `Some(value)` and the other is `None`, returns\n `false`.\n\n If arguments are `Some(value1)` and `Some(value2)`, returns the result of\n `predicate(value1, value2)`; the predicate function must return a bool.\n\n ```res example\n let clockEqual = (a, b) => mod(a, 12) == mod(b, 12)\n\n open Belt.Option\n\n eq(Some(3), Some(15), clockEqual) /* true */\n\n eq(Some(3), None, clockEqual) /* false */\n\n eq(None, Some(3), clockEqual) /* false */\n\n eq(None, None, clockEqual) /* true */\n ```\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/Completion.res 44:7 @@ -496,14 +622,18 @@ Completable: Cpath Value[fa]-> "tags": [], "detail": "(t, int) => t", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "ForAuto.abd", "kind": 12, "tags": [], "detail": "(t, int) => t", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/Completion.res 47:21 @@ -517,14 +647,18 @@ Completable: Cpath Value[Js, Dict, u] "tags": [], "detail": "(t<'a>, key) => 'a", "documentation": {"kind": "markdown", "value": "\n`Js.Dict.unsafeGet(key)` returns the value if the key exists, otherwise an `undefined` value is returned. Use this only when you are sure the key exists (i.e. when having used the `keys()` function to check that the key is valid).\n\n```res example\nJs.Dict.unsafeGet(ages, \"Fred\") == 49\nJs.Dict.unsafeGet(ages, \"Paul\") // returns undefined\n```\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "unsafeDeleteKey", "kind": 12, "tags": [], "detail": "(. t, string) => unit", "documentation": {"kind": "markdown", "value": " Experimental internal function "}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/Completion.res 59:30 @@ -539,7 +673,9 @@ Completable: Cpath Value[z] "tags": [], "detail": "int", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/Completion.res 62:23 @@ -552,20 +688,15 @@ Completable: Cjsx([O, Comp], z, [z]) "tags": [], "detail": "option", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/Completion.res 65:8 Attribute id:reac:[65:3->65:8] label:reac -Completable: Cdecorator(reac) -[{ - "label": "react.component", - "kind": 4, - "tags": [], - "detail": "", - "documentation": {"kind": "markdown", "value": "The `@react.component` decorator is used to annotate functions that are RescriptReact components.\n\nYou will need this decorator whenever you want to use a ReScript / React component in ReScript JSX expressions.\n\nNote: The `@react.component` decorator requires the react-jsx config to be set in your `bsconfig.json` to enable the required React transformations.\n\n[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#react-component-decorator)."}, - "sortText": null - }] +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 68:10 posCursor:[68:10] posNoWhite:[68:9] Found expr:[0:-1->86:1] @@ -578,7 +709,9 @@ Completable: Cdecorator(react.) "tags": [], "detail": "", "documentation": {"kind": "markdown", "value": "The `@react.component` decorator is used to annotate functions that are RescriptReact components.\n\nYou will need this decorator whenever you want to use a ReScript / React component in ReScript JSX expressions.\n\nNote: The `@react.component` decorator requires the react-jsx config to be set in your `bsconfig.json` to enable the required React transformations.\n\n[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#react-component-decorator)."}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/Completion.res 71:27 @@ -592,7 +725,9 @@ Found type for function (~age: int, ~name: string) => string "tags": [], "detail": "int", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/Completion.res 74:26 @@ -606,7 +741,9 @@ Found type for function (~age: int, ~name: string) => string "tags": [], "detail": "string", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/Completion.res 77:32 @@ -620,1075 +757,334 @@ Found type for function (~age: int, ~name: string) => string "tags": [], "detail": "string", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/Completion.res 82:5 -posCursor:[82:5] posNoWhite:[82:4] Found expr:[80:8->86:1] -Pexp_apply ...[80:8->80:15] (~age84:3->84:6=...[84:7->84:8], ~name85:3->85:7=...[85:8->85:10]) -Completable: CnamedArg(Value[Lib, foo], "", [age, name]) -Found type for function (~age: int, ~name: string) => string +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](Nolabel, ~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Completion.res 90:13 -posCursor:[90:13] posNoWhite:[90:12] Found expr:[90:3->93:18] -Pexp_send a[90:12->90:13] e:[90:3->90:10] -Completable: Cpath Value[someObj]["a"] -[{ - "label": "age", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 95:24 -posCursor:[95:24] posNoWhite:[95:23] Found expr:[95:3->99:6] -Pexp_send [95:24->95:24] e:[95:3->95:22] -Completable: Cpath Value[nestedObj]["x"]["y"][""] -[{ - "label": "age", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }, { - "label": "name", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 99:7 -posCursor:[99:7] posNoWhite:[99:6] Found expr:[99:3->102:20] -Pexp_send a[99:6->99:7] e:[99:3->99:4] -Completable: Cpath Value[o]["a"] -[{ - "label": "age", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 104:17 -posCursor:[104:17] posNoWhite:[104:16] Found expr:[104:3->125:18] -Pexp_send [104:17->104:17] e:[104:3->104:15] -Completable: Cpath Value[no]["x"]["y"][""] -[{ - "label": "name", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }, { - "label": "age", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 110:5 -posCursor:[110:5] posNoWhite:[110:4] Found expr:[110:3->110:5] -Pexp_field [110:3->110:4] _:[116:0->110:5] -Completable: Cpath Value[r]."" -[{ - "label": "x", - "kind": 5, - "tags": [], - "detail": "x: int\n\ntype r = {x: int, y: string}", - "documentation": null, - "sortText": null - }, { - "label": "y", - "kind": 5, - "tags": [], - "detail": "y: string\n\ntype r = {x: int, y: string}", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 113:24 -posCursor:[113:24] posNoWhite:[113:23] Found expr:[113:3->113:24] -Pexp_field [113:3->113:23] _:[116:0->113:24] -Completable: Cpath Value[Object, Rec, recordVal]."" -[{ - "label": "xx", - "kind": 5, - "tags": [], - "detail": "xx: int\n\ntype recordt = {xx: int, ss: string}", - "documentation": null, - "sortText": null - }, { - "label": "ss", - "kind": 5, - "tags": [], - "detail": "ss: string\n\ntype recordt = {xx: int, ss: string}", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 120:7 -posCursor:[120:7] posNoWhite:[120:6] Found expr:[119:11->123:1] -posCursor:[120:7] posNoWhite:[120:6] Found expr:[120:5->122:5] -posCursor:[120:7] posNoWhite:[120:6] Found expr:[120:5->120:7] -Pexp_ident my:[120:5->120:7] -Completable: Cpath Value[my] -[{ - "label": "myAmazingFunction", - "kind": 12, - "tags": [], - "detail": "(int, int) => int", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 125:18 -posCursor:[125:18] posNoWhite:[125:17] Found expr:[125:3->145:32] -Pexp_send [125:18->125:18] e:[125:3->125:16] -Completable: Cpath Value[Object, object][""] -[{ - "label": "name", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }, { - "label": "age", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 151:6 -posCursor:[151:6] posNoWhite:[151:5] Found expr:[151:4->151:6] -JSX 151:6] > _children:None -Completable: Cpath Module[O, ""] -[{ - "label": "Comp", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 157:8 -posCursor:[157:8] posNoWhite:[157:7] Found expr:[157:3->157:8] -Pexp_field [157:3->157:7] _:[165:0->157:8] -Completable: Cpath Value[q].aa."" -[{ - "label": "x", - "kind": 5, - "tags": [], - "detail": "x: int\n\ntype aa = {x: int, name: string}", - "documentation": null, - "sortText": null - }, { - "label": "name", - "kind": 5, - "tags": [], - "detail": "name: string\n\ntype aa = {x: int, name: string}", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 159:9 -posCursor:[159:9] posNoWhite:[159:8] Found expr:[159:3->159:9] -Pexp_field [159:3->159:7] n:[159:8->159:9] -Completable: Cpath Value[q].aa.n -[{ - "label": "name", - "kind": 5, - "tags": [], - "detail": "name: string\n\ntype aa = {x: int, name: string}", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 162:6 -posCursor:[162:6] posNoWhite:[162:5] Found expr:[162:3->162:6] -Pexp_construct Lis:[162:3->162:6] None -Completable: Cpath Value[Lis] -[{ - "label": "List", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null, - "sortText": null - }, { - "label": "ListLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 169:16 -posCursor:[169:16] posNoWhite:[169:15] Found expr:[169:4->169:16] -JSX 169:16] > _children:None -Completable: Cpath Module[WithChildren] -[{ - "label": "WithChildren", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 172:16 posCursor:[172:16] posNoWhite:[172:15] Found type:[172:12->172:16] Ptyp_constr Js.n:[172:12->172:16] -Completable: Cpath Type[Js, n] -[{ - "label": "null_undefined", - "kind": 22, - "tags": [], - "detail": "type null_undefined<'a> = nullable<'a>", - "documentation": null, - "sortText": null - }, { - "label": "nullable", - "kind": 22, - "tags": [], - "detail": "type nullable<+'a>", - "documentation": {"kind": "markdown", "value": "\n A value of this type can be undefined, null or 'a. This type is equivalent to Js.Null_undefined.t.\n"}, - "sortText": null - }, { - "label": "null", - "kind": 22, - "tags": [], - "detail": "type null<+'a>", - "documentation": {"kind": "markdown", "value": "\n Nullable value of this type can be either null or 'a. This type is equivalent to Js.Null.t.\n"}, - "sortText": null - }] +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 174:20 posCursor:[174:20] posNoWhite:[174:19] Found type:[174:12->174:20] Ptyp_constr ForAuto.:[174:12->174:20] -Completable: Cpath Type[ForAuto, ""] -[{ - "label": "t", - "kind": 22, - "tags": [], - "detail": "type t = int", - "documentation": null, - "sortText": null - }] +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 179:13 -posCursor:[179:13] posNoWhite:[179:12] Found expr:[179:11->179:13] -Pexp_construct As:[179:11->179:13] None -Completable: Cpath Value[As] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Completion.res 182:17 Pmod_ident For:[182:14->182:17] -Completable: Cpath Module[For] -[{ - "label": "ForAuto", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null, - "sortText": null - }] +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 190:11 -posCursor:[190:11] posNoWhite:[190:10] Found expr:[190:3->190:11] -Pexp_ident Private.:[190:3->190:11] -Completable: Cpath Value[Private, ""] -[{ - "label": "b", - "kind": 12, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 202:6 -posCursor:[202:6] posNoWhite:[202:5] Found expr:[202:3->202:6] -Pexp_ident sha:[202:3->202:6] -Completable: Cpath Value[sha] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Completion.res 205:6 -posCursor:[205:6] posNoWhite:[205:5] Found expr:[205:3->205:6] -Pexp_ident sha:[205:3->205:6] -Completable: Cpath Value[sha] -[{ - "label": "shadowed", - "kind": 12, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 208:6 -posCursor:[208:6] posNoWhite:[208:5] Found expr:[208:3->208:6] -Pexp_ident sha:[208:3->208:6] -Completable: Cpath Value[sha] -[{ - "label": "shadowed", - "kind": 12, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 221:22 -posCursor:[221:22] posNoWhite:[221:21] Found expr:[221:3->224:22] -Pexp_send [221:22->221:22] e:[221:3->221:20] -Completable: Cpath Value[FAO, forAutoObject][""] -[{ - "label": "age", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }, { - "label": "forAutoLabel", - "kind": 4, - "tags": [], - "detail": "FAR.forAutoRecord", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 224:37 -posCursor:[224:37] posNoWhite:[224:36] Found expr:[224:3->224:37] -Pexp_field [224:3->224:36] _:[233:0->224:37] -Completable: Cpath Value[FAO, forAutoObject]["forAutoLabel"]."" -[{ - "label": "forAuto", - "kind": 5, - "tags": [], - "detail": "forAuto: ForAuto.t\n\ntype forAutoRecord = {\n forAuto: ForAuto.t,\n something: option,\n}", - "documentation": null, - "sortText": null - }, { - "label": "something", - "kind": 5, - "tags": [], - "detail": "something: option\n\ntype forAutoRecord = {\n forAuto: ForAuto.t,\n something: option,\n}", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 227:46 posCursor:[227:46] posNoWhite:[227:45] Found expr:[227:3->0:-1] -Completable: Cpath Value[FAO, forAutoObject]["forAutoLabel"].forAuto-> -[{ - "label": "ForAuto.abc", - "kind": 12, - "tags": [], - "detail": "(t, int) => t", - "documentation": null, - "sortText": null - }, { - "label": "ForAuto.abd", - "kind": 12, - "tags": [], - "detail": "(t, int) => t", - "documentation": null, - "sortText": null - }] +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 230:55 -posCursor:[230:55] posNoWhite:[230:54] Found expr:[230:3->230:55] -posCursor:[230:55] posNoWhite:[230:54] Found expr:[230:46->230:55] -Pexp_ident ForAuto.a:[230:46->230:55] -Completable: Cpath Value[ForAuto, a] -[{ - "label": "abc", - "kind": 12, - "tags": [], - "detail": "(t, int) => t", - "documentation": null, - "sortText": null - }, { - "label": "abd", - "kind": 12, - "tags": [], - "detail": "(t, int) => t", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 234:34 -posCursor:[234:34] posNoWhite:[234:33] Found expr:[234:18->234:36] -Pexp_apply ...__ghost__[0:-1->0:-1] (...[234:18->234:34], ...[234:34->234:35]) -posCursor:[234:34] posNoWhite:[234:33] Found expr:[234:18->234:34] -Pexp_apply ...__ghost__[0:-1->0:-1] (...[234:18->234:30], ...[234:32->234:34]) -posCursor:[234:34] posNoWhite:[234:33] Found expr:[234:32->234:34] -Pexp_ident na:[234:32->234:34] -Completable: Cpath Value[na] -[{ - "label": "name", - "kind": 12, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 237:17 -posCursor:[237:17] posNoWhite:[237:14] Found expr:[237:14->237:22] -Completable: Cnone +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Completion.res 243:8 -posCursor:[243:8] posNoWhite:[243:7] Found expr:[241:8->246:1] -posCursor:[243:8] posNoWhite:[243:7] Found expr:[242:14->243:8] -Pexp_apply ...[243:3->243:4] (...[242:14->242:15], ...[243:5->243:8]) -posCursor:[243:8] posNoWhite:[243:7] Found expr:[243:5->243:8] -Pexp_field [243:5->243:7] _:[245:0->243:8] -Completable: Cpath Value[_z]."" -[{ - "label": "x", - "kind": 5, - "tags": [], - "detail": "x: int\n\ntype r = {x: int, y: string}", - "documentation": null, - "sortText": null - }, { - "label": "y", - "kind": 5, - "tags": [], - "detail": "y: string\n\ntype r = {x: int, y: string}", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 254:17 -posCursor:[254:17] posNoWhite:[254:16] Found expr:[254:11->254:17] -Pexp_construct SomeLo:[254:11->254:17] None -Completable: Cpath Value[SomeLo] -[{ - "label": "SomeLocalModule", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 256:29 posCursor:[256:29] posNoWhite:[256:28] Found type:[256:13->256:29] Ptyp_constr SomeLocalModule.:[256:13->256:29] -Completable: Cpath Type[SomeLocalModule, ""] -[{ - "label": "zz", - "kind": 22, - "tags": [], - "detail": "type zz = int", - "documentation": null, - "sortText": null - }] +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 261:33 posCursor:[261:33] posNoWhite:[261:32] Found type:[261:17->263:11] Ptyp_constr SomeLocalModule.:[261:17->263:11] -Completable: Cpath Type[SomeLocalModule, ""] -[{ - "label": "zz", - "kind": 22, - "tags": [], - "detail": "type zz = int", - "documentation": null, - "sortText": null - }] +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 268:21 Ptype_variant unary SomeLocal:[268:12->268:21] -Completable: Cpath Value[SomeLocal] -[{ - "label": "SomeLocalModule", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null, - "sortText": null - }] +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 271:20 posCursor:[271:20] posNoWhite:[271:19] Found pattern:[271:7->274:3] posCursor:[271:20] posNoWhite:[271:19] Found type:[271:11->274:3] Ptyp_constr SomeLocal:[271:11->274:3] -Completable: Cpath Type[SomeLocal] -[{ - "label": "SomeLocalModule", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null, - "sortText": null - }] +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 275:15 -posCursor:[275:15] posNoWhite:[275:14] Found expr:[274:11->278:1] -posCursor:[275:15] posNoWhite:[275:14] Found expr:[275:5->277:3] -posCursor:[275:15] posNoWhite:[275:14] Found expr:[275:13->275:15] -Pexp_ident _w:[275:13->275:15] -Completable: Cpath Value[_w] -[{ - "label": "_world", - "kind": 12, - "tags": [], - "detail": "'a", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 281:22 posCursor:[281:22] posNoWhite:[281:21] Found type:[281:21->281:22] Ptyp_constr s:[281:21->281:22] -Completable: Cpath Type[s] -[{ - "label": "someType", - "kind": 22, - "tags": [], - "detail": "type someType = {hello: string}", - "documentation": null, - "sortText": null - }, { - "label": "someLocalVariant", - "kind": 22, - "tags": [], - "detail": "type someLocalVariant = SomeLocalVariantItem", - "documentation": null, - "sortText": null - }] +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 291:30 -posCursor:[291:30] posNoWhite:[291:29] Found expr:[291:11->291:32] -Pexp_apply ...[291:11->291:28] () -Completable: CnamedArg(Value[funRecord].someFun, "", []) -Found type for function (~name: string) => unit -[{ - "label": "name", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 296:11 -posCursor:[296:11] posNoWhite:[296:10] Found expr:[296:3->296:11] -Pexp_field [296:3->296:10] _:[299:0->296:11] -Completable: Cpath Value[retAA](Nolabel)."" -[{ - "label": "x", - "kind": 5, - "tags": [], - "detail": "x: int\n\ntype aa = {x: int, name: string}", - "documentation": null, - "sortText": null - }, { - "label": "name", - "kind": 5, - "tags": [], - "detail": "name: string\n\ntype aa = {x: int, name: string}", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 301:13 -posCursor:[301:13] posNoWhite:[301:12] Found expr:[301:3->301:13] -Pexp_apply ...[301:3->301:11] () -Completable: CnamedArg(Value[ff](~c), "", []) -Found type for function ( - ~opt1: int=?, - ~a: int, - ~b: int, - unit, - ~opt2: int=?, - unit, -) => int -[{ - "label": "opt1", - "kind": 4, - "tags": [], - "detail": "option", - "documentation": null, - "sortText": null - }, { - "label": "a", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }, { - "label": "b", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }, { - "label": "opt2", - "kind": 4, - "tags": [], - "detail": "option", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 304:15 -posCursor:[304:15] posNoWhite:[304:14] Found expr:[304:3->304:15] -Pexp_apply ...[304:3->304:13] () -Completable: CnamedArg(Value[ff](~c)(Nolabel), "", []) -Found type for function (~a: int, ~b: int, ~opt2: int=?, unit) => int -[{ - "label": "a", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }, { - "label": "b", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }, { - "label": "opt2", - "kind": 4, - "tags": [], - "detail": "option", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 307:17 -posCursor:[307:17] posNoWhite:[307:16] Found expr:[307:3->307:17] -Pexp_apply ...[307:3->307:15] () -Completable: CnamedArg(Value[ff](~c, Nolabel), "", []) -Found type for function (~a: int, ~b: int, ~opt2: int=?, unit) => int -[{ - "label": "a", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }, { - "label": "b", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }, { - "label": "opt2", - "kind": 4, - "tags": [], - "detail": "option", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 310:21 -posCursor:[310:21] posNoWhite:[310:20] Found expr:[310:3->310:21] -Pexp_apply ...[310:3->310:19] () -Completable: CnamedArg(Value[ff](~c, Nolabel, Nolabel), "", []) -Found type for function (~a: int, ~b: int) => int -[{ - "label": "a", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }, { - "label": "b", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 313:23 -posCursor:[313:23] posNoWhite:[313:22] Found expr:[313:3->313:23] -Pexp_apply ...[313:3->313:21] () -Completable: CnamedArg(Value[ff](~c, Nolabel, ~b), "", []) -Found type for function (~a: int, ~opt2: int=?, unit) => int -[{ - "label": "a", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }, { - "label": "opt2", - "kind": 4, - "tags": [], - "detail": "option", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 316:16 -posCursor:[316:16] posNoWhite:[316:15] Found expr:[316:3->316:16] -Pexp_apply ...[316:3->316:14] () -Completable: CnamedArg(Value[ff](~opt2), "", []) -Found type for function (~opt1: int=?, ~a: int, ~b: int, unit, unit, ~c: int) => int -[{ - "label": "opt1", - "kind": 4, - "tags": [], - "detail": "option", - "documentation": null, - "sortText": null - }, { - "label": "a", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }, { - "label": "b", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }, { - "label": "c", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 323:17 -posCursor:[323:17] posNoWhite:[323:16] Found expr:[323:3->323:17] -Pexp_apply ...[323:3->323:15] () -Completable: CnamedArg(Value[withCallback], "", []) -Found type for function (~b: int) => callback -[{ - "label": "b", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }, { - "label": "a", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 326:21 -posCursor:[326:21] posNoWhite:[326:20] Found expr:[326:3->326:21] -Pexp_apply ...[326:3->326:19] () -Completable: CnamedArg(Value[withCallback](~a), "", []) -Found type for function (~b: int) => int -[{ - "label": "b", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 329:21 -posCursor:[329:21] posNoWhite:[329:20] Found expr:[329:3->329:21] -Pexp_apply ...[329:3->329:19] () -Completable: CnamedArg(Value[withCallback](~b), "", []) -Found type for function (~a: int) => int -[{ - "label": "a", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 336:26 -posCursor:[336:26] posNoWhite:[336:25] Found expr:[333:3->346:23] -JSX 333:6] onClick[334:4->334:11]=...[334:13->346:23]> _children:None -posCursor:[336:26] posNoWhite:[336:25] Found expr:[334:13->346:23] -posCursor:[336:26] posNoWhite:[336:25] Found expr:[334:13->338:6] -posCursor:[336:26] posNoWhite:[336:25] Found expr:[335:6->338:5] -posCursor:[336:26] posNoWhite:[336:25] Found expr:[336:16->338:5] posCursor:[336:26] posNoWhite:[336:25] Found pattern:[336:20->338:5] posCursor:[336:26] posNoWhite:[336:25] Found type:[336:23->338:5] Ptyp_constr Res:[336:23->338:5] -Completable: Cpath Type[Res] -[{ - "label": "RescriptReactErrorBoundary", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null, - "sortText": null - }, { - "label": "RescriptReactRouter", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null, - "sortText": null - }] +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 343:57 -posCursor:[343:57] posNoWhite:[343:56] Found expr:[343:10->346:23] -posCursor:[343:57] posNoWhite:[343:56] Found expr:[343:53->346:23] -posCursor:[343:57] posNoWhite:[343:56] Found expr:[343:53->343:57] -Pexp_ident this:[343:53->343:57] -Completable: Cpath Value[this] -[{ - "label": "thisIsNotSaved", - "kind": 12, - "tags": [], - "detail": "\\\"Type Not Known\"", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Hover src/Completion.res 346:14 Nothing at that position. Now trying to use completion. -posCursor:[346:14] posNoWhite:[346:13] Found expr:[346:9->346:23] -JSX 346:12] name[346:13->346:17]=...[346:18->346:20]> _children:346:21 -Completable: Cjsx([div], name, [name]) -{"contents": "```rescript\nstring\n```"} +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +null Hover src/Completion.res 349:17 Nothing at that position. Now trying to use completion. -posCursor:[349:17] posNoWhite:[349:16] Found expr:[349:11->349:35] -Pexp_send age[349:30->349:33] e:[349:11->349:28] -posCursor:[349:17] posNoWhite:[349:16] Found expr:[349:11->349:28] -Pexp_ident FAO.forAutoObject:[349:11->349:28] -Completable: Cpath Value[FAO, forAutoObject] -{"contents": "```rescript\n{\"age\": int, \"forAutoLabel\": FAR.forAutoRecord}\n```"} +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +null Hover src/Completion.res 352:17 Nothing at that position. Now trying to use completion. -posCursor:[352:17] posNoWhite:[352:16] Found expr:[352:11->352:22] -Pexp_apply ...[352:11->352:13] (~opt1352:15->352:19=...[352:20->352:21]) -Completable: CnamedArg(Value[ff], opt1, [opt1]) -Found type for function ( - ~opt1: int=?, - ~a: int, - ~b: int, - unit, - ~opt2: int=?, - unit, - ~c: int, -) => int -{"contents": "```rescript\noption\n```"} +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +null Complete src/Completion.res 355:23 -posCursor:[355:23] posNoWhite:[355:22] Found expr:[0:-1->355:23] -posCursor:[355:23] posNoWhite:[355:22] Found expr:[355:12->355:23] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Completion.res 362:8 -posCursor:[362:8] posNoWhite:[362:7] Found expr:[360:8->365:3] -posCursor:[362:8] posNoWhite:[362:7] Found expr:[361:2->365:3] posCursor:[362:8] posNoWhite:[362:7] Found pattern:[362:7->364:5] posCursor:[362:8] posNoWhite:[362:7] Found pattern:[362:7->362:8] Ppat_construct T:[362:7->362:8] -Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [], seenIdents: [T]) +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Completion.res 373:21 -posCursor:[373:21] posNoWhite:[373:20] Found expr:[371:8->376:3] -posCursor:[373:21] posNoWhite:[373:20] Found expr:[372:2->376:3] posCursor:[373:21] posNoWhite:[373:20] Found pattern:[373:7->375:5] posCursor:[373:21] posNoWhite:[373:20] Found pattern:[373:7->373:21] Ppat_construct AndThatOther.T:[373:7->373:21] -Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CVariant, patternType:Switch, prefix:AndThatOther, pattern: [], seenIdents: [AndThatOther]) +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Completion.res 378:24 -posCursor:[378:24] posNoWhite:[378:23] Found expr:[378:12->378:26] -Pexp_apply ...__ghost__[0:-1->0:-1] (...[378:12->378:24], ...[378:24->378:25]) -posCursor:[378:24] posNoWhite:[378:23] Found expr:[378:12->378:24] -Pexp_apply ...__ghost__[0:-1->0:-1] (...[378:12->378:14], ...[378:16->378:24]) -posCursor:[378:24] posNoWhite:[378:23] Found expr:[378:16->378:24] -Pexp_ident ForAuto.:[378:16->378:24] -Completable: Cpath Value[ForAuto, ""] -[{ - "label": "abc", - "kind": 12, - "tags": [], - "detail": "(t, int) => t", - "documentation": null, - "sortText": null - }, { - "label": "abd", - "kind": 12, - "tags": [], - "detail": "(t, int) => t", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 381:38 -posCursor:[381:38] posNoWhite:[381:37] Found expr:[381:12->381:41] -Pexp_apply ...__ghost__[0:-1->0:-1] (...[381:12->381:39], ...[381:39->381:40]) -posCursor:[381:38] posNoWhite:[381:37] Found expr:[381:12->381:39] -Pexp_apply ...__ghost__[0:-1->0:-1] (...[381:12->381:17], ...[381:19->381:39]) -posCursor:[381:38] posNoWhite:[381:37] Found expr:[381:19->381:39] -Pexp_send [381:38->381:38] e:[381:19->381:36] -Completable: Cpath Value[FAO, forAutoObject][""] -[{ - "label": "age", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }, { - "label": "forAutoLabel", - "kind": 4, - "tags": [], - "detail": "FAR.forAutoRecord", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 384:24 -posCursor:[384:24] posNoWhite:[384:23] Found expr:[384:11->384:26] -Pexp_apply ...__ghost__[0:-1->0:-1] (...[384:11->384:24], ...[384:24->384:25]) -posCursor:[384:24] posNoWhite:[384:23] Found expr:[384:11->384:24] -Pexp_apply ...__ghost__[0:-1->0:-1] (...[384:11->384:12], ...[384:14->384:24]) -posCursor:[384:24] posNoWhite:[384:23] Found expr:[384:14->384:24] -Pexp_field [384:14->384:23] _:[384:24->384:24] -Completable: Cpath Value[funRecord]."" -[{ - "label": "someFun", - "kind": 5, - "tags": [], - "detail": "someFun: (~name: string) => unit\n\ntype funRecord = {\n someFun: (~name: string) => unit,\n stuff: string,\n}", - "documentation": null, - "sortText": null - }, { - "label": "stuff", - "kind": 5, - "tags": [], - "detail": "stuff: string\n\ntype funRecord = {\n someFun: (~name: string) => unit,\n stuff: string,\n}", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 389:12 -posCursor:[389:12] posNoWhite:[389:11] Found expr:[387:8->392:1] -posCursor:[389:12] posNoWhite:[389:11] Found expr:[388:2->391:4] -posCursor:[389:12] posNoWhite:[389:11] Found expr:[389:6->391:4] -posCursor:[389:12] posNoWhite:[389:11] Found expr:[389:6->389:12] -Completable: Cpath array->ma -[{ - "label": "Array2.mapi", - "kind": 12, - "tags": [], - "detail": "(t<'a>, ('a, int) => 'b) => t<'b>", - "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The function acceps two arguments: an item from the array and its\nindex number. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\n// multiply each item in array by its position\nlet product = (item, index) => item * index\nJs.Array2.mapi([10, 11, 12], product) == [0, 11, 24]\n```\n"}, - "sortText": null - }, { - "label": "Array2.map", - "kind": 12, - "tags": [], - "detail": "(t<'a>, 'a => 'b) => t<'b>", - "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\nJs.Array2.map([12, 4, 8], x => x * x) == [144, 16, 64]\nJs.Array2.map([\"animal\", \"vegetable\", \"mineral\"], Js.String.length) == [6, 9, 7]\n```\n"}, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 397:14 -posCursor:[397:14] posNoWhite:[397:13] Found expr:[396:14->397:20] -Pexp_apply ...__ghost__[0:-1->0:-1] (...[396:14->397:16], ...[397:16->397:19]) -posCursor:[397:14] posNoWhite:[397:13] Found expr:[396:14->397:16] -Pexp_apply ...__ghost__[0:-1->0:-1] (...[396:14->397:11], ...[397:13->397:16]) -posCursor:[397:14] posNoWhite:[397:13] Found expr:[397:13->397:16] -Pexp_ident red:[397:13->397:16] -Completable: Cpath Value[red] -[{ - "label": "red", - "kind": 12, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 402:25 -posCursor:[402:25] posNoWhite:[402:24] Found expr:[400:14->402:31] -Pexp_apply ...__ghost__[0:-1->0:-1] (...[400:14->402:27], ...[402:27->402:30]) -posCursor:[402:25] posNoWhite:[402:24] Found expr:[400:14->402:27] -Pexp_apply ...__ghost__[0:-1->0:-1] (...[400:14->402:22], ...[402:24->402:27]) -posCursor:[402:25] posNoWhite:[402:24] Found expr:[402:24->402:27] -Pexp_ident red:[402:24->402:27] -Completable: Cpath Value[red] -[{ - "label": "red", - "kind": 12, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Completion.res 405:22 -posCursor:[405:22] posNoWhite:[405:21] Found expr:[405:11->408:0] -Pexp_apply ...__ghost__[0:-1->0:-1] (...[405:11->405:22], ...[408:0->408:0]) -posCursor:[405:22] posNoWhite:[405:21] Found expr:[405:11->405:22] -Pexp_apply ...__ghost__[0:-1->0:-1] (...[405:11->405:19], ...[405:21->405:22]) -posCursor:[405:22] posNoWhite:[405:21] Found expr:[405:21->405:22] -Pexp_ident r:[405:21->405:22] -Completable: Cpath Value[r] -[{ - "label": "red", - "kind": 12, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }, { - "label": "retAA", - "kind": 12, - "tags": [], - "detail": "unit => aa", - "documentation": null, - "sortText": null - }, { - "label": "r", - "kind": 12, - "tags": [], - "detail": "rAlias", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] diff --git a/analysis/tests/src/expected/Cross.res.txt b/analysis/tests/src/expected/Cross.res.txt index b045e8a02..06e48f632 100644 --- a/analysis/tests/src/expected/Cross.res.txt +++ b/analysis/tests/src/expected/Cross.res.txt @@ -94,8 +94,7 @@ TypeDefinition src/Cross.res 33:37 {"uri": "DefinitionWithInterface.resi", "range": {"start": {"line": 3, "character": 0}, "end": {"line": 3, "character": 6}}} Complete src/Cross.res 36:28 -posCursor:[36:28] posNoWhite:[36:27] Found expr:[36:3->36:28] -Pexp_ident DefinitionWithInterface.a:[36:3->36:28] -Completable: Cpath Value[DefinitionWithInterface, a] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[RenameWithInterface, x], lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] diff --git a/analysis/tests/src/expected/Debug.res.txt b/analysis/tests/src/expected/Debug.res.txt index 6da6f3fc0..e5be9b9a6 100644 --- a/analysis/tests/src/expected/Debug.res.txt +++ b/analysis/tests/src/expected/Debug.res.txt @@ -70,33 +70,21 @@ resolvePath path:map {"uri": "list.mli", "range": {"start": {"line": 116, "character": 4}, "end": {"line": 116, "character": 7}}} Complete src/Debug.res 13:8 -posCursor:[13:8] posNoWhite:[13:7] Found expr:[13:5->13:8] -Pexp_ident eqN:[13:5->13:8] -Completable: Cpath Value[eqN] -Raw ppens: 1 Js.place holder +XXX Not found! +Completable: CtypedPattern(sourceType:Value[Belt, List, map], lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Raw ppens: 0 Package opens -resolving open Js.place holder -resolvePath path:Js.place holder -Not local -fileForModule Impl cmt:./node_modules/rescript/lib/ocaml/js.cmt res:./node_modules/rescript/lib/ocaml/js.ml -resolvePath path:place holder -Resolved opens 1 js.ml -findLocalCompletionsWithOpens uri:Debug.res pos:13:8 -findAllCompletions uri:js.ml -[{ - "label": "eqNullable", - "kind": 12, - "tags": [], - "detail": "('a, nullable<'a>) => bool", - "documentation": null, - "sortText": null - }, { - "label": "eqNull", - "kind": 12, - "tags": [], - "detail": "('a, null<'a>) => bool", - "documentation": null, - "sortText": null - }] +Resolved opens 0 +Path List.map +Getting module Belt +fileForModule Impl cmt:./node_modules/rescript/lib/ocaml/belt.cmt res:./node_modules/rescript/lib/ocaml/belt.ml +got it +resolvePath path:List.map +resolvePath Global path:map module:Belt_List +fileForModule Impl cmt:./node_modules/rescript/lib/ocaml/belt_List.cmti res:./node_modules/rescript/lib/ocaml/belt_List.mli +resolvePath path:map +Got the env +findAllCompletions uri:belt_List.mli +[] diff --git a/analysis/tests/src/expected/Div.res.txt b/analysis/tests/src/expected/Div.res.txt index cc82a7263..44e3b35a9 100644 --- a/analysis/tests/src/expected/Div.res.txt +++ b/analysis/tests/src/expected/Div.res.txt @@ -12,6 +12,8 @@ Completable: Cjsx([div], dangerous, [dangerous]) "tags": [], "detail": "{\"__html\": string}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] diff --git a/analysis/tests/src/expected/Hover.res.txt b/analysis/tests/src/expected/Hover.res.txt index f1b882d13..2194c955b 100644 --- a/analysis/tests/src/expected/Hover.res.txt +++ b/analysis/tests/src/expected/Hover.res.txt @@ -83,8 +83,8 @@ Hover src/Hover.res 109:25 Hover src/Hover.res 112:3 Nothing at that position. Now trying to use completion. Attribute id:live:[112:0->112:5] label:live -Completable: Cdecorator(live) -{"contents": "The `@live` decorator is for reanalyze, a static analysis tool for ReScript that can do dead code analysis.\n\n`@live` tells the dead code analysis that the value should be considered live, even though it might appear to be dead. This is typically used in case of FFI where there are indirect ways to access values. It can be added to everything that could otherwise be considered unused by the dead code analysis - values, functions, arguments, records, individual record fields, and so on.\n\n[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#live-decorator).\n\nHint: Did you know you can run an interactive code analysis in your project by running the command `> ReScript: Start Code Analyzer`? Try it!"} +Completable: CtypedPattern(sourceType:Value[Comp, createElement](~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +null Hover src/Hover.res 115:4 {"contents": "```rescript\n(. ()) => unit => int\n```"} diff --git a/analysis/tests/src/expected/Jsx.res.txt b/analysis/tests/src/expected/Jsx.res.txt index 6d5a9e9c0..df8aa5bcf 100644 --- a/analysis/tests/src/expected/Jsx.res.txt +++ b/analysis/tests/src/expected/Jsx.res.txt @@ -4,222 +4,79 @@ the type is not great but jump to definition works {"uri": "Jsx.res", "range": {"start": {"line": 2, "character": 6}, "end": {"line": 2, "character": 10}}} Complete src/Jsx.res 8:15 -posCursor:[8:15] posNoWhite:[8:14] Found expr:[8:4->8:15] -JSX 8:5] second[8:6->8:12]=...[8:13->8:15]> _children:None -posCursor:[8:15] posNoWhite:[8:14] Found expr:[8:13->8:15] -Pexp_ident fi:[8:13->8:15] -Completable: Cpath Value[fi] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Jsx.res 11:20 -posCursor:[11:20] posNoWhite:[11:19] Found expr:[11:4->11:20] -JSX 11:5] second[11:6->11:12]=...[11:13->11:18] f[11:19->11:20]=...[11:19->11:20]> _children:None -Completable: Cjsx([M], f, [second, f]) -[{ - "label": "first", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }, { - "label": "fun", - "kind": 4, - "tags": [], - "detail": "option", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 14:13 -posCursor:[14:13] posNoWhite:[14:12] Found expr:[14:12->14:13] -JSX 14:13] > _children:None -Completable: Cpath Module[M] -[{ - "label": "M", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null, - "sortText": null - }, { - "label": "Map", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null, - "sortText": null - }, { - "label": "MapLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null, - "sortText": null - }, { - "label": "MoreLabels", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 22:19 -posCursor:[22:19] posNoWhite:[22:18] Found expr:[22:4->22:19] -JSX 22:5] prop[22:6->22:10]=...[22:12->22:16] k[22:18->22:19]=...[22:18->22:19]> _children:None -Completable: Cjsx([M], k, [prop, k]) -[{ - "label": "key", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 25:17 -posCursor:[25:17] posNoWhite:[25:16] Found expr:[25:4->25:17] -JSX 25:5] prop[25:6->25:10]=...[25:11->25:15] k[25:16->25:17]=...[25:16->25:17]> _children:None -Completable: Cjsx([M], k, [prop, k]) -[{ - "label": "key", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 28:21 -posCursor:[28:21] posNoWhite:[28:20] Found expr:[28:4->28:21] -JSX 28:5] prop[28:6->28:10]=...[28:11->28:19] k[28:20->28:21]=...[28:20->28:21]> _children:None -Completable: Cjsx([M], k, [prop, k]) -[{ - "label": "key", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 31:24 -posCursor:[31:24] posNoWhite:[31:23] Found expr:[31:4->31:24] -JSX 31:5] prop[31:6->31:10]=...[31:11->31:22] k[31:23->31:24]=...[31:23->31:24]> _children:None -Completable: Cjsx([M], k, [prop, k]) -[{ - "label": "key", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 34:18 -posCursor:[34:18] posNoWhite:[34:17] Found expr:[34:4->34:18] -JSX 34:5] prop[34:6->34:10]=...[34:12->34:16] k[34:17->34:18]=...[34:17->34:18]> _children:None -Completable: Cjsx([M], k, [prop, k]) -[{ - "label": "key", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 37:16 -posCursor:[37:16] posNoWhite:[37:15] Found expr:[37:4->37:16] -JSX 37:5] prop[37:6->37:10]=...[37:11->37:14] k[37:15->37:16]=...[37:15->37:16]> _children:None -Completable: Cjsx([M], k, [prop, k]) -[{ - "label": "key", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 40:17 -posCursor:[40:17] posNoWhite:[40:16] Found expr:[40:4->40:17] -JSX 40:5] prop[40:6->40:10]=...[40:11->40:15] k[40:16->40:17]=...[40:16->40:17]> _children:None -Completable: Cjsx([M], k, [prop, k]) -[{ - "label": "key", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 43:18 -posCursor:[43:18] posNoWhite:[43:17] Found expr:[43:4->43:18] -JSX 43:5] prop[43:6->43:10]=...[43:11->43:16] k[43:17->43:18]=...[43:17->43:18]> _children:None -Completable: Cjsx([M], k, [prop, k]) -[{ - "label": "key", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 46:16 -posCursor:[46:16] posNoWhite:[46:15] Found expr:[46:4->46:16] -JSX 46:5] prop[46:6->46:10]=...[46:11->46:14] k[46:15->46:16]=...[46:15->46:16]> _children:None -Completable: Cjsx([M], k, [prop, k]) -[{ - "label": "key", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 49:27 -posCursor:[49:27] posNoWhite:[49:26] Found expr:[49:4->49:27] -JSX 49:5] prop[49:6->49:10]=...[49:11->49:25] k[49:26->49:27]=...[49:26->49:27]> _children:None -Completable: Cjsx([M], k, [prop, k]) -[{ - "label": "key", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 52:38 -posCursor:[52:38] posNoWhite:[52:37] Found expr:[52:4->52:38] -JSX 52:5] prop[52:6->52:10]=...[52:11->52:36] k[52:37->52:38]=...[52:37->52:38]> _children:None -Completable: Cjsx([M], k, [prop, k]) -[{ - "label": "key", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 55:25 -posCursor:[55:25] posNoWhite:[55:24] Found expr:[55:4->55:25] -JSX 55:5] prop[55:6->55:10]=...[55:11->55:23] k[55:24->55:25]=...[55:24->55:25]> _children:None -Completable: Cjsx([M], k, [prop, k]) -[{ - "label": "key", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Definition src/Jsx.res 58:11 getLocItem #4: heuristic for within fragments: take make as makeProps does not work @@ -227,273 +84,108 @@ the type is not great but jump to definition works {"uri": "Component.res", "range": {"start": {"line": 1, "character": 4}, "end": {"line": 1, "character": 8}}} Complete src/Jsx.res 68:10 -posCursor:[68:10] posNoWhite:[68:9] Found expr:[68:4->68:10] -JSX 68:7] al[68:8->68:10]=...[68:8->68:10]> _children:None -Completable: Cjsx([Ext], al, [al]) -[{ - "label": "align", - "kind": 4, - "tags": [], - "detail": "option", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 71:11 -posCursor:[71:11] posNoWhite:[71:10] Found expr:[71:4->71:11] -JSX 71:5] first[71:6->71:11]=...[71:6->71:11]> _children:None -Completable: Cjsx([M], first, [first]) +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Jsx.res 74:16 -posCursor:[74:16] posNoWhite:[74:15] Found expr:[74:4->74:16] -JSX 74:5] first[74:6->74:11]=...[74:12->74:14] k[74:15->74:16]=...[74:15->74:16]> _children:None -Completable: Cjsx([M], k, [first, k]) -[{ - "label": "key", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 77:23 -posCursor:[77:23] posNoWhite:[77:22] Found expr:[77:4->77:23] -JSX 77:5] first[77:6->77:11]=...[77:19->77:21] k[77:22->77:23]=...[77:22->77:23]> _children:None -Completable: Cjsx([M], k, [first, k]) -[{ - "label": "key", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 80:6 -posCursor:[80:6] posNoWhite:[80:5] Found expr:[80:4->85:69] -Pexp_apply ...[83:20->83:21] (...[80:4->83:19], ...[84:2->85:69]) -posCursor:[80:6] posNoWhite:[80:5] Found expr:[80:4->83:19] -JSX 80:5] > _children:80:5 -posCursor:[80:6] posNoWhite:[80:5] Found expr:[80:5->83:20] -Pexp_construct :::[83:0->83:20] [83:0->83:20] -posCursor:[80:6] posNoWhite:[80:5] Found expr:__ghost__[80:5->83:20] -Pexp_construct []:__ghost__[80:5->83:20] None +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Jsx.res 89:16 -posCursor:[89:16] posNoWhite:[89:15] Found expr:[89:4->89:16] -JSX 89:16] > _children:None -Completable: Cpath Module[WithChildren] -[{ - "label": "WithChildren", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 91:18 -posCursor:[91:18] posNoWhite:[91:17] Found expr:[91:4->91:18] -JSX 91:16] n[91:17->91:18]=...[91:17->91:18]> _children:None -Completable: Cjsx([WithChildren], n, [n]) -[{ - "label": "name", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 94:18 posCursor:[94:18] posNoWhite:[94:17] Found pattern:[94:7->94:18] posCursor:[94:18] posNoWhite:[94:17] Found type:[94:11->94:18] Ptyp_constr React.e:[94:11->94:18] -Completable: Cpath Type[React, e] -[{ - "label": "element", - "kind": 22, - "tags": [], - "detail": "type element", - "documentation": null, - "sortText": null - }] +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 96:20 posCursor:[96:20] posNoWhite:[96:19] Found pattern:[96:7->99:6] posCursor:[96:20] posNoWhite:[96:19] Found type:[96:11->99:6] Ptyp_constr ReactDOMR:[96:11->99:6] -Completable: Cpath Type[ReactDOMR] -[{ - "label": "ReactDOMRe", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null, - "sortText": null - }] +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 102:21 -posCursor:[102:21] posNoWhite:[102:20] Found expr:[102:13->102:21] -Pexp_apply ...[102:15->102:16] (...[102:13->102:14], ...[102:17->102:21]) -posCursor:[102:21] posNoWhite:[102:20] Found expr:[102:17->102:21] -Pexp_field [102:17->102:18] th:[102:19->102:21] -Completable: Cpath Value[x].th +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Jsx.res 106:28 -posCursor:[106:28] posNoWhite:[106:27] Found expr:[106:11->106:28] -Pexp_ident DefineSomeFields.:[106:11->106:28] -Completable: Cpath Value[DefineSomeFields, ""] -[{ - "label": "thisValue", - "kind": 12, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 108:36 -posCursor:[108:36] posNoWhite:[108:35] Found expr:[108:11->108:36] -Pexp_apply ...[108:13->108:14] (...[108:11->108:12], ...[108:15->108:36]) -posCursor:[108:36] posNoWhite:[108:35] Found expr:[108:15->108:36] -Pexp_field [108:15->108:16] DefineSomeFields.th:[108:17->108:36] -Completable: Cpath Module[DefineSomeFields].th -[{ - "label": "thisField", - "kind": 5, - "tags": [], - "detail": "thisField: int\n\ntype r = {thisField: int, thatField: string}", - "documentation": null, - "sortText": null - }, { - "label": "thatField", - "kind": 5, - "tags": [], - "detail": "thatField: string\n\ntype r = {thisField: int, thatField: string}", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 122:20 -posCursor:[122:20] posNoWhite:[122:19] Found expr:[121:3->125:4] -JSX 121:6] x[122:5->122:6]=...[122:7->122:20] name[124:4->124:8]=...[124:9->124:11]> _children:125:2 -posCursor:[122:20] posNoWhite:[122:19] Found expr:[122:7->122:20] -Pexp_ident Outer.Inner.h:[122:7->122:20] -Completable: Cpath Value[Outer, Inner, h] -[{ - "label": "hello", - "kind": 12, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 129:19 -posCursor:[129:19] posNoWhite:[129:18] Found expr:[128:3->131:9] -JSX 128:6] x[129:5->129:6]=...[129:7->131:8]> _children:None -posCursor:[129:19] posNoWhite:[129:18] Found expr:[129:7->131:8] -Pexp_ident Outer.Inner.:[129:7->131:8] -Completable: Cpath Value[Outer, Inner, ""] -[{ - "label": "hello", - "kind": 12, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 136:7 -posCursor:[136:7] posNoWhite:[136:6] Found expr:[135:3->138:9] -JSX 135:6] x[136:5->136:6]=...[138:4->138:8]> _children:None +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Jsx.res 150:21 -posCursor:[150:21] posNoWhite:[150:20] Found expr:[150:12->150:32] -JSX 150:21] name[150:22->150:26]=...[150:27->150:29]> _children:150:30 -Completable: Cpath Module[Nested, Co] -[{ - "label": "Comp", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Complete src/Jsx.res 153:19 -posCursor:[153:19] posNoWhite:[153:18] Found expr:[153:12->153:25] -JSX 153:24] > _children:None -Completable: Cpath Module[Nested, ""] -[{ - "label": "Comp", - "kind": 9, - "tags": [], - "detail": "module", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] Hover src/Jsx.res 162:12 Nothing at that position. Now trying to use completion. -posCursor:[162:12] posNoWhite:[162:11] Found expr:[162:3->162:21] -Pexp_construct :::[162:6->162:21] [162:6->162:21] -posCursor:[162:12] posNoWhite:[162:11] Found expr:[162:6->162:21] -posCursor:[162:12] posNoWhite:[162:11] Found expr:[162:6->162:20] -JSX 162:10] age[162:11->162:14]=...[162:15->162:17]> _children:162:18 -Completable: Cjsx([Comp], age, [age]) -{"contents": "```rescript\nint\n```"} +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +null Hover src/Jsx.res 167:16 Nothing at that position. Now trying to use completion. -posCursor:[167:16] posNoWhite:[167:15] Found expr:[167:3->167:30] -Pexp_construct :::[167:7->167:30] [167:7->167:30] -posCursor:[167:16] posNoWhite:[167:15] Found expr:[167:7->167:30] -posCursor:[167:16] posNoWhite:[167:15] Found expr:[167:7->167:25] -Pexp_construct :::[167:10->167:25] [167:10->167:25] -posCursor:[167:16] posNoWhite:[167:15] Found expr:[167:10->167:25] -posCursor:[167:16] posNoWhite:[167:15] Found expr:[167:10->167:24] -JSX 167:14] age[167:15->167:18]=...[167:19->167:21]> _children:167:22 -Completable: Cjsx([Comp], age, [age]) -{"contents": "```rescript\nint\n```"} +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +null Complete src/Jsx.res 171:30 -posCursor:[171:30] posNoWhite:[171:28] Found expr:[171:12->171:33] -JSX 171:29] > _children:171:31 -Completable: Cjsx([Completion, O, Comp], "", []) -[{ - "label": "first", - "kind": 4, - "tags": [], - "detail": "option", - "documentation": null, - "sortText": null - }, { - "label": "second", - "kind": 4, - "tags": [], - "detail": "int", - "documentation": null, - "sortText": null - }, { - "label": "zoo", - "kind": 4, - "tags": [], - "detail": "option", - "documentation": null, - "sortText": null - }, { - "label": "key", - "kind": 4, - "tags": [], - "detail": "string", - "documentation": null, - "sortText": null - }] +XXX Not found! +Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] diff --git a/analysis/tests/src/expected/Jsx.resi.txt b/analysis/tests/src/expected/Jsx.resi.txt index 670c65be9..b012794d4 100644 --- a/analysis/tests/src/expected/Jsx.resi.txt +++ b/analysis/tests/src/expected/Jsx.resi.txt @@ -16,7 +16,9 @@ Completable: Cpath Type[React, e] "tags": [], "detail": "type element", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/Jsx.resi 10:18 @@ -29,6 +31,8 @@ Completable: Cpath Type[React, e] "tags": [], "detail": "type element", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] diff --git a/analysis/tests/src/expected/RecordCompletion.res.txt b/analysis/tests/src/expected/RecordCompletion.res.txt index 12a3f7ce5..567c549d0 100644 --- a/analysis/tests/src/expected/RecordCompletion.res.txt +++ b/analysis/tests/src/expected/RecordCompletion.res.txt @@ -7,14 +7,18 @@ Completable: Cpath Value[t].n->m "tags": [], "detail": "(t<'a>, ('a, int) => 'b) => t<'b>", "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The function acceps two arguments: an item from the array and its\nindex number. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\n// multiply each item in array by its position\nlet product = (item, index) => item * index\nJs.Array2.mapi([10, 11, 12], product) == [0, 11, 24]\n```\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js.Array2.map", "kind": 12, "tags": [], "detail": "(t<'a>, 'a => 'b) => t<'b>", "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\nJs.Array2.map([12, 4, 8], x => x * x) == [144, 16, 64]\nJs.Array2.map([\"animal\", \"vegetable\", \"mineral\"], Js.String.length) == [6, 9, 7]\n```\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/RecordCompletion.res 11:13 @@ -26,14 +30,18 @@ Completable: Cpath Value[t2].n2.n->m "tags": [], "detail": "(t<'a>, ('a, int) => 'b) => t<'b>", "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The function acceps two arguments: an item from the array and its\nindex number. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\n// multiply each item in array by its position\nlet product = (item, index) => item * index\nJs.Array2.mapi([10, 11, 12], product) == [0, 11, 24]\n```\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js.Array2.map", "kind": 12, "tags": [], "detail": "(t<'a>, 'a => 'b) => t<'b>", "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\nJs.Array2.map([12, 4, 8], x => x * x) == [144, 16, 64]\nJs.Array2.map([\"animal\", \"vegetable\", \"mineral\"], Js.String.length) == [6, 9, 7]\n```\n"}, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/RecordCompletion.res 19:7 @@ -46,7 +54,9 @@ Completable: Cpath Module[R]."" "tags": [], "detail": "name: string\n\ntype t = {name: string}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/RecordCompletion.res 22:7 @@ -59,6 +69,8 @@ Completable: Cpath Module[R]."" "tags": [], "detail": "name: string\n\ntype t = {name: string}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] diff --git a/analysis/tests/src/expected/RecoveryOnProp.res.txt b/analysis/tests/src/expected/RecoveryOnProp.res.txt index 8b3dcf599..7dcea2f3a 100644 --- a/analysis/tests/src/expected/RecoveryOnProp.res.txt +++ b/analysis/tests/src/expected/RecoveryOnProp.res.txt @@ -1,26 +1,7 @@ Complete src/RecoveryOnProp.res 6:26 -posCursor:[6:26] posNoWhite:[6:25] Found expr:[3:3->11:8] -JSX 3:6] onClick[4:4->4:11]=...[4:13->0:-1]> _children:None -posCursor:[6:26] posNoWhite:[6:25] Found expr:[4:13->8:6] -posCursor:[6:26] posNoWhite:[6:25] Found expr:[5:6->8:5] -posCursor:[6:26] posNoWhite:[6:25] Found expr:[6:16->8:5] posCursor:[6:26] posNoWhite:[6:25] Found pattern:[6:20->8:5] posCursor:[6:26] posNoWhite:[6:25] Found type:[6:23->8:5] Ptyp_constr Res:[6:23->8:5] -Completable: Cpath Type[Res] -[{ - "label": "RescriptReactErrorBoundary", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null, - "sortText": null - }, { - "label": "RescriptReactRouter", - "kind": 9, - "tags": [], - "detail": "file module", - "documentation": null, - "sortText": null - }] +Completable: CtypedPattern(sourceType:Value[div](~onClick, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +[] diff --git a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt index 9b99934c1..f4cb773bb 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Jsx.res.txt @@ -8,7 +8,9 @@ Completable: Cjsx([SomeComponent], someVaria, [someVaria]) "tags": [], "detail": "someVariant", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Jsx.res 23:38 @@ -33,42 +35,54 @@ Completable: Cpath Value[T] "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "TypeContextCompletion_Jsx", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "TypeContextCompletion_LabelledArguments", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "TypeContextCompletion_Records", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "TypeDefinition", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "TypedContextCompletionSpec", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Jsx.res 32:39 diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index ef0446702..9540fa82e 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -13,7 +13,9 @@ Found type for function ( "tags": [], "detail": "someVariant", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_LabelledArguments.res 25:44 @@ -38,42 +40,54 @@ Completable: Cpath Value[T] "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "TypeContextCompletion_Jsx", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "TypeContextCompletion_LabelledArguments", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "TypeContextCompletion_Records", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "TypeDefinition", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "TypedContextCompletionSpec", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_LabelledArguments.res 34:45 @@ -88,7 +102,9 @@ Completable: Cpath Value[t] "tags": [], "detail": "someVariant", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_LabelledArguments.res 37:59 @@ -103,49 +119,63 @@ Completable: Cpath Value[TypeDefinition, ""] "tags": [], "detail": "variant => string", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "x", "kind": 12, "tags": [], "detail": "variant", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "y", "kind": 12, "tags": [], "detail": "record", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "obj", "kind": 12, "tags": [], "detail": "obj", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "f", "kind": 12, "tags": [], "detail": "record => string", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Foo", "kind": 4, "tags": [], "detail": "Foo\n\ntype variant = Foo | Bar", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Bar", "kind": 4, "tags": [], "detail": "Bar\n\ntype variant = Foo | Bar", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_LabelledArguments.res 40:45 @@ -176,10 +206,8 @@ posCursor:[52:45] posNoWhite:[52:44] Found expr:[52:43->52:45] [] Complete src/TypeContextCompletion_LabelledArguments.res 64:36 -posCursor:[64:36] posNoWhite:[64:35] Found expr:[64:11->64:47] -Pexp_apply ...[64:11->64:18] (~doThing64:20->64:27=...[64:28->64:46]) -posCursor:[64:36] posNoWhite:[64:35] Found expr:[64:28->64:46] posCursor:[64:36] posNoWhite:[64:35] Found pattern:[64:29->64:37] posCursor:[64:36] posNoWhite:[64:35] Found pattern:[64:35->64:36] +Completable: CtypedPattern(sourceType:Value[doStuff](~doThing), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 71b9e5b7d..4f1e6f579 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -8,7 +8,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 19:23 @@ -21,7 +23,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 22:8 @@ -33,21 +37,27 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "anotherThing", "kind": 5, "tags": [], "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "thirdThing", "kind": 5, "tags": [], "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 31:8 @@ -59,21 +69,27 @@ Completable: CtypedPattern(sourceType:Value[getSomeVal](~irrelevant), lookingToC "tags": [], "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "anotherThing", "kind": 5, "tags": [], "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "thirdThing", "kind": 5, "tags": [], "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 35:20 @@ -86,21 +102,27 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "whatIsThis", "kind": 5, "tags": [], "detail": "whatIsThis: bool\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "anotherLevel", "kind": 5, "tags": [], "detail": "anotherLevel: anotherLevel\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 38:47 @@ -114,14 +136,18 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "level: int\n\ntype anotherLevel = {level: int, someOtherArg: bool}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "someOtherArg", "kind": 5, "tags": [], "detail": "someOtherArg: bool\n\ntype anotherLevel = {level: int, someOtherArg: bool}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 41:48 @@ -136,7 +162,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "level: int\n\ntype anotherLevel = {level: int, someOtherArg: bool}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 44:47 @@ -149,7 +177,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 47:31 @@ -162,7 +192,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 50:44 @@ -176,7 +208,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 53:52 @@ -189,21 +223,27 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "anotherThing", "kind": 5, "tags": [], "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "thirdThing", "kind": 5, "tags": [], "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 56:89 @@ -217,7 +257,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 81:48 @@ -233,7 +275,9 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "tags": [], "detail": "Three(int)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 84:48 @@ -250,14 +294,18 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "tags": [], "detail": "Two\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Three(_)", "kind": 4, "tags": [], "detail": "Three(int)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 87:47 @@ -273,14 +321,18 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "tags": [], "detail": "Two\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Three(_)", "kind": 4, "tags": [], "detail": "Three(int)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 90:51 @@ -310,7 +362,9 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "tags": [], "detail": "One\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 96:63 @@ -342,7 +396,9 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "tags": [], "detail": "Three(int)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 102:43 @@ -357,42 +413,54 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "tags": [], "detail": "None\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(One)", "kind": 4, "tags": [], "detail": "One\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(Two)", "kind": 4, "tags": [], "detail": "Two\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(Three(_))", "kind": 4, "tags": [], "detail": "Three(int)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(Four(_))", "kind": 4, "tags": [], "detail": "Four(someOtherVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(Five(_))", "kind": 4, "tags": [], "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 105:39 @@ -407,14 +475,18 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "tags": [], "detail": "None\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(_)", "kind": 4, "tags": [], "detail": "Some(_)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 108:64 @@ -436,14 +508,18 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "tags": [], "detail": "None\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(_)", "kind": 4, "tags": [], "detail": "Some(_)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 114:55 @@ -457,7 +533,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoConte "tags": [], "detail": "boolean\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 117:46 @@ -471,14 +549,18 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoConte "tags": [], "detail": "boolean\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "true", "kind": 12, "tags": [], "detail": "boolean\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 120:49 @@ -493,7 +575,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CVariant "tags": [], "detail": "boolean\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 125:15 @@ -505,42 +589,54 @@ Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CNoContext, pa "tags": [], "detail": "None\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(One)", "kind": 4, "tags": [], "detail": "One\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(Two)", "kind": 4, "tags": [], "detail": "Two\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(Three(_))", "kind": 4, "tags": [], "detail": "Three(int)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(Four(_))", "kind": 4, "tags": [], "detail": "Four(someOtherVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(Five(_))", "kind": 4, "tags": [], "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 128:14 @@ -556,35 +652,45 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "tags": [], "detail": "One\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Two", "kind": 4, "tags": [], "detail": "Two\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Three(_)", "kind": 4, "tags": [], "detail": "Three(int)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Four(_)", "kind": 4, "tags": [], "detail": "Four(someOtherVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Five(_)", "kind": 4, "tags": [], "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 136:36 @@ -596,14 +702,18 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "tags": [], "detail": "Four(someOtherVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Five(_)", "kind": 4, "tags": [], "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 140:33 @@ -616,7 +726,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoConte "tags": [], "detail": "Empty record", "documentation": null, - "sortText": "a" + "sortText": "a", + "insertText": null, + "insertTextFormat": null }] Complete src/TypeContextCompletion_Records.res 144:35 @@ -630,20 +742,52 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "whatIsThis", "kind": 5, "tags": [], "detail": "whatIsThis: bool\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "anotherLevel", "kind": 5, "tags": [], "detail": "anotherLevel: anotherLevel\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] + +Complete src/TypeContextCompletion_Records.res 147:45 +posCursor:[147:45] posNoWhite:[147:44] Found expr:[147:3->147:58] +posCursor:[147:45] posNoWhite:[147:44] Found pattern:[147:29->147:50] +posCursor:[147:45] posNoWhite:[147:44] Found pattern:[147:43->147:49] +posCursor:[147:45] posNoWhite:[147:44] Found pattern:[147:44->147:45] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:fourthStuff, Tuple:0], seenIdents: []) +[{ + "label": "None", + "kind": 4, + "tags": [], + "detail": "None\n\n", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "Some(#WithPayload(_))", + "kind": 4, + "tags": [], + "detail": "#WithPayload(someVariant)", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null }] diff --git a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt index 154bfb59f..1d2b85f10 100644 --- a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt +++ b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt @@ -180,11 +180,9 @@ Pstr_value( ) Complete src/TypedContextCompletionSpec.res 93:36 -posCursor:[93:36] posNoWhite:[93:35] Found expr:[93:11->93:47] -Pexp_apply ...[93:11->93:18] (~doThing93:20->93:27=...[93:28->93:46]) -posCursor:[93:36] posNoWhite:[93:35] Found expr:[93:28->93:46] posCursor:[93:36] posNoWhite:[93:35] Found pattern:[93:29->93:37] posCursor:[93:36] posNoWhite:[93:35] Found pattern:[93:35->93:36] +Completable: CtypedPattern(sourceType:Value[doStuff](~doThing), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/TypedContextCompletionSpec.res 97:15 @@ -197,7 +195,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 101:23 @@ -210,7 +210,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 105:8 @@ -222,21 +224,27 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "anotherThing", "kind": 5, "tags": [], "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "thirdThing", "kind": 5, "tags": [], "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 109:8 @@ -248,21 +256,27 @@ Completable: CtypedPattern(sourceType:Value[getSomeVal](~irrelevant), lookingToC "tags": [], "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "anotherThing", "kind": 5, "tags": [], "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "thirdThing", "kind": 5, "tags": [], "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 113:20 @@ -275,21 +289,27 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "whatIsThis", "kind": 5, "tags": [], "detail": "whatIsThis: bool\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "anotherLevel", "kind": 5, "tags": [], "detail": "anotherLevel: anotherLevel\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 117:47 @@ -303,14 +323,18 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "level: int\n\ntype anotherLevel = {level: int, someOtherArg: bool}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "someOtherArg", "kind": 5, "tags": [], "detail": "someOtherArg: bool\n\ntype anotherLevel = {level: int, someOtherArg: bool}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 121:48 @@ -325,7 +349,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "level: int\n\ntype anotherLevel = {level: int, someOtherArg: bool}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 125:47 @@ -338,7 +364,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 129:31 @@ -351,7 +379,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 137:44 @@ -365,7 +395,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 141:52 @@ -378,21 +410,27 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "anotherThing", "kind": 5, "tags": [], "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "thirdThing", "kind": 5, "tags": [], "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 145:89 @@ -406,7 +444,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 149:48 @@ -422,7 +462,9 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "tags": [], "detail": "Three(int)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 152:48 @@ -439,14 +481,18 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "tags": [], "detail": "Two\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Three(_)", "kind": 4, "tags": [], "detail": "Three(int)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 155:47 @@ -462,14 +508,18 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "tags": [], "detail": "Two\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Three(_)", "kind": 4, "tags": [], "detail": "Three(int)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 158:51 @@ -499,7 +549,9 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "tags": [], "detail": "One\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 164:63 @@ -531,7 +583,9 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "tags": [], "detail": "Three(int)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 170:43 @@ -546,42 +600,54 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "tags": [], "detail": "None\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(One)", "kind": 4, "tags": [], "detail": "One\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(Two)", "kind": 4, "tags": [], "detail": "Two\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(Three(_))", "kind": 4, "tags": [], "detail": "Three(int)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(Four(_))", "kind": 4, "tags": [], "detail": "Four(someOtherVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(Five(_))", "kind": 4, "tags": [], "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 173:39 @@ -596,14 +662,18 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "tags": [], "detail": "None\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(_)", "kind": 4, "tags": [], "detail": "Some(_)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 176:64 @@ -625,14 +695,18 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "tags": [], "detail": "None\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(_)", "kind": 4, "tags": [], "detail": "Some(_)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 182:55 @@ -646,7 +720,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoConte "tags": [], "detail": "boolean\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 185:46 @@ -660,14 +736,18 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoConte "tags": [], "detail": "boolean\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "true", "kind": 12, "tags": [], "detail": "boolean\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 188:49 @@ -682,7 +762,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CVariant "tags": [], "detail": "boolean\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 192:15 @@ -694,42 +776,54 @@ Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CNoContext, pa "tags": [], "detail": "None\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(One)", "kind": 4, "tags": [], "detail": "One\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(Two)", "kind": 4, "tags": [], "detail": "Two\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(Three(_))", "kind": 4, "tags": [], "detail": "Three(int)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(Four(_))", "kind": 4, "tags": [], "detail": "Four(someOtherVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Some(Five(_))", "kind": 4, "tags": [], "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 196:14 @@ -745,35 +839,45 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "tags": [], "detail": "One\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Two", "kind": 4, "tags": [], "detail": "Two\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Three(_)", "kind": 4, "tags": [], "detail": "Three(int)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Four(_)", "kind": 4, "tags": [], "detail": "Four(someOtherVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Five(_)", "kind": 4, "tags": [], "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 202:36 @@ -785,14 +889,18 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "tags": [], "detail": "Four(someOtherVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Five(_)", "kind": 4, "tags": [], "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 206:33 @@ -805,7 +913,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoConte "tags": [], "detail": "Empty record", "documentation": null, - "sortText": "a" + "sortText": "a", + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 210:22 @@ -817,1239 +927,1593 @@ Completable: Cpath Value[""] "tags": [], "detail": "someVariant", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "x", "kind": 12, "tags": [], "detail": "option", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "someOtherValue", "kind": 12, "tags": [], "detail": "someRecordWithVariant", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "getSomeVal", "kind": 12, "tags": [], "detail": "(~irrelevant: int) => anotherRecord", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "someVal", "kind": 12, "tags": [], "detail": "anotherRecord", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Arg", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Array", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "ArrayLabels", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Auto", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_Array", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_Float", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_HashMap", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_HashMapInt", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_HashMapString", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_HashSet", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_HashSetInt", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_HashSetString", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_Id", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_Int", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_List", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_Map", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_MapDict", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_MapInt", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_MapString", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_MutableMap", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_MutableMapInt", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_MutableMapString", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_MutableQueue", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_MutableSet", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_MutableSetInt", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_MutableSetString", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_MutableStack", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_Option", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_Range", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_Result", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_Set", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_SetDict", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_SetInt", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_SetString", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_SortArray", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_SortArrayInt", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_SortArrayString", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_internalAVLset", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_internalAVLtree", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_internalBuckets", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_internalBucketsType", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_internalMapInt", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_internalMapString", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_internalSetBuckets", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_internalSetInt", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_internalSetString", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Belt_internals", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Buffer", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Bytes", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "BytesLabels", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Callback", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "CamlinternalLazy", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "CamlinternalMod", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Char", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "CodeLens", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "CompletePrioritize1", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "CompletePrioritize2", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Completion", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Complex", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Component", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "CreateInterface", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Cross", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Dce", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Debug", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Definition", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "DefinitionWithInterface", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Digest", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Div", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "DocumentSymbol", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Dom", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Dom_storage", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Dom_storage2", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Filename", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Fragment", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Genlex", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Hashtbl", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "HashtblLabels", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Highlight", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Hover", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "InlayHint", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Int32", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Int64", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_OO", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_array", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_array2", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_bigint", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_cast", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_console", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_date", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_dict", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_exn", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_float", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_global", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_int", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_json", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_list", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_mapperRt", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_math", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_null", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_null_undefined", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_obj", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_option", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_promise", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_re", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_result", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_string", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_string2", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_typed_array", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_typed_array2", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_types", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_undefined", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Js_vector", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Jsx", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Lazy", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Lexing", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "List", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "ListLabels", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "LongIdentTest", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Map", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "MapLabels", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "MoreLabels", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Node", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Node_buffer", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Node_child_process", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Node_fs", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Node_module", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Node_path", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Node_process", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Obj", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Object", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Parsing", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Patterns", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Pervasives", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Printexc", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Queue", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Random", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "React", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "ReactDOM", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "ReactDOMRe", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "ReactDOMServer", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "ReactDOMStyle", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "ReactEvent", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "ReactTestUtils", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "ReasonReact", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "RecModules", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "RecordCompletion", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "RecoveryOnProp", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "References", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "ReferencesWithInterface", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Rename", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "RenameWithInterface", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "RescriptReactErrorBoundary", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "RescriptReactRouter", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Set", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "SetLabels", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Sort", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Stack", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "StdLabels", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Stream", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "String", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "StringLabels", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Sys", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "TableclothMap", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "TypeContextCompletion_Jsx", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "TypeContextCompletion_LabelledArguments", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "TypeContextCompletion_Records", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "TypeDefinition", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "TypedContextCompletionSpec", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Uchar", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Xform", "kind": 9, "tags": [], "detail": "file module", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 214:23 @@ -2062,21 +2526,27 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "something: someRecord\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "anotherThing", "kind": 5, "tags": [], "detail": "anotherThing: option\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "thirdThing", "kind": 5, "tags": [], "detail": "thirdThing: string\n\ntype anotherRecord = {\n something: someRecord,\n anotherThing: option,\n thirdThing: string,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 218:31 @@ -2097,21 +2567,27 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CRecordF "tags": [], "detail": "somethingElse: int\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "whatIsThis", "kind": 5, "tags": [], "detail": "whatIsThis: bool\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "anotherLevel", "kind": 5, "tags": [], "detail": "anotherLevel: anotherLevel\n\ntype someRecord = {\n somethingElse: int,\n whatIsThis: bool,\n anotherLevel: anotherLevel,\n}", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 225:38 @@ -2168,7 +2644,9 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoConte "tags": [], "detail": "boolean\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 245:49 @@ -2180,14 +2658,18 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "tags": [], "detail": "Four(someOtherVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Five(_)", "kind": 4, "tags": [], "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, - "sortText": null + "sortText": null, + "insertText": null, + "insertTextFormat": null }] Complete src/TypedContextCompletionSpec.res 248:41 @@ -2200,13 +2682,17 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "tags": [], "detail": "Full tuple match", "documentation": null, - "sortText": "a" + "sortText": "a", + "insertText": "(${1:_}, ${2:_}, ${3:_}, ${4:_})", + "insertTextFormat": 2 }, { "label": "()", "kind": 4, "tags": [], "detail": "Empty tuple match for single element", "documentation": null, - "sortText": "b" + "sortText": "b", + "insertText": null, + "insertTextFormat": null }] diff --git a/server/src/server.ts b/server/src/server.ts index 76c78e0b7..cdea55c7d 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -34,6 +34,12 @@ interface extensionConfiguration { binaryPath: string | null; } +interface clientCapabilites { + completion: { + supportsSnippets: boolean; + }; +} + // All values here are temporary, and will be overridden as the server is // initialized, and the current config is received from the client. let extensionConfiguration: extensionConfiguration = { @@ -45,6 +51,11 @@ let extensionConfiguration: extensionConfiguration = { codeLens: false, binaryPath: null, }; +let clientCapabilites: clientCapabilites = { + completion: { + supportsSnippets: false, + }, +}; let pullConfigurationPeriodically: NodeJS.Timeout | null = null; // https://microsoft.github.io/language-server-protocol/specification#initialize @@ -607,7 +618,7 @@ function semanticTokens(msg: p.RequestMessage) { function completion(msg: p.RequestMessage) { // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion - let params = msg.params as p.ReferenceParams; + let params = msg.params as p.CompletionParams; let filePath = fileURLToPath(params.textDocument.uri); let code = getOpenedFileContent(params.textDocument.uri); let tmpname = utils.createFileInTempDir(); @@ -620,6 +631,7 @@ function completion(msg: p.RequestMessage) { params.position.line, params.position.character, tmpname, + clientCapabilites.completion.supportsSnippets ? "true" : "false", ], msg ); @@ -1000,6 +1012,15 @@ function onMessage(msg: p.Message) { extensionConfiguration = initialConfiguration; } + // Build and save config representing the client capabilities we care about. + clientCapabilites = { + completion: { + supportsSnippets: + initParams.capabilities.textDocument?.completion?.completionItem + ?.snippetSupport === true, + }, + }; + // send the list of features we support let result: p.InitializeResult = { // This tells the client: "hey, we support the following operations". From f98db04556492c89135371386d73daeb290e232d Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 16 Aug 2022 15:21:52 +0200 Subject: [PATCH 67/80] properly apply command --- analysis/src/Commands.ml | 3 +- .../TypeContextCompletion_Records.res.txt | 112 ++++++++-------- .../TypedContextCompletionSpec.res.txt | 120 +++++++++--------- 3 files changed, 118 insertions(+), 117 deletions(-) diff --git a/analysis/src/Commands.ml b/analysis/src/Commands.ml index 82ce646e7..3f5fe9ed0 100644 --- a/analysis/src/Commands.ml +++ b/analysis/src/Commands.ml @@ -328,7 +328,8 @@ let test ~path = ("Complete " ^ path ^ " " ^ string_of_int line ^ ":" ^ string_of_int col); let currentFile = createCurrentFile () in - completion ~debug:true ~path ~pos:(line, col) ~currentFile; + completion ~debug:true ~path ~pos:(line, col) ~currentFile + ~supportsSnippets:true; Sys.remove currentFile | "dce" -> print_endline ("DCE " ^ path); diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 4f1e6f579..377ece653 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -276,8 +276,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Three(int)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Three(${1:_})", + "insertTextFormat": 2 }] Complete src/TypeContextCompletion_Records.res 84:48 @@ -295,8 +295,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Two\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Two", + "insertTextFormat": 2 }, { "label": "Three(_)", "kind": 4, @@ -304,8 +304,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Three(int)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Three(${1:_})", + "insertTextFormat": 2 }] Complete src/TypeContextCompletion_Records.res 87:47 @@ -322,8 +322,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Two\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Two", + "insertTextFormat": 2 }, { "label": "Three(_)", "kind": 4, @@ -331,8 +331,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Three(int)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Three(${1:_})", + "insertTextFormat": 2 }] Complete src/TypeContextCompletion_Records.res 90:51 @@ -363,8 +363,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "One\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "One", + "insertTextFormat": 2 }] Complete src/TypeContextCompletion_Records.res 96:63 @@ -397,8 +397,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Three(int)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Three(${1:_})", + "insertTextFormat": 2 }] Complete src/TypeContextCompletion_Records.res 102:43 @@ -423,8 +423,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "One\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(One)", + "insertTextFormat": 2 }, { "label": "Some(Two)", "kind": 4, @@ -432,8 +432,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Two\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(Two)", + "insertTextFormat": 2 }, { "label": "Some(Three(_))", "kind": 4, @@ -441,8 +441,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Three(int)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(Three(${1:_}))", + "insertTextFormat": 2 }, { "label": "Some(Four(_))", "kind": 4, @@ -450,8 +450,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Four(someOtherVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(Four(${1:_}))", + "insertTextFormat": 2 }, { "label": "Some(Five(_))", "kind": 4, @@ -459,8 +459,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(Five(${1:_}))", + "insertTextFormat": 2 }] Complete src/TypeContextCompletion_Records.res 105:39 @@ -485,8 +485,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Some(_)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(${1:_})", + "insertTextFormat": 2 }] Complete src/TypeContextCompletion_Records.res 108:64 @@ -518,8 +518,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Some(_)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(${1:_})", + "insertTextFormat": 2 }] Complete src/TypeContextCompletion_Records.res 114:55 @@ -599,8 +599,8 @@ Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CNoContext, pa "detail": "One\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(One)", + "insertTextFormat": 2 }, { "label": "Some(Two)", "kind": 4, @@ -608,8 +608,8 @@ Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CNoContext, pa "detail": "Two\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(Two)", + "insertTextFormat": 2 }, { "label": "Some(Three(_))", "kind": 4, @@ -617,8 +617,8 @@ Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CNoContext, pa "detail": "Three(int)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(Three(${1:_}))", + "insertTextFormat": 2 }, { "label": "Some(Four(_))", "kind": 4, @@ -626,8 +626,8 @@ Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CNoContext, pa "detail": "Four(someOtherVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(Four(${1:_}))", + "insertTextFormat": 2 }, { "label": "Some(Five(_))", "kind": 4, @@ -635,8 +635,8 @@ Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CNoContext, pa "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(Five(${1:_}))", + "insertTextFormat": 2 }] Complete src/TypeContextCompletion_Records.res 128:14 @@ -653,8 +653,8 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "detail": "One\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "One", + "insertTextFormat": 2 }, { "label": "Two", "kind": 4, @@ -662,8 +662,8 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "detail": "Two\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Two", + "insertTextFormat": 2 }, { "label": "Three(_)", "kind": 4, @@ -671,8 +671,8 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "detail": "Three(int)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Three(${1:_})", + "insertTextFormat": 2 }, { "label": "Four(_)", "kind": 4, @@ -680,8 +680,8 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "detail": "Four(someOtherVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Four(${1:_})", + "insertTextFormat": 2 }, { "label": "Five(_)", "kind": 4, @@ -689,8 +689,8 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Five(${1:_})", + "insertTextFormat": 2 }] Complete src/TypeContextCompletion_Records.res 136:36 @@ -703,8 +703,8 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "detail": "Four(someOtherVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Four(${1:_})", + "insertTextFormat": 2 }, { "label": "Five(_)", "kind": 4, @@ -712,8 +712,8 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Five(${1:_})", + "insertTextFormat": 2 }] Complete src/TypeContextCompletion_Records.res 140:33 @@ -727,8 +727,8 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoConte "detail": "Empty record", "documentation": null, "sortText": "a", - "insertText": null, - "insertTextFormat": null + "insertText": "{${1}}", + "insertTextFormat": 2 }] Complete src/TypeContextCompletion_Records.res 144:35 @@ -787,7 +787,7 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "#WithPayload(someVariant)", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(#WithPayload(${1:_}))", + "insertTextFormat": 2 }] diff --git a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt index 1d2b85f10..5a681e90a 100644 --- a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt +++ b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt @@ -463,8 +463,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Three(int)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Three(${1:_})", + "insertTextFormat": 2 }] Complete src/TypedContextCompletionSpec.res 152:48 @@ -482,8 +482,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Two\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Two", + "insertTextFormat": 2 }, { "label": "Three(_)", "kind": 4, @@ -491,8 +491,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Three(int)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Three(${1:_})", + "insertTextFormat": 2 }] Complete src/TypedContextCompletionSpec.res 155:47 @@ -509,8 +509,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Two\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Two", + "insertTextFormat": 2 }, { "label": "Three(_)", "kind": 4, @@ -518,8 +518,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Three(int)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Three(${1:_})", + "insertTextFormat": 2 }] Complete src/TypedContextCompletionSpec.res 158:51 @@ -550,8 +550,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "One\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "One", + "insertTextFormat": 2 }] Complete src/TypedContextCompletionSpec.res 164:63 @@ -584,8 +584,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Three(int)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Three(${1:_})", + "insertTextFormat": 2 }] Complete src/TypedContextCompletionSpec.res 170:43 @@ -610,8 +610,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "One\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(One)", + "insertTextFormat": 2 }, { "label": "Some(Two)", "kind": 4, @@ -619,8 +619,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Two\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(Two)", + "insertTextFormat": 2 }, { "label": "Some(Three(_))", "kind": 4, @@ -628,8 +628,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Three(int)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(Three(${1:_}))", + "insertTextFormat": 2 }, { "label": "Some(Four(_))", "kind": 4, @@ -637,8 +637,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Four(someOtherVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(Four(${1:_}))", + "insertTextFormat": 2 }, { "label": "Some(Five(_))", "kind": 4, @@ -646,8 +646,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(Five(${1:_}))", + "insertTextFormat": 2 }] Complete src/TypedContextCompletionSpec.res 173:39 @@ -672,8 +672,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Some(_)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(${1:_})", + "insertTextFormat": 2 }] Complete src/TypedContextCompletionSpec.res 176:64 @@ -705,8 +705,8 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Some(_)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(${1:_})", + "insertTextFormat": 2 }] Complete src/TypedContextCompletionSpec.res 182:55 @@ -786,8 +786,8 @@ Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CNoContext, pa "detail": "One\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(One)", + "insertTextFormat": 2 }, { "label": "Some(Two)", "kind": 4, @@ -795,8 +795,8 @@ Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CNoContext, pa "detail": "Two\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(Two)", + "insertTextFormat": 2 }, { "label": "Some(Three(_))", "kind": 4, @@ -804,8 +804,8 @@ Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CNoContext, pa "detail": "Three(int)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(Three(${1:_}))", + "insertTextFormat": 2 }, { "label": "Some(Four(_))", "kind": 4, @@ -813,8 +813,8 @@ Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CNoContext, pa "detail": "Four(someOtherVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(Four(${1:_}))", + "insertTextFormat": 2 }, { "label": "Some(Five(_))", "kind": 4, @@ -822,8 +822,8 @@ Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CNoContext, pa "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Some(Five(${1:_}))", + "insertTextFormat": 2 }] Complete src/TypedContextCompletionSpec.res 196:14 @@ -840,8 +840,8 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "detail": "One\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "One", + "insertTextFormat": 2 }, { "label": "Two", "kind": 4, @@ -849,8 +849,8 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "detail": "Two\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Two", + "insertTextFormat": 2 }, { "label": "Three(_)", "kind": 4, @@ -858,8 +858,8 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "detail": "Three(int)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Three(${1:_})", + "insertTextFormat": 2 }, { "label": "Four(_)", "kind": 4, @@ -867,8 +867,8 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "detail": "Four(someOtherVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Four(${1:_})", + "insertTextFormat": 2 }, { "label": "Five(_)", "kind": 4, @@ -876,8 +876,8 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Five(${1:_})", + "insertTextFormat": 2 }] Complete src/TypedContextCompletionSpec.res 202:36 @@ -890,8 +890,8 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "detail": "Four(someOtherVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Four(${1:_})", + "insertTextFormat": 2 }, { "label": "Five(_)", "kind": 4, @@ -899,8 +899,8 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Five(${1:_})", + "insertTextFormat": 2 }] Complete src/TypedContextCompletionSpec.res 206:33 @@ -914,8 +914,8 @@ Completable: CtypedPattern(sourceType:Value[someVal], lookingToComplete:CNoConte "detail": "Empty record", "documentation": null, "sortText": "a", - "insertText": null, - "insertTextFormat": null + "insertText": "{${1}}", + "insertTextFormat": 2 }] Complete src/TypedContextCompletionSpec.res 210:22 @@ -2659,8 +2659,8 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "detail": "Four(someOtherVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Four(${1:_})", + "insertTextFormat": 2 }, { "label": "Five(_)", "kind": 4, @@ -2668,8 +2668,8 @@ Completable: CtypedPattern(sourceType:Value[y], lookingToComplete:CNoContext, pa "detail": "Five(someOtherVariant, someVariant)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Five(${1:_})", + "insertTextFormat": 2 }] Complete src/TypedContextCompletionSpec.res 248:41 @@ -2692,7 +2692,7 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "detail": "Empty tuple match for single element", "documentation": null, "sortText": "b", - "insertText": null, - "insertTextFormat": null + "insertText": "($1)", + "insertTextFormat": 2 }] From 5558995e1958c4cc51ef9a4eeb7a9682bb38444e Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 16 Aug 2022 16:18:39 +0200 Subject: [PATCH 68/80] implement support for tuple context paths in completion --- analysis/src/CompletionBackEnd.ml | 31 +++++++++++++++++++++++++++++- analysis/src/CompletionFrontEnd.ml | 5 +++++ analysis/src/SharedTypes.ml | 4 ++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 3fa3b7e6f..945088d3f 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1280,6 +1280,34 @@ let rec getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos ] | _ -> []) | None -> []) + | CTuple ctxPaths -> + (* Turn a list of context paths into a list of type expressions. *) + let typeExrps = + ctxPaths + |> List.map (fun contextPath -> + contextPath + |> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles + ~pos ~env ~exact:true ~scope) + |> List.filter_map (fun completionItems -> + match completionItems with + | completionItem :: _ -> ( + match completionItem.Completion.kind with + | Value typ -> Some typ + | _ -> None) + | _ -> None) + in + if List.length ctxPaths = List.length typeExrps then + (* We return a "dummy" completion here with a dummy made-up type. + This completion and type is never meant to be used for anything but looking up _other_ types, + which is why this is presumably OK to do. *) + [ + Completion.create ~name:"dummy" ~env + ~kind: + (Completion.Value + Types.{level = 0; id = -1; desc = Ttuple typeExrps}) + (); + ] + else [] | CPField (CPId (path, Module), fieldName) -> (* M.field *) path @ [fieldName] @@ -2216,6 +2244,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i else None) | Some (CRecord _), _ -> [ - Completion.create ~name:"{}" ~insertText:"{${1}}" ~insertTextFormat:Snippet ~env ~sortText:"a" + Completion.create ~name:"{}" ~insertText:"{${1}}" + ~insertTextFormat:Snippet ~env ~sortText:"a" ~kind:(Completion.Label "Empty record") (); ])) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 38011a30c..b6bb95e90 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -102,6 +102,11 @@ let rec exprToContextPath (e : Parsetree.expression) = match exprToContextPath e1 with | None -> None | Some contexPath -> Some (CPApply (contexPath, args |> List.map fst))) + | Pexp_tuple exprs -> + let exprsAsContextPaths = exprs |> List.filter_map exprToContextPath in + if List.length exprs = List.length exprsAsContextPaths then + Some (CTuple exprsAsContextPaths) + else None | _ -> None type prop = { diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 69a2a3bb6..43eed18ab 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -446,6 +446,8 @@ module Completable = struct | CPField of contextPath * string | CPObj of contextPath * string | CPPipe of contextPath * string + (* A tuple containing a bunch of context paths (which are what we really want to complete). *) + | CTuple of contextPath list (* How to move through a nested type context, like from a root record to the type of one of its fields, and beyond. *) type patternPathItem = @@ -501,6 +503,8 @@ module Completable = struct | CPField (cp, s) -> contextPathToString cp ^ "." ^ str s | CPObj (cp, s) -> contextPathToString cp ^ "[\"" ^ s ^ "\"]" | CPPipe (cp, s) -> contextPathToString cp ^ "->" ^ s + | CTuple contextPaths -> + contextPaths |> List.map contextPathToString |> list type lookingToComplete = CRecordField | CVariant | CPolyvariant | CNoContext From 5320d9e8e16f2a7073453c911dc792c0365914a5 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Tue, 16 Aug 2022 16:24:58 +0200 Subject: [PATCH 69/80] dump pexp_field --- analysis/src/DumpAst.ml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/analysis/src/DumpAst.ml b/analysis/src/DumpAst.ml index adf3be23c..14f54c243 100644 --- a/analysis/src/DumpAst.ml +++ b/analysis/src/DumpAst.ml @@ -223,6 +223,11 @@ and printExprItem expr ~pos ~indentation = ^ "\n" ^ addIndentation indentation ^ ")" | Pexp_extension (({txt} as loc), _) -> "Pexp_extension(%" ^ (loc |> printLocDenominatorLoc ~pos) ^ txt ^ ")" + | Pexp_field (exp, loc) -> + "Pexp_field(" + ^ (loc |> printLocDenominatorLoc ~pos) + ^ printExprItem exp ~pos ~indentation + ^ ")" | v -> Printf.sprintf "" (Utils.identifyPexp v) let printValueBinding value ~pos ~indentation = From 36832cc351a0f2139fc02d84abbbb42106af4b83 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Wed, 17 Aug 2022 13:56:12 +0200 Subject: [PATCH 70/80] add typed expression completion type --- analysis/src/CompletionBackEnd.ml | 182 +++ analysis/src/CompletionFrontEnd.ml | 101 +- analysis/src/DumpAst.ml | 11 +- analysis/src/SharedTypes.ml | 16 + .../tests/src/TypedContextCompletionSpec.res | 6 + .../src/expected/CompletePrioritize2.res.txt | 29 +- .../tests/src/expected/Completion.res.txt | 1063 ++++++++++++++--- analysis/tests/src/expected/Cross.res.txt | 5 +- analysis/tests/src/expected/Debug.res.txt | 46 +- analysis/tests/src/expected/Hover.res.txt | 4 +- analysis/tests/src/expected/Jsx.res.txt | 473 ++++++-- .../TypedContextCompletionSpec.res.txt | 49 +- 12 files changed, 1674 insertions(+), 311 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 945088d3f..d21a545d5 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -2248,3 +2248,185 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i ~insertTextFormat:Snippet ~env ~sortText:"a" ~kind:(Completion.Label "Empty record") (); ])) + | CtypedExpression + {howToRetrieveSourceType; expressionPath; lookingToComplete; prefix} -> ( + let sourceType = + howToRetrieveSourceType + |> findSourceType ~package ~opens ~rawOpens ~allFiles ~env ~pos ~scope + in + match sourceType with + | None -> + Printf.printf "no source type\n"; + [] + | Some typ -> ( + match + ( typ + |> findTypeInContext ~env ~nestedContextPath:expressionPath ~package, + lookingToComplete ) + with + | None, _ -> [] + | Some (CTuple {types}), _ -> + (* Completing a tuple itself, like `{someFieldWithTuple: }` *) + [ + Completion.create + ~name: + ("(" + ^ (types |> List.map (fun _t -> "_") |> String.concat ", ") + ^ ")") + ~insertText: + ("(" + ^ (types + |> List.mapi (fun index _t -> + Printf.sprintf "${%i:_}" (index + 1)) + |> String.concat ", ") + ^ ")") + ~insertTextFormat:Snippet ~env ~sortText:"a" + ~kind:(Completion.Label "Full tuple match") (); + ] + | Some CBool, _ -> + (* Completing booleans - doesn't matter what we're looking to complete, since there's only one thing to complete (the bool values themselves). *) + ["false"; "true"] + |> List.filter (fun boolEntry -> Utils.startsWith boolEntry prefix) + |> List.map (fun boolEntry -> + Completion.create ~name:boolEntry ~kind:Bool ~env ()) + | Some (COptional completable), _lookingToComplete -> ( + match completable with + | CVariant {constructors} -> + (* TOOD: Unify with other variant completion handler *) + let constructorCompletions = + constructors + |> List.filter (fun constructor -> + Utils.startsWith + ("Some(" ^ constructor.Constructor.cname.txt ^ ")") + prefix) + |> List.map (fun (constructor : Constructor.t) -> + (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? + Eg. Some($1) as completion item. *) + Completion.create + ~name: + ("Some(" ^ constructor.cname.txt + ^ + if constructor.args |> List.length > 0 then "(_))" + else ")") + ~insertText: + ("Some(" ^ constructor.cname.txt + ^ + if constructor.args |> List.length > 0 then "(${1:_}))" + else ")") + ~insertTextFormat:Snippet + ~kind:(Constructor (constructor, "")) + ~env ()) + in + (* TODO: Patterns should not include local completions *) + let _localCompletions = + typ + |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix + ~exact:false ~opens ~scope + in + [Completion.create ~name:"None" ~kind:OptionNone ~env ()] + @ constructorCompletions + | CPolyVariant {constructors} -> + (* TOOD: Unify with other variant completion handler *) + let constructorCompletions = + constructors + |> List.filter (fun constructor -> + Utils.startsWith ("Some(#" ^ constructor.name ^ ")") prefix) + |> List.map (fun constructor -> + Completion.create + ~name: + ("Some(#" ^ constructor.name + ^ + if constructor.payload |> Option.is_some then "(_))" + else ")") + ~insertTextFormat:Snippet + ~insertText: + ("Some(#" ^ constructor.name + ^ + if constructor.payload |> Option.is_some then "(${1:_}))" + else ")") + ~kind:(PolyvariantConstructor constructor) ~env ()) + in + (* TODO: Patterns should not include local completions *) + let _localCompletions = + typ + |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix + ~exact:false ~opens ~scope + in + [Completion.create ~name:"None" ~kind:OptionNone ~env ()] + @ constructorCompletions + | _ -> + [ + Completion.create ~name:"None" ~kind:OptionNone ~env (); + Completion.create ~name:"Some()" ~insertText:"Some($1)" + ~insertTextFormat:Snippet ~kind:OptionSome ~env (); + ]) + | Some (CPolyVariant {constructors}), _ -> + let constructorCompletions = + constructors + |> List.filter (fun constructor -> + Utils.startsWith constructor.name prefix) + |> List.map (fun constructor -> + Completion.create + ~name: + ("#" ^ constructor.name + ^ + if constructor.payload |> Option.is_some then "(_)" else "" + ) + ~insertText: + ("#" ^ constructor.name + ^ + if constructor.payload |> Option.is_some then "($1)" + else "") + ~insertTextFormat:Snippet + ~kind:(PolyvariantConstructor constructor) ~env ()) + in + let _localCompletions = + typ + |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix ~exact:false + ~opens ~scope + in + constructorCompletions + | Some (CVariant {constructors}), _ -> + let constructorCompletions = + constructors + |> List.filter (fun constructor -> + Utils.startsWith constructor.Constructor.cname.txt prefix) + |> List.map (fun (constructor : Constructor.t) -> + Completion.create + ~name: + (constructor.cname.txt + ^ if constructor.args |> List.length > 0 then "(_)" else "" + ) + ~insertTextFormat:Snippet + ~insertText: + (constructor.cname.txt + ^ + if constructor.args |> List.length > 0 then "($1)" else "" + ) + ~kind:(Constructor (constructor, "")) + ~env ()) + in + let _localCompletions = + typ + |> findLocalCompletionsForTypeExprWithOpens ~env ~prefix ~exact:false + ~opens ~scope + in + constructorCompletions + | Some (CRecord {fields; decl; name}), CRecordField -> + fields + |> Utils.filterMap (fun (field : field) -> + if prefix = "" || checkName field.fname.txt ~prefix ~exact:false + then + Some + (Completion.create ~name:field.fname.txt ~env + ~kind: + (Completion.Field + (field, decl |> Shared.declToString name.txt)) + ()) + else None) + | Some (CRecord _), _ -> + [ + Completion.create ~name:"{}" ~insertText:"{${1}}" + ~insertTextFormat:Snippet ~env ~sortText:"a" + ~kind:(Completion.Label "Empty record") (); + ])) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index b6bb95e90..da4d5c5f9 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -772,36 +772,77 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | Pstr_value (recFlag, bindings) -> if recFlag = Recursive then bindings |> List.iter scopeValueBinding; - (* This is an experiment and should most likely not live here in its final form. *) - (* Check for: let {destructuringSomething} = someIdentifier *) - (* Ensure cursor is inside of record pattern. *) - (* TODO: Handle let {SomeModule.recordField} = ...*) - (match bindings with - | [{pvb_pat; pvb_expr = expr}] when !result = None -> ( - (* The contextPath is what we'll use to look up the root record type for this completion. - Depending on if the destructure is nested or not, we may or may not use that directly.*) - match exprToContextPath expr with - | None -> () - | Some contextPath -> ( - match - findContextInPattern pvb_pat ~firstCharBeforeCursorNoWhite - ~pos:posBeforeCursor ~patternPath:[] ~seenIdentsFromParent:[] - ~debug - with - | None -> () - | Some res -> - setResultOpt - (Some - (Completable.CtypedPattern - { - howToRetrieveSourceType = CtxPath contextPath; - patternPath = res.patternPath |> List.rev; - patternType = Destructure; - lookingToComplete = res.lookingToComplete; - prefix = res.prefix; - alreadySeenIdents = res.alreadySeenIdents; - })))) - | _ -> ()); + (if + !result = None + && item.pstr_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + = HasCursor + then + match bindings with + (* TODO: This is currently broken, as we need to support using a type_decl, which is what a type annotation gives us, + to look up types (currently only support type_expr). *) + (* E.g let expr: someType = ... *) + | [ + { + pvb_pat = + { + ppat_loc; + ppat_desc = + Ppat_constraint + (_, {ptyp_desc = Ptyp_constr (typIdentifier, [])}); + }; + pvb_expr = expr; + }; + ] -> ( + match expr with + (* E.g let expr: someType = + Produces a "broken" source *) + | { + pexp_desc = Pexp_extension ({Location.txt = "rescript.exprhole"}, _); + } + when ppat_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + = NoCursor -> + setResultOpt + (Some + (Completable.CtypedExpression + { + howToRetrieveSourceType = + CtxPath + (CPId (Utils.flattenLongIdent typIdentifier.txt, Type)); + expressionPath = []; + lookingToComplete = CNoContext; + prefix = ""; + })) + | _ -> ()) + | [{pvb_pat; pvb_expr = expr}] -> ( + (* Check for: let {destructuringSomething} = someIdentifier *) + (* TODO: Handle let {SomeModule.recordField} = ...*) + + (* The contextPath is what we'll use to look up the root record type for this completion. + Depending on if the destructure is nested or not, we may or may not use that directly.*) + match exprToContextPath expr with + | None -> () + | Some contextPath -> ( + match + findContextInPattern pvb_pat ~firstCharBeforeCursorNoWhite + ~pos:posBeforeCursor ~patternPath:[] ~seenIdentsFromParent:[] + ~debug + with + | None -> () + | Some res -> + setResultOpt + (Some + (Completable.CtypedPattern + { + howToRetrieveSourceType = CtxPath contextPath; + patternPath = res.patternPath |> List.rev; + patternType = Destructure; + lookingToComplete = res.lookingToComplete; + prefix = res.prefix; + alreadySeenIdents = res.alreadySeenIdents; + })))) + | _ -> ()); bindings |> List.iter (fun vb -> iterator.value_binding iterator vb); if recFlag = Nonrecursive then bindings |> List.iter scopeValueBinding; processed := true diff --git a/analysis/src/DumpAst.ml b/analysis/src/DumpAst.ml index 14f54c243..244191461 100644 --- a/analysis/src/DumpAst.ml +++ b/analysis/src/DumpAst.ml @@ -64,6 +64,7 @@ let printCoreType typ ~pos = ^ (loc |> printLocDenominatorLoc ~pos) ^ (Utils.flattenLongIdent loc.txt |> Completable.ident |> Completable.str) ^ ")" + | Ptyp_variant _ -> "Ptyp_variant()" | _ -> "" let rec printPattern pattern ~pos ~indentation = @@ -258,10 +259,12 @@ let printStructItem structItem ~pos ~source = | None -> 0 | Some offset -> offset in - print_endline - ("\nSource:\n// " - ^ String.sub source startOffset (endOffset - startOffset) - ^ "\n"); + + ("\nSource:\n// " + ^ String.sub source startOffset (endOffset - startOffset) + ^ "\n") + ^ printLocDenominator structItem.pstr_loc ~pos + ^ match structItem.pstr_desc with | Pstr_eval (expr, _attributes) -> "Pstr_eval(\n" ^ printExprItem expr ~pos ~indentation:1 ^ "\n)" diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 43eed18ab..984e9471c 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -586,6 +586,13 @@ module Completable = struct This is contextual of course, but putting it here in the general type to simplify things. *) alreadySeenIdents: string list; } + | CtypedExpression of { + howToRetrieveSourceType: howToRetrieveSourceType; + expressionPath: patternPathItem list; + lookingToComplete: lookingToComplete; + (* What the user has already started writing, if anything. *) + prefix: string; + } let toString = function | Cpath cp -> "Cpath " ^ contextPathToString cp @@ -616,6 +623,15 @@ module Completable = struct ^ ", pattern: " ^ (patternPath |> patternContextPathToString) ^ ", seenIdents: " ^ list alreadySeenIdents ^ ")" + | CtypedExpression + {howToRetrieveSourceType; prefix; expressionPath; lookingToComplete} -> + ("CtypedExpression(sourceType:" + ^ (howToRetrieveSourceType |> howToRetrieveSourceTypeToString) + ^ ", lookingToComplete:" + ^ lookingToCompleteToString lookingToComplete + ^ ", prefix:" ^ str prefix) + ^ ", pattern: " + ^ (expressionPath |> patternContextPathToString) end module CursorPosition = struct diff --git a/analysis/tests/src/TypedContextCompletionSpec.res b/analysis/tests/src/TypedContextCompletionSpec.res index c781e5457..a70d9e6e2 100644 --- a/analysis/tests/src/TypedContextCompletionSpec.res +++ b/analysis/tests/src/TypedContextCompletionSpec.res @@ -250,3 +250,9 @@ let y = One // ^com // --- Pattern matching end --- + +// let someVar: Completion.r = +// ^ast + +// let someVar: Completion.r = +// ^com diff --git a/analysis/tests/src/expected/CompletePrioritize2.res.txt b/analysis/tests/src/expected/CompletePrioritize2.res.txt index 7d62533c1..378e7411c 100644 --- a/analysis/tests/src/expected/CompletePrioritize2.res.txt +++ b/analysis/tests/src/expected/CompletePrioritize2.res.txt @@ -1,10 +1,29 @@ Complete src/CompletePrioritize2.res 9:7 posCursor:[9:7] posNoWhite:[9:6] Found expr:[9:3->0:-1] -Completable: CtypedPattern(sourceType:Value[ax], lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +Completable: Cpath Value[ax]-> +[{ + "label": "Test.add", + "kind": 12, + "tags": [], + "detail": "t => int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/CompletePrioritize2.res 12:5 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[ax], lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[12:5] posNoWhite:[12:4] Found expr:[12:3->12:5] +Pexp_ident ax:[12:3->12:5] +Completable: Cpath Value[ax] +[{ + "label": "ax", + "kind": 12, + "tags": [], + "detail": "Test.t", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index 69fb03e35..eaf97589b 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -768,323 +768,1090 @@ Completable: CtypedPattern(sourceType:Value[Lib, foo](Nolabel, ~age, ~name), loo [] Complete src/Completion.res 90:13 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[90:13] posNoWhite:[90:12] Found expr:[90:3->93:18] +Pexp_send a[90:12->90:13] e:[90:3->90:10] +Completable: Cpath Value[someObj]["a"] +[{ + "label": "age", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 95:24 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[95:24] posNoWhite:[95:23] Found expr:[95:3->99:6] +Pexp_send [95:24->95:24] e:[95:3->95:22] +Completable: Cpath Value[nestedObj]["x"]["y"][""] +[{ + "label": "age", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "name", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 99:7 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[99:7] posNoWhite:[99:6] Found expr:[99:3->102:20] +Pexp_send a[99:6->99:7] e:[99:3->99:4] +Completable: Cpath Value[o]["a"] +[{ + "label": "age", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 104:17 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[104:17] posNoWhite:[104:16] Found expr:[104:3->125:18] +Pexp_send [104:17->104:17] e:[104:3->104:15] +Completable: Cpath Value[no]["x"]["y"][""] +[{ + "label": "name", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "age", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 110:5 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[110:5] posNoWhite:[110:4] Found expr:[110:3->110:5] +Pexp_field [110:3->110:4] _:[116:0->110:5] +Completable: Cpath Value[r]."" +[{ + "label": "x", + "kind": 5, + "tags": [], + "detail": "x: int\n\ntype r = {x: int, y: string}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "y", + "kind": 5, + "tags": [], + "detail": "y: string\n\ntype r = {x: int, y: string}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 113:24 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[113:24] posNoWhite:[113:23] Found expr:[113:3->113:24] +Pexp_field [113:3->113:23] _:[116:0->113:24] +Completable: Cpath Value[Object, Rec, recordVal]."" +[{ + "label": "xx", + "kind": 5, + "tags": [], + "detail": "xx: int\n\ntype recordt = {xx: int, ss: string}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "ss", + "kind": 5, + "tags": [], + "detail": "ss: string\n\ntype recordt = {xx: int, ss: string}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 120:7 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[120:7] posNoWhite:[120:6] Found expr:[119:11->123:1] +posCursor:[120:7] posNoWhite:[120:6] Found expr:[120:5->122:5] +posCursor:[120:7] posNoWhite:[120:6] Found expr:[120:5->120:7] +Pexp_ident my:[120:5->120:7] +Completable: Cpath Value[my] +[{ + "label": "myAmazingFunction", + "kind": 12, + "tags": [], + "detail": "(int, int) => int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 125:18 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[125:18] posNoWhite:[125:17] Found expr:[125:3->145:32] +Pexp_send [125:18->125:18] e:[125:3->125:16] +Completable: Cpath Value[Object, object][""] +[{ + "label": "name", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "age", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 151:6 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[151:6] posNoWhite:[151:5] Found expr:[151:4->151:6] +JSX 151:6] > _children:None +Completable: Cpath Module[O, ""] +[{ + "label": "Comp", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 157:8 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[157:8] posNoWhite:[157:7] Found expr:[157:3->157:8] +Pexp_field [157:3->157:7] _:[165:0->157:8] +Completable: Cpath Value[q].aa."" +[{ + "label": "x", + "kind": 5, + "tags": [], + "detail": "x: int\n\ntype aa = {x: int, name: string}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "name", + "kind": 5, + "tags": [], + "detail": "name: string\n\ntype aa = {x: int, name: string}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 159:9 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[159:9] posNoWhite:[159:8] Found expr:[159:3->159:9] +Pexp_field [159:3->159:7] n:[159:8->159:9] +Completable: Cpath Value[q].aa.n +[{ + "label": "name", + "kind": 5, + "tags": [], + "detail": "name: string\n\ntype aa = {x: int, name: string}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 162:6 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[162:6] posNoWhite:[162:5] Found expr:[162:3->162:6] +Pexp_construct Lis:[162:3->162:6] None +Completable: Cpath Value[Lis] +[{ + "label": "List", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "ListLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 169:16 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[169:16] posNoWhite:[169:15] Found expr:[169:4->169:16] +JSX 169:16] > _children:None +Completable: Cpath Module[WithChildren] +[{ + "label": "WithChildren", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 172:16 posCursor:[172:16] posNoWhite:[172:15] Found type:[172:12->172:16] Ptyp_constr Js.n:[172:12->172:16] -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +Completable: Cpath Type[Js, n] +[{ + "label": "null_undefined", + "kind": 22, + "tags": [], + "detail": "type null_undefined<'a> = nullable<'a>", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "nullable", + "kind": 22, + "tags": [], + "detail": "type nullable<+'a>", + "documentation": {"kind": "markdown", "value": "\n A value of this type can be undefined, null or 'a. This type is equivalent to Js.Null_undefined.t.\n"}, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "null", + "kind": 22, + "tags": [], + "detail": "type null<+'a>", + "documentation": {"kind": "markdown", "value": "\n Nullable value of this type can be either null or 'a. This type is equivalent to Js.Null.t.\n"}, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 174:20 posCursor:[174:20] posNoWhite:[174:19] Found type:[174:12->174:20] Ptyp_constr ForAuto.:[174:12->174:20] -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +Completable: Cpath Type[ForAuto, ""] +[{ + "label": "t", + "kind": 22, + "tags": [], + "detail": "type t = int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 179:13 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +posCursor:[179:13] posNoWhite:[179:12] Found expr:[179:11->179:13] +Pexp_construct As:[179:11->179:13] None +Completable: Cpath Value[As] [] Complete src/Completion.res 182:17 Pmod_ident For:[182:14->182:17] -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +Completable: Cpath Module[For] +[{ + "label": "ForAuto", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 190:11 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[190:11] posNoWhite:[190:10] Found expr:[190:3->190:11] +Pexp_ident Private.:[190:3->190:11] +Completable: Cpath Value[Private, ""] +[{ + "label": "b", + "kind": 12, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 202:6 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +posCursor:[202:6] posNoWhite:[202:5] Found expr:[202:3->202:6] +Pexp_ident sha:[202:3->202:6] +Completable: Cpath Value[sha] [] Complete src/Completion.res 205:6 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[205:6] posNoWhite:[205:5] Found expr:[205:3->205:6] +Pexp_ident sha:[205:3->205:6] +Completable: Cpath Value[sha] +[{ + "label": "shadowed", + "kind": 12, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 208:6 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[208:6] posNoWhite:[208:5] Found expr:[208:3->208:6] +Pexp_ident sha:[208:3->208:6] +Completable: Cpath Value[sha] +[{ + "label": "shadowed", + "kind": 12, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 221:22 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[221:22] posNoWhite:[221:21] Found expr:[221:3->224:22] +Pexp_send [221:22->221:22] e:[221:3->221:20] +Completable: Cpath Value[FAO, forAutoObject][""] +[{ + "label": "age", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "forAutoLabel", + "kind": 4, + "tags": [], + "detail": "FAR.forAutoRecord", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 224:37 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[224:37] posNoWhite:[224:36] Found expr:[224:3->224:37] +Pexp_field [224:3->224:36] _:[233:0->224:37] +Completable: Cpath Value[FAO, forAutoObject]["forAutoLabel"]."" +[{ + "label": "forAuto", + "kind": 5, + "tags": [], + "detail": "forAuto: ForAuto.t\n\ntype forAutoRecord = {\n forAuto: ForAuto.t,\n something: option,\n}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "something", + "kind": 5, + "tags": [], + "detail": "something: option\n\ntype forAutoRecord = {\n forAuto: ForAuto.t,\n something: option,\n}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 227:46 posCursor:[227:46] posNoWhite:[227:45] Found expr:[227:3->0:-1] -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +Completable: Cpath Value[FAO, forAutoObject]["forAutoLabel"].forAuto-> +[{ + "label": "ForAuto.abc", + "kind": 12, + "tags": [], + "detail": "(t, int) => t", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "ForAuto.abd", + "kind": 12, + "tags": [], + "detail": "(t, int) => t", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 230:55 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[230:55] posNoWhite:[230:54] Found expr:[230:3->230:55] +posCursor:[230:55] posNoWhite:[230:54] Found expr:[230:46->230:55] +Pexp_ident ForAuto.a:[230:46->230:55] +Completable: Cpath Value[ForAuto, a] +[{ + "label": "abc", + "kind": 12, + "tags": [], + "detail": "(t, int) => t", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "abd", + "kind": 12, + "tags": [], + "detail": "(t, int) => t", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 234:34 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[234:34] posNoWhite:[234:33] Found expr:[234:18->234:36] +Pexp_apply ...__ghost__[0:-1->0:-1] (...[234:18->234:34], ...[234:34->234:35]) +posCursor:[234:34] posNoWhite:[234:33] Found expr:[234:18->234:34] +Pexp_apply ...__ghost__[0:-1->0:-1] (...[234:18->234:30], ...[234:32->234:34]) +posCursor:[234:34] posNoWhite:[234:33] Found expr:[234:32->234:34] +Pexp_ident na:[234:32->234:34] +Completable: Cpath Value[na] +[{ + "label": "name", + "kind": 12, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 237:17 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +posCursor:[237:17] posNoWhite:[237:14] Found expr:[237:14->237:22] +Completable: Cnone [] Complete src/Completion.res 243:8 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[243:8] posNoWhite:[243:7] Found expr:[241:8->246:1] +posCursor:[243:8] posNoWhite:[243:7] Found expr:[242:14->243:8] +Pexp_apply ...[243:3->243:4] (...[242:14->242:15], ...[243:5->243:8]) +posCursor:[243:8] posNoWhite:[243:7] Found expr:[243:5->243:8] +Pexp_field [243:5->243:7] _:[245:0->243:8] +Completable: Cpath Value[_z]."" +[{ + "label": "x", + "kind": 5, + "tags": [], + "detail": "x: int\n\ntype r = {x: int, y: string}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "y", + "kind": 5, + "tags": [], + "detail": "y: string\n\ntype r = {x: int, y: string}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 254:17 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[254:17] posNoWhite:[254:16] Found expr:[254:11->254:17] +Pexp_construct SomeLo:[254:11->254:17] None +Completable: Cpath Value[SomeLo] +[{ + "label": "SomeLocalModule", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 256:29 posCursor:[256:29] posNoWhite:[256:28] Found type:[256:13->256:29] Ptyp_constr SomeLocalModule.:[256:13->256:29] -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +Completable: Cpath Type[SomeLocalModule, ""] +[{ + "label": "zz", + "kind": 22, + "tags": [], + "detail": "type zz = int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 261:33 posCursor:[261:33] posNoWhite:[261:32] Found type:[261:17->263:11] Ptyp_constr SomeLocalModule.:[261:17->263:11] -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +Completable: Cpath Type[SomeLocalModule, ""] +[{ + "label": "zz", + "kind": 22, + "tags": [], + "detail": "type zz = int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 268:21 Ptype_variant unary SomeLocal:[268:12->268:21] -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +Completable: Cpath Value[SomeLocal] +[{ + "label": "SomeLocalModule", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 271:20 posCursor:[271:20] posNoWhite:[271:19] Found pattern:[271:7->274:3] posCursor:[271:20] posNoWhite:[271:19] Found type:[271:11->274:3] Ptyp_constr SomeLocal:[271:11->274:3] -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +Completable: Cpath Type[SomeLocal] +[{ + "label": "SomeLocalModule", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 275:15 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[275:15] posNoWhite:[275:14] Found expr:[274:11->278:1] +posCursor:[275:15] posNoWhite:[275:14] Found expr:[275:5->277:3] +posCursor:[275:15] posNoWhite:[275:14] Found expr:[275:13->275:15] +Pexp_ident _w:[275:13->275:15] +Completable: Cpath Value[_w] +[{ + "label": "_world", + "kind": 12, + "tags": [], + "detail": "'a", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 281:22 posCursor:[281:22] posNoWhite:[281:21] Found type:[281:21->281:22] Ptyp_constr s:[281:21->281:22] -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +Completable: Cpath Type[s] +[{ + "label": "someType", + "kind": 22, + "tags": [], + "detail": "type someType = {hello: string}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "someLocalVariant", + "kind": 22, + "tags": [], + "detail": "type someLocalVariant = SomeLocalVariantItem", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 291:30 XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[funRecord].someFun(Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Completion.res 296:11 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[296:11] posNoWhite:[296:10] Found expr:[296:3->296:11] +Pexp_field [296:3->296:10] _:[299:0->296:11] +Completable: Cpath Value[retAA](Nolabel)."" +[{ + "label": "x", + "kind": 5, + "tags": [], + "detail": "x: int\n\ntype aa = {x: int, name: string}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "name", + "kind": 5, + "tags": [], + "detail": "name: string\n\ntype aa = {x: int, name: string}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 301:13 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[301:13] posNoWhite:[301:12] Found expr:[301:3->301:13] +Pexp_apply ...[301:3->301:11] () +Completable: CnamedArg(Value[ff](~c), "", []) +Found type for function ( + ~opt1: int=?, + ~a: int, + ~b: int, + unit, + ~opt2: int=?, + unit, +) => int +[{ + "label": "opt1", + "kind": 4, + "tags": [], + "detail": "option", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "a", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "b", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "opt2", + "kind": 4, + "tags": [], + "detail": "option", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 304:15 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[304:15] posNoWhite:[304:14] Found expr:[304:3->304:15] +Pexp_apply ...[304:3->304:13] () +Completable: CnamedArg(Value[ff](~c)(Nolabel), "", []) +Found type for function (~a: int, ~b: int, ~opt2: int=?, unit) => int +[{ + "label": "a", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "b", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "opt2", + "kind": 4, + "tags": [], + "detail": "option", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 307:17 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[307:17] posNoWhite:[307:16] Found expr:[307:3->307:17] +Pexp_apply ...[307:3->307:15] () +Completable: CnamedArg(Value[ff](~c, Nolabel), "", []) +Found type for function (~a: int, ~b: int, ~opt2: int=?, unit) => int +[{ + "label": "a", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "b", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "opt2", + "kind": 4, + "tags": [], + "detail": "option", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 310:21 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[310:21] posNoWhite:[310:20] Found expr:[310:3->310:21] +Pexp_apply ...[310:3->310:19] () +Completable: CnamedArg(Value[ff](~c, Nolabel, Nolabel), "", []) +Found type for function (~a: int, ~b: int) => int +[{ + "label": "a", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "b", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 313:23 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[313:23] posNoWhite:[313:22] Found expr:[313:3->313:23] +Pexp_apply ...[313:3->313:21] () +Completable: CnamedArg(Value[ff](~c, Nolabel, ~b), "", []) +Found type for function (~a: int, ~opt2: int=?, unit) => int +[{ + "label": "a", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "opt2", + "kind": 4, + "tags": [], + "detail": "option", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 316:16 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[316:16] posNoWhite:[316:15] Found expr:[316:3->316:16] +Pexp_apply ...[316:3->316:14] () +Completable: CnamedArg(Value[ff](~opt2), "", []) +Found type for function (~opt1: int=?, ~a: int, ~b: int, unit, unit, ~c: int) => int +[{ + "label": "opt1", + "kind": 4, + "tags": [], + "detail": "option", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "a", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "b", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "c", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 323:17 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[323:17] posNoWhite:[323:16] Found expr:[323:3->323:17] +Pexp_apply ...[323:3->323:15] () +Completable: CnamedArg(Value[withCallback], "", []) +Found type for function (~b: int) => callback +[{ + "label": "b", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "a", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 326:21 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[326:21] posNoWhite:[326:20] Found expr:[326:3->326:21] +Pexp_apply ...[326:3->326:19] () +Completable: CnamedArg(Value[withCallback](~a), "", []) +Found type for function (~b: int) => int +[{ + "label": "b", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 329:21 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[329:21] posNoWhite:[329:20] Found expr:[329:3->329:21] +Pexp_apply ...[329:3->329:19] () +Completable: CnamedArg(Value[withCallback](~b), "", []) +Found type for function (~a: int) => int +[{ + "label": "a", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 336:26 posCursor:[336:26] posNoWhite:[336:25] Found pattern:[336:20->338:5] posCursor:[336:26] posNoWhite:[336:25] Found type:[336:23->338:5] Ptyp_constr Res:[336:23->338:5] -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[div](~onClick, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Completion.res 343:57 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[343:57] posNoWhite:[343:56] Found expr:[343:10->346:23] +posCursor:[343:57] posNoWhite:[343:56] Found expr:[343:53->346:23] +posCursor:[343:57] posNoWhite:[343:56] Found expr:[343:53->343:57] +Pexp_ident this:[343:53->343:57] +Completable: Cpath Value[this] +[{ + "label": "thisIsNotSaved", + "kind": 12, + "tags": [], + "detail": "\\\"Type Not Known\"", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Hover src/Completion.res 346:14 Nothing at that position. Now trying to use completion. XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[div](~name, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) null Hover src/Completion.res 349:17 Nothing at that position. Now trying to use completion. XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[FAO, forAutoObject]["age"], lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) null Hover src/Completion.res 352:17 Nothing at that position. Now trying to use completion. XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[ff](~opt1), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) null Complete src/Completion.res 355:23 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +posCursor:[355:23] posNoWhite:[355:22] Found expr:[0:-1->355:23] +posCursor:[355:23] posNoWhite:[355:22] Found expr:[355:12->355:23] [] Complete src/Completion.res 362:8 +posCursor:[362:8] posNoWhite:[362:7] Found expr:[360:8->365:3] +posCursor:[362:8] posNoWhite:[362:7] Found expr:[361:2->365:3] posCursor:[362:8] posNoWhite:[362:7] Found pattern:[362:7->364:5] posCursor:[362:8] posNoWhite:[362:7] Found pattern:[362:7->362:8] Ppat_construct T:[362:7->362:8] -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CVariant, patternType:Switch, prefix:T, pattern: [], seenIdents: [T]) [] Complete src/Completion.res 373:21 +posCursor:[373:21] posNoWhite:[373:20] Found expr:[371:8->376:3] +posCursor:[373:21] posNoWhite:[373:20] Found expr:[372:2->376:3] posCursor:[373:21] posNoWhite:[373:20] Found pattern:[373:7->375:5] posCursor:[373:21] posNoWhite:[373:20] Found pattern:[373:7->373:21] Ppat_construct AndThatOther.T:[373:7->373:21] -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CVariant, patternType:Switch, prefix:AndThatOther, pattern: [], seenIdents: [AndThatOther]) [] Complete src/Completion.res 378:24 XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[^](Nolabel, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Completion.res 381:38 XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[^](Nolabel, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Completion.res 384:24 XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[^](Nolabel, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Completion.res 389:12 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[389:12] posNoWhite:[389:11] Found expr:[387:8->392:1] +posCursor:[389:12] posNoWhite:[389:11] Found expr:[388:2->391:4] +posCursor:[389:12] posNoWhite:[389:11] Found expr:[389:6->391:4] +posCursor:[389:12] posNoWhite:[389:11] Found expr:[389:6->389:12] +Completable: Cpath array->ma +[{ + "label": "Array2.mapi", + "kind": 12, + "tags": [], + "detail": "(t<'a>, ('a, int) => 'b) => t<'b>", + "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The function acceps two arguments: an item from the array and its\nindex number. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\n// multiply each item in array by its position\nlet product = (item, index) => item * index\nJs.Array2.mapi([10, 11, 12], product) == [0, 11, 24]\n```\n"}, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "Array2.map", + "kind": 12, + "tags": [], + "detail": "(t<'a>, 'a => 'b) => t<'b>", + "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n```res example\nJs.Array2.map([12, 4, 8], x => x * x) == [144, 16, 64]\nJs.Array2.map([\"animal\", \"vegetable\", \"mineral\"], Js.String.length) == [6, 9, 7]\n```\n"}, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 397:14 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[397:14] posNoWhite:[397:13] Found expr:[396:14->397:20] +Pexp_apply ...__ghost__[0:-1->0:-1] (...[396:14->397:16], ...[397:16->397:19]) +posCursor:[397:14] posNoWhite:[397:13] Found expr:[396:14->397:16] +Pexp_apply ...__ghost__[0:-1->0:-1] (...[396:14->397:11], ...[397:13->397:16]) +posCursor:[397:14] posNoWhite:[397:13] Found expr:[397:13->397:16] +Pexp_ident red:[397:13->397:16] +Completable: Cpath Value[red] +[{ + "label": "red", + "kind": 12, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 402:25 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[402:25] posNoWhite:[402:24] Found expr:[400:14->402:31] +Pexp_apply ...__ghost__[0:-1->0:-1] (...[400:14->402:27], ...[402:27->402:30]) +posCursor:[402:25] posNoWhite:[402:24] Found expr:[400:14->402:27] +Pexp_apply ...__ghost__[0:-1->0:-1] (...[400:14->402:22], ...[402:24->402:27]) +posCursor:[402:25] posNoWhite:[402:24] Found expr:[402:24->402:27] +Pexp_ident red:[402:24->402:27] +Completable: Cpath Value[red] +[{ + "label": "red", + "kind": 12, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 405:22 XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[^](Nolabel, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] diff --git a/analysis/tests/src/expected/Cross.res.txt b/analysis/tests/src/expected/Cross.res.txt index 06e48f632..b045e8a02 100644 --- a/analysis/tests/src/expected/Cross.res.txt +++ b/analysis/tests/src/expected/Cross.res.txt @@ -94,7 +94,8 @@ TypeDefinition src/Cross.res 33:37 {"uri": "DefinitionWithInterface.resi", "range": {"start": {"line": 3, "character": 0}, "end": {"line": 3, "character": 6}}} Complete src/Cross.res 36:28 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[RenameWithInterface, x], lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +posCursor:[36:28] posNoWhite:[36:27] Found expr:[36:3->36:28] +Pexp_ident DefinitionWithInterface.a:[36:3->36:28] +Completable: Cpath Value[DefinitionWithInterface, a] [] diff --git a/analysis/tests/src/expected/Debug.res.txt b/analysis/tests/src/expected/Debug.res.txt index e5be9b9a6..cea26e4a0 100644 --- a/analysis/tests/src/expected/Debug.res.txt +++ b/analysis/tests/src/expected/Debug.res.txt @@ -70,21 +70,37 @@ resolvePath path:map {"uri": "list.mli", "range": {"start": {"line": 116, "character": 4}, "end": {"line": 116, "character": 7}}} Complete src/Debug.res 13:8 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Belt, List, map], lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -Raw ppens: 0 +posCursor:[13:8] posNoWhite:[13:7] Found expr:[13:5->13:8] +Pexp_ident eqN:[13:5->13:8] +Completable: Cpath Value[eqN] +Raw ppens: 1 Js.place holder Package opens -Resolved opens 0 -Path List.map -Getting module Belt -fileForModule Impl cmt:./node_modules/rescript/lib/ocaml/belt.cmt res:./node_modules/rescript/lib/ocaml/belt.ml -got it -resolvePath path:List.map -resolvePath Global path:map module:Belt_List -fileForModule Impl cmt:./node_modules/rescript/lib/ocaml/belt_List.cmti res:./node_modules/rescript/lib/ocaml/belt_List.mli -resolvePath path:map -Got the env -findAllCompletions uri:belt_List.mli -[] +resolving open Js.place holder +resolvePath path:Js.place holder +Not local +fileForModule Impl cmt:./node_modules/rescript/lib/ocaml/js.cmt res:./node_modules/rescript/lib/ocaml/js.ml +resolvePath path:place holder +Resolved opens 1 js.ml +findLocalCompletionsWithOpens uri:Debug.res pos:13:8 +findAllCompletions uri:js.ml +[{ + "label": "eqNullable", + "kind": 12, + "tags": [], + "detail": "('a, nullable<'a>) => bool", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "eqNull", + "kind": 12, + "tags": [], + "detail": "('a, null<'a>) => bool", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] diff --git a/analysis/tests/src/expected/Hover.res.txt b/analysis/tests/src/expected/Hover.res.txt index 2194c955b..f1b882d13 100644 --- a/analysis/tests/src/expected/Hover.res.txt +++ b/analysis/tests/src/expected/Hover.res.txt @@ -83,8 +83,8 @@ Hover src/Hover.res 109:25 Hover src/Hover.res 112:3 Nothing at that position. Now trying to use completion. Attribute id:live:[112:0->112:5] label:live -Completable: CtypedPattern(sourceType:Value[Comp, createElement](~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -null +Completable: Cdecorator(live) +{"contents": "The `@live` decorator is for reanalyze, a static analysis tool for ReScript that can do dead code analysis.\n\n`@live` tells the dead code analysis that the value should be considered live, even though it might appear to be dead. This is typically used in case of FFI where there are indirect ways to access values. It can be added to everything that could otherwise be considered unused by the dead code analysis - values, functions, arguments, records, individual record fields, and so on.\n\n[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#live-decorator).\n\nHint: Did you know you can run an interactive code analysis in your project by running the command `> ReScript: Start Code Analyzer`? Try it!"} Hover src/Hover.res 115:4 {"contents": "```rescript\n(. ()) => unit => int\n```"} diff --git a/analysis/tests/src/expected/Jsx.res.txt b/analysis/tests/src/expected/Jsx.res.txt index df8aa5bcf..7cd6fcb1c 100644 --- a/analysis/tests/src/expected/Jsx.res.txt +++ b/analysis/tests/src/expected/Jsx.res.txt @@ -4,79 +4,258 @@ the type is not great but jump to definition works {"uri": "Jsx.res", "range": {"start": {"line": 2, "character": 6}, "end": {"line": 2, "character": 10}}} Complete src/Jsx.res 8:15 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +posCursor:[8:15] posNoWhite:[8:14] Found expr:[8:4->8:15] +JSX 8:5] second[8:6->8:12]=...[8:13->8:15]> _children:None +posCursor:[8:15] posNoWhite:[8:14] Found expr:[8:13->8:15] +Pexp_ident fi:[8:13->8:15] +Completable: Cpath Value[fi] [] Complete src/Jsx.res 11:20 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[11:20] posNoWhite:[11:19] Found expr:[11:4->11:20] +JSX 11:5] second[11:6->11:12]=...[11:13->11:18] f[11:19->11:20]=...[11:19->11:20]> _children:None +Completable: Cjsx([M], f, [second, f]) +[{ + "label": "first", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "fun", + "kind": 4, + "tags": [], + "detail": "option", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 14:13 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[14:13] posNoWhite:[14:12] Found expr:[14:12->14:13] +JSX 14:13] > _children:None +Completable: Cpath Module[M] +[{ + "label": "M", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "Map", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "MapLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "MoreLabels", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 22:19 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[22:19] posNoWhite:[22:18] Found expr:[22:4->22:19] +JSX 22:5] prop[22:6->22:10]=...[22:12->22:16] k[22:18->22:19]=...[22:18->22:19]> _children:None +Completable: Cjsx([M], k, [prop, k]) +[{ + "label": "key", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 25:17 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[25:17] posNoWhite:[25:16] Found expr:[25:4->25:17] +JSX 25:5] prop[25:6->25:10]=...[25:11->25:15] k[25:16->25:17]=...[25:16->25:17]> _children:None +Completable: Cjsx([M], k, [prop, k]) +[{ + "label": "key", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 28:21 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[28:21] posNoWhite:[28:20] Found expr:[28:4->28:21] +JSX 28:5] prop[28:6->28:10]=...[28:11->28:19] k[28:20->28:21]=...[28:20->28:21]> _children:None +Completable: Cjsx([M], k, [prop, k]) +[{ + "label": "key", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 31:24 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[31:24] posNoWhite:[31:23] Found expr:[31:4->31:24] +JSX 31:5] prop[31:6->31:10]=...[31:11->31:22] k[31:23->31:24]=...[31:23->31:24]> _children:None +Completable: Cjsx([M], k, [prop, k]) +[{ + "label": "key", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 34:18 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[34:18] posNoWhite:[34:17] Found expr:[34:4->34:18] +JSX 34:5] prop[34:6->34:10]=...[34:12->34:16] k[34:17->34:18]=...[34:17->34:18]> _children:None +Completable: Cjsx([M], k, [prop, k]) +[{ + "label": "key", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 37:16 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[37:16] posNoWhite:[37:15] Found expr:[37:4->37:16] +JSX 37:5] prop[37:6->37:10]=...[37:11->37:14] k[37:15->37:16]=...[37:15->37:16]> _children:None +Completable: Cjsx([M], k, [prop, k]) +[{ + "label": "key", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 40:17 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[40:17] posNoWhite:[40:16] Found expr:[40:4->40:17] +JSX 40:5] prop[40:6->40:10]=...[40:11->40:15] k[40:16->40:17]=...[40:16->40:17]> _children:None +Completable: Cjsx([M], k, [prop, k]) +[{ + "label": "key", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 43:18 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[43:18] posNoWhite:[43:17] Found expr:[43:4->43:18] +JSX 43:5] prop[43:6->43:10]=...[43:11->43:16] k[43:17->43:18]=...[43:17->43:18]> _children:None +Completable: Cjsx([M], k, [prop, k]) +[{ + "label": "key", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 46:16 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[46:16] posNoWhite:[46:15] Found expr:[46:4->46:16] +JSX 46:5] prop[46:6->46:10]=...[46:11->46:14] k[46:15->46:16]=...[46:15->46:16]> _children:None +Completable: Cjsx([M], k, [prop, k]) +[{ + "label": "key", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 49:27 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[49:27] posNoWhite:[49:26] Found expr:[49:4->49:27] +JSX 49:5] prop[49:6->49:10]=...[49:11->49:25] k[49:26->49:27]=...[49:26->49:27]> _children:None +Completable: Cjsx([M], k, [prop, k]) +[{ + "label": "key", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 52:38 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[52:38] posNoWhite:[52:37] Found expr:[52:4->52:38] +JSX 52:5] prop[52:6->52:10]=...[52:11->52:36] k[52:37->52:38]=...[52:37->52:38]> _children:None +Completable: Cjsx([M], k, [prop, k]) +[{ + "label": "key", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 55:25 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[55:25] posNoWhite:[55:24] Found expr:[55:4->55:25] +JSX 55:5] prop[55:6->55:10]=...[55:11->55:23] k[55:24->55:25]=...[55:24->55:25]> _children:None +Completable: Cjsx([M], k, [prop, k]) +[{ + "label": "key", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Definition src/Jsx.res 58:11 getLocItem #4: heuristic for within fragments: take make as makeProps does not work @@ -84,108 +263,228 @@ the type is not great but jump to definition works {"uri": "Component.res", "range": {"start": {"line": 1, "character": 4}, "end": {"line": 1, "character": 8}}} Complete src/Jsx.res 68:10 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[68:10] posNoWhite:[68:9] Found expr:[68:4->68:10] +JSX 68:7] al[68:8->68:10]=...[68:8->68:10]> _children:None +Completable: Cjsx([Ext], al, [al]) +[{ + "label": "align", + "kind": 4, + "tags": [], + "detail": "option", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 71:11 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +posCursor:[71:11] posNoWhite:[71:10] Found expr:[71:4->71:11] +JSX 71:5] first[71:6->71:11]=...[71:6->71:11]> _children:None +Completable: Cjsx([M], first, [first]) [] Complete src/Jsx.res 74:16 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[74:16] posNoWhite:[74:15] Found expr:[74:4->74:16] +JSX 74:5] first[74:6->74:11]=...[74:12->74:14] k[74:15->74:16]=...[74:15->74:16]> _children:None +Completable: Cjsx([M], k, [first, k]) +[{ + "label": "key", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 77:23 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[77:23] posNoWhite:[77:22] Found expr:[77:4->77:23] +JSX 77:5] first[77:6->77:11]=...[77:19->77:21] k[77:22->77:23]=...[77:22->77:23]> _children:None +Completable: Cjsx([M], k, [first, k]) +[{ + "label": "key", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 80:6 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +posCursor:[80:6] posNoWhite:[80:5] Found expr:[80:4->85:69] +Pexp_apply ...[83:20->83:21] (...[80:4->83:19], ...[84:2->85:69]) +posCursor:[80:6] posNoWhite:[80:5] Found expr:[80:4->83:19] +JSX 80:5] > _children:80:5 +posCursor:[80:6] posNoWhite:[80:5] Found expr:[80:5->83:20] +Pexp_construct :::[83:0->83:20] [83:0->83:20] +posCursor:[80:6] posNoWhite:[80:5] Found expr:__ghost__[80:5->83:20] +Pexp_construct []:__ghost__[80:5->83:20] None [] Complete src/Jsx.res 89:16 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[89:16] posNoWhite:[89:15] Found expr:[89:4->89:16] +JSX 89:16] > _children:None +Completable: Cpath Module[WithChildren] +[{ + "label": "WithChildren", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 91:18 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[91:18] posNoWhite:[91:17] Found expr:[91:4->91:18] +JSX 91:16] n[91:17->91:18]=...[91:17->91:18]> _children:None +Completable: Cjsx([WithChildren], n, [n]) +[{ + "label": "name", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 94:18 posCursor:[94:18] posNoWhite:[94:17] Found pattern:[94:7->94:18] posCursor:[94:18] posNoWhite:[94:17] Found type:[94:11->94:18] Ptyp_constr React.e:[94:11->94:18] -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +Completable: Cpath Type[React, e] +[{ + "label": "element", + "kind": 22, + "tags": [], + "detail": "type element", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 96:20 posCursor:[96:20] posNoWhite:[96:19] Found pattern:[96:7->99:6] posCursor:[96:20] posNoWhite:[96:19] Found type:[96:11->99:6] Ptyp_constr ReactDOMR:[96:11->99:6] -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +Completable: Cpath Type[ReactDOMR] +[{ + "label": "ReactDOMRe", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 102:21 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +posCursor:[102:21] posNoWhite:[102:20] Found expr:[102:13->102:21] +Pexp_apply ...[102:15->102:16] (...[102:13->102:14], ...[102:17->102:21]) +posCursor:[102:21] posNoWhite:[102:20] Found expr:[102:17->102:21] +Pexp_field [102:17->102:18] th:[102:19->102:21] +Completable: Cpath Value[x].th [] Complete src/Jsx.res 106:28 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[106:28] posNoWhite:[106:27] Found expr:[106:11->106:28] +Pexp_ident DefineSomeFields.:[106:11->106:28] +Completable: Cpath Value[DefineSomeFields, ""] +[{ + "label": "thisValue", + "kind": 12, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 108:36 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[108:36] posNoWhite:[108:35] Found expr:[108:11->108:36] +Pexp_apply ...[108:13->108:14] (...[108:11->108:12], ...[108:15->108:36]) +posCursor:[108:36] posNoWhite:[108:35] Found expr:[108:15->108:36] +Pexp_field [108:15->108:16] DefineSomeFields.th:[108:17->108:36] +Completable: Cpath Module[DefineSomeFields].th +[{ + "label": "thisField", + "kind": 5, + "tags": [], + "detail": "thisField: int\n\ntype r = {thisField: int, thatField: string}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "thatField", + "kind": 5, + "tags": [], + "detail": "thatField: string\n\ntype r = {thisField: int, thatField: string}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 122:20 XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[div](~x, ~name, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Jsx.res 129:19 XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[div](~x, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Jsx.res 136:7 XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[div](~x, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Jsx.res 150:21 XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[Nested, Co, createElement](~name, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/Jsx.res 153:19 XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[Nested, name, createElement](~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Hover src/Jsx.res 162:12 Nothing at that position. Now trying to use completion. -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -null +posCursor:[162:12] posNoWhite:[162:11] Found expr:[162:3->162:21] +Pexp_construct :::[162:6->162:21] [162:6->162:21] +posCursor:[162:12] posNoWhite:[162:11] Found expr:[162:6->162:21] +posCursor:[162:12] posNoWhite:[162:11] Found expr:[162:6->162:20] +JSX 162:10] age[162:11->162:14]=...[162:15->162:17]> _children:162:18 +Completable: Cjsx([Comp], age, [age]) +{"contents": "```rescript\nint\n```"} Hover src/Jsx.res 167:16 Nothing at that position. Now trying to use completion. -XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -null +posCursor:[167:16] posNoWhite:[167:15] Found expr:[167:3->167:30] +Pexp_construct :::[167:7->167:30] [167:7->167:30] +posCursor:[167:16] posNoWhite:[167:15] Found expr:[167:7->167:30] +posCursor:[167:16] posNoWhite:[167:15] Found expr:[167:7->167:25] +Pexp_construct :::[167:10->167:25] [167:10->167:25] +posCursor:[167:16] posNoWhite:[167:15] Found expr:[167:10->167:25] +posCursor:[167:16] posNoWhite:[167:15] Found expr:[167:10->167:24] +JSX 167:14] age[167:15->167:18]=...[167:19->167:21]> _children:167:22 +Completable: Cjsx([Comp], age, [age]) +{"contents": "```rescript\nint\n```"} Complete src/Jsx.res 171:30 XXX Not found! -Completable: CtypedPattern(sourceType:Value[M, createElement](~first, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[Completion, O, Comp, createElement](~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] diff --git a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt index 5a681e90a..2bf9c24a9 100644 --- a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt +++ b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt @@ -4,8 +4,7 @@ Source: // let x = someVariantToString(~someVaria // ^ast - -Pstr_value( +<*>Pstr_value( value: Ppat_var(x) expr: @@ -24,8 +23,7 @@ Source: // let x = someVariantToString(~someVariant= // ^ast - -Pstr_value( +<*>Pstr_value( value: Ppat_var(x) expr: @@ -45,8 +43,7 @@ Source: // let x = someVariantToString(~someVariant=T // ^ast - -Pstr_value( +<*>Pstr_value( value: Ppat_var(x) expr: @@ -65,8 +62,7 @@ Source: // let x = someVariantToString(~someVariant=t // ^ast - -Pstr_value( +<*>Pstr_value( value: Ppat_var(x) expr: @@ -85,8 +81,7 @@ Source: // let x = someVariantToString(~someVariant=TypeDefinition. // ^ast - -Pstr_value( +<*>Pstr_value( value: Ppat_var(x) expr: @@ -105,8 +100,7 @@ Source: // let x = someVariantToString(~anotherThing= // ^ast - -Pstr_value( +<*>Pstr_value( value: Ppat_var(x) expr: @@ -125,8 +119,7 @@ Source: // let x = someVariantToString(~thirdThing= // ^ast - -Pstr_value( +<*>Pstr_value( value: Ppat_var(x) expr: @@ -145,8 +138,7 @@ Source: // let x = someVariantToString(~thirdThing=#t // ^ast - -Pstr_value( +<*>Pstr_value( value: Ppat_var(x) expr: @@ -165,8 +157,7 @@ Source: // let x = someVariantToString(~thirdThing=#T // ^ast - -Pstr_value( +<*>Pstr_value( value: Ppat_var(x) expr: @@ -2696,3 +2687,25 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "insertTextFormat": 2 }] +Dump AST src/TypedContextCompletionSpec.res 253:29 + +Source: +// let someVar: Completion.r = +// ^ast + +<*>Pstr_value( + value: + Ppat_constraint( + Ptyp_constr(Completion.r), + Ppat_var(someVar) + ) + expr: + Pexp_extension(%rescript.exprhole) +) + +Complete src/TypedContextCompletionSpec.res 256:30 +XXX Not found! +Completable: CtypedExpression(sourceType:Type[Completion, r], lookingToComplete:CNoContext, prefix:"", pattern: [] +no source type +[] + From eb3eb8053d5632db5b3d242df0762da49b018c67 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Wed, 17 Aug 2022 21:18:05 +0200 Subject: [PATCH 71/80] some cleanup and other fixes --- analysis/src/CompletionBackEnd.ml | 52 +- analysis/src/CompletionFrontEnd.ml | 695 +++++++++++------- analysis/src/DumpAst.ml | 45 +- analysis/src/Pos.ml | 20 + analysis/src/SharedTypes.ml | 43 +- ...ypeContextCompletion_LabelledArguments.res | 21 +- .../tests/src/expected/Completion.res.txt | 221 +++++- analysis/tests/src/expected/Dce.res.txt | 2 +- analysis/tests/src/expected/Jsx.res.txt | 115 ++- .../tests/src/expected/RecoveryOnProp.res.txt | 27 +- ...ontextCompletion_LabelledArguments.res.txt | 385 ++++++++-- .../TypedContextCompletionSpec.res.txt | 25 +- 12 files changed, 1255 insertions(+), 396 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index d21a545d5..5d15ca688 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1558,7 +1558,8 @@ let findTypeInContext (typ : Types.type_expr) ~env ~nestedContextPath ~package = -> ( match constructors - |> List.find_opt (fun constructor -> constructor.name = name) + |> List.find_opt (fun (constructor : polyVariantConstructor) -> + constructor.name = name) with | Some constructor -> ( match payloadNum with @@ -2132,9 +2133,9 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i (* TOOD: Unify with other variant completion handler *) let constructorCompletions = constructors - |> List.filter (fun constructor -> + |> List.filter (fun (constructor : polyVariantConstructor) -> Utils.startsWith ("Some(#" ^ constructor.name ^ ")") prefix) - |> List.map (fun constructor -> + |> List.map (fun (constructor : polyVariantConstructor) -> (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? Eg. Some($1) as completion item. *) Completion.create @@ -2168,9 +2169,9 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i | Some (CPolyVariant {constructors}), _ -> let constructorCompletions = constructors - |> List.filter (fun constructor -> + |> List.filter (fun (constructor : polyVariantConstructor) -> Utils.startsWith constructor.name prefix) - |> List.map (fun constructor -> + |> List.map (fun (constructor : polyVariantConstructor) -> (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? Eg. Some($1) as completion item. *) Completion.create @@ -2255,9 +2256,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i |> findSourceType ~package ~opens ~rawOpens ~allFiles ~env ~pos ~scope in match sourceType with - | None -> - Printf.printf "no source type\n"; - [] + | None -> [] | Some typ -> ( match ( typ @@ -2281,7 +2280,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i |> String.concat ", ") ^ ")") ~insertTextFormat:Snippet ~env ~sortText:"a" - ~kind:(Completion.Label "Full tuple match") (); + ~kind:(Completion.Label "Tuple") (); ] | Some CBool, _ -> (* Completing booleans - doesn't matter what we're looking to complete, since there's only one thing to complete (the bool values themselves). *) @@ -2300,8 +2299,6 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i ("Some(" ^ constructor.Constructor.cname.txt ^ ")") prefix) |> List.map (fun (constructor : Constructor.t) -> - (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? - Eg. Some($1) as completion item. *) Completion.create ~name: ("Some(" ^ constructor.cname.txt @@ -2311,7 +2308,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i ~insertText: ("Some(" ^ constructor.cname.txt ^ - if constructor.args |> List.length > 0 then "(${1:_}))" + if constructor.args |> List.length > 0 then "($1))" else ")") ~insertTextFormat:Snippet ~kind:(Constructor (constructor, "")) @@ -2329,9 +2326,9 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i (* TOOD: Unify with other variant completion handler *) let constructorCompletions = constructors - |> List.filter (fun constructor -> + |> List.filter (fun (constructor : polyVariantConstructor) -> Utils.startsWith ("Some(#" ^ constructor.name ^ ")") prefix) - |> List.map (fun constructor -> + |> List.map (fun (constructor : polyVariantConstructor) -> Completion.create ~name: ("Some(#" ^ constructor.name @@ -2342,7 +2339,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i ~insertText: ("Some(#" ^ constructor.name ^ - if constructor.payload |> Option.is_some then "(${1:_}))" + if constructor.payload |> Option.is_some then "($1))" else ")") ~kind:(PolyvariantConstructor constructor) ~env ()) in @@ -2363,9 +2360,9 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i | Some (CPolyVariant {constructors}), _ -> let constructorCompletions = constructors - |> List.filter (fun constructor -> + |> List.filter (fun (constructor : polyVariantConstructor) -> Utils.startsWith constructor.name prefix) - |> List.map (fun constructor -> + |> List.map (fun (constructor : polyVariantConstructor) -> Completion.create ~name: ("#" ^ constructor.name @@ -2424,9 +2421,26 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i (field, decl |> Shared.declToString name.txt)) ()) else None) - | Some (CRecord _), _ -> + | Some (CRecord {fields}), _ -> [ - Completion.create ~name:"{}" ~insertText:"{${1}}" + Completion.create + ~name: + ("{" + ^ (fields + |> List.map (fun field -> field.fname.txt) + |> String.concat ", ") + ^ "}") + ~insertText: + ("{\n" + ^ (fields + |> List.mapi (fun index field -> + Printf.sprintf " %s: ${%i:%s}" field.fname.txt + (index + 1) "assert false") + |> String.concat ", \n") + ^ "\n}") ~insertTextFormat:Snippet ~env ~sortText:"a" + ~kind:(Completion.Label "Complete record props") (); + Completion.create ~name:"{}" ~insertText:"{$1}" + ~insertTextFormat:Snippet ~env ~sortText:"b" ~kind:(Completion.Label "Empty record") (); ])) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index da4d5c5f9..a58aebc2a 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -7,26 +7,6 @@ let rec skipWhite text i = | ' ' | '\n' | '\r' | '\t' -> skipWhite text (i - 1) | _ -> i -let offsetOfLine text line = - let ln = String.length text in - let rec loop i lno = - if i >= ln then None - else - match text.[i] with - | '\n' -> if lno = line - 1 then Some (i + 1) else loop (i + 1) (lno + 1) - | _ -> loop (i + 1) lno - in - match line with - | 0 -> Some 0 - | _ -> loop 0 0 - -let positionToOffset text (line, character) = - match offsetOfLine text line with - | None -> None - | Some bol -> - if bol + character <= String.length text then Some (bol + character) - else None - let rec getSimpleFieldName txt = match txt with | Longident.Lident fieldName -> fieldName @@ -109,216 +89,236 @@ let rec exprToContextPath (e : Parsetree.expression) = else None | _ -> None -type prop = { - name: string; - posStart: int * int; - posEnd: int * int; - exp: Parsetree.expression; -} +let rec findPatternTupleItemWithCursor items ~index ~pos = + match items with + | [] -> None + | item :: rest -> + if CursorPosition.classifyLoc item.Parsetree.ppat_loc ~pos = HasCursor then + Some (Some item, index) + else findPatternTupleItemWithCursor rest ~index:(index + 1) ~pos -type jsxProps = { - compName: Longident.t Location.loc; - props: prop list; - childrenStart: (int * int) option; -} +let rec findExprTupleItemWithCursor items ~index ~pos = + match items with + | [] -> None + | item :: rest -> + if CursorPosition.classifyLoc item.Parsetree.pexp_loc ~pos = HasCursor then + Some (Some item, index) + else findExprTupleItemWithCursor rest ~index:(index + 1) ~pos -let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName - = - let allLabels = - List.fold_right - (fun prop allLabels -> prop.name :: allLabels) - jsxProps.props [] - in - let rec loop props = - match props with - | prop :: rest -> - if prop.posStart <= posBeforeCursor && posBeforeCursor < prop.posEnd then - (* Cursor on the prop name *) - Some - (Completable.Cjsx - ( Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt, - prop.name, - allLabels )) - else if - prop.posEnd <= posBeforeCursor - && posBeforeCursor < Loc.start prop.exp.pexp_loc - then (* Cursor between the prop name and expr assigned *) - None - else if prop.exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then - (* Cursor on expr assigned *) - (* TODO: Add expr completion *) - None - else if prop.exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then - (* Expr assigned presumably is "rescript.exprhole" after parser recovery. - Complete for the value. *) - (* TODO: Add expr completion *) - None - else loop rest - | [] -> - let beforeChildrenStart = - match jsxProps.childrenStart with - | Some childrenPos -> posBeforeCursor < childrenPos - | None -> posBeforeCursor <= endPos - in - let afterCompName = posBeforeCursor >= posAfterCompName in - if afterCompName && beforeChildrenStart then - Some - (Cjsx - ( Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt, - "", - allLabels )) - else None - in - loop jsxProps.props +type findContextInExprRes = { + lookingToComplete: Completable.lookingToComplete; + expressionPath: Completable.patternPathItem list; + prefix: string; +} -let extractJsxProps ~(compName : Longident.t Location.loc) ~args = - let thisCaseShouldNotHappen = - { - compName = Location.mknoloc (Longident.Lident ""); - props = []; - childrenStart = None; - } - in - let rec processProps ~acc args = - match args with - | (Asttypes.Labelled "children", {Parsetree.pexp_loc}) :: _ -> +let rec findContextInExpr expr ~pos ~expressionPath ~debug + ~firstCharBeforeCursorNoWhite = + match expr.Parsetree.pexp_desc with + (* In expressions, there's ambiguity between an empty record and an empty expression block. There's simply no way to express a record with 0 fields, like there is in patterns. + The heuristic below matches `{}` and interprets it as an empty record rather than an expression block with braces + unit, which is what the parser parses it as. *) + | Pexp_construct ({txt = Lident "()"}, None) + when expr.Parsetree.pexp_attributes + |> List.exists (fun (loc, _) -> loc.Location.txt = "ns.braces") + && CursorPosition.classifyLoc expr.pexp_loc ~pos = HasCursor -> + Some { - compName; - props = List.rev acc; - childrenStart = - (if pexp_loc.loc_ghost then None else Some (Loc.start pexp_loc)); + lookingToComplete = CRecordField; + expressionPath = expressionPath |> List.rev; + prefix = ""; } - | ((Labelled s | Optional s), (eProp : Parsetree.expression)) :: rest -> ( - let namedArgLoc = - eProp.pexp_attributes - |> List.find_opt (fun ({Asttypes.txt}, _) -> txt = "ns.namedArgLoc") - in - match namedArgLoc with - | Some ({loc}, _) -> - processProps - ~acc: - ({ - name = s; - posStart = Loc.start loc; - posEnd = Loc.end_ loc; - exp = eProp; - } - :: acc) - rest - | None -> processProps ~acc rest) - | _ -> thisCaseShouldNotHappen - in - args |> processProps ~acc:[] - -type labelled = { - name: string; - opt: bool; - posStart: int * int; - posEnd: int * int; -} - -type label = labelled option -type arg = {label: label; exp: Parsetree.expression} - -let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor - ~(contextPath : Completable.contextPath) ~posAfterFunExpr = - let allNames = - List.fold_right - (fun arg allLabels -> - match arg with - | {label = Some labelled} -> labelled.name :: allLabels - | {label = None} -> allLabels) - args [] - in - let rec loop args = - match args with - | {label = Some labelled; exp} :: rest -> - (* Figure out if we're completing the labelled argument name, or assigning to the labelled argument *) - if - labelled.posStart <= posBeforeCursor - && posBeforeCursor < labelled.posEnd - then Some (Completable.CnamedArg (contextPath, labelled.name, allNames)) - else if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then - (* Ok, were completing in the expression. Inspect what the expression is. *) - (* TODO: Apply the same thing to JSX *) - match exp.pexp_desc with - | Pexp_fun _ -> ( - (* If this is a function expression, there might be function argument patterns we can - complete (like the record destructuring in `someFunc(~someArg=({}) => {...})`) *) - let idx = ref 0 in - let rec findTargetArg exp = - match exp.Parsetree.pexp_desc with - | Pexp_fun (label, _, fnArgPattern, nextFunExpr) -> ( - let currentUnlabelledArgIdx = !idx in - (match label with - | Nolabel -> idx := !idx + 1 - | _ -> ()); - (* Check if the cursor is inside this args pattern. *) - match - ( fnArgPattern.ppat_loc - |> CursorPosition.classifyLoc ~pos:posBeforeCursor, - label ) - with - | (EmptyLoc | HasCursor), Nolabel -> - Some - (Completable.Unlabelled currentUnlabelledArgIdx, fnArgPattern) - | (EmptyLoc | HasCursor), (Labelled label | Optional label) -> - Some (Completable.Labelled label, fnArgPattern) - | NoCursor, _ -> findTargetArg nextFunExpr) - | _ -> None - in - match findTargetArg exp with - | None -> None - | Some (_arg, _argPattern) -> (* TODO: Add expr completion *) None) - | _ -> - (* TODO: Add expr completion *) - None - else if exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then - (* Expr assigned presumably is "rescript.exprhole" after parser recovery. - Assume this is an empty expression. *) - (* TODO: Add expr completion *) - None - else loop rest - | {label = None; exp} :: rest -> - if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then None - else loop rest - | [] -> - if posAfterFunExpr <= posBeforeCursor && posBeforeCursor < endPos then - Some (CnamedArg (contextPath, "", allNames)) - else None - in - loop args - -let extractExpApplyArgs ~args = - let rec processArgs ~acc args = - match args with - | (((Asttypes.Labelled s | Optional s) as label), (e : Parsetree.expression)) - :: rest -> ( - let namedArgLoc = - e.pexp_attributes - |> List.find_opt (fun ({Asttypes.txt}, _) -> txt = "ns.namedArgLoc") - in - match namedArgLoc with - | Some ({loc}, _) -> - let labelled = - { - name = s; - opt = - (match label with - | Optional _ -> true - | _ -> false); - posStart = Loc.start loc; - posEnd = Loc.end_ loc; - } - in - processArgs ~acc:({label = Some labelled; exp = e} :: acc) rest - | None -> processArgs ~acc rest) - | (Asttypes.Nolabel, (e : Parsetree.expression)) :: rest -> - if e.pexp_loc.loc_ghost then processArgs ~acc rest - else processArgs ~acc:({label = None; exp = e} :: acc) rest - | [] -> List.rev acc - in - args |> processArgs ~acc:[] + (* This mmeans parser recovery has been made, which typically means the expr was an empty assignment of some sort. *) + | Pexp_extension ({txt = "rescript.exprhole"}, _) -> + Some + { + lookingToComplete = CNoContext; + expressionPath = expressionPath |> List.rev; + prefix = ""; + } + (* Variants etc *) + | Pexp_construct ({txt}, Some payload) + when CursorPosition.classifyLoc payload.pexp_loc ~pos = HasCursor -> + (* When there's a variant with a payload, and the cursor is in the pattern. Some(S) for example. *) + let payloadNum = + match payload.pexp_desc with + | Pexp_tuple items -> + (* Find the tuple item that has the cursor, so we can add that as payload num for the variant.*) + findExprTupleItemWithCursor items ~index:0 ~pos + | _ -> Some (None, 0) + in + let exprToContinueFrom = + match payloadNum with + | Some (Some pat, _) -> pat + | _ -> payload + in + findContextInExpr exprToContinueFrom ~pos ~debug + ~firstCharBeforeCursorNoWhite + ~expressionPath: + ([ + Completable.Variant + { + constructorName = getSimpleFieldName txt; + payloadNum = + (match payloadNum with + | Some (_, payloadNum) -> Some payloadNum + | _ -> None); + }; + ] + @ expressionPath) + | Pexp_variant (constructorName, Some exp) + when CursorPosition.classifyLoc exp.pexp_loc ~pos = HasCursor -> ( + (* When there's a polyvariant with a payload, and the cursor is in the pattern. Some(S) for example. *) + match exp.pexp_desc with + | Pexp_tuple _ -> + (* Continue down here too, but let us discover the tuple in the next step. *) + findContextInExpr exp ~firstCharBeforeCursorNoWhite ~pos ~expressionPath + ~debug + | _ -> + findContextInExpr exp ~firstCharBeforeCursorNoWhite ~pos ~debug + ~expressionPath: + ([Completable.Variant {constructorName; payloadNum = Some 0}] + @ expressionPath)) + | Pexp_construct ({txt}, None) -> ( + (* Payload-less variant *) + match CursorPosition.classifyLoc expr.pexp_loc ~pos with + | HasCursor -> + Some + { + lookingToComplete = CVariant; + expressionPath = expressionPath |> List.rev; + prefix = getSimpleFieldName txt; + } + | NoCursor -> None + | EmptyLoc -> None) + | Pexp_variant (label, None) -> ( + (* Payload-less polyvariant *) + match CursorPosition.classifyLoc expr.pexp_loc ~pos with + | HasCursor -> + Some {lookingToComplete = CPolyvariant; expressionPath; prefix = label} + | NoCursor -> None + | EmptyLoc -> None) + | Pexp_construct + ( {txt}, + Some {pexp_loc; pexp_desc = Pexp_construct ({txt = Lident "()"}, _)} ) + -> ( + (* A variant like SomeVariant(). Interpret as completing the payload of the variant *) + match CursorPosition.classifyLoc pexp_loc ~pos with + | HasCursor -> + Some + { + lookingToComplete = CNoContext; + expressionPath = + [ + Completable.Variant + {constructorName = getSimpleFieldName txt; payloadNum = Some 0}; + ] + @ expressionPath + |> List.rev; + prefix = ""; + } + | NoCursor -> None + | EmptyLoc -> None) + | Pexp_variant + ( label, + Some {pexp_loc; pexp_desc = Pexp_construct ({txt = Lident "()"}, _)} ) + -> ( + (* A polyvariant like #SomeVariant(). Interpret as completing the payload of the variant *) + match CursorPosition.classifyLoc pexp_loc ~pos with + | HasCursor -> + Some + { + lookingToComplete = CNoContext; + expressionPath = + [Completable.Polyvariant {name = label; payloadNum = Some 0}] + @ expressionPath + |> List.rev; + prefix = ""; + } + | NoCursor -> None + | EmptyLoc -> None (* Records *)) + | Pexp_record ([], _) -> + (* No fields mean we're in an empty record body. We can complete for that. *) + Some {lookingToComplete = CRecordField; expressionPath; prefix = ""} + | Pexp_record (fields, _) -> ( + (* TODO: Restore for exprs *) + let _seenFields = + fields |> List.map (fun ({Location.txt}, _) -> getSimpleFieldName txt) + in + let fieldWithCursorExists = + fields + |> List.exists (fun (_, fieldPat) -> + CursorPosition.classifyLoc fieldPat.Parsetree.pexp_loc ~pos + = HasCursor) + in + let completableFromField = + fields + |> List.find_map (fun (loc, fieldExpr) -> + match + CursorPosition.classifyLoc fieldExpr.Parsetree.pexp_loc ~pos + with + | HasCursor -> ( + match fieldExpr.pexp_desc with + | Pexp_ident loc -> + Some + { + lookingToComplete = CRecordField; + expressionPath = expressionPath |> List.rev; + prefix = getSimpleFieldName loc.txt; + } + | _ -> + (* We can continue down into anything else *) + findContextInExpr fieldExpr ~pos ~firstCharBeforeCursorNoWhite + ~debug + ~expressionPath: + ([ + Completable.RField + {fieldName = getSimpleFieldName loc.Location.txt}; + ] + @ expressionPath)) + | NoCursor -> None + | EmptyLoc -> + if + (* We only care about empty locations if there's no field with the cursor *) + fieldWithCursorExists + then None + else + findContextInExpr fieldExpr ~pos ~debug + ~firstCharBeforeCursorNoWhite + ~expressionPath: + ([ + Completable.RField + {fieldName = getSimpleFieldName loc.txt}; + ] + @ expressionPath)) + in + match + (completableFromField, fieldWithCursorExists, firstCharBeforeCursorNoWhite) + with + | None, false, Some ',' -> + (* If there's no field with the cursor, and we found no completable, and the first char before the + cursor is ',' we can assume that this is a pattern like `{someField, }`. + The parser discards any unecessary commas, so we can't leverage the parser to figure out that + we're looking to complete for a new field. *) + Some + { + lookingToComplete = CRecordField; + expressionPath = expressionPath |> List.rev; + prefix = ""; + } + | completableFromField, _, _ -> completableFromField) + | Pexp_tuple items -> ( + match findExprTupleItemWithCursor items ~pos ~index:0 with + | Some (Some tupleExprWithCursor, itemNumber) -> + findContextInExpr tupleExprWithCursor ~pos ~debug + ~firstCharBeforeCursorNoWhite + ~expressionPath:([Completable.PTuple {itemNumber}] @ expressionPath) + | None -> + (* TODO: No tuple item had the cursor, but we might still be able to complete + for the next tuple item. We just need to figure out where in the pattern + we are. E.g. `(_, , A)` is parsed the same as `(_, A, )` or `(_, A, ,)`. + Figuring out exactly which tuple item we're in is problematic because of that. *) + None + | _ -> None) + | _v -> None type findContextInPatternRes = { lookingToComplete: Completable.lookingToComplete; @@ -327,14 +327,6 @@ type findContextInPatternRes = { alreadySeenIdents: string list; } -let rec findTupleItemWithCursor items ~index ~pos = - match items with - | [] -> None - | item :: rest -> - if CursorPosition.classifyLoc item.Parsetree.ppat_loc ~pos = HasCursor then - Some (Some item, index) - else findTupleItemWithCursor rest ~index:(index + 1) ~pos - let rec findContextInPattern pattern ~pos ~patternPath ~debug ~seenIdentsFromParent ~firstCharBeforeCursorNoWhite = match pattern.Parsetree.ppat_desc with @@ -344,7 +336,7 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug Some { lookingToComplete = CNoContext; - patternPath; + patternPath = patternPath |> List.rev; prefix = ""; alreadySeenIdents = seenIdentsFromParent; } @@ -356,7 +348,7 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug (* We're completing vars as variants for now, since bool (which is a variant) is the only thing I can think of that needs completion here. *) lookingToComplete = CNoContext; - patternPath; + patternPath = patternPath |> List.rev; prefix = ""; alreadySeenIdents = seenIdentsFromParent; } @@ -367,7 +359,7 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug (* We're completing vars as variants for now, since bool (which is a variant) is the only thing I can think of that needs completion here. *) lookingToComplete = CVariant; - patternPath; + patternPath = patternPath |> List.rev; prefix = loc.txt; alreadySeenIdents = []; } @@ -379,7 +371,7 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug match payload.ppat_desc with | Ppat_tuple items -> (* Find the tuple item that has the cursor, so we can add that as payload num for the variant.*) - findTupleItemWithCursor items ~index:0 ~pos + findPatternTupleItemWithCursor items ~index:0 ~pos | _ -> Some (None, 0) in let patternToContinueFrom = @@ -422,7 +414,7 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug Some { lookingToComplete = CVariant; - patternPath; + patternPath = patternPath |> List.rev; prefix = getSimpleFieldName txt; alreadySeenIdents = seenIdentsFromParent; } @@ -435,7 +427,7 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug Some { lookingToComplete = CPolyvariant; - patternPath; + patternPath = patternPath |> List.rev; prefix = label; alreadySeenIdents = seenIdentsFromParent; } @@ -456,7 +448,8 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug Completable.Variant {constructorName = getSimpleFieldName txt; payloadNum = Some 0}; ] - @ patternPath; + @ patternPath + |> List.rev; prefix = ""; alreadySeenIdents = []; } @@ -474,7 +467,8 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug lookingToComplete = CNoContext; patternPath = [Completable.Polyvariant {name = label; payloadNum = Some 0}] - @ patternPath; + @ patternPath + |> List.rev; prefix = ""; alreadySeenIdents = []; } @@ -486,7 +480,7 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug Some { lookingToComplete = CRecordField; - patternPath; + patternPath = patternPath |> List.rev; prefix = ""; alreadySeenIdents = []; } @@ -515,7 +509,7 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug Some { lookingToComplete = CRecordField; - patternPath; + patternPath = patternPath |> List.rev; prefix = varName; alreadySeenIdents = seenFields; } @@ -556,13 +550,13 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug Some { lookingToComplete = CRecordField; - patternPath; + patternPath = patternPath |> List.rev; prefix = ""; alreadySeenIdents = seenFields; } | completableFromField, _, _ -> completableFromField) | Ppat_tuple items -> ( - match findTupleItemWithCursor items ~pos ~index:0 with + match findPatternTupleItemWithCursor items ~pos ~index:0 with | Some (Some tuplePatternWithCursor, itemNumber) -> findContextInPattern tuplePatternWithCursor ~pos ~debug ~seenIdentsFromParent:[] ~firstCharBeforeCursorNoWhite @@ -617,7 +611,7 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug Some { lookingToComplete = CNoContext; - patternPath; + patternPath = patternPath |> List.rev; prefix = ""; alreadySeenIdents = identsFromBranches; } @@ -632,6 +626,197 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug Printf.printf "warning: unhandled pattern %s\n" (Utils.identifyPpat v);*) None +type prop = { + name: string; + posStart: int * int; + posEnd: int * int; + exp: Parsetree.expression; +} + +type jsxProps = { + compName: Longident.t Location.loc; + props: prop list; + childrenStart: (int * int) option; +} + +let findJsxPropsCompletable ~jsxProps ~endPos ~posBeforeCursor ~posAfterCompName + = + let allLabels = + List.fold_right + (fun prop allLabels -> prop.name :: allLabels) + jsxProps.props [] + in + let rec loop props = + match props with + | prop :: rest -> + if prop.posStart <= posBeforeCursor && posBeforeCursor < prop.posEnd then + (* Cursor on the prop name *) + Some + (Completable.Cjsx + ( Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt, + prop.name, + allLabels )) + else if + prop.posEnd <= posBeforeCursor + && posBeforeCursor < Loc.start prop.exp.pexp_loc + then (* Cursor between the prop name and expr assigned *) + None + else if prop.exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then + (* Cursor on expr assigned *) + (* TODO: Add expr completion *) + None + else if prop.exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then + (* Expr assigned presumably is "rescript.exprhole" after parser recovery. + Complete for the value. *) + (* TODO: Add expr completion *) + None + else loop rest + | [] -> + let beforeChildrenStart = + match jsxProps.childrenStart with + | Some childrenPos -> posBeforeCursor < childrenPos + | None -> posBeforeCursor <= endPos + in + let afterCompName = posBeforeCursor >= posAfterCompName in + if afterCompName && beforeChildrenStart then + Some + (Cjsx + ( Utils.flattenLongIdent ~jsx:true jsxProps.compName.txt, + "", + allLabels )) + else None + in + loop jsxProps.props + +let extractJsxProps ~(compName : Longident.t Location.loc) ~args = + let thisCaseShouldNotHappen = + { + compName = Location.mknoloc (Longident.Lident ""); + props = []; + childrenStart = None; + } + in + let rec processProps ~acc args = + match args with + | (Asttypes.Labelled "children", {Parsetree.pexp_loc}) :: _ -> + { + compName; + props = List.rev acc; + childrenStart = + (if pexp_loc.loc_ghost then None else Some (Loc.start pexp_loc)); + } + | ((Labelled s | Optional s), (eProp : Parsetree.expression)) :: rest -> ( + let namedArgLoc = + eProp.pexp_attributes + |> List.find_opt (fun ({Asttypes.txt}, _) -> txt = "ns.namedArgLoc") + in + match namedArgLoc with + | Some ({loc}, _) -> + processProps + ~acc: + ({ + name = s; + posStart = Loc.start loc; + posEnd = Loc.end_ loc; + exp = eProp; + } + :: acc) + rest + | None -> processProps ~acc rest) + | _ -> thisCaseShouldNotHappen + in + args |> processProps ~acc:[] + +let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor + ~(contextPath : Completable.contextPath) ~posAfterFunExpr + ~firstCharBeforeCursorNoWhite ~debug = + let allNames = + List.fold_right + (fun arg allLabels -> + match arg with + | {label = Some labelled} -> labelled.name :: allLabels + | {label = None} -> allLabels) + args [] + in + let rec loop args = + match args with + | {label = Some labelled; exp} :: rest -> + (* Figure out if we're completing the labelled argument name, or assigning to the labelled argument *) + if + labelled.posStart <= posBeforeCursor + && posBeforeCursor < labelled.posEnd + then Some (Completable.CnamedArg (contextPath, labelled.name, allNames)) + else if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then + (* Ok, were completing in the expression. Inspect what the expression is. *) + (* TODO: Apply the same thing to JSX *) + match exp.pexp_desc with + | Pexp_fun _ -> ( + (* If this is a function expression, there might be function argument patterns we can + complete (like the record destructuring in `someFunc(~someArg=({}) => {...})`) *) + let idx = ref 0 in + let rec findTargetArg exp = + match exp.Parsetree.pexp_desc with + | Pexp_fun (label, _, fnArgPattern, nextFunExpr) -> ( + let currentUnlabelledArgIdx = !idx in + (match label with + | Nolabel -> idx := !idx + 1 + | _ -> ()); + (* Check if the cursor is inside this args pattern. *) + match + ( fnArgPattern.ppat_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor, + label ) + with + | (EmptyLoc | HasCursor), Nolabel -> + Some + (Completable.Unlabelled currentUnlabelledArgIdx, fnArgPattern) + | (EmptyLoc | HasCursor), (Labelled label | Optional label) -> + Some (Completable.Labelled label, fnArgPattern) + | NoCursor, _ -> findTargetArg nextFunExpr) + | _ -> None + in + match findTargetArg exp with + | None -> None + | Some (_arg, _argPattern) -> (* TODO: Add expr completion *) None) + | _ -> ( + match + findContextInExpr exp ~debug ~pos:posBeforeCursor ~expressionPath:[] + ~firstCharBeforeCursorNoWhite + with + | None -> None + | Some res -> + Some + (CtypedExpression + { + prefix = res.prefix; + lookingToComplete = res.lookingToComplete; + expressionPath = res.expressionPath; + howToRetrieveSourceType = + NamedArg {label = labelled.name; contextPath}; + })) + else if exp.pexp_loc |> Loc.end_ = (Location.none |> Loc.end_) then + (* Expr assigned presumably is "rescript.exprhole" after parser recovery. + Assume this is an empty expression. *) + Some + (CtypedExpression + { + prefix = ""; + lookingToComplete = CNoContext; + expressionPath = []; + howToRetrieveSourceType = + NamedArg {label = labelled.name; contextPath}; + }) + else loop rest + | {label = None; exp} :: rest -> + if exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then None + else loop rest + | [] -> + if posAfterFunExpr <= posBeforeCursor && posBeforeCursor < endPos then + Some (CnamedArg (contextPath, "", allNames)) + else None + in + loop args + let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = let offsetNoWhite = skipWhite text (offset - 1) in let posNoWhite = @@ -649,7 +834,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = in let posBeforeCursor = (fst posCursor, max 0 (snd posCursor - 1)) in let charBeforeCursor, blankAfterCursor = - match positionToOffset text posCursor with + match Pos.positionToOffset text posCursor with | Some offset when offset > 0 -> ( let charBeforeCursor = text.[offset - 1] in let charAtCursor = @@ -815,7 +1000,10 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = prefix = ""; })) | _ -> ()) - | [{pvb_pat; pvb_expr = expr}] -> ( + | [{pvb_pat; pvb_expr = expr}] + when pvb_pat.ppat_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + = HasCursor -> ( (* Check for: let {destructuringSomething} = someIdentifier *) (* TODO: Handle let {SomeModule.recordField} = ...*) @@ -836,7 +1024,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = (Completable.CtypedPattern { howToRetrieveSourceType = CtxPath contextPath; - patternPath = res.patternPath |> List.rev; + patternPath = res.patternPath; patternType = Destructure; lookingToComplete = res.lookingToComplete; prefix = res.prefix; @@ -900,7 +1088,9 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = else if id.loc.loc_ghost then () else if id.loc |> Loc.hasPos ~pos:posBeforeCursor then let posStart, posEnd = Loc.range id.loc in - match (positionToOffset text posStart, positionToOffset text posEnd) with + match + (Pos.positionToOffset text posStart, Pos.positionToOffset text posEnd) + with | Some offsetStart, Some offsetEnd -> (* Can't trust the parser's location E.g. @foo. let x... gives as label @foo.let *) @@ -1086,6 +1276,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = match exprToContextPath funExpr with | Some contextPath -> findNamedArgCompletable ~contextPath ~args + ~firstCharBeforeCursorNoWhite ~debug ~endPos:(Loc.end_ expr.pexp_loc) ~posBeforeCursor ~posAfterFunExpr:(Loc.end_ funExpr.pexp_loc) | None -> None @@ -1197,7 +1388,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = (CtypedPattern { howToRetrieveSourceType = CtxPath contextPath; - patternPath = res.patternPath |> List.rev; + patternPath = res.patternPath; patternType = Switch; lookingToComplete = res.lookingToComplete; prefix = res.prefix; @@ -1335,7 +1526,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = else None let completionWithParser ~debug ~path ~posCursor ~currentFile ~text = - match positionToOffset text posCursor with + match Pos.positionToOffset text posCursor with | Some offset -> completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text | None -> None diff --git a/analysis/src/DumpAst.ml b/analysis/src/DumpAst.ml index 244191461..3a67ceb3e 100644 --- a/analysis/src/DumpAst.ml +++ b/analysis/src/DumpAst.ml @@ -148,8 +148,7 @@ and printCase case ~pos ~indentation ~caseNum = ^ printExprItem case.pc_rhs ~pos ~indentation:(indentation + 2) and printExprItem expr ~pos ~indentation = - addIndentation indentation - ^ printAttributes expr.Parsetree.pexp_attributes + printAttributes expr.Parsetree.pexp_attributes ^ (expr.pexp_loc |> printLocDenominator ~pos) ^ match expr.Parsetree.pexp_desc with @@ -169,15 +168,16 @@ and printExprItem expr ~pos ~indentation = match labelled with | None -> "" | Some labelled -> - printLocDenominatorPos pos - ~posStart:labelled.CompletionFrontEnd.posStart ~posEnd:labelled.posEnd + printLocDenominatorPos pos ~posStart:labelled.posStart + ~posEnd:labelled.posEnd ^ "~" ^ if labelled.opt then "?" else "" ^ labelled.name in - let args = CompletionFrontEnd.extractExpApplyArgs ~args in + let args = extractExpApplyArgs ~args in "Pexp_apply(\n" ^ addIndentation (indentation + 1) ^ "expr:\n" + ^ addIndentation (indentation + 2) ^ printExprItem expr ~pos ~indentation:(indentation + 2) ^ "\n" ^ addIndentation (indentation + 1) @@ -185,8 +185,8 @@ and printExprItem expr ~pos ~indentation = ^ (args |> List.map (fun arg -> addIndentation (indentation + 2) - ^ printLabel arg.CompletionFrontEnd.label ~pos - ^ "=\n" + ^ printLabel arg.label ~pos ^ "=\n" + ^ addIndentation (indentation + 3) ^ printExprItem arg.exp ~pos ~indentation:(indentation + 3)) |> String.concat ",\n") ^ "\n" ^ addIndentation indentation ^ ")" @@ -224,11 +224,35 @@ and printExprItem expr ~pos ~indentation = ^ "\n" ^ addIndentation indentation ^ ")" | Pexp_extension (({txt} as loc), _) -> "Pexp_extension(%" ^ (loc |> printLocDenominatorLoc ~pos) ^ txt ^ ")" + | Pexp_assert expr -> + "Pexp_assert(" ^ printExprItem expr ~pos ~indentation ^ ")" | Pexp_field (exp, loc) -> "Pexp_field(" ^ (loc |> printLocDenominatorLoc ~pos) ^ printExprItem exp ~pos ~indentation ^ ")" + | Pexp_record (fields, _) -> + "Pexp_record(\n" + ^ addIndentation (indentation + 1) + ^ "fields:\n" + ^ (fields + |> List.map (fun ((Location.{txt} as loc), expr) -> + addIndentation (indentation + 2) + ^ (loc |> printLocDenominatorLoc ~pos) + ^ (Utils.flattenLongIdent txt |> Completable.ident + |> Completable.str) + ^ ": " + ^ printExprItem expr ~pos ~indentation:(indentation + 2)) + |> String.concat "\n") + ^ "\n" ^ addIndentation indentation ^ ")" + | Pexp_tuple exprs -> + "Pexp_tuple(\n" + ^ (exprs + |> List.map (fun expr -> + addIndentation (indentation + 2) + ^ (expr |> printExprItem ~pos ~indentation:(indentation + 2))) + |> String.concat ",\n") + ^ "\n" ^ addIndentation indentation ^ ")" | v -> Printf.sprintf "" (Utils.identifyPexp v) let printValueBinding value ~pos ~indentation = @@ -243,10 +267,7 @@ let printStructItem structItem ~pos ~source = match structItem.Parsetree.pstr_loc |> CursorPosition.classifyLoc ~pos with | HasCursor -> ( let startOffset = - match - CompletionFrontEnd.positionToOffset source - (structItem.pstr_loc |> Loc.start) - with + match Pos.positionToOffset source (structItem.pstr_loc |> Loc.start) with | None -> 0 | Some offset -> offset in @@ -255,7 +276,7 @@ let printStructItem structItem ~pos ~source = Caveat: this only works for single line sources with a comment on the next line. Will need to be adapted if that's not the only use case.*) let line, _col = structItem.pstr_loc |> Loc.end_ in - match CompletionFrontEnd.positionToOffset source (line + 2, 0) with + match Pos.positionToOffset source (line + 2, 0) with | None -> 0 | Some offset -> offset in diff --git a/analysis/src/Pos.ml b/analysis/src/Pos.ml index cfcf6b7b6..818178d28 100644 --- a/analysis/src/Pos.ml +++ b/analysis/src/Pos.ml @@ -4,3 +4,23 @@ let ofLexing {Lexing.pos_lnum; pos_cnum; pos_bol} = (pos_lnum - 1, pos_cnum - pos_bol) let toString (loc, col) = Printf.sprintf "%d:%d" loc col + +let offsetOfLine text line = + let ln = String.length text in + let rec loop i lno = + if i >= ln then None + else + match text.[i] with + | '\n' -> if lno = line - 1 then Some (i + 1) else loop (i + 1) (lno + 1) + | _ -> loop (i + 1) lno + in + match line with + | 0 -> Some 0 + | _ -> loop 0 0 + +let positionToOffset text (line, character) = + match offsetOfLine text line with + | None -> None + | Some bol -> + if bol + character <= String.length text then Some (bol + character) + else None \ No newline at end of file diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index 984e9471c..c0b57f6e3 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -652,4 +652,45 @@ module CursorPosition = struct if posStart <= pos && pos <= posEnd then HasCursor else if posEnd = (Location.none |> Loc.end_) then EmptyLoc else NoCursor -end \ No newline at end of file +end + +type labelled = { + name: string; + opt: bool; + posStart: int * int; + posEnd: int * int; +} + +type label = labelled option +type arg = {label: label; exp: Parsetree.expression} + +let extractExpApplyArgs ~args = + let rec processArgs ~acc args = + match args with + | (((Asttypes.Labelled s | Optional s) as label), (e : Parsetree.expression)) + :: rest -> ( + let namedArgLoc = + e.pexp_attributes + |> List.find_opt (fun ({Asttypes.txt}, _) -> txt = "ns.namedArgLoc") + in + match namedArgLoc with + | Some ({loc}, _) -> + let labelled = + { + name = s; + opt = + (match label with + | Optional _ -> true + | _ -> false); + posStart = Loc.start loc; + posEnd = Loc.end_ loc; + } + in + processArgs ~acc:({label = Some labelled; exp = e} :: acc) rest + | None -> processArgs ~acc rest) + | (Asttypes.Nolabel, (e : Parsetree.expression)) :: rest -> + if e.pexp_loc.loc_ghost then processArgs ~acc rest + else processArgs ~acc:({label = None; exp = e} :: acc) rest + | [] -> List.rev acc + in + args |> processArgs ~acc:[] \ No newline at end of file diff --git a/analysis/tests/src/TypeContextCompletion_LabelledArguments.res b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res index c3322dff7..8f4377b42 100644 --- a/analysis/tests/src/TypeContextCompletion_LabelledArguments.res +++ b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res @@ -56,11 +56,30 @@ let someVariantToString = ( type someRecord = { age: int, name: string, + maybeVariant: option, + definitivelyVariant: someVariant, + someTup: (string, someVariant), } let doStuff = (~doThing: someRecord => unit) => { - ignore(doThing({age: 123, name: "hello"})) + ignore( + doThing({ + age: 123, + name: "hello", + maybeVariant: None, + definitivelyVariant: One, + someTup: ("123", One), + }), + ) } // let _ = doStuff(~doThing=({age, n}) => {()}) // ^com + +let doMoreStuff = (~someRecord: someRecord): someRecord => someRecord + +// doMoreStuff(~someRecord={someTup: ("123", O)}) +// ^com + +// let _ = doMoreStuff(~someRecord={}) +// ^com diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index eaf97589b..f58ecdfcf 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -695,8 +695,17 @@ Completable: Cjsx([O, Comp], z, [z]) Complete src/Completion.res 65:8 Attribute id:reac:[65:3->65:8] label:reac -Completable: CtypedPattern(sourceType:Value[Lib, foo](~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +Completable: Cdecorator(reac) +[{ + "label": "react.component", + "kind": 4, + "tags": [], + "detail": "", + "documentation": {"kind": "markdown", "value": "The `@react.component` decorator is used to annotate functions that are RescriptReact components.\n\nYou will need this decorator whenever you want to use a ReScript / React component in ReScript JSX expressions.\n\nNote: The `@react.component` decorator requires the react-jsx config to be set in your `bsconfig.json` to enable the required React transformations.\n\n[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#react-component-decorator)."}, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 68:10 posCursor:[68:10] posNoWhite:[68:9] Found expr:[0:-1->86:1] @@ -763,8 +772,10 @@ Found type for function (~age: int, ~name: string) => string }] Complete src/Completion.res 82:5 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Lib, foo](Nolabel, ~age, ~name), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +posCursor:[82:5] posNoWhite:[82:4] Found expr:[80:8->86:1] +Pexp_apply ...[80:8->80:15] (~age84:3->84:6=...[84:7->84:8], ~name85:3->85:7=...[85:8->85:10]) +Completable: CnamedArg(Value[Lib, foo], "", [age, name]) +Found type for function (~age: int, ~name: string) => string [] Complete src/Completion.res 90:13 @@ -1410,9 +1421,20 @@ Completable: Cpath Type[s] }] Complete src/Completion.res 291:30 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[funRecord].someFun(Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[291:30] posNoWhite:[291:29] Found expr:[291:11->291:32] +Pexp_apply ...[291:11->291:28] () +Completable: CnamedArg(Value[funRecord].someFun, "", []) +Found type for function (~name: string) => unit +[{ + "label": "name", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 296:11 posCursor:[296:11] posNoWhite:[296:10] Found expr:[296:3->296:11] @@ -1707,11 +1729,35 @@ Found type for function (~a: int) => int }] Complete src/Completion.res 336:26 +posCursor:[336:26] posNoWhite:[336:25] Found expr:[333:3->346:23] +JSX 333:6] onClick[334:4->334:11]=...[334:13->346:23]> _children:None +posCursor:[336:26] posNoWhite:[336:25] Found expr:[334:13->346:23] +posCursor:[336:26] posNoWhite:[336:25] Found expr:[334:13->338:6] +posCursor:[336:26] posNoWhite:[336:25] Found expr:[335:6->338:5] +posCursor:[336:26] posNoWhite:[336:25] Found expr:[336:16->338:5] posCursor:[336:26] posNoWhite:[336:25] Found pattern:[336:20->338:5] posCursor:[336:26] posNoWhite:[336:25] Found type:[336:23->338:5] Ptyp_constr Res:[336:23->338:5] -Completable: CtypedPattern(sourceType:Value[div](~onClick, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +Completable: Cpath Type[Res] +[{ + "label": "RescriptReactErrorBoundary", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "RescriptReactRouter", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 343:57 posCursor:[343:57] posNoWhite:[343:56] Found expr:[343:10->346:23] @@ -1732,21 +1778,35 @@ Completable: Cpath Value[this] Hover src/Completion.res 346:14 Nothing at that position. Now trying to use completion. -XXX Not found! -Completable: CtypedPattern(sourceType:Value[div](~name, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -null +posCursor:[346:14] posNoWhite:[346:13] Found expr:[346:9->346:23] +JSX 346:12] name[346:13->346:17]=...[346:18->346:20]> _children:346:21 +Completable: Cjsx([div], name, [name]) +{"contents": "```rescript\nstring\n```"} Hover src/Completion.res 349:17 Nothing at that position. Now trying to use completion. -XXX Not found! -Completable: CtypedPattern(sourceType:Value[FAO, forAutoObject]["age"], lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -null +posCursor:[349:17] posNoWhite:[349:16] Found expr:[349:11->349:35] +Pexp_send age[349:30->349:33] e:[349:11->349:28] +posCursor:[349:17] posNoWhite:[349:16] Found expr:[349:11->349:28] +Pexp_ident FAO.forAutoObject:[349:11->349:28] +Completable: Cpath Value[FAO, forAutoObject] +{"contents": "```rescript\n{\"age\": int, \"forAutoLabel\": FAR.forAutoRecord}\n```"} Hover src/Completion.res 352:17 Nothing at that position. Now trying to use completion. -XXX Not found! -Completable: CtypedPattern(sourceType:Value[ff](~opt1), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -null +posCursor:[352:17] posNoWhite:[352:16] Found expr:[352:11->352:22] +Pexp_apply ...[352:11->352:13] (~opt1352:15->352:19=...[352:20->352:21]) +Completable: CnamedArg(Value[ff], opt1, [opt1]) +Found type for function ( + ~opt1: int=?, + ~a: int, + ~b: int, + unit, + ~opt2: int=?, + unit, + ~c: int, +) => int +{"contents": "```rescript\noption\n```"} Complete src/Completion.res 355:23 posCursor:[355:23] posNoWhite:[355:22] Found expr:[0:-1->355:23] @@ -1772,19 +1832,88 @@ Completable: CtypedPattern(sourceType:Value[x], lookingToComplete:CVariant, patt [] Complete src/Completion.res 378:24 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[^](Nolabel, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[378:24] posNoWhite:[378:23] Found expr:[378:12->378:26] +Pexp_apply ...__ghost__[0:-1->0:-1] (...[378:12->378:24], ...[378:24->378:25]) +posCursor:[378:24] posNoWhite:[378:23] Found expr:[378:12->378:24] +Pexp_apply ...__ghost__[0:-1->0:-1] (...[378:12->378:14], ...[378:16->378:24]) +posCursor:[378:24] posNoWhite:[378:23] Found expr:[378:16->378:24] +Pexp_ident ForAuto.:[378:16->378:24] +Completable: Cpath Value[ForAuto, ""] +[{ + "label": "abc", + "kind": 12, + "tags": [], + "detail": "(t, int) => t", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "abd", + "kind": 12, + "tags": [], + "detail": "(t, int) => t", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 381:38 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[^](Nolabel, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[381:38] posNoWhite:[381:37] Found expr:[381:12->381:41] +Pexp_apply ...__ghost__[0:-1->0:-1] (...[381:12->381:39], ...[381:39->381:40]) +posCursor:[381:38] posNoWhite:[381:37] Found expr:[381:12->381:39] +Pexp_apply ...__ghost__[0:-1->0:-1] (...[381:12->381:17], ...[381:19->381:39]) +posCursor:[381:38] posNoWhite:[381:37] Found expr:[381:19->381:39] +Pexp_send [381:38->381:38] e:[381:19->381:36] +Completable: Cpath Value[FAO, forAutoObject][""] +[{ + "label": "age", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "forAutoLabel", + "kind": 4, + "tags": [], + "detail": "FAR.forAutoRecord", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 384:24 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[^](Nolabel, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[384:24] posNoWhite:[384:23] Found expr:[384:11->384:26] +Pexp_apply ...__ghost__[0:-1->0:-1] (...[384:11->384:24], ...[384:24->384:25]) +posCursor:[384:24] posNoWhite:[384:23] Found expr:[384:11->384:24] +Pexp_apply ...__ghost__[0:-1->0:-1] (...[384:11->384:12], ...[384:14->384:24]) +posCursor:[384:24] posNoWhite:[384:23] Found expr:[384:14->384:24] +Pexp_field [384:14->384:23] _:[384:24->384:24] +Completable: Cpath Value[funRecord]."" +[{ + "label": "someFun", + "kind": 5, + "tags": [], + "detail": "someFun: (~name: string) => unit\n\ntype funRecord = {\n someFun: (~name: string) => unit,\n stuff: string,\n}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "stuff", + "kind": 5, + "tags": [], + "detail": "stuff: string\n\ntype funRecord = {\n someFun: (~name: string) => unit,\n stuff: string,\n}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Completion.res 389:12 posCursor:[389:12] posNoWhite:[389:11] Found expr:[387:8->392:1] @@ -1851,7 +1980,39 @@ Completable: Cpath Value[red] }] Complete src/Completion.res 405:22 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[^](Nolabel, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[405:22] posNoWhite:[405:21] Found expr:[405:11->408:0] +Pexp_apply ...__ghost__[0:-1->0:-1] (...[405:11->405:22], ...[408:0->408:0]) +posCursor:[405:22] posNoWhite:[405:21] Found expr:[405:11->405:22] +Pexp_apply ...__ghost__[0:-1->0:-1] (...[405:11->405:19], ...[405:21->405:22]) +posCursor:[405:22] posNoWhite:[405:21] Found expr:[405:21->405:22] +Pexp_ident r:[405:21->405:22] +Completable: Cpath Value[r] +[{ + "label": "red", + "kind": 12, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "retAA", + "kind": 12, + "tags": [], + "detail": "unit => aa", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "r", + "kind": 12, + "tags": [], + "detail": "rAlias", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index cf91af19b..858e4da99 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:313 +issues:316 diff --git a/analysis/tests/src/expected/Jsx.res.txt b/analysis/tests/src/expected/Jsx.res.txt index 7cd6fcb1c..614e4a28c 100644 --- a/analysis/tests/src/expected/Jsx.res.txt +++ b/analysis/tests/src/expected/Jsx.res.txt @@ -436,29 +436,73 @@ Completable: Cpath Module[DefineSomeFields].th }] Complete src/Jsx.res 122:20 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[div](~x, ~name, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[122:20] posNoWhite:[122:19] Found expr:[121:3->125:4] +JSX 121:6] x[122:5->122:6]=...[122:7->122:20] name[124:4->124:8]=...[124:9->124:11]> _children:125:2 +posCursor:[122:20] posNoWhite:[122:19] Found expr:[122:7->122:20] +Pexp_ident Outer.Inner.h:[122:7->122:20] +Completable: Cpath Value[Outer, Inner, h] +[{ + "label": "hello", + "kind": 12, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 129:19 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[div](~x, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[129:19] posNoWhite:[129:18] Found expr:[128:3->131:9] +JSX 128:6] x[129:5->129:6]=...[129:7->131:8]> _children:None +posCursor:[129:19] posNoWhite:[129:18] Found expr:[129:7->131:8] +Pexp_ident Outer.Inner.:[129:7->131:8] +Completable: Cpath Value[Outer, Inner, ""] +[{ + "label": "hello", + "kind": 12, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 136:7 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[div](~x, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +posCursor:[136:7] posNoWhite:[136:6] Found expr:[135:3->138:9] +JSX 135:6] x[136:5->136:6]=...[138:4->138:8]> _children:None [] Complete src/Jsx.res 150:21 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Nested, Co, createElement](~name, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[150:21] posNoWhite:[150:20] Found expr:[150:12->150:32] +JSX 150:21] name[150:22->150:26]=...[150:27->150:29]> _children:150:30 +Completable: Cpath Module[Nested, Co] +[{ + "label": "Comp", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Complete src/Jsx.res 153:19 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Nested, name, createElement](~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[153:19] posNoWhite:[153:18] Found expr:[153:12->153:25] +JSX 153:24] > _children:None +Completable: Cpath Module[Nested, ""] +[{ + "label": "Comp", + "kind": 9, + "tags": [], + "detail": "module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] Hover src/Jsx.res 162:12 Nothing at that position. Now trying to use completion. @@ -484,7 +528,44 @@ Completable: Cjsx([Comp], age, [age]) {"contents": "```rescript\nint\n```"} Complete src/Jsx.res 171:30 -XXX Not found! -Completable: CtypedPattern(sourceType:Value[Completion, O, Comp, createElement](~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +posCursor:[171:30] posNoWhite:[171:28] Found expr:[171:12->171:33] +JSX 171:29] > _children:171:31 +Completable: Cjsx([Completion, O, Comp], "", []) +[{ + "label": "first", + "kind": 4, + "tags": [], + "detail": "option", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "second", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "zoo", + "kind": 4, + "tags": [], + "detail": "option", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "key", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] diff --git a/analysis/tests/src/expected/RecoveryOnProp.res.txt b/analysis/tests/src/expected/RecoveryOnProp.res.txt index 7dcea2f3a..90005826d 100644 --- a/analysis/tests/src/expected/RecoveryOnProp.res.txt +++ b/analysis/tests/src/expected/RecoveryOnProp.res.txt @@ -1,7 +1,30 @@ Complete src/RecoveryOnProp.res 6:26 +posCursor:[6:26] posNoWhite:[6:25] Found expr:[3:3->11:8] +JSX 3:6] onClick[4:4->4:11]=...[4:13->0:-1]> _children:None +posCursor:[6:26] posNoWhite:[6:25] Found expr:[4:13->8:6] +posCursor:[6:26] posNoWhite:[6:25] Found expr:[5:6->8:5] +posCursor:[6:26] posNoWhite:[6:25] Found expr:[6:16->8:5] posCursor:[6:26] posNoWhite:[6:25] Found pattern:[6:20->8:5] posCursor:[6:26] posNoWhite:[6:25] Found type:[6:23->8:5] Ptyp_constr Res:[6:23->8:5] -Completable: CtypedPattern(sourceType:Value[div](~onClick, ~children, Nolabel), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) -[] +Completable: Cpath Type[Res] +[{ + "label": "RescriptReactErrorBoundary", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "RescriptReactRouter", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index 9540fa82e..bb144908c 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -21,73 +21,145 @@ Found type for function ( Complete src/TypeContextCompletion_LabelledArguments.res 25:44 posCursor:[25:44] posNoWhite:[25:43] Found expr:[25:11->25:44] Pexp_apply ...[25:11->25:30] (~someVariant25:32->25:43=...__ghost__[0:-1->0:-1]) -[] +Completable: CtypedExpression(sourceType:NamedArg(someVariant, Value[someVariantToString]), lookingToComplete:CNoContext, prefix:"", pattern: [] +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null, + "sortText": null, + "insertText": "One", + "insertTextFormat": 2 + }, { + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null, + "sortText": null, + "insertText": "Two", + "insertTextFormat": 2 + }, { + "label": "Three", + "kind": 4, + "tags": [], + "detail": "Three\n\n", + "documentation": null, + "sortText": null, + "insertText": "Three", + "insertTextFormat": 2 + }, { + "label": "Four", + "kind": 4, + "tags": [], + "detail": "Four\n\n", + "documentation": null, + "sortText": null, + "insertText": "Four", + "insertTextFormat": 2 + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\n", + "documentation": null, + "sortText": null, + "insertText": "Five($1)", + "insertTextFormat": 2 + }, { + "label": "Six(_)", + "kind": 4, + "tags": [], + "detail": "Six(option, int)\n\n", + "documentation": null, + "sortText": null, + "insertText": "Six($1)", + "insertTextFormat": 2 + }] Complete src/TypeContextCompletion_LabelledArguments.res 28:45 posCursor:[28:45] posNoWhite:[28:43] Found expr:[28:11->28:44] Pexp_apply ...[28:11->28:30] (~someVariant28:32->28:43=...__ghost__[0:-1->0:-1]) -[] - -Complete src/TypeContextCompletion_LabelledArguments.res 31:45 -posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:11->31:45] -Pexp_apply ...[31:11->31:30] (~someVariant31:32->31:43=...[31:44->31:45]) -posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:44->31:45] -Pexp_construct T:[31:44->31:45] None -Completable: Cpath Value[T] +Completable: CtypedExpression(sourceType:NamedArg(someVariant, Value[someVariantToString]), lookingToComplete:CNoContext, prefix:"", pattern: [] [{ - "label": "TableclothMap", - "kind": 9, + "label": "One", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "One\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "One", + "insertTextFormat": 2 }, { - "label": "TypeContextCompletion_Jsx", - "kind": 9, + "label": "Two", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Two\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Two", + "insertTextFormat": 2 }, { - "label": "TypeContextCompletion_LabelledArguments", - "kind": 9, + "label": "Three", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Three\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Three", + "insertTextFormat": 2 }, { - "label": "TypeContextCompletion_Records", - "kind": 9, + "label": "Four", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Four\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Four", + "insertTextFormat": 2 + }, { + "label": "Five(_)", + "kind": 4, + "tags": [], + "detail": "Five(int)\n\n", + "documentation": null, + "sortText": null, + "insertText": "Five($1)", + "insertTextFormat": 2 }, { - "label": "TypeDefinition", - "kind": 9, + "label": "Six(_)", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Six(option, int)\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Six($1)", + "insertTextFormat": 2 + }] + +Complete src/TypeContextCompletion_LabelledArguments.res 31:45 +posCursor:[31:45] posNoWhite:[31:44] Found expr:[31:11->31:45] +Pexp_apply ...[31:11->31:30] (~someVariant31:32->31:43=...[31:44->31:45]) +Completable: CtypedExpression(sourceType:NamedArg(someVariant, Value[someVariantToString]), lookingToComplete:CVariant, prefix:T, pattern: [] +[{ + "label": "Two", + "kind": 4, + "tags": [], + "detail": "Two\n\n", + "documentation": null, + "sortText": null, + "insertText": "Two", + "insertTextFormat": 2 }, { - "label": "TypedContextCompletionSpec", - "kind": 9, + "label": "Three", + "kind": 4, "tags": [], - "detail": "file module", + "detail": "Three\n\n", "documentation": null, "sortText": null, - "insertText": null, - "insertTextFormat": null + "insertText": "Three", + "insertTextFormat": 2 }] Complete src/TypeContextCompletion_LabelledArguments.res 34:45 @@ -181,33 +253,248 @@ Completable: Cpath Value[TypeDefinition, ""] Complete src/TypeContextCompletion_LabelledArguments.res 40:45 posCursor:[40:45] posNoWhite:[40:44] Found expr:[40:11->40:45] Pexp_apply ...[40:11->40:30] (~anotherThing40:32->40:44=...__ghost__[0:-1->0:-1]) -[] +Completable: CtypedExpression(sourceType:NamedArg(anotherThing, Value[someVariantToString]), lookingToComplete:CNoContext, prefix:"", pattern: [] +[{ + "label": "Foo", + "kind": 4, + "tags": [], + "detail": "Foo\n\n", + "documentation": null, + "sortText": null, + "insertText": "Foo", + "insertTextFormat": 2 + }, { + "label": "Bar", + "kind": 4, + "tags": [], + "detail": "Bar\n\n", + "documentation": null, + "sortText": null, + "insertText": "Bar", + "insertTextFormat": 2 + }] Complete src/TypeContextCompletion_LabelledArguments.res 43:43 posCursor:[43:43] posNoWhite:[43:42] Found expr:[43:11->43:43] Pexp_apply ...[43:11->43:30] (~thirdThing43:32->43:42=...__ghost__[0:-1->0:-1]) -[] +Completable: CtypedExpression(sourceType:NamedArg(thirdThing, Value[someVariantToString]), lookingToComplete:CNoContext, prefix:"", pattern: [] +[{ + "label": "#one", + "kind": 4, + "tags": [], + "detail": "#one", + "documentation": null, + "sortText": null, + "insertText": "#one", + "insertTextFormat": 2 + }, { + "label": "#six(_)", + "kind": 4, + "tags": [], + "detail": "#six(option, int)", + "documentation": null, + "sortText": null, + "insertText": "#six($1)", + "insertTextFormat": 2 + }, { + "label": "#three", + "kind": 4, + "tags": [], + "detail": "#three", + "documentation": null, + "sortText": null, + "insertText": "#three", + "insertTextFormat": 2 + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two", + "documentation": null, + "sortText": null, + "insertText": "#two", + "insertTextFormat": 2 + }, { + "label": "#five(_)", + "kind": 4, + "tags": [], + "detail": "#five(int)", + "documentation": null, + "sortText": null, + "insertText": "#five($1)", + "insertTextFormat": 2 + }, { + "label": "#four", + "kind": 4, + "tags": [], + "detail": "#four", + "documentation": null, + "sortText": null, + "insertText": "#four", + "insertTextFormat": 2 + }] Complete src/TypeContextCompletion_LabelledArguments.res 46:44 posCursor:[46:44] posNoWhite:[46:42] Found expr:[46:11->46:43] Pexp_apply ...[46:11->46:30] (~thirdThing46:32->46:42=...__ghost__[0:-1->0:-1]) -[] +Completable: CtypedExpression(sourceType:NamedArg(thirdThing, Value[someVariantToString]), lookingToComplete:CNoContext, prefix:"", pattern: [] +[{ + "label": "#one", + "kind": 4, + "tags": [], + "detail": "#one", + "documentation": null, + "sortText": null, + "insertText": "#one", + "insertTextFormat": 2 + }, { + "label": "#six(_)", + "kind": 4, + "tags": [], + "detail": "#six(option, int)", + "documentation": null, + "sortText": null, + "insertText": "#six($1)", + "insertTextFormat": 2 + }, { + "label": "#three", + "kind": 4, + "tags": [], + "detail": "#three", + "documentation": null, + "sortText": null, + "insertText": "#three", + "insertTextFormat": 2 + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two", + "documentation": null, + "sortText": null, + "insertText": "#two", + "insertTextFormat": 2 + }, { + "label": "#five(_)", + "kind": 4, + "tags": [], + "detail": "#five(int)", + "documentation": null, + "sortText": null, + "insertText": "#five($1)", + "insertTextFormat": 2 + }, { + "label": "#four", + "kind": 4, + "tags": [], + "detail": "#four", + "documentation": null, + "sortText": null, + "insertText": "#four", + "insertTextFormat": 2 + }] Complete src/TypeContextCompletion_LabelledArguments.res 49:45 posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:11->49:45] Pexp_apply ...[49:11->49:30] (~thirdThing49:32->49:42=...[49:43->49:45]) -posCursor:[49:45] posNoWhite:[49:44] Found expr:[49:43->49:45] -[] +Completable: CtypedExpression(sourceType:NamedArg(thirdThing, Value[someVariantToString]), lookingToComplete:CPolyvariant, prefix:t, pattern: [] +[{ + "label": "#three", + "kind": 4, + "tags": [], + "detail": "#three", + "documentation": null, + "sortText": null, + "insertText": "#three", + "insertTextFormat": 2 + }, { + "label": "#two", + "kind": 4, + "tags": [], + "detail": "#two", + "documentation": null, + "sortText": null, + "insertText": "#two", + "insertTextFormat": 2 + }] Complete src/TypeContextCompletion_LabelledArguments.res 52:45 posCursor:[52:45] posNoWhite:[52:44] Found expr:[52:11->52:45] Pexp_apply ...[52:11->52:30] (~thirdThing52:32->52:42=...[52:43->52:45]) -posCursor:[52:45] posNoWhite:[52:44] Found expr:[52:43->52:45] +Completable: CtypedExpression(sourceType:NamedArg(thirdThing, Value[someVariantToString]), lookingToComplete:CPolyvariant, prefix:T, pattern: [] [] -Complete src/TypeContextCompletion_LabelledArguments.res 64:36 -posCursor:[64:36] posNoWhite:[64:35] Found pattern:[64:29->64:37] -posCursor:[64:36] posNoWhite:[64:35] Found pattern:[64:35->64:36] -Completable: CtypedPattern(sourceType:Value[doStuff](~doThing), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) +Complete src/TypeContextCompletion_LabelledArguments.res 75:36 +posCursor:[75:36] posNoWhite:[75:35] Found expr:[75:11->75:47] +Pexp_apply ...[75:11->75:18] (~doThing75:20->75:27=...[75:28->75:46]) +posCursor:[75:36] posNoWhite:[75:35] Found expr:[75:28->75:46] +posCursor:[75:36] posNoWhite:[75:35] Found pattern:[75:29->75:37] +posCursor:[75:36] posNoWhite:[75:35] Found pattern:[75:35->75:36] [] +Complete src/TypeContextCompletion_LabelledArguments.res 80:46 +posCursor:[80:46] posNoWhite:[80:45] Found expr:[80:3->80:49] +Pexp_apply ...[80:3->80:14] (~someRecord80:16->80:26=...[80:27->80:48]) +Completable: CtypedExpression(sourceType:NamedArg(someRecord, Value[doMoreStuff]), lookingToComplete:CVariant, prefix:O, pattern: [RecordField:someTup, Tuple:1] +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null, + "sortText": null, + "insertText": "One", + "insertTextFormat": 2 + }] + +Complete src/TypeContextCompletion_LabelledArguments.res 83:37 +posCursor:[83:37] posNoWhite:[83:36] Found expr:[83:12->83:39] +Pexp_apply ...[83:12->83:23] (~someRecord83:25->83:35=...[83:36->83:38]) +Completable: CtypedExpression(sourceType:NamedArg(someRecord, Value[doMoreStuff]), lookingToComplete:CRecordField, prefix:"", pattern: [] +[{ + "label": "age", + "kind": 5, + "tags": [], + "detail": "age: int\n\ntype someRecord = {\n age: int,\n name: string,\n maybeVariant: option,\n definitivelyVariant: someVariant,\n someTup: (string, someVariant),\n}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "name", + "kind": 5, + "tags": [], + "detail": "name: string\n\ntype someRecord = {\n age: int,\n name: string,\n maybeVariant: option,\n definitivelyVariant: someVariant,\n someTup: (string, someVariant),\n}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "maybeVariant", + "kind": 5, + "tags": [], + "detail": "maybeVariant: option\n\ntype someRecord = {\n age: int,\n name: string,\n maybeVariant: option,\n definitivelyVariant: someVariant,\n someTup: (string, someVariant),\n}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "definitivelyVariant", + "kind": 5, + "tags": [], + "detail": "definitivelyVariant: someVariant\n\ntype someRecord = {\n age: int,\n name: string,\n maybeVariant: option,\n definitivelyVariant: someVariant,\n someTup: (string, someVariant),\n}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "someTup", + "kind": 5, + "tags": [], + "detail": "someTup: (string, someVariant)\n\ntype someRecord = {\n age: int,\n name: string,\n maybeVariant: option,\n definitivelyVariant: someVariant,\n someTup: (string, someVariant),\n}", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] + diff --git a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt index 2bf9c24a9..2acac6acc 100644 --- a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt +++ b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt @@ -8,7 +8,7 @@ Source: value: Ppat_var(x) expr: - <*>Pexp_apply( +<*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -27,7 +27,7 @@ Source: value: Ppat_var(x) expr: - <*>Pexp_apply( +<*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -47,7 +47,7 @@ Source: value: Ppat_var(x) expr: - <*>Pexp_apply( +<*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -66,7 +66,7 @@ Source: value: Ppat_var(x) expr: - <*>Pexp_apply( +<*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -85,7 +85,7 @@ Source: value: Ppat_var(x) expr: - <*>Pexp_apply( +<*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -104,7 +104,7 @@ Source: value: Ppat_var(x) expr: - <*>Pexp_apply( +<*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -123,7 +123,7 @@ Source: value: Ppat_var(x) expr: - <*>Pexp_apply( +<*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -142,7 +142,7 @@ Source: value: Ppat_var(x) expr: - <*>Pexp_apply( +<*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -161,7 +161,7 @@ Source: value: Ppat_var(x) expr: - <*>Pexp_apply( +<*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -171,9 +171,11 @@ Source: ) Complete src/TypedContextCompletionSpec.res 93:36 +posCursor:[93:36] posNoWhite:[93:35] Found expr:[93:11->93:47] +Pexp_apply ...[93:11->93:18] (~doThing93:20->93:27=...[93:28->93:46]) +posCursor:[93:36] posNoWhite:[93:35] Found expr:[93:28->93:46] posCursor:[93:36] posNoWhite:[93:35] Found pattern:[93:29->93:37] posCursor:[93:36] posNoWhite:[93:35] Found pattern:[93:35->93:36] -Completable: CtypedPattern(sourceType:Value[doStuff](~doThing), lookingToComplete:CNoContext, patternType:Destructure, prefix:"", pattern: [], seenIdents: []) [] Complete src/TypedContextCompletionSpec.res 97:15 @@ -2700,12 +2702,11 @@ Source: Ppat_var(someVar) ) expr: - Pexp_extension(%rescript.exprhole) +Pexp_extension(%rescript.exprhole) ) Complete src/TypedContextCompletionSpec.res 256:30 XXX Not found! Completable: CtypedExpression(sourceType:Type[Completion, r], lookingToComplete:CNoContext, prefix:"", pattern: [] -no source type [] From 859c3fdc6d17cf7f8a0a6001b9ec729a20467055 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Wed, 17 Aug 2022 21:35:09 +0200 Subject: [PATCH 72/80] track seen record fields when constructing a record --- analysis/src/CompletionBackEnd.ml | 12 +++++++- analysis/src/CompletionFrontEnd.ml | 28 +++++++++++++------ analysis/src/SharedTypes.ml | 14 +++++++++- ...ypeContextCompletion_LabelledArguments.res | 4 +-- ...ontextCompletion_LabelledArguments.res.txt | 26 +++-------------- 5 files changed, 50 insertions(+), 34 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 5d15ca688..149b3fc40 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -2250,7 +2250,13 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i ~kind:(Completion.Label "Empty record") (); ])) | CtypedExpression - {howToRetrieveSourceType; expressionPath; lookingToComplete; prefix} -> ( + { + howToRetrieveSourceType; + expressionPath; + lookingToComplete; + prefix; + alreadySeenIdents; + } -> ( let sourceType = howToRetrieveSourceType |> findSourceType ~package ~opens ~rawOpens ~allFiles ~env ~pos ~scope @@ -2411,6 +2417,10 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i constructorCompletions | Some (CRecord {fields; decl; name}), CRecordField -> fields + |> List.filter (fun (field : field) -> + not + (alreadySeenIdents + |> List.exists (fun fieldName -> fieldName = field.fname.txt))) |> Utils.filterMap (fun (field : field) -> if prefix = "" || checkName field.fname.txt ~prefix ~exact:false then diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index a58aebc2a..f7f8ba05a 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -109,6 +109,7 @@ type findContextInExprRes = { lookingToComplete: Completable.lookingToComplete; expressionPath: Completable.patternPathItem list; prefix: string; + alreadySeenIdents: string list; } let rec findContextInExpr expr ~pos ~expressionPath ~debug @@ -125,6 +126,7 @@ let rec findContextInExpr expr ~pos ~expressionPath ~debug lookingToComplete = CRecordField; expressionPath = expressionPath |> List.rev; prefix = ""; + alreadySeenIdents = []; } (* This mmeans parser recovery has been made, which typically means the expr was an empty assignment of some sort. *) | Pexp_extension ({txt = "rescript.exprhole"}, _) -> @@ -133,6 +135,7 @@ let rec findContextInExpr expr ~pos ~expressionPath ~debug lookingToComplete = CNoContext; expressionPath = expressionPath |> List.rev; prefix = ""; + alreadySeenIdents = []; } (* Variants etc *) | Pexp_construct ({txt}, Some payload) @@ -186,6 +189,7 @@ let rec findContextInExpr expr ~pos ~expressionPath ~debug lookingToComplete = CVariant; expressionPath = expressionPath |> List.rev; prefix = getSimpleFieldName txt; + alreadySeenIdents = []; } | NoCursor -> None | EmptyLoc -> None) @@ -193,7 +197,13 @@ let rec findContextInExpr expr ~pos ~expressionPath ~debug (* Payload-less polyvariant *) match CursorPosition.classifyLoc expr.pexp_loc ~pos with | HasCursor -> - Some {lookingToComplete = CPolyvariant; expressionPath; prefix = label} + Some + { + lookingToComplete = CPolyvariant; + expressionPath; + prefix = label; + alreadySeenIdents = []; + } | NoCursor -> None | EmptyLoc -> None) | Pexp_construct @@ -214,6 +224,7 @@ let rec findContextInExpr expr ~pos ~expressionPath ~debug @ expressionPath |> List.rev; prefix = ""; + alreadySeenIdents = []; } | NoCursor -> None | EmptyLoc -> None) @@ -232,15 +243,11 @@ let rec findContextInExpr expr ~pos ~expressionPath ~debug @ expressionPath |> List.rev; prefix = ""; + alreadySeenIdents = []; } - | NoCursor -> None - | EmptyLoc -> None (* Records *)) - | Pexp_record ([], _) -> - (* No fields mean we're in an empty record body. We can complete for that. *) - Some {lookingToComplete = CRecordField; expressionPath; prefix = ""} + | NoCursor | EmptyLoc -> None) | Pexp_record (fields, _) -> ( - (* TODO: Restore for exprs *) - let _seenFields = + let seenFields = fields |> List.map (fun ({Location.txt}, _) -> getSimpleFieldName txt) in let fieldWithCursorExists = @@ -263,6 +270,7 @@ let rec findContextInExpr expr ~pos ~expressionPath ~debug lookingToComplete = CRecordField; expressionPath = expressionPath |> List.rev; prefix = getSimpleFieldName loc.txt; + alreadySeenIdents = seenFields; } | _ -> (* We can continue down into anything else *) @@ -303,6 +311,7 @@ let rec findContextInExpr expr ~pos ~expressionPath ~debug lookingToComplete = CRecordField; expressionPath = expressionPath |> List.rev; prefix = ""; + alreadySeenIdents = seenFields; } | completableFromField, _, _ -> completableFromField) | Pexp_tuple items -> ( @@ -791,6 +800,7 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor prefix = res.prefix; lookingToComplete = res.lookingToComplete; expressionPath = res.expressionPath; + alreadySeenIdents = res.alreadySeenIdents; howToRetrieveSourceType = NamedArg {label = labelled.name; contextPath}; })) @@ -803,6 +813,7 @@ let findNamedArgCompletable ~(args : arg list) ~endPos ~posBeforeCursor prefix = ""; lookingToComplete = CNoContext; expressionPath = []; + alreadySeenIdents = []; howToRetrieveSourceType = NamedArg {label = labelled.name; contextPath}; }) @@ -996,6 +1007,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = CtxPath (CPId (Utils.flattenLongIdent typIdentifier.txt, Type)); expressionPath = []; + alreadySeenIdents = []; lookingToComplete = CNoContext; prefix = ""; })) diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index c0b57f6e3..0bd94b464 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -592,6 +592,8 @@ module Completable = struct lookingToComplete: lookingToComplete; (* What the user has already started writing, if anything. *) prefix: string; + (* This is only really relevant for constructing records/objects in expressions. *) + alreadySeenIdents: string list; } let toString = function @@ -624,7 +626,13 @@ module Completable = struct ^ (patternPath |> patternContextPathToString) ^ ", seenIdents: " ^ list alreadySeenIdents ^ ")" | CtypedExpression - {howToRetrieveSourceType; prefix; expressionPath; lookingToComplete} -> + { + howToRetrieveSourceType; + prefix; + expressionPath; + lookingToComplete; + alreadySeenIdents; + } -> ("CtypedExpression(sourceType:" ^ (howToRetrieveSourceType |> howToRetrieveSourceTypeToString) ^ ", lookingToComplete:" @@ -632,6 +640,10 @@ module Completable = struct ^ ", prefix:" ^ str prefix) ^ ", pattern: " ^ (expressionPath |> patternContextPathToString) + ^ + if List.length alreadySeenIdents > 0 then + ", seenIdents: " ^ list alreadySeenIdents ^ ")" + else "" end module CursorPosition = struct diff --git a/analysis/tests/src/TypeContextCompletion_LabelledArguments.res b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res index 8f4377b42..e8074abe1 100644 --- a/analysis/tests/src/TypeContextCompletion_LabelledArguments.res +++ b/analysis/tests/src/TypeContextCompletion_LabelledArguments.res @@ -81,5 +81,5 @@ let doMoreStuff = (~someRecord: someRecord): someRecord => someRecord // doMoreStuff(~someRecord={someTup: ("123", O)}) // ^com -// let _ = doMoreStuff(~someRecord={}) -// ^com +// let _ = doMoreStuff(~someRecord={age: 123, name: "123", }) +// ^com diff --git a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt index bb144908c..379129b68 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_LabelledArguments.res.txt @@ -447,29 +447,11 @@ Completable: CtypedExpression(sourceType:NamedArg(someRecord, Value[doMoreStuff] "insertTextFormat": 2 }] -Complete src/TypeContextCompletion_LabelledArguments.res 83:37 -posCursor:[83:37] posNoWhite:[83:36] Found expr:[83:12->83:39] -Pexp_apply ...[83:12->83:23] (~someRecord83:25->83:35=...[83:36->83:38]) -Completable: CtypedExpression(sourceType:NamedArg(someRecord, Value[doMoreStuff]), lookingToComplete:CRecordField, prefix:"", pattern: [] +Complete src/TypeContextCompletion_LabelledArguments.res 83:60 +posCursor:[83:60] posNoWhite:[83:58] Found expr:[83:12->83:62] +Pexp_apply ...[83:12->83:23] (~someRecord83:25->83:35=...[83:36->83:61]) +Completable: CtypedExpression(sourceType:NamedArg(someRecord, Value[doMoreStuff]), lookingToComplete:CRecordField, prefix:"", pattern: [], seenIdents: [age, name]) [{ - "label": "age", - "kind": 5, - "tags": [], - "detail": "age: int\n\ntype someRecord = {\n age: int,\n name: string,\n maybeVariant: option,\n definitivelyVariant: someVariant,\n someTup: (string, someVariant),\n}", - "documentation": null, - "sortText": null, - "insertText": null, - "insertTextFormat": null - }, { - "label": "name", - "kind": 5, - "tags": [], - "detail": "name: string\n\ntype someRecord = {\n age: int,\n name: string,\n maybeVariant: option,\n definitivelyVariant: someVariant,\n someTup: (string, someVariant),\n}", - "documentation": null, - "sortText": null, - "insertText": null, - "insertTextFormat": null - }, { "label": "maybeVariant", "kind": 5, "tags": [], From e67f63cc52362f7a3c48076783f969e2b0f7e912 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 18 Aug 2022 18:11:21 +0200 Subject: [PATCH 73/80] add a few test fixtures where the parser doesnt do quite what I need it to --- analysis/src/DumpAst.ml | 5 +- analysis/tests/src/BrokenParserCases.res | 12 ++++ .../src/expected/BrokenParserCases.res.txt | 62 +++++++++++++++++++ analysis/tests/src/expected/Debug.res.txt | 3 +- .../TypedContextCompletionSpec.res.txt | 29 ++++++--- 5 files changed, 99 insertions(+), 12 deletions(-) create mode 100644 analysis/tests/src/BrokenParserCases.res create mode 100644 analysis/tests/src/expected/BrokenParserCases.res.txt diff --git a/analysis/src/DumpAst.ml b/analysis/src/DumpAst.ml index 3a67ceb3e..1ed85cd82 100644 --- a/analysis/src/DumpAst.ml +++ b/analysis/src/DumpAst.ml @@ -145,6 +145,7 @@ and printCase case ~pos ~indentation ~caseNum = ^ "expr" ^ (case.Parsetree.pc_rhs.pexp_loc |> printLocDenominator ~pos) ^ ":\n" + ^ addIndentation (indentation + 2) ^ printExprItem case.pc_rhs ~pos ~indentation:(indentation + 2) and printExprItem expr ~pos ~indentation = @@ -214,12 +215,13 @@ and printExprItem expr ~pos ~indentation = | Labelled name -> "Labelled(" ^ name ^ ")" | Optional name -> "Optional(" ^ name ^ ")") ^ ",\n" - ^ addIndentation (indentation + 1) + ^ addIndentation (indentation + 2) ^ "pattern: " ^ printPattern pattern ~pos ~indentation:(indentation + 2) ^ ",\n" ^ addIndentation (indentation + 1) ^ "next expr:\n" + ^ addIndentation (indentation + 2) ^ printExprItem nextExpr ~pos ~indentation:(indentation + 2) ^ "\n" ^ addIndentation indentation ^ ")" | Pexp_extension (({txt} as loc), _) -> @@ -261,6 +263,7 @@ let printValueBinding value ~pos ~indentation = ^ addIndentation (indentation + 1) ^ (value.pvb_pat |> printPattern ~pos ~indentation:(indentation + 1)) ^ "\n" ^ addIndentation indentation ^ "expr:\n" + ^ addIndentation (indentation + 1) ^ printExprItem value.pvb_expr ~pos ~indentation:(indentation + 1) let printStructItem structItem ~pos ~source = diff --git a/analysis/tests/src/BrokenParserCases.res b/analysis/tests/src/BrokenParserCases.res new file mode 100644 index 000000000..701f81c49 --- /dev/null +++ b/analysis/tests/src/BrokenParserCases.res @@ -0,0 +1,12 @@ +// I would want this to recover to {someProp: %rescript.exprhole, ...}, but it currently eats the tuple + parses to {someProp: otherProp} +// let _ = ({someProp: , otherProp: 123}, 123) +// ^ast + +// Same problem here, does not recover from the missing prop, and ends up eating the rest of the record declaration while only parsing {firstProp: secondProp} +// let _ = someFunc({firstProp: , secondProp: 123, thirdProp: 123}) +// ^ast + +// I'd like the commas to be parsed as (broken) tuple "members" too. There's currently no robust way to derive _where_ in that tuple the cursor is, or even how many members the tuple has, because there's no pos match, and the empty comma item is just discarded. +// switch v { | (_, , _) => () } +// ^ast + diff --git a/analysis/tests/src/expected/BrokenParserCases.res.txt b/analysis/tests/src/expected/BrokenParserCases.res.txt new file mode 100644 index 000000000..1d4c2a883 --- /dev/null +++ b/analysis/tests/src/expected/BrokenParserCases.res.txt @@ -0,0 +1,62 @@ +Dump AST src/BrokenParserCases.res 1:22 + +Source: +// let _ = ({someProp: , otherProp: 123}, 123) +// ^ast + +<*>Pstr_value( + value: + Ppat_any + expr: + <*>Pexp_record( + fields: + someProp: Pexp_ident:otherProp + ) +) + +Dump AST src/BrokenParserCases.res 5:31 + +Source: +// let _ = someFunc({firstProp: , secondProp: 123, thirdProp: 123}) +// ^ast + +<*>Pstr_value( + value: + Ppat_any + expr: + <*>Pexp_apply( + expr: + Pexp_ident:someFunc + args: + = + <*>Pexp_record( + fields: + firstProp: Pexp_ident:secondProp + ), + = + Pexp_constant(Pconst_integer(123)), + = + , + = + Pexp_constant(Pconst_integer(123)) + ) +) + +Dump AST src/BrokenParserCases.res 9:19 + +Source: +// switch v { | (_, , _) => () } +// ^ast + +<*>Pstr_eval( +<*>Pexp_match(Pexp_ident:v) + case 1: + pattern<*>: + <*>Ppat_tuple( + Ppat_any, + Ppat_any + ) + expr: + Pexp_construct(()) +) + diff --git a/analysis/tests/src/expected/Debug.res.txt b/analysis/tests/src/expected/Debug.res.txt index cea26e4a0..492bb7311 100644 --- a/analysis/tests/src/expected/Debug.res.txt +++ b/analysis/tests/src/expected/Debug.res.txt @@ -4,8 +4,9 @@ Dependencies: @rescript/react Source directories: ./node_modules/@rescript/react/src ./node_modules/@rescript/react/src/legacy Source files: ./node_modules/@rescript/react/src/React.res ./node_modules/@rescript/react/src/ReactDOM.res ./node_modules/@rescript/react/src/ReactDOMServer.res ./node_modules/@rescript/react/src/ReactDOMStyle.res ./node_modules/@rescript/react/src/ReactEvent.res ./node_modules/@rescript/react/src/ReactEvent.resi ./node_modules/@rescript/react/src/ReactTestUtils.res ./node_modules/@rescript/react/src/ReactTestUtils.resi ./node_modules/@rescript/react/src/RescriptReactErrorBoundary.res ./node_modules/@rescript/react/src/RescriptReactErrorBoundary.resi ./node_modules/@rescript/react/src/RescriptReactRouter.res ./node_modules/@rescript/react/src/RescriptReactRouter.resi ./node_modules/@rescript/react/src/legacy/ReactDOMRe.res ./node_modules/@rescript/react/src/legacy/ReasonReact.res Source directories: ./src ./src/expected -Source files: ./src/Auto.res ./src/CodeLens.res ./src/CompletePrioritize1.res ./src/CompletePrioritize2.res ./src/Completion.res ./src/Component.res ./src/Component.resi ./src/CreateInterface.res ./src/Cross.res ./src/Dce.res ./src/Debug.res ./src/Definition.res ./src/DefinitionWithInterface.res ./src/DefinitionWithInterface.resi ./src/Div.res ./src/DocumentSymbol.res ./src/Fragment.res ./src/Highlight.res ./src/Hover.res ./src/InlayHint.res ./src/Jsx.res ./src/Jsx.resi ./src/LongIdentTest.res ./src/Object.res ./src/Patterns.res ./src/RecModules.res ./src/RecordCompletion.res ./src/RecoveryOnProp.res ./src/References.res ./src/ReferencesWithInterface.res ./src/ReferencesWithInterface.resi ./src/Rename.res ./src/RenameWithInterface.res ./src/RenameWithInterface.resi ./src/TableclothMap.ml ./src/TableclothMap.mli ./src/TypeContextCompletion_Jsx.res ./src/TypeContextCompletion_LabelledArguments.res ./src/TypeContextCompletion_Records.res ./src/TypeDefinition.res ./src/TypedContextCompletionSpec.res ./src/Xform.res +Source files: ./src/Auto.res ./src/BrokenParserCases.res ./src/CodeLens.res ./src/CompletePrioritize1.res ./src/CompletePrioritize2.res ./src/Completion.res ./src/Component.res ./src/Component.resi ./src/CreateInterface.res ./src/Cross.res ./src/Dce.res ./src/Debug.res ./src/Definition.res ./src/DefinitionWithInterface.res ./src/DefinitionWithInterface.resi ./src/Div.res ./src/DocumentSymbol.res ./src/Fragment.res ./src/Highlight.res ./src/Hover.res ./src/InlayHint.res ./src/Jsx.res ./src/Jsx.resi ./src/LongIdentTest.res ./src/Object.res ./src/Patterns.res ./src/RecModules.res ./src/RecordCompletion.res ./src/RecoveryOnProp.res ./src/References.res ./src/ReferencesWithInterface.res ./src/ReferencesWithInterface.resi ./src/Rename.res ./src/RenameWithInterface.res ./src/RenameWithInterface.resi ./src/TableclothMap.ml ./src/TableclothMap.mli ./src/TypeContextCompletion_Jsx.res ./src/TypeContextCompletion_LabelledArguments.res ./src/TypeContextCompletion_Records.res ./src/TypeDefinition.res ./src/TypedContextCompletionSpec.res ./src/Xform.res Impl cmt:./lib/bs/src/Auto.cmt res:./src/Auto.res +Impl cmt:./lib/bs/src/BrokenParserCases.cmt res:./src/BrokenParserCases.res Impl cmt:./lib/bs/src/CodeLens.cmt res:./src/CodeLens.res Impl cmt:./lib/bs/src/CompletePrioritize1.cmt res:./src/CompletePrioritize1.res Impl cmt:./lib/bs/src/CompletePrioritize2.cmt res:./src/CompletePrioritize2.res diff --git a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt index 2acac6acc..ae007840b 100644 --- a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt +++ b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt @@ -8,7 +8,7 @@ Source: value: Ppat_var(x) expr: -<*>Pexp_apply( + <*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -27,7 +27,7 @@ Source: value: Ppat_var(x) expr: -<*>Pexp_apply( + <*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -47,7 +47,7 @@ Source: value: Ppat_var(x) expr: -<*>Pexp_apply( + <*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -66,7 +66,7 @@ Source: value: Ppat_var(x) expr: -<*>Pexp_apply( + <*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -85,7 +85,7 @@ Source: value: Ppat_var(x) expr: -<*>Pexp_apply( + <*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -104,7 +104,7 @@ Source: value: Ppat_var(x) expr: -<*>Pexp_apply( + <*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -123,7 +123,7 @@ Source: value: Ppat_var(x) expr: -<*>Pexp_apply( + <*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -142,7 +142,7 @@ Source: value: Ppat_var(x) expr: -<*>Pexp_apply( + <*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -161,7 +161,7 @@ Source: value: Ppat_var(x) expr: -<*>Pexp_apply( + <*>Pexp_apply( expr: Pexp_ident:someVariantToString args: @@ -1391,6 +1391,15 @@ Completable: Cpath Value[""] "sortText": null, "insertText": null, "insertTextFormat": null + }, { + "label": "BrokenParserCases", + "kind": 9, + "tags": [], + "detail": "file module", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null }, { "label": "Buffer", "kind": 9, @@ -2702,7 +2711,7 @@ Source: Ppat_var(someVar) ) expr: -Pexp_extension(%rescript.exprhole) + Pexp_extension(%rescript.exprhole) ) Complete src/TypedContextCompletionSpec.res 256:30 From 64f4f77c0dd36b6cdc4e5a4967a9ebf6bc534b44 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sat, 20 Aug 2022 09:27:24 +0200 Subject: [PATCH 74/80] another broken case --- analysis/tests/src/BrokenParserCases.res | 4 ++++ .../src/expected/BrokenParserCases.res.txt | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/analysis/tests/src/BrokenParserCases.res b/analysis/tests/src/BrokenParserCases.res index 701f81c49..0e5c9495c 100644 --- a/analysis/tests/src/BrokenParserCases.res +++ b/analysis/tests/src/BrokenParserCases.res @@ -10,3 +10,7 @@ // switch v { | (_, , _) => () } // ^ast +// Same problem here, does not recover from the missing prop, and ends up eating the rest of the record declaration while only parsing {firstProp: secondProp} +// let {someField, , otherField, } = someVal +// ^ast + diff --git a/analysis/tests/src/expected/BrokenParserCases.res.txt b/analysis/tests/src/expected/BrokenParserCases.res.txt index 1d4c2a883..e8c6e2e37 100644 --- a/analysis/tests/src/expected/BrokenParserCases.res.txt +++ b/analysis/tests/src/expected/BrokenParserCases.res.txt @@ -60,3 +60,20 @@ Source: Pexp_construct(()) ) +Dump AST src/BrokenParserCases.res 13:18 + +Source: +// let {someField, , otherField, } = someVal +// ^ast + +<*>Pstr_value( + value: + <*>Ppat_record( + fields: + someField: Ppat_var(someField) + otherField: Ppat_var(otherField) + ) + expr: + Pexp_ident:someVal +) + From 40e3ec1df7d17aefa6e2d98a18c07eb67ae50a6e Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sat, 20 Aug 2022 09:29:10 +0200 Subject: [PATCH 75/80] support completing expressions when assigning variables, even if the expression strictly does not compile (but the compiler understands what type it will be eventually --- analysis/src/CompletionFrontEnd.ml | 178 ++++++++++++++++------------- 1 file changed, 101 insertions(+), 77 deletions(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index f7f8ba05a..39a387ff0 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -965,87 +965,111 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | Pstr_open {popen_lid} -> scope := !scope |> Scope.addOpen ~lid:popen_lid.txt | Pstr_primitive vd -> scopeValueDescription vd - | Pstr_value (recFlag, bindings) -> + | Pstr_value (recFlag, bindings) -> ( if recFlag = Recursive then bindings |> List.iter scopeValueBinding; + bindings |> List.iter (fun vb -> iterator.value_binding iterator vb); + if recFlag = Nonrecursive then bindings |> List.iter scopeValueBinding; + processed := true; - (if - !result = None - && item.pstr_loc - |> CursorPosition.classifyLoc ~pos:posBeforeCursor - = HasCursor + if + !result = None + && item.pstr_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + = HasCursor then - match bindings with - (* TODO: This is currently broken, as we need to support using a type_decl, which is what a type annotation gives us, - to look up types (currently only support type_expr). *) - (* E.g let expr: someType = ... *) - | [ - { - pvb_pat = - { - ppat_loc; - ppat_desc = - Ppat_constraint - (_, {ptyp_desc = Ptyp_constr (typIdentifier, [])}); - }; - pvb_expr = expr; - }; - ] -> ( - match expr with - (* E.g let expr: someType = - Produces a "broken" source *) - | { - pexp_desc = Pexp_extension ({Location.txt = "rescript.exprhole"}, _); - } - when ppat_loc - |> CursorPosition.classifyLoc ~pos:posBeforeCursor - = NoCursor -> - setResultOpt - (Some - (Completable.CtypedExpression - { - howToRetrieveSourceType = - CtxPath - (CPId (Utils.flattenLongIdent typIdentifier.txt, Type)); - expressionPath = []; - alreadySeenIdents = []; - lookingToComplete = CNoContext; - prefix = ""; - })) - | _ -> ()) - | [{pvb_pat; pvb_expr = expr}] - when pvb_pat.ppat_loc - |> CursorPosition.classifyLoc ~pos:posBeforeCursor - = HasCursor -> ( - (* Check for: let {destructuringSomething} = someIdentifier *) - (* TODO: Handle let {SomeModule.recordField} = ...*) + match bindings with + (* TODO: This is currently broken, as we need to support using a type_decl, which is what a type annotation gives us, + to look up types (currently only support type_expr). *) + (* E.g let expr: someType = ... *) + | [ + { + pvb_pat = + { + ppat_loc; + ppat_desc = + Ppat_constraint + (_, {ptyp_desc = Ptyp_constr (typIdentifier, [])}); + }; + pvb_expr = expr; + }; + ] -> ( + match expr with + (* E.g let expr: someType = + Produces a "broken" source *) + | { + pexp_desc = Pexp_extension ({Location.txt = "rescript.exprhole"}, _); + } + when ppat_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + = NoCursor -> + setResultOpt + (Some + (Completable.CtypedExpression + { + howToRetrieveSourceType = + CtxPath + (CPId (Utils.flattenLongIdent typIdentifier.txt, Type)); + expressionPath = []; + alreadySeenIdents = []; + lookingToComplete = CNoContext; + prefix = ""; + })) + | _ -> ()) + | [{pvb_pat = {ppat_desc = Ppat_var loc}; pvb_expr = expr}] + when expr.pexp_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + = HasCursor -> ( + (* E.g `let something = {someVal: 123}` + This handles the case when the assignment of `something` might not be complete (missing record fields for example), + but where even if compilation has failed the compiler might know enough about the value of `something` to use it + for expression based completion. *) + match + findContextInExpr expr ~firstCharBeforeCursorNoWhite + ~pos:posBeforeCursor ~expressionPath:[] ~debug + with + | None -> () + | Some res -> + setResultOpt + (Some + (Completable.CtypedExpression + { + howToRetrieveSourceType = CtxPath (CPId ([loc.txt], Value)); + expressionPath = res.expressionPath; + lookingToComplete = res.lookingToComplete; + prefix = res.prefix; + alreadySeenIdents = res.alreadySeenIdents; + }))) + | [{pvb_pat; pvb_expr = expr}] + when pvb_pat.ppat_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + = HasCursor -> ( + (* Check for: let {destructuringSomething} = someIdentifier *) + (* TODO: Handle let {SomeModule.recordField} = ...*) - (* The contextPath is what we'll use to look up the root record type for this completion. - Depending on if the destructure is nested or not, we may or may not use that directly.*) - match exprToContextPath expr with - | None -> () - | Some contextPath -> ( - match - findContextInPattern pvb_pat ~firstCharBeforeCursorNoWhite - ~pos:posBeforeCursor ~patternPath:[] ~seenIdentsFromParent:[] - ~debug - with - | None -> () - | Some res -> - setResultOpt - (Some - (Completable.CtypedPattern - { - howToRetrieveSourceType = CtxPath contextPath; - patternPath = res.patternPath; - patternType = Destructure; - lookingToComplete = res.lookingToComplete; - prefix = res.prefix; - alreadySeenIdents = res.alreadySeenIdents; - })))) - | _ -> ()); - bindings |> List.iter (fun vb -> iterator.value_binding iterator vb); - if recFlag = Nonrecursive then bindings |> List.iter scopeValueBinding; - processed := true + (* The contextPath is what we'll use to look up the root record type for this completion. + Depending on if the destructure is nested or not, we may or may not use that directly.*) + match exprToContextPath expr with + | None -> () + | Some contextPath -> ( + match + findContextInPattern pvb_pat ~firstCharBeforeCursorNoWhite + ~pos:posBeforeCursor ~patternPath:[] ~seenIdentsFromParent:[] + ~debug + with + | None -> () + | Some res -> + setResultOpt + (Some + (Completable.CtypedPattern + { + howToRetrieveSourceType = CtxPath contextPath; + patternPath = res.patternPath; + patternType = Destructure; + lookingToComplete = res.lookingToComplete; + prefix = res.prefix; + alreadySeenIdents = res.alreadySeenIdents; + })))) + | _ -> ()) | Pstr_type (recFlag, decls) -> if recFlag = Recursive then decls |> List.iter scopeTypeDeclaration; decls |> List.iter (fun td -> iterator.type_declaration iterator td); From e330b68600c40fdeb77f6ad8f98251191ede3adb Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sat, 20 Aug 2022 12:07:48 +0200 Subject: [PATCH 76/80] pull put var from constraint pattern for now --- analysis/src/CompletionFrontEnd.ml | 66 +++++++++++-------- .../tests/src/TypedContextCompletionSpec.res | 6 +- .../TypedContextCompletionSpec.res.txt | 23 ++----- 3 files changed, 48 insertions(+), 47 deletions(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 39a387ff0..ed0c5213e 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -985,37 +985,15 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = { pvb_pat = { - ppat_loc; ppat_desc = - Ppat_constraint - (_, {ptyp_desc = Ptyp_constr (typIdentifier, [])}); + ( Ppat_var loc + (* Handles the `let someVar: someType = ...` case until we've refactored so we can do proper completion via + the type annotation. *) + | Ppat_constraint ({ppat_desc = Ppat_var loc}, _) ); }; pvb_expr = expr; }; - ] -> ( - match expr with - (* E.g let expr: someType = - Produces a "broken" source *) - | { - pexp_desc = Pexp_extension ({Location.txt = "rescript.exprhole"}, _); - } - when ppat_loc - |> CursorPosition.classifyLoc ~pos:posBeforeCursor - = NoCursor -> - setResultOpt - (Some - (Completable.CtypedExpression - { - howToRetrieveSourceType = - CtxPath - (CPId (Utils.flattenLongIdent typIdentifier.txt, Type)); - expressionPath = []; - alreadySeenIdents = []; - lookingToComplete = CNoContext; - prefix = ""; - })) - | _ -> ()) - | [{pvb_pat = {ppat_desc = Ppat_var loc}; pvb_expr = expr}] + ] when expr.pexp_loc |> CursorPosition.classifyLoc ~pos:posBeforeCursor = HasCursor -> ( @@ -1069,6 +1047,40 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = prefix = res.prefix; alreadySeenIdents = res.alreadySeenIdents; })))) + | [ + { + pvb_pat = + { + ppat_loc; + ppat_desc = + Ppat_constraint + (_, {ptyp_desc = Ptyp_constr (typIdentifier, [])}); + }; + pvb_expr = expr; + }; + ] -> ( + match expr with + (* E.g let expr: someType = + Produces a "broken" source *) + | { + pexp_desc = Pexp_extension ({Location.txt = "rescript.exprhole"}, _); + } + when ppat_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + = NoCursor -> + setResultOpt + (Some + (Completable.CtypedExpression + { + howToRetrieveSourceType = + CtxPath + (CPId (Utils.flattenLongIdent typIdentifier.txt, Type)); + expressionPath = []; + alreadySeenIdents = []; + lookingToComplete = CNoContext; + prefix = ""; + })) + | _ -> ()) | _ -> ()) | Pstr_type (recFlag, decls) -> if recFlag = Recursive then decls |> List.iter scopeTypeDeclaration; diff --git a/analysis/tests/src/TypedContextCompletionSpec.res b/analysis/tests/src/TypedContextCompletionSpec.res index a70d9e6e2..fa26ed995 100644 --- a/analysis/tests/src/TypedContextCompletionSpec.res +++ b/analysis/tests/src/TypedContextCompletionSpec.res @@ -251,8 +251,8 @@ let y = One // --- Pattern matching end --- -// let someVar: Completion.r = -// ^ast - // let someVar: Completion.r = // ^com + +// let x: user = {age: 123, } +// ^com diff --git a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt index ae007840b..5561ec4ed 100644 --- a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt +++ b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt @@ -2698,24 +2698,13 @@ Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:C "insertTextFormat": 2 }] -Dump AST src/TypedContextCompletionSpec.res 253:29 - -Source: -// let someVar: Completion.r = -// ^ast - -<*>Pstr_value( - value: - Ppat_constraint( - Ptyp_constr(Completion.r), - Ppat_var(someVar) - ) - expr: - Pexp_extension(%rescript.exprhole) -) - -Complete src/TypedContextCompletionSpec.res 256:30 +Complete src/TypedContextCompletionSpec.res 253:30 XXX Not found! Completable: CtypedExpression(sourceType:Type[Completion, r], lookingToComplete:CNoContext, prefix:"", pattern: [] [] +Complete src/TypedContextCompletionSpec.res 256:27 +posCursor:[256:27] posNoWhite:[256:26] Found expr:[256:17->256:29] +Completable: CtypedExpression(sourceType:Value[x], lookingToComplete:CRecordField, prefix:"", pattern: [], seenIdents: [age]) +[] + From fc48ca8f31a30b8ce4c7c30a7879109555f8f2ca Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sat, 20 Aug 2022 21:03:33 +0200 Subject: [PATCH 77/80] more cases --- analysis/src/CompletionFrontEnd.ml | 185 ++++++++++-------- .../tests/src/expected/Completion.res.txt | 2 +- 2 files changed, 106 insertions(+), 81 deletions(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index ed0c5213e..59c08098f 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -112,14 +112,16 @@ type findContextInExprRes = { alreadySeenIdents: string list; } +let hasBraces attributes = + attributes |> List.exists (fun (loc, _) -> loc.Location.txt = "ns.braces") + let rec findContextInExpr expr ~pos ~expressionPath ~debug ~firstCharBeforeCursorNoWhite = match expr.Parsetree.pexp_desc with (* In expressions, there's ambiguity between an empty record and an empty expression block. There's simply no way to express a record with 0 fields, like there is in patterns. The heuristic below matches `{}` and interprets it as an empty record rather than an expression block with braces + unit, which is what the parser parses it as. *) | Pexp_construct ({txt = Lident "()"}, None) - when expr.Parsetree.pexp_attributes - |> List.exists (fun (loc, _) -> loc.Location.txt = "ns.braces") + when hasBraces expr.Parsetree.pexp_attributes && CursorPosition.classifyLoc expr.pexp_loc ~pos = HasCursor -> Some { @@ -128,7 +130,33 @@ let rec findContextInExpr expr ~pos ~expressionPath ~debug prefix = ""; alreadySeenIdents = []; } - (* This mmeans parser recovery has been made, which typically means the expr was an empty assignment of some sort. *) + (* Handles `Some({})`, with the same logic as above for handling the empty record ambiguity. *) + | Pexp_construct + ( {txt}, + Some + { + pexp_loc; + pexp_attributes; + pexp_desc = Pexp_construct ({txt = Lident "()"}, _); + } ) + when hasBraces pexp_attributes -> ( + match CursorPosition.classifyLoc pexp_loc ~pos with + | HasCursor -> + Some + { + lookingToComplete = CRecordField; + expressionPath = + [ + Completable.Variant + {constructorName = getSimpleFieldName txt; payloadNum = Some 0}; + ] + @ expressionPath + |> List.rev; + prefix = ""; + alreadySeenIdents = []; + } + | NoCursor | EmptyLoc -> None) + (* This mmeans parser recovery has been made, which typically means the expr was an empty assignment of some sort. *) | Pexp_extension ({txt = "rescript.exprhole"}, _) -> Some { @@ -138,6 +166,45 @@ let rec findContextInExpr expr ~pos ~expressionPath ~debug alreadySeenIdents = []; } (* Variants etc *) + | Pexp_construct + ( {txt}, + Some {pexp_loc; pexp_desc = Pexp_construct ({txt = Lident "()"}, _)} ) + -> ( + (* A variant like SomeVariant(). Interpret as completing the payload of the variant *) + match CursorPosition.classifyLoc pexp_loc ~pos with + | HasCursor -> + Some + { + lookingToComplete = CNoContext; + expressionPath = + [ + Completable.Variant + {constructorName = getSimpleFieldName txt; payloadNum = Some 0}; + ] + @ expressionPath + |> List.rev; + prefix = ""; + alreadySeenIdents = []; + } + | NoCursor | EmptyLoc -> None) + | Pexp_variant + ( label, + Some {pexp_loc; pexp_desc = Pexp_construct ({txt = Lident "()"}, _)} ) + -> ( + (* A polyvariant like #SomeVariant(). Interpret as completing the payload of the variant *) + match CursorPosition.classifyLoc pexp_loc ~pos with + | HasCursor -> + Some + { + lookingToComplete = CNoContext; + expressionPath = + [Completable.Polyvariant {name = label; payloadNum = Some 0}] + @ expressionPath + |> List.rev; + prefix = ""; + alreadySeenIdents = []; + } + | NoCursor | EmptyLoc -> None) | Pexp_construct ({txt}, Some payload) when CursorPosition.classifyLoc payload.pexp_loc ~pos = HasCursor -> (* When there's a variant with a payload, and the cursor is in the pattern. Some(S) for example. *) @@ -206,46 +273,6 @@ let rec findContextInExpr expr ~pos ~expressionPath ~debug } | NoCursor -> None | EmptyLoc -> None) - | Pexp_construct - ( {txt}, - Some {pexp_loc; pexp_desc = Pexp_construct ({txt = Lident "()"}, _)} ) - -> ( - (* A variant like SomeVariant(). Interpret as completing the payload of the variant *) - match CursorPosition.classifyLoc pexp_loc ~pos with - | HasCursor -> - Some - { - lookingToComplete = CNoContext; - expressionPath = - [ - Completable.Variant - {constructorName = getSimpleFieldName txt; payloadNum = Some 0}; - ] - @ expressionPath - |> List.rev; - prefix = ""; - alreadySeenIdents = []; - } - | NoCursor -> None - | EmptyLoc -> None) - | Pexp_variant - ( label, - Some {pexp_loc; pexp_desc = Pexp_construct ({txt = Lident "()"}, _)} ) - -> ( - (* A polyvariant like #SomeVariant(). Interpret as completing the payload of the variant *) - match CursorPosition.classifyLoc pexp_loc ~pos with - | HasCursor -> - Some - { - lookingToComplete = CNoContext; - expressionPath = - [Completable.Polyvariant {name = label; payloadNum = Some 0}] - @ expressionPath - |> List.rev; - prefix = ""; - alreadySeenIdents = []; - } - | NoCursor | EmptyLoc -> None) | Pexp_record (fields, _) -> ( let seenFields = fields |> List.map (fun ({Location.txt}, _) -> getSimpleFieldName txt) @@ -883,6 +910,8 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = | Some x -> result := Some (x, !scope) in let setResult x = setResultOpt (Some x) in + (* `setResultForced` is mostly an experiment as I figure things out *) + let setResultForced x = result := Some (x, !scope) in let scopeValueDescription (vd : Parsetree.value_description) = scope := !scope |> Scope.addValue ~name:vd.pval_name.txt ~loc:vd.pval_name.loc @@ -972,10 +1001,9 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = processed := true; if - !result = None - && item.pstr_loc - |> CursorPosition.classifyLoc ~pos:posBeforeCursor - = HasCursor + item.pstr_loc + |> CursorPosition.classifyLoc ~pos:posBeforeCursor + = HasCursor then match bindings with (* TODO: This is currently broken, as we need to support using a type_decl, which is what a type annotation gives us, @@ -1007,16 +1035,15 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = with | None -> () | Some res -> - setResultOpt - (Some - (Completable.CtypedExpression - { - howToRetrieveSourceType = CtxPath (CPId ([loc.txt], Value)); - expressionPath = res.expressionPath; - lookingToComplete = res.lookingToComplete; - prefix = res.prefix; - alreadySeenIdents = res.alreadySeenIdents; - }))) + setResultForced + (Completable.CtypedExpression + { + howToRetrieveSourceType = CtxPath (CPId ([loc.txt], Value)); + expressionPath = res.expressionPath; + lookingToComplete = res.lookingToComplete; + prefix = res.prefix; + alreadySeenIdents = res.alreadySeenIdents; + })) | [{pvb_pat; pvb_expr = expr}] when pvb_pat.ppat_loc |> CursorPosition.classifyLoc ~pos:posBeforeCursor @@ -1036,17 +1063,16 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = with | None -> () | Some res -> - setResultOpt - (Some - (Completable.CtypedPattern - { - howToRetrieveSourceType = CtxPath contextPath; - patternPath = res.patternPath; - patternType = Destructure; - lookingToComplete = res.lookingToComplete; - prefix = res.prefix; - alreadySeenIdents = res.alreadySeenIdents; - })))) + setResultForced + (Completable.CtypedPattern + { + howToRetrieveSourceType = CtxPath contextPath; + patternPath = res.patternPath; + patternType = Destructure; + lookingToComplete = res.lookingToComplete; + prefix = res.prefix; + alreadySeenIdents = res.alreadySeenIdents; + }))) | [ { pvb_pat = @@ -1068,18 +1094,17 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = when ppat_loc |> CursorPosition.classifyLoc ~pos:posBeforeCursor = NoCursor -> - setResultOpt - (Some - (Completable.CtypedExpression - { - howToRetrieveSourceType = - CtxPath - (CPId (Utils.flattenLongIdent typIdentifier.txt, Type)); - expressionPath = []; - alreadySeenIdents = []; - lookingToComplete = CNoContext; - prefix = ""; - })) + setResultForced + (Completable.CtypedExpression + { + howToRetrieveSourceType = + CtxPath + (CPId (Utils.flattenLongIdent typIdentifier.txt, Type)); + expressionPath = []; + alreadySeenIdents = []; + lookingToComplete = CNoContext; + prefix = ""; + }) | _ -> ()) | _ -> ()) | Pstr_type (recFlag, decls) -> diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index f58ecdfcf..287652a32 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -1089,7 +1089,7 @@ Completable: Cpath Type[ForAuto, ""] Complete src/Completion.res 179:13 posCursor:[179:13] posNoWhite:[179:12] Found expr:[179:11->179:13] Pexp_construct As:[179:11->179:13] None -Completable: Cpath Value[As] +Completable: CtypedExpression(sourceType:Value[q], lookingToComplete:CVariant, prefix:As, pattern: [] [] Complete src/Completion.res 182:17 From cd2161aaa4ea1879bf14a2f319a9baace92ff5eb Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Fri, 2 Sep 2022 21:31:14 +0200 Subject: [PATCH 78/80] make sure the newest env is always propagated --- analysis/src/CompletionBackEnd.ml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 149b3fc40..b8fe48faa 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1527,7 +1527,7 @@ let findTypeInContext (typ : Types.type_expr) ~env ~nestedContextPath ~package = | targetItem :: nestedContextPath -> ( match (targetItem, currentType |> extractType ~env ~package) with | ( Completable.RField {fieldName}, - Some (Declared (_, {item = {kind = Record fields}})) ) -> ( + Some (Declared (env, {item = {kind = Record fields}})) ) -> ( match fields |> List.find_opt (fun field -> field.fname.txt = fieldName) with @@ -1537,7 +1537,7 @@ let findTypeInContext (typ : Types.type_expr) ~env ~nestedContextPath ~package = targetField.typ |> digToType ~env ~nestedContextPath ~package else typeExprToCompletable targetField.typ ~env ~package) | ( Variant {constructorName; payloadNum}, - Some (Declared (_, {item = {kind = Variant constructors}})) ) -> ( + Some (Declared (env, {item = {kind = Variant constructors}})) ) -> ( match constructors |> List.find_opt (fun constructor -> @@ -1554,7 +1554,7 @@ let findTypeInContext (typ : Types.type_expr) ~env ~nestedContextPath ~package = | Some (argType, _) -> argType |> digToType ~env ~nestedContextPath ~package)) | None -> None) - | Polyvariant {name; payloadNum}, Some (Polyvariant (_, constructors)) + | Polyvariant {name; payloadNum}, Some (Polyvariant (env, constructors)) -> ( match constructors @@ -1570,12 +1570,12 @@ let findTypeInContext (typ : Types.type_expr) ~env ~nestedContextPath ~package = | Some argType -> argType |> digToType ~env ~nestedContextPath ~package)) | None -> None) - | PTuple {itemNumber}, Some (Tuple (_, exprs)) -> ( + | PTuple {itemNumber}, Some (Tuple (env, exprs)) -> ( match List.nth_opt exprs itemNumber with | None -> None | Some typeExpr -> typeExpr |> digToType ~env ~nestedContextPath ~package) - | Variant {constructorName = "Some"}, Some (Toption (_, typeExpr)) -> + | Variant {constructorName = "Some"}, Some (Toption (env, typeExpr)) -> typeExpr |> digToType ~env ~nestedContextPath ~package | _ -> None) in @@ -1670,7 +1670,7 @@ let rec findSourceType sourceType ~package ~opens ~rawOpens ~allFiles ~env labels |> List.find_opt (fun (name, _t) -> name = label) in match targetLabel with - | Some (_, typeExpr) -> Some typeExpr + | Some (_, typeExpr) -> Some (typeExpr, env) | _ -> None) | JsxProp {componentPath; propName} -> ( match @@ -1679,7 +1679,7 @@ let rec findSourceType sourceType ~package ~opens ~rawOpens ~allFiles ~env |> List.find_opt (fun (label, _typeExpr) -> label = propName) with | None -> None - | Some (_label, typeExpr) -> Some typeExpr) + | Some (_label, typeExpr) -> Some (typeExpr, env)) | CtxPath typeSourceContextPath -> ( match typeSourceContextPath @@ -1687,14 +1687,14 @@ let rec findSourceType sourceType ~package ~opens ~rawOpens ~allFiles ~env ~env ~exact:true ~scope |> completionsGetTypeEnv with - | Some (typ, _env) -> Some typ + | Some (typ, env) -> Some (typ, env) | None -> None) | FunctionArgument {howToFindFunctionType; arg} -> ( match howToFindFunctionType |> findSourceType ~package ~opens ~rawOpens ~allFiles ~env ~scope ~pos with - | Some typ -> ( + | Some (typ, env) -> ( let labels, _ = typ |> extractFunctionType ~env ~package in match arg with | Unlabelled argNum -> @@ -1703,7 +1703,7 @@ let rec findSourceType sourceType ~package ~opens ~rawOpens ~allFiles ~env |> List.find_map (fun (label, typExpr) -> match label with | Asttypes.Nolabel -> - if argNum = !idx then Some typExpr + if argNum = !idx then Some (typExpr, env) else ( idx := !idx + 1; None) @@ -1714,7 +1714,7 @@ let rec findSourceType sourceType ~package ~opens ~rawOpens ~allFiles ~env match label with | (Asttypes.Labelled labelName | Optional labelName) when labelName = lookingForLabel -> - Some typExpr + Some (typExpr, env) | _ -> None)) | _ -> None) @@ -2050,7 +2050,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i in match sourceType with | None -> [] - | Some typ -> ( + | Some (typ, env) -> ( match ( typ |> findTypeInContext ~env ~nestedContextPath:patternPath ~package, lookingToComplete ) @@ -2263,7 +2263,7 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i in match sourceType with | None -> [] - | Some typ -> ( + | Some (typ, env) -> ( match ( typ |> findTypeInContext ~env ~nestedContextPath:expressionPath ~package, From 0522d015500d749ffe5e52e5a26be1b927152aea Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Wed, 7 Sep 2022 18:30:40 +0200 Subject: [PATCH 79/80] fix issue where Some variants wouldnt be handled properly --- analysis/src/CompletionFrontEnd.ml | 82 ++++++------- .../tests/src/TypedContextCompletionSpec.res | 20 ++++ analysis/tests/src/expected/Dce.res.txt | 2 +- .../TypeContextCompletion_Records.res.txt | 22 +++- .../TypedContextCompletionSpec.res.txt | 108 +++++++++++++++++- 5 files changed, 187 insertions(+), 47 deletions(-) diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 59c08098f..27d1fd6ef 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -400,6 +400,47 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug alreadySeenIdents = []; } (* Variants etc *) + | Ppat_construct + ( {txt}, + Some {ppat_loc; ppat_desc = Ppat_construct ({txt = Lident "()"}, _)} ) + -> ( + (* A variant like SomeVariant(). Interpret as completing the payload of the variant *) + match CursorPosition.classifyLoc ppat_loc ~pos with + | HasCursor -> + Some + { + lookingToComplete = CNoContext; + patternPath = + [ + Completable.Variant + {constructorName = getSimpleFieldName txt; payloadNum = Some 0}; + ] + @ patternPath + |> List.rev; + prefix = ""; + alreadySeenIdents = []; + } + | NoCursor -> None + | EmptyLoc -> None) + | Ppat_variant + ( label, + Some {ppat_loc; ppat_desc = Ppat_construct ({txt = Lident "()"}, _)} ) + -> ( + (* A polyvariant like #SomeVariant(). Interpret as completing the payload of the variant *) + match CursorPosition.classifyLoc ppat_loc ~pos with + | HasCursor -> + Some + { + lookingToComplete = CNoContext; + patternPath = + [Completable.Polyvariant {name = label; payloadNum = Some 0}] + @ patternPath + |> List.rev; + prefix = ""; + alreadySeenIdents = []; + } + | NoCursor -> None + | EmptyLoc -> None) | Ppat_construct ({txt}, Some payload) when CursorPosition.classifyLoc payload.ppat_loc ~pos = HasCursor -> (* When there's a variant with a payload, and the cursor is in the pattern. Some(S) for example. *) @@ -469,47 +510,6 @@ let rec findContextInPattern pattern ~pos ~patternPath ~debug } | NoCursor -> None | EmptyLoc -> None) - | Ppat_construct - ( {txt}, - Some {ppat_loc; ppat_desc = Ppat_construct ({txt = Lident "()"}, _)} ) - -> ( - (* A variant like SomeVariant(). Interpret as completing the payload of the variant *) - match CursorPosition.classifyLoc ppat_loc ~pos with - | HasCursor -> - Some - { - lookingToComplete = CNoContext; - patternPath = - [ - Completable.Variant - {constructorName = getSimpleFieldName txt; payloadNum = Some 0}; - ] - @ patternPath - |> List.rev; - prefix = ""; - alreadySeenIdents = []; - } - | NoCursor -> None - | EmptyLoc -> None) - | Ppat_variant - ( label, - Some {ppat_loc; ppat_desc = Ppat_construct ({txt = Lident "()"}, _)} ) - -> ( - (* A polyvariant like #SomeVariant(). Interpret as completing the payload of the variant *) - match CursorPosition.classifyLoc ppat_loc ~pos with - | HasCursor -> - Some - { - lookingToComplete = CNoContext; - patternPath = - [Completable.Polyvariant {name = label; payloadNum = Some 0}] - @ patternPath - |> List.rev; - prefix = ""; - alreadySeenIdents = []; - } - | NoCursor -> None - | EmptyLoc -> None) (* Records *) | Ppat_record ([], _) -> (* No fields mean we're in an empty record body. We can complete for that. *) diff --git a/analysis/tests/src/TypedContextCompletionSpec.res b/analysis/tests/src/TypedContextCompletionSpec.res index fa26ed995..800aef188 100644 --- a/analysis/tests/src/TypedContextCompletionSpec.res +++ b/analysis/tests/src/TypedContextCompletionSpec.res @@ -256,3 +256,23 @@ let y = One // let x: user = {age: 123, } // ^com + +// --- Inline records --- +type withInlineRecords = One({first: bool, second: option}) | TTwo | TThree + +let withInlineRecords: withInlineRecords = TTwo + +// switch withInlineRecords { | } +// ^com + +type locationState = {shallow: option} + +type location = {state: locationState} + +let location = {state: {shallow: None}} + +// let isShallow = switch location.state { | {shallow: Some()} => true | _ => false } +// ^com + +// let isShallow = switch location.state { | {shallow: } => true | _ => false } +// ^com diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index 858e4da99..2d5dea86d 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:316 +issues:322 diff --git a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt index 377ece653..77142a785 100644 --- a/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt +++ b/analysis/tests/src/expected/TypeContextCompletion_Records.res.txt @@ -343,8 +343,26 @@ posCursor:[90:51] posNoWhite:[90:50] Found pattern:[90:46->90:52] Ppat_construct Four:[90:46->90:50] posCursor:[90:51] posNoWhite:[90:50] Found pattern:[90:50->90:52] Ppat_construct ():[90:50->90:52] -Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:(), pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)], seenIdents: []) -[] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)], seenIdents: []) +[{ + "label": "TwentyFive", + "kind": 4, + "tags": [], + "detail": "TwentyFive\n\n", + "documentation": null, + "sortText": null, + "insertText": "TwentyFive", + "insertTextFormat": 2 + }, { + "label": "SixtyTwo", + "kind": 4, + "tags": [], + "detail": "SixtyTwo\n\n", + "documentation": null, + "sortText": null, + "insertText": "SixtyTwo", + "insertTextFormat": 2 + }] Complete src/TypeContextCompletion_Records.res 93:55 posCursor:[93:55] posNoWhite:[93:54] Found expr:[93:3->93:66] diff --git a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt index 5561ec4ed..9721d7048 100644 --- a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt +++ b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt @@ -523,8 +523,26 @@ posCursor:[158:51] posNoWhite:[158:50] Found pattern:[158:46->158:52] Ppat_construct Four:[158:46->158:50] posCursor:[158:51] posNoWhite:[158:50] Found pattern:[158:50->158:52] Ppat_construct ():[158:50->158:52] -Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:(), pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)], seenIdents: []) -[] +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:thirdStuff, Tuple:1, Variant:Four(0)], seenIdents: []) +[{ + "label": "TwentyFive", + "kind": 4, + "tags": [], + "detail": "TwentyFive\n\n", + "documentation": null, + "sortText": null, + "insertText": "TwentyFive", + "insertTextFormat": 2 + }, { + "label": "SixtyTwo", + "kind": 4, + "tags": [], + "detail": "SixtyTwo\n\n", + "documentation": null, + "sortText": null, + "insertText": "SixtyTwo", + "insertTextFormat": 2 + }] Complete src/TypedContextCompletionSpec.res 161:55 posCursor:[161:55] posNoWhite:[161:54] Found expr:[161:3->161:66] @@ -2605,7 +2623,7 @@ posCursor:[228:41] posNoWhite:[228:40] Found pattern:[228:29->228:43] posCursor:[228:41] posNoWhite:[228:40] Found pattern:[228:38->228:42] posCursor:[228:41] posNoWhite:[228:40] Found pattern:[228:40->228:41] Ppat_construct ():[228:40->228:41] -Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CVariant, patternType:Switch, prefix:(), pattern: [RecordField:other2, Variant:S(0)], seenIdents: []) +Completable: CtypedPattern(sourceType:Value[someOtherValue], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:other2, Polyvariant:S(0)], seenIdents: []) [] Complete src/TypedContextCompletionSpec.res 231:63 @@ -2708,3 +2726,87 @@ posCursor:[256:27] posNoWhite:[256:26] Found expr:[256:17->256:29] Completable: CtypedExpression(sourceType:Value[x], lookingToComplete:CRecordField, prefix:"", pattern: [], seenIdents: [age]) [] +Complete src/TypedContextCompletionSpec.res 264:32 +posCursor:[264:32] posNoWhite:[264:30] Found expr:[264:3->264:34] +Completable: CtypedPattern(sourceType:Value[withInlineRecords], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [], seenIdents: []) +[{ + "label": "One", + "kind": 4, + "tags": [], + "detail": "One\n\n", + "documentation": null, + "sortText": null, + "insertText": "One", + "insertTextFormat": 2 + }, { + "label": "TTwo", + "kind": 4, + "tags": [], + "detail": "TTwo\n\n", + "documentation": null, + "sortText": null, + "insertText": "TTwo", + "insertTextFormat": 2 + }, { + "label": "TThree", + "kind": 4, + "tags": [], + "detail": "TThree\n\n", + "documentation": null, + "sortText": null, + "insertText": "TThree", + "insertTextFormat": 2 + }] + +Complete src/TypedContextCompletionSpec.res 273:60 +posCursor:[273:60] posNoWhite:[273:59] Found expr:[273:19->273:85] +posCursor:[273:60] posNoWhite:[273:59] Found pattern:[273:45->273:62] +posCursor:[273:60] posNoWhite:[273:59] Found pattern:[273:55->273:61] +Ppat_construct Some:[273:55->273:59] +posCursor:[273:60] posNoWhite:[273:59] Found pattern:[273:59->273:61] +Ppat_construct ():[273:59->273:61] +Completable: CtypedPattern(sourceType:Value[location].state, lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:shallow, Variant:Some(0)], seenIdents: []) +[{ + "label": "false", + "kind": 12, + "tags": [], + "detail": "boolean\n\n", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "true", + "kind": 12, + "tags": [], + "detail": "boolean\n\n", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] + +Complete src/TypedContextCompletionSpec.res 276:54 +posCursor:[276:54] posNoWhite:[276:53] Found expr:[276:19->276:79] +posCursor:[276:54] posNoWhite:[276:53] Found pattern:[276:45->276:56] +Completable: CtypedPattern(sourceType:Value[location].state, lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:shallow], seenIdents: []) +[{ + "label": "None", + "kind": 4, + "tags": [], + "detail": "None\n\n", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "Some(_)", + "kind": 4, + "tags": [], + "detail": "Some(_)\n\n", + "documentation": null, + "sortText": null, + "insertText": "Some(${1:_})", + "insertTextFormat": 2 + }] + From 16a6f0f3911e050b6d763d628f1dd11beda77fdc Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Wed, 7 Sep 2022 20:42:14 +0200 Subject: [PATCH 80/80] complete inline records --- analysis/src/CompletionBackEnd.ml | 75 +++++++++++++++---- analysis/src/ProcessCmt.ml | 17 ++--- .../tests/src/TypedContextCompletionSpec.res | 6 +- .../TypedContextCompletionSpec.res.txt | 54 +++++++++---- 4 files changed, 114 insertions(+), 38 deletions(-) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index b8fe48faa..19bbd64ea 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1491,6 +1491,7 @@ type completable = decl: Types.type_declaration; name: string Location.loc; } + | CInlineRecord of field list | CVariant of {constructors: Constructor.t list} | CPolyVariant of {constructors: polyVariantConstructor list} | COptional of completable @@ -1513,6 +1514,20 @@ let rec typeExprToCompletable typ ~env ~package = | Some (Tuple (_, types)) -> Some (CTuple {types}) | _ -> None +let findInlineRecordInConstructor constructor = + let _, typeDecl = constructor.Constructor.typeDecl in + match typeDecl.type_kind with + | Type_variant constructors -> ( + match + constructors + |> List.find_opt (fun constr -> + constr.Types.cd_id.Ident.name == constructor.cname.txt) + with + | Some {cd_args = Cstr_record fields} -> + Some (fields |> List.map ProcessCmt.mapRecordField) + | _ -> None) + | _ -> None + (* Takes a type_expr and figures out what completable it corresponds to, if any. If the target type is nested somewhere inside of the type_expr, nestedContextPath will be populated with instructions on how to reach that part. This is primarily used in patterns, where the cursor can be deep into the pattern. *) @@ -1550,7 +1565,12 @@ let findTypeInContext (typ : Types.type_expr) ~env ~nestedContextPath ~package = | Some argNum -> ( (* If we find the argument/payload requested, descend into that *) match List.nth_opt constructor.args argNum with - | None -> None + | None -> ( + (* If we can't find the arg, it might be an inline record *) + match findInlineRecordInConstructor constructor with + | Some inlineRecordFields -> + Some (CInlineRecord inlineRecordFields) + | _ -> None) | Some (argType, _) -> argType |> digToType ~env ~nestedContextPath ~package)) | None -> None) @@ -1718,6 +1738,10 @@ let rec findSourceType sourceType ~package ~opens ~rawOpens ~allFiles ~env | _ -> None)) | _ -> None) +let constructorHasArgs constructor = + constructor.Constructor.args |> List.length > 0 + || findInlineRecordInConstructor constructor |> Option.is_some + let processCompletable ~debug ~package ~scope ~env ~pos ~forHover (completable : Completable.t) = let rawOpens = Scope.getRawOpens scope in @@ -2205,19 +2229,12 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i alreadySeenConstructorName = constructor.Constructor.cname.txt))) |> List.map (fun (constructor : Constructor.t) -> - (* TODO: Can we leverage snippets here for automatically moving the cursor when there are multiple payloads? - Eg. Some($1) as completion item. *) + let hasArgs = constructorHasArgs constructor in Completion.create - ~name: - (constructor.cname.txt - ^ if constructor.args |> List.length > 0 then "(_)" else "" - ) + ~name:(constructor.cname.txt ^ if hasArgs then "(_)" else "") ~insertTextFormat:Snippet ~insertText: - (constructor.cname.txt - ^ - if constructor.args |> List.length > 0 then "(${1:_})" - else "") + (constructor.cname.txt ^ if hasArgs then "(${1:_})" else "") ~kind:(Constructor (constructor, "")) ~env ()) in @@ -2243,7 +2260,23 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i (field, decl |> Shared.declToString name.txt)) ()) else None) - | Some (CRecord _), _ -> + | Some (CInlineRecord fields), CRecordField -> + fields + |> List.filter (fun (field : field) -> + not + (alreadySeenIdents + |> List.exists (fun fieldName -> fieldName = field.fname.txt))) + |> Utils.filterMap (fun (field : field) -> + if prefix = "" || checkName field.fname.txt ~prefix ~exact:false + then + Some + (Completion.create ~name:field.fname.txt ~env + ~kind: + (Completion.Field + (field, field.typ |> Shared.typeToString)) + ()) + else None) + | Some (CRecord _ | CInlineRecord _), _ -> [ Completion.create ~name:"{}" ~insertText:"{${1}}" ~insertTextFormat:Snippet ~env ~sortText:"a" @@ -2431,7 +2464,23 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i (field, decl |> Shared.declToString name.txt)) ()) else None) - | Some (CRecord {fields}), _ -> + | Some (CInlineRecord fields), CRecordField -> + fields + |> List.filter (fun (field : field) -> + not + (alreadySeenIdents + |> List.exists (fun fieldName -> fieldName = field.fname.txt))) + |> Utils.filterMap (fun (field : field) -> + if prefix = "" || checkName field.fname.txt ~prefix ~exact:false + then + Some + (Completion.create ~name:field.fname.txt ~env + ~kind: + (Completion.Field + (field, field.typ |> Shared.typeToString)) + ()) + else None) + | Some (CRecord {fields} | CInlineRecord fields), _ -> [ Completion.create ~name: diff --git a/analysis/src/ProcessCmt.ml b/analysis/src/ProcessCmt.ml index fd53e58df..cbced9e53 100644 --- a/analysis/src/ProcessCmt.ml +++ b/analysis/src/ProcessCmt.ml @@ -10,6 +10,12 @@ let addDeclared ~(name : string Location.loc) ~extent ~stamp ~(env : Env.t) addStamp env.stamps stamp declared; declared +let mapRecordField field = + let {Types.ld_id; ld_type} = field in + let astamp = Ident.binding_time ld_id in + let name = Ident.name ld_id in + {stamp = astamp; fname = Location.mknoloc name; typ = ld_type} + let rec forTypeSignatureItem ~env ~(exported : Exported.t) (item : Types.signature_item) = match item with @@ -75,16 +81,7 @@ let rec forTypeSignatureItem ~env ~(exported : Exported.t) Stamps.addConstructor env.stamps stamp declared; item)) | Type_record (fields, _) -> - Record - (fields - |> List.map (fun {Types.ld_id; ld_type} -> - let astamp = Ident.binding_time ld_id in - let name = Ident.name ld_id in - { - stamp = astamp; - fname = Location.mknoloc name; - typ = ld_type; - }))); + Record (fields |> List.map mapRecordField)); } ~name ~stamp:(Ident.binding_time ident) ~env type_attributes (Exported.add exported Exported.Type) diff --git a/analysis/tests/src/TypedContextCompletionSpec.res b/analysis/tests/src/TypedContextCompletionSpec.res index 800aef188..408f9d49d 100644 --- a/analysis/tests/src/TypedContextCompletionSpec.res +++ b/analysis/tests/src/TypedContextCompletionSpec.res @@ -262,9 +262,13 @@ type withInlineRecords = One({first: bool, second: option}) | let withInlineRecords: withInlineRecords = TTwo -// switch withInlineRecords { | } +// switch withInlineRecords { | One({}) } +// ^com + +// switch withInlineRecords { | } // ^com +// -- Nested optionals --- type locationState = {shallow: option} type location = {state: locationState} diff --git a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt index 9721d7048..66239d087 100644 --- a/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt +++ b/analysis/tests/src/expected/TypedContextCompletionSpec.res.txt @@ -2726,17 +2726,43 @@ posCursor:[256:27] posNoWhite:[256:26] Found expr:[256:17->256:29] Completable: CtypedExpression(sourceType:Value[x], lookingToComplete:CRecordField, prefix:"", pattern: [], seenIdents: [age]) [] -Complete src/TypedContextCompletionSpec.res 264:32 -posCursor:[264:32] posNoWhite:[264:30] Found expr:[264:3->264:34] +Complete src/TypedContextCompletionSpec.res 264:37 +posCursor:[264:37] posNoWhite:[264:36] Found expr:[264:3->264:42] +posCursor:[264:37] posNoWhite:[264:36] Found pattern:[264:32->264:39] +Ppat_construct One:[264:32->264:35] +posCursor:[264:37] posNoWhite:[264:36] Found pattern:[264:36->264:38] +Completable: CtypedPattern(sourceType:Value[withInlineRecords], lookingToComplete:CRecordField, patternType:Switch, prefix:"", pattern: [Variant:One(0)], seenIdents: []) +[{ + "label": "first", + "kind": 5, + "tags": [], + "detail": "first: bool\n\nbool", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }, { + "label": "second", + "kind": 5, + "tags": [], + "detail": "second: option\n\noption", + "documentation": null, + "sortText": null, + "insertText": null, + "insertTextFormat": null + }] + +Complete src/TypedContextCompletionSpec.res 267:32 +posCursor:[267:32] posNoWhite:[267:30] Found expr:[267:3->267:35] Completable: CtypedPattern(sourceType:Value[withInlineRecords], lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [], seenIdents: []) [{ - "label": "One", + "label": "One(_)", "kind": 4, "tags": [], "detail": "One\n\n", "documentation": null, "sortText": null, - "insertText": "One", + "insertText": "One(${1:_})", "insertTextFormat": 2 }, { "label": "TTwo", @@ -2758,13 +2784,13 @@ Completable: CtypedPattern(sourceType:Value[withInlineRecords], lookingToComplet "insertTextFormat": 2 }] -Complete src/TypedContextCompletionSpec.res 273:60 -posCursor:[273:60] posNoWhite:[273:59] Found expr:[273:19->273:85] -posCursor:[273:60] posNoWhite:[273:59] Found pattern:[273:45->273:62] -posCursor:[273:60] posNoWhite:[273:59] Found pattern:[273:55->273:61] -Ppat_construct Some:[273:55->273:59] -posCursor:[273:60] posNoWhite:[273:59] Found pattern:[273:59->273:61] -Ppat_construct ():[273:59->273:61] +Complete src/TypedContextCompletionSpec.res 277:60 +posCursor:[277:60] posNoWhite:[277:59] Found expr:[277:19->277:85] +posCursor:[277:60] posNoWhite:[277:59] Found pattern:[277:45->277:62] +posCursor:[277:60] posNoWhite:[277:59] Found pattern:[277:55->277:61] +Ppat_construct Some:[277:55->277:59] +posCursor:[277:60] posNoWhite:[277:59] Found pattern:[277:59->277:61] +Ppat_construct ():[277:59->277:61] Completable: CtypedPattern(sourceType:Value[location].state, lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:shallow, Variant:Some(0)], seenIdents: []) [{ "label": "false", @@ -2786,9 +2812,9 @@ Completable: CtypedPattern(sourceType:Value[location].state, lookingToComplete:C "insertTextFormat": null }] -Complete src/TypedContextCompletionSpec.res 276:54 -posCursor:[276:54] posNoWhite:[276:53] Found expr:[276:19->276:79] -posCursor:[276:54] posNoWhite:[276:53] Found pattern:[276:45->276:56] +Complete src/TypedContextCompletionSpec.res 280:54 +posCursor:[280:54] posNoWhite:[280:53] Found expr:[280:19->280:79] +posCursor:[280:54] posNoWhite:[280:53] Found pattern:[280:45->280:56] Completable: CtypedPattern(sourceType:Value[location].state, lookingToComplete:CNoContext, patternType:Switch, prefix:"", pattern: [RecordField:shallow], seenIdents: []) [{ "label": "None",