Skip to content

Autocomplete for function calls: only suggest labeled args that were … #217

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## master
- ppx autocomplete: handle more atomic expressions to the rhs of `=` without braces (variant, polymorphic variant, function call, list literal, nested component, characters, templates).
- Autocomplete for function calls: only suggest labeled args that were not yet assigned.

## 1.1.1

Expand Down
5 changes: 3 additions & 2 deletions analysis/src/NewCompletions.ml
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ let processCompletable ~findItems ~package ~rawOpens
in
dec2)
|> List.map mkDecorator
| Clabel (funPath, prefix) ->
| Clabel (funPath, prefix, identsSeen) ->
let labels =
match funPath |> findItems ~exact:true with
| {SharedTypes.item = Value typ} :: _ ->
Expand All @@ -631,7 +631,8 @@ let processCompletable ~findItems ~package ~rawOpens
~docstring:[]
in
labels
|> List.filter (fun (name, _t) -> Utils.startsWith name prefix)
|> List.filter (fun (name, _t) ->
Utils.startsWith name prefix && not (List.mem name identsSeen))
|> List.map mkLabel

let computeCompletions ~full ~maybeText ~pos =
Expand Down
50 changes: 38 additions & 12 deletions analysis/src/PartialParser.ml
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,46 @@ let rec startOfLident text i =

(* foo(... ~arg) from ~arg find foo *)
let findCallFromArgument text offset =
let rec loop ~i ~nClosed =
let none = ([], []) in
let rec loop identsSeen i =
let i = skipWhite text i in
if i > 0 then
match text.[i] with
| '(' when nClosed > 0 -> loop ~i:(i - 1) ~nClosed:(nClosed - 1)
| '}' ->
let i1 = findBackSkippingCommentsAndStrings text '{' '}' (i - 1) 0 in
if i1 > 0 then loop identsSeen i1 else none
| ')' ->
let i1 = findBackSkippingCommentsAndStrings text '(' ')' (i - 1) 0 in
if i1 > 0 then loop identsSeen i1 else none
| ']' ->
let i1 = findBackSkippingCommentsAndStrings text '[' ']' (i - 1) 0 in
if i1 > 0 then loop identsSeen i1 else none
| '"' ->
let i1 = findBack text '"' (i - 1) in
if i1 > 0 then loop identsSeen i1 else none
| '\'' ->
let i1 = findBack text '\'' (i - 1) in
if i1 > 0 then loop identsSeen i1 else none
| '`' ->
let i1 = findBack text '`' (i - 1) in
if i1 > 0 then loop identsSeen i1 else none
| '(' ->
let i1 = skipWhite text (i - 1) in
let i0 = startOfLident text i1 in
let funLident = String.sub text i0 (i1 - i0 + 1) in
Str.split (Str.regexp_string ".") funLident
| ')' -> loop ~i:(i - 1) ~nClosed:(nClosed + 1)
| _ -> loop ~i:(i - 1) ~nClosed
else []
(Str.split (Str.regexp_string ".") funLident, identsSeen)
| 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '.' | '_' ->
let i1 = startOfLident text i in
let ident = String.sub text i1 (i - i1 + 1) in
if i1 - 1 > 0 then
match text.[i1 - 1] with
| '~' -> loop (ident :: identsSeen) (i1 - 2)
| _ -> loop identsSeen (i1 - 1)
else none
| _ -> loop identsSeen (i - 1)
else none
in
loop ~i:offset ~nClosed:0
loop [] offset

(* skip A or #A or %A if present *)
let skipOptVariantExtension text i =
Expand All @@ -61,7 +87,7 @@ let skipOptVariantExtension text i =
if i > 0 then match text.[i] with '#' | '%' -> i - 1 | _ -> i else i
in
i
| _ -> i
| _ -> i
else i

(* Figure out whether id should be autocompleted as component prop.
Expand Down Expand Up @@ -143,8 +169,8 @@ type pipe = PipeId of string | PipeArray | PipeString

type completable =
| Cdecorator of string (** e.g. @module *)
| Clabel of string list * string
(** e.g. (["M", "foo"], "label") for M.foo(...~label...) *)
| Clabel of string list * string * string list
(** e.g. (["M", "foo"], "label", ["l1", "l2"]) for M.foo(...~l1...~l2...~label...) *)
| Cpath of string list (** e.g. ["M", "foo"] for M.foo *)
| Cjsx of string list * string * string list
(** E.g. (["M", "Comp"], "id", ["id1", "id2"]) for <M.Comp id1=... id2=... ... id *)
Expand Down Expand Up @@ -201,8 +227,8 @@ let findCompletable text offset =
else Some (mkPath rest)
| '~' ->
let labelPrefix = suffix i in
let funPath = findCallFromArgument text (i - 1) in
Some (Clabel (funPath, labelPrefix))
let funPath, identsSeen = findCallFromArgument text (i - 1) in
Some (Clabel (funPath, labelPrefix, identsSeen))
| '@' -> Some (Cdecorator (suffix i))
| 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '.' | '_' -> loop (i - 1)
| ' ' when i = offset - 1 -> (
Expand Down
8 changes: 7 additions & 1 deletion analysis/tests/src/Completion.res
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module Lib = {
let next = (~number=0, ~year) => number + year
}

//^com let x = foo(~
//^com let x = Lib.foo(~

//^com [1,2,3]->m

Expand Down Expand Up @@ -58,3 +58,9 @@ let zzz = 11
//^com @reac

//^com @react.

//^com let x = Lib.foo(~name, ~

//^com let x = Lib.foo(~age, ~

//^com let x = Lib.foo(~age={3+4}, ~
27 changes: 27 additions & 0 deletions analysis/tests/src/expected/Completion.res.txt
Original file line number Diff line number Diff line change
Expand Up @@ -556,3 +556,30 @@ Complete tests/src/Completion.res 58:2
"documentation": null
}]

Complete tests/src/Completion.res 60:2
[{
"label": "age",
"kind": 4,
"tags": [],
"detail": "int",
"documentation": null
}]

Complete tests/src/Completion.res 62:2
[{
"label": "name",
"kind": 4,
"tags": [],
"detail": "string",
"documentation": null
}]

Complete tests/src/Completion.res 64:2
[{
"label": "name",
"kind": 4,
"tags": [],
"detail": "string",
"documentation": null
}]