eslint 8.57.0 → 9.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/README.md +31 -28
- package/bin/eslint.js +4 -3
- package/conf/ecma-version.js +16 -0
- package/conf/globals.js +1 -0
- package/conf/rule-type-list.json +3 -1
- package/lib/api.js +7 -11
- package/lib/cli-engine/cli-engine.js +14 -3
- package/lib/cli-engine/formatters/formatters-meta.json +1 -29
- package/lib/cli-engine/lint-result-cache.js +2 -2
- package/lib/cli.js +115 -36
- package/lib/config/default-config.js +3 -0
- package/lib/config/flat-config-array.js +110 -24
- package/lib/config/flat-config-helpers.js +41 -20
- package/lib/config/flat-config-schema.js +1 -7
- package/lib/config/rule-validator.js +42 -6
- package/lib/eslint/eslint-helpers.js +116 -58
- package/lib/eslint/eslint.js +892 -377
- package/lib/eslint/index.js +2 -2
- package/lib/eslint/legacy-eslint.js +728 -0
- package/lib/linter/apply-disable-directives.js +59 -31
- package/lib/linter/code-path-analysis/code-path-analyzer.js +0 -1
- package/lib/linter/code-path-analysis/code-path.js +32 -30
- package/lib/linter/code-path-analysis/fork-context.js +1 -1
- package/lib/linter/config-comment-parser.js +8 -11
- package/lib/linter/index.js +1 -3
- package/lib/linter/interpolate.js +24 -2
- package/lib/linter/linter.js +428 -207
- package/lib/linter/report-translator.js +3 -3
- package/lib/linter/rules.js +6 -15
- package/lib/linter/source-code-fixer.js +1 -1
- package/lib/linter/timing.js +16 -8
- package/lib/options.js +35 -3
- package/lib/rule-tester/index.js +3 -1
- package/lib/rule-tester/rule-tester.js +424 -347
- package/lib/rules/array-bracket-newline.js +1 -1
- package/lib/rules/array-bracket-spacing.js +1 -1
- package/lib/rules/block-scoped-var.js +1 -1
- package/lib/rules/callback-return.js +2 -2
- package/lib/rules/camelcase.js +3 -5
- package/lib/rules/capitalized-comments.js +10 -7
- package/lib/rules/comma-dangle.js +1 -1
- package/lib/rules/comma-style.js +2 -2
- package/lib/rules/complexity.js +14 -1
- package/lib/rules/constructor-super.js +99 -100
- package/lib/rules/default-case.js +1 -1
- package/lib/rules/eol-last.js +2 -2
- package/lib/rules/function-paren-newline.js +2 -2
- package/lib/rules/indent-legacy.js +5 -5
- package/lib/rules/indent.js +5 -5
- package/lib/rules/index.js +1 -2
- package/lib/rules/key-spacing.js +2 -2
- package/lib/rules/line-comment-position.js +1 -1
- package/lib/rules/lines-around-directive.js +2 -2
- package/lib/rules/max-depth.js +1 -1
- package/lib/rules/max-len.js +3 -3
- package/lib/rules/max-lines.js +3 -3
- package/lib/rules/max-nested-callbacks.js +1 -1
- package/lib/rules/max-params.js +1 -1
- package/lib/rules/max-statements.js +1 -1
- package/lib/rules/multiline-comment-style.js +7 -7
- package/lib/rules/new-cap.js +1 -1
- package/lib/rules/newline-after-var.js +1 -1
- package/lib/rules/newline-before-return.js +1 -1
- package/lib/rules/no-case-declarations.js +13 -1
- package/lib/rules/no-constant-binary-expression.js +7 -8
- package/lib/rules/no-constant-condition.js +18 -7
- package/lib/rules/no-constructor-return.js +2 -2
- package/lib/rules/no-dupe-class-members.js +2 -2
- package/lib/rules/no-else-return.js +1 -1
- package/lib/rules/no-empty-function.js +2 -2
- package/lib/rules/no-empty-static-block.js +1 -1
- package/lib/rules/no-extend-native.js +1 -2
- package/lib/rules/no-extra-semi.js +1 -1
- package/lib/rules/no-fallthrough.js +41 -16
- package/lib/rules/no-implicit-coercion.js +66 -24
- package/lib/rules/no-inner-declarations.js +23 -2
- package/lib/rules/no-invalid-regexp.js +1 -1
- package/lib/rules/no-invalid-this.js +1 -1
- package/lib/rules/no-lone-blocks.js +3 -3
- package/lib/rules/no-loss-of-precision.js +1 -1
- package/lib/rules/no-misleading-character-class.js +225 -69
- package/lib/rules/no-mixed-spaces-and-tabs.js +1 -1
- package/lib/rules/no-multiple-empty-lines.js +1 -1
- package/lib/rules/no-new-native-nonconstructor.js +1 -1
- package/lib/rules/no-new-symbol.js +8 -1
- package/lib/rules/no-restricted-globals.js +1 -1
- package/lib/rules/no-restricted-imports.js +186 -40
- package/lib/rules/no-restricted-modules.js +2 -2
- package/lib/rules/no-return-await.js +1 -1
- package/lib/rules/no-sequences.js +1 -0
- package/lib/rules/no-this-before-super.js +45 -13
- package/lib/rules/no-trailing-spaces.js +2 -3
- package/lib/rules/no-unneeded-ternary.js +1 -1
- package/lib/rules/no-unsafe-optional-chaining.js +1 -1
- package/lib/rules/no-unused-private-class-members.js +1 -1
- package/lib/rules/no-unused-vars.js +197 -36
- package/lib/rules/no-useless-assignment.js +566 -0
- package/lib/rules/no-useless-backreference.js +1 -1
- package/lib/rules/no-useless-computed-key.js +2 -2
- package/lib/rules/no-useless-return.js +7 -2
- package/lib/rules/object-curly-spacing.js +3 -3
- package/lib/rules/object-property-newline.js +1 -1
- package/lib/rules/one-var.js +5 -5
- package/lib/rules/padded-blocks.js +7 -7
- package/lib/rules/prefer-arrow-callback.js +3 -3
- package/lib/rules/prefer-reflect.js +1 -1
- package/lib/rules/prefer-regex-literals.js +1 -1
- package/lib/rules/prefer-template.js +1 -1
- package/lib/rules/radix.js +2 -2
- package/lib/rules/semi-style.js +1 -1
- package/lib/rules/sort-imports.js +1 -1
- package/lib/rules/sort-keys.js +1 -1
- package/lib/rules/sort-vars.js +1 -1
- package/lib/rules/space-unary-ops.js +1 -1
- package/lib/rules/strict.js +1 -1
- package/lib/rules/use-isnan.js +101 -7
- package/lib/rules/utils/ast-utils.js +16 -7
- package/lib/rules/utils/char-source.js +240 -0
- package/lib/rules/utils/lazy-loading-rule-map.js +1 -1
- package/lib/rules/utils/unicode/index.js +9 -4
- package/lib/rules/yield-star-spacing.js +1 -1
- package/lib/shared/runtime-info.js +1 -0
- package/lib/shared/serialization.js +55 -0
- package/lib/shared/stats.js +30 -0
- package/lib/shared/string-utils.js +9 -11
- package/lib/shared/types.js +35 -1
- package/lib/source-code/index.js +3 -1
- package/lib/source-code/source-code.js +299 -85
- package/lib/source-code/token-store/backward-token-cursor.js +3 -3
- package/lib/source-code/token-store/cursors.js +4 -2
- package/lib/source-code/token-store/forward-token-comment-cursor.js +3 -3
- package/lib/source-code/token-store/forward-token-cursor.js +3 -3
- package/lib/source-code/token-store/index.js +2 -2
- package/lib/unsupported-api.js +3 -5
- package/messages/no-config-found.js +1 -1
- package/messages/plugin-conflict.js +1 -1
- package/messages/plugin-invalid.js +1 -1
- package/messages/plugin-missing.js +1 -1
- package/package.json +32 -29
- package/conf/config-schema.js +0 -93
- package/lib/cli-engine/formatters/checkstyle.js +0 -60
- package/lib/cli-engine/formatters/compact.js +0 -60
- package/lib/cli-engine/formatters/jslint-xml.js +0 -41
- package/lib/cli-engine/formatters/junit.js +0 -82
- package/lib/cli-engine/formatters/tap.js +0 -95
- package/lib/cli-engine/formatters/unix.js +0 -58
- package/lib/cli-engine/formatters/visualstudio.js +0 -63
- package/lib/cli-engine/xml-escape.js +0 -34
- package/lib/eslint/flat-eslint.js +0 -1155
- package/lib/rule-tester/flat-rule-tester.js +0 -1131
- package/lib/rules/require-jsdoc.js +0 -122
- package/lib/rules/utils/patterns/letters.js +0 -36
- package/lib/rules/valid-jsdoc.js +0 -516
- package/lib/shared/config-validator.js +0 -347
- package/lib/shared/deprecation-warnings.js +0 -58
- package/lib/shared/relative-module-resolver.js +0 -50
@@ -199,7 +199,7 @@ module.exports = {
|
|
199
199
|
: sourceCode.getLastToken(node),
|
200
200
|
penultimate = sourceCode.getTokenBefore(last),
|
201
201
|
firstElement = node.elements[0],
|
202
|
-
lastElement = node.elements
|
202
|
+
lastElement = node.elements.at(-1);
|
203
203
|
|
204
204
|
const openingBracketMustBeSpaced =
|
205
205
|
options.objectsInArraysException && isObjectType(firstElement) ||
|
@@ -147,7 +147,7 @@ module.exports = {
|
|
147
147
|
if (closestBlock.type === "BlockStatement") {
|
148
148
|
|
149
149
|
// find the last item in the block
|
150
|
-
const lastItem = closestBlock.body
|
150
|
+
const lastItem = closestBlock.body.at(-1);
|
151
151
|
|
152
152
|
// if the callback is the last thing in a block that might be ok
|
153
153
|
if (isCallbackExpression(node, lastItem)) {
|
@@ -168,7 +168,7 @@ module.exports = {
|
|
168
168
|
if (lastItem.type === "ReturnStatement") {
|
169
169
|
|
170
170
|
// but only if the callback is immediately before
|
171
|
-
if (isCallbackExpression(node, closestBlock.body
|
171
|
+
if (isCallbackExpression(node, closestBlock.body.at(-2))) {
|
172
172
|
return;
|
173
173
|
}
|
174
174
|
}
|
package/lib/rules/camelcase.js
CHANGED
@@ -8,7 +8,6 @@
|
|
8
8
|
// Requirements
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
|
11
|
-
const LETTER_PATTERN = require("./utils/patterns/letters");
|
12
11
|
const astUtils = require("./utils/ast-utils");
|
13
12
|
|
14
13
|
//------------------------------------------------------------------------------
|
@@ -17,7 +16,8 @@ const astUtils = require("./utils/ast-utils");
|
|
17
16
|
|
18
17
|
const DEFAULT_IGNORE_PATTERN = astUtils.COMMENTS_IGNORE_PATTERN,
|
19
18
|
WHITESPACE = /\s/gu,
|
20
|
-
MAYBE_URL = /^\s*[^:/?#\s]+:\/\/[^?#]/u
|
19
|
+
MAYBE_URL = /^\s*[^:/?#\s]+:\/\/[^?#]/u, // TODO: Combine w/ max-len pattern?
|
20
|
+
LETTER_PATTERN = /\p{L}/u;
|
21
21
|
|
22
22
|
/*
|
23
23
|
* Base schema body for defining the basic capitalization rule, ignorePattern,
|
@@ -233,7 +233,8 @@ module.exports = {
|
|
233
233
|
return true;
|
234
234
|
}
|
235
235
|
|
236
|
-
|
236
|
+
// Get the first Unicode character (1 or 2 code units).
|
237
|
+
const [firstWordChar] = commentWordCharsOnly;
|
237
238
|
|
238
239
|
if (!LETTER_PATTERN.test(firstWordChar)) {
|
239
240
|
return true;
|
@@ -273,12 +274,14 @@ module.exports = {
|
|
273
274
|
messageId,
|
274
275
|
fix(fixer) {
|
275
276
|
const match = comment.value.match(LETTER_PATTERN);
|
277
|
+
const char = match[0];
|
276
278
|
|
277
|
-
|
279
|
+
// Offset match.index by 2 to account for the first 2 characters that start the comment (// or /*)
|
280
|
+
const charIndex = comment.range[0] + match.index + 2;
|
278
281
|
|
279
|
-
|
280
|
-
[
|
281
|
-
capitalize === "always" ?
|
282
|
+
return fixer.replaceTextRange(
|
283
|
+
[charIndex, charIndex + char.length],
|
284
|
+
capitalize === "always" ? char.toLocaleUpperCase() : char.toLocaleLowerCase()
|
282
285
|
);
|
283
286
|
}
|
284
287
|
});
|
package/lib/rules/comma-style.js
CHANGED
@@ -66,7 +66,7 @@ module.exports = {
|
|
66
66
|
NewExpression: true
|
67
67
|
};
|
68
68
|
|
69
|
-
if (context.options.length === 2 && Object.
|
69
|
+
if (context.options.length === 2 && Object.hasOwn(context.options[1], "exceptions")) {
|
70
70
|
const keys = Object.keys(context.options[1].exceptions);
|
71
71
|
|
72
72
|
for (let i = 0; i < keys.length; i++) {
|
@@ -218,7 +218,7 @@ module.exports = {
|
|
218
218
|
|
219
219
|
previousItemToken = tokenAfterItem
|
220
220
|
? sourceCode.getTokenBefore(tokenAfterItem)
|
221
|
-
: sourceCode.ast.tokens
|
221
|
+
: sourceCode.ast.tokens.at(-1);
|
222
222
|
} else {
|
223
223
|
previousItemToken = currentItemToken;
|
224
224
|
}
|
package/lib/rules/complexity.js
CHANGED
@@ -64,7 +64,7 @@ module.exports = {
|
|
64
64
|
|
65
65
|
if (
|
66
66
|
typeof option === "object" &&
|
67
|
-
(Object.
|
67
|
+
(Object.hasOwn(option, "maximum") || Object.hasOwn(option, "max"))
|
68
68
|
) {
|
69
69
|
THRESHOLD = option.maximum || option.max;
|
70
70
|
} else if (typeof option === "number") {
|
@@ -109,6 +109,7 @@ module.exports = {
|
|
109
109
|
IfStatement: increaseComplexity,
|
110
110
|
WhileStatement: increaseComplexity,
|
111
111
|
DoWhileStatement: increaseComplexity,
|
112
|
+
AssignmentPattern: increaseComplexity,
|
112
113
|
|
113
114
|
// Avoid `default`
|
114
115
|
"SwitchCase[test]": increaseComplexity,
|
@@ -120,6 +121,18 @@ module.exports = {
|
|
120
121
|
}
|
121
122
|
},
|
122
123
|
|
124
|
+
MemberExpression(node) {
|
125
|
+
if (node.optional === true) {
|
126
|
+
increaseComplexity();
|
127
|
+
}
|
128
|
+
},
|
129
|
+
|
130
|
+
CallExpression(node) {
|
131
|
+
if (node.optional === true) {
|
132
|
+
increaseComplexity();
|
133
|
+
}
|
134
|
+
},
|
135
|
+
|
123
136
|
onCodePathEnd(codePath, node) {
|
124
137
|
const complexity = complexities.pop();
|
125
138
|
|
@@ -9,22 +9,6 @@
|
|
9
9
|
// Helpers
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
-
/**
|
13
|
-
* Checks all segments in a set and returns true if any are reachable.
|
14
|
-
* @param {Set<CodePathSegment>} segments The segments to check.
|
15
|
-
* @returns {boolean} True if any segment is reachable; false otherwise.
|
16
|
-
*/
|
17
|
-
function isAnySegmentReachable(segments) {
|
18
|
-
|
19
|
-
for (const segment of segments) {
|
20
|
-
if (segment.reachable) {
|
21
|
-
return true;
|
22
|
-
}
|
23
|
-
}
|
24
|
-
|
25
|
-
return false;
|
26
|
-
}
|
27
|
-
|
28
12
|
/**
|
29
13
|
* Checks whether or not a given node is a constructor.
|
30
14
|
* @param {ASTNode} node A node to check. This node type is one of
|
@@ -109,7 +93,7 @@ function isPossibleConstructor(node) {
|
|
109
93
|
);
|
110
94
|
|
111
95
|
case "SequenceExpression": {
|
112
|
-
const lastExpression = node.expressions
|
96
|
+
const lastExpression = node.expressions.at(-1);
|
113
97
|
|
114
98
|
return isPossibleConstructor(lastExpression);
|
115
99
|
}
|
@@ -119,6 +103,30 @@ function isPossibleConstructor(node) {
|
|
119
103
|
}
|
120
104
|
}
|
121
105
|
|
106
|
+
/**
|
107
|
+
* A class to store information about a code path segment.
|
108
|
+
*/
|
109
|
+
class SegmentInfo {
|
110
|
+
|
111
|
+
/**
|
112
|
+
* Indicates if super() is called in all code paths.
|
113
|
+
* @type {boolean}
|
114
|
+
*/
|
115
|
+
calledInEveryPaths = false;
|
116
|
+
|
117
|
+
/**
|
118
|
+
* Indicates if super() is called in any code paths.
|
119
|
+
* @type {boolean}
|
120
|
+
*/
|
121
|
+
calledInSomePaths = false;
|
122
|
+
|
123
|
+
/**
|
124
|
+
* The nodes which have been validated and don't need to be reconsidered.
|
125
|
+
* @type {ASTNode[]}
|
126
|
+
*/
|
127
|
+
validNodes = [];
|
128
|
+
}
|
129
|
+
|
122
130
|
//------------------------------------------------------------------------------
|
123
131
|
// Rule Definition
|
124
132
|
//------------------------------------------------------------------------------
|
@@ -141,8 +149,7 @@ module.exports = {
|
|
141
149
|
missingAll: "Expected to call 'super()'.",
|
142
150
|
|
143
151
|
duplicate: "Unexpected duplicate 'super()'.",
|
144
|
-
badSuper: "Unexpected 'super()' because 'super' is not a constructor."
|
145
|
-
unexpected: "Unexpected 'super()'."
|
152
|
+
badSuper: "Unexpected 'super()' because 'super' is not a constructor."
|
146
153
|
}
|
147
154
|
},
|
148
155
|
|
@@ -159,14 +166,10 @@ module.exports = {
|
|
159
166
|
*/
|
160
167
|
let funcInfo = null;
|
161
168
|
|
162
|
-
|
163
|
-
* {
|
164
|
-
* Information for each code path segment.
|
165
|
-
* - calledInSomePaths: A flag of be called `super()` in some code paths.
|
166
|
-
* - calledInEveryPaths: A flag of be called `super()` in all code paths.
|
167
|
-
* - validNodes:
|
169
|
+
/**
|
170
|
+
* @type {Record<string, SegmentInfo>}
|
168
171
|
*/
|
169
|
-
|
172
|
+
const segInfoMap = Object.create(null);
|
170
173
|
|
171
174
|
/**
|
172
175
|
* Gets the flag which shows `super()` is called in some paths.
|
@@ -177,23 +180,21 @@ module.exports = {
|
|
177
180
|
return segment.reachable && segInfoMap[segment.id].calledInSomePaths;
|
178
181
|
}
|
179
182
|
|
183
|
+
/**
|
184
|
+
* Determines if a segment has been seen in the traversal.
|
185
|
+
* @param {CodePathSegment} segment A code path segment to check.
|
186
|
+
* @returns {boolean} `true` if the segment has been seen.
|
187
|
+
*/
|
188
|
+
function hasSegmentBeenSeen(segment) {
|
189
|
+
return !!segInfoMap[segment.id];
|
190
|
+
}
|
191
|
+
|
180
192
|
/**
|
181
193
|
* Gets the flag which shows `super()` is called in all paths.
|
182
194
|
* @param {CodePathSegment} segment A code path segment to get.
|
183
195
|
* @returns {boolean} The flag which shows `super()` is called in all paths.
|
184
196
|
*/
|
185
197
|
function isCalledInEveryPath(segment) {
|
186
|
-
|
187
|
-
/*
|
188
|
-
* If specific segment is the looped segment of the current segment,
|
189
|
-
* skip the segment.
|
190
|
-
* If not skipped, this never becomes true after a loop.
|
191
|
-
*/
|
192
|
-
if (segment.nextSegments.length === 1 &&
|
193
|
-
segment.nextSegments[0].isLoopedPrevSegment(segment)
|
194
|
-
) {
|
195
|
-
return true;
|
196
|
-
}
|
197
198
|
return segment.reachable && segInfoMap[segment.id].calledInEveryPaths;
|
198
199
|
}
|
199
200
|
|
@@ -250,9 +251,9 @@ module.exports = {
|
|
250
251
|
}
|
251
252
|
|
252
253
|
// Reports if `super()` lacked.
|
253
|
-
const
|
254
|
-
const calledInEveryPaths =
|
255
|
-
const calledInSomePaths =
|
254
|
+
const returnedSegments = codePath.returnedSegments;
|
255
|
+
const calledInEveryPaths = returnedSegments.every(isCalledInEveryPath);
|
256
|
+
const calledInSomePaths = returnedSegments.some(isCalledInSomePath);
|
256
257
|
|
257
258
|
if (!calledInEveryPaths) {
|
258
259
|
context.report({
|
@@ -267,29 +268,37 @@ module.exports = {
|
|
267
268
|
/**
|
268
269
|
* Initialize information of a given code path segment.
|
269
270
|
* @param {CodePathSegment} segment A code path segment to initialize.
|
271
|
+
* @param {CodePathSegment} node Node that starts the segment.
|
270
272
|
* @returns {void}
|
271
273
|
*/
|
272
|
-
onCodePathSegmentStart(segment) {
|
274
|
+
onCodePathSegmentStart(segment, node) {
|
273
275
|
|
274
276
|
funcInfo.currentSegments.add(segment);
|
275
277
|
|
276
|
-
if (!(funcInfo
|
278
|
+
if (!(funcInfo.isConstructor && funcInfo.hasExtends)) {
|
277
279
|
return;
|
278
280
|
}
|
279
281
|
|
280
282
|
// Initialize info.
|
281
|
-
const info = segInfoMap[segment.id] =
|
282
|
-
|
283
|
-
|
284
|
-
validNodes: []
|
285
|
-
};
|
283
|
+
const info = segInfoMap[segment.id] = new SegmentInfo();
|
284
|
+
|
285
|
+
const seenPrevSegments = segment.prevSegments.filter(hasSegmentBeenSeen);
|
286
286
|
|
287
287
|
// When there are previous segments, aggregates these.
|
288
|
-
|
288
|
+
if (seenPrevSegments.length > 0) {
|
289
|
+
info.calledInSomePaths = seenPrevSegments.some(isCalledInSomePath);
|
290
|
+
info.calledInEveryPaths = seenPrevSegments.every(isCalledInEveryPath);
|
291
|
+
}
|
289
292
|
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
+
/*
|
294
|
+
* ForStatement > *.update segments are a special case as they are created in advance,
|
295
|
+
* without seen previous segments. Since they logically don't affect `calledInEveryPaths`
|
296
|
+
* calculations, and they can never be a lone previous segment of another one, we'll set
|
297
|
+
* their `calledInEveryPaths` to `true` to effectively ignore them in those calculations.
|
298
|
+
* .
|
299
|
+
*/
|
300
|
+
if (node.parent && node.parent.type === "ForStatement" && node.parent.update === node) {
|
301
|
+
info.calledInEveryPaths = true;
|
293
302
|
}
|
294
303
|
},
|
295
304
|
|
@@ -316,25 +325,30 @@ module.exports = {
|
|
316
325
|
* @returns {void}
|
317
326
|
*/
|
318
327
|
onCodePathSegmentLoop(fromSegment, toSegment) {
|
319
|
-
if (!(funcInfo
|
328
|
+
if (!(funcInfo.isConstructor && funcInfo.hasExtends)) {
|
320
329
|
return;
|
321
330
|
}
|
322
331
|
|
323
|
-
// Update information inside of the loop.
|
324
|
-
const isRealLoop = toSegment.prevSegments.length >= 2;
|
325
|
-
|
326
332
|
funcInfo.codePath.traverseSegments(
|
327
333
|
{ first: toSegment, last: fromSegment },
|
328
|
-
segment => {
|
334
|
+
(segment, controller) => {
|
329
335
|
const info = segInfoMap[segment.id];
|
330
|
-
const prevSegments = segment.prevSegments;
|
331
336
|
|
332
|
-
//
|
333
|
-
|
334
|
-
|
337
|
+
// skip segments after the loop
|
338
|
+
if (!info) {
|
339
|
+
controller.skip();
|
340
|
+
return;
|
341
|
+
}
|
342
|
+
|
343
|
+
const seenPrevSegments = segment.prevSegments.filter(hasSegmentBeenSeen);
|
344
|
+
const calledInSomePreviousPaths = seenPrevSegments.some(isCalledInSomePath);
|
345
|
+
const calledInEveryPreviousPaths = seenPrevSegments.every(isCalledInEveryPath);
|
346
|
+
|
347
|
+
info.calledInSomePaths ||= calledInSomePreviousPaths;
|
348
|
+
info.calledInEveryPaths ||= calledInEveryPreviousPaths;
|
335
349
|
|
336
350
|
// If flags become true anew, reports the valid nodes.
|
337
|
-
if (
|
351
|
+
if (calledInSomePreviousPaths) {
|
338
352
|
const nodes = info.validNodes;
|
339
353
|
|
340
354
|
info.validNodes = [];
|
@@ -358,7 +372,7 @@ module.exports = {
|
|
358
372
|
* @returns {void}
|
359
373
|
*/
|
360
374
|
"CallExpression:exit"(node) {
|
361
|
-
if (!(funcInfo && funcInfo.
|
375
|
+
if (!(funcInfo.isConstructor && funcInfo.hasExtends)) {
|
362
376
|
return;
|
363
377
|
}
|
364
378
|
|
@@ -368,41 +382,34 @@ module.exports = {
|
|
368
382
|
}
|
369
383
|
|
370
384
|
// Reports if needed.
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
let info = null;
|
385
|
+
const segments = funcInfo.currentSegments;
|
386
|
+
let duplicate = false;
|
387
|
+
let info = null;
|
375
388
|
|
376
|
-
|
389
|
+
for (const segment of segments) {
|
377
390
|
|
378
|
-
|
379
|
-
|
391
|
+
if (segment.reachable) {
|
392
|
+
info = segInfoMap[segment.id];
|
380
393
|
|
381
|
-
|
382
|
-
|
383
|
-
}
|
394
|
+
duplicate = duplicate || info.calledInSomePaths;
|
395
|
+
info.calledInSomePaths = info.calledInEveryPaths = true;
|
384
396
|
}
|
397
|
+
}
|
385
398
|
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
}
|
399
|
+
if (info) {
|
400
|
+
if (duplicate) {
|
401
|
+
context.report({
|
402
|
+
messageId: "duplicate",
|
403
|
+
node
|
404
|
+
});
|
405
|
+
} else if (!funcInfo.superIsConstructor) {
|
406
|
+
context.report({
|
407
|
+
messageId: "badSuper",
|
408
|
+
node
|
409
|
+
});
|
410
|
+
} else {
|
411
|
+
info.validNodes.push(node);
|
400
412
|
}
|
401
|
-
} else if (isAnySegmentReachable(funcInfo.currentSegments)) {
|
402
|
-
context.report({
|
403
|
-
messageId: "unexpected",
|
404
|
-
node
|
405
|
-
});
|
406
413
|
}
|
407
414
|
},
|
408
415
|
|
@@ -412,7 +419,7 @@ module.exports = {
|
|
412
419
|
* @returns {void}
|
413
420
|
*/
|
414
421
|
ReturnStatement(node) {
|
415
|
-
if (!(funcInfo
|
422
|
+
if (!(funcInfo.isConstructor && funcInfo.hasExtends)) {
|
416
423
|
return;
|
417
424
|
}
|
418
425
|
|
@@ -432,14 +439,6 @@ module.exports = {
|
|
432
439
|
info.calledInSomePaths = info.calledInEveryPaths = true;
|
433
440
|
}
|
434
441
|
}
|
435
|
-
},
|
436
|
-
|
437
|
-
/**
|
438
|
-
* Resets state.
|
439
|
-
* @returns {void}
|
440
|
-
*/
|
441
|
-
"Program:exit"() {
|
442
|
-
segInfoMap = Object.create(null);
|
443
442
|
}
|
444
443
|
};
|
445
444
|
}
|
package/lib/rules/eol-last.js
CHANGED
@@ -45,7 +45,7 @@ module.exports = {
|
|
45
45
|
Program: function checkBadEOF(node) {
|
46
46
|
const sourceCode = context.sourceCode,
|
47
47
|
src = sourceCode.getText(),
|
48
|
-
lastLine = sourceCode.lines
|
48
|
+
lastLine = sourceCode.lines.at(-1),
|
49
49
|
location = {
|
50
50
|
column: lastLine.length,
|
51
51
|
line: sourceCode.lines.length
|
@@ -89,7 +89,7 @@ module.exports = {
|
|
89
89
|
});
|
90
90
|
} else if (mode === "never" && endsWithNewline) {
|
91
91
|
|
92
|
-
const secondLastLine = sourceCode.lines
|
92
|
+
const secondLastLine = sourceCode.lines.at(-2);
|
93
93
|
|
94
94
|
// File is newline-terminated, but shouldn't be
|
95
95
|
context.report({
|
@@ -218,7 +218,7 @@ module.exports = {
|
|
218
218
|
case "FunctionExpression": {
|
219
219
|
const leftParen = sourceCode.getFirstToken(node, astUtils.isOpeningParenToken);
|
220
220
|
const rightParen = node.params.length
|
221
|
-
? sourceCode.getTokenAfter(node.params
|
221
|
+
? sourceCode.getTokenAfter(node.params.at(-1), astUtils.isClosingParenToken)
|
222
222
|
: sourceCode.getTokenAfter(leftParen);
|
223
223
|
|
224
224
|
return { leftParen, rightParen };
|
@@ -234,7 +234,7 @@ module.exports = {
|
|
234
234
|
}
|
235
235
|
|
236
236
|
const rightParen = node.params.length
|
237
|
-
? sourceCode.getTokenAfter(node.params
|
237
|
+
? sourceCode.getTokenAfter(node.params.at(-1), astUtils.isClosingParenToken)
|
238
238
|
: sourceCode.getTokenAfter(firstToken);
|
239
239
|
|
240
240
|
return {
|
@@ -789,7 +789,7 @@ module.exports = {
|
|
789
789
|
if (elements.length > 0) {
|
790
790
|
|
791
791
|
// Skip last block line check if last item in same line
|
792
|
-
if (elements
|
792
|
+
if (elements.at(-1).loc.end.line === node.loc.end.line) {
|
793
793
|
return;
|
794
794
|
}
|
795
795
|
}
|
@@ -830,7 +830,7 @@ module.exports = {
|
|
830
830
|
}
|
831
831
|
|
832
832
|
let indent;
|
833
|
-
let nodesToCheck
|
833
|
+
let nodesToCheck;
|
834
834
|
|
835
835
|
/*
|
836
836
|
* For this statements we should check indent from statement beginning,
|
@@ -873,7 +873,7 @@ module.exports = {
|
|
873
873
|
*/
|
874
874
|
function filterOutSameLineVars(node) {
|
875
875
|
return node.declarations.reduce((finalCollection, elem) => {
|
876
|
-
const lastElem = finalCollection
|
876
|
+
const lastElem = finalCollection.at(-1);
|
877
877
|
|
878
878
|
if ((elem.loc.start.line !== node.loc.start.line && !lastElem) ||
|
879
879
|
(lastElem && lastElem.loc.start.line !== elem.loc.start.line)) {
|
@@ -892,7 +892,7 @@ module.exports = {
|
|
892
892
|
function checkIndentInVariableDeclarations(node) {
|
893
893
|
const elements = filterOutSameLineVars(node);
|
894
894
|
const nodeIndent = getNodeIndent(node).goodChar;
|
895
|
-
const lastElement = elements
|
895
|
+
const lastElement = elements.at(-1);
|
896
896
|
|
897
897
|
const elementsIndent = nodeIndent + indentSize * options.VariableDeclarator[node.kind];
|
898
898
|
|
@@ -999,7 +999,7 @@ module.exports = {
|
|
999
999
|
},
|
1000
1000
|
|
1001
1001
|
VariableDeclaration(node) {
|
1002
|
-
if (node.declarations
|
1002
|
+
if (node.declarations.at(-1).loc.start.line > node.declarations[0].loc.start.line) {
|
1003
1003
|
checkIndentInVariableDeclarations(node);
|
1004
1004
|
}
|
1005
1005
|
},
|
package/lib/rules/indent.js
CHANGED
@@ -1077,7 +1077,7 @@ module.exports = {
|
|
1077
1077
|
"ObjectExpression, ObjectPattern"(node) {
|
1078
1078
|
const openingCurly = sourceCode.getFirstToken(node);
|
1079
1079
|
const closingCurly = sourceCode.getTokenAfter(
|
1080
|
-
node.properties.length ? node.properties
|
1080
|
+
node.properties.length ? node.properties.at(-1) : openingCurly,
|
1081
1081
|
astUtils.isClosingBraceToken
|
1082
1082
|
);
|
1083
1083
|
|
@@ -1407,7 +1407,7 @@ module.exports = {
|
|
1407
1407
|
PropertyDefinition(node) {
|
1408
1408
|
const firstToken = sourceCode.getFirstToken(node);
|
1409
1409
|
const maybeSemicolonToken = sourceCode.getLastToken(node);
|
1410
|
-
let keyLastToken
|
1410
|
+
let keyLastToken;
|
1411
1411
|
|
1412
1412
|
// Indent key.
|
1413
1413
|
if (node.computed) {
|
@@ -1458,7 +1458,7 @@ module.exports = {
|
|
1458
1458
|
|
1459
1459
|
if (node.cases.length) {
|
1460
1460
|
sourceCode.getTokensBetween(
|
1461
|
-
node.cases
|
1461
|
+
node.cases.at(-1),
|
1462
1462
|
closingCurly,
|
1463
1463
|
{ includeComments: true, filter: astUtils.isCommentToken }
|
1464
1464
|
).forEach(token => offsets.ignoreToken(token));
|
@@ -1488,7 +1488,7 @@ module.exports = {
|
|
1488
1488
|
},
|
1489
1489
|
|
1490
1490
|
VariableDeclaration(node) {
|
1491
|
-
let variableIndent = Object.
|
1491
|
+
let variableIndent = Object.hasOwn(options.VariableDeclarator, node.kind)
|
1492
1492
|
? options.VariableDeclarator[node.kind]
|
1493
1493
|
: DEFAULT_VARIABLE_INDENT;
|
1494
1494
|
|
@@ -1509,7 +1509,7 @@ module.exports = {
|
|
1509
1509
|
variableIndent = DEFAULT_VARIABLE_INDENT;
|
1510
1510
|
}
|
1511
1511
|
|
1512
|
-
if (node.declarations
|
1512
|
+
if (node.declarations.at(-1).loc.start.line > node.loc.start.line) {
|
1513
1513
|
|
1514
1514
|
/*
|
1515
1515
|
* VariableDeclarator indentation is a bit different from other forms of indentation, in that the
|
package/lib/rules/index.js
CHANGED
@@ -229,6 +229,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|
229
229
|
"no-unused-private-class-members": () => require("./no-unused-private-class-members"),
|
230
230
|
"no-unused-vars": () => require("./no-unused-vars"),
|
231
231
|
"no-use-before-define": () => require("./no-use-before-define"),
|
232
|
+
"no-useless-assignment": () => require("./no-useless-assignment"),
|
232
233
|
"no-useless-backreference": () => require("./no-useless-backreference"),
|
233
234
|
"no-useless-call": () => require("./no-useless-call"),
|
234
235
|
"no-useless-catch": () => require("./no-useless-catch"),
|
@@ -273,7 +274,6 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|
273
274
|
radix: () => require("./radix"),
|
274
275
|
"require-atomic-updates": () => require("./require-atomic-updates"),
|
275
276
|
"require-await": () => require("./require-await"),
|
276
|
-
"require-jsdoc": () => require("./require-jsdoc"),
|
277
277
|
"require-unicode-regexp": () => require("./require-unicode-regexp"),
|
278
278
|
"require-yield": () => require("./require-yield"),
|
279
279
|
"rest-spread-spacing": () => require("./rest-spread-spacing"),
|
@@ -296,7 +296,6 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
|
|
296
296
|
"template-tag-spacing": () => require("./template-tag-spacing"),
|
297
297
|
"unicode-bom": () => require("./unicode-bom"),
|
298
298
|
"use-isnan": () => require("./use-isnan"),
|
299
|
-
"valid-jsdoc": () => require("./valid-jsdoc"),
|
300
299
|
"valid-typeof": () => require("./valid-typeof"),
|
301
300
|
"vars-on-top": () => require("./vars-on-top"),
|
302
301
|
"wrap-iife": () => require("./wrap-iife"),
|