@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,61 @@
1
+ ---
2
+ id: js/no-obj-calls
3
+ title: "No calling Math, JSON, Reflect, Atomics or Intl as functions"
4
+ languages: [javascript, jsx]
5
+ fix: manual
6
+ fix_reason: "which method was meant needs the author"
7
+ stability: preview
8
+ ported_from: [eslint/no-obj-calls]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ The built-in namespace objects `Math`, `JSON`, `Reflect`, `Atomics` and `Intl` are not called or
13
+ constructed.
14
+
15
+ **Why:** They are plain objects; calling one throws a TypeError.
16
+
17
+ ```codelaw
18
+ match:
19
+ any:
20
+ - pattern: $C($$$ARGS)
21
+ - pattern: new $C($$$ARGS)
22
+ constraints:
23
+ C: { regex: ^(Math|JSON|Reflect|Atomics|Intl)$ }
24
+ where:
25
+ $C: builtin
26
+ message: "`$C` is a namespace object, not a function"
27
+ ```
28
+
29
+ ## How to fix
30
+
31
+ 1. Call the method of the namespace that was meant, e.g. `Math.round(x)`.
32
+
33
+ ## Examples
34
+
35
+ ### JavaScript
36
+
37
+ #### Don't
38
+
39
+ ```js
40
+ const n = Math(2.5);
41
+ ```
42
+
43
+ #### Do
44
+
45
+ ```js
46
+ const n = Math.round(2.5);
47
+ ```
48
+
49
+ ### JSX
50
+
51
+ #### Don't
52
+
53
+ ```jsx
54
+ const n = Math(2.5);
55
+ ```
56
+
57
+ #### Do
58
+
59
+ ```jsx
60
+ const n = Math.round(2.5);
61
+ ```
@@ -0,0 +1,84 @@
1
+ ---
2
+ id: js/no-octal
3
+ title: "No legacy octal literals"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "whether octal or decimal was meant needs the author"
7
+ stability: preview
8
+ ported_from: [eslint/no-octal]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ Number literals don't start with `0` followed by a digit.
13
+
14
+ **Why:** `071` is octal (57) in sloppy code and an error in strict code; `0o71` says what it means.
15
+
16
+ ```codelaw
17
+ match:
18
+ kind: number
19
+ regex: ^0[0-9]
20
+ message: "`$$MATCH` is a legacy octal literal; write 0o… for octal or drop the leading 0"
21
+ ```
22
+
23
+ ## How to fix
24
+
25
+ 1. For an octal number, write `0o` and the digits.
26
+ 2. For a decimal number, drop the leading zero.
27
+
28
+ ## Examples
29
+
30
+ ### JavaScript
31
+
32
+ #### Don't
33
+
34
+ ```js
35
+ const mode = 0755;
36
+ ```
37
+
38
+ #### Do
39
+
40
+ ```js
41
+ const mode = 0o755;
42
+ ```
43
+
44
+ ### JSX
45
+
46
+ #### Don't
47
+
48
+ ```jsx
49
+ const mode = 0755;
50
+ ```
51
+
52
+ #### Do
53
+
54
+ ```jsx
55
+ const mode = 0o755;
56
+ ```
57
+
58
+ ### TypeScript
59
+
60
+ #### Don't
61
+
62
+ ```ts
63
+ const mode = 0755;
64
+ ```
65
+
66
+ #### Do
67
+
68
+ ```ts
69
+ const mode = 0o755;
70
+ ```
71
+
72
+ ### TSX
73
+
74
+ #### Don't
75
+
76
+ ```tsx
77
+ const mode = 0755;
78
+ ```
79
+
80
+ #### Do
81
+
82
+ ```tsx
83
+ const mode = 0o755;
84
+ ```
@@ -0,0 +1,99 @@
1
+ ---
2
+ id: js/no-prototype-builtins
3
+ title: "No calling Object.prototype methods on the object itself"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: suggest
6
+ fix_reason: "an object whose own method is meant would change behaviour"
7
+ stability: preview
8
+ ported_from: [eslint/no-prototype-builtins]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ `hasOwnProperty`, `isPrototypeOf` and `propertyIsEnumerable` are called through `Object.prototype`,
13
+ not on the object being tested.
14
+
15
+ **Why:** An object can shadow these methods, or have no prototype at all, and then the call breaks
16
+ or lies.
17
+
18
+ ```codelaw
19
+ match:
20
+ pattern: $O.$M($$$ARGS)
21
+ constraints:
22
+ M: { regex: ^(hasOwnProperty|isPrototypeOf|propertyIsEnumerable)$ }
23
+ message: "Call `Object.prototype.$M` through `.call`, or use `Object.hasOwn`"
24
+ fix: "Object.prototype.$M.call($O, $$$ARGS)"
25
+ ```
26
+
27
+ ## Examples
28
+
29
+ ### JavaScript
30
+
31
+ #### Don't
32
+
33
+ ```js
34
+ if (options.hasOwnProperty("debug")) {
35
+ enable();
36
+ }
37
+ ```
38
+
39
+ #### Do
40
+
41
+ ```js
42
+ if (Object.prototype.hasOwnProperty.call(options, "debug")) {
43
+ enable();
44
+ }
45
+ ```
46
+
47
+ ### JSX
48
+
49
+ #### Don't
50
+
51
+ ```jsx
52
+ if (options.hasOwnProperty("debug")) {
53
+ enable();
54
+ }
55
+ ```
56
+
57
+ #### Do
58
+
59
+ ```jsx
60
+ if (Object.prototype.hasOwnProperty.call(options, "debug")) {
61
+ enable();
62
+ }
63
+ ```
64
+
65
+ ### TypeScript
66
+
67
+ #### Don't
68
+
69
+ ```ts
70
+ if (options.hasOwnProperty("debug")) {
71
+ enable();
72
+ }
73
+ ```
74
+
75
+ #### Do
76
+
77
+ ```ts
78
+ if (Object.prototype.hasOwnProperty.call(options, "debug")) {
79
+ enable();
80
+ }
81
+ ```
82
+
83
+ ### TSX
84
+
85
+ #### Don't
86
+
87
+ ```tsx
88
+ if (options.hasOwnProperty("debug")) {
89
+ enable();
90
+ }
91
+ ```
92
+
93
+ #### Do
94
+
95
+ ```tsx
96
+ if (Object.prototype.hasOwnProperty.call(options, "debug")) {
97
+ enable();
98
+ }
99
+ ```
@@ -0,0 +1,61 @@
1
+ ---
2
+ id: js/no-redeclare
3
+ title: "No variable is declared twice"
4
+ languages: [javascript, jsx]
5
+ fix: manual
6
+ fix_reason: "whether to rename or to assign needs the author"
7
+ stability: preview
8
+ ported_from: [eslint/no-redeclare]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ A name is declared once per scope: a second `var` or `function` with the same name is not allowed.
13
+
14
+ **Why:** Redeclaring silently merges two declarations, so one of them is usually a mistake.
15
+
16
+ ```codelaw
17
+ match:
18
+ kind: identifier
19
+ where:
20
+ $$MATCH: [declaration, redeclared]
21
+ message: "`$$MATCH` is already declared in this scope"
22
+ ```
23
+
24
+ ## How to fix
25
+
26
+ 1. If it's the same variable, drop the second `var` and assign.
27
+ 2. If it's a different one, rename it.
28
+
29
+ ## Examples
30
+
31
+ ### JavaScript
32
+
33
+ #### Don't
34
+
35
+ ```js
36
+ var count = 1;
37
+ var count = 2;
38
+ ```
39
+
40
+ #### Do
41
+
42
+ ```js
43
+ var count = 1;
44
+ count = 2;
45
+ ```
46
+
47
+ ### JSX
48
+
49
+ #### Don't
50
+
51
+ ```jsx
52
+ var count = 1;
53
+ var count = 2;
54
+ ```
55
+
56
+ #### Do
57
+
58
+ ```jsx
59
+ var count = 1;
60
+ count = 2;
61
+ ```
@@ -0,0 +1,75 @@
1
+ ---
2
+ id: js/no-regex-spaces
3
+ title: "No runs of spaces in a regular expression"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: auto
6
+ stability: preview
7
+ ported_from: [eslint/no-regex-spaces]
8
+ since: 0.1.0
9
+ ---
10
+
11
+ A regular expression writes several spaces as ` {n}`, not as a run of spaces.
12
+
13
+ **Why:** A run of spaces is impossible to count by eye.
14
+
15
+ ```codelaw
16
+ native: js/no-regex-spaces
17
+ ```
18
+
19
+ ## Examples
20
+
21
+ ### JavaScript
22
+
23
+ #### Don't
24
+
25
+ ```js
26
+ const re = /a b/;
27
+ ```
28
+
29
+ #### Do
30
+
31
+ ```js
32
+ const re = /a {3}b/;
33
+ ```
34
+
35
+ ### JSX
36
+
37
+ #### Don't
38
+
39
+ ```jsx
40
+ const re = /a b/;
41
+ ```
42
+
43
+ #### Do
44
+
45
+ ```jsx
46
+ const re = /a {3}b/;
47
+ ```
48
+
49
+ ### TypeScript
50
+
51
+ #### Don't
52
+
53
+ ```ts
54
+ const re = /a b/;
55
+ ```
56
+
57
+ #### Do
58
+
59
+ ```ts
60
+ const re = /a {3}b/;
61
+ ```
62
+
63
+ ### TSX
64
+
65
+ #### Don't
66
+
67
+ ```tsx
68
+ const re = /a b/;
69
+ ```
70
+
71
+ #### Do
72
+
73
+ ```tsx
74
+ const re = /a {3}b/;
75
+ ```
@@ -0,0 +1,91 @@
1
+ ---
2
+ id: js/no-self-assign
3
+ title: "No assigning a variable to itself"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "assigning a property to itself can run a setter, so removing it may change behaviour"
7
+ stability: preview
8
+ ported_from: [eslint/no-self-assign]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ An assignment's left and right sides are not the same expression.
13
+
14
+ **Why:** `a = a` has no effect; it is usually a typo for another name.
15
+
16
+ ```codelaw
17
+ match:
18
+ pattern: $A = $A
19
+ message: "Assigning `$A` to itself does nothing"
20
+ ```
21
+
22
+ ## How to fix
23
+
24
+ 1. If another value was meant, assign that.
25
+ 2. Otherwise remove the assignment.
26
+
27
+ ## Examples
28
+
29
+ ### JavaScript
30
+
31
+ #### Don't
32
+
33
+ ```js
34
+ let x = 1;
35
+ x = x;
36
+ ```
37
+
38
+ #### Do
39
+
40
+ ```js
41
+ let x = 1;
42
+ x = y;
43
+ ```
44
+
45
+ ### JSX
46
+
47
+ #### Don't
48
+
49
+ ```jsx
50
+ let x = 1;
51
+ x = x;
52
+ ```
53
+
54
+ #### Do
55
+
56
+ ```jsx
57
+ let x = 1;
58
+ x = y;
59
+ ```
60
+
61
+ ### TypeScript
62
+
63
+ #### Don't
64
+
65
+ ```ts
66
+ let x = 1;
67
+ x = x;
68
+ ```
69
+
70
+ #### Do
71
+
72
+ ```ts
73
+ let x = 1;
74
+ x = y;
75
+ ```
76
+
77
+ ### TSX
78
+
79
+ #### Don't
80
+
81
+ ```tsx
82
+ let x = 1;
83
+ x = x;
84
+ ```
85
+
86
+ #### Do
87
+
88
+ ```tsx
89
+ let x = 1;
90
+ x = y;
91
+ ```
@@ -0,0 +1,69 @@
1
+ ---
2
+ id: js/no-setter-return
3
+ title: "A setter does not return a value"
4
+ languages: [javascript, jsx]
5
+ fix: manual
6
+ fix_reason: "whether the returned expression was meant as a side effect needs a reader"
7
+ stability: preview
8
+ ported_from: [eslint/no-setter-return]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ A setter body contains no `return <value>`; a bare `return;` to leave early is fine.
13
+
14
+ **Why:** The value a setter returns is discarded, so returning one hides a mistake.
15
+
16
+ ```codelaw
17
+ native: js/no-setter-return
18
+ ```
19
+
20
+ ## How to fix
21
+
22
+ 1. Keep the expression's side effect as a statement.
23
+ 2. Remove the value from the `return`, or the `return`.
24
+
25
+ ## Examples
26
+
27
+ ### JavaScript
28
+
29
+ #### Don't
30
+
31
+ ```js
32
+ const box = {
33
+ set size(n) {
34
+ return (this.n = n);
35
+ },
36
+ };
37
+ ```
38
+
39
+ #### Do
40
+
41
+ ```js
42
+ const box = {
43
+ set size(n) {
44
+ this.n = n;
45
+ },
46
+ };
47
+ ```
48
+
49
+ ### JSX
50
+
51
+ #### Don't
52
+
53
+ ```jsx
54
+ const box = {
55
+ set size(n) {
56
+ return (this.n = n);
57
+ },
58
+ };
59
+ ```
60
+
61
+ #### Do
62
+
63
+ ```jsx
64
+ const box = {
65
+ set size(n) {
66
+ this.n = n;
67
+ },
68
+ };
69
+ ```
@@ -0,0 +1,102 @@
1
+ ---
2
+ id: js/no-shadow-restricted-names
3
+ title: "No declaring undefined, NaN, Infinity, arguments, eval or globalThis"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "the new name is the author's choice"
7
+ stability: preview
8
+ ported_from: [eslint/no-shadow-restricted-names]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ No variable, parameter or function is named `undefined`, `NaN`, `Infinity`, `arguments`, `eval` or
13
+ `globalThis`.
14
+
15
+ **Why:** Shadowing these names makes code that relies on them behave in confusing ways.
16
+
17
+ ```codelaw
18
+ match:
19
+ kind: identifier
20
+ regex: ^(undefined|NaN|Infinity|arguments|eval|globalThis)$
21
+ where:
22
+ $$MATCH: declaration
23
+ message: "`$$MATCH` is a restricted name; don't declare it"
24
+ ```
25
+
26
+ ## How to fix
27
+
28
+ 1. Rename the declaration and its uses.
29
+
30
+ ## Examples
31
+
32
+ ### JavaScript
33
+
34
+ #### Don't
35
+
36
+ ```js
37
+ function check(NaN) {
38
+ return NaN;
39
+ }
40
+ ```
41
+
42
+ #### Do
43
+
44
+ ```js
45
+ function check(value) {
46
+ return value;
47
+ }
48
+ ```
49
+
50
+ ### JSX
51
+
52
+ #### Don't
53
+
54
+ ```jsx
55
+ function check(NaN) {
56
+ return NaN;
57
+ }
58
+ ```
59
+
60
+ #### Do
61
+
62
+ ```jsx
63
+ function check(value) {
64
+ return value;
65
+ }
66
+ ```
67
+
68
+ ### TypeScript
69
+
70
+ #### Don't
71
+
72
+ ```ts
73
+ function check(NaN) {
74
+ return NaN;
75
+ }
76
+ ```
77
+
78
+ #### Do
79
+
80
+ ```ts
81
+ function check(value) {
82
+ return value;
83
+ }
84
+ ```
85
+
86
+ ### TSX
87
+
88
+ #### Don't
89
+
90
+ ```tsx
91
+ function check(NaN) {
92
+ return NaN;
93
+ }
94
+ ```
95
+
96
+ #### Do
97
+
98
+ ```tsx
99
+ function check(value) {
100
+ return value;
101
+ }
102
+ ```
@@ -0,0 +1,82 @@
1
+ ---
2
+ id: js/no-sparse-arrays
3
+ title: "No holes in array literals"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "whether a value is missing or a comma is extra needs a reader"
7
+ stability: preview
8
+ ported_from: [eslint/no-sparse-arrays]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ An array literal has no empty slots such as `[1, , 2]`.
13
+
14
+ **Why:** A hole is usually a typo, and holes behave differently from `undefined` in many array
15
+ methods.
16
+
17
+ ```codelaw
18
+ native: js/no-sparse-arrays
19
+ ```
20
+
21
+ ## How to fix
22
+
23
+ 1. Put the missing value in the slot, or remove the extra comma.
24
+ 2. If an empty slot is really meant, write `undefined` explicitly.
25
+
26
+ ## Examples
27
+
28
+ ### JavaScript
29
+
30
+ #### Don't
31
+
32
+ ```js
33
+ const colors = ["red", , "blue"];
34
+ ```
35
+
36
+ #### Do
37
+
38
+ ```js
39
+ const colors = ["red", "green", "blue"];
40
+ ```
41
+
42
+ ### JSX
43
+
44
+ #### Don't
45
+
46
+ ```jsx
47
+ const colors = ["red", , "blue"];
48
+ ```
49
+
50
+ #### Do
51
+
52
+ ```jsx
53
+ const colors = ["red", "green", "blue"];
54
+ ```
55
+
56
+ ### TypeScript
57
+
58
+ #### Don't
59
+
60
+ ```ts
61
+ const colors = ["red", , "blue"];
62
+ ```
63
+
64
+ #### Do
65
+
66
+ ```ts
67
+ const colors = ["red", "green", "blue"];
68
+ ```
69
+
70
+ ### TSX
71
+
72
+ #### Don't
73
+
74
+ ```tsx
75
+ const colors = ["red", , "blue"];
76
+ ```
77
+
78
+ #### Do
79
+
80
+ ```tsx
81
+ const colors = ["red", "green", "blue"];
82
+ ```