Skip to content

Commit 17c52a8

Browse files
committed
correctly insert completion item text removing the dot when selecting a pipe function
1 parent c92c269 commit 17c52a8

File tree

5 files changed

+112
-32
lines changed

5 files changed

+112
-32
lines changed

analysis/src/CompletionBackEnd.ml

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,8 @@ let rec digToRecordFieldsForCompletion ~debug ~package ~opens ~full ~pos ~env
653653
| {kind = Type {kind = Record fields}} :: _ -> Some fields
654654
| _ -> None
655655

656-
let mkItem ?data name ~kind ~detail ~deprecated ~docstring =
656+
let mkItem ?data ?(range : Location.t option) name ~kind ~detail ~deprecated
657+
~docstring =
657658
let docContent =
658659
(match deprecated with
659660
| None -> ""
@@ -682,6 +683,23 @@ let mkItem ?data name ~kind ~detail ~deprecated ~docstring =
682683
insertTextFormat = None;
683684
filterText = None;
684685
data;
686+
range =
687+
(match range with
688+
| None -> None
689+
| Some range ->
690+
Some
691+
{
692+
start =
693+
{
694+
line = range.loc_start.pos_lnum - 1;
695+
character = range.loc_start.pos_cnum - range.loc_start.pos_bol;
696+
};
697+
end_ =
698+
{
699+
line = range.loc_end.pos_lnum - 1;
700+
character = range.loc_end.pos_cnum - range.loc_end.pos_bol;
701+
};
702+
});
685703
}
686704

687705
let completionToItem
@@ -696,9 +714,10 @@ let completionToItem
696714
filterText;
697715
detail;
698716
env;
717+
range;
699718
} ~full =
700719
let item =
701-
mkItem name
720+
mkItem name ?range
702721
?data:(kindToData (full.file.uri |> Uri.toPath) kind)
703722
~kind:(Completion.kindToInt kind)
704723
~deprecated
@@ -950,13 +969,14 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
950969
[Completion.create "dummy" ~env ~kind:(Completion.Value retType)]
951970
| _ -> [])
952971
| _ -> [])
953-
| CPField (CPId {path; completionContext = Module}, fieldName) ->
972+
| CPField {contextPath = CPId {path; completionContext = Module}; fieldName}
973+
->
954974
if Debug.verbose () then print_endline "[ctx_path]--> CPField: M.field";
955975
(* M.field *)
956976
path @ [fieldName]
957977
|> getCompletionsForPath ~debug ~opens ~full ~pos ~exact
958978
~completionContext:Field ~env ~scope
959-
| CPField (cp, fieldName) -> (
979+
| CPField {contextPath = cp; fieldName; fieldNameLoc} -> (
960980
if Debug.verbose () then print_endline "[ctx_path]--> CPField";
961981
let completionsForCtxPath =
962982
cp
@@ -1054,6 +1074,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
10541074
|> List.hd);
10551075
insertText = Some nameWithPipe;
10561076
env;
1077+
range = Some fieldNameLoc;
10571078
}
10581079
| _ -> None)
10591080
| None -> []

analysis/src/CompletionFrontEnd.ml

Lines changed: 51 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -222,21 +222,26 @@ let rec exprToContextPathInner (e : Parsetree.expression) =
222222
| Pexp_ident {txt; loc} ->
223223
Some
224224
(CPId {path = Utils.flattenLongIdent txt; completionContext = Value; loc})
225-
| Pexp_field (e1, {txt = Lident name}) -> (
225+
| Pexp_field (e1, {txt = Lident name; loc}) -> (
226226
match exprToContextPath e1 with
227-
| Some contextPath -> Some (CPField (contextPath, name))
227+
| Some contextPath ->
228+
Some (CPField {contextPath; fieldName = name; fieldNameLoc = loc})
228229
| _ -> None)
229230
| Pexp_field (_, {loc; txt = Ldot (lid, name)}) ->
230231
(* Case x.M.field ignore the x part *)
231232
Some
232233
(CPField
233-
( CPId
234-
{
235-
path = Utils.flattenLongIdent lid;
236-
completionContext = Module;
237-
loc;
238-
},
239-
name ))
234+
{
235+
contextPath =
236+
CPId
237+
{
238+
path = Utils.flattenLongIdent lid;
239+
completionContext = Module;
240+
loc;
241+
};
242+
fieldName = name;
243+
fieldNameLoc = loc;
244+
})
240245
| Pexp_send (e1, {txt}) -> (
241246
match exprToContextPath e1 with
242247
| None -> None
@@ -1130,29 +1135,54 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
11301135
| Lident name -> (
11311136
match exprToContextPath e with
11321137
| Some contextPath ->
1133-
let contextPath = Completable.CPField (contextPath, name) in
1138+
let contextPath =
1139+
Completable.CPField
1140+
{
1141+
contextPath;
1142+
fieldName = name;
1143+
fieldNameLoc = fieldName.loc;
1144+
}
1145+
in
11341146
setResult (Cpath contextPath)
11351147
| None -> ())
11361148
| Ldot (id, name) ->
11371149
(* Case x.M.field ignore the x part *)
11381150
let contextPath =
11391151
Completable.CPField
1140-
( CPId
1141-
{
1142-
loc = fieldName.loc;
1143-
path = Utils.flattenLongIdent id;
1144-
completionContext = Module;
1145-
},
1146-
if blankAfterCursor = Some '.' then
1147-
(* x.M. field ---> M. *) ""
1148-
else if name = "_" then ""
1149-
else name )
1152+
{
1153+
contextPath =
1154+
CPId
1155+
{
1156+
loc = fieldName.loc;
1157+
path = Utils.flattenLongIdent id;
1158+
completionContext = Module;
1159+
};
1160+
fieldName =
1161+
(if blankAfterCursor = Some '.' then
1162+
(* x.M. field ---> M. *) ""
1163+
else if name = "_" then ""
1164+
else name);
1165+
fieldNameLoc = fieldName.loc;
1166+
}
11501167
in
11511168
setResult (Cpath contextPath)
11521169
| Lapply _ -> ()
11531170
else if Loc.end_ e.pexp_loc = posBeforeCursor then
11541171
match exprToContextPath e with
1155-
| Some contextPath -> setResult (Cpath (CPField (contextPath, "")))
1172+
| Some contextPath ->
1173+
setResult
1174+
(Cpath
1175+
(CPField
1176+
{
1177+
contextPath;
1178+
fieldName = "";
1179+
fieldNameLoc =
1180+
{
1181+
loc_start = e.pexp_loc.loc_end;
1182+
loc_end = e.pexp_loc.loc_end;
1183+
loc_ghost = false;
1184+
};
1185+
}))
11561186
| None -> ())
11571187
| Pexp_apply ({pexp_desc = Pexp_ident compName}, args)
11581188
when Res_parsetree_viewer.is_jsx_expression expr ->

