Skip to content

In Jsx autocomplete, don't list props already used. #185

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
Apr 28, 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
- Fix issue jumping to variables defined in complex patterns.
- In Jsx autocomplete, don't suggest props already assigned.

## beta 2

Expand Down
5 changes: 3 additions & 2 deletions analysis/src/NewCompletions.ml
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ let mkItem ~name ~kind ~detail ~deprecated ~docstring =
let processCompletable ~findItems ~package ~rawOpens
(completable : PartialParser.completable) =
match completable with
| Cjsx (componentPath, prefix) ->
| Cjsx (componentPath, prefix, identsSeen) ->
let items = findItems ~exact:true (componentPath @ ["make"]) in
let labels =
match items with
Expand Down Expand Up @@ -473,7 +473,8 @@ let processCompletable ~findItems ~package ~rawOpens
else
keyLabel
:: (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)
| Cpath parts ->
let items = parts |> findItems ~exact:false in
Expand Down
50 changes: 28 additions & 22 deletions analysis/src/PartialParser.ml
Original file line number Diff line number Diff line change
Expand Up @@ -57,57 +57,60 @@ let findCallFromArgument text offset =
(* arg ::= id | id = [?] val *)
(* val ::= id | "abc" | 42 | {...} | (...) | [...] *)
let findJsxContext text offset =
let rec loop i =
let rec loop identsSeen i =
let i = skipWhite text i in
if i > 0 then
match text.[i] with
| '}' ->
let i1 = findBackSkippingCommentsAndStrings text '{' '}' (i - 1) 0 in
if i1 > 0 then beforeValue i1 else None
if i1 > 0 then beforeValue identsSeen i1 else None
| ')' ->
let i1 = findBackSkippingCommentsAndStrings text '(' ')' (i - 1) 0 in
if i1 > 0 then beforeValue i1 else None
if i1 > 0 then beforeValue identsSeen i1 else None
| ']' ->
let i1 = findBackSkippingCommentsAndStrings text '[' ']' (i - 1) 0 in
if i1 > 0 then beforeValue i1 else None
if i1 > 0 then beforeValue identsSeen i1 else None
| '"' ->
let i1 = findBack text '"' (i - 1) in
if i1 > 0 then beforeValue i1 else None
if i1 > 0 then beforeValue identsSeen i1 else None
| _ ->
let i1 = startOfLident text i in
let ident = String.sub text i1 (i - i1 + 1) in
if i1 >= 1 && ident <> "" then
match ident.[0] with
| 'A' .. 'Z' when i1 >= 1 && text.[i1 - 1] = '<' -> Some ident
| _ -> beforeIdent (i1 - 1)
| 'A' .. 'Z' when i1 >= 1 && text.[i1 - 1] = '<' ->
Some (ident, identsSeen)
| _ -> beforeIdent identsSeen (i1 - 1)
else None
else None
and beforeIdent i =
and beforeIdent identsSeen i =
let i = skipWhite text i in
if i > 0 then
match text.[i] with
| '?' -> fromEquals (i - 1)
| '=' -> fromEquals i
| _ -> loop (i - 1)
| '?' -> fromEquals identsSeen (i - 1)
| '=' -> fromEquals identsSeen i
| _ -> loop identsSeen (i - 1)
else None
and beforeValue i =
and beforeValue identsSeen i =
let i = skipWhite text i in
if i > 0 then
match text.[i] with '?' -> fromEquals (i - 1) | _ -> fromEquals i
match text.[i] with
| '?' -> fromEquals identsSeen (i - 1)
| _ -> fromEquals identsSeen i
else None
and fromEquals i =
and fromEquals identsSeen i =
let i = skipWhite text i in
if i > 0 then
match text.[i] with
| '=' -> (
let i = skipWhite text (i - 1) in
let i1 = startOfLident text i in
let ident = String.sub text i1 (i - i1 + 1) in
match ident with "" -> None | _ -> loop (i1 - 1))
match ident with "" -> None | _ -> loop (ident :: identsSeen) (i1 - 1))
| _ -> None
else None
in
loop offset
loop [] offset

type pipe = PipeId of string | PipeArray | PipeString

Expand All @@ -116,8 +119,8 @@ type completable =
| Clabel of string list * string
(** e.g. (["M", "foo"], "label") for M.foo(...~label...) *)
| Cpath of string list (** e.g. ["M", "foo"] for M.foo *)
| Cjsx of string list * string
(** E.g. (["M", "Comp"], "id") for <M.Comp ... id *)
| Cjsx of string list * string * string list
(** E.g. (["M", "Comp"], "id", ["id1", "id2"]) for <M.Comp id1=... id2=... ... id *)
| Cpipe of pipe * string (** E.g. ("x", "foo") for "x->foo" *)

let isLowercaseIdent id =
Expand All @@ -140,8 +143,8 @@ let findCompletable text offset =
| [id] when String.lowercase_ascii id = id -> (
match findJsxContext text (offset - len - 1) with
| None -> Cpath parts
| Some componentName ->
Cjsx (Str.split (Str.regexp_string ".") componentName, id))
| Some (componentName, identsSeen) ->
Cjsx (Str.split (Str.regexp_string ".") componentName, id, identsSeen))
| _ -> Cpath parts
in
let mkPipe off partialName =
Expand Down Expand Up @@ -179,8 +182,11 @@ let findCompletable text offset =
(* autocomplete with no id: check if inside JSX *)
match findJsxContext text (offset - 1) with
| None -> None
| Some componentName ->
Some (Cjsx (Str.split (Str.regexp_string ".") componentName, "")))
| Some (componentName, identsSeen) ->
Some
(Cjsx
(Str.split (Str.regexp_string ".") componentName, "", identsSeen))
)
| _ -> if i = offset - 1 then None else Some (mkPath (suffix i))
in
if offset > String.length text || offset = 0 then None else loop (offset - 1)
Expand Down
1 change: 1 addition & 0 deletions analysis/tests/.bsb.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
81015
6 changes: 0 additions & 6 deletions analysis/tests/src/expected/Jsx.res.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@ Complete tests/src/Jsx.res 7:2
"tags": [],
"detail": "string",
"documentation": null
}, {
"label": "second",
"kind": 4,
"tags": [],
"detail": "option<string>",
"documentation": null
}, {
"label": "first",
"kind": 4,
Expand Down