Priority
P2 — classic Access syntax, zero coverage today.
Context
Access VBA uses the bang operator for default-collection access. Three idioms matter:
Me!txtNombre — control access on the own form (equivalent to Me.txtNombre).
Forms!FormPrincipal!txtEstado — cross-form control access (also Forms("FormPrincipal")).
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
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).
Priority
P2 — classic Access syntax, zero coverage today.
Context
Access VBA uses the bang operator for default-collection access. Three idioms matter:
Me!txtNombre— control access on the own form (equivalent toMe.txtNombre).Forms!FormPrincipal!txtEstado— cross-form control access (alsoForms("FormPrincipal")).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!Ctlbehaves exactly likeMe.Ctl: an UnresolvedReference taggedvba-me-control.Forms!FormName!Ctl(andForms!FormNamealone) emits a cross-form reference: an UnresolvedReference to the form (resolver matches theform-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!Campois 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 theOpenRecordsetthat producedrs; otherwise leave explicitly out with a test documenting the decision.Implementation sketch
ME_CONTROL_REto/\bMe[.!](\p{L}[\p{L}\p{N}_]*)/gu(scan on the masked line, as today).Formsbang/paren access:/\bForms\s*(?:!\s*(\p{L}[\p{L}\p{N}_]*)|\(\s*"([^"]+)"\s*\))(?:\s*!\s*(\p{L}[\p{L}\p{N}_]*))?/gu— noteFormsis inRUNTIME_RECEIVER_BLACKLISTfor the generic call path; this dedicated scanner runs independently (same pattern asDoCmd.OpenForm). TheForms("...")literal form must scan the ORIGINAL line (string content), the bang form the masked line.Forms![Mi Formulario]) — accept\[[^\]]+\]as the name segment, unwrap brackets.Acceptance criteria
Me!txtFooproduces the same UnresolvedReference asMe.txtFoo.Forms!FormX!txtY.Value = 1andForms("FormX")!txtYemit a reference from the current proc to formFormX.rs!Campoeither resolves via SQL lineage or is proven silent by a test.Me.tests green.Validation
Index
C:\Proyectos\dysflow\E2E_testing\src; count newvba-me-controlresolutions and cross-form references; verify no false positives from!inside strings (masking).