Skip to content

Commit ce80c6c

Browse files
committed
filter pipe completions to only applicable functions
1 parent 72a522c commit ce80c6c

12 files changed

+87
-240
lines changed

analysis/src/CompletionBackEnd.ml

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -828,41 +828,31 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
828828
if Debug.verbose () then print_endline "[ctx_path]--> CPString";
829829
[
830830
Completion.create "dummy" ~env
831-
~kind:
832-
(Completion.Value
833-
(Ctype.newconstr (Path.Pident (Ident.create "string")) []));
831+
~kind:(Completion.Value (Ctype.newconstr Predef.path_string []));
834832
]
835833
| CPBool ->
836834
if Debug.verbose () then print_endline "[ctx_path]--> CPBool";
837835
[
838836
Completion.create "dummy" ~env
839-
~kind:
840-
(Completion.Value
841-
(Ctype.newconstr (Path.Pident (Ident.create "bool")) []));
837+
~kind:(Completion.Value (Ctype.newconstr Predef.path_bool []));
842838
]
843839
| CPInt ->
844840
if Debug.verbose () then print_endline "[ctx_path]--> CPInt";
845841
[
846842
Completion.create "dummy" ~env
847-
~kind:
848-
(Completion.Value
849-
(Ctype.newconstr (Path.Pident (Ident.create "int")) []));
843+
~kind:(Completion.Value (Ctype.newconstr Predef.path_int []));
850844
]
851845
| CPFloat ->
852846
if Debug.verbose () then print_endline "[ctx_path]--> CPFloat";
853847
[
854848
Completion.create "dummy" ~env
855-
~kind:
856-
(Completion.Value
857-
(Ctype.newconstr (Path.Pident (Ident.create "float")) []));
849+
~kind:(Completion.Value (Ctype.newconstr Predef.path_float []));
858850
]
859851
| CPArray None ->
860852
if Debug.verbose () then print_endline "[ctx_path]--> CPArray (no payload)";
861853
[
862854
Completion.create "array" ~env
863-
~kind:
864-
(Completion.Value
865-
(Ctype.newconstr (Path.Pident (Ident.create "array")) []));
855+
~kind:(Completion.Value (Ctype.newconstr Predef.path_array []));
866856
]
867857
| CPArray (Some cp) -> (
868858
if Debug.verbose () then
@@ -887,9 +877,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
887877
what inner type it has. *)
888878
[
889879
Completion.create "dummy" ~env
890-
~kind:
891-
(Completion.Value
892-
(Ctype.newconstr (Path.Pident (Ident.create "array")) []));
880+
~kind:(Completion.Value (Ctype.newconstr Predef.path_array []));
893881
])
894882
| CPOption cp -> (
895883
if Debug.verbose () then print_endline "[ctx_path]--> CPOption";
@@ -1135,6 +1123,10 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
11351123
(QueryEnv.toString env)
11361124
(QueryEnv.toString envFromCompletionItem)
11371125
else Printf.printf "CPPipe env:%s\n" (QueryEnv.toString env);
1126+
let tPath =
1127+
match typ with
1128+
| Builtin (_, t) | TypExpr t -> TypeUtils.pathFromTypeExpr t
1129+
in
11381130
let completionPath =
11391131
match typ with
11401132
| Builtin (builtin, _) ->
@@ -1186,13 +1178,15 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
11861178
completionsForPipeFromCompletionPath ~envCompletionIsMadeFrom ~opens
11871179
~pos ~scope ~debug ~prefix:funNamePrefix ~env ~rawOpens ~full
11881180
completionPath
1181+
|> TypeUtils.filterPipeableFunctions ~env ~full ?path:tPath
11891182
in
11901183
match completionPath with
11911184
| Some completionPath -> (
11921185
let completionsFromMainFn =
11931186
completionsForPipeFromCompletionPath ~envCompletionIsMadeFrom ~opens
11941187
~pos ~scope ~debug ~prefix:funNamePrefix ~env ~rawOpens ~full
11951188
completionPath
1189+
|> TypeUtils.filterPipeableFunctions ~env ~full ?path:tPath
11961190
in
11971191
let completions = completionsFromMainFn @ completionsFromExtraModule in
11981192
(* We add React element functions to the completion if we're in a JSX context *)
@@ -1822,8 +1816,7 @@ let rec completeTypedValue ?(typeArgContext : typeArgContext option) ~rawOpens
18221816
if prefix = "" then
18231817
[
18241818
create "\"\"" ~includesSnippets:true ~insertText:"\"$0\"" ~sortText:"A"
1825-
~kind:
1826-
(Value (Ctype.newconstr (Path.Pident (Ident.create "string")) []))
1819+
~kind:(Value (Ctype.newconstr Predef.path_string []))
18271820
~env;
18281821
]
18291822
else []
@@ -2012,7 +2005,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
20122005
stamp = -1;
20132006
fname = {loc = Location.none; txt = name};
20142007
optional = true;
2015-
typ = Ctype.newconstr (Path.Pident (Ident.create primitive)) [];
2008+
typ = Ctype.newconstr primitive [];
20162009
docstring = [];
20172010
deprecated = None;
20182011
}
@@ -2026,9 +2019,9 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
20262019
attributes = [];
20272020
fields =
20282021
[
2029-
mkField ~name:"version" ~primitive:"int";
2030-
mkField ~name:"module_" ~primitive:"string";
2031-
mkField ~name:"mode" ~primitive:"string";
2022+
mkField ~name:"version" ~primitive:Predef.path_int;
2023+
mkField ~name:"module_" ~primitive:Predef.path_string;
2024+
mkField ~name:"mode" ~primitive:Predef.path_string;
20322025
];
20332026
}
20342027
in
@@ -2044,7 +2037,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
20442037
stamp = -1;
20452038
fname = {loc = Location.none; txt = name};
20462039
optional = true;
2047-
typ = Ctype.newconstr (Path.Pident (Ident.create primitive)) [];
2040+
typ = Ctype.newconstr primitive [];
20482041
docstring = [];
20492042
deprecated = None;
20502043
}
@@ -2056,7 +2049,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
20562049
path = None;
20572050
attributes = [];
20582051
definition = `NameOnly "importAttributesConfig";
2059-
fields = [mkField ~name:"type_" ~primitive:"string"];
2052+
fields = [mkField ~name:"type_" ~primitive:Predef.path_string];
20602053
}
20612054
in
20622055
let rootConfig : completionType =
@@ -2068,8 +2061,8 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
20682061
definition = `NameOnly "moduleConfig";
20692062
fields =
20702063
[
2071-
mkField ~name:"from" ~primitive:"string";
2072-
mkField ~name:"with" ~primitive:"string";
2064+
mkField ~name:"from" ~primitive:Predef.path_string;
2065+
mkField ~name:"with" ~primitive:Predef.path_string;
20732066
];
20742067
}
20752068
in

