@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,62 @@
1
+ ---
2
+ id: js/no-func-assign
3
+ title: "A function declaration is not reassigned"
4
+ languages: [javascript, jsx]
5
+ fix: manual
6
+ fix_reason: "what the assignment was for is the author's call"
7
+ stability: preview
8
+ ported_from: [eslint/no-func-assign]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ Code doesn't assign a new value to the name a function declaration binds.
13
+
14
+ **Why:** Overwriting a declared function is almost always a mistake, and every later call means
15
+ something else.
16
+
17
+ ```codelaw
18
+ match:
19
+ kind: identifier
20
+ where:
21
+ $$MATCH: [write, { binding: function }]
22
+ message: "`$$MATCH` is a function declaration; don't assign to it"
23
+ ```
24
+
25
+ ## How to fix
26
+
27
+ 1. Assign to a new variable instead.
28
+ 2. If the function must be replaceable, declare it with `let` as a function expression.
29
+
30
+ ## Examples
31
+
32
+ ### JavaScript
33
+
34
+ #### Don't
35
+
36
+ ```js
37
+ function save() {}
38
+ save = null;
39
+ ```
40
+
41
+ #### Do
42
+
43
+ ```js
44
+ function save() {}
45
+ const saveHandler = null;
46
+ ```
47
+
48
+ ### JSX
49
+
50
+ #### Don't
51
+
52
+ ```jsx
53
+ function save() {}
54
+ save = null;
55
+ ```
56
+
57
+ #### Do
58
+
59
+ ```jsx
60
+ function save() {}
61
+ const saveHandler = null;
62
+ ```
@@ -0,0 +1,85 @@
1
+ ---
2
+ id: js/no-global-assign
3
+ title: "No assignment to built-in globals"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "the intended variable needs a name of its own"
7
+ stability: preview
8
+ ported_from: [eslint/no-global-assign]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ Code doesn't assign to JavaScript's built-in globals such as `Object`, `undefined` or `NaN`.
13
+
14
+ **Why:** Built-in globals are read-only or shared by every module, so assigning to one is a bug or a
15
+ hazard.
16
+
17
+ ```codelaw
18
+ match:
19
+ kind: identifier
20
+ where:
21
+ $$MATCH: [write, builtin]
22
+ message: "`$$MATCH` is a built-in global; don't assign to it"
23
+ ```
24
+
25
+ ## How to fix
26
+
27
+ 1. Declare a local variable with its own name.
28
+
29
+ ## Examples
30
+
31
+ ### JavaScript
32
+
33
+ #### Don't
34
+
35
+ ```js
36
+ Object = null;
37
+ ```
38
+
39
+ #### Do
40
+
41
+ ```js
42
+ const object = null;
43
+ ```
44
+
45
+ ### JSX
46
+
47
+ #### Don't
48
+
49
+ ```jsx
50
+ Object = null;
51
+ ```
52
+
53
+ #### Do
54
+
55
+ ```jsx
56
+ const object = null;
57
+ ```
58
+
59
+ ### TypeScript
60
+
61
+ #### Don't
62
+
63
+ ```ts
64
+ Object = null;
65
+ ```
66
+
67
+ #### Do
68
+
69
+ ```ts
70
+ const object = null;
71
+ ```
72
+
73
+ ### TSX
74
+
75
+ #### Don't
76
+
77
+ ```tsx
78
+ Object = null;
79
+ ```
80
+
81
+ #### Do
82
+
83
+ ```tsx
84
+ const object = null;
85
+ ```
@@ -0,0 +1,60 @@
1
+ ---
2
+ id: js/no-import-assign
3
+ title: "An imported binding is not reassigned"
4
+ languages: [javascript, jsx]
5
+ fix: manual
6
+ fix_reason: "the new value needs a variable of its own"
7
+ stability: preview
8
+ ported_from: [eslint/no-import-assign]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ Code doesn't assign a new value to a name bound by `import`.
13
+
14
+ **Why:** Imported bindings are read-only: assigning to one throws a TypeError.
15
+
16
+ ```codelaw
17
+ match:
18
+ kind: identifier
19
+ where:
20
+ $$MATCH: [write, { binding: import }]
21
+ message: "`$$MATCH` is an import; imports are read-only"
22
+ ```
23
+
24
+ ## How to fix
25
+
26
+ 1. Copy the import into a local variable and change that.
27
+
28
+ ## Examples
29
+
30
+ ### JavaScript
31
+
32
+ #### Don't
33
+
34
+ ```js
35
+ import config from "./config.js";
36
+ config = {};
37
+ ```
38
+
39
+ #### Do
40
+
41
+ ```js
42
+ import config from "./config.js";
43
+ const local = { ...config };
44
+ ```
45
+
46
+ ### JSX
47
+
48
+ #### Don't
49
+
50
+ ```jsx
51
+ import config from "./config.js";
52
+ config = {};
53
+ ```
54
+
55
+ #### Do
56
+
57
+ ```jsx
58
+ import config from "./config.js";
59
+ const local = { ...config };
60
+ ```
@@ -0,0 +1,86 @@
1
+ ---
2
+ id: js/no-invalid-regexp
3
+ title: "RegExp() is given a valid pattern and flags"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "the intended pattern needs the author"
7
+ stability: preview
8
+ ported_from: [eslint/no-invalid-regexp]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ A `RegExp(...)` or `new RegExp(...)` whose pattern and flags are string literals is valid: brackets
13
+ and groups close, quantifiers follow something, and the flags are known and not repeated.
14
+
15
+ **Why:** An invalid pattern throws a SyntaxError when that line runs, not when the file loads.
16
+
17
+ ```codelaw
18
+ native: js/no-invalid-regexp
19
+ ```
20
+
21
+ ## How to fix
22
+
23
+ 1. Correct the pattern or the flags the message names.
24
+
25
+ ## Examples
26
+
27
+ ### JavaScript
28
+
29
+ #### Don't
30
+
31
+ ```js
32
+ const re = new RegExp("[a-z");
33
+ ```
34
+
35
+ #### Do
36
+
37
+ ```js
38
+ const re = new RegExp("[a-z]");
39
+ ```
40
+
41
+ ### JSX
42
+
43
+ #### Don't
44
+
45
+ ```jsx
46
+ const re = new RegExp("[a-z");
47
+ ```
48
+
49
+ #### Do
50
+
51
+ ```jsx
52
+ const re = new RegExp("[a-z]");
53
+ ```
54
+
55
+ ### TypeScript
56
+
57
+ #### Don't
58
+
59
+ ```ts
60
+ const re = new RegExp("[a-z");
61
+ ```
62
+
63
+ #### Do
64
+
65
+ ```ts
66
+ const re = new RegExp("[a-z]");
67
+ ```
68
+
69
+ ### TSX
70
+
71
+ #### Don't
72
+
73
+ ```tsx
74
+ const re = new RegExp("[a-z");
75
+ ```
76
+
77
+ #### Do
78
+
79
+ ```tsx
80
+ const re = new RegExp("[a-z]");
81
+ ```
82
+
83
+ ## Differences from the source
84
+
85
+ Only structural problems are found: unbalanced brackets and groups, misplaced quantifiers, out-of-
86
+ order ranges, invalid group syntax and flags.
@@ -0,0 +1,87 @@
1
+ ---
2
+ id: js/no-irregular-whitespace
3
+ title: "No irregular whitespace in templates, regular expressions, JSX text or comments"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: suggest
6
+ fix_reason: "the escape keeps a template's cooked value but changes the raw string a tagged template such as `String.raw` sees"
7
+ stability: preview
8
+ ported_from: [eslint/no-irregular-whitespace]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ Templates, regular expressions and JSX text spell a no-break space, zero-width space or other
13
+ irregular whitespace as an escape (`\u00A0`, ` `), and comments use ordinary spaces.
14
+
15
+ **Why:** Irregular whitespace is invisible in most editors. In a template, regular expression or JSX
16
+ text it silently becomes part of the value, so the text looks right and compares wrong.
17
+
18
+ ```codelaw
19
+ native: js/no-irregular-whitespace
20
+ ```
21
+
22
+ ## Examples
23
+
24
+ ### JavaScript
25
+
26
+ #### Don't
27
+
28
+ ```js
29
+ const label = `Total: 1`;
30
+ ```
31
+
32
+ #### Do
33
+
34
+ ```js
35
+ const label = `Total:\u00A01`;
36
+ ```
37
+
38
+ ### JSX
39
+
40
+ #### Don't
41
+
42
+ ```jsx
43
+ const label = <p>Total: 1</p>;
44
+ ```
45
+
46
+ #### Do
47
+
48
+ ```jsx
49
+ const label = <p>Total:&#x00A0;1</p>;
50
+ ```
51
+
52
+ ### TypeScript
53
+
54
+ #### Don't
55
+
56
+ ```ts
57
+ const label = `Total: 1`;
58
+ ```
59
+
60
+ #### Do
61
+
62
+ ```ts
63
+ const label = `Total:\u00A01`;
64
+ ```
65
+
66
+ ### TSX
67
+
68
+ #### Don't
69
+
70
+ ```tsx
71
+ const label = <p>Total: 1</p>;
72
+ ```
73
+
74
+ #### Do
75
+
76
+ ```tsx
77
+ const label = <p>Total:&#x00A0;1</p>;
78
+ ```
79
+
80
+ ## Differences from the source
81
+
82
+ - **Between tokens the formatter owns it.** ESLint also reports irregular whitespace between tokens;
83
+ here that is layout, and `codelaw format` replaces it with a space (SR-FORMATTER decision 3), so
84
+ this rule does not report it.
85
+ - **Strings are skipped**, as ESLint's `skipStrings` default does.
86
+ - **The fix escapes, it doesn't delete:** `\uXXXX` in a template or regular expression, `&#xXXXX;`
87
+ in JSX text, so the value is unchanged; a comment gets an ordinary space.
@@ -0,0 +1,82 @@
1
+ ---
2
+ id: js/no-loss-of-precision
3
+ title: "Number literals keep their value"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "whether to use a BigInt, a string or a rounder value depends on how the number is used"
7
+ stability: preview
8
+ ported_from: [eslint/no-loss-of-precision]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ A number literal can be represented exactly as a JavaScript number.
13
+
14
+ **Why:** A literal with more precision than a double holds is silently rounded, so the code doesn't
15
+ mean what it says.
16
+
17
+ ```codelaw
18
+ native: js/no-loss-of-precision
19
+ ```
20
+
21
+ ## How to fix
22
+
23
+ 1. Use a BigInt (`123n`) for an exact large integer.
24
+ 2. Or keep the value as a string, or write the value the code really gets.
25
+
26
+ ## Examples
27
+
28
+ ### JavaScript
29
+
30
+ #### Don't
31
+
32
+ ```js
33
+ const id = 9007199254740993;
34
+ ```
35
+
36
+ #### Do
37
+
38
+ ```js
39
+ const id = 9007199254740993n;
40
+ ```
41
+
42
+ ### JSX
43
+
44
+ #### Don't
45
+
46
+ ```jsx
47
+ const id = 9007199254740993;
48
+ ```
49
+
50
+ #### Do
51
+
52
+ ```jsx
53
+ const id = 9007199254740993n;
54
+ ```
55
+
56
+ ### TypeScript
57
+
58
+ #### Don't
59
+
60
+ ```ts
61
+ const id = 9007199254740993;
62
+ ```
63
+
64
+ #### Do
65
+
66
+ ```ts
67
+ const id = 9007199254740993n;
68
+ ```
69
+
70
+ ### TSX
71
+
72
+ #### Don't
73
+
74
+ ```tsx
75
+ const id = 9007199254740993;
76
+ ```
77
+
78
+ #### Do
79
+
80
+ ```tsx
81
+ const id = 9007199254740993n;
82
+ ```
@@ -0,0 +1,83 @@
1
+ ---
2
+ id: js/no-misleading-character-class
3
+ title: "No character class holding a character made of several code points"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "whether an alternation or a different class was meant needs the author"
7
+ stability: preview
8
+ ported_from: [eslint/no-misleading-character-class]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ A character class contains no character built from several code points — an emoji with a skin-tone
13
+ modifier, a flag, a letter with a combining mark — and no astral character without the `u` flag.
14
+
15
+ **Why:** A class matches one code point at a time, so `[👍🏻]` matches the thumb or the tone, never
16
+ the pair.
17
+
18
+ ```codelaw
19
+ native: js/no-misleading-character-class
20
+ ```
21
+
22
+ ## How to fix
23
+
24
+ 1. Use an alternation such as `(?:👍🏻|👍)` for multi-code-point characters.
25
+ 2. Add the `u` flag for astral characters.
26
+
27
+ ## Examples
28
+
29
+ ### JavaScript
30
+
31
+ #### Don't
32
+
33
+ ```js
34
+ const re = /^[❤️]$/u;
35
+ ```
36
+
37
+ #### Do
38
+
39
+ ```js
40
+ const re = /^(?:❤️)$/u;
41
+ ```
42
+
43
+ ### JSX
44
+
45
+ #### Don't
46
+
47
+ ```jsx
48
+ const re = /^[❤️]$/u;
49
+ ```
50
+
51
+ #### Do
52
+
53
+ ```jsx
54
+ const re = /^(?:❤️)$/u;
55
+ ```
56
+
57
+ ### TypeScript
58
+
59
+ #### Don't
60
+
61
+ ```ts
62
+ const re = /^[❤️]$/u;
63
+ ```
64
+
65
+ #### Do
66
+
67
+ ```ts
68
+ const re = /^(?:❤️)$/u;
69
+ ```
70
+
71
+ ### TSX
72
+
73
+ #### Don't
74
+
75
+ ```tsx
76
+ const re = /^[❤️]$/u;
77
+ ```
78
+
79
+ #### Do
80
+
81
+ ```tsx
82
+ const re = /^(?:❤️)$/u;
83
+ ```
@@ -0,0 +1,55 @@
1
+ ---
2
+ id: js/no-new-native-nonconstructor
3
+ title: "No new on Symbol or BigInt"
4
+ languages: [javascript, jsx]
5
+ fix: suggest
6
+ fix_reason: "the call throws today, so removing `new` changes what the code does"
7
+ stability: preview
8
+ ported_from: [eslint/no-new-native-nonconstructor]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ `Symbol` and `BigInt` are called as functions, never with `new`.
13
+
14
+ **Why:** `new Symbol()` and `new BigInt()` throw a TypeError.
15
+
16
+ ```codelaw
17
+ match:
18
+ pattern: new $C($$$ARGS)
19
+ constraints:
20
+ C: { regex: ^(Symbol|BigInt)$ }
21
+ where:
22
+ $C: builtin
23
+ message: "`$C` is not a constructor; call it without `new`"
24
+ fix: "$C($$$ARGS)"
25
+ ```
26
+
27
+ ## Examples
28
+
29
+ ### JavaScript
30
+
31
+ #### Don't
32
+
33
+ ```js
34
+ const id = new Symbol("id");
35
+ ```
36
+
37
+ #### Do
38
+
39
+ ```js
40
+ const id = Symbol("id");
41
+ ```
42
+
43
+ ### JSX
44
+
45
+ #### Don't
46
+
47
+ ```jsx
48
+ const id = new Symbol("id");
49
+ ```
50
+
51
+ #### Do
52
+
53
+ ```jsx
54
+ const id = Symbol("id");
55
+ ```
@@ -0,0 +1,84 @@
1
+ ---
2
+ id: js/no-nonoctal-decimal-escape
3
+ title: "No \\8 or \\9 escapes in strings"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "whether the digit or a literal backslash was meant needs the author"
7
+ stability: preview
8
+ ported_from: [eslint/no-nonoctal-decimal-escape]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ A string contains no `\8` or `\9` escape.
13
+
14
+ **Why:** `\8` and `\9` are legacy escapes that just mean the digits, and are errors in template
15
+ literals and strict code.
16
+
17
+ ```codelaw
18
+ match:
19
+ kind: escape_sequence
20
+ regex: ^\\[89]$
21
+ message: "`$$MATCH` is not an escape; it's the digit itself"
22
+ ```
23
+
24
+ ## How to fix
25
+
26
+ 1. Write the digit without the backslash, or `\\8` for a backslash and a digit.
27
+
28
+ ## Examples
29
+
30
+ ### JavaScript
31
+
32
+ #### Don't
33
+
34
+ ```js
35
+ const msg = "version \8";
36
+ ```
37
+
38
+ #### Do
39
+
40
+ ```js
41
+ const msg = "version 8";
42
+ ```
43
+
44
+ ### JSX
45
+
46
+ #### Don't
47
+
48
+ ```jsx
49
+ const msg = "version \8";
50
+ ```
51
+
52
+ #### Do
53
+
54
+ ```jsx
55
+ const msg = "version 8";
56
+ ```
57
+
58
+ ### TypeScript
59
+
60
+ #### Don't
61
+
62
+ ```ts
63
+ const msg = "version \8";
64
+ ```
65
+
66
+ #### Do
67
+
68
+ ```ts
69
+ const msg = "version 8";
70
+ ```
71
+
72
+ ### TSX
73
+
74
+ #### Don't
75
+
76
+ ```tsx
77
+ const msg = "version \8";
78
+ ```
79
+
80
+ #### Do
81
+
82
+ ```tsx
83
+ const msg = "version 8";
84
+ ```