Skip to content

Commit 4438ac7

Browse files
committed
fix triggering value completion vs named arg ambiguity
1 parent c342130 commit 4438ac7

File tree

3 files changed

+68
-25
lines changed

3 files changed

+68
-25
lines changed

analysis/src/CompletionFrontEnd.ml

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ let extractJsxProps ~(compName : Longident.t Location.loc) ~args =
109109
let extractCompletableArgValueInfo exp =
110110
match exp.Parsetree.pexp_desc with
111111
| Pexp_ident {txt = Lident txt} -> Some txt
112+
| Pexp_construct ({txt = Lident "()"}, _) -> Some ""
112113
| Pexp_construct ({txt = Lident txt}, _) -> Some txt
113114
| _ -> None
114115

@@ -118,7 +119,11 @@ let isExprHole exp =
118119
| _ -> false
119120

120121
let findArgCompletables ~(args : arg list) ~endPos ~posBeforeCursor
121-
~(contextPath : Completable.contextPath) ~posAfterFunExpr =
122+
~(contextPath : Completable.contextPath) ~posAfterFunExpr ~charBeforeCursor
123+
=
124+
let fnHasCursor =
125+
posAfterFunExpr <= posBeforeCursor && posBeforeCursor < endPos
126+
in
122127
let allNames =
123128
List.fold_right
124129
(fun arg allLabels ->
@@ -183,11 +188,34 @@ let findArgCompletables ~(args : arg list) ~endPos ~posBeforeCursor
183188
unlabelledCount := !unlabelledCount + 1;
184189
loop rest)
185190
| [] ->
186-
if posAfterFunExpr <= posBeforeCursor && posBeforeCursor < endPos then
187-
Some (CnamedArg (contextPath, "", allNames))
191+
if fnHasCursor then
192+
match charBeforeCursor with
193+
| Some '~' -> Some (Completable.CnamedArg (contextPath, "", allNames))
194+
| _ ->
195+
Some
196+
(Cargument
197+
{
198+
functionContextPath = contextPath;
199+
argumentLabel =
200+
Unlabelled {argumentPosition = !unlabelledCount};
201+
prefix = "";
202+
})
188203
else None
189204
in
190-
loop args
205+
match args with
206+
(* Special handling for empty fn calls, e.g. `let _ = someFn(<com>)` *)
207+
| [
208+
{label = None; exp = {pexp_desc = Pexp_construct ({txt = Lident "()"}, _)}};
209+
]
210+
when fnHasCursor ->
211+
Some
212+
(Completable.Cargument
213+
{
214+
functionContextPath = contextPath;
215+
argumentLabel = Unlabelled {argumentPosition = 0};
216+
prefix = "";
217+
})
218+
| _ -> loop args
191219

192220
let rec exprToContextPath (e : Parsetree.expression) =
193221
match e.pexp_desc with
@@ -638,6 +666,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text =
638666
findArgCompletables ~contextPath ~args
639667
~endPos:(Loc.end_ expr.pexp_loc) ~posBeforeCursor
640668
~posAfterFunExpr:(Loc.end_ funExpr.pexp_loc)
669+
~charBeforeCursor
641670
| None -> None
642671
in
643672

analysis/tests/src/CompletionFunctionArguments.res

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,9 @@ let someFnTakingVariant = (
6161
// let _ = someFnTakingVariant(~configOpt2=O)
6262
// ^com
6363

64-
// --- UNIMPLEMENTED CASES ---
65-
// The following two cases does not complete to a values because of ambiguity - should it complete for a value, or for a named argument? We don't know whether the function has args or not when deciding, since we're just in the AST at that point. Can potentially be fixed in the future.
6664
// let _ = someOtherFn()
6765
// ^com
66+
6867
// let _ = someOtherFn(1, 2, )
6968
// ^com
7069

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

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -158,30 +158,45 @@ Completable: Cargument Value[someFnTakingVariant](~configOpt2=O)
158158
"documentation": null
159159
}]
160160

161-
Complete src/CompletionFunctionArguments.res 65:23
162-
posCursor:[65:23] posNoWhite:[65:22] Found expr:[65:11->65:24]
163-
Pexp_apply ...[65:11->65:22] (...[65:23->65:24])
164-
Completable: CnamedArg(Value[someOtherFn], "", [])
165-
Found type for function (bool, int, bool) => string
166-
[]
167-
168-
Complete src/CompletionFunctionArguments.res 67:28
169-
posCursor:[67:28] posNoWhite:[67:27] Found expr:[67:11->67:30]
170-
Pexp_apply ...[67:11->67:22] (...[67:23->67:24], ...[67:26->67:27])
171-
Completable: CnamedArg(Value[someOtherFn], "", [])
172-
Found type for function (bool, int, bool) => string
173-
[]
161+
Complete src/CompletionFunctionArguments.res 63:23
162+
posCursor:[63:23] posNoWhite:[63:22] Found expr:[63:11->63:24]
163+
Pexp_apply ...[63:11->63:22] (...[63:23->63:24])
164+
Completable: Cargument Value[someOtherFn]($0)
165+
[{
166+
"label": "true",
167+
"kind": 4,
168+
"tags": [],
169+
"detail": "bool",
170+
"documentation": null
171+
}, {
172+
"label": "false",
173+
"kind": 4,
174+
"tags": [],
175+
"detail": "bool",
176+
"documentation": null
177+
}]
174178

175-
Complete src/CompletionFunctionArguments.res 72:25
176-
posCursor:[72:25] posNoWhite:[72:24] Found expr:[72:11->72:30]
177-
Pexp_apply ...[72:11->72:17] (~isOff72:19->72:24=...[72:27->72:29])
178-
Completable: CnamedArg(Value[someFn], "", [isOff])
179-
Found type for function (~isOn: bool, ~isOff: bool=?, unit) => string
179+
Complete src/CompletionFunctionArguments.res 66:28
180+
posCursor:[66:28] posNoWhite:[66:27] Found expr:[66:11->66:30]
181+
Pexp_apply ...[66:11->66:22] (...[66:23->66:24], ...[66:26->66:27])
182+
Completable: Cargument Value[someOtherFn]($2)
180183
[{
181-
"label": "isOn",
184+
"label": "true",
185+
"kind": 4,
186+
"tags": [],
187+
"detail": "bool",
188+
"documentation": null
189+
}, {
190+
"label": "false",
182191
"kind": 4,
183192
"tags": [],
184193
"detail": "bool",
185194
"documentation": null
186195
}]
187196

197+
Complete src/CompletionFunctionArguments.res 71:25
198+
posCursor:[71:25] posNoWhite:[71:24] Found expr:[71:11->71:30]
199+
Pexp_apply ...[71:11->71:17] (~isOff71:19->71:24=...[71:27->71:29])
200+
Completable: Cargument Value[someFn]($0)
201+
[]
202+

0 commit comments

Comments
 (0)