Skip to content

Commit f3cf286

Browse files
cknittclaude
andcommitted
Resolve applied fields and constructors to the functor's declarations
Codex review on #9084: an applied functor's record fields and constructors are read from its signature, where they have no location. Go to Definition returned that missing location, and rename added it as a reference, producing edits at character -1. Their lookups now go through the type they were renamed from, which has the body's locations, and fields and constructors without a location are not registered as references. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gLMawVgtmiKy3TMBc3 Claude-Session: https://claude.ai/code/session_01Kr4cjoUi2f5VpMvE6wT9bo Signed-off-by: Christoph Knittel <ck@cca.io>
1 parent 6f601b0 commit f3cf286

4 files changed

Lines changed: 86 additions & 2 deletions

File tree

‎analysis/src/process_extra.ml‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,19 @@ let extra_for_file ~(file : File.t) =
2929
(TypeDefinition (d.name.txt, d.item.Type.decl, stamp));
3030
add_reference ~extra stamp d.name.loc;
3131
match d.item.Type.kind with
32+
(* Fields and constructors of a type read from a signature, such as
33+
an applied functor's, have no location of their own; references
34+
to them are those of the declarations they come from. *)
3235
| Record labels ->
3336
labels
37+
|> List.filter (fun {fname} -> not fname.loc.loc_ghost)
3438
|> List.iter (fun {stamp; fname; typ} ->
3539
add_reference ~extra stamp fname.loc;
3640
add_loc_item extra fname.loc
3741
(Typed (d.name.txt, typ, Definition (d.stamp, Field fname.txt))))
3842
| Variant constructors ->
3943
constructors
44+
|> List.filter (fun {Constructor.cname} -> not cname.loc.loc_ghost)
4045
|> List.iter (fun {Constructor.stamp; cname} ->
4146
add_reference ~extra stamp cname.loc;
4247
let t =

‎analysis/src/references.ml‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,16 +124,23 @@ let declared_for_tip ~(stamps : Stamps.t) stamp (tip : Tip.t) =
124124
Stamps.find_module stamps stamp
125125
|> Option.map (fun x -> {x with Declared.item = ()})
126126

127+
(* The type a renamed type of an applied functor comes from, whose fields
128+
and constructors have source locations. *)
129+
let original_type_stamp (file : File.t) stamp =
130+
match Hashtbl.find_opt file.renamed_stamps stamp with
131+
| Some original -> original
132+
| None -> stamp
133+
127134
let get_field (file : File.t) stamp name =
128-
match Stamps.find_type file.stamps stamp with
135+
match Stamps.find_type file.stamps (original_type_stamp file stamp) with
129136
| None -> None
130137
| Some {item = {kind}} -> (
131138
match kind with
132139
| Record fields -> fields |> List.find_opt (fun f -> f.fname.txt = name)
133140
| _ -> None)
134141

135142
let get_constructor (file : File.t) stamp name =
136-
match Stamps.find_type file.stamps stamp with
143+
match Stamps.find_type file.stamps (original_type_stamp file stamp) with
137144
| None -> None
138145
| Some {item = {kind}} -> (
139146
match kind with

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,20 @@ module N = WithNested(IntOrd)
4545

4646
let n = N.Nested.value
4747
// ^ref
48+
49+
module WithShapes = (O: Ord) => {
50+
type point = {x: int}
51+
type shape = Dot | Box(int)
52+
}
53+
54+
module Shapes = WithShapes(IntOrd)
55+
56+
let p: Shapes.point = {x: 1}
57+
let px = p.x
58+
// ^def
59+
60+
let shape = Shapes.Box(1)
61+
// ^def
62+
63+
let py = p.x
64+
// ^ren y

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

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,58 @@ References src/AppliedFunctor.res 45:10
168168
}
169169
]
170170

171+
Definition src/AppliedFunctor.res 56:11
172+
{
173+
"range": {
174+
"end": { "character": 17, "line": 49 },
175+
"start": { "character": 16, "line": 49 }
176+
},
177+
"uri": "file:///AppliedFunctor.res"
178+
}
179+
180+
Definition src/AppliedFunctor.res 59:19
181+
{
182+
"range": {
183+
"end": { "character": 24, "line": 50 },
184+
"start": { "character": 21, "line": 50 }
185+
},
186+
"uri": "file:///AppliedFunctor.res"
187+
}
188+
189+
Rename src/AppliedFunctor.res 62:11 y
190+
[
191+
{
192+
"edits": [
193+
{
194+
"newText": "y",
195+
"range": {
196+
"end": { "character": 17, "line": 49 },
197+
"start": { "character": 16, "line": 49 }
198+
}
199+
},
200+
{
201+
"newText": "y",
202+
"range": {
203+
"end": { "character": 24, "line": 55 },
204+
"start": { "character": 23, "line": 55 }
205+
}
206+
},
207+
{
208+
"newText": "y",
209+
"range": {
210+
"end": { "character": 12, "line": 56 },
211+
"start": { "character": 11, "line": 56 }
212+
}
213+
},
214+
{
215+
"newText": "y",
216+
"range": {
217+
"end": { "character": 12, "line": 62 },
218+
"start": { "character": 11, "line": 62 }
219+
}
220+
}
221+
],
222+
"textDocument": { "uri": "file:///AppliedFunctor.res", "version": 0 }
223+
}
224+
]
225+

0 commit comments

Comments
 (0)