@aroman22/codegraph-vba-darwin-arm64 1.5.1 → 1.6.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/bin/codegraph +5 -0
- package/lib/dist/bin/codegraph.d.ts +1 -1
- package/lib/dist/bin/codegraph.d.ts.map +1 -1
- package/lib/dist/bin/codegraph.js +307 -81
- package/lib/dist/bin/codegraph.js.map +1 -1
- package/lib/dist/bin/command-supervision.d.ts +38 -1
- package/lib/dist/bin/command-supervision.d.ts.map +1 -1
- package/lib/dist/bin/command-supervision.js +22 -3
- package/lib/dist/bin/command-supervision.js.map +1 -1
- package/lib/dist/db/index.d.ts +84 -5
- package/lib/dist/db/index.d.ts.map +1 -1
- package/lib/dist/db/index.js +209 -12
- package/lib/dist/db/index.js.map +1 -1
- package/lib/dist/db/migrations.d.ts +1 -1
- package/lib/dist/db/migrations.d.ts.map +1 -1
- package/lib/dist/db/migrations.js +80 -3
- package/lib/dist/db/migrations.js.map +1 -1
- package/lib/dist/db/queries.d.ts +127 -4
- package/lib/dist/db/queries.d.ts.map +1 -1
- package/lib/dist/db/queries.js +317 -7
- package/lib/dist/db/queries.js.map +1 -1
- package/lib/dist/db/schema.sql +43 -1
- package/lib/dist/db/wal-valve.d.ts +106 -0
- package/lib/dist/db/wal-valve.d.ts.map +1 -0
- package/lib/dist/db/wal-valve.js +208 -0
- package/lib/dist/db/wal-valve.js.map +1 -0
- package/lib/dist/directory.d.ts +9 -5
- package/lib/dist/directory.d.ts.map +1 -1
- package/lib/dist/directory.js +210 -19
- package/lib/dist/directory.js.map +1 -1
- package/lib/dist/extraction/cfml-extractor.d.ts +107 -0
- package/lib/dist/extraction/cfml-extractor.d.ts.map +1 -0
- package/lib/dist/extraction/cfml-extractor.js +494 -0
- package/lib/dist/extraction/cfml-extractor.js.map +1 -0
- package/lib/dist/extraction/grammars.d.ts +25 -1
- package/lib/dist/extraction/grammars.d.ts.map +1 -1
- package/lib/dist/extraction/grammars.js +177 -23
- package/lib/dist/extraction/grammars.js.map +1 -1
- package/lib/dist/extraction/index.d.ts +47 -2
- package/lib/dist/extraction/index.d.ts.map +1 -1
- package/lib/dist/extraction/index.js +568 -51
- package/lib/dist/extraction/index.js.map +1 -1
- package/lib/dist/extraction/languages/arkts.d.ts +3 -0
- package/lib/dist/extraction/languages/arkts.d.ts.map +1 -0
- package/lib/dist/extraction/languages/arkts.js +127 -0
- package/lib/dist/extraction/languages/arkts.js.map +1 -0
- package/lib/dist/extraction/languages/c-cpp.d.ts +98 -0
- package/lib/dist/extraction/languages/c-cpp.d.ts.map +1 -1
- package/lib/dist/extraction/languages/c-cpp.js +563 -1
- package/lib/dist/extraction/languages/c-cpp.js.map +1 -1
- package/lib/dist/extraction/languages/cfquery.d.ts +12 -0
- package/lib/dist/extraction/languages/cfquery.d.ts.map +1 -0
- package/lib/dist/extraction/languages/cfquery.js +28 -0
- package/lib/dist/extraction/languages/cfquery.js.map +1 -0
- package/lib/dist/extraction/languages/cfscript.d.ts +3 -0
- package/lib/dist/extraction/languages/cfscript.d.ts.map +1 -0
- package/lib/dist/extraction/languages/cfscript.js +73 -0
- package/lib/dist/extraction/languages/cfscript.js.map +1 -0
- package/lib/dist/extraction/languages/cobol.d.ts +33 -0
- package/lib/dist/extraction/languages/cobol.d.ts.map +1 -0
- package/lib/dist/extraction/languages/cobol.js +499 -0
- package/lib/dist/extraction/languages/cobol.js.map +1 -0
- package/lib/dist/extraction/languages/erlang.d.ts +3 -0
- package/lib/dist/extraction/languages/erlang.d.ts.map +1 -0
- package/lib/dist/extraction/languages/erlang.js +350 -0
- package/lib/dist/extraction/languages/erlang.js.map +1 -0
- package/lib/dist/extraction/languages/index.d.ts.map +1 -1
- package/lib/dist/extraction/languages/index.js +18 -0
- package/lib/dist/extraction/languages/index.js.map +1 -1
- package/lib/dist/extraction/languages/nix.d.ts +3 -0
- package/lib/dist/extraction/languages/nix.d.ts.map +1 -0
- package/lib/dist/extraction/languages/nix.js +294 -0
- package/lib/dist/extraction/languages/nix.js.map +1 -0
- package/lib/dist/extraction/languages/solidity.d.ts +3 -0
- package/lib/dist/extraction/languages/solidity.d.ts.map +1 -0
- package/lib/dist/extraction/languages/solidity.js +293 -0
- package/lib/dist/extraction/languages/solidity.js.map +1 -0
- package/lib/dist/extraction/languages/terraform.d.ts +3 -0
- package/lib/dist/extraction/languages/terraform.d.ts.map +1 -0
- package/lib/dist/extraction/languages/terraform.js +641 -0
- package/lib/dist/extraction/languages/terraform.js.map +1 -0
- package/lib/dist/extraction/languages/vbnet.d.ts +11 -0
- package/lib/dist/extraction/languages/vbnet.d.ts.map +1 -0
- package/lib/dist/extraction/languages/vbnet.js +141 -0
- package/lib/dist/extraction/languages/vbnet.js.map +1 -0
- package/lib/dist/extraction/mybatis-extractor.d.ts +30 -10
- package/lib/dist/extraction/mybatis-extractor.d.ts.map +1 -1
- package/lib/dist/extraction/mybatis-extractor.js +140 -38
- package/lib/dist/extraction/mybatis-extractor.js.map +1 -1
- package/lib/dist/extraction/parse-pool.d.ts +28 -1
- package/lib/dist/extraction/parse-pool.d.ts.map +1 -1
- package/lib/dist/extraction/parse-pool.js +76 -7
- package/lib/dist/extraction/parse-pool.js.map +1 -1
- package/lib/dist/extraction/parse-worker.js +11 -4
- package/lib/dist/extraction/parse-worker.js.map +1 -1
- package/lib/dist/extraction/tree-sitter-helpers.d.ts.map +1 -1
- package/lib/dist/extraction/tree-sitter-helpers.js +1 -0
- package/lib/dist/extraction/tree-sitter-helpers.js.map +1 -1
- package/lib/dist/extraction/tree-sitter-types.d.ts +20 -1
- package/lib/dist/extraction/tree-sitter-types.d.ts.map +1 -1
- package/lib/dist/extraction/tree-sitter.d.ts +60 -1
- package/lib/dist/extraction/tree-sitter.d.ts.map +1 -1
- package/lib/dist/extraction/tree-sitter.js +905 -20
- package/lib/dist/extraction/tree-sitter.js.map +1 -1
- package/lib/dist/extraction/vba/call-sweep.d.ts +3 -0
- package/lib/dist/extraction/vba/call-sweep.d.ts.map +1 -0
- package/lib/dist/extraction/vba/call-sweep.js +206 -0
- package/lib/dist/extraction/vba/call-sweep.js.map +1 -0
- package/lib/dist/extraction/vba/calls.d.ts +55 -0
- package/lib/dist/extraction/vba/calls.d.ts.map +1 -0
- package/lib/dist/extraction/vba/calls.js +439 -0
- package/lib/dist/extraction/vba/calls.js.map +1 -0
- package/lib/dist/extraction/vba/constants.d.ts +42 -0
- package/lib/dist/extraction/vba/constants.d.ts.map +1 -0
- package/lib/dist/extraction/vba/constants.js +112 -0
- package/lib/dist/extraction/vba/constants.js.map +1 -0
- package/lib/dist/extraction/vba/context.d.ts +175 -0
- package/lib/dist/extraction/vba/context.d.ts.map +1 -0
- package/lib/dist/extraction/vba/context.js +268 -0
- package/lib/dist/extraction/vba/context.js.map +1 -0
- package/lib/dist/extraction/vba/controls.d.ts +24 -0
- package/lib/dist/extraction/vba/controls.d.ts.map +1 -0
- package/lib/dist/extraction/vba/controls.js +89 -0
- package/lib/dist/extraction/vba/controls.js.map +1 -0
- package/lib/dist/extraction/vba/declarations.d.ts +3 -0
- package/lib/dist/extraction/vba/declarations.d.ts.map +1 -0
- package/lib/dist/extraction/vba/declarations.js +154 -0
- package/lib/dist/extraction/vba/declarations.js.map +1 -0
- package/lib/dist/extraction/vba/dims.d.ts +3 -0
- package/lib/dist/extraction/vba/dims.d.ts.map +1 -0
- package/lib/dist/extraction/vba/dims.js +186 -0
- package/lib/dist/extraction/vba/dims.js.map +1 -0
- package/lib/dist/extraction/vba/docmd.d.ts +16 -0
- package/lib/dist/extraction/vba/docmd.d.ts.map +1 -0
- package/lib/dist/extraction/vba/docmd.js +179 -0
- package/lib/dist/extraction/vba/docmd.js.map +1 -0
- package/lib/dist/extraction/vba/enums-consts.d.ts +15 -0
- package/lib/dist/extraction/vba/enums-consts.d.ts.map +1 -0
- package/lib/dist/extraction/vba/enums-consts.js +178 -0
- package/lib/dist/extraction/vba/enums-consts.js.map +1 -0
- package/lib/dist/extraction/vba/implements.d.ts +3 -0
- package/lib/dist/extraction/vba/implements.d.ts.map +1 -0
- package/lib/dist/extraction/vba/implements.js +52 -0
- package/lib/dist/extraction/vba/implements.js.map +1 -0
- package/lib/dist/extraction/vba/procedures.d.ts +3 -0
- package/lib/dist/extraction/vba/procedures.d.ts.map +1 -0
- package/lib/dist/extraction/vba/procedures.js +239 -0
- package/lib/dist/extraction/vba/procedures.js.map +1 -0
- package/lib/dist/extraction/vba/sql-wrapper.d.ts +17 -0
- package/lib/dist/extraction/vba/sql-wrapper.d.ts.map +1 -0
- package/lib/dist/extraction/vba/sql-wrapper.js +212 -0
- package/lib/dist/extraction/vba/sql-wrapper.js.map +1 -0
- package/lib/dist/extraction/vba/tempvars.d.ts +10 -0
- package/lib/dist/extraction/vba/tempvars.d.ts.map +1 -0
- package/lib/dist/extraction/vba/tempvars.js +138 -0
- package/lib/dist/extraction/vba/tempvars.js.map +1 -0
- package/lib/dist/extraction/vba/text-utils.d.ts +73 -0
- package/lib/dist/extraction/vba/text-utils.d.ts.map +1 -0
- package/lib/dist/extraction/vba/text-utils.js +195 -0
- package/lib/dist/extraction/vba/text-utils.js.map +1 -0
- package/lib/dist/extraction/vba-extractor.d.ts +3 -951
- package/lib/dist/extraction/vba-extractor.d.ts.map +1 -1
- package/lib/dist/extraction/vba-extractor.js +46 -2934
- package/lib/dist/extraction/vba-extractor.js.map +1 -1
- package/lib/dist/extraction/vba-preprocess.d.ts +1 -1
- package/lib/dist/extraction/vba-preprocess.d.ts.map +1 -1
- package/lib/dist/extraction/vba-preprocess.js +300 -88
- package/lib/dist/extraction/vba-preprocess.js.map +1 -1
- package/lib/dist/extraction/wasm/tree-sitter-arkts.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-cfml.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-cfquery.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-cfscript.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-cobol.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-erlang.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-terraform.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-vbnet.wasm +0 -0
- package/lib/dist/graph/traversal.d.ts.map +1 -1
- package/lib/dist/graph/traversal.js +76 -17
- package/lib/dist/graph/traversal.js.map +1 -1
- package/lib/dist/index.d.ts +81 -1
- package/lib/dist/index.d.ts.map +1 -1
- package/lib/dist/index.js +467 -10
- package/lib/dist/index.js.map +1 -1
- package/lib/dist/installer/index.d.ts +42 -0
- package/lib/dist/installer/index.d.ts.map +1 -1
- package/lib/dist/installer/index.js +97 -2
- package/lib/dist/installer/index.js.map +1 -1
- package/lib/dist/mcp/daemon.d.ts +35 -3
- package/lib/dist/mcp/daemon.d.ts.map +1 -1
- package/lib/dist/mcp/daemon.js +101 -9
- package/lib/dist/mcp/daemon.js.map +1 -1
- package/lib/dist/mcp/dynamic-boundaries.d.ts.map +1 -1
- package/lib/dist/mcp/dynamic-boundaries.js +2 -1
- package/lib/dist/mcp/dynamic-boundaries.js.map +1 -1
- package/lib/dist/mcp/early-ppid.d.ts +26 -0
- package/lib/dist/mcp/early-ppid.d.ts.map +1 -0
- package/lib/dist/mcp/early-ppid.js +29 -0
- package/lib/dist/mcp/early-ppid.js.map +1 -0
- package/lib/dist/mcp/index.d.ts.map +1 -1
- package/lib/dist/mcp/index.js +29 -4
- package/lib/dist/mcp/index.js.map +1 -1
- package/lib/dist/mcp/liveness-watchdog.d.ts +18 -1
- package/lib/dist/mcp/liveness-watchdog.d.ts.map +1 -1
- package/lib/dist/mcp/liveness-watchdog.js +73 -13
- package/lib/dist/mcp/liveness-watchdog.js.map +1 -1
- package/lib/dist/mcp/proxy.d.ts.map +1 -1
- package/lib/dist/mcp/proxy.js +30 -4
- package/lib/dist/mcp/proxy.js.map +1 -1
- package/lib/dist/mcp/query-pool.d.ts +14 -0
- package/lib/dist/mcp/query-pool.d.ts.map +1 -1
- package/lib/dist/mcp/query-pool.js +18 -0
- package/lib/dist/mcp/query-pool.js.map +1 -1
- package/lib/dist/mcp/session.d.ts +14 -0
- package/lib/dist/mcp/session.d.ts.map +1 -1
- package/lib/dist/mcp/session.js +28 -1
- package/lib/dist/mcp/session.js.map +1 -1
- package/lib/dist/mcp/startup-handshake.d.ts +44 -0
- package/lib/dist/mcp/startup-handshake.d.ts.map +1 -0
- package/lib/dist/mcp/startup-handshake.js +73 -0
- package/lib/dist/mcp/startup-handshake.js.map +1 -0
- package/lib/dist/mcp/tools.d.ts +22 -0
- package/lib/dist/mcp/tools.d.ts.map +1 -1
- package/lib/dist/mcp/tools.js +289 -23
- package/lib/dist/mcp/tools.js.map +1 -1
- package/lib/dist/mcp/transport.d.ts.map +1 -1
- package/lib/dist/mcp/transport.js +18 -0
- package/lib/dist/mcp/transport.js.map +1 -1
- package/lib/dist/project-config.d.ts +44 -0
- package/lib/dist/project-config.d.ts.map +1 -1
- package/lib/dist/project-config.js +151 -2
- package/lib/dist/project-config.js.map +1 -1
- package/lib/dist/resolution/c-fnptr-synthesizer.d.ts +2 -1
- package/lib/dist/resolution/c-fnptr-synthesizer.d.ts.map +1 -1
- package/lib/dist/resolution/c-fnptr-synthesizer.js +170 -146
- package/lib/dist/resolution/c-fnptr-synthesizer.js.map +1 -1
- package/lib/dist/resolution/callback-synthesizer.d.ts +1 -1
- package/lib/dist/resolution/callback-synthesizer.d.ts.map +1 -1
- package/lib/dist/resolution/callback-synthesizer.js +1109 -97
- package/lib/dist/resolution/callback-synthesizer.js.map +1 -1
- package/lib/dist/resolution/cooperative-yield.d.ts +32 -0
- package/lib/dist/resolution/cooperative-yield.d.ts.map +1 -0
- package/lib/dist/resolution/cooperative-yield.js +42 -0
- package/lib/dist/resolution/cooperative-yield.js.map +1 -0
- package/lib/dist/resolution/frameworks/cics.d.ts +20 -0
- package/lib/dist/resolution/frameworks/cics.d.ts.map +1 -0
- package/lib/dist/resolution/frameworks/cics.js +90 -0
- package/lib/dist/resolution/frameworks/cics.js.map +1 -0
- package/lib/dist/resolution/frameworks/index.d.ts.map +1 -1
- package/lib/dist/resolution/frameworks/index.js +6 -0
- package/lib/dist/resolution/frameworks/index.js.map +1 -1
- package/lib/dist/resolution/frameworks/java.d.ts.map +1 -1
- package/lib/dist/resolution/frameworks/java.js +14 -6
- package/lib/dist/resolution/frameworks/java.js.map +1 -1
- package/lib/dist/resolution/frameworks/terraform.d.ts +38 -0
- package/lib/dist/resolution/frameworks/terraform.d.ts.map +1 -0
- package/lib/dist/resolution/frameworks/terraform.js +277 -0
- package/lib/dist/resolution/frameworks/terraform.js.map +1 -0
- package/lib/dist/resolution/goframe-synthesizer.d.ts +2 -1
- package/lib/dist/resolution/goframe-synthesizer.d.ts.map +1 -1
- package/lib/dist/resolution/goframe-synthesizer.js +8 -3
- package/lib/dist/resolution/goframe-synthesizer.js.map +1 -1
- package/lib/dist/resolution/import-resolver.d.ts +7 -0
- package/lib/dist/resolution/import-resolver.d.ts.map +1 -1
- package/lib/dist/resolution/import-resolver.js +129 -4
- package/lib/dist/resolution/import-resolver.js.map +1 -1
- package/lib/dist/resolution/index.d.ts +85 -2
- package/lib/dist/resolution/index.d.ts.map +1 -1
- package/lib/dist/resolution/index.js +535 -58
- package/lib/dist/resolution/index.js.map +1 -1
- package/lib/dist/resolution/name-matcher.d.ts +22 -3
- package/lib/dist/resolution/name-matcher.d.ts.map +1 -1
- package/lib/dist/resolution/name-matcher.js +613 -39
- package/lib/dist/resolution/name-matcher.js.map +1 -1
- package/lib/dist/resolution/strip-comments.d.ts +1 -1
- package/lib/dist/resolution/strip-comments.d.ts.map +1 -1
- package/lib/dist/resolution/strip-comments.js +49 -0
- package/lib/dist/resolution/strip-comments.js.map +1 -1
- package/lib/dist/resolution/types.d.ts +29 -0
- package/lib/dist/resolution/types.d.ts.map +1 -1
- package/lib/dist/resolution/workspace-packages.d.ts +10 -0
- package/lib/dist/resolution/workspace-packages.d.ts.map +1 -1
- package/lib/dist/resolution/workspace-packages.js +142 -4
- package/lib/dist/resolution/workspace-packages.js.map +1 -1
- package/lib/dist/search/identifier-segments.d.ts +60 -0
- package/lib/dist/search/identifier-segments.d.ts.map +1 -0
- package/lib/dist/search/identifier-segments.js +176 -0
- package/lib/dist/search/identifier-segments.js.map +1 -0
- package/lib/dist/sync/git-hooks.d.ts.map +1 -1
- package/lib/dist/sync/git-hooks.js +2 -0
- package/lib/dist/sync/git-hooks.js.map +1 -1
- package/lib/dist/sync/watcher.d.ts +10 -5
- package/lib/dist/sync/watcher.d.ts.map +1 -1
- package/lib/dist/sync/watcher.js +51 -14
- package/lib/dist/sync/watcher.js.map +1 -1
- package/lib/dist/sync/worktree.d.ts +9 -0
- package/lib/dist/sync/worktree.d.ts.map +1 -1
- package/lib/dist/sync/worktree.js +45 -0
- package/lib/dist/sync/worktree.js.map +1 -1
- package/lib/dist/types.d.ts +25 -2
- package/lib/dist/types.d.ts.map +1 -1
- package/lib/dist/types.js +10 -0
- package/lib/dist/types.js.map +1 -1
- package/lib/dist/upgrade/index.d.ts +32 -0
- package/lib/dist/upgrade/index.d.ts.map +1 -1
- package/lib/dist/upgrade/index.js +163 -14
- package/lib/dist/upgrade/index.js.map +1 -1
- package/lib/dist/upgrade/remove-binary.d.ts +87 -0
- package/lib/dist/upgrade/remove-binary.d.ts.map +1 -0
- package/lib/dist/upgrade/remove-binary.js +289 -0
- package/lib/dist/upgrade/remove-binary.js.map +1 -0
- package/lib/dist/upgrade/update-check.d.ts +92 -0
- package/lib/dist/upgrade/update-check.d.ts.map +1 -0
- package/lib/dist/upgrade/update-check.js +258 -0
- package/lib/dist/upgrade/update-check.js.map +1 -0
- package/lib/node_modules/.modules.yaml +1 -1
- package/lib/node_modules/.pnpm-workspace-state-v1.json +1 -1
- package/lib/package.json +1 -1
- package/package.json +1 -1
- package/lib/dist/reasoning/config.d.ts +0 -45
- package/lib/dist/reasoning/config.d.ts.map +0 -1
- package/lib/dist/reasoning/config.js +0 -171
- package/lib/dist/reasoning/config.js.map +0 -1
- package/lib/dist/reasoning/credentials.d.ts +0 -5
- package/lib/dist/reasoning/credentials.d.ts.map +0 -1
- package/lib/dist/reasoning/credentials.js +0 -83
- package/lib/dist/reasoning/credentials.js.map +0 -1
- package/lib/dist/reasoning/login.d.ts +0 -21
- package/lib/dist/reasoning/login.d.ts.map +0 -1
- package/lib/dist/reasoning/login.js +0 -85
- package/lib/dist/reasoning/login.js.map +0 -1
- package/lib/dist/reasoning/reasoner.d.ts +0 -43
- package/lib/dist/reasoning/reasoner.d.ts.map +0 -1
- package/lib/dist/reasoning/reasoner.js +0 -308
- package/lib/dist/reasoning/reasoner.js.map +0 -1
|
@@ -2,962 +2,14 @@ import { ExtractionResult } from '../types';
|
|
|
2
2
|
export declare class VbaExtractor {
|
|
3
3
|
private filePath;
|
|
4
4
|
private source;
|
|
5
|
-
private
|
|
6
|
-
private
|
|
7
|
-
|
|
8
|
-
private unresolvedReferences;
|
|
9
|
-
private moduleOrClassNode;
|
|
10
|
-
/**
|
|
11
|
-
* Class-name prefix for `qualifiedName` composition.
|
|
12
|
-
*
|
|
13
|
-
* B3 (hueco 5): for `.cls` files every function node's `qualifiedName`
|
|
14
|
-
* is composed as `${className}.${procName}` (e.g. `Form_TestForm.Form_Load`)
|
|
15
|
-
* so cross-class callers can disambiguate which form each `Form_Load`
|
|
16
|
-
* belongs to. For `.bas` files this is `null` — module-scoped procs
|
|
17
|
-
* keep their bare-name `qualifiedName` (e.g. `DoThing`), preserving
|
|
18
|
-
* the pre-hueco-5 behavior and every existing qualifiedName-based
|
|
19
|
-
* assertion in `extraction-vba.test.ts`.
|
|
20
|
-
*
|
|
21
|
-
* Resolved once per `extract()` from `isCls` + `vbName` (both already
|
|
22
|
-
* computed for `createModuleOrClassNode`); `sweepProcedures` reads it
|
|
23
|
-
* to set `ProcInfo.qualifiedName` and the function node's qualifiedName.
|
|
24
|
-
*/
|
|
25
|
-
private classNamePrefix;
|
|
26
|
-
/**
|
|
27
|
-
* Map of procedure name (within this file) → list of ProcInfo. The list
|
|
28
|
-
* (rather than a single value) is needed because VBA allows multiple
|
|
29
|
-
* Property accessors with the same name: `Property Get Foo`, `Property
|
|
30
|
-
* Let Foo`, and `Property Set Foo` all share the name `Foo`. Audit W6
|
|
31
|
-
* (June 2026): the previous Map<string, ProcInfo> kept only the last
|
|
32
|
-
* accessor, breaking same-file call resolution and emitting the wrong
|
|
33
|
-
* `findFunctionNodeByName` match.
|
|
34
|
-
*/
|
|
35
|
-
private localProcs;
|
|
36
|
-
/**
|
|
37
|
-
* Cache: procedure name → first matching function node emitted for that
|
|
38
|
-
* name. Audit S2 (June 2026): the previous implementation did an O(n)
|
|
39
|
-
* linear scan of all nodes for every call site; with W6's multimap
|
|
40
|
-
* the same-name collision can return multiple matches but bare-name
|
|
41
|
-
* call resolution only needs the first.
|
|
42
|
-
*/
|
|
43
|
-
private functionNodeByName;
|
|
44
|
-
/**
|
|
45
|
-
* Cache: startLine → function node emitted for that line. Used by Fix 1
|
|
46
|
-
* (June 2026): when Property Get/Let/Set share a name, we need to find
|
|
47
|
-
* the SPECIFIC accessor's node by its declaration line rather than relying
|
|
48
|
-
* on `functionNodeByName` which only stores the first accessor.
|
|
49
|
-
*/
|
|
50
|
-
private functionNodeByStartLine;
|
|
51
|
-
constructor(filePath: string, source: string);
|
|
5
|
+
private ctx;
|
|
6
|
+
private vbaTargets?;
|
|
7
|
+
constructor(filePath: string, source: string, vbaTargets?: Record<string, boolean>);
|
|
52
8
|
extract(): ExtractionResult;
|
|
53
9
|
private result;
|
|
54
10
|
private isFormOrReportFile;
|
|
55
11
|
private createFileNode;
|
|
56
12
|
private detectVbName;
|
|
57
13
|
private createModuleOrClassNode;
|
|
58
|
-
/** Sub/Function/Property regex — captures visibility prefix, kind, and name. */
|
|
59
|
-
private static readonly PROC_RE;
|
|
60
|
-
/**
|
|
61
|
-
* Walk the (uncommented, line-joined) source and emit one `function` node
|
|
62
|
-
* per `Sub` / `Function` / `Property` declaration. Also records the proc
|
|
63
|
-
* in `localProcs` so call-site resolution can distinguish same-file from
|
|
64
|
-
* cross-module calls.
|
|
65
|
-
*/
|
|
66
|
-
private sweepProcedures;
|
|
67
|
-
/** `[visibility] Event <Name>(...)` custom event declaration. */
|
|
68
|
-
private static readonly EVENT_DECL_RE;
|
|
69
|
-
/** `[visibility] Type <Name>` user-defined type block start. */
|
|
70
|
-
private static readonly TYPE_START_RE;
|
|
71
|
-
/** `End Type` user-defined type block end. */
|
|
72
|
-
private static readonly TYPE_END_RE;
|
|
73
|
-
/** `<MemberName> As <Type>` inside a user-defined type block. */
|
|
74
|
-
private static readonly TYPE_MEMBER_RE;
|
|
75
|
-
/** `[visibility] Declare [PtrSafe] Sub|Function <Name> Lib "dll" [Alias "x"] ...` */
|
|
76
|
-
private static readonly DLL_DECLARE_RE;
|
|
77
|
-
/**
|
|
78
|
-
* Roadmap #26 declaration sweep:
|
|
79
|
-
* - Event declarations become `event` nodes and `RaiseEvent` can point to them.
|
|
80
|
-
* - Type...End Type blocks become `type` + `type_member` nodes.
|
|
81
|
-
* - Win32 API Declare statements become `declare` nodes, while still being
|
|
82
|
-
* cached by name so normal call-site scanning can emit `calls` edges.
|
|
83
|
-
*/
|
|
84
|
-
private sweepEventsTypesAndDeclares;
|
|
85
|
-
/** Implements regex. */
|
|
86
|
-
private static readonly IMPLEMENTS_RE;
|
|
87
|
-
/** Edges whose source needs to be set to the module/class id once it exists. */
|
|
88
|
-
private pendingModuleOrClassSource;
|
|
89
|
-
private sweepImplements;
|
|
90
|
-
/**
|
|
91
|
-
* Check that a line is a variable declaration and NOT a Sub/Function/
|
|
92
|
-
* Property/Const/WithEvents header (those have their own sweeps).
|
|
93
|
-
* Fix 1+3 (Issues #1,#3): replaced the old single-match DIM_QUAL_RE /
|
|
94
|
-
* DIM_UNQUAL_RE pair with a prefix-check + global scan that handles
|
|
95
|
-
* `As New <Type>`, multi-variable `Dim a As Foo, b As Bar`, and all
|
|
96
|
-
* visibility keywords in one pass.
|
|
97
|
-
* Issue #47: now also accepts `Global` (module-level typed instance) and
|
|
98
|
-
* `Static` (procedure-local retention modifier) so they emit the same
|
|
99
|
-
* `references` edge and `localVarTypeMap` registration as their `Dim`
|
|
100
|
-
* siblings today. The negative lookahead is unchanged: `Const` is still
|
|
101
|
-
* routed to `sweepEnumsAndConsts`.
|
|
102
|
-
*/
|
|
103
|
-
private static readonly DIM_DECL_PREFIX_RE;
|
|
104
|
-
/**
|
|
105
|
-
* Globally scan all `identifier As [New] TypePart1[.TypePart2]` on a
|
|
106
|
-
* variable declaration line. Run with /g after confirming DIM_DECL_PREFIX_RE.
|
|
107
|
-
*
|
|
108
|
-
* Groups: (1) variable name, (2) bracketed outer type, (3) unbracketed
|
|
109
|
-
* outer type, (4) bracketed inner type (if qualified), (5) unbracketed
|
|
110
|
-
* inner type. The variable name is always bare (`Dim` cannot declare a
|
|
111
|
-
* bracketed variable). The TYPE position accepts BOTH bracketed names
|
|
112
|
-
* with spaces (e.g. `[Clase Con Espacios]`) and bare identifiers — the
|
|
113
|
-
* bracketed capture wins when present. Only one of (2)/(3) and one of
|
|
114
|
-
* (4)/(5) is ever populated per match.
|
|
115
|
-
* `(?:New\s+)?` consumes the VBA auto-instantiation keyword so it is
|
|
116
|
-
* never captured as the type name (Fix 1).
|
|
117
|
-
*
|
|
118
|
-
* Issue #54: extends the type alternative to accept `[Name With Spaces]`
|
|
119
|
-
* so `Dim x As [Clase Con Espacios]` emits a `references` edge to
|
|
120
|
-
* `Clase Con Espacios` (brackets unwrapped). The unwrap is applied in
|
|
121
|
-
* the sweep loop by picking the bracketed capture group when present.
|
|
122
|
-
*/
|
|
123
|
-
private static readonly DIM_ALL_VARS_RE;
|
|
124
|
-
/**
|
|
125
|
-
* Bare-declared variable capture for the `Dim|Private|Public|Global|Static`
|
|
126
|
-
* prefix. Captures (1) the variable name. Used to register bare `Dim x`
|
|
127
|
-
* (no `As` clause) and explicit-primitive `Dim x As Long|String|...`
|
|
128
|
-
* declarations into `localVarTypeMap` so the type tracking is consistent
|
|
129
|
-
* across all three Dim shapes:
|
|
130
|
-
*
|
|
131
|
-
* `Dim x` → outer = 'variant' (VBA default)
|
|
132
|
-
* `Dim x As Variant` → outer = 'variant' (PRIMITIVE_TYPES member)
|
|
133
|
-
* `Dim x As Long` → outer = 'long' (PRIMITIVE_TYPES member)
|
|
134
|
-
* `Dim x As Foo` → outer = 'foo' (project class — non-primitive)
|
|
135
|
-
*
|
|
136
|
-
* Antigravity audit Task 3: the previous `DIM_ALL_VARS_RE` only matched
|
|
137
|
-
* the `... As <Type>` form, so a bare `Dim x` was invisible to
|
|
138
|
-
* `isLocalProjectClassVar` / `scanCallSites` and `x.Method(1)` produced
|
|
139
|
-
* a dead-end `calls` edge to a stub named `x.Method` that no resolver
|
|
140
|
-
* could repoint. Registering bare Dim with `outer = 'variant'` closes
|
|
141
|
-
* the gate, so `scanCallSites` skips ONLY when the receiver is mapped
|
|
142
|
-
* as a primitive — leaving the "undeclared receiver → stub → resolver
|
|
143
|
-
* repoints" path intact for cross-module qualified calls like
|
|
144
|
-
* `modUtils.Foo(1)` (`modUtils` is not in `localVarTypeMap`).
|
|
145
|
-
*/
|
|
146
|
-
private static readonly BARE_DIM_VAR_RE;
|
|
147
|
-
/**
|
|
148
|
-
* VBA primitive type names — skipped when emitted as Dim targets so
|
|
149
|
-
* we don't pollute the graph with `As Long` / `As String` references.
|
|
150
|
-
* Fix 4: all entries are LOWERCASE and the lookup lowercases the
|
|
151
|
-
* captured type name so `As long`, `As LONG`, `As Long` all match.
|
|
152
|
-
* Fix 1 (Issue #1): added `'new'` as a backstop so that if the `As New`
|
|
153
|
-
* pattern is ever captured as a type name it is silently skipped.
|
|
154
|
-
*/
|
|
155
|
-
private static readonly PRIMITIVE_TYPES;
|
|
156
|
-
/** `WithEvents m_X As Form_Foo` — Dim/Private/Public/Global/Static prefix is optional. */
|
|
157
|
-
private static readonly WITHEVENTS_RE;
|
|
158
|
-
private sweepDimsAndWithEvents;
|
|
159
|
-
/** `[visibility] Enum <Name>` — opens an enum block. */
|
|
160
|
-
private static readonly ENUM_START_RE;
|
|
161
|
-
/** `End Enum` — closes the current enum block. */
|
|
162
|
-
private static readonly ENUM_END_RE;
|
|
163
|
-
/**
|
|
164
|
-
* An enum member line: a leading identifier optionally followed by `=
|
|
165
|
-
* <value>`. Runs only inside an open Enum block, on the (already
|
|
166
|
-
* comment-stripped) source, so a trailing `'comment` never reaches here.
|
|
167
|
-
* `\p{L}` covers accented member names (e.g. `Sí`).
|
|
168
|
-
*/
|
|
169
|
-
private static readonly ENUM_MEMBER_RE;
|
|
170
|
-
/** `[visibility] Const <decls>` — captures visibility (1) and the rest (2). */
|
|
171
|
-
private static readonly CONST_DECL_RE;
|
|
172
|
-
/**
|
|
173
|
-
* Issue #52: shared `End Sub` / `End Function` / `End Property` marker.
|
|
174
|
-
* Promoted from a local regex in `sweepCallsAndSql` so `sweepEnumsAndConsts`
|
|
175
|
-
* can walk the same proc boundaries and decide Const scope per line.
|
|
176
|
-
* The `(?:^|:\s*)` prefix tolerates colon-separated single-line procs
|
|
177
|
-
* (`Public Sub X(): ... : End Sub`) so the proc stack pops on the same
|
|
178
|
-
* physical line.
|
|
179
|
-
*/
|
|
180
|
-
private static readonly PROCEDURE_END_RE;
|
|
181
|
-
/**
|
|
182
|
-
* Fold a VBA visibility keyword to the canonical lowercase enum, matching
|
|
183
|
-
* the procedure convention: `Private` → 'private'; `Public`, `Global`,
|
|
184
|
-
* `Friend`, or none → 'public' (VBA's default module-level `Const`/`Enum`
|
|
185
|
-
* is Private, but we follow the same broader-than-private fold the proc
|
|
186
|
-
* sweep uses so visibility is consistent across symbol kinds).
|
|
187
|
-
*/
|
|
188
|
-
private static foldVisibility;
|
|
189
|
-
/**
|
|
190
|
-
* Walk the (uncommented, line-joined) source and emit:
|
|
191
|
-
* - one `enum` node per `Enum <Name>` block, with one `enum_member` node
|
|
192
|
-
* per member and a `contains` edge enum→member;
|
|
193
|
-
* - one `constant` node per name declared on a `Const` line (multi-name
|
|
194
|
-
* lines emit one node per name);
|
|
195
|
-
* - a `contains` edge from the module/class node to each enum and constant
|
|
196
|
-
* (held in `pendingModuleOrClassSource` until the module node exists).
|
|
197
|
-
*
|
|
198
|
-
* Returns the number of top-level symbols (enums + constants) emitted so
|
|
199
|
-
* the caller can flip `hasAnySymbols`.
|
|
200
|
-
*/
|
|
201
|
-
private sweepEnumsAndConsts;
|
|
202
|
-
/**
|
|
203
|
-
* Emit a `contains` edge from the (lazily-created) module/class node to
|
|
204
|
-
* `targetId`. Mirrors the pending-source pattern the procedure and
|
|
205
|
-
* implements sweeps use: the module node doesn't exist yet, so the edge's
|
|
206
|
-
* source is rewritten once `extract()` creates it.
|
|
207
|
-
*/
|
|
208
|
-
private pushContainsFromModule;
|
|
209
|
-
/**
|
|
210
|
-
* Walk the (uncommented) source per line. For each line:
|
|
211
|
-
* - If it starts a `Sub`/`Function`/`Property`, push the proc onto a stack.
|
|
212
|
-
* - If it ends one (`End Sub` / `End Function` / `End Property`), pop.
|
|
213
|
-
* - While inside a procedure, scan the line for call-site patterns and
|
|
214
|
-
* SQL-wrapper patterns.
|
|
215
|
-
*
|
|
216
|
-
* Call-site regex captures either `Name(...)` (same-file candidate) or
|
|
217
|
-
* `Receiver.Member(...)` (qualified — emit a synthetic node + heuristic
|
|
218
|
-
* edge). The receiver AND member alternatives accept BOTH the bare form
|
|
219
|
-
* (`Foo`) and the VBA bracketed form (`[Foo Bar]`) — bracketed captures
|
|
220
|
-
* win when present. Only one of (1)/(2) and one of (3)/(4) is ever
|
|
221
|
-
* populated per match. Brackets are stripped by the regex itself (the
|
|
222
|
-
* capture groups hold the inner content), so callers receive unwrapped
|
|
223
|
-
* identifiers and the `${name}.${proc}` stub shape stays canonical.
|
|
224
|
-
*
|
|
225
|
-
* Issue #54: the bracketed alternative was previously absent, so
|
|
226
|
-
* `[FUNCIONES UTILES].FormatearFecha(fecha)` (a real Dysflow-exported
|
|
227
|
-
* idiom for modules with spaces in their names) was silently dropped.
|
|
228
|
-
*/
|
|
229
|
-
private static readonly CALL_RE;
|
|
230
|
-
/** SQL wrapper helpers — order matters because `db.Execute` is a suffix of others. */
|
|
231
|
-
private static readonly SQL_WRAPPERS;
|
|
232
|
-
/**
|
|
233
|
-
* `DoCmd.OpenForm "<FormName>"` modelling regex — B4 (hueco 6).
|
|
234
|
-
*
|
|
235
|
-
* Real VBA idiom (matches literal and bare-identifier forms):
|
|
236
|
-
* `DoCmd.OpenForm "MyForm"`
|
|
237
|
-
* `DoCmd.OpenForm FORM_MY_FORM`
|
|
238
|
-
* `DoCmd.OpenForm "MyForm", acNormal, , , acFormEdit`
|
|
239
|
-
*
|
|
240
|
-
* Captures the first argument (group 1). String literals are unwrapped;
|
|
241
|
-
* bare identifiers resolve against local Const declarations, falling back
|
|
242
|
-
* to the identifier name when unknown. The trailing positional args
|
|
243
|
-
* (`acNormal`, `acFormEdit`, etc.) are intentionally NOT captured.
|
|
244
|
-
*
|
|
245
|
-
* Why a separate dispatch: `DoCmd` is in `RUNTIME_RECEIVER_BLACKLIST`
|
|
246
|
-
* (R4 invariant), so `DoCmd.OpenForm` is intentionally SKIPPED by the
|
|
247
|
-
* generic `CALL_RE` path that would otherwise emit a junk `calls` edge
|
|
248
|
-
* to a synthetic `function` node for `DoCmd.OpenForm`. This regex
|
|
249
|
-
* matches BEFORE the call-site scan and uses its own dispatch to emit
|
|
250
|
-
* the `opens-form` edge instead — sharing no logic with CALL_RE.
|
|
251
|
-
*/
|
|
252
|
-
private static readonly OPEN_FORM_ARG_RE;
|
|
253
|
-
/**
|
|
254
|
-
* Issue #48: `DoCmd.OpenReport "<ReportName>"` modelling regex — sibling
|
|
255
|
-
* of `OPEN_FORM_ARG_RE` (hueco 6 expanded). Same literal-or-bare-id argument
|
|
256
|
-
* capture (group 1) and same trailing positional-args drop. The dispatch
|
|
257
|
-
* table `DOCMD_OPEN_DISPATCH` (below) carries the per-method metadata so
|
|
258
|
-
* OpenForm and OpenReport share the same scan/emit pipeline while their
|
|
259
|
-
* edge kinds (`opens-form` vs `opens-report`), stub node kinds
|
|
260
|
-
* (`form-layout` vs `report-layout`), synthetic file-path prefixes, and
|
|
261
|
-
* qualifiedName prefixes (`Form_<Name>` vs `Report_<Name>`) stay
|
|
262
|
-
* distinct.
|
|
263
|
-
*/
|
|
264
|
-
private static readonly OPEN_REPORT_ARG_RE;
|
|
265
|
-
/**
|
|
266
|
-
* Issue #48 dispatch table — shared literal-or-Const argument resolution
|
|
267
|
-
* for `DoCmd.OpenForm` and `DoCmd.OpenReport`. Each entry is everything
|
|
268
|
-
* `scanDoCmdOpenCalls` + `emitOpensStubEdge` need to share the pipeline
|
|
269
|
-
* between methods while keeping the per-method names distinct.
|
|
270
|
-
*
|
|
271
|
-
* OpenQuery is intentionally NOT in this dispatch — it emits an
|
|
272
|
-
* `UnresolvedReference` (not a stub + edge), resolution to the REAL
|
|
273
|
-
* `query` node emitted by `SqlQueryExtractor`. See
|
|
274
|
-
* `OPEN_QUERY_ARG_RE` + `scanDoCmdOpenQuery`.
|
|
275
|
-
*
|
|
276
|
-
* Why a separate dispatch: `DoCmd` is in `RUNTIME_RECEIVER_BLACKLIST`
|
|
277
|
-
* (R4 invariant), so ALL of these methods are intentionally SKIPPED by
|
|
278
|
-
* the generic `CALL_RE` path that would otherwise emit a junk `calls`
|
|
279
|
-
* edge to a synthetic `function` node for `DoCmd.OpenX`. This dispatch
|
|
280
|
-
* matches BEFORE the call-site scan and uses its own emission path.
|
|
281
|
-
*/
|
|
282
|
-
private static readonly DOCMD_OPEN_DISPATCH;
|
|
283
|
-
/**
|
|
284
|
-
* Issue #48: `DoCmd.OpenQuery "<QueryName>"` modelling regex. Emits an
|
|
285
|
-
* `UnresolvedReference` (NOT a stub + edge) so the resolver binds to the
|
|
286
|
-
* REAL `query` node `SqlQueryExtractor` emits for `queries/<Name>.sql`
|
|
287
|
-
* — the same shape as `vba-me-control` and `vba-forms-bang`. The query
|
|
288
|
-
* may not yet exist in the index when the .bas is parsed; the resolver
|
|
289
|
-
* does the binding when the .sql is later indexed.
|
|
290
|
-
*
|
|
291
|
-
* Argument shape: identical to OpenForm/OpenReport — literal `"..."` or
|
|
292
|
-
* bare identifier resolved against local `Const` declarations, falling
|
|
293
|
-
* back to the bare identifier when unknown.
|
|
294
|
-
*/
|
|
295
|
-
private static readonly OPEN_QUERY_ARG_RE;
|
|
296
|
-
/** SQL assigned to a local variable, e.g. `m_SQL = "SELECT ..." & ...`. */
|
|
297
|
-
private static readonly SQL_VAR_ASSIGN_RE;
|
|
298
|
-
/** SQL wrapper called with a variable, e.g. `getdb().Execute m_SQL`. */
|
|
299
|
-
private static readonly SQL_VAR_EXEC_RE;
|
|
300
|
-
/**
|
|
301
|
-
* Issue #42: `DoCmd.RunSQL <identifier>` (variable form) — the dominant
|
|
302
|
-
* Access idiom for executing a dynamically-built SQL string. Today only
|
|
303
|
-
* the literal form `DoCmd.RunSQL "DELETE FROM X"` is tracked via the
|
|
304
|
-
* `SQL_WRAPPERS` regex at line 1108; the variable form silently dropped
|
|
305
|
-
* table impact for every procedure that builds SQL in a string and runs
|
|
306
|
-
* it through `DoCmd.RunSQL`.
|
|
307
|
-
*
|
|
308
|
-
* This regex is the DoCmd.RunSQL analogue of `SQL_VAR_EXEC_RE` above and
|
|
309
|
-
* is iterated by `scanSqlInLine` (lines 2051+). When a match is found,
|
|
310
|
-
* the captured identifier is resolved against `sqlVariables` (populated
|
|
311
|
-
* by `trackSqlVariableAssignment` with `&`-accumulate semantics — Issue
|
|
312
|
-
* #13) and the resulting SQL string drives `emitSqlTableReferences`.
|
|
313
|
-
*
|
|
314
|
-
* The optional `(?:\(\))?` + `\s*\(?` shape lets the regex match both
|
|
315
|
-
* the parenthesised form `DoCmd.RunSQL(strSQL)` and the no-paren form
|
|
316
|
-
* `DoCmd.RunSQL strSQL` that the existing SQL_WRAPPERS literal regex
|
|
317
|
-
* does not cover. The captured identifier is the only thing we need —
|
|
318
|
-
* we DO NOT try to parse what the variable points at; that's the
|
|
319
|
-
* existing `sqlVariables` map's job.
|
|
320
|
-
*/
|
|
321
|
-
private static readonly SQL_VAR_DOCMD_RUNSQL_RE;
|
|
322
|
-
/**
|
|
323
|
-
* SQL table-name regex scoped to the clauses that introduce a table
|
|
324
|
-
* reference: `FROM <t>`, `JOIN <t>`, `INTO <t>`, `UPDATE <t>`. Adding
|
|
325
|
-
* `JOIN` lets the scanner pick up tables from joined fragments that
|
|
326
|
-
* arrive via `&`-concatenated wrapper literals (e.g.
|
|
327
|
-
* `db.Execute "FROM A" & " JOIN B"`); without it the second literal's
|
|
328
|
-
* table was silently dropped even though the wrapper regex now matches
|
|
329
|
-
* the chain.
|
|
330
|
-
*
|
|
331
|
-
* The captured table name is an optional bracketed/unbracketed schema
|
|
332
|
-
* prefix followed by a `.`, then a bracketed-or-bare identifier — so
|
|
333
|
-
* `FROM dbo.tblCustomers` and `FROM [My Schema].[My Table]` come
|
|
334
|
-
* through as one composite reference. Without the prefix the regex
|
|
335
|
-
* still matches a single identifier byte-identical to the old shape.
|
|
336
|
-
* Brackets in the captured composite are stripped by
|
|
337
|
-
* `emitSqlTableReferences` (`replace(/[\[\]]/g, '')`), so the public
|
|
338
|
-
* node name is the unwrapped form `dbo.tblCustomers` /
|
|
339
|
-
* `My Schema.My Table` — matching how plain `[Order Details]` is also
|
|
340
|
-
* unwrapped to `Order Details`. The identifier class
|
|
341
|
-
* `\[[^\]]+\]|\p{L}[\p{L}\p{N}_]*` (same as the saved-queries
|
|
342
|
-
* `TABLE_RE` in `sql-query-extractor.ts`) ensures bracketed names
|
|
343
|
-
* with spaces — `[Order Details]`, `[My Schema]`, `[My Table]` —
|
|
344
|
-
* are captured whole.
|
|
345
|
-
*/
|
|
346
|
-
private static readonly SQL_TABLE_RE;
|
|
347
|
-
/**
|
|
348
|
-
* Issue #50: TempVars — Access's global key-value store for cross-form
|
|
349
|
-
* state. We model each STATIC-LITERAL key as a synthetic `class` placeholder
|
|
350
|
-
* (same NodeKind as SQL table refs, see `emitReference`) and emit one
|
|
351
|
-
* `references` edge per reading/writing procedure with
|
|
352
|
-
* `metadata.synthesizedBy: 'vba-tempvar'` and `metadata.access` ∈
|
|
353
|
-
* `{'read','write'}` (the user-facing enum; lowercase single-tokens).
|
|
354
|
-
*
|
|
355
|
-
* Three scanner surfaces cover the four real idioms:
|
|
356
|
-
* - `TEMP_VAR_BANG_RE` — `TempVars!clave` (no parens; write or read)
|
|
357
|
-
* - `TEMP_VAR_PAREN_RE` — `TempVars("clave")` (parens; write or read)
|
|
358
|
-
* - `TEMP_VAR_ADD_RE` — `TempVars.Add "clave", v` (always a write)
|
|
359
|
-
*
|
|
360
|
-
* Bang vs paren split by line-source: the bang form has no string literals
|
|
361
|
-
* in scope, so we scan the MASKED line (`maskStringContent` replaces
|
|
362
|
-
* `"…"` content with spaces — same line source the call-site / With
|
|
363
|
-
* event scanners consume). The paren and Add forms have their key INSIDE
|
|
364
|
-
* a `"…"` literal that gets blanked by the masker, so those regexes scan
|
|
365
|
-
* the ORIGINAL (unmasked) line — same split the SQL_TABLE_RE/OpenForm
|
|
366
|
-
* literal scanners already use.
|
|
367
|
-
*
|
|
368
|
-
* Dynamic-key forms — `TempVars(strNombre)`,
|
|
369
|
-
* `TempVars("clave" & suffix)` — are silently unmatched by all three
|
|
370
|
-
* regexes (none of them tolerate a function-call or `&` arg). REQ-CODE-4
|
|
371
|
-
* "unresolvable is silent" applies: these stay silent by design to
|
|
372
|
-
* prevent placeholder-node explosion.
|
|
373
|
-
*/
|
|
374
|
-
private static readonly TEMP_VAR_BANG_RE;
|
|
375
|
-
/**
|
|
376
|
-
* Issue #50 (cont.):
|
|
377
|
-
* `TempVars("clave")` / `TempVars( "clave" )` capture. Scanned
|
|
378
|
-
* over the original (unmasked) line — the literal lives INSIDE a
|
|
379
|
-
* string and would be stripped by `maskStringContent`.
|
|
380
|
-
*/
|
|
381
|
-
private static readonly TEMP_VAR_PAREN_RE;
|
|
382
|
-
/**
|
|
383
|
-
* Issue #50 (cont.):
|
|
384
|
-
* `TempVars.Add "clave", value` capture. Always a write (the
|
|
385
|
-
* `.Add` method inserts/updates the entry). Scanned over the
|
|
386
|
-
* original (unmasked) line for the same string-literal reason as
|
|
387
|
-
* `TEMP_VAR_PAREN_RE`.
|
|
388
|
-
*/
|
|
389
|
-
private static readonly TEMP_VAR_ADD_RE;
|
|
390
|
-
/**
|
|
391
|
-
* `Me.<ControlName>` / `Me!<ControlName>` reference capture — hole 1
|
|
392
|
-
* of VBA control-modeling. Extended by Issue #44 to accept the bang
|
|
393
|
-
* form (the default-collection shortcut Access VBA inherits from VB).
|
|
394
|
-
*
|
|
395
|
-
* Real VBA idioms:
|
|
396
|
-
* `Me.lblTitulo.Caption = "Hello"` ← dot form, property assignment
|
|
397
|
-
* `Me.txtDescripcion.Value = "World"` ← dot form, property assignment
|
|
398
|
-
* `Me.ComandoGrabar.Enabled = True` ← dot form, property assignment
|
|
399
|
-
* `Me!txtNombre = "Hello"` ← BANG form (default collection)
|
|
400
|
-
* `Me!txtEstado.Value = 1` ← BANG form, then property
|
|
401
|
-
* `If Nz(Me.MotivoBorrado, "") = "" Then` ← read in expression
|
|
402
|
-
*
|
|
403
|
-
* The existing call-site scanner (CALL_RE) only fires on `Name(`
|
|
404
|
-
* (paren form) and `Me` is in its keyword blacklist anyway, so
|
|
405
|
-
* `Me.<Control>` references are silently invisible. This regex matches
|
|
406
|
-
* the FIRST identifier after `Me.` or `Me!` regardless of what follows
|
|
407
|
-
* (a property, an index, an assignment, a call argument, etc.) so the
|
|
408
|
-
* form → control binding is surfaced as an UnresolvedReference for the
|
|
409
|
-
* resolver to pick up later. Subsequent segments (`.Caption`, `.Value`,
|
|
410
|
-
* `.Enabled`) are intentionally NOT captured — they are properties of
|
|
411
|
-
* the control, not new symbols. The bang (`!`) is the default-collection
|
|
412
|
-
* shortcut: `Me!txtFoo` is semantically identical to `Me.txtFoo` and
|
|
413
|
-
* produces a byte-identical UnresolvedReference (same `referenceName`,
|
|
414
|
-
* `referenceKind`, and `metadata.synthesizedBy`) — the regression test
|
|
415
|
-
* in `__tests__/extraction-vba.test.ts` pins this parity.
|
|
416
|
-
*
|
|
417
|
-
* Provenance: `metadata.synthesizedBy = 'vba-me-control'`. Mirrors the
|
|
418
|
-
* `vba-form-binding` (form→sibling-`.cls`) and `vba-name-resolution`
|
|
419
|
-
* (qualified Dim) patterns already documented on `UnresolvedReference.metadata`
|
|
420
|
-
* in `src/types.ts`.
|
|
421
|
-
*/
|
|
422
|
-
private static readonly ME_CONTROL_RE;
|
|
423
|
-
/**
|
|
424
|
-
* Issue #44: `Forms!<FormName>` / `Forms("<FormName>")!<Ctl>` cross-form
|
|
425
|
-
* reference capture — companion to `ME_CONTROL_RE` above. Access VBA's
|
|
426
|
-
* default-collection shortcut for cross-form control access, captured
|
|
427
|
-
* BEFORE the generic call-site scan and emitted as its own
|
|
428
|
-
* `UnresolvedReference` family.
|
|
429
|
-
*
|
|
430
|
-
* Real VBA idioms:
|
|
431
|
-
* `Forms!FormX!txtY.Value = 1` — bang form, with control segment
|
|
432
|
-
* `Forms!FormX.Recordsource = "..."` — bang form, trailing property access
|
|
433
|
-
* `Set f = Forms!FormX` — bang form, no control segment
|
|
434
|
-
* `Forms("FormX")!txtY.Value = 1` — paren form, with control
|
|
435
|
-
* `Forms![Mi Formulario]!txtY` — bracketed form name (#54 mirror)
|
|
436
|
-
*
|
|
437
|
-
* Why a dedicated scanner (mirroring `OPEN_FORM_ARG_RE` / B4 / DoCmd.OpenForm):
|
|
438
|
-
* `Forms` is in `RUNTIME_RECEIVER_BLACKLIST`, so the generic CALL_RE
|
|
439
|
-
* path silently skips both `Forms!X` and `Forms("X")!Y`. Without this
|
|
440
|
-
* scanner, cross-form UI traffic from `Forms!FormX!txtY.Value` would
|
|
441
|
-
* never surface the form → control binding that the resolver needs to
|
|
442
|
-
* glue form `form-layout` nodes to control `form-instance-control`
|
|
443
|
-
* nodes. The dedicated dispatch fires BEFORE the call-site scan and
|
|
444
|
-
* uses its own emission path; the runtime-blacklist constraint is
|
|
445
|
-
* preserved (we intentionally do not rewrite CALL_RE).
|
|
446
|
-
*
|
|
447
|
-
* What this scanner emits per match:
|
|
448
|
-
* - ONE `UnresolvedReference` whose `referenceName` is the form's
|
|
449
|
-
* identifier (stripped of any surrounding quote or bracket
|
|
450
|
-
* decoration), tagged `metadata.synthesizedBy = 'vba-forms-bang'`
|
|
451
|
-
* and `referenceKind = 'references'`. The control segment (if
|
|
452
|
-
* present) is consumed by the regex so `Forms!FormX!txtY.Value` is
|
|
453
|
-
* captured as a single match, but the control name is NOT emitted
|
|
454
|
-
* as its own reference — control emission is the form's
|
|
455
|
-
* responsibility downstream.
|
|
456
|
-
* - NO synthetic `function` node (W4 graph-pollution invariant — the
|
|
457
|
-
* form is a real `.cls` / `.form.txt` pair the resolver already
|
|
458
|
-
* picks up via the `vba-form-binding` path). Without this guard the
|
|
459
|
-
* bang form would synthesize one stub per cross-form reference
|
|
460
|
-
* site, identical to what `bumpShapes` from #43 audited out.
|
|
461
|
-
*
|
|
462
|
-
* What this scanner does NOT match (intentional, pinned by tests):
|
|
463
|
-
* - `Forms!FormX.Foo` — the trailing `.Foo` IS a property
|
|
464
|
-
* access on the form (e.g. `Recordsource`), NOT a control access.
|
|
465
|
-
* The bang alternative carries a `(?![.\w])` negative-lookahead
|
|
466
|
-
* after the form identifier to drop this shape. The "W4
|
|
467
|
-
* no-synthetic-fn" test pins both halves of this contract.
|
|
468
|
-
* - `rs!Campo` — recordset field access (DAO/ADO
|
|
469
|
-
* default-member field read) is explicitly out of scope for the
|
|
470
|
-
* current change. The runtime-receiver blacklist plus the absence
|
|
471
|
-
* of any `Forms`/`Me` prefix means the existing scanners already
|
|
472
|
-
* skip it cleanly; the "STRETCH SCOPE" test pins that behaviour
|
|
473
|
-
* so a future change to bring recordset bangs in is reviewed
|
|
474
|
-
* explicitly against the bang-form scope decision.
|
|
475
|
-
*
|
|
476
|
-
* Operates on the ORIGINAL (unmasked) line — the paren form
|
|
477
|
-
* `Forms("FormX")!txtY` has the form name INSIDE a string literal, so
|
|
478
|
-
* masking string content would destroy the form identifier. Same
|
|
479
|
-
* unmasked-line constraint as `scanOpenFormCalls`.
|
|
480
|
-
*/
|
|
481
|
-
private static readonly FORMS_BANG_RE;
|
|
482
|
-
/**
|
|
483
|
-
* Issue #46: scan `Set <var> = New <Type>[.<Inner>]` lines — the dominant
|
|
484
|
-
* VBA late-instantiation idiom. Run inside `sweepCallsAndSql`'s proc-stack
|
|
485
|
-
* loop so the surrounding procedure is known. For each match:
|
|
486
|
-
* - register `<var>` in `localVarTypeMap` with `outer=<Type>`,
|
|
487
|
-
* `qualified=<hasInner>`, `assignedWithSet=true` so the PR #61 refined
|
|
488
|
-
* gate lets subsequent `<var>.Member ...` qualified calls resolve via
|
|
489
|
-
* the resolved class name;
|
|
490
|
-
* - emit a `references` edge from the module/class node to a synthetic
|
|
491
|
-
* node named `<Type>`, tagged `synthesizedBy: 'vba-set-new'`.
|
|
492
|
-
*
|
|
493
|
-
* Groups: (1) variable name, (2) outer type, (3) optional inner type.
|
|
494
|
-
* Operates on the MASKED line (string-literal content already replaced
|
|
495
|
-
* with spaces) so `Set x = New Foo` inside a string literal never matches.
|
|
496
|
-
*/
|
|
497
|
-
private static readonly SET_NEW_RE;
|
|
498
|
-
/** Issue #43: track the receiver for `With <expr>` / `End With` blocks. */
|
|
499
|
-
private static readonly WITH_START_RE;
|
|
500
|
-
private static readonly WITH_END_RE;
|
|
501
|
-
/** Keywords we never want to match as call receivers. */
|
|
502
|
-
private static readonly CALL_KEYWORD_BLACKLIST;
|
|
503
|
-
/**
|
|
504
|
-
* Access runtime objects and singletons. Calls on these receivers are
|
|
505
|
-
* real VBA calls but the targets are NOT user-defined modules or
|
|
506
|
-
* classes — they're Access/DAO/ADO runtime types. Synthesizing a
|
|
507
|
-
* `function` node for each would pollute the graph with ~20+ junk
|
|
508
|
-
* nodes per real-world file (audit W4, June 2026). Skip synthesis
|
|
509
|
-
* for any receiver or member in this set.
|
|
510
|
-
*
|
|
511
|
-
* Note: `DoCmd.RunSQL`, `DoCmd.OpenForm`, etc. still get SQL/edge
|
|
512
|
-
* tracking via the dedicated `SQL_WRAPPERS` regex path (REQ-CODE-8),
|
|
513
|
-
* which fires BEFORE this scan and uses its own dispatch — so
|
|
514
|
-
* blacklisting DoCmd here doesn't lose the SQL-flow edges.
|
|
515
|
-
*/
|
|
516
|
-
private static readonly RUNTIME_RECEIVER_BLACKLIST;
|
|
517
|
-
/**
|
|
518
|
-
* Fix 2 (Issue #2): replace string-literal content with spaces so that
|
|
519
|
-
* call-site patterns inside `"..."` spans are invisible to CALL_RE and
|
|
520
|
-
* the statement-form detectors. Column positions are preserved (each
|
|
521
|
-
* character is replaced 1-for-1) so any col-based metadata stays correct.
|
|
522
|
-
*/
|
|
523
|
-
private static maskStringContent;
|
|
524
|
-
/**
|
|
525
|
-
* Fix 2 (Issue #2): return true iff `receiverName` is a file-local variable
|
|
526
|
-
* (appears in `localVarTypeMap`) whose declared type is a SIMPLE (non-
|
|
527
|
-
* qualified, non-primitive) identifier — a candidate project-defined class.
|
|
528
|
-
* Qualified types (e.g. `DAO.Recordset`) and primitives (`String`, `Long`)
|
|
529
|
-
* return false so runtime/DAO calls are suppressed.
|
|
530
|
-
*
|
|
531
|
-
* Issue #54 (defensive): brackets are stripped from the lookup key, so a
|
|
532
|
-
* caller that forgets to unwrap a bracketed name still finds the
|
|
533
|
-
* corresponding entry. This is a no-op when the name is already bare —
|
|
534
|
-
* the unwrap pattern only matches an opening `[` at the start and a
|
|
535
|
-
* closing `]` at the end. Today's call sites (`scanCallSites`,
|
|
536
|
-
* `detectQualifiedStatementCall`) already unwrap in the regex captures,
|
|
537
|
-
* so this defensive strip is a belt-and-braces guard for any future
|
|
538
|
-
* caller that forgets.
|
|
539
|
-
*/
|
|
540
|
-
private isLocalProjectClassVar;
|
|
541
|
-
/**
|
|
542
|
-
* Qualified-call eligibility is intentionally shared by paren-form
|
|
543
|
-
* (`Receiver.Member(...)`) and statement-form (`Receiver.Member args`) scans:
|
|
544
|
-
* project-class locals are processed after type resolution, declared
|
|
545
|
-
* primitive/external locals are silent, and undeclared receivers remain
|
|
546
|
-
* candidate module names.
|
|
547
|
-
*/
|
|
548
|
-
private shouldProcessQualifiedCall;
|
|
549
|
-
/**
|
|
550
|
-
* #12a: resolve the "receiver type" used to build a qualified call-stub's
|
|
551
|
-
* name/qualifiedName. When `receiverName` is a file-local variable typed
|
|
552
|
-
* as a candidate project class (`isLocalProjectClassVar`), returns the
|
|
553
|
-
* RESOLVED CLASS NAME from `localVarTypeMap` (e.g. `m_NCOp` typed
|
|
554
|
-
* `As NCOperaciones` → `'NCOperaciones'`) so the stub's qualifiedName
|
|
555
|
-
* matches the real `.cls` method's `${className}.${proc}` shape and the
|
|
556
|
-
* post-extraction resolver (#12b) can find it via an exact qualifiedName
|
|
557
|
-
* match. Otherwise returns `receiverName` unchanged — this is the case
|
|
558
|
-
* for `.bas`-qualified module calls (`modUtils.Foo`), where the receiver
|
|
559
|
-
* IS already the target module's name and no resolution is needed.
|
|
560
|
-
*/
|
|
561
|
-
private resolveReceiverType;
|
|
562
|
-
private normalizeWithReceiver;
|
|
563
|
-
private detectWithMemberCall;
|
|
564
|
-
private sweepCallsAndSql;
|
|
565
|
-
private static readonly RAISE_EVENT_RE;
|
|
566
|
-
private scanRaiseEvents;
|
|
567
|
-
private scanCallSites;
|
|
568
|
-
/** Cache so we don't re-emit the same proc function node per call site. */
|
|
569
|
-
private procNodeIdCache;
|
|
570
|
-
private callDedupe;
|
|
571
|
-
private synthFunctionNodeIds;
|
|
572
|
-
/**
|
|
573
|
-
* B4 (hueco 6) extended by Issue #48: cache of stub node ids we've already
|
|
574
|
-
* emitted for a given (method, target name) pair in this file. Avoids
|
|
575
|
-
* emitting duplicate stubs when `DoCmd.OpenForm "FormTest"` or
|
|
576
|
-
* `DoCmd.OpenReport "InformeMensual"` shows up N times across N calls.
|
|
577
|
-
* Keyed by `${cacheKey}:${lowerName}` so the OpenForm and OpenReport
|
|
578
|
-
* de-dup buckets stay disjoint — `OpenForm:Form1` ≠ `OpenReport:Form1`.
|
|
579
|
-
* The name part is lowercased so `FormTest` / `formtest` collapse.
|
|
580
|
-
*/
|
|
581
|
-
private opensStubIdsByKey;
|
|
582
|
-
/**
|
|
583
|
-
* Hueco 1: scan a line for `Me.<ControlName>` / `Me!<ControlName>`
|
|
584
|
-
* patterns and emit one UnresolvedReference per occurrence, tagged
|
|
585
|
-
* `metadata.synthesizedBy: 'vba-me-control'`. Issue #44 extended
|
|
586
|
-
* `ME_CONTROL_RE` from `Me\.` to `Me[.!]` so the bang form (default-
|
|
587
|
-
* collection shortcut) is captured byte-identically to the dot form.
|
|
588
|
-
*
|
|
589
|
-
* Operates on the masked `callScanLine` (string-literal content already
|
|
590
|
-
* replaced with spaces) so `Me.X` inside a string literal is not falsely
|
|
591
|
-
* captured. Per-site emission — every `Me.lblTitulo` reference site
|
|
592
|
-
* produces its own UnresolvedReference carrying the line/column; the
|
|
593
|
-
* resolver fans them out into multiple `references` edges at index time
|
|
594
|
-
* once the matching `form-instance-control` node exists.
|
|
595
|
-
*
|
|
596
|
-
* `fromNodeId` is the current procedure's function node — that's the
|
|
597
|
-
* "owner" of the reference (the Sub body that wrote `Me.lblTitulo = …`).
|
|
598
|
-
* The +3 column offset remains correct under Issue #44's regex change
|
|
599
|
-
* because both `Me.` and `Me!` are 3-character prefixes.
|
|
600
|
-
*/
|
|
601
|
-
private scanMeControlReferences;
|
|
602
|
-
/**
|
|
603
|
-
* Issue #44: scan a line for cross-form bang references
|
|
604
|
-
* (`Forms!<FormName>[!<Ctl>]` and `Forms("<FormName>")!<Ctl>`) and
|
|
605
|
-
* emit ONE UnresolvedReference per match with `metadata.synthesizedBy
|
|
606
|
-
* = 'vba-forms-bang'`. Companion to `scanMeControlReferences` above;
|
|
607
|
-
* shares the emission shape (a single `UnresolvedReference` per match,
|
|
608
|
-
* `referenceKind: 'references'`), keeping the W4 invariant that we
|
|
609
|
-
* synthesize NO `function` node for forms.
|
|
610
|
-
*
|
|
611
|
-
* Operates on the ORIGINAL (unmasked) line — the paren form
|
|
612
|
-
* `Forms("FormX")!txtY` carries the form name INSIDE a string literal
|
|
613
|
-
* and would be destroyed by `maskStringContent`. Mirrors
|
|
614
|
-
* `scanOpenFormCalls`'s unmasked-line constraint.
|
|
615
|
-
*
|
|
616
|
-
* Regex alternatives (see `FORMS_BANG_RE`):
|
|
617
|
-
* 1. `Forms!<FormName>` (bare or `[bracketed]`, NOT followed by `.X`)
|
|
618
|
-
* — bang form, may have a trailing `!<Ctl>[.<Prop>]` that is
|
|
619
|
-
* consumed but NOT emitted.
|
|
620
|
-
* 2. `Forms("<FormName>")!<Ctl>` (quoted or bare/bracketed form arg)
|
|
621
|
-
* — paren form, ALWAYS with a control segment.
|
|
622
|
-
*
|
|
623
|
-
* Stripping: the form's identifier is unwrapped of `"` quotes (string
|
|
624
|
-
* literals) and `[…]` brackets (Issue #54 reserved-identifier shape) so
|
|
625
|
-
* the public `referenceName` is the bare form name. Bracketed forms
|
|
626
|
-
* (`Forms![Mi Formulario]`) follow the same strip rules as the paren
|
|
627
|
-
* form so the resolver sees `Mi Formulario` either way.
|
|
628
|
-
*/
|
|
629
|
-
private scanFormsBang;
|
|
630
|
-
private findOrCreateFunctionNodeId;
|
|
631
|
-
private findFunctionNodeByName;
|
|
632
|
-
/**
|
|
633
|
-
* Issue #45: split a single-line VBA `If <cond> Then <body>` into one or
|
|
634
|
-
* more statement-clause fragments that the existing `detectStatementCall`
|
|
635
|
-
* and `detectQualifiedStatementCall` detectors can process. Handles:
|
|
636
|
-
*
|
|
637
|
-
* - `If x Then Foo` → `['Foo']`
|
|
638
|
-
* - `If x Then Foo Else Bar` → `['Foo', 'Bar']`
|
|
639
|
-
* - `If x Then DoA: DoB` → `['DoA', 'DoB']` (colon-separated multi-statement)
|
|
640
|
-
* - `If x Then Foo Else A: B` → `['Foo', 'A', 'B']`
|
|
641
|
-
* - `If x Then GoTo fin` → `[]` (GoTo clause filtered out)
|
|
642
|
-
* - `If x Then Exit Sub` → `[]` (Exit clause filtered out)
|
|
643
|
-
*
|
|
644
|
-
* When the line does NOT match a single-line `If … Then` shape — for
|
|
645
|
-
* instance a block-form `If x Then` whose body lives on subsequent
|
|
646
|
-
* lines — the splitter returns `[<line>]` (the original input) so
|
|
647
|
-
* callers can use this method unconditionally and let the existing
|
|
648
|
-
* per-line scan pick up the body on a separate line.
|
|
649
|
-
*
|
|
650
|
-
* `GoTo`, `Exit`, and `Resume` clauses are filtered at the fragment
|
|
651
|
-
* level (defense in depth): even though `emitStatementCallEdge` already
|
|
652
|
-
* drops these via the `CALL_KEYWORD_BLACKLIST`, filtering here prevents
|
|
653
|
-
* any chance of `detectStatementCall`'s generic identifier extractor
|
|
654
|
-
* matching a substring (e.g. an identifier like `GoToFinishingTouches`)
|
|
655
|
-
* as a side effect of a richer clause where the keyword happens to be
|
|
656
|
-
* the leading token.
|
|
657
|
-
*
|
|
658
|
-
* `line` is the string-literal-masked scan line. The mask makes global
|
|
659
|
-
* `:` splitting safe: real VBA colons never appear inside string
|
|
660
|
-
* literals (already masked to spaces) and never inside expressions
|
|
661
|
-
* inside parens at the source level (a colon ends a statement in VBA,
|
|
662
|
-
* so it cannot appear inside a parenthesised argument list either).
|
|
663
|
-
* The `Else` keyword is a VBA statement-level separator and is
|
|
664
|
-
* forbidden inside parens or expressions, so splitting on
|
|
665
|
-
* `\s+Else\s+` does not need paren tracking either.
|
|
666
|
-
*/
|
|
667
|
-
private splitSingleLineIfClauses;
|
|
668
|
-
/**
|
|
669
|
-
* H1: detect a statement-form Sub call.
|
|
670
|
-
*
|
|
671
|
-
* Real VBA idioms:
|
|
672
|
-
* `MySub` — bare no-argument statement call
|
|
673
|
-
* `MySub arg1, Nz(x, 0)` — bare statement call
|
|
674
|
-
* `Call MySub arg1, Nz(x, 0)` — Call keyword, no parens around call
|
|
675
|
-
* `MySub(arg1, arg2)` — parens call (handled by CALL_RE)
|
|
676
|
-
* `Call MySub(arg1, arg2)` — Call keyword + parens (also CALL_RE)
|
|
677
|
-
*
|
|
678
|
-
* Returns the called proc name if the line matches the statement form
|
|
679
|
-
* AND the proc name is in localProcs (same-file resolution). Returns
|
|
680
|
-
* null for declarations, assignments, comments, keyword lines, etc.
|
|
681
|
-
*
|
|
682
|
-
* The `Call` keyword form is handled by stripping `Call ` and
|
|
683
|
-
* running the same logic on the remainder — they're structurally the
|
|
684
|
-
* same call after the keyword.
|
|
685
|
-
*/
|
|
686
|
-
private detectStatementCall;
|
|
687
|
-
/**
|
|
688
|
-
* H1: emit a same-file `calls` edge for a statement-form Sub call.
|
|
689
|
-
* `caller` is the current procedure (from the stack); `procName` is
|
|
690
|
-
* the called procedure name. Emits a plain `calls` edge to the
|
|
691
|
-
* already-emitted function node.
|
|
692
|
-
*/
|
|
693
|
-
private emitStatementCallEdge;
|
|
694
|
-
/**
|
|
695
|
-
* Fix 7: detect a qualified statement-form call — `Receiver.Member <args>`
|
|
696
|
-
* where `Receiver.Member` is NOT followed by `(`.
|
|
697
|
-
*
|
|
698
|
-
* Real VBA idioms this covers:
|
|
699
|
-
* `m_NCOp.Registrar m_ARAlInicio, p_Error`
|
|
700
|
-
* `m_Obj.Init`
|
|
701
|
-
*
|
|
702
|
-
* These are distinct from the paren form (`m_NCOp.Registrar(...)`) which is
|
|
703
|
-
* already handled by `CALL_RE`. Returns `{receiver, member}` or `null`.
|
|
704
|
-
*
|
|
705
|
-
* Property assignments (`Receiver.Prop = value`) are excluded via the `=`
|
|
706
|
-
* guard — consistent with `detectStatementCall`'s same-file assignment skip.
|
|
707
|
-
* Blacklisted receivers (runtime objects, keywords) are excluded too.
|
|
708
|
-
*/
|
|
709
|
-
private detectQualifiedStatementCall;
|
|
710
|
-
/**
|
|
711
|
-
* Fix 7: emit a heuristic `calls` edge for a qualified statement-form call.
|
|
712
|
-
* Same shape as the qualified-paren path in `scanCallSites` — reuses the
|
|
713
|
-
* same `callDedupe` / `synthFunctionNodeIds` sets for de-duplication so a
|
|
714
|
-
* paren and non-paren form on the same line don't create duplicate edges.
|
|
715
|
-
*/
|
|
716
|
-
private emitQualifiedStatementCallEdge;
|
|
717
|
-
/**
|
|
718
|
-
* B4 (hueco 6) extended by Issue #48: scan one line of VBA source for
|
|
719
|
-
* `DoCmd.OpenX "Target"` calls where X ∈ {Form, Report} (see the
|
|
720
|
-
* `DOCMD_OPEN_DISPATCH` table). For each match, emit:
|
|
721
|
-
* - a stub node (form-layout / report-layout) for the target, cached
|
|
722
|
-
* per-(method, name) so the same target referenced from N sites
|
|
723
|
-
* emits exactly ONE stub,
|
|
724
|
-
* - an `opens-form` / `opens-report` heuristic edge from the calling
|
|
725
|
-
* Sub to that stub.
|
|
726
|
-
*
|
|
727
|
-
* Both endpoints are pushed into `this.nodes` / `this.edges`, so the
|
|
728
|
-
* per-file edge filter at `index.ts:insertedIds.has(source) &&
|
|
729
|
-
* insertedIds.has(target)` passes the edge naturally without any
|
|
730
|
-
* exemption to the filter.
|
|
731
|
-
*
|
|
732
|
-
* Why a stub and not a direct lookup: the target form/report lives in a
|
|
733
|
-
* DIFFERENT file (its own `.form.txt` / `.report.txt`), and the extractor
|
|
734
|
-
* doesn't have DB access at parse time. The stub's synthetic file path
|
|
735
|
-
* (`synthetic:opensFormStub/<Name>.form.txt` /
|
|
736
|
-
* `synthetic:opensReportStub/<Name>.form.txt`) guarantees a deterministic
|
|
737
|
-
* node id so re-indexes collapse to the same stub. When the consumer's
|
|
738
|
-
* `.form.txt` / `.report.txt` is later indexed, the real
|
|
739
|
-
* `form-layout` / `report-layout` node carries a different id (it uses
|
|
740
|
-
* the real file path); the stub and the real coexist harmlessly.
|
|
741
|
-
*
|
|
742
|
-
* Why a separate dispatch from CALL_RE: `DoCmd` is in
|
|
743
|
-
* `RUNTIME_RECEIVER_BLACKLIST` (R4 invariant), so `DoCmd.OpenForm` /
|
|
744
|
-
* `DoCmd.OpenReport` are intentionally SKIPPED by the generic CALL_RE
|
|
745
|
-
* path that would otherwise emit a junk `calls` edge to a synthetic
|
|
746
|
-
* `function` node for `DoCmd.OpenX`. The dispatch below matches BEFORE
|
|
747
|
-
* the call-site scan and uses its own emission path.
|
|
748
|
-
*
|
|
749
|
-
* Scope note: literal-string and bare-identifier argument forms are
|
|
750
|
-
* supported. Bare identifiers resolve only through local `Const`
|
|
751
|
-
* declarations; arbitrary variable data-flow remains intentionally
|
|
752
|
-
* out of scope.
|
|
753
|
-
*/
|
|
754
|
-
private scanDoCmdOpenCalls;
|
|
755
|
-
/**
|
|
756
|
-
* B4 (hueco 6) extended by Issue #48: emit a stub `form-layout` /
|
|
757
|
-
* `report-layout` node for `targetName` (cached per dispatch entry so
|
|
758
|
-
* duplicates collapse and OpenForm/OpenReport de-dup buckets stay
|
|
759
|
-
* disjoint) and a single `opens-form` / `opens-report` heuristic edge
|
|
760
|
-
* from `caller` to that stub.
|
|
761
|
-
*
|
|
762
|
-
* The edge carries:
|
|
763
|
-
* - `kind` — dispatch-specific (`opens-form` / `opens-report`)
|
|
764
|
-
* - `provenance: 'heuristic'` — synthesized, not parsed
|
|
765
|
-
* - `metadata.<dispatchTargetKey>` (e.g. `targetFormName`) — the resolved name
|
|
766
|
-
* - `metadata.synthesizedBy` — dispatch-specific (`vba-opens-form` /
|
|
767
|
-
* `vba-opens-report`); distinguishes this synthesis from the
|
|
768
|
-
* dim/sql/event-handler families
|
|
769
|
-
*
|
|
770
|
-
* The stub's `metadata.stub: true` flag lets downstream UI render
|
|
771
|
-
* stubs distinctly (e.g. with a dashed border) and gives later
|
|
772
|
-
* re-resolution pass a hook for collapse. The stub is
|
|
773
|
-
* line-independent (`line = 0`) so re-indexes produce identical ids.
|
|
774
|
-
*/
|
|
775
|
-
private emitOpensStubEdge;
|
|
776
|
-
/**
|
|
777
|
-
* Issue #48: scan one line of VBA source for `DoCmd.OpenQuery "X"` calls.
|
|
778
|
-
* Each match emits ONE `UnresolvedReference` (NOT a stub + edge) so the
|
|
779
|
-
* resolver binds to the REAL `query` node that `SqlQueryExtractor`
|
|
780
|
-
* produces for `queries/<Name>.sql` (dysflow exports every saved QueryDef
|
|
781
|
-
* + `queries.json` manifest). Falls back to silent when the .sql is not
|
|
782
|
-
* yet in the index — the resolver does the binding when it's later
|
|
783
|
-
* indexed, exactly like `vba-me-control` and `vba-forms-bang`.
|
|
784
|
-
*
|
|
785
|
-
* Companion to `scanDoCmdOpenCalls` but intentionally NOT in the
|
|
786
|
-
* dispatch table — OpenQuery's emission shape (`UnresolvedReference`)
|
|
787
|
-
* is structurally different from OpenForm/OpenReport's (synthetic node
|
|
788
|
-
* + heuristic edge). The two pipelines share the literal-vs-Const
|
|
789
|
-
* argument resolution pattern via `localConstants.get(...)` but emit
|
|
790
|
-
* via two different branches of `unresolvedReferences` vs
|
|
791
|
-
* `nodes`/`edges`.
|
|
792
|
-
*
|
|
793
|
-
* UnresolvedReference shape (per Issue #48 spec — must match
|
|
794
|
-
* SqlQueryExtractor's query node name exactly):
|
|
795
|
-
* - `referenceName` = resolved query name
|
|
796
|
-
* - `referenceKind: 'references'` = same kind the resolver binds
|
|
797
|
-
* - `metadata.synthesizedBy: 'vba-opens-query'`
|
|
798
|
-
* - NO synthetic `function` node (W4 graph-pollution invariant — the
|
|
799
|
-
* real `query` node already exists in the index once `.sql` is
|
|
800
|
-
* processed, and creating stubs would compete with the binding).
|
|
801
|
-
*/
|
|
802
|
-
private scanDoCmdOpenQuery;
|
|
803
|
-
/**
|
|
804
|
-
* Regex matching the chained `& "..."` literals that may follow a
|
|
805
|
-
* wrapper's first literal on the same physical line. Captures the
|
|
806
|
-
* literal CONTENT (group 1); the surrounding `&` and quotes are
|
|
807
|
-
* structural, not data. VBA allows whitespace around `&` and around
|
|
808
|
-
* the inner quotes — handled with `\s*`. The `((?:[^"]|"")*)` body
|
|
809
|
-
* mirrors the wrapper regex so a `""` inside a chained literal still
|
|
810
|
-
* decodes to a single `"`.
|
|
811
|
-
*
|
|
812
|
-
* Cross-physical-line concat via `_` continuation is OUT OF SCOPE for
|
|
813
|
-
* v1 (deferred; see commit message).
|
|
814
|
-
*/
|
|
815
|
-
private static readonly SQL_WRAPPER_CHAIN_RE;
|
|
816
|
-
/**
|
|
817
|
-
* Given the text that follows a SQL wrapper's first literal on the same
|
|
818
|
-
* physical line, return the contents of every `& "..."` chained literal
|
|
819
|
-
* in source order. Operates per-physical-line only — VBA `_` line
|
|
820
|
-
* continuation across physical lines is handled separately by
|
|
821
|
-
* `collectStringLiteralText` for the variable-assignment path.
|
|
822
|
-
*/
|
|
823
|
-
private collectSqlWrapperChain;
|
|
824
|
-
private scanSqlInLine;
|
|
825
|
-
/**
|
|
826
|
-
* #13 fix: `sql = sql & "..."` (self-referential concatenation) must
|
|
827
|
-
* ACCUMULATE the new fragment onto whatever was already tracked for
|
|
828
|
-
* `varName`, not overwrite it. Overwriting silently dropped earlier
|
|
829
|
-
* fragments' tables — typically the initial `FROM <table>` in
|
|
830
|
-
* `sql = "SELECT * FROM tblA"` followed by `sql = sql & " WHERE x=1"`.
|
|
831
|
-
*
|
|
832
|
-
* Detection: the RHS (`m[2]`, trimmed) starts with `<varName> &`,
|
|
833
|
-
* case-insensitively — matching VBA's case-insensitive identifiers (`Sql`
|
|
834
|
-
* and `sql` are the same variable). A genuine fresh assignment (RHS does
|
|
835
|
-
* NOT start with the self-reference) still RESETS tracking — that
|
|
836
|
-
* behavior is unchanged.
|
|
837
|
-
*/
|
|
838
|
-
private trackSqlVariableAssignment;
|
|
839
|
-
private collectStringLiteralText;
|
|
840
|
-
private emitSqlTableReferences;
|
|
841
|
-
/**
|
|
842
|
-
* Emit a `references` edge from the file's module/class node to a synthetic
|
|
843
|
-
* node named `targetName`. Used by Dim, WithEvents, Implements, and SQL.
|
|
844
|
-
*/
|
|
845
|
-
private emitReference;
|
|
846
|
-
private synthClassNodeIds;
|
|
847
|
-
/**
|
|
848
|
-
* Issue #50: TempVars placeholder-node de-dup cache. Keys are the
|
|
849
|
-
* deterministic node ids produced by `emitTempVarReference` — those
|
|
850
|
-
* ids intentionally ignore `this.filePath` (use a synthetic
|
|
851
|
-
* `synthetic:tempvar/<key>` path instead) so the SAME key referenced
|
|
852
|
-
* from Form_A.cls AND Form_B.cls collapses to ONE placeholder node.
|
|
853
|
-
* Cross-file id stability is the cross-form state premise that makes
|
|
854
|
-
* `codegraph_explore` connect producer ⇄ consumer in one hop.
|
|
855
|
-
*/
|
|
856
|
-
private synthTempVarNodeIds;
|
|
857
|
-
/**
|
|
858
|
-
* Issue #50: emit one TempVar reading/writing site. Per call:
|
|
859
|
-
* - placeholder `class` node keyed on the synthetic
|
|
860
|
-
* `synthetic:tempvar/<key>` file path so cross-file extraction
|
|
861
|
-
* calls collapse to one node per key,
|
|
862
|
-
* - `references` edge from the calling `function` node
|
|
863
|
-
* (via `findOrCreateFunctionNodeId` — same access pattern as
|
|
864
|
-
* `scanDoCmdOpenCalls` / `scanDoCmdOpenQuery`) carrying
|
|
865
|
-
* `metadata.synthesizedBy: 'vba-tempvar'` AND
|
|
866
|
-
* `metadata.access: 'read' | 'write'`.
|
|
867
|
-
*
|
|
868
|
-
* Reuses the synthetic-`class`-placeholder shape established by
|
|
869
|
-
* `emitReference` for SQL tables, events, Dim types, etc. — so every
|
|
870
|
-
* synthesized `references` edge in the file already carries the same
|
|
871
|
-
* `kind: 'class'` target, and downstream consumers (UI, resolvers,
|
|
872
|
-
* search queries) filter on `metadata.synthesizedBy` rather than
|
|
873
|
-
* NodeKind anyway. The `metadata.synthesizedBy` tag cleanly distinguishes
|
|
874
|
-
* TempVars refs from SQL-table refs inside the same NodeKind bucket.
|
|
875
|
-
*
|
|
876
|
-
* Skips when stack is empty (the writer/reader is module-level code
|
|
877
|
-
* — REQ-CODE-4 "unresolvable/runtime reference is silent"). The
|
|
878
|
-
* spec wires this per-proc only; the module-level shape would need
|
|
879
|
-
* a different emission (no procedure source) and is out of scope.
|
|
880
|
-
*/
|
|
881
|
-
private emitTempVarReference;
|
|
882
|
-
/**
|
|
883
|
-
* Issue #50: scan one line of VBA source for TempVars access sites and
|
|
884
|
-
* emit one `references` edge per site. Three regex runs:
|
|
885
|
-
* - bang form `TempVars!x` over the MASKED line (`!` itself never
|
|
886
|
-
* lives inside a string literal, so masked == unmasked here — using
|
|
887
|
-
* the masked line is conservative against false positives in
|
|
888
|
-
* concatenated string content),
|
|
889
|
-
* - paren form `TempVars("x")` over the ORIGINAL line (the literal is
|
|
890
|
-
* inside a string — masked would strip the key),
|
|
891
|
-
* - Add form `TempVars.Add "x", v` over the ORIGINAL line (same reason),
|
|
892
|
-
* always classified as a write.
|
|
893
|
-
*
|
|
894
|
-
* Each match classifies access by looking at the LINE SUFFIX (after the
|
|
895
|
-
* closing paren / bang-key) on the SAME line: if `=` (and not the
|
|
896
|
-
* nonexistent `==`) is the next non-whitespace character, it's a write.
|
|
897
|
-
* VBA has no `==` so a bare `=` suffix check is safe.
|
|
898
|
-
*
|
|
899
|
-
* The caller parameter comes from `stack[stack.length - 1]` in
|
|
900
|
-
* `sweepCallsAndSql`. Pass `undefined` for module-level access — we
|
|
901
|
-
* drop the edge (per REQ-CODE-4 spirit, runtime references have no
|
|
902
|
-
* static source to anchor against).
|
|
903
|
-
*/
|
|
904
|
-
private sweepTempVars;
|
|
905
|
-
/**
|
|
906
|
-
* Maps `variableName.toLowerCase()` → declared type info.
|
|
907
|
-
* Built by `sweepDimsAndWithEvents`; consulted by the unified qualified-call
|
|
908
|
-
* gate (`shouldProcessQualifiedCall`) so declared project-class locals emit
|
|
909
|
-
* edges, declared primitive/external locals stay silent, and undeclared
|
|
910
|
-
* receivers remain module-name candidates for the resolver (Fix 2 / Issue #2).
|
|
911
|
-
*/
|
|
912
|
-
private localVarTypeMap;
|
|
913
|
-
/**
|
|
914
|
-
* Issue #52: Const resolution buckets, scoped per procedure. Key is
|
|
915
|
-
* `'module'` for module-level Consts, or the procedure's `startLine`
|
|
916
|
-
* (stringified) for proc-local Consts. Each bucket maps the lowercase
|
|
917
|
-
* constant name to its simple-literal value (used by `DoCmd.OpenForm` /
|
|
918
|
-
* `OpenReport` / `OpenQuery` argument resolution via `resolveLocalConst`).
|
|
919
|
-
*
|
|
920
|
-
* Two procs declaring the same Const name with different values stay
|
|
921
|
-
* isolated (each in its own bucket); reads look up the current proc's
|
|
922
|
-
* bucket first and fall back to the module bucket. The bucket-per-proc
|
|
923
|
-
* model was chosen over a single file-wide Map (the pre-fix shape) so
|
|
924
|
-
* `DoCmd.OpenForm FORM_DESTINO` resolves to the proc-local value, not
|
|
925
|
-
* whichever was written last.
|
|
926
|
-
*/
|
|
927
|
-
private localConstants;
|
|
928
|
-
/**
|
|
929
|
-
* Issue #52: shared lookup helper for `scanDoCmdOpenCalls` and
|
|
930
|
-
* `scanDoCmdOpenQuery`. The current scope is the procedure whose
|
|
931
|
-
* `startLine` is on top of `procStack` (or `'module'` when the stack is
|
|
932
|
-
* empty). Per-proc bucket first; module bucket is the fallback.
|
|
933
|
-
*/
|
|
934
|
-
private resolveLocalConst;
|
|
935
|
-
/**
|
|
936
|
-
* Issue #52: shared writer. `scopeKey` is `'module'` or the procedure's
|
|
937
|
-
* startLine-as-string. Creates the bucket lazily so callers do not have
|
|
938
|
-
* to pre-allocate per proc. Returns the bucket the value was written to
|
|
939
|
-
* (mostly useful for tests; production code ignores it).
|
|
940
|
-
*/
|
|
941
|
-
private setLocalConstInScope;
|
|
942
|
-
/**
|
|
943
|
-
* Issue #52: the current Const-lookup scope. `'module'` when no procedure
|
|
944
|
-
* is open, otherwise the top-of-stack proc's `startLine` as a string.
|
|
945
|
-
* Both `sweepEnumsAndConsts` (to decide whether to emit a `constant`
|
|
946
|
-
* node) and `sweepCallsAndSql` (to drive OpenForm/OpenQuery resolution)
|
|
947
|
-
* keep this in sync with their per-line stack walk by pushing/popping
|
|
948
|
-
* `procStack` and writing the new top's key here.
|
|
949
|
-
*/
|
|
950
|
-
private currentProcKey;
|
|
951
|
-
/**
|
|
952
|
-
* Issue #52: per-extraction proc-stack shared between `sweepEnumsAndConsts`
|
|
953
|
-
* and `sweepCallsAndSql`. Each sweep clears it at the start so the file's
|
|
954
|
-
* mid-proc structural state never leaks across sweeps. Holds the
|
|
955
|
-
* `startLine` (1-based, matches `ProcInfo.startLine`) of every procedure
|
|
956
|
-
* whose body the sweep has not yet emitted `End Sub`/`End Function`/
|
|
957
|
-
* `End Property` for.
|
|
958
|
-
*/
|
|
959
|
-
private procStack;
|
|
960
|
-
/** Local event name (lowercase) → event node for `RaiseEvent` edge emission. */
|
|
961
|
-
private localEvents;
|
|
962
14
|
}
|
|
963
15
|
//# sourceMappingURL=vba-extractor.d.ts.map
|