@eslint-sh/eslint-plugin 0.7.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 +14 -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 +4 -3
- package/dist/configs/posix-portable.d.ts +1 -1
- 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.js +4 -4
- 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 +9 -9
- package/dist/rules/compat/version-gates.js +13 -13
- package/dist/rules/create-wrapper-rule.js +12 -7
- 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/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 +76 -27
- package/docs/custom-rule-tutorial.md +9 -3
- package/docs/examples/no-listed-commands-rule.ts +2 -2
- package/docs/rules/README.md +36 -4
- 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 +12 -12
- 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/shellcheck.md +9 -5
- package/docs/transparent-wrappers.md +97 -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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# `sh/compat/no-parameter-transformation`
|
|
2
2
|
|
|
3
|
-
Disallow the parameter transformations `${v@op}` in scripts
|
|
3
|
+
Disallow the parameter transformations `${v@op}` in scripts that must support a shell lacking the
|
|
4
4
|
operator: `@Q`, `@E`, `@P`, `@A` and `@a` need Bash 4.4, `@U`, `@u`, `@L` and `@K` need Bash 5.1,
|
|
5
5
|
and `@k` needs Bash 5.2. POSIX sh has none of them.
|
|
6
6
|
|
|
@@ -12,14 +12,14 @@ and `@k` needs Bash 5.2. POSIX sh has none of them.
|
|
|
12
12
|
|
|
13
13
|
Bash 4.4 added the first transformations (Bash NEWS for 4.4), Bash 5.1 the case operators and `@K`, and Bash 5.2 `@k`. A release that lacks the operator fails with `${v@Q}: bad substitution` at the moment the word is expanded. The boundary of each operator was checked against real shells; see [Evidence](../../compat.md#evidence).
|
|
14
14
|
|
|
15
|
-
The rule reads every parameter expansion whose operator is `@` followed by one of the ten letters. It reports when the file
|
|
15
|
+
The rule reads every parameter expansion whose operator is `@` followed by one of the ten letters. It reports when the minimum Bash version the file must support predates that letter's release; the report is on the whole expansion. A file that must support Bash 5.0, for example, gets reports for `@U` but not for `@Q`. An `@` inside another expansion's word (`${v:-@Q}`) and text in single quotes are not expansions and are not reported.
|
|
16
16
|
|
|
17
|
-
The message names
|
|
17
|
+
The message names an alternative that works on the shells the file must support:
|
|
18
18
|
|
|
19
|
-
- `@Q`: `printf '%q' "$v"`. It quotes differently (`a\ b` instead of `'a b'`), but `eval` reads it back as the same value. Not offered for a POSIX
|
|
19
|
+
- `@Q`: `printf '%q' "$v"`. It quotes differently (`a\ b` instead of `'a b'`), but `eval` reads it back as the same value. Not offered for a file that must support POSIX sh, whose `printf` has no `%q`.
|
|
20
20
|
- `@E`: `printf '%b' "$v"`.
|
|
21
|
-
- `@A`: `declare -p v`. It prints the declaration rather than expanding to it, so capture it (`s=$(declare -p v)`) and `eval "$s"` to re-create the variable. Not offered for a POSIX
|
|
22
|
-
- `@U`, `@u`, `@L`: the Bash 4.0 case expansions `"${v^^}"`, `"${v^}"`, `"${v,,}"`
|
|
21
|
+
- `@A`: `declare -p v`. It prints the declaration rather than expanding to it, so capture it (`s=$(declare -p v)`) and `eval "$s"` to re-create the variable. Not offered for a file that must support POSIX sh.
|
|
22
|
+
- `@U`, `@u`, `@L`: the Bash 4.0 case expansions `"${v^^}"`, `"${v^}"`, `"${v,,}"` when the minimum supported Bash is from 4.0 to 5.0, or a `tr` conversion for an older Bash.
|
|
23
23
|
- `@P`, `@a`, `@K`, `@k`: no equivalent expansion; the message says so.
|
|
24
24
|
|
|
25
25
|
Under `dialect: "posix"` the parser itself rejects `${v@op}`, so a POSIX file that uses it fails to parse and this rule does not run on it.
|
|
@@ -27,18 +27,18 @@ Under `dialect: "posix"` the parser itself rejects `${v@op}`, so a POSIX file th
|
|
|
27
27
|
This is a version-compat rule. Whether it reports depends only on `languageOptions`, as
|
|
28
28
|
described in [version compatibility](../../compat.md):
|
|
29
29
|
|
|
30
|
-
- `
|
|
31
|
-
- `dialect: "bash"` (the default) or `"bats"`: reports an operator when `
|
|
30
|
+
- `minBashVersion` unset: no Bash version constraint, so no report under `bash` or `bats`.
|
|
31
|
+
- `dialect: "bash"` (the default) or `"bats"`: reports an operator when `minBashVersion` is older than its release.
|
|
32
32
|
- `dialect: "mksh"` or `"zsh"`: never reports.
|
|
33
33
|
|
|
34
34
|
## Options
|
|
35
35
|
|
|
36
|
-
This rule has no options. Set the
|
|
36
|
+
This rule has no options. Set the required support through `languageOptions`:
|
|
37
37
|
|
|
38
38
|
```js
|
|
39
39
|
// eslint.config.js
|
|
40
40
|
{
|
|
41
|
-
languageOptions: { dialect: 'bash',
|
|
41
|
+
languageOptions: { dialect: 'bash', minBashVersion: '3.2' },
|
|
42
42
|
rules: {
|
|
43
43
|
'sh/compat/no-parameter-transformation': 'error',
|
|
44
44
|
},
|
|
@@ -49,9 +49,9 @@ This rule has no options. Set the target through `languageOptions`:
|
|
|
49
49
|
|
|
50
50
|
### Incorrect
|
|
51
51
|
|
|
52
|
-
With `
|
|
52
|
+
With `minBashVersion: "3.2"`:
|
|
53
53
|
|
|
54
|
-
<!-- example: {"dialect": "bash", "
|
|
54
|
+
<!-- example: {"dialect": "bash", "minBashVersion": "3.2", "findings": 3} -->
|
|
55
55
|
|
|
56
56
|
```sh
|
|
57
57
|
log "running ${cmd@Q}"
|
|
@@ -59,9 +59,9 @@ upper=${name@U}
|
|
|
59
59
|
printf '%s\n' "${args[@]@K}"
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
With `
|
|
62
|
+
With `minBashVersion: "5.0"`, only the case operator reports:
|
|
63
63
|
|
|
64
|
-
<!-- example: {"dialect": "bash", "
|
|
64
|
+
<!-- example: {"dialect": "bash", "minBashVersion": "5.0", "findings": 1} -->
|
|
65
65
|
|
|
66
66
|
```sh
|
|
67
67
|
log "running ${cmd@Q}"
|
|
@@ -70,25 +70,25 @@ upper=${name@U}
|
|
|
70
70
|
|
|
71
71
|
### Correct
|
|
72
72
|
|
|
73
|
-
With `
|
|
73
|
+
With `minBashVersion: "3.2"`:
|
|
74
74
|
|
|
75
|
-
<!-- example: {"dialect": "bash", "
|
|
75
|
+
<!-- example: {"dialect": "bash", "minBashVersion": "3.2"} -->
|
|
76
76
|
|
|
77
77
|
```sh
|
|
78
78
|
log "running $(printf '%q' "$cmd")"
|
|
79
79
|
upper=$(printf '%s' "$name" | tr '[:lower:]' '[:upper:]')
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
-
With `
|
|
82
|
+
With `minBashVersion: "5.2"` or newer, or with no `minBashVersion`, every transformation is fine.
|
|
83
83
|
|
|
84
84
|
## When not to use it
|
|
85
85
|
|
|
86
86
|
Turn the rule off when your scripts never run on a Bash older than the operators they use, or
|
|
87
|
-
leave `
|
|
87
|
+
leave `minBashVersion` unset, which makes the rule report nothing.
|
|
88
88
|
|
|
89
89
|
## Relationship to shellcheck
|
|
90
90
|
|
|
91
91
|
eslint-sh is a convention and contract linter: a policy layer, where shellcheck is the gotcha
|
|
92
92
|
layer. Run shellcheck beside it.
|
|
93
93
|
|
|
94
|
-
shellcheck 0.11.0 reports nothing for `${v@U}`, `${v@Q}` or `${v@a}` under either `-s sh` or `-s bash` (a variable that is never assigned still draws its unrelated SC2154). So shellcheck gives no finding for these expansions in a POSIX sh script or in a Bash
|
|
94
|
+
shellcheck 0.11.0 reports nothing for `${v@U}`, `${v@Q}` or `${v@a}` under either `-s sh` or `-s bash` (a variable that is never assigned still draws its unrelated SC2154). So shellcheck gives no finding for these expansions in a POSIX sh script or in a script that must support a Bash older than the operator's release. This rule exists for those targets.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# `sh/compat/no-pipe-all`
|
|
2
2
|
|
|
3
|
-
Disallow the `|&` pipe, shorthand for `2>&1 |`, in scripts
|
|
3
|
+
Disallow the `|&` pipe, shorthand for `2>&1 |`, in scripts that must support a shell lacking it: Bash older
|
|
4
4
|
than 4.0, including the Bash 3.2 that macOS ships as `/bin/bash`, and POSIX sh.
|
|
5
5
|
|
|
6
6
|
| Configs | Fixable | Languages |
|
|
@@ -20,15 +20,15 @@ Under `dialect: "posix"` the parser itself rejects `|&`, so a POSIX file that us
|
|
|
20
20
|
This is a version-compat rule. Whether it reports depends only on `languageOptions`, as
|
|
21
21
|
described in [version compatibility](../../compat.md):
|
|
22
22
|
|
|
23
|
-
- `
|
|
24
|
-
- `dialect: "bash"` (the default) or `"bats"`: reports when `
|
|
23
|
+
- `minBashVersion` unset: no Bash version constraint, so no report under `bash` or `bats`.
|
|
24
|
+
- `dialect: "bash"` (the default) or `"bats"`: reports when `minBashVersion` is older than `4.0`.
|
|
25
25
|
- `dialect: "mksh"` or `"zsh"`: never reports (in zsh, `|&` is a different operator).
|
|
26
26
|
|
|
27
27
|
### Suggestion
|
|
28
28
|
|
|
29
29
|
A suggestion rewrites the operator:
|
|
30
30
|
|
|
31
|
-
<!-- transform: {"kind": "suggestion", "dialect": "bash", "
|
|
31
|
+
<!-- transform: {"kind": "suggestion", "dialect": "bash", "minBashVersion": "3.2"} -->
|
|
32
32
|
```sh
|
|
33
33
|
make |& tee build.log
|
|
34
34
|
# becomes
|
|
@@ -37,12 +37,12 @@ make 2>&1 | tee build.log
|
|
|
37
37
|
|
|
38
38
|
## Options
|
|
39
39
|
|
|
40
|
-
This rule has no options. Set the
|
|
40
|
+
This rule has no options. Set the required support through `languageOptions`:
|
|
41
41
|
|
|
42
42
|
```js
|
|
43
43
|
// eslint.config.js
|
|
44
44
|
{
|
|
45
|
-
languageOptions: { dialect: 'bash',
|
|
45
|
+
languageOptions: { dialect: 'bash', minBashVersion: '3.2' },
|
|
46
46
|
rules: {
|
|
47
47
|
'sh/compat/no-pipe-all': 'error',
|
|
48
48
|
},
|
|
@@ -53,28 +53,28 @@ This rule has no options. Set the target through `languageOptions`:
|
|
|
53
53
|
|
|
54
54
|
### Incorrect
|
|
55
55
|
|
|
56
|
-
With `
|
|
56
|
+
With `minBashVersion: "3.2"`:
|
|
57
57
|
|
|
58
|
-
<!-- example: {"dialect": "bash", "
|
|
58
|
+
<!-- example: {"dialect": "bash", "minBashVersion": "3.2", "findings": 1} -->
|
|
59
59
|
```sh
|
|
60
60
|
make |& tee build.log
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
### Correct
|
|
64
64
|
|
|
65
|
-
With `
|
|
65
|
+
With `minBashVersion: "3.2"`:
|
|
66
66
|
|
|
67
|
-
<!-- example: {"dialect": "bash", "
|
|
67
|
+
<!-- example: {"dialect": "bash", "minBashVersion": "3.2"} -->
|
|
68
68
|
```sh
|
|
69
69
|
make 2>&1 | tee build.log
|
|
70
70
|
make || echo "failed |& retried"
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
With `
|
|
73
|
+
With `minBashVersion: "4.0"` or newer, or with no `minBashVersion`, `|&` is fine.
|
|
74
74
|
|
|
75
75
|
## When not to use it
|
|
76
76
|
|
|
77
|
-
Turn the rule off when your scripts never run on Bash older than 4.0, or leave `
|
|
77
|
+
Turn the rule off when your scripts never run on Bash older than 4.0, or leave `minBashVersion`
|
|
78
78
|
unset, which makes the rule report nothing.
|
|
79
79
|
|
|
80
80
|
## Relationship to shellcheck
|
|
@@ -82,4 +82,4 @@ unset, which makes the rule report nothing.
|
|
|
82
82
|
eslint-sh is a convention and contract linter: a policy layer, where shellcheck is the gotcha
|
|
83
83
|
layer. Run shellcheck beside it.
|
|
84
84
|
|
|
85
|
-
shellcheck reports `|&` only for a script it treats as POSIX `sh` (its SC3xxx portability checks). It does not know which Bash release a script must run on, so it cannot report `|&` for a Bash 3.2
|
|
85
|
+
shellcheck reports `|&` only for a script it treats as POSIX `sh` (its SC3xxx portability checks). It does not know which Bash release a script must run on, so it cannot report `|&` for a script that must support Bash 3.2. This rule checks that support requirement.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# `sh/compat/no-printf-time-format`
|
|
2
2
|
|
|
3
|
-
Disallow `printf`'s `%(fmt)T` date format in scripts
|
|
3
|
+
Disallow `printf`'s `%(fmt)T` date format in scripts that must support a shell lacking it: Bash older than
|
|
4
4
|
4.2, including the Bash 3.2 that macOS ships as `/bin/bash`, and POSIX sh.
|
|
5
5
|
|
|
6
6
|
| Configs | Fixable | Languages |
|
|
@@ -18,19 +18,19 @@ The portable alternative for the current time is `date '+fmt'`, which takes the
|
|
|
18
18
|
This is a version-compat rule. Whether it reports depends only on `languageOptions`, as
|
|
19
19
|
described in [version compatibility](../../compat.md):
|
|
20
20
|
|
|
21
|
-
- `
|
|
22
|
-
- `dialect: "bash"` (the default) or `"bats"`: reports when `
|
|
23
|
-
- `dialect: "posix"`: reports
|
|
21
|
+
- `minBashVersion` unset: no Bash version constraint, so no report under `bash` or `bats`.
|
|
22
|
+
- `dialect: "bash"` (the default) or `"bats"`: reports when `minBashVersion` is older than `4.2`.
|
|
23
|
+
- `dialect: "posix"`: reports regardless of Bash releases; dash's `printf` has no `%(fmt)T`.
|
|
24
24
|
- `dialect: "mksh"` or `"zsh"`: never reports.
|
|
25
25
|
|
|
26
26
|
## Options
|
|
27
27
|
|
|
28
|
-
This rule has no options. Set the
|
|
28
|
+
This rule has no options. Set the required support through `languageOptions`:
|
|
29
29
|
|
|
30
30
|
```js
|
|
31
31
|
// eslint.config.js
|
|
32
32
|
{
|
|
33
|
-
languageOptions: { dialect: 'bash',
|
|
33
|
+
languageOptions: { dialect: 'bash', minBashVersion: '3.2' },
|
|
34
34
|
rules: {
|
|
35
35
|
'sh/compat/no-printf-time-format': 'error',
|
|
36
36
|
},
|
|
@@ -41,9 +41,9 @@ This rule has no options. Set the target through `languageOptions`:
|
|
|
41
41
|
|
|
42
42
|
### Incorrect
|
|
43
43
|
|
|
44
|
-
With `
|
|
44
|
+
With `minBashVersion: "3.2"`:
|
|
45
45
|
|
|
46
|
-
<!-- example: {"dialect": "bash", "
|
|
46
|
+
<!-- example: {"dialect": "bash", "minBashVersion": "3.2", "findings": 2} -->
|
|
47
47
|
```sh
|
|
48
48
|
printf '%(%Y-%m-%d)T\n' -1
|
|
49
49
|
printf -v stamp '[%(%H:%M:%S)T]' -1
|
|
@@ -51,20 +51,20 @@ printf -v stamp '[%(%H:%M:%S)T]' -1
|
|
|
51
51
|
|
|
52
52
|
### Correct
|
|
53
53
|
|
|
54
|
-
With `
|
|
54
|
+
With `minBashVersion: "3.2"`:
|
|
55
55
|
|
|
56
|
-
<!-- example: {"dialect": "bash", "
|
|
56
|
+
<!-- example: {"dialect": "bash", "minBashVersion": "3.2"} -->
|
|
57
57
|
```sh
|
|
58
58
|
date '+%Y-%m-%d'
|
|
59
59
|
stamp="[$(date '+%H:%M:%S')]"
|
|
60
60
|
printf '100%%(of it)T\n'
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
With `
|
|
63
|
+
With `minBashVersion: "4.2"` or newer, or with no `minBashVersion`, `%(fmt)T` is fine.
|
|
64
64
|
|
|
65
65
|
## When not to use it
|
|
66
66
|
|
|
67
|
-
Turn the rule off when your scripts never run on Bash older than 4.2, or leave `
|
|
67
|
+
Turn the rule off when your scripts never run on Bash older than 4.2, or leave `minBashVersion`
|
|
68
68
|
unset, which makes the rule report nothing.
|
|
69
69
|
|
|
70
70
|
## Relationship to shellcheck
|
|
@@ -72,4 +72,4 @@ unset, which makes the rule report nothing.
|
|
|
72
72
|
eslint-sh is a convention and contract linter: a policy layer, where shellcheck is the gotcha
|
|
73
73
|
layer. Run shellcheck beside it.
|
|
74
74
|
|
|
75
|
-
shellcheck 0.11.0 reports nothing for `printf "%(%s)T\n" -1` under either `-s sh` or `-s bash`. So shellcheck gives no finding for `%(fmt)T` in a POSIX sh script or in a Bash 3.2
|
|
75
|
+
shellcheck 0.11.0 reports nothing for `printf "%(%s)T\n" -1` under either `-s sh` or `-s bash`. So shellcheck gives no finding for `%(fmt)T` in a POSIX sh script or in a script that must support Bash 3.2. This rule exists for both.
|
|
@@ -47,12 +47,12 @@ if [ -r ./lib.sh ]; then . ./lib.sh; else echo fallback; fi
|
|
|
47
47
|
|
|
48
48
|
This is a POSIX-only gate. Every Bash has `source`, so whether the rule reports depends only on `dialect`, as described in [version compatibility](../../compat.md):
|
|
49
49
|
|
|
50
|
-
- `dialect: "posix"`: reports
|
|
50
|
+
- `dialect: "posix"`: reports regardless of Bash releases.
|
|
51
51
|
- `dialect: "bash"` (the default), `"bats"`, `"mksh"` or `"zsh"`: never reports.
|
|
52
52
|
|
|
53
53
|
## Options
|
|
54
54
|
|
|
55
|
-
This rule has no options. Set the
|
|
55
|
+
This rule has no options. Set the required support through `languageOptions`:
|
|
56
56
|
|
|
57
57
|
```js
|
|
58
58
|
// eslint.config.js
|
|
@@ -24,19 +24,19 @@ The portable alternative is `[ -n "${name+set}" ]`. `${name+set}` expands to `se
|
|
|
24
24
|
This is a version-compat rule. Whether it reports depends only on `languageOptions`, as
|
|
25
25
|
described in [version compatibility](../../compat.md):
|
|
26
26
|
|
|
27
|
-
- `
|
|
28
|
-
- `dialect: "bash"` (the default) or `"bats"`: reports when `
|
|
29
|
-
- `dialect: "posix"`: reports `test -v` and `[ -v ]`
|
|
27
|
+
- `minBashVersion` unset: no Bash version constraint, so no report under `bash` or `bats`.
|
|
28
|
+
- `dialect: "bash"` (the default) or `"bats"`: reports when `minBashVersion` is older than `4.2`.
|
|
29
|
+
- `dialect: "posix"`: reports `test -v` and `[ -v ]` regardless of Bash releases; dash has no `-v` test.
|
|
30
30
|
- `dialect: "mksh"` or `"zsh"`: never reports.
|
|
31
31
|
|
|
32
32
|
## Options
|
|
33
33
|
|
|
34
|
-
This rule has no options. Set the
|
|
34
|
+
This rule has no options. Set the required support through `languageOptions`:
|
|
35
35
|
|
|
36
36
|
```js
|
|
37
37
|
// eslint.config.js
|
|
38
38
|
{
|
|
39
|
-
languageOptions: { dialect: 'bash',
|
|
39
|
+
languageOptions: { dialect: 'bash', minBashVersion: '3.2' },
|
|
40
40
|
rules: {
|
|
41
41
|
'sh/compat/no-test-v': 'error',
|
|
42
42
|
},
|
|
@@ -47,9 +47,9 @@ This rule has no options. Set the target through `languageOptions`:
|
|
|
47
47
|
|
|
48
48
|
### Incorrect
|
|
49
49
|
|
|
50
|
-
With `
|
|
50
|
+
With `minBashVersion: "3.2"`:
|
|
51
51
|
|
|
52
|
-
<!-- example: {"dialect": "bash", "
|
|
52
|
+
<!-- example: {"dialect": "bash", "minBashVersion": "3.2", "findings": 3} -->
|
|
53
53
|
```sh
|
|
54
54
|
if [[ -v CI ]]; then echo ci; fi
|
|
55
55
|
if test -v HOME; then echo home; fi
|
|
@@ -58,20 +58,20 @@ if test -v HOME; then echo home; fi
|
|
|
58
58
|
|
|
59
59
|
### Correct
|
|
60
60
|
|
|
61
|
-
With `
|
|
61
|
+
With `minBashVersion: "3.2"`:
|
|
62
62
|
|
|
63
|
-
<!-- example: {"dialect": "bash", "
|
|
63
|
+
<!-- example: {"dialect": "bash", "minBashVersion": "3.2"} -->
|
|
64
64
|
```sh
|
|
65
65
|
if [ -n "${CI+set}" ]; then echo ci; fi
|
|
66
66
|
[ "$flag" = -v ] && verbose=1
|
|
67
67
|
grep -v '^#' config
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
With `
|
|
70
|
+
With `minBashVersion: "4.2"` or newer, or with no `minBashVersion`, the `-v` test is fine.
|
|
71
71
|
|
|
72
72
|
## When not to use it
|
|
73
73
|
|
|
74
|
-
Turn the rule off when your scripts never run on Bash older than 4.2, or leave `
|
|
74
|
+
Turn the rule off when your scripts never run on Bash older than 4.2, or leave `minBashVersion`
|
|
75
75
|
unset, which makes the rule report nothing.
|
|
76
76
|
|
|
77
77
|
## Relationship to shellcheck
|
|
@@ -79,4 +79,4 @@ unset, which makes the rule report nothing.
|
|
|
79
79
|
eslint-sh is a convention and contract linter: a policy layer, where shellcheck is the gotcha
|
|
80
80
|
layer. Run shellcheck beside it.
|
|
81
81
|
|
|
82
|
-
shellcheck reports `[[` and `test -v` only for a script it treats as POSIX `sh` (its SC3xxx portability checks). It does not know which Bash release a script must run on, so it cannot report `[[ -v x ]]` for a Bash 3.2
|
|
82
|
+
shellcheck reports `[[` and `test -v` only for a script it treats as POSIX `sh` (its SC3xxx portability checks). It does not know which Bash release a script must run on, so it cannot report `[[ -v x ]]` for a script that must support Bash 3.2. This rule checks that support requirement.
|
|
@@ -27,18 +27,18 @@ Under `dialect: "posix"` the parser reads `$'…'` as a literal `$` followed by
|
|
|
27
27
|
This is a version-compat rule. Whether it reports depends only on `languageOptions`, as
|
|
28
28
|
described in [version compatibility](../../compat.md):
|
|
29
29
|
|
|
30
|
-
- `
|
|
31
|
-
- `dialect: "bash"` (the default) or `"bats"`: reports an escape when `
|
|
30
|
+
- `minBashVersion` unset: no Bash version constraint, so no report under `bash` or `bats`.
|
|
31
|
+
- `dialect: "bash"` (the default) or `"bats"`: reports an escape when `minBashVersion` is older than its release (4.2, or 4.3 for U+0080 to U+00FF).
|
|
32
32
|
- `dialect: "mksh"` or `"zsh"`: never reports.
|
|
33
33
|
|
|
34
34
|
## Options
|
|
35
35
|
|
|
36
|
-
This rule has no options. Set the
|
|
36
|
+
This rule has no options. Set the required support through `languageOptions`:
|
|
37
37
|
|
|
38
38
|
```js
|
|
39
39
|
// eslint.config.js
|
|
40
40
|
{
|
|
41
|
-
languageOptions: { dialect: 'bash',
|
|
41
|
+
languageOptions: { dialect: 'bash', minBashVersion: '3.2' },
|
|
42
42
|
rules: {
|
|
43
43
|
'sh/compat/no-unicode-escape': 'error',
|
|
44
44
|
},
|
|
@@ -49,17 +49,17 @@ This rule has no options. Set the target through `languageOptions`:
|
|
|
49
49
|
|
|
50
50
|
### Incorrect
|
|
51
51
|
|
|
52
|
-
With `
|
|
52
|
+
With `minBashVersion: "3.2"`:
|
|
53
53
|
|
|
54
|
-
<!-- example: {"dialect": "bash", "
|
|
54
|
+
<!-- example: {"dialect": "bash", "minBashVersion": "3.2", "findings": 2} -->
|
|
55
55
|
```sh
|
|
56
56
|
ok=$'\u2713'
|
|
57
57
|
printf '%s\n' $'caf\u00e9'
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
With `
|
|
60
|
+
With `minBashVersion: "4.2"`, only the Latin-1 range reports:
|
|
61
61
|
|
|
62
|
-
<!-- example: {"dialect": "bash", "
|
|
62
|
+
<!-- example: {"dialect": "bash", "minBashVersion": "4.2", "findings": 1} -->
|
|
63
63
|
```sh
|
|
64
64
|
ok=$'\u2713'
|
|
65
65
|
printf '%s\n' $'caf\u00e9'
|
|
@@ -67,20 +67,20 @@ printf '%s\n' $'caf\u00e9'
|
|
|
67
67
|
|
|
68
68
|
### Correct
|
|
69
69
|
|
|
70
|
-
With `
|
|
70
|
+
With `minBashVersion: "3.2"`:
|
|
71
71
|
|
|
72
|
-
<!-- example: {"dialect": "bash", "
|
|
72
|
+
<!-- example: {"dialect": "bash", "minBashVersion": "3.2"} -->
|
|
73
73
|
```sh
|
|
74
74
|
ok=$'\342\234\223'
|
|
75
75
|
printf '%s\n' $'caf\303\251'
|
|
76
76
|
echo '\u00e9 is written literally here'
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
With `
|
|
79
|
+
With `minBashVersion: "4.3"` or newer, or with no `minBashVersion`, every escape is fine.
|
|
80
80
|
|
|
81
81
|
## When not to use it
|
|
82
82
|
|
|
83
|
-
Turn the rule off when your scripts never run on Bash older than 4.3, or leave `
|
|
83
|
+
Turn the rule off when your scripts never run on Bash older than 4.3, or leave `minBashVersion`
|
|
84
84
|
unset, which makes the rule report nothing.
|
|
85
85
|
|
|
86
86
|
## Relationship to shellcheck
|
|
@@ -88,4 +88,4 @@ unset, which makes the rule report nothing.
|
|
|
88
88
|
eslint-sh is a convention and contract linter: a policy layer, where shellcheck is the gotcha
|
|
89
89
|
layer. Run shellcheck beside it.
|
|
90
90
|
|
|
91
|
-
shellcheck reports `$'…'` only for a script it treats as POSIX `sh` (its SC3xxx portability checks). It does not know which Bash release a script must run on, so it cannot report a `\u` escape for a Bash 3.2 or 4.2
|
|
91
|
+
shellcheck reports `$'…'` only for a script it treats as POSIX `sh` (its SC3xxx portability checks). It does not know which Bash release a script must run on, so it cannot report a `\u` escape for a script that must support Bash 3.2 or 4.2. This rule checks that support requirement.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# `sh/compat/no-wait-n`
|
|
2
2
|
|
|
3
|
-
Disallow `wait -n` in scripts
|
|
3
|
+
Disallow `wait -n` in scripts that must support a shell lacking it: Bash older than 4.3, including the
|
|
4
4
|
Bash 3.2 that macOS ships as `/bin/bash`, and POSIX sh.
|
|
5
5
|
|
|
6
6
|
| Configs | Fixable | Languages |
|
|
@@ -20,19 +20,19 @@ The portable alternative is to wait for one job at a time by its PID: keep each
|
|
|
20
20
|
This is a version-compat rule. Whether it reports depends only on `languageOptions`, as
|
|
21
21
|
described in [version compatibility](../../compat.md):
|
|
22
22
|
|
|
23
|
-
- `
|
|
24
|
-
- `dialect: "bash"` (the default) or `"bats"`: reports when `
|
|
25
|
-
- `dialect: "posix"`: reports
|
|
23
|
+
- `minBashVersion` unset: no Bash version constraint, so no report under `bash` or `bats`.
|
|
24
|
+
- `dialect: "bash"` (the default) or `"bats"`: reports when `minBashVersion` is older than `4.3`.
|
|
25
|
+
- `dialect: "posix"`: reports regardless of Bash releases; POSIX `wait` has no options.
|
|
26
26
|
- `dialect: "mksh"` or `"zsh"`: never reports.
|
|
27
27
|
|
|
28
28
|
## Options
|
|
29
29
|
|
|
30
|
-
This rule has no options. Set the
|
|
30
|
+
This rule has no options. Set the required support through `languageOptions`:
|
|
31
31
|
|
|
32
32
|
```js
|
|
33
33
|
// eslint.config.js
|
|
34
34
|
{
|
|
35
|
-
languageOptions: { dialect: 'bash',
|
|
35
|
+
languageOptions: { dialect: 'bash', minBashVersion: '3.2' },
|
|
36
36
|
rules: {
|
|
37
37
|
'sh/compat/no-wait-n': 'error',
|
|
38
38
|
},
|
|
@@ -43,9 +43,9 @@ This rule has no options. Set the target through `languageOptions`:
|
|
|
43
43
|
|
|
44
44
|
### Incorrect
|
|
45
45
|
|
|
46
|
-
With `
|
|
46
|
+
With `minBashVersion: "3.2"`:
|
|
47
47
|
|
|
48
|
-
<!-- example: {"dialect": "bash", "
|
|
48
|
+
<!-- example: {"dialect": "bash", "minBashVersion": "3.2", "findings": 1} -->
|
|
49
49
|
```sh
|
|
50
50
|
for job in a b c d; do
|
|
51
51
|
run "$job" &
|
|
@@ -56,9 +56,9 @@ wait
|
|
|
56
56
|
|
|
57
57
|
### Correct
|
|
58
58
|
|
|
59
|
-
With `
|
|
59
|
+
With `minBashVersion: "3.2"`:
|
|
60
60
|
|
|
61
|
-
<!-- example: {"dialect": "bash", "
|
|
61
|
+
<!-- example: {"dialect": "bash", "minBashVersion": "3.2"} -->
|
|
62
62
|
```sh
|
|
63
63
|
pids=
|
|
64
64
|
for job in a b c d; do
|
|
@@ -70,11 +70,11 @@ for pid in $pids; do
|
|
|
70
70
|
done
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
With `
|
|
73
|
+
With `minBashVersion: "4.3"` or newer, or with no `minBashVersion`, `wait -n` is fine.
|
|
74
74
|
|
|
75
75
|
## When not to use it
|
|
76
76
|
|
|
77
|
-
Turn the rule off when your scripts never run on Bash older than 4.3, or leave `
|
|
77
|
+
Turn the rule off when your scripts never run on Bash older than 4.3, or leave `minBashVersion`
|
|
78
78
|
unset, which makes the rule report nothing.
|
|
79
79
|
|
|
80
80
|
## Relationship to shellcheck
|
|
@@ -82,4 +82,4 @@ unset, which makes the rule report nothing.
|
|
|
82
82
|
eslint-sh is a convention and contract linter: a policy layer, where shellcheck is the gotcha
|
|
83
83
|
layer. Run shellcheck beside it.
|
|
84
84
|
|
|
85
|
-
shellcheck reports `wait` options only for a script it treats as POSIX `sh` (its SC3xxx portability checks). It does not know which Bash release a script must run on, so it cannot report `wait -n` for a Bash 4.2
|
|
85
|
+
shellcheck reports `wait` options only for a script it treats as POSIX `sh` (its SC3xxx portability checks). It does not know which Bash release a script must run on, so it cannot report `wait -n` for a script that must support Bash 4.2. This rule checks that support requirement.
|
|
@@ -30,7 +30,8 @@ wrappers_: commands that run the word after them. `time ls` runs `ls`, and
|
|
|
30
30
|
`bash ./build.sh` runs `./build.sh`. `bash -c STRING`, including a one-letter cluster such as
|
|
31
31
|
`bash -lc STRING`, runs an embedded string. `bash -s` and a bare `bash` read commands from
|
|
32
32
|
standard input, so the shell itself is the command.
|
|
33
|
-
-
|
|
33
|
+
- Project wrappers declared in `settings: { sh: { transparentWrappers: ['with-retry'] } }`,
|
|
34
|
+
and the shared network wrapper. See [shared transparent wrappers](../transparent-wrappers.md).
|
|
34
35
|
|
|
35
36
|
A command then reports in one of two ways:
|
|
36
37
|
|
|
@@ -45,8 +46,9 @@ A command then reports in one of two ways:
|
|
|
45
46
|
|
|
46
47
|
The rule is syntactic by design. It doesn't track values, so `cmd=ls; "$cmd"` reports. Aliases
|
|
47
48
|
need no handling: non-interactive shells don't expand them, so an alias name is an ordinary
|
|
48
|
-
static command word.
|
|
49
|
-
|
|
49
|
+
static command word. Utility wrappers match absolute paths by basename, so `/bin/bash -c …` runs an
|
|
50
|
+
embedded command. Configured utility wrappers also match relative paths; builtin specs
|
|
51
|
+
require exact names.
|
|
50
52
|
|
|
51
53
|
It does not depend on `languageOptions`.
|
|
52
54
|
|
|
@@ -56,18 +58,20 @@ It does not depend on `languageOptions`.
|
|
|
56
58
|
`dynamicInvocation` inside a function with one of these names, at any nesting depth, does not
|
|
57
59
|
report. The same command outside that function still reports. `embeddedCommand` still reports
|
|
58
60
|
inside these functions. Each use of the dispatcher stays visible at its call sites.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
Project wrapper facts belong in shared settings, with no rule override. The former
|
|
62
|
+
`allowWrappers` option is rejected. It added checks rather than suppressing them:
|
|
63
|
+
move its list to shared settings to preserve those checks across all wrapper-following
|
|
64
|
+
rules. Use `allowInFunctions` or a justified ESLint disable comment for an actual allowance.
|
|
65
|
+
See [migration](../transparent-wrappers.md#migration).
|
|
63
66
|
|
|
64
67
|
```js
|
|
65
68
|
// eslint.config.js
|
|
66
69
|
{
|
|
70
|
+
settings: { sh: { transparentWrappers: ['with-retry'] } },
|
|
67
71
|
rules: {
|
|
68
72
|
'sh/no-dynamic-invocation': [
|
|
69
73
|
'error',
|
|
70
|
-
{ allowInFunctions: ['dispatch']
|
|
74
|
+
{ allowInFunctions: ['dispatch'] },
|
|
71
75
|
],
|
|
72
76
|
},
|
|
73
77
|
}
|
|
@@ -91,9 +95,9 @@ bash -c "$script" # embeddedCommand: a string of shell code
|
|
|
91
95
|
sh -c 'make test' # embeddedCommand, even for a literal string
|
|
92
96
|
```
|
|
93
97
|
|
|
94
|
-
With `{
|
|
98
|
+
With `settings: { sh: { transparentWrappers: ['with-retry'] } }`:
|
|
95
99
|
|
|
96
|
-
<!-- example: {"
|
|
100
|
+
<!-- example: {"settings": {"sh": {"transparentWrappers": ["with-retry"]}}, "findings": 1, "messageIds": ["dynamicInvocation"]} -->
|
|
97
101
|
```sh
|
|
98
102
|
with-retry "$c" # the wrapped command is dynamic
|
|
99
103
|
```
|
|
@@ -110,9 +114,10 @@ alias ll='ls -l'
|
|
|
110
114
|
ll # an alias name is a static command word
|
|
111
115
|
```
|
|
112
116
|
|
|
113
|
-
With `{ allowInFunctions: ['dispatch']
|
|
117
|
+
With `{ allowInFunctions: ['dispatch'] }` and
|
|
118
|
+
`settings: { sh: { transparentWrappers: ['with-retry'] } }`:
|
|
114
119
|
|
|
115
|
-
<!-- example: {"options": {"allowInFunctions": ["dispatch"], "
|
|
120
|
+
<!-- example: {"options": {"allowInFunctions": ["dispatch"]}, "settings": {"sh": {"transparentWrappers": ["with-retry"]}}} -->
|
|
116
121
|
```sh
|
|
117
122
|
dispatch() {
|
|
118
123
|
"$@" # allowed inside the dispatcher
|
package/docs/rules/no-eval.md
CHANGED
|
@@ -7,6 +7,10 @@ of code a script runs can be reviewed before it runs.
|
|
|
7
7
|
| ------- | ------------ | --------- |
|
|
8
8
|
| `recommended`, `agent-authored` | not fixable | `sh/sh` |
|
|
9
9
|
|
|
10
|
+
Project wrapper facts are shared through
|
|
11
|
+
`settings: { sh: { transparentWrappers: ['with-retry'] } }`. This rule follows
|
|
12
|
+
those wrappers and the shared network wrapper; see [shared transparent wrappers](../transparent-wrappers.md).
|
|
13
|
+
|
|
10
14
|
## Rule details
|
|
11
15
|
|
|
12
16
|
A script you can review is a script whose code is all in front of you. Two constructs defeat
|
|
@@ -98,7 +102,8 @@ still report.
|
|
|
98
102
|
eslint-sh is a convention and contract linter: a policy layer, where shellcheck is the gotcha
|
|
99
103
|
layer. Run shellcheck beside it.
|
|
100
104
|
|
|
101
|
-
This rule is one of eslint-sh's
|
|
105
|
+
This rule is one of eslint-sh's
|
|
106
|
+
[deliberate overlaps with shellcheck](../shellcheck.md#deliberate-overlaps). shellcheck flags
|
|
102
107
|
`eval` only in specific misuse patterns, such as SC2294 (`eval` on an array negates the benefit
|
|
103
108
|
of arrays), and flags `source` of a non-constant path as SC1090 because shellcheck cannot follow
|
|
104
109
|
it. Both treat these as hazards to work around. This rule treats them as a policy: code that
|
|
@@ -6,6 +6,10 @@ Disallow `local`, `declare`, `typeset`, `export` and `readonly` with a value tak
|
|
|
6
6
|
| ---------------- | ----------------------------------------- | --------- |
|
|
7
7
|
| `agent-authored` | suggestions (split into two statements) | `sh/sh` |
|
|
8
8
|
|
|
9
|
+
Project wrapper facts are shared through
|
|
10
|
+
`settings: { sh: { transparentWrappers: ['with-retry'] } }`. This rule follows
|
|
11
|
+
those wrappers and the shared network wrapper; see [shared transparent wrappers](../transparent-wrappers.md).
|
|
12
|
+
|
|
9
13
|
## Rule details
|
|
10
14
|
|
|
11
15
|
`local x=$(cmd)` runs `cmd`, then runs `local`, and the statement's exit status is the status of
|