mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-08-28 05:25:25 +00:00
fix(cache): bump SCHEMA_BUMP for the six-language capture change, + review fixes
SCHEMA_BUMP 39 -> 40. THIS IS THE MERGE-BLOCKER of the review: every language change in this PR is PARSE-TIME capture emission, and `analyze` skips tree-sitter dispatch for byte-unchanged chunks (GUARDRAILS.md:34), so a warm cache replays the pre-fix capture set verbatim and the new receiver edges never appear — silently, no error. Exactly the v27/v30 failure mode this file already documents. The PR description's claim that "no schema or version constant applies" was wrong on both counts: a bump IS required, and a plain re-analyze does NOT surface the captures without it. Re-check against origin/main before merging — main was also at 39 when 40 was allocated, and this file records eight prior collisions. Also from the review: - dart/simple-hooks.ts hand-rolled a 9-line parent walk byte-identical to the shared `walkToScope(innermost, tree, 'Class')` that TypeScript and Ruby call in one line in this same PR. Now uses the helper. - utils/call-analysis.ts: the doc framed the postfix-`!` peel as Swift-only. It is not — Kotlin `!!` parses as the same node and is peeled too, which the receiver-resolution bench proved (kotlin.nonNullAssert VISIBLE-GAP -> RESOLVES). The comment now says so, and names the `!` gate rather than the language as the bound. - test/helpers/temp-dir-pool.ts: its doc claimed four consumers; on THIS branch only `pdg-chained-receiver-callees` uses it (the other three convert on #2802). Corrected, and the byte-identical-to-#2802 intent recorded. - inferred-field-receiver-matrix: adds the Dart shadowing assertion the header comment already CLAIMED to make but never did. First attempt was vacuous — `var s = Outer()` is a declaration, so it never produced the bare `assignment_expression` the guard inspects; removing the guard did not fail the row. Fixture corrected to `var s; s = Outer();`, and mutation-verified: guard present 35 pass, guard removed the row goes red. Refs #2807 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fc90d94f06
commit
0418b0aac1
5 changed files with 57 additions and 12 deletions
|
|
@ -23,6 +23,7 @@ import type {
|
|||
TypeRef,
|
||||
CaptureMatch,
|
||||
} from 'gitnexus-shared';
|
||||
import { walkToScope } from '../typescript/simple-hooks.js';
|
||||
|
||||
export function dartBindingScopeFor(
|
||||
decl: CaptureMatch,
|
||||
|
|
@ -47,13 +48,7 @@ export function dartBindingScopeFor(
|
|||
// looks (#2807). Gated on the dedicated marker, never on
|
||||
// `@type-binding.constructor` at large, which also fires for genuine locals.
|
||||
if (decl['@type-binding.dart-field'] !== undefined) {
|
||||
let cur: Scope | undefined = innermost;
|
||||
while (cur !== undefined) {
|
||||
if (cur.kind === 'Class') return cur.id;
|
||||
if (cur.parent === null) break;
|
||||
cur = tree.getScope(cur.parent);
|
||||
}
|
||||
return null;
|
||||
return walkToScope(innermost, tree, 'Class');
|
||||
}
|
||||
|
||||
// (2) Function/method/constructor names are visible in the enclosing scope.
|
||||
|
|
|
|||
|
|
@ -574,7 +574,13 @@ const TRANSPARENT_RECEIVER_WRAPPERS = new Set([
|
|||
* type-preserving.
|
||||
*/
|
||||
const OPERATOR_GATED_RECEIVER_WRAPPERS = new Map<string, string>([
|
||||
['postfix_expression', '!'], // Swift `self.a!`
|
||||
// NOT Swift-only: Kotlin's `!!` non-null assertion parses as the same node type
|
||||
// and is equally type-preserving, so it is peeled too. Measured — the
|
||||
// receiver-resolution bench moved `kotlin.nonNullAssert` VISIBLE-GAP ->
|
||||
// RESOLVES when this landed, which is how the Kotlin effect was discovered
|
||||
// rather than assumed. Any other grammar emitting `postfix_expression` is
|
||||
// affected as well; the `!` gate, not the language, is what bounds this.
|
||||
['postfix_expression', '!'], // Swift `self.a!`, Kotlin `a!!`
|
||||
]);
|
||||
|
||||
/** Is `node` a wrapper that denotes exactly what its operand denotes? */
|
||||
|
|
|
|||
|
|
@ -174,7 +174,19 @@ import type { ParseWorkerResult } from '../core/ingestion/workers/parse-worker.j
|
|||
// "pick a bigger number": it is that the check must happen immediately before
|
||||
// merge, because the window between review and merge is exactly when `main`
|
||||
// allocates. Re-check against origin/main before merging this.
|
||||
const SCHEMA_BUMP = 39;
|
||||
// v40: inference-typed class fields emit type-binding captures in SIX languages
|
||||
// (#2807) — TypeScript/JavaScript `public_field_definition|field_definition` with a
|
||||
// `new_expression` value and `this.<field> = new X()`; Python `self.x = Outer()`;
|
||||
// Ruby `@ivar = Foo.new`; Swift optional property annotations; Dart inferred-type
|
||||
// and final field declarations plus constructor-body field writes. Every one of
|
||||
// these is PARSE-TIME capture emission, so a warm cache replays the pre-fix
|
||||
// capture set verbatim for byte-unchanged files and the new receiver edges never
|
||||
// appear — silently, with no error, exactly the v27/v30 failure mode. `analyze`
|
||||
// skips tree-sitter dispatch for unchanged chunks (GUARDRAILS.md), so a plain
|
||||
// re-analyze does NOT surface them without this bump.
|
||||
// RE-CHECK AGAINST origin/main IMMEDIATELY BEFORE MERGING — main was also at 39
|
||||
// when this was allocated, and this file records eight prior collisions.
|
||||
const SCHEMA_BUMP = 40;
|
||||
const GITNEXUS_PKG_VERSION = (() => {
|
||||
try {
|
||||
// package.json sits at gitnexus/package.json — two levels up from
|
||||
|
|
|
|||
|
|
@ -5,9 +5,16 @@
|
|||
* these tests each run against a throwaway copy of a fixture. Every consumer
|
||||
* had hand-rolled the SAME three parts — a `string[]` of created dirs, a
|
||||
* `mkdtempSync` that pushes onto it, and an `afterAll` that `rmSync`s the lot.
|
||||
* Extracted at the fourth consumer (`pipeline-pdg`, `pipeline-pdg-streaming`,
|
||||
* `interproc-taint`, `pdg-chained-receiver-callees`); the copies had already
|
||||
* drifted — `pipeline-pdg` registered two cleanup hooks over one array.
|
||||
* Extracted at the fourth consumer on the branch it came from (`pipeline-pdg`,
|
||||
* `pipeline-pdg-streaming`, `interproc-taint`, `pdg-chained-receiver-callees`),
|
||||
* where the copies had already drifted — `pipeline-pdg` registered two cleanup
|
||||
* hooks over one array.
|
||||
*
|
||||
* ON THIS BRANCH it arrives with exactly ONE consumer,
|
||||
* `pdg-chained-receiver-callees`, which is the only file here that needs it; the
|
||||
* other three still hand-roll their own cleanup and convert on #2802. The file
|
||||
* is byte-identical to that branch's copy on purpose, so if both land the add
|
||||
* resolves as a duplicate rather than a divergence.
|
||||
*
|
||||
* Only the LIFECYCLE is shared, deliberately: seeding differs per test (a
|
||||
* recursive fixture copy, a single file, an inline-written source, or nothing
|
||||
|
|
|
|||
|
|
@ -272,6 +272,17 @@ class AssignedField {
|
|||
return r.inner().compute(x);
|
||||
}
|
||||
}
|
||||
|
||||
class ShadowedAssignedField {
|
||||
var s;
|
||||
ShadowedAssignedField() {
|
||||
var s;
|
||||
s = Outer();
|
||||
}
|
||||
int run(int x) {
|
||||
return s.inner().compute(x);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
// ── Swift ────────────────────────────────────────────────────────────────────
|
||||
|
|
@ -500,6 +511,20 @@ const CASES: readonly LanguageCase[] = [
|
|||
targets: [`Method:${DART_FILE}:Outer.inner#0`],
|
||||
status: 'resolves',
|
||||
},
|
||||
// The shadowing guard, asserted rather than asserted-in-a-comment. Dart
|
||||
// writes a field with no receiver prefix, so `s = Outer()` is
|
||||
// syntactically identical to assigning a constructor-local. Here the
|
||||
// constructor declares its OWN `var s`, so the write targets that local
|
||||
// and the FIELD must stay untyped — `run` reads the field and must
|
||||
// therefore resolve nothing. Without the `locals.has(...)` guard in
|
||||
// `emitDartFieldAssignmentBindings` this row goes green with a WRONG edge,
|
||||
// which is the failure mode the guard exists to prevent.
|
||||
{
|
||||
name: 'shadowed-assigned-field',
|
||||
callerId: `Method:${DART_FILE}:ShadowedAssignedField.run#1`,
|
||||
targets: [],
|
||||
status: 'known-gap',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue