Skip to content

Commit ae3a615

Browse files
committed
Prevent duplication of top-level files under the root package in subtree builds
1 parent e916062 commit ae3a615

2 files changed

Lines changed: 33 additions & 0 deletions

File tree

internal/wikiindex/builder.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ func (b *Builder) folderChildren(ctx context.Context, folderPath string) ([]*rag
251251
}
252252
entries := map[string]lazyEntry{}
253253
for _, node := range nodes {
254+
if node.Kind == model.NodeKindPackage && isRootPackagePath(node.FilePath) {
255+
continue
256+
}
254257
childPath, immediate, ok := immediateChildPath(folderPath, node.FilePath)
255258
if !ok {
256259
continue
@@ -505,6 +508,13 @@ func immediateChildPath(parentPath, filePath string) (string, bool, bool) {
505508
return childPath, len(parts) == 1, true
506509
}
507510

511+
// @intent identify package nodes that represent the repository root rather than a sidebar child.
512+
// @domainRule the root package is folded into the Wiki root so top-level files are not duplicated under a synthetic "." package.
513+
func isRootPackagePath(filePath string) bool {
514+
filePath = strings.Trim(path.Clean(filePath), "/")
515+
return filePath == "." || filePath == ""
516+
}
517+
508518
// @intent collect graph node IDs for batch annotation lookup.
509519
func nodeIDs(nodes []model.Node) []uint {
510520
ids := make([]uint, 0, len(nodes))

internal/wikiindex/builder_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,29 @@ func TestBuilder_BuildSubtreeReturnsBoundedLazyChildren(t *testing.T) {
221221
}
222222
}
223223

224+
func TestBuilder_BuildSubtreeDoesNotDuplicateTopLevelFilesUnderRootPackage(t *testing.T) {
225+
db := setupDB(t)
226+
createNode(t, db, model.Node{QualifiedName: "github.com/example/project", Kind: model.NodeKindPackage, Name: "project", FilePath: ".", StartLine: 1, EndLine: 1, Language: "go"})
227+
createNode(t, db, model.Node{QualifiedName: "context.go", Kind: model.NodeKindFile, Name: "context.go", FilePath: "context.go", StartLine: 1, EndLine: 40, Language: "go"})
228+
createNode(t, db, model.Node{QualifiedName: "trace.Context", Kind: model.NodeKindFunction, Name: "Context", FilePath: "context.go", StartLine: 10, EndLine: 20, Language: "go"})
229+
230+
builder := &wikiindex.Builder{DB: db, OutDir: "docs"}
231+
root, err := builder.BuildSubtree(context.Background(), "", 1)
232+
if err != nil {
233+
t.Fatalf("BuildSubtree root: %v", err)
234+
}
235+
if pkg := ragindex.FindNode(root, "package:."); pkg != nil {
236+
t.Fatalf("root package should be folded into root, got %#v", pkg)
237+
}
238+
fileNode := ragindex.FindNode(root, "file:context.go")
239+
if fileNode == nil {
240+
t.Fatalf("expected top-level file under root: %#v", root.Children)
241+
}
242+
if !fileNode.HasChildren || len(fileNode.Children) != 0 {
243+
t.Fatalf("top-level file lazy state = %#v", fileNode)
244+
}
245+
}
246+
224247
func TestBuilder_RespectsExclude(t *testing.T) {
225248
db := setupDB(t)
226249
tmpDir := t.TempDir()

0 commit comments

Comments
 (0)