@aroman22/codegraph-vba 1.15.0 → 1.16.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.
- package/dist/bin/daemon-release.d.ts +7 -0
- package/dist/db/queries.d.ts +30 -0
- package/dist/extraction/access-erd-extractor.d.ts +57 -0
- package/dist/extraction/extraction-version.d.ts +1 -1
- package/dist/extraction/grammars.d.ts +20 -0
- package/dist/extraction/index.d.ts +1 -0
- package/dist/extraction/parse-pool.d.ts +8 -3
- package/dist/extraction/sql-query-extractor.d.ts +16 -14
- package/dist/extraction/sql-table-scan.d.ts +184 -0
- package/dist/extraction/tree-sitter.d.ts +10 -1
- package/dist/extraction/vba/call-sweep.d.ts +2 -7
- package/dist/extraction/vba/calls.d.ts +24 -4
- package/dist/extraction/vba/constants.d.ts +7 -14
- package/dist/extraction/vba/context.d.ts +443 -7
- package/dist/extraction/vba/controls.d.ts +18 -1
- package/dist/extraction/vba/declarations.d.ts +1 -6
- package/dist/extraction/vba/dims.d.ts +11 -7
- package/dist/extraction/vba/docmd.d.ts +29 -2
- package/dist/extraction/vba/enums-consts.d.ts +7 -14
- package/dist/extraction/vba/error-channel.d.ts +57 -0
- package/dist/extraction/vba/errors.d.ts +64 -0
- package/dist/extraction/vba/filesystem-statements.d.ts +23 -0
- package/dist/extraction/vba/implements.d.ts +1 -6
- package/dist/extraction/vba/labels.d.ts +26 -0
- package/dist/extraction/vba/module-vars.d.ts +36 -0
- package/dist/extraction/vba/options.d.ts +88 -0
- package/dist/extraction/vba/parameters.d.ts +35 -0
- package/dist/extraction/vba/procedures.d.ts +1 -9
- package/dist/extraction/vba/rules.d.ts +10 -5
- package/dist/extraction/vba/runtime-objects.d.ts +59 -0
- package/dist/extraction/vba/signature.d.ts +57 -0
- package/dist/extraction/vba/sql-wrapper.d.ts +76 -3
- package/dist/extraction/vba/text-utils.d.ts +62 -2
- package/dist/extraction/vba-extractor.d.ts +18 -1
- package/dist/extraction/vba-form-extractor.d.ts +28 -14
- package/dist/extraction/vba-preprocess.d.ts +89 -3
- package/dist/extraction/vba-source.d.ts +0 -10
- package/dist/extraction/vba-test-manifest-extractor.d.ts +0 -6
- package/dist/mcp/daemon-paths.d.ts +6 -0
- package/dist/mcp/daemon-registry.d.ts +82 -7
- package/dist/mcp/daemon-watchdog.d.ts +12 -0
- package/dist/mcp/daemon.d.ts +20 -1
- package/dist/mcp/proxy.d.ts +32 -0
- package/dist/project-config.d.ts +43 -2
- package/dist/resolution/index.d.ts +47 -2
- package/dist/resolution/name-matcher.d.ts +25 -0
- package/dist/resolution/vba-runtime-objects.d.ts +11 -11
- package/dist/types.d.ts +13 -5
- package/package.json +7 -7
|
@@ -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
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
|
|
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 {
|
|
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
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { VbaClassifier } from './context';
|
|
2
2
|
import { VbaExtractionRule } from './rules';
|
|
3
3
|
/**
|
|
4
4
|
* Issue #153: the declarative rule table for the Dim / WithEvents
|
|
@@ -34,12 +34,16 @@ export declare const RULES: readonly VbaExtractionRule<unknown>[];
|
|
|
34
34
|
* rules are independent: `dim-decl` handles typed declarations
|
|
35
35
|
* (REJECTED if the line is a `WithEvents` because the prefix
|
|
36
36
|
* negative-lookahead excludes `WithEvents`), `withevents-decl`
|
|
37
|
-
* handles WithEvents.
|
|
37
|
+
* handles WithEvents.
|
|
38
|
+
*
|
|
39
|
+
* Issue #205: the classifier maintains a closure-local proc stack
|
|
40
|
+
* (parallel to the calls-sweep's `ctx.procStack` in
|
|
41
|
+
* `call-sweep.ts:213`) and writes the top of that stack into
|
|
42
|
+
* `ctx.currentVarTypeProcKey` so `localVarTypeMap` writes are scoped
|
|
43
|
+
* to the procedure whose body the `Dim` is inside (or `'module'`
|
|
44
|
+
* when no procedure is open). The two stacks track the same
|
|
45
|
+
* `PROC_RE` / `PROCEDURE_END_RE` boundaries so they stay in sync at
|
|
46
|
+
* every line.
|
|
38
47
|
*/
|
|
39
48
|
export declare function createDimsClassifier(): VbaClassifier;
|
|
40
|
-
/**
|
|
41
|
-
* Backward-compat wrapper (see procedures.ts). Returns the classifier's
|
|
42
|
-
* `count` so the orchestrator can decide `hasAnySymbols`.
|
|
43
|
-
*/
|
|
44
|
-
export declare function sweepDimsAndWithEvents(ctx: VbaExtractorContext, src: string): number;
|
|
45
49
|
//# sourceMappingURL=dims.d.ts.map
|
|
@@ -5,12 +5,39 @@ import { VbaExtractorContext, ProcInfo } from './context';
|
|
|
5
5
|
* a cached stub node (form-layout / report-layout) and an
|
|
6
6
|
* `opens-form` / `opens-report` heuristic edge from the calling Sub.
|
|
7
7
|
*/
|
|
8
|
-
export declare function scanDoCmdOpenCalls(ctx: VbaExtractorContext, line: string, caller: ProcInfo, lineNum: number): void;
|
|
8
|
+
export declare function scanDoCmdOpenCalls(ctx: VbaExtractorContext, line: string, maskedLine: string, caller: ProcInfo, lineNum: number): void;
|
|
9
9
|
/**
|
|
10
10
|
* Issue #48: scan one line of VBA source for `DoCmd.OpenQuery "X"` calls.
|
|
11
11
|
* Each match emits ONE `UnresolvedReference` (NOT a stub + edge) so the
|
|
12
12
|
* resolver binds to the REAL `query` node that `SqlQueryExtractor`
|
|
13
13
|
* produces for `queries/<Name>.sql`, tagged `synthesizedBy: 'vba-opens-query'`.
|
|
14
14
|
*/
|
|
15
|
-
export declare function scanDoCmdOpenQuery(ctx: VbaExtractorContext, line: string, caller: ProcInfo, lineNum: number): void;
|
|
15
|
+
export declare function scanDoCmdOpenQuery(ctx: VbaExtractorContext, line: string, maskedLine: string, caller: ProcInfo, lineNum: number): void;
|
|
16
|
+
/**
|
|
17
|
+
* Issue #246 (task T4): scan one line of VBA source for
|
|
18
|
+
* `DoCmd.Close acForm|acReport, "<Name>"`.
|
|
19
|
+
*
|
|
20
|
+
* Each match emits ONE `references` edge -- not a new edge kind -- from the
|
|
21
|
+
* calling procedure to the very same `form-layout` / `report-layout` stub
|
|
22
|
+
* that `opens-form` / `opens-report` already point at, by reusing
|
|
23
|
+
* `resolveOpensStubId`'s cache. A form that is both opened and closed
|
|
24
|
+
* therefore ends up with ONE node carrying two distinct edges.
|
|
25
|
+
*
|
|
26
|
+
* The edge carries `synthesizedBy: 'vba-closes-form'` for both object types
|
|
27
|
+
* (one tag for the whole verb keeps every close edge queryable as a set) and
|
|
28
|
+
* `targetFormName` as its single name key, for the same reason. If a
|
|
29
|
+
* first-class `closes-form` edge kind is ever wanted, that tag is the seam.
|
|
30
|
+
*/
|
|
31
|
+
export declare function scanDoCmdCloseCalls(ctx: VbaExtractorContext, line: string, maskedLine: string, caller: ProcInfo, lineNum: number): void;
|
|
32
|
+
/**
|
|
33
|
+
* Issue #254: scan one line of VBA source for every `DoCmd` verb in
|
|
34
|
+
* `DOCMD_OBJECT_DISPATCH`. Each match whose object argument resolves to a
|
|
35
|
+
* static name emits ONE `UnresolvedReference` — no node, ever.
|
|
36
|
+
*
|
|
37
|
+
* `maskedLine` has string CONTENT blanked out, so the `docmd` prefix check
|
|
38
|
+
* rejects a verb name that only appears inside a string literal. The object
|
|
39
|
+
* name itself lives inside a literal, which is why the split runs on the
|
|
40
|
+
* original `line`.
|
|
41
|
+
*/
|
|
42
|
+
export declare function scanDoCmdObjectCalls(ctx: VbaExtractorContext, line: string, maskedLine: string, caller: ProcInfo, lineNum: number): void;
|
|
16
43
|
//# sourceMappingURL=docmd.d.ts.map
|