Skip to content

Commit f6e5118

Browse files
uniqueiniquitybradzacher
authored andcommitted
fix(eslint-plugin): fix false positives for adjacent-overload-signatures regarding computed property names (typescript-eslint#340)
Currently, the name of a method definition or a class property is always assumed to be a literal or an identifier. However, this fails to account for computed property names. In those cases, we currently sometimes give the name for a method definition with a computed name as `undefined`, which as a result causes methods with differing computed property names to be marked as overloads of each other. In this PR, we slice the text of the computed property name out to handle these cases.
1 parent b66363a commit f6e5118

File tree

8 files changed

+47
-5
lines changed

8 files changed

+47
-5
lines changed

packages/eslint-plugin/src/rules/adjacent-overload-signatures.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ export default util.createRule({
2626
},
2727
defaultOptions: [],
2828
create(context) {
29+
const sourceCode = context.getSourceCode();
30+
2931
/**
3032
* Gets the name of the member being processed.
3133
* @param member the member being processed.
@@ -57,7 +59,7 @@ export default util.createRule({
5759
case AST_NODE_TYPES.TSConstructSignatureDeclaration:
5860
return 'new';
5961
case AST_NODE_TYPES.MethodDefinition:
60-
return util.getNameFromPropertyName(member.key);
62+
return util.getNameFromClassMember(member, sourceCode);
6163
}
6264

6365
return null;

packages/eslint-plugin/src/rules/explicit-member-accessibility.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export default util.createRule({
2020
},
2121
defaultOptions: [],
2222
create(context) {
23+
const sourceCode = context.getSourceCode();
2324
/**
2425
* Checks if a method declaration has an accessibility modifier.
2526
* @param methodDefinition The node representing a MethodDefinition.
@@ -36,7 +37,7 @@ export default util.createRule({
3637
messageId: 'missingAccessibility',
3738
data: {
3839
type: 'method definition',
39-
name: util.getNameFromPropertyName(methodDefinition.key),
40+
name: util.getNameFromClassMember(methodDefinition, sourceCode),
4041
},
4142
});
4243
}

packages/eslint-plugin/src/rules/member-naming.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ export default util.createRule<Options, MessageIds>({
5151
},
5252
defaultOptions: [{}],
5353
create(context, [config]) {
54+
const sourceCode = context.getSourceCode();
55+
5456
const conventions = (Object.keys(config) as Modifiers[]).reduce<
5557
Config<RegExp>
5658
>((acc, accessibility) => {
@@ -69,7 +71,7 @@ export default util.createRule<Options, MessageIds>({
6971
function validateName(
7072
node: TSESTree.MethodDefinition | TSESTree.ClassProperty,
7173
): void {
72-
const name = util.getNameFromPropertyName(node.key);
74+
const name = util.getNameFromClassMember(node, sourceCode);
7375
const accessibility: Modifiers = node.accessibility || 'public';
7476
const convention = conventions[accessibility];
7577

packages/eslint-plugin/src/rules/member-ordering.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ export default util.createRule<Options, MessageIds>({
164164
},
165165
],
166166
create(context, [options]) {
167+
const sourceCode = context.getSourceCode();
168+
167169
const functionExpressions = [
168170
AST_NODE_TYPES.FunctionExpression,
169171
AST_NODE_TYPES.ArrowFunctionExpression,
@@ -213,7 +215,7 @@ export default util.createRule<Options, MessageIds>({
213215
case AST_NODE_TYPES.MethodDefinition:
214216
return node.kind === 'constructor'
215217
? 'constructor'
216-
: util.getNameFromPropertyName(node.key);
218+
: util.getNameFromClassMember(node, sourceCode);
217219
case AST_NODE_TYPES.TSConstructSignatureDeclaration:
218220
return 'new';
219221
default:

packages/eslint-plugin/src/util/misc.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree';
66
import RuleModule from 'ts-eslint';
7+
import { SourceCode } from 'ts-eslint';
78

89
/**
910
* Check if the context file name is *.ts or *.tsx
@@ -63,3 +64,31 @@ export function getNameFromPropertyName(
6364
}
6465
return `${propertyName.value}`;
6566
}
67+
68+
/**
69+
* Gets a string name representation of the name of the given MethodDefinition
70+
* or ClassProperty node, with handling for computed property names.
71+
*/
72+
export function getNameFromClassMember(
73+
methodDefinition: TSESTree.MethodDefinition | TSESTree.ClassProperty,
74+
sourceCode: SourceCode,
75+
): string {
76+
if (keyCanBeReadAsPropertyName(methodDefinition.key)) {
77+
return getNameFromPropertyName(methodDefinition.key);
78+
}
79+
80+
return sourceCode.text.slice(...methodDefinition.key.range);
81+
}
82+
83+
/**
84+
* This covers both actual property names, as well as computed properties that are either
85+
* an identifier or a literal at the top level.
86+
*/
87+
function keyCanBeReadAsPropertyName(
88+
node: TSESTree.Expression,
89+
): node is TSESTree.PropertyName {
90+
return (
91+
node.type === AST_NODE_TYPES.Literal ||
92+
node.type === AST_NODE_TYPES.Identifier
93+
);
94+
}

packages/eslint-plugin/tests/rules/adjacent-overload-signatures.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,11 @@ class Test {
217217
// examples from https://github.com/nzakas/eslint-plugin-typescript/issues/138
218218
'export default function<T>(foo : T) {}',
219219
'export default function named<T>(foo : T) {}',
220+
`
221+
interface Foo {
222+
[Symbol.toStringTag](): void;
223+
[Symbol.iterator](): void;
224+
}`,
220225
],
221226
invalid: [
222227
{

packages/eslint-plugin/typings/ts-eslint.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,7 @@ declare module 'ts-eslint' {
683683
RuleMetaData,
684684
RuleMetaDataDocs,
685685
Scope,
686+
SourceCode,
686687
};
687688
export default RuleModule;
688689
}

packages/typescript-estree/src/ts-estree/ts-estree.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ interface LiteralBase extends BaseNode {
500500
}
501501

502502
interface MethodDefinitionBase extends BaseNode {
503-
key: PropertyName;
503+
key: Expression;
504504
value: FunctionExpression | TSEmptyBodyFunctionExpression;
505505
computed: boolean;
506506
static: boolean;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy