Skip to content

Commit 6a1e4a1

Browse files
committed
Add type hovers for jkinds
1 parent 3cab6af commit 6a1e4a1

File tree

4 files changed

+99
-0
lines changed

4 files changed

+99
-0
lines changed

src/analysis/type_enclosing.ml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ type type_info =
99
| Type of Env.t * Types.type_expr
1010
| Type_decl of Env.t * Ident.t * Types.type_declaration
1111
| Type_constr of Env.t * Types.constructor_description
12+
| Jkind of Env.t * Types.jkind_lr
1213
| String of string
1314

1415
type typed_enclosings =
@@ -34,6 +35,10 @@ let print_type ~verbosity type_info =
3435
wrap_printing_env env (fun () ->
3536
Printtyp.modtype env ppf m;
3637
Format.flush_str_formatter ())
38+
| Jkind (env, jkind) ->
39+
wrap_printing_env env (fun () ->
40+
Jkind.format_expanded ppf jkind;
41+
Format.flush_str_formatter ())
3742
| String s -> s
3843

3944
let from_nodes ~path =
@@ -57,6 +62,21 @@ let from_nodes ~path =
5762
| Module_declaration_name { md_type = { mty_type = m } }
5863
| Module_type_declaration_name { mtd_type = Some { mty_type = m } } ->
5964
ret (Modtype (env, m))
65+
| Jkind_annotation annot -> (
66+
(* CR-someday: We need to parse the annotation because the compiler doesn't include
67+
the parsed jkind in the relevant spots. We should track it so that this is less
68+
hacky. It would also make it easier to deal with with-bounds. *)
69+
(* [Jkind.of_annotation] will fail to parse jkinds with with-bounds. For now, this
70+
isn't important. Usually, users will be hovering a jkind to know what an
71+
abbreviation means. *)
72+
try
73+
(* The context isn't important. It's just used for printing error messages, which
74+
we immediately discard anyways. *)
75+
let jkind =
76+
Jkind.of_annotation ~context:(Type_variable "fake_for_merlin") annot
77+
in
78+
ret (Jkind (env, jkind))
79+
with Jkind.Error.User_error _ -> None)
6080
| Class_field
6181
{ cf_desc = Tcf_method (_, _, Tcfk_concrete (_, { exp_type })) } ->
6282
begin

src/analysis/type_enclosing.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type type_info =
3939
| Type of Env.t * Types.type_expr
4040
| Type_decl of Env.t * Ident.t * Types.type_declaration
4141
| Type_constr of Env.t * Types.constructor_description
42+
| Jkind of Env.t * Types.jkind_lr
4243
| String of string
4344

4445
type typed_enclosings =

src/ocaml/typing/jkind.mli

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,3 +899,11 @@ module Debug_printers : sig
899899
val t : Format.formatter -> 'd Const.t -> unit
900900
end
901901
end
902+
903+
(* For Merlin *)
904+
905+
module Error : sig
906+
type t
907+
908+
exception User_error of Location.t * t
909+
end
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
Test that hovering over jkind annotations shows their full expansion.
2+
3+
$ file="test.ml"
4+
5+
$ print_merlin_result () {
6+
> result="$1"
7+
> line=$(echo "$result" | jq '.start.line')
8+
> start=$(echo "$result" | jq '.start.col')
9+
> end=$(echo "$result" | jq '.end.col')
10+
>
11+
> start_for_cut=$((start + 1))
12+
> end_for_cut=$((end + 1))
13+
> value=$(sed -n "${line}p" "$file" | cut -c "${start_for_cut}-${end_for_cut}")
14+
> type=$(echo "$result" | jq '.type' -r)
15+
> echo "\"$value\" : \"$type\""
16+
> }
17+
18+
$ hover () {
19+
> line="$1"
20+
> col="$2"
21+
> enclosings="$3"
22+
>
23+
> # Print the location we are hovering
24+
> sed -n "${line}p" "$file"
25+
> printf '%*s^\n' "$col" ''
26+
>
27+
> # Then print the output from Merlin
28+
> $MERLIN single type-enclosing -position "$line:$col" -filename "$file" < "$file" \
29+
> | jq -c ".value[:$enclosings][]" \
30+
> | while read -r result; do
31+
> print_merlin_result "$result"
32+
> done
33+
> }
34+
35+
$ cat > "$file" << EOF
36+
> type t1 : immutable_data
37+
> type t2 : value mod portable
38+
> type ('a : immediate) t3 : value
39+
> type 'a t4 : immutable_data mod global with 'a
40+
> EOF
41+
42+
$ hover 1 14 1
43+
type t1 : immutable_data
44+
^
45+
"immutable_data" : "value mod forkable unyielding many stateless immutable non_float"
46+
47+
$ hover 2 11 2
48+
type t2 : value mod portable
49+
^
50+
"value " : "value"
51+
"value mod portable" : "value mod portable"
52+
53+
$ hover 3 16 1
54+
type ('a : immediate) t3 : value
55+
^
56+
"immediate)" : "value mod global many stateless immutable external_ non_float"
57+
58+
$ hover 3 28 2
59+
type ('a : immediate) t3 : value
60+
^
61+
"value" : "value"
62+
"type ('a : immediate) t3 : value" : "type ('a : immediate) t3"
63+
64+
# CR-someday: It'd be nice to print the with-bounds when we enclose the whole jkind
65+
$ hover 4 20 3
66+
type 'a t4 : immutable_data mod global with 'a
67+
^
68+
"immutable_data " : "value mod forkable unyielding many stateless immutable non_float"
69+
"immutable_data mod global " : "value mod global many stateless immutable non_float"
70+
"type 'a t4 : immutable_data mod global with 'a" : "type 'a t4 : immutable_data mod global unforkable yielding with 'a"

0 commit comments

Comments
 (0)