Repository navigation
fix(incremental): keep interface implementers of unchanged files - #3299
Conversation
A call typed to an interface with one first-party implementer also binds the implementation and each of its `@line` variants (enum constant bodies), read from `interface_implementers` and the registry's duplicate buckets. Both were filled only by the classes parsed in the current run, so a comment edit to the caller dropped the fan-out (gson: 8 edges), and beside a new implementer the stored one did not count, so the new one looked sole. The run now reads the project's IMPLEMENTS edges back into `interface_implementers` beside the INHERITS rehydration, and a rehydrated `natural@line` qn rejoins its natural qn's variant bucket. Fixes #3256 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EbsCWQcSTGQXv3g5sk418m
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 89a4b22cac
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
…ehydrate-3256 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016xpVRsxnpLfjsPc7qrjoyy # Conflicts: # codebase_rag/constants/graph.py # codebase_rag/function_registry.py # codebase_rag/graph_updater.py # codebase_rag/tests/test_incremental_interface_implementers.py
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016xpVRsxnpLfjsPc7qrjoyy
…ehydrate-3256 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016xpVRsxnpLfjsPc7qrjoyy
No conflicts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013MgsnsA3jM14E4ai22xnhy
|



Summary
@linevariants, such as enum-constant bodies (_emit_interface_sole_impls). A fresh index emits them. After any incremental sync that re-parses the caller's file but not the implementer's, they were gone. On google/gson, a 40-commit replay lost 8 edges, among themgetFieldNames → FieldNamingPolicy.translateNameand its six constant overrides.interface_implementers, which says whether an interface has a sole implementer;variants()the@linebodies._rehydrate_interface_implementers_from_graph, run beside_rehydrate_class_inheritance_from_graph, reads the project'sIMPLEMENTSedges (CYPHER_ALL_IMPLEMENTS) intointerface_implementers. A re-parsed file's classes were deleted with their old edges, so a droppedimplementsisn't read back.FunctionRegistryTrie.restore_variant(qn)puts a rehydratednatural@line(or@line_col) qn back in its natural qn's bucket._rehydrate_definition_rowcalls it for every row it restores; any other qn is left alone.Demo
The GIF plays the issue's
jirepro step by step against Memgraph.enum Policy implements Strategyhasname(String)and two constant-body overrides, andFactory.namescallsstrategy.name(f).callees Factory.names, a comment-only edit toFactory.javacommitted, an incrementalcgr start --update-graph, andcalleesagain.Policy.name(String),@11,@8andStrategy.name(String); after the sync,Strategy.name(String)only.Type of Change
Related Issues
Fixes #3256
Test Plan
make test): related suites run, full suite see belowRed/green TDD in
codebase_rag/tests/test_incremental_interface_implementers.py: a fresh index and then an incremental run, through the stateful graph double.test_a_reparsed_caller_keeps_its_sole_implementer_edges: the issue's repro, with all four callees after an edit toFactory.javaalone.test_a_second_implementer_ends_the_sole_fan_out:Other implements Strategyis added whilePolicyis unchanged. On main the call gains a wrong edge toOther.name; it must match a fresh index of the same tree.test_restore_variant_reads_only_a_line_or_line_column_suffix, a unit test.test_an_implementer_that_drops_the_interface_loses_its_edges.Policyre-parsed withoutimplements Strategygives what a fresh index gives: the interface method only.test_java*,test_jvm*,test_incremental*,test_reingest*,test_function_registry*,test_registry*,test_graph_updater*,test_eval_double*,test_interface*,test_implements*,test_rehydrat*andtest_duplicate*file (114 files): 1,236 passed, 1 skipped.ILog.Info(string)underInfo(string), notInfo), so a re-parsed caller bindsl.Info("hi")to an unrelatedLevels.Info()(serilog replay: all 33 incremental-only heuristic edges) #3261) edits the same lines of_rehydrate_definition_row; whichever merges second keeps both calls.-n 4): 109 failed, 17,712 passed, 176 skipped. The 109 failures are the same set main fails in this environment (LLM provider keys, the build-binary check, the unreachable-network tests); none is new.Checklist
StrEnum)# type: ignore,cast(),Any, orobjecttype hints🤖 Generated with Claude Code
https://claude.ai/code/session_01EbsCWQcSTGQXv3g5sk418m
Generated by Claude Code
Summary by CodeRabbit