@codelaw/rules-js 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/LICENSE +23 -0
  2. package/NOTICE +10 -0
  3. package/README.md +57 -2
  4. package/codelaw-pack.toml +6 -0
  5. package/corpus.toml +76 -0
  6. package/data/globals/browser.json +1209 -0
  7. package/data/globals/commonjs.json +6 -0
  8. package/data/globals/jest.json +15 -0
  9. package/data/globals/mocha.json +22 -0
  10. package/data/globals/node.json +83 -0
  11. package/data/globals/serviceworker.json +328 -0
  12. package/data/globals/shared-node-browser.json +73 -0
  13. package/data/globals/vitest.json +19 -0
  14. package/data/globals/worker.json +349 -0
  15. package/package.json +14 -4
  16. package/presets/js/conventions.toml +6 -0
  17. package/presets/js/project.toml +4 -0
  18. package/presets/js/recommended.toml +67 -0
  19. package/presets/js/typescript.toml +7 -0
  20. package/rules/graph/no-unused-exports.md +135 -0
  21. package/rules/js/constructor-super.md +77 -0
  22. package/rules/js/exports-at-end.md +134 -0
  23. package/rules/js/for-direction.md +106 -0
  24. package/rules/js/getter-return.md +74 -0
  25. package/rules/js/import-groups.md +117 -0
  26. package/rules/js/no-async-promise-executor.md +95 -0
  27. package/rules/js/no-case-declarations.md +134 -0
  28. package/rules/js/no-class-assign.md +61 -0
  29. package/rules/js/no-compare-neg-zero.md +105 -0
  30. package/rules/js/no-cond-assign.md +135 -0
  31. package/rules/js/no-const-assign.md +61 -0
  32. package/rules/js/no-constant-binary-expression.md +83 -0
  33. package/rules/js/no-constant-condition.md +150 -0
  34. package/rules/js/no-control-regex.md +84 -0
  35. package/rules/js/no-debugger.md +99 -0
  36. package/rules/js/no-default-export.md +88 -0
  37. package/rules/js/no-delete-var.md +93 -0
  38. package/rules/js/no-dupe-args.md +61 -0
  39. package/rules/js/no-dupe-class-members.md +82 -0
  40. package/rules/js/no-dupe-else-if.md +113 -0
  41. package/rules/js/no-dupe-keys.md +66 -0
  42. package/rules/js/no-duplicate-case.md +137 -0
  43. package/rules/js/no-empty-character-class.md +98 -0
  44. package/rules/js/no-empty-pattern.md +86 -0
  45. package/rules/js/no-empty-static-block.md +99 -0
  46. package/rules/js/no-empty.md +116 -0
  47. package/rules/js/no-ex-assign.md +121 -0
  48. package/rules/js/no-extra-boolean-cast.md +107 -0
  49. package/rules/js/no-fallthrough.md +178 -0
  50. package/rules/js/no-func-assign.md +62 -0
  51. package/rules/js/no-global-assign.md +85 -0
  52. package/rules/js/no-import-assign.md +60 -0
  53. package/rules/js/no-invalid-regexp.md +86 -0
  54. package/rules/js/no-irregular-whitespace.md +87 -0
  55. package/rules/js/no-loss-of-precision.md +82 -0
  56. package/rules/js/no-misleading-character-class.md +83 -0
  57. package/rules/js/no-new-native-nonconstructor.md +55 -0
  58. package/rules/js/no-nonoctal-decimal-escape.md +84 -0
  59. package/rules/js/no-obj-calls.md +61 -0
  60. package/rules/js/no-octal.md +84 -0
  61. package/rules/js/no-prototype-builtins.md +99 -0
  62. package/rules/js/no-redeclare.md +61 -0
  63. package/rules/js/no-regex-spaces.md +75 -0
  64. package/rules/js/no-self-assign.md +91 -0
  65. package/rules/js/no-setter-return.md +69 -0
  66. package/rules/js/no-shadow-restricted-names.md +102 -0
  67. package/rules/js/no-sparse-arrays.md +82 -0
  68. package/rules/js/no-this-before-super.md +74 -0
  69. package/rules/js/no-unassigned-vars.md +102 -0
  70. package/rules/js/no-undef.md +76 -0
  71. package/rules/js/no-unexpected-multiline.md +91 -0
  72. package/rules/js/no-unreachable.md +59 -0
  73. package/rules/js/no-unsafe-finally.md +145 -0
  74. package/rules/js/no-unsafe-negation.md +71 -0
  75. package/rules/js/no-unsafe-optional-chaining.md +83 -0
  76. package/rules/js/no-unused-labels.md +102 -0
  77. package/rules/js/no-unused-private-class-members.md +126 -0
  78. package/rules/js/no-unused-vars.md +69 -0
  79. package/rules/js/no-useless-assignment.md +115 -0
  80. package/rules/js/no-useless-backreference.md +83 -0
  81. package/rules/js/no-useless-catch.md +105 -0
  82. package/rules/js/no-useless-escape.md +81 -0
  83. package/rules/js/no-var.md +76 -0
  84. package/rules/js/no-with.md +60 -0
  85. package/rules/js/prefer-const.md +83 -0
  86. package/rules/js/prefer-rest-params.md +103 -0
  87. package/rules/js/prefer-spread.md +95 -0
  88. package/rules/js/preserve-caught-error.md +122 -0
  89. package/rules/js/require-yield.md +107 -0
  90. package/rules/js/use-isnan.md +105 -0
  91. package/rules/js/valid-typeof.md +111 -0
