From 9d1178ef96ffb368456d6c3d3752677b8f42e5da Mon Sep 17 00:00:00 2001 From: Vapurrmaid Date: Sat, 11 Apr 2020 07:43:19 -0400 Subject: [PATCH 1/5] fix(eslint-plugin): suggest within TSModuleDecl --- .../src/rules/no-empty-interface.ts | 54 ++++++++++++++----- .../tests/rules/no-empty-interface.test.ts | 22 ++++++++ 2 files changed, 64 insertions(+), 12 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-empty-interface.ts b/packages/eslint-plugin/src/rules/no-empty-interface.ts index 2e9e61c1e0e..39ecfcba39a 100644 --- a/packages/eslint-plugin/src/rules/no-empty-interface.ts +++ b/packages/eslint-plugin/src/rules/no-empty-interface.ts @@ -1,4 +1,9 @@ import * as util from '../util'; +import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils'; +import { + RuleFix, + RuleFixer, +} from '@typescript-eslint/experimental-utils/dist/ts-eslint'; type Options = [ { @@ -43,6 +48,7 @@ export default util.createRule({ return { TSInterfaceDeclaration(node): void { const sourceCode = context.getSourceCode(); + const filename = context.getFilename(); if (node.body.body.length !== 0) { // interface contains members --> Nothing to report @@ -58,21 +64,45 @@ export default util.createRule({ } else if (extend.length === 1) { // interface extends exactly 1 interface --> Report depending on rule setting if (!allowSingleExtends) { + const fix = (fixer: RuleFixer): RuleFix => { + let typeParam = ''; + if (node.typeParameters) { + typeParam = sourceCode.getText(node.typeParameters); + } + return fixer.replaceText( + node, + `type ${sourceCode.getText( + node.id, + )}${typeParam} = ${sourceCode.getText(extend[0])}`, + ); + }; + + // Check if interface is within ambient declaration + let useAutoFix = true; + if (util.isDefinitionFile(filename)) { + const scope = context.getScope(); + if ( + scope.block.parent && + scope.block.parent.type === + AST_NODE_TYPES.TSModuleDeclaration && + scope.block.parent.declare + ) { + useAutoFix = false; + } + } + context.report({ node: node.id, messageId: 'noEmptyWithSuper', - fix: fixer => { - let typeParam = ''; - if (node.typeParameters) { - typeParam = sourceCode.getText(node.typeParameters); - } - return fixer.replaceText( - node, - `type ${sourceCode.getText( - node.id, - )}${typeParam} = ${sourceCode.getText(extend[0])}`, - ); - }, + fix: useAutoFix ? fix : undefined, + suggest: useAutoFix + ? undefined + : [ + { + messageId: 'noEmptyWithSuper', + fix, + }, + ], }); } } diff --git a/packages/eslint-plugin/tests/rules/no-empty-interface.test.ts b/packages/eslint-plugin/tests/rules/no-empty-interface.test.ts index 840e729f183..01b96561cd0 100644 --- a/packages/eslint-plugin/tests/rules/no-empty-interface.test.ts +++ b/packages/eslint-plugin/tests/rules/no-empty-interface.test.ts @@ -148,5 +148,27 @@ type Foo = Bar }, ], }, + { + filename: 'test.d.ts', + code: ` +declare module FooBar { + type Baz = typeof baz; + export interface Bar extends Baz {} +} + `, + errors: [ + { + messageId: 'noEmptyWithSuper', + line: 4, + }, + ], + // output matches input because a suggestion was made + output: ` +declare module FooBar { + type Baz = typeof baz; + export interface Bar extends Baz {} +} + `, + }, ], }); From 14d5ae0ee764086a5a8100438676b144bacf0852 Mon Sep 17 00:00:00 2001 From: G r e y Date: Sat, 11 Apr 2020 22:10:08 -0500 Subject: [PATCH 2/5] Fixup import Co-Authored-By: Brad Zacher --- packages/eslint-plugin/src/rules/no-empty-interface.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-empty-interface.ts b/packages/eslint-plugin/src/rules/no-empty-interface.ts index 39ecfcba39a..217d6a6d8a7 100644 --- a/packages/eslint-plugin/src/rules/no-empty-interface.ts +++ b/packages/eslint-plugin/src/rules/no-empty-interface.ts @@ -1,9 +1,5 @@ import * as util from '../util'; -import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils'; -import { - RuleFix, - RuleFixer, -} from '@typescript-eslint/experimental-utils/dist/ts-eslint'; +import { AST_NODE_TYPES, TSESLint } from '@typescript-eslint/experimental-utils'; type Options = [ { From a7d6923f0735410b90cf83895d650b02f4abf9bb Mon Sep 17 00:00:00 2001 From: Vapurrmaid Date: Sat, 11 Apr 2020 23:15:04 -0400 Subject: [PATCH 3/5] Fixup imports --- packages/eslint-plugin/src/rules/no-empty-interface.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-empty-interface.ts b/packages/eslint-plugin/src/rules/no-empty-interface.ts index 217d6a6d8a7..8abac25dd30 100644 --- a/packages/eslint-plugin/src/rules/no-empty-interface.ts +++ b/packages/eslint-plugin/src/rules/no-empty-interface.ts @@ -1,5 +1,8 @@ import * as util from '../util'; -import { AST_NODE_TYPES, TSESLint } from '@typescript-eslint/experimental-utils'; +import { + AST_NODE_TYPES, + TSESLint, +} from '@typescript-eslint/experimental-utils'; type Options = [ { @@ -60,7 +63,7 @@ export default util.createRule({ } else if (extend.length === 1) { // interface extends exactly 1 interface --> Report depending on rule setting if (!allowSingleExtends) { - const fix = (fixer: RuleFixer): RuleFix => { + const fix = (fixer: TSESLint.RuleFixer): TSESLint.RuleFix => { let typeParam = ''; if (node.typeParameters) { typeParam = sourceCode.getText(node.typeParameters); From aa386638a5bcac62254e53377c92dbbddb16dadb Mon Sep 17 00:00:00 2001 From: Vapurrmaid Date: Sat, 11 Apr 2020 23:33:07 -0400 Subject: [PATCH 4/5] Use spread to replace duplicated ternary --- .../src/rules/no-empty-interface.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-empty-interface.ts b/packages/eslint-plugin/src/rules/no-empty-interface.ts index 8abac25dd30..d279e9bd4f6 100644 --- a/packages/eslint-plugin/src/rules/no-empty-interface.ts +++ b/packages/eslint-plugin/src/rules/no-empty-interface.ts @@ -93,15 +93,16 @@ export default util.createRule({ context.report({ node: node.id, messageId: 'noEmptyWithSuper', - fix: useAutoFix ? fix : undefined, - suggest: useAutoFix - ? undefined - : [ - { - messageId: 'noEmptyWithSuper', - fix, - }, - ], + ...(useAutoFix + ? { fix } + : { + suggest: [ + { + messageId: 'noEmptyWithSuper', + fix, + }, + ], + }), }); } } From 87a7b135edaac48e9310f1db1fda3d97c0bc0d39 Mon Sep 17 00:00:00 2001 From: Vapurrmaid Date: Sat, 11 Apr 2020 23:59:32 -0400 Subject: [PATCH 5/5] Add suggested fix to test case This should fix the -0.01 coverage report --- .../tests/rules/no-empty-interface.test.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/tests/rules/no-empty-interface.test.ts b/packages/eslint-plugin/tests/rules/no-empty-interface.test.ts index 01b96561cd0..d0281ec77a0 100644 --- a/packages/eslint-plugin/tests/rules/no-empty-interface.test.ts +++ b/packages/eslint-plugin/tests/rules/no-empty-interface.test.ts @@ -155,11 +155,25 @@ declare module FooBar { type Baz = typeof baz; export interface Bar extends Baz {} } - `, + `.trimRight(), errors: [ { messageId: 'noEmptyWithSuper', line: 4, + column: 20, + endLine: 4, + endColumn: 23, + suggestions: [ + { + messageId: 'noEmptyWithSuper', + output: noFormat` +declare module FooBar { + type Baz = typeof baz; + export type Bar = Baz +} + `.trimRight(), + }, + ], }, ], // output matches input because a suggestion was made @@ -168,7 +182,7 @@ declare module FooBar { type Baz = typeof baz; export interface Bar extends Baz {} } - `, + `.trimRight(), }, ], });