diff --git a/Changes.md b/Changes.md index d4d38fb7..fc18cbe2 100644 --- a/Changes.md +++ b/Changes.md @@ -2,6 +2,7 @@ - Fix issue in jump-to-definition on Windows. (See https://github.com/rescript-lang/rescript-vscode/issues/98) where the wrong URI was generated. - Don't show file path on hover. - Add autocomplete for props in JSX components. +- Autocomplete: fix issue where `->` autocomplete was overruling `.`. See https://github.com/rescript-lang/rescript-editor-support/issues/99. ## Release 1.0.6 of rescript-vscode This [commit](https://github.com/rescript-lang/rescript-editor-support/commit/03ee0d97b250474028d4fb08eac81ddb21ccb082) is vendored in [rescript-vscode 1.0.6](https://github.com/rescript-lang/rescript-vscode/releases/tag/1.0.6). diff --git a/src/PartialParser.ml b/src/PartialParser.ml index aeca63fa..371cd8ad 100644 --- a/src/PartialParser.ml +++ b/src/PartialParser.ml @@ -63,16 +63,16 @@ let findJsxContext text offset = match text.[i] with | '}' -> ( let i1 = findBackSkippingCommentsAndStrings text '{' '}' (i - 1) 0 in - match i1 > 0 with true -> beforeValue i1 | false -> None ) + match i1 > 0 with true -> beforeValue i1 | false -> None) | ')' -> ( let i1 = findBackSkippingCommentsAndStrings text '(' ')' (i - 1) 0 in - match i1 > 0 with true -> beforeValue i1 | false -> None ) + match i1 > 0 with true -> beforeValue i1 | false -> None) | ']' -> ( let i1 = findBackSkippingCommentsAndStrings text '[' ']' (i - 1) 0 in - match i1 > 0 with true -> beforeValue i1 | false -> None ) + match i1 > 0 with true -> beforeValue i1 | false -> None) | '"' -> ( let i1 = findBack text '"' (i - 1) in - match i1 > 0 with true -> beforeValue i1 | false -> None ) + match i1 > 0 with true -> beforeValue i1 | false -> None) | _ -> let i1 = startOfLident text i in let ident = String.sub text i1 (i - i1 + 1) in @@ -103,18 +103,29 @@ 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 true -> None | false -> loop (i1 - 1) ) + match ident = "" with true -> None | false -> loop (i1 - 1)) | _ -> None else None in loop offset type completable = - | Cdecorator of string (* e.g. @module *) - | 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" *) + | Cdecorator of string (** e.g. @module *) + | 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 = + let rec loop i = + if i < 0 then true + else + match id.[i] with + | ('a' .. 'z' | '_') when i = 0 -> true + | ('a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '_') when i > 0 -> loop (i - 1) + | _ -> false + in + loop (String.length id - 1) let findCompletable text offset = let mkPath s = @@ -134,26 +145,28 @@ let findCompletable text offset = match findJsxContext text (offset - len - 1) with | None -> Cpath parts | Some componentName -> - Cjsx (Str.split (Str.regexp_string ".") componentName, id) ) + Cjsx (Str.split (Str.regexp_string ".") componentName, id)) | _ -> Cpath parts in + let suffix i = String.sub text (i + 1) (offset - (i + 1)) in let rec loop i = match i < 0 with - | true -> Some (mkPath (String.sub text (i + 1) (offset - (i + 1)))) + | true -> Some (mkPath (suffix i)) | false -> ( match text.[i] with - | '>' when i > 0 && text.[i - 1] = '-' -> loop (i - 2) + | '>' when i > 0 && text.[i - 1] = '-' -> + let rest = suffix i in + if isLowercaseIdent rest then loop (i - 2) else Some (mkPath rest) | '~' -> - let labelPrefix = String.sub text (i + 1) (offset - (i + 1)) in + let labelPrefix = suffix i in let funPath = findCallFromArgument text (i - 1) in Some (Clabel (funPath, labelPrefix)) - | '@' -> Some (Cdecorator (String.sub text (i + 1) (offset - (i + 1)))) + | '@' -> Some (Cdecorator (suffix i)) | 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' | '.' | '_' -> loop (i - 1) | _ -> ( match i = offset - 1 with | true -> None - | false -> Some (mkPath (String.sub text (i + 1) (offset - (i + 1)))) ) - ) + | false -> Some (mkPath (suffix i)))) in if offset > String.length text || offset = 0 then None else loop (offset - 1) @@ -197,7 +210,7 @@ let findOpens text offset = && not (insideLineComment text (at - 4)) then ( add (String.sub text (i + 1) (i0 + 1 - (i + 1))); - at - 4 ) + at - 4) else at | _ -> i in @@ -216,7 +229,7 @@ let findOpens text offset = | 'a' .. 'z' | 'A' .. 'Z' | '_' | '0' .. '9' -> let i0 = startOfLident text (i - 3) in add (String.sub text i0 (i - i0 - 1)) - | _ -> loop (i - 1) ) + | _ -> loop (i - 1)) | _ -> if i > 1 && text.[i] = '/' && text.[i - 1] = '*' then loop (findOpenComment text (i - 2)) @@ -235,8 +248,8 @@ let offsetOfLine text line = | '\n' -> ( match lno = line - 1 with | true -> Some (i + 1) - | false -> loop (i + 1) (lno + 1) ) - | _ -> loop (i + 1) lno ) + | false -> loop (i + 1) (lno + 1)) + | _ -> loop (i + 1) lno) in match line = 0 with true -> Some 0 | false -> loop 0 0