mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-09-10 22:43:40 +00:00
* feat(java): synthesize Lombok @Data/@Getter/@Setter accessor methods * fix(lombok): resolve class identity by AST node id, not simple name Root-cause fix for the bot review's name-ambiguity findings: 1. Cross-file collision: the owner map was rebuilt per file from result.symbols, which accumulates across the whole language group — a later Java file with the same simple class name resolved to the earlier file's class node. The map is now filled INSIDE the capture loop (per-file scope) and keyed by the class_declaration AST node id (SyntaxNode.id), which is unique by construction. 2. Same-tail nested classes (Outer.A vs Other.A): a name-keyed map overwrote one with the other; AST-node-id keys cannot collide. 3. Synthesized method ids now follow the SAME convention real nested member ids use (keyed by the class's own simple name, matching findEnclosingClassInfo().className), so call resolution can hit synthesized accessors exactly like hand-written ones. 4. Lombok semantics: setters are no longer generated for final fields (Lombok never emits those) and @Setter(AccessLevel.NONE) now suppresses setters, symmetric to the existing getter suppression. Also tightens two vacuous test loops flagged by the bot (empty-array for..of passed trivially): counts are asserted before property loops, and a new regression test pins distinct owners for same-tailed nested classes plus the real id convention for nested accessors. * feat(java): synthesize Lombok accessors via provider hook and scope dual-path Replace the worker language===Java branch with LanguageProvider.synthesizeStructureMembers, align MethodRegistry ownership through scope captures, and bump parse-cache schema to 83 so warm caches cannot replay pre-synthesis worker output. Co-authored-by: Cursor <cursoragent@cursor.com> * test(java): cover Lombok synthesis semantics, cache replay, and CI bench Add unit/integration matrices (including durable cold/warm/historical parse-cache), a permanent no-Lombok vs Lombok-heavy harness with fingerprint budgets, and a CI --check step. Document that Kotlin→Java member CALLS remains a pre-existing gap. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(lombok): drop dead state and redundant scans from accessor synthesis Collapse Lombok import provenance into one compilation-unit scan with a cached wildcard flag, remove unused planned-accessor fields and the duplicate @Data enable flag, and plan scope captures without wrapping a fake Parser.Tree. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#2885) Give each Lombok accessor a unique scope range so multi-declarator fields do not share @scope.function IDs, and type the owner map as ReadonlyMap to match the provider hook. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(bench): pin the real Lombok synthesis fingerprint (#2885) The committed baseline held a fingerprint no revision of this branch ever produced, so the CI guard failed on every push. Re-pin it to the value the synthesizer deterministically emits and correct the method count the comment claims (800 x 4 x 2 = 6400, not 12800). Co-authored-by: Cursor <cursoragent@cursor.com> * feat(kotlin): synthesize JVM accessors using shared beanspec helpers (#2885) Kotlin val/var properties now emit the same JavaBeans get/set Methods as Lombok, via jvm/beanspec + jvm/synthetic-accessors. SCHEMA_BUMP 84 invalidates warm caches that would omit those callables. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(kotlin): match kotlinc JVM accessor ABI (#2885) Emit custom getters, preserve is-prefix names, and convert synthetic graph lines to 0-based so same-name accessors resolve to the owner. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#2885) Restrict Lombok provenance to lombok/experimental FQNs and match Kotlin existing methods by exact JVM name. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(jvm): consolidate accessor synthesis (#2885) Keep language-specific discovery in Java and Kotlin adapters while centralizing owner orchestration, collision policy, graph emission, and captures. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(jvm): align accessor synthesis with compiler ABI (#2885) Match Lombok and kotlinc provenance, companion owners, and collision arity so mixed-JVM CALLS bind to the Methods compilers actually emit. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#2885) Mark Kotlin interface accessors abstract, pin the Lombok case-fold collision test, and document the non-lowercase is-prefix rule. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#2885) Honor explicit Getter/Setter over @Data regardless of order, and let field @Accessors replace class-level fluent/chain. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): pin Kotlin scope-capture fingerprint after interface accessors (#2885) Invalidate warm parse cache so interface property Methods are not replayed as concrete. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: ChunxueLi <mecoloud@users.noreply.gitee.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
62 lines
1.8 KiB
JavaScript
62 lines
1.8 KiB
JavaScript
/**
|
|
* Shared fingerprint + --check for JVM accessor synthesis benches.
|
|
*/
|
|
import fs from 'node:fs';
|
|
import crypto from 'node:crypto';
|
|
|
|
export function fingerprintIds(ids) {
|
|
return crypto
|
|
.createHash('sha256')
|
|
.update([...ids].sort().join('\n'))
|
|
.digest('hex');
|
|
}
|
|
|
|
export function minSample(run, warmup, reps) {
|
|
for (let w = 0; w < warmup; w++) run();
|
|
const samples = [];
|
|
let last;
|
|
for (let r = 0; r < reps; r++) {
|
|
const t0 = performance.now();
|
|
last = run();
|
|
samples.push(performance.now() - t0);
|
|
}
|
|
return { last, ms: Math.min(...samples) };
|
|
}
|
|
|
|
export function runMethodCountCheck(report, expectedCounts) {
|
|
const errors = [];
|
|
for (const [arm, expected] of Object.entries(expectedCounts)) {
|
|
const actual = report[arm]?.methods;
|
|
if (actual !== expected) {
|
|
errors.push(`${arm}.methods ${String(actual)} != ${expected}`);
|
|
}
|
|
}
|
|
if (errors.length) {
|
|
console.error(JSON.stringify({ report, errors }, null, 2));
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
export function runBaselineCheck(report, baselinePath) {
|
|
const baseline = JSON.parse(fs.readFileSync(baselinePath, 'utf-8'));
|
|
const errors = [];
|
|
if (report.fingerprint !== baseline.fingerprint) {
|
|
errors.push(`fingerprint drift: ${report.fingerprint} != ${baseline.fingerprint}`);
|
|
}
|
|
if (report.scaling_ratio > baseline.scaling_budget) {
|
|
errors.push(`scaling_ratio ${report.scaling_ratio} > ${baseline.scaling_budget}`);
|
|
}
|
|
if (
|
|
baseline.widening_overhead_budget !== undefined &&
|
|
report.widening_overhead > baseline.widening_overhead_budget
|
|
) {
|
|
errors.push(
|
|
`widening_overhead ${report.widening_overhead} > ${baseline.widening_overhead_budget}`,
|
|
);
|
|
}
|
|
if (errors.length) {
|
|
console.error(JSON.stringify({ report, errors }, null, 2));
|
|
process.exit(1);
|
|
}
|
|
console.log(JSON.stringify({ ok: true, report }, null, 2));
|
|
}
|