Skip to content

Commit 0375df3

Browse files
committed
Add locate_type_multi query
1 parent ed68782 commit 0375df3

File tree

15 files changed

+394
-5
lines changed

15 files changed

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

src/analysis/locate_type_multi.mli

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module Type_tree : sig
2+
type node_data =
3+
| Arrow
4+
| Tuple
5+
| Object
6+
| Type_ref of { path : Path.t; ty : Types.type_expr }
7+
8+
type t = { data : node_data; children : t list }
9+
end
10+
11+
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: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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+
| Arrow
22+
| Tuple
23+
| Object
24+
| Type_ref of
25+
{ type_ : string;
26+
result :
27+
[ `Found of string option * Lexing.position
28+
| `Builtin of string
29+
| `Not_in_env of string
30+
| `File_not_found of string
31+
| `Not_found of string * string option ]
32+
}
33+
[@@deriving yojson]
34+
35+
type type_tree = { data : node_data; children : type_tree list }
36+
[@@deriving yojson]
37+
38+
type t = Success of type_tree | Invalid_context [@@deriving yojson]
39+
end

0 commit comments

Comments
 (0)