@typescript-eslint/eslint-plugin 8.62.2-alpha.9 → 8.63.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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type Options = [('method' | 'property')?];
|
|
2
|
-
export type MessageIds = 'errorMethod' | 'errorProperty';
|
|
2
|
+
export type MessageIds = 'convertToMethodSignature' | 'errorMethod' | 'errorProperty';
|
|
3
3
|
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageIds, Options, import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
4
4
|
name: string;
|
|
5
5
|
};
|
|
@@ -10,7 +10,9 @@ exports.default = (0, util_1.createRule)({
|
|
|
10
10
|
description: 'Enforce using a particular method signature syntax',
|
|
11
11
|
},
|
|
12
12
|
fixable: 'code',
|
|
13
|
+
hasSuggestions: true,
|
|
13
14
|
messages: {
|
|
15
|
+
convertToMethodSignature: 'Convert to a method signature. This removes the `readonly` modifier, allowing the member to be reassigned.',
|
|
14
16
|
errorMethod: 'Shorthand method signature is forbidden. Use a function property instead.',
|
|
15
17
|
errorProperty: 'Function property signature is forbidden. Use a method shorthand instead.',
|
|
16
18
|
},
|
|
@@ -32,9 +34,6 @@ exports.default = (0, util_1.createRule)({
|
|
|
32
34
|
if (node.optional) {
|
|
33
35
|
key = `${key}?`;
|
|
34
36
|
}
|
|
35
|
-
if (node.readonly) {
|
|
36
|
-
key = `readonly ${key}`;
|
|
37
|
-
}
|
|
38
37
|
return key;
|
|
39
38
|
}
|
|
40
39
|
function getMethodParams(node) {
|
|
@@ -164,16 +163,30 @@ exports.default = (0, util_1.createRule)({
|
|
|
164
163
|
if (typeNode?.type !== utils_1.AST_NODE_TYPES.TSFunctionType) {
|
|
165
164
|
return;
|
|
166
165
|
}
|
|
166
|
+
const fix = fixer => {
|
|
167
|
+
const key = getMethodKey(propertyNode);
|
|
168
|
+
const params = getMethodParams(typeNode);
|
|
169
|
+
const returnType = getMethodReturnType(typeNode);
|
|
170
|
+
const delimiter = getDelimiter(propertyNode);
|
|
171
|
+
return fixer.replaceText(propertyNode, `${key}${params}: ${returnType}${delimiter}`);
|
|
172
|
+
};
|
|
173
|
+
// There is no syntax for a `readonly` method signature, so converting
|
|
174
|
+
// a `readonly` function-typed property drops the `readonly` modifier.
|
|
175
|
+
// That is a behavioral change (a method may be reassigned, a
|
|
176
|
+
// `readonly` property may not), so it is offered as a suggestion
|
|
177
|
+
// rather than applied as an autofix.
|
|
178
|
+
if (propertyNode.readonly) {
|
|
179
|
+
context.report({
|
|
180
|
+
node: propertyNode,
|
|
181
|
+
messageId: 'errorProperty',
|
|
182
|
+
suggest: [{ messageId: 'convertToMethodSignature', fix }],
|
|
183
|
+
});
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
167
186
|
context.report({
|
|
168
187
|
node: propertyNode,
|
|
169
188
|
messageId: 'errorProperty',
|
|
170
|
-
fix
|
|
171
|
-
const key = getMethodKey(propertyNode);
|
|
172
|
-
const params = getMethodParams(typeNode);
|
|
173
|
-
const returnType = getMethodReturnType(typeNode);
|
|
174
|
-
const delimiter = getDelimiter(propertyNode);
|
|
175
|
-
return fixer.replaceText(propertyNode, `${key}${params}: ${returnType}${delimiter}`);
|
|
176
|
-
},
|
|
189
|
+
fix,
|
|
177
190
|
});
|
|
178
191
|
},
|
|
179
192
|
}),
|
|
@@ -234,7 +234,7 @@ exports.default = (0, util_1.createRule)({
|
|
|
234
234
|
node.arguments[0]) {
|
|
235
235
|
const scope = context.sourceCode.getScope(node);
|
|
236
236
|
// eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum
|
|
237
|
-
const variable =
|
|
237
|
+
const variable = utils_1.ASTUtils.findVariable(scope, 'String');
|
|
238
238
|
return !variable?.defs.length;
|
|
239
239
|
}
|
|
240
240
|
return false;
|
|
@@ -340,11 +340,27 @@ exports.default = (0, util_1.createRule)({
|
|
|
340
340
|
}
|
|
341
341
|
function checkVariableDeclaration(node) {
|
|
342
342
|
const tsNode = services.esTreeNodeToTSNodeMap.get(node);
|
|
343
|
-
if (tsNode.initializer == null ||
|
|
344
|
-
node.init == null ||
|
|
345
|
-
node.id.typeAnnotation == null) {
|
|
343
|
+
if (tsNode.initializer == null || node.init == null) {
|
|
346
344
|
return;
|
|
347
345
|
}
|
|
346
|
+
if (node.parent.kind === 'using' &&
|
|
347
|
+
hasWellKnownSymbolWithThenableReturn(checker, tsNode.initializer, checker.getTypeAtLocation(tsNode.initializer), 'dispose')) {
|
|
348
|
+
context.report({
|
|
349
|
+
node: node.init,
|
|
350
|
+
messageId: 'voidReturnVariable',
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
if (node.id.typeAnnotation == null) {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
const variableType = services.getTypeAtLocation(node.id);
|
|
357
|
+
if (hasWellKnownSymbolWithVoidReturn(checker, tsNode.name, variableType, 'dispose') &&
|
|
358
|
+
hasWellKnownSymbolWithThenableReturn(checker, tsNode.initializer, checker.getTypeAtLocation(tsNode.initializer), 'dispose')) {
|
|
359
|
+
context.report({
|
|
360
|
+
node: node.init,
|
|
361
|
+
messageId: 'voidReturnVariable',
|
|
362
|
+
});
|
|
363
|
+
}
|
|
348
364
|
// syntactically ignore some known-good cases to avoid touching type info
|
|
349
365
|
if (!isPossiblyFunctionType(node.id.typeAnnotation)) {
|
|
350
366
|
return;
|
|
@@ -763,3 +779,25 @@ function isStaticMember(node) {
|
|
|
763
779
|
node.type === utils_1.AST_NODE_TYPES.AccessorProperty) &&
|
|
764
780
|
node.static);
|
|
765
781
|
}
|
|
782
|
+
function hasWellKnownSymbolWithThenableReturn(checker, node, type, symbolName) {
|
|
783
|
+
return tsutils
|
|
784
|
+
.unionConstituents(checker.getApparentType(type))
|
|
785
|
+
.some(typePart => {
|
|
786
|
+
const symbol = tsutils.getWellKnownSymbolPropertyOfType(typePart, symbolName, checker);
|
|
787
|
+
if (symbol == null) {
|
|
788
|
+
return false;
|
|
789
|
+
}
|
|
790
|
+
return isThenableReturningFunctionType(checker, node, checker.getTypeOfSymbolAtLocation(symbol, node));
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
function hasWellKnownSymbolWithVoidReturn(checker, node, type, symbolName) {
|
|
794
|
+
return tsutils
|
|
795
|
+
.unionConstituents(checker.getApparentType(type))
|
|
796
|
+
.some(typePart => {
|
|
797
|
+
const symbol = tsutils.getWellKnownSymbolPropertyOfType(typePart, symbolName, checker);
|
|
798
|
+
if (symbol == null) {
|
|
799
|
+
return false;
|
|
800
|
+
}
|
|
801
|
+
return isVoidReturningFunctionType(checker, node, checker.getTypeOfSymbolAtLocation(symbol, node));
|
|
802
|
+
});
|
|
803
|
+
}
|
|
@@ -414,7 +414,11 @@ exports.default = (0, util_1.createRule)({
|
|
|
414
414
|
!parent.arguments.includes(node)) {
|
|
415
415
|
return false;
|
|
416
416
|
}
|
|
417
|
-
|
|
417
|
+
// An optional-chained callee (`foo?.bar(...)`) types as `<method> | undefined`,
|
|
418
|
+
// and a union exposes no call signatures — strip the nullability first.
|
|
419
|
+
const calleeType = services
|
|
420
|
+
.getTypeAtLocation(parent.callee)
|
|
421
|
+
.getNonNullableType();
|
|
418
422
|
const signatures = calleeType.getCallSignatures();
|
|
419
423
|
if (signatures.length <= 1) {
|
|
420
424
|
return false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typescript-eslint/eslint-plugin",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.63.0",
|
|
4
4
|
"description": "TypeScript plugin for ESLint",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -49,10 +49,10 @@
|
|
|
49
49
|
"ignore": "^7.0.5",
|
|
50
50
|
"natural-compare": "^1.4.0",
|
|
51
51
|
"ts-api-utils": "^2.5.0",
|
|
52
|
-
"@typescript-eslint/scope-manager": "8.
|
|
53
|
-
"@typescript-eslint/type-utils": "8.
|
|
54
|
-
"@typescript-eslint/utils": "8.
|
|
55
|
-
"@typescript-eslint/visitor-keys": "8.
|
|
52
|
+
"@typescript-eslint/scope-manager": "8.63.0",
|
|
53
|
+
"@typescript-eslint/type-utils": "8.63.0",
|
|
54
|
+
"@typescript-eslint/utils": "8.63.0",
|
|
55
|
+
"@typescript-eslint/visitor-keys": "8.63.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@types/json-schema": "^7.0.15",
|
|
@@ -76,13 +76,13 @@
|
|
|
76
76
|
"typescript": ">=4.8.4 <6.1.0",
|
|
77
77
|
"unist-util-visit": "^5.0.0",
|
|
78
78
|
"vitest": "^4.0.18",
|
|
79
|
-
"@typescript-eslint/rule-
|
|
80
|
-
"@typescript-eslint/rule-
|
|
79
|
+
"@typescript-eslint/rule-schema-to-typescript-types": "8.63.0",
|
|
80
|
+
"@typescript-eslint/rule-tester": "8.63.0"
|
|
81
81
|
},
|
|
82
82
|
"peerDependencies": {
|
|
83
83
|
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
|
|
84
84
|
"typescript": ">=4.8.4 <6.1.0",
|
|
85
|
-
"@typescript-eslint/parser": "^8.
|
|
85
|
+
"@typescript-eslint/parser": "^8.63.0"
|
|
86
86
|
},
|
|
87
87
|
"funding": {
|
|
88
88
|
"type": "opencollective",
|