Environment
- codebase-memory-mcp 0.9.0 (macOS arm64, Darwin 25.0.0)
- Project: Java 21 / Spring Boot 3 monorepo, ~1,358 Java files, indexed in full mode (20,530 nodes / 70,485 edges)
Summary
Methods declared on Java interfaces are emitted as two nodes: a Method (correct, with parent_class) and a duplicate Function node at the same file/line. Java has no free-standing functions, so any Function node in a .java file is spurious. Our graph has 472 Function nodes pointing into .java files.
Repro
Source (MarketplaceReservationService.java, an interface):
ReservationResponseDTO createReservation(Authentication authentication, ReservationRequestDTO request);
Cypher:
MATCH (m) WHERE m.name = 'createReservation' RETURN m.qualified_name, labels(m)
Result contains both:
...reservation.service.MarketplaceReservationService.createReservation ["Method"]
...reservation.service.createReservation ["Function"] <- duplicate, same file/line
Aggregate check:
MATCH (f:Function) WHERE f.file_path ENDS WITH '.java' RETURN count(f) // 472
Impact
- Search results show doubled entries for interface methods.
- Node/label counts and any per-label analytics are skewed.
- Structural boosting in BM25 (Functions +10) double-boosts these phantoms.
Notes
Looks like the interface-body visitor emits the method both under the parent type and at file scope. Happy to test a fix.
Environment
Summary
Methods declared on Java interfaces are emitted as two nodes: a
Method(correct, withparent_class) and a duplicateFunctionnode at the same file/line. Java has no free-standing functions, so anyFunctionnode in a.javafile is spurious. Our graph has 472 Function nodes pointing into.javafiles.Repro
Source (
MarketplaceReservationService.java, an interface):Cypher:
Result contains both:
Aggregate check:
Impact
Notes
Looks like the interface-body visitor emits the method both under the parent type and at file scope. Happy to test a fix.