analysis/src/TypeUtils.ml

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,17 +1159,20 @@ let getExtraModuleToCompleteFromForType ~env ~full (t : Types.type_expr) =
11591159

11601160
(** Checks whether the provided type represents a function that takes the provided path
11611161
as the first argument (meaning it's pipeable). *)
1162-
let rec fnTakesType ~env ~full ~path t =
1162+
let rec fnTakesTypeAsFirstArg ~env ~full ~path t =
11631163
match t.Types.desc with
11641164
| Tlink t1
11651165
| Tsubst t1
11661166
| Tpoly (t1, [])
11671167
| Tconstr (Pident {name = "function$"}, [t1; _], _) ->
1168-
fnTakesType ~env ~full ~path t1
1168+
fnTakesTypeAsFirstArg ~env ~full ~path t1
11691169
| Tarrow _ -> (
11701170
match extractFunctionType ~env ~package:full.package t with
1171-
| (Nolabel, {desc = Tconstr (p, _, _)}) :: _, _ ->
1172-
Path.same p path || Path.name p = "t"
1171+
| (Nolabel, t) :: _, _ -> (
1172+
let p = pathFromTypeExpr t in
1173+
match p with
1174+
| None -> false
1175+
| Some p -> Path.same p path || Path.name p = "t")
11731176
| _ -> false)
11741177
| _ -> false
11751178

@@ -1189,13 +1192,20 @@ let transformCompletionToPipeCompletion ~env ~replaceRange
11891192
}
11901193

11911194
(** Filters out completions that are not pipeable from a list of completions. *)
1192-
let filterPipeableFunctions ~env ~full ~path ~replaceRange completions =
1193-
completions
1194-
|> List.filter_map (fun (completion : Completion.t) ->
1195-
match completion.kind with
1196-
| Value t when fnTakesType ~env ~full ~path t ->
1197-
transformCompletionToPipeCompletion ~env ~replaceRange completion
1198-
| _ -> None)
1195+
let filterPipeableFunctions ~env ~full ?path ?replaceRange completions =
1196+
match path with
1197+
| None -> completions
1198+
| Some path ->
1199+
completions
1200+
|> List.filter_map (fun (completion : Completion.t) ->
1201+
match completion.kind with
1202+
| Value t when fnTakesTypeAsFirstArg ~env ~full ~path t -> (
1203+
match replaceRange with
1204+
| None -> Some completion
1205+
| Some replaceRange ->
1206+
transformCompletionToPipeCompletion ~env ~replaceRange completion
1207+
)
1208+
| _ -> None)
11991209

12001210
let removeCurrentModuleIfNeeded ~envCompletionIsMadeFrom completionPath =
12011211
if

analysis/tests/src/CompletePrioritize1.res

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module Test = {
22
type t = {name: int}
33
let add = (a: float) => a +. 1.0
4+
let name = t => t.name
45
}
56
let a: Test.t = {name: 4}
67
// a->

analysis/tests/src/CompletionInferValues.res

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ let reactEventFn = (cb: ReactEvent.Mouse.t => unit) => {
1313

1414
@val external getSomeRecord: unit => someRecord = "getSomeRecord"
1515

16-
// let x = 123; let aliased = x; aliased->f
16+
// let x = 123; let aliased = x; aliased->t
1717
// ^com
1818

1919
// let x = getSomeRecord(); x.
@@ -166,4 +166,4 @@ let fn3 = (~cb: sameFileRecord => unit) => {
166166
// Handles reusing the same name already in scope for bindings
167167
let res = 1
168168
// switch res { | res => res }
169-
// ^hov
169+
// ^hov

analysis/tests/src/CompletionPipeSubmodules.res

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
module A = {
22
module B1 = {
33
type b1 = B1
4+
type t = b1 // TODO(pipe-filter) Should be allowed without needing type t
45
let xx = B1
6+
let d = (_: t) => ""
57
}
68
module B2 = {
79
let yy = 20
810
}
9-
type t = {v: B1.b1}
11+
type t = {v: B1.t} // TODO(pipe-filter) Should be allowed without needing type t
1012
let x = {v: B1.B1}
1113
}
1214

@@ -20,11 +22,14 @@ module A = {
2022

2123
module C = {
2224
type t = C
25+
let do = (_: t) => ""
2326
}
2427

2528
module D = {
2629
module C2 = {
2730
type t2 = C2
31+
type t = t2 // TODO(pipe-filter) Should be allowed without needing type t
32+
let do = (_: t) => ""
2833
}
2934

3035
type d = {v: C.t, v2: C2.t2}
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
Complete src/CompletePrioritize1.res 5:6
2-
posCursor:[5:6] posNoWhite:[5:5] Found expr:[5:3->0:-1]
1+
Complete src/CompletePrioritize1.res 6:6
2+
posCursor:[6:6] posNoWhite:[6:5] Found expr:[6:3->0:-1]
33
Completable: Cpath Value[a]->
44
Package opens Pervasives.JsxModules.place holder
55
Resolved opens 1 pervasives
@@ -11,10 +11,10 @@ CPPipe type path:Test.t
1111
CPPipe pathFromEnv:Test found:true
1212
Path Test.
1313
[{
14-
"label": "Test.add",
14+
"label": "Test.name",
1515
"kind": 12,
1616
"tags": [],
17-
"detail": "float => float",
17+
"detail": "t => int",
1818
"documentation": null
1919
}]
2020

analysis/tests/src/expected/CompletionFromModule.res.txt

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -100,18 +100,6 @@ Path SomeOtherModule.
100100
"tags": [],
101101
"detail": "t => string",
102102
"documentation": null
103-
}, {
104-
"label": "SomeOtherModule.getNName3",
105-
"kind": 12,
106-
"tags": [],
107-
"detail": "irrelevantType => string",
108-
"documentation": null
109-
}, {
110-
"label": "SomeOtherModule.thisShouldNotBeCompletedFor",
111-
"kind": 12,
112-
"tags": [],
113-
"detail": "unit => string",
114-
"documentation": null
115103
}, {
116104
"label": "SomeOtherModule.getNName2",
117105
"kind": 12,
@@ -139,18 +127,6 @@ Path SomeOtherModule.
139127
"tags": [],
140128
"detail": "t => string",
141129
"documentation": null
142-
}, {
143-
"label": "getNName3",
144-
"kind": 12,
145-
"tags": [],
146-
"detail": "irrelevantType => string",
147-
"documentation": null
148-
}, {
149-
"label": "thisShouldNotBeCompletedFor",
150-
"kind": 12,
151-
"tags": [],
152-
"detail": "unit => string",
153-
"documentation": null
154130
}, {
155131
"label": "getNName2",
156132
"kind": 12,

analysis/tests/src/expected/CompletionFromModule2.res.txt

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -74,18 +74,6 @@ Path CompletionFromModule.SomeOtherModule.
7474
"tags": [],
7575
"detail": "t => string",
7676
"documentation": null
77-
}, {
78-
"label": "CompletionFromModule.SomeOtherModule.getNName3",
79-
"kind": 12,
80-
"tags": [],
81-
"detail": "irrelevantType => string",
82-
"documentation": null
83-
}, {
84-
"label": "CompletionFromModule.SomeOtherModule.thisShouldNotBeCompletedFor",
85-
"kind": 12,
86-
"tags": [],
87-
"detail": "unit => string",
88-
"documentation": null
8977
}, {
9078
"label": "CompletionFromModule.SomeOtherModule.getNName2",
9179
"kind": 12,
@@ -113,18 +101,6 @@ Path CompletionFromModule.SomeOtherModule.
113101
"tags": [],
114102
"detail": "t => string",
115103
"documentation": null
116-
}, {
117-
"label": "getNName3",
118-
"kind": 12,
119-
"tags": [],
120-
"detail": "irrelevantType => string",
121-
"documentation": null
122-
}, {
123-
"label": "thisShouldNotBeCompletedFor",
124-
"kind": 12,
125-
"tags": [],
126-
"detail": "unit => string",
127-
"documentation": null
128104
}, {
129105
"label": "getNName2",
130106
"kind": 12,

0 commit comments

Comments
 (0)