@codelaw/rules-js 0.0.0-stage → 0.1.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 (162) hide show
  1. package/LICENSE +23 -0
  2. package/NOTICE +19 -0
  3. package/README.md +90 -2
  4. package/codelaw-pack.toml +6 -0
  5. package/data/globals/browser.json +1209 -0
  6. package/data/globals/commonjs.json +6 -0
  7. package/data/globals/jest.json +15 -0
  8. package/data/globals/mocha.json +22 -0
  9. package/data/globals/node.json +83 -0
  10. package/data/globals/serviceworker.json +328 -0
  11. package/data/globals/shared-node-browser.json +73 -0
  12. package/data/globals/vitest.json +19 -0
  13. package/data/globals/worker.json +349 -0
  14. package/data/node/deprecated-api.json +83 -0
  15. package/data/react/dom-property-aliases.json +131 -0
  16. package/package.json +14 -4
  17. package/presets/js/conventions.toml +10 -0
  18. package/presets/js/recommended.toml +67 -0
  19. package/presets/node/recommended.toml +13 -0
  20. package/presets/react/recommended.toml +22 -0
  21. package/presets/stencil/recommended.toml +18 -0
  22. package/presets/ts/recommended.toml +27 -0
  23. package/rules/graph/no-unused-exports.md +135 -0
  24. package/rules/js/constructor-super.md +77 -0
  25. package/rules/js/exports-at-end.md +134 -0
  26. package/rules/js/for-direction.md +106 -0
  27. package/rules/js/getter-return.md +74 -0
  28. package/rules/js/import-groups.md +117 -0
  29. package/rules/js/no-async-promise-executor.md +95 -0
  30. package/rules/js/no-case-declarations.md +134 -0
  31. package/rules/js/no-class-assign.md +61 -0
  32. package/rules/js/no-compare-neg-zero.md +105 -0
  33. package/rules/js/no-cond-assign.md +135 -0
  34. package/rules/js/no-const-assign.md +61 -0
  35. package/rules/js/no-constant-binary-expression.md +83 -0
  36. package/rules/js/no-constant-condition.md +150 -0
  37. package/rules/js/no-control-regex.md +84 -0
  38. package/rules/js/no-debugger.md +99 -0
  39. package/rules/js/no-default-export.md +88 -0
  40. package/rules/js/no-delete-var.md +93 -0
  41. package/rules/js/no-dupe-args.md +61 -0
  42. package/rules/js/no-dupe-class-members.md +82 -0
  43. package/rules/js/no-dupe-else-if.md +113 -0
  44. package/rules/js/no-dupe-keys.md +66 -0
  45. package/rules/js/no-duplicate-case.md +137 -0
  46. package/rules/js/no-empty-character-class.md +98 -0
  47. package/rules/js/no-empty-pattern.md +86 -0
  48. package/rules/js/no-empty-static-block.md +99 -0
  49. package/rules/js/no-empty.md +116 -0
  50. package/rules/js/no-ex-assign.md +121 -0
  51. package/rules/js/no-extra-boolean-cast.md +107 -0
  52. package/rules/js/no-fallthrough.md +178 -0
  53. package/rules/js/no-func-assign.md +62 -0
  54. package/rules/js/no-global-assign.md +85 -0
  55. package/rules/js/no-import-assign.md +60 -0
  56. package/rules/js/no-invalid-regexp.md +86 -0
  57. package/rules/js/no-irregular-whitespace.md +87 -0
  58. package/rules/js/no-loss-of-precision.md +82 -0
  59. package/rules/js/no-misleading-character-class.md +83 -0
  60. package/rules/js/no-new-native-nonconstructor.md +55 -0
  61. package/rules/js/no-nonoctal-decimal-escape.md +84 -0
  62. package/rules/js/no-obj-calls.md +61 -0
  63. package/rules/js/no-octal.md +84 -0
  64. package/rules/js/no-prototype-builtins.md +99 -0
  65. package/rules/js/no-redeclare.md +61 -0
  66. package/rules/js/no-regex-spaces.md +75 -0
  67. package/rules/js/no-self-assign.md +91 -0
  68. package/rules/js/no-setter-return.md +69 -0
  69. package/rules/js/no-shadow-restricted-names.md +102 -0
  70. package/rules/js/no-sparse-arrays.md +82 -0
  71. package/rules/js/no-this-before-super.md +74 -0
  72. package/rules/js/no-unassigned-vars.md +102 -0
  73. package/rules/js/no-undef.md +76 -0
  74. package/rules/js/no-unexpected-multiline.md +91 -0
  75. package/rules/js/no-unreachable.md +59 -0
  76. package/rules/js/no-unsafe-finally.md +145 -0
  77. package/rules/js/no-unsafe-negation.md +71 -0
  78. package/rules/js/no-unsafe-optional-chaining.md +83 -0
  79. package/rules/js/no-unused-labels.md +102 -0
  80. package/rules/js/no-unused-private-class-members.md +126 -0
  81. package/rules/js/no-unused-vars.md +69 -0
  82. package/rules/js/no-useless-assignment.md +115 -0
  83. package/rules/js/no-useless-backreference.md +83 -0
  84. package/rules/js/no-useless-catch.md +105 -0
  85. package/rules/js/no-useless-escape.md +81 -0
  86. package/rules/js/no-var.md +76 -0
  87. package/rules/js/no-with.md +60 -0
  88. package/rules/js/prefer-const.md +83 -0
  89. package/rules/js/prefer-rest-params.md +103 -0
  90. package/rules/js/prefer-spread.md +95 -0
  91. package/rules/js/preserve-caught-error.md +122 -0
  92. package/rules/js/require-yield.md +107 -0
  93. package/rules/js/use-isnan.md +105 -0
  94. package/rules/js/valid-typeof.md +111 -0
  95. package/rules/node/hashbang.md +71 -0
  96. package/rules/node/no-deprecated-api.md +91 -0
  97. package/rules/node/no-exports-assign.md +92 -0
  98. package/rules/node/no-extraneous-import.md +118 -0
  99. package/rules/node/no-extraneous-require.md +117 -0
  100. package/rules/node/no-missing-import.md +118 -0
  101. package/rules/node/no-missing-require.md +117 -0
  102. package/rules/node/no-process-exit.md +99 -0
  103. package/rules/node/no-unpublished-import.md +134 -0
  104. package/rules/node/no-unpublished-require.md +133 -0
  105. package/rules/react/display-name.md +91 -0
  106. package/rules/react/exhaustive-deps.md +116 -0
  107. package/rules/react/hook-prefix.md +108 -0
  108. package/rules/react/jsx-key.md +99 -0
  109. package/rules/react/jsx-no-comment-textnodes.md +87 -0
  110. package/rules/react/jsx-no-duplicate-props.md +66 -0
  111. package/rules/react/jsx-no-target-blank.md +78 -0
  112. package/rules/react/jsx-no-undef.md +78 -0
  113. package/rules/react/no-children-prop.md +80 -0
  114. package/rules/react/no-danger-with-children.md +83 -0
  115. package/rules/react/no-deprecated.md +84 -0
  116. package/rules/react/no-direct-mutation-state.md +102 -0
  117. package/rules/react/no-find-dom-node.md +72 -0
  118. package/rules/react/no-is-mounted.md +109 -0
  119. package/rules/react/no-render-return-value.md +75 -0
  120. package/rules/react/no-string-refs.md +72 -0
  121. package/rules/react/no-unescaped-entities.md +69 -0
  122. package/rules/react/no-unknown-property.md +69 -0
  123. package/rules/react/props-type-name.md +43 -0
  124. package/rules/react/require-render-return.md +91 -0
  125. package/rules/react/rules-of-hooks.md +128 -0
  126. package/rules/stencil/ban-default-true.md +70 -0
  127. package/rules/stencil/ban-exported-const-enums.md +60 -0
  128. package/rules/stencil/ban-prefix.md +76 -0
  129. package/rules/stencil/decorators-context.md +61 -0
  130. package/rules/stencil/host-data-deprecated.md +73 -0
  131. package/rules/stencil/methods-must-be-public.md +69 -0
  132. package/rules/stencil/no-unused-watch.md +68 -0
  133. package/rules/stencil/own-methods-must-be-private.md +68 -0
  134. package/rules/stencil/own-props-must-be-private.md +60 -0
  135. package/rules/stencil/prefer-vdom-listener.md +67 -0
  136. package/rules/stencil/prop-readonly.md +63 -0
  137. package/rules/stencil/props-must-be-public.md +68 -0
  138. package/rules/stencil/required-jsdoc.md +66 -0
  139. package/rules/stencil/reserved-member-names.md +70 -0
  140. package/rules/stencil/strict-mutable.md +75 -0
  141. package/rules/stencil/tag-prefix.md +75 -0
  142. package/rules/ts/ban-ts-comment.md +64 -0
  143. package/rules/ts/no-array-constructor.md +58 -0
  144. package/rules/ts/no-duplicate-enum-values.md +65 -0
  145. package/rules/ts/no-empty-object-type.md +65 -0
  146. package/rules/ts/no-explicit-any.md +61 -0
  147. package/rules/ts/no-extra-non-null-assertion.md +50 -0
  148. package/rules/ts/no-misused-new.md +70 -0
  149. package/rules/ts/no-namespace.md +65 -0
  150. package/rules/ts/no-non-null-asserted-optional-chain.md +55 -0
  151. package/rules/ts/no-require-imports.md +54 -0
  152. package/rules/ts/no-this-alias.md +68 -0
  153. package/rules/ts/no-unnecessary-type-constraint.md +64 -0
  154. package/rules/ts/no-unsafe-declaration-merging.md +73 -0
  155. package/rules/ts/no-unsafe-function-type.md +57 -0
  156. package/rules/ts/no-unused-expressions.md +61 -0
  157. package/rules/ts/no-unused-vars.md +68 -0
  158. package/rules/ts/no-wrapper-object-types.md +49 -0
  159. package/rules/ts/prefer-as-const.md +47 -0
  160. package/rules/ts/prefer-namespace-keyword.md +63 -0
  161. package/rules/ts/triple-slash-reference.md +60 -0
  162. package/rules/ts/type-only-imports.md +57 -0
@@ -0,0 +1,22 @@
1
+ description = "eslint-plugin-react 7.37.5 recommended with jsx-runtime, and eslint-plugin-react-hooks 7.1.1 rules-of-hooks and exhaustive-deps, reimplemented"
2
+
3
+ [rules]
4
+ "react/display-name" = "error"
5
+ "react/exhaustive-deps" = "error"
6
+ "react/jsx-key" = "error"
7
+ "react/jsx-no-comment-textnodes" = "error"
8
+ "react/jsx-no-duplicate-props" = "error"
9
+ "react/jsx-no-target-blank" = "error"
10
+ "react/jsx-no-undef" = "error"
11
+ "react/no-children-prop" = "error"
12
+ "react/no-danger-with-children" = "error"
13
+ "react/no-deprecated" = "error"
14
+ "react/no-direct-mutation-state" = "error"
15
+ "react/no-find-dom-node" = "error"
16
+ "react/no-is-mounted" = "error"
17
+ "react/no-render-return-value" = "error"
18
+ "react/no-string-refs" = "error"
19
+ "react/no-unescaped-entities" = "error"
20
+ "react/no-unknown-property" = "error"
21
+ "react/require-render-return" = "error"
22
+ "react/rules-of-hooks" = "error"
@@ -0,0 +1,18 @@
1
+ description = "@stencil/eslint-plugin 1.4.0 recommended without its type-checked rules, reimplemented"
2
+
3
+ [rules]
4
+ "stencil/ban-default-true" = "error"
5
+ "stencil/ban-exported-const-enums" = "error"
6
+ "stencil/ban-prefix" = "error"
7
+ "stencil/decorators-context" = "error"
8
+ "stencil/host-data-deprecated" = "error"
9
+ "stencil/methods-must-be-public" = "error"
10
+ "stencil/no-unused-watch" = "error"
11
+ "stencil/own-methods-must-be-private" = "error"
12
+ "stencil/own-props-must-be-private" = "error"
13
+ "stencil/prefer-vdom-listener" = "error"
14
+ "stencil/prop-readonly" = "error"
15
+ "stencil/props-must-be-public" = "error"
16
+ "stencil/required-jsdoc" = "error"
17
+ "stencil/reserved-member-names" = "error"
18
+ "stencil/strict-mutable" = "error"
@@ -0,0 +1,27 @@
1
+ description = "typescript-eslint's recommended preset (8.71.2, not type-checked), reimplemented, with the core rules it switches on for TypeScript"
2
+
3
+ [rules]
4
+ "ts/ban-ts-comment" = "error"
5
+ "ts/no-array-constructor" = "error"
6
+ "ts/no-duplicate-enum-values" = "error"
7
+ "ts/no-empty-object-type" = "error"
8
+ "ts/no-explicit-any" = "error"
9
+ "ts/no-extra-non-null-assertion" = "error"
10
+ "ts/no-misused-new" = "error"
11
+ "ts/no-namespace" = "error"
12
+ "ts/no-non-null-asserted-optional-chain" = "error"
13
+ "ts/no-require-imports" = "error"
14
+ "ts/no-this-alias" = "error"
15
+ "ts/no-unnecessary-type-constraint" = "error"
16
+ "ts/no-unsafe-declaration-merging" = "error"
17
+ "ts/no-unsafe-function-type" = "error"
18
+ "ts/no-unused-expressions" = "error"
19
+ "ts/no-unused-vars" = "error"
20
+ "ts/no-wrapper-object-types" = "error"
21
+ "ts/prefer-as-const" = "error"
22
+ "ts/prefer-namespace-keyword" = "error"
23
+ "ts/triple-slash-reference" = "error"
24
+ "js/no-var" = "error"
25
+ "js/prefer-const" = "error"
26
+ "js/prefer-rest-params" = "error"
27
+ "js/prefer-spread" = "error"
@@ -0,0 +1,135 @@
1
+ ---
2
+ id: graph/no-unused-exports
3
+ title: Exported symbols must be used somewhere
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ scope: project
6
+ severity: error
7
+ fix: suggest
8
+ fix_reason: "Static analysis can't rule out reflective or external use, so removal needs a human or agent to accept the diff."
9
+ stability: preview
10
+ ported_from: [knip/exports, knip/types]
11
+ since: 0.1.0
12
+ ---
13
+
14
+ Every exported symbol is imported by another module, is reachable from an entry point, or is marked `@public` / `@keep`.
15
+
16
+ **Why:** an export nothing imports is dead code that still looks like API: readers keep it, refactors carry it, and it hides what a module is really for.
17
+
18
+ ```codelaw
19
+ graph:
20
+ symbol:
21
+ exported: true
22
+ kind: [function, class, variable, type, interface, enum]
23
+ unless:
24
+ - reachable_from: entry
25
+ - tagged: [public, keep]
26
+ when:
27
+ external_references: 0
28
+ certainty_from: module.dynamic
29
+ message: "`$SYMBOL` is exported but never used outside `$FILE`"
30
+ fix:
31
+ - when: { local_references: ">0" }
32
+ do: [strip-export-keyword]
33
+ - else:
34
+ do: [remove-declaration]
35
+ ```
36
+
37
+ ## How to fix
38
+
39
+ 1. Run `codelaw graph why-unused <symbol>` (`<file>#<export>` or `<module>:<name>`) to see each entry, keep and import clause.
40
+ 2. If something outside the repo uses it, add the file to `[graph] entry` or `[graph] keep`, add its decorator to `[graph] registrars`, or tag it `/** @public */` / `# codelaw: keep`.
41
+ 3. Otherwise delete the declaration (and its `__all__` or `export { … }` entry), or drop `export` if its own file still uses it.
42
+
43
+ ## Examples
44
+
45
+ ### JavaScript
46
+
47
+ #### Don't
48
+
49
+ ```js files
50
+ // src/date.js
51
+ export function formatDate(d) { return d.toISOString(); }
52
+ export function parseDate(s) { return new Date(s); }
53
+ // src/app.js
54
+ import { formatDate } from "./date";
55
+ console.log(formatDate(new Date()));
56
+ ```
57
+
58
+ #### Do
59
+
60
+ ```js files
61
+ // src/date.js
62
+ export function formatDate(d) { return d.toISOString(); }
63
+ // src/app.js
64
+ import { formatDate } from "./date";
65
+ console.log(formatDate(new Date()));
66
+ ```
67
+
68
+ ### JSX
69
+
70
+ #### Don't
71
+
72
+ ```jsx files
73
+ // src/Button.jsx
74
+ export function Button() { return <button />; }
75
+ export function Unused() { return <span />; }
76
+ // src/App.jsx
77
+ import { Button } from "./Button";
78
+ console.log(<Button />);
79
+ ```
80
+
81
+ #### Do
82
+
83
+ ```jsx files
84
+ // src/Button.jsx
85
+ export function Button() { return <button />; }
86
+ // src/App.jsx
87
+ import { Button } from "./Button";
88
+ console.log(<Button />);
89
+ ```
90
+
91
+ ### TypeScript
92
+
93
+ #### Don't
94
+
95
+ ```ts files
96
+ // packages/utils/src/date.ts
97
+ export function formatDate(d: Date) { return d.toISOString(); }
98
+ export function parseDate(s: string) { return new Date(s); }
99
+ // packages/web/src/app.ts
100
+ import { formatDate } from "../../utils/src/date";
101
+ console.log(formatDate(new Date()));
102
+ ```
103
+
104
+ #### Do
105
+
106
+ ```ts files
107
+ // packages/utils/src/date.ts
108
+ export function formatDate(d: Date) { return d.toISOString(); }
109
+ // packages/web/src/app.ts
110
+ import { formatDate } from "../../utils/src/date";
111
+ console.log(formatDate(new Date()));
112
+ ```
113
+
114
+ ### TSX
115
+
116
+ #### Don't
117
+
118
+ ```tsx files
119
+ // src/theme.tsx
120
+ export const theme = { dark: false };
121
+ export const unusedTheme = { dark: true };
122
+ // src/main.tsx
123
+ import { theme } from "./theme";
124
+ console.log(theme);
125
+ ```
126
+
127
+ #### Do
128
+
129
+ ```tsx files
130
+ // src/theme.tsx
131
+ export const theme = { dark: false };
132
+ // src/main.tsx
133
+ import { theme } from "./theme";
134
+ console.log(theme);
135
+ ```
@@ -0,0 +1,77 @@
1
+ ---
2
+ id: js/constructor-super
3
+ title: "A derived class's constructor calls super(); a base class's does not"
4
+ languages: [javascript, jsx]
5
+ fix: manual
6
+ fix_reason: "what `super()` must receive depends on the base class"
7
+ stability: preview
8
+ ported_from: [eslint/constructor-super]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ A class that extends another must call `super()` in its constructor before it returns, and a class
13
+ that extends nothing must not call `super()` at all.
14
+
15
+ **Why:** Without `super()` the instance is never initialised and the constructor throws; in a base
16
+ class `super()` is a syntax error.
17
+
18
+ ```codelaw
19
+ native: js/constructor-super
20
+ ```
21
+
22
+ ## How to fix
23
+
24
+ 1. In a class with `extends`, call `super(...)` with the arguments the base class expects, before any use of `this`.
25
+ 2. In a class without `extends`, remove the `super()` call.
26
+
27
+ ## Examples
28
+
29
+ ### JavaScript
30
+
31
+ #### Don't
32
+
33
+ ```js
34
+ class Cat extends Animal {
35
+ constructor() {
36
+ this.lives = 9;
37
+ }
38
+ }
39
+ ```
40
+
41
+ #### Do
42
+
43
+ ```js
44
+ class Cat extends Animal {
45
+ constructor() {
46
+ super();
47
+ this.lives = 9;
48
+ }
49
+ }
50
+ ```
51
+
52
+ ### JSX
53
+
54
+ #### Don't
55
+
56
+ ```jsx
57
+ class Cat extends Animal {
58
+ constructor() {
59
+ this.lives = 9;
60
+ }
61
+ }
62
+ ```
63
+
64
+ #### Do
65
+
66
+ ```jsx
67
+ class Cat extends Animal {
68
+ constructor() {
69
+ super();
70
+ this.lives = 9;
71
+ }
72
+ }
73
+ ```
74
+
75
+ ## Differences from the source
76
+
77
+ Paths are followed in straight-line order: a `super()` on any branch counts as called.
@@ -0,0 +1,134 @@
1
+ ---
2
+ id: js/exports-at-end
3
+ title: "Exports are gathered at the end of the file"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: auto
6
+ stability: preview
7
+ invariant: exports-unchanged
8
+ since: 0.1.0
9
+ ---
10
+
11
+ Declarations are written without `export`, and the module's exports are listed in one `export { … }`
12
+ (and `export type { … }`) block at the end of the file.
13
+
14
+ **Why:** A reader or an agent sees the module's whole public API in one place.
15
+
16
+ ```codelaw
17
+ match:
18
+ kind: export_statement
19
+ has: { field: declaration, pattern: $DECL }
20
+ not:
21
+ any:
22
+ - has: { regex: ^default$ }
23
+ - has: { field: declaration, kind: internal_module }
24
+ - has: { field: declaration, kind: ambient_declaration }
25
+ - has: { field: declaration, kind: module }
26
+ message: "Export at the end of the file, in one `export { … }` block"
27
+ fix:
28
+ - strip-export-keyword: $DECL
29
+ - collect-into-block:
30
+ target: $DECL
31
+ block: "export { $$$NAMES };"
32
+ type_block: "export type { $$$TYPE_NAMES };"
33
+ position: end-of-file
34
+ ```
35
+
36
+ ## Examples
37
+
38
+ ### JavaScript
39
+
40
+ #### Don't
41
+
42
+ ```js
43
+ export function add(a, b) {
44
+ return a + b;
45
+ }
46
+ export const zero = 0;
47
+ ```
48
+
49
+ #### Do
50
+
51
+ ```js
52
+ function add(a, b) {
53
+ return a + b;
54
+ }
55
+ const zero = 0;
56
+ export { add, zero };
57
+ ```
58
+
59
+ ### JSX
60
+
61
+ #### Don't
62
+
63
+ ```jsx
64
+ export function add(a, b) {
65
+ return a + b;
66
+ }
67
+ export const zero = 0;
68
+ ```
69
+
70
+ #### Do
71
+
72
+ ```jsx
73
+ function add(a, b) {
74
+ return a + b;
75
+ }
76
+ const zero = 0;
77
+ export { add, zero };
78
+ ```
79
+
80
+ ### TypeScript
81
+
82
+ #### Don't
83
+
84
+ ```ts
85
+ export function add(a: number, b: number) {
86
+ return a + b;
87
+ }
88
+ export interface Point {
89
+ x: number;
90
+ }
91
+ ```
92
+
93
+ #### Do
94
+
95
+ ```ts
96
+ function add(a: number, b: number) {
97
+ return a + b;
98
+ }
99
+ interface Point {
100
+ x: number;
101
+ }
102
+ export { add };
103
+ export type { Point };
104
+ ```
105
+
106
+ ### TSX
107
+
108
+ #### Don't
109
+
110
+ ```tsx
111
+ export function add(a: number, b: number) {
112
+ return a + b;
113
+ }
114
+ export interface Point {
115
+ x: number;
116
+ }
117
+ ```
118
+
119
+ #### Do
120
+
121
+ ```tsx
122
+ function add(a: number, b: number) {
123
+ return a + b;
124
+ }
125
+ interface Point {
126
+ x: number;
127
+ }
128
+ export { add };
129
+ export type { Point };
130
+ ```
131
+
132
+ ## Differences from the source
133
+
134
+ `export default`, namespaces and `declare` blocks are left alone.
@@ -0,0 +1,106 @@
1
+ ---
2
+ id: js/for-direction
3
+ title: "A for loop's counter moves toward its end condition"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "whether the condition or the update is wrong needs the author"
7
+ stability: preview
8
+ ported_from: [eslint/for-direction]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ A `for` loop whose condition tests `i < n` counts up, and one that tests `i > n` counts down.
13
+
14
+ **Why:** A counter that moves the wrong way never meets its end condition, so the loop never ends.
15
+
16
+ ```codelaw
17
+ match:
18
+ kind: for_statement
19
+ any:
20
+ - all:
21
+ - has: { field: condition, any: [{ pattern: $I < $END }, { pattern: $I <= $END }] }
22
+ - has: { field: increment, any: [{ pattern: $I-- }, { pattern: --$I }] }
23
+ - all:
24
+ - has: { field: condition, any: [{ pattern: $I > $END }, { pattern: $I >= $END }] }
25
+ - has: { field: increment, any: [{ pattern: $I++ }, { pattern: ++$I }] }
26
+ message: "The counter `$I` moves away from the condition that ends this loop"
27
+ ```
28
+
29
+ ## How to fix
30
+
31
+ 1. Decide which way the loop should count.
32
+ 2. Fix the update (`i++` or `i--`) or the comparison to match.
33
+
34
+ ## Examples
35
+
36
+ ### JavaScript
37
+
38
+ #### Don't
39
+
40
+ ```js
41
+ for (let i = 0; i < 10; i--) {
42
+ draw(i);
43
+ }
44
+ ```
45
+
46
+ #### Do
47
+
48
+ ```js
49
+ for (let i = 0; i < 10; i++) {
50
+ draw(i);
51
+ }
52
+ ```
53
+
54
+ ### JSX
55
+
56
+ #### Don't
57
+
58
+ ```jsx
59
+ for (let i = 0; i < 10; i--) {
60
+ draw(i);
61
+ }
62
+ ```
63
+
64
+ #### Do
65
+
66
+ ```jsx
67
+ for (let i = 0; i < 10; i++) {
68
+ draw(i);
69
+ }
70
+ ```
71
+
72
+ ### TypeScript
73
+
74
+ #### Don't
75
+
76
+ ```ts
77
+ for (let i = 0; i < 10; i--) {
78
+ draw(i);
79
+ }
80
+ ```
81
+
82
+ #### Do
83
+
84
+ ```ts
85
+ for (let i = 0; i < 10; i++) {
86
+ draw(i);
87
+ }
88
+ ```
89
+
90
+ ### TSX
91
+
92
+ #### Don't
93
+
94
+ ```tsx
95
+ for (let i = 0; i < 10; i--) {
96
+ draw(i);
97
+ }
98
+ ```
99
+
100
+ #### Do
101
+
102
+ ```tsx
103
+ for (let i = 0; i < 10; i++) {
104
+ draw(i);
105
+ }
106
+ ```
@@ -0,0 +1,74 @@
1
+ ---
2
+ id: js/getter-return
3
+ title: "A getter returns a value on every path"
4
+ languages: [javascript, jsx]
5
+ fix: manual
6
+ fix_reason: "the value a getter should return is the author's decision"
7
+ stability: preview
8
+ ported_from: [eslint/getter-return]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ Every path through a getter ends in `return <value>` or a `throw`.
13
+
14
+ **Why:** A getter that falls off its end returns `undefined`, which is almost always a forgotten
15
+ `return`.
16
+
17
+ ```codelaw
18
+ native: js/getter-return
19
+ ```
20
+
21
+ ## How to fix
22
+
23
+ 1. Find the path that ends without a `return`.
24
+ 2. Return the value the property should have there, or throw.
25
+
26
+ ## Examples
27
+
28
+ ### JavaScript
29
+
30
+ #### Don't
31
+
32
+ ```js
33
+ const box = {
34
+ get size() {
35
+ if (this.items) {
36
+ return this.items.length;
37
+ }
38
+ },
39
+ };
40
+ ```
41
+
42
+ #### Do
43
+
44
+ ```js
45
+ const box = {
46
+ get size() {
47
+ return this.items ? this.items.length : 0;
48
+ },
49
+ };
50
+ ```
51
+
52
+ ### JSX
53
+
54
+ #### Don't
55
+
56
+ ```jsx
57
+ const box = {
58
+ get size() {
59
+ if (this.items) {
60
+ return this.items.length;
61
+ }
62
+ },
63
+ };
64
+ ```
65
+
66
+ #### Do
67
+
68
+ ```jsx
69
+ const box = {
70
+ get size() {
71
+ return this.items ? this.items.length : 0;
72
+ },
73
+ };
74
+ ```
@@ -0,0 +1,117 @@
1
+ ---
2
+ id: js/import-groups
3
+ title: "Imports are grouped builtin, external, internal, relative"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: auto
6
+ stability: preview
7
+ options:
8
+ internal: { type: "string[]", default: ["@/", "~/"], description: "prefixes of internal imports" }
9
+ since: 0.1.0
10
+ ---
11
+
12
+ The file's leading imports come in four groups, in order — Node.js built-ins, packages, internal
13
+ aliases (the `internal` option, `@/` and `~/` by default), relative paths — with a blank line
14
+ between groups.
15
+
16
+ **Why:** Grouped imports show at a glance what a module depends on, and keep diffs of the import
17
+ block small.
18
+
19
+ ```codelaw
20
+ native: js/import-groups
21
+ ```
22
+
23
+ ## Examples
24
+
25
+ ### JavaScript
26
+
27
+ #### Don't
28
+
29
+ ```js
30
+ import { helper } from "./helper";
31
+ import fs from "node:fs";
32
+ import React from "react";
33
+ helper(fs, React);
34
+ ```
35
+
36
+ #### Do
37
+
38
+ ```js
39
+ import fs from "node:fs";
40
+
41
+ import React from "react";
42
+
43
+ import { helper } from "./helper";
44
+ helper(fs, React);
45
+ ```
46
+
47
+ ### JSX
48
+
49
+ #### Don't
50
+
51
+ ```jsx
52
+ import { helper } from "./helper";
53
+ import fs from "node:fs";
54
+ import React from "react";
55
+ helper(fs, React);
56
+ ```
57
+
58
+ #### Do
59
+
60
+ ```jsx
61
+ import fs from "node:fs";
62
+
63
+ import React from "react";
64
+
65
+ import { helper } from "./helper";
66
+ helper(fs, React);
67
+ ```
68
+
69
+ ### TypeScript
70
+
71
+ #### Don't
72
+
73
+ ```ts
74
+ import { helper } from "./helper";
75
+ import fs from "node:fs";
76
+ import React from "react";
77
+ helper(fs, React);
78
+ ```
79
+
80
+ #### Do
81
+
82
+ ```ts
83
+ import fs from "node:fs";
84
+
85
+ import React from "react";
86
+
87
+ import { helper } from "./helper";
88
+ helper(fs, React);
89
+ ```
90
+
91
+ ### TSX
92
+
93
+ #### Don't
94
+
95
+ ```tsx
96
+ import { helper } from "./helper";
97
+ import fs from "node:fs";
98
+ import React from "react";
99
+ helper(fs, React);
100
+ ```
101
+
102
+ #### Do
103
+
104
+ ```tsx
105
+ import fs from "node:fs";
106
+
107
+ import React from "react";
108
+
109
+ import { helper } from "./helper";
110
+ helper(fs, React);
111
+ ```
112
+
113
+ ## Differences from the source
114
+
115
+ A block of imports with a comment inside is left alone, so no comment is moved away from the import
116
+ it describes. A side-effect import (`import './polyfills'`, a stylesheet) stays where it is, since moving it
117
+ changes what runs first; only the imports between two of them are ordered.