Skip to content

Commit 53f14e8

Browse files
fix(resolve): bind imports for multi-file packages
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
1 parent 13e6407 commit 53f14e8

2 files changed

Lines changed: 44 additions & 8 deletions

File tree

internal/edgeresolve/resolve.go

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package edgeresolve
44
import (
55
"context"
66
"path"
7+
"sort"
78
"strconv"
89
"strings"
910

@@ -351,7 +352,7 @@ func resolveImportFile(ctx context.Context, lookup NodeLookup, st *resolveState,
351352
if prefixLookup, ok := lookup.(filePrefixLookup); ok {
352353
queried, err := prefixLookup.GetFileNodesByPathSuffix(ctx, importPath)
353354
if err == nil {
354-
return uniqueFileNode(queried)
355+
return representativeImportFile(queried)
355356
}
356357
}
357358
return nil
@@ -381,13 +382,48 @@ func bestImportFileMatch(fileNodeByPath map[string]model.Node, importPath string
381382
}
382383
}
383384
}
384-
if target := uniqueFileNode(exact); target != nil {
385+
if target := representativeImportFile(exact); target != nil {
385386
return target
386387
}
387388
if len(exact) > 0 {
388389
return nil
389390
}
390-
return uniqueFileNode(candidates)
391+
return representativeImportFile(candidates)
392+
}
393+
394+
func representativeImportFile(nodes []model.Node) *model.Node {
395+
files := uniqueFileNodes(nodes)
396+
if len(files) == 0 {
397+
return nil
398+
}
399+
firstDir := strings.Trim(path.Dir(files[0].FilePath), "/")
400+
for _, node := range files[1:] {
401+
if strings.Trim(path.Dir(node.FilePath), "/") != firstDir {
402+
return nil
403+
}
404+
}
405+
sort.Slice(files, func(i, j int) bool {
406+
return files[i].FilePath < files[j].FilePath
407+
})
408+
return &files[0]
409+
}
410+
411+
func uniqueFileNodes(nodes []model.Node) []model.Node {
412+
seen := make(map[uint]bool)
413+
var files []model.Node
414+
for _, node := range nodes {
415+
if node.Kind != model.NodeKindFile {
416+
continue
417+
}
418+
if node.ID != 0 && seen[node.ID] {
419+
continue
420+
}
421+
if node.ID != 0 {
422+
seen[node.ID] = true
423+
}
424+
files = append(files, node)
425+
}
426+
return files
391427
}
392428

393429
func commonSuffixDepth(a, b string) int {

internal/edgeresolve/resolve_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -311,11 +311,11 @@ func TestResolveImportsFromPrefersExactDirectoryMatch(t *testing.T) {
311311
}
312312
}
313313

314-
func TestResolveImportsFromLeavesAmbiguousExactDirectoryUnresolved(t *testing.T) {
314+
func TestResolveImportsFromBindsLexicographicRepresentativeForMultiFilePackage(t *testing.T) {
315315
lookup := fakeLookup{nodes: []model.Node{
316316
{ID: 10, QualifiedName: "cmd/main.go", Name: "cmd/main.go", Kind: model.NodeKindFile, FilePath: "cmd/main.go", Language: "go"},
317-
{ID: 20, QualifiedName: "internal/mcp/deps.go", Name: "internal/mcp/deps.go", Kind: model.NodeKindFile, FilePath: "internal/mcp/deps.go", Language: "go"},
318-
{ID: 21, QualifiedName: "internal/mcp/extra.go", Name: "internal/mcp/extra.go", Kind: model.NodeKindFile, FilePath: "internal/mcp/extra.go", Language: "go"},
317+
{ID: 21, QualifiedName: "internal/mcp/z.go", Name: "internal/mcp/z.go", Kind: model.NodeKindFile, FilePath: "internal/mcp/z.go", Language: "go"},
318+
{ID: 20, QualifiedName: "internal/mcp/a.go", Name: "internal/mcp/a.go", Kind: model.NodeKindFile, FilePath: "internal/mcp/a.go", Language: "go"},
319319
}}
320320
edges, err := Resolve(context.Background(), lookup, []model.Edge{{
321321
Kind: model.EdgeKindImportsFrom,
@@ -326,8 +326,8 @@ func TestResolveImportsFromLeavesAmbiguousExactDirectoryUnresolved(t *testing.T)
326326
if err != nil {
327327
t.Fatal(err)
328328
}
329-
if got := edges[0].ToNodeID; got != 0 {
330-
t.Fatalf("ToNodeID=%d, want unresolved 0 for ambiguous exact dir", got)
329+
if got := edges[0].ToNodeID; got != 20 {
330+
t.Fatalf("ToNodeID=%d, want lexicographic representative 20", got)
331331
}
332332
}
333333

0 commit comments

Comments
 (0)