From 916a6669f82efbef386e751583380059348fbd3b Mon Sep 17 00:00:00 2001 From: Idan Attias Date: Mon, 21 Jun 2021 13:20:43 +0300 Subject: [PATCH] feat(eslint-plugin): [no-redeclare] ignoreDeclarationMerge of enum+namespace --- .../eslint-plugin/docs/rules/no-redeclare.md | 1 + .../eslint-plugin/src/rules/no-redeclare.ts | 27 ++++++++++++++++++- .../tests/rules/no-redeclare.test.ts | 24 +++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/docs/rules/no-redeclare.md b/packages/eslint-plugin/docs/rules/no-redeclare.md index 4b5164d6f0e0..539e691cfb26 100644 --- a/packages/eslint-plugin/docs/rules/no-redeclare.md +++ b/packages/eslint-plugin/docs/rules/no-redeclare.md @@ -41,6 +41,7 @@ When set to `true`, the rule will ignore declaration merges between the followin - class + namespace - class + interface + namespace - function + namespace +- enum + namespace Examples of **correct** code with `{ ignoreDeclarationMerge: true }`: diff --git a/packages/eslint-plugin/src/rules/no-redeclare.ts b/packages/eslint-plugin/src/rules/no-redeclare.ts index 399966b16d2c..ae4b2e9a3f5a 100644 --- a/packages/eslint-plugin/src/rules/no-redeclare.ts +++ b/packages/eslint-plugin/src/rules/no-redeclare.ts @@ -63,6 +63,10 @@ export default util.createRule({ AST_NODE_TYPES.TSModuleDeclaration, AST_NODE_TYPES.FunctionDeclaration, ]); + const ENUM_DECLARATION_MERGE_NODES = new Set([ + AST_NODE_TYPES.TSEnumDeclaration, + AST_NODE_TYPES.TSModuleDeclaration, + ]); function* iterateDeclarations(variable: TSESLint.Scope.Variable): Generator< { @@ -164,12 +168,33 @@ export default util.createRule({ return; } - // there's more than one class declaration, which needs to be reported + // there's more than one function declaration, which needs to be reported for (const { identifier } of functionDecls) { yield { type: 'syntax', node: identifier, loc: identifier.loc }; } return; } + + if ( + // enum + namespace merging + identifiers.every(({ parent }) => + ENUM_DECLARATION_MERGE_NODES.has(parent.type), + ) + ) { + const enumDecls = identifiers.filter( + ({ parent }) => parent.type === AST_NODE_TYPES.TSEnumDeclaration, + ); + if (enumDecls.length === 1) { + // safe declaration merging + return; + } + + // there's more than one enum declaration, which needs to be reported + for (const { identifier } of enumDecls) { + yield { type: 'syntax', node: identifier, loc: identifier.loc }; + } + return; + } } for (const { identifier } of identifiers) { diff --git a/packages/eslint-plugin/tests/rules/no-redeclare.test.ts b/packages/eslint-plugin/tests/rules/no-redeclare.test.ts index f227c5ac8919..c371a738755e 100644 --- a/packages/eslint-plugin/tests/rules/no-redeclare.test.ts +++ b/packages/eslint-plugin/tests/rules/no-redeclare.test.ts @@ -122,6 +122,13 @@ namespace A {} code: ` interface A {} class A {} +namespace A {} + `, + options: [{ ignoreDeclarationMerge: true }], + }, + { + code: ` +enum A {} namespace A {} `, options: [{ ignoreDeclarationMerge: true }], @@ -605,6 +612,23 @@ class A {} }, { code: ` +enum A {} +namespace A {} +enum A {} + `, + options: [{ ignoreDeclarationMerge: true }], + errors: [ + { + messageId: 'redeclared', + data: { + id: 'A', + }, + line: 4, + }, + ], + }, + { + code: ` function A() {} class A {} namespace A {}