Skip to content

Commit 8e3cbb2

Browse files
cknittclaude
andcommitted
Keep the functor's file for members of an applied functor
Codex review on #9084: the members of `module M = Other.Make(X)` were registered in the current file with the locations of Other's functor body, so Go to Definition and hover's type-definition link combined Other's location with the current file. Their module path now records the functor, as it does for included modules, so both resolve to the functor's file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gLMawVgtmiKy3TMBc3 Signed-off-by: Christoph Knittel <ck@cca.io>
1 parent cd32c86 commit 8e3cbb2

6 files changed

Lines changed: 58 additions & 9 deletions

File tree

‎analysis/src/hover.ml‎

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ type extracted_type = {
6464
decl: Types.type_declaration;
6565
env: Shared_types.Query_env.t;
6666
loc: Warnings.loc;
67+
uri: Uri.t;
68+
(** the file of [loc], which differs from [env]'s for a type
69+
of an applied or included module of another file *)
6770
}
6871

6972
let find_relevant_types_from_type ~state ~file ~package typ =
@@ -103,9 +106,13 @@ let find_relevant_types_from_type ~state ~file ~package typ =
103106
let from_constructor_path ~env path =
104107
match References.dig_constructor ~state ~env ~package path with
105108
| None -> None
106-
| Some (env, {name = {txt}; extent_loc; item = {decl}}) ->
109+
| Some (env, {name = {txt}; extent_loc; item = {decl}; module_path}) ->
107110
if Utils.is_uncurried_internal path then None
108-
else Some {name = txt; env; loc = extent_loc; decl; path}
111+
else
112+
let uri =
113+
Resolve_path.get_source_uri ~state ~env ~package module_path
114+
in
115+
Some {name = txt; env; loc = extent_loc; decl; path; uri}
109116
in
110117
let constructors = Shared.find_type_constructors types_to_search in
111118
constructors |> List.filter_map (from_constructor_path ~env:env_to_search)
@@ -142,12 +149,14 @@ let expand_types ~state ~file ~package ~supports_markdown_links typ =
142149
else (
143150
types_seen := String_set.add type_id !types_seen;
144151
true))
145-
|> List.map (fun {decl; env; loc; path} ->
152+
|> List.map (fun {decl; env; loc; path; uri} ->
146153
let link_to_type_definition_str =
147154
if
148155
supports_markdown_links
149156
&& not (is_inline_record_definition decl path)
150-
then Markdown.go_to_definition_text ~env ~pos:loc.Warnings.loc_start
157+
then
158+
Markdown.go_to_definition_text ~uri ~env
159+
~pos:loc.Warnings.loc_start ()
151160
else ""
152161
in
153162
Markdown.divider

‎analysis/src/markdown.ml‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,17 @@ let make_goto_command link =
88
Printf.sprintf "[%s](%s#L%d,%d)" link.label link.file (link.start_pos.line + 1)
99
(link.start_pos.character + 1)
1010

11-
let go_to_definition_text ~env ~pos =
11+
let go_to_definition_text ?uri ~env ~pos () =
1212
let start_line, start_col = Pos.of_lexing pos in
13+
let uri =
14+
match uri with
15+
| Some uri -> uri
16+
| None -> env.Shared_types.Query_env.file.uri
17+
in
1318
"\nGo to: "
1419
^ make_goto_command
1520
{
1621
label = "Type definition";
17-
file = Uri.to_string env.Shared_types.Query_env.file.uri;
22+
file = Uri.to_string uri;
1823
start_pos = {line = start_line; character = start_col};
1924
}

‎analysis/src/process_cmt.ml‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -669,12 +669,20 @@ and for_module ~env (mod_expr : Typedtree.module_expr) module_name =
669669
in
670670
Stamps.add_module env.stamps stamp declared);
671671
for_module ~env result_expr module_name
672-
| Tmod_apply _ ->
672+
| Tmod_apply (functor_, _arg, _coercion) ->
673673
(* The functor's body has the parameter's types; the application's
674674
signature has the argument's. Its items keep the identifiers of the
675675
body, whose stamps are already taken, so they are renamed first,
676-
with stamps above any that a compilation hands out. *)
676+
with stamps above any that a compilation hands out. Their locations
677+
are in the functor's body, so they are marked as coming from the
678+
functor, like included items, for definitions to find its file. *)
677679
let env = env |> Env.add_module ~name:module_name in
680+
let env =
681+
match get_module_path functor_.mod_desc with
682+
| Some path ->
683+
{env with module_path = IncludedModule (path, env.module_path)}
684+
| None -> env
685+
in
678686
if Ident.current_time () < renamed_stamp_floor then
679687
Ident.set_current_time renamed_stamp_floor;
680688
for_type_module ~name:module_name ~env

‎analysis/src/signature_help.ml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ let docs_for_label type_expr ~file ~state ~package ~supports_markdown_links =
1212
|> List.map (fun {Hover.decl; name; env; loc; path} ->
1313
let link_to_type_definition_str =
1414
if supports_markdown_links then
15-
Markdown.go_to_definition_text ~env ~pos:loc.Warnings.loc_start
15+
Markdown.go_to_definition_text ~env ~pos:loc.Warnings.loc_start ()
1616
else ""
1717
in
1818
(* Since printing the whole name via its path can get quite long, and
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module StrSet = AppliedFunctor.MakeSet({
2+
type t = string
3+
let compare = (a: string, b) => a < b ? -1 : a > b ? 1 : 0
4+
})
5+
6+
let s = StrSet.add([], "a")
7+
// ^def
8+
9+
let t: StrSet.t = []
10+
// ^hov
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Definition src/AppliedFunctorUse.res 5:15
2+
{
3+
"range": {
4+
"end": { "character": 9, "line": 7 },
5+
"start": { "character": 6, "line": 7 }
6+
},
7+
"uri": "file:///AppliedFunctor.res"
8+
}
9+
10+
Hover src/AppliedFunctorUse.res 8:14
11+
{
12+
"contents": {
13+
"kind": "markdown",
14+
"value": "```rescript\nStrSet.t\n```\n\n---\n\n```\n \n```\n```rescript\ntype StrSet.t = array<string>\n```\nGo to: [Type definition](AppliedFunctor.res#L7,3)\n"
15+
}
16+
}
17+

0 commit comments

Comments
 (0)