Skip to content

Commit 89f01ee

Browse files
committed
Add locate_type_multi query
1 parent ed68782 commit 89f01ee

File tree

14 files changed

+189
-5
lines changed

14 files changed

+189
-5
lines changed

merlin-lib.opam

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ depends: [
1717
"menhir" {dev & = "20231231"}
1818
"menhirLib" {dev & = "20231231"}
1919
"menhirSdk" {dev & = "20231231"}
20+
"yojson" {>= "2.0.0"}
21+
"ppx_yojson_conv" {>= "0.17.0"}
2022
]
2123
synopsis:
2224
"Merlin's libraries"

merlin.opam

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ depends: [
1616
"merlin-lib" {= version}
1717
"dot-merlin-reader" {>= "5.0"}
1818
"ocaml-index" {>= "1.0" & post}
19-
"yojson" {>= "2.0.0"}
2019
"conf-jq" {with-test}
2120
"ppxlib" {with-test}
2221
]

src/analysis/locate_type_multi.ml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
open StdLabels
2+
3+
module Type_tree = struct
4+
type node_data =
5+
| Artificial_node of [ `Arrow | `Tuple ]
6+
| Type of { path : Path.t; ty : Types.type_expr }
7+
8+
type t = { data : node_data; children : t list }
9+
end
10+
11+
let rec flatten_arrow ret_ty =
12+
match Types.get_desc ret_ty with
13+
| Tarrow (_, ty1, ty2, _) -> ty1 :: flatten_arrow ty2
14+
| _ -> [ ret_ty ]
15+
16+
let rec create_type_tree ty : Type_tree.t option =
17+
match Types.get_desc ty with
18+
| Tarrow (_, ty1, ty2, _) ->
19+
let tys = ty1 :: flatten_arrow ty2 in
20+
let children = List.filter_map tys ~f:create_type_tree in
21+
Some { data = Artificial_node `Arrow; children }
22+
| Ttuple tys | Tunboxed_tuple tys ->
23+
let children =
24+
List.filter_map tys ~f:(fun (_, ty) -> create_type_tree ty)
25+
in
26+
Some { data = Artificial_node `Tuple; children }
27+
| Tconstr (path, arg_tys, abbrev_memo) ->
28+
let ty_without_args =
29+
Types.newty2 ~level:Ident.highest_scope (Tconstr (path, [], abbrev_memo))
30+
in
31+
let children = List.filter_map arg_tys ~f:create_type_tree in
32+
Some { data = Type { path; ty = ty_without_args }; children }
33+
| Tlink ty | Tpoly (ty, _) -> create_type_tree ty
34+
| Tobject _ | Tfield _ ->
35+
(* CR-someday: support objects *)
36+
None
37+
| Tnil | Tvar _ | Tsubst _ | Tvariant _ | Tunivar _ | Tpackage _ -> None

src/analysis/locate_type_multi.mli

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module Type_tree : sig
2+
type node_data =
3+
| Artificial_node of [ `Arrow | `Tuple ]
4+
| Type of { path : Path.t; ty : Types.type_expr }
5+
6+
type t = { data : node_data; children : t list }
7+
end
8+
9+
val create_type_tree : Types.type_expr -> Type_tree.t option

src/commands/dune

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,8 @@
1212
merlin-lib.utils
1313
merlin-lib.kernel
1414
merlin-lib.query_protocol
15+
merlin-lib.query_protocol_kernel
1516
merlin-lib.query_commands
16-
merlin-lib.ocaml_utils))
17+
merlin-lib.ocaml_utils
18+
yojson)
19+
(preprocess (pps ppx_yojson_conv)))

