Repository navigation
Java: index Lombok-generated members, so calls to them resolve by type #2662
Description
What problem does this solve?
Lombok writes getters, setters, builders and withers at compile time, so the source has no declaration for invoice.getNumber() or Invoice.builder().number("1").build(). The graph has no node for them, the type-aware resolver cannot find them, and the call binds by name to any project method that happens to share it.
// src/com/example/model/Invoice.java
@Data @Builder
public class Invoice { private String number; private boolean paid; }
// src/com/example/model/Report.java: an unrelated class
public class Report {
public String getNumber() { return "r"; }
public static Report builder() { return new Report(); }
}
// src/com/example/app/Caller.java
public String number(Invoice invoice) { return invoice.getNumber(); }
public Invoice make() { return Invoice.builder().number("1").paid(true).build(); }On main (v0.12.0): number → Report.getNumber (unique_name); make → the fields Invoice.number and Invoice.paid (suffix_match, unique_name); builder() and build() get no edge. On a real Spring service with Lombok, about 8,300 generated members are missing, and Dto.builder() calls bind to whichever project class has the first builder by name.
Proposed solution
In extraction, for a class or field with a Lombok annotation, add the members Lombok would generate as Method (and builder Class) definitions, marked generated and tagged "lombok" in their properties:
- only annotations that the file's imports make Lombok's (
import lombok.Data;,import lombok.*;, or@lombok.Data); Spring's@Valuegenerates nothing; - a member the source declares by name is not generated, as Lombok itself skips it;
@Getter,@Setter,@Data,@Value(fields final unless@NonFinal),@With,AccessLevel.NONE; then@Builder/@SuperBuilder(also on records,@Builder.Default, builder options) and@Accessors(fluent, chain, prefix);- registered by QN only: generated members never enter the by-name index, so the name guess can never pick one; only the type-aware resolver reaches them. On the measured service, registering them by name as well let the name guess land 14,061 extra
suffix_matchedges on them.
Cost on that service, measured for this together with two smaller resolver fixes: index time about +0.5 s (+10 %), DB +52 MB (+21 %), mostly the generated nodes and their edges.
I have this implemented in two parts (accessors first, then builders and @Accessors), each with tests, and would like a maintainer view before opening the PRs: is a generated member in the definition list acceptable, and is QN-only registration the right way to keep it out of the name guess?
Activity
DeusData commentedon Oct 17, 2026
Thank you @tfactor2, both for the careful write-up and for asking before opening the PRs. That saved a round trip on a design question that really was ours to answer.
The answer is yes. Lombok-generated members should become ordinary
Methodnodes (and aClassnode for a generated builder), carrying agenerated: "lombok"entry in their node properties, and registered by qualified name only so that no name guess can land on them. Only the type-aware resolver should reach them. That matches your measurement: registering them by name as well let the name guess pick up thousands of extrasuffix_matchedges.A property in the node's properties JSON is already queryable everywhere we need it (
n.generatedin Cypher, and thefieldsoption ofsearch_graph), so this needs no new label. We are applying the same shape to Java record accessors in #2295 (generated: "record"). The "a Java call never binds to a field" veto from that PR is planned to land alongside, which also covers themake -> Invoice.numberfield binding from your example.Please go ahead and open both parts (accessors first, then builders and
@Accessors). We will measure them on the Lombok-heavy projects in our evaluation corpus (ruoyi-vue-pro, thingsboard, shardingsphere, skywalking, JeecgBoot, halo, eladmin, mall), which carry about 82k generated members between them, and report the numbers back on the PRs. If you would rather hand it over, just say so, and we will carry it with full credit to you.Thanks again, also for #2667, which we are measuring now.
tfactor2 commentedon Oct 19, 2026
Np,
I will do it closer to weekends.
PS: Opus 5.5 should be credited as well :)