analysis/src/Protocol.ml

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ type completionItem = {
5151
insertText: string option;
5252
documentation: markupContent option;
5353
data: (string * string) list option;
54+
range: range option;
5455
}
5556

5657
type location = {uri: string; range: range}
@@ -142,7 +143,10 @@ let stringifyCompletionItem c =
142143
| Some doc -> stringifyMarkupContent doc) );
143144
("sortText", optWrapInQuotes c.sortText);
144145
("filterText", optWrapInQuotes c.filterText);
145-
("insertText", optWrapInQuotes c.insertText);
146+
( "insertText",
147+
match c.range with
148+
| Some _ -> None
149+
| None -> optWrapInQuotes c.insertText );
146150
( "insertTextFormat",
147151
match c.insertTextFormat with
148152
| None -> None
@@ -156,6 +160,20 @@ let stringifyCompletionItem c =
156160
(fields
157161
|> List.map (fun (key, value) -> (key, Some (wrapInQuotes value)))
158162
|> stringifyObject ~indentation:2) );
163+
( "textEdit",
164+
match c.range with
165+
| Some range ->
166+
Some
167+
(stringifyObject
168+
[
169+
("range", Some (stringifyRange range));
170+
( "newText",
171+
optWrapInQuotes
172+
(match c.insertText with
173+
| None -> Some c.label
174+
| v -> v) );
175+
])
176+
| None -> None );
159177
]
160178

161179
let stringifyHover value =
@@ -282,7 +300,7 @@ let stringifyCodeAction ca =
282300
(wrapInQuotes (codeActionKindToString ca.codeActionKind))
283301
(ca.edit |> stringifyCodeActionEdit)
284302

285-
let stringifyHint hint =
303+
let stringifyHint (hint : inlayHint) =
286304
Printf.sprintf
287305
{|{
288306
"position": %s,

analysis/src/SharedTypes.ml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,11 @@ module Completable = struct
612612
completionContext: completionContext;
613613
loc: Location.t;
614614
}
615-
| CPField of contextPath * string
615+
| CPField of {
616+
contextPath: contextPath;
617+
fieldName: string;
618+
fieldNameLoc: Location.t;
619+
}
616620
| CPObj of contextPath * string
617621
| CPAwait of contextPath
618622
| CPPipe of {
@@ -696,7 +700,8 @@ module Completable = struct
696700
| CPArray None -> "array"
697701
| CPId {path; completionContext} ->
698702
completionContextToString completionContext ^ list path
699-
| CPField (cp, s) -> contextPathToString cp ^ "." ^ str s
703+
| CPField {contextPath = cp; fieldName = s} ->
704+
contextPathToString cp ^ "." ^ str s
700705
| CPObj (cp, s) -> contextPathToString cp ^ "[\"" ^ s ^ "\"]"
701706
| CPPipe {contextPath; id; inJsx} ->
702707
contextPathToString contextPath
@@ -808,10 +813,12 @@ module Completion = struct
808813
detail: string option;
809814
typeArgContext: typeArgContext option;
810815
data: (string * string) list option;
816+
range: Location.t option;
811817
}
812818

813-
let create ?data ?typeArgContext ?(includesSnippets = false) ?insertText ~kind
814-
~env ?sortText ?deprecated ?filterText ?detail ?(docstring = []) name =
819+
let create ?range ?data ?typeArgContext ?(includesSnippets = false)
820+
?insertText ~kind ~env ?sortText ?deprecated ?filterText ?detail
821+
?(docstring = []) name =
815822
{
816823
name;
817824
env;
@@ -826,6 +833,7 @@ module Completion = struct
826833
detail;
827834
typeArgContext;
828835
data;
836+
range;
829837
}
830838

831839
(* https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion *)

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ Path SomeModule.
1919
"detail": "t => string",
2020
"documentation": null,
2121
"sortText": "getName",
22-
"insertText": "->SomeModule.getName"
22+
"textEdit": {
23+
"range": {"start": {"line": 11, "character": 4}, "end": {"line": 11, "character": 4}},
24+
"newText": "->SomeModule.getName"
25+
}
2326
}, {
2427
"label": "name",
2528
"kind": 5,

0 commit comments

Comments
 (0)