From f14aa956e8e7403f0dff2b8581e8c572bd1d7a52 Mon Sep 17 00:00:00 2001 From: Richard Cooke Date: Wed, 16 Feb 2022 15:48:01 +0000 Subject: [PATCH] `prefer-export-from`: Fix TypeScript compatibility (#1728) Co-authored-by: fisker Cheung --- rules/prefer-export-from.js | 32 +- test/prefer-export-from.mjs | 114 ++++- test/snapshots/prefer-export-from.mjs.md | 466 +++++++++++++++++++++ test/snapshots/prefer-export-from.mjs.snap | Bin 3598 -> 4547 bytes 4 files changed, 604 insertions(+), 8 deletions(-) diff --git a/rules/prefer-export-from.js b/rules/prefer-export-from.js index b440360dd5..ee979cad27 100644 --- a/rules/prefer-export-from.js +++ b/rules/prefer-export-from.js @@ -26,6 +26,10 @@ const getSpecifierName = node => { } }; +const isTypeExport = specifier => specifier.exportKind === 'type' || specifier.parent.exportKind === 'type'; + +const isTypeImport = specifier => specifier.importKind === 'type' || specifier.parent.importKind === 'type'; + function * removeSpecifier(node, fixer, sourceCode) { const {parent} = node; const {specifiers} = parent; @@ -108,7 +112,17 @@ function getFixFunction({ const importDeclaration = imported.declaration; const sourceNode = importDeclaration.source; const sourceValue = sourceNode.value; - const exportDeclaration = exportDeclarations.find(({source}) => source.value === sourceValue); + const shouldExportAsType = imported.isTypeImport || exported.isTypeExport; + + let exportDeclaration; + if (shouldExportAsType) { + // If a type export declaration already exists, reuse it, else use a value export declaration with an inline type specifier. + exportDeclaration = exportDeclarations.find(({source, exportKind}) => source.value === sourceValue && exportKind === 'type'); + } + + if (!exportDeclaration) { + exportDeclaration = exportDeclarations.find(({source, exportKind}) => source.value === sourceValue && exportKind !== 'type'); + } /** @param {import('eslint').Rule.RuleFixer} fixer */ return function * (fixer) { @@ -118,24 +132,29 @@ function getFixFunction({ `\nexport * as ${exported.text} ${getSourceAndAssertionsText(importDeclaration, sourceCode)}`, ); } else { - const specifier = exported.name === imported.name + let specifierText = exported.name === imported.name ? exported.text : `${imported.text} as ${exported.text}`; + // Add an inline type specifier if the value is a type and the export deceleration is a value deceleration + if (shouldExportAsType && (!exportDeclaration || exportDeclaration.exportKind !== 'type')) { + specifierText = `type ${specifierText}`; + } + if (exportDeclaration) { const lastSpecifier = exportDeclaration.specifiers[exportDeclaration.specifiers.length - 1]; // `export {} from 'foo';` if (lastSpecifier) { - yield fixer.insertTextAfter(lastSpecifier, `, ${specifier}`); + yield fixer.insertTextAfter(lastSpecifier, `, ${specifierText}`); } else { const openingBraceToken = sourceCode.getFirstToken(exportDeclaration, isOpeningBraceToken); - yield fixer.insertTextAfter(openingBraceToken, specifier); + yield fixer.insertTextAfter(openingBraceToken, specifierText); } } else { yield fixer.insertTextAfter( program, - `\nexport {${specifier}} ${getSourceAndAssertionsText(importDeclaration, sourceCode)}`, + `\nexport {${specifierText}} ${getSourceAndAssertionsText(importDeclaration, sourceCode)}`, ); } } @@ -156,6 +175,7 @@ function getExported(identifier, context, sourceCode) { node: parent, name: DEFAULT_SPECIFIER_NAME, text: 'default', + isTypeExport: isTypeExport(parent), }; case 'ExportSpecifier': @@ -163,6 +183,7 @@ function getExported(identifier, context, sourceCode) { node: parent, name: getSpecifierName(parent.exported), text: sourceCode.getText(parent.exported), + isTypeExport: isTypeExport(parent), }; case 'VariableDeclarator': { @@ -212,6 +233,7 @@ function getImported(variable, sourceCode) { node: specifier, declaration: specifier.parent, variable, + isTypeImport: isTypeImport(specifier), }; switch (specifier.type) { diff --git a/test/prefer-export-from.mjs b/test/prefer-export-from.mjs index 63b9247bb6..346bd37794 100644 --- a/test/prefer-export-from.mjs +++ b/test/prefer-export-from.mjs @@ -1,5 +1,5 @@ import outdent from 'outdent'; -import {getTester} from './utils/test.mjs'; +import {getTester, parsers} from './utils/test.mjs'; const {test} = getTester(import.meta); @@ -318,7 +318,10 @@ test.snapshot({ ], }); -test.typescript({ +test.snapshot({ + testerOptions: { + parser: parsers.typescript, + }, valid: [ // #1579 outdent` @@ -347,8 +350,113 @@ test.typescript({ type AceEditor = import("ace-builds").Ace.Editor; export {AceEditor}; `, + 'export type { bar, foo } from "foo";', + ], + invalid: [ + outdent` + import { foo } from "foo"; + export { foo }; + export type { bar } from "foo"; + `, + outdent` + import { foo } from "foo"; + export { foo }; + export { type bar } from "foo"; + `, + outdent` + import { foo } from 'foo'; + export { foo }; + export type { bar } from "foo"; + export { baz } from "foo"; + `, + outdent` + import { foo } from 'foo'; + export { foo }; + export { type bar } from "foo"; + export { baz } from "foo"; + `, + outdent` + import type { foo } from "foo"; + export type { foo }; + export type { bar } from "foo"; + `, + outdent` + import { foo } from 'foo'; + export { foo }; + export { baz } from "foo"; + export { type bar } from "foo"; + `, + outdent` + import type { foo } from "foo"; + export type { foo }; + export { type bar } from "foo"; + `, + outdent` + import type { foo } from 'foo'; + export type { foo }; + export type { bar } from "foo"; + export { baz } from "foo"; + `, + outdent` + import type { foo } from 'foo'; + export type { foo }; + export { baz } from "foo"; + export type { bar } from "foo"; + `, + outdent` + import type { foo } from 'foo'; + export type { foo }; + export { type bar } from "foo"; + export { baz } from "foo"; + `, + outdent` + import type { foo } from 'foo'; + export type { foo }; + export { baz } from "foo"; + export { type bar } from "foo"; + `, + outdent` + import { type foo } from 'foo'; + export type { foo }; + `, + outdent` + import { foo } from 'foo'; + export type { foo }; + `, + outdent` + import type { foo } from 'foo'; + export { type foo }; + `, + outdent` + import type foo from "foo"; + export default foo + `, + outdent` + import {type foo} from 'foo'; + export {type foo as bar}; + `, + outdent` + import {type foo} from 'foo'; + export {type foo as bar}; + export {type bar} from 'foo'; + `, + outdent` + import {type foo as bar} from 'foo'; + export {type bar as baz}; + `, + outdent` + import {type foo as foo} from 'foo'; + export {type foo as bar}; + `, + outdent` + import {type foo as bar} from 'foo'; + export {type bar as bar}; + `, + outdent` + import {type foo as bar} from 'foo'; + export {type bar as foo}; + `, ], - invalid: [], }); // `ignoreUsedVariables` diff --git a/test/snapshots/prefer-export-from.mjs.md b/test/snapshots/prefer-export-from.mjs.md index bfdc266eb5..0b437ae40b 100644 --- a/test/snapshots/prefer-export-from.mjs.md +++ b/test/snapshots/prefer-export-from.mjs.md @@ -1282,6 +1282,472 @@ Generated by [AVA](https://avajs.dev). | ^^^ Use \`export…from\` to re-export \`foo\`.␊ ` +## Invalid #1 + 1 | import { foo } from "foo"; + 2 | export { foo }; + 3 | export type { bar } from "foo"; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export type { bar } from "foo";␊ + 4 | export {foo} from "foo";␊ + ` + +> Error 1/1 + + `␊ + 1 | import { foo } from "foo";␊ + > 2 | export { foo };␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ + 3 | export type { bar } from "foo";␊ + ` + +## Invalid #2 + 1 | import { foo } from "foo"; + 2 | export { foo }; + 3 | export { type bar } from "foo"; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export { type bar, foo } from "foo";␊ + ` + +> Error 1/1 + + `␊ + 1 | import { foo } from "foo";␊ + > 2 | export { foo };␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ + 3 | export { type bar } from "foo";␊ + ` + +## Invalid #3 + 1 | import { foo } from 'foo'; + 2 | export { foo }; + 3 | export type { bar } from "foo"; + 4 | export { baz } from "foo"; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export type { bar } from "foo";␊ + 4 | export { baz, foo } from "foo";␊ + ` + +> Error 1/1 + + `␊ + 1 | import { foo } from 'foo';␊ + > 2 | export { foo };␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ + 3 | export type { bar } from "foo";␊ + 4 | export { baz } from "foo";␊ + ` + +## Invalid #4 + 1 | import { foo } from 'foo'; + 2 | export { foo }; + 3 | export { type bar } from "foo"; + 4 | export { baz } from "foo"; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export { type bar, foo } from "foo";␊ + 4 | export { baz } from "foo";␊ + ` + +> Error 1/1 + + `␊ + 1 | import { foo } from 'foo';␊ + > 2 | export { foo };␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ + 3 | export { type bar } from "foo";␊ + 4 | export { baz } from "foo";␊ + ` + +## Invalid #5 + 1 | import type { foo } from "foo"; + 2 | export type { foo }; + 3 | export type { bar } from "foo"; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export type { bar, foo } from "foo";␊ + ` + +> Error 1/1 + + `␊ + 1 | import type { foo } from "foo";␊ + > 2 | export type { foo };␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ + 3 | export type { bar } from "foo";␊ + ` + +## Invalid #6 + 1 | import { foo } from 'foo'; + 2 | export { foo }; + 3 | export { baz } from "foo"; + 4 | export { type bar } from "foo"; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export { baz, foo } from "foo";␊ + 4 | export { type bar } from "foo";␊ + ` + +> Error 1/1 + + `␊ + 1 | import { foo } from 'foo';␊ + > 2 | export { foo };␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ + 3 | export { baz } from "foo";␊ + 4 | export { type bar } from "foo";␊ + ` + +## Invalid #7 + 1 | import type { foo } from "foo"; + 2 | export type { foo }; + 3 | export { type bar } from "foo"; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export { type bar, type foo } from "foo";␊ + ` + +> Error 1/1 + + `␊ + 1 | import type { foo } from "foo";␊ + > 2 | export type { foo };␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ + 3 | export { type bar } from "foo";␊ + ` + +## Invalid #8 + 1 | import type { foo } from 'foo'; + 2 | export type { foo }; + 3 | export type { bar } from "foo"; + 4 | export { baz } from "foo"; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export type { bar, foo } from "foo";␊ + 4 | export { baz } from "foo";␊ + ` + +> Error 1/1 + + `␊ + 1 | import type { foo } from 'foo';␊ + > 2 | export type { foo };␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ + 3 | export type { bar } from "foo";␊ + 4 | export { baz } from "foo";␊ + ` + +## Invalid #9 + 1 | import type { foo } from 'foo'; + 2 | export type { foo }; + 3 | export { baz } from "foo"; + 4 | export type { bar } from "foo"; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export { baz } from "foo";␊ + 4 | export type { bar, foo } from "foo";␊ + ` + +> Error 1/1 + + `␊ + 1 | import type { foo } from 'foo';␊ + > 2 | export type { foo };␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ + 3 | export { baz } from "foo";␊ + 4 | export type { bar } from "foo";␊ + ` + +## Invalid #10 + 1 | import type { foo } from 'foo'; + 2 | export type { foo }; + 3 | export { type bar } from "foo"; + 4 | export { baz } from "foo"; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export { type bar, type foo } from "foo";␊ + 4 | export { baz } from "foo";␊ + ` + +> Error 1/1 + + `␊ + 1 | import type { foo } from 'foo';␊ + > 2 | export type { foo };␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ + 3 | export { type bar } from "foo";␊ + 4 | export { baz } from "foo";␊ + ` + +## Invalid #11 + 1 | import type { foo } from 'foo'; + 2 | export type { foo }; + 3 | export { baz } from "foo"; + 4 | export { type bar } from "foo"; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export { baz, type foo } from "foo";␊ + 4 | export { type bar } from "foo";␊ + ` + +> Error 1/1 + + `␊ + 1 | import type { foo } from 'foo';␊ + > 2 | export type { foo };␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ + 3 | export { baz } from "foo";␊ + 4 | export { type bar } from "foo";␊ + ` + +## Invalid #12 + 1 | import { type foo } from 'foo'; + 2 | export type { foo }; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {type foo} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + 1 | import { type foo } from 'foo';␊ + > 2 | export type { foo };␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ + ` + +## Invalid #13 + 1 | import { foo } from 'foo'; + 2 | export type { foo }; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {type foo} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + 1 | import { foo } from 'foo';␊ + > 2 | export type { foo };␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ + ` + +## Invalid #14 + 1 | import type { foo } from 'foo'; + 2 | export { type foo }; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {type foo} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + 1 | import type { foo } from 'foo';␊ + > 2 | export { type foo };␊ + | ^^^^^^^^ Use \`export…from\` to re-export \`foo\`.␊ + ` + +## Invalid #15 + 1 | import type foo from "foo"; + 2 | export default foo + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {type default} from "foo";␊ + ` + +> Error 1/1 + + `␊ + 1 | import type foo from "foo";␊ + > 2 | export default foo␊ + | ^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ + ` + +## Invalid #16 + 1 | import {type foo} from 'foo'; + 2 | export {type foo as bar}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {type foo as bar} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + 1 | import {type foo} from 'foo';␊ + > 2 | export {type foo as bar};␊ + | ^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`bar\`.␊ + ` + +## Invalid #17 + 1 | import {type foo} from 'foo'; + 2 | export {type foo as bar}; + 3 | export {type bar} from 'foo'; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {type bar, type foo as bar} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + 1 | import {type foo} from 'foo';␊ + > 2 | export {type foo as bar};␊ + | ^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`bar\`.␊ + 3 | export {type bar} from 'foo';␊ + ` + +## Invalid #18 + 1 | import {type foo as bar} from 'foo'; + 2 | export {type bar as baz}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {type foo as baz} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + 1 | import {type foo as bar} from 'foo';␊ + > 2 | export {type bar as baz};␊ + | ^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`baz\`.␊ + ` + +## Invalid #19 + 1 | import {type foo as foo} from 'foo'; + 2 | export {type foo as bar}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {type foo as bar} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + 1 | import {type foo as foo} from 'foo';␊ + > 2 | export {type foo as bar};␊ + | ^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`bar\`.␊ + ` + +## Invalid #20 + 1 | import {type foo as bar} from 'foo'; + 2 | export {type bar as bar}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {type foo as bar} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + 1 | import {type foo as bar} from 'foo';␊ + > 2 | export {type bar as bar};␊ + | ^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`bar\`.␊ + ` + +## Invalid #21 + 1 | import {type foo as bar} from 'foo'; + 2 | export {type bar as foo}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {type foo} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + 1 | import {type foo as bar} from 'foo';␊ + > 2 | export {type bar as foo};␊ + | ^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`foo\`.␊ + ` + ## Invalid #1 1 | import defaultExport from 'foo'; 2 | export {defaultExport as default}; diff --git a/test/snapshots/prefer-export-from.mjs.snap b/test/snapshots/prefer-export-from.mjs.snap index f69722641f6b987a02b69670c192c8d1e7444ef1..15f693095deae1368fcc4d16b9a03902a20d9f85 100644 GIT binary patch literal 4547 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 literal 3598 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�PmM~8 zPnkSbI|9z2JS0d&Jb%hBGs!_FDVfTez-7j!VVg>tHXRFdn{8l*4bV&0)g|H$D^@e< zTz6Xf_*)q`^!Nqd(*1EYG@-+p+oxG_+*;)1mBX~;1=#o-DgHKvpl~U55GBjG& zZfk5V*NeQXaZ|mgjo_6hFj8`NO@Z+lZg9NFt{RuWE6vKEfcy!bSM$D<=tHmtiZ~5L zd@t|;-+O`7bT7{gnQsOtvF8HPUJ6k9j|85uv%bwwh|QF9#>c(!A^9+e8FR}Y@4oTU#8nP^7%4uL=IPCrj~oCCgWN~bKX2K(SIme UZ>no}&6FGa2LwW>=}A`r08lvT#{d8T