@@ -0,0 +1,105 @@
1
+ ---
2
+ id: js/no-compare-neg-zero
3
+ title: "No comparisons against -0"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "whether `0` or `-0` was meant needs the author"
7
+ stability: preview
8
+ ported_from: [eslint/no-compare-neg-zero]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ Code doesn't compare a value with `-0` using `==`, `===`, `<` or the other comparison operators.
13
+
14
+ **Why:** These operators treat `-0` and `0` as equal, so the comparison doesn't test what it says.
15
+
16
+ ```codelaw
17
+ match:
18
+ kind: binary_expression
19
+ any:
20
+ - has: { field: right, pattern: "-0" }
21
+ - has: { field: left, pattern: "-0" }
22
+ has:
23
+ field: operator
24
+ regex: ^(==|===|!=|!==|<|>|<=|>=)$
25
+ message: "Comparing with -0 is the same as comparing with 0; use Object.is(x, -0) to test for -0"
26
+ ```
27
+
28
+ ## How to fix
29
+
30
+ 1. To test for negative zero, use `Object.is(x, -0)`.
31
+ 2. To test for zero of either sign, compare with `0`.
32
+
33
+ ## Examples
34
+
35
+ ### JavaScript
36
+
37
+ #### Don't
38
+
39
+ ```js
40
+ if (x === -0) {
41
+ flip();
42
+ }
43
+ ```
44
+
45
+ #### Do
46
+
47
+ ```js
48
+ if (Object.is(x, -0)) {
49
+ flip();
50
+ }
51
+ ```
52
+
53
+ ### JSX
54
+
55
+ #### Don't
56
+
57
+ ```jsx
58
+ if (x === -0) {
59
+ flip();
60
+ }
61
+ ```
62
+
63
+ #### Do
64
+
65
+ ```jsx
66
+ if (Object.is(x, -0)) {
67
+ flip();
68
+ }
69
+ ```
70
+
71
+ ### TypeScript
72
+
73
+ #### Don't
74
+
75
+ ```ts
76
+ if (x === -0) {
77
+ flip();
78
+ }
79
+ ```
80
+
81
+ #### Do
82
+
83
+ ```ts
84
+ if (Object.is(x, -0)) {
85
+ flip();
86
+ }
87
+ ```
88
+
89
+ ### TSX
90
+
91
+ #### Don't
92
+
93
+ ```tsx
94
+ if (x === -0) {
95
+ flip();
96
+ }
97
+ ```
98
+
99
+ #### Do
100
+
101
+ ```tsx
102
+ if (Object.is(x, -0)) {
103
+ flip();
104
+ }
105
+ ```
@@ -0,0 +1,135 @@
1
+ ---
2
+ id: js/no-cond-assign
3
+ title: "No assignment in a condition, unless doubly parenthesised"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "whether a comparison or an assignment was meant needs the author"
7
+ stability: preview
8
+ ported_from: [eslint/no-cond-assign]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ The condition of an `if`, `while`, `do … while` or `for` is not an assignment, unless it is wrapped
13
+ in a second pair of parentheses to say it's meant.
14
+
15
+ **Why:** `if (a = b)` assigns and tests the result, which is almost always a mistyped `===`.
16
+
17
+ ```codelaw
18
+ match:
19
+ kind: assignment_expression
20
+ any:
21
+ - inside:
22
+ stopBy: neighbor
23
+ kind: parenthesized_expression
24
+ inside:
25
+ stopBy: neighbor
26
+ any: [{ kind: if_statement }, { kind: while_statement }, { kind: do_statement }]
27
+ - inside:
28
+ stopBy: neighbor
29
+ kind: expression_statement
30
+ inside: { stopBy: neighbor, kind: for_statement, field: condition }
31
+ message: "An assignment in a condition is usually a mistyped comparison"
32
+ ```
33
+
34
+ ## How to fix
35
+
36
+ 1. If a comparison was meant, use `===`.
37
+ 2. If the assignment is meant, wrap it in a second pair of parentheses.
38
+
39
+ ## Examples
40
+
41
+ ### JavaScript
42
+
43
+ #### Don't
44
+
45
+ ```js
46
+ if (user = admin) {
47
+ grant();
48
+ }
49
+ ```
50
+
51
+ #### Do
52
+
53
+ ```js
54
+ if (user === admin) {
55
+ grant();
56
+ }
57
+ ```
58
+
59
+ ```js
60
+ while ((node = node.next)) {
61
+ visit(node);
62
+ }
63
+ ```
64
+
65
+ ### JSX
66
+
67
+ #### Don't
68
+
69
+ ```jsx
70
+ if (user = admin) {
71
+ grant();
72
+ }
73
+ ```
74
+
75
+ #### Do
76
+
77
+ ```jsx
78
+ if (user === admin) {
79
+ grant();
80
+ }
81
+ ```
82
+
83
+ ```jsx
84
+ while ((node = node.next)) {
85
+ visit(node);
86
+ }
87
+ ```
88
+
89
+ ### TypeScript
90
+
91
+ #### Don't
92
+
93
+ ```ts
94
+ if (user = admin) {
95
+ grant();
96
+ }
97
+ ```
98
+
99
+ #### Do
100
+
101
+ ```ts
102
+ if (user === admin) {
103
+ grant();
104
+ }
105
+ ```
106
+
107
+ ```ts
108
+ while ((node = node.next)) {
109
+ visit(node);
110
+ }
111
+ ```
112
+
113
+ ### TSX
114
+
115
+ #### Don't
116
+
117
+ ```tsx
118
+ if (user = admin) {
119
+ grant();
120
+ }
121
+ ```
122
+
123
+ #### Do
124
+
125
+ ```tsx
126
+ if (user === admin) {
127
+ grant();
128
+ }
129
+ ```
130
+
131
+ ```tsx
132
+ while ((node = node.next)) {
133
+ visit(node);
134
+ }
135
+ ```
@@ -0,0 +1,61 @@
1
+ ---
2
+ id: js/no-const-assign
3
+ title: "A const is not reassigned"
4
+ languages: [javascript, jsx]
5
+ fix: manual
6
+ fix_reason: "whether the variable should be `let` or the assignment should go is the author's call"
7
+ stability: preview
8
+ ported_from: [eslint/no-const-assign]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ Code doesn't assign a new value to a `const`.
13
+
14
+ **Why:** Assigning to a `const` throws a TypeError at run time.
15
+
16
+ ```codelaw
17
+ match:
18
+ kind: identifier
19
+ where:
20
+ $$MATCH: [write, { binding: const }]
21
+ message: "`$$MATCH` is a const; assigning to it throws"
22
+ ```
23
+
24
+ ## How to fix
25
+
26
+ 1. If the value is meant to change, declare it with `let`.
27
+ 2. Otherwise assign to a new variable.
28
+
29
+ ## Examples
30
+
31
+ ### JavaScript
32
+
33
+ #### Don't
34
+
35
+ ```js
36
+ const total = 0;
37
+ total = 1;
38
+ ```
39
+
40
+ #### Do
41
+
42
+ ```js
43
+ let total = 0;
44
+ total = 1;
45
+ ```
46
+
47
+ ### JSX
48
+
49
+ #### Don't
50
+
51
+ ```jsx
52
+ const total = 0;
53
+ total = 1;
54
+ ```
55
+
56
+ #### Do
57
+
58
+ ```jsx
59
+ let total = 0;
60
+ total = 1;
61
+ ```
@@ -0,0 +1,83 @@
1
+ ---
2
+ id: js/no-constant-binary-expression
3
+ title: "No binary expression whose result is fixed"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "the intended grouping or comparison needs the author"
7
+ stability: preview
8
+ ported_from: [eslint/no-constant-binary-expression]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ The left side of `??`, `||` and `&&` is not a value whose nullishness or truthiness is fixed, and
13
+ nothing is compared with a newly created object or with `null` when it can never be `null`.
14
+
15
+ **Why:** Such an expression always gives the same answer, which usually means the author misread
16
+ operator precedence.
17
+
18
+ ```codelaw
19
+ native: js/no-constant-binary-expression
20
+ ```
21
+
22
+ ## How to fix
23
+
24
+ 1. Add the parentheses the expression was meant to have.
25
+ 2. Or compare with the value that was meant.
26
+
27
+ ## Examples
28
+
29
+ ### JavaScript
30
+
31
+ #### Don't
32
+
33
+ ```js
34
+ const total = price + tax ?? 0;
35
+ ```
36
+
37
+ #### Do
38
+
39
+ ```js
40
+ const total = price + (tax ?? 0);
41
+ ```
42
+
43
+ ### JSX
44
+
45
+ #### Don't
46
+
47
+ ```jsx
48
+ const total = price + tax ?? 0;
49
+ ```
50
+
51
+ #### Do
52
+
53
+ ```jsx
54
+ const total = price + (tax ?? 0);
55
+ ```
56
+
57
+ ### TypeScript
58
+
59
+ #### Don't
60
+
61
+ ```ts
62
+ const total = price + tax ?? 0;
63
+ ```
64
+
65
+ #### Do
66
+
67
+ ```ts
68
+ const total = price + (tax ?? 0);
69
+ ```
70
+
71
+ ### TSX
72
+
73
+ #### Don't
74
+
75
+ ```tsx
76
+ const total = price + tax ?? 0;
77
+ ```
78
+
79
+ #### Do
80
+
81
+ ```tsx
82
+ const total = price + (tax ?? 0);
83
+ ```
@@ -0,0 +1,150 @@
1
+ ---
2
+ id: js/no-constant-condition
3
+ title: "No conditions that are always true or always false"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "whether to remove the branch or fix the condition needs the author"
7
+ stability: preview
8
+ ported_from: [eslint/no-constant-condition]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ The condition of an `if`, `while` or `do … while` is not a literal or another value that is always
13
+ truthy or always falsy; `while (true)` is allowed.
14
+
15
+ **Why:** A constant condition is usually leftover debugging or a typo, and hides dead code.
16
+
17
+ ```codelaw
18
+ match:
19
+ kind: parenthesized_expression
20
+ inside:
21
+ stopBy: neighbor
22
+ any: [{ kind: if_statement }, { kind: while_statement }, { kind: do_statement }]
23
+ field: condition
24
+ has:
25
+ stopBy: neighbor
26
+ any:
27
+ - kind: number
28
+ - kind: string
29
+ - kind: "true"
30
+ - kind: "false"
31
+ - kind: "null"
32
+ - kind: undefined
33
+ - kind: array
34
+ - kind: object
35
+ - kind: arrow_function
36
+ - kind: function_expression
37
+ - kind: regex
38
+ not:
39
+ all:
40
+ - inside: { stopBy: neighbor, kind: while_statement }
41
+ - has: { stopBy: neighbor, kind: "true" }
42
+ message: "This condition is a constant, so the branch always or never runs"
43
+ ```
44
+
45
+ ## How to fix
46
+
47
+ 1. If the branch is dead, remove it.
48
+ 2. Otherwise replace the constant with the condition that was meant.
49
+
50
+ ## Examples
51
+
52
+ ### JavaScript
53
+
54
+ #### Don't
55
+
56
+ ```js
57
+ if (0) {
58
+ debugPanel();
59
+ }
60
+ ```
61
+
62
+ #### Do
63
+
64
+ ```js
65
+ if (debug) {
66
+ debugPanel();
67
+ }
68
+ ```
69
+
70
+ ```js
71
+ while (true) {
72
+ step();
73
+ }
74
+ ```
75
+
76
+ ### JSX
77
+
78
+ #### Don't
79
+
80
+ ```jsx
81
+ if (0) {
82
+ debugPanel();
83
+ }
84
+ ```
85
+
86
+ #### Do
87
+
88
+ ```jsx
89
+ if (debug) {
90
+ debugPanel();
91
+ }
92
+ ```
93
+
94
+ ```jsx
95
+ while (true) {
96
+ step();
97
+ }
98
+ ```
99
+
100
+ ### TypeScript
101
+
102
+ #### Don't
103
+
104
+ ```ts
105
+ if (0) {
106
+ debugPanel();
107
+ }
108
+ ```
109
+
110
+ #### Do
111
+
112
+ ```ts
113
+ if (debug) {
114
+ debugPanel();
115
+ }
116
+ ```
117
+
118
+ ```ts
119
+ while (true) {
120
+ step();
121
+ }
122
+ ```
123
+
124
+ ### TSX
125
+
126
+ #### Don't
127
+
128
+ ```tsx
129
+ if (0) {
130
+ debugPanel();
131
+ }
132
+ ```
133
+
134
+ #### Do
135
+
136
+ ```tsx
137
+ if (debug) {
138
+ debugPanel();
139
+ }
140
+ ```
141
+
142
+ ```tsx
143
+ while (true) {
144
+ step();
145
+ }
146
+ ```
147
+
148
+ ## Differences from the source
149
+
150
+ Only literal conditions are checked; ESLint also folds some expressions such as `typeof x` and `!1`.
@@ -0,0 +1,84 @@
1
+ ---
2
+ id: js/no-control-regex
3
+ title: "No control characters in regular expressions"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "which character was meant needs the author"
7
+ stability: preview
8
+ ported_from: [eslint/no-control-regex]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ A regular expression literal doesn't match ASCII control characters (`\x00`–`\x1F`).
13
+
14
+ **Why:** Control characters rarely appear in text, so matching them is usually an escaping mistake.
15
+
16
+ ```codelaw
17
+ match:
18
+ kind: regex_pattern
19
+ regex: \\x[01][0-9a-fA-F]|\\u00[01][0-9a-fA-F]|[\x00-\x1f]
20
+ message: "Control characters in a regular expression are almost always a mistake"
21
+ ```
22
+
23
+ ## How to fix
24
+
25
+ 1. Use the named escape (`\t`, `\n`, `\f`) if one was meant.
26
+ 2. Otherwise remove the control character from the pattern.
27
+
28
+ ## Examples
29
+
30
+ ### JavaScript
31
+
32
+ #### Don't
33
+
34
+ ```js
35
+ const re = /\x0C/;
36
+ ```
37
+
38
+ #### Do
39
+
40
+ ```js
41
+ const re = /\f/;
42
+ ```
43
+
44
+ ### JSX
45
+
46
+ #### Don't
47
+
48
+ ```jsx
49
+ const re = /\x0C/;
50
+ ```
51
+
52
+ #### Do
53
+
54
+ ```jsx
55
+ const re = /\f/;
56
+ ```
57
+
58
+ ### TypeScript
59
+
60
+ #### Don't
61
+
62
+ ```ts
63
+ const re = /\x0C/;
64
+ ```
65
+
66
+ #### Do
67
+
68
+ ```ts
69
+ const re = /\f/;
70
+ ```
71
+
72
+ ### TSX
73
+
74
+ #### Don't
75
+
76
+ ```tsx
77
+ const re = /\x0C/;
78
+ ```
79
+
80
+ #### Do
81
+
82
+ ```tsx
83
+ const re = /\f/;
84
+ ```
@@ -0,0 +1,99 @@
1
+ ---
2
+ id: js/no-debugger
3
+ title: "No debugger statements"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: auto
6
+ stability: preview
7
+ ported_from: [eslint/no-debugger]
8
+ since: 0.1.0
9
+ ---
10
+
11
+ Code contains no `debugger` statements.
12
+
13
+ **Why:** `debugger` pauses execution wherever developer tools are open, which nobody wants in
14
+ shipped code.
15
+
16
+ ```codelaw
17
+ match:
18
+ kind: debugger_statement
19
+ message: "Remove `debugger` before committing"
20
+ fix: [remove]
21
+ ```
22
+
23
+ ## Examples
24
+
25
+ ### JavaScript
26
+
27
+ #### Don't
28
+
29
+ ```js
30
+ function load() {
31
+ debugger;
32
+ return fetchAll();
33
+ }
34
+ ```
35
+
36
+ #### Do
37
+
38
+ ```js
39
+ function load() {
40
+ return fetchAll();
41
+ }
42
+ ```
43
+
44
+ ### JSX
45
+
46
+ #### Don't
47
+
48
+ ```jsx
49
+ function load() {
50
+ debugger;
51
+ return fetchAll();
52
+ }
53
+ ```
54
+
55
+ #### Do
56
+
57
+ ```jsx
58
+ function load() {
59
+ return fetchAll();
60
+ }
61
+ ```
62
+
63
+ ### TypeScript
64
+
65
+ #### Don't
66
+
67
+ ```ts
68
+ function load() {
69
+ debugger;
70
+ return fetchAll();
71
+ }
72
+ ```
73
+
74
+ #### Do
75
+
76
+ ```ts
77
+ function load() {
78
+ return fetchAll();
79
+ }
80
+ ```
81
+
82
+ ### TSX
83
+
84
+ #### Don't
85
+
86
+ ```tsx
87
+ function load() {
88
+ debugger;
89
+ return fetchAll();
90
+ }
91
+ ```
92
+
93
+ #### Do
94
+
95
+ ```tsx
96
+ function load() {
97
+ return fetchAll();
98
+ }
99
+ ```