Skip to content

Universal dot completion #1054

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 34 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
565edda
wip complete pipeable functions from dot completion on record when re…
zth Nov 5, 2024
4347fa3
correctly insert completion item text removing the dot when selecting…
zth Nov 6, 2024
eefe5f6
add experimental mainTypeForModule annotation
zth Nov 6, 2024
ca1c8d1
complete modules in payload of mainTypeForModule
zth Nov 7, 2024
7110db8
rename attribute
zth Nov 12, 2024
af54200
hover for new decorator
zth Nov 12, 2024
e3d1470
allow extra module completions also for pipe
zth Nov 13, 2024
72a522c
make sure completions work across files
zth Nov 14, 2024
ce80c6c
filter pipe completions to only applicable functions
zth Nov 14, 2024
5ad0319
pipe complete only for functions that take the expected type as the f…
zth Nov 16, 2024
943b01f
start refactoring dot completion everywhere
zth Nov 20, 2024
ebc5d9e
refactor dot completion
zth Nov 28, 2024
8e2395e
add a few more synthetic
zth Nov 28, 2024
8e166ac
disable verbose log
zth Nov 28, 2024
2b3190c
cleanup
zth Nov 28, 2024
58cf089
pipe dot completion for builtins
zth Nov 28, 2024
70b7db6
Add example case (#1058)
nojaf Nov 29, 2024
931fd28
Additional completion tests (#1062)
nojaf Dec 19, 2024
e347146
make dot completion everywhere actually work
zth Dec 25, 2024
415eea9
do not care about ExtractedType now that we have incremental type che…
zth Dec 25, 2024
c715071
refactor to share pipe completion code logic
zth Dec 25, 2024
dfc3eb0
cleanup
zth Dec 25, 2024
4e4d03c
cleanup
zth Dec 25, 2024
0fa56aa
fix debug command
zth Dec 28, 2024
b6f7ccc
up rescript in test project
zth Dec 28, 2024
eb4cea5
change strategy for removing dot on completion
zth Dec 29, 2024
b1c6850
contonous dot completion
zth Dec 31, 2024
9c29710
handle dot completions on piped idents
zth Dec 31, 2024
9ac0817
handle scope
zth Dec 31, 2024
3d0a1c8
inline pipe completion logic again
zth Jan 2, 2025
bf7eeba
refactor
zth Jan 2, 2025
380e8a9
more compl spec
zth Jan 2, 2025
603b8d9
refactor
zth Jan 2, 2025
b5053bc
changelog
zth Jan 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
cleanup
  • Loading branch information
zth committed Jan 2, 2025
commit dfc3eb00eabc3b5ebbecd6bf72e76082d7bb98bd
4 changes: 2 additions & 2 deletions analysis/src/CompletionBackEnd.ml
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@ let getPipeCompletions ~env ~full ~identifierLoc ~debug ~envCompletionIsMadeFrom
typ =
let env, typ =
typ
|> TypeUtils.resolveTypeForPipeCompletion2 ~env ~package:full.package ~full
|> TypeUtils.resolveTypeForPipeCompletion ~env ~package:full.package ~full
~lhsLoc:identifierLoc
in
let mainTypeId = TypeUtils.findRootTypeId ~full ~env typ in
Expand Down Expand Up @@ -730,7 +730,7 @@ let getPipeCompletions ~env ~full ~identifierLoc ~debug ~envCompletionIsMadeFrom
(* Extra completions can be drawn from the @editor.completeFrom attribute. Here we
find and add those completions as well. *)
let extraCompletions =
TypeUtils.getExtraModuleTosCompleteFromForType ~env ~full typ
TypeUtils.getExtraModulesToCompleteFromForType ~env ~full typ
|> List.map (fun completionPath ->
completionsForPipeFromCompletionPath ~envCompletionIsMadeFrom
~opens ~pos ~scope ~debug ~prefix ~env ~rawOpens ~full
Expand Down
136 changes: 2 additions & 134 deletions analysis/src/TypeUtils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,6 @@ open SharedTypes

let modulePathFromEnv env = env.QueryEnv.file.moduleName :: List.rev env.pathRev

let completionPathFromEnvAndPath env ~path =
modulePathFromEnv env @ List.rev (Utils.expandPath path)
|> List.rev |> List.tl |> List.rev

let getFullTypeId ~env (path : Path.t) =
modulePathFromEnv env @ List.rev (Utils.expandPath path) |> String.concat "."

let fullTypeIdFromDecl ~env ~name ~modulePath =
env.QueryEnv.file.moduleName :: ModulePath.toPath modulePath name
|> String.concat "."
Expand Down Expand Up @@ -506,45 +499,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
Expand All @@ -563,47 +517,6 @@ 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
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
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)

let rec resolveTypeForPipeCompletion2 ~env ~package ~lhsLoc ~full
(t : Types.type_expr) =
(* 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
Expand All @@ -616,7 +529,7 @@ let rec resolveTypeForPipeCompletion2 ~env ~package ~lhsLoc ~full
in
match typFromLoc with
| Some typFromLoc ->
typFromLoc |> resolveTypeForPipeCompletion2 ~lhsLoc ~env ~package ~full
typFromLoc |> resolveTypeForPipeCompletion ~lhsLoc ~env ~package ~full
| None ->
let rec digToRelevantType ~env ~package (t : Types.type_expr) =
match t.desc with
Expand Down Expand Up @@ -1190,21 +1103,9 @@ let pathToElementProps package =
| None -> ["ReactDOM"; "domProps"]
| Some g -> (g |> String.split_on_char '.') @ ["Elements"; "props"]

(** Extracts module to draw extra completions from for the type, if it has been annotated with @editor.completeFrom. *)
let rec getExtraModuleToCompleteFromForType ~env ~full (t : Types.type_expr) =
match t |> Shared.digConstructor with
| Some path -> (
match References.digConstructor ~env ~package:full.package path with
| None -> None
| Some (env, {item = {decl = {type_manifest = Some t}}}) ->
getExtraModuleToCompleteFromForType ~env ~full t
| Some (_, {item = {attributes}}) ->
ProcessAttributes.findEditorCompleteFromAttribute attributes)
| None -> None

module StringSet = Set.Make (String)

let rec getExtraModuleTosCompleteFromForType ~env ~full (t : Types.type_expr) =
let getExtraModulesToCompleteFromForType ~env ~full (t : Types.type_expr) =
let foundModulePaths = ref StringSet.empty in
let addToModulePaths attributes =
ProcessAttributes.findEditorCompleteFromAttribute2 attributes
Expand All @@ -1227,39 +1128,6 @@ let rec getExtraModuleTosCompleteFromForType ~env ~full (t : Types.type_expr) =
!foundModulePaths |> StringSet.elements
|> List.map (fun l -> String.split_on_char '.' l)

(** Checks whether the provided type represents a function that takes the provided path
as the first argument (meaning it's pipeable). *)
let rec fnTakesTypeAsFirstArg ~env ~full ~targetTypeId t =
(*if Debug.verbose () then
Printf.printf "[fnTakesTypeAsFirstArg] start env: %s\n"
env.QueryEnv.file.moduleName;*)
match t.Types.desc with
| Tlink t1
| Tsubst t1
| Tpoly (t1, [])
| Tconstr (Pident {name = "function$"}, [t1; _], _) ->
fnTakesTypeAsFirstArg ~env ~full ~targetTypeId t1
| Tarrow _ -> (
match extractFunctionTypeWithEnv ~env ~package:full.package t with
| (Nolabel, t) :: _, _, env -> (
(*if Debug.verbose () then
Printf.printf "[fnTakesTypeAsFirstArg] extracted env: %s\n"
env.QueryEnv.file.moduleName;*)
let mainTypeId =
match pathFromTypeExpr t with
| None -> None
| Some tPath -> Some (getFullTypeId ~env tPath)
in
(*if Debug.verbose () then
Printf.printf "[filterPipeableFunctions]--> targetTypeId:%s = %s\n"
targetTypeId
(Option.value ~default:"None" mainTypeId);*)
match mainTypeId with
| None -> false
| Some mainTypeId -> mainTypeId = targetTypeId)
| _ -> false)
| _ -> false

let getFirstFnUnlabelledArgType ~env ~full t =
let labels, _, env =
extractFunctionTypeWithEnv ~env ~package:full.package t
Expand Down