@eslint-sh/eslint-plugin 0.6.0 → 0.8.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/README.md +19 -8
- package/dist/command-harvest/builtins/bash.d.ts +1 -1
- package/dist/command-harvest/builtins/bash.js +1 -1
- package/dist/command-harvest/builtins/bats.d.ts +2 -0
- package/dist/command-harvest/builtins/bats.js +3 -0
- package/dist/command-harvest/wrapper-table.d.ts +3 -19
- package/dist/command-harvest/wrapper-table.js +8 -38
- package/dist/configs/bash-3-2.d.ts +7 -6
- package/dist/configs/bash-3-2.js +5 -3
- package/dist/configs/posix-portable.d.ts +1 -1
- package/dist/configs/posix-portable.js +1 -0
- package/dist/declaration-conventions/read-declared-commands.d.ts +2 -2
- package/dist/declaration-conventions/read-declared-commands.js +2 -2
- package/dist/eslint-plugin-syntax.d.ts +4 -0
- package/dist/eslint-plugin.d.ts +86 -40
- package/dist/index.d.ts +5 -2
- package/dist/index.js +4 -2
- package/dist/language/shell-language-options.d.ts +18 -15
- package/dist/language/shell-language-options.js +33 -26
- package/dist/language/shell-language.d.ts +10 -9
- package/dist/language/shell-language.js +18 -35
- package/dist/language/shell-source-code.d.ts +17 -9
- package/dist/language/shell-source-code.js +53 -12
- package/dist/rules/bash-variable-semantics.d.ts +22 -0
- package/dist/rules/bash-variable-semantics.js +41 -0
- package/dist/rules/compat/create-compat-rule.js +1 -1
- package/dist/rules/compat/declaration-options.d.ts +2 -2
- package/dist/rules/compat/declaration-options.js +5 -2
- package/dist/rules/compat/no-append-all-redirect.js +1 -1
- package/dist/rules/compat/no-associative-arrays.js +2 -2
- package/dist/rules/compat/no-brace-sequence-padding-step.d.ts +15 -0
- package/dist/rules/compat/no-brace-sequence-padding-step.js +287 -0
- package/dist/rules/compat/no-case-attributes.js +3 -3
- package/dist/rules/compat/no-case-fallthrough.js +2 -2
- package/dist/rules/compat/no-case-modification.js +2 -2
- package/dist/rules/compat/no-coproc.js +1 -1
- package/dist/rules/compat/no-declare-g.js +3 -3
- package/dist/rules/compat/no-double-bracket.js +2 -2
- package/dist/rules/compat/no-epoch-variables.js +2 -2
- package/dist/rules/compat/no-fd-variable.js +1 -1
- package/dist/rules/compat/no-globstar.js +1 -1
- package/dist/rules/compat/no-lastpipe-semantics.js +2 -2
- package/dist/rules/compat/no-let.js +2 -1
- package/dist/rules/compat/no-mapfile.js +4 -2
- package/dist/rules/compat/no-nameref.js +3 -3
- package/dist/rules/compat/no-negative-array-index.js +39 -9
- package/dist/rules/compat/no-nounset-empty-array.js +15 -4
- package/dist/rules/compat/no-parameter-transformation.js +2 -2
- package/dist/rules/compat/no-pipe-all.js +1 -1
- package/dist/rules/compat/no-printf-time-format.js +4 -2
- package/dist/rules/compat/no-source.js +2 -1
- package/dist/rules/compat/no-test-v.js +4 -2
- package/dist/rules/compat/no-unicode-escape.js +2 -2
- package/dist/rules/compat/no-wait-n.js +4 -2
- package/dist/rules/compat/nounset-array-proof.d.ts +8 -0
- package/dist/rules/compat/nounset-array-proof.js +563 -0
- package/dist/rules/compat/posix-absent-command.d.ts +7 -8
- package/dist/rules/compat/posix-absent-command.js +17 -15
- package/dist/rules/compat/shopt-options.js +3 -1
- package/dist/rules/compat/version-gates.d.ts +10 -10
- package/dist/rules/compat/version-gates.js +21 -13
- package/dist/rules/create-wrapper-rule.js +12 -7
- package/dist/rules/index.js +2 -0
- package/dist/rules/no-dynamic-invocation.d.ts +0 -8
- package/dist/rules/no-dynamic-invocation.js +7 -15
- package/dist/rules/no-eval.js +3 -1
- package/dist/rules/no-masked-exit-status.js +15 -8
- package/dist/rules/no-secret-env-reads.d.ts +4 -3
- package/dist/rules/no-secret-env-reads.js +37 -14
- package/dist/rules/no-secret-flags.d.ts +2 -1
- package/dist/rules/no-secret-flags.js +7 -8
- package/dist/rules/no-unchecked-cd.js +3 -1
- package/dist/rules/no-undeclared-commands.d.ts +1 -15
- package/dist/rules/no-undeclared-commands.js +3 -15
- package/dist/rules/no-unused-declarations.d.ts +1 -18
- package/dist/rules/no-unused-declarations.js +9 -34
- package/dist/rules/prefer-local.js +4 -3
- package/dist/rules/quote-expansions.js +3 -28
- package/dist/rules/require-network-wrapper.d.ts +2 -17
- package/dist/rules/require-network-wrapper.js +33 -4
- package/dist/rules/require-tty-guard.js +30 -1
- package/dist/rules/resolve-declaration-convention.d.ts +5 -6
- package/dist/rules/resolve-declaration-convention.js +5 -6
- package/dist/rules/resolve-network-wrapper.d.ts +19 -0
- package/dist/rules/resolve-network-wrapper.js +57 -26
- package/dist/rules/resolve-transparent-wrappers.d.ts +43 -0
- package/dist/rules/resolve-transparent-wrappers.js +98 -0
- package/dist/rules/set-options.d.ts +2 -1
- package/dist/rules/set-options.js +17 -5
- package/dist/rules/shebang-interpreter.js +4 -2
- package/dist/rules/transparent-wrappers.d.ts +4 -3
- package/dist/rules/transparent-wrappers.js +5 -4
- package/dist/rules/user-pattern.d.ts +5 -3
- package/dist/rules/user-pattern.js +6 -4
- package/dist/syntax/index.d.ts +4 -0
- package/dist/syntax/index.js +4 -0
- package/docs/compat.md +90 -34
- package/docs/custom-rule-tutorial.md +9 -3
- package/docs/examples/no-listed-commands-rule.ts +2 -2
- package/docs/rules/README.md +38 -5
- package/docs/rules/_template.md +2 -2
- package/docs/rules/compat/no-append-all-redirect.md +12 -12
- package/docs/rules/compat/no-associative-arrays.md +14 -14
- package/docs/rules/compat/no-brace-sequence-padding-step.md +90 -0
- package/docs/rules/compat/no-case-attributes.md +13 -13
- package/docs/rules/compat/no-case-fallthrough.md +12 -12
- package/docs/rules/compat/no-case-modification.md +11 -11
- package/docs/rules/compat/no-coproc.md +13 -13
- package/docs/rules/compat/no-declare-g.md +13 -13
- package/docs/rules/compat/no-double-bracket.md +2 -2
- package/docs/rules/compat/no-epoch-variables.md +13 -13
- package/docs/rules/compat/no-fd-variable.md +12 -12
- package/docs/rules/compat/no-globstar.md +13 -13
- package/docs/rules/compat/no-lastpipe-semantics.md +13 -13
- package/docs/rules/compat/no-let.md +2 -2
- package/docs/rules/compat/no-mapfile.md +16 -16
- package/docs/rules/compat/no-nameref.md +13 -13
- package/docs/rules/compat/no-negative-array-index.md +14 -14
- package/docs/rules/compat/no-nounset-empty-array.md +72 -17
- package/docs/rules/compat/no-parameter-transformation.md +19 -19
- package/docs/rules/compat/no-pipe-all.md +13 -13
- package/docs/rules/compat/no-printf-time-format.md +13 -13
- package/docs/rules/compat/no-source.md +2 -2
- package/docs/rules/compat/no-test-v.md +12 -12
- package/docs/rules/compat/no-unicode-escape.md +13 -13
- package/docs/rules/compat/no-wait-n.md +13 -13
- package/docs/rules/no-dynamic-invocation.md +17 -12
- package/docs/rules/no-eval.md +6 -1
- package/docs/rules/no-masked-exit-status.md +4 -0
- package/docs/rules/no-secret-env-reads.md +34 -3
- package/docs/rules/no-secret-flags.md +19 -2
- package/docs/rules/no-unchecked-cd.md +9 -2
- package/docs/rules/no-undeclared-commands.md +16 -15
- package/docs/rules/no-unused-declarations.md +17 -20
- package/docs/rules/prefer-local.md +20 -2
- package/docs/rules/quote-expansions.md +8 -5
- package/docs/rules/require-network-wrapper.md +22 -17
- package/docs/rules/require-shebang.md +10 -4
- package/docs/rules/require-strict-mode.md +6 -0
- package/docs/rules/require-tty-guard.md +4 -1
- package/docs/shellcheck.md +10 -5
- package/docs/transparent-wrappers.md +97 -0
- package/docs/untrusted-code.md +440 -0
- package/docs/wrapper-rules.md +9 -0
- package/package.json +2 -2
- package/dist/language/end-of-input-marker.d.ts +0 -29
- package/dist/language/end-of-input-marker.js +0 -88
package/README.md
CHANGED
|
@@ -24,9 +24,10 @@ recipes. Four shared configs ship, each supplying `plugins: { sh }` and `languag
|
|
|
24
24
|
`sh/max-script-complexity`, with every rule at `error`. Its convention and wrapper rules report nothing until you bind a declaration
|
|
25
25
|
convention or a wrapper. The [rules index](./docs/rules/README.md) lists all forty built-in rules,
|
|
26
26
|
their presets, and
|
|
27
|
-
autofix availability. The version-gated rules `sh/compat/no-append-all-redirect`, `sh/compat/no-associative-arrays`, `sh/compat/no-case-attributes`, `sh/compat/no-case-fallthrough`, `sh/compat/no-case-modification`, `sh/compat/no-coproc`, `sh/compat/no-declare-g`, `sh/compat/no-epoch-variables`, `sh/compat/no-fd-variable`, `sh/compat/no-globstar`, `sh/compat/no-lastpipe-semantics`, `sh/compat/no-mapfile`, `sh/compat/no-nameref`, `sh/compat/no-negative-array-index`, `sh/compat/no-nounset-empty-array`, `sh/compat/no-parameter-transformation`, `sh/compat/no-pipe-all`, `sh/compat/no-printf-time-format`, `sh/compat/no-test-v`, `sh/compat/no-unicode-escape` and `sh/compat/no-wait-n`, report features your
|
|
28
|
-
|
|
29
|
-
`sh/
|
|
27
|
+
autofix availability. The version-gated rules `sh/compat/no-append-all-redirect`, `sh/compat/no-associative-arrays`, `sh/compat/no-brace-sequence-padding-step`, `sh/compat/no-case-attributes`, `sh/compat/no-case-fallthrough`, `sh/compat/no-case-modification`, `sh/compat/no-coproc`, `sh/compat/no-declare-g`, `sh/compat/no-epoch-variables`, `sh/compat/no-fd-variable`, `sh/compat/no-globstar`, `sh/compat/no-lastpipe-semantics`, `sh/compat/no-mapfile`, `sh/compat/no-nameref`, `sh/compat/no-negative-array-index`, `sh/compat/no-nounset-empty-array`, `sh/compat/no-parameter-transformation`, `sh/compat/no-pipe-all`, `sh/compat/no-printf-time-format`, `sh/compat/no-test-v`, `sh/compat/no-unicode-escape` and `sh/compat/no-wait-n`, report features the minimum Bash version your scripts must support lacks; `configs['bash-3.2']` (`minBashVersion: '3.2'`) and `configs['posix-portable']` (`dialect: 'posix'`, with
|
|
28
|
+
`sh/require-strict-mode` as `set -eu`) enable them for those targets, except that
|
|
29
|
+
`sh/compat/no-nounset-empty-array` is an explicit opt-in for `bash-3.2`. Enable it for scripts
|
|
30
|
+
that use `set -u` on Bash below 4.4 and have arrays that can really be empty. `configs['posix-portable']` also reports `[[`, `let` and `source`, which fail on dash (`sh/compat/no-double-bracket`, `sh/compat/no-let`, `sh/compat/no-source`), but not `local`, `echo -e` or the other constructs it leaves to shellcheck, so a clean run does not prove a script runs under every POSIX `sh`; see [version compatibility](./docs/compat.md). Run shellcheck alongside eslint-sh: shellcheck catches shell correctness
|
|
30
31
|
problems; eslint-sh enforces project policy. [Running eslint-sh beside shellcheck](./docs/shellcheck.md)
|
|
31
32
|
covers who owns what and the rules that overlap it deliberately (see also the
|
|
32
33
|
[design rationale](https://github.com/mike-north/eslint-sh/blob/main/design/README.md#eslint-sh-and-shellcheck)).
|
|
@@ -36,6 +37,11 @@ Disable directives / inline config are implemented and live: all four
|
|
|
36
37
|
interplay work through ESLint's native machinery. The rule id below is illustrative; the
|
|
37
38
|
directives suppress built-in rules and your own custom rules alike: for a rule you've configured as `sh/your-rule`,
|
|
38
39
|
`# eslint-disable-next-line sh/your-rule -- justification` suppresses it on the following line.
|
|
40
|
+
A script can therefore switch any rule off for itself. When the scripts you lint come from someone
|
|
41
|
+
who doesn't own the policy, see [linting code you don't control](./docs/untrusted-code.md): a
|
|
42
|
+
config that ignores those comments, and how to run ESLint from outside the checkout under review,
|
|
43
|
+
so that it can't supply the config, ESLint, the plugin, or anything else ESLint looks for in the
|
|
44
|
+
directory it runs in.
|
|
39
45
|
|
|
40
46
|
## CommonJS config
|
|
41
47
|
|
|
@@ -73,7 +79,7 @@ ShellLanguage }, rules, configs: { recommended, 'agent-authored', 'bash-3.2', 'p
|
|
|
73
79
|
- `ShellLanguage` — the `@eslint/core` `Language` implementation: `fileType: "text"`,
|
|
74
80
|
`lineStart`/`columnStart: 1`, `nodeTypeKey: "type"`, the consumer's schema-derived `visitorKeys`,
|
|
75
81
|
`validateLanguageOptions`/`normalizeLanguageOptions` for the
|
|
76
|
-
`{dialect,
|
|
82
|
+
`{dialect, minBashVersion, directivePrefix}` schema, `parse`/`createSourceCode`, and
|
|
77
83
|
`matchesSelectorClass` for the six launch esquery selector classes (`:command`, `:loop`,
|
|
78
84
|
`:conditional`, `:expansion`, `:quoted`, `:function` — see the
|
|
79
85
|
[selector cookbook](./docs/selectors.md)).
|
|
@@ -86,9 +92,9 @@ ShellLanguage }, rules, configs: { recommended, 'agent-authored', 'bash-3.2', 'p
|
|
|
86
92
|
without following wrappers), and `resolveInvokedCommand(callExpr, { transparentWrappers? })` (the
|
|
87
93
|
full `Argv0Resolution` once wrappers such as `env`, `sudo`, and `exec` are followed, including the
|
|
88
94
|
wrapper `chain` and the `effective` command or the reason it is unknowable). The `dialect` and
|
|
89
|
-
`
|
|
95
|
+
`minBashVersion` accessors return the file's normalized language options.
|
|
90
96
|
- `ShellLanguageOptions` / `NormalizedShellLanguageOptions` / `ShellLanguageOptionsJSON` — the
|
|
91
|
-
`languageOptions` types (`dialect`, `
|
|
97
|
+
`languageOptions` types (`dialect`, `minBashVersion`, `directivePrefix`). `directivePrefix` is the
|
|
92
98
|
prefix directive/inline-config comments must start with — e.g. the default `"eslint"` recognizes
|
|
93
99
|
`# eslint-disable-next-line ...`; consumers who already overload `# eslint-*` comments for
|
|
94
100
|
something else can configure a different prefix (e.g. `directivePrefix: 'shellcheck-sh'`).
|
|
@@ -149,9 +155,14 @@ ShellLanguage }, rules, configs: { recommended, 'agent-authored', 'bash-3.2', 'p
|
|
|
149
155
|
`ShellRuleVisitor`. See [Writing your own rules](#writing-your-own-rules).
|
|
150
156
|
- `resolveDeclarationConvention` / `DeclarationConventionBindingContext` — resolves the declaration
|
|
151
157
|
convention bound for a rule (its `declarationConvention` option, else
|
|
152
|
-
`settings
|
|
158
|
+
`settings: { sh: { declarationConvention: commentPragma } }`, else `null`) with the validation and error messages the
|
|
153
159
|
built-in consumers use, so a rule of your own can read the convention. See [declaration
|
|
154
160
|
conventions](./docs/declaration-conventions.md#reading-the-convention-in-your-own-rule).
|
|
161
|
+
- `resolveTransparentWrappers` / `TransparentWrappersBindingContext` — resolves project wrapper
|
|
162
|
+
facts from `settings: { sh: { transparentWrappers: ['with-retry'] } }` and the shared network
|
|
163
|
+
wrapper, composed with a rule's built-in scope. Every wrapper-following built-in uses it;
|
|
164
|
+
rule packs can use the same validation, precedence and path matching. See
|
|
165
|
+
[shared transparent wrappers](./docs/transparent-wrappers.md).
|
|
155
166
|
- `createWrapperRule` / `WrapperRuleConfig` / `WrapperRuleSubcommands` / `WrapperSpec` — the
|
|
156
167
|
factory for "command X must be run through wrapper Y" rules a rule pack
|
|
157
168
|
binds to its own commands and wrapper. `sh/require-network-wrapper` is the built-in rule made
|
|
@@ -189,7 +200,7 @@ import {
|
|
|
189
200
|
`…/syntax/analyze` takes a faithful `Node`. That is why the subpaths are kept apart from the
|
|
190
201
|
root.
|
|
191
202
|
- **Versioning.** `…/syntax` and `…/syntax/analyze` track this plugin's pinned `sh-ast` minor
|
|
192
|
-
(currently `sh-ast@^0.
|
|
203
|
+
(currently `sh-ast@^0.9.0`). Under 0.x, a different `sh-ast` minor is a breaking change, so
|
|
193
204
|
an `sh-ast` 0.x minor bump is a minor bump of this plugin, and the changelog entry names the
|
|
194
205
|
new `sh-ast` version.
|
|
195
206
|
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* Reserved words (`if`, `time`, `[[`, `function`, …) are not here: the
|
|
18
18
|
* parser never produces them as command words.
|
|
19
19
|
*
|
|
20
|
-
* The list is the latest bash's, and is not narrowed by `
|
|
20
|
+
* The list is the latest bash's, and is not narrowed by `minBashVersion`:
|
|
21
21
|
* `mapfile`, `readarray` and `compopt` (added in bash 4.0) are builtins here
|
|
22
22
|
* even for a file configured as bash 3.2. Whether a script may use them on
|
|
23
23
|
* an old bash is a version-compatibility question, not a dependency one.
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* Reserved words (`if`, `time`, `[[`, `function`, …) are not here: the
|
|
18
18
|
* parser never produces them as command words.
|
|
19
19
|
*
|
|
20
|
-
* The list is the latest bash's, and is not narrowed by `
|
|
20
|
+
* The list is the latest bash's, and is not narrowed by `minBashVersion`:
|
|
21
21
|
* `mapfile`, `readarray` and `compopt` (added in bash 4.0) are builtins here
|
|
22
22
|
* even for a file configured as bash 3.2. Whether a script may use them on
|
|
23
23
|
* an old bash is a version-compatibility question, not a dependency one.
|
|
@@ -32,6 +32,8 @@ export declare const BATS_HELPERS: readonly string[];
|
|
|
32
32
|
/**
|
|
33
33
|
* bats' `run`, as a transparent wrapper: it runs the command after its own
|
|
34
34
|
* options and captures the result, so `run curl x` uses `curl`.
|
|
35
|
+
* Only the exact function name has these semantics; an executable path such
|
|
36
|
+
* as `/tmp/run` is an external dependency whose arguments remain opaque.
|
|
35
37
|
*
|
|
36
38
|
* Its options, all before the command (bats-core manual, "`run`: Test other
|
|
37
39
|
* commands"): `-N` (expect exit status N, 0–255), `!` (expect a nonzero
|
|
@@ -16,6 +16,8 @@ export const BATS_HELPERS = Object.freeze([
|
|
|
16
16
|
/**
|
|
17
17
|
* bats' `run`, as a transparent wrapper: it runs the command after its own
|
|
18
18
|
* options and captures the result, so `run curl x` uses `curl`.
|
|
19
|
+
* Only the exact function name has these semantics; an executable path such
|
|
20
|
+
* as `/tmp/run` is an external dependency whose arguments remain opaque.
|
|
19
21
|
*
|
|
20
22
|
* Its options, all before the command (bats-core manual, "`run`: Test other
|
|
21
23
|
* commands"): `-N` (expect exit status N, 0–255), `!` (expect a nonzero
|
|
@@ -28,6 +30,7 @@ export const BATS_HELPERS = Object.freeze([
|
|
|
28
30
|
*/
|
|
29
31
|
export const BATS_RUN_WRAPPER = Object.freeze({
|
|
30
32
|
names: Object.freeze(['run']),
|
|
33
|
+
shellBuiltin: true,
|
|
31
34
|
noArgFlags: Object.freeze(['!', '--keep-empty-lines', '--separate-stderr']),
|
|
32
35
|
noArgFlagPattern: /^-\d+$/u,
|
|
33
36
|
});
|
|
@@ -1,24 +1,8 @@
|
|
|
1
1
|
import type { WrapperSpec } from 'sh-ast/analyze';
|
|
2
2
|
import type { ShellDialect } from '../language/shell-language-options.js';
|
|
3
3
|
/**
|
|
4
|
-
* Returns the
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* 1. `sh-ast/analyze`'s `DEFAULT_TRANSPARENT_WRAPPERS` (`sudo`, `env`, …);
|
|
8
|
-
* 2. the dialect's own wrappers (`run` under `bats`);
|
|
9
|
-
* 3. the project's network wrapper (`settings.sh.networkWrapper`), when set,
|
|
10
|
-
* with the options its spec declares: a wrapper that network commands must
|
|
11
|
-
* run through runs the command after it;
|
|
12
|
-
* 4. one name-only entry per configured name. A name-only entry recognizes
|
|
13
|
-
* no flags, so `with-retry -n 3 curl` stops at `-n` rather than guessing
|
|
14
|
-
* past it.
|
|
15
|
-
*
|
|
16
|
-
* The first entry whose names match is the one used, so a network wrapper
|
|
17
|
-
* spec with options wins over a name-only entry for the same name.
|
|
18
|
-
*
|
|
19
|
-
* @param dialect - The linted file's `sourceCode.dialect`.
|
|
20
|
-
* @param wrapperNames - The rule's `transparentWrappers` option names.
|
|
21
|
-
* @param networkWrapper - The spec from `settings.sh.networkWrapper`, or `null`.
|
|
4
|
+
* Returns the built-in harvest scope for a dialect, including bats' in-process
|
|
5
|
+
* `run` helper only in bats files. Project wrappers are resolved separately.
|
|
22
6
|
* @internal
|
|
23
7
|
*/
|
|
24
|
-
export declare function harvestWrapperTable(dialect: ShellDialect
|
|
8
|
+
export declare function harvestWrapperTable(dialect: ShellDialect): readonly WrapperSpec[];
|
|
@@ -1,49 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* `no-undeclared-commands` and `no-unused-declarations` must agree exactly on
|
|
6
|
-
* which commands a file uses, or one would report a command the other calls
|
|
7
|
-
* unused. Usage depends on the wrapper table, so both build it here from the
|
|
8
|
-
* same inputs: the file's dialect, the network wrapper from
|
|
9
|
-
* `settings.sh.networkWrapper`, and the rule's `transparentWrappers` option
|
|
10
|
-
* names.
|
|
2
|
+
* Built-in wrappers used when comparing command declarations with usage.
|
|
3
|
+
* Both declaration rules compose this dialect scope with the shared project
|
|
4
|
+
* facts through resolveTransparentWrappers, so they compute the same usage.
|
|
11
5
|
*/
|
|
12
6
|
import { DEFAULT_TRANSPARENT_WRAPPERS } from 'sh-ast/analyze';
|
|
13
7
|
import { BATS_RUN_WRAPPER } from './builtins/bats.js';
|
|
14
|
-
/**
|
|
15
|
-
* Wrappers a dialect's runtime provides beyond sh-ast's defaults: bats' `run`
|
|
16
|
-
* for `bats` files.
|
|
17
|
-
*/
|
|
8
|
+
/** Wrappers a dialect runtime provides beyond sh-ast's defaults. */
|
|
18
9
|
const DIALECT_WRAPPERS = {
|
|
19
10
|
bats: [BATS_RUN_WRAPPER],
|
|
20
11
|
};
|
|
21
12
|
/**
|
|
22
|
-
* Returns the
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* 1. `sh-ast/analyze`'s `DEFAULT_TRANSPARENT_WRAPPERS` (`sudo`, `env`, …);
|
|
26
|
-
* 2. the dialect's own wrappers (`run` under `bats`);
|
|
27
|
-
* 3. the project's network wrapper (`settings.sh.networkWrapper`), when set,
|
|
28
|
-
* with the options its spec declares: a wrapper that network commands must
|
|
29
|
-
* run through runs the command after it;
|
|
30
|
-
* 4. one name-only entry per configured name. A name-only entry recognizes
|
|
31
|
-
* no flags, so `with-retry -n 3 curl` stops at `-n` rather than guessing
|
|
32
|
-
* past it.
|
|
33
|
-
*
|
|
34
|
-
* The first entry whose names match is the one used, so a network wrapper
|
|
35
|
-
* spec with options wins over a name-only entry for the same name.
|
|
36
|
-
*
|
|
37
|
-
* @param dialect - The linted file's `sourceCode.dialect`.
|
|
38
|
-
* @param wrapperNames - The rule's `transparentWrappers` option names.
|
|
39
|
-
* @param networkWrapper - The spec from `settings.sh.networkWrapper`, or `null`.
|
|
13
|
+
* Returns the built-in harvest scope for a dialect, including bats' in-process
|
|
14
|
+
* `run` helper only in bats files. Project wrappers are resolved separately.
|
|
40
15
|
* @internal
|
|
41
16
|
*/
|
|
42
|
-
export function harvestWrapperTable(dialect
|
|
43
|
-
return [
|
|
44
|
-
...DEFAULT_TRANSPARENT_WRAPPERS,
|
|
45
|
-
...(DIALECT_WRAPPERS[dialect] ?? []),
|
|
46
|
-
...(networkWrapper === null ? [] : [networkWrapper]),
|
|
47
|
-
...wrapperNames.map((name) => ({ names: [name] })),
|
|
48
|
-
];
|
|
17
|
+
export function harvestWrapperTable(dialect) {
|
|
18
|
+
return [...DEFAULT_TRANSPARENT_WRAPPERS, ...(DIALECT_WRAPPERS[dialect] ?? [])];
|
|
49
19
|
}
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
* The `sh/bash-3.2` shared config: the preset for scripts that must run on the
|
|
3
3
|
* Bash 3.2 that macOS ships as `/bin/bash`.
|
|
4
4
|
*
|
|
5
|
-
* The parser accepts every construct its grammar knows whatever
|
|
6
|
-
* configured, so
|
|
7
|
-
* This preset names that
|
|
8
|
-
* and
|
|
9
|
-
*
|
|
5
|
+
* The parser accepts every construct its grammar knows whatever floor is
|
|
6
|
+
* configured, so required Bash 3.2 support is enforced only by the `compat/*` rules.
|
|
7
|
+
* This preset names that floor once (`languageOptions.minBashVersion: '3.2'`)
|
|
8
|
+
* and enables the version gates except the opt-in empty-array nounset check,
|
|
9
|
+
* so a project states its minimum supported Bash as a config choice instead of
|
|
10
|
+
* enumerating rules.
|
|
10
11
|
*
|
|
11
12
|
* It follows the shape contract in `./recommended.ts`, with one deliberate
|
|
12
|
-
* extension: it carries `languageOptions`, because the
|
|
13
|
+
* extension: it carries `languageOptions`, because the minimum supported version is the
|
|
13
14
|
* preset's whole meaning and a pack that left it to the user would enable
|
|
14
15
|
* rules that report nothing. It still carries no `files` or `ignores`, so it
|
|
15
16
|
* inherits the user's globs, and it composes with the other presets through
|
package/dist/configs/bash-3-2.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The rules `sh/bash-3.2` enables:
|
|
2
|
+
* The rules `sh/bash-3.2` enables: twenty-one version-gated `compat/*` rules, all at
|
|
3
3
|
* `error`, keyed as a user writes them (`sh/<rule-name>`). Each reports a
|
|
4
4
|
* feature that Bash 3.2 lacks and names the portable alternative.
|
|
5
|
+
* `compat/no-nounset-empty-array` is opt-in: caller and helper contracts can
|
|
6
|
+
* guarantee non-empty arrays beyond the rule's local safety proofs.
|
|
5
7
|
* `shebang-matches-dialect` is not a version gate and belongs to the
|
|
6
8
|
* presets whose catalog row names it. The POSIX-only gates
|
|
7
9
|
* (`compat/no-double-bracket`, `compat/no-let`, `compat/no-source`) are not
|
|
@@ -13,6 +15,7 @@
|
|
|
13
15
|
const bash32Rules = {
|
|
14
16
|
'sh/compat/no-append-all-redirect': 'error',
|
|
15
17
|
'sh/compat/no-associative-arrays': 'error',
|
|
18
|
+
'sh/compat/no-brace-sequence-padding-step': 'error',
|
|
16
19
|
'sh/compat/no-case-attributes': 'error',
|
|
17
20
|
'sh/compat/no-case-fallthrough': 'error',
|
|
18
21
|
'sh/compat/no-case-modification': 'error',
|
|
@@ -25,7 +28,6 @@ const bash32Rules = {
|
|
|
25
28
|
'sh/compat/no-mapfile': 'error',
|
|
26
29
|
'sh/compat/no-nameref': 'error',
|
|
27
30
|
'sh/compat/no-negative-array-index': 'error',
|
|
28
|
-
'sh/compat/no-nounset-empty-array': 'error',
|
|
29
31
|
'sh/compat/no-parameter-transformation': 'error',
|
|
30
32
|
'sh/compat/no-pipe-all': 'error',
|
|
31
33
|
'sh/compat/no-printf-time-format': 'error',
|
|
@@ -44,7 +46,7 @@ export function createBash32Config(plugin) {
|
|
|
44
46
|
name: 'sh/bash-3.2',
|
|
45
47
|
plugins: { sh: plugin },
|
|
46
48
|
language: 'sh/sh',
|
|
47
|
-
languageOptions: { dialect: 'bash',
|
|
49
|
+
languageOptions: { dialect: 'bash', minBashVersion: '3.2' },
|
|
48
50
|
rules: { ...bash32Rules },
|
|
49
51
|
};
|
|
50
52
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* POSIX `sh` rather than for Bash.
|
|
4
4
|
*
|
|
5
5
|
* It sets `languageOptions.dialect: 'posix'`, which makes every Bash-only
|
|
6
|
-
* feature unavailable at any `
|
|
6
|
+
* feature unavailable at any `minBashVersion`, and enables the `compat/*` rules
|
|
7
7
|
* that report those features. The dialect is also what every dialect-aware
|
|
8
8
|
* rule reads, so the preset is one switch rather than a list of settings that
|
|
9
9
|
* could drift apart.
|
|
@@ -12,6 +12,7 @@ const posixPortableRules = {
|
|
|
12
12
|
'sh/shebang-matches-dialect': 'error',
|
|
13
13
|
'sh/compat/no-append-all-redirect': 'error',
|
|
14
14
|
'sh/compat/no-associative-arrays': 'error',
|
|
15
|
+
'sh/compat/no-brace-sequence-padding-step': 'error',
|
|
15
16
|
'sh/compat/no-case-attributes': 'error',
|
|
16
17
|
'sh/compat/no-case-fallthrough': 'error',
|
|
17
18
|
'sh/compat/no-case-modification': 'error',
|
|
@@ -44,8 +44,8 @@ export declare function toLintedFile(context: LintedFile): LintedFile;
|
|
|
44
44
|
* `filename`, `physicalFilename` and `cwd`, never the whole context, so it
|
|
45
45
|
* sees which file it is reading and nothing it could report through.
|
|
46
46
|
*
|
|
47
|
-
* Throws an `Error`
|
|
48
|
-
*
|
|
47
|
+
* Throws an `Error` naming the declaration-convention setting and showing the
|
|
48
|
+
* offending value when
|
|
49
49
|
* `declaredCommands` does not return an array, or returns a declaration with
|
|
50
50
|
* a missing or unknown `kind`, without its kind's fields, or with a `range`
|
|
51
51
|
* outside the linted text.
|
|
@@ -88,8 +88,8 @@ function describe(value) {
|
|
|
88
88
|
* `filename`, `physicalFilename` and `cwd`, never the whole context, so it
|
|
89
89
|
* sees which file it is reading and nothing it could report through.
|
|
90
90
|
*
|
|
91
|
-
* Throws an `Error`
|
|
92
|
-
*
|
|
91
|
+
* Throws an `Error` naming the declaration-convention setting and showing the
|
|
92
|
+
* offending value when
|
|
93
93
|
* `declaredCommands` does not return an array, or returns a declaration with
|
|
94
94
|
* a missing or unknown `kind`, without its kind's fields, or with a `range`
|
|
95
95
|
* outside the linted text.
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
* `@eslint-sh/eslint-plugin/syntax/analyze`. That is why these names live on their own subpath
|
|
19
19
|
* and are not merged into the root.
|
|
20
20
|
*
|
|
21
|
+
* The low-level `printSync` keeps upstream behavior, including changes to literal vertical tabs
|
|
22
|
+
* and form feeds. It does not apply the high-level content refusal used by `format` and
|
|
23
|
+
* `ShellSourceCode.getPrintedReplacement`; callers printing directly must account for that loss.
|
|
24
|
+
*
|
|
21
25
|
* @packageDocumentation
|
|
22
26
|
*/
|
|
23
27
|
|
package/dist/eslint-plugin.d.ts
CHANGED
|
@@ -333,7 +333,7 @@ export declare interface LintedFile {
|
|
|
333
333
|
export declare interface NormalizedShellLanguageOptions extends Record<string, unknown> {
|
|
334
334
|
readonly dialect: ShellDialect;
|
|
335
335
|
readonly directivePrefix: string;
|
|
336
|
-
readonly
|
|
336
|
+
readonly minBashVersion?: string;
|
|
337
337
|
toJSON(): ShellLanguageOptionsJSON;
|
|
338
338
|
}
|
|
339
339
|
|
|
@@ -362,8 +362,9 @@ export declare interface NormalizedShellLanguageOptions extends Record<string, u
|
|
|
362
362
|
* machine-written, human-reviewed scripts:
|
|
363
363
|
* every `recommended` rule plus the contract rules, all at `error`.
|
|
364
364
|
* `configs['bash-3.2']` and `configs['posix-portable']` are deployment-target
|
|
365
|
-
* packs: the first sets `languageOptions.
|
|
366
|
-
*
|
|
365
|
+
* packs: the first sets `languageOptions.minBashVersion: "3.2"` and enables
|
|
366
|
+
* the version-gated `compat/*` rules except the opt-in
|
|
367
|
+
* `compat/no-nounset-empty-array`; the second sets
|
|
367
368
|
* `languageOptions.dialect: "posix"`, enables the `compat/*` rules and the
|
|
368
369
|
* shebang/dialect check, and requires `set -eu`; it reports named constructs
|
|
369
370
|
* that fail on dash, not every non-POSIX construct, and leaves `local`,
|
|
@@ -407,8 +408,8 @@ export default plugin;
|
|
|
407
408
|
* `filename`, `physicalFilename` and `cwd`, never the whole context, so it
|
|
408
409
|
* sees which file it is reading and nothing it could report through.
|
|
409
410
|
*
|
|
410
|
-
* Throws an `Error`
|
|
411
|
-
*
|
|
411
|
+
* Throws an `Error` naming the declaration-convention setting and showing the
|
|
412
|
+
* offending value when
|
|
412
413
|
* `declaredCommands` does not return an array, or returns a declaration with
|
|
413
414
|
* a missing or unknown `kind`, without its kind's fields, or with a `range`
|
|
414
415
|
* outside the linted text.
|
|
@@ -437,16 +438,15 @@ export { ResolveArgv0Options }
|
|
|
437
438
|
/**
|
|
438
439
|
* Resolves the declaration convention bound for the rule running in
|
|
439
440
|
* `context`: the rule's `declarationConvention` option, else
|
|
440
|
-
* `settings
|
|
441
|
+
* `settings: { sh: { declarationConvention: convention } }`, else `null`
|
|
442
|
+
* (the rule is inert).
|
|
441
443
|
*
|
|
442
444
|
* Throws an `Error` naming the offending setting when the configured value is
|
|
443
445
|
* present but does not implement `declaredCommands` (or has a non-function
|
|
444
446
|
* `removeDeclaration`). The message names where the value came from and what
|
|
445
|
-
* it was,
|
|
446
|
-
* `
|
|
447
|
-
*
|
|
448
|
-
* surfaces as ESLint's
|
|
449
|
-
* configuration message for the file being linted.
|
|
447
|
+
* it was, including the expected convention shape and the received value.
|
|
448
|
+
* Call it from `create()`, so the error surfaces as ESLint's configuration
|
|
449
|
+
* message for the file being linted.
|
|
450
450
|
*
|
|
451
451
|
* A rule that receives `null` should register no listeners: with no
|
|
452
452
|
* convention bound, a convention consumer has nothing to check.
|
|
@@ -480,6 +480,34 @@ export { ResolveArgv0Options }
|
|
|
480
480
|
*/
|
|
481
481
|
export declare function resolveDeclarationConvention(context: DeclarationConventionBindingContext): DeclarationConvention | null;
|
|
482
482
|
|
|
483
|
+
/**
|
|
484
|
+
* Returns the shared project wrappers followed by `builtIns` (defaults when
|
|
485
|
+
* omitted). Entries accept command names or JSON-expressible `WrapperSpec`s
|
|
486
|
+
* in `settings: { sh: { transparentWrappers: [...] } }`. The shared network
|
|
487
|
+
* wrapper is also transparent; conflicting specs for the same project name
|
|
488
|
+
* throw rather than allowing policies to disagree. Shared specs compare effective
|
|
489
|
+
* grammars for overlapping names, normalizing matcher defaults and retaining
|
|
490
|
+
* expanded built-in flag patterns; an extra transparent alias does not acquire
|
|
491
|
+
* network approval. Explicit specs remain complete replacements. Duplicate project
|
|
492
|
+
* names are rejected so list order cannot silently choose their meaning.
|
|
493
|
+
*
|
|
494
|
+
* Utility wrappers match absolute and relative paths by basename. Path words
|
|
495
|
+
* remain unchanged in analysis results. `shellBuiltin: true` entries match
|
|
496
|
+
* exact names only: an executable path cannot acquire in-process semantics.
|
|
497
|
+
* An explicit path spec takes precedence over a basename fallback regardless
|
|
498
|
+
* of configuration order.
|
|
499
|
+
* Aliases are built even when only `builtIns` are supplied. Overridden names
|
|
500
|
+
* are removed from lower-priority entries, preserving their unrelated aliases
|
|
501
|
+
* and preventing a utility entry from undoing an exact-name builtin override.
|
|
502
|
+
* The input tables are never mutated.
|
|
503
|
+
*
|
|
504
|
+
* @param context - The consuming rule's context.
|
|
505
|
+
* @param builtIns - The rule's own built-in wrapper scope.
|
|
506
|
+
* @throws Error when a configured wrapper is malformed or contradictory.
|
|
507
|
+
* @public
|
|
508
|
+
*/
|
|
509
|
+
export declare function resolveTransparentWrappers(context: TransparentWrappersBindingContext, builtIns?: readonly WrapperSpec[]): readonly WrapperSpec[];
|
|
510
|
+
|
|
483
511
|
/**
|
|
484
512
|
* Resolves a parsed lint Word using the upstream-shaped syntax associated with it.
|
|
485
513
|
* The view supplies locations and selector fields; sh-ast/analyze owns the word
|
|
@@ -610,11 +638,12 @@ export declare class ShellLanguage implements Language {
|
|
|
610
638
|
readonly defaultLanguageOptions: ShellLanguageOptions;
|
|
611
639
|
/**
|
|
612
640
|
* Validates `languageOptions.dialect` (must be one of the five supported
|
|
613
|
-
* dialects, if present), `languageOptions.
|
|
614
|
-
* string matching the `MAJOR[.MINOR]` numeric shape, if present
|
|
641
|
+
* dialects, if present), `languageOptions.minBashVersion` (must be a
|
|
642
|
+
* string matching the `MAJOR[.MINOR]` numeric shape, if present, and
|
|
643
|
+
* applies only to `bash` and `bats`), and
|
|
615
644
|
* `languageOptions.directivePrefix` (must be a valid directive-comment
|
|
616
|
-
* label, if present).
|
|
617
|
-
*
|
|
645
|
+
* label, if present). The removed `shellVersion` key throws with
|
|
646
|
+
* migration guidance; other unknown keys are silently ignored. See `shell-language-options.ts`'s
|
|
618
647
|
* `validateShellLanguageOptions` for the full rationale.
|
|
619
648
|
*/
|
|
620
649
|
validateLanguageOptions(languageOptions: ShellLanguageOptions): void;
|
|
@@ -648,9 +677,9 @@ export declare class ShellLanguage implements Language {
|
|
|
648
677
|
* A file whose extension marks it as a known non-shell source type (for
|
|
649
678
|
* example `.js` or `.json`) is never shell-parsed: it fails with a single
|
|
650
679
|
* diagnostic explaining that a `language: 'sh/sh'` config entry without
|
|
651
|
-
* `files` reached it, and how to scope that entry.
|
|
652
|
-
*
|
|
653
|
-
*
|
|
680
|
+
* `files` reached it, and how to scope that entry. Unicode characters remain
|
|
681
|
+
* source text. A native nesting-budget refusal returns no partial tree and
|
|
682
|
+
* becomes a fatal resource diagnostic at 1:1.
|
|
654
683
|
*/
|
|
655
684
|
parse(file: File_2, context: {
|
|
656
685
|
languageOptions: ShellLanguageOptions;
|
|
@@ -665,8 +694,8 @@ export declare class ShellLanguage implements Language {
|
|
|
665
694
|
* present, but `?? 'eslint'` stays as an explicit, honest fallback for
|
|
666
695
|
* direct construction (e.g. tests that skip the `Language` normalization
|
|
667
696
|
* step), mirroring `parse()`'s `dialect` default above. `dialect` and
|
|
668
|
-
* `
|
|
669
|
-
* through `sourceCode.dialect` / `sourceCode.
|
|
697
|
+
* `minBashVersion` are forwarded so rules read the same normalized values
|
|
698
|
+
* through `sourceCode.dialect` / `sourceCode.minBashVersion`.
|
|
670
699
|
*/
|
|
671
700
|
createSourceCode(file: File_2, parseResult: OkParseResult<ShellFile>, context: {
|
|
672
701
|
languageOptions: ShellLanguageOptions;
|
|
@@ -675,7 +704,7 @@ export declare class ShellLanguage implements Language {
|
|
|
675
704
|
|
|
676
705
|
/**
|
|
677
706
|
* `languageOptions` accepted by {@link ShellLanguage}: `dialect` selects
|
|
678
|
-
* mvdan/sh's `LangVariant` through a consumer-owned mapping (default `"bash"`); `
|
|
707
|
+
* mvdan/sh's `LangVariant` through a consumer-owned mapping (default `"bash"`); `minBashVersion`
|
|
679
708
|
* is consumed by the rule layer (e.g. the bash-3.2 compatibility pack),
|
|
680
709
|
* never by the parser itself.
|
|
681
710
|
*
|
|
@@ -691,13 +720,14 @@ export declare class ShellLanguage implements Language {
|
|
|
691
720
|
export declare interface ShellLanguageOptions extends Record<string, unknown> {
|
|
692
721
|
readonly dialect?: ShellDialect;
|
|
693
722
|
/**
|
|
694
|
-
* The Bash version (`MAJOR[.MINOR]`, such as `"3.2"`) the
|
|
695
|
-
*
|
|
696
|
-
*
|
|
697
|
-
*
|
|
698
|
-
* version.
|
|
723
|
+
* The minimum Bash version (`MAJOR[.MINOR]`, such as `"3.2"`) the
|
|
724
|
+
* script must support, including every newer Bash. Only valid with the
|
|
725
|
+
* `bash` or `bats` dialect (the default is `bash`). The parser ignores
|
|
726
|
+
* it; `compat/*` rules report features unavailable at this floor. Unset
|
|
727
|
+
* means no Bash version constraint. Versions compare numerically by
|
|
728
|
+
* major then minor, with no upper version limit.
|
|
699
729
|
*/
|
|
700
|
-
readonly
|
|
730
|
+
readonly minBashVersion?: string;
|
|
701
731
|
/**
|
|
702
732
|
* The prefix directive/inline-config comments must start with — e.g. the
|
|
703
733
|
* default `"eslint"` recognizes `# eslint-disable-next-line ...` and
|
|
@@ -711,14 +741,14 @@ export declare interface ShellLanguageOptions extends Record<string, unknown> {
|
|
|
711
741
|
|
|
712
742
|
/**
|
|
713
743
|
* The plain-data shape {@link NormalizedShellLanguageOptions.toJSON} returns:
|
|
714
|
-
* `dialect` and `directivePrefix` always present (both defaulted), `
|
|
744
|
+
* `dialect` and `directivePrefix` always present (both defaulted), `minBashVersion`
|
|
715
745
|
* present only when the caller supplied one. Keys are always emitted in this
|
|
716
746
|
* fixed order so that two logically-identical inputs serialize identically
|
|
717
747
|
* regardless of the key order the caller happened to use — the property this
|
|
718
748
|
* type exists to guarantee for cache-key stability (see
|
|
719
749
|
* {@link NormalizedShellLanguageOptions}). `directivePrefix` is included
|
|
720
|
-
* unconditionally (like `dialect`, unlike `
|
|
721
|
-
* `dialect` and unlike `
|
|
750
|
+
* unconditionally (like `dialect`, unlike `minBashVersion`) because — like
|
|
751
|
+
* `dialect` and unlike `minBashVersion` — it always has a concrete effect on
|
|
722
752
|
* linting results (which comments the `SourceCode` recognizes as directives)
|
|
723
753
|
* whether or not the caller supplied one, so two configs that differ only in
|
|
724
754
|
* an *implicit* default vs. an *explicit* `directivePrefix: "eslint"` must
|
|
@@ -729,7 +759,7 @@ export declare interface ShellLanguageOptions extends Record<string, unknown> {
|
|
|
729
759
|
export declare interface ShellLanguageOptionsJSON {
|
|
730
760
|
readonly dialect: ShellDialect;
|
|
731
761
|
readonly directivePrefix: string;
|
|
732
|
-
readonly
|
|
762
|
+
readonly minBashVersion?: string;
|
|
733
763
|
}
|
|
734
764
|
|
|
735
765
|
/**
|
|
@@ -974,7 +1004,7 @@ export declare interface ShellRuleVisitor extends ShellTypedListeners {
|
|
|
974
1004
|
* the string `jq`?", "which command does this invocation run?", and "which
|
|
975
1005
|
* commands does this file run, and where?" by delegating to
|
|
976
1006
|
* `sh-ast/analyze`. They never reinterpret words themselves, so every rule
|
|
977
|
-
* gets the same answer for the same syntax. `dialect` and `
|
|
1007
|
+
* gets the same answer for the same syntax. `dialect` and `minBashVersion`
|
|
978
1008
|
* expose the file's normalized language options.
|
|
979
1009
|
*
|
|
980
1010
|
* Syntax access (`getSyntax`, `getViewNode`, `getIndexFromSyntaxPos`,
|
|
@@ -1001,7 +1031,7 @@ export declare class ShellSourceCode extends TextSourceCodeBase<{
|
|
|
1001
1031
|
ast: ShellFile;
|
|
1002
1032
|
directivePrefix?: string;
|
|
1003
1033
|
dialect?: ShellDialect;
|
|
1004
|
-
|
|
1034
|
+
minBashVersion?: string;
|
|
1005
1035
|
});
|
|
1006
1036
|
/**
|
|
1007
1037
|
* The shell dialect this file was parsed as: the normalized
|
|
@@ -1010,11 +1040,12 @@ export declare class ShellSourceCode extends TextSourceCodeBase<{
|
|
|
1010
1040
|
*/
|
|
1011
1041
|
get dialect(): ShellDialect;
|
|
1012
1042
|
/**
|
|
1013
|
-
* The configured `languageOptions.
|
|
1043
|
+
* The configured `languageOptions.minBashVersion` (a `MAJOR[.MINOR]` string
|
|
1014
1044
|
* such as `"3.2"`), or `undefined` when the config does not set one. The
|
|
1015
|
-
*
|
|
1045
|
+
* script must support this Bash and every newer release. The parser never
|
|
1046
|
+
* reads it; compatibility rules use it as a floor with no upper limit.
|
|
1016
1047
|
*/
|
|
1017
|
-
get
|
|
1048
|
+
get minBashVersion(): string | undefined;
|
|
1018
1049
|
/**
|
|
1019
1050
|
* The one-based location of a UTF-16 `index` in this file's text, where
|
|
1020
1051
|
* `index` may be anywhere from 0 to `text.length`. CRLF counts as one line
|
|
@@ -1103,13 +1134,19 @@ export declare class ShellSourceCode extends TextSourceCodeBase<{
|
|
|
1103
1134
|
* effective command's name as
|
|
1104
1135
|
* `res.effective.static ? res.effective.text : null`.
|
|
1105
1136
|
* `sudo -u x "$prog"` and `exec "$@"` have a non-static `effective` with
|
|
1106
|
-
* reason `expansion`; `env -S '…'`
|
|
1137
|
+
* reason `expansion`; `env -S '…'` and `bash -c '…'` have reason
|
|
1138
|
+
* `embedded-command`; `chain`
|
|
1107
1139
|
* lists every word resolved along the way, outermost wrapper first, and
|
|
1108
1140
|
* `chainIndices` gives each entry's position in the command's `argv` (as
|
|
1109
1141
|
* {@link ShellSourceCode.getCommandSites} reports it). When `effective` is
|
|
1110
1142
|
* static, the effective command's arguments are
|
|
1111
1143
|
* `argv.slice(chainIndices.at(-1)! + 1)`: every entry after the effective
|
|
1112
|
-
* command's own index.
|
|
1144
|
+
* command's own index. For an interpreter command string the final chain
|
|
1145
|
+
* index instead locates the selector flag; the interpreter is in `chain.at(-2)`.
|
|
1146
|
+
* `embeddedCommandInterpreters: []` retains the interpreter as the static
|
|
1147
|
+
* effective command when a policy needs program identity. Utility wrappers
|
|
1148
|
+
* can match absolute-path basenames; `shellBuiltin: true` entries require
|
|
1149
|
+
* exact names, so external paths do not acquire in-process semantics.
|
|
1113
1150
|
*
|
|
1114
1151
|
* Enumeration runs once per file, the first time any command helper is
|
|
1115
1152
|
* called. If the file's nesting exceeds `enumerateCommands`'s recursion
|
|
@@ -1270,8 +1307,9 @@ export declare class ShellSourceCode extends TextSourceCodeBase<{
|
|
|
1270
1307
|
* @throws TypeError when `node` has no original record in this file (see
|
|
1271
1308
|
* {@link ShellSourceCode.getEditableSyntax}), when `edited` is not a
|
|
1272
1309
|
* printable root (the message names its type), or when the printer's output
|
|
1273
|
-
* is not valid UTF-8
|
|
1274
|
-
*
|
|
1310
|
+
* is not valid UTF-8, or the edited syntax contains literal vertical tabs or
|
|
1311
|
+
* form feeds that the printer cannot preserve. Non-UTF-8 output comes back
|
|
1312
|
+
* from `printSync` as a `Uint8Array` and is never decoded lossily into a fix.
|
|
1275
1313
|
* @throws `PrintError` or `PrintPanicError` (from sh-ast) when upstream's
|
|
1276
1314
|
* printer fails for `edited` or `options`.
|
|
1277
1315
|
*/
|
|
@@ -1400,6 +1438,14 @@ export declare type ShellTypedListeners = {
|
|
|
1400
1438
|
[Type in ShellNodeType as Type | `${Type}:exit`]?: ShellListener<ShellNodeOf<Type>>;
|
|
1401
1439
|
};
|
|
1402
1440
|
|
|
1441
|
+
/** The rule-context fields needed to resolve shared wrappers and their path spellings. @public */
|
|
1442
|
+
export declare interface TransparentWrappersBindingContext {
|
|
1443
|
+
/** Shared ESLint configuration containing the project's shell facts. */
|
|
1444
|
+
readonly settings: SettingsConfig;
|
|
1445
|
+
/** The current file supplies path spellings without filesystem inspection or execution. */
|
|
1446
|
+
readonly sourceCode: ShellSourceCode;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1403
1449
|
export { WordResolution }
|
|
1404
1450
|
|
|
1405
1451
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export type { DeclarationConvention, DeclaredCommand, FileDeclaredCommand, Linte
|
|
|
14
14
|
export { readDeclaredCommands } from './declaration-conventions/read-declared-commands.js';
|
|
15
15
|
export type { DeclarationReadContext } from './declaration-conventions/read-declared-commands.js';
|
|
16
16
|
export { commentPragma } from './declaration-conventions/comment-pragma.js';
|
|
17
|
+
export { resolveTransparentWrappers } from './rules/resolve-transparent-wrappers.js';
|
|
18
|
+
export type { TransparentWrappersBindingContext } from './rules/resolve-transparent-wrappers.js';
|
|
17
19
|
export { resolveDeclarationConvention } from './rules/resolve-declaration-convention.js';
|
|
18
20
|
export type { DeclarationConventionBindingContext } from './rules/resolve-declaration-convention.js';
|
|
19
21
|
export { defineShellRule } from './rules/define-shell-rule.js';
|
|
@@ -46,8 +48,9 @@ export type { WrapperSpec } from 'sh-ast/analyze';
|
|
|
46
48
|
* machine-written, human-reviewed scripts:
|
|
47
49
|
* every `recommended` rule plus the contract rules, all at `error`.
|
|
48
50
|
* `configs['bash-3.2']` and `configs['posix-portable']` are deployment-target
|
|
49
|
-
* packs: the first sets `languageOptions.
|
|
50
|
-
*
|
|
51
|
+
* packs: the first sets `languageOptions.minBashVersion: "3.2"` and enables
|
|
52
|
+
* the version-gated `compat/*` rules except the opt-in
|
|
53
|
+
* `compat/no-nounset-empty-array`; the second sets
|
|
51
54
|
* `languageOptions.dialect: "posix"`, enables the `compat/*` rules and the
|
|
52
55
|
* shebang/dialect check, and requires `set -eu`; it reports named constructs
|
|
53
56
|
* that fail on dash, not every non-POSIX construct, and leaves `local`,
|