Skip to content

Commit d22c654

Browse files
cknittclaude
andcommitted
Refer uses of a functor applied from another file to that file's members
A use of a member of a functor applied from another file referred to the caller's copy, so references and renames no longer crossed files as they did when the application resolved to the functor. Such a use refers to the functor's member again, for values, types, fields, constructors and modules, and a signature's nested modules now name their items' paths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gGkPma9LAZimuQjnrP Claude-Session: https://claude.ai/code/session_01Kr4cjoUi2f5VpMvE6wT9bo Signed-off-by: Christoph Knittel <ck@cca.io>
1 parent e886bad commit d22c654

6 files changed

Lines changed: 912 additions & 141 deletions

File tree

‎analysis/src/process_cmt.ml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ let rec for_type_signature_item ~(env : Shared_types.Env.t)
148148
let name = Ident.name ident in
149149
let declared =
150150
add_declared ~extent:md_loc
151-
~item:(for_type_module ~name ~env md_type)
151+
~item:(for_type_module ~name ~env:(env |> Env.add_module ~name) md_type)
152152
~name:(Location.mkloc name md_loc)
153153
~stamp:(Ident.binding_time ident) ~env md_attributes
154154
(Exported.add exported Exported.Module)

‎analysis/src/process_extra.ml‎

Lines changed: 58 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -152,22 +152,55 @@ let extra_for_cmt ~(iterator : Tast_iterator.iterator)
152152
extra_for_signature_items ~iterator items;
153153
extra_for_parts parts
154154

155-
(* A use of an applied functor's member is also a use of the declaration
156-
in the functor's body that it was renamed from. *)
157-
let add_reference_with_original ~(env : Query_env.t) ~extra stamp loc =
158-
add_reference ~extra stamp loc;
159-
match Hashtbl.find_opt env.file.renamed_stamps stamp with
160-
| Some original -> add_reference ~extra original loc
161-
| None -> ()
155+
(* The module and path of a member of a functor applied from another file:
156+
the functor's path followed by the member's path inside its result. *)
157+
let applied_global ~(env : Query_env.t) stamp (tip : Tip.t) =
158+
let declared =
159+
let of_declared (d : _ Declared.t) = (d.module_path, d.name.txt) in
160+
match tip with
161+
| Value -> Stamps.find_value env.file.stamps stamp |> Option.map of_declared
162+
| Type | Field _ | Constructor _ ->
163+
Stamps.find_type env.file.stamps stamp |> Option.map of_declared
164+
| Module ->
165+
Stamps.find_module env.file.stamps stamp |> Option.map of_declared
166+
in
167+
let rec loop (module_path : Module_path.t) inner =
168+
match module_path with
169+
| IncludedModule (functor_path, _) -> (
170+
match Resolve_path.from_compiler_path ~env functor_path with
171+
| Global (module_name, path) -> Some (module_name, path @ inner)
172+
| Stamp _ | Exported _ | GlobalMod _ | NotFound -> None)
173+
| ExportedModule {name; module_path} -> loop module_path (name :: inner)
174+
| File _ | NotVisible -> None
175+
in
176+
match declared with
177+
| Some (module_path, name) when stamp >= Process_cmt.renamed_stamp_floor ->
178+
loop module_path [name]
179+
| _ -> None
180+
181+
(* A use of a local declaration. A use of an applied functor's member is
182+
also a use of the declaration in the functor's body that it was renamed
183+
from, and when the functor is in another file, it is a use of that file's
184+
declaration, as uses of the functor's own members are, for references
185+
across files to find it. *)
186+
let reference_to_stamp ~(env : Query_env.t) ~extra stamp tip loc =
187+
match applied_global ~env stamp tip with
188+
| Some (module_name, path) ->
189+
add_external_reference ~extra module_name path tip loc;
190+
GlobalReference (module_name, path, tip)
191+
| None ->
192+
add_reference ~extra stamp loc;
193+
(match Hashtbl.find_opt env.file.renamed_stamps stamp with
194+
| Some original -> add_reference ~extra original loc
195+
| None -> ());
196+
LocalReference (stamp, tip)
162197

163198
let add_for_path ~env ~extra path lident loc typ tip =
164199
let ident_name = Longident.last lident in
165200
let ident_loc = Utils.end_of_location loc (String.length ident_name) in
166201
let loc_type =
167202
match Resolve_path.from_compiler_path ~env path with
168-
| Stamp stamp ->
169-
add_reference_with_original ~env ~extra stamp ident_loc;
170-
LocalReference (stamp, tip)
203+
| Stamp stamp -> reference_to_stamp ~env ~extra stamp tip ident_loc
171204
| NotFound -> NotFound
172205
| Global (module_name, path) ->
173206
add_external_reference ~extra module_name path tip ident_loc;
@@ -178,9 +211,7 @@ let add_for_path ~env ~extra path lident loc typ tip =
178211
| Type -> Exported.find env.exported Exported.Type name
179212
| _ -> Exported.find env.exported Exported.Value name
180213
with
181-
| Some stamp ->
182-
add_reference_with_original ~env ~extra stamp ident_loc;
183-
LocalReference (stamp, tip)
214+
| Some stamp -> reference_to_stamp ~env ~extra stamp tip ident_loc
184215
| None -> NotFound)
185216
| GlobalMod _ -> NotFound
186217
in
@@ -192,22 +223,28 @@ let add_for_path_parent ~env ~extra path loc =
192223
| GlobalMod module_name ->
193224
add_file_reference ~extra module_name loc;
194225
TopLevelModule module_name
195-
| Stamp stamp ->
196-
add_reference_with_original ~env ~extra stamp loc;
197-
LModule (LocalReference (stamp, Module))
226+
| Stamp stamp -> LModule (reference_to_stamp ~env ~extra stamp Module loc)
198227
| NotFound -> LModule NotFound
199228
| Global (module_name, path) ->
200229
add_external_reference ~extra module_name path Module loc;
201230
LModule (GlobalReference (module_name, path, Module))
202231
| Exported (env, name) -> (
203232
match Exported.find env.exported Exported.Module name with
204-
| Some stamp ->
205-
add_reference_with_original ~env ~extra stamp loc;
206-
LModule (LocalReference (stamp, Module))
233+
| Some stamp -> LModule (reference_to_stamp ~env ~extra stamp Module loc)
207234
| None -> LModule NotFound)
208235
in
209236
add_loc_item extra loc loc_type
210237

238+
(* A type of a functor applied from another file is that file's type, as
239+
for its other members. *)
240+
let get_type_at_stamp ~env stamp =
241+
match applied_global ~env stamp Type with
242+
| Some (module_name, path) -> `Global (module_name, path)
243+
| None -> (
244+
match Stamps.find_type env.file.stamps stamp with
245+
| Some declared_type -> `Local declared_type
246+
| None -> `Not_found)
247+
211248
let get_type_at_path ~env path =
212249
match Resolve_path.from_compiler_path ~env path with
213250
| GlobalMod _ -> `Not_found
@@ -216,16 +253,8 @@ let get_type_at_path ~env path =
216253
| Exported (env, name) -> (
217254
match Exported.find env.exported Exported.Type name with
218255
| None -> `Not_found
219-
| Some stamp -> (
220-
let declared_type = Stamps.find_type env.file.stamps stamp in
221-
match declared_type with
222-
| Some declared_type -> `Local declared_type
223-
| None -> `Not_found))
224-
| Stamp stamp -> (
225-
let declared_type = Stamps.find_type env.file.stamps stamp in
226-
match declared_type with
227-
| Some declared_type -> `Local declared_type
228-
| None -> `Not_found)
256+
| Some stamp -> get_type_at_stamp ~env stamp)
257+
| Stamp stamp -> get_type_at_stamp ~env stamp
229258

230259
let add_for_field ~env ~extra ~record_type ~field_type {Asttypes.txt; loc} =
231260
match (Shared.dig record_type).desc with

‎tests/analysis_tests/tests/src/AppliedFunctor.res‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ module WithNested = (O: Ord) => {
3333
module Nested = {
3434
// ^ref
3535
let value = 1
36+
// ^ren nestedValue
3637
}
3738
}
3839

@@ -48,6 +49,7 @@ let n = N.Nested.value
4849

4950
module WithShapes = (O: Ord) => {
5051
type point = {x: int}
52+
// ^ref
5153
type shape = Dot | Box(int)
5254
}
5355

‎tests/analysis_tests/tests/src/AppliedFunctorUse.res‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,18 @@ let nv4 = N.Nested.value
5959

6060
let p2: Shapes.point = {x: 2}
6161
// ^ref
62+
63+
let s3 = StrSet.add([], "c")
64+
// ^ren addItem
65+
66+
let p3: Shapes.point = {x: 3}
67+
// ^ren location
68+
69+
let nv5 = N.Nested.value
70+
// ^ren renamedValue
71+
72+
let px2 = p.x
73+
// ^ref
74+
75+
let box2 = Shapes.Box(2)
76+
// ^ren Square

0 commit comments

Comments
 (0)