Skip to content

Commit fc560ed

Browse files
committed
add config options for pattern variables and let bindings
1 parent 062952a commit fc560ed

File tree

2 files changed

+183
-12
lines changed

2 files changed

+183
-12
lines changed

ocaml-lsp-server/src/config_data.ml

Lines changed: 137 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,106 @@
11
open Import
22
open Import.Json.Conv
33

4+
module InlayHints = struct
5+
type t =
6+
{ hint_pattern_variables : bool
7+
[@key "hintPatternVariables"] [@default false]
8+
; hint_let_bindings : bool [@key "hintLetBindings"] [@default false]
9+
}
10+
[@@deriving_inline yojson] [@@yojson.allow_extra_fields]
11+
12+
let _ = fun (_ : t) -> ()
13+
14+
15+
let t_of_yojson =
16+
(let _tp_loc = "ocaml-lsp-server/src/config_data.ml.InlayHints.t" in
17+
function
18+
| `Assoc field_yojsons as yojson ->
19+
let hint_pattern_variables_field = ref Ppx_yojson_conv_lib.Option.None
20+
and hint_let_bindings_field = ref Ppx_yojson_conv_lib.Option.None
21+
and duplicates = ref []
22+
and extra = ref [] in
23+
let rec iter =
24+
function
25+
| (field_name, _field_yojson)::tail ->
26+
((match field_name with
27+
| "hintPatternVariables" ->
28+
(match Ppx_yojson_conv_lib.(!)
29+
hint_pattern_variables_field
30+
with
31+
| Ppx_yojson_conv_lib.Option.None ->
32+
let fvalue = bool_of_yojson _field_yojson in
33+
hint_pattern_variables_field :=
34+
(Ppx_yojson_conv_lib.Option.Some fvalue)
35+
| Ppx_yojson_conv_lib.Option.Some _ ->
36+
duplicates := (field_name ::
37+
(Ppx_yojson_conv_lib.(!) duplicates)))
38+
| "hintLetBindings" ->
39+
(match Ppx_yojson_conv_lib.(!) hint_let_bindings_field
40+
with
41+
| Ppx_yojson_conv_lib.Option.None ->
42+
let fvalue = bool_of_yojson _field_yojson in
43+
hint_let_bindings_field :=
44+
(Ppx_yojson_conv_lib.Option.Some fvalue)
45+
| Ppx_yojson_conv_lib.Option.Some _ ->
46+
duplicates := (field_name ::
47+
(Ppx_yojson_conv_lib.(!) duplicates)))
48+
| _ -> ());
49+
iter tail)
50+
| [] -> () in
51+
(iter field_yojsons;
52+
(match Ppx_yojson_conv_lib.(!) duplicates with
53+
| _::_ ->
54+
Ppx_yojson_conv_lib.Yojson_conv_error.record_duplicate_fields
55+
_tp_loc (Ppx_yojson_conv_lib.(!) duplicates) yojson
56+
| [] ->
57+
(match Ppx_yojson_conv_lib.(!) extra with
58+
| _::_ ->
59+
Ppx_yojson_conv_lib.Yojson_conv_error.record_extra_fields
60+
_tp_loc (Ppx_yojson_conv_lib.(!) extra) yojson
61+
| [] ->
62+
let (hint_pattern_variables_value, hint_let_bindings_value)
63+
=
64+
((Ppx_yojson_conv_lib.(!) hint_pattern_variables_field),
65+
(Ppx_yojson_conv_lib.(!) hint_let_bindings_field)) in
66+
{
67+
hint_pattern_variables =
68+
((match hint_pattern_variables_value with
69+
| Ppx_yojson_conv_lib.Option.None -> false
70+
| Ppx_yojson_conv_lib.Option.Some v -> v));
71+
hint_let_bindings =
72+
((match hint_let_bindings_value with
73+
| Ppx_yojson_conv_lib.Option.None -> false
74+
| Ppx_yojson_conv_lib.Option.Some v -> v))
75+
})))
76+
| _ as yojson ->
77+
Ppx_yojson_conv_lib.Yojson_conv_error.record_list_instead_atom _tp_loc
78+
yojson : Ppx_yojson_conv_lib.Yojson.Safe.t -> t)
79+
80+
let _ = t_of_yojson
81+
82+
let yojson_of_t =
83+
(function
84+
| { hint_pattern_variables = v_hint_pattern_variables
85+
; hint_let_bindings = v_hint_let_bindings
86+
} ->
87+
let bnds : (string * Ppx_yojson_conv_lib.Yojson.Safe.t) list = [] in
88+
let bnds =
89+
let arg = yojson_of_bool v_hint_let_bindings in
90+
("hintLetBindings", arg) :: bnds
91+
in
92+
let bnds =
93+
let arg = yojson_of_bool v_hint_pattern_variables in
94+
("hintPatternVariables", arg) :: bnds
95+
in
96+
`Assoc bnds
97+
: t -> Ppx_yojson_conv_lib.Yojson.Safe.t)
98+
99+
let _ = yojson_of_t
100+
101+
[@@@end]
102+
end
103+
4104
module Lens = struct
5105
type t = { enable : bool [@default true] }
6106
[@@deriving_inline yojson] [@@yojson.allow_extra_fields]
@@ -150,6 +250,8 @@ type t =
150250
[@default None] [@yojson_drop_default ( = )]
151251
; extended_hover : ExtendedHover.t Json.Nullable_option.t
152252
[@key "extendedHover"] [@default None] [@yojson_drop_default ( = )]
253+
; inlay_hints : InlayHints.t Json.Nullable_option.t
254+
[@key "inlayHints"] [@default None] [@yojson_drop_default ( = )]
153255
}
154256
[@@deriving_inline yojson] [@@yojson.allow_extra_fields]
155257

