@typescript-eslint/eslint-plugin 8.52.1-alpha.8 → 8.53.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/dist/configs/eslintrc/all.d.ts +1 -0
- package/dist/configs/eslintrc/all.js +1 -0
- package/dist/configs/eslintrc/disable-type-checked.d.ts +1 -0
- package/dist/configs/eslintrc/disable-type-checked.js +1 -0
- package/dist/configs/flat/all.js +1 -0
- package/dist/configs/flat/disable-type-checked.js +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/raw-plugin.d.ts +7 -0
- package/dist/rules/index.d.ts +5 -0
- package/dist/rules/index.js +2 -0
- package/dist/rules/no-unsafe-call.d.ts +1 -1
- package/dist/rules/no-unsafe-call.js +19 -14
- package/dist/rules/no-unsafe-member-access.d.ts +1 -1
- package/dist/rules/no-unsafe-member-access.js +24 -13
- package/dist/rules/no-unused-vars.d.ts +4 -1
- package/dist/rules/no-unused-vars.js +373 -40
- package/dist/rules/no-useless-default-assignment.js +5 -0
- package/dist/rules/strict-void-return.d.ts +10 -0
- package/dist/rules/strict-void-return.js +356 -0
- package/dist/util/getBaseTypesOfClassMember.d.ts +11 -0
- package/dist/util/getBaseTypesOfClassMember.js +31 -0
- package/dist/util/index.d.ts +2 -0
- package/dist/util/index.js +2 -0
- package/dist/util/walkStatements.d.ts +7 -0
- package/dist/util/walkStatements.js +56 -0
- package/package.json +8 -8
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
37
|
+
const tsutils = __importStar(require("ts-api-utils"));
|
|
38
|
+
const ts = __importStar(require("typescript"));
|
|
39
|
+
const util = __importStar(require("../util"));
|
|
40
|
+
exports.default = util.createRule({
|
|
41
|
+
name: 'strict-void-return',
|
|
42
|
+
meta: {
|
|
43
|
+
type: 'problem',
|
|
44
|
+
docs: {
|
|
45
|
+
description: 'Disallow passing a value-returning function in a position accepting a void function',
|
|
46
|
+
requiresTypeChecking: true,
|
|
47
|
+
},
|
|
48
|
+
messages: {
|
|
49
|
+
asyncFunc: 'Async function used in a context where a void function is expected.',
|
|
50
|
+
nonVoidFunc: 'Value-returning function used in a context where a void function is expected.',
|
|
51
|
+
nonVoidReturn: 'Value returned in a context where a void return is expected.',
|
|
52
|
+
},
|
|
53
|
+
schema: [
|
|
54
|
+
{
|
|
55
|
+
type: 'object',
|
|
56
|
+
additionalProperties: false,
|
|
57
|
+
properties: {
|
|
58
|
+
allowReturnAny: {
|
|
59
|
+
type: 'boolean',
|
|
60
|
+
description: 'Whether to allow functions returning `any` to be used in place expecting a `void` function.',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
defaultOptions: [
|
|
67
|
+
{
|
|
68
|
+
allowReturnAny: false,
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
create(context, [options]) {
|
|
72
|
+
const sourceCode = context.sourceCode;
|
|
73
|
+
const parserServices = util.getParserServices(context);
|
|
74
|
+
const checker = parserServices.program.getTypeChecker();
|
|
75
|
+
return {
|
|
76
|
+
ArrayExpression: (node) => {
|
|
77
|
+
for (const elemNode of node.elements) {
|
|
78
|
+
if (elemNode != null &&
|
|
79
|
+
elemNode.type !== utils_1.AST_NODE_TYPES.SpreadElement) {
|
|
80
|
+
checkExpressionNode(elemNode);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
ArrowFunctionExpression: (node) => {
|
|
85
|
+
if (node.body.type !== utils_1.AST_NODE_TYPES.BlockStatement) {
|
|
86
|
+
checkExpressionNode(node.body);
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
AssignmentExpression: (node) => {
|
|
90
|
+
checkExpressionNode(node.right); // should ignore operators like `+=` or `-=` automatically
|
|
91
|
+
},
|
|
92
|
+
'CallExpression, NewExpression': checkFunctionCallNode,
|
|
93
|
+
JSXAttribute: (node) => {
|
|
94
|
+
if (node.value?.type === utils_1.AST_NODE_TYPES.JSXExpressionContainer &&
|
|
95
|
+
node.value.expression.type !== utils_1.AST_NODE_TYPES.JSXEmptyExpression) {
|
|
96
|
+
checkExpressionNode(node.value.expression);
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
MethodDefinition: checkClassMethodNode,
|
|
100
|
+
ObjectExpression: (node) => {
|
|
101
|
+
for (const propNode of node.properties) {
|
|
102
|
+
if (propNode.type !== utils_1.AST_NODE_TYPES.SpreadElement) {
|
|
103
|
+
checkObjectPropertyNode(propNode);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
PropertyDefinition: checkClassPropertyNode,
|
|
108
|
+
ReturnStatement: (node) => {
|
|
109
|
+
if (node.argument != null) {
|
|
110
|
+
checkExpressionNode(node.argument);
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
VariableDeclarator: (node) => {
|
|
114
|
+
if (node.init != null) {
|
|
115
|
+
checkExpressionNode(node.init);
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
function isVoidReturningFunctionType(type) {
|
|
120
|
+
const returnTypes = tsutils
|
|
121
|
+
.getCallSignaturesOfType(type)
|
|
122
|
+
.flatMap(signature => tsutils.unionConstituents(signature.getReturnType()));
|
|
123
|
+
return (returnTypes.length > 0 &&
|
|
124
|
+
returnTypes.every(type => tsutils.isTypeFlagSet(type, ts.TypeFlags.Void)));
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Finds errors in any expression node.
|
|
128
|
+
*
|
|
129
|
+
* Compares the type of the node against the contextual (expected) type.
|
|
130
|
+
*
|
|
131
|
+
* @returns `true` if the expected type was void function.
|
|
132
|
+
*/
|
|
133
|
+
function checkExpressionNode(node) {
|
|
134
|
+
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node);
|
|
135
|
+
const expectedType = checker.getContextualType(tsNode);
|
|
136
|
+
if (expectedType != null && isVoidReturningFunctionType(expectedType)) {
|
|
137
|
+
reportIfNonVoidFunction(node);
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Finds errors in function calls.
|
|
144
|
+
*
|
|
145
|
+
* When checking arguments, we also manually figure out the argument types
|
|
146
|
+
* by iterating over all the function signatures.
|
|
147
|
+
* Thanks to this, we can find arguments like `(() => void) | (() => any)`
|
|
148
|
+
* and treat them as void too.
|
|
149
|
+
* This is done to also support checking functions like `addEventListener`
|
|
150
|
+
* which have overloads where one callback returns any.
|
|
151
|
+
*
|
|
152
|
+
* Implementation mostly based on no-misused-promises,
|
|
153
|
+
* which does this to find `(() => void) | (() => NotThenable)`
|
|
154
|
+
* and report them too.
|
|
155
|
+
*/
|
|
156
|
+
function checkFunctionCallNode(callNode) {
|
|
157
|
+
const callTsNode = parserServices.esTreeNodeToTSNodeMap.get(callNode);
|
|
158
|
+
const funcType = checker.getTypeAtLocation(callTsNode.expression);
|
|
159
|
+
const funcSignatures = tsutils
|
|
160
|
+
.unionConstituents(funcType)
|
|
161
|
+
.flatMap(type => ts.isCallExpression(callTsNode)
|
|
162
|
+
? type.getCallSignatures()
|
|
163
|
+
: type.getConstructSignatures());
|
|
164
|
+
for (const [argIdx, argNode] of callNode.arguments.entries()) {
|
|
165
|
+
if (argNode.type === utils_1.AST_NODE_TYPES.SpreadElement) {
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
// Check against the contextual type first
|
|
169
|
+
if (checkExpressionNode(argNode)) {
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
// Check against the types from all of the call signatures
|
|
173
|
+
const argExpectedReturnTypes = funcSignatures
|
|
174
|
+
.map(s => s.parameters[argIdx])
|
|
175
|
+
.filter(Boolean)
|
|
176
|
+
.map(param => checker.getTypeOfSymbolAtLocation(param, callTsNode.expression))
|
|
177
|
+
.flatMap(paramType => tsutils.unionConstituents(paramType))
|
|
178
|
+
.flatMap(paramType => paramType.getCallSignatures())
|
|
179
|
+
.map(paramSignature => paramSignature.getReturnType());
|
|
180
|
+
if (
|
|
181
|
+
// At least one return type is void
|
|
182
|
+
argExpectedReturnTypes.some(type => tsutils.isTypeFlagSet(type, ts.TypeFlags.Void)) &&
|
|
183
|
+
// The rest are nullish or any
|
|
184
|
+
argExpectedReturnTypes.every(type => tsutils.isTypeFlagSet(type, ts.TypeFlags.VoidLike |
|
|
185
|
+
ts.TypeFlags.Undefined |
|
|
186
|
+
ts.TypeFlags.Null |
|
|
187
|
+
ts.TypeFlags.Any |
|
|
188
|
+
ts.TypeFlags.Never))) {
|
|
189
|
+
// We treat this argument as void even though it might be technically any.
|
|
190
|
+
reportIfNonVoidFunction(argNode);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Finds errors in an object property.
|
|
196
|
+
*
|
|
197
|
+
* Object properties require different logic
|
|
198
|
+
* when the property is a method shorthand.
|
|
199
|
+
*/
|
|
200
|
+
function checkObjectPropertyNode(propNode) {
|
|
201
|
+
const valueNode = propNode.value;
|
|
202
|
+
const propTsNode = parserServices.esTreeNodeToTSNodeMap.get(propNode);
|
|
203
|
+
if (propTsNode.kind === ts.SyntaxKind.MethodDeclaration) {
|
|
204
|
+
// Object property is a method shorthand.
|
|
205
|
+
if (propTsNode.name.kind === ts.SyntaxKind.ComputedPropertyName) {
|
|
206
|
+
// Don't check object methods with computed name.
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const objTsNode = propTsNode.parent;
|
|
210
|
+
const objType = checker.getContextualType(objTsNode);
|
|
211
|
+
if (objType == null) {
|
|
212
|
+
// Expected object type is unknown.
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const propSymbol = checker.getPropertyOfType(objType, propTsNode.name.text);
|
|
216
|
+
if (propSymbol == null) {
|
|
217
|
+
// Expected object type is known, but it doesn't have this method.
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const propExpectedType = checker.getTypeOfSymbolAtLocation(propSymbol, propTsNode);
|
|
221
|
+
if (isVoidReturningFunctionType(propExpectedType)) {
|
|
222
|
+
reportIfNonVoidFunction(valueNode);
|
|
223
|
+
}
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
// Object property is a regular property.
|
|
227
|
+
checkExpressionNode(valueNode);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Finds errors in a class property.
|
|
231
|
+
*
|
|
232
|
+
* In addition to the regular check against the contextual type,
|
|
233
|
+
* we also check against the base class property (when the class extends another class)
|
|
234
|
+
* and the implemented interfaces (when the class implements an interface).
|
|
235
|
+
*/
|
|
236
|
+
function checkClassPropertyNode(propNode) {
|
|
237
|
+
if (propNode.value == null) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
// Check in comparison to the base types.
|
|
241
|
+
for (const { baseMemberType } of util.getBaseTypesOfClassMember(parserServices, propNode)) {
|
|
242
|
+
if (isVoidReturningFunctionType(baseMemberType)) {
|
|
243
|
+
reportIfNonVoidFunction(propNode.value);
|
|
244
|
+
return; // Report at most one error.
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
// Check in comparison to the contextual type.
|
|
248
|
+
checkExpressionNode(propNode.value);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Finds errors in a class method.
|
|
252
|
+
*
|
|
253
|
+
* We check against the base class method (when the class extends another class)
|
|
254
|
+
* and the implemented interfaces (when the class implements an interface).
|
|
255
|
+
*/
|
|
256
|
+
function checkClassMethodNode(methodNode) {
|
|
257
|
+
if (methodNode.value.type === utils_1.AST_NODE_TYPES.TSEmptyBodyFunctionExpression) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
// Check in comparison to the base types.
|
|
261
|
+
for (const { baseMemberType } of util.getBaseTypesOfClassMember(parserServices, methodNode)) {
|
|
262
|
+
if (isVoidReturningFunctionType(baseMemberType)) {
|
|
263
|
+
reportIfNonVoidFunction(methodNode.value);
|
|
264
|
+
return; // Report at most one error.
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Reports an error if the provided node is not allowed in a void function context.
|
|
270
|
+
*/
|
|
271
|
+
function reportIfNonVoidFunction(funcNode) {
|
|
272
|
+
const allowedReturnType = ts.TypeFlags.Void |
|
|
273
|
+
ts.TypeFlags.Never |
|
|
274
|
+
ts.TypeFlags.Undefined |
|
|
275
|
+
(options.allowReturnAny ? ts.TypeFlags.Any : 0);
|
|
276
|
+
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(funcNode);
|
|
277
|
+
const actualType = checker.getApparentType(checker.getTypeAtLocation(tsNode));
|
|
278
|
+
if (tsutils
|
|
279
|
+
.getCallSignaturesOfType(actualType)
|
|
280
|
+
.map(signature => signature.getReturnType())
|
|
281
|
+
.flatMap(returnType => tsutils.unionConstituents(returnType))
|
|
282
|
+
.every(type => tsutils.isTypeFlagSet(type, allowedReturnType))) {
|
|
283
|
+
// The function is already void.
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
if (funcNode.type !== utils_1.AST_NODE_TYPES.ArrowFunctionExpression &&
|
|
287
|
+
funcNode.type !== utils_1.AST_NODE_TYPES.FunctionExpression) {
|
|
288
|
+
// The provided function is not a function literal.
|
|
289
|
+
// Report a generic error.
|
|
290
|
+
return context.report({
|
|
291
|
+
node: funcNode,
|
|
292
|
+
messageId: `nonVoidFunc`,
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
// The provided function is a function literal.
|
|
296
|
+
if (funcNode.generator) {
|
|
297
|
+
// The provided function is a generator function.
|
|
298
|
+
// Generator functions are not allowed.
|
|
299
|
+
return context.report({
|
|
300
|
+
loc: util.getFunctionHeadLoc(funcNode, sourceCode),
|
|
301
|
+
messageId: `nonVoidFunc`,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
if (funcNode.async) {
|
|
305
|
+
// The provided function is an async function.
|
|
306
|
+
// Async functions aren't allowed.
|
|
307
|
+
return context.report({
|
|
308
|
+
loc: util.getFunctionHeadLoc(funcNode, sourceCode),
|
|
309
|
+
messageId: `asyncFunc`,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
if (funcNode.body.type !== utils_1.AST_NODE_TYPES.BlockStatement) {
|
|
313
|
+
// The provided function is an arrow function shorthand without braces.
|
|
314
|
+
return context.report({
|
|
315
|
+
node: funcNode.body,
|
|
316
|
+
messageId: `nonVoidReturn`,
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
// The function is a regular or arrow function with a block body.
|
|
320
|
+
// Check return type annotation.
|
|
321
|
+
if (funcNode.returnType != null) {
|
|
322
|
+
// The provided function has an explicit return type annotation.
|
|
323
|
+
const typeAnnotationNode = funcNode.returnType.typeAnnotation;
|
|
324
|
+
if (typeAnnotationNode.type !== utils_1.AST_NODE_TYPES.TSVoidKeyword) {
|
|
325
|
+
// The explicit return type is not `void`.
|
|
326
|
+
return context.report({
|
|
327
|
+
node: typeAnnotationNode,
|
|
328
|
+
messageId: `nonVoidFunc`,
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
// Iterate over all function's return statements.
|
|
333
|
+
for (const statement of util.walkStatements(funcNode.body.body)) {
|
|
334
|
+
if (statement.type !== utils_1.AST_NODE_TYPES.ReturnStatement ||
|
|
335
|
+
statement.argument == null) {
|
|
336
|
+
// We only care about return statements with a value.
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
const returnType = checker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(statement.argument));
|
|
340
|
+
if (tsutils.isTypeFlagSet(returnType, allowedReturnType)) {
|
|
341
|
+
// Only visit return statements with invalid type.
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
// This return statement causes the non-void return type.
|
|
345
|
+
const returnKeyword = util.nullThrows(sourceCode.getFirstToken(statement, {
|
|
346
|
+
filter: token => token.value === 'return',
|
|
347
|
+
}), util.NullThrowsReasons.MissingToken('return keyword', statement.type));
|
|
348
|
+
context.report({
|
|
349
|
+
node: returnKeyword,
|
|
350
|
+
messageId: `nonVoidReturn`,
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
// No invalid returns found. The function is allowed.
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TSESTree, ParserServicesWithTypeInformation } from '@typescript-eslint/utils';
|
|
2
|
+
import type * as ts from 'typescript';
|
|
3
|
+
/**
|
|
4
|
+
* Given a member of a class which extends another class or implements an interface,
|
|
5
|
+
* yields the corresponding member type for each of the base class/interfaces.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getBaseTypesOfClassMember(services: ParserServicesWithTypeInformation, memberNode: TSESTree.MethodDefinition | TSESTree.PropertyDefinition): Generator<{
|
|
8
|
+
baseType: ts.Type;
|
|
9
|
+
baseMemberType: ts.Type;
|
|
10
|
+
heritageToken: ts.SyntaxKind.ExtendsKeyword | ts.SyntaxKind.ImplementsKeyword;
|
|
11
|
+
}>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getBaseTypesOfClassMember = getBaseTypesOfClassMember;
|
|
4
|
+
/**
|
|
5
|
+
* Given a member of a class which extends another class or implements an interface,
|
|
6
|
+
* yields the corresponding member type for each of the base class/interfaces.
|
|
7
|
+
*/
|
|
8
|
+
function* getBaseTypesOfClassMember(services, memberNode) {
|
|
9
|
+
const memberTsNode = services.esTreeNodeToTSNodeMap.get(memberNode);
|
|
10
|
+
if (memberTsNode.name == null) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const checker = services.program.getTypeChecker();
|
|
14
|
+
const memberSymbol = checker.getSymbolAtLocation(memberTsNode.name);
|
|
15
|
+
if (memberSymbol == null) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const classNode = memberTsNode.parent;
|
|
19
|
+
for (const clauseNode of classNode.heritageClauses ?? []) {
|
|
20
|
+
for (const baseTypeNode of clauseNode.types) {
|
|
21
|
+
const baseType = checker.getTypeAtLocation(baseTypeNode);
|
|
22
|
+
const baseMemberSymbol = checker.getPropertyOfType(baseType, memberSymbol.name);
|
|
23
|
+
if (baseMemberSymbol == null) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const baseMemberType = checker.getTypeOfSymbolAtLocation(baseMemberSymbol, memberTsNode);
|
|
27
|
+
const heritageToken = clauseNode.token;
|
|
28
|
+
yield { baseMemberType, baseType, heritageToken };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
package/dist/util/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from './astUtils';
|
|
|
3
3
|
export * from './baseTypeUtils';
|
|
4
4
|
export * from './collectUnusedVariables';
|
|
5
5
|
export * from './createRule';
|
|
6
|
+
export * from './getBaseTypesOfClassMember';
|
|
6
7
|
export * from './getFixOrSuggest';
|
|
7
8
|
export * from './getFunctionHeadLoc';
|
|
8
9
|
export * from './getOperatorPrecedence';
|
|
@@ -29,6 +30,7 @@ export * from './getValueOfLiteralType';
|
|
|
29
30
|
export * from './isHigherPrecedenceThanAwait';
|
|
30
31
|
export * from './skipChainExpression';
|
|
31
32
|
export * from './truthinessUtils';
|
|
33
|
+
export * from './walkStatements';
|
|
32
34
|
export * from '@typescript-eslint/type-utils';
|
|
33
35
|
export declare const applyDefault: typeof ESLintUtils.applyDefault, deepMerge: typeof ESLintUtils.deepMerge, getParserServices: typeof ESLintUtils.getParserServices, isObjectNotArray: typeof ESLintUtils.isObjectNotArray, nullThrows: typeof ESLintUtils.nullThrows, NullThrowsReasons: {
|
|
34
36
|
readonly MissingParent: "Expected node to have a parent.";
|
package/dist/util/index.js
CHANGED
|
@@ -20,6 +20,7 @@ __exportStar(require("./astUtils"), exports);
|
|
|
20
20
|
__exportStar(require("./baseTypeUtils"), exports);
|
|
21
21
|
__exportStar(require("./collectUnusedVariables"), exports);
|
|
22
22
|
__exportStar(require("./createRule"), exports);
|
|
23
|
+
__exportStar(require("./getBaseTypesOfClassMember"), exports);
|
|
23
24
|
__exportStar(require("./getFixOrSuggest"), exports);
|
|
24
25
|
__exportStar(require("./getFunctionHeadLoc"), exports);
|
|
25
26
|
__exportStar(require("./getOperatorPrecedence"), exports);
|
|
@@ -46,6 +47,7 @@ __exportStar(require("./getValueOfLiteralType"), exports);
|
|
|
46
47
|
__exportStar(require("./isHigherPrecedenceThanAwait"), exports);
|
|
47
48
|
__exportStar(require("./skipChainExpression"), exports);
|
|
48
49
|
__exportStar(require("./truthinessUtils"), exports);
|
|
50
|
+
__exportStar(require("./walkStatements"), exports);
|
|
49
51
|
// this is done for convenience - saves migrating all of the old rules
|
|
50
52
|
__exportStar(require("@typescript-eslint/type-utils"), exports);
|
|
51
53
|
exports.applyDefault = utils_1.ESLintUtils.applyDefault, exports.deepMerge = utils_1.ESLintUtils.deepMerge, exports.getParserServices = utils_1.ESLintUtils.getParserServices, exports.isObjectNotArray = utils_1.ESLintUtils.isObjectNotArray, exports.nullThrows = utils_1.ESLintUtils.nullThrows, exports.NullThrowsReasons = utils_1.ESLintUtils.NullThrowsReasons;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TSESTree } from '@typescript-eslint/utils';
|
|
2
|
+
/**
|
|
3
|
+
* Yields all statement nodes in a block, including nested blocks.
|
|
4
|
+
*
|
|
5
|
+
* You can use it to find all return statements in a function body.
|
|
6
|
+
*/
|
|
7
|
+
export declare function walkStatements(body: readonly TSESTree.Statement[]): Generator<TSESTree.Statement>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.walkStatements = walkStatements;
|
|
4
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
5
|
+
/**
|
|
6
|
+
* Yields all statement nodes in a block, including nested blocks.
|
|
7
|
+
*
|
|
8
|
+
* You can use it to find all return statements in a function body.
|
|
9
|
+
*/
|
|
10
|
+
function* walkStatements(body) {
|
|
11
|
+
for (const statement of body) {
|
|
12
|
+
switch (statement.type) {
|
|
13
|
+
case utils_1.AST_NODE_TYPES.BlockStatement: {
|
|
14
|
+
yield* walkStatements(statement.body);
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
case utils_1.AST_NODE_TYPES.SwitchStatement: {
|
|
18
|
+
for (const switchCase of statement.cases) {
|
|
19
|
+
yield* walkStatements(switchCase.consequent);
|
|
20
|
+
}
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
case utils_1.AST_NODE_TYPES.IfStatement: {
|
|
24
|
+
yield* walkStatements([statement.consequent]);
|
|
25
|
+
if (statement.alternate) {
|
|
26
|
+
yield* walkStatements([statement.alternate]);
|
|
27
|
+
}
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
case utils_1.AST_NODE_TYPES.WhileStatement:
|
|
31
|
+
case utils_1.AST_NODE_TYPES.DoWhileStatement:
|
|
32
|
+
case utils_1.AST_NODE_TYPES.ForStatement:
|
|
33
|
+
case utils_1.AST_NODE_TYPES.ForInStatement:
|
|
34
|
+
case utils_1.AST_NODE_TYPES.ForOfStatement:
|
|
35
|
+
case utils_1.AST_NODE_TYPES.WithStatement:
|
|
36
|
+
case utils_1.AST_NODE_TYPES.LabeledStatement: {
|
|
37
|
+
yield* walkStatements([statement.body]);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
case utils_1.AST_NODE_TYPES.TryStatement: {
|
|
41
|
+
yield* walkStatements([statement.block]);
|
|
42
|
+
if (statement.handler) {
|
|
43
|
+
yield* walkStatements([statement.handler.body]);
|
|
44
|
+
}
|
|
45
|
+
if (statement.finalizer) {
|
|
46
|
+
yield* walkStatements([statement.finalizer]);
|
|
47
|
+
}
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
default: {
|
|
51
|
+
yield statement;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typescript-eslint/eslint-plugin",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.53.0",
|
|
4
4
|
"description": "TypeScript plugin for ESLint",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -59,10 +59,10 @@
|
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"@eslint-community/regexpp": "^4.12.2",
|
|
62
|
-
"@typescript-eslint/scope-manager": "8.
|
|
63
|
-
"@typescript-eslint/type-utils": "8.
|
|
64
|
-
"@typescript-eslint/utils": "8.
|
|
65
|
-
"@typescript-eslint/visitor-keys": "8.
|
|
62
|
+
"@typescript-eslint/scope-manager": "8.53.0",
|
|
63
|
+
"@typescript-eslint/type-utils": "8.53.0",
|
|
64
|
+
"@typescript-eslint/utils": "8.53.0",
|
|
65
|
+
"@typescript-eslint/visitor-keys": "8.53.0",
|
|
66
66
|
"ignore": "^7.0.5",
|
|
67
67
|
"natural-compare": "^1.4.0",
|
|
68
68
|
"ts-api-utils": "^2.4.0"
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@types/mdast": "^4.0.4",
|
|
72
72
|
"@types/natural-compare": "*",
|
|
73
|
-
"@typescript-eslint/rule-schema-to-typescript-types": "8.
|
|
74
|
-
"@typescript-eslint/rule-tester": "8.
|
|
73
|
+
"@typescript-eslint/rule-schema-to-typescript-types": "8.53.0",
|
|
74
|
+
"@typescript-eslint/rule-tester": "8.53.0",
|
|
75
75
|
"@vitest/coverage-v8": "^3.2.4",
|
|
76
76
|
"ajv": "^6.12.6",
|
|
77
77
|
"eslint": "*",
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"vitest": "^3.2.4"
|
|
91
91
|
},
|
|
92
92
|
"peerDependencies": {
|
|
93
|
-
"@typescript-eslint/parser": "^8.
|
|
93
|
+
"@typescript-eslint/parser": "^8.53.0",
|
|
94
94
|
"eslint": "^8.57.0 || ^9.0.0",
|
|
95
95
|
"typescript": ">=4.8.4 <6.0.0"
|
|
96
96
|
},
|