@aroman22/codegraph-vba 1.15.0 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +131 -3
  2. package/dist/bin/daemon-release.d.ts +7 -0
  3. package/dist/db/queries.d.ts +41 -0
  4. package/dist/extraction/access-erd-extractor.d.ts +57 -0
  5. package/dist/extraction/extraction-version.d.ts +1 -1
  6. package/dist/extraction/grammars.d.ts +20 -0
  7. package/dist/extraction/index.d.ts +1 -0
  8. package/dist/extraction/parse-pool.d.ts +8 -3
  9. package/dist/extraction/sql-query-extractor.d.ts +16 -14
  10. package/dist/extraction/sql-table-scan.d.ts +184 -0
  11. package/dist/extraction/tree-sitter.d.ts +10 -1
  12. package/dist/extraction/vba/call-sweep.d.ts +2 -7
  13. package/dist/extraction/vba/calls.d.ts +24 -4
  14. package/dist/extraction/vba/constants.d.ts +7 -14
  15. package/dist/extraction/vba/context.d.ts +443 -7
  16. package/dist/extraction/vba/controls.d.ts +18 -1
  17. package/dist/extraction/vba/declarations.d.ts +1 -6
  18. package/dist/extraction/vba/dims.d.ts +11 -7
  19. package/dist/extraction/vba/docmd.d.ts +29 -2
  20. package/dist/extraction/vba/enums-consts.d.ts +7 -14
  21. package/dist/extraction/vba/error-channel.d.ts +57 -0
  22. package/dist/extraction/vba/errors.d.ts +64 -0
  23. package/dist/extraction/vba/filesystem-statements.d.ts +23 -0
  24. package/dist/extraction/vba/implements.d.ts +1 -6
  25. package/dist/extraction/vba/labels.d.ts +26 -0
  26. package/dist/extraction/vba/module-vars.d.ts +36 -0
  27. package/dist/extraction/vba/options.d.ts +88 -0
  28. package/dist/extraction/vba/parameters.d.ts +35 -0
  29. package/dist/extraction/vba/procedures.d.ts +1 -9
  30. package/dist/extraction/vba/rules.d.ts +10 -5
  31. package/dist/extraction/vba/runtime-objects.d.ts +59 -0
  32. package/dist/extraction/vba/signature.d.ts +57 -0
  33. package/dist/extraction/vba/sql-wrapper.d.ts +76 -3
  34. package/dist/extraction/vba/text-utils.d.ts +62 -2
  35. package/dist/extraction/vba-extractor.d.ts +18 -1
  36. package/dist/extraction/vba-form-extractor.d.ts +28 -14
  37. package/dist/extraction/vba-preprocess.d.ts +89 -3
  38. package/dist/extraction/vba-source.d.ts +0 -10
  39. package/dist/extraction/vba-test-manifest-extractor.d.ts +0 -6
  40. package/dist/graph/behavior-evidence.d.ts +162 -0
  41. package/dist/index.d.ts +22 -0
  42. package/dist/mcp/daemon-paths.d.ts +6 -0
  43. package/dist/mcp/daemon-registry.d.ts +82 -7
  44. package/dist/mcp/daemon-watchdog.d.ts +12 -0
  45. package/dist/mcp/daemon.d.ts +20 -1
  46. package/dist/mcp/proxy.d.ts +32 -0
  47. package/dist/mcp/server-instructions.d.ts +1 -1
  48. package/dist/mcp/tools.d.ts +12 -0
  49. package/dist/project-config.d.ts +43 -2
  50. package/dist/resolution/index.d.ts +47 -2
  51. package/dist/resolution/name-matcher.d.ts +25 -0
  52. package/dist/resolution/vba-runtime-objects.d.ts +11 -11
  53. package/dist/types.d.ts +13 -5
  54. package/dist/utils/backtrace-helpers.d.ts +14 -2
  55. package/package.json +7 -7
