feat(java): wire annotation usage as references edges (#89) - #207
feat(java): wire annotation usage as references edges (#89)#207Frankie-Xu wants to merge 2 commits into
Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
|
Thanks for taking this up — the shape is right, the bare-name fallback matches heritage's contract, and the field-annotation exclusion is sound even for imported in-repo annotations (the annotation-name identifier is suppressed from the imported-symbol path via One finding worth addressing before merge:
public interface Service {} // Service.java — plain interface, not an annotation
@Service public class Foo {} // @Service is the external (Spring) annotation→ emits The fix is cheap because the discriminator is reliable: restrict resolution to annotation-type nodes. E.g. filter the candidate by its Minor, non-blocking:
|
|
Thanks for the catch — Blocking: Fixed in Pinned by public interface Service {} // in-repo, not an annotation
@Service public class Foo {} // external Spring annotation→ Non-blocking: Keeping them. The heritage contract this PR already follows (and you flagged as matching) is keep-the-bare-name rather than drop; Non-blocking: invariants relaxation is language-agnostic Added a note on |
🌱 graft blast radius2 areas changed → 2 areas can be affected. 3 dependent symbols, depth 2. flowchart TB
A0(("Graph Building<br/>2 symbols"))
A1(("Engine<br/>1 symbol"))
classDef reached fill:#D9EDF3,stroke:#3AA7C9,stroke-width:1.5px,color:#0E313C;
class A0,A1 reached;
All 3 dependent symbols, grouped by areaGraph Building — 2 symbols in 2 files
Engine — 1 symbol in 1 file
Test signal per changed area — 1 ✓ · 1 –Reached = a node under a test path has a resolved edge into the changed symbol. It undercounts anything called indirectly — through a CLI, a spawned process or a dynamic import — so read a low ratio as “look here”, never as a coverage gate.
28 test suites also reference this code29 symbols, kept out of the diagram and the table so they cannot crowd out the areas a reviewer has to look at.
Open the interactive graph → — click an area to see its dependent symbols at file:line. |
Summary
marker_annotation/annotationon already-noded definitions (class / interface / enum / record / method / constructor) and emitreferencesedges from the annotated symbol to the annotation type.@interfacehits viaresolveName(same-file, then globally uniqueinterfacekind). Unresolved targets keep the bare name — heritage's contract, not PHP feat(php): wire attribute usage as references edges (#144 part 1) #155's drop.@Entitycannot collapse onto an in-repoclass Entity(fix: Java constructor calls lose their target when the type is generic #103).@MyAnno(value = "x")emits the same edge as marker@MyAnno. Field annotations are not edges (fields are not nodes).Mirrors #155 (PHP attributes →
references). Does not touch the #176 anonymous-class path.Scope
Slice C as aligned on #89 (Frankie-Xu 2026-08-21, endorsed by @dbianco: "Your C is a better slice than my A… The #155 precedent settles the design questions… Nothing left to adjudicate."):
referencesWALK_RELATIONSYield
Measured by @dbianco on current
main(issue comment):@interfaceUsages that point at a type the repo actually declares (gson):
Petclinic is 0 of 268 — every annotation there is Spring / JPA / Jackson, so every edge targets an unresolved name. That is still a navigable
Owner → Entitystring, same as heritage.Honest headline: a name-level annotation graph, mostly to external types; gson is where the resolved slice is visible. Those 182 counts include field usages; this PR only wires class/method-level ones (
@JsonAdapteron a type, a method@SerializedName, …). Field annotations stay insignature/graft grep.Test plan
node --import tsx --test test/graph-java.test.ts— 35/35, including:@interface MyAnnoon class + method →referencesto the annotation node@MyAnno(value = "x")same edges as marker@MyAnno@Override/@Entitykeep the bare name@Entitydoes not false-match an in-repoclass Entity@Transientis not a class-level edgenpm run buildcleannpm test— 913 pass; 5 failures were load flakes (PageRank3s budget, MCP stdio timeout,viz --tabsagainst a worktree with nograft/). Isolated re-run of those files +graph-php/graph-references/graph-invariantsis green except the pre-existingviz --tabscwd-graph assumption.@JsonAdapter/@SerializedName/@Expose, class + method + field usages):Field
@SerializedName/@Exposeproduced 0 extra class-level edges.Closes #89
Made with Cursor