@sasjs/lint 2.6.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/.git-hooks/pre-commit +18 -0
  2. package/.github/CONTRIBUTING.md +27 -0
  3. package/.github/workflows/build.yml +13 -7
  4. package/.github/workflows/publish.yml +12 -1
  5. package/.pre-commit-config.yaml +16 -0
  6. package/README.md +49 -1
  7. package/package.json +12 -12
  8. package/rules/file/index.d.ts +3 -0
  9. package/rules/file/index.js +7 -1
  10. package/rules/file/index.js.map +1 -1
  11. package/rules/file/noSingleAsteriskComments.d.ts +7 -0
  12. package/rules/file/noSingleAsteriskComments.js +219 -0
  13. package/rules/file/noSingleAsteriskComments.js.map +1 -0
  14. package/rules/file/noUndeclaredMacros.d.ts +7 -0
  15. package/rules/file/noUndeclaredMacros.js +77 -0
  16. package/rules/file/noUndeclaredMacros.js.map +1 -0
  17. package/rules/file/noUnusedMacros.d.ts +7 -0
  18. package/rules/file/noUnusedMacros.js +67 -0
  19. package/rules/file/noUnusedMacros.js.map +1 -0
  20. package/sasjslint-schema.json +53 -2
  21. package/scripts/generate-macro-names.mjs +101 -0
  22. package/types/LintConfig.js +9 -0
  23. package/types/LintConfig.js.map +1 -1
  24. package/utils/getLintConfig.js +1 -1
  25. package/utils/getLintConfig.js.map +1 -1
  26. package/utils/headerMacros.d.ts +51 -0
  27. package/utils/headerMacros.js +309 -0
  28. package/utils/headerMacros.js.map +1 -0
  29. package/utils/index.d.ts +3 -0
  30. package/utils/index.js +3 -0
  31. package/utils/index.js.map +1 -1
  32. package/utils/parseMacroCalls.d.ts +28 -0
  33. package/utils/parseMacroCalls.js +230 -0
  34. package/utils/parseMacroCalls.js.map +1 -0
  35. package/utils/sasMacros.d.ts +16 -0
  36. package/utils/sasMacros.generated.d.ts +6 -0
  37. package/utils/sasMacros.generated.js +136 -0
  38. package/utils/sasMacros.generated.js.map +1 -0
  39. package/utils/sasMacros.js +22 -0
  40. package/utils/sasMacros.js.map +1 -0
  41. package/scripts/audit.mjs +0 -131
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ // Generated by scripts/generate-macro-names.mjs from @sasjs/sas-language.
3
+ // Do not edit. Regenerate with `npm run generate:macros`.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.sasMacros = void 0;
6
+ /**
7
+ * The macro names that ship with SAS, lower-cased and without the leading
8
+ * `%`, as published in the macroStatements and macroFunctions groups of
9
+ * `@sasjs/sas-language`.
10
+ */
11
+ exports.sasMacros = [
12
+ 'abort',
13
+ 'armconv',
14
+ 'armend',
15
+ 'armgtid',
16
+ 'arminit',
17
+ 'armjoin',
18
+ 'armproc',
19
+ 'armstop',
20
+ 'armstrt',
21
+ 'armupdt',
22
+ 'bquote',
23
+ 'by',
24
+ 'cmpres',
25
+ 'colormac',
26
+ 'compstor',
27
+ 'copy',
28
+ 'datatyp',
29
+ 'dequote',
30
+ 'display',
31
+ 'do',
32
+ 'dqload',
33
+ 'dqputloc',
34
+ 'dqunload',
35
+ 'else',
36
+ 'end',
37
+ 'eval',
38
+ 'global',
39
+ 'goto',
40
+ 'helpclr',
41
+ 'if',
42
+ 'inc',
43
+ 'include',
44
+ 'index',
45
+ 'indexc',
46
+ 'indexw',
47
+ 'input',
48
+ 'kcmpres',
49
+ 'kindex',
50
+ 'kleft',
51
+ 'klength',
52
+ 'klowcase',
53
+ 'kscan',
54
+ 'ksubstr',
55
+ 'ktrim',
56
+ 'kupcase',
57
+ 'kverify',
58
+ 'left',
59
+ 'length',
60
+ 'let',
61
+ 'list',
62
+ 'local',
63
+ 'lowcase',
64
+ 'macro',
65
+ 'mend',
66
+ 'nrbquote',
67
+ 'nrquote',
68
+ 'nrstr',
69
+ 'perfend',
70
+ 'perfinit',
71
+ 'perfstop',
72
+ 'perfstrt',
73
+ 'put',
74
+ 'qbquote',
75
+ 'qcmpres',
76
+ 'qdequote',
77
+ 'qindex',
78
+ 'qindexc',
79
+ 'qindexw',
80
+ 'qkcmpres',
81
+ 'qkleft',
82
+ 'qklowcas',
83
+ 'qklowcase',
84
+ 'qkscan',
85
+ 'qksubstr',
86
+ 'qktrim',
87
+ 'qkupcase',
88
+ 'qleft',
89
+ 'qlowcase',
90
+ 'qscan',
91
+ 'qsubstr',
92
+ 'qsysfunc',
93
+ 'qtrim',
94
+ 'quote',
95
+ 'qupcase',
96
+ 'return',
97
+ 'run',
98
+ 'scan',
99
+ 'str',
100
+ 'substr',
101
+ 'superq',
102
+ 'symdel',
103
+ 'symexist',
104
+ 'symglobl',
105
+ 'symlocal',
106
+ 'syscall',
107
+ 'sysevalf',
108
+ 'sysexec',
109
+ 'sysfunc',
110
+ 'sysget',
111
+ 'syslput',
112
+ 'sysmacdelete',
113
+ 'sysmacexec',
114
+ 'sysmacexist',
115
+ 'sysmexecdepth',
116
+ 'sysmexecname',
117
+ 'sysmstoreclear',
118
+ 'sysprod',
119
+ 'sysrc',
120
+ 'sysrput',
121
+ 'then',
122
+ 'to',
123
+ 'tplot',
124
+ 'translate',
125
+ 'tranwrd',
126
+ 'trim',
127
+ 'trimn',
128
+ 'unquote',
129
+ 'until',
130
+ 'upcase',
131
+ 'validchs',
132
+ 'verify',
133
+ 'while',
134
+ 'window'
135
+ ];
136
+ //# sourceMappingURL=sasMacros.generated.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sasMacros.generated.js","sourceRoot":"","sources":["../../src/utils/sasMacros.generated.ts"],"names":[],"mappings":";AAAA,0EAA0E;AAC1E,0DAA0D;;;AAE1D;;;;GAIG;AACU,QAAA,SAAS,GAAsB;IAC1C,OAAO;IACP,SAAS;IACT,QAAQ;IACR,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,QAAQ;IACR,IAAI;IACJ,QAAQ;IACR,UAAU;IACV,UAAU;IACV,MAAM;IACN,SAAS;IACT,SAAS;IACT,SAAS;IACT,IAAI;IACJ,QAAQ;IACR,UAAU;IACV,UAAU;IACV,MAAM;IACN,KAAK;IACL,MAAM;IACN,QAAQ;IACR,MAAM;IACN,SAAS;IACT,IAAI;IACJ,KAAK;IACL,SAAS;IACT,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,SAAS;IACT,QAAQ;IACR,OAAO;IACP,SAAS;IACT,UAAU;IACV,OAAO;IACP,SAAS;IACT,OAAO;IACP,SAAS;IACT,SAAS;IACT,MAAM;IACN,QAAQ;IACR,KAAK;IACL,MAAM;IACN,OAAO;IACP,SAAS;IACT,OAAO;IACP,MAAM;IACN,UAAU;IACV,SAAS;IACT,OAAO;IACP,SAAS;IACT,UAAU;IACV,UAAU;IACV,UAAU;IACV,KAAK;IACL,SAAS;IACT,SAAS;IACT,UAAU;IACV,QAAQ;IACR,SAAS;IACT,SAAS;IACT,UAAU;IACV,QAAQ;IACR,UAAU;IACV,WAAW;IACX,QAAQ;IACR,UAAU;IACV,QAAQ;IACR,UAAU;IACV,OAAO;IACP,UAAU;IACV,OAAO;IACP,SAAS;IACT,UAAU;IACV,OAAO;IACP,OAAO;IACP,SAAS;IACT,QAAQ;IACR,KAAK;IACL,MAAM;IACN,KAAK;IACL,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,UAAU;IACV,UAAU;IACV,SAAS;IACT,UAAU;IACV,SAAS;IACT,SAAS;IACT,QAAQ;IACR,SAAS;IACT,cAAc;IACd,YAAY;IACZ,aAAa;IACb,eAAe;IACf,cAAc;IACd,gBAAgB;IAChB,SAAS;IACT,OAAO;IACP,SAAS;IACT,MAAM;IACN,IAAI;IACJ,OAAO;IACP,WAAW;IACX,SAAS;IACT,MAAM;IACN,OAAO;IACP,SAAS;IACT,OAAO;IACP,QAAQ;IACR,UAAU;IACV,QAAQ;IACR,OAAO;IACP,QAAQ;CACT,CAAA"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isSasMacro = exports.sasMacros = void 0;
4
+ const sasMacros_generated_1 = require("./sasMacros.generated");
5
+ /**
6
+ * The set of macro names that ship with SAS, lower-cased for comparison.
7
+ *
8
+ * The names are generated from the macroStatements and macroFunctions groups of
9
+ * `@sasjs/sas-language`, which owns the SAS language data - see
10
+ * `scripts/generate-macro-names.mjs`. A macro matching one of these names is
11
+ * treated as declared, so it is never reported by `noUndeclaredMacros` and
12
+ * never written to a file header by the formatter.
13
+ */
14
+ exports.sasMacros = new Set(sasMacros_generated_1.sasMacros);
15
+ /**
16
+ * Reports whether a macro name is one of the macros that ship with SAS.
17
+ * @param {string} name - the macro name to test.
18
+ * @returns {boolean} true when the name belongs to a SAS-provided macro.
19
+ */
20
+ const isSasMacro = (name) => exports.sasMacros.has(name.toLowerCase());
21
+ exports.isSasMacro = isSasMacro;
22
+ //# sourceMappingURL=sasMacros.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sasMacros.js","sourceRoot":"","sources":["../../src/utils/sasMacros.ts"],"names":[],"mappings":";;;AAAA,+DAA0D;AAE1D;;;;;;;;GAQG;AACU,QAAA,SAAS,GAAgB,IAAI,GAAG,CAAC,+BAAK,CAAC,CAAA;AAEpD;;;;GAIG;AACI,MAAM,UAAU,GAAG,CAAC,IAAY,EAAW,EAAE,CAClD,iBAAS,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAA;AADtB,QAAA,UAAU,cACY"}
package/scripts/audit.mjs DELETED
@@ -1,131 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * A strict dependency audit.
4
- *
5
- * `npm audit` fails on ANY advisory, which cannot pass in this repo: the
6
- * advisories below sit inside the `npm` package that `@semantic-release/npm`
7
- * depends on, in its bundled tree, where no `overrides` entry can reach them.
8
- * npm 12.1.0 bundles the same versions as 11.20.0, so no upgrade clears them.
9
- * They are unreachable from this package's own code and its runtime
10
- * dependencies.
11
- *
12
- * Lowering the threshold for everything would hide a new advisory anywhere
13
- * else, so instead they are named below and every other advisory fails the
14
- * build - including one of the same severity. If one disappears upstream, this
15
- * script says so, so the exemption does not outlive its reason.
16
- *
17
- * Run with `npm run audit`.
18
- */
19
- import { execFileSync } from 'node:child_process'
20
-
21
- /**
22
- * Advisories that cannot be fixed from this repo, and why.
23
- */
24
- const EXEMPT = new Map([
25
- ['GHSA-rpw4-54j3-4h4q', 'ip-address, inside the npm package bundled by @semantic-release/npm'],
26
- ['GHSA-2vr4-cq9g-pvrc', 'ip-address, inside the npm package bundled by @semantic-release/npm'],
27
- ['GHSA-3wwx-pv8p-q78v', 'undici, inside the npm package bundled by @semantic-release/npm'],
28
- // The advisories below landed upstream after the exemptions above were
29
- // written, against the same bundled copies. npm 12.1.0 bundles identical
30
- // versions of all three packages, so an upgrade clears none of them.
31
- ['GHSA-j6r3-76f7-8jcv', 'ip-address, inside the npm package bundled by @semantic-release/npm'],
32
- ['GHSA-h3mg-xc3c-68pw', 'ip-address, inside the npm package bundled by @semantic-release/npm'],
33
- ['GHSA-r53p-7pc4-xj5r', 'undici, inside the npm package bundled by @semantic-release/npm'],
34
- ['GHSA-rfgv-xxqx-mfg5', 'undici, inside the npm package bundled by @semantic-release/npm'],
35
- [
36
- 'GHSA-q2hr-2g5m-vwhr',
37
- 'brace-expansion, inside the npm package bundled by @semantic-release/npm'
38
- ],
39
- [
40
- 'GHSA-qhr7-859c-m2p7',
41
- 'brace-expansion, inside the npm package bundled by @semantic-release/npm'
42
- ],
43
- [
44
- 'GHSA-6j4f-fj2g-mc7p',
45
- 'brace-expansion, inside the npm package bundled by @semantic-release/npm'
46
- ]
47
- ])
48
-
49
- const run = () => {
50
- try {
51
- return execFileSync('npm', ['audit', '--json'], {
52
- encoding: 'utf8',
53
- stdio: ['ignore', 'pipe', 'ignore']
54
- })
55
- } catch (error) {
56
- // npm audit exits non-zero when it finds anything, which is the case we are
57
- // here to read, so the report on stdout is the payload either way.
58
- if (error.stdout) return error.stdout
59
- throw error
60
- }
61
- }
62
-
63
- let report
64
- try {
65
- report = JSON.parse(run())
66
- } catch {
67
- console.error('could not read the npm audit report')
68
- process.exit(1)
69
- }
70
-
71
- const ghsaOf = (via) => {
72
- if (typeof via === 'string') return undefined
73
- const match = /GHSA-[a-z0-9-]+/i.exec(via?.url ?? '')
74
- return match ? match[0] : undefined
75
- }
76
-
77
- const found = new Map()
78
- for (const vulnerability of Object.values(report.vulnerabilities ?? {})) {
79
- for (const via of vulnerability.via ?? []) {
80
- const id = ghsaOf(via)
81
- if (!id) continue
82
- if (!found.has(id)) {
83
- found.set(id, {
84
- id,
85
- title: via.title ?? '',
86
- severity: via.severity ?? vulnerability.severity,
87
- packages: new Set()
88
- })
89
- }
90
- found.get(id).packages.add(vulnerability.name)
91
- }
92
- }
93
-
94
- const exempt = [...found.keys()].filter((id) => EXEMPT.has(id))
95
- const failing = [...found.values()].filter((entry) => !EXEMPT.has(entry.id))
96
- const stale = [...EXEMPT.keys()].filter((id) => !found.has(id))
97
-
98
- console.log(`advisories found: ${found.size}`)
99
- for (const entry of found.values()) {
100
- const mark = EXEMPT.has(entry.id) ? 'exempt' : 'FAIL '
101
- console.log(
102
- ` ${mark} ${entry.severity.padEnd(8)} ${entry.id} ${[...entry.packages].join(', ')}`
103
- )
104
- }
105
-
106
- for (const id of stale) {
107
- console.log(` GONE ${id} no longer reported - remove its exemption`)
108
- }
109
-
110
- if (failing.length === 0 && stale.length === 0) {
111
- console.log(
112
- `audit clean: ${exempt.length} exempt, ${stale.length} stale, ${failing.length} failing`
113
- )
114
- process.exit(0)
115
- }
116
-
117
- if (stale.length > 0) {
118
- console.error(
119
- `${stale.length} exemption(s) no longer match a reported advisory.`
120
- )
121
- }
122
-
123
- if (failing.length > 0) {
124
- console.error(`${failing.length} advisory(ies) are NOT exempt:`)
125
- for (const entry of failing) {
126
- console.error(` ${entry.severity} ${entry.id} ${entry.title}`)
127
- console.error(` ${[...entry.packages].join(', ')}`)
128
- }
129
- }
130
-
131
- process.exit(1)