Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 20 additions & 0 deletions src/analysis/type_enclosing.ml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type type_info =
| Type of Env.t * Types.type_expr
| Type_decl of Env.t * Ident.t * Types.type_declaration
| Type_constr of Env.t * Types.constructor_description
| Jkind of Env.t * Types.jkind_lr
| String of string

type typed_enclosings =
Expand All @@ -34,6 +35,10 @@ let print_type ~verbosity type_info =
wrap_printing_env env (fun () ->
Printtyp.modtype env ppf m;
Format.flush_str_formatter ())
| Jkind (env, jkind) ->
wrap_printing_env env (fun () ->
Jkind.format_expanded ppf jkind;
Format.flush_str_formatter ())
| String s -> s

let from_nodes ~path =
Expand All @@ -57,6 +62,21 @@ let from_nodes ~path =
| Module_declaration_name { md_type = { mty_type = m } }
| Module_type_declaration_name { mtd_type = Some { mty_type = m } } ->
ret (Modtype (env, m))
| Jkind_annotation annot -> (
(* CR-someday: We need to parse the annotation because the compiler doesn't include
the parsed jkind in the relevant spots. We should track it so that this is less
hacky. It would also make it easier to deal with with-bounds. *)
(* [Jkind.of_annotation] will fail to parse jkinds with with-bounds. For now, this
isn't important. Usually, users will be hovering a jkind to know what an
abbreviation means. *)
try
(* The context isn't important. It's just used for printing error messages, which
we immediately discard anyways. *)
let jkind =
Jkind.of_annotation ~context:(Type_variable "fake_for_merlin") annot
in
ret (Jkind (env, jkind))
with Jkind.Error.User_error _ -> None)
| Class_field
{ cf_desc = Tcf_method (_, _, Tcfk_concrete (_, { exp_type })) } ->
begin
Expand Down
1 change: 1 addition & 0 deletions src/analysis/type_enclosing.mli
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type type_info =
| Type of Env.t * Types.type_expr
| Type_decl of Env.t * Ident.t * Types.type_declaration
| Type_constr of Env.t * Types.constructor_description
| Jkind of Env.t * Types.jkind_lr
| String of string

type typed_enclosings =
Expand Down
8 changes: 8 additions & 0 deletions src/ocaml/typing/jkind.mli
Original file line number Diff line number Diff line change
Expand Up @@ -899,3 +899,11 @@ module Debug_printers : sig
val t : Format.formatter -> 'd Const.t -> unit
end
end

(* For Merlin *)

module Error : sig
type t

exception User_error of Location.t * t
end
70 changes: 70 additions & 0 deletions tests/test-dirs/type-enclosing/jkind-hover.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
Test that hovering over jkind annotations shows their full expansion.

$ file="test.ml"

$ print_merlin_result () {
> result="$1"
> line=$(echo "$result" | jq '.start.line')
> start=$(echo "$result" | jq '.start.col')
> end=$(echo "$result" | jq '.end.col')
>
> start_for_cut=$((start + 1))
> end_for_cut=$((end + 1))
> value=$(sed -n "${line}p" "$file" | cut -c "${start_for_cut}-${end_for_cut}")
> type=$(echo "$result" | jq '.type' -r)
> echo "\"$value\" : \"$type\""
> }

$ hover () {
> line="$1"
> col="$2"
> enclosings="$3"
>
> # Print the location we are hovering
> sed -n "${line}p" "$file"
> printf '%*s^\n' "$col" ''
>
> # Then print the output from Merlin
> $MERLIN single type-enclosing -position "$line:$col" -filename "$file" < "$file" \
> | jq -c ".value[:$enclosings][]" \
> | while read -r result; do
> print_merlin_result "$result"
> done
> }

$ cat > "$file" << EOF
> type t1 : immutable_data
> type t2 : value mod portable
> type ('a : immediate) t3 : value
> type 'a t4 : immutable_data mod global with 'a
> EOF

$ hover 1 14 1
type t1 : immutable_data
^
"immutable_data" : "value mod forkable unyielding many stateless immutable non_float"

$ hover 2 11 2
type t2 : value mod portable
^
"value " : "value"
"value mod portable" : "value mod portable"

$ hover 3 16 1
type ('a : immediate) t3 : value
^
"immediate)" : "value mod global many stateless immutable external_ non_float"

$ hover 3 28 2
type ('a : immediate) t3 : value
^
"value" : "value"
"type ('a : immediate) t3 : value" : "type ('a : immediate) t3"

# CR-someday: It'd be nice to print the with-bounds when we enclose the whole jkind
$ hover 4 20 3
type 'a t4 : immutable_data mod global with 'a
^
"immutable_data " : "value mod forkable unyielding many stateless immutable non_float"
"immutable_data mod global " : "value mod global many stateless immutable non_float"
"type 'a t4 : immutable_data mod global with 'a" : "type 'a t4 : immutable_data mod global unforkable yielding with 'a"