diff --git a/CHANGELOG.md b/CHANGELOG.md index 584efd3d9..99697c182 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/analysis/src/NewCompletions.ml b/analysis/src/NewCompletions.ml index d42d84a08..bb6712fae 100644 --- a/analysis/src/NewCompletions.ml +++ b/analysis/src/NewCompletions.ml @@ -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 @@ -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 diff --git a/analysis/src/PartialParser.ml b/analysis/src/PartialParser.ml index 002e9b8cb..caa66583a 100644 --- a/analysis/src/PartialParser.ml +++ b/analysis/src/PartialParser.ml @@ -57,45 +57,48 @@ 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 @@ -103,11 +106,11 @@ let findJsxContext text offset = 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 @@ -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 foo" *) let isLowercaseIdent id = @@ -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 = @@ -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) diff --git a/analysis/tests/.bsb.lock b/analysis/tests/.bsb.lock new file mode 100644 index 000000000..5d957852f --- /dev/null +++ b/analysis/tests/.bsb.lock @@ -0,0 +1 @@ +81015 \ 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 3a8f550ae..2af23248e 100644 --- a/analysis/tests/src/expected/Jsx.res.txt +++ b/analysis/tests/src/expected/Jsx.res.txt @@ -8,12 +8,6 @@ Complete tests/src/Jsx.res 7:2 "tags": [], "detail": "string", "documentation": null - }, { - "label": "second", - "kind": 4, - "tags": [], - "detail": "option", - "documentation": null }, { "label": "first", "kind": 4,