Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Changed

- VBA extraction now exposes only the classifier factories used by the shared source walker, removing obsolete compatibility entry points and other unused public helpers. (#217)

### Fixes

- VBA references mentioned only inside messages, logs, and other string literals no longer create false form, query, or temporary-variable relationships. (#209)
Expand Down
38 changes: 38 additions & 0 deletions __tests__/extraction-vba-dead-exports.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { readFileSync } from 'node:fs';
import { describe, expect, it } from 'vitest';

const readSource = (relativePath: string): string =>
readFileSync(new URL(`../src/${relativePath}`, import.meta.url), 'utf8');

describe('VBA extraction public surface', () => {
it('keeps the split-once classifiers free of legacy source wrappers', () => {
const wrappers = [
['extraction/vba/procedures.ts', 'sweepProcedures'],
['extraction/vba/dims.ts', 'sweepDimsAndWithEvents'],
['extraction/vba/declarations.ts', 'sweepEventsTypesAndDeclares'],
['extraction/vba/implements.ts', 'sweepImplements'],
['extraction/vba/enums-consts.ts', 'sweepEnumsAndConsts'],
['extraction/vba/call-sweep.ts', 'sweepCallsAndSql'],
] as const;

for (const [path, wrapper] of wrappers) {
const source = readSource(path);
expect(source, path).not.toContain(`function ${wrapper}`);
expect(source, path).not.toContain("src.split('\\n')");
}
});

it('removes or narrows internal-only exports while preserving RUNTIME_OBJECTS', () => {
expect(readSource('extraction/vba-source.ts')).not.toContain('function stripUtf8Bom');
expect(readSource('extraction/vba/text-utils.ts')).not.toContain(
'export function splitOutsideVbaStrings',
);
expect(readSource('extraction/vba-test-manifest-extractor.ts')).not.toContain(
'export function isVbaTestManifestShape',
);

const runtimeObjects = readSource('resolution/vba-runtime-objects.ts');
expect(runtimeObjects).not.toContain('export const VBA_STDLIB_FUNCTIONS');
expect(runtimeObjects).toContain('export const RUNTIME_OBJECTS');
});
});
10 changes: 7 additions & 3 deletions __tests__/extraction-vba-issue-207.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import { describe, it, expect } from 'vitest';
import { VbaExtractor } from '../src/extraction/vba-extractor';
import { VbaExtractorContext } from '../src/extraction/vba/context';
import { sweepDimsAndWithEvents } from '../src/extraction/vba/dims';
import { createDimsClassifier } from '../src/extraction/vba/dims';

function extract(filePath: string, source: string) {
return new VbaExtractor(filePath, source).extract();
Expand Down Expand Up @@ -56,7 +56,11 @@ function dimMapFor(source: string): Map<
{ outer: string; qualified: boolean }
> {
const ctx = new VbaExtractorContext('src/modules/m.bas');
sweepDimsAndWithEvents(ctx, source);
const classifier = createDimsClassifier();
const lines = source.split('\n');
for (let i = 0; i < lines.length; i++) {
classifier.classifyLine(lines[i] ?? '', i, ctx);
}
return ctx.localVarTypeMap;
}

Expand Down Expand Up @@ -232,4 +236,4 @@ describe('Issue #207 — DIM_DECL_PREFIX_RE lookahead must exclude Declare/Event
expect(referencedTypeNames(r)).toHaveLength(0);
});
});
});
});
13 changes: 0 additions & 13 deletions src/extraction/vba-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,16 +122,3 @@ export function readVbaSource(
return { text, bomStripped };
}
}

