Skip to content

Commit e012049

Browse files
authored
fix(eslint-plugin): [method-signature-style] don't auto-fix interfaces within namespaces (typescript-eslint#2678)
1 parent 5225a76 commit e012049

File tree

2 files changed

+99
-43
lines changed

2 files changed

+99
-43
lines changed

packages/eslint-plugin/src/rules/method-signature-style.ts

Lines changed: 76 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,21 @@ export default util.createRule<Options, MessageIds>({
9797
return '';
9898
}
9999

100+
function isNodeParentModuleDeclaration(node: TSESTree.Node): boolean {
101+
if (!node.parent) {
102+
return false;
103+
}
104+
105+
if (node.parent.type === AST_NODE_TYPES.TSModuleDeclaration) {
106+
return true;
107+
}
108+
109+
if (node.parent.type === AST_NODE_TYPES.Program) {
110+
return false;
111+
}
112+
return isNodeParentModuleDeclaration(node.parent);
113+
}
114+
100115
return {
101116
TSMethodSignature(methodNode): void {
102117
if (mode === 'method') {
@@ -112,61 +127,79 @@ export default util.createRule<Options, MessageIds>({
112127
getMethodKey(element) === getMethodKey(methodNode),
113128
)
114129
: [];
130+
const isParentModule = isNodeParentModuleDeclaration(methodNode);
115131

116132
if (duplicatedKeyMethodNodes.length > 0) {
133+
if (isParentModule) {
134+
context.report({
135+
node: methodNode,
136+
messageId: 'errorMethod',
137+
});
138+
} else {
139+
context.report({
140+
node: methodNode,
141+
messageId: 'errorMethod',
142+
*fix(fixer) {
143+
const methodNodes = [
144+
methodNode,
145+
...duplicatedKeyMethodNodes,
146+
].sort((a, b) => (a.range[0] < b.range[0] ? -1 : 1));
147+
const typeString = methodNodes.reduce(
148+
(str, node, idx, nodes) => {
149+
const params = getMethodParams(node);
150+
const returnType = getMethodReturnType(node);
151+
return `${str}(${params} => ${returnType})${
152+
idx !== nodes.length - 1 ? ' & ' : ''
153+
}`;
154+
},
155+
'',
156+
);
157+
const key = getMethodKey(methodNode);
158+
const delimiter = getDelimiter(methodNode);
159+
yield fixer.replaceText(
160+
methodNode,
161+
`${key}: ${typeString}${delimiter}`,
162+
);
163+
for (const node of duplicatedKeyMethodNodes) {
164+
const lastToken = sourceCode.getLastToken(node);
165+
if (lastToken) {
166+
const nextToken = sourceCode.getTokenAfter(lastToken);
167+
if (nextToken) {
168+
yield fixer.remove(node);
169+
yield fixer.replaceTextRange(
170+
[lastToken.range[1], nextToken.range[0]],
171+
'',
172+
);
173+
}
174+
}
175+
}
176+
},
177+
});
178+
}
179+
return;
180+
}
181+
182+
if (isParentModule) {
117183
context.report({
118184
node: methodNode,
119185
messageId: 'errorMethod',
120-
*fix(fixer) {
121-
const methodNodes = [
122-
methodNode,
123-
...duplicatedKeyMethodNodes,
124-
].sort((a, b) => (a.range[0] < b.range[0] ? -1 : 1));
125-
const typeString = methodNodes.reduce((str, node, idx, nodes) => {
126-
const params = getMethodParams(node);
127-
const returnType = getMethodReturnType(node);
128-
return `${str}(${params} => ${returnType})${
129-
idx !== nodes.length - 1 ? ' & ' : ''
130-
}`;
131-
}, '');
186+
});
187+
} else {
188+
context.report({
189+
node: methodNode,
190+
messageId: 'errorMethod',
191+
fix: fixer => {
132192
const key = getMethodKey(methodNode);
193+
const params = getMethodParams(methodNode);
194+
const returnType = getMethodReturnType(methodNode);
133195
const delimiter = getDelimiter(methodNode);
134-
yield fixer.replaceText(
196+
return fixer.replaceText(
135197
methodNode,
136-
`${key}: ${typeString}${delimiter}`,
198+
`${key}: ${params} => ${returnType}${delimiter}`,
137199
);
138-
for (const node of duplicatedKeyMethodNodes) {
139-
const lastToken = sourceCode.getLastToken(node);
140-
if (lastToken) {
141-
const nextToken = sourceCode.getTokenAfter(lastToken);
142-
if (nextToken) {
143-
yield fixer.remove(node);
144-
yield fixer.replaceTextRange(
145-
[lastToken.range[1], nextToken.range[0]],
146-
'',
147-
);
148-
}
149-
}
150-
}
151200
},
152201
});
153-
return;
154202
}
155-
156-
context.report({
157-
node: methodNode,
158-
messageId: 'errorMethod',
159-
fix: fixer => {
160-
const key = getMethodKey(methodNode);
161-
const params = getMethodParams(methodNode);
162-
const returnType = getMethodReturnType(methodNode);
163-
const delimiter = getDelimiter(methodNode);
164-
return fixer.replaceText(
165-
methodNode,
166-
`${key}: ${params} => ${returnType}${delimiter}`,
167-
);
168-
},
169-
});
170203
},
171204
TSPropertySignature(propertyNode): void {
172205
const typeNode = propertyNode.typeAnnotation?.typeAnnotation;

packages/eslint-plugin/tests/rules/method-signature-style.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,5 +348,28 @@ interface Foo {
348348
},
349349
],
350350
},
351+
{
352+
code: noFormat`
353+
declare global {
354+
namespace jest {
355+
interface Matchers<R, T> {
356+
// Add overloads specific to the DOM
357+
toHaveProp<K extends keyof DomPropsOf<T>>(name: K, value?: DomPropsOf<T>[K]): R;
358+
toHaveProps(props: Partial<DomPropsOf<T>>): R;
359+
}
360+
}
361+
}
362+
`,
363+
errors: [
364+
{
365+
messageId: 'errorMethod',
366+
line: 6,
367+
},
368+
{
369+
messageId: 'errorMethod',
370+
line: 7,
371+
},
372+
],
373+
},
351374
],
352375
});

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