@@ -11,13 +11,33 @@ export declare function scanCallSites(ctx: VbaExtractorContext, line: string, fr
11
11
  * scan line, which makes global `:`/`Else` splitting safe.
12
12
  */
13
13
  export declare function splitSingleLineIfClauses(line: string): string[];
14
+ /**
15
+ * Issue #265: the outcome of `detectStatementCall`.
16
+ *
17
+ * `unambiguous` records whether the *syntax* of the statement can only be a
18
+ * procedure call:
19
+ *
20
+ * - `Call MySub` — the `Call` keyword is only valid on a procedure.
21
+ * - `MySub 1, 2` — a constant cannot take an argument list.
22
+ * - `MySub` — AMBIGUOUS: a bare identifier is equally a `Const` read.
23
+ *
24
+ * The call sweep uses this to pick the unresolved-reference kind: `calls` for
25
+ * the two unambiguous shapes, `unqualified-ident` for the bare read (the
26
+ * bucket the const-first disambiguation rule of issue #108 / FR-3.1 needs).
27
+ */
28
+ export interface StatementCall {
29
+ /** The called procedure name (the leading identifier). */
30
+ name: string;
31
+ /** True when the `Call` keyword or an argument list rules out a Const read. */
32
+ unambiguous: boolean;
33
+ }
14
34
  /**
15
35
  * H1: detect a statement-form Sub call (`MySub`, `MySub arg1, x`,
16
- * `Call MySub arg1`). Returns the called proc name, or null for
17
- * declarations, assignments, comments, keyword lines, and the paren form
18
- * (handled by CALL_RE).
36
+ * `Call MySub arg1`). Returns the called proc name plus its syntactic
37
+ * unambiguity (issue #265), or null for declarations, assignments,
38
+ * comments, keyword lines, and the paren form (handled by CALL_RE).
19
39
  */
20
- export declare function detectStatementCall(line: string): string | null;
40
+ export declare function detectStatementCall(line: string): StatementCall | null;
21
41
  /**
22
42
  * H1: emit a same-file `calls` edge for a statement-form Sub call to the
23
43
  * already-emitted function node named `procName`. Returns `true` when a
@@ -10,8 +10,8 @@ export declare const PROC_RE: RegExp;
10
10
  * Promoted from a local regex in `sweepCallsAndSql` so `sweepEnumsAndConsts`
11
11
  * can walk the same proc boundaries and decide Const scope per line.
12
12
  * The `(?:^|:\s*)` prefix tolerates colon-separated single-line procs
13
- * (`Public Sub X(): ... : End Sub`) so the proc stack pops on the same
14
- * physical line.
13
+ * (`Public Sub X(): ... : End Sub`). Classifiers must test procedure start
14
+ * and end independently because both can occur on the same physical line.
15
15
  */
16
16
  export declare const PROCEDURE_END_RE: RegExp;
17
17
  /**
@@ -32,17 +32,10 @@ export declare const CALL_KEYWORD_BLACKLIST: Set<string>;
32
32
  export declare const VBA_KEYWORDS: Set<string>;
33
33
  export declare function isVbaKeyword(name: string): boolean;
34
34
  /**
35
- * Access runtime objects and singletons. Calls on these receivers are
36
- * real VBA calls but the targets are NOT user-defined modules or
37
- * classes they're Access/DAO/ADO runtime types. Synthesizing a
38
- * `function` node for each would pollute the graph with ~20+ junk
39
- * nodes per real-world file (audit W4, June 2026). Skip synthesis
40
- * for any receiver or member in this set.
41
- *
42
- * Note: `DoCmd.RunSQL`, `DoCmd.OpenForm`, etc. still get SQL/edge
43
- * tracking via the dedicated `SQL_WRAPPERS` regex path (REQ-CODE-8),
44
- * which fires BEFORE this scan and uses its own dispatch — so
45
- * blacklisting DoCmd here doesn't lose the SQL-flow edges.
35
+ * Access runtime objects and singletons whose calls the call-site scans drop
36
+ * outright. Issue #245 collapsed this literal into the canonical
37
+ * `RUNTIME_OBJECT_DEFS` in `./runtime-objects.ts`; it is re-exported here so
38
+ * every existing `from './constants'` import keeps working unchanged.
46
39
  */
47
- export declare const RUNTIME_RECEIVER_BLACKLIST: Set<string>;
40
+ export { RUNTIME_RECEIVER_BLACKLIST } from './runtime-objects';
48
41
  //# sourceMappingURL=constants.d.ts.map
@@ -12,6 +12,8 @@
12
12
  * gates, and the per-scope Const lookup) live here as methods.
13
13
  */
14
14
  import { Node, Edge, ExtractionError, UnresolvedReference } from '../../types';