/**
* String-level BOM strip — survives when the upstream `fsp.readFile(path, 'utf-8')`
* already decoded the bytes (it's the only way the `\uFEFF` char survives in
* a string). Used as a defensive last resort when a read site has NOT gone
* through `readVbaSource` and the source text starts with the BOM marker.
*
* Most call sites should prefer `readVbaSource` for fresh reads; this is
* a string post-process for callers that already have a `string` in hand.
*/
export function stripUtf8Bom(text: string): string {
return text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;
}
2 changes: 1 addition & 1 deletion src/extraction/vba-test-manifest-extractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ interface ManifestTestEntry {
* array with at least one item carrying a string `procedure`? Pure; the file's
* basename is gated separately by `isVbaTestManifestFile` in `grammars.ts`.
*/
export function isVbaTestManifestShape(parsed: unknown): boolean {
function isVbaTestManifestShape(parsed: unknown): boolean {
if (!parsed || typeof parsed !== 'object') return false;
const tests = (parsed as { tests?: unknown }).tests;
if (!Array.isArray(tests)) return false;
Expand Down
16 changes: 1 addition & 15 deletions src/extraction/vba/call-sweep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/
import { PROC_RE, PROCEDURE_END_RE, PRIMITIVE_TYPES, isVbaKeyword } from './constants';
import { maskStringContent } from './text-utils';
import { VbaExtractorContext, ProcInfo, VbaClassifier } from './context';
import { ProcInfo, VbaClassifier } from './context';
import { defineRule, matchRuleForScan, VbaExtractionRule } from './rules';
import {
scanRaiseEvents,
Expand Down Expand Up @@ -450,17 +450,3 @@ export function createCallsAndSqlClassifier(

return cls;
}

/**
* Backward-compat wrapper (see procedures.ts). Returns void — the calls
* sweep never contributed to `hasAnySymbols` directly (every other
* concern's `count` is the signal the orchestrator reads).
*/
export function sweepCallsAndSql(ctx: VbaExtractorContext, src: string): void {
const lines = src.split('\n');
const cls = createCallsAndSqlClassifier(lines);
for (let i = 0; i < lines.length; i++) {
cls.classifyLine(lines[i] ?? '', i, ctx);
}
cls.finalize?.(ctx);
}
15 changes: 1 addition & 14 deletions src/extraction/vba/declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { Node } from '../../types';
import { generateNodeId } from '../tree-sitter-helpers';
import { foldVisibility } from './text-utils';
import { VbaExtractorContext, VbaClassifier } from './context';
import { VbaClassifier } from './context';
import { defineRule, matchRule, VbaExtractionRule } from './rules';

/** `[visibility] Event <Name>(...)` custom event declaration. */
Expand Down Expand Up @@ -257,16 +257,3 @@ export function createEventsTypesDeclaresClassifier(): VbaClassifier {
};
return cls;
}

/**
* Backward-compat wrapper (see procedures.ts). Returns the classifier's
* `count` so the orchestrator can decide `hasAnySymbols`.
*/
export function sweepEventsTypesAndDeclares(ctx: VbaExtractorContext, src: string): number {
const cls = createEventsTypesDeclaresClassifier();
const lines = src.split('\n');
for (let i = 0; i < lines.length; i++) {
cls.classifyLine(lines[i] ?? '', i, ctx);
}
return cls.count;
}
15 changes: 1 addition & 14 deletions src/extraction/vba/dims.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import { Edge } from '../../types';
import { generateNodeId } from '../tree-sitter-helpers';
import { PRIMITIVE_TYPES, PROC_RE, PROCEDURE_END_RE } from './constants';
import { VbaExtractorContext, VbaClassifier } from './context';
import { VbaClassifier } from './context';
import { defineRule, matchRule, VbaExtractionRule } from './rules';

/**
Expand Down Expand Up @@ -346,16 +346,3 @@ export function createDimsClassifier(): VbaClassifier {
},
};
}

/**
* Backward-compat wrapper (see procedures.ts). Returns the classifier's
* `count` so the orchestrator can decide `hasAnySymbols`.
*/
export function sweepDimsAndWithEvents(ctx: VbaExtractorContext, src: string): number {
const cls = createDimsClassifier();
const lines = src.split('\n');
for (let i = 0; i < lines.length; i++) {
cls.classifyLine(lines[i] ?? '', i, ctx);
}
return cls.count;
}
15 changes: 1 addition & 14 deletions src/extraction/vba/enums-consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import { generateNodeId } from '../tree-sitter-helpers';
import { PROC_RE, PROCEDURE_END_RE } from './constants';
import { foldVisibility, parseConstDeclarations } from './text-utils';
import { VbaExtractorContext, VbaClassifier } from './context';
import { VbaClassifier } from './context';
import { defineRule, matchRule, VbaExtractionRule } from './rules';

/** `[visibility] Enum <Name>` — opens an enum block. */
Expand Down Expand Up @@ -264,16 +264,3 @@ export function createEnumsConstsClassifier(): VbaClassifier {
};
return cls;
}

/**
* Backward-compat wrapper (see procedures.ts). Returns the classifier's
* `count` so the orchestrator can decide `hasAnySymbols`.
*/
export function sweepEnumsAndConsts(ctx: VbaExtractorContext, src: string): number {
const cls = createEnumsConstsClassifier();
const lines = src.split('\n');
for (let i = 0; i < lines.length; i++) {
cls.classifyLine(lines[i] ?? '', i, ctx);
}
return cls.count;
}
15 changes: 1 addition & 14 deletions src/extraction/vba/implements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/
import { Edge } from '../../types';
import { generateNodeId } from '../tree-sitter-helpers';
import { VbaExtractorContext, VbaClassifier } from './context';
import { VbaClassifier } from './context';
import { defineRule, matchRule, VbaExtractionRule } from './rules';

/** Implements regex. */
Expand Down Expand Up @@ -88,16 +88,3 @@ export function createImplementsClassifier(): VbaClassifier {
},
};
}

/**
* Backward-compat wrapper (see procedures.ts). Returns the classifier's
* `count` so the orchestrator can decide `hasAnySymbols`.
*/
export function sweepImplements(ctx: VbaExtractorContext, src: string): number {
const cls = createImplementsClassifier();
const lines = src.split('\n');
for (let i = 0; i < lines.length; i++) {
cls.classifyLine(lines[i] ?? '', i, ctx);
}
return cls.count;
}
18 changes: 1 addition & 17 deletions src/extraction/vba/procedures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Node, Edge } from '../../types';
import { generateNodeId } from '../tree-sitter-helpers';
import { PROC_RE, PRIMITIVE_TYPES } from './constants';
import { parseEventHandlerName } from './text-utils';
import { VbaExtractorContext, ProcInfo, VbaClassifier } from './context';
import { ProcInfo, VbaClassifier } from './context';
import { defineRule, matchRule, VbaExtractionRule } from './rules';

/**
Expand Down Expand Up @@ -309,19 +309,3 @@ export function createProceduresClassifier(): VbaClassifier {
},
};
}

/**
* Backward-compat wrapper: pre-#83 callers (e.g. legacy test fixtures)
* used `sweepProcedures(ctx, src)` and got back the ProcInfo[].
* Now it returns `ctx.procedures` (the same flat list the factory
* appends to). The implementation still calls the classifier once per
* pre-split line, so the count is identical to the new walker path.
*/
export function sweepProcedures(ctx: VbaExtractorContext, src: string): ProcInfo[] {
const cls = createProceduresClassifier();
const lines = src.split('\n');
for (let i = 0; i < lines.length; i++) {
cls.classifyLine(lines[i] ?? '', i, ctx);
}
return ctx.procedures;
}
2 changes: 1 addition & 1 deletion src/extraction/vba/text-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export function parseConstDeclarations(
return declarations;
}

export function splitOutsideVbaStrings(value: string, separator: string): string[] {
function splitOutsideVbaStrings(value: string, separator: string): string[] {
const parts: string[] = [];
let current = '';
let inString = false;
Expand Down
2 changes: 1 addition & 1 deletion src/resolution/vba-runtime-objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export function isRuntimeObject(receiver: string | null | undefined): boolean {
}

/** Canonical VBA and Access built-in functions that never resolve to project code. */
export const VBA_STDLIB_FUNCTIONS: ReadonlySet<string> = new Set([
const VBA_STDLIB_FUNCTIONS: ReadonlySet<string> = new Set([
'cstr', 'cint', 'clng', 'cdbl', 'csng', 'cbyte', 'cbool', 'cdate', 'cverr',
'isnull', 'isempty', 'isnumeric', 'isdate', 'isarray', 'isobject', 'ismissing',
'typename', 'vartype', 'len', 'lenb', 'instr', 'instrb', 'instrrev', 'lcase',
Expand Down