Skip to content

fix: vba-extractor — audit and fix VBA structural-recognition gaps from F.1 spike #167

Description

@ardelperal

Issue 4 — [P1] fix: vba-extractor — audit and fix VBA structural-recognition gaps from F.1 spike

Context

The F.1 spike report (docs/spikes/vbnet-as-vba.md, "VBA constructs the vbnet grammar fails on" section) identified 12 specific VBA constructs where the vbnet grammar fails to emit a dedicated node type. The full regex-based pipeline ALSO doesn't extract some of these directly — they fall back to heuristics or are not emitted.

The 12 gaps:

# Construct Current regex behavior Fix or accept?
1 class_declaration / module_declaration wrapper Heuristic (isCls ? kind='class' : kind='module' at vba-extractor.ts:281) Accept (heuristic is fine for the bench corpus)
2 method_declaration / constructor_declaration / abstract_method_declaration Extracted by PROC_RE in procedures.ts Accept
3 field_declaration Extracted by DIMS_RULES in dims.ts Accept
4 property_declaration Extracted via PROCEDURES_RULES (treating Property Get/Set/Let as procedures) Accept
5 event_declaration / custom_event_declaration / raiseevent_statement Partially handled by event-synth.ts Audit (see below)
6 implements_clause Handled by IMPLEMENTS_RULES Accept
7 parameter_list / parameter Handled inside procedures.ts signature parsing Accept
8 const_declaration BUG: Public Const X = Y is parsed as member_modifier (Public Const) + assignment_statement (X = Y) — the const nature is LOST FIX (highest priority within this issue)
9 Wend loop terminator Handled by pre-processing rewrite Accept
10 VERSION 1.0 CLASS + BEGIN...END header Handled by vba-extractor.ts:detectVbName Accept
11 Attribute VB_* lines Handled by stripVbaComments in vba-preprocess.ts Accept
12 Option Compare Database / Option Explicit Recognized as option_statement but position is wrong Audit (see below)

Acceptance criteria

Suggested approach

For the Public Const fix, add a rule to enums-consts.ts:

defineRule({
  id: 'module-const',
  description: 'Match `Public Const NAME = VALUE` or `Private Const NAME = VALUE`; emit a const symbol with kind:"const" so the const nature survives (vs. the dim-const rule which treats it as an assignment).',
  pattern: /^\s*(?:Public|Private)\s+Const\s+(\w+)\s*(?:As\s+(\w+))?\s*=\s*(.+?)\s*$/i,
  requires: 'module',
  emit: (m, ctx, line, lineNum) => {
    const name = m[1];
    const asType = m[2] ?? 'Variant';
    const value = m[3];
    ctx.nodes.push({
      id: generateNodeId(ctx.filePath, 'const', name, lineNum),
      kind: 'const',
      name,
      qualifiedName: name,
      filePath: ctx.filePath,
      language: 'vba',
      startLine: lineNum,
      endLine: lineNum,
      metadata: { value, asType, visibility: /Public/i.test(line) ? 'public' : 'private' },
    });
    return null;
  },
});

Place this rule BEFORE the dim-const rule in the table so the more specific pattern wins. Add a test fixture to __tests__/extraction-vba-realfixtures.test.ts.

Files touched

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:vbaVBA/Access-specific work (parent codegraph product)bugSomething isn't workingstatus:approvedApproved for implementation

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions