diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js index d277ca9ae..9f38ac8e1 100644 --- a/src/rules/no-unused-modules.js +++ b/src/rules/no-unused-modules.js @@ -63,8 +63,6 @@ const IMPORT_DEFAULT_SPECIFIER = 'ImportDefaultSpecifier' const VARIABLE_DECLARATION = 'VariableDeclaration' const FUNCTION_DECLARATION = 'FunctionDeclaration' const CLASS_DECLARATION = 'ClassDeclaration' -const INTERFACE_DECLARATION = 'InterfaceDeclaration' -const TYPE_ALIAS = 'TypeAlias' const TS_INTERFACE_DECLARATION = 'TSInterfaceDeclaration' const TS_TYPE_ALIAS_DECLARATION = 'TSTypeAliasDeclaration' const TS_ENUM_DECLARATION = 'TSEnumDeclaration' @@ -75,8 +73,6 @@ function forEachDeclarationIdentifier(declaration, cb) { if ( declaration.type === FUNCTION_DECLARATION || declaration.type === CLASS_DECLARATION || - declaration.type === INTERFACE_DECLARATION || - declaration.type === TYPE_ALIAS || declaration.type === TS_INTERFACE_DECLARATION || declaration.type === TS_TYPE_ALIAS_DECLARATION || declaration.type === TS_ENUM_DECLARATION diff --git a/tests/files/no-unused-modules/flow/flow-0.js b/tests/files/no-unused-modules/flow/flow-0.js new file mode 100644 index 000000000..b5e5d8b01 --- /dev/null +++ b/tests/files/no-unused-modules/flow/flow-0.js @@ -0,0 +1 @@ +import { type FooType, type FooInterface } from './flow-2'; diff --git a/tests/files/no-unused-modules/flow/flow-1.js b/tests/files/no-unused-modules/flow/flow-1.js new file mode 100644 index 000000000..4828eb575 --- /dev/null +++ b/tests/files/no-unused-modules/flow/flow-1.js @@ -0,0 +1,3 @@ +// @flow strict +export type Bar = number; +export interface BarInterface {}; diff --git a/tests/files/no-unused-modules/flow/flow-2.js b/tests/files/no-unused-modules/flow/flow-2.js new file mode 100644 index 000000000..0c632c247 --- /dev/null +++ b/tests/files/no-unused-modules/flow/flow-2.js @@ -0,0 +1,3 @@ +// @flow strict +export type FooType = string; +export interface FooInterface {}; diff --git a/tests/files/no-unused-modules/flow/flow-3.js b/tests/files/no-unused-modules/flow/flow-3.js new file mode 100644 index 000000000..ade5393a7 --- /dev/null +++ b/tests/files/no-unused-modules/flow/flow-3.js @@ -0,0 +1 @@ +import type { FooType, FooInterface } from './flow-4'; diff --git a/tests/files/no-unused-modules/flow/flow-4.js b/tests/files/no-unused-modules/flow/flow-4.js new file mode 100644 index 000000000..0c632c247 --- /dev/null +++ b/tests/files/no-unused-modules/flow/flow-4.js @@ -0,0 +1,3 @@ +// @flow strict +export type FooType = string; +export interface FooInterface {}; diff --git a/tests/files/no-unused-modules/typescript/file-ts-a-import-type.ts b/tests/files/no-unused-modules/typescript/file-ts-a-import-type.ts new file mode 100644 index 000000000..357d890b9 --- /dev/null +++ b/tests/files/no-unused-modules/typescript/file-ts-a-import-type.ts @@ -0,0 +1,9 @@ +import type {b} from './file-ts-b-used-as-type'; +import type {c} from './file-ts-c-used-as-type'; +import type {d} from './file-ts-d-used-as-type'; +import type {e} from './file-ts-e-used-as-type'; + +const a: typeof b = 2; +const a2: c = {}; +const a3: d = {}; +const a4: typeof e = undefined; diff --git a/tests/files/no-unused-modules/typescript/file-ts-a.ts b/tests/files/no-unused-modules/typescript/file-ts-a.ts index a5cc56671..2e7984cb9 100644 --- a/tests/files/no-unused-modules/typescript/file-ts-a.ts +++ b/tests/files/no-unused-modules/typescript/file-ts-a.ts @@ -3,6 +3,6 @@ import {c} from './file-ts-c'; import {d} from './file-ts-d'; import {e} from './file-ts-e'; -export const a = b + 1 + e.f; -export const a2: c = {}; -export const a3: d = {}; +const a = b + 1 + e.f; +const a2: c = {}; +const a3: d = {}; diff --git a/tests/files/no-unused-modules/typescript/file-ts-b-unused.ts b/tests/files/no-unused-modules/typescript/file-ts-b-unused.ts new file mode 100644 index 000000000..202103085 --- /dev/null +++ b/tests/files/no-unused-modules/typescript/file-ts-b-unused.ts @@ -0,0 +1 @@ +export const b = 2; diff --git a/tests/files/no-unused-modules/typescript/file-ts-b-used-as-type.ts b/tests/files/no-unused-modules/typescript/file-ts-b-used-as-type.ts new file mode 100644 index 000000000..202103085 --- /dev/null +++ b/tests/files/no-unused-modules/typescript/file-ts-b-used-as-type.ts @@ -0,0 +1 @@ +export const b = 2; diff --git a/tests/files/no-unused-modules/typescript/file-ts-c-unused.ts b/tests/files/no-unused-modules/typescript/file-ts-c-unused.ts new file mode 100644 index 000000000..aedf4062b --- /dev/null +++ b/tests/files/no-unused-modules/typescript/file-ts-c-unused.ts @@ -0,0 +1 @@ +export interface c {}; diff --git a/tests/files/no-unused-modules/typescript/file-ts-c-used-as-type.ts b/tests/files/no-unused-modules/typescript/file-ts-c-used-as-type.ts new file mode 100644 index 000000000..aedf4062b --- /dev/null +++ b/tests/files/no-unused-modules/typescript/file-ts-c-used-as-type.ts @@ -0,0 +1 @@ +export interface c {}; diff --git a/tests/files/no-unused-modules/typescript/file-ts-d-unused.ts b/tests/files/no-unused-modules/typescript/file-ts-d-unused.ts new file mode 100644 index 000000000..7679b3de0 --- /dev/null +++ b/tests/files/no-unused-modules/typescript/file-ts-d-unused.ts @@ -0,0 +1 @@ +export type d = {}; diff --git a/tests/files/no-unused-modules/typescript/file-ts-d-used-as-type.ts b/tests/files/no-unused-modules/typescript/file-ts-d-used-as-type.ts new file mode 100644 index 000000000..7679b3de0 --- /dev/null +++ b/tests/files/no-unused-modules/typescript/file-ts-d-used-as-type.ts @@ -0,0 +1 @@ +export type d = {}; diff --git a/tests/files/no-unused-modules/typescript/file-ts-e-unused.ts b/tests/files/no-unused-modules/typescript/file-ts-e-unused.ts new file mode 100644 index 000000000..d1787a11a --- /dev/null +++ b/tests/files/no-unused-modules/typescript/file-ts-e-unused.ts @@ -0,0 +1 @@ +export enum e { f }; diff --git a/tests/files/no-unused-modules/typescript/file-ts-e-used-as-type.ts b/tests/files/no-unused-modules/typescript/file-ts-e-used-as-type.ts new file mode 100644 index 000000000..d1787a11a --- /dev/null +++ b/tests/files/no-unused-modules/typescript/file-ts-e-used-as-type.ts @@ -0,0 +1 @@ +export enum e { f }; diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js index b6554d129..3e63a6ac9 100644 --- a/tests/src/rules/no-unused-modules.js +++ b/tests/src/rules/no-unused-modules.js @@ -744,65 +744,96 @@ describe('Avoid errors if re-export all from umd compiled library', () => { }) }) -describe('correctly work with Typescript only files', () => { - typescriptRuleTester.run('no-unused-modules', rule, { - valid: [ - test({ - options: unusedExportsTypescriptOptions, - code: 'import a from "file-ts-a";', - parser: require.resolve('babel-eslint'), - filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'), - }), - ], - invalid: [ - test({ - options: unusedExportsTypescriptOptions, - code: `export const b = 2;`, - parser: require.resolve('babel-eslint'), - filename: testFilePath('./no-unused-modules/typescript/file-ts-b.ts'), - errors: [ - error(`exported declaration 'b' not used within other modules`), - ], - }), - test({ - options: unusedExportsTypescriptOptions, - code: `export interface c {};`, - parser: require.resolve('babel-eslint'), - filename: testFilePath('./no-unused-modules/typescript/file-ts-c.ts'), - errors: [ - error(`exported declaration 'c' not used within other modules`), - ], - }), - test({ - options: unusedExportsTypescriptOptions, - code: `export type d = {};`, - parser: require.resolve('babel-eslint'), - filename: testFilePath('./no-unused-modules/typescript/file-ts-d.ts'), - errors: [ - error(`exported declaration 'd' not used within other modules`), - ], - }), - ], - }) -}) - context('TypeScript', function () { getTSParsers().forEach((parser) => { typescriptRuleTester.run('no-unused-modules', rule, { valid: [ test({ options: unusedExportsTypescriptOptions, - code: 'import a from "file-ts-a";', + code: ` + import {b} from './file-ts-b'; + import {c} from './file-ts-c'; + import {d} from './file-ts-d'; + import {e} from './file-ts-e'; + + const a = b + 1 + e.f; + const a2: c = {}; + const a3: d = {}; + `, parser: parser, filename: testFilePath('./no-unused-modules/typescript/file-ts-a.ts'), }), + test({ + options: unusedExportsTypescriptOptions, + code: `export const b = 2;`, + parser: parser, + filename: testFilePath('./no-unused-modules/typescript/file-ts-b.ts'), + }), + test({ + options: unusedExportsTypescriptOptions, + code: `export interface c {};`, + parser: parser, + filename: testFilePath('./no-unused-modules/typescript/file-ts-c.ts'), + }), + test({ + options: unusedExportsTypescriptOptions, + code: `export type d = {};`, + parser: parser, + filename: testFilePath('./no-unused-modules/typescript/file-ts-d.ts'), + }), + test({ + options: unusedExportsTypescriptOptions, + code: `export enum e { f };`, + parser: parser, + filename: testFilePath('./no-unused-modules/typescript/file-ts-e.ts'), + }), + test({ + options: unusedExportsTypescriptOptions, + code: ` + import type {b} from './file-ts-b-used-as-type'; + import type {c} from './file-ts-c-used-as-type'; + import type {d} from './file-ts-d-used-as-type'; + import type {e} from './file-ts-e-used-as-type'; + + const a: typeof b = 2; + const a2: c = {}; + const a3: d = {}; + const a4: typeof e = undefined; + `, + parser: parser, + filename: testFilePath('./no-unused-modules/typescript/file-ts-a-import-type.ts'), + }), + test({ + options: unusedExportsTypescriptOptions, + code: `export const b = 2;`, + parser: parser, + filename: testFilePath('./no-unused-modules/typescript/file-ts-b-used-as-type.ts'), + }), + test({ + options: unusedExportsTypescriptOptions, + code: `export interface c {};`, + parser: parser, + filename: testFilePath('./no-unused-modules/typescript/file-ts-c-used-as-type.ts'), + }), + test({ + options: unusedExportsTypescriptOptions, + code: `export type d = {};`, + parser: parser, + filename: testFilePath('./no-unused-modules/typescript/file-ts-d-used-as-type.ts'), + }), + test({ + options: unusedExportsTypescriptOptions, + code: `export enum e { f };`, + parser: parser, + filename: testFilePath('./no-unused-modules/typescript/file-ts-e-used-as-type.ts'), + }), ], invalid: [ test({ options: unusedExportsTypescriptOptions, code: `export const b = 2;`, parser: parser, - filename: testFilePath('./no-unused-modules/typescript/file-ts-b.ts'), + filename: testFilePath('./no-unused-modules/typescript/file-ts-b-unused.ts'), errors: [ error(`exported declaration 'b' not used within other modules`), ], @@ -811,7 +842,7 @@ context('TypeScript', function () { options: unusedExportsTypescriptOptions, code: `export interface c {};`, parser: parser, - filename: testFilePath('./no-unused-modules/typescript/file-ts-c.ts'), + filename: testFilePath('./no-unused-modules/typescript/file-ts-c-unused.ts'), errors: [ error(`exported declaration 'c' not used within other modules`), ], @@ -820,7 +851,7 @@ context('TypeScript', function () { options: unusedExportsTypescriptOptions, code: `export type d = {};`, parser: parser, - filename: testFilePath('./no-unused-modules/typescript/file-ts-d.ts'), + filename: testFilePath('./no-unused-modules/typescript/file-ts-d-unused.ts'), errors: [ error(`exported declaration 'd' not used within other modules`), ], @@ -829,7 +860,7 @@ context('TypeScript', function () { options: unusedExportsTypescriptOptions, code: `export enum e { f };`, parser: parser, - filename: testFilePath('./no-unused-modules/typescript/file-ts-e.ts'), + filename: testFilePath('./no-unused-modules/typescript/file-ts-e-unused.ts'), errors: [ error(`exported declaration 'e' not used within other modules`), ], @@ -862,3 +893,51 @@ describe('correctly work with JSX only files', () => { ], }) }) + +describe('ignore flow types', () => { + ruleTester.run('no-unused-modules', rule, { + valid: [ + test({ + options: unusedExportsOptions, + code: 'import { type FooType, type FooInterface } from "./flow-2";', + parser: require.resolve('babel-eslint'), + filename: testFilePath('./no-unused-modules/flow/flow-0.js'), + }), + test({ + options: unusedExportsOptions, + code: `// @flow strict + export type FooType = string; + export interface FooInterface {}; + `, + parser: require.resolve('babel-eslint'), + filename: testFilePath('./no-unused-modules/flow/flow-2.js'), + }), + test({ + options: unusedExportsOptions, + code: 'import type { FooType, FooInterface } from "./flow-4";', + parser: require.resolve('babel-eslint'), + filename: testFilePath('./no-unused-modules/flow/flow-3.js'), + }), + test({ + options: unusedExportsOptions, + code: `// @flow strict + export type FooType = string; + export interface FooInterface {}; + `, + parser: require.resolve('babel-eslint'), + filename: testFilePath('./no-unused-modules/flow/flow-4.js'), + }), + test({ + options: unusedExportsOptions, + code: `// @flow strict + export type Bar = number; + export interface BarInterface {}; + `, + parser: require.resolve('babel-eslint'), + filename: testFilePath('./no-unused-modules/flow/flow-1.js'), + }), + ], + invalid: [], + }) +}) +