diff --git a/CHANGELOG.md b/CHANGELOG.md index 411d38b1d..e4301e619 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ ## master +#### :rocket: New Feature + +- Add support for "dot completion everywhere". In addition to record fields, dots will now complete for object fields, and pipe completions applicable to the type the dot is on. You can also configure where the editor draws extra pipe completions from via the `@editor.completeFrom` attribute. https://github.com/rescript-lang/rescript-vscode/pull/1054 + ## 1.60.0 #### :rocket: New Feature diff --git a/analysis/src/Codemod.ml b/analysis/src/Codemod.ml index 61d7318cc..5c273637d 100644 --- a/analysis/src/Codemod.ml +++ b/analysis/src/Codemod.ml @@ -41,7 +41,7 @@ let transform ~path ~pos ~debug ~typ ~hint = if debug then print_endline "Found no result"; exit 1 | Some switchExpr -> - printExpr ~range:(Xform.rangeOfLoc switchExpr.pexp_loc) switchExpr) + printExpr ~range:(Loc.rangeOfLoc switchExpr.pexp_loc) switchExpr) | _ -> if debug then print_endline "Mismatch in expected structure"; exit 1) diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 5d7542e83..7589e45f9 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -594,7 +594,8 @@ let getComplementaryCompletionsForTypedValue ~opens ~allFiles ~scope ~env prefix (Utils.fileNameHasUnallowedChars name) then Some - (Completion.create name ~env ~kind:(Completion.FileModule name)) + (Completion.create name ~synthetic:true ~env + ~kind:(Completion.FileModule name)) else None) in localCompletionsWithOpens @ fileModules @@ -635,6 +636,34 @@ let getCompletionsForPath ~debug ~opens ~full ~pos ~exact ~scope findAllCompletions ~env ~prefix ~exact ~namesUsed ~completionContext | None -> []) +(** Completions intended for piping, from a completion path. *) +let completionsForPipeFromCompletionPath ~envCompletionIsMadeFrom ~opens ~pos + ~scope ~debug ~prefix ~env ~rawOpens ~full completionPath = + let completionPathWithoutCurrentModule = + TypeUtils.removeCurrentModuleIfNeeded ~envCompletionIsMadeFrom + completionPath + in + let completionPathMinusOpens = + TypeUtils.removeOpensFromCompletionPath ~rawOpens ~package:full.package + completionPathWithoutCurrentModule + |> String.concat "." + in + let completionName name = + if completionPathMinusOpens = "" then name + else completionPathMinusOpens ^ "." ^ name + in + let completions = + completionPath @ [prefix] + |> getCompletionsForPath ~debug ~completionContext:Value ~exact:false ~opens + ~full ~pos ~env ~scope + in + let completions = + completions + |> List.map (fun (completion : Completion.t) -> + {completion with name = completionName completion.name}) + in + completions + let rec digToRecordFieldsForCompletion ~debug ~package ~opens ~full ~pos ~env ~scope path = match @@ -653,7 +682,8 @@ let rec digToRecordFieldsForCompletion ~debug ~package ~opens ~full ~pos ~env | {kind = Type {kind = Record fields}} :: _ -> Some fields | _ -> None -let mkItem ?data name ~kind ~detail ~deprecated ~docstring = +let mkItem ?data ?additionalTextEdits name ~kind ~detail ~deprecated ~docstring + = let docContent = (match deprecated with | None -> "" @@ -682,6 +712,7 @@ let mkItem ?data name ~kind ~detail ~deprecated ~docstring = insertTextFormat = None; filterText = None; data; + additionalTextEdits; } let completionToItem @@ -696,9 +727,10 @@ let completionToItem filterText; detail; env; + additionalTextEdits; } ~full = let item = - mkItem name + mkItem name ?additionalTextEdits ?data:(kindToData (full.file.uri |> Uri.toPath) kind) ~kind:(Completion.kindToInt kind) ~deprecated @@ -723,46 +755,58 @@ let completionsGetTypeEnv = function type getCompletionsForContextPathMode = Regular | Pipe -let completionsGetCompletionType ~full = function - | {Completion.kind = Value typ; env} :: _ - | {Completion.kind = ObjLabel typ; env} :: _ - | {Completion.kind = Field ({typ}, _); env} :: _ -> +let completionsGetCompletionType ~full completions = + let firstNonSyntheticCompletion = + List.find_opt (fun c -> not c.Completion.synthetic) completions + in + match firstNonSyntheticCompletion with + | Some {Completion.kind = Value typ; env} + | Some {Completion.kind = ObjLabel typ; env} + | Some {Completion.kind = Field ({typ}, _); env} -> typ |> TypeUtils.extractType ~env ~package:full.package |> Option.map (fun (typ, _) -> (typ, env)) - | {Completion.kind = Type typ; env} :: _ -> ( + | Some {Completion.kind = Type typ; env} -> ( match TypeUtils.extractTypeFromResolvedType typ ~env ~full with | None -> None | Some extractedType -> Some (extractedType, env)) - | {Completion.kind = ExtractedType (typ, _); env} :: _ -> Some (typ, env) + | Some {Completion.kind = ExtractedType (typ, _); env} -> Some (typ, env) | _ -> None -let rec completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos = - function - | {Completion.kind = Value typ; env} :: _ - | {Completion.kind = ObjLabel typ; env} :: _ - | {Completion.kind = Field ({typ}, _); env} :: _ -> +let rec completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos + completions = + let firstNonSyntheticCompletion = + List.find_opt (fun c -> not c.Completion.synthetic) completions + in + match firstNonSyntheticCompletion with + | Some + ( {Completion.kind = Value typ; env} + | {Completion.kind = ObjLabel typ; env} + | {Completion.kind = Field ({typ}, _); env} ) -> Some (TypeExpr typ, env) - | {Completion.kind = FollowContextPath (ctxPath, scope); env} :: _ -> + | Some {Completion.kind = FollowContextPath (ctxPath, scope); env} -> ctxPath |> getCompletionsForContextPath ~debug ~full ~env ~exact:true ~opens ~rawOpens ~pos ~scope |> completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos - | {Completion.kind = Type typ; env} :: _ -> ( + | Some {Completion.kind = Type typ; env} -> ( match TypeUtils.extractTypeFromResolvedType typ ~env ~full with | None -> None | Some extractedType -> Some (ExtractedType extractedType, env)) - | {Completion.kind = ExtractedType (typ, _); env} :: _ -> + | Some {Completion.kind = ExtractedType (typ, _); env} -> Some (ExtractedType typ, env) | _ -> None and completionsGetTypeEnv2 ~debug (completions : Completion.t list) ~full ~opens ~rawOpens ~pos = - match completions with - | {Completion.kind = Value typ; env} :: _ -> Some (typ, env) - | {Completion.kind = ObjLabel typ; env} :: _ -> Some (typ, env) - | {Completion.kind = Field ({typ}, _); env} :: _ -> Some (typ, env) - | {Completion.kind = FollowContextPath (ctxPath, scope); env} :: _ -> + let firstNonSyntheticCompletion = + List.find_opt (fun c -> not c.Completion.synthetic) completions + in + match firstNonSyntheticCompletion with + | Some {Completion.kind = Value typ; env} -> Some (typ, env) + | Some {Completion.kind = ObjLabel typ; env} -> Some (typ, env) + | Some {Completion.kind = Field ({typ}, _); env} -> Some (typ, env) + | Some {Completion.kind = FollowContextPath (ctxPath, scope); env} -> ctxPath |> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact:true ~scope @@ -771,6 +815,7 @@ and completionsGetTypeEnv2 ~debug (completions : Completion.t list) ~full ~opens and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact ~scope ?(mode = Regular) contextPath = + let envCompletionIsMadeFrom = env in if debug then Printf.printf "ContextPath %s\n" (Completable.contextPathToString contextPath); @@ -780,41 +825,31 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact if Debug.verbose () then print_endline "[ctx_path]--> CPString"; [ Completion.create "dummy" ~env - ~kind: - (Completion.Value - (Ctype.newconstr (Path.Pident (Ident.create "string")) [])); + ~kind:(Completion.Value (Ctype.newconstr Predef.path_string [])); ] | CPBool -> if Debug.verbose () then print_endline "[ctx_path]--> CPBool"; [ Completion.create "dummy" ~env - ~kind: - (Completion.Value - (Ctype.newconstr (Path.Pident (Ident.create "bool")) [])); + ~kind:(Completion.Value (Ctype.newconstr Predef.path_bool [])); ] | CPInt -> if Debug.verbose () then print_endline "[ctx_path]--> CPInt"; [ Completion.create "dummy" ~env - ~kind: - (Completion.Value - (Ctype.newconstr (Path.Pident (Ident.create "int")) [])); + ~kind:(Completion.Value (Ctype.newconstr Predef.path_int [])); ] | CPFloat -> if Debug.verbose () then print_endline "[ctx_path]--> CPFloat"; [ Completion.create "dummy" ~env - ~kind: - (Completion.Value - (Ctype.newconstr (Path.Pident (Ident.create "float")) [])); + ~kind:(Completion.Value (Ctype.newconstr Predef.path_float [])); ] | CPArray None -> if Debug.verbose () then print_endline "[ctx_path]--> CPArray (no payload)"; [ - Completion.create "array" ~env - ~kind: - (Completion.Value - (Ctype.newconstr (Path.Pident (Ident.create "array")) [])); + Completion.create "dummy" ~env + ~kind:(Completion.Value (Ctype.newconstr Predef.path_array [])); ] | CPArray (Some cp) -> ( if Debug.verbose () then @@ -839,9 +874,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact what inner type it has. *) [ Completion.create "dummy" ~env - ~kind: - (Completion.Value - (Ctype.newconstr (Path.Pident (Ident.create "array")) [])); + ~kind:(Completion.Value (Ctype.newconstr Predef.path_array [])); ]) | CPOption cp -> ( if Debug.verbose () then print_endline "[ctx_path]--> CPOption"; @@ -950,50 +983,60 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact [Completion.create "dummy" ~env ~kind:(Completion.Value retType)] | _ -> []) | _ -> []) - | CPField (CPId {path; completionContext = Module}, fieldName) -> + | CPField {contextPath = CPId {path; completionContext = Module}; fieldName} + -> if Debug.verbose () then print_endline "[ctx_path]--> CPField: M.field"; (* M.field *) path @ [fieldName] |> getCompletionsForPath ~debug ~opens ~full ~pos ~exact ~completionContext:Field ~env ~scope - | CPField (cp, fieldName) -> ( - if Debug.verbose () then print_endline "[ctx_path]--> CPField"; - let completionsForCtxPath = + | CPField {contextPath = cp; fieldName; posOfDot; exprLoc} -> ( + if Debug.verbose () then print_endline "[dot_completion]--> Triggered"; + let completionsFromCtxPath = cp |> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact:true ~scope in - let extracted = - match - completionsForCtxPath - |> completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos - with - | Some (TypeExpr typ, env) -> ( - match typ |> TypeUtils.extractRecordType ~env ~package with - | Some (env, fields, typDecl) -> - Some - ( env, - fields, - typDecl.item.decl |> Shared.declToString typDecl.name.txt ) - | None -> None) - | Some (ExtractedType typ, env) -> ( - match typ with - | Trecord {fields} -> - Some (env, fields, typ |> TypeUtils.extractedTypeToString) - | _ -> None) - | None -> None + let mainTypeCompletionEnv = + completionsFromCtxPath + |> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos in - match extracted with - | None -> [] - | Some (env, fields, recordAsString) -> - fields - |> Utils.filterMap (fun field -> - if Utils.checkName field.fname.txt ~prefix:fieldName ~exact then - Some - (Completion.create field.fname.txt ~env - ?deprecated:field.deprecated ~docstring:field.docstring - ~kind:(Completion.Field (field, recordAsString))) - else None)) + match mainTypeCompletionEnv with + | None -> + if Debug.verbose () then + Printf.printf + "[dot_completion] Could not extract main type completion env.\n"; + [] + | Some (typ, env) -> + let fieldCompletions = + DotCompletionUtils.fieldCompletionsForDotCompletion typ ~env ~package + ~prefix:fieldName ?posOfDot ~exact + in + (* Get additional completions acting as if this field completion was actually a pipe completion. *) + let cpAsPipeCompletion = + Completable.CPPipe + { + synthetic = true; + contextPath = + (match cp with + | CPApply (c, args) -> CPApply (c, args @ [Asttypes.Nolabel]) + | CPId _ when TypeUtils.isFunctionType ~env ~package typ -> + CPApply (cp, [Asttypes.Nolabel]) + | _ -> cp); + id = fieldName; + inJsx = false; + lhsLoc = exprLoc; + } + in + let pipeCompletions = + cpAsPipeCompletion + |> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos + ~env:envCompletionIsMadeFrom ~exact ~scope + |> List.filter_map (fun c -> + TypeUtils.transformCompletionToPipeCompletion ~synthetic:true + ~env ?posOfDot c) + in + fieldCompletions @ pipeCompletions) | CPObj (cp, label) -> ( (* TODO: Also needs to support ExtractedType *) if Debug.verbose () then print_endline "[ctx_path]--> CPObj"; @@ -1006,16 +1049,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact | Some (typ, env) -> ( match typ |> TypeUtils.extractObjectType ~env ~package with | Some (env, tObj) -> - let rec getFields (texp : Types.type_expr) = - match texp.desc with - | Tfield (name, _, t1, t2) -> - let fields = t2 |> getFields in - (name, t1) :: fields - | Tlink te | Tsubst te | Tpoly (te, []) -> te |> getFields - | Tvar None -> [] - | _ -> [] - in - tObj |> getFields + tObj |> TypeUtils.getObjFields |> Utils.filterMap (fun (field, typ) -> if Utils.checkName field ~prefix:label ~exact then Some @@ -1023,7 +1057,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact else None) | None -> []) | None -> []) - | CPPipe {contextPath = cp; id = funNamePrefix; lhsLoc; inJsx} -> ( + | CPPipe {contextPath = cp; id = prefix; lhsLoc; inJsx; synthetic} -> ( if Debug.verbose () then print_endline "[ctx_path]--> CPPipe"; match cp @@ -1031,121 +1065,107 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact ~exact:true ~scope ~mode:Pipe |> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos with - | None -> [] - | Some (typ, envFromCompletionItem) -> ( + | None -> + if Debug.verbose () then + print_endline "[CPPipe]--> Could not resolve type env"; + [] + | Some (typ, env) -> ( let env, typ = typ - |> TypeUtils.resolveTypeForPipeCompletion ~env ~package ~full ~lhsLoc + |> TypeUtils.resolveTypeForPipeCompletion ~env ~package:full.package + ~full ~lhsLoc in - if debug then - if env <> envFromCompletionItem then - Printf.printf "CPPipe env:%s envFromCompletionItem:%s\n" - (QueryEnv.toString env) - (QueryEnv.toString envFromCompletionItem) - else Printf.printf "CPPipe env:%s\n" (QueryEnv.toString env); - let completionPath = - match typ with - | Builtin (builtin, _) -> - let { - arrayModulePath; - optionModulePath; - stringModulePath; - intModulePath; - floatModulePath; - promiseModulePath; - listModulePath; - resultModulePath; - regexpModulePath; - } = - package.builtInCompletionModules + let mainTypeId = TypeUtils.findRootTypeId ~full ~env typ in + let typePath = TypeUtils.pathFromTypeExpr typ in + match mainTypeId with + | None -> + if Debug.verbose () then + Printf.printf + "[pipe_completion] Could not find mainTypeId. Aborting pipe \ + completions.\n"; + [] + | Some mainTypeId -> + if Debug.verbose () then + Printf.printf "[pipe_completion] mainTypeId: %s\n" mainTypeId; + let pipeCompletions = + (* We now need a completion path from where to look up the module for our dot completion type. + This is from where we pull all of the functions we want to complete for the pipe. + + A completion path here could be one of two things: + 1. A module path to the main module for the type we've found + 2. A module path to a builtin module, like `Int` for `int`, or `Array` for `array` + + The below code will deliberately _not_ dig into type aliases for the main type when we're looking + for what _module_ to complete from. This is because you should be able to control where completions + come from even if your type is an alias. + *) + let completeAsBuiltin = + match typePath with + | Some t -> + TypeUtils.completionPathFromMaybeBuiltin t ~package:full.package + | None -> None in - Some - (match builtin with - | Array -> arrayModulePath - | Option -> optionModulePath - | String -> stringModulePath - | Int -> intModulePath - | Float -> floatModulePath - | Promise -> promiseModulePath - | List -> listModulePath - | Result -> resultModulePath - | RegExp -> regexpModulePath - | Lazy -> ["Lazy"] - | Char -> ["Char"]) - | TypExpr t -> ( - match t.Types.desc with - | Tconstr (path, _typeArgs, _) - | Tlink {desc = Tconstr (path, _typeArgs, _)} - | Tsubst {desc = Tconstr (path, _typeArgs, _)} - | Tpoly ({desc = Tconstr (path, _typeArgs, _)}, []) -> - if debug then Printf.printf "CPPipe type path:%s\n" (Path.name path); - TypeUtils.getPathRelativeToEnv ~debug ~env - ~envFromItem:envFromCompletionItem (Utils.expandPath path) - | _ -> None) - in - match completionPath with - | Some completionPath -> ( - let completionPathMinusOpens = - TypeUtils.removeOpensFromCompletionPath ~rawOpens ~package - completionPath - |> String.concat "." - in - let completionName name = - if completionPathMinusOpens = "" then name - else completionPathMinusOpens ^ "." ^ name - in - let completions = - completionPath @ [funNamePrefix] - |> getCompletionsForPath ~debug ~completionContext:Value ~exact:false - ~opens ~full ~pos ~env ~scope + let completionPath = + match (completeAsBuiltin, typePath) with + | Some completionPathForBuiltin, _ -> + Some (false, completionPathForBuiltin) + | _, Some p -> ( + (* If this isn't a builtin, but we have a path, we try to resolve the + module path relative to the env we're completing from. This ensures that + what we get here is a module path we can find completions for regardless of + of the current scope for the position we're at.*) + match + TypeUtils.getModulePathRelativeToEnv ~debug + ~env:envCompletionIsMadeFrom ~envFromItem:env + (Utils.expandPath p) + with + | None -> Some (true, [env.file.moduleName]) + | Some p -> Some (false, p)) + | _ -> None + in + match completionPath with + | None -> [] + | Some (isFromCurrentModule, completionPath) -> + completionsForPipeFromCompletionPath ~envCompletionIsMadeFrom ~opens + ~pos ~scope ~debug ~prefix ~env ~rawOpens ~full completionPath + |> TypeUtils.filterPipeableFunctions ~env ~full ~synthetic + ~targetTypeId:mainTypeId + |> List.filter (fun (c : Completion.t) -> + (* If we're completing from the current module then we need to care about scope. + This is automatically taken care of in other cases. *) + if isFromCurrentModule then + match c.kind with + | Value _ -> + scope + |> List.find_opt (fun (item : ScopeTypes.item) -> + match item with + | Value (scopeItemName, _, _, _) -> + scopeItemName = c.name + | _ -> false) + |> Option.is_some + | _ -> false + else true) in - let completions = - completions - |> List.map (fun (completion : Completion.t) -> - { - completion with - name = completionName completion.name; - env - (* Restore original env for the completion after x->foo()... *); - }) + (* Extra completions can be drawn from the @editor.completeFrom attribute. Here we + find and add those completions as well. *) + let extraCompletions = + TypeUtils.getExtraModulesToCompleteFromForType ~env ~full typ + |> List.map (fun completionPath -> + completionsForPipeFromCompletionPath ~envCompletionIsMadeFrom + ~opens ~pos ~scope ~debug ~prefix ~env ~rawOpens ~full + completionPath) + |> List.flatten + |> TypeUtils.filterPipeableFunctions ~synthetic:true ~env ~full + ~targetTypeId:mainTypeId in - (* We add React element functions to the completion if we're in a JSX context *) - let forJsxCompletion = + (* Add JSX completion items if we're in a JSX context. *) + let jsxCompletions = if inJsx then - match typ with - | Builtin (Int, t) -> Some ("int", t) - | Builtin (Float, t) -> Some ("float", t) - | Builtin (String, t) -> Some ("string", t) - | Builtin (Array, t) -> Some ("array", t) - | _ -> None - else None + PipeCompletionUtils.addJsxCompletionItems ~env ~mainTypeId ~prefix + ~full ~rawOpens typ + else [] in - match forJsxCompletion with - | Some (builtinNameToComplete, typ) - when Utils.checkName builtinNameToComplete ~prefix:funNamePrefix - ~exact:false -> - let name = - match package.genericJsxModule with - | None -> "React." ^ builtinNameToComplete - | Some g -> - g ^ "." ^ builtinNameToComplete - |> String.split_on_char '.' - |> TypeUtils.removeOpensFromCompletionPath ~rawOpens - ~package:full.package - |> String.concat "." - in - [ - Completion.create name ~includesSnippets:true ~kind:(Value typ) ~env - ~sortText:"A" - ~docstring: - [ - "Turns `" ^ builtinNameToComplete - ^ "` into a JSX element so it can be used inside of JSX."; - ]; - ] - @ completions - | _ -> completions) - | None -> [])) + jsxCompletions @ pipeCompletions @ extraCompletions)) | CTuple ctxPaths -> if Debug.verbose () then print_endline "[ctx_path]--> CTuple"; (* Turn a list of context paths into a list of type expressions. *) @@ -1416,7 +1436,7 @@ let rec completeTypedValue ?(typeArgContext : typeArgContext option) ~rawOpens in let getCompletionName exportedValueName = let fnNname = - TypeUtils.getPathRelativeToEnv ~debug:false + TypeUtils.getModulePathRelativeToEnv ~debug:false ~env:(QueryEnv.fromFile full.file) ~envFromItem:env (Utils.expandPath path) in @@ -1736,8 +1756,7 @@ let rec completeTypedValue ?(typeArgContext : typeArgContext option) ~rawOpens if prefix = "" then [ create "\"\"" ~includesSnippets:true ~insertText:"\"$0\"" ~sortText:"A" - ~kind: - (Value (Ctype.newconstr (Path.Pident (Ident.create "string")) [])) + ~kind:(Value (Ctype.newconstr Predef.path_string [])) ~env; ] else [] @@ -1926,7 +1945,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable = stamp = -1; fname = {loc = Location.none; txt = name}; optional = true; - typ = Ctype.newconstr (Path.Pident (Ident.create primitive)) []; + typ = Ctype.newconstr primitive []; docstring = []; deprecated = None; } @@ -1938,9 +1957,9 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable = definition = `NameOnly "jsxConfig"; fields = [ - mkField ~name:"version" ~primitive:"int"; - mkField ~name:"module_" ~primitive:"string"; - mkField ~name:"mode" ~primitive:"string"; + mkField ~name:"version" ~primitive:Predef.path_int; + mkField ~name:"module_" ~primitive:Predef.path_string; + mkField ~name:"mode" ~primitive:Predef.path_string; ]; } in @@ -1956,7 +1975,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable = stamp = -1; fname = {loc = Location.none; txt = name}; optional = true; - typ = Ctype.newconstr (Path.Pident (Ident.create primitive)) []; + typ = Ctype.newconstr primitive []; docstring = []; deprecated = None; } @@ -1966,7 +1985,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable = { env; definition = `NameOnly "importAttributesConfig"; - fields = [mkField ~name:"type_" ~primitive:"string"]; + fields = [mkField ~name:"type_" ~primitive:Predef.path_string]; } in let rootConfig : completionType = @@ -1976,8 +1995,8 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable = definition = `NameOnly "moduleConfig"; fields = [ - mkField ~name:"from" ~primitive:"string"; - mkField ~name:"with" ~primitive:"string"; + mkField ~name:"from" ~primitive:Predef.path_string; + mkField ~name:"with" ~primitive:Predef.path_string; ]; } in @@ -2074,8 +2093,8 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable = | Cdecorator prefix -> let mkDecorator (name, docstring, maybeInsertText) = { - (Completion.create name ~includesSnippets:true ~kind:(Label "") ~env - ?insertText:maybeInsertText) + (Completion.create name ~synthetic:true ~includesSnippets:true + ~kind:(Label "") ~env ?insertText:maybeInsertText) with docstring; } @@ -2339,8 +2358,9 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable = if Utils.startsWith elementName prefix then let name = "<" ^ elementName ^ ">" in Some - (Completion.create name ~kind:(Label name) ~detail:description - ~env ~docstring:[description] ~insertText:elementName + (Completion.create name ~synthetic:true ~kind:(Label name) + ~detail:description ~env ~docstring:[description] + ~insertText:elementName ?deprecated: (match deprecated with | true -> Some "true" @@ -2353,10 +2373,10 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable = implemented." in [ - Completion.create "todo" ~kind:(Label "todo") ~detail ~env - ~insertText:"todo"; - Completion.create "todo (with payload)" ~includesSnippets:true - ~kind:(Label "todo") + Completion.create "todo" ~synthetic:true ~kind:(Label "todo") ~detail + ~env ~insertText:"todo"; + Completion.create "todo (with payload)" ~synthetic:true + ~includesSnippets:true ~kind:(Label "todo") ~detail:(detail ^ " With a payload.") ~env ~insertText:"todo(\"${0:TODO}\")"; ] diff --git a/analysis/src/CompletionDecorators.ml b/analysis/src/CompletionDecorators.ml index 8319a5f4c..f43e5e16b 100644 --- a/analysis/src/CompletionDecorators.ml +++ b/analysis/src/CompletionDecorators.ml @@ -259,6 +259,11 @@ You will need this decorator whenever you want to use a JSX component in ReScrip [Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#variadic-decorator).|}; ] ); + ( "editor.completeFrom", + None, + [ + {|The `@editor.completeFrom` decorator instructs the editor where it can draw additional completions from for this type.|}; + ] ); ] let toplevel = diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index f5957a8ed..00cd2cb66 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -224,19 +224,32 @@ let rec exprToContextPathInner (e : Parsetree.expression) = (CPId {path = Utils.flattenLongIdent txt; completionContext = Value; loc}) | Pexp_field (e1, {txt = Lident name}) -> ( match exprToContextPath e1 with - | Some contextPath -> Some (CPField (contextPath, name)) + | Some contextPath -> + Some + (CPField + { + contextPath; + fieldName = name; + posOfDot = None; + exprLoc = e1.pexp_loc; + }) | _ -> None) - | Pexp_field (_, {loc; txt = Ldot (lid, name)}) -> + | Pexp_field (e1, {loc; txt = Ldot (lid, name)}) -> (* Case x.M.field ignore the x part *) Some (CPField - ( CPId - { - path = Utils.flattenLongIdent lid; - completionContext = Module; - loc; - }, - name )) + { + contextPath = + CPId + { + path = Utils.flattenLongIdent lid; + completionContext = Module; + loc; + }; + fieldName = name; + posOfDot = None; + exprLoc = e1.pexp_loc; + }) | Pexp_send (e1, {txt}) -> ( match exprToContextPath e1 with | None -> None @@ -327,6 +340,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor Some text.[offsetNoWhite] else None in + let posOfDot = Pos.posOfDot text ~pos:posCursor ~offset in let charAtCursor = if offset < String.length text then text.[offset] else '\n' in @@ -941,6 +955,32 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor setResult (Completable.CdecoratorPayload (JsxConfig {nested = List.rev nested; prefix}))) + | _ -> () + else if id.txt = "editor.completeFrom" then + match payload with + | PStr + [ + { + pstr_desc = + Pstr_eval + ( { + pexp_loc; + pexp_desc = Pexp_construct ({txt = path; loc}, None); + }, + _ ); + }; + ] + when locHasCursor pexp_loc -> + if Debug.verbose () then + print_endline "[decoratorCompletion] Found @editor.completeFrom"; + setResult + (Completable.Cpath + (CPId + { + path = Utils.flattenLongIdent path; + completionContext = Module; + loc; + })) | _ -> ()); Ast_iterator.default_iterator.attribute iterator (id, payload) in @@ -1010,6 +1050,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor (Cpath (CPPipe { + synthetic = false; contextPath = pipe; id; lhsLoc = lhs.pexp_loc; @@ -1020,7 +1061,14 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor | Some (pipe, lhsLoc) -> setResult (Cpath - (CPPipe {contextPath = pipe; id; lhsLoc; inJsx = !inJsxContext})); + (CPPipe + { + synthetic = false; + contextPath = pipe; + id; + lhsLoc; + inJsx = !inJsxContext; + })); true in typedCompletionExpr expr; @@ -1130,29 +1178,52 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor | Lident name -> ( match exprToContextPath e with | Some contextPath -> - let contextPath = Completable.CPField (contextPath, name) in + let contextPath = + Completable.CPField + { + contextPath; + fieldName = name; + posOfDot; + exprLoc = e.pexp_loc; + } + in setResult (Cpath contextPath) | None -> ()) | Ldot (id, name) -> (* Case x.M.field ignore the x part *) let contextPath = Completable.CPField - ( CPId - { - loc = fieldName.loc; - path = Utils.flattenLongIdent id; - completionContext = Module; - }, - if blankAfterCursor = Some '.' then - (* x.M. field ---> M. *) "" - else if name = "_" then "" - else name ) + { + contextPath = + CPId + { + loc = fieldName.loc; + path = Utils.flattenLongIdent id; + completionContext = Module; + }; + fieldName = + (if blankAfterCursor = Some '.' then + (* x.M. field ---> M. *) "" + else if name = "_" then "" + else name); + posOfDot; + exprLoc = e.pexp_loc; + } in setResult (Cpath contextPath) | Lapply _ -> () else if Loc.end_ e.pexp_loc = posBeforeCursor then match exprToContextPath e with - | Some contextPath -> setResult (Cpath (CPField (contextPath, ""))) + | Some contextPath -> + setResult + (Cpath + (CPField + { + contextPath; + fieldName = ""; + posOfDot; + exprLoc = e.pexp_loc; + })) | None -> ()) | Pexp_apply ({pexp_desc = Pexp_ident compName}, args) when Res_parsetree_viewer.is_jsx_expression expr -> diff --git a/analysis/src/DotCompletionUtils.ml b/analysis/src/DotCompletionUtils.ml new file mode 100644 index 000000000..fc2574279 --- /dev/null +++ b/analysis/src/DotCompletionUtils.ml @@ -0,0 +1,42 @@ +let filterRecordFields ~env ~recordAsString ~prefix ~exact fields = + fields + |> Utils.filterMap (fun (field : SharedTypes.field) -> + if Utils.checkName field.fname.txt ~prefix ~exact then + Some + (SharedTypes.Completion.create field.fname.txt ~env + ?deprecated:field.deprecated ~docstring:field.docstring + ~kind:(SharedTypes.Completion.Field (field, recordAsString))) + else None) + +let fieldCompletionsForDotCompletion ?posOfDot typ ~env ~package ~prefix ~exact + = + let asObject = typ |> TypeUtils.extractObjectType ~env ~package in + match asObject with + | Some (objEnv, obj) -> + (* Handle obj completion via dot *) + if Debug.verbose () then + Printf.printf "[dot_completion]--> Obj type found:\n"; + obj |> TypeUtils.getObjFields + |> Utils.filterMap (fun (field, _typ) -> + if Utils.checkName field ~prefix ~exact then + let fullObjFieldName = Printf.sprintf "[\"%s\"]" field in + Some + (SharedTypes.Completion.create fullObjFieldName ~synthetic:true + ~insertText:fullObjFieldName ~env:objEnv + ~kind:(SharedTypes.Completion.ObjLabel typ) + ?additionalTextEdits: + (match posOfDot with + | None -> None + | Some posOfDot -> + Some + (TypeUtils.makeAdditionalTextEditsForRemovingDot + posOfDot))) + else None) + | None -> ( + match typ |> TypeUtils.extractRecordType ~env ~package with + | Some (env, fields, typDecl) -> + fields + |> filterRecordFields ~env ~prefix ~exact + ~recordAsString: + (typDecl.item.decl |> Shared.declToString typDecl.name.txt) + | None -> []) diff --git a/analysis/src/Loc.ml b/analysis/src/Loc.ml index a9e42979c..2ab1d8fbd 100644 --- a/analysis/src/Loc.ml +++ b/analysis/src/Loc.ml @@ -12,3 +12,12 @@ let hasPos ~pos loc = start loc <= pos && pos < end_ loc (** Allows the character after the end to be included. Ie when the cursor is at the end of the word, like `someIdentifier`. Useful in some scenarios. *) let hasPosInclusiveEnd ~pos loc = start loc <= pos && pos <= end_ loc + +let mkPosition (pos : Pos.t) = + let line, character = pos in + {Protocol.line; character} + +let rangeOfLoc (loc : t) = + let start = loc |> start |> mkPosition in + let end_ = loc |> end_ |> mkPosition in + {Protocol.start; end_} diff --git a/analysis/src/PipeCompletionUtils.ml b/analysis/src/PipeCompletionUtils.ml new file mode 100644 index 000000000..f66c93e23 --- /dev/null +++ b/analysis/src/PipeCompletionUtils.ml @@ -0,0 +1,26 @@ +let addJsxCompletionItems ~mainTypeId ~env ~prefix ~(full : SharedTypes.full) + ~rawOpens typ = + match mainTypeId with + | ("array" | "float" | "string" | "int") as builtinNameToComplete -> + if Utils.checkName builtinNameToComplete ~prefix ~exact:false then + let name = + match full.package.genericJsxModule with + | None -> "React." ^ builtinNameToComplete + | Some g -> + g ^ "." ^ builtinNameToComplete + |> String.split_on_char '.' + |> TypeUtils.removeOpensFromCompletionPath ~rawOpens + ~package:full.package + |> String.concat "." + in + [ + SharedTypes.Completion.create name ~synthetic:true + ~includesSnippets:true ~kind:(Value typ) ~env ~sortText:"A" + ~docstring: + [ + "Turns `" ^ builtinNameToComplete + ^ "` into a JSX element so it can be used inside of JSX."; + ]; + ] + else [] + | _ -> [] diff --git a/analysis/src/Pos.ml b/analysis/src/Pos.ml index 081c575ea..e20af11e5 100644 --- a/analysis/src/Pos.ml +++ b/analysis/src/Pos.ml @@ -26,3 +26,19 @@ let positionToOffset text (line, character) = else None let posBeforeCursor pos = (fst pos, max 0 (snd pos - 1)) + +let posOfDot text ~(pos : int * int) ~offset = + let rec loop i = + if i < 0 then None + else + match text.[i] with + | '.' -> Some (i + 1) + | '\n' -> None + | _ -> loop (i - 1) + in + match loop (offset - 1) with + | None -> None + | Some offsetBeforeDot -> + let line, col = pos in + let newCol = max 0 (col - (offset - offsetBeforeDot)) in + Some (line, newCol) diff --git a/analysis/src/ProcessAttributes.ml b/analysis/src/ProcessAttributes.ml index 60ba88c21..10e43d511 100644 --- a/analysis/src/ProcessAttributes.ml +++ b/analysis/src/ProcessAttributes.ml @@ -48,3 +48,28 @@ let newDeclared ~item ~extent ~name ~stamp ~modulePath isExported attributes = | Some d -> [d]); item; } + +let rec findEditorCompleteFromAttribute ?(modulePaths = []) attributes = + let open Parsetree in + match attributes with + | [] -> modulePaths + | ( {Asttypes.txt = "editor.completeFrom"}, + PStr [{pstr_desc = Pstr_eval (payloadExpr, _)}] ) + :: rest -> + let items = + match payloadExpr with + | {pexp_desc = Pexp_array items} -> items + | p -> [p] + in + let modulePathsFromArray = + items + |> List.filter_map (fun item -> + match item.Parsetree.pexp_desc with + | Pexp_construct ({txt = path}, None) -> + Some (Utils.flattenLongIdent path) + | _ -> None) + in + findEditorCompleteFromAttribute + ~modulePaths:(modulePathsFromArray @ modulePaths) + rest + | _ :: rest -> findEditorCompleteFromAttribute ~modulePaths rest diff --git a/analysis/src/Protocol.ml b/analysis/src/Protocol.ml index 8297b3505..3631192cb 100644 --- a/analysis/src/Protocol.ml +++ b/analysis/src/Protocol.ml @@ -40,6 +40,8 @@ let insertTextFormatToInt f = match f with | Snippet -> 2 +type textEdit = {range: range; newText: string} + type completionItem = { label: string; kind: int; @@ -51,6 +53,7 @@ type completionItem = { insertText: string option; documentation: markupContent option; data: (string * string) list option; + additionalTextEdits: textEdit list option; } type location = {uri: string; range: range} @@ -61,8 +64,6 @@ type documentSymbolItem = { children: documentSymbolItem list; } type renameFile = {oldUri: string; newUri: string} -type textEdit = {range: range; newText: string} - type diagnostic = {range: range; message: string; severity: int} type optionalVersionedTextDocumentIdentifier = { @@ -104,6 +105,14 @@ let stringifyRange r = (stringifyPosition r.start) (stringifyPosition r.end_) +let stringifyTextEdit (te : textEdit) = + Printf.sprintf + {|{ + "range": %s, + "newText": %s + }|} + (stringifyRange te.range) (wrapInQuotes te.newText) + let stringifyMarkupContent (m : markupContent) = Printf.sprintf {|{"kind": %s, "value": %s}|} (wrapInQuotes m.kind) (wrapInQuotes m.value) @@ -156,6 +165,11 @@ let stringifyCompletionItem c = (fields |> List.map (fun (key, value) -> (key, Some (wrapInQuotes value))) |> stringifyObject ~indentation:2) ); + ( "additionalTextEdits", + match c.additionalTextEdits with + | Some additionalTextEdits -> + Some (additionalTextEdits |> List.map stringifyTextEdit |> array) + | None -> None ); ] let stringifyHover value = @@ -215,13 +229,6 @@ let stringifyRenameFile {oldUri; newUri} = }|} (wrapInQuotes oldUri) (wrapInQuotes newUri) -let stringifyTextEdit (te : textEdit) = - Printf.sprintf {|{ - "range": %s, - "newText": %s - }|} - (stringifyRange te.range) (wrapInQuotes te.newText) - let stringifyoptionalVersionedTextDocumentIdentifier td = Printf.sprintf {|{ "version": %s, @@ -282,7 +289,7 @@ let stringifyCodeAction ca = (wrapInQuotes (codeActionKindToString ca.codeActionKind)) (ca.edit |> stringifyCodeActionEdit) -let stringifyHint hint = +let stringifyHint (hint : inlayHint) = Printf.sprintf {|{ "position": %s, diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index aa3dffb1e..59675f181 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -611,10 +611,16 @@ module Completable = struct completionContext: completionContext; loc: Location.t; } - | CPField of contextPath * string + | CPField of { + contextPath: contextPath; + fieldName: string; + posOfDot: (int * int) option; + exprLoc: Location.t; + } | CPObj of contextPath * string | CPAwait of contextPath | CPPipe of { + synthetic: bool; (** Whether this pipe completion is synthetic. *) contextPath: contextPath; id: string; inJsx: bool; (** Whether this pipe was found in a JSX context. *) @@ -695,7 +701,8 @@ module Completable = struct | CPArray None -> "array" | CPId {path; completionContext} -> completionContextToString completionContext ^ list path - | CPField (cp, s) -> contextPathToString cp ^ "." ^ str s + | CPField {contextPath = cp; fieldName = s} -> + contextPathToString cp ^ "." ^ str s | CPObj (cp, s) -> contextPathToString cp ^ "[\"" ^ s ^ "\"]" | CPPipe {contextPath; id; inJsx} -> contextPathToString contextPath @@ -807,10 +814,14 @@ module Completion = struct detail: string option; typeArgContext: typeArgContext option; data: (string * string) list option; + additionalTextEdits: Protocol.textEdit list option; + synthetic: bool; + (** Whether this item is an made up, synthetic item or not. *) } - let create ?data ?typeArgContext ?(includesSnippets = false) ?insertText ~kind - ~env ?sortText ?deprecated ?filterText ?detail ?(docstring = []) name = + let create ?(synthetic = false) ?additionalTextEdits ?data ?typeArgContext + ?(includesSnippets = false) ?insertText ~kind ~env ?sortText ?deprecated + ?filterText ?detail ?(docstring = []) name = { name; env; @@ -825,6 +836,8 @@ module Completion = struct detail; typeArgContext; data; + additionalTextEdits; + synthetic; } (* https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion *) diff --git a/analysis/src/TypeUtils.ml b/analysis/src/TypeUtils.ml index 6701b57a7..2394f2803 100644 --- a/analysis/src/TypeUtils.ml +++ b/analysis/src/TypeUtils.ml @@ -1,5 +1,11 @@ open SharedTypes +let modulePathFromEnv env = env.QueryEnv.file.moduleName :: List.rev env.pathRev + +let fullTypeIdFromDecl ~env ~name ~modulePath = + env.QueryEnv.file.moduleName :: ModulePath.toPath modulePath name + |> String.concat "." + let debugLogTypeArgContext {env; typeArgs; typeParams} = Printf.sprintf "Type arg context. env: %s, typeArgs: %s, typeParams: %s\n" (Debug.debugPrintEnv env) @@ -259,6 +265,28 @@ let rec extractFunctionType ~env ~package typ = in loop ~env [] typ +let rec extractFunctionTypeWithEnv ~env ~package typ = + let rec loop ~env acc (t : Types.type_expr) = + match t.desc with + | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> loop ~env acc t1 + | Tarrow (label, tArg, tRet, _) -> loop ~env ((label, tArg) :: acc) tRet + | Tconstr (Pident {name = "function$"}, [t; _], _) -> + extractFunctionTypeWithEnv ~env ~package t + | Tconstr (path, typeArgs, _) -> ( + match References.digConstructor ~env ~package path with + | Some + ( env, + { + item = {decl = {type_manifest = Some t1; type_params = typeParams}}; + } ) -> + let t1 = t1 |> instantiateType ~typeParams ~typeArgs in + loop ~env acc t1 + | Some _ -> (List.rev acc, t, env) + | _ -> (List.rev acc, t, env)) + | _ -> (List.rev acc, t, env) + in + loop ~env [] typ + let maybeSetTypeArgCtx ?typeArgContextFromTypeManifest ~typeParams ~typeArgs env = match typeArgContextFromTypeManifest with @@ -463,6 +491,11 @@ let rec extractType ?(printOpeningDebug = true) if Debug.verbose () then print_endline "[extract_type]--> miss"; None +let isFunctionType ~env ~package t = + match extractType ~env ~package t with + | Some (Tfunction _, _) -> true + | _ -> false + let findReturnTypeOfFunctionAtLoc loc ~(env : QueryEnv.t) ~full ~debug = match References.getLocItem ~full ~pos:(loc |> Loc.end_) ~debug with | Some {locType = Typed (_, typExpr, _)} -> ( @@ -471,45 +504,6 @@ let findReturnTypeOfFunctionAtLoc loc ~(env : QueryEnv.t) ~full ~debug = | _ -> None) | _ -> None -type builtinType = - | Array - | Option - | String - | Int - | Float - | Promise - | List - | Result - | Lazy - | Char - | RegExp - -type pipeCompletionType = - | Builtin of builtinType * Types.type_expr - | TypExpr of Types.type_expr - -let getBuiltinFromTypePath path = - match path with - | Path.Pident _ -> ( - match Path.name path with - | "array" -> Some Array - | "option" -> Some Option - | "string" -> Some String - | "int" -> Some Int - | "float" -> Some Float - | "promise" -> Some Promise - | "list" -> Some List - | "result" -> Some Result - | "lazy_t" -> Some Lazy - | "char" -> Some Char - | _ -> None) - | Pdot (Pdot (Pident m, "Re", _), "t", _) when Ident.name m = "Js" -> - Some RegExp - | Pdot (Pident id, "result", _) - when Ident.name id = "Pervasives" || Ident.name id = "PervasivesU" -> - Some Result - | _ -> None - let rec digToRelevantTemplateNameType ~env ~package ?(suffix = "") (t : Types.type_expr) = match t.desc with @@ -528,44 +522,34 @@ let rec digToRelevantTemplateNameType ~env ~package ?(suffix = "") let rec resolveTypeForPipeCompletion ~env ~package ~lhsLoc ~full (t : Types.type_expr) = - let builtin = - match t |> pathFromTypeExpr with - | Some path -> path |> getBuiltinFromTypePath - | None -> None + (* If the type we're completing on is a type parameter, we won't be able to + do completion unless we know what that type parameter is compiled as. + This attempts to look up the compiled type for that type parameter by + looking for compiled information at the loc of that expression. *) + let typFromLoc = + match t with + | {Types.desc = Tvar _} -> + findReturnTypeOfFunctionAtLoc lhsLoc ~env ~full ~debug:false + | _ -> None in - match builtin with - | Some builtin -> (env, Builtin (builtin, t)) - | None -> ( - (* If the type we're completing on is a type parameter, we won't be able to - do completion unless we know what that type parameter is compiled as. - This attempts to look up the compiled type for that type parameter by - looking for compiled information at the loc of that expression. *) - let typFromLoc = - match t with - | {Types.desc = Tvar _} -> ( - match findReturnTypeOfFunctionAtLoc lhsLoc ~env ~full ~debug:false with - | None -> None - | Some typFromLoc -> Some typFromLoc) - | _ -> None + match typFromLoc with + | Some typFromLoc -> + typFromLoc |> resolveTypeForPipeCompletion ~lhsLoc ~env ~package ~full + | None -> + let rec digToRelevantType ~env ~package (t : Types.type_expr) = + match t.desc with + | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> + digToRelevantType ~env ~package t1 + (* Don't descend into types named "t". Type t is a convention in the ReScript ecosystem. *) + | Tconstr (path, _, _) when path |> Path.last = "t" -> (env, t) + | Tconstr (path, _, _) -> ( + match References.digConstructor ~env ~package path with + | Some (env, {item = {decl = {type_manifest = Some typ}}}) -> + digToRelevantType ~env ~package typ + | _ -> (env, t)) + | _ -> (env, t) in - match typFromLoc with - | Some typFromLoc -> - typFromLoc |> resolveTypeForPipeCompletion ~lhsLoc ~env ~package ~full - | None -> - let rec digToRelevantType ~env ~package (t : Types.type_expr) = - match t.desc with - | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> - digToRelevantType ~env ~package t1 - (* Don't descend into types named "t". Type t is a convention in the ReScript ecosystem. *) - | Tconstr (path, _, _) when path |> Path.last = "t" -> (env, TypExpr t) - | Tconstr (path, _, _) -> ( - match References.digConstructor ~env ~package path with - | Some (env, {item = {decl = {type_manifest = Some typ}}}) -> - digToRelevantType ~env ~package typ - | _ -> (env, TypExpr t)) - | _ -> (env, TypExpr t) - in - digToRelevantType ~env ~package t) + digToRelevantType ~env ~package t let extractTypeFromResolvedType (typ : Type.t) ~env ~full = match typ.kind with @@ -1074,7 +1058,7 @@ module Codegen = struct Ast_helper.Exp.case pat (mkFailWithExp ()))) end -let getPathRelativeToEnv ~debug ~(env : QueryEnv.t) ~envFromItem path = +let getModulePathRelativeToEnv ~debug ~(env : QueryEnv.t) ~envFromItem path = match path with | _ :: pathRev -> (* type path is relative to the completion environment @@ -1123,3 +1107,178 @@ let pathToElementProps package = match package.genericJsxModule with | None -> ["ReactDOM"; "domProps"] | Some g -> (g |> String.split_on_char '.') @ ["Elements"; "props"] + +module StringSet = Set.Make (String) + +let getExtraModulesToCompleteFromForType ~env ~full (t : Types.type_expr) = + let foundModulePaths = ref StringSet.empty in + let addToModulePaths attributes = + ProcessAttributes.findEditorCompleteFromAttribute attributes + |> List.iter (fun e -> + foundModulePaths := + StringSet.add (e |> String.concat ".") !foundModulePaths) + in + let rec inner ~env ~full (t : Types.type_expr) = + match t |> Shared.digConstructor with + | Some path -> ( + match References.digConstructor ~env ~package:full.package path with + | None -> () + | Some (env, {item = {decl = {type_manifest = Some t}; attributes}}) -> + addToModulePaths attributes; + inner ~env ~full t + | Some (_, {item = {attributes}}) -> addToModulePaths attributes) + | None -> () + in + inner ~env ~full t; + !foundModulePaths |> StringSet.elements + |> List.map (fun l -> String.split_on_char '.' l) + +let getFirstFnUnlabelledArgType ~env ~full t = + let labels, _, env = + extractFunctionTypeWithEnv ~env ~package:full.package t + in + let rec findFirstUnlabelledArgType labels = + match labels with + | (Asttypes.Nolabel, t) :: _ -> Some t + | _ :: rest -> findFirstUnlabelledArgType rest + | [] -> None + in + match findFirstUnlabelledArgType labels with + | Some t -> Some (t, env) + | _ -> None + +let makeAdditionalTextEditsForRemovingDot posOfDot = + [ + { + Protocol.range = + { + start = {line = fst posOfDot; character = snd posOfDot - 1}; + end_ = {line = fst posOfDot; character = snd posOfDot}; + }; + newText = ""; + }; + ] + +(** Turns a completion into a pipe completion. *) +let transformCompletionToPipeCompletion ?(synthetic = false) ~env ?posOfDot + (completion : Completion.t) = + let name = completion.name in + let nameWithPipe = "->" ^ name in + Some + { + completion with + name = nameWithPipe; + sortText = Some (name |> String.split_on_char '.' |> List.rev |> List.hd); + insertText = Some nameWithPipe; + env; + synthetic; + additionalTextEdits = + (match posOfDot with + | None -> None + | Some posOfDot -> Some (makeAdditionalTextEditsForRemovingDot posOfDot)); + } + +(** This takes a type expr and the env that type expr was found in, and produces a globally unique + id for that specific type. The globally unique id is the full path to the type as seen from the root + of the project. Example: type x in module SomeModule in file SomeFile would get the globally + unique id `SomeFile.SomeModule.x`.*) +let rec findRootTypeId ~full ~env (t : Types.type_expr) = + let debug = false in + match t.desc with + | Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> findRootTypeId ~full ~env t1 + | Tconstr (Pident {name = "function$"}, [t; _], _) -> + findRootTypeId ~full ~env t + | Tconstr (path, _, _) -> ( + (* We have a path. Try to dig to its declaration *) + if debug then + Printf.printf "[findRootTypeId] path %s, dig\n" (Path.name path); + match References.digConstructor ~env ~package:full.package path with + | Some (env, {item = {decl = {type_manifest = Some t1}}}) -> + if debug then + Printf.printf "[findRootTypeId] dug up type alias at module path %s \n" + (modulePathFromEnv env |> String.concat "."); + findRootTypeId ~full ~env t1 + | Some (env, {item = {name}; modulePath}) -> + (* if it's a named type, then we know its name will be its module path from the env + its name.*) + if debug then + Printf.printf + "[findRootTypeId] dug up named type at module path %s, from item: %s \n" + (modulePathFromEnv env |> String.concat ".") + (ModulePath.toPath modulePath name |> String.concat "."); + Some (fullTypeIdFromDecl ~env ~name ~modulePath) + | None -> + (* If we didn't find anything, then it might be a builtin type. Check it.*) + if debug then Printf.printf "[findRootTypeId] dug up non-type alias\n"; + if + Predef.builtin_idents + |> List.find_opt (fun (_, i) -> Ident.same i (Path.head path)) + |> Option.is_some + then + Some + (if debug then Printf.printf "[findRootTypeId] returning builtin\n"; + Path.name path) + else None) + | _ -> None + +(** Filters out completions that are not pipeable from a list of completions. *) +let filterPipeableFunctions ~env ~full ?synthetic ?targetTypeId ?posOfDot + completions = + match targetTypeId with + | None -> completions + | Some targetTypeId -> + completions + |> List.filter_map (fun (completion : Completion.t) -> + let thisCompletionItemTypeId = + match completion.kind with + | Value t -> ( + match + getFirstFnUnlabelledArgType ~full ~env:completion.env t + with + | None -> None + | Some (t, envFromLabelledArg) -> + findRootTypeId ~full ~env:envFromLabelledArg t) + | _ -> None + in + match thisCompletionItemTypeId with + | Some mainTypeId when mainTypeId = targetTypeId -> ( + match posOfDot with + | None -> Some completion + | Some posOfDot -> + transformCompletionToPipeCompletion ?synthetic ~env ~posOfDot + completion) + | _ -> None) + +let removeCurrentModuleIfNeeded ~envCompletionIsMadeFrom completionPath = + if + List.length completionPath > 0 + && List.hd completionPath = envCompletionIsMadeFrom.QueryEnv.file.moduleName + then List.tl completionPath + else completionPath + +let rec getObjFields (texp : Types.type_expr) = + match texp.desc with + | Tfield (name, _, t1, t2) -> + let fields = t2 |> getObjFields in + (name, t1) :: fields + | Tlink te | Tsubst te | Tpoly (te, []) -> te |> getObjFields + | Tvar None -> [] + | _ -> [] + +let pathToBuiltin path = + Predef.builtin_idents + |> List.find_opt (fun (_, i) -> Ident.same i (Path.head path)) + +let completionPathFromMaybeBuiltin path ~package = + match pathToBuiltin path with + | Some ("array", _) -> Some package.builtInCompletionModules.arrayModulePath + | Some ("option", _) -> Some package.builtInCompletionModules.optionModulePath + | Some ("string", _) -> Some package.builtInCompletionModules.stringModulePath + | Some ("int", _) -> Some package.builtInCompletionModules.intModulePath + | Some ("float", _) -> Some package.builtInCompletionModules.floatModulePath + | Some ("promise", _) -> + Some package.builtInCompletionModules.promiseModulePath + | Some ("list", _) -> Some package.builtInCompletionModules.listModulePath + | Some ("result", _) -> Some package.builtInCompletionModules.resultModulePath + | Some ("dict", _) -> Some ["Dict"] + | Some ("char", _) -> Some ["Char"] + | _ -> None diff --git a/analysis/src/Xform.ml b/analysis/src/Xform.ml index 64c90be18..904fa5bf8 100644 --- a/analysis/src/Xform.ml +++ b/analysis/src/Xform.ml @@ -2,15 +2,6 @@ let isBracedExpr = Res_parsetree_viewer.is_braced_expr -let mkPosition (pos : Pos.t) = - let line, character = pos in - {Protocol.line; character} - -let rangeOfLoc (loc : Location.t) = - let start = loc |> Loc.start |> mkPosition in - let end_ = loc |> Loc.end_ |> mkPosition in - {Protocol.start; end_} - let extractTypeFromExpr expr ~debug ~path ~currentFile ~full ~pos = match expr.Parsetree.pexp_loc @@ -144,7 +135,7 @@ module IfThenElse = struct match !changed with | None -> () | Some newExpr -> - let range = rangeOfLoc newExpr.pexp_loc in + let range = Loc.rangeOfLoc newExpr.pexp_loc in let newText = printExpr ~range newExpr in let codeAction = CodeActions.make ~title:"Replace with switch" ~kind:RefactorRewrite @@ -161,7 +152,7 @@ module ModuleToFile = struct | Pstr_module {pmb_loc; pmb_name; pmb_expr = {pmod_desc = Pmod_structure structure}} when structure_item.pstr_loc |> Loc.hasPos ~pos -> - let range = rangeOfLoc structure_item.pstr_loc in + let range = Loc.rangeOfLoc structure_item.pstr_loc in let newTextInCurrentFile = "" in let textForExtractedFile = printStandaloneStructure ~loc:pmb_loc structure @@ -280,7 +271,7 @@ module AddBracesToFn = struct match !changed with | None -> () | Some newStructureItem -> - let range = rangeOfLoc newStructureItem.pstr_loc in + let range = Loc.rangeOfLoc newStructureItem.pstr_loc in let newText = printStructureItem ~range newStructureItem in let codeAction = CodeActions.make ~title:"Add braces to function" ~kind:RefactorRewrite @@ -349,10 +340,10 @@ module AddTypeAnnotation = struct let range, newText = match annotation with | Plain -> - ( rangeOfLoc {locItem.loc with loc_start = locItem.loc.loc_end}, + ( Loc.rangeOfLoc {locItem.loc with loc_start = locItem.loc.loc_end}, ": " ^ (typ |> Shared.typeToString) ) | WithParens -> - ( rangeOfLoc locItem.loc, + ( Loc.rangeOfLoc locItem.loc, "(" ^ name ^ ": " ^ (typ |> Shared.typeToString) ^ ")" ) in let codeAction = @@ -439,7 +430,7 @@ module ExpandCatchAllForVariants = struct | Args _ | InlineRecord _ -> "(_)") |> String.concat " | " in - let range = rangeOfLoc catchAllCase.pc_lhs.ppat_loc in + let range = Loc.rangeOfLoc catchAllCase.pc_lhs.ppat_loc in let codeAction = CodeActions.make ~title:"Expand catch-all" ~kind:RefactorRewrite ~uri:path ~newText ~range @@ -463,7 +454,7 @@ module ExpandCatchAllForVariants = struct | _ -> "(_)") |> String.concat " | " in - let range = rangeOfLoc catchAllCase.pc_lhs.ppat_loc in + let range = Loc.rangeOfLoc catchAllCase.pc_lhs.ppat_loc in let codeAction = CodeActions.make ~title:"Expand catch-all" ~kind:RefactorRewrite ~uri:path ~newText ~range @@ -532,7 +523,7 @@ module ExpandCatchAllForVariants = struct let newText = if hasNoneCase then newText else newText ^ " | None" in - let range = rangeOfLoc catchAllCase.pc_lhs.ppat_loc in + let range = Loc.rangeOfLoc catchAllCase.pc_lhs.ppat_loc in let codeAction = CodeActions.make ~title:"Expand catch-all" ~kind:RefactorRewrite ~uri:path ~newText ~range @@ -627,7 +618,7 @@ module ExhaustiveSwitch = struct match exhaustiveSwitch with | None -> () | Some cases -> - let range = rangeOfLoc expr.pexp_loc in + let range = Loc.rangeOfLoc expr.pexp_loc in let newText = printExpr ~range {expr with pexp_desc = Pexp_match (expr, cases)} in @@ -652,7 +643,7 @@ module ExhaustiveSwitch = struct match exhaustiveSwitch with | None -> () | Some cases -> - let range = rangeOfLoc switchExpr.pexp_loc in + let range = Loc.rangeOfLoc switchExpr.pexp_loc in let newText = printExpr ~range {switchExpr with pexp_desc = Pexp_match (completionExpr, cases)} @@ -752,7 +743,7 @@ module AddDocTemplate = struct match newSignatureItem with | Some signatureItem -> - let range = rangeOfLoc signatureItem.psig_loc in + let range = Loc.rangeOfLoc signatureItem.psig_loc in let newText = printSignatureItem ~range signatureItem in let codeAction = CodeActions.make ~title:"Add Documentation template" @@ -837,7 +828,7 @@ module AddDocTemplate = struct match newStructureItem with | Some structureItem -> - let range = rangeOfLoc structureItem.pstr_loc in + let range = Loc.rangeOfLoc structureItem.pstr_loc in let newText = printStructureItem ~range structureItem in let codeAction = CodeActions.make ~title:"Add Documentation template" diff --git a/analysis/tests-generic-jsx-transform/src/expected/GenericJsxCompletion.res.txt b/analysis/tests-generic-jsx-transform/src/expected/GenericJsxCompletion.res.txt index 9368a52a3..daf436d52 100644 --- a/analysis/tests-generic-jsx-transform/src/expected/GenericJsxCompletion.res.txt +++ b/analysis/tests-generic-jsx-transform/src/expected/GenericJsxCompletion.res.txt @@ -63,8 +63,8 @@ Resolved opens 1 pervasives ContextPath Value[someString]->st <> ContextPath Value[someString] Path someString -CPPipe env:GenericJsxCompletion -Path Js.String2.st +CPPipe pathFromEnv: found:true +Path GenericJsxCompletion.st [{ "label": "GenericJsx.string", "kind": 12, @@ -73,18 +73,6 @@ Path Js.String2.st "documentation": {"kind": "markdown", "value": "Turns `string` into a JSX element so it can be used inside of JSX."}, "sortText": "A", "insertTextFormat": 2 - }, { - "label": "Js.String2.startsWith", - "kind": 12, - "tags": [], - "detail": "(t, t) => bool", - "documentation": {"kind": "markdown", "value": "\nES2015: `startsWith(str, substr)` returns `true` if the `str` starts with\n`substr`, `false` otherwise.\n\nSee [`String.startsWith`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith)\non MDN.\n\n## Examples\n\n```rescript\nJs.String2.startsWith(\"ReScript\", \"Re\") == true\nJs.String2.startsWith(\"ReScript\", \"\") == true\nJs.String2.startsWith(\"JavaScript\", \"Re\") == false\n```\n"} - }, { - "label": "Js.String2.startsWithFrom", - "kind": 12, - "tags": [], - "detail": "(t, t, int) => bool", - "documentation": {"kind": "markdown", "value": "\nES2015: `startsWithFrom(str, substr, n)` returns `true` if the `str` starts\nwith `substr` starting at position `n`, false otherwise. If `n` is negative,\nthe search starts at the beginning of `str`.\n\nSee [`String.startsWith`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith)\non MDN.\n\n## Examples\n\n```rescript\nJs.String2.startsWithFrom(\"ReScript\", \"Scri\", 2) == true\nJs.String2.startsWithFrom(\"ReScript\", \"\", 2) == true\nJs.String2.startsWithFrom(\"JavaScript\", \"Scri\", 2) == false\n```\n"} }] Complete src/GenericJsxCompletion.res 20:24 @@ -112,8 +100,8 @@ Resolved opens 2 pervasives GenericJsx.res ContextPath Value[someString]->st <> ContextPath Value[someString] Path someString -CPPipe env:GenericJsxCompletion -Path Js.String2.st +CPPipe pathFromEnv: found:true +Path GenericJsxCompletion.st [{ "label": "string", "kind": 12, @@ -122,17 +110,5 @@ Path Js.String2.st "documentation": {"kind": "markdown", "value": "Turns `string` into a JSX element so it can be used inside of JSX."}, "sortText": "A", "insertTextFormat": 2 - }, { - "label": "Js.String2.startsWith", - "kind": 12, - "tags": [], - "detail": "(t, t) => bool", - "documentation": {"kind": "markdown", "value": "\nES2015: `startsWith(str, substr)` returns `true` if the `str` starts with\n`substr`, `false` otherwise.\n\nSee [`String.startsWith`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith)\non MDN.\n\n## Examples\n\n```rescript\nJs.String2.startsWith(\"ReScript\", \"Re\") == true\nJs.String2.startsWith(\"ReScript\", \"\") == true\nJs.String2.startsWith(\"JavaScript\", \"Re\") == false\n```\n"} - }, { - "label": "Js.String2.startsWithFrom", - "kind": 12, - "tags": [], - "detail": "(t, t, int) => bool", - "documentation": {"kind": "markdown", "value": "\nES2015: `startsWithFrom(str, substr, n)` returns `true` if the `str` starts\nwith `substr` starting at position `n`, false otherwise. If `n` is negative,\nthe search starts at the beginning of `str`.\n\nSee [`String.startsWith`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith)\non MDN.\n\n## Examples\n\n```rescript\nJs.String2.startsWithFrom(\"ReScript\", \"Scri\", 2) == true\nJs.String2.startsWithFrom(\"ReScript\", \"\", 2) == true\nJs.String2.startsWithFrom(\"JavaScript\", \"Scri\", 2) == false\n```\n"} }] diff --git a/analysis/tests/package-lock.json b/analysis/tests/package-lock.json index aa28542ff..cd47acceb 100644 --- a/analysis/tests/package-lock.json +++ b/analysis/tests/package-lock.json @@ -5,7 +5,7 @@ "packages": { "": { "dependencies": { - "rescript": "^11.1.0" + "rescript": "11.1.4" }, "devDependencies": { "@rescript/react": "0.12.0" @@ -69,9 +69,9 @@ } }, "node_modules/rescript": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/rescript/-/rescript-11.1.0.tgz", - "integrity": "sha512-9la2Dv+ACylQ77I8s4spPu1JnLZXbH5WgxcLHLLUBWgFFSiv0wXqgzWztrBIZqwFgVX5BYcwldUqUVcEzdCyHg==", + "version": "11.1.4", + "resolved": "https://registry.npmjs.org/rescript/-/rescript-11.1.4.tgz", + "integrity": "sha512-0bGU0bocihjSC6MsE3TMjHjY0EUpchyrREquLS8VsZ3ohSMD+VHUEwimEfB3kpBI1vYkw3UFZ3WD8R28guz/Vw==", "hasInstallScript": true, "bin": { "bsc": "bsc", @@ -140,9 +140,9 @@ } }, "rescript": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/rescript/-/rescript-11.1.0.tgz", - "integrity": "sha512-9la2Dv+ACylQ77I8s4spPu1JnLZXbH5WgxcLHLLUBWgFFSiv0wXqgzWztrBIZqwFgVX5BYcwldUqUVcEzdCyHg==" + "version": "11.1.4", + "resolved": "https://registry.npmjs.org/rescript/-/rescript-11.1.4.tgz", + "integrity": "sha512-0bGU0bocihjSC6MsE3TMjHjY0EUpchyrREquLS8VsZ3ohSMD+VHUEwimEfB3kpBI1vYkw3UFZ3WD8R28guz/Vw==" }, "scheduler": { "version": "0.23.0", diff --git a/analysis/tests/package.json b/analysis/tests/package.json index c34977ca6..3d9b9a107 100644 --- a/analysis/tests/package.json +++ b/analysis/tests/package.json @@ -8,6 +8,6 @@ "@rescript/react": "0.12.0" }, "dependencies": { - "rescript": "^11.1.0" + "rescript": "11.1.4" } } diff --git a/analysis/tests/src/CompletePrioritize1.res b/analysis/tests/src/CompletePrioritize1.res index 5fcccf3de..39c1775ec 100644 --- a/analysis/tests/src/CompletePrioritize1.res +++ b/analysis/tests/src/CompletePrioritize1.res @@ -1,6 +1,7 @@ module Test = { type t = {name: int} let add = (a: float) => a +. 1.0 + let name = t => t.name } let a: Test.t = {name: 4} // a-> diff --git a/analysis/tests/src/CompletionFromModule.res b/analysis/tests/src/CompletionFromModule.res new file mode 100644 index 000000000..d18624836 --- /dev/null +++ b/analysis/tests/src/CompletionFromModule.res @@ -0,0 +1,44 @@ +module SomeModule = { + type t = {name: string} + + @get external getName: t => string = "name" + + let thisShouldNotBeCompletedFor = () => "hi" +} + +let n = {SomeModule.name: "hello"} + +// n. +// ^com + +@editor.completeFrom(CompletionFromModule.SomeOtherModule) +type typeOutsideModule = {nname: string} + +module SomeOtherModule = { + type t = typeOutsideModule + + type irrelevantType = string + + @get external getNName: t => string = "nname" + @get external getNName2: typeOutsideModule => string = "nname" + @get external getNName3: irrelevantType => string = "nname" + + let thisShouldNotBeCompletedFor = () => "hi" +} + +let nn: SomeOtherModule.t = {nname: "hello"} + +// nn. +// ^com + +// @editor.completeFrom(SomeOthe) type typeOutsideModule = {nname: string} +// ^com + +let nnn: typeOutsideModule = {nname: "hello"} + +// nnn-> +// ^com + +open SomeOtherModule +// nnn-> +// ^com diff --git a/analysis/tests/src/CompletionFromModule2.res b/analysis/tests/src/CompletionFromModule2.res new file mode 100644 index 000000000..61776cee1 --- /dev/null +++ b/analysis/tests/src/CompletionFromModule2.res @@ -0,0 +1,14 @@ +// Used to check completions across files + +// CompletionFromModule.n. +// ^com + +// CompletionFromModule.nn. +// ^com + +// CompletionFromModule.nnn-> +// ^com + +open CompletionFromModule.SomeOtherModule +// CompletionFromModule.nnn-> +// ^com diff --git a/analysis/tests/src/CompletionInferValues.res b/analysis/tests/src/CompletionInferValues.res index f0edbfe8c..48ce0e253 100644 --- a/analysis/tests/src/CompletionInferValues.res +++ b/analysis/tests/src/CompletionInferValues.res @@ -13,7 +13,7 @@ let reactEventFn = (cb: ReactEvent.Mouse.t => unit) => { @val external getSomeRecord: unit => someRecord = "getSomeRecord" -// let x = 123; let aliased = x; aliased->f +// let x = 123; let aliased = x; aliased->t // ^com // let x = getSomeRecord(); x. @@ -54,9 +54,6 @@ module Div = { // let _ =
{ let btn = event->JsxEvent.Mouse.button->Belt.Int.toString->Js.String2.split("/"); btn->ma }} /> // ^com -// let x: someRecord = {name: "Hello", age: 123}; x. -// ^com - type someVariant = One | Two | Three(int, string) type somePolyVariant = [#one | #two | #three(int, string)] type someNestedRecord = {someRecord: someRecord} @@ -115,10 +112,6 @@ type otherNestedRecord = { // let x: otherNestedRecord; switch x { | {optRecord:Some({name})} => name->slic } // ^com -// Follow arrays -// let x: array; switch x { | [inner] => inner.s } -// ^com - // Infer top level return // let x = 123; switch x { | 123 => () | v => v->toSt } // ^com @@ -166,4 +159,4 @@ let fn3 = (~cb: sameFileRecord => unit) => { // Handles reusing the same name already in scope for bindings let res = 1 // switch res { | res => res } -// ^hov \ No newline at end of file +// ^hov diff --git a/analysis/tests/src/CompletionMultipleEditorCompleteFrom.res b/analysis/tests/src/CompletionMultipleEditorCompleteFrom.res new file mode 100644 index 000000000..35950e161 --- /dev/null +++ b/analysis/tests/src/CompletionMultipleEditorCompleteFrom.res @@ -0,0 +1,22 @@ +@@warning("-26") +@@warning("-27") +@@warning("-110") + +module A = { + @editor.completeFrom(B) @editor.completeFrom(C) + type a +} + +module B = { + let b = (a: A.a) => 1 +} + +module C = { + open A + let c = (a: a) => {'c'} +} + +let a : A.a = %todo +// a. +// ^com +// B.b and C.c should be completed \ No newline at end of file diff --git a/analysis/tests/src/CompletionPipeChain.res b/analysis/tests/src/CompletionPipeChain.res index 2a16c21cf..adfdc6548 100644 --- a/analysis/tests/src/CompletionPipeChain.res +++ b/analysis/tests/src/CompletionPipeChain.res @@ -103,3 +103,12 @@ let r = %re("/t/g") // r->la // ^com + +module Xyz = { + type xx = One + let do = (_: xx) => "" +} + +let xx = Xyz.One +// xx-> +// ^com diff --git a/analysis/tests/src/CompletionPipeProperty.res b/analysis/tests/src/CompletionPipeProperty.res new file mode 100644 index 000000000..3ef739ed9 --- /dev/null +++ b/analysis/tests/src/CompletionPipeProperty.res @@ -0,0 +1,23 @@ +module ObservablePoint = { + type op = { + mutable x: int, + mutable y: int, + } + + @send + external setBoth: (op, float) => unit = "set" + + @send + external set: (op, float, float) => unit = "set" +} + +module Sprite = { + type s = { + anchor: ObservablePoint.op, + } +} + +let sprite : Sprite.s = %todo + +// sprite.anchor. +// ^com \ No newline at end of file diff --git a/analysis/tests/src/CompletionPipeSubmodules.res b/analysis/tests/src/CompletionPipeSubmodules.res index a3ee0af8d..5870f5345 100644 --- a/analysis/tests/src/CompletionPipeSubmodules.res +++ b/analysis/tests/src/CompletionPipeSubmodules.res @@ -2,11 +2,12 @@ module A = { module B1 = { type b1 = B1 let xx = B1 + let d = (_: b1) => "" } module B2 = { let yy = 20 } - type t = {v: B1.b1} + type t2 = {v: B1.b1} let x = {v: B1.B1} } @@ -20,11 +21,13 @@ module A = { module C = { type t = C + let do = (_: t) => "" } module D = { module C2 = { type t2 = C2 + let do = (_: t2) => "" } type d = {v: C.t, v2: C2.t2} diff --git a/analysis/tests/src/DotPipeCompletionSpec.res b/analysis/tests/src/DotPipeCompletionSpec.res new file mode 100644 index 000000000..9e141cb2c --- /dev/null +++ b/analysis/tests/src/DotPipeCompletionSpec.res @@ -0,0 +1,146 @@ +// +module SomeModule = { + type t = {name: string} + + @get external getName: t => string = "name" + @send + external withUnlabelledArgumentNotFirst: (~name: string=?, t) => unit = + "withUnlabelledArgumentNotFirst" + + let thisShouldNotBeCompletedFor = () => "hi" +} + +let n = {SomeModule.name: "hello"} + +// Type from inside of a module +// n. +// ^com + +@editor.completeFrom(DotPipeCompletionSpec.SomeOtherModule) +type typeOutsideModule = {nname: string} + +let doWithTypeOutsideModule = (_: typeOutsideModule) => "" + +module CompleteFromThisToo = { + external a: typeOutsideModule => string = "a" + external b: unit => typeOutsideModule = "b" +} + +module SomeOtherModule = { + @editor.completeFrom(DotPipeCompletionSpec.CompleteFromThisToo) + type t = typeOutsideModule + + type irrelevantType = string + + @get external getNName: t => string = "nname" + @get external getNName2: typeOutsideModule => string = "nname" + @get external getNName3: irrelevantType => string = "nname" + + let thisShouldNotBeCompletedFor = () => "hi" +} + +let nn: SomeOtherModule.t = {nname: "hello"} + +// Type from module but that's an alias +// nn. +// ^com + +module A = { + @editor.completeFrom(B) + type a + + external withA: a => unit = "withA" + external make: unit => a = "makeA" +} + +module B = { + let b = (_a: A.a) => 1 +} + +external a: A.a = "a" + +// Main type in other module +// a. +// ^com + +let xx: CompletionFromModule.SomeModule.t = {name: "hello"} +// Type from other file +// xx. +// ^com + +type builtinType = array + +let ffff: builtinType = [] + +// A built in type +// ffff.u +// ^com + +// Type outside of module with complete from pointing to other module +let nnn: typeOutsideModule = {nname: "hello"} +// nnn. +// ^com + +// Continuous completion +let xxxx = [1, 2] + +// xxxx->Js.Array2.filter(v => v > 10).filt +// ^com + +// xxxx->Js.Array2.filter(v => v > 10)->Js.Array2.joinWith(",").includ +// ^com + +let str = "hello" + +// str->Js.String2.toLowerCase.toUpperCa +// ^com + +// str->Js.String2.toLowerCase->Js.String2.toUpperCase.toLowerC +// ^com + +let cc = (t: typeOutsideModule) => { + // t. + // ^com + t +} + +let outOfScope = (t: typeOutsideModule) => t + +// @editor.completeFrom(Dot) type t +// ^com + +// @editor.completeFrom([CompletionPipe]) type t +// ^com + +// @editor.completeFrom([CompletionPipe, Dot]) type t +// ^com + +let someObj = { + "name": "hello", + "age": 123, +} + +// someObj. +// ^com + +// someObj.na +// ^com + +module DOMAPI = { + type htmlElement = {prefix: string} + + @editor.completeFrom(DotPipeCompletionSpec.HTMLButtonElement) + type rec htmlButtonElement = {mutable disabled: bool} +} + +module HTMLButtonElement = { + open DOMAPI + + @send + external checkValidity: htmlButtonElement => bool = "checkValidity" +} + +external button: DOMAPI.htmlButtonElement = "button" + +// button. +// ^com diff --git a/analysis/tests/src/Rxjs.res b/analysis/tests/src/Rxjs.res new file mode 100644 index 000000000..8d3cecbc1 --- /dev/null +++ b/analysis/tests/src/Rxjs.res @@ -0,0 +1,51 @@ +// These are bindings used in RxjsCompletion.res +// We are using a separate file to test complication for modules of external files. +type target + +module Subscriber = { + type t<'t> = {next: 't => unit} +} + +module Observable = { + // Complete items defined inside the parent module. + @editor.completeFrom(Rxjs) + type t<'t> + + type dispose = unit => unit + + @new @module("rxjs") + external make: (Subscriber.t<'t> => dispose) => t<'t> = "Observable" + + type subscription + + @send + external subscribe: (t<'t>, 't => unit) => subscription = "subscribe" +} + +@module("rxjs") +external fromEvent: (target, string) => Observable.t<'t> = "fromEvent" + +type operation<'t, 'u> + +@send +external pipe: (Observable.t<'t>, operation<'t, 'u>) => Observable.t<'u> = "pipe" + +@send +external pipe2: (Observable.t<'t>, operation<'t, 'u>, operation<'u, 'i>) => Observable.t<'i> = + "pipe" + +@module("rxjs") +external map: ('t => 'u) => operation<'t, 'u> = "map" + +@module("rxjs") +external distinctUntilChanged: unit => operation<'t, 't> = "distinctUntilChanged" + +@module("rxjs") +external merge: (Observable.t<'t>, Observable.t<'t>) => Observable.t<'t> = "merge" + +@module("rxjs") +external scan: (('acc, 't) => 'acc, 'acc) => operation<'t, 'acc> = "scan" + +@module("rxjs") +external combineLatest: (Observable.t<'a>, Observable.t<'b>) => Observable.t<('a, 'b)> = + "combineLatest" diff --git a/analysis/tests/src/RxjsCompletion.res b/analysis/tests/src/RxjsCompletion.res new file mode 100644 index 000000000..eaf2b40d4 --- /dev/null +++ b/analysis/tests/src/RxjsCompletion.res @@ -0,0 +1,39 @@ +@@warning("-26") +@@warning("-110") + +type keyPress = + | Up(string) + | Down(string) + +@val +external window: {..} = "window" + +let main = async () => { + let keyMapObservable = { + open Rxjs + + let keydown = + fromEvent(Obj.magic(window), "keydown")->pipe2( + map(event => Down(event["key"])), + distinctUntilChanged(), + ) + + let keyup = + fromEvent(Obj.magic(window), "keyup")->pipe2( + map(event => Up(event["key"])), + distinctUntilChanged(), + ) + + // merge(keydown, keyup). + // ^com + + // Rxjs.Observable.subscribe, Rxjs.pipe and Rxjs.pipe2 should be completed + } + + let (a,b) : ( Rxjs.Observable.t , Rxjs.Observable.t) = %todo + + // Rxjs.combineLatest(a, b). + // ^com + + // Rxjs.Observable.subscribe, Rxjs.pipe and Rxjs.pipe2 should be completed +} diff --git a/analysis/tests/src/expected/CompletePrioritize1.res.txt b/analysis/tests/src/expected/CompletePrioritize1.res.txt index b520a84a2..6ba73f80e 100644 --- a/analysis/tests/src/expected/CompletePrioritize1.res.txt +++ b/analysis/tests/src/expected/CompletePrioritize1.res.txt @@ -1,20 +1,18 @@ -Complete src/CompletePrioritize1.res 5:6 -posCursor:[5:6] posNoWhite:[5:5] Found expr:[5:3->0:-1] +Complete src/CompletePrioritize1.res 6:6 +posCursor:[6:6] posNoWhite:[6:5] Found expr:[6:3->0:-1] Completable: Cpath Value[a]-> Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives ContextPath Value[a]-> ContextPath Value[a] Path a -CPPipe env:CompletePrioritize1 -CPPipe type path:Test.t CPPipe pathFromEnv:Test found:true Path Test. [{ - "label": "Test.add", + "label": "Test.name", "kind": 12, "tags": [], - "detail": "float => float", + "detail": "t => int", "documentation": null }] diff --git a/analysis/tests/src/expected/CompletePrioritize2.res.txt b/analysis/tests/src/expected/CompletePrioritize2.res.txt index b6bea71f9..b8a2e04ee 100644 --- a/analysis/tests/src/expected/CompletePrioritize2.res.txt +++ b/analysis/tests/src/expected/CompletePrioritize2.res.txt @@ -6,8 +6,6 @@ Resolved opens 1 pervasives ContextPath Value[ax]-> ContextPath Value[ax] Path ax -CPPipe env:CompletePrioritize2 -CPPipe type path:Test.t CPPipe pathFromEnv:Test found:true Path Test. [{ diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index ccadf462f..6b8c8577a 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -404,7 +404,6 @@ Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives ContextPath array->m ContextPath array -CPPipe env:Completion Path Js.Array2.m [{ "label": "Js.Array2.mapi", @@ -427,7 +426,6 @@ Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives ContextPath string->toU ContextPath string -CPPipe env:Completion Path Js.String2.toU [{ "label": "Js.String2.toUpperCase", @@ -445,7 +443,6 @@ Resolved opens 1 pervasives ContextPath Value[op]->e ContextPath Value[op] Path op -CPPipe env:Completion Path Belt.Option.e [{ "label": "Belt.Option.eqU", @@ -471,8 +468,6 @@ Resolved opens 1 pervasives ContextPath Value[fa]-> ContextPath Value[fa] Path fa -CPPipe env:Completion -CPPipe type path:ForAuto.t CPPipe pathFromEnv:ForAuto found:true Path ForAuto. [{ @@ -728,6 +723,11 @@ Resolved opens 1 pervasives ContextPath Value[r]."" ContextPath Value[r] Path r +ContextPath Value[r]-> +ContextPath Value[r] +Path r +CPPipe pathFromEnv: found:true +Path Completion. [{ "label": "x", "kind": 5, @@ -751,6 +751,11 @@ Resolved opens 1 pervasives ContextPath Value[Objects, Rec, recordVal]."" ContextPath Value[Objects, Rec, recordVal] Path Objects.Rec.recordVal +ContextPath Value[Objects, Rec, recordVal]-> +ContextPath Value[Objects, Rec, recordVal] +Path Objects.Rec.recordVal +CPPipe pathFromEnv:Rec found:true +Path Objects.Rec. [{ "label": "xx", "kind": 5, @@ -833,6 +838,22 @@ ContextPath Value[q].aa."" ContextPath Value[q].aa ContextPath Value[q] Path q +ContextPath Value[q]->aa +ContextPath Value[q] +Path q +CPPipe pathFromEnv: found:true +Path Completion.aa +ContextPath Value[q].aa-> +ContextPath Value[q].aa +ContextPath Value[q] +Path q +ContextPath Value[q]->aa +ContextPath Value[q] +Path q +CPPipe pathFromEnv: found:true +Path Completion.aa +CPPipe pathFromEnv: found:true +Path Completion. [{ "label": "x", "kind": 5, @@ -857,6 +878,22 @@ ContextPath Value[q].aa.n ContextPath Value[q].aa ContextPath Value[q] Path q +ContextPath Value[q]->aa +ContextPath Value[q] +Path q +CPPipe pathFromEnv: found:true +Path Completion.aa +ContextPath Value[q].aa->n +ContextPath Value[q].aa +ContextPath Value[q] +Path q +ContextPath Value[q]->aa +ContextPath Value[q] +Path q +CPPipe pathFromEnv: found:true +Path Completion.aa +CPPipe pathFromEnv: found:true +Path Completion.n [{ "label": "name", "kind": 5, @@ -1081,6 +1118,12 @@ ContextPath Value[FAO, forAutoObject]["forAutoLabel"]."" ContextPath Value[FAO, forAutoObject]["forAutoLabel"] ContextPath Value[FAO, forAutoObject] Path FAO.forAutoObject +ContextPath Value[FAO, forAutoObject]["forAutoLabel"]-> +ContextPath Value[FAO, forAutoObject]["forAutoLabel"] +ContextPath Value[FAO, forAutoObject] +Path FAO.forAutoObject +CPPipe pathFromEnv:FAR found:true +Path FAR. [{ "label": "forAuto", "kind": 5, @@ -1106,8 +1149,12 @@ ContextPath Value[FAO, forAutoObject]["forAutoLabel"].forAuto ContextPath Value[FAO, forAutoObject]["forAutoLabel"] ContextPath Value[FAO, forAutoObject] Path FAO.forAutoObject -CPPipe env:Completion envFromCompletionItem:Completion.FAR -CPPipe type path:ForAuto.t +ContextPath Value[FAO, forAutoObject]["forAutoLabel"]->forAuto +ContextPath Value[FAO, forAutoObject]["forAutoLabel"] +ContextPath Value[FAO, forAutoObject] +Path FAO.forAutoObject +CPPipe pathFromEnv:FAR found:true +Path FAR.forAuto CPPipe pathFromEnv:ForAuto found:false Path ForAuto. [{ @@ -1189,6 +1236,11 @@ Resolved opens 3 pervasives Completion.res Completion.res ContextPath Value[_z]."" ContextPath Value[_z] Path _z +ContextPath Value[_z]-> +ContextPath Value[_z] +Path _z +CPPipe pathFromEnv: found:true +Path Completion. [{ "label": "x", "kind": 5, @@ -1347,6 +1399,11 @@ Resolved opens 3 pervasives Completion.res Completion.res ContextPath Value[funRecord].someFun ContextPath Value[funRecord] Path funRecord +ContextPath Value[funRecord]->someFun +ContextPath Value[funRecord] +Path funRecord +CPPipe pathFromEnv: found:true +Path Completion.someFun Found type for function (~name: string) => unit [{ "label": "name", @@ -1367,6 +1424,12 @@ ContextPath Value[retAA](Nolabel)."" ContextPath Value[retAA](Nolabel) ContextPath Value[retAA] Path retAA +ContextPath Value[retAA](Nolabel, Nolabel)-> +ContextPath Value[retAA](Nolabel, Nolabel) +ContextPath Value[retAA] +Path retAA +CPPipe pathFromEnv: found:true +Path Completion. [{ "label": "x", "kind": 5, @@ -1897,6 +1960,11 @@ Resolved opens 3 pervasives Completion.res Completion.res ContextPath Value[funRecord]."" ContextPath Value[funRecord] Path funRecord +ContextPath Value[funRecord]-> +ContextPath Value[funRecord] +Path funRecord +CPPipe pathFromEnv: found:true +Path Completion. [{ "label": "someFun", "kind": 5, @@ -1923,7 +1991,6 @@ Package opens Pervasives.JsxModules.place holder Resolved opens 4 pervasives Completion.res Completion.res js.ml ContextPath array->ma ContextPath array -CPPipe env:Completion Path Js.Array2.ma [{ "label": "Array2.mapi", @@ -2078,7 +2145,6 @@ Package opens Pervasives.JsxModules.place holder Resolved opens 3 pervasives Completion.res Completion.res ContextPath int->t ContextPath int -CPPipe env:Completion Path Belt.Int.t [{ "label": "Belt.Int.toString", @@ -2102,7 +2168,6 @@ Package opens Pervasives.JsxModules.place holder Resolved opens 3 pervasives Completion.res Completion.res ContextPath float->t ContextPath float -CPPipe env:Completion Path Belt.Float.t [{ "label": "Belt.Float.toInt", @@ -2127,7 +2192,6 @@ Resolved opens 3 pervasives Completion.res Completion.res ContextPath Value[ok]->g ContextPath Value[ok] Path ok -CPPipe env:Completion Path Belt.Result.g [{ "label": "Belt.Result.getExn", @@ -2153,6 +2217,11 @@ Resolved opens 3 pervasives Completion.res Completion.res ContextPath Value[rWithDepr].so ContextPath Value[rWithDepr] Path rWithDepr +ContextPath Value[rWithDepr]->so +ContextPath Value[rWithDepr] +Path rWithDepr +CPPipe pathFromEnv: found:true +Path Completion.so [{ "label": "someInt", "kind": 5, @@ -2211,7 +2280,6 @@ ContextPath Value[uncurried](Nolabel)->toS ContextPath Value[uncurried](Nolabel) ContextPath Value[uncurried] Path uncurried -CPPipe env:Completion Path Belt.Int.toS [{ "label": "Belt.Int.toString", diff --git a/analysis/tests/src/expected/CompletionExpressions.res.txt b/analysis/tests/src/expected/CompletionExpressions.res.txt index 2d5c7438c..1065df396 100644 --- a/analysis/tests/src/expected/CompletionExpressions.res.txt +++ b/analysis/tests/src/expected/CompletionExpressions.res.txt @@ -946,6 +946,11 @@ Resolved opens 1 pervasives ContextPath Value[fff].someOpt ContextPath Value[fff] Path fff +ContextPath Value[fff]->someOpt +ContextPath Value[fff] +Path fff +CPPipe pathFromEnv: found:true +Path CompletionExpressions.someOpt [{ "label": "someOptField", "kind": 5, @@ -1415,6 +1420,11 @@ Resolved opens 2 pervasives CompletionSupport.res ContextPath Value[someTyp]."" ContextPath Value[someTyp] Path someTyp +ContextPath Value[someTyp]-> +ContextPath Value[someTyp] +Path someTyp +CPPipe pathFromEnv: found:true +Path CompletionExpressions. [{ "label": "test", "kind": 5, @@ -1470,6 +1480,11 @@ Resolved opens 2 pervasives CompletionSupport.res ContextPath Value[someTyp]."" ContextPath Value[someTyp] Path someTyp +ContextPath Value[someTyp]-> +ContextPath Value[someTyp] +Path someTyp +CPPipe pathFromEnv: found:true +Path CompletionExpressions. [{ "label": "test", "kind": 5, diff --git a/analysis/tests/src/expected/CompletionFromModule.res.txt b/analysis/tests/src/expected/CompletionFromModule.res.txt new file mode 100644 index 000000000..01512adcc --- /dev/null +++ b/analysis/tests/src/expected/CompletionFromModule.res.txt @@ -0,0 +1,171 @@ +Complete src/CompletionFromModule.res 10:5 +posCursor:[10:5] posNoWhite:[10:4] Found expr:[10:3->10:5] +Pexp_field [10:3->10:4] _:[13:0->10:5] +Completable: Cpath Value[n]."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[n]."" +ContextPath Value[n] +Path n +ContextPath Value[n]-> +ContextPath Value[n] +Path n +CPPipe pathFromEnv:SomeModule found:true +Path SomeModule. +[{ + "label": "name", + "kind": 5, + "tags": [], + "detail": "string", + "documentation": {"kind": "markdown", "value": "```rescript\nname: string\n```\n\n```rescript\ntype t = {name: string}\n```"} + }, { + "label": "->SomeModule.getName", + "kind": 12, + "tags": [], + "detail": "t => string", + "documentation": null, + "sortText": "getName", + "insertText": "->SomeModule.getName", + "additionalTextEdits": [{ + "range": {"start": {"line": 10, "character": 4}, "end": {"line": 10, "character": 5}}, + "newText": "" + }] + }] + +Complete src/CompletionFromModule.res 30:6 +posCursor:[30:6] posNoWhite:[30:5] Found expr:[30:3->30:6] +Pexp_field [30:3->30:5] _:[36:0->30:6] +Completable: Cpath Value[nn]."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[nn]."" +ContextPath Value[nn] +Path nn +ContextPath Value[nn]-> +ContextPath Value[nn] +Path nn +CPPipe pathFromEnv:SomeOtherModule found:true +Path SomeOtherModule. +Path CompletionFromModule.SomeOtherModule. +[{ + "label": "nname", + "kind": 5, + "tags": [], + "detail": "string", + "documentation": {"kind": "markdown", "value": "```rescript\nnname: string\n```\n\n```rescript\ntype typeOutsideModule = {nname: string}\n```"} + }, { + "label": "->SomeOtherModule.getNName", + "kind": 12, + "tags": [], + "detail": "t => string", + "documentation": null, + "sortText": "getNName", + "insertText": "->SomeOtherModule.getNName", + "additionalTextEdits": [{ + "range": {"start": {"line": 30, "character": 5}, "end": {"line": 30, "character": 6}}, + "newText": "" + }] + }, { + "label": "->SomeOtherModule.getNName2", + "kind": 12, + "tags": [], + "detail": "typeOutsideModule => string", + "documentation": null, + "sortText": "getNName2", + "insertText": "->SomeOtherModule.getNName2", + "additionalTextEdits": [{ + "range": {"start": {"line": 30, "character": 5}, "end": {"line": 30, "character": 6}}, + "newText": "" + }] + }, { + "label": "->SomeOtherModule.getNName", + "kind": 12, + "tags": [], + "detail": "t => string", + "documentation": null, + "sortText": "getNName", + "insertText": "->SomeOtherModule.getNName", + "additionalTextEdits": [{ + "range": {"start": {"line": 30, "character": 5}, "end": {"line": 30, "character": 6}}, + "newText": "" + }] + }, { + "label": "->SomeOtherModule.getNName2", + "kind": 12, + "tags": [], + "detail": "typeOutsideModule => string", + "documentation": null, + "sortText": "getNName2", + "insertText": "->SomeOtherModule.getNName2", + "additionalTextEdits": [{ + "range": {"start": {"line": 30, "character": 5}, "end": {"line": 30, "character": 6}}, + "newText": "" + }] + }] + +Complete src/CompletionFromModule.res 33:32 +XXX Not found! +Completable: Cpath Module[SomeOthe] +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Module[SomeOthe] +Path SomeOthe +[{ + "label": "SomeOtherModule", + "kind": 9, + "tags": [], + "detail": "module SomeOtherModule", + "documentation": null + }] + +Complete src/CompletionFromModule.res 38:8 +posCursor:[38:8] posNoWhite:[38:7] Found expr:[38:3->0:-1] +Completable: Cpath Value[nnn]-> +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[nnn]-> +ContextPath Value[nnn] +Path nnn +CPPipe pathFromEnv: found:true +Path CompletionFromModule. +Path CompletionFromModule.SomeOtherModule. +[{ + "label": "SomeOtherModule.getNName", + "kind": 12, + "tags": [], + "detail": "t => string", + "documentation": null + }, { + "label": "SomeOtherModule.getNName2", + "kind": 12, + "tags": [], + "detail": "typeOutsideModule => string", + "documentation": null + }] + +Complete src/CompletionFromModule.res 42:8 +posCursor:[42:8] posNoWhite:[42:7] Found expr:[42:3->0:-1] +Completable: Cpath Value[nnn]-> +Raw opens: 1 SomeOtherModule.place holder +Package opens Pervasives.JsxModules.place holder +Resolved opens 2 pervasives CompletionFromModule.res +ContextPath Value[nnn]-> +ContextPath Value[nnn] +Path nnn +CPPipe pathFromEnv: found:true +Path CompletionFromModule. +Path CompletionFromModule.SomeOtherModule. +[{ + "label": "getNName", + "kind": 12, + "tags": [], + "detail": "t => string", + "documentation": null + }, { + "label": "getNName2", + "kind": 12, + "tags": [], + "detail": "typeOutsideModule => string", + "documentation": null + }] + diff --git a/analysis/tests/src/expected/CompletionFromModule2.res.txt b/analysis/tests/src/expected/CompletionFromModule2.res.txt new file mode 100644 index 000000000..0f60e0158 --- /dev/null +++ b/analysis/tests/src/expected/CompletionFromModule2.res.txt @@ -0,0 +1,156 @@ +Complete src/CompletionFromModule2.res 2:26 +posCursor:[2:26] posNoWhite:[2:25] Found expr:[2:3->2:26] +Pexp_field [2:3->2:25] _:[11:0->2:26] +Completable: Cpath Value[CompletionFromModule, n]."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[CompletionFromModule, n]."" +ContextPath Value[CompletionFromModule, n] +Path CompletionFromModule.n +ContextPath Value[CompletionFromModule, n]-> +ContextPath Value[CompletionFromModule, n] +Path CompletionFromModule.n +CPPipe pathFromEnv:SomeModule found:true +Path CompletionFromModule.SomeModule. +[{ + "label": "name", + "kind": 5, + "tags": [], + "detail": "string", + "documentation": {"kind": "markdown", "value": "```rescript\nname: string\n```\n\n```rescript\ntype t = {name: string}\n```"} + }, { + "label": "->CompletionFromModule.SomeModule.getName", + "kind": 12, + "tags": [], + "detail": "t => string", + "documentation": null, + "sortText": "getName", + "insertText": "->CompletionFromModule.SomeModule.getName", + "additionalTextEdits": [{ + "range": {"start": {"line": 2, "character": 25}, "end": {"line": 2, "character": 26}}, + "newText": "" + }] + }] + +Complete src/CompletionFromModule2.res 5:27 +posCursor:[5:27] posNoWhite:[5:26] Found expr:[5:3->5:27] +Pexp_field [5:3->5:26] _:[11:0->5:27] +Completable: Cpath Value[CompletionFromModule, nn]."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[CompletionFromModule, nn]."" +ContextPath Value[CompletionFromModule, nn] +Path CompletionFromModule.nn +ContextPath Value[CompletionFromModule, nn]-> +ContextPath Value[CompletionFromModule, nn] +Path CompletionFromModule.nn +CPPipe pathFromEnv:SomeOtherModule found:true +Path CompletionFromModule.SomeOtherModule. +Path CompletionFromModule.SomeOtherModule. +[{ + "label": "nname", + "kind": 5, + "tags": [], + "detail": "string", + "documentation": {"kind": "markdown", "value": "```rescript\nnname: string\n```\n\n```rescript\ntype typeOutsideModule = {nname: string}\n```"} + }, { + "label": "->CompletionFromModule.SomeOtherModule.getNName", + "kind": 12, + "tags": [], + "detail": "t => string", + "documentation": null, + "sortText": "getNName", + "insertText": "->CompletionFromModule.SomeOtherModule.getNName", + "additionalTextEdits": [{ + "range": {"start": {"line": 5, "character": 26}, "end": {"line": 5, "character": 27}}, + "newText": "" + }] + }, { + "label": "->CompletionFromModule.SomeOtherModule.getNName2", + "kind": 12, + "tags": [], + "detail": "typeOutsideModule => string", + "documentation": null, + "sortText": "getNName2", + "insertText": "->CompletionFromModule.SomeOtherModule.getNName2", + "additionalTextEdits": [{ + "range": {"start": {"line": 5, "character": 26}, "end": {"line": 5, "character": 27}}, + "newText": "" + }] + }, { + "label": "->CompletionFromModule.SomeOtherModule.getNName", + "kind": 12, + "tags": [], + "detail": "t => string", + "documentation": null, + "sortText": "getNName", + "insertText": "->CompletionFromModule.SomeOtherModule.getNName", + "additionalTextEdits": [{ + "range": {"start": {"line": 5, "character": 26}, "end": {"line": 5, "character": 27}}, + "newText": "" + }] + }, { + "label": "->CompletionFromModule.SomeOtherModule.getNName2", + "kind": 12, + "tags": [], + "detail": "typeOutsideModule => string", + "documentation": null, + "sortText": "getNName2", + "insertText": "->CompletionFromModule.SomeOtherModule.getNName2", + "additionalTextEdits": [{ + "range": {"start": {"line": 5, "character": 26}, "end": {"line": 5, "character": 27}}, + "newText": "" + }] + }] + +Complete src/CompletionFromModule2.res 8:29 +posCursor:[8:29] posNoWhite:[8:28] Found expr:[8:3->0:-1] +Completable: Cpath Value[CompletionFromModule, nnn]-> +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[CompletionFromModule, nnn]-> +ContextPath Value[CompletionFromModule, nnn] +Path CompletionFromModule.nnn +CPPipe pathFromEnv: found:true +Path CompletionFromModule. +Path CompletionFromModule.SomeOtherModule. +[{ + "label": "CompletionFromModule.SomeOtherModule.getNName", + "kind": 12, + "tags": [], + "detail": "t => string", + "documentation": null + }, { + "label": "CompletionFromModule.SomeOtherModule.getNName2", + "kind": 12, + "tags": [], + "detail": "typeOutsideModule => string", + "documentation": null + }] + +Complete src/CompletionFromModule2.res 12:29 +posCursor:[12:29] posNoWhite:[12:28] Found expr:[12:3->0:-1] +Completable: Cpath Value[CompletionFromModule, nnn]-> +Raw opens: 1 CompletionFromModule.SomeOtherModule.place holder +Package opens Pervasives.JsxModules.place holder +Resolved opens 2 pervasives CompletionFromModule.res +ContextPath Value[CompletionFromModule, nnn]-> +ContextPath Value[CompletionFromModule, nnn] +Path CompletionFromModule.nnn +CPPipe pathFromEnv: found:true +Path CompletionFromModule. +Path CompletionFromModule.SomeOtherModule. +[{ + "label": "getNName", + "kind": 12, + "tags": [], + "detail": "t => string", + "documentation": null + }, { + "label": "getNName2", + "kind": 12, + "tags": [], + "detail": "typeOutsideModule => string", + "documentation": null + }] + diff --git a/analysis/tests/src/expected/CompletionFunctionArguments.res.txt b/analysis/tests/src/expected/CompletionFunctionArguments.res.txt index b84d25a27..003691cdd 100644 --- a/analysis/tests/src/expected/CompletionFunctionArguments.res.txt +++ b/analysis/tests/src/expected/CompletionFunctionArguments.res.txt @@ -400,8 +400,6 @@ Resolved opens 1 pervasives ContextPath Value[thisGetsBrokenLoc]->a <> ContextPath Value[thisGetsBrokenLoc] Path thisGetsBrokenLoc -CPPipe env:CompletionFunctionArguments -CPPipe type path:ReactEvent.Mouse.t CPPipe pathFromEnv:ReactEvent.Mouse found:false Path ReactEvent.Mouse.a [{ @@ -426,8 +424,6 @@ Resolved opens 1 pervasives ContextPath Value[reassignedWorks]->a <> ContextPath Value[reassignedWorks] Path reassignedWorks -CPPipe env:CompletionFunctionArguments -CPPipe type path:ReactEvent.Mouse.t CPPipe pathFromEnv:ReactEvent.Mouse found:false Path ReactEvent.Mouse.a [{ @@ -449,8 +445,6 @@ Resolved opens 1 pervasives ContextPath Value[fineModuleVal]-> ContextPath Value[fineModuleVal] Path fineModuleVal -CPPipe env:CompletionFunctionArguments -CPPipe type path:FineModule.t CPPipe pathFromEnv:FineModule found:true Path FineModule. [{ diff --git a/analysis/tests/src/expected/CompletionInferValues.res.txt b/analysis/tests/src/expected/CompletionInferValues.res.txt index 356a23819..57fc82343 100644 --- a/analysis/tests/src/expected/CompletionInferValues.res.txt +++ b/analysis/tests/src/expected/CompletionInferValues.res.txt @@ -1,28 +1,27 @@ Complete src/CompletionInferValues.res 15:43 posCursor:[15:43] posNoWhite:[15:42] Found expr:[15:33->15:43] -Completable: Cpath Value[aliased]->f +Completable: Cpath Value[aliased]->t Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives -ContextPath Value[aliased]->f +ContextPath Value[aliased]->t ContextPath Value[aliased] Path aliased ContextPath Value[x] Path x ContextPath int -CPPipe env:CompletionInferValues -Path Belt.Int.f +Path Belt.Int.t [{ - "label": "Belt.Int.fromString", + "label": "Belt.Int.toString", "kind": 12, "tags": [], - "detail": "string => option", - "documentation": {"kind": "markdown", "value": "\nConverts a given `string` to an `int`. Returns `Some(int)` when the input is a number, `None` otherwise.\n\n## Examples\n\n```rescript\nJs.log(Belt.Int.fromString(\"1\") === Some(1)) /* true */\n```\n"} + "detail": "int => string", + "documentation": {"kind": "markdown", "value": "\nConverts a given `int` to a `string`. Uses the JavaScript `String` constructor under the hood.\n\n## Examples\n\n```rescript\nJs.log(Belt.Int.toString(1) === \"1\") /* true */\n```\n"} }, { - "label": "Belt.Int.fromFloat", + "label": "Belt.Int.toFloat", "kind": 12, "tags": [], - "detail": "float => int", - "documentation": {"kind": "markdown", "value": "\nConverts a given `float` to an `int`.\n\n## Examples\n\n```rescript\nJs.log(Belt.Int.fromFloat(1.0) === 1) /* true */\n```\n"} + "detail": "int => float", + "documentation": {"kind": "markdown", "value": "\nConverts a given `int` to a `float`.\n\n## Examples\n\n```rescript\nJs.log(Belt.Int.toFloat(1) === 1.0) /* true */\n```\n"} }] Complete src/CompletionInferValues.res 18:30 @@ -37,6 +36,14 @@ Path x ContextPath Value[getSomeRecord](Nolabel) ContextPath Value[getSomeRecord] Path getSomeRecord +ContextPath Value[x]-> +ContextPath Value[x] +Path x +ContextPath Value[getSomeRecord](Nolabel) +ContextPath Value[getSomeRecord] +Path getSomeRecord +CPPipe pathFromEnv: found:true +Path CompletionInferValues. [{ "label": "name", "kind": 5, @@ -65,6 +72,16 @@ Path x ContextPath Value[getSomeRecord](Nolabel) ContextPath Value[getSomeRecord] Path getSomeRecord +ContextPath Value[aliased]-> +ContextPath Value[aliased] +Path aliased +ContextPath Value[x] +Path x +ContextPath Value[getSomeRecord](Nolabel) +ContextPath Value[getSomeRecord] +Path getSomeRecord +CPPipe pathFromEnv: found:true +Path CompletionInferValues. [{ "label": "name", "kind": 5, @@ -98,6 +115,15 @@ ContextPath CArgument CArgument Value[someFnWithCallback]($0)(~someRecord) ContextPath CArgument Value[someFnWithCallback]($0) ContextPath Value[someFnWithCallback] Path someFnWithCallback +ContextPath Value[someRecord]-> +ContextPath Value[someRecord] +Path someRecord +ContextPath CArgument CArgument Value[someFnWithCallback]($0)(~someRecord) +ContextPath CArgument Value[someFnWithCallback]($0) +ContextPath Value[someFnWithCallback] +Path someFnWithCallback +CPPipe pathFromEnv: found:true +Path CompletionInferValues. [{ "label": "name", "kind": 5, @@ -133,6 +159,17 @@ ContextPath Value[aliasedFn] Path aliasedFn ContextPath Value[someFnWithCallback] Path someFnWithCallback +ContextPath Value[someRecord]-> +ContextPath Value[someRecord] +Path someRecord +ContextPath CArgument CArgument Value[aliasedFn]($0)(~someRecord) +ContextPath CArgument Value[aliasedFn]($0) +ContextPath Value[aliasedFn] +Path aliasedFn +ContextPath Value[someFnWithCallback] +Path someFnWithCallback +CPPipe pathFromEnv: found:true +Path CompletionInferValues. [{ "label": "name", "kind": 5, @@ -163,8 +200,6 @@ ContextPath CArgument CArgument Value[reactEventFn]($0)($0) ContextPath CArgument Value[reactEventFn]($0) ContextPath Value[reactEventFn] Path reactEventFn -CPPipe env:CompletionInferValues -CPPipe type path:ReactEvent.Mouse.t CPPipe pathFromEnv:ReactEvent.Mouse found:false Path ReactEvent.Mouse.pr [{ @@ -191,8 +226,6 @@ ContextPath CArgument CJsxPropValue [div] onMouseEnter($0) ContextPath CJsxPropValue [div] onMouseEnter Path ReactDOM.domProps Path PervasivesU.JsxDOM.domProps -CPPipe env:CompletionInferValues -CPPipe type path:JsxEventU.Mouse.t CPPipe pathFromEnv:JsxEventU.Mouse found:false Path JsxEventU.Mouse.pr [{ @@ -218,8 +251,6 @@ Path event ContextPath CArgument CJsxPropValue [Div] onMouseEnter($0) ContextPath CJsxPropValue [Div] onMouseEnter Path Div.make -CPPipe env:CompletionInferValues envFromCompletionItem:CompletionInferValues.Div -CPPipe type path:PervasivesU.JsxEvent.Mouse.t CPPipe pathFromEnv:PervasivesU.JsxEvent.Mouse found:false Path PervasivesU.JsxEvent.Mouse.pr [{ @@ -246,7 +277,6 @@ Path btn ContextPath Value[JsxEvent, Mouse, button](Nolabel) ContextPath Value[JsxEvent, Mouse, button] Path JsxEvent.Mouse.button -CPPipe env:CompletionInferValues envFromCompletionItem:JsxEventU.Mouse Path Belt.Int.t [{ "label": "Belt.Int.toString", @@ -278,7 +308,6 @@ Path btn ContextPath Value[Belt, Int, toString](Nolabel) ContextPath Value[Belt, Int, toString] Path Belt.Int.toString -CPPipe env:CompletionInferValues envFromCompletionItem:Belt_Int Path Js.String2.spl [{ "label": "Js.String2.splitAtMost", @@ -322,7 +351,6 @@ Path btn ContextPath Value[Js, String2, split](Nolabel, Nolabel) ContextPath Value[Js, String2, split] Path Js.String2.split -CPPipe env:CompletionInferValues envFromCompletionItem:Js_string2 Path Js.Array2.ma [{ "label": "Js.Array2.mapi", @@ -338,34 +366,9 @@ Path Js.Array2.ma "documentation": {"kind": "markdown", "value": "\nApplies the function (the second argument) to each item in the array, returning\na new array. The result array does not have to have elements of the same type\nas the input array. See\n[`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)\non MDN.\n\n## Examples\n\n```rescript\nJs.Array2.map([12, 4, 8], x => x * x) == [144, 16, 64]\nJs.Array2.map([\"animal\", \"vegetable\", \"mineral\"], Js.String.length) == [6, 9, 7]\n```\n"} }] -Complete src/CompletionInferValues.res 56:52 -posCursor:[56:52] posNoWhite:[56:51] Found expr:[56:50->56:52] -Pexp_field [56:50->56:51] _:[59:0->56:52] -Completable: Cpath Value[x]."" -Package opens Pervasives.JsxModules.place holder -Resolved opens 1 pervasives -ContextPath Value[x]."" -ContextPath Value[x] -Path x -ContextPath Type[someRecord] -Path someRecord -[{ - "label": "name", - "kind": 5, - "tags": [], - "detail": "string", - "documentation": {"kind": "markdown", "value": "```rescript\nname: string\n```\n\n```rescript\ntype someRecord = {name: string, age: int}\n```"} - }, { - "label": "age", - "kind": 5, - "tags": [], - "detail": "int", - "documentation": {"kind": "markdown", "value": "```rescript\nage: int\n```\n\n```rescript\ntype someRecord = {name: string, age: int}\n```"} - }] - -Complete src/CompletionInferValues.res 78:78 -posCursor:[78:78] posNoWhite:[78:77] Found expr:[78:70->78:78] -Pexp_field [78:70->78:77] _:[125:0->78:78] +Complete src/CompletionInferValues.res 75:78 +posCursor:[75:78] posNoWhite:[75:77] Found expr:[75:70->75:78] +Pexp_field [75:70->75:77] _:[118:0->75:78] Completable: Cpath Value[srecord]."" Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -377,6 +380,16 @@ ContextPath Value[x] Path x ContextPath Type[someRecordWithNestedStuff] Path someRecordWithNestedStuff +ContextPath Value[srecord]-> +ContextPath Value[srecord] +Path srecord +ContextPath CPatternPath(Value[x])->recordField(srecord) +ContextPath Value[x] +Path x +ContextPath Type[someRecordWithNestedStuff] +Path someRecordWithNestedStuff +CPPipe pathFromEnv: found:true +Path CompletionInferValues. [{ "label": "name", "kind": 5, @@ -391,9 +404,9 @@ Path someRecordWithNestedStuff "documentation": {"kind": "markdown", "value": "```rescript\nage: int\n```\n\n```rescript\ntype someRecord = {name: string, age: int}\n```"} }] -Complete src/CompletionInferValues.res 82:86 -posCursor:[82:86] posNoWhite:[82:85] Found expr:[82:78->82:86] -Pexp_field [82:78->82:85] _:[125:0->82:86] +Complete src/CompletionInferValues.res 79:86 +posCursor:[79:86] posNoWhite:[79:85] Found expr:[79:78->79:86] +Pexp_field [79:78->79:85] _:[118:0->79:86] Completable: Cpath Value[aliased]."" Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -405,6 +418,16 @@ ContextPath Value[x] Path x ContextPath Type[someRecordWithNestedStuff] Path someRecordWithNestedStuff +ContextPath Value[aliased]-> +ContextPath Value[aliased] +Path aliased +ContextPath CPatternPath(Value[x])->recordField(nested) +ContextPath Value[x] +Path x +ContextPath Type[someRecordWithNestedStuff] +Path someRecordWithNestedStuff +CPPipe pathFromEnv: found:true +Path CompletionInferValues. [{ "label": "someRecord", "kind": 5, @@ -413,9 +436,9 @@ Path someRecordWithNestedStuff "documentation": {"kind": "markdown", "value": "```rescript\nsomeRecord: someRecord\n```\n\n```rescript\ntype someNestedRecord = {someRecord: someRecord}\n```"} }] -Complete src/CompletionInferValues.res 86:103 -posCursor:[86:103] posNoWhite:[86:102] Found expr:[86:92->86:103] -Pexp_field [86:92->86:102] _:[125:0->86:103] +Complete src/CompletionInferValues.res 83:103 +posCursor:[83:103] posNoWhite:[83:102] Found expr:[83:92->83:103] +Pexp_field [83:92->83:102] _:[118:0->83:103] Completable: Cpath Value[someRecord]."" Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -427,6 +450,16 @@ ContextPath Value[x] Path x ContextPath Type[someRecordWithNestedStuff] Path someRecordWithNestedStuff +ContextPath Value[someRecord]-> +ContextPath Value[someRecord] +Path someRecord +ContextPath CPatternPath(Value[x])->recordField(nested)->recordField(someRecord) +ContextPath Value[x] +Path x +ContextPath Type[someRecordWithNestedStuff] +Path someRecordWithNestedStuff +CPPipe pathFromEnv: found:true +Path CompletionInferValues. [{ "label": "name", "kind": 5, @@ -441,8 +474,8 @@ Path someRecordWithNestedStuff "documentation": {"kind": "markdown", "value": "```rescript\nage: int\n```\n\n```rescript\ntype someRecord = {name: string, age: int}\n```"} }] -Complete src/CompletionInferValues.res 90:81 -posCursor:[90:81] posNoWhite:[90:80] Found expr:[90:69->90:81] +Complete src/CompletionInferValues.res 87:81 +posCursor:[87:81] posNoWhite:[87:80] Found expr:[87:69->87:81] Completable: Cpath Value[things]->slic Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -454,7 +487,6 @@ ContextPath Value[x] Path x ContextPath Type[someRecordWithNestedStuff] Path someRecordWithNestedStuff -CPPipe env:CompletionInferValues Path Js.String2.slic [{ "label": "Js.String2.sliceToEnd", @@ -470,8 +502,8 @@ Path Js.String2.slic "documentation": {"kind": "markdown", "value": "\n`slice(str, from:n1, to_:n2)` returns the substring of `str` starting at\ncharacter `n1` up to but not including `n2`.\n- If either `n1` or `n2` is negative, then it is evaluated as `length(str - n1)` or `length(str - n2)`.\n- If `n2` is greater than the length of `str`, then it is treated as `length(str)`.\n- If `n1` is greater than `n2`, slice returns the empty string.\n\nSee [`String.slice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice) on MDN.\n\n## Examples\n\n```rescript\nJs.String2.slice(\"abcdefg\", ~from=2, ~to_=5) == \"cde\"\nJs.String2.slice(\"abcdefg\", ~from=2, ~to_=9) == \"cdefg\"\nJs.String2.slice(\"abcdefg\", ~from=-4, ~to_=-2) == \"de\"\nJs.String2.slice(\"abcdefg\", ~from=5, ~to_=1) == \"\"\n```\n"} }] -Complete src/CompletionInferValues.res 94:82 -posCursor:[94:82] posNoWhite:[94:81] Found expr:[94:70->94:82] +Complete src/CompletionInferValues.res 91:82 +posCursor:[91:82] posNoWhite:[91:81] Found expr:[91:70->91:82] Completable: Cpath Value[someInt]->toS Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -483,7 +515,6 @@ ContextPath Value[x] Path x ContextPath Type[someRecordWithNestedStuff] Path someRecordWithNestedStuff -CPPipe env:CompletionInferValues Path Belt.Int.toS [{ "label": "Belt.Int.toString", @@ -493,8 +524,8 @@ Path Belt.Int.toS "documentation": {"kind": "markdown", "value": "\nConverts a given `int` to a `string`. Uses the JavaScript `String` constructor under the hood.\n\n## Examples\n\n```rescript\nJs.log(Belt.Int.toString(1) === \"1\") /* true */\n```\n"} }] -Complete src/CompletionInferValues.res 98:109 -posCursor:[98:109] posNoWhite:[98:108] Found expr:[98:97->98:109] +Complete src/CompletionInferValues.res 95:109 +posCursor:[95:109] posNoWhite:[95:108] Found expr:[95:97->95:109] Completable: Cpath Value[someInt]->toS Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -509,7 +540,6 @@ ContextPath Value[x] Path x ContextPath Type[otherNestedRecord] Path otherNestedRecord -CPPipe env:CompletionInferValues Path Belt.Int.toS [{ "label": "Belt.Int.toString", @@ -519,9 +549,9 @@ Path Belt.Int.toS "documentation": {"kind": "markdown", "value": "\nConverts a given `int` to a `string`. Uses the JavaScript `String` constructor under the hood.\n\n## Examples\n\n```rescript\nJs.log(Belt.Int.toString(1) === \"1\") /* true */\n```\n"} }] -Complete src/CompletionInferValues.res 102:102 -posCursor:[102:102] posNoWhite:[102:101] Found expr:[102:57->102:102] -posCursor:[102:102] posNoWhite:[102:101] Found expr:[102:90->102:102] +Complete src/CompletionInferValues.res 99:102 +posCursor:[99:102] posNoWhite:[99:101] Found expr:[99:57->99:102] +posCursor:[99:102] posNoWhite:[99:101] Found expr:[99:90->99:102] Completable: Cpath Value[someInt]->toS Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -536,7 +566,6 @@ ContextPath Value[x] Path x ContextPath Type[otherNestedRecord] Path otherNestedRecord -CPPipe env:CompletionInferValues Path Belt.Int.toS [{ "label": "Belt.Int.toString", @@ -546,8 +575,8 @@ Path Belt.Int.toS "documentation": {"kind": "markdown", "value": "\nConverts a given `int` to a `string`. Uses the JavaScript `String` constructor under the hood.\n\n## Examples\n\n```rescript\nJs.log(Belt.Int.toString(1) === \"1\") /* true */\n```\n"} }] -Complete src/CompletionInferValues.res 106:88 -posCursor:[106:88] posNoWhite:[106:87] Found expr:[106:79->106:88] +Complete src/CompletionInferValues.res 103:88 +posCursor:[103:88] posNoWhite:[103:87] Found expr:[103:79->103:88] Completable: Cpath Value[str]->slic Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -559,7 +588,6 @@ ContextPath Value[x] Path x ContextPath Type[otherNestedRecord] Path otherNestedRecord -CPPipe env:CompletionInferValues Path Js.String2.slic [{ "label": "Js.String2.sliceToEnd", @@ -575,8 +603,8 @@ Path Js.String2.slic "documentation": {"kind": "markdown", "value": "\n`slice(str, from:n1, to_:n2)` returns the substring of `str` starting at\ncharacter `n1` up to but not including `n2`.\n- If either `n1` or `n2` is negative, then it is evaluated as `length(str - n1)` or `length(str - n2)`.\n- If `n2` is greater than the length of `str`, then it is treated as `length(str)`.\n- If `n1` is greater than `n2`, slice returns the empty string.\n\nSee [`String.slice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice) on MDN.\n\n## Examples\n\n```rescript\nJs.String2.slice(\"abcdefg\", ~from=2, ~to_=5) == \"cde\"\nJs.String2.slice(\"abcdefg\", ~from=2, ~to_=9) == \"cdefg\"\nJs.String2.slice(\"abcdefg\", ~from=-4, ~to_=-2) == \"de\"\nJs.String2.slice(\"abcdefg\", ~from=5, ~to_=1) == \"\"\n```\n"} }] -Complete src/CompletionInferValues.res 110:89 -posCursor:[110:89] posNoWhite:[110:88] Found expr:[110:80->110:89] +Complete src/CompletionInferValues.res 107:89 +posCursor:[107:89] posNoWhite:[107:88] Found expr:[107:80->107:89] Completable: Cpath Value[str]->slic Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -588,7 +616,6 @@ ContextPath Value[x] Path x ContextPath Type[otherNestedRecord] Path otherNestedRecord -CPPipe env:CompletionInferValues Path Js.String2.slic [{ "label": "Js.String2.sliceToEnd", @@ -604,8 +631,8 @@ Path Js.String2.slic "documentation": {"kind": "markdown", "value": "\n`slice(str, from:n1, to_:n2)` returns the substring of `str` starting at\ncharacter `n1` up to but not including `n2`.\n- If either `n1` or `n2` is negative, then it is evaluated as `length(str - n1)` or `length(str - n2)`.\n- If `n2` is greater than the length of `str`, then it is treated as `length(str)`.\n- If `n1` is greater than `n2`, slice returns the empty string.\n\nSee [`String.slice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice) on MDN.\n\n## Examples\n\n```rescript\nJs.String2.slice(\"abcdefg\", ~from=2, ~to_=5) == \"cde\"\nJs.String2.slice(\"abcdefg\", ~from=2, ~to_=9) == \"cdefg\"\nJs.String2.slice(\"abcdefg\", ~from=-4, ~to_=-2) == \"de\"\nJs.String2.slice(\"abcdefg\", ~from=5, ~to_=1) == \"\"\n```\n"} }] -Complete src/CompletionInferValues.res 114:80 -posCursor:[114:80] posNoWhite:[114:79] Found expr:[114:70->114:80] +Complete src/CompletionInferValues.res 111:80 +posCursor:[111:80] posNoWhite:[111:79] Found expr:[111:70->111:80] Completable: Cpath Value[name]->slic Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -617,7 +644,6 @@ ContextPath Value[x] Path x ContextPath Type[otherNestedRecord] Path otherNestedRecord -CPPipe env:CompletionInferValues Path Js.String2.slic [{ "label": "Js.String2.sliceToEnd", @@ -633,37 +659,8 @@ Path Js.String2.slic "documentation": {"kind": "markdown", "value": "\n`slice(str, from:n1, to_:n2)` returns the substring of `str` starting at\ncharacter `n1` up to but not including `n2`.\n- If either `n1` or `n2` is negative, then it is evaluated as `length(str - n1)` or `length(str - n2)`.\n- If `n2` is greater than the length of `str`, then it is treated as `length(str)`.\n- If `n1` is greater than `n2`, slice returns the empty string.\n\nSee [`String.slice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice) on MDN.\n\n## Examples\n\n```rescript\nJs.String2.slice(\"abcdefg\", ~from=2, ~to_=5) == \"cde\"\nJs.String2.slice(\"abcdefg\", ~from=2, ~to_=9) == \"cdefg\"\nJs.String2.slice(\"abcdefg\", ~from=-4, ~to_=-2) == \"de\"\nJs.String2.slice(\"abcdefg\", ~from=5, ~to_=1) == \"\"\n```\n"} }] -Complete src/CompletionInferValues.res 118:67 -posCursor:[118:67] posNoWhite:[118:66] Found expr:[118:60->118:67] -Pexp_field [118:60->118:65] s:[118:66->118:67] -Completable: Cpath Value[inner].s -Package opens Pervasives.JsxModules.place holder -Resolved opens 1 pervasives -ContextPath Value[inner].s -ContextPath Value[inner] -Path inner -ContextPath CPatternPath(Value[x])->array -ContextPath Value[x] -Path x -ContextPath array -ContextPath Type[otherNestedRecord] -Path otherNestedRecord -[{ - "label": "someRecord", - "kind": 5, - "tags": [], - "detail": "someRecord", - "documentation": {"kind": "markdown", "value": "```rescript\nsomeRecord: someRecord\n```\n\n```rescript\ntype otherNestedRecord = {someRecord: someRecord, someTuple: (someVariant, int, somePolyVariant), optRecord: option}\n```"} - }, { - "label": "someTuple", - "kind": 5, - "tags": [], - "detail": "(someVariant, int, somePolyVariant)", - "documentation": {"kind": "markdown", "value": "```rescript\nsomeTuple: (someVariant, int, somePolyVariant)\n```\n\n```rescript\ntype otherNestedRecord = {someRecord: someRecord, someTuple: (someVariant, int, somePolyVariant), optRecord: option}\n```"} - }] - -Complete src/CompletionInferValues.res 122:53 -posCursor:[122:53] posNoWhite:[122:52] Found expr:[122:46->122:53] +Complete src/CompletionInferValues.res 115:53 +posCursor:[115:53] posNoWhite:[115:52] Found expr:[115:46->115:53] Completable: Cpath Value[v]->toSt Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -673,7 +670,6 @@ Path v ContextPath Value[x] Path x ContextPath int -CPPipe env:CompletionInferValues Path Belt.Int.toSt [{ "label": "Belt.Int.toString", @@ -683,13 +679,13 @@ Path Belt.Int.toSt "documentation": {"kind": "markdown", "value": "\nConverts a given `int` to a `string`. Uses the JavaScript `String` constructor under the hood.\n\n## Examples\n\n```rescript\nJs.log(Belt.Int.toString(1) === \"1\") /* true */\n```\n"} }] -Complete src/CompletionInferValues.res 130:26 -posCursor:[130:26] posNoWhite:[130:25] Found expr:[130:3->130:37] -Pexp_apply ...[130:3->130:23] (...[130:24->130:36]) -posCursor:[130:26] posNoWhite:[130:25] Found expr:[130:24->130:36] -posCursor:[130:26] posNoWhite:[130:25] Found expr:[130:25->130:36] -posCursor:[130:26] posNoWhite:[130:25] Found pattern:[130:25->130:27] -posCursor:[130:26] posNoWhite:[130:25] Found pattern:[130:25->130:27] +Complete src/CompletionInferValues.res 123:26 +posCursor:[123:26] posNoWhite:[123:25] Found expr:[123:3->123:37] +Pexp_apply ...[123:3->123:23] (...[123:24->123:36]) +posCursor:[123:26] posNoWhite:[123:25] Found expr:[123:24->123:36] +posCursor:[123:26] posNoWhite:[123:25] Found expr:[123:25->123:36] +posCursor:[123:26] posNoWhite:[123:25] Found pattern:[123:25->123:27] +posCursor:[123:26] posNoWhite:[123:25] Found pattern:[123:25->123:27] Completable: Cpattern CArgument CArgument Value[fnWithRecordCallback]($0)($0)->recordBody Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -711,13 +707,13 @@ Path fnWithRecordCallback "documentation": {"kind": "markdown", "value": "```rescript\nage: int\n```\n\n```rescript\ntype someRecord = {name: string, age: int}\n```"} }] -Complete src/CompletionInferValues.res 137:30 -posCursor:[137:30] posNoWhite:[137:29] Found expr:[137:3->137:33] -Pexp_apply ...[137:3->137:6] (~cb137:8->137:10=...[137:11->137:32]) -posCursor:[137:30] posNoWhite:[137:29] Found expr:[137:11->137:32] -posCursor:[137:30] posNoWhite:[137:29] Found expr:[137:12->137:32] -posCursor:[137:30] posNoWhite:[137:29] Found expr:[137:24->0:-1] -posCursor:[137:30] posNoWhite:[137:29] Found expr:[137:24->0:-1] +Complete src/CompletionInferValues.res 130:30 +posCursor:[130:30] posNoWhite:[130:29] Found expr:[130:3->130:33] +Pexp_apply ...[130:3->130:6] (~cb130:8->130:10=...[130:11->130:32]) +posCursor:[130:30] posNoWhite:[130:29] Found expr:[130:11->130:32] +posCursor:[130:30] posNoWhite:[130:29] Found expr:[130:12->130:32] +posCursor:[130:30] posNoWhite:[130:29] Found expr:[130:24->0:-1] +posCursor:[130:30] posNoWhite:[130:29] Found expr:[130:24->0:-1] Completable: Cpath Value[root]-> Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -729,8 +725,6 @@ ContextPath CArgument CArgument Value[fn2](~cb)($0) ContextPath CArgument Value[fn2](~cb) ContextPath Value[fn2] Path fn2 -CPPipe env:CompletionInferValues -CPPipe type path:ReactDOM.Client.Root.t CPPipe pathFromEnv:ReactDOM.Client.Root found:false Path ReactDOM.Client.Root. [{ @@ -747,13 +741,13 @@ Path ReactDOM.Client.Root. "documentation": null }] -Complete src/CompletionInferValues.res 146:30 -posCursor:[146:30] posNoWhite:[146:29] Found expr:[146:3->146:33] -Pexp_apply ...[146:3->146:6] (~cb146:8->146:10=...[146:11->146:32]) -posCursor:[146:30] posNoWhite:[146:29] Found expr:[146:11->146:32] -posCursor:[146:30] posNoWhite:[146:29] Found expr:[146:12->146:32] -posCursor:[146:30] posNoWhite:[146:29] Found expr:[146:24->0:-1] -posCursor:[146:30] posNoWhite:[146:29] Found expr:[146:24->0:-1] +Complete src/CompletionInferValues.res 139:30 +posCursor:[139:30] posNoWhite:[139:29] Found expr:[139:3->139:33] +Pexp_apply ...[139:3->139:6] (~cb139:8->139:10=...[139:11->139:32]) +posCursor:[139:30] posNoWhite:[139:29] Found expr:[139:11->139:32] +posCursor:[139:30] posNoWhite:[139:29] Found expr:[139:12->139:32] +posCursor:[139:30] posNoWhite:[139:29] Found expr:[139:24->0:-1] +posCursor:[139:30] posNoWhite:[139:29] Found expr:[139:24->0:-1] Completable: Cpath Value[root]-> Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -765,8 +759,6 @@ ContextPath CArgument CArgument Value[fn3](~cb)($0) ContextPath CArgument Value[fn3](~cb) ContextPath Value[fn3] Path fn3 -CPPipe env:CompletionInferValues -CPPipe type path:CompletionSupport.Test.t CPPipe pathFromEnv:CompletionSupport.Test found:false Path CompletionSupport.Test. [{ @@ -781,15 +773,9 @@ Path CompletionSupport.Test. "tags": [], "detail": "t => t", "documentation": null - }, { - "label": "CompletionSupport.Test.make", - "kind": 12, - "tags": [], - "detail": "int => t", - "documentation": null }] -Complete src/CompletionInferValues.res 150:47 +Complete src/CompletionInferValues.res 143:47 XXX Not found! Completable: Cpattern Value[Belt, Int, toString](Nolabel) Package opens Pervasives.JsxModules.place holder @@ -808,7 +794,7 @@ Path Belt.Int.toString "insertTextFormat": 2 }] -Complete src/CompletionInferValues.res 154:70 +Complete src/CompletionInferValues.res 147:70 XXX Not found! Completable: Cpattern Value[Js, String2, split](Nolabel, Nolabel) Package opens Pervasives.JsxModules.place holder @@ -827,13 +813,13 @@ Path Js.String2.split "insertTextFormat": 2 }] -Complete src/CompletionInferValues.res 158:105 -posCursor:[158:105] posNoWhite:[158:104] Found expr:[158:18->158:110] -Pexp_apply ...[158:18->158:49] (~prepare158:51->158:58=...[158:59->158:72], ~render158:74->158:80=...[158:81->158:106], ...[158:107->158:109]) -posCursor:[158:105] posNoWhite:[158:104] Found expr:[158:81->158:106] -posCursor:[158:105] posNoWhite:[158:104] Found expr:[158:82->158:106] -posCursor:[158:105] posNoWhite:[158:104] Found expr:[158:97->158:105] -Pexp_field [158:97->158:104] _:[158:105->158:105] +Complete src/CompletionInferValues.res 151:105 +posCursor:[151:105] posNoWhite:[151:104] Found expr:[151:18->151:110] +Pexp_apply ...[151:18->151:49] (~prepare151:51->151:58=...[151:59->151:72], ~render151:74->151:80=...[151:81->151:106], ...[151:107->151:109]) +posCursor:[151:105] posNoWhite:[151:104] Found expr:[151:81->151:106] +posCursor:[151:105] posNoWhite:[151:104] Found expr:[151:82->151:106] +posCursor:[151:105] posNoWhite:[151:104] Found expr:[151:97->151:105] +Pexp_field [151:97->151:104] _:[151:105->151:105] Completable: Cpath Value[support]."" Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -845,6 +831,16 @@ ContextPath CArgument CArgument Value[CompletionSupport2, makeRenderer](~render) ContextPath CArgument Value[CompletionSupport2, makeRenderer](~render) ContextPath Value[CompletionSupport2, makeRenderer] Path CompletionSupport2.makeRenderer +ContextPath Value[support]-> +ContextPath Value[support] +Path support +ContextPath CPatternPath(CArgument CArgument Value[CompletionSupport2, makeRenderer](~render)($0))->recordField(support) +ContextPath CArgument CArgument Value[CompletionSupport2, makeRenderer](~render)($0) +ContextPath CArgument Value[CompletionSupport2, makeRenderer](~render) +ContextPath Value[CompletionSupport2, makeRenderer] +Path CompletionSupport2.makeRenderer +CPPipe pathFromEnv:CompletionSupport.Nested found:false +Path CompletionSupport.Nested. [{ "label": "root", "kind": 5, @@ -853,13 +849,13 @@ Path CompletionSupport2.makeRenderer "documentation": {"kind": "markdown", "value": "```rescript\nroot: ReactDOM.Client.Root.t\n```\n\n```rescript\ntype config = {root: ReactDOM.Client.Root.t}\n```"} }] -Complete src/CompletionInferValues.res 162:110 -posCursor:[162:110] posNoWhite:[162:109] Found expr:[162:18->162:115] -Pexp_apply ...[162:18->162:49] (~prepare162:51->162:58=...[162:59->162:72], ~render162:74->162:80=...[162:81->162:111], ...[162:112->162:114]) -posCursor:[162:110] posNoWhite:[162:109] Found expr:[162:81->162:111] -posCursor:[162:110] posNoWhite:[162:109] Found expr:[162:82->162:111] -posCursor:[162:110] posNoWhite:[162:109] Found expr:[162:104->0:-1] -posCursor:[162:110] posNoWhite:[162:109] Found expr:[162:104->0:-1] +Complete src/CompletionInferValues.res 155:110 +posCursor:[155:110] posNoWhite:[155:109] Found expr:[155:18->155:115] +Pexp_apply ...[155:18->155:49] (~prepare155:51->155:58=...[155:59->155:72], ~render155:74->155:80=...[155:81->155:111], ...[155:112->155:114]) +posCursor:[155:110] posNoWhite:[155:109] Found expr:[155:81->155:111] +posCursor:[155:110] posNoWhite:[155:109] Found expr:[155:82->155:111] +posCursor:[155:110] posNoWhite:[155:109] Found expr:[155:104->0:-1] +posCursor:[155:110] posNoWhite:[155:109] Found expr:[155:104->0:-1] Completable: Cpath Value[root]-> Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -871,8 +867,6 @@ ContextPath CArgument CArgument Value[CompletionSupport2, makeRenderer](~render) ContextPath CArgument Value[CompletionSupport2, makeRenderer](~render) ContextPath Value[CompletionSupport2, makeRenderer] Path CompletionSupport2.makeRenderer -CPPipe env:CompletionInferValues envFromCompletionItem:CompletionSupport2.Internal -CPPipe type path:ReactDOM.Client.Root.t CPPipe pathFromEnv:ReactDOM.Client.Root found:false Path ReactDOM.Client.Root. [{ @@ -889,10 +883,10 @@ Path ReactDOM.Client.Root. "documentation": null }] -Hover src/CompletionInferValues.res 167:27 +Hover src/CompletionInferValues.res 160:27 Nothing at that position. Now trying to use completion. -posCursor:[167:27] posNoWhite:[167:26] Found expr:[167:25->167:28] -Pexp_ident res:[167:25->167:28] +posCursor:[160:27] posNoWhite:[160:26] Found expr:[160:25->160:28] +Pexp_ident res:[160:25->160:28] Completable: Cpath Value[res] Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives diff --git a/analysis/tests/src/expected/CompletionJsx.res.txt b/analysis/tests/src/expected/CompletionJsx.res.txt index 65c5e9e89..31041216d 100644 --- a/analysis/tests/src/expected/CompletionJsx.res.txt +++ b/analysis/tests/src/expected/CompletionJsx.res.txt @@ -6,7 +6,6 @@ Resolved opens 1 pervasives ContextPath Value[someString]->st ContextPath Value[someString] Path someString -CPPipe env:CompletionJsx Path Js.String2.st [{ "label": "Js.String2.startsWith", @@ -37,7 +36,6 @@ Resolved opens 1 pervasives ContextPath Value[someString]->st <> ContextPath Value[someString] Path someString -CPPipe env:CompletionJsx Path Js.String2.st [{ "label": "React.string", @@ -83,7 +81,6 @@ Resolved opens 1 pervasives ContextPath Value[someString]->st <> ContextPath Value[someString] Path someString -CPPipe env:CompletionJsx Path Js.String2.st [{ "label": "React.string", @@ -128,7 +125,6 @@ Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives ContextPath string->st <> ContextPath string -CPPipe env:CompletionJsx Path Js.String2.st [{ "label": "React.string", @@ -175,7 +171,6 @@ ContextPath Value[Js, String2, trim](Nolabel)->st <> ContextPath Value[Js, String2, trim](Nolabel) ContextPath Value[Js, String2, trim] Path Js.String2.trim -CPPipe env:CompletionJsx envFromCompletionItem:Js_string2 Path Js.String2.st [{ "label": "React.string", @@ -221,7 +216,6 @@ Resolved opens 1 pervasives ContextPath Value[someInt]-> <> ContextPath Value[someInt] Path someInt -CPPipe env:CompletionJsx Path Belt.Int. [{ "label": "React.int", @@ -231,12 +225,6 @@ Path Belt.Int. "documentation": {"kind": "markdown", "value": "Turns `int` into a JSX element so it can be used inside of JSX."}, "sortText": "A", "insertTextFormat": 2 - }, { - "label": "Belt.Int.fromString", - "kind": 12, - "tags": [], - "detail": "string => option", - "documentation": {"kind": "markdown", "value": "\nConverts a given `string` to an `int`. Returns `Some(int)` when the input is a number, `None` otherwise.\n\n## Examples\n\n```rescript\nJs.log(Belt.Int.fromString(\"1\") === Some(1)) /* true */\n```\n"} }, { "label": "Belt.Int.*", "kind": 12, @@ -261,12 +249,6 @@ Path Belt.Int. "tags": [], "detail": "int => float", "documentation": {"kind": "markdown", "value": "\nConverts a given `int` to a `float`.\n\n## Examples\n\n```rescript\nJs.log(Belt.Int.toFloat(1) === 1.0) /* true */\n```\n"} - }, { - "label": "Belt.Int.fromFloat", - "kind": 12, - "tags": [], - "detail": "float => int", - "documentation": {"kind": "markdown", "value": "\nConverts a given `float` to an `int`.\n\n## Examples\n\n```rescript\nJs.log(Belt.Int.fromFloat(1.0) === 1) /* true */\n```\n"} }, { "label": "Belt.Int.-", "kind": 12, @@ -302,7 +284,6 @@ Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives ContextPath int-> <> ContextPath int -CPPipe env:CompletionJsx Path Belt.Int. [{ "label": "React.int", @@ -312,12 +293,6 @@ Path Belt.Int. "documentation": {"kind": "markdown", "value": "Turns `int` into a JSX element so it can be used inside of JSX."}, "sortText": "A", "insertTextFormat": 2 - }, { - "label": "Belt.Int.fromString", - "kind": 12, - "tags": [], - "detail": "string => option", - "documentation": {"kind": "markdown", "value": "\nConverts a given `string` to an `int`. Returns `Some(int)` when the input is a number, `None` otherwise.\n\n## Examples\n\n```rescript\nJs.log(Belt.Int.fromString(\"1\") === Some(1)) /* true */\n```\n"} }, { "label": "Belt.Int.*", "kind": 12, @@ -342,12 +317,6 @@ Path Belt.Int. "tags": [], "detail": "int => float", "documentation": {"kind": "markdown", "value": "\nConverts a given `int` to a `float`.\n\n## Examples\n\n```rescript\nJs.log(Belt.Int.toFloat(1) === 1.0) /* true */\n```\n"} - }, { - "label": "Belt.Int.fromFloat", - "kind": 12, - "tags": [], - "detail": "float => int", - "documentation": {"kind": "markdown", "value": "\nConverts a given `float` to an `int`.\n\n## Examples\n\n```rescript\nJs.log(Belt.Int.fromFloat(1.0) === 1) /* true */\n```\n"} }, { "label": "Belt.Int.-", "kind": 12, @@ -384,7 +353,6 @@ Resolved opens 1 pervasives ContextPath Value[someArr]->a <> ContextPath Value[someArr] Path someArr -CPPipe env:CompletionJsx Path Js.Array2.a [{ "label": "React.array", diff --git a/analysis/tests/src/expected/CompletionMultipleEditorCompleteFrom.res.txt b/analysis/tests/src/expected/CompletionMultipleEditorCompleteFrom.res.txt new file mode 100644 index 000000000..76504e198 --- /dev/null +++ b/analysis/tests/src/expected/CompletionMultipleEditorCompleteFrom.res.txt @@ -0,0 +1,42 @@ +Complete src/CompletionMultipleEditorCompleteFrom.res 19:5 +posCursor:[19:5] posNoWhite:[19:4] Found expr:[19:3->19:5] +Pexp_field [19:3->19:4] _:[22:0->19:5] +Completable: Cpath Value[a]."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[a]."" +ContextPath Value[a] +Path a +ContextPath Value[a]-> +ContextPath Value[a] +Path a +CPPipe pathFromEnv:A found:true +Path A. +Path B. +Path C. +[{ + "label": "->B.b", + "kind": 12, + "tags": [], + "detail": "A.a => int", + "documentation": null, + "sortText": "b", + "insertText": "->B.b", + "additionalTextEdits": [{ + "range": {"start": {"line": 19, "character": 4}, "end": {"line": 19, "character": 5}}, + "newText": "" + }] + }, { + "label": "->C.c", + "kind": 12, + "tags": [], + "detail": "A.a => char", + "documentation": null, + "sortText": "c", + "insertText": "->C.c", + "additionalTextEdits": [{ + "range": {"start": {"line": 19, "character": 4}, "end": {"line": 19, "character": 5}}, + "newText": "" + }] + }] + diff --git a/analysis/tests/src/expected/CompletionPipeChain.res.txt b/analysis/tests/src/expected/CompletionPipeChain.res.txt index 91f6ca0e1..d1eb333af 100644 --- a/analysis/tests/src/expected/CompletionPipeChain.res.txt +++ b/analysis/tests/src/expected/CompletionPipeChain.res.txt @@ -6,8 +6,6 @@ Resolved opens 1 pervasives ContextPath Value[int]-> ContextPath Value[int] Path int -CPPipe env:CompletionPipeChain -CPPipe type path:Integer.t CPPipe pathFromEnv:Integer found:true Path Integer. [{ @@ -28,12 +26,6 @@ Path Integer. "tags": [], "detail": "(t, int => int) => t", "documentation": null - }, { - "label": "Integer.make", - "kind": 12, - "tags": [], - "detail": "int => t", - "documentation": null }] Complete src/CompletionPipeChain.res 30:23 @@ -45,17 +37,9 @@ ContextPath Value[toFlt](Nolabel)-> ContextPath Value[toFlt](Nolabel) ContextPath Value[toFlt] Path toFlt -CPPipe env:CompletionPipeChain -CPPipe type path:SuperFloat.t CPPipe pathFromEnv:SuperFloat found:true Path SuperFloat. [{ - "label": "SuperFloat.fromInteger", - "kind": 12, - "tags": [], - "detail": "Integer.t => t", - "documentation": null - }, { "label": "SuperFloat.toInteger", "kind": 12, "tags": [], @@ -72,8 +56,6 @@ ContextPath Value[Integer, increment](Nolabel, Nolabel)-> ContextPath Value[Integer, increment](Nolabel, Nolabel) ContextPath Value[Integer, increment] Path Integer.increment -CPPipe env:CompletionPipeChain envFromCompletionItem:CompletionPipeChain.Integer -CPPipe type path:t CPPipe pathFromEnv:Integer found:true Path Integer. [{ @@ -94,12 +76,6 @@ Path Integer. "tags": [], "detail": "(t, int => int) => t", "documentation": null - }, { - "label": "Integer.make", - "kind": 12, - "tags": [], - "detail": "int => t", - "documentation": null }] Complete src/CompletionPipeChain.res 36:38 @@ -111,8 +87,6 @@ ContextPath Value[Integer, increment](Nolabel, Nolabel)-> ContextPath Value[Integer, increment](Nolabel, Nolabel) ContextPath Value[Integer, increment] Path Integer.increment -CPPipe env:CompletionPipeChain envFromCompletionItem:CompletionPipeChain.Integer -CPPipe type path:t CPPipe pathFromEnv:Integer found:true Path Integer. [{ @@ -133,12 +107,6 @@ Path Integer. "tags": [], "detail": "(t, int => int) => t", "documentation": null - }, { - "label": "Integer.make", - "kind": 12, - "tags": [], - "detail": "int => t", - "documentation": null }] Complete src/CompletionPipeChain.res 39:47 @@ -150,8 +118,6 @@ ContextPath Value[Integer, decrement](Nolabel, Nolabel)-> ContextPath Value[Integer, decrement](Nolabel, Nolabel) ContextPath Value[Integer, decrement] Path Integer.decrement -CPPipe env:CompletionPipeChain envFromCompletionItem:CompletionPipeChain.Integer -CPPipe type path:t CPPipe pathFromEnv:Integer found:true Path Integer. [{ @@ -172,12 +138,6 @@ Path Integer. "tags": [], "detail": "(t, int => int) => t", "documentation": null - }, { - "label": "Integer.make", - "kind": 12, - "tags": [], - "detail": "int => t", - "documentation": null }] Complete src/CompletionPipeChain.res 42:69 @@ -189,8 +149,6 @@ ContextPath Value[Integer, decrement](Nolabel, Nolabel)-> ContextPath Value[Integer, decrement](Nolabel, Nolabel) ContextPath Value[Integer, decrement] Path Integer.decrement -CPPipe env:CompletionPipeChain envFromCompletionItem:CompletionPipeChain.Integer -CPPipe type path:t CPPipe pathFromEnv:Integer found:true Path Integer. [{ @@ -211,12 +169,6 @@ Path Integer. "tags": [], "detail": "(t, int => int) => t", "documentation": null - }, { - "label": "Integer.make", - "kind": 12, - "tags": [], - "detail": "int => t", - "documentation": null }] Complete src/CompletionPipeChain.res 45:62 @@ -228,17 +180,9 @@ ContextPath Value[SuperFloat, fromInteger](Nolabel)-> ContextPath Value[SuperFloat, fromInteger](Nolabel) ContextPath Value[SuperFloat, fromInteger] Path SuperFloat.fromInteger -CPPipe env:CompletionPipeChain envFromCompletionItem:CompletionPipeChain.SuperFloat -CPPipe type path:t CPPipe pathFromEnv:SuperFloat found:true Path SuperFloat. [{ - "label": "SuperFloat.fromInteger", - "kind": 12, - "tags": [], - "detail": "Integer.t => t", - "documentation": null - }, { "label": "SuperFloat.toInteger", "kind": 12, "tags": [], @@ -255,8 +199,6 @@ ContextPath Value[SuperFloat, fromInteger](Nolabel)->t ContextPath Value[SuperFloat, fromInteger](Nolabel) ContextPath Value[SuperFloat, fromInteger] Path SuperFloat.fromInteger -CPPipe env:CompletionPipeChain envFromCompletionItem:CompletionPipeChain.SuperFloat -CPPipe type path:t CPPipe pathFromEnv:SuperFloat found:true Path SuperFloat.t [{ @@ -276,8 +218,6 @@ ContextPath Value[CompletionSupport, Test, make](Nolabel)-> ContextPath Value[CompletionSupport, Test, make](Nolabel) ContextPath Value[CompletionSupport, Test, make] Path CompletionSupport.Test.make -CPPipe env:CompletionPipeChain envFromCompletionItem:CompletionSupport.Test -CPPipe type path:t CPPipe pathFromEnv:Test found:true Path CompletionSupport.Test. [{ @@ -292,12 +232,6 @@ Path CompletionSupport.Test. "tags": [], "detail": "t => t", "documentation": null - }, { - "label": "CompletionSupport.Test.make", - "kind": 12, - "tags": [], - "detail": "int => t", - "documentation": null }] Complete src/CompletionPipeChain.res 54:78 @@ -309,8 +243,6 @@ ContextPath Value[CompletionSupport, Test, addSelf](Nolabel, Nolabel)-> ContextPath Value[CompletionSupport, Test, addSelf](Nolabel, Nolabel) ContextPath Value[CompletionSupport, Test, addSelf] Path CompletionSupport.Test.addSelf -CPPipe env:CompletionPipeChain envFromCompletionItem:CompletionSupport.Test -CPPipe type path:t CPPipe pathFromEnv:Test found:true Path CompletionSupport.Test. [{ @@ -325,12 +257,6 @@ Path CompletionSupport.Test. "tags": [], "detail": "t => t", "documentation": null - }, { - "label": "CompletionSupport.Test.make", - "kind": 12, - "tags": [], - "detail": "int => t", - "documentation": null }] Complete src/CompletionPipeChain.res 58:5 @@ -342,9 +268,8 @@ ContextPath Value[Js, Array2, forEach](Nolabel, Nolabel)-> ContextPath Value[Js, Array2, forEach](Nolabel, Nolabel) ContextPath Value[Js, Array2, forEach] Path Js.Array2.forEach -CPPipe env:CompletionPipeChain envFromCompletionItem:Js_array2 -CPPipe type path:unit CPPipe pathFromEnv: found:true +Path Js_array2. [] Complete src/CompletionPipeChain.res 62:6 @@ -356,7 +281,6 @@ ContextPath Value[Belt, Array, reduce](Nolabel, Nolabel, Nolabel)->t ContextPath Value[Belt, Array, reduce](Nolabel, Nolabel, Nolabel) ContextPath Value[Belt, Array, reduce] Path Belt.Array.reduce -CPPipe env:CompletionPipeChain envFromCompletionItem:Belt_Array Path Belt.Int.t [{ "label": "Belt.Int.toString", @@ -380,8 +304,6 @@ Resolved opens 1 pervasives ContextPath Value[aliased]-> ContextPath Value[aliased] Path aliased -CPPipe env:CompletionPipeChain -CPPipe type path:CompletionSupport.Test.t CPPipe pathFromEnv:CompletionSupport.Test found:false Path CompletionSupport.Test. [{ @@ -396,12 +318,6 @@ Path CompletionSupport.Test. "tags": [], "detail": "t => t", "documentation": null - }, { - "label": "CompletionSupport.Test.make", - "kind": 12, - "tags": [], - "detail": "int => t", - "documentation": null }] Complete src/CompletionPipeChain.res 73:15 @@ -412,8 +328,6 @@ Resolved opens 1 pervasives ContextPath Value[notAliased]-> ContextPath Value[notAliased] Path notAliased -CPPipe env:CompletionPipeChain -CPPipe type path:CompletionSupport.Test.t CPPipe pathFromEnv:CompletionSupport.Test found:false Path CompletionSupport.Test. [{ @@ -428,12 +342,6 @@ Path CompletionSupport.Test. "tags": [], "detail": "t => t", "documentation": null - }, { - "label": "CompletionSupport.Test.make", - "kind": 12, - "tags": [], - "detail": "int => t", - "documentation": null }] Complete src/CompletionPipeChain.res 82:30 @@ -452,8 +360,22 @@ ContextPath Value[props].support.root ContextPath Value[props].support ContextPath Value[props] Path props -CPPipe env:CompletionPipeChain envFromCompletionItem:CompletionSupport.Nested -CPPipe type path:ReactDOM.Client.Root.t +ContextPath Value[props]->support +ContextPath Value[props] +Path props +CPPipe pathFromEnv:CompletionSupport2.Internal found:false +Path CompletionSupport2.Internal.support +ContextPath Value[props].support->root +ContextPath Value[props].support +ContextPath Value[props] +Path props +ContextPath Value[props]->support +ContextPath Value[props] +Path props +CPPipe pathFromEnv:CompletionSupport2.Internal found:false +Path CompletionSupport2.Internal.support +CPPipe pathFromEnv:CompletionSupport.Nested found:false +Path CompletionSupport.Nested.root CPPipe pathFromEnv:ReactDOM.Client.Root found:false Path ReactDOM.Client.Root.ren [{ @@ -480,8 +402,6 @@ Resolved opens 1 pervasives ContextPath Value[root]->ren ContextPath Value[root] Path root -CPPipe env:CompletionPipeChain -CPPipe type path:ReactDOM.Client.Root.t CPPipe pathFromEnv:ReactDOM.Client.Root found:false Path ReactDOM.Client.Root.ren [{ @@ -503,8 +423,6 @@ Resolved opens 1 pervasives ContextPath Value[int]-> ContextPath Value[int] Path int -CPPipe env:CompletionPipeChain -CPPipe type path:Integer.t CPPipe pathFromEnv:Integer found:true Path Integer. [{ @@ -525,12 +443,6 @@ Path Integer. "tags": [], "detail": "(t, int => int) => t", "documentation": null - }, { - "label": "Integer.make", - "kind": 12, - "tags": [], - "detail": "int => t", - "documentation": null }] Complete src/CompletionPipeChain.res 98:21 @@ -543,8 +455,6 @@ Resolved opens 1 pervasives ContextPath Value[int]->t ContextPath Value[int] Path int -CPPipe env:CompletionPipeChain -CPPipe type path:Integer.t CPPipe pathFromEnv:Integer found:true Path Integer.t [{ @@ -563,7 +473,7 @@ Resolved opens 1 pervasives ContextPath Value[r]->la ContextPath Value[r] Path r -CPPipe env:CompletionPipeChain +CPPipe pathFromEnv:Js.Re found:false Path Js.Re.la [{ "label": "Js.Re.lastIndex", @@ -573,3 +483,21 @@ Path Js.Re.la "documentation": {"kind": "markdown", "value": "\nReturns the index where the next match will start its search. This property\nwill be modified when the RegExp object is used, if the global (\"g\") flag is\nset.\n\n## Examples\n\n```rescript\nlet re = %re(\"/ab*TODO/g\")\nlet str = \"abbcdefabh\"\n\nlet break = ref(false)\nwhile !break.contents {\n switch Js.Re.exec_(re, str) {\n | Some(result) => Js.Nullable.iter(Js.Re.captures(result)[0], (. match_) => {\n let next = Belt.Int.toString(Js.Re.lastIndex(re))\n Js.log(\"Found \" ++ (match_ ++ (\". Next match starts at \" ++ next)))\n })\n | None => break := true\n }\n}\n```\n\nSee\n[`RegExp: lastIndex`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastIndex)\non MDN.\n"} }] +Complete src/CompletionPipeChain.res 112:7 +posCursor:[112:7] posNoWhite:[112:6] Found expr:[112:3->0:-1] +Completable: Cpath Value[xx]-> +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[xx]-> +ContextPath Value[xx] +Path xx +CPPipe pathFromEnv:Xyz found:true +Path Xyz. +[{ + "label": "Xyz.do", + "kind": 12, + "tags": [], + "detail": "xx => string", + "documentation": null + }] + diff --git a/analysis/tests/src/expected/CompletionPipeProperty.res.txt b/analysis/tests/src/expected/CompletionPipeProperty.res.txt new file mode 100644 index 000000000..ac83d3192 --- /dev/null +++ b/analysis/tests/src/expected/CompletionPipeProperty.res.txt @@ -0,0 +1,64 @@ +Complete src/CompletionPipeProperty.res 21:17 +posCursor:[21:17] posNoWhite:[21:16] Found expr:[21:3->21:17] +Pexp_field [21:3->21:16] _:[23:0->21:17] +Completable: Cpath Value[sprite].anchor."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[sprite].anchor."" +ContextPath Value[sprite].anchor +ContextPath Value[sprite] +Path sprite +ContextPath Value[sprite]->anchor +ContextPath Value[sprite] +Path sprite +CPPipe pathFromEnv:Sprite found:true +Path Sprite.anchor +ContextPath Value[sprite].anchor-> +ContextPath Value[sprite].anchor +ContextPath Value[sprite] +Path sprite +ContextPath Value[sprite]->anchor +ContextPath Value[sprite] +Path sprite +CPPipe pathFromEnv:Sprite found:true +Path Sprite.anchor +CPPipe pathFromEnv:ObservablePoint found:true +Path ObservablePoint. +[{ + "label": "x", + "kind": 5, + "tags": [], + "detail": "int", + "documentation": {"kind": "markdown", "value": "```rescript\nx: int\n```\n\n```rescript\ntype op = {mutable x: int, mutable y: int}\n```"} + }, { + "label": "y", + "kind": 5, + "tags": [], + "detail": "int", + "documentation": {"kind": "markdown", "value": "```rescript\ny: int\n```\n\n```rescript\ntype op = {mutable x: int, mutable y: int}\n```"} + }, { + "label": "->ObservablePoint.setBoth", + "kind": 12, + "tags": [], + "detail": "(op, float) => unit", + "documentation": null, + "sortText": "setBoth", + "insertText": "->ObservablePoint.setBoth", + "additionalTextEdits": [{ + "range": {"start": {"line": 21, "character": 16}, "end": {"line": 21, "character": 17}}, + "newText": "" + }] + }, { + "label": "->ObservablePoint.set", + "kind": 12, + "tags": [], + "detail": "(op, float, float) => unit", + "documentation": null, + "sortText": "set", + "insertText": "->ObservablePoint.set", + "additionalTextEdits": [{ + "range": {"start": {"line": 21, "character": 16}, "end": {"line": 21, "character": 17}}, + "newText": "" + }] + }] + diff --git a/analysis/tests/src/expected/CompletionPipeSubmodules.res.txt b/analysis/tests/src/expected/CompletionPipeSubmodules.res.txt index 73f9ab4a5..90f0e089e 100644 --- a/analysis/tests/src/expected/CompletionPipeSubmodules.res.txt +++ b/analysis/tests/src/expected/CompletionPipeSubmodules.res.txt @@ -1,31 +1,23 @@ -Complete src/CompletionPipeSubmodules.res 12:20 -posCursor:[12:20] posNoWhite:[12:19] Found expr:[12:11->20:8] +Complete src/CompletionPipeSubmodules.res 13:20 +posCursor:[13:20] posNoWhite:[13:19] Found expr:[13:11->21:8] Completable: Cpath Value[A, B1, xx]-> Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives ContextPath Value[A, B1, xx]-> ContextPath Value[A, B1, xx] Path A.B1.xx -CPPipe env:CompletionPipeSubmodules envFromCompletionItem:CompletionPipeSubmodules.A.B1 -CPPipe type path:b1 CPPipe pathFromEnv:A.B1 found:true Path A.B1. [{ - "label": "A.B1.xx", + "label": "A.B1.d", "kind": 12, "tags": [], - "detail": "b1", - "documentation": {"kind": "markdown", "value": "```rescript\ntype b1 = B1\n```"} - }, { - "label": "A.B1.B1", - "kind": 4, - "tags": [], - "detail": "B1", - "documentation": {"kind": "markdown", "value": "```rescript\nB1\n```\n\n```rescript\ntype b1 = B1\n```"} + "detail": "b1 => string", + "documentation": null }] -Complete src/CompletionPipeSubmodules.res 16:18 -posCursor:[16:18] posNoWhite:[16:17] Found expr:[16:11->20:8] +Complete src/CompletionPipeSubmodules.res 17:18 +posCursor:[17:18] posNoWhite:[17:17] Found expr:[17:11->21:8] Completable: Cpath Value[A, x].v-> Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -33,26 +25,23 @@ ContextPath Value[A, x].v-> ContextPath Value[A, x].v ContextPath Value[A, x] Path A.x -CPPipe env:CompletionPipeSubmodules envFromCompletionItem:CompletionPipeSubmodules.A -CPPipe type path:B1.b1 +ContextPath Value[A, x]->v +ContextPath Value[A, x] +Path A.x +CPPipe pathFromEnv:A found:true +Path A.v CPPipe pathFromEnv:A.B1 found:true Path A.B1. [{ - "label": "A.B1.xx", + "label": "A.B1.d", "kind": 12, "tags": [], - "detail": "b1", - "documentation": {"kind": "markdown", "value": "```rescript\ntype b1 = B1\n```"} - }, { - "label": "A.B1.B1", - "kind": 4, - "tags": [], - "detail": "B1", - "documentation": {"kind": "markdown", "value": "```rescript\nB1\n```\n\n```rescript\ntype b1 = B1\n```"} + "detail": "b1 => string", + "documentation": null }] -Complete src/CompletionPipeSubmodules.res 38:20 -posCursor:[38:20] posNoWhite:[38:19] Found expr:[38:11->0:-1] +Complete src/CompletionPipeSubmodules.res 41:20 +posCursor:[41:20] posNoWhite:[41:19] Found expr:[41:11->0:-1] Completable: Cpath Value[E, e].v.v-> Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -61,20 +50,34 @@ ContextPath Value[E, e].v.v ContextPath Value[E, e].v ContextPath Value[E, e] Path E.e -CPPipe env:CompletionPipeSubmodules envFromCompletionItem:CompletionPipeSubmodules.D -CPPipe type path:C.t +ContextPath Value[E, e]->v +ContextPath Value[E, e] +Path E.e +CPPipe pathFromEnv:E found:true +Path E.v +ContextPath Value[E, e].v->v +ContextPath Value[E, e].v +ContextPath Value[E, e] +Path E.e +ContextPath Value[E, e]->v +ContextPath Value[E, e] +Path E.e +CPPipe pathFromEnv:E found:true +Path E.v +CPPipe pathFromEnv:D found:true +Path D.v CPPipe pathFromEnv:C found:false Path C. [{ - "label": "C.C", - "kind": 4, + "label": "C.do", + "kind": 12, "tags": [], - "detail": "C", - "documentation": {"kind": "markdown", "value": "```rescript\nC\n```\n\n```rescript\ntype t = C\n```"} + "detail": "t => string", + "documentation": null }] -Complete src/CompletionPipeSubmodules.res 42:21 -posCursor:[42:21] posNoWhite:[42:20] Found expr:[42:11->0:-1] +Complete src/CompletionPipeSubmodules.res 45:21 +posCursor:[45:21] posNoWhite:[45:20] Found expr:[45:11->0:-1] Completable: Cpath Value[E, e].v.v2-> Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives @@ -83,15 +86,29 @@ ContextPath Value[E, e].v.v2 ContextPath Value[E, e].v ContextPath Value[E, e] Path E.e -CPPipe env:CompletionPipeSubmodules envFromCompletionItem:CompletionPipeSubmodules.D -CPPipe type path:C2.t2 +ContextPath Value[E, e]->v +ContextPath Value[E, e] +Path E.e +CPPipe pathFromEnv:E found:true +Path E.v +ContextPath Value[E, e].v->v2 +ContextPath Value[E, e].v +ContextPath Value[E, e] +Path E.e +ContextPath Value[E, e]->v +ContextPath Value[E, e] +Path E.e +CPPipe pathFromEnv:E found:true +Path E.v +CPPipe pathFromEnv:D found:true +Path D.v2 CPPipe pathFromEnv:D.C2 found:true Path D.C2. [{ - "label": "D.C2.C2", - "kind": 4, + "label": "D.C2.do", + "kind": 12, "tags": [], - "detail": "C2", - "documentation": {"kind": "markdown", "value": "```rescript\nC2\n```\n\n```rescript\ntype t2 = C2\n```"} + "detail": "t2 => string", + "documentation": null }] diff --git a/analysis/tests/src/expected/Cross.res.txt b/analysis/tests/src/expected/Cross.res.txt index 6f5ad3e43..a4c058b6a 100644 --- a/analysis/tests/src/expected/Cross.res.txt +++ b/analysis/tests/src/expected/Cross.res.txt @@ -35,12 +35,12 @@ Rename src/Cross.res 18:13 RenameWithInterfacePrime "uri": "Cross.res" }, "edits": [{ - "range": {"start": {"line": 18, "character": 8}, "end": {"line": 18, "character": 27}}, - "newText": "RenameWithInterfacePrime" - }, { - "range": {"start": {"line": 21, "character": 8}, "end": {"line": 21, "character": 27}}, - "newText": "RenameWithInterfacePrime" - }] + "range": {"start": {"line": 18, "character": 8}, "end": {"line": 18, "character": 27}}, + "newText": "RenameWithInterfacePrime" + }, { + "range": {"start": {"line": 21, "character": 8}, "end": {"line": 21, "character": 27}}, + "newText": "RenameWithInterfacePrime" + }] } ] @@ -52,9 +52,9 @@ Rename src/Cross.res 21:28 xPrime "uri": "RenameWithInterface.resi" }, "edits": [{ - "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, - "newText": "xPrime" - }] + "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, + "newText": "xPrime" + }] }, { "textDocument": { @@ -62,9 +62,9 @@ Rename src/Cross.res 21:28 xPrime "uri": "RenameWithInterface.res" }, "edits": [{ - "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, - "newText": "xPrime" - }] + "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, + "newText": "xPrime" + }] }, { "textDocument": { @@ -72,12 +72,12 @@ Rename src/Cross.res 21:28 xPrime "uri": "Cross.res" }, "edits": [{ - "range": {"start": {"line": 18, "character": 28}, "end": {"line": 18, "character": 29}}, - "newText": "xPrime" - }, { - "range": {"start": {"line": 21, "character": 28}, "end": {"line": 21, "character": 29}}, - "newText": "xPrime" - }] + "range": {"start": {"line": 18, "character": 28}, "end": {"line": 18, "character": 29}}, + "newText": "xPrime" + }, { + "range": {"start": {"line": 21, "character": 28}, "end": {"line": 21, "character": 29}}, + "newText": "xPrime" + }] } ] diff --git a/analysis/tests/src/expected/DotPipeCompletionSpec.res.txt b/analysis/tests/src/expected/DotPipeCompletionSpec.res.txt new file mode 100644 index 000000000..4126787a3 --- /dev/null +++ b/analysis/tests/src/expected/DotPipeCompletionSpec.res.txt @@ -0,0 +1,707 @@ +Complete src/DotPipeCompletionSpec.res 15:5 +posCursor:[15:5] posNoWhite:[15:4] Found expr:[15:3->15:5] +Pexp_field [15:3->15:4] _:[18:0->15:5] +Completable: Cpath Value[n]."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[n]."" +ContextPath Value[n] +Path n +ContextPath Value[n]-> +ContextPath Value[n] +Path n +CPPipe pathFromEnv:SomeModule found:true +Path SomeModule. +[{ + "label": "name", + "kind": 5, + "tags": [], + "detail": "string", + "documentation": {"kind": "markdown", "value": "```rescript\nname: string\n```\n\n```rescript\ntype t = {name: string}\n```"} + }, { + "label": "->SomeModule.withUnlabelledArgumentNotFirst", + "kind": 12, + "tags": [], + "detail": "(~name: string=?, t) => unit", + "documentation": null, + "sortText": "withUnlabelledArgumentNotFirst", + "insertText": "->SomeModule.withUnlabelledArgumentNotFirst", + "additionalTextEdits": [{ + "range": {"start": {"line": 15, "character": 4}, "end": {"line": 15, "character": 5}}, + "newText": "" + }] + }, { + "label": "->SomeModule.getName", + "kind": 12, + "tags": [], + "detail": "t => string", + "documentation": null, + "sortText": "getName", + "insertText": "->SomeModule.getName", + "additionalTextEdits": [{ + "range": {"start": {"line": 15, "character": 4}, "end": {"line": 15, "character": 5}}, + "newText": "" + }] + }] + +Complete src/DotPipeCompletionSpec.res 44:6 +posCursor:[44:6] posNoWhite:[44:5] Found expr:[44:3->44:6] +Pexp_field [44:3->44:5] _:[47:0->44:6] +Completable: Cpath Value[nn]."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[nn]."" +ContextPath Value[nn] +Path nn +ContextPath Value[nn]-> +ContextPath Value[nn] +Path nn +CPPipe pathFromEnv:SomeOtherModule found:true +Path SomeOtherModule. +Path DotPipeCompletionSpec.CompleteFromThisToo. +Path DotPipeCompletionSpec.SomeOtherModule. +[{ + "label": "nname", + "kind": 5, + "tags": [], + "detail": "string", + "documentation": {"kind": "markdown", "value": "```rescript\nnname: string\n```\n\n```rescript\ntype typeOutsideModule = {nname: string}\n```"} + }, { + "label": "->SomeOtherModule.getNName", + "kind": 12, + "tags": [], + "detail": "t => string", + "documentation": null, + "sortText": "getNName", + "insertText": "->SomeOtherModule.getNName", + "additionalTextEdits": [{ + "range": {"start": {"line": 44, "character": 5}, "end": {"line": 44, "character": 6}}, + "newText": "" + }] + }, { + "label": "->SomeOtherModule.getNName2", + "kind": 12, + "tags": [], + "detail": "typeOutsideModule => string", + "documentation": null, + "sortText": "getNName2", + "insertText": "->SomeOtherModule.getNName2", + "additionalTextEdits": [{ + "range": {"start": {"line": 44, "character": 5}, "end": {"line": 44, "character": 6}}, + "newText": "" + }] + }, { + "label": "->CompleteFromThisToo.a", + "kind": 12, + "tags": [], + "detail": "typeOutsideModule => string", + "documentation": null, + "sortText": "a", + "insertText": "->CompleteFromThisToo.a", + "additionalTextEdits": [{ + "range": {"start": {"line": 44, "character": 5}, "end": {"line": 44, "character": 6}}, + "newText": "" + }] + }, { + "label": "->SomeOtherModule.getNName", + "kind": 12, + "tags": [], + "detail": "t => string", + "documentation": null, + "sortText": "getNName", + "insertText": "->SomeOtherModule.getNName", + "additionalTextEdits": [{ + "range": {"start": {"line": 44, "character": 5}, "end": {"line": 44, "character": 6}}, + "newText": "" + }] + }, { + "label": "->SomeOtherModule.getNName2", + "kind": 12, + "tags": [], + "detail": "typeOutsideModule => string", + "documentation": null, + "sortText": "getNName2", + "insertText": "->SomeOtherModule.getNName2", + "additionalTextEdits": [{ + "range": {"start": {"line": 44, "character": 5}, "end": {"line": 44, "character": 6}}, + "newText": "" + }] + }] + +Complete src/DotPipeCompletionSpec.res 62:5 +posCursor:[62:5] posNoWhite:[62:4] Found expr:[62:3->62:5] +Pexp_field [62:3->62:4] _:[65:0->62:5] +Completable: Cpath Value[a]."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[a]."" +ContextPath Value[a] +Path a +ContextPath Value[a]-> +ContextPath Value[a] +Path a +CPPipe pathFromEnv:A found:true +Path A. +Path B. +[{ + "label": "->A.withA", + "kind": 12, + "tags": [], + "detail": "a => unit", + "documentation": null, + "sortText": "withA", + "insertText": "->A.withA", + "additionalTextEdits": [{ + "range": {"start": {"line": 62, "character": 4}, "end": {"line": 62, "character": 5}}, + "newText": "" + }] + }, { + "label": "->B.b", + "kind": 12, + "tags": [], + "detail": "A.a => int", + "documentation": null, + "sortText": "b", + "insertText": "->B.b", + "additionalTextEdits": [{ + "range": {"start": {"line": 62, "character": 4}, "end": {"line": 62, "character": 5}}, + "newText": "" + }] + }] + +Complete src/DotPipeCompletionSpec.res 67:6 +posCursor:[67:6] posNoWhite:[67:5] Found expr:[67:3->67:6] +Pexp_field [67:3->67:5] _:[70:0->67:6] +Completable: Cpath Value[xx]."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[xx]."" +ContextPath Value[xx] +Path xx +ContextPath Value[xx]-> +ContextPath Value[xx] +Path xx +CPPipe pathFromEnv:CompletionFromModule.SomeModule found:false +Path CompletionFromModule.SomeModule. +[{ + "label": "name", + "kind": 5, + "tags": [], + "detail": "string", + "documentation": {"kind": "markdown", "value": "```rescript\nname: string\n```\n\n```rescript\ntype t = {name: string}\n```"} + }, { + "label": "->CompletionFromModule.SomeModule.getName", + "kind": 12, + "tags": [], + "detail": "t => string", + "documentation": null, + "sortText": "getName", + "insertText": "->CompletionFromModule.SomeModule.getName", + "additionalTextEdits": [{ + "range": {"start": {"line": 67, "character": 5}, "end": {"line": 67, "character": 6}}, + "newText": "" + }] + }] + +Complete src/DotPipeCompletionSpec.res 75:9 +posCursor:[75:9] posNoWhite:[75:8] Found expr:[75:3->75:9] +Pexp_field [75:3->75:7] u:[75:8->75:9] +Completable: Cpath Value[ffff].u +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[ffff].u +ContextPath Value[ffff] +Path ffff +ContextPath Value[ffff]->u +ContextPath Value[ffff] +Path ffff +Path Js.Array2.u +[{ + "label": "->Js.Array2.unshiftMany", + "kind": 12, + "tags": [], + "detail": "(t<'a>, array<'a>) => int", + "documentation": {"kind": "markdown", "value": "\nAdds the elements in the second array argument at the beginning of the first\narray argument, returning the new number of elements in the array. *This\nfunction modifies the original array.* See\n[`Array.unshift`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift)\non MDN.\n\n## Examples\n\n```rescript\nlet arr = [\"d\", \"e\"]\nJs.Array2.unshiftMany(arr, [\"a\", \"b\", \"c\"]) == 5\narr == [\"a\", \"b\", \"c\", \"d\", \"e\"]\n```\n"}, + "sortText": "unshiftMany", + "insertText": "->Js.Array2.unshiftMany", + "additionalTextEdits": [{ + "range": {"start": {"line": 75, "character": 7}, "end": {"line": 75, "character": 8}}, + "newText": "" + }] + }, { + "label": "->Js.Array2.unshift", + "kind": 12, + "tags": [], + "detail": "(t<'a>, 'a) => int", + "documentation": {"kind": "markdown", "value": "\nAdds the given element to the array, returning the new number of elements in\nthe array. *This function modifies the original array.* See\n[`Array.unshift`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift)\non MDN.\n\n## Examples\n\n```rescript\nlet arr = [\"b\", \"c\", \"d\"]\nJs.Array2.unshift(arr, \"a\") == 4\narr == [\"a\", \"b\", \"c\", \"d\"]\n```\n"}, + "sortText": "unshift", + "insertText": "->Js.Array2.unshift", + "additionalTextEdits": [{ + "range": {"start": {"line": 75, "character": 7}, "end": {"line": 75, "character": 8}}, + "newText": "" + }] + }, { + "label": "->Js.Array2.unsafe_get", + "kind": 12, + "tags": [], + "detail": "(array<'a>, int) => 'a", + "documentation": {"kind": "markdown", "value": "\nReturns the value at the given position in the array if the position is in\nbounds; returns the JavaScript value `undefined` otherwise.\n\n## Examples\n\n```rescript\nlet arr = [100, 101, 102, 103]\nJs.Array2.unsafe_get(arr, 3) == 103\nJs.Array2.unsafe_get(arr, 4) // returns undefined\n```\n"}, + "sortText": "unsafe_get", + "insertText": "->Js.Array2.unsafe_get", + "additionalTextEdits": [{ + "range": {"start": {"line": 75, "character": 7}, "end": {"line": 75, "character": 8}}, + "newText": "" + }] + }, { + "label": "->Js.Array2.unsafe_set", + "kind": 12, + "tags": [], + "detail": "(array<'a>, int, 'a) => unit", + "documentation": {"kind": "markdown", "value": "\nSets the value at the given position in the array if the position is in bounds.\nIf the index is out of bounds, well, “here there be dragons.“\n\n*This function modifies the original array.*\n\n## Examples\n\n```rescript\nlet arr = [100, 101, 102, 103]\nJs.Array2.unsafe_set(arr, 3, 99)\n// result is [100, 101, 102, 99];\n\nJs.Array2.unsafe_set(arr, 4, 88)\n// result is [100, 101, 102, 99, 88]\n\nJs.Array2.unsafe_set(arr, 6, 77)\n// result is [100, 101, 102, 99, 88, <1 empty item>, 77]\n\nJs.Array2.unsafe_set(arr, -1, 66)\n// you don't want to know.\n```\n"}, + "sortText": "unsafe_set", + "insertText": "->Js.Array2.unsafe_set", + "additionalTextEdits": [{ + "range": {"start": {"line": 75, "character": 7}, "end": {"line": 75, "character": 8}}, + "newText": "" + }] + }] + +Complete src/DotPipeCompletionSpec.res 80:7 +posCursor:[80:7] posNoWhite:[80:6] Found expr:[80:3->80:7] +Pexp_field [80:3->80:6] _:[84:0->80:7] +Completable: Cpath Value[nnn]."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[nnn]."" +ContextPath Value[nnn] +Path nnn +ContextPath Value[nnn]-> +ContextPath Value[nnn] +Path nnn +CPPipe pathFromEnv: found:true +Path DotPipeCompletionSpec. +Path DotPipeCompletionSpec.SomeOtherModule. +[{ + "label": "nname", + "kind": 5, + "tags": [], + "detail": "string", + "documentation": {"kind": "markdown", "value": "```rescript\nnname: string\n```\n\n```rescript\ntype typeOutsideModule = {nname: string}\n```"} + }, { + "label": "->doWithTypeOutsideModule", + "kind": 12, + "tags": [], + "detail": "typeOutsideModule => string", + "documentation": null, + "sortText": "doWithTypeOutsideModule", + "insertText": "->doWithTypeOutsideModule", + "additionalTextEdits": [{ + "range": {"start": {"line": 80, "character": 6}, "end": {"line": 80, "character": 7}}, + "newText": "" + }] + }, { + "label": "->SomeOtherModule.getNName", + "kind": 12, + "tags": [], + "detail": "t => string", + "documentation": null, + "sortText": "getNName", + "insertText": "->SomeOtherModule.getNName", + "additionalTextEdits": [{ + "range": {"start": {"line": 80, "character": 6}, "end": {"line": 80, "character": 7}}, + "newText": "" + }] + }, { + "label": "->SomeOtherModule.getNName2", + "kind": 12, + "tags": [], + "detail": "typeOutsideModule => string", + "documentation": null, + "sortText": "getNName2", + "insertText": "->SomeOtherModule.getNName2", + "additionalTextEdits": [{ + "range": {"start": {"line": 80, "character": 6}, "end": {"line": 80, "character": 7}}, + "newText": "" + }] + }] + +Complete src/DotPipeCompletionSpec.res 86:43 +posCursor:[86:43] posNoWhite:[86:42] Found expr:[86:3->86:43] +posCursor:[86:43] posNoWhite:[86:42] Found expr:[86:9->86:43] +Pexp_field [86:9->86:38] filt:[86:39->86:43] +Completable: Cpath Value[Js, Array2, filter](Nolabel).filt +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[Js, Array2, filter](Nolabel).filt +ContextPath Value[Js, Array2, filter](Nolabel) +ContextPath Value[Js, Array2, filter] +Path Js.Array2.filter +ContextPath Value[Js, Array2, filter](Nolabel, Nolabel)->filt +ContextPath Value[Js, Array2, filter](Nolabel, Nolabel) +ContextPath Value[Js, Array2, filter] +Path Js.Array2.filter +Path Js.Array2.filt +[{ + "label": "->Js.Array2.filter", + "kind": 12, + "tags": [], + "detail": "(t<'a>, 'a => bool) => t<'a>", + "documentation": {"kind": "markdown", "value": "\nApplies the given predicate function (the second argument) to each element in\nthe array; the result is an array of those elements for which the predicate\nfunction returned `true`. See\n[`Array.filter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)\non MDN.\n\n## Examples\n\n```rescript\nlet nonEmpty = s => s != \"\"\nJs.Array2.filter([\"abc\", \"\", \"\", \"def\", \"ghi\"], nonEmpty) == [\"abc\", \"def\", \"ghi\"]\n```\n"}, + "sortText": "filter", + "insertText": "->Js.Array2.filter", + "additionalTextEdits": [{ + "range": {"start": {"line": 86, "character": 38}, "end": {"line": 86, "character": 39}}, + "newText": "" + }] + }, { + "label": "->Js.Array2.filteri", + "kind": 12, + "tags": [], + "detail": "(t<'a>, ('a, int) => bool) => t<'a>", + "documentation": {"kind": "markdown", "value": "\nEach element of the given array are passed to the predicate function. The\nreturn value is an array of all those elements for which the predicate function\nreturned `true`.\n\nSee\n[`Array.filter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)\non MDN.\n\n## Examples\n\n```rescript\n// keep only positive elements at odd indices\nlet positiveOddElement = (item, index) => mod(index, 2) == 1 && item > 0\n\nJs.Array2.filteri([6, 3, 5, 8, 7, -4, 1], positiveOddElement) == [3, 8]\n```\n"}, + "sortText": "filteri", + "insertText": "->Js.Array2.filteri", + "additionalTextEdits": [{ + "range": {"start": {"line": 86, "character": 38}, "end": {"line": 86, "character": 39}}, + "newText": "" + }] + }] + +Complete src/DotPipeCompletionSpec.res 89:70 +posCursor:[89:70] posNoWhite:[89:69] Found expr:[89:3->89:70] +posCursor:[89:70] posNoWhite:[89:69] Found expr:[89:40->89:70] +Pexp_field [89:40->89:63] includ:[89:64->89:70] +Completable: Cpath Value[Js, Array2, joinWith](Nolabel).includ +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[Js, Array2, joinWith](Nolabel).includ +ContextPath Value[Js, Array2, joinWith](Nolabel) +ContextPath Value[Js, Array2, joinWith] +Path Js.Array2.joinWith +ContextPath Value[Js, Array2, joinWith](Nolabel, Nolabel)->includ +ContextPath Value[Js, Array2, joinWith](Nolabel, Nolabel) +ContextPath Value[Js, Array2, joinWith] +Path Js.Array2.joinWith +Path Js.String2.includ +[{ + "label": "->Js.String2.includesFrom", + "kind": 12, + "tags": [], + "detail": "(t, t, int) => bool", + "documentation": {"kind": "markdown", "value": "\nES2015: `includes(str, searchValue start)` returns `true` if `searchValue` is\nfound anywhere within `str` starting at character number `start` (where 0 is\nthe first character), `false` otherwise.\n\nSee [`String.includes`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes)\non MDN.\n\n## Examples\n\n```rescript\nJs.String2.includesFrom(\"programmer\", \"gram\", 1) == true\nJs.String2.includesFrom(\"programmer\", \"gram\", 4) == false\nJs.String2.includesFrom(`대한민국`, `한`, 1) == true\n```\n"}, + "sortText": "includesFrom", + "insertText": "->Js.String2.includesFrom", + "additionalTextEdits": [{ + "range": {"start": {"line": 89, "character": 63}, "end": {"line": 89, "character": 64}}, + "newText": "" + }] + }, { + "label": "->Js.String2.includes", + "kind": 12, + "tags": [], + "detail": "(t, t) => bool", + "documentation": {"kind": "markdown", "value": "\nES2015: `includes(str, searchValue)` returns `true` if `searchValue` is found\nanywhere within `str`, false otherwise.\n\nSee [`String.includes`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes)\non MDN.\n\n## Examples\n\n```rescript\nJs.String2.includes(\"programmer\", \"gram\") == true\nJs.String2.includes(\"programmer\", \"er\") == true\nJs.String2.includes(\"programmer\", \"pro\") == true\nJs.String2.includes(\"programmer.dat\", \"xyz\") == false\n```\n"}, + "sortText": "includes", + "insertText": "->Js.String2.includes", + "additionalTextEdits": [{ + "range": {"start": {"line": 89, "character": 63}, "end": {"line": 89, "character": 64}}, + "newText": "" + }] + }] + +Complete src/DotPipeCompletionSpec.res 94:40 +posCursor:[94:40] posNoWhite:[94:39] Found expr:[94:3->94:40] +posCursor:[94:40] posNoWhite:[94:39] Found expr:[94:8->94:40] +Pexp_field [94:8->94:30] toUpperCa:[94:31->94:40] +Completable: Cpath Value[Js, String2, toLowerCase].toUpperCa +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[Js, String2, toLowerCase].toUpperCa +ContextPath Value[Js, String2, toLowerCase] +Path Js.String2.toLowerCase +ContextPath Value[Js, String2, toLowerCase](Nolabel)->toUpperCa +ContextPath Value[Js, String2, toLowerCase](Nolabel) +ContextPath Value[Js, String2, toLowerCase] +Path Js.String2.toLowerCase +Path Js.String2.toUpperCa +[{ + "label": "->Js.String2.toUpperCase", + "kind": 12, + "tags": [], + "detail": "t => t", + "documentation": {"kind": "markdown", "value": "\n`toUpperCase(str)` converts `str` to upper case using the locale-insensitive\ncase mappings in the Unicode Character Database. Notice that the conversion can\nexpand the number of letters in the result; for example the German ß\ncapitalizes to two Ses in a row.\n\nSee [`String.toUpperCase`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase)\non MDN.\n\n## Examples\n\n```rescript\nJs.String2.toUpperCase(\"abc\") == \"ABC\"\nJs.String2.toUpperCase(`Straße`) == `STRASSE`\nJs.String2.toUpperCase(`πς`) == `ΠΣ`\n```\n"}, + "sortText": "toUpperCase", + "insertText": "->Js.String2.toUpperCase", + "additionalTextEdits": [{ + "range": {"start": {"line": 94, "character": 30}, "end": {"line": 94, "character": 31}}, + "newText": "" + }] + }] + +Complete src/DotPipeCompletionSpec.res 97:63 +posCursor:[97:63] posNoWhite:[97:62] Found expr:[97:3->97:63] +posCursor:[97:63] posNoWhite:[97:62] Found expr:[97:32->97:63] +Pexp_field [97:32->97:54] toLowerC:[97:55->97:63] +Completable: Cpath Value[Js, String2, toUpperCase].toLowerC +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[Js, String2, toUpperCase].toLowerC +ContextPath Value[Js, String2, toUpperCase] +Path Js.String2.toUpperCase +ContextPath Value[Js, String2, toUpperCase](Nolabel)->toLowerC +ContextPath Value[Js, String2, toUpperCase](Nolabel) +ContextPath Value[Js, String2, toUpperCase] +Path Js.String2.toUpperCase +Path Js.String2.toLowerC +[{ + "label": "->Js.String2.toLowerCase", + "kind": 12, + "tags": [], + "detail": "t => t", + "documentation": {"kind": "markdown", "value": "\n`toLowerCase(str)` converts `str` to lower case using the locale-insensitive\ncase mappings in the Unicode Character Database. Notice that the conversion can\ngive different results depending upon context, for example with the Greek\nletter sigma, which has two different lower case forms; one when it is the last\ncharacter in a string and another when it is not.\n\nSee [`String.toLowerCase`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase)\non MDN.\n\n## Examples\n\n```rescript\nJs.String2.toLowerCase(\"ABC\") == \"abc\"\nJs.String2.toLowerCase(`ΣΠ`) == `σπ`\nJs.String2.toLowerCase(`ΠΣ`) == `πς`\n```\n"}, + "sortText": "toLowerCase", + "insertText": "->Js.String2.toLowerCase", + "additionalTextEdits": [{ + "range": {"start": {"line": 97, "character": 54}, "end": {"line": 97, "character": 55}}, + "newText": "" + }] + }] + +Complete src/DotPipeCompletionSpec.res 101:7 +posCursor:[101:7] posNoWhite:[101:6] Found expr:[100:9->104:1] +posCursor:[101:7] posNoWhite:[101:6] Found expr:[100:10->104:1] +posCursor:[101:7] posNoWhite:[101:6] Found expr:[101:5->103:3] +Pexp_field [101:5->101:6] t:[103:2->103:3] +Completable: Cpath Value[t]."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[t]."" +ContextPath Value[t] +Path t +ContextPath Value[t]-> +ContextPath Value[t] +Path t +CPPipe pathFromEnv: found:true +Path DotPipeCompletionSpec. +Path DotPipeCompletionSpec.SomeOtherModule. +[{ + "label": "nname", + "kind": 5, + "tags": [], + "detail": "string", + "documentation": {"kind": "markdown", "value": "```rescript\nnname: string\n```\n\n```rescript\ntype typeOutsideModule = {nname: string}\n```"} + }, { + "label": "->doWithTypeOutsideModule", + "kind": 12, + "tags": [], + "detail": "typeOutsideModule => string", + "documentation": null, + "sortText": "doWithTypeOutsideModule", + "insertText": "->doWithTypeOutsideModule", + "additionalTextEdits": [{ + "range": {"start": {"line": 101, "character": 6}, "end": {"line": 101, "character": 7}}, + "newText": "" + }] + }, { + "label": "->SomeOtherModule.getNName", + "kind": 12, + "tags": [], + "detail": "t => string", + "documentation": null, + "sortText": "getNName", + "insertText": "->SomeOtherModule.getNName", + "additionalTextEdits": [{ + "range": {"start": {"line": 101, "character": 6}, "end": {"line": 101, "character": 7}}, + "newText": "" + }] + }, { + "label": "->SomeOtherModule.getNName2", + "kind": 12, + "tags": [], + "detail": "typeOutsideModule => string", + "documentation": null, + "sortText": "getNName2", + "insertText": "->SomeOtherModule.getNName2", + "additionalTextEdits": [{ + "range": {"start": {"line": 101, "character": 6}, "end": {"line": 101, "character": 7}}, + "newText": "" + }] + }] + +Complete src/DotPipeCompletionSpec.res 108:27 +XXX Not found! +Completable: Cpath Module[Dot] +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Module[Dot] +Path Dot +[{ + "label": "DotPipeCompletionSpec", + "kind": 9, + "tags": [], + "detail": "module DotPipeCompletionSpec", + "documentation": null, + "data": { + "modulePath": "DotPipeCompletionSpec", + "filePath": "src/DotPipeCompletionSpec.res" + } + }] + +Complete src/DotPipeCompletionSpec.res 111:39 +posCursor:[111:39] posNoWhite:[111:38] Found expr:[111:24->111:40] +posCursor:[111:39] posNoWhite:[111:38] Found expr:[111:25->111:39] +Pexp_construct CompletionPipe:[111:25->111:39] None +Completable: Cpath Value[CompletionPipe] +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[CompletionPipe] +Path CompletionPipe +[{ + "label": "CompletionPipeChain", + "kind": 9, + "tags": [], + "detail": "module CompletionPipeChain", + "documentation": null, + "data": { + "modulePath": "CompletionPipeChain", + "filePath": "src/DotPipeCompletionSpec.res" + } + }, { + "label": "CompletionPipeProperty", + "kind": 9, + "tags": [], + "detail": "module CompletionPipeProperty", + "documentation": null, + "data": { + "modulePath": "CompletionPipeProperty", + "filePath": "src/DotPipeCompletionSpec.res" + } + }, { + "label": "CompletionPipeSubmodules", + "kind": 9, + "tags": [], + "detail": "module CompletionPipeSubmodules", + "documentation": null, + "data": { + "modulePath": "CompletionPipeSubmodules", + "filePath": "src/DotPipeCompletionSpec.res" + } + }] + +Complete src/DotPipeCompletionSpec.res 114:44 +posCursor:[114:44] posNoWhite:[114:43] Found expr:[114:24->114:45] +posCursor:[114:44] posNoWhite:[114:43] Found expr:[114:41->114:44] +Pexp_construct Dot:[114:41->114:44] None +Completable: Cpath Value[Dot] +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[Dot] +Path Dot +[{ + "label": "DotPipeCompletionSpec", + "kind": 9, + "tags": [], + "detail": "module DotPipeCompletionSpec", + "documentation": null, + "data": { + "modulePath": "DotPipeCompletionSpec", + "filePath": "src/DotPipeCompletionSpec.res" + } + }] + +Complete src/DotPipeCompletionSpec.res 122:11 +posCursor:[122:11] posNoWhite:[122:10] Found expr:[122:3->122:11] +Pexp_field [122:3->122:10] _:[128:0->122:11] +Completable: Cpath Value[someObj]."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[someObj]."" +ContextPath Value[someObj] +Path someObj +ContextPath Value[someObj]-> +ContextPath Value[someObj] +Path someObj +[{ + "label": "[\"age\"]", + "kind": 4, + "tags": [], + "detail": "{\"age\": int, \"name\": string}", + "documentation": null, + "insertText": "[\"age\"]", + "additionalTextEdits": [{ + "range": {"start": {"line": 122, "character": 10}, "end": {"line": 122, "character": 11}}, + "newText": "" + }] + }, { + "label": "[\"name\"]", + "kind": 4, + "tags": [], + "detail": "{\"age\": int, \"name\": string}", + "documentation": null, + "insertText": "[\"name\"]", + "additionalTextEdits": [{ + "range": {"start": {"line": 122, "character": 10}, "end": {"line": 122, "character": 11}}, + "newText": "" + }] + }] + +Complete src/DotPipeCompletionSpec.res 125:13 +posCursor:[125:13] posNoWhite:[125:12] Found expr:[125:3->125:13] +Pexp_field [125:3->125:10] na:[125:11->125:13] +Completable: Cpath Value[someObj].na +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[someObj].na +ContextPath Value[someObj] +Path someObj +ContextPath Value[someObj]->na +ContextPath Value[someObj] +Path someObj +[{ + "label": "[\"name\"]", + "kind": 4, + "tags": [], + "detail": "{\"age\": int, \"name\": string}", + "documentation": null, + "insertText": "[\"name\"]", + "additionalTextEdits": [{ + "range": {"start": {"line": 125, "character": 10}, "end": {"line": 125, "character": 11}}, + "newText": "" + }] + }] + +Complete src/DotPipeCompletionSpec.res 144:10 +posCursor:[144:10] posNoWhite:[144:9] Found expr:[144:3->144:10] +Pexp_field [144:3->144:9] _:[147:0->144:10] +Completable: Cpath Value[button]."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[button]."" +ContextPath Value[button] +Path button +ContextPath Value[button]-> +ContextPath Value[button] +Path button +CPPipe pathFromEnv:DOMAPI found:true +Path DOMAPI. +Path DotPipeCompletionSpec.HTMLButtonElement. +[{ + "label": "disabled", + "kind": 5, + "tags": [], + "detail": "bool", + "documentation": {"kind": "markdown", "value": "```rescript\ndisabled: bool\n```\n\n```rescript\ntype htmlButtonElement = {mutable disabled: bool}\n```"} + }, { + "label": "->HTMLButtonElement.checkValidity", + "kind": 12, + "tags": [], + "detail": "DOMAPI.htmlButtonElement => bool", + "documentation": null, + "sortText": "checkValidity", + "insertText": "->HTMLButtonElement.checkValidity", + "additionalTextEdits": [{ + "range": {"start": {"line": 144, "character": 9}, "end": {"line": 144, "character": 10}}, + "newText": "" + }] + }] + diff --git a/analysis/tests/src/expected/ExhaustiveSwitch.res.txt b/analysis/tests/src/expected/ExhaustiveSwitch.res.txt index bf1cc8447..b89a5ce19 100644 --- a/analysis/tests/src/expected/ExhaustiveSwitch.res.txt +++ b/analysis/tests/src/expected/ExhaustiveSwitch.res.txt @@ -103,9 +103,10 @@ Resolved opens 1 pervasives ContextPath Value[x]-> ContextPath Value[x] Path x -CPPipe env:ExhaustiveSwitch -CPPipe type path:rcrd CPPipe pathFromEnv: found:true +Path ExhaustiveSwitch. +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives Xform src/ExhaustiveSwitch.res start: 33:3, end: 33:10 found selection: [33:3->33:10] -> [33:6->33:10] diff --git a/analysis/tests/src/expected/Hover.res.txt b/analysis/tests/src/expected/Hover.res.txt index 725c5a93a..07aa4ca22 100644 --- a/analysis/tests/src/expected/Hover.res.txt +++ b/analysis/tests/src/expected/Hover.res.txt @@ -124,6 +124,22 @@ ContextPath Value[x1].content."" ContextPath Value[x1].content ContextPath Value[x1] Path x1 +ContextPath Value[x1]->content +ContextPath Value[x1] +Path x1 +CPPipe pathFromEnv: found:true +Path Hover.content +ContextPath Value[x1].content-> +ContextPath Value[x1].content +ContextPath Value[x1] +Path x1 +ContextPath Value[x1]->content +ContextPath Value[x1] +Path x1 +CPPipe pathFromEnv: found:true +Path Hover.content +CPPipe pathFromEnv: found:true +Path Hover. [{ "label": "age", "kind": 5, @@ -142,6 +158,22 @@ ContextPath Value[x2].content."" ContextPath Value[x2].content ContextPath Value[x2] Path x2 +ContextPath Value[x2]->content +ContextPath Value[x2] +Path x2 +CPPipe pathFromEnv: found:true +Path Hover.content +ContextPath Value[x2].content-> +ContextPath Value[x2].content +ContextPath Value[x2] +Path x2 +ContextPath Value[x2]->content +ContextPath Value[x2] +Path x2 +CPPipe pathFromEnv: found:true +Path Hover.content +CPPipe pathFromEnv: found:true +Path Hover. [{ "label": "age", "kind": 5, @@ -160,6 +192,22 @@ ContextPath Value[y1].content."" ContextPath Value[y1].content ContextPath Value[y1] Path y1 +ContextPath Value[y1]->content +ContextPath Value[y1] +Path y1 +CPPipe pathFromEnv: found:true +Path Hover.content +ContextPath Value[y1].content-> +ContextPath Value[y1].content +ContextPath Value[y1] +Path y1 +ContextPath Value[y1]->content +ContextPath Value[y1] +Path y1 +CPPipe pathFromEnv: found:true +Path Hover.content +CPPipe pathFromEnv: found:true +Path Hover. [{ "label": "age", "kind": 5, @@ -178,6 +226,22 @@ ContextPath Value[y2].content."" ContextPath Value[y2].content ContextPath Value[y2] Path y2 +ContextPath Value[y2]->content +ContextPath Value[y2] +Path y2 +CPPipe pathFromEnv: found:true +Path Hover.content +ContextPath Value[y2].content-> +ContextPath Value[y2].content +ContextPath Value[y2] +Path y2 +ContextPath Value[y2]->content +ContextPath Value[y2] +Path y2 +CPPipe pathFromEnv: found:true +Path Hover.content +CPPipe pathFromEnv: found:true +Path Hover. [{ "label": "age", "kind": 5, @@ -221,6 +285,11 @@ Resolved opens 1 pervasives ContextPath Value[x].someField ContextPath Value[x] Path x +ContextPath Value[x]->someField +ContextPath Value[x] +Path x +CPPipe pathFromEnv: found:true +Path Hover.someField Package opens Pervasives.JsxModules.place holder Resolved opens 1 pervasives {"contents": {"kind": "markdown", "value": " Mighty fine field here. \n\n```rescript\nbool\n```"}} diff --git a/analysis/tests/src/expected/RecordCompletion.res.txt b/analysis/tests/src/expected/RecordCompletion.res.txt index 90787363b..d0cefde7e 100644 --- a/analysis/tests/src/expected/RecordCompletion.res.txt +++ b/analysis/tests/src/expected/RecordCompletion.res.txt @@ -7,7 +7,11 @@ ContextPath Value[t].n->m ContextPath Value[t].n ContextPath Value[t] Path t -CPPipe env:RecordCompletion +ContextPath Value[t]->n +ContextPath Value[t] +Path t +CPPipe pathFromEnv: found:true +Path RecordCompletion.n Path Js.Array2.m [{ "label": "Js.Array2.mapi", @@ -33,7 +37,22 @@ ContextPath Value[t2].n2.n ContextPath Value[t2].n2 ContextPath Value[t2] Path t2 -CPPipe env:RecordCompletion +ContextPath Value[t2]->n2 +ContextPath Value[t2] +Path t2 +CPPipe pathFromEnv: found:true +Path RecordCompletion.n2 +ContextPath Value[t2].n2->n +ContextPath Value[t2].n2 +ContextPath Value[t2] +Path t2 +ContextPath Value[t2]->n2 +ContextPath Value[t2] +Path t2 +CPPipe pathFromEnv: found:true +Path RecordCompletion.n2 +CPPipe pathFromEnv: found:true +Path RecordCompletion.n Path Js.Array2.m [{ "label": "Js.Array2.mapi", diff --git a/analysis/tests/src/expected/Rename.res.txt b/analysis/tests/src/expected/Rename.res.txt index 5cd2adfee..92c381452 100644 --- a/analysis/tests/src/expected/Rename.res.txt +++ b/analysis/tests/src/expected/Rename.res.txt @@ -6,15 +6,15 @@ Rename src/Rename.res 0:4 y "uri": "Rename.res" }, "edits": [{ - "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, - "newText": "y" - }, { - "range": {"start": {"line": 3, "character": 8}, "end": {"line": 3, "character": 9}}, - "newText": "y" - }, { - "range": {"start": {"line": 7, "character": 8}, "end": {"line": 7, "character": 9}}, - "newText": "y" - }] + "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, + "newText": "y" + }, { + "range": {"start": {"line": 3, "character": 8}, "end": {"line": 3, "character": 9}}, + "newText": "y" + }, { + "range": {"start": {"line": 7, "character": 8}, "end": {"line": 7, "character": 9}}, + "newText": "y" + }] } ] @@ -26,12 +26,12 @@ Rename src/Rename.res 9:19 yy "uri": "Rename.res" }, "edits": [{ - "range": {"start": {"line": 9, "character": 11}, "end": {"line": 9, "character": 14}}, - "newText": "yy" - }, { - "range": {"start": {"line": 9, "character": 19}, "end": {"line": 9, "character": 21}}, - "newText": "yy" - }] + "range": {"start": {"line": 9, "character": 11}, "end": {"line": 9, "character": 14}}, + "newText": "yy" + }, { + "range": {"start": {"line": 9, "character": 19}, "end": {"line": 9, "character": 21}}, + "newText": "yy" + }] } ] diff --git a/analysis/tests/src/expected/RenameWithInterface.res.txt b/analysis/tests/src/expected/RenameWithInterface.res.txt index a13988fa9..48ecdabc5 100644 --- a/analysis/tests/src/expected/RenameWithInterface.res.txt +++ b/analysis/tests/src/expected/RenameWithInterface.res.txt @@ -6,9 +6,9 @@ Rename src/RenameWithInterface.res 0:4 y "uri": "RenameWithInterface.resi" }, "edits": [{ - "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, - "newText": "y" - }] + "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, + "newText": "y" + }] }, { "textDocument": { @@ -16,9 +16,9 @@ Rename src/RenameWithInterface.res 0:4 y "uri": "RenameWithInterface.res" }, "edits": [{ - "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, - "newText": "y" - }] + "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, + "newText": "y" + }] }, { "textDocument": { @@ -26,12 +26,12 @@ Rename src/RenameWithInterface.res 0:4 y "uri": "Cross.res" }, "edits": [{ - "range": {"start": {"line": 18, "character": 28}, "end": {"line": 18, "character": 29}}, - "newText": "y" - }, { - "range": {"start": {"line": 21, "character": 28}, "end": {"line": 21, "character": 29}}, - "newText": "y" - }] + "range": {"start": {"line": 18, "character": 28}, "end": {"line": 18, "character": 29}}, + "newText": "y" + }, { + "range": {"start": {"line": 21, "character": 28}, "end": {"line": 21, "character": 29}}, + "newText": "y" + }] } ] diff --git a/analysis/tests/src/expected/RenameWithInterface.resi.txt b/analysis/tests/src/expected/RenameWithInterface.resi.txt index 2a1dabb44..3c5d52909 100644 --- a/analysis/tests/src/expected/RenameWithInterface.resi.txt +++ b/analysis/tests/src/expected/RenameWithInterface.resi.txt @@ -6,9 +6,9 @@ Rename src/RenameWithInterface.resi 0:4 y "uri": "RenameWithInterface.resi" }, "edits": [{ - "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, - "newText": "y" - }] + "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, + "newText": "y" + }] }, { "textDocument": { @@ -16,9 +16,9 @@ Rename src/RenameWithInterface.resi 0:4 y "uri": "RenameWithInterface.res" }, "edits": [{ - "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, - "newText": "y" - }] + "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 5}}, + "newText": "y" + }] }, { "textDocument": { @@ -26,12 +26,12 @@ Rename src/RenameWithInterface.resi 0:4 y "uri": "Cross.res" }, "edits": [{ - "range": {"start": {"line": 18, "character": 28}, "end": {"line": 18, "character": 29}}, - "newText": "y" - }, { - "range": {"start": {"line": 21, "character": 28}, "end": {"line": 21, "character": 29}}, - "newText": "y" - }] + "range": {"start": {"line": 18, "character": 28}, "end": {"line": 18, "character": 29}}, + "newText": "y" + }, { + "range": {"start": {"line": 21, "character": 28}, "end": {"line": 21, "character": 29}}, + "newText": "y" + }] } ] diff --git a/analysis/tests/src/expected/Rxjs.res.txt b/analysis/tests/src/expected/Rxjs.res.txt new file mode 100644 index 000000000..e69de29bb diff --git a/analysis/tests/src/expected/RxjsCompletion.res.txt b/analysis/tests/src/expected/RxjsCompletion.res.txt new file mode 100644 index 000000000..f8a17be58 --- /dev/null +++ b/analysis/tests/src/expected/RxjsCompletion.res.txt @@ -0,0 +1,168 @@ +Complete src/RxjsCompletion.res 26:29 +posCursor:[26:29] posNoWhite:[26:28] Found expr:[10:17->38:1] +posCursor:[26:29] posNoWhite:[26:28] Found expr:[11:2->32:78] +posCursor:[26:29] posNoWhite:[26:28] Found expr:[12:4->26:29] +posCursor:[26:29] posNoWhite:[26:28] Found expr:[14:4->26:29] +posCursor:[26:29] posNoWhite:[26:28] Found expr:[20:4->26:29] +posCursor:[26:29] posNoWhite:[26:28] Found expr:[26:7->26:29] +Pexp_field [26:7->26:28] _:[30:2->26:29] +Completable: Cpath Value[merge](Nolabel, Nolabel)."" +Raw opens: 1 Rxjs.place holder +Package opens Pervasives.JsxModules.place holder +Resolved opens 2 pervasives Rxjs.res +ContextPath Value[merge](Nolabel, Nolabel)."" +ContextPath Value[merge](Nolabel, Nolabel) +ContextPath Value[merge] +Path merge +ContextPath Value[merge](Nolabel, Nolabel, Nolabel)-> +ContextPath Value[merge](Nolabel, Nolabel, Nolabel) +ContextPath Value[merge] +Path merge +CPPipe pathFromEnv:Observable found:true +Path Rxjs.Observable. +Path Rxjs. +[{ + "label": "->Observable.subscribe", + "kind": 12, + "tags": [], + "detail": "(t<'t>, 't => unit) => subscription", + "documentation": null, + "sortText": "subscribe", + "insertText": "->Observable.subscribe", + "additionalTextEdits": [{ + "range": {"start": {"line": 26, "character": 28}, "end": {"line": 26, "character": 29}}, + "newText": "" + }] + }, { + "label": "->pipe", + "kind": 12, + "tags": [], + "detail": "(Observable.t<'t>, operation<'t, 'u>) => Observable.t<'u>", + "documentation": null, + "sortText": "pipe", + "insertText": "->pipe", + "additionalTextEdits": [{ + "range": {"start": {"line": 26, "character": 28}, "end": {"line": 26, "character": 29}}, + "newText": "" + }] + }, { + "label": "->combineLatest", + "kind": 12, + "tags": [], + "detail": "(\n Observable.t<'a>,\n Observable.t<'b>,\n) => Observable.t<('a, 'b)>", + "documentation": null, + "sortText": "combineLatest", + "insertText": "->combineLatest", + "additionalTextEdits": [{ + "range": {"start": {"line": 26, "character": 28}, "end": {"line": 26, "character": 29}}, + "newText": "" + }] + }, { + "label": "->merge", + "kind": 12, + "tags": [], + "detail": "(Observable.t<'t>, Observable.t<'t>) => Observable.t<'t>", + "documentation": null, + "sortText": "merge", + "insertText": "->merge", + "additionalTextEdits": [{ + "range": {"start": {"line": 26, "character": 28}, "end": {"line": 26, "character": 29}}, + "newText": "" + }] + }, { + "label": "->pipe2", + "kind": 12, + "tags": [], + "detail": "(\n Observable.t<'t>,\n operation<'t, 'u>,\n operation<'u, 'i>,\n) => Observable.t<'i>", + "documentation": null, + "sortText": "pipe2", + "insertText": "->pipe2", + "additionalTextEdits": [{ + "range": {"start": {"line": 26, "character": 28}, "end": {"line": 26, "character": 29}}, + "newText": "" + }] + }] + +Complete src/RxjsCompletion.res 34:30 +posCursor:[34:30] posNoWhite:[34:29] Found expr:[10:17->38:1] +posCursor:[34:30] posNoWhite:[34:29] Found expr:[10:11->38:1] +posCursor:[34:30] posNoWhite:[34:29] Found expr:[11:2->34:30] +posCursor:[34:30] posNoWhite:[34:29] Found expr:[32:2->34:30] +posCursor:[34:30] posNoWhite:[34:29] Found expr:[34:5->34:30] +Pexp_field [34:5->34:29] _:[38:0->34:30] +Completable: Cpath Value[Rxjs, combineLatest](Nolabel, Nolabel)."" +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath Value[Rxjs, combineLatest](Nolabel, Nolabel)."" +ContextPath Value[Rxjs, combineLatest](Nolabel, Nolabel) +ContextPath Value[Rxjs, combineLatest] +Path Rxjs.combineLatest +ContextPath Value[Rxjs, combineLatest](Nolabel, Nolabel, Nolabel)-> +ContextPath Value[Rxjs, combineLatest](Nolabel, Nolabel, Nolabel) +ContextPath Value[Rxjs, combineLatest] +Path Rxjs.combineLatest +CPPipe pathFromEnv:Observable found:true +Path Rxjs.Observable. +Path Rxjs. +[{ + "label": "->Rxjs.Observable.subscribe", + "kind": 12, + "tags": [], + "detail": "(t<'t>, 't => unit) => subscription", + "documentation": null, + "sortText": "subscribe", + "insertText": "->Rxjs.Observable.subscribe", + "additionalTextEdits": [{ + "range": {"start": {"line": 34, "character": 29}, "end": {"line": 34, "character": 30}}, + "newText": "" + }] + }, { + "label": "->Rxjs.pipe", + "kind": 12, + "tags": [], + "detail": "(Observable.t<'t>, operation<'t, 'u>) => Observable.t<'u>", + "documentation": null, + "sortText": "pipe", + "insertText": "->Rxjs.pipe", + "additionalTextEdits": [{ + "range": {"start": {"line": 34, "character": 29}, "end": {"line": 34, "character": 30}}, + "newText": "" + }] + }, { + "label": "->Rxjs.combineLatest", + "kind": 12, + "tags": [], + "detail": "(\n Observable.t<'a>,\n Observable.t<'b>,\n) => Observable.t<('a, 'b)>", + "documentation": null, + "sortText": "combineLatest", + "insertText": "->Rxjs.combineLatest", + "additionalTextEdits": [{ + "range": {"start": {"line": 34, "character": 29}, "end": {"line": 34, "character": 30}}, + "newText": "" + }] + }, { + "label": "->Rxjs.merge", + "kind": 12, + "tags": [], + "detail": "(Observable.t<'t>, Observable.t<'t>) => Observable.t<'t>", + "documentation": null, + "sortText": "merge", + "insertText": "->Rxjs.merge", + "additionalTextEdits": [{ + "range": {"start": {"line": 34, "character": 29}, "end": {"line": 34, "character": 30}}, + "newText": "" + }] + }, { + "label": "->Rxjs.pipe2", + "kind": 12, + "tags": [], + "detail": "(\n Observable.t<'t>,\n operation<'t, 'u>,\n operation<'u, 'i>,\n) => Observable.t<'i>", + "documentation": null, + "sortText": "pipe2", + "insertText": "->Rxjs.pipe2", + "additionalTextEdits": [{ + "range": {"start": {"line": 34, "character": 29}, "end": {"line": 34, "character": 30}}, + "newText": "" + }] + }] + diff --git a/client/src/commands/dump_debug.ts b/client/src/commands/dump_debug.ts index 168d87a22..9b41c4a9b 100644 --- a/client/src/commands/dump_debug.ts +++ b/client/src/commands/dump_debug.ts @@ -200,13 +200,7 @@ export const dumpDebug = async ( switch (callType.command) { case "completion": { - opts.push( - filePath, - line.toString(), - character.toString(), - currentFile, - "true" - ); + opts.push(filePath, line.toString(), character.toString(), currentFile); break; } case "definition": { @@ -222,13 +216,7 @@ export const dumpDebug = async ( break; } case "hover": { - opts.push( - filePath, - line.toString(), - character.toString(), - currentFile, - "true" - ); + opts.push(filePath, line.toString(), character.toString(), currentFile); break; } case "signatureHelp": {