eslint 10.2.1 → 10.4.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/README.md +3 -3
- package/lib/config/config-loader.js +1 -1
- package/lib/config-api.js +7 -1
- package/lib/eslint/eslint.js +29 -6
- package/lib/linter/code-path-analysis/code-path-analyzer.js +7 -7
- package/lib/linter/code-path-analysis/debug-helpers.js +12 -1
- package/lib/linter/code-path-analysis/id-generator.js +1 -2
- package/lib/rules/capitalized-comments.js +3 -1
- package/lib/rules/class-methods-use-this.js +1 -2
- package/lib/rules/default-param-last.js +1 -2
- package/lib/rules/eqeqeq.js +3 -1
- package/lib/rules/for-direction.js +55 -11
- package/lib/rules/func-name-matching.js +2 -0
- package/lib/rules/func-style.js +1 -2
- package/lib/rules/init-declarations.js +7 -8
- package/lib/rules/logical-assignment-operators.js +4 -1
- package/lib/rules/max-classes-per-file.js +4 -2
- package/lib/rules/max-depth.js +3 -0
- package/lib/rules/max-lines-per-function.js +3 -0
- package/lib/rules/max-lines.js +3 -0
- package/lib/rules/max-nested-callbacks.js +3 -0
- package/lib/rules/max-params.js +4 -2
- package/lib/rules/max-statements.js +3 -0
- package/lib/rules/no-array-constructor.js +1 -2
- package/lib/rules/no-dupe-class-members.js +1 -2
- package/lib/rules/no-duplicate-imports.js +1 -2
- package/lib/rules/no-empty-function.js +1 -2
- package/lib/rules/no-invalid-this.js +1 -2
- package/lib/rules/no-loop-func.js +1 -2
- package/lib/rules/no-loss-of-precision.js +1 -2
- package/lib/rules/no-magic-numbers.js +29 -24
- package/lib/rules/no-restricted-exports.js +8 -8
- package/lib/rules/no-restricted-globals.js +1 -2
- package/lib/rules/no-restricted-imports.js +1 -2
- package/lib/rules/no-restricted-properties.js +2 -0
- package/lib/rules/no-restricted-syntax.js +2 -0
- package/lib/rules/no-shadow.js +1 -2
- package/lib/rules/no-unassigned-vars.js +1 -2
- package/lib/rules/no-unused-expressions.js +1 -2
- package/lib/rules/no-unused-private-class-members.js +201 -1
- package/lib/rules/no-unused-vars.js +50 -53
- package/lib/rules/no-use-before-define.js +1 -2
- package/lib/rules/no-useless-concat.js +2 -2
- package/lib/rules/no-useless-constructor.js +4 -4
- package/lib/rules/no-var.js +1 -2
- package/lib/rules/object-shorthand.js +3 -1
- package/lib/rules/one-var.js +3 -1
- package/lib/rules/prefer-arrow-callback.js +1 -2
- package/lib/rules/require-await.js +6 -4
- package/lib/rules/utils/ast-utils.js +36 -4
- package/lib/types/config-api.d.ts +2 -1
- package/package.json +8 -7
|
@@ -91,11 +91,10 @@ function isAncestorTSIndexedAccessType(node) {
|
|
|
91
91
|
module.exports = {
|
|
92
92
|
meta: {
|
|
93
93
|
type: "suggestion",
|
|
94
|
-
dialects: ["typescript", "javascript"],
|
|
95
|
-
language: "javascript",
|
|
96
94
|
|
|
97
95
|
docs: {
|
|
98
96
|
description: "Disallow magic numbers",
|
|
97
|
+
dialects: ["JavaScript", "TypeScript"],
|
|
99
98
|
recommended: false,
|
|
100
99
|
frozen: true,
|
|
101
100
|
url: "https://eslint.org/docs/latest/rules/no-magic-numbers",
|
|
@@ -107,11 +106,9 @@ module.exports = {
|
|
|
107
106
|
properties: {
|
|
108
107
|
detectObjects: {
|
|
109
108
|
type: "boolean",
|
|
110
|
-
default: false,
|
|
111
109
|
},
|
|
112
110
|
enforceConst: {
|
|
113
111
|
type: "boolean",
|
|
114
|
-
default: false,
|
|
115
112
|
},
|
|
116
113
|
ignore: {
|
|
117
114
|
type: "array",
|
|
@@ -128,37 +125,45 @@ module.exports = {
|
|
|
128
125
|
},
|
|
129
126
|
ignoreArrayIndexes: {
|
|
130
127
|
type: "boolean",
|
|
131
|
-
default: false,
|
|
132
128
|
},
|
|
133
129
|
ignoreDefaultValues: {
|
|
134
130
|
type: "boolean",
|
|
135
|
-
default: false,
|
|
136
131
|
},
|
|
137
132
|
ignoreClassFieldInitialValues: {
|
|
138
133
|
type: "boolean",
|
|
139
|
-
default: false,
|
|
140
134
|
},
|
|
141
135
|
ignoreEnums: {
|
|
142
136
|
type: "boolean",
|
|
143
|
-
default: false,
|
|
144
137
|
},
|
|
145
138
|
ignoreNumericLiteralTypes: {
|
|
146
139
|
type: "boolean",
|
|
147
|
-
default: false,
|
|
148
140
|
},
|
|
149
141
|
ignoreReadonlyClassProperties: {
|
|
150
142
|
type: "boolean",
|
|
151
|
-
default: false,
|
|
152
143
|
},
|
|
153
144
|
ignoreTypeIndexes: {
|
|
154
145
|
type: "boolean",
|
|
155
|
-
default: false,
|
|
156
146
|
},
|
|
157
147
|
},
|
|
158
148
|
additionalProperties: false,
|
|
159
149
|
},
|
|
160
150
|
],
|
|
161
151
|
|
|
152
|
+
defaultOptions: [
|
|
153
|
+
{
|
|
154
|
+
detectObjects: false,
|
|
155
|
+
enforceConst: false,
|
|
156
|
+
ignore: [],
|
|
157
|
+
ignoreArrayIndexes: false,
|
|
158
|
+
ignoreDefaultValues: false,
|
|
159
|
+
ignoreClassFieldInitialValues: false,
|
|
160
|
+
ignoreEnums: false,
|
|
161
|
+
ignoreNumericLiteralTypes: false,
|
|
162
|
+
ignoreReadonlyClassProperties: false,
|
|
163
|
+
ignoreTypeIndexes: false,
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
|
|
162
167
|
messages: {
|
|
163
168
|
useConst: "Number constants declarations must use 'const'.",
|
|
164
169
|
noMagic: "No magic number: {{raw}}.",
|
|
@@ -166,19 +171,19 @@ module.exports = {
|
|
|
166
171
|
},
|
|
167
172
|
|
|
168
173
|
create(context) {
|
|
169
|
-
const
|
|
170
|
-
detectObjects
|
|
171
|
-
enforceConst
|
|
172
|
-
ignore
|
|
173
|
-
ignoreArrayIndexes
|
|
174
|
-
ignoreDefaultValues
|
|
175
|
-
ignoreClassFieldInitialValues
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
174
|
+
const {
|
|
175
|
+
detectObjects,
|
|
176
|
+
enforceConst,
|
|
177
|
+
ignore: rawIgnore,
|
|
178
|
+
ignoreArrayIndexes,
|
|
179
|
+
ignoreDefaultValues,
|
|
180
|
+
ignoreClassFieldInitialValues,
|
|
181
|
+
ignoreEnums,
|
|
182
|
+
ignoreNumericLiteralTypes,
|
|
183
|
+
ignoreReadonlyClassProperties,
|
|
184
|
+
ignoreTypeIndexes,
|
|
185
|
+
} = context.options[0];
|
|
186
|
+
const ignore = new Set(rawIgnore.map(normalizeIgnoreValue));
|
|
182
187
|
|
|
183
188
|
const okTypes = detectObjects
|
|
184
189
|
? []
|
|
@@ -92,6 +92,8 @@ module.exports = {
|
|
|
92
92
|
},
|
|
93
93
|
],
|
|
94
94
|
|
|
95
|
+
defaultOptions: [{}],
|
|
96
|
+
|
|
95
97
|
messages: {
|
|
96
98
|
restrictedNamed:
|
|
97
99
|
"'{{name}}' is restricted from being used as an exported name.",
|
|
@@ -100,14 +102,12 @@ module.exports = {
|
|
|
100
102
|
},
|
|
101
103
|
|
|
102
104
|
create(context) {
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const restrictDefaultExports =
|
|
110
|
-
context.options[0] && context.options[0].restrictDefaultExports;
|
|
105
|
+
const {
|
|
106
|
+
restrictedNamedExports,
|
|
107
|
+
restrictedNamedExportsPattern: restrictedNamePattern,
|
|
108
|
+
restrictDefaultExports,
|
|
109
|
+
} = context.options[0];
|
|
110
|
+
const restrictedNames = new Set(restrictedNamedExports);
|
|
111
111
|
const sourceCode = context.sourceCode;
|
|
112
112
|
|
|
113
113
|
/**
|
|
@@ -53,12 +53,11 @@ const arrayOfGlobals = {
|
|
|
53
53
|
/** @type {import('../types').Rule.RuleModule} */
|
|
54
54
|
module.exports = {
|
|
55
55
|
meta: {
|
|
56
|
-
dialects: ["javascript", "typescript"],
|
|
57
|
-
language: "javascript",
|
|
58
56
|
type: "suggestion",
|
|
59
57
|
|
|
60
58
|
docs: {
|
|
61
59
|
description: "Disallow specified global variables",
|
|
60
|
+
dialects: ["JavaScript", "TypeScript"],
|
|
62
61
|
recommended: false,
|
|
63
62
|
url: "https://eslint.org/docs/latest/rules/no-restricted-globals",
|
|
64
63
|
},
|
|
@@ -171,11 +171,10 @@ const arrayOfStringsOrObjectPatterns = {
|
|
|
171
171
|
module.exports = {
|
|
172
172
|
meta: {
|
|
173
173
|
type: "suggestion",
|
|
174
|
-
dialects: ["typescript", "javascript"],
|
|
175
|
-
language: "javascript",
|
|
176
174
|
|
|
177
175
|
docs: {
|
|
178
176
|
description: "Disallow specified modules when loaded by `import`",
|
|
177
|
+
dialects: ["JavaScript", "TypeScript"],
|
|
179
178
|
recommended: false,
|
|
180
179
|
url: "https://eslint.org/docs/latest/rules/no-restricted-imports",
|
|
181
180
|
},
|
package/lib/rules/no-shadow.js
CHANGED
|
@@ -55,8 +55,6 @@ const ALLOWED_FUNCTION_VARIABLE_DEF_TYPES = new Set([
|
|
|
55
55
|
module.exports = {
|
|
56
56
|
meta: {
|
|
57
57
|
type: "suggestion",
|
|
58
|
-
dialects: ["typescript", "javascript"],
|
|
59
|
-
language: "javascript",
|
|
60
58
|
|
|
61
59
|
defaultOptions: [
|
|
62
60
|
{
|
|
@@ -72,6 +70,7 @@ module.exports = {
|
|
|
72
70
|
docs: {
|
|
73
71
|
description:
|
|
74
72
|
"Disallow variable declarations from shadowing variables declared in the outer scope",
|
|
73
|
+
dialects: ["JavaScript", "TypeScript"],
|
|
75
74
|
recommended: false,
|
|
76
75
|
url: "https://eslint.org/docs/latest/rules/no-shadow",
|
|
77
76
|
},
|
|
@@ -12,12 +12,11 @@
|
|
|
12
12
|
module.exports = {
|
|
13
13
|
meta: {
|
|
14
14
|
type: "problem",
|
|
15
|
-
dialects: ["typescript", "javascript"],
|
|
16
|
-
language: "javascript",
|
|
17
15
|
|
|
18
16
|
docs: {
|
|
19
17
|
description:
|
|
20
18
|
"Disallow `let` or `var` variables that are read but never assigned",
|
|
19
|
+
dialects: ["JavaScript", "TypeScript"],
|
|
21
20
|
recommended: true,
|
|
22
21
|
url: "https://eslint.org/docs/latest/rules/no-unassigned-vars",
|
|
23
22
|
},
|
|
@@ -29,12 +29,11 @@ function alwaysFalse() {
|
|
|
29
29
|
/** @type {import('../types').Rule.RuleModule} */
|
|
30
30
|
module.exports = {
|
|
31
31
|
meta: {
|
|
32
|
-
dialects: ["javascript", "typescript"],
|
|
33
|
-
language: "javascript",
|
|
34
32
|
type: "suggestion",
|
|
35
33
|
|
|
36
34
|
docs: {
|
|
37
35
|
description: "Disallow unused expressions",
|
|
36
|
+
dialects: ["JavaScript", "TypeScript"],
|
|
38
37
|
recommended: false,
|
|
39
38
|
url: "https://eslint.org/docs/latest/rules/no-unused-expressions",
|
|
40
39
|
},
|
|
@@ -5,6 +5,12 @@
|
|
|
5
5
|
|
|
6
6
|
"use strict";
|
|
7
7
|
|
|
8
|
+
//------------------------------------------------------------------------------
|
|
9
|
+
// Requirements
|
|
10
|
+
//------------------------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
const astUtils = require("./utils/ast-utils");
|
|
13
|
+
|
|
8
14
|
//------------------------------------------------------------------------------
|
|
9
15
|
// Rule Definition
|
|
10
16
|
//------------------------------------------------------------------------------
|
|
@@ -13,6 +19,7 @@
|
|
|
13
19
|
module.exports = {
|
|
14
20
|
meta: {
|
|
15
21
|
type: "problem",
|
|
22
|
+
hasSuggestions: true,
|
|
16
23
|
|
|
17
24
|
docs: {
|
|
18
25
|
description: "Disallow unused private class members",
|
|
@@ -25,12 +32,168 @@ module.exports = {
|
|
|
25
32
|
messages: {
|
|
26
33
|
unusedPrivateClassMember:
|
|
27
34
|
"'{{classMemberName}}' is defined but never used.",
|
|
35
|
+
removeUnusedPrivateClassMember:
|
|
36
|
+
"Remove unused private class member '{{classMemberName}}'.",
|
|
28
37
|
},
|
|
29
38
|
},
|
|
30
39
|
|
|
31
40
|
create(context) {
|
|
41
|
+
const sourceCode = context.sourceCode;
|
|
32
42
|
const trackedClasses = [];
|
|
33
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Gets the start index of the line that contains a given token or node.
|
|
46
|
+
* @param {ASTNode|Token|Comment} nodeOrToken The token or node to check
|
|
47
|
+
* @returns {number} The line start index
|
|
48
|
+
*/
|
|
49
|
+
function getLineStartIndex(nodeOrToken) {
|
|
50
|
+
return nodeOrToken.range[0] - nodeOrToken.loc.start.column;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Checks whether a token or node starts on its own line, preceded only by whitespace.
|
|
55
|
+
* @param {ASTNode|Token|Comment} nodeOrToken The token or node to check
|
|
56
|
+
* @returns {boolean} Whether the token or node starts on its own line
|
|
57
|
+
*/
|
|
58
|
+
function startsOnOwnLine(nodeOrToken) {
|
|
59
|
+
return (
|
|
60
|
+
sourceCode.getTokenBefore(nodeOrToken, {
|
|
61
|
+
includeComments: true,
|
|
62
|
+
}).loc.end.line !== nodeOrToken.loc.start.line
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Gets leading comments that are directly attached to a class member.
|
|
68
|
+
* @param {ASTNode} classMemberNode The class member node
|
|
69
|
+
* @returns {Comment[]} Leading comments to remove with the member
|
|
70
|
+
*/
|
|
71
|
+
function getLeadingComments(classMemberNode) {
|
|
72
|
+
const commentsBefore =
|
|
73
|
+
sourceCode.getCommentsBefore(classMemberNode);
|
|
74
|
+
const lastNonLeadingCommentIndex = commentsBefore.findLastIndex(
|
|
75
|
+
(comment, index, self) => {
|
|
76
|
+
const next =
|
|
77
|
+
index < self.length - 1
|
|
78
|
+
? self[index + 1]
|
|
79
|
+
: classMemberNode;
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
!startsOnOwnLine(comment) ||
|
|
83
|
+
next.loc.start.line - comment.loc.end.line > 1
|
|
84
|
+
);
|
|
85
|
+
},
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
return commentsBefore.slice(lastNonLeadingCommentIndex + 1);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Checks whether a class member shares its line with another token.
|
|
93
|
+
* @param {ASTNode} classMemberNode The class member node
|
|
94
|
+
* @returns {boolean} Whether the member shares its line with another token
|
|
95
|
+
*/
|
|
96
|
+
function sharesLineWithAnotherToken(classMemberNode) {
|
|
97
|
+
const previousToken = sourceCode.getTokenBefore(classMemberNode);
|
|
98
|
+
const nextToken = sourceCode.getTokenAfter(classMemberNode);
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
previousToken.loc.end.line === classMemberNode.loc.start.line ||
|
|
102
|
+
nextToken.loc.start.line === classMemberNode.loc.end.line
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Gets trailing comments that are directly attached to a class member.
|
|
108
|
+
* Same-line trailing comments are preserved when another token shares
|
|
109
|
+
* the line, because the comment might describe the remaining code rather
|
|
110
|
+
* than the unused member alone.
|
|
111
|
+
* @param {ASTNode} classMemberNode The class member node
|
|
112
|
+
* @returns {Comment[]} Trailing comments to remove with the member
|
|
113
|
+
*/
|
|
114
|
+
function getTrailingComments(classMemberNode) {
|
|
115
|
+
if (sharesLineWithAnotherToken(classMemberNode)) {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return sourceCode
|
|
120
|
+
.getCommentsAfter(classMemberNode)
|
|
121
|
+
.filter(
|
|
122
|
+
comment =>
|
|
123
|
+
comment.loc.start.line === classMemberNode.loc.end.line,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Gets the token after which a semicolon should be inserted when removing a class member.
|
|
129
|
+
* @param {ASTNode} classMemberNode The member that would be removed
|
|
130
|
+
* @returns {Token|null} The token after which a semicolon should be inserted, or null if no semicolon is needed
|
|
131
|
+
*/
|
|
132
|
+
function getSemicolonInsertionToken(classMemberNode) {
|
|
133
|
+
const nextToken = sourceCode.getTokenAfter(classMemberNode);
|
|
134
|
+
|
|
135
|
+
if (
|
|
136
|
+
astUtils.canContinueExpressionInClassBody(nextToken) &&
|
|
137
|
+
astUtils.needsPrecedingSemicolon(sourceCode, classMemberNode)
|
|
138
|
+
) {
|
|
139
|
+
return sourceCode.getTokenBefore(classMemberNode);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Gets the replacement range for removing an unused class member.
|
|
147
|
+
* @param {ASTNode} classMemberNode The member that would be removed
|
|
148
|
+
* @returns {number[]} The text range to remove
|
|
149
|
+
*/
|
|
150
|
+
function getMemberRemovalRange(classMemberNode) {
|
|
151
|
+
const leadingComments = getLeadingComments(classMemberNode);
|
|
152
|
+
const trailingComments = getTrailingComments(classMemberNode);
|
|
153
|
+
const shouldRemoveLeadingComments =
|
|
154
|
+
leadingComments.length > 0 &&
|
|
155
|
+
!sharesLineWithAnotherToken(classMemberNode);
|
|
156
|
+
const lastItemToRemove =
|
|
157
|
+
trailingComments.length > 0
|
|
158
|
+
? trailingComments.at(-1)
|
|
159
|
+
: classMemberNode;
|
|
160
|
+
|
|
161
|
+
const previousToken = sourceCode.getTokenBefore(classMemberNode);
|
|
162
|
+
const nextToken = sourceCode.getTokenAfter(lastItemToRemove, {
|
|
163
|
+
includeComments: true,
|
|
164
|
+
});
|
|
165
|
+
const nextTokenStartsOnNewLine =
|
|
166
|
+
nextToken.loc.start.line > lastItemToRemove.loc.end.line;
|
|
167
|
+
const shouldRemoveOwnLine =
|
|
168
|
+
!shouldRemoveLeadingComments &&
|
|
169
|
+
startsOnOwnLine(classMemberNode) &&
|
|
170
|
+
nextTokenStartsOnNewLine;
|
|
171
|
+
let start = classMemberNode.range[0];
|
|
172
|
+
let end = lastItemToRemove.range[1];
|
|
173
|
+
|
|
174
|
+
if (shouldRemoveLeadingComments) {
|
|
175
|
+
start = nextTokenStartsOnNewLine
|
|
176
|
+
? getLineStartIndex(leadingComments[0])
|
|
177
|
+
: leadingComments[0].range[0];
|
|
178
|
+
end = nextTokenStartsOnNewLine
|
|
179
|
+
? getLineStartIndex(nextToken)
|
|
180
|
+
: nextToken.range[0];
|
|
181
|
+
} else if (shouldRemoveOwnLine) {
|
|
182
|
+
start = getLineStartIndex(classMemberNode);
|
|
183
|
+
end = getLineStartIndex(nextToken);
|
|
184
|
+
} else if (
|
|
185
|
+
previousToken.loc.end.line === classMemberNode.loc.start.line
|
|
186
|
+
) {
|
|
187
|
+
start = previousToken.range[1];
|
|
188
|
+
} else if (
|
|
189
|
+
nextToken.loc.start.line === lastItemToRemove.loc.end.line
|
|
190
|
+
) {
|
|
191
|
+
end = nextToken.range[0];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return [start, end];
|
|
195
|
+
}
|
|
196
|
+
|
|
34
197
|
/**
|
|
35
198
|
* Check whether the current node is in a write only assignment.
|
|
36
199
|
* @param {ASTNode} privateIdentifierNode Node referring to a private identifier
|
|
@@ -86,6 +249,7 @@ module.exports = {
|
|
|
86
249
|
if (bodyMember.key.type === "PrivateIdentifier") {
|
|
87
250
|
privateMembers.set(bodyMember.key.name, {
|
|
88
251
|
declaredNode: bodyMember,
|
|
252
|
+
hasReference: false,
|
|
89
253
|
isAccessor:
|
|
90
254
|
bodyMember.type === "MethodDefinition" &&
|
|
91
255
|
(bodyMember.kind === "set" ||
|
|
@@ -128,6 +292,8 @@ module.exports = {
|
|
|
128
292
|
return;
|
|
129
293
|
}
|
|
130
294
|
|
|
295
|
+
memberDefinition.hasReference = true;
|
|
296
|
+
|
|
131
297
|
/*
|
|
132
298
|
* Any usage of an accessor is considered a read, as the getter/setter can have
|
|
133
299
|
* side-effects in its definition.
|
|
@@ -199,11 +365,12 @@ module.exports = {
|
|
|
199
365
|
|
|
200
366
|
for (const [
|
|
201
367
|
classMemberName,
|
|
202
|
-
{ declaredNode, isUsed },
|
|
368
|
+
{ declaredNode, hasReference, isUsed },
|
|
203
369
|
] of unusedPrivateMembers.entries()) {
|
|
204
370
|
if (isUsed) {
|
|
205
371
|
continue;
|
|
206
372
|
}
|
|
373
|
+
|
|
207
374
|
context.report({
|
|
208
375
|
node: declaredNode,
|
|
209
376
|
loc: declaredNode.key.loc,
|
|
@@ -211,6 +378,39 @@ module.exports = {
|
|
|
211
378
|
data: {
|
|
212
379
|
classMemberName: `#${classMemberName}`,
|
|
213
380
|
},
|
|
381
|
+
suggest: [
|
|
382
|
+
{
|
|
383
|
+
messageId: "removeUnusedPrivateClassMember",
|
|
384
|
+
data: {
|
|
385
|
+
classMemberName: `#${classMemberName}`,
|
|
386
|
+
},
|
|
387
|
+
*fix(fixer) {
|
|
388
|
+
if (hasReference) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const removalRange =
|
|
393
|
+
getMemberRemovalRange(declaredNode);
|
|
394
|
+
const semicolonInsertionToken =
|
|
395
|
+
getSemicolonInsertionToken(
|
|
396
|
+
declaredNode,
|
|
397
|
+
);
|
|
398
|
+
const removalFix = fixer.replaceTextRange(
|
|
399
|
+
removalRange,
|
|
400
|
+
"",
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
yield removalFix;
|
|
404
|
+
|
|
405
|
+
if (semicolonInsertionToken) {
|
|
406
|
+
yield fixer.insertTextAfter(
|
|
407
|
+
semicolonInsertionToken,
|
|
408
|
+
";",
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
],
|
|
214
414
|
});
|
|
215
415
|
}
|
|
216
416
|
},
|
|
@@ -42,6 +42,20 @@ const astUtils = require("./utils/ast-utils");
|
|
|
42
42
|
* @property {string} additional Any additional info to be appended at the end.
|
|
43
43
|
*/
|
|
44
44
|
|
|
45
|
+
//------------------------------------------------------------------------------
|
|
46
|
+
// Helpers
|
|
47
|
+
//------------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
const DEFAULT_OPTIONS = {
|
|
50
|
+
vars: "all",
|
|
51
|
+
args: "after-used",
|
|
52
|
+
ignoreRestSiblings: false,
|
|
53
|
+
caughtErrors: "all",
|
|
54
|
+
ignoreClassWithStaticInitBlock: false,
|
|
55
|
+
ignoreUsingDeclarations: false,
|
|
56
|
+
reportUsedIgnorePattern: false,
|
|
57
|
+
};
|
|
58
|
+
|
|
45
59
|
//------------------------------------------------------------------------------
|
|
46
60
|
// Rule Definition
|
|
47
61
|
//------------------------------------------------------------------------------
|
|
@@ -108,6 +122,8 @@ module.exports = {
|
|
|
108
122
|
},
|
|
109
123
|
],
|
|
110
124
|
|
|
125
|
+
defaultOptions: [DEFAULT_OPTIONS],
|
|
126
|
+
|
|
111
127
|
messages: {
|
|
112
128
|
unusedVar:
|
|
113
129
|
"'{{varName}}' is {{action}} but never used{{additional}}.",
|
|
@@ -123,65 +139,46 @@ module.exports = {
|
|
|
123
139
|
const REST_PROPERTY_TYPE =
|
|
124
140
|
/^(?:RestElement|(?:Experimental)?RestProperty)$/u;
|
|
125
141
|
|
|
126
|
-
|
|
127
|
-
vars: "all",
|
|
128
|
-
args: "after-used",
|
|
129
|
-
ignoreRestSiblings: false,
|
|
130
|
-
caughtErrors: "all",
|
|
131
|
-
ignoreClassWithStaticInitBlock: false,
|
|
132
|
-
ignoreUsingDeclarations: false,
|
|
133
|
-
reportUsedIgnorePattern: false,
|
|
134
|
-
};
|
|
142
|
+
let config;
|
|
135
143
|
|
|
136
144
|
const firstOption = context.options[0];
|
|
137
145
|
|
|
138
|
-
if (firstOption) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
firstOption.caughtErrors || config.caughtErrors;
|
|
148
|
-
config.ignoreClassWithStaticInitBlock =
|
|
149
|
-
firstOption.ignoreClassWithStaticInitBlock ||
|
|
150
|
-
config.ignoreClassWithStaticInitBlock;
|
|
151
|
-
config.ignoreUsingDeclarations =
|
|
152
|
-
firstOption.ignoreUsingDeclarations ||
|
|
153
|
-
config.ignoreUsingDeclarations;
|
|
154
|
-
config.reportUsedIgnorePattern =
|
|
155
|
-
firstOption.reportUsedIgnorePattern ||
|
|
156
|
-
config.reportUsedIgnorePattern;
|
|
157
|
-
|
|
158
|
-
if (firstOption.varsIgnorePattern) {
|
|
159
|
-
config.varsIgnorePattern = new RegExp(
|
|
160
|
-
firstOption.varsIgnorePattern,
|
|
161
|
-
"u",
|
|
162
|
-
);
|
|
163
|
-
}
|
|
146
|
+
if (typeof firstOption === "string") {
|
|
147
|
+
config = {
|
|
148
|
+
...DEFAULT_OPTIONS,
|
|
149
|
+
vars: firstOption,
|
|
150
|
+
};
|
|
151
|
+
} else {
|
|
152
|
+
config = {
|
|
153
|
+
...firstOption,
|
|
154
|
+
};
|
|
164
155
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
156
|
+
if (firstOption.varsIgnorePattern) {
|
|
157
|
+
config.varsIgnorePattern = new RegExp(
|
|
158
|
+
firstOption.varsIgnorePattern,
|
|
159
|
+
"u",
|
|
160
|
+
);
|
|
161
|
+
}
|
|
171
162
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
163
|
+
if (firstOption.argsIgnorePattern) {
|
|
164
|
+
config.argsIgnorePattern = new RegExp(
|
|
165
|
+
firstOption.argsIgnorePattern,
|
|
166
|
+
"u",
|
|
167
|
+
);
|
|
168
|
+
}
|
|
178
169
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
170
|
+
if (firstOption.caughtErrorsIgnorePattern) {
|
|
171
|
+
config.caughtErrorsIgnorePattern = new RegExp(
|
|
172
|
+
firstOption.caughtErrorsIgnorePattern,
|
|
173
|
+
"u",
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (firstOption.destructuredArrayIgnorePattern) {
|
|
178
|
+
config.destructuredArrayIgnorePattern = new RegExp(
|
|
179
|
+
firstOption.destructuredArrayIgnorePattern,
|
|
180
|
+
"u",
|
|
181
|
+
);
|
|
185
182
|
}
|
|
186
183
|
}
|
|
187
184
|
|
|
@@ -276,13 +276,12 @@ function isClassRefInClassDecorator(variable, reference) {
|
|
|
276
276
|
/** @type {import('../types').Rule.RuleModule} */
|
|
277
277
|
module.exports = {
|
|
278
278
|
meta: {
|
|
279
|
-
dialects: ["javascript", "typescript"],
|
|
280
|
-
language: "javascript",
|
|
281
279
|
type: "problem",
|
|
282
280
|
|
|
283
281
|
docs: {
|
|
284
282
|
description:
|
|
285
283
|
"Disallow the use of variables before they are defined",
|
|
284
|
+
dialects: ["JavaScript", "TypeScript"],
|
|
286
285
|
recommended: false,
|
|
287
286
|
url: "https://eslint.org/docs/latest/rules/no-use-before-define",
|
|
288
287
|
},
|
|
@@ -33,7 +33,7 @@ function isConcatOperatorToken(token) {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
36
|
+
* Gets the right most node on the left side of a BinaryExpression with + operator.
|
|
37
37
|
* @param {ASTNode} node A BinaryExpression node to check.
|
|
38
38
|
* @returns {ASTNode} node
|
|
39
39
|
*/
|
|
@@ -47,7 +47,7 @@ function getLeft(node) {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
|
-
*
|
|
50
|
+
* Gets the left most node on the right side of a BinaryExpression with + operator.
|
|
51
51
|
* @param {ASTNode} node A BinaryExpression node to check.
|
|
52
52
|
* @returns {ASTNode} node
|
|
53
53
|
*/
|
|
@@ -164,12 +164,11 @@ function isRedundantSuperCall(body, ctorParams) {
|
|
|
164
164
|
/** @type {import('../types').Rule.RuleModule} */
|
|
165
165
|
module.exports = {
|
|
166
166
|
meta: {
|
|
167
|
-
dialects: ["javascript", "typescript"],
|
|
168
|
-
language: "javascript",
|
|
169
167
|
type: "suggestion",
|
|
170
168
|
|
|
171
169
|
docs: {
|
|
172
170
|
description: "Disallow unnecessary constructors",
|
|
171
|
+
dialects: ["JavaScript", "TypeScript"],
|
|
173
172
|
recommended: false,
|
|
174
173
|
url: "https://eslint.org/docs/latest/rules/no-useless-constructor",
|
|
175
174
|
},
|
|
@@ -237,8 +236,9 @@ module.exports = {
|
|
|
237
236
|
const nextToken =
|
|
238
237
|
sourceCode.getTokenAfter(node);
|
|
239
238
|
const addSemiColon =
|
|
240
|
-
|
|
241
|
-
|
|
239
|
+
astUtils.canContinueExpressionInClassBody(
|
|
240
|
+
nextToken,
|
|
241
|
+
) &&
|
|
242
242
|
astUtils.needsPrecedingSemicolon(
|
|
243
243
|
sourceCode,
|
|
244
244
|
node,
|