Skip to content

Commit 1b45f23

Browse files
committed
Fix stdlib alias go-to-definition
Signed-off-by: Codex Bot <[email protected]>
1 parent 34e1219 commit 1b45f23

File tree

4 files changed

+427
-59
lines changed

4 files changed

+427
-59
lines changed

analysis/src/References.ml

Lines changed: 90 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -291,22 +291,79 @@ let validateLoc (loc : Location.t) (backup : Location.t) =
291291
loc_start = {pos_cnum = 0; pos_lnum = 1; pos_bol = 0; pos_fname = ""};
292292
loc_end = {pos_cnum = 0; pos_lnum = 1; pos_bol = 0; pos_fname = ""};
293293
}
294-
else backup
294+
else backup
295295
else loc
296296

297-
let resolveModuleDefinition ~(file : File.t) ~package stamp =
298-
match Stamps.findModule file.stamps stamp with
297+
let isGhostLoc (loc : Location.t) =
298+
loc.loc_ghost
299+
|| (loc.loc_start.pos_fname = "" && loc.loc_end.pos_fname = "")
300+
|| (loc.loc_start.pos_cnum = 0 && loc.loc_end.pos_cnum = 0)
301+
302+
let fallbackLocFromSource ~(uri : Uri.t) ~(tip : Tip.t) ~(name : string) =
303+
let path = Uri.toPath uri in
304+
let mk_regexp prefix =
305+
Str.regexp
306+
(Printf.sprintf "^ *%s +\\(?:rec +\\)?\\(%s\\)\\b" prefix (Str.quote name))
307+
in
308+
let regexpOpt =
309+
match tip with
310+
| Value -> Some (mk_regexp "let")
311+
| Type -> Some (mk_regexp "type")
312+
| _ -> None
313+
in
314+
match regexpOpt with
299315
| None -> None
300-
| Some md -> (
301-
match resolveModuleReference ~file ~package md with
316+
| Some regexp -> (
317+
match Files.readFile path with
302318
| None -> None
303-
| Some (file, declared) ->
304-
let loc =
305-
match declared with
306-
| None -> Uri.toTopLevelLoc file.uri
307-
| Some declared -> validateLoc declared.name.loc declared.extentLoc
319+
| Some text ->
320+
let lines = String.split_on_char '\n' text in
321+
let rec loop lineNumber = function
322+
| [] -> None
323+
| line :: rest ->
324+
if Str.string_match regexp line 0 then (
325+
let endIdx = Str.match_end () in
326+
let startIdx = endIdx - String.length name in
327+
let loc_start =
328+
{
329+
Lexing.pos_fname = path;
330+
pos_lnum = lineNumber + 1;
331+
pos_bol = 0;
332+
pos_cnum = startIdx;
333+
}
334+
in
335+
let loc_end =
336+
{
337+
Lexing.pos_fname = path;
338+
pos_lnum = lineNumber + 1;
339+
pos_bol = 0;
340+
pos_cnum = endIdx;
341+
}
342+
in
343+
Some {Location.loc_start; loc_end; loc_ghost = false}
344+
)
345+
else loop (lineNumber + 1) rest
308346
in
309-
Some (file.uri, loc))
347+
loop 0 lines)
348+
349+
let resolveModuleDefinition ~(file : File.t) ~package stamp =
350+
match Stamps.findModule file.stamps stamp with
351+
| None -> None
352+
| Some aliasDeclared -> (
353+
let aliasLoc =
354+
validateLoc aliasDeclared.name.loc aliasDeclared.extentLoc
355+
in
356+
match resolveModuleReference ~file ~package aliasDeclared with
357+
| None ->
358+
Some (file.uri, aliasLoc)
359+
| Some (resolvedFile, declared) -> (
360+
match declared with
361+
| None ->
362+
(* Alias resolved to a top-level module in another file; surface the alias site. *)
363+
Some (file.uri, aliasLoc)
364+
| Some declared ->
365+
let loc = validateLoc declared.name.loc declared.extentLoc in
366+
Some (resolvedFile.uri, loc)))
310367

311368
let definition ~file ~package stamp (tip : Tip.t) =
312369
match tip with
@@ -323,16 +380,22 @@ let definition ~file ~package stamp (tip : Tip.t) =
323380
match declaredForTip ~stamps:file.stamps stamp tip with
324381
| None -> None
325382
| Some declared ->
326-
let fileImpl, declaredImpl =
383+
let fileForLoc, declaredForLoc =
327384
match alternateDeclared ~package ~file declared tip with
328-
| Some (fileImpl, _extra, declaredImpl) when Uri.isInterface file.uri ->
329-
(fileImpl, declaredImpl)
330-
| _ -> (file, declared)
385+
| Some (fileImpl, _extra, declaredImpl) -> (fileImpl, declaredImpl)
386+
| None -> (file, declared)
331387
in
332-
let loc = validateLoc declaredImpl.name.loc declaredImpl.extentLoc in
333-
let env = QueryEnv.fromFile fileImpl in
388+
let loc = validateLoc declaredForLoc.name.loc declaredForLoc.extentLoc in
389+
let env = QueryEnv.fromFile fileForLoc in
334390
let uri =
335-
ResolvePath.getSourceUri ~env ~package declaredImpl.modulePath
391+
ResolvePath.getSourceUri ~env ~package declaredForLoc.modulePath
392+
in
393+
let loc =
394+
if isGhostLoc loc || Uri.isInterface uri then
395+
match fallbackLocFromSource ~uri ~tip ~name:declaredForLoc.name.txt with
396+
| None -> loc
397+
| Some foundLoc -> foundLoc
398+
else loc
336399
in
337400
maybeLog ("Inner uri " ^ Uri.toString uri);
338401
Some (uri, loc))
@@ -345,15 +408,15 @@ let definitionForLocItem ~full:{file; package} locItem =
345408
^ Tip.toString tip);
346409
match declaredForTip ~stamps:file.stamps stamp tip with
347410
| None -> None
348-
| Some declared ->
349-
maybeLog ("Declared " ^ declared.name.txt);
350-
if declared.isExported then (
351-
maybeLog ("exported, looking for alternate " ^ file.moduleName);
352-
match alternateDeclared ~package ~file declared tip with
353-
| None -> None
354-
| Some (file, _extra, declared) ->
355-
let loc = validateLoc declared.name.loc declared.extentLoc in
356-
Some (file.uri, loc))
411+
| Some declared ->
412+
maybeLog ("Declared " ^ declared.name.txt);
413+
if declared.isExported then (
414+
maybeLog ("exported, looking for alternate " ^ file.moduleName);
415+
match alternateDeclared ~package ~file declared tip with
416+
| None -> None
417+
| Some (file, _extra, declared) ->
418+
let loc = validateLoc declared.name.loc declared.extentLoc in
419+
Some (file.uri, loc))
357420
else None)
358421
| Typed (_, _, NotFound)
359422
| LModule (NotFound | Definition (_, _))

0 commit comments

Comments
 (0)