Skip to content

fix(resolver-vba): decline runtime-object call stubs; preserve shadow user classes (#110) - #113

Merged
ardelperal merged 1 commit into
mainfrom
fix/stub-resolver-both-flags
Jul 13, 2026
Merged

fix(resolver-vba): decline runtime-object call stubs; preserve shadow user classes (#110)#113
ardelperal merged 1 commit into
mainfrom
fix/stub-resolver-both-flags

Conversation

@ardelperal

Copy link
Copy Markdown
Owner

Summary

Closes #110 (supersedes #109). The post-extraction VBA call-stub resolver in codegraph-vba was emitting stub:true for ALL Receiver.Member calls whose target didn't match an existing function node by qualified_name — including runtime-object calls like DAO.Execute, fso.GetFileName, ListBox.AddItem, Collection.Add, err.Raise, VBA.DoEvents. These are NEVER user code, so the consumer's WHERE stub=true filter returned self-referential noise (the synthetic stub's own qualified_name matches itself). gestion_riesgos PR #117 was rolled back for exactly this.

This change runs the existing two-step name resolution FIRST and only classifies the receiver as a runtime object when no real target was found. A user class or module that happens to share a runtime-object name (e.g. a user .cls actually named DAO) is still repointed like any other real declaration. Every stub edge now carries a metadata.repointDecision field so consumers can tell a runtime-object decline apart from a genuinely-missing callee.

What's in

  • New canonical file src/resolution/vba-runtime-objects.ts with the lowercased runtime-object list and isRuntimeObject() helper.
  • src/resolution/index.tsresolveVbaCallStubTarget() returns a StubResolution { decision, target? }; the orchestrating resolveVbaCallStubs() stamps repointDecision on every stub edge (repointed: reponted-to-real, stub:false; declined: keeps stub:true + the matching decline label). New RepointDecision type is exported.
  • New test file __tests__/extraction-vba-stub-resolver.test.ts — 6 tests (5 active + 1 meta-classification). RED→GREEN documented in commit body.

What's deferred

Acceptance

  • npm test — 2770 green (2764 pre-existing + 6 new), 2 failed (pre-existing npm-sdk.test.ts bundle packaging failures, unchanged from baseline; require npm run build+scripts/pack-npm.sh flow), 52 skipped.
  • npx tsc --noEmit clean.
  • Schema unchanged (src/db/schema.sql 0 diff).
  • Parser unchanged (src/extraction/vba/* 0 diff). The new file lives in src/resolution/, not in the extractor.
  • CHANGELOG entry under [Unreleased] → Fixes. No pre-staged [X.Y.Z] block. No package.json bump (maintainer handles).

Closes #110. Supersedes #109.

… user classes (#110)

The post-extraction VBA call-stub resolver pointed every
`Receiver.Member` call that lacked a same-file declaration at itself
(via the synthetic stub's own qualifiedName). For runtime objects
(DAO, FileSystemObject, ListBox, Collection, err, DoCmd, VBA, ...)
the "stub target" was never user code, so consumer SQL filters
like `WHERE stub=true` returned self-referential noise (issue
#109/110: gestion_riesgos PR #117 was rolled back for exactly this).

This change runs the two-step name resolution FIRST so a user class or
module that happens to share a runtime-object name (a "shadow" user
class named, e.g., `DAO`) is still repointed like any other real
symbol (FR-2.1). When no real target exists, the resolver now
classifies the decline:
  - `declined-runtime`    — receiver is a runtime object, kept stub:true
  - `declined-ambiguous`  — 2+ real candidates, kept stub:true
  - `declined-not-found`  — genuine miss, kept stub:true
  - `reponted-to-real`    — edge repointed, stub:false

The decision is recorded on every stub edge as
`metadata.repointDecision` for observability (FR-3.1/3.2).

Scope:
- NEW: src/resolution/vba-runtime-objects.ts — canonical lowercase
  list of runtime receivers + `isRuntimeObject()` helper.
- MOD: src/resolution/index.ts — `resolveVbaCallStubTarget` now
  returns a `StubResolution { decision, target? }`; the orchestrating
  `resolveVbaCallStubs` stamps `repointDecision` on every stub edge
  (repointed: `reponted-to-real`; declined: keeps `stub:true` + the
  matching decline label) and exports the `RepointDecision` type.
- NEW: __tests__/extraction-vba-stub-resolver.test.ts — 6 RED-then-
  GREEN tests (1, 4, 5 fail before the resolver change; 2, 3 mirror
  tests 6.1/6.2 to keep the existing real-fixture contract; 6 is the
  meta-classification case).
- MOD: CHANGELOG.md — `[Unreleased] → Fixes` entry referencing #110.

FR checklist:
- FR-1.1 Runtime-object list in canonical file (18 seeds).
- FR-1.2 Two-step first; runtime skip only when no real target.
- FR-1.3 Single source of truth (canonical file); the VBA extractor's
  own RUNTIME_RECEIVER_BLACKLIST in src/extraction/vba/constants.ts
  is intentionally NOT wired to the canonical file because AC-4
  requires `src/extraction/vba/*` to have 0 diff. The two lists
  coexist: the extractor suppresses stub SYNTHESIS (PascalCase,
  short pre-filter), the resolver suppresses stub REPOINTING
  (lowercase, post-extraction safety net). Documented in the
  canonical file's header.
- FR-2.1 Shadow user class preserved: `DAO.Execute` on a user `.cls`
  named `DAO` -> repointed-to-real (verified by Test 4).
- FR-3.1, FR-3.2 `repointDecision` + exported `RepointDecision` type.
- FR-4.1 0 diff in src/extraction/vba/*, src/db/schema.sql,
  package.json.
- FR-5.1 Tests 6.1-6.6 in extraction-vba-realfixtures.test.ts stay
  green.
- FR-7.1 Genuinely-missing callee preserved (Test 5): edge keeps
  stub:true, decision = 'declined-not-found', exactly one row.

Tests (npm test, 2824 total):
- baseline (pre-change): 2764 passed, 2 failed, 52 skipped
  (npm-sdk.test.ts requires a packaged npm bundle; pre-existing,
  unrelated).
- post-change:           2770 passed, 2 failed, 52 skipped
  (same 2 npm-sdk failures, unchanged; +6 new tests, all green).
- npx tsc --noEmit: clean.

Supersedes #109 (the original runtime-object hypothesis, which
proposed a NEW resolver pass that already exists at
src/resolution/index.ts:1867). Closes #110.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(extractor-vba): post-extraction resolver must cover BOTH stub:true and stub:false (round-5 amplifier of #109)

1 participant