Skip to content

feat(vba): support the bang operator — Me!Ctl, Forms!Form!Ctl #44

Description

@ardelperal

Priority

P2 — classic Access syntax, zero coverage today.

Context

Access VBA uses the bang operator for default-collection access. Three idioms matter:

  1. Me!txtNombre — control access on the own form (equivalent to Me.txtNombre).
  2. Forms!FormPrincipal!txtEstado — cross-form control access (also Forms("FormPrincipal")).
  3. rs!Campo — recordset field access (column-level data flow).

Current behavior

Only Me. is scanned (ME_CONTROL_RE, src/extraction/vba-extractor.ts ~1114). All bang forms are invisible.

Expected behavior

  • Me!Ctl behaves exactly like Me.Ctl: an UnresolvedReference tagged vba-me-control.
  • Forms!FormName!Ctl (and Forms!FormName alone) emits a cross-form reference: an UnresolvedReference to the form (resolver matches the form-layout / Form_<Name> class node), tagged e.g. vba-forms-bang; when the control segment is present, optionally a second reference to <FormName>::<Ctl>.
  • rs!Campo is stretch scope: valuable for column-level impact but noisy without knowing the recordset's source table — implement only if it can be tied to the tracked SQL variable of the OpenRecordset that produced rs; otherwise leave explicitly out with a test documenting the decision.

Implementation sketch

  • Extend ME_CONTROL_RE to /\bMe[.!](\p{L}[\p{L}\p{N}_]*)/gu (scan on the masked line, as today).
  • New regex for Forms bang/paren access: /\bForms\s*(?:!\s*(\p{L}[\p{L}\p{N}_]*)|\(\s*"([^"]+)"\s*\))(?:\s*!\s*(\p{L}[\p{L}\p{N}_]*))?/gu — note Forms is in RUNTIME_RECEIVER_BLACKLIST for the generic call path; this dedicated scanner runs independently (same pattern as DoCmd.OpenForm). The Forms("...") literal form must scan the ORIGINAL line (string content), the bang form the masked line.
  • Bracketed names (Forms![Mi Formulario]) — accept \[[^\]]+\] as the name segment, unwrap brackets.

Acceptance criteria

  • Me!txtFoo produces the same UnresolvedReference as Me.txtFoo.
  • Forms!FormX!txtY.Value = 1 and Forms("FormX")!txtY emit a reference from the current proc to form FormX.
  • rs!Campo either resolves via SQL lineage or is proven silent by a test.
  • Existing Me. tests green.

Validation

Index C:\Proyectos\dysflow\E2E_testing\src; count new vba-me-control resolutions and cross-form references; verify no false positives from ! inside strings (masking).

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:vbaVBA/Access-specific work (parent codegraph product)enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions