@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.
- package/.git-hooks/pre-commit +18 -0
- package/.github/CONTRIBUTING.md +27 -0
- package/.github/workflows/build.yml +13 -7
- package/.github/workflows/publish.yml +12 -1
- package/.pre-commit-config.yaml +16 -0
- package/README.md +49 -1
- package/package.json +12 -12
- package/rules/file/index.d.ts +3 -0
- package/rules/file/index.js +7 -1
- package/rules/file/index.js.map +1 -1
- package/rules/file/noSingleAsteriskComments.d.ts +7 -0
- package/rules/file/noSingleAsteriskComments.js +219 -0
- package/rules/file/noSingleAsteriskComments.js.map +1 -0
- package/rules/file/noUndeclaredMacros.d.ts +7 -0
- package/rules/file/noUndeclaredMacros.js +77 -0
- package/rules/file/noUndeclaredMacros.js.map +1 -0
- package/rules/file/noUnusedMacros.d.ts +7 -0
- package/rules/file/noUnusedMacros.js +67 -0
- package/rules/file/noUnusedMacros.js.map +1 -0
- package/sasjslint-schema.json +53 -2
- package/scripts/generate-macro-names.mjs +101 -0
- package/types/LintConfig.js +9 -0
- package/types/LintConfig.js.map +1 -1
- package/utils/getLintConfig.js +1 -1
- package/utils/getLintConfig.js.map +1 -1
- package/utils/headerMacros.d.ts +51 -0
- package/utils/headerMacros.js +309 -0
- package/utils/headerMacros.js.map +1 -0
- package/utils/index.d.ts +3 -0
- package/utils/index.js +3 -0
- package/utils/index.js.map +1 -1
- package/utils/parseMacroCalls.d.ts +28 -0
- package/utils/parseMacroCalls.js +230 -0
- package/utils/parseMacroCalls.js.map +1 -0
- package/utils/sasMacros.d.ts +16 -0
- package/utils/sasMacros.generated.d.ts +6 -0
- package/utils/sasMacros.generated.js +136 -0
- package/utils/sasMacros.generated.js.map +1 -0
- package/utils/sasMacros.js +22 -0
- package/utils/sasMacros.js.map +1 -0
- 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)
|