@@ -161,6 +263,7 @@ let t_of_yojson =
161263
| `Assoc field_yojsons as yojson -> (
162264
let codelens_field = ref Ppx_yojson_conv_lib.Option.None
163265
and extended_hover_field = ref Ppx_yojson_conv_lib.Option.None
266+
and inlay_hints_field = ref Ppx_yojson_conv_lib.Option.None
164267
and duplicates = ref []
165268
and extra = ref [] in
166269
let rec iter = function
@@ -186,6 +289,17 @@ let t_of_yojson =
186289
extended_hover_field := Ppx_yojson_conv_lib.Option.Some fvalue
187290
| Ppx_yojson_conv_lib.Option.Some _ ->
188291
duplicates := field_name :: Ppx_yojson_conv_lib.( ! ) duplicates)
292+
| "inlayHints" -> (
293+
match Ppx_yojson_conv_lib.( ! ) inlay_hints_field with
294+
| Ppx_yojson_conv_lib.Option.None ->
295+
let fvalue =
296+
Json.Nullable_option.t_of_yojson
297+
InlayHints.t_of_yojson
298+
_field_yojson
299+
in
300+
inlay_hints_field := Ppx_yojson_conv_lib.Option.Some fvalue
301+
| Ppx_yojson_conv_lib.Option.Some _ ->
302+
duplicates := field_name :: Ppx_yojson_conv_lib.( ! ) duplicates)
189303
| _ -> ());
190304
iter tail
191305
| [] -> ()
@@ -205,9 +319,10 @@ let t_of_yojson =
205319
(Ppx_yojson_conv_lib.( ! ) extra)
206320
yojson
207321
| [] ->
208-
let codelens_value, extended_hover_value =
322+
let codelens_value, extended_hover_value, inlay_hints_value =
209323
( Ppx_yojson_conv_lib.( ! ) codelens_field
210-
, Ppx_yojson_conv_lib.( ! ) extended_hover_field )
324+
, Ppx_yojson_conv_lib.( ! ) extended_hover_field
325+
, Ppx_yojson_conv_lib.( ! ) inlay_hints_field )
211326
in
212327
{ codelens =
213328
(match codelens_value with
@@ -217,6 +332,10 @@ let t_of_yojson =
217332
(match extended_hover_value with
218333
| Ppx_yojson_conv_lib.Option.None -> None
219334
| Ppx_yojson_conv_lib.Option.Some v -> v)
335+
; inlay_hints =
336+
(match inlay_hints_value with
337+
| Ppx_yojson_conv_lib.Option.None -> None
338+
| Ppx_yojson_conv_lib.Option.Some v -> v)
220339
}))
221340
| _ as yojson ->
222341
Ppx_yojson_conv_lib.Yojson_conv_error.record_list_instead_atom
@@ -228,8 +347,21 @@ let _ = t_of_yojson
228347

229348
let yojson_of_t =
230349
(function
231-
| { codelens = v_codelens; extended_hover = v_extended_hover } ->
350+
| { codelens = v_codelens
351+
; extended_hover = v_extended_hover
352+
; inlay_hints = v_inlay_hints
353+
} ->
232354
let bnds : (string * Ppx_yojson_conv_lib.Yojson.Safe.t) list = [] in
355+
let bnds =
356+
if None = v_inlay_hints then bnds
357+
else
358+
let arg =
359+
(Json.Nullable_option.yojson_of_t InlayHints.yojson_of_t)
360+
v_inlay_hints
361+
in
362+
let bnd = ("inlayHints", arg) in
363+
bnd :: bnds
364+
in
233365
let bnds =
234366
if None = v_extended_hover then bnds
235367
else
@@ -259,4 +391,6 @@ let _ = yojson_of_t
259391
let default =
260392
{ codelens = Some { enable = false }
261393
; extended_hover = Some { enable = false }
394+
; inlay_hints =
395+
Some { hint_pattern_variables = true; hint_let_bindings = true }
262396
}

ocaml-lsp-server/src/inlay_hints.ml

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,26 @@ let outline_type ~env typ =
1414
| _ -> true)
1515
|> String.concat ~sep:" "
1616

17-
let hint_binding_iter typedtree range k =
17+
let hint_binding_iter ?(hint_let_bindings = false)
18+
?(hint_pattern_variables = false) typedtree range k =
1819
let module I = Ocaml_typing.Tast_iterator in
20+
(* to be used for pattern variables in match cases, but not for function
21+
arguments *)
22+
let case hint_lhs (iter : I.iterator) (case : _ Typedtree.case) =
23+
if hint_lhs then iter.pat iter case.c_lhs;
24+
Option.iter case.c_guard ~f:(iter.expr iter);
25+
iter.expr iter case.c_rhs
26+
in
27+
let value_binding hint_lhs (iter : I.iterator) (vb : Typedtree.value_binding)
28+
=
29+
if range_overlaps_loc range vb.vb_loc then
30+
if not hint_lhs then iter.expr iter vb.vb_expr
31+
else
32+
match vb.vb_expr.exp_desc with
33+
| Texp_function _ -> iter.expr iter vb.vb_expr
34+
| _ -> I.default_iterator.value_binding iter vb
35+
in
36+
1937
let expr (iter : I.iterator) (e : Typedtree.expression) =
2038
if range_overlaps_loc range e.exp_loc then
2139
match e.exp_desc with
@@ -31,19 +49,20 @@ let hint_binding_iter typedtree range k =
3149
} ->
3250
iter.pat iter vb_pat;
3351
iter.expr iter body
52+
| Texp_let (_, vbs, body) ->
53+
List.iter vbs ~f:(value_binding hint_let_bindings iter);
54+
iter.expr iter body
55+
| Texp_letop { body; _ } -> case hint_let_bindings iter body
56+
| Texp_match (expr, cases, _) ->
57+
iter.expr iter expr;
58+
List.iter cases ~f:(case hint_pattern_variables iter)
3459
| _ -> I.default_iterator.expr iter e
3560
in
3661

3762
let structure_item (iter : I.iterator) (item : Typedtree.structure_item) =
3863
if range_overlaps_loc range item.str_loc then
3964
I.default_iterator.structure_item iter item
4065
in
41-
let value_binding (iter : I.iterator) (vb : Typedtree.value_binding) =
42-
if range_overlaps_loc range vb.vb_loc then
43-
match vb.vb_expr.exp_desc with
44-
| Texp_function _ -> iter.expr iter vb.vb_expr
45-
| _ -> I.default_iterator.value_binding iter vb
46-
in
4766
let pat (type k) iter (pat : k Typedtree.general_pattern) =
4867
if range_overlaps_loc range pat.pat_loc then
4968
let has_constraint =
@@ -60,14 +79,27 @@ let hint_binding_iter typedtree range k =
6079
| _ -> ())
6180
in
6281
let iterator =
63-
{ I.default_iterator with expr; structure_item; pat; value_binding }
82+
{ I.default_iterator with
83+
expr
84+
; structure_item
85+
; pat
86+
; value_binding = value_binding true
87+
}
6488
in
6589
iterator.structure iterator typedtree
6690

6791
let compute (state : State.t)
6892
{ InlayHintParams.range; textDocument = { uri }; _ } =
6993
let store = state.store in
7094
let doc = Document_store.get store uri in
95+
let hint_let_bindings =
96+
Option.map state.configuration.data.inlay_hints ~f:(fun c ->
97+
c.hint_let_bindings)
98+
in
99+
let hint_pattern_variables =
100+
Option.map state.configuration.data.inlay_hints ~f:(fun c ->
101+
c.hint_pattern_variables)
102+
in
71103
match Document.kind doc with
72104
| `Other -> Fiber.return None
73105
| `Merlin m when Document.Merlin.kind m = Intf -> Fiber.return None
@@ -78,7 +110,12 @@ let compute (state : State.t)
78110
match Mtyper.get_typedtree (Mpipeline.typer_result pipeline) with
79111
| `Interface _ -> ()
80112
| `Implementation typedtree ->
81-
hint_binding_iter typedtree range (fun env type_ loc ->
113+
hint_binding_iter
114+
?hint_let_bindings
115+
?hint_pattern_variables
116+
typedtree
117+
range
118+
(fun env type_ loc ->
82119
let open Option.O in
83120
let hint =
84121
let label = outline_type ~env type_ in

0 commit comments

Comments
 (0)