15
+ import type { CompiledSqlWrappers } from './sql-wrapper';
16
+ import type { CompiledErrorChannel } from './error-channel';
15
17
  export interface ProcInfo {
16
18
  name: string;
17
19
  qualifiedName: string;
@@ -33,6 +35,186 @@ export interface ProcInfo {
33
35
  */
34
36
  arrayParameters?: string[];
35
37
  }
38
+ /**
39
+ * Issue #259: how one procedure handles errors, recorded as
40
+ * `metadata.errorPolicy` on its `function` node.
41
+ *
42
+ * This is the whole of task E2 in `docs/vba-error-handling-plan.md`: the plan
43
+ * deliberately adds NO node kind and NO edge kind for error handling (§4),
44
+ * because 96.5% of the corpus's line labels are the same label (`errores`)
45
+ * doing the same job — one bit of information, which belongs in a field.
46
+ * Everything below is therefore metadata on a node that already exists.
47
+ */
48
+ export interface VbaErrorPolicy {
49
+ /**
50
+ * `'handler'` — the procedure runs at least one `On Error GoTo <label>`.
51
+ * `'resume-next'` — only `On Error Resume Next`; every error is swallowed.
52
+ * `'none'` — no `On Error` statement at all (§3.1's defect class).
53
+ *
54
+ * A `GoTo <label>` that is NOT an `On Error GoTo` never reaches this field:
55
+ * a label nobody targets with `On Error` is control flow, not a handler.
56
+ */
57
+ protection: 'handler' | 'resume-next' | 'none';
58
+ /** The `On Error GoTo` target as written — `'errores'` in ~98% of cases. */
59
+ handlerLabel: string | null;
60
+ /** First line of the handler body: the line AFTER the label definition. */
61
+ handlerStartLine: number | null;
62
+ /** The procedure's terminating `End Sub` / `End Function` / `End Property`. */
63
+ handlerEndLine: number | null;
64
+ /**
65
+ * Issue #260 (task E3): what the handler body does.
66
+ *
67
+ * `'channel'` — writes the error message into `m_Error` / `p_Error` /
68
+ * `g_Error` / `Me.Error` and returns normally, which is how ~71% of this
69
+ * corpus propagates errors. `'display'` — `MsgBox` / `Debug.Print`, i.e.
70
+ * the error surfaces to a human here. `'reraise'` — `Err.Raise`, the only
71
+ * shape that uses VBA's own mechanism to propagate. `'mixed'` — more than
72
+ * one of those. `'unknown'` — a handler with no recognised signal.
73
+ *
74
+ * `null` means the procedure has no handler to describe at all
75
+ * (`protection` is `'resume-next'` or `'none'`), which is deliberately a
76
+ * different answer from `'unknown'`.
77
+ */
78
+ behavior: 'channel' | 'display' | 'reraise' | 'mixed' | 'unknown' | null;
79
+ /** `On Error GoTo <label>` sites; `> 1` means the procedure swaps handlers. */
80
+ handlerCount: number;
81
+ /** An `On Error Resume Next` never closed by `On Error GoTo 0` / `-1`. */
82
+ resumeNextOpen: boolean;
83
+ /**
84
+ * Executable statements in the procedure body. Blank/comment-only lines,
85
+ * declarations, labels, and the procedure declaration/end markers do not
86
+ * contribute; colon-separated statements contribute individually.
87
+ */
88
+ executableStatementCount: number;
89
+ /**
90
+ * An `On Error GoTo <label>` whose `<label>` this procedure never defines —
91
+ * a handler that can never run. Resolved per PROCEDURE, not per module: a
92
+ * label defined in a sibling procedure is out of scope and still dangling.
93
+ * No procedure in the measured corpus has one.
94
+ */
95
+ danglingTarget: string | null;
96
+ }
97
+ /**
98
+ * Issue #260: the three independent things a handler body can do, collected
99
+ * per line and OR-ed over the handler region at the procedure's end.
100
+ *
101
+ * Independent on purpose: `behavior` is `mixed` when more than one of them
102
+ * fired, so a body that both records the error and shows it must not have a
103
+ * winner picked for it by evaluation order. This mirrors the `signals` object
104
+ * in `scripts/vba-coverage-probe.mjs`, which is the instrument the corpus
105
+ * census was measured with.
106
+ */
107
+ export interface VbaErrorHandlerSignals {
108
+ /** A write to a configured error-channel variable (`p_Error = "…"`). */
109
+ channel: boolean;
110
+ /** A call that shows the error to a human (`MsgBox`, `Debug.Print`). */
111
+ display: boolean;
112
+ /** `Err.Raise` — the frame re-throws instead of recording. */
113
+ reraise: boolean;
114
+ }
115
+ /**
116
+ * Issue #259: the mutable accumulator the error-policy classifier keeps while
117
+ * one procedure body is open. Folded into a {@link VbaErrorPolicy} at the
118
+ * procedure's end boundary; never surfaced to consumers.
119
+ */
120
+ export interface VbaErrorPolicyState {
121
+ /** The procedure's declaration line — the `functionNodeByStartLine` key. */
122
+ startLine: number;
123
+ protection: VbaErrorPolicy['protection'];
124
+ /** lowercased `On Error GoTo` target → the label as first written. */
125
+ targets: Map<string, string>;
126
+ /** lowercased line-label definition → the line it is defined on. */
127
+ definedLabels: Map<string, number>;
128
+ handlerCount: number;
129
+ /** Exact executable-statement count accumulated while this body is open. */
130
+ executableStatementCount: number;
131
+ /**
132
+ * The LAST `On Error Resume Next` (`opens: true`) or `On Error GoTo 0|-1`
133
+ * (`opens: false`) seen, by source position. Position-ordered rather than
134
+ * counted so two of them on one colon-separated line resolve in source
135
+ * order regardless of which rule in the table fires first.
136
+ */
137
+ lastScopeEvent: {
138
+ line: number;
139
+ column: number;
140
+ opens: boolean;
141
+ } | null;
142
+ /** lowercased label whose definition opened the handler region. */
143
+ openedTarget: string | null;
144
+ handlerStartLine: number | null;
145
+ /**
146
+ * Issue #260: `ctx.edges.length` / `ctx.unresolvedReferences.length` at the
147
+ * moment this procedure body opened. Everything emitted from inside the
148
+ * body sits at or after these marks, so the end-of-procedure pass that
149
+ * stamps `metadata.inErrorHandler` scans only this procedure's own rows
150
+ * instead of re-walking the whole file once per procedure.
151
+ */
152
+ edgeMark: number;
153
+ refMark: number;
154
+ /**
155
+ * Issue #260: sparse per-line handler signals for THIS procedure body,
156
+ * keyed by 1-based line. Only lines that fired at least one signal get an
157
+ * entry. Collected for the whole body and filtered to the handler region at
158
+ * close, because the region's first line is only known for certain once the
159
+ * body has been fully read (a label defined BEFORE the `On Error GoTo` that
160
+ * targets it is resolved retroactively).
161
+ */
162
+ signalsByLine: Map<number, VbaErrorHandlerSignals>;
163
+ /**
164
+ * Issue #260: signals from the text AFTER a label definition on the label's
165
+ * OWN line, keyed by that line. VBA allows `errores: MsgBox "x"`, and only
166
+ * the trailing statement belongs to the handler — the label itself does
167
+ * not. Kept apart from {@link signalsByLine} (which holds the whole line)
168
+ * so the region's first line contributes only its trailing statement,
169
+ * exactly as the probe's `handlerLines[0] = first.rest` does.
170
+ */
171
+ labelRestSignals: Map<number, VbaErrorHandlerSignals>;
172
+ /**
173
+ * Issue #263 (task E6): every line-label DEFINITION in this body, in source
174
+ * order, with the name exactly as written and its source position.
175
+ *
176
+ * Additive to {@link definedLabels}, which the region resolver reads and
177
+ * which deliberately stores only `key → line`: the `label` node needs the
178
+ * original casing for its `name` and its position for `startColumn`, and
179
+ * duplicating those onto the existing map would change a structure three
180
+ * older code paths already depend on. One entry per DISTINCT label — a
181
+ * repeated definition is illegal VBA, and the first one wins here exactly
182
+ * as it does in `definedLabels`.
183
+ */
184
+ labelDefs: VbaLabelSite[];
185
+ /**
186
+ * Issue #263: every `On Error GoTo <label>` STATEMENT in this body, in
187
+ * source order — not a set of targets. 47 procedures in the reference
188
+ * corpus issue more than one, and each is its own routing decision with its
189
+ * own line, so each emits its own `handles-error` edge.
190
+ *
191
+ * Numeric targets (`On Error GoTo 0` / `-1`, and the VBA line-number form)
192
+ * never reach here: the first two are resets owned by another rule, and a
193
+ * line number is not a label this extractor can ever define a node for.
194
+ */
195
+ onErrorSites: VbaLabelSite[];
196
+ /**
197
+ * Issue #263: every plain `GoTo <label>` jump in this body — an
198
+ * `On Error GoTo` is excluded, since that is a routing decision, not a
199
+ * jump. Emitted as a generic `references` edge tagged `vba-goto`.
200
+ */
201
+ gotoSites: VbaLabelSite[];
202
+ }
203
+ /**
204
+ * Issue #263: one occurrence of a line label — a definition (`errores:`) or a
205
+ * mention (`On Error GoTo errores`, `GoTo salir`) — with the name both
206
+ * lowercased for matching and preserved as written for display.
207
+ */
208
+ export interface VbaLabelSite {
209
+ /** Lowercased name; the key `targets` / `definedLabels` are keyed by. */
210
+ key: string;
211
+ /** The label exactly as written at THIS site. */
212
+ name: string;
213
+ /** 1-based source line. */
214
+ line: number;
215
+ /** 0-based column of the match that produced this site. */
216
+ column: number;
217
+ }
36
218
  /**
37
219
  * Issue #83: the per-concern classifier shape. The single walker in
38
220
  * `vba-extractor.ts` calls `classifyLine(line, index, ctx)` once per
@@ -63,6 +245,52 @@ export declare class VbaExtractorContext {
63
245
  errors: ExtractionError[];
64
246
  unresolvedReferences: UnresolvedReference[];
65
247
  moduleOrClassNode: Node | null;
248
+ /**
249
+ * Issue #251: the module/class name this file's symbols belong to —
250
+ * the resolved `Attribute VB_Name`, or the file basename when the
251
+ * attribute is absent. It is the SAME string the module/class node is
252
+ * later created with (`createModuleOrClassNode`), but it is resolved
253
+ * BEFORE the walk so a classifier can compose a `<Module>.<name>`
254
+ * qualifiedName while the module node itself does not exist yet.
255
+ *
256
+ * `classNamePrefix` right below cannot serve that purpose: it is
257
+ * deliberately `null` for `.bas` modules so procedure qualifiedNames
258
+ * keep their bare-name shape. Module-level variables want the module
259
+ * prefix in BOTH file kinds, so they read this field instead.
260
+ */
261
+ moduleName: string | null;
262
+ /**
263
+ * Issue #251: module-level variables declared in THIS file, keyed by
264
+ * the lowercase variable name. Populated by the dims classifier at the
265
+ * moment it emits the `variable` node, so membership means exactly
266
+ * "this name is a module-level variable of this module and has a node
267
+ * in the graph".
268
+ *
269
+ * This is the ONLY gate the read/write reference scan consults. It is
270
+ * deliberately NOT `localVarTypeMap.get('module')`: that map also holds
271
+ * bookkeeping entries the sweeps write for type-tracking purposes, and
272
+ * scanning identifiers against anything broader than "names we emitted
273
+ * a node for" is how a reference sweep turns into thousands of false
274
+ * positives.
275
+ */
276
+ moduleVariables: Map<string, {
277
+ name: string;
278
+ nodeId: string;
279
+ }>;
280
+ /**
281
+ * Issue #251: for each procedure (keyed by its `startLine` as a string,
282
+ * the same key `currentVarTypeProcKey` uses), the lowercase names that
283
+ * procedure declares itself — its parameters and every `Dim` / `Static`
284
+ * / `Private` declaration in its body.
285
+ *
286
+ * The module-level variable read/write scan consults this to honour the
287
+ * issue #205 scoping rule: a procedure that declares its own `codigo`
288
+ * must not report a read of the module-level `codigo`. `localVarTypeMap`
289
+ * cannot answer that question on its own — its bare-`Dim` path skips the
290
+ * write when an outer declaration of the same name already resolves, and
291
+ * it never sees parameters at all — so both would read as unshadowed.
292
+ */
293
+ procLocalNames: Map<string, Set<string>>;
66
294
  /**
67
295
  * Class-name prefix for `qualifiedName` composition.
68
296
  *
@@ -122,20 +350,58 @@ export declare class VbaExtractorContext {
122
350
  */
123
351
  synthTempVarNodeIds: Set<string>;
124
352
  /**
125
- * Maps `variableName.toLowerCase()` declared type info.
126
- * Built by `sweepDimsAndWithEvents`; consulted by the unified qualified-call
127
- * gate (`shouldProcessQualifiedCall`) so declared project-class locals emit
128
- * edges, declared primitive/external locals stay silent, and undeclared
129
- * receivers remain module-name candidates for the resolver (Fix 2 / Issue #2).
353
+ * Issue #256: external-backend (`IN "<path>"`) node de-dup cache. Same
354
+ * rationale as `synthTempVarNodeIds`: the ids are keyed on the
355
+ * normalized backend path via a synthetic file path, so the SAME
356
+ * `.accdb` referenced from N modules collapses to ONE node.
357
+ */
358
+ synthExternalBackendNodeIds: Set<string>;
359
+ /**
360
+ * Issue #205: `variableName.toLowerCase()` → declared type info,
361
+ * **scoped per procedure**. The outer key is `'module'` for module-
362
+ * level `Dim`s, or the procedure's `startLine` (stringified) for
363
+ * proc-local `Dim`s — mirroring `localConstants` directly above and
364
+ * `ProcInfo.arrayParameters` (`context.ts:42`).
365
+ *
366
+ * The pre-#205 shape was a flat `Map<string, …>` keyed on the bare
367
+ * name, so the last `Dim` in a file silently won for the whole file
368
+ * and qualified calls (`item.Method`) resolved to whichever
369
+ * procedure declared `item` most recently — even when the call site
370
+ * was in a different procedure that had its OWN `Dim item As
371
+ * <OtherType>`. Worse, a module-level `Dim` was overwritten by the
372
+ * first proc-local `Dim` of the same name and never re-asserted, so
373
+ * a different procedure without its own local `Dim` would resolve
374
+ * `item.Method` to the wrong class with no diagnostic.
375
+ *
376
+ * Built by the dims classifier (which tracks the current scope via
377
+ * `currentVarTypeProcKey`); consulted by the unified qualified-call
378
+ * gate (`shouldProcessQualifiedCall`, `isLocalProjectClassVar`,
379
+ * `resolveReceiverType`) so declared project-class locals emit
380
+ * edges, declared primitive/external locals stay silent, and
381
+ * undeclared receivers remain module-name candidates for the
382
+ * resolver (Fix 2 / Issue #2). The proc bucket is consulted first
383
+ * and the `'module'` bucket is the fallback — same two-tier lookup
384
+ * `resolveLocalConst` performs.
130
385
  */
131
- localVarTypeMap: Map<string, {
386
+ localVarTypeMap: Map<'module' | string, Map<string, {
132
387
  outer: string;
133
388
  qualified: boolean;
134
389
  withEvents?: boolean;
135
390
  variableName?: string;
136
391
  assignedWithSet?: boolean;
137
392
  isArray?: boolean;
138
- }>;
393
+ }>>;
394
+ /**
395
+ * Issue #205: the current scope the dims classifier writes to. Set
396
+ * to `'module'` when no procedure is open, otherwise the top of the
397
+ * dims classifier's per-instance proc stack (the startLine of the
398
+ * procedure whose `End Sub`/`End Function`/`End Property` has not
399
+ * been seen yet). The dims classifier updates this on every
400
+ * `PROC_RE` / `PROCEDURE_END_RE` boundary so the bucket the call
401
+ * sweep later consults (via the per-proc-then-module lookup) lines
402
+ * up with the procedure the call site is inside.
403
+ */
404
+ currentVarTypeProcKey: 'module' | string;
139
405
  /**
140
406
  * Issue #52: Const resolution buckets, scoped per procedure. Key is
141
407
  * `'module'` for module-level Consts, or the procedure's `startLine`
@@ -185,6 +451,17 @@ export declare class VbaExtractorContext {
185
451
  id: string;
186
452
  name: string;
187
453
  } | null;
454
+ /**
455
+ * Issue #259: per-extraction state for the error-policy classifier
456
+ * (`src/extraction/vba/errors.ts`). Non-null exactly while a procedure
457
+ * body is open; the classifier folds it into the `errorPolicy` metadata
458
+ * object on that procedure's `function` node when the body closes.
459
+ *
460
+ * Same rationale as `vbaEnumBlock` / `vbaDeclTypeBlock`: the declarative
461
+ * RULES table's `emit` functions need somewhere to accumulate inter-line
462
+ * state, and `ctx` is the only thing they are handed.
463
+ */
464
+ vbaErrorPolicy: VbaErrorPolicyState | null;
188
465
  /**
189
466
  * Issue #153: per-extraction state for the calls/SQL classifier's
190
467
  * `With <receiver> ... End With` block tracking. The with-receiver
@@ -237,6 +514,39 @@ export declare class VbaExtractorContext {
237
514
  * pays no cost.
238
515
  */
239
516
  classifierInvokeCounts: Map<string, number> | null;
517
+ /**
518
+ * Issue #244: the SQL execution-site matcher, compiled ONCE per extractor
519
+ * instance from `codegraph.json` → `vba.sqlWrappers` and parked here.
520
+ * `scanSqlInLine` runs on every line of every VBA file, so the two
521
+ * stateful `/g` RegExps it holds must outlive the line loop — building
522
+ * them per line (the pre-#244 shape) burned a RegExp compile per line for
523
+ * no behavioural gain.
524
+ *
525
+ * `null` means "nobody supplied options" (tests, out-of-repo callers);
526
+ * `sql-wrapper.ts` then falls back to its module-level default set, which
527
+ * is compiled once as well. The type is imported TYPE-ONLY on purpose:
528
+ * `sql-wrapper.ts` imports this module, so a value import here would close
529
+ * a runtime require cycle.
530
+ */
531
+ sqlWrappers: CompiledSqlWrappers | null;
532
+ /**
533
+ * Issue #261: the error channel — the module-level variable names this
534
+ * project propagates error messages through — compiled ONCE per extractor
535
+ * instance from `codegraph.json` → `vba.errorChannel` and parked here.
536
+ *
537
+ * Two hot paths read it: `module-vars.ts` tests every identifier that is
538
+ * already a module-level variable of this file (flagging the reference
539
+ * `errorChannel: true`), and `errors.ts` tests every statement of every
540
+ * procedure body for a channel WRITE. Neither may rebuild the `Set` and the
541
+ * RegExps it holds inside the line loop.
542
+ *
543
+ * `null` means "nobody supplied options" (tests, out-of-repo callers);
544
+ * `error-channel.ts` then falls back to its memoised default channel, which
545
+ * is the same four names. The type is imported TYPE-ONLY on purpose, exactly
546
+ * as {@link sqlWrappers} is: `error-channel.ts` is a leaf and a value import
547
+ * here would be the start of a runtime cycle.
548
+ */
549
+ errorChannel: CompiledErrorChannel | null;
240
550
  constructor(filePath: string);
241
551
  /**
242
552
  * Issue #156: ensure the timings Maps exist. Called once per
@@ -244,6 +554,23 @@ export declare class VbaExtractorContext {
244
554
  * No-op when already allocated.
245
555
  */
246
556
  ensureTimings(): void;
557
+ /**
558
+ * Issue #260: is `lineNum` inside the error handler of the procedure that
559
+ * is open right now?
560
+ *
561
+ * The lower bound is the open procedure's `handlerStartLine` — the line
562
+ * AFTER the handler label, which is the same boundary published on the
563
+ * node's `errorPolicy`. The upper bound is implicit and is the reason this
564
+ * reads live state rather than a stored range: `vbaErrorPolicy` is cleared
565
+ * at the procedure's `End Sub` / `End Function` / `End Property`, so the
566
+ * next procedure starts with a fresh accumulator and can never inherit the
567
+ * previous one's region. That is the off-by-one guard, by construction.
568
+ *
569
+ * Returns `false` outside any procedure, and inside a procedure whose
570
+ * handler region has not opened yet (no `On Error GoTo`, or a label nobody
571
+ * targets — which is control flow, not a handler).
572
+ */
573
+ inErrorHandler(lineNum: number): boolean;
247
574
  /**
248
575
  * Issue #156: add `ms` to the stage named `name`. No-op when
249
576
  * `timings` is null (default path).
@@ -263,6 +590,14 @@ export declare class VbaExtractorContext {
263
590
  * Qualified types (e.g. `DAO.Recordset`) and primitives (`String`, `Long`)
264
591
  * return false so runtime/DAO calls are suppressed. Brackets are stripped
265
592
  * from the lookup key defensively (Issue #54).
593
+ *
594
+ * Issue #205: the lookup is two-tier — the current procedure's bucket is
595
+ * consulted first, then the `'module'` bucket — so a proc-local
596
+ * `Dim x As Producto` in `Sub Foo` does NOT make `x` a project class
597
+ * in `Sub Bar` (where `Dim x As Variant` is the only declaration, or
598
+ * `x` is undeclared). Without the per-proc scoping, the last `Dim` in
599
+ * the file would silently win and the wrong class would propagate
600
+ * into `x.Method` qualified-call stub edges.
266
601
  */
267
602
  isLocalProjectClassVar(receiverName: string): boolean;
268
603
  /**
@@ -271,6 +606,10 @@ export declare class VbaExtractorContext {
271
606
  * project-class locals are processed after type resolution, declared
272
607
  * primitive/external locals are silent, and undeclared receivers remain
273
608
  * candidate module names.
609
+ *
610
+ * Issue #205: the underlying `localVarTypeMap` lookup is two-tier
611
+ * (current proc → module) so the eligibility check inherits the
612
+ * same scoping discipline.
274
613
  */
275
614
  shouldProcessQualifiedCall(receiverName: string): boolean;
276
615
  /**
@@ -281,6 +620,9 @@ export declare class VbaExtractorContext {
281
620
  * → `'NCOperaciones'`) so the stub matches the real `.cls` method's
282
621
  * `${className}.${proc}` shape. Otherwise returns `receiverName` unchanged
283
622
  * (the `.bas`-qualified module call case).
623
+ *
624
+ * Issue #205: lookup is two-tier (current proc → module) so the
625
+ * resolved class name matches the procedure the call site is inside.
284
626
  */
285
627
  resolveReceiverType(receiverName: string): string;
286
628
  findOrCreateFunctionNodeId(proc: ProcInfo): string;
@@ -306,6 +648,34 @@ export declare class VbaExtractorContext {
306
648
  * gate is disabled or no event exceeds the cap — useful for tests).
307
649
  */
308
650
  applyRaiseFanoutGate(maxFanout: number | undefined): number;
651
+ /**
652
+ * Create — once per file, per name — the synthetic `class` node that stands
653
+ * in for a type this file names but does not declare, and return its id.
654
+ *
655
+ * The id is keyed on (filePath, 'class', name) WITHOUT a line number so the
656
+ * same type named on N lines produces ONE node, and
657
+ * `resolveVbaReferenceStubs` can later repoint every edge pointing at it onto
658
+ * the real declaration and delete the stub.
659
+ *
660
+ * Factored out of `emitReference` (issue #257) so a caller that needs a
661
+ * different EDGE kind onto the same stub — `emitTypeOf` below — cannot drift
662
+ * from the id formula the resolver depends on.
663
+ */
664
+ private ensureSynthTypeNode;
665
+ /**
666
+ * Issue #257: emit a `type_of` edge from an arbitrary node — a `parameter`,
667
+ * today — to the synthetic node standing in for its declared type.
668
+ *
669
+ * Deliberately NOT `emitReference`: that helper always sources the edge from
670
+ * the file's module/class node, which is the right answer for "this module
671
+ * mentions type X" but the wrong one for "this parameter IS an X". Both
672
+ * share the stub, so a parameter typed `As Cliente` and a `Dim c As Cliente`
673
+ * in the same file converge on ONE node and `resolveVbaReferenceStubs`
674
+ * repoints their edges together.
675
+ *
676
+ * The caller owns the primitive gate — see `emitParameterNodes`.
677
+ */
678
+ emitTypeOf(sourceNodeId: string, targetName: string, lineNum: number, column: number, synthesizedBy: string): void;
309
679
  /**
310
680
  * Emit a `references` edge from the file's module/class node to a synthetic
311
681
  * node named `targetName`. Used by Dim, WithEvents, Set-New, and SQL sweeps.
@@ -331,6 +701,20 @@ export declare class VbaExtractorContext {
331
701
  * (rarely useful) but not accidentally drop the stamp.
332
702
  */
333
703
  emitReference(targetName: string, lineNum: number, column: number, synthesizedBy: string, access?: 'read' | 'write', extras?: Record<string, unknown>): void;
704
+ /**
705
+ * Issue #256: emit a `references` edge from the file's module/class node
706
+ * to the external database file an Access `IN "<path>"` clause points at.
707
+ *
708
+ * The target is a `file`-kind node built by `buildExternalBackendNode`,
709
+ * keyed on the NORMALIZED path, so the same backend named from several
710
+ * modules — or from a saved query — converges on ONE node. The edge
711
+ * carries only `synthesizedBy`; the `external` / `backendPath` facts
712
+ * live on the node, which is the thing they describe.
713
+ *
714
+ * `backendPath` must already be normalized (the caller gets it from
715
+ * `scanSqlExternalBackends`). An empty path is a no-op.
716
+ */
717
+ emitExternalBackendReference(backendPath: string, lineNum: number, column: number): void;
334
718
  /**
335
719
  * Issue #52: shared lookup helper for `scanDoCmdOpenCalls` and
336
720
  * `scanDoCmdOpenQuery`. The current scope is the procedure whose
@@ -344,5 +728,57 @@ export declare class VbaExtractorContext {
344
728
  * value was written to (mostly useful for tests).
345
729
  */
346
730
  setLocalConstInScope(scopeKey: 'module' | string, name: string, value: string): Map<string, string>;
731
+ /**
732
+ * Issue #205: shared lookup helper for the procedure-scoped
733
+ * `localVarTypeMap`. The current scope is the procedure whose
734
+ * `startLine` is on top of the dims classifier's proc stack, kept in
735
+ * sync via `currentVarTypeProcKey` (or `'module'` when no procedure
736
+ * is open). Per-proc bucket first; the `'module'` bucket is the
737
+ * fallback — mirrors `resolveLocalConst` and the `arrayParameters`
738
+ * rationale spelled out at `calls.ts:86-90` ("a same-named
739
+ * parameter on a different procedure cannot suppress a genuine
740
+ * missing-call elsewhere in the file").
741
+ *
742
+ * `name` is normalized to lowercase so the dim sweep's
743
+ * `varName.toLowerCase()` key matches the call sweep's
744
+ * `receiverName.toLowerCase()` key.
745
+ */
746
+ lookupLocalVarType(name: string): {
747
+ outer: string;
748
+ qualified: boolean;
749
+ withEvents?: boolean;
750
+ variableName?: string;
751
+ assignedWithSet?: boolean;
752
+ isArray?: boolean;
753
+ } | undefined;
754
+ /**
755
+ * Issue #205: shared writer for the procedure-scoped
756
+ * `localVarTypeMap`. `scopeKey` is `'module'` for module-level
757
+ * `Dim`s, or the procedure's `startLine` (stringified) for
758
+ * proc-local `Dim`s — the same shape the dims classifier uses for
759
+ * `currentVarTypeProcKey`. Creates the bucket lazily. Returns the
760
+ * bucket the entry was written to (mostly useful for tests).
761
+ */
762
+ /**
763
+ * Issue #251: record `name` as declared by the procedure `procKey`
764
+ * (`'module'` is accepted and simply ignored — a module-level
765
+ * declaration shadows nothing). Creates the bucket lazily.
766
+ */
767
+ declareProcLocalName(procKey: 'module' | string, name: string): void;
768
+ setLocalVarTypeInScope(scopeKey: 'module' | string, name: string, entry: {
769
+ outer: string;
770
+ qualified: boolean;
771
+ withEvents?: boolean;
772
+ variableName?: string;
773
+ assignedWithSet?: boolean;
774
+ isArray?: boolean;
775
+ }): Map<string, {
776
+ outer: string;
777
+ qualified: boolean;
778
+ withEvents?: boolean;
779
+ variableName?: string;
780
+ assignedWithSet?: boolean;
781
+ isArray?: boolean;
782
+ }>;
347
783
  }
348
784
  //# sourceMappingURL=context.d.ts.map
@@ -5,6 +5,23 @@
5
5
  * node) the resolver later binds to the form's controls.
6
6
  */
7
7
  import { VbaExtractorContext, ProcInfo } from './context';
8
+ /**
9
+ * Issue #211: shared direct-assignment predicate. The same-line rule
10
+ * the third branch (`control` for non-builtin Me.<Ctl>) already uses is
11
+ * the right shape — `before` must be empty (or whitespace) AND `after`
12
+ * must start with `=` — and lifts cleanly into the `builtIn` and bang
13
+ * branches too. Returning `true` means the match IS the LHS of an
14
+ * assignment (`Me.X = ...`), so callers should tag it `*-set`. Any
15
+ * other shape (e.g. `If Me.X = ...`, `MsgBox Me.X`, `x = Me.X`) is a
16
+ * read and must tag `*-get`. The function is intentionally narrow; a
17
+ * cross-line assignment is out of scope (matches the prior comment).
18
+ *
19
+ * Issue #251: exported so the module-level variable sweep
20
+ * (`module-vars.ts`) reads `gblConn = Nothing` as a write and
21
+ * `x = gblConn` as a read through the SAME predicate. There must only
22
+ * ever be one direct-assignment rule in the VBA extractor.
23
+ */
24
+ export declare function isDirectAssignment(before: string, after: string): boolean;
8
25
  /**
9
26
  * Hueco 1: scan a line for `Me.<ControlName>` / `Me!<ControlName>`
10
27
  * patterns and emit one UnresolvedReference per occurrence, tagged
@@ -37,5 +54,5 @@ export declare function scanMeControlReferences(ctx: VbaExtractorContext, line:
37
54
  * (`Forms!FormX!Ctl = value`) is rare; round-3 emits `'bang-get'`
38
55
  * uniformly and the resolvers do not care about access direction here.
39
56
  */
40
- export declare function scanFormsBang(ctx: VbaExtractorContext, line: string, from: ProcInfo, lineNum: number): void;
57
+ export declare function scanFormsBang(ctx: VbaExtractorContext, line: string, maskedLine: string, from: ProcInfo, lineNum: number): void;
41
58
  //# sourceMappingURL=controls.d.ts.map
@@ -1,4 +1,4 @@
1
- import { VbaExtractorContext, VbaClassifier } from './context';
1
+ import { VbaClassifier } from './context';
2
2
  import { VbaExtractionRule } from './rules';
3
3
  /**
4
4
  * Issue #153: the declarative rule table for the events/types/declares
@@ -40,9 +40,4 @@ export declare const RULES: readonly VbaExtractionRule<unknown>[];
40
40
  * }
41
41
  */
42
42
  export declare function createEventsTypesDeclaresClassifier(): VbaClassifier;
43
- /**
44
- * Backward-compat wrapper (see procedures.ts). Returns the classifier's
45
- * `count` so the orchestrator can decide `hasAnySymbols`.
46
- */
47
- export declare function sweepEventsTypesAndDeclares(ctx: VbaExtractorContext, src: string): number;
48
43
  //# sourceMappingURL=declarations.d.ts.map