src/commands/new_commands.ml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,22 @@ let all_commands =
513513
| #Msource.position as pos ->
514514
run buffer (Query_protocol.Locate_type pos)
515515
end;
516+
command "locate-type-multi"
517+
~spec:
518+
[ arg "-position" "<position> Position to locate the type of"
519+
(marg_position (fun pos _ -> pos))
520+
]
521+
~doc:
522+
"Locate the declaration of the type of the expression. If the type is \
523+
expressed via multiple identifiers, it returns the location of each identifier."
524+
~default:`None
525+
begin
526+
fun buffer pos ->
527+
match pos with
528+
| `None -> failwith "-position <pos> is mandatory"
529+
| #Msource.position as pos ->
530+
run buffer (Query_protocol.Locate_type_multi pos)
531+
end;
516532
command "occurrences"
517533
~spec:
518534
[ arg "-identifier-at" "<position> Position of the identifier"

src/commands/query_json.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ let dump (type a) : a t -> json =
7979
("position", mk_position pos)
8080
]
8181
| Locate_type pos -> mk "locate-type" [ ("position", mk_position pos) ]
82+
| Locate_type_multi pos ->
83+
mk "locate-type-multi" [ ("position", mk_position pos) ]
8284
| Enclosing pos -> mk "enclosing" [ ("position", mk_position pos) ]
8385
| Complete_prefix (prefix, pos, kind, doc, typ) ->
8486
mk "complete-prefix"
@@ -474,6 +476,8 @@ let json_of_response (type a) (query : a t) (response : a) : json =
474476
in
475477
str
476478
| Locate_type _, resp -> json_of_locate resp
479+
| Locate_type_multi _, resp ->
480+
Json.of_yojson_safe (Locate_type_multi_result.yojson_of_t resp)
477481
| Locate _, resp -> json_of_locate resp
478482
| Jump _, resp -> begin
479483
match resp with

src/frontend/dune

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
(name query_protocol)
33
(public_name merlin-lib.query_protocol)
44
(modules query_protocol)
5-
(flags :standard -open Merlin_utils -open Merlin_kernel -open Ocaml_parsing -open Ocaml_utils)
6-
(libraries merlin_kernel merlin_utils ocaml_parsing ocaml_utils))
5+
(flags :standard -open Merlin_utils -open Merlin_kernel -open Ocaml_parsing -open Ocaml_utils -open Query_protocol_kernel)
6+
(libraries merlin_kernel merlin_utils ocaml_parsing ocaml_utils query_protocol_kernel))
77

88
(library
99
(name query_commands)
@@ -32,4 +32,5 @@
3232
merlin_analysis
3333
merlin_sherlodoc
3434
query_protocol
35+
query_protocol_kernel
3536
str))

src/frontend/kernel/dune

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
(library
2+
(name query_protocol_kernel)
3+
(public_name merlin-lib.query_protocol_kernel)
4+
(libraries yojson)
5+
(preprocess (pps ppx_yojson_conv)))
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
(* This module contains definitions that can be used in a js-of-ocaml environment. This
2+
is useful because it allows VSCode extensions (which run in javascript) to use the
3+
serializers/deserializers defined in this module. *)
4+
5+
open struct
6+
include Ppx_yojson_conv_lib.Yojson_conv.Primitives
7+
8+
module Lexing = struct
9+
include Lexing
10+
11+
type nonrec position = position =
12+
{ pos_fname : string; pos_lnum : int; pos_bol : int; pos_cnum : int }
13+
[@@deriving yojson]
14+
end
15+
end
16+
17+
module Locate_type_multi_result = struct
18+
open Ppx_yojson_conv_lib.Yojson_conv.Primitives
19+
20+
type node_data =
21+
| Artificial_node of [ `Arrow | `Tuple ]
22+
| Type of
23+
{ type_ : string;
24+
result :
25+
[ `Found of string option * Lexing.position
26+
| `Builtin of string
27+
| `Not_in_env of string
28+
| `File_not_found of string
29+
| `Not_found of string * string option ]
30+
}
31+
[@@deriving yojson]
32+
33+
type type_tree = { data : node_data; children : type_tree list }
34+
[@@deriving yojson]
35+
36+
type t = Success of type_tree | Invalid_context [@@deriving yojson]
37+
end

0 commit comments

Comments
 (0)