@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.
- package/LICENSE +23 -0
- package/NOTICE +10 -0
- package/README.md +57 -2
- package/codelaw-pack.toml +6 -0
- package/corpus.toml +76 -0
- package/data/globals/browser.json +1209 -0
- package/data/globals/commonjs.json +6 -0
- package/data/globals/jest.json +15 -0
- package/data/globals/mocha.json +22 -0
- package/data/globals/node.json +83 -0
- package/data/globals/serviceworker.json +328 -0
- package/data/globals/shared-node-browser.json +73 -0
- package/data/globals/vitest.json +19 -0
- package/data/globals/worker.json +349 -0
- package/package.json +14 -4
- package/presets/js/conventions.toml +6 -0
- package/presets/js/project.toml +4 -0
- package/presets/js/recommended.toml +67 -0
- package/presets/js/typescript.toml +7 -0
- package/rules/graph/no-unused-exports.md +135 -0
- package/rules/js/constructor-super.md +77 -0
- package/rules/js/exports-at-end.md +134 -0
- package/rules/js/for-direction.md +106 -0
- package/rules/js/getter-return.md +74 -0
- package/rules/js/import-groups.md +117 -0
- package/rules/js/no-async-promise-executor.md +95 -0
- package/rules/js/no-case-declarations.md +134 -0
- package/rules/js/no-class-assign.md +61 -0
- package/rules/js/no-compare-neg-zero.md +105 -0
- package/rules/js/no-cond-assign.md +135 -0
- package/rules/js/no-const-assign.md +61 -0
- package/rules/js/no-constant-binary-expression.md +83 -0
- package/rules/js/no-constant-condition.md +150 -0
- package/rules/js/no-control-regex.md +84 -0
- package/rules/js/no-debugger.md +99 -0
- package/rules/js/no-default-export.md +88 -0
- package/rules/js/no-delete-var.md +93 -0
- package/rules/js/no-dupe-args.md +61 -0
- package/rules/js/no-dupe-class-members.md +82 -0
- package/rules/js/no-dupe-else-if.md +113 -0
- package/rules/js/no-dupe-keys.md +66 -0
- package/rules/js/no-duplicate-case.md +137 -0
- package/rules/js/no-empty-character-class.md +98 -0
- package/rules/js/no-empty-pattern.md +86 -0
- package/rules/js/no-empty-static-block.md +99 -0
- package/rules/js/no-empty.md +116 -0
- package/rules/js/no-ex-assign.md +121 -0
- package/rules/js/no-extra-boolean-cast.md +107 -0
- package/rules/js/no-fallthrough.md +178 -0
- package/rules/js/no-func-assign.md +62 -0
- package/rules/js/no-global-assign.md +85 -0
- package/rules/js/no-import-assign.md +60 -0
- package/rules/js/no-invalid-regexp.md +86 -0
- package/rules/js/no-irregular-whitespace.md +87 -0
- package/rules/js/no-loss-of-precision.md +82 -0
- package/rules/js/no-misleading-character-class.md +83 -0
- package/rules/js/no-new-native-nonconstructor.md +55 -0
- package/rules/js/no-nonoctal-decimal-escape.md +84 -0
- package/rules/js/no-obj-calls.md +61 -0
- package/rules/js/no-octal.md +84 -0
- package/rules/js/no-prototype-builtins.md +99 -0
- package/rules/js/no-redeclare.md +61 -0
- package/rules/js/no-regex-spaces.md +75 -0
- package/rules/js/no-self-assign.md +91 -0
- package/rules/js/no-setter-return.md +69 -0
- package/rules/js/no-shadow-restricted-names.md +102 -0
- package/rules/js/no-sparse-arrays.md +82 -0
- package/rules/js/no-this-before-super.md +74 -0
- package/rules/js/no-unassigned-vars.md +102 -0
- package/rules/js/no-undef.md +76 -0
- package/rules/js/no-unexpected-multiline.md +91 -0
- package/rules/js/no-unreachable.md +59 -0
- package/rules/js/no-unsafe-finally.md +145 -0
- package/rules/js/no-unsafe-negation.md +71 -0
- package/rules/js/no-unsafe-optional-chaining.md +83 -0
- package/rules/js/no-unused-labels.md +102 -0
- package/rules/js/no-unused-private-class-members.md +126 -0
- package/rules/js/no-unused-vars.md +69 -0
- package/rules/js/no-useless-assignment.md +115 -0
- package/rules/js/no-useless-backreference.md +83 -0
- package/rules/js/no-useless-catch.md +105 -0
- package/rules/js/no-useless-escape.md +81 -0
- package/rules/js/no-var.md +76 -0
- package/rules/js/no-with.md +60 -0
- package/rules/js/prefer-const.md +83 -0
- package/rules/js/prefer-rest-params.md +103 -0
- package/rules/js/prefer-spread.md +95 -0
- package/rules/js/preserve-caught-error.md +122 -0
- package/rules/js/require-yield.md +107 -0
- package/rules/js/use-isnan.md +105 -0
- package/rules/js/valid-typeof.md +111 -0
|
@@ -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.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: js/no-async-promise-executor
|
|
3
|
+
title: "A Promise executor is not an async function"
|
|
4
|
+
languages: [javascript, jsx, typescript, tsx]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the rewrite depends on what the executor does"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [eslint/no-async-promise-executor]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
The function passed to `new Promise(...)` is not `async`.
|
|
13
|
+
|
|
14
|
+
**Why:** An error thrown in an async executor doesn't reject the promise, and an executor that needs
|
|
15
|
+
`await` doesn't need the `Promise` wrapper.
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
match:
|
|
19
|
+
any:
|
|
20
|
+
- pattern: new Promise(async ($$$P) => $$$B)
|
|
21
|
+
- pattern: new Promise(async function ($$$P) { $$$B })
|
|
22
|
+
- pattern: new Promise(async $P => $$$B)
|
|
23
|
+
message: "An async Promise executor loses its errors; await inside a plain async function instead"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## How to fix
|
|
27
|
+
|
|
28
|
+
1. If the executor only awaits and resolves, use the awaited promise directly.
|
|
29
|
+
2. Otherwise make the executor a plain function and handle errors with `reject`.
|
|
30
|
+
|
|
31
|
+
## Examples
|
|
32
|
+
|
|
33
|
+
### JavaScript
|
|
34
|
+
|
|
35
|
+
#### Don't
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
const data = new Promise(async (resolve) => {
|
|
39
|
+
resolve(await load());
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
#### Do
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
const data = load();
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### JSX
|
|
50
|
+
|
|
51
|
+
#### Don't
|
|
52
|
+
|
|
53
|
+
```jsx
|
|
54
|
+
const data = new Promise(async (resolve) => {
|
|
55
|
+
resolve(await load());
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
#### Do
|
|
60
|
+
|
|
61
|
+
```jsx
|
|
62
|
+
const data = load();
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### TypeScript
|
|
66
|
+
|
|
67
|
+
#### Don't
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
const data = new Promise(async (resolve) => {
|
|
71
|
+
resolve(await load());
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
#### Do
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
const data = load();
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### TSX
|
|
82
|
+
|
|
83
|
+
#### Don't
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
const data = new Promise(async (resolve) => {
|
|
87
|
+
resolve(await load());
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### Do
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
const data = load();
|
|
95
|
+
```
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: js/no-case-declarations
|
|
3
|
+
title: "No let, const, function or class directly in a case"
|
|
4
|
+
languages: [javascript, jsx, typescript, tsx]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "another case may rely on the shared declaration"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [eslint/no-case-declarations]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A `let`, `const`, `function` or `class` inside a `case` sits in a block `{ … }` of its own.
|
|
13
|
+
|
|
14
|
+
**Why:** Declarations in a case are scoped to the whole `switch`, so another case can see them
|
|
15
|
+
uninitialised.
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
match:
|
|
19
|
+
any:
|
|
20
|
+
- kind: lexical_declaration
|
|
21
|
+
- kind: class_declaration
|
|
22
|
+
- kind: function_declaration
|
|
23
|
+
inside:
|
|
24
|
+
stopBy: neighbor
|
|
25
|
+
any: [{ kind: switch_case }, { kind: switch_default }]
|
|
26
|
+
message: "A declaration in a case is visible to the whole switch; wrap the case in braces"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## How to fix
|
|
30
|
+
|
|
31
|
+
1. Wrap the case's statements in `{ … }`.
|
|
32
|
+
2. If another case uses the declaration, move it above the `switch`.
|
|
33
|
+
|
|
34
|
+
## Examples
|
|
35
|
+
|
|
36
|
+
### JavaScript
|
|
37
|
+
|
|
38
|
+
#### Don't
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
switch (kind) {
|
|
42
|
+
case "a":
|
|
43
|
+
const n = 1;
|
|
44
|
+
use(n);
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
#### Do
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
switch (kind) {
|
|
53
|
+
case "a": {
|
|
54
|
+
const n = 1;
|
|
55
|
+
use(n);
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### JSX
|
|
62
|
+
|
|
63
|
+
#### Don't
|
|
64
|
+
|
|
65
|
+
```jsx
|
|
66
|
+
switch (kind) {
|
|
67
|
+
case "a":
|
|
68
|
+
const n = 1;
|
|
69
|
+
use(n);
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### Do
|
|
75
|
+
|
|
76
|
+
```jsx
|
|
77
|
+
switch (kind) {
|
|
78
|
+
case "a": {
|
|
79
|
+
const n = 1;
|
|
80
|
+
use(n);
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### TypeScript
|
|
87
|
+
|
|
88
|
+
#### Don't
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
switch (kind) {
|
|
92
|
+
case "a":
|
|
93
|
+
const n = 1;
|
|
94
|
+
use(n);
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### Do
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
switch (kind) {
|
|
103
|
+
case "a": {
|
|
104
|
+
const n = 1;
|
|
105
|
+
use(n);
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### TSX
|
|
112
|
+
|
|
113
|
+
#### Don't
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
switch (kind) {
|
|
117
|
+
case "a":
|
|
118
|
+
const n = 1;
|
|
119
|
+
use(n);
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
#### Do
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
switch (kind) {
|
|
128
|
+
case "a": {
|
|
129
|
+
const n = 1;
|
|
130
|
+
use(n);
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: js/no-class-assign
|
|
3
|
+
title: "A class name 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-class-assign]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Code doesn't assign a new value to the name a class declaration binds.
|
|
13
|
+
|
|
14
|
+
**Why:** Reassigning a class name is almost always a mistake, and makes every later use mean
|
|
15
|
+
something else.
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
match:
|
|
19
|
+
kind: identifier
|
|
20
|
+
where:
|
|
21
|
+
$$MATCH: [write, { binding: class }]
|
|
22
|
+
message: "`$$MATCH` is a class; don't assign to it"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## How to fix
|
|
26
|
+
|
|
27
|
+
1. Assign to a new variable instead of the class name.
|
|
28
|
+
|
|
29
|
+
## Examples
|
|
30
|
+
|
|
31
|
+
### JavaScript
|
|
32
|
+
|
|
33
|
+
#### Don't
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
class Point {}
|
|
37
|
+
Point = null;
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
#### Do
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
class Point {}
|
|
44
|
+
const origin = null;
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### JSX
|
|
48
|
+
|
|
49
|
+
#### Don't
|
|
50
|
+
|
|
51
|
+
```jsx
|
|
52
|
+
class Point {}
|
|
53
|
+
Point = null;
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
#### Do
|
|
57
|
+
|
|
58
|
+
```jsx
|
|
59
|
+
class Point {}
|
|
60
|
+
const origin = null;
|
|
61
|
+
```
|