@@ -7,36 +7,27 @@ open Grain_diagnostics;
77open Sourcetree ;
88open Lsp_types ;
99
10+ type goto_request_type =
11+ | Definition
12+ | TypeDefinition ;
13+
1014// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#definitionParams
1115module RequestParams = {
1216 [@ deriving yojson({strict: false })]
13- type t = {
14- [@key "textDocument"]
15- text_document: Protocol . text_document_identifier ,
16- position: Protocol . position ,
17- };
17+ type t = Protocol . text_document_position_params ;
1818};
1919
2020// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#locationLink
2121module ResponseResult = {
2222 [@ deriving yojson]
23- type t = {
24- [@key "originSelectionRange"]
25- origin_selection_range: Protocol . range ,
26- [@key "targetUri"]
27- target_uri: Protocol . uri ,
28- [@key "targetRange"]
29- target_range: Protocol . range ,
30- [@key "targetSelectionRange"]
31- target_selection_range: Protocol . range ,
32- };
23+ type t = Protocol . location_link ;
3324};
3425
3526let send_no_result = (~id: Protocol . message_id ) => {
3627 Protocol . response(~id, ` Null );
3728};
3829
39- let send_definition =
30+ let send_location_link =
4031 (
4132 ~id: Protocol . message_id ,
4233 ~range: Protocol . range ,
@@ -45,48 +36,43 @@ let send_definition =
4536 ) => {
4637 Protocol . response(
4738 ~id,
48- ResponseResult . to_yojson ({
39+ Protocol . location_link_to_yojson ({
4940 origin_selection_range: range,
5041 target_uri,
5142 target_range,
5243 target_selection_range: target_range,
5344 }),
5445 );
5546};
47+
5648type check_position =
5749 | Forward
5850 | Backward ;
59- let rec find_definition =
51+
52+ let rec find_location =
6053 (
6154 ~check_position= Forward ,
55+ get_location: list (Sourcetree . node ) => option (Location . t ),
6256 sourcetree: Sourcetree . sourcetree ,
6357 position: Protocol . position ,
6458 ) => {
6559 let results = Sourcetree . query(position, sourcetree);
6660
6761 let result =
68- switch (results) {
69- | [Value ({definition}), ... _ ]
70- | [Pattern ({definition}), ... _ ]
71- | [Type ({definition}), ... _ ]
72- | [Declaration ({definition}), ... _ ]
73- | [Exception ({definition}), ... _ ]
74- | [Module ({definition}), ... _ ] =>
75- switch (definition) {
76- | None => None
77- | Some (loc ) =>
78- let uri = Utils . filename_to_uri(loc. loc_start. pos_fname);
79- Some ((loc, uri));
80- }
81- | _ => None
62+ switch (get_location(results)) {
63+ | None => None
64+ | Some (loc ) =>
65+ let uri = Utils . filename_to_uri(loc. loc_start. pos_fname);
66+ Some ((loc, uri));
8267 };
8368 switch (result) {
8469 | None =>
8570 if (check_position == Forward && position. character > 0 ) {
8671 // If a user selects from left to right, their pointer ends up after the identifier
8772 // this tries to check if the identifier was selected.
88- find_definition (
73+ find_location (
8974 ~check_position= Backward ,
75+ get_location,
9076 sourcetree,
9177 {line: position. line, character: position. character - 1 },
9278 );
@@ -102,16 +88,44 @@ let process =
10288 ~id: Protocol . message_id ,
10389 ~compiled_code: Hashtbl . t (Protocol . uri , Lsp_types . code ),
10490 ~documents: Hashtbl . t (Protocol . uri , string ),
91+ goto_request_type: goto_request_type ,
10592 params: RequestParams . t ,
10693 ) => {
10794 switch (Hashtbl . find_opt(compiled_code, params. text_document. uri)) {
10895 | None => send_no_result(~id)
10996 | Some ({program, sourcetree}) =>
110- let result = find_definition(sourcetree, params. position);
97+ let get_location =
98+ switch (goto_request_type) {
99+ | Definition => (
100+ results => {
101+ switch (results) {
102+ | [ Sourcetree . Value ({definition}), ... _ ]
103+ | [Pattern ({definition}), ... _ ]
104+ | [Type ({definition}), ... _ ]
105+ | [Declaration ({definition}), ... _ ]
106+ | [Exception ({definition}), ... _ ]
107+ | [Module ({definition}), ... _ ] => definition
108+ | _ => None
109+ };
110+ }
111+ )
112+ | TypeDefinition => (
113+ results => {
114+ switch (results) {
115+ | [Value ({env, value_type: type_expr }), ... _ ] =>
116+ Env . get_type_definition_loc(type_expr, env)
117+ | [Pattern ({definition}), ... _ ] => definition
118+ | _ => None
119+ };
120+ }
121+ )
122+ };
123+
124+ let result = find_location(get_location, sourcetree, params. position);
111125 switch (result) {
112126 | None => send_no_result(~id)
113127 | Some ((loc , uri )) =>
114- send_definition (
128+ send_location_link (
115129 ~id,
116130 ~range= Utils . loc_to_range(loc),
117131 ~target_uri= uri,
0 commit comments