Rung 2 of the #376 ratchet, on top of #418. sas/.sasjslint promotes noUndeclaredMacros to error; its 25 findings on release/7.22 are cleared, and two of them were real faults rather than missing prose.
What was broken
Rather than trusting the linter alone, I compared each compiled service against the macros it calls: compile, then list every macro that a generated program calls but does not define (filtered to macros that exist somewhere in the project).
Three services were calling a macro that was absent from their own compiled program:
services/validations/tables_all.sas calls %mf_getuniquename() on its third line and never declared it.
services/validations/mpe_tables.dsn.sas calls %mf_getuniquename() and %dc_assignlib() and declared neither.
services/hooks/mpe_tables_postedit.sas calls %dc_assignlib(), which is supplied by the service that includes the hook (see below).
The two validation services are configured as rule_value entries in MPE_TABLES (mpe_makedata.sas and the v3.12/v3.13 migrations), so those calls run when a user reviews or filters a library, and each would have raised Apparent invocation of macro ... not resolved. Both now declare what they call, and the definitions are present in the compiled program.
What changed
14 files declare the macros they call but had been relying on another declaration to pull them in: mf_getquotedstr, mf_nobs, mf_getuser (twice), mf_getapploc, mf_getattrn, mp_abort (six services), mf_getuniquename (twice), dc_assignlib, bitemporal_closeouts. These were already defined in the compiled program through another macro's header; the declarations make the dependency visible, and make the two validation services correct.
6 hook scripts get a file-local @sasjslint {"ignoredMacros": [...]} (mp_abort, plus dc_assignlib in mpe_tables_postedit) instead of a macro list. Hooks are included at run time by the service that owns them, so those macros are already in the session, and these files are copied and edited by end users - they should not carry a declaration section to maintain. Recorded in AGENTS.md.
bitemporal_dataloader.test.2.sas loses its test 30 block. It is gated with and 0 ("skip until have a db") and its only setup line calls %assign_direct_lib, a macro that exists nowhere in this project or in @sasjs/core - enabling the block would fail on its first line.
Verification
npm run lint:sas: 18 warnings, 0 errors, exit 0.
sasjs compile: succeeds. The called-but-undefined list drops from three services to the single hook exception; every other definition-count change is an addition (no definition removed).
No new files call a macro that is not defined.
Remaining, per rung
18 warnings: noBannedStrings (13), macro name length (2) and case (2), indentationMultiple (1). Next PR takes the naming, indentation and banned-string findings, which are the same kind of mechanical edit.
Rung 2 of the #376 ratchet, on top of #418. `sas/.sasjslint` promotes `noUndeclaredMacros` to `error`; its 25 findings on `release/7.22` are cleared, and two of them were real faults rather than missing prose.
## What was broken
Rather than trusting the linter alone, I compared each compiled service against the macros it calls: compile, then list every macro that a generated program calls but does not define (filtered to macros that exist somewhere in the project).
Three services were calling a macro that was absent from their own compiled program:
- `services/validations/tables_all.sas` calls `%mf_getuniquename()` on its third line and never declared it.
- `services/validations/mpe_tables.dsn.sas` calls `%mf_getuniquename()` and `%dc_assignlib()` and declared neither.
- `services/hooks/mpe_tables_postedit.sas` calls `%dc_assignlib()`, which is supplied by the service that includes the hook (see below).
The two validation services are configured as `rule_value` entries in `MPE_TABLES` (`mpe_makedata.sas` and the v3.12/v3.13 migrations), so those calls run when a user reviews or filters a library, and each would have raised `Apparent invocation of macro ... not resolved`. Both now declare what they call, and the definitions are present in the compiled program.
## What changed
- **14 files declare the macros they call** but had been relying on another declaration to pull them in: `mf_getquotedstr`, `mf_nobs`, `mf_getuser` (twice), `mf_getapploc`, `mf_getattrn`, `mp_abort` (six services), `mf_getuniquename` (twice), `dc_assignlib`, `bitemporal_closeouts`. These were already defined in the compiled program through another macro's header; the declarations make the dependency visible, and make the two validation services correct.
- **6 hook scripts get a file-local `@sasjslint {"ignoredMacros": [...]}`** (`mp_abort`, plus `dc_assignlib` in `mpe_tables_postedit`) instead of a macro list. Hooks are included at run time by the service that owns them, so those macros are already in the session, and these files are copied and edited by end users - they should not carry a declaration section to maintain. Recorded in `AGENTS.md`.
- **`bitemporal_dataloader.test.2.sas` loses its test 30 block.** It is gated with `and 0` ("skip until have a db") and its only setup line calls `%assign_direct_lib`, a macro that exists nowhere in this project or in `@sasjs/core` - enabling the block would fail on its first line.
## Verification
- `npm run lint:sas`: 18 warnings, 0 errors, exit 0.
- `sasjs compile`: succeeds. The called-but-undefined list drops from three services to the single hook exception; every other definition-count change is an addition (no definition removed).
- No new files call a macro that is not defined.
## Remaining, per rung
18 warnings: `noBannedStrings` (13), macro name length (2) and case (2), `indentationMultiple` (1). Next PR takes the naming, indentation and banned-string findings, which are the same kind of mechanical edit.
Rung 2 of the #376 ratchet: `sas/.sasjslint` promotes noUndeclaredMacros to
"error". Its 25 findings on release/7.22 are cleared, and two of them were
real faults rather than missing prose.
WHAT WAS BROKEN
Comparing the compiled program against the macros it calls (compile, then
list every project macro each generated service calls but does not define)
found three services calling macros that were absent from their own
compiled program:
- services/validations/tables_all.sas calls %mf_getuniquename() on its
third line and never declared it.
- services/validations/mpe_tables.dsn.sas calls %mf_getuniquename() and
%dc_assignlib() and declared neither.
- services/hooks/mpe_tables_postedit.sas calls %dc_assignlib(), which is
supplied by the service that includes the hook (see below).
The two validation services are configured as rule_value entries in
MPE_TABLES (mpe_makedata.sas and the v3.12/v3.13 migrations), so the calls
run when a user reviews or filters a library - each would have raised
"Apparent invocation of macro ... not resolved". Both now declare what
they call, and the definitions are present in the compiled program.
WHAT CHANGED
- 14 files declare the macros they call but had been relying on another
declaration to bring in: mf_getquotedstr, mf_nobs, mf_getuser (twice),
mf_getapploc, mf_getattrn, mp_abort (six services), mf_getuniquename
(twice), dc_assignlib, bitemporal_closeouts. These were defined in the
compiled program already; the declarations make the dependency visible
and the two validation services correct.
- 6 hook scripts get a file-local @sasjslint {"ignoredMacros": [...]}
(mp_abort, plus dc_assignlib in mpe_tables_postedit) instead of a macro
list. Hooks are included at run time by the service that owns them, so
the macros are already in that session, and these files are copied and
edited by end users - they should not carry a declaration section to
maintain. Recorded in AGENTS.md.
- bitemporal_dataloader.test.2.sas loses its test 30 block: it is gated
with `and 0` ("skip until have a db") and its only setup line calls
%assign_direct_lib, a macro that exists nowhere in this project or in
@sasjs/core. Enabling it would fail on the first line.
VERIFICATION
- `npm run lint:sas`: 18 warnings, 0 errors, exit 0.
- `sasjs compile`: succeeds; the called-but-undefined list drops from
three services to the one hook exception; the only definition-count
changes are additions.
- 18 warnings remain for the next rungs: noBannedStrings (13), macro name
length (2) and case (2), indentationMultiple (1).
allan
merged commit 4c09c02998 into release/7.222026-11-01 01:41:33 +00:00
allan
deleted branch fix/lint-no-undeclared-macros2026-11-01 01:41:33 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Rung 2 of the #376 ratchet, on top of #418.
sas/.sasjslintpromotesnoUndeclaredMacrostoerror; its 25 findings onrelease/7.22are cleared, and two of them were real faults rather than missing prose.What was broken
Rather than trusting the linter alone, I compared each compiled service against the macros it calls: compile, then list every macro that a generated program calls but does not define (filtered to macros that exist somewhere in the project).
Three services were calling a macro that was absent from their own compiled program:
services/validations/tables_all.sascalls%mf_getuniquename()on its third line and never declared it.services/validations/mpe_tables.dsn.sascalls%mf_getuniquename()and%dc_assignlib()and declared neither.services/hooks/mpe_tables_postedit.sascalls%dc_assignlib(), which is supplied by the service that includes the hook (see below).The two validation services are configured as
rule_valueentries inMPE_TABLES(mpe_makedata.sasand the v3.12/v3.13 migrations), so those calls run when a user reviews or filters a library, and each would have raisedApparent invocation of macro ... not resolved. Both now declare what they call, and the definitions are present in the compiled program.What changed
mf_getquotedstr,mf_nobs,mf_getuser(twice),mf_getapploc,mf_getattrn,mp_abort(six services),mf_getuniquename(twice),dc_assignlib,bitemporal_closeouts. These were already defined in the compiled program through another macro's header; the declarations make the dependency visible, and make the two validation services correct.@sasjslint {"ignoredMacros": [...]}(mp_abort, plusdc_assignlibinmpe_tables_postedit) instead of a macro list. Hooks are included at run time by the service that owns them, so those macros are already in the session, and these files are copied and edited by end users - they should not carry a declaration section to maintain. Recorded inAGENTS.md.bitemporal_dataloader.test.2.sasloses its test 30 block. It is gated withand 0("skip until have a db") and its only setup line calls%assign_direct_lib, a macro that exists nowhere in this project or in@sasjs/core- enabling the block would fail on its first line.Verification
npm run lint:sas: 18 warnings, 0 errors, exit 0.sasjs compile: succeeds. The called-but-undefined list drops from three services to the single hook exception; every other definition-count change is an addition (no definition removed).Remaining, per rung
18 warnings:
noBannedStrings(13), macro name length (2) and case (2),indentationMultiple(1). Next PR takes the naming, indentation and banned-string findings, which are the same kind of mechanical edit.