@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.
- package/LICENSE +23 -0
- package/NOTICE +19 -0
- package/README.md +90 -2
- package/codelaw-pack.toml +6 -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/data/node/deprecated-api.json +83 -0
- package/data/react/dom-property-aliases.json +131 -0
- package/package.json +14 -4
- package/presets/js/conventions.toml +10 -0
- package/presets/js/recommended.toml +67 -0
- package/presets/node/recommended.toml +13 -0
- package/presets/react/recommended.toml +22 -0
- package/presets/stencil/recommended.toml +18 -0
- package/presets/ts/recommended.toml +27 -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
- package/rules/node/hashbang.md +71 -0
- package/rules/node/no-deprecated-api.md +91 -0
- package/rules/node/no-exports-assign.md +92 -0
- package/rules/node/no-extraneous-import.md +118 -0
- package/rules/node/no-extraneous-require.md +117 -0
- package/rules/node/no-missing-import.md +118 -0
- package/rules/node/no-missing-require.md +117 -0
- package/rules/node/no-process-exit.md +99 -0
- package/rules/node/no-unpublished-import.md +134 -0
- package/rules/node/no-unpublished-require.md +133 -0
- package/rules/react/display-name.md +91 -0
- package/rules/react/exhaustive-deps.md +116 -0
- package/rules/react/hook-prefix.md +108 -0
- package/rules/react/jsx-key.md +99 -0
- package/rules/react/jsx-no-comment-textnodes.md +87 -0
- package/rules/react/jsx-no-duplicate-props.md +66 -0
- package/rules/react/jsx-no-target-blank.md +78 -0
- package/rules/react/jsx-no-undef.md +78 -0
- package/rules/react/no-children-prop.md +80 -0
- package/rules/react/no-danger-with-children.md +83 -0
- package/rules/react/no-deprecated.md +84 -0
- package/rules/react/no-direct-mutation-state.md +102 -0
- package/rules/react/no-find-dom-node.md +72 -0
- package/rules/react/no-is-mounted.md +109 -0
- package/rules/react/no-render-return-value.md +75 -0
- package/rules/react/no-string-refs.md +72 -0
- package/rules/react/no-unescaped-entities.md +69 -0
- package/rules/react/no-unknown-property.md +69 -0
- package/rules/react/props-type-name.md +43 -0
- package/rules/react/require-render-return.md +91 -0
- package/rules/react/rules-of-hooks.md +128 -0
- package/rules/stencil/ban-default-true.md +70 -0
- package/rules/stencil/ban-exported-const-enums.md +60 -0
- package/rules/stencil/ban-prefix.md +76 -0
- package/rules/stencil/decorators-context.md +61 -0
- package/rules/stencil/host-data-deprecated.md +73 -0
- package/rules/stencil/methods-must-be-public.md +69 -0
- package/rules/stencil/no-unused-watch.md +68 -0
- package/rules/stencil/own-methods-must-be-private.md +68 -0
- package/rules/stencil/own-props-must-be-private.md +60 -0
- package/rules/stencil/prefer-vdom-listener.md +67 -0
- package/rules/stencil/prop-readonly.md +63 -0
- package/rules/stencil/props-must-be-public.md +68 -0
- package/rules/stencil/required-jsdoc.md +66 -0
- package/rules/stencil/reserved-member-names.md +70 -0
- package/rules/stencil/strict-mutable.md +75 -0
- package/rules/stencil/tag-prefix.md +75 -0
- package/rules/ts/ban-ts-comment.md +64 -0
- package/rules/ts/no-array-constructor.md +58 -0
- package/rules/ts/no-duplicate-enum-values.md +65 -0
- package/rules/ts/no-empty-object-type.md +65 -0
- package/rules/ts/no-explicit-any.md +61 -0
- package/rules/ts/no-extra-non-null-assertion.md +50 -0
- package/rules/ts/no-misused-new.md +70 -0
- package/rules/ts/no-namespace.md +65 -0
- package/rules/ts/no-non-null-asserted-optional-chain.md +55 -0
- package/rules/ts/no-require-imports.md +54 -0
- package/rules/ts/no-this-alias.md +68 -0
- package/rules/ts/no-unnecessary-type-constraint.md +64 -0
- package/rules/ts/no-unsafe-declaration-merging.md +73 -0
- package/rules/ts/no-unsafe-function-type.md +57 -0
- package/rules/ts/no-unused-expressions.md +61 -0
- package/rules/ts/no-unused-vars.md +68 -0
- package/rules/ts/no-wrapper-object-types.md +49 -0
- package/rules/ts/prefer-as-const.md +47 -0
- package/rules/ts/prefer-namespace-keyword.md +63 -0
- package/rules/ts/triple-slash-reference.md +60 -0
- package/rules/ts/type-only-imports.md +57 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: js/prefer-rest-params
|
|
3
|
+
title: "Rest parameters instead of arguments"
|
|
4
|
+
languages: [javascript, jsx, typescript, tsx]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the parameter list has to be rewritten by hand"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [eslint/prefer-rest-params]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Functions take a rest parameter `...args` instead of reading `arguments`.
|
|
13
|
+
|
|
14
|
+
**Why:** `arguments` is not a real array, isn't available in arrow functions, and hides how many
|
|
15
|
+
arguments a function takes.
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
match:
|
|
19
|
+
kind: identifier
|
|
20
|
+
regex: ^arguments$
|
|
21
|
+
where:
|
|
22
|
+
$$MATCH: builtin
|
|
23
|
+
message: "Use a rest parameter (`...args`) instead of `arguments`"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## How to fix
|
|
27
|
+
|
|
28
|
+
1. Add a rest parameter `...args` to the function.
|
|
29
|
+
2. Replace each use of `arguments` with it.
|
|
30
|
+
|
|
31
|
+
## Examples
|
|
32
|
+
|
|
33
|
+
### JavaScript
|
|
34
|
+
|
|
35
|
+
#### Don't
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
function sum() {
|
|
39
|
+
return Array.from(arguments).reduce(add, 0);
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
#### Do
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
function sum(...numbers) {
|
|
47
|
+
return numbers.reduce(add, 0);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### JSX
|
|
52
|
+
|
|
53
|
+
#### Don't
|
|
54
|
+
|
|
55
|
+
```jsx
|
|
56
|
+
function sum() {
|
|
57
|
+
return Array.from(arguments).reduce(add, 0);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
#### Do
|
|
62
|
+
|
|
63
|
+
```jsx
|
|
64
|
+
function sum(...numbers) {
|
|
65
|
+
return numbers.reduce(add, 0);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### TypeScript
|
|
70
|
+
|
|
71
|
+
#### Don't
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
function sum() {
|
|
75
|
+
return Array.from(arguments).reduce(add, 0);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
#### Do
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
function sum(...numbers) {
|
|
83
|
+
return numbers.reduce(add, 0);
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### TSX
|
|
88
|
+
|
|
89
|
+
#### Don't
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
function sum() {
|
|
93
|
+
return Array.from(arguments).reduce(add, 0);
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
#### Do
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
function sum(...numbers) {
|
|
101
|
+
return numbers.reduce(add, 0);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: js/prefer-spread
|
|
3
|
+
title: "Spread instead of .apply()"
|
|
4
|
+
languages: [javascript, jsx, typescript, tsx]
|
|
5
|
+
fix: auto
|
|
6
|
+
stability: preview
|
|
7
|
+
ported_from: [eslint/prefer-spread]
|
|
8
|
+
since: 0.1.0
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
A function is called with spread arguments, `f(...args)`, instead of `f.apply(null, args)`.
|
|
12
|
+
|
|
13
|
+
**Why:** Spread says the same thing more directly, and doesn't need a `this` value.
|
|
14
|
+
|
|
15
|
+
```codelaw
|
|
16
|
+
match:
|
|
17
|
+
any:
|
|
18
|
+
- pattern: $F.apply(null, $ARGS)
|
|
19
|
+
- pattern: $F.apply(undefined, $ARGS)
|
|
20
|
+
constraints:
|
|
21
|
+
F: { kind: identifier }
|
|
22
|
+
message: "Use spread: `$F(...$ARGS)`"
|
|
23
|
+
fix: "$F(...$ARGS)"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
### JavaScript
|
|
29
|
+
|
|
30
|
+
#### Don't
|
|
31
|
+
|
|
32
|
+
```js
|
|
33
|
+
const max = Math.max.apply(null, values);
|
|
34
|
+
const min = least.apply(null, values);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
#### Do
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
const max = Math.max.apply(null, values);
|
|
41
|
+
const min = least(...values);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### JSX
|
|
45
|
+
|
|
46
|
+
#### Don't
|
|
47
|
+
|
|
48
|
+
```jsx
|
|
49
|
+
const max = Math.max.apply(null, values);
|
|
50
|
+
const min = least.apply(null, values);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
#### Do
|
|
54
|
+
|
|
55
|
+
```jsx
|
|
56
|
+
const max = Math.max.apply(null, values);
|
|
57
|
+
const min = least(...values);
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### TypeScript
|
|
61
|
+
|
|
62
|
+
#### Don't
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
const max = Math.max.apply(null, values);
|
|
66
|
+
const min = least.apply(null, values);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
#### Do
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
const max = Math.max.apply(null, values);
|
|
73
|
+
const min = least(...values);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### TSX
|
|
77
|
+
|
|
78
|
+
#### Don't
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
const max = Math.max.apply(null, values);
|
|
82
|
+
const min = least.apply(null, values);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
#### Do
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
const max = Math.max.apply(null, values);
|
|
89
|
+
const min = least(...values);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Differences from the source
|
|
93
|
+
|
|
94
|
+
Only `f.apply(null, args)` and `f.apply(undefined, args)` on a plain function name are checked;
|
|
95
|
+
method calls are left alone.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: js/preserve-caught-error
|
|
3
|
+
title: "A rethrown error keeps the caught one as its cause"
|
|
4
|
+
languages: [javascript, jsx, typescript, tsx]
|
|
5
|
+
fix: suggest
|
|
6
|
+
fix_reason: "the new error class must accept an options argument"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [eslint/preserve-caught-error]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A built-in error (`Error`, `TypeError` and the rest) thrown from a `catch` block passes the caught
|
|
13
|
+
error as `{ cause }`.
|
|
14
|
+
|
|
15
|
+
**Why:** Without the cause, the original error and its stack are lost.
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
match:
|
|
19
|
+
pattern: throw new $C($MSG);
|
|
20
|
+
inside:
|
|
21
|
+
kind: catch_clause
|
|
22
|
+
has: { field: parameter, pattern: $E }
|
|
23
|
+
stopBy:
|
|
24
|
+
any: [{kind: function_declaration}, {kind: function_expression}, {kind: arrow_function}, {kind: method_definition}, {kind: generator_function_declaration}, {kind: generator_function}]
|
|
25
|
+
constraints:
|
|
26
|
+
C: { regex: ^(Error|TypeError|RangeError|ReferenceError|SyntaxError|URIError|EvalError)$ }
|
|
27
|
+
MSG: { not: { kind: object } }
|
|
28
|
+
where:
|
|
29
|
+
$C: builtin
|
|
30
|
+
message: "Pass the caught error as the cause: `new $C($MSG, { cause: $E })`"
|
|
31
|
+
fix: "throw new $C($MSG, { cause: $E });"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Examples
|
|
35
|
+
|
|
36
|
+
### JavaScript
|
|
37
|
+
|
|
38
|
+
#### Don't
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
try {
|
|
42
|
+
load();
|
|
43
|
+
} catch (err) {
|
|
44
|
+
throw new Error("Load failed");
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
#### Do
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
try {
|
|
52
|
+
load();
|
|
53
|
+
} catch (err) {
|
|
54
|
+
throw new Error("Load failed", { cause: err });
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### JSX
|
|
59
|
+
|
|
60
|
+
#### Don't
|
|
61
|
+
|
|
62
|
+
```jsx
|
|
63
|
+
try {
|
|
64
|
+
load();
|
|
65
|
+
} catch (err) {
|
|
66
|
+
throw new Error("Load failed");
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
#### Do
|
|
71
|
+
|
|
72
|
+
```jsx
|
|
73
|
+
try {
|
|
74
|
+
load();
|
|
75
|
+
} catch (err) {
|
|
76
|
+
throw new Error("Load failed", { cause: err });
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### TypeScript
|
|
81
|
+
|
|
82
|
+
#### Don't
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
try {
|
|
86
|
+
load();
|
|
87
|
+
} catch (err) {
|
|
88
|
+
throw new Error("Load failed");
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### Do
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
try {
|
|
96
|
+
load();
|
|
97
|
+
} catch (err) {
|
|
98
|
+
throw new Error("Load failed", { cause: err });
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### TSX
|
|
103
|
+
|
|
104
|
+
#### Don't
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
try {
|
|
108
|
+
load();
|
|
109
|
+
} catch (err) {
|
|
110
|
+
throw new Error("Load failed");
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
#### Do
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
try {
|
|
118
|
+
load();
|
|
119
|
+
} catch (err) {
|
|
120
|
+
throw new Error("Load failed", { cause: err });
|
|
121
|
+
}
|
|
122
|
+
```
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: js/require-yield
|
|
3
|
+
title: "A generator function yields"
|
|
4
|
+
languages: [javascript, jsx, typescript, tsx]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "whether to yield or to drop the `*` needs the author"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [eslint/require-yield]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A non-empty generator function contains at least one `yield`.
|
|
13
|
+
|
|
14
|
+
**Why:** A generator without `yield` is either unfinished or should be a plain function.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
match:
|
|
18
|
+
any:
|
|
19
|
+
- kind: generator_function_declaration
|
|
20
|
+
- kind: generator_function
|
|
21
|
+
not:
|
|
22
|
+
any:
|
|
23
|
+
- has: { field: body, regex: '^\{\s*\}$' }
|
|
24
|
+
- has:
|
|
25
|
+
kind: yield_expression
|
|
26
|
+
stopBy:
|
|
27
|
+
any: [{kind: function_declaration}, {kind: function_expression}, {kind: arrow_function}, {kind: method_definition}, {kind: generator_function_declaration}, {kind: generator_function}]
|
|
28
|
+
message: "A generator that never yields is a plain function"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## How to fix
|
|
32
|
+
|
|
33
|
+
1. Add the `yield` the generator was meant to have, or remove the `*`.
|
|
34
|
+
|
|
35
|
+
## Examples
|
|
36
|
+
|
|
37
|
+
### JavaScript
|
|
38
|
+
|
|
39
|
+
#### Don't
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
function* ids() {
|
|
43
|
+
return 1;
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
#### Do
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
function* ids() {
|
|
51
|
+
yield 1;
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### JSX
|
|
56
|
+
|
|
57
|
+
#### Don't
|
|
58
|
+
|
|
59
|
+
```jsx
|
|
60
|
+
function* ids() {
|
|
61
|
+
return 1;
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
#### Do
|
|
66
|
+
|
|
67
|
+
```jsx
|
|
68
|
+
function* ids() {
|
|
69
|
+
yield 1;
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### TypeScript
|
|
74
|
+
|
|
75
|
+
#### Don't
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
function* ids() {
|
|
79
|
+
return 1;
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
#### Do
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
function* ids() {
|
|
87
|
+
yield 1;
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### TSX
|
|
92
|
+
|
|
93
|
+
#### Don't
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
function* ids() {
|
|
97
|
+
return 1;
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
#### Do
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
function* ids() {
|
|
105
|
+
yield 1;
|
|
106
|
+
}
|
|
107
|
+
```
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: js/use-isnan
|
|
3
|
+
title: "Test for NaN with Number.isNaN"
|
|
4
|
+
languages: [javascript, jsx, typescript, tsx]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the comparison's operator decides whether to negate"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [eslint/use-isnan]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Code tests for `NaN` with `Number.isNaN(x)`, never by comparing with `NaN`.
|
|
13
|
+
|
|
14
|
+
**Why:** `NaN` is not equal to anything, itself included, so `x === NaN` is always false.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
match:
|
|
18
|
+
kind: binary_expression
|
|
19
|
+
has:
|
|
20
|
+
field: operator
|
|
21
|
+
regex: ^(==|===|!=|!==|<|>|<=|>=)$
|
|
22
|
+
any:
|
|
23
|
+
- has: { field: left, regex: '^(Number\.)?NaN$' }
|
|
24
|
+
- has: { field: right, regex: '^(Number\.)?NaN$' }
|
|
25
|
+
message: "Nothing equals NaN, not even NaN; use Number.isNaN(x)"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## How to fix
|
|
29
|
+
|
|
30
|
+
1. Replace `x === NaN` or `x == NaN` with `Number.isNaN(x)`.
|
|
31
|
+
2. Replace `x !== NaN` or `x != NaN` with `!Number.isNaN(x)`.
|
|
32
|
+
|
|
33
|
+
## Examples
|
|
34
|
+
|
|
35
|
+
### JavaScript
|
|
36
|
+
|
|
37
|
+
#### Don't
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
if (price === NaN) {
|
|
41
|
+
reset();
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
#### Do
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
if (Number.isNaN(price)) {
|
|
49
|
+
reset();
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### JSX
|
|
54
|
+
|
|
55
|
+
#### Don't
|
|
56
|
+
|
|
57
|
+
```jsx
|
|
58
|
+
if (price === NaN) {
|
|
59
|
+
reset();
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
#### Do
|
|
64
|
+
|
|
65
|
+
```jsx
|
|
66
|
+
if (Number.isNaN(price)) {
|
|
67
|
+
reset();
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### TypeScript
|
|
72
|
+
|
|
73
|
+
#### Don't
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
if (price === NaN) {
|
|
77
|
+
reset();
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
#### Do
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
if (Number.isNaN(price)) {
|
|
85
|
+
reset();
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### TSX
|
|
90
|
+
|
|
91
|
+
#### Don't
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
if (price === NaN) {
|
|
95
|
+
reset();
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### Do
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
if (Number.isNaN(price)) {
|
|
103
|
+
reset();
|
|
104
|
+
}
|
|
105
|
+
```
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: js/valid-typeof
|
|
3
|
+
title: "typeof is compared with a type it can return"
|
|
4
|
+
languages: [javascript, jsx, typescript, tsx]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "which type was meant needs the author"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [eslint/valid-typeof]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
`typeof x` is compared only with a string it can return: `"undefined"`, `"object"`, `"boolean"`,
|
|
13
|
+
`"number"`, `"string"`, `"function"`, `"symbol"` or `"bigint"`.
|
|
14
|
+
|
|
15
|
+
**Why:** A misspelled type such as `"strnig"` makes the comparison always false.
|
|
16
|
+
|
|
17
|
+
```codelaw
|
|
18
|
+
match:
|
|
19
|
+
any:
|
|
20
|
+
- pattern: typeof $X == $S
|
|
21
|
+
- pattern: typeof $X === $S
|
|
22
|
+
- pattern: typeof $X != $S
|
|
23
|
+
- pattern: typeof $X !== $S
|
|
24
|
+
- pattern: $S == typeof $X
|
|
25
|
+
- pattern: $S === typeof $X
|
|
26
|
+
- pattern: $S != typeof $X
|
|
27
|
+
- pattern: $S !== typeof $X
|
|
28
|
+
constraints:
|
|
29
|
+
S:
|
|
30
|
+
kind: string
|
|
31
|
+
not: { regex: "^[\"'](undefined|object|boolean|number|string|function|symbol|bigint)[\"']$" }
|
|
32
|
+
message: "`typeof` never returns $S"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## How to fix
|
|
36
|
+
|
|
37
|
+
1. Correct the string to the type that was meant.
|
|
38
|
+
|
|
39
|
+
## Examples
|
|
40
|
+
|
|
41
|
+
### JavaScript
|
|
42
|
+
|
|
43
|
+
#### Don't
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
if (typeof name === "strnig") {
|
|
47
|
+
greet(name);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
#### Do
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
if (typeof name === "string") {
|
|
55
|
+
greet(name);
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### JSX
|
|
60
|
+
|
|
61
|
+
#### Don't
|
|
62
|
+
|
|
63
|
+
```jsx
|
|
64
|
+
if (typeof name === "strnig") {
|
|
65
|
+
greet(name);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
#### Do
|
|
70
|
+
|
|
71
|
+
```jsx
|
|
72
|
+
if (typeof name === "string") {
|
|
73
|
+
greet(name);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### TypeScript
|
|
78
|
+
|
|
79
|
+
#### Don't
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
if (typeof name === "strnig") {
|
|
83
|
+
greet(name);
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
#### Do
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
if (typeof name === "string") {
|
|
91
|
+
greet(name);
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### TSX
|
|
96
|
+
|
|
97
|
+
#### Don't
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
if (typeof name === "strnig") {
|
|
101
|
+
greet(name);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### Do
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
if (typeof name === "string") {
|
|
109
|
+
greet(name);
|
|
110
|
+
}
|
|
111
|
+
```
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: node/hashbang
|
|
3
|
+
title: "Commands start with a Node.js hashbang, and nothing else has one"
|
|
4
|
+
languages: [javascript, jsx]
|
|
5
|
+
fix: suggest
|
|
6
|
+
fix_reason: "removing the hashbang of a script someone runs directly (`./tool.js`) stops it running"
|
|
7
|
+
stability: preview
|
|
8
|
+
ported_from: [eslint-plugin-n/hashbang]
|
|
9
|
+
since: 0.1.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A file the nearest `package.json` names in `bin` starts with `#!/usr/bin/env node`; a file it doesn't name has no hashbang. Without a `package.json` above the file, nothing is checked.
|
|
13
|
+
|
|
14
|
+
**Why:** npm links a `bin` entry as an executable, which the shell runs through its hashbang: without one the command fails, or runs under the wrong interpreter. A hashbang on a library file is noise that suggests it is a command.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: node/hashbang
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. On a command `bin` names, make the first line `#!/usr/bin/env node`.
|
|
23
|
+
2. On any other file, remove the hashbang, or add the file to `bin` if it is a command.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### JavaScript
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
// package.json
|
|
33
|
+
{ "name": "tool", "bin": { "tool": "./bin/tool.js" } }
|
|
34
|
+
// bin/tool.js
|
|
35
|
+
console.log("hello");
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### Do
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
// package.json
|
|
42
|
+
{ "name": "tool", "bin": { "tool": "./bin/tool.js" } }
|
|
43
|
+
// bin/tool.js
|
|
44
|
+
#!/usr/bin/env node
|
|
45
|
+
console.log("hello");
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### JSX
|
|
49
|
+
|
|
50
|
+
#### Don't
|
|
51
|
+
|
|
52
|
+
```jsx
|
|
53
|
+
// package.json
|
|
54
|
+
{ "name": "tool", "bin": "./cli.jsx" }
|
|
55
|
+
// lib/view.jsx
|
|
56
|
+
#!/usr/bin/env node
|
|
57
|
+
export const View = () => <p>hello</p>;
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
#### Do
|
|
61
|
+
|
|
62
|
+
```jsx
|
|
63
|
+
// package.json
|
|
64
|
+
{ "name": "tool", "bin": "./cli.jsx" }
|
|
65
|
+
// lib/view.jsx
|
|
66
|
+
export const View = () => <p>hello</p>;
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Differences from the source
|
|
70
|
+
|
|
71
|
+
TypeScript sources are not checked: eslint-plugin-n maps them to their built JavaScript through `convertPath`, which this rule has no option for yet. The source's checks for a byte-order mark and CRLF line endings in a command are not ported, and there is no `additionalExecutables` or `executableMap` option.
|