From 7731e236b38c4b56b0aff7a461a088a5b7d4ff21 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Tue, 27 Jul 2021 20:23:07 +0800 Subject: [PATCH 01/21] Add `prefer-export-from` rule --- docs/rules/prefer-export-from.md | 17 + index.js | 1 + package.json | 5 + rules/prefer-export-from.js | 321 +++++++++ test/prefer-export-from.mjs | 194 ++++++ test/snapshots/prefer-export-from.mjs.md | 747 +++++++++++++++++++++ test/snapshots/prefer-export-from.mjs.snap | Bin 0 -> 1803 bytes 7 files changed, 1285 insertions(+) create mode 100644 docs/rules/prefer-export-from.md create mode 100644 rules/prefer-export-from.js create mode 100644 test/prefer-export-from.mjs create mode 100644 test/snapshots/prefer-export-from.mjs.md create mode 100644 test/snapshots/prefer-export-from.mjs.snap diff --git a/docs/rules/prefer-export-from.md b/docs/rules/prefer-export-from.md new file mode 100644 index 0000000000..c3a3b06003 --- /dev/null +++ b/docs/rules/prefer-export-from.md @@ -0,0 +1,17 @@ +# Prefer "export from" syntax when re-exporting. + + + +This rule is fixable. + +## Fail + +```js +const foo = 'unicorn'; +``` + +## Pass + +```js +const foo = 'πŸ¦„'; +``` diff --git a/index.js b/index.js index f95407c5eb..89fd2b944b 100644 --- a/index.js +++ b/index.js @@ -97,6 +97,7 @@ module.exports = { 'unicorn/prefer-dom-node-dataset': 'error', 'unicorn/prefer-dom-node-remove': 'error', 'unicorn/prefer-dom-node-text-content': 'error', + 'unicorn/prefer-export-from': 'error', 'unicorn/prefer-includes': 'error', 'unicorn/prefer-keyboard-event-key': 'error', 'unicorn/prefer-math-trunc': 'error', diff --git a/package.json b/package.json index 35f0cbe6b4..5e85350070 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,12 @@ "enquirer": "2.3.6", "eslint": "^7.28.0", "eslint-ava-rule-tester": "^4.0.0", + "eslint-plugin-ava": "12.0.0", + "eslint-plugin-eslint-comments": "3.2.0", "eslint-plugin-eslint-plugin": "^3.1.0", + "eslint-plugin-node": "11.1.0", + "eslint-plugin-promise": "5.1.0", + "eslint-plugin-unicorn": "34.0.1", "eslint-remote-tester": "^1.2.0", "execa": "^5.1.1", "listr": "^0.14.3", diff --git a/rules/prefer-export-from.js b/rules/prefer-export-from.js new file mode 100644 index 0000000000..591b0da7a3 --- /dev/null +++ b/rules/prefer-export-from.js @@ -0,0 +1,321 @@ +'use strict'; +const {isCommaToken, isOpeningBraceToken, isClosingBraceToken} = require('eslint-utils'); +const MESSAGE_ID = 'prefer-export-from'; +const messages = { + [MESSAGE_ID]: 'Use `export from` syntax to re-export `{{imported}}`.', +}; + +function * removeSpecifier(node, options) { + const {nodes, removedSpecifiers, fixer, sourceCode} = options; + + const {parent} = node; + const {specifiers} = parent; + + if (specifiers.every(specifier => nodes.has(specifier))) { + for (const specifier of specifiers) { + removedSpecifiers.add(specifier); + } + + yield * removeImportOrExport(parent, options); + return; + } + + switch (node.type) { + case 'ExportSpecifier': + case 'ImportSpecifier': { + const hasOtherSpecifiers = specifiers.some(specifier => specifier !== node && specifier.type === node.type); + if (!hasOtherSpecifiers) { + const closingBraceToken = sourceCode.getTokenAfter(node, isClosingBraceToken); + // If there are other specifiers, they have to be default or namespace import/export + // And default or namespace import/export has to write before the named import/export + // So there must be a comma before + const commaToken = sourceCode.getTokenBefore(node, isCommaToken); + yield fixer.replaceTextRange([commaToken.range[0], closingBraceToken.range[1]], ''); + return; + } + // Fallthrough + } + + case 'ImportNamespaceSpecifier': + case 'ImportDefaultSpecifier': { + yield fixer.remove(node); + + const tokenAfter = sourceCode.getTokenAfter(node); + if (isCommaToken(tokenAfter)) { + yield fixer.remove(tokenAfter); + } + + break; + } + + // No default + } +} + +function * removeImportOrExport(node, options) { + switch (node.type) { + case 'ImportSpecifier': + case 'ExportSpecifier': + case 'ImportDefaultSpecifier': + case 'ImportNamespaceSpecifier': { + yield * removeSpecifier(node, options); + return; + } + + case 'ImportDeclaration': + case 'ExportDefaultDeclaration': + case 'ExportNamedDeclaration': { + yield options.fixer.remove(node); + } + + // No default + } +} + +function fix({ + context, + exportDeclarations, + importDeclaration, + imported, + exported, + program, +}) { + const sourceCode = context.getSourceCode(); + const sourceNode = importDeclaration.source; + const sourceValue = sourceNode.value; + const sourceText = sourceCode.getText(sourceNode); + const exportDeclaration = exportDeclarations.find(({source}) => source.value === sourceValue); + + /** @param {import('eslint').Rule.RuleFixer} fixer */ + return function * (fixer) { + if (imported.name === '*') { + for (const {name: exportedName} of exported) { + const specifier = `* as ${exportedName}`; + + if (!exportDeclaration || exportDeclaration.specifiers.some(({type}) => type === 'ExportNamespaceSpecifier')) { + yield fixer.insertTextAfter( + program, + `\nexport ${specifier} from ${sourceText};`, + ); + } else { + const exportToken = sourceCode.getFirstToken(exportDeclaration); + yield fixer.insertTextAfter(exportToken, ` ${specifier},`); + } + } + } else { + const specifiers = exported.map(({name}) => name === imported.name ? name : `${imported.name} as ${name}`) + .join(','); + + if (exportDeclaration) { + const lastSpecifier = exportDeclaration.specifiers[exportDeclaration.specifiers.length - 1]; + + // `export {} from 'foo';` + if (!lastSpecifier) { + const openingBraceToken = sourceCode.getFirstToken(exportDeclaration, isOpeningBraceToken); + yield fixer.insertTextAfter(openingBraceToken, specifiers); + } else if (lastSpecifier.type === 'ExportSpecifier') { + yield fixer.insertTextAfter(lastSpecifier, `, ${specifiers}`); + } else { + yield fixer.insertTextAfter(lastSpecifier, `, {${specifiers}}`); + } + } else { + yield fixer.insertTextAfter( + program, + `\nexport {${specifiers}} from ${sourceText};`, + ); + } + } + + const nodes = new Set([imported.node, ...exported.map(({node}) => node)]); + // This cache to prevent removing specifiers one by one and leave an empty `export {}` + const removedSpecifiers = new Set(); + for (const node of nodes) { + if (removedSpecifiers.has(node)) { + continue; + } + + yield * removeImportOrExport(node, { + fixer, + sourceCode, + removedSpecifiers, + nodes, + }); + } + }; +} + +function getImported(identifier) { + const {parent} = identifier; + switch (parent.type) { + case 'ImportDefaultSpecifier': + return { + node: parent, + name: 'default', + }; + case 'ImportSpecifier': + return { + node: parent, + name: parent.imported.name, + }; + case 'ImportNamespaceSpecifier': + return { + node: parent, + name: '*', + }; + default: + console.log(parent); + throw new Error('unexpected2'); + } +} + +function getExported(identifier, context) { + const {parent} = identifier; + switch (parent.type) { + case 'ExportDefaultDeclaration': + return { + node: parent, + name: 'default', + }; + case 'ExportSpecifier': + return { + node: parent, + name: parent.exported.name, + }; + case 'VariableDeclarator': + if ( + parent.init === identifier && + parent.id.type === 'Identifier' && + parent.parent.type === 'VariableDeclaration' && + parent.parent.declarations.length === 1 && + parent.parent.declarations[0] === parent && + parent.parent.parent.type === 'ExportNamedDeclaration' && + isVariableNotUsed(parent, context) + ) { + return { + node: parent.parent.parent, + name: parent.id.name}; + } + + break; + + // No default + } +} + +function isVariableNotUsed(node, context) { + const variables = context.getDeclaredVariables(node); + if (variables.length !== 1) { + return false; + } + + const [{identifiers, references}] = variables; + return identifiers.length === 1 && + identifiers[0] === node.id && + references.length === 1 && + references[0].identifier === node.id; +} + +function getProblem({ + context, + variable, + importDeclaration, + program, + exportDeclarations, +}) { + const { + identifiers, + references, + } = variable; + + const exported = references.map(({identifier}) => getExported(identifier, context)); + + if (!exported.every(Boolean)) { + return; + } + + const [identifier] = identifiers; + const imported = getImported(identifier); + + /* + There is no substitute for + ```js + import * as foo from 'foo'; + export default foo; + ```js + */ + if (imported.name === '*' && exported.some(({name}) => name === 'default')) { + return; + } + + return { + node: imported.node, + messageId: MESSAGE_ID, + data: { + imported: imported.name, + }, + fix: fix({ + context, + exportDeclarations, + imported, + exported, + importDeclaration, + program, + }), + }; +} + +/** @param {import('eslint').Rule.RuleContext} context */ +function create(context) { + const importDeclarations = new Set(); + const exportDeclarations = []; + + return { + 'ImportDeclaration[specifiers.length>0]'(node) { + importDeclarations.add({ + node, + variables: context.getDeclaredVariables(node), + }); + }, + ':matches(ExportNamedDeclaration,ExportDefaultDeclaration)[source][source.type="Literal"]'(node) { + exportDeclarations.push(node); + }, + * 'Program:exit'(program) { + for (const {node: importDeclaration, variables} of importDeclarations) { + for (const variable of variables) { + const { + identifiers, + references, + } = variable; + + if (identifiers.length !== 1 || references.length === 0) { + continue; + } + + const problem = getProblem({ + context, + variable, + importDeclaration, + program, + exportDeclarations, + }); + + if (problem) { + yield problem; + } + } + } + }, + }; +} + +module.exports = { + create, + meta: { + type: 'suggestion', + docs: { + description: 'Prefer "export from" syntax when re-exporting.', + }, + fixable: 'code', + messages, + }, +}; diff --git a/test/prefer-export-from.mjs b/test/prefer-export-from.mjs new file mode 100644 index 0000000000..68d83ac13d --- /dev/null +++ b/test/prefer-export-from.mjs @@ -0,0 +1,194 @@ +import outdent from 'outdent'; +import {getTester} from './utils/test.mjs'; + +const {test} = getTester(import.meta); + +test.snapshot({ + valid: [ + // Exported variable is reused + outdent` + import defaultExport from 'foo'; + export const variable = defaultExport; + use(variable); + `, + outdent` + import defaultExport from 'foo'; + export let variable = defaultExport; + variable = 1; + `, + // Export namespace as default + outdent` + import * as namespace from 'foo'; + export default namespace; + `, + outdent` + import * as namespace from 'foo'; + export {namespace as default}; + `, + // Cases we are not handled + outdent` + import defaultExport from 'foo'; + const variable = defaultExport; + export {variable} + `, + outdent` + import defaultExport from 'foo'; + export const {variable} = {variable: defaultExport}; + `, + ], + invalid: [ + // `default` + outdent` + import defaultExport from 'foo'; + export default defaultExport; + `, + outdent` + import defaultExport from 'foo'; + export {defaultExport as default}; + `, + outdent` + import defaultExport from 'foo'; + export {defaultExport as named}; + `, + outdent` + import defaultExport from 'foo'; + export const variable = defaultExport; + `, + outdent` + import {default as defaultExport} from 'foo'; + export default defaultExport; + `, + outdent` + import {default as defaultExport} from 'foo'; + export {defaultExport as default}; + `, + outdent` + import {default as defaultExport} from 'foo'; + export {defaultExport as named}; + `, + outdent` + import defaultExport from 'foo'; + export const variable = defaultExport; + `, + // `named` + outdent` + import {named} from 'foo'; + export default named; + `, + outdent` + import {named} from 'foo'; + export {named as default}; + `, + outdent` + import {named} from 'foo'; + export {named as named}; + `, + outdent` + import {named} from 'foo'; + export {named as renamed}; + `, + outdent` + import {named} from 'foo'; + export const variable = named; + `, + // Namespace + outdent` + import * as namespace from 'foo'; + export {namespace as namespace}; + `, + outdent` + import * as namespace from 'foo'; + export {namespace as renamed}; + `, + outdent` + import * as namespace from 'foo'; + export const variable = namespace; + `, + // Some not exported + outdent` + import {named1, named2} from 'foo'; + export {named1}; + `, + outdent` + import defaultExport, {named} from 'foo'; + export {defaultExport}; + `, + outdent` + import defaultExport, {named} from 'foo'; + export {named}; + `, + outdent` + import defaultExport, * as namespace from 'foo'; + export {defaultExport}; + `, + // Existing export + outdent` + import * as foo from 'foo'; + export {foo}; + export * as bar from 'foo'; + `, + outdent` + import * as foo from 'foo'; + export {foo}; + export {bar} from 'foo'; + `, + outdent` + import * as foo from 'foo'; + export {foo}; + export {} from 'foo'; + `, + outdent` + import * as foo from 'foo'; + export {foo}; + export * from 'foo'; + `, + outdent` + import foo from 'foo'; + export {foo}; + export * as bar from 'foo'; + `, + outdent` + import foo from 'foo'; + export {foo}; + export {bar} from 'foo'; + `, + outdent` + import foo from 'foo'; + export {foo}; + export {} from 'foo'; + `, + outdent` + import foo from 'foo'; + export {foo}; + export * from 'foo'; + `, + // Multiple + outdent` + import {named1, named2} from 'foo'; + export {named1, named2}; + `, + outdent` + import {named} from 'foo'; + export {named as default, named}; + `, + outdent` + import {named, named as renamed} from 'foo'; + export {named, renamed}; + `, + outdent` + import defaultExport, {named1, named2} from 'foo'; + export {named1 as default}; + export {named2}; + export {defaultExport}; + `, + // Variable is not `const` + outdent` + import defaultExport from 'foo'; + export var variable = defaultExport; + `, + outdent` + import defaultExport from 'foo'; + export let variable = defaultExport; + `, + ], +}); diff --git a/test/snapshots/prefer-export-from.mjs.md b/test/snapshots/prefer-export-from.mjs.md new file mode 100644 index 0000000000..f3bcbfb1bd --- /dev/null +++ b/test/snapshots/prefer-export-from.mjs.md @@ -0,0 +1,747 @@ +# Snapshot report for `test/prefer-export-from.mjs` + +The actual snapshot is saved in `prefer-export-from.mjs.snap`. + +Generated by [AVA](https://avajs.dev). + +## Invalid #1 + 1 | import defaultExport from 'foo'; + 2 | export default defaultExport; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {default} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import defaultExport from 'foo';␊ + | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export default defaultExport;␊ + ` + +## Invalid #2 + 1 | import defaultExport from 'foo'; + 2 | export {defaultExport as default}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {default} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import defaultExport from 'foo';␊ + | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export {defaultExport as default};␊ + ` + +## Invalid #3 + 1 | import defaultExport from 'foo'; + 2 | export {defaultExport as named}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {default as named} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import defaultExport from 'foo';␊ + | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export {defaultExport as named};␊ + ` + +## Invalid #4 + 1 | import defaultExport from 'foo'; + 2 | export const variable = defaultExport; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {default as variable} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import defaultExport from 'foo';␊ + | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export const variable = defaultExport;␊ + ` + +## Invalid #5 + 1 | import {default as defaultExport} from 'foo'; + 2 | export default defaultExport; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {default} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import {default as defaultExport} from 'foo';␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export default defaultExport;␊ + ` + +## Invalid #6 + 1 | import {default as defaultExport} from 'foo'; + 2 | export {defaultExport as default}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {default} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import {default as defaultExport} from 'foo';␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export {defaultExport as default};␊ + ` + +## Invalid #7 + 1 | import {default as defaultExport} from 'foo'; + 2 | export {defaultExport as named}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {default as named} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import {default as defaultExport} from 'foo';␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export {defaultExport as named};␊ + ` + +## Invalid #8 + 1 | import defaultExport from 'foo'; + 2 | export const variable = defaultExport; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {default as variable} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import defaultExport from 'foo';␊ + | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export const variable = defaultExport;␊ + ` + +## Invalid #9 + 1 | import {named} from 'foo'; + 2 | export default named; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {named as default} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import {named} from 'foo';␊ + | ^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + 2 | export default named;␊ + ` + +## Invalid #10 + 1 | import {named} from 'foo'; + 2 | export {named as default}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {named as default} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import {named} from 'foo';␊ + | ^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + 2 | export {named as default};␊ + ` + +## Invalid #11 + 1 | import {named} from 'foo'; + 2 | export {named as named}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {named} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import {named} from 'foo';␊ + | ^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + 2 | export {named as named};␊ + ` + +## Invalid #12 + 1 | import {named} from 'foo'; + 2 | export {named as renamed}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {named as renamed} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import {named} from 'foo';␊ + | ^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + 2 | export {named as renamed};␊ + ` + +## Invalid #13 + 1 | import {named} from 'foo'; + 2 | export const variable = named; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {named as variable} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import {named} from 'foo';␊ + | ^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + 2 | export const variable = named;␊ + ` + +## Invalid #14 + 1 | import * as namespace from 'foo'; + 2 | export {namespace as namespace}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export * as namespace from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import * as namespace from 'foo';␊ + | ^^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + 2 | export {namespace as namespace};␊ + ` + +## Invalid #15 + 1 | import * as namespace from 'foo'; + 2 | export {namespace as renamed}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export * as renamed from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import * as namespace from 'foo';␊ + | ^^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + 2 | export {namespace as renamed};␊ + ` + +## Invalid #16 + 1 | import * as namespace from 'foo'; + 2 | export const variable = namespace; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export * as variable from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import * as namespace from 'foo';␊ + | ^^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + 2 | export const variable = namespace;␊ + ` + +## Invalid #17 + 1 | import {named1, named2} from 'foo'; + 2 | export {named1}; + +> Output + + `␊ + 1 | import { named2} from 'foo';␊ + 2 |␊ + 3 | export {named1} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import {named1, named2} from 'foo';␊ + | ^^^^^^ Use \`export from\` syntax to re-export \`named1\`.␊ + 2 | export {named1};␊ + ` + +## Invalid #18 + 1 | import defaultExport, {named} from 'foo'; + 2 | export {defaultExport}; + +> Output + + `␊ + 1 | import {named} from 'foo';␊ + 2 |␊ + 3 | export {default as defaultExport} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import defaultExport, {named} from 'foo';␊ + | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export {defaultExport};␊ + ` + +## Invalid #19 + 1 | import defaultExport, {named} from 'foo'; + 2 | export {named}; + +> Output + + `␊ + 1 | import defaultExport from 'foo';␊ + 2 |␊ + 3 | export {named} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import defaultExport, {named} from 'foo';␊ + | ^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + 2 | export {named};␊ + ` + +## Invalid #20 + 1 | import defaultExport, * as namespace from 'foo'; + 2 | export {defaultExport}; + +> Output + + `␊ + 1 | import * as namespace from 'foo';␊ + 2 |␊ + 3 | export {default as defaultExport} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import defaultExport, * as namespace from 'foo';␊ + | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export {defaultExport};␊ + ` + +## Invalid #21 + 1 | import * as foo from 'foo'; + 2 | export {foo}; + 3 | export * as bar from 'foo'; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export * as bar from 'foo';␊ + 4 | export * as foo from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import * as foo from 'foo';␊ + | ^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + 2 | export {foo};␊ + 3 | export * as bar from 'foo';␊ + ` + +## Invalid #22 + 1 | import * as foo from 'foo'; + 2 | export {foo}; + 3 | export {bar} from 'foo'; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export * as foo, {bar} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import * as foo from 'foo';␊ + | ^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + 2 | export {foo};␊ + 3 | export {bar} from 'foo';␊ + ` + +## Invalid #23 + 1 | import * as foo from 'foo'; + 2 | export {foo}; + 3 | export {} from 'foo'; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export * as foo, {} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import * as foo from 'foo';␊ + | ^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + 2 | export {foo};␊ + 3 | export {} from 'foo';␊ + ` + +## Invalid #24 + 1 | import * as foo from 'foo'; + 2 | export {foo}; + 3 | export * from 'foo'; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export * from 'foo';␊ + 4 | export * as foo from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import * as foo from 'foo';␊ + | ^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + 2 | export {foo};␊ + 3 | export * from 'foo';␊ + ` + +## Invalid #25 + 1 | import foo from 'foo'; + 2 | export {foo}; + 3 | export * as bar from 'foo'; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export * as bar from 'foo';␊ + 4 | export {default as foo} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import foo from 'foo';␊ + | ^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export {foo};␊ + 3 | export * as bar from 'foo';␊ + ` + +## Invalid #26 + 1 | import foo from 'foo'; + 2 | export {foo}; + 3 | export {bar} from 'foo'; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {bar, default as foo} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import foo from 'foo';␊ + | ^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export {foo};␊ + 3 | export {bar} from 'foo';␊ + ` + +## Invalid #27 + 1 | import foo from 'foo'; + 2 | export {foo}; + 3 | export {} from 'foo'; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {default as foo} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import foo from 'foo';␊ + | ^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export {foo};␊ + 3 | export {} from 'foo';␊ + ` + +## Invalid #28 + 1 | import foo from 'foo'; + 2 | export {foo}; + 3 | export * from 'foo'; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export * from 'foo';␊ + 4 | export {default as foo} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import foo from 'foo';␊ + | ^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export {foo};␊ + 3 | export * from 'foo';␊ + ` + +## Invalid #29 + 1 | import {named1, named2} from 'foo'; + 2 | export {named1, named2}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {named1, named2} from 'foo';␊ + ` + +> Error 1/2 + + `␊ + > 1 | import {named1, named2} from 'foo';␊ + | ^^^^^^ Use \`export from\` syntax to re-export \`named1\`.␊ + 2 | export {named1, named2};␊ + ` + +> Error 2/2 + + `␊ + > 1 | import {named1, named2} from 'foo';␊ + | ^^^^^^ Use \`export from\` syntax to re-export \`named2\`.␊ + 2 | export {named1, named2};␊ + ` + +## Invalid #30 + 1 | import {named} from 'foo'; + 2 | export {named as default, named}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {named as default,named} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import {named} from 'foo';␊ + | ^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + 2 | export {named as default, named};␊ + ` + +## Invalid #31 + 1 | import {named, named as renamed} from 'foo'; + 2 | export {named, renamed}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {named, named as renamed} from 'foo';␊ + ` + +> Error 1/2 + + `␊ + > 1 | import {named, named as renamed} from 'foo';␊ + | ^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + 2 | export {named, renamed};␊ + ` + +> Error 2/2 + + `␊ + > 1 | import {named, named as renamed} from 'foo';␊ + | ^^^^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + 2 | export {named, renamed};␊ + ` + +## Invalid #32 + 1 | import defaultExport, {named1, named2} from 'foo'; + 2 | export {named1 as default}; + 3 | export {named2}; + 4 | export {defaultExport}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 |␊ + 4 |␊ + 5 | export {default as defaultExport, named1 as default, named2} from 'foo';␊ + ` + +> Error 1/3 + + `␊ + > 1 | import defaultExport, {named1, named2} from 'foo';␊ + | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export {named1 as default};␊ + 3 | export {named2};␊ + 4 | export {defaultExport};␊ + ` + +> Error 2/3 + + `␊ + > 1 | import defaultExport, {named1, named2} from 'foo';␊ + | ^^^^^^ Use \`export from\` syntax to re-export \`named1\`.␊ + 2 | export {named1 as default};␊ + 3 | export {named2};␊ + 4 | export {defaultExport};␊ + ` + +> Error 3/3 + + `␊ + > 1 | import defaultExport, {named1, named2} from 'foo';␊ + | ^^^^^^ Use \`export from\` syntax to re-export \`named2\`.␊ + 2 | export {named1 as default};␊ + 3 | export {named2};␊ + 4 | export {defaultExport};␊ + ` + +## Invalid #33 + 1 | import defaultExport from 'foo'; + 2 | export var variable = defaultExport; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {default as variable} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import defaultExport from 'foo';␊ + | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export var variable = defaultExport;␊ + ` + +## Invalid #34 + 1 | import defaultExport from 'foo'; + 2 | export let variable = defaultExport; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {default as variable} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import defaultExport from 'foo';␊ + | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export let variable = defaultExport;␊ + ` diff --git a/test/snapshots/prefer-export-from.mjs.snap b/test/snapshots/prefer-export-from.mjs.snap new file mode 100644 index 0000000000000000000000000000000000000000..ec9ff61c5bb76b60468c467a8486cd4a5f06da40 GIT binary patch literal 1803 zcmV+m2lV(sRzV${-k<42TFQF5rsGkM=9HwV9&``-Wk_rL%D-}@{x z1i%46pMx{cdd~TNSGe5!aowUE2$a_hjC&-kzgZ5e>>9>D_X-T3xW%goBGySnp_W9S z>lxU$t#*foOstsn z)K-ywcNIh|Fs4vW!gt>u`}@X{<{Os}-w)4{5$J#c< zileK;4G>$5;blhQHVOZl#T(u$3Cgz#lOMlSxAH7R?93h%ekUH=kd7BPH8mae5X+ ztcL}K8WQsZyWO1bFK;NFv)srp_V(T$J z>ji-9Lcb*jgG>zbEz4>%GepS{v5zo5vH~EtK;ji3{xT={a*##!qsCx}*cOaJYXCNG zF1!+HT|RZY19ASKgF`Vy>?Mqx-sG?Px8z+jsdIh4X{N_r^OLtAVozYK=>x#d(>}gg zvyE;IZ88jfDETW0B36NsZ3Dm|s~w`U^b-aCim$9rr`KCU#8zWS`jQc0*62HZjrTjV zidILQ$(?Hf5qlCN&K7{LOExstR1_UpVeFoEVcL+Z5V2(#Gx`DWL-U=RPdBd~dF0sq zQ$MZG%!i2GgyGsBfSfo8o5wjZ*xcC8h5qW z>!KlI3ovp9Qb-*{A$c$W*Sti=t;Z_z3>-@qxP)x^79v)T5pD;-gTw*u>qZyMSfa=+ zm4D&s2oYO}5lH~hbZJC*L*1F7HnU!Uh6c+th}iuY6YK%_?MC^ZdwV;-tPHb@kUm*- z93nOy!_)zQ=CB8wWa5-(jjP7}^5p2b{t&Uz7=MuX+xAdHfQ4*cK!y3<^Mr(qC?z}j z4GQ;37=Z35D~XIiFOjz?LAVfE9XXclvE-!QIa5yCL}Tff~a$^_jq#T_hrEbJ3?gN@QG)g%}mMmE) zW!ETHyM$_WV$?}J>Xo&0ksdrEnax#`xw9+DZ2JdY=y;B>#c`k-&lRw8dceLm7XRso z?#dg(43|(J;0Lwygqi`b)X+RJQJ5!|N>bt^3*x05&M2liL;d-}CSFU;q?K)!5?<;S z&~%4#g}S=2?#wPBzvl49R+=}+pK$s>+u2rHGl5Hon)+x;y~;T5RmvF{9AU2Jk59Rx z!?|N=LZ>T4lN8ZbGgNt$U3Z>dYZ^ka2SP zZqYf@?aVUSuv7;|vXrV$G+Q*5Z>C(Z1Xm5RFy~07vaFFp7iNjC9>>!wX<(feR=R3t zr6__{E0{BwPKv}H?jpgPJO91v5XRFfFCaS+9dr@&1f!QOfOmLd+|dP&=I?hnWF79pyF8UC zTs_Z!YKs>y72N9ubZCp`gtIcc7j`gZE56LEU53(dd#7Ez7wLbN+aF%2%+{&Wqg{Aq z3wFW(cQePeMG)L#ZPR~?mC0_NC`6k^lRua3?kc&AugT;)e!UZ^>QSznouyd|?QDliI@T^4Bd82;u1e-t zlzONH+_@u2{n(8wo3rfNIb1+LaMARjjWJ?$a2nj9moWULQNJ%?So-#neA+k!t<|d_ t#;FQakJn6=^uu Date: Wed, 28 Jul 2021 10:19:41 +0800 Subject: [PATCH 02/21] Tweak --- rules/prefer-export-from.js | 59 +++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/rules/prefer-export-from.js b/rules/prefer-export-from.js index 591b0da7a3..5af8220b58 100644 --- a/rules/prefer-export-from.js +++ b/rules/prefer-export-from.js @@ -1,5 +1,9 @@ 'use strict'; -const {isCommaToken, isOpeningBraceToken, isClosingBraceToken} = require('eslint-utils'); +const { + isCommaToken, + isOpeningBraceToken, + isClosingBraceToken, +} = require('eslint-utils'); const MESSAGE_ID = 'prefer-export-from'; const messages = { [MESSAGE_ID]: 'Use `export from` syntax to re-export `{{imported}}`.', @@ -74,10 +78,10 @@ function * removeImportOrExport(node, options) { function fix({ context, - exportDeclarations, - importDeclaration, imported, + importDeclaration, exported, + exportDeclarations, program, }) { const sourceCode = context.getSourceCode(); @@ -127,7 +131,7 @@ function fix({ } const nodes = new Set([imported.node, ...exported.map(({node}) => node)]); - // This cache to prevent removing specifiers one by one and leave an empty `export {}` + // Add this cache to prevent removing specifiers one by one and leave an empty `export {}` const removedSpecifiers = new Set(); for (const node of nodes) { if (removedSpecifiers.has(node)) { @@ -152,19 +156,20 @@ function getImported(identifier) { node: parent, name: 'default', }; + case 'ImportSpecifier': return { node: parent, name: parent.imported.name, }; + case 'ImportNamespaceSpecifier': return { node: parent, name: '*', }; - default: - console.log(parent); - throw new Error('unexpected2'); + + // No default } } @@ -176,12 +181,14 @@ function getExported(identifier, context) { node: parent, name: 'default', }; + case 'ExportSpecifier': return { node: parent, name: parent.exported.name, }; - case 'VariableDeclarator': + + case 'VariableDeclarator': { if ( parent.init === identifier && parent.id.type === 'Identifier' && @@ -189,21 +196,25 @@ function getExported(identifier, context) { parent.parent.declarations.length === 1 && parent.parent.declarations[0] === parent && parent.parent.parent.type === 'ExportNamedDeclaration' && - isVariableNotUsed(parent, context) + isVariableUnused(parent, context) ) { return { node: parent.parent.parent, - name: parent.id.name}; + name: parent.id.name, + }; } break; + } // No default } } -function isVariableNotUsed(node, context) { +function isVariableUnused(node, context) { const variables = context.getDeclaredVariables(node); + + /* istanbul ignore next */ if (variables.length !== 1) { return false; } @@ -222,18 +233,19 @@ function getProblem({ program, exportDeclarations, }) { - const { - identifiers, - references, - } = variable; + const {identifiers, references} = variable; + + if (identifiers.length !== 1 || references.length === 0) { + return; + } + const [identifier] = identifiers; const exported = references.map(({identifier}) => getExported(identifier, context)); if (!exported.every(Boolean)) { return; } - const [identifier] = identifiers; const imported = getImported(identifier); /* @@ -255,10 +267,10 @@ function getProblem({ }, fix: fix({ context, - exportDeclarations, imported, - exported, importDeclaration, + exported, + exportDeclarations, program, }), }; @@ -282,21 +294,12 @@ function create(context) { * 'Program:exit'(program) { for (const {node: importDeclaration, variables} of importDeclarations) { for (const variable of variables) { - const { - identifiers, - references, - } = variable; - - if (identifiers.length !== 1 || references.length === 0) { - continue; - } - const problem = getProblem({ context, variable, importDeclaration, - program, exportDeclarations, + program, }); if (problem) { From 98080b3991f83efe9053faa30aff80318b7dcf6d Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 28 Jul 2021 10:34:33 +0800 Subject: [PATCH 03/21] Fix wrong fix --- rules/prefer-export-from.js | 17 +++++------------ test/snapshots/prefer-export-from.mjs.md | 6 ++++-- test/snapshots/prefer-export-from.mjs.snap | Bin 1803 -> 1804 bytes 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/rules/prefer-export-from.js b/rules/prefer-export-from.js index 5af8220b58..cab5a3378a 100644 --- a/rules/prefer-export-from.js +++ b/rules/prefer-export-from.js @@ -94,23 +94,16 @@ function fix({ return function * (fixer) { if (imported.name === '*') { for (const {name: exportedName} of exported) { - const specifier = `* as ${exportedName}`; - - if (!exportDeclaration || exportDeclaration.specifiers.some(({type}) => type === 'ExportNamespaceSpecifier')) { - yield fixer.insertTextAfter( - program, - `\nexport ${specifier} from ${sourceText};`, - ); - } else { - const exportToken = sourceCode.getFirstToken(exportDeclaration); - yield fixer.insertTextAfter(exportToken, ` ${specifier},`); - } + yield fixer.insertTextAfter( + program, + `\nexport * as ${exportedName} from ${sourceText};`, + ); } } else { const specifiers = exported.map(({name}) => name === imported.name ? name : `${imported.name} as ${name}`) .join(','); - if (exportDeclaration) { + if (exportDeclaration && exportDeclaration.specifiers.every(({type}) => type === 'ExportSpecifier')) { const lastSpecifier = exportDeclaration.specifiers[exportDeclaration.specifiers.length - 1]; // `export {} from 'foo';` diff --git a/test/snapshots/prefer-export-from.mjs.md b/test/snapshots/prefer-export-from.mjs.md index f3bcbfb1bd..70491640f2 100644 --- a/test/snapshots/prefer-export-from.mjs.md +++ b/test/snapshots/prefer-export-from.mjs.md @@ -437,7 +437,8 @@ Generated by [AVA](https://avajs.dev). `␊ 1 |␊ 2 |␊ - 3 | export * as foo, {bar} from 'foo';␊ + 3 | export {bar} from 'foo';␊ + 4 | export * as foo from 'foo';␊ ` > Error 1/1 @@ -459,7 +460,8 @@ Generated by [AVA](https://avajs.dev). `␊ 1 |␊ 2 |␊ - 3 | export * as foo, {} from 'foo';␊ + 3 | export {} from 'foo';␊ + 4 | export * as foo from 'foo';␊ ` > Error 1/1 diff --git a/test/snapshots/prefer-export-from.mjs.snap b/test/snapshots/prefer-export-from.mjs.snap index ec9ff61c5bb76b60468c467a8486cd4a5f06da40..8e4037109c2f0bdd3834a46472631d5899b74ea3 100644 GIT binary patch literal 1804 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 t#;FQakJn6=^uu Date: Wed, 28 Jul 2021 11:05:13 +0800 Subject: [PATCH 04/21] Improve --- rules/prefer-export-from.js | 18 +-- test/prefer-export-from.mjs | 59 +++++++- test/snapshots/prefer-export-from.mjs.md | 159 +++++++++++++++++++-- test/snapshots/prefer-export-from.mjs.snap | Bin 1804 -> 2114 bytes 4 files changed, 209 insertions(+), 27 deletions(-) diff --git a/rules/prefer-export-from.js b/rules/prefer-export-from.js index cab5a3378a..f30a59ee43 100644 --- a/rules/prefer-export-from.js +++ b/rules/prefer-export-from.js @@ -30,8 +30,8 @@ function * removeSpecifier(node, options) { const hasOtherSpecifiers = specifiers.some(specifier => specifier !== node && specifier.type === node.type); if (!hasOtherSpecifiers) { const closingBraceToken = sourceCode.getTokenAfter(node, isClosingBraceToken); - // If there are other specifiers, they have to be default or namespace import/export - // And default or namespace import/export has to write before the named import/export + // If there are other specifiers, they have to be default import/export + // And default import/export has to write before the named import/export // So there must be a comma before const commaToken = sourceCode.getTokenBefore(node, isCommaToken); yield fixer.replaceTextRange([commaToken.range[0], closingBraceToken.range[1]], ''); @@ -103,17 +103,15 @@ function fix({ const specifiers = exported.map(({name}) => name === imported.name ? name : `${imported.name} as ${name}`) .join(','); - if (exportDeclaration && exportDeclaration.specifiers.every(({type}) => type === 'ExportSpecifier')) { + if (exportDeclaration) { const lastSpecifier = exportDeclaration.specifiers[exportDeclaration.specifiers.length - 1]; // `export {} from 'foo';` - if (!lastSpecifier) { - const openingBraceToken = sourceCode.getFirstToken(exportDeclaration, isOpeningBraceToken); - yield fixer.insertTextAfter(openingBraceToken, specifiers); - } else if (lastSpecifier.type === 'ExportSpecifier') { + if (lastSpecifier) { yield fixer.insertTextAfter(lastSpecifier, `, ${specifiers}`); } else { - yield fixer.insertTextAfter(lastSpecifier, `, {${specifiers}}`); + const openingBraceToken = sourceCode.getFirstToken(exportDeclaration, isOpeningBraceToken); + yield fixer.insertTextAfter(openingBraceToken, specifiers); } } else { yield fixer.insertTextAfter( @@ -186,6 +184,7 @@ function getExported(identifier, context) { parent.init === identifier && parent.id.type === 'Identifier' && parent.parent.type === 'VariableDeclaration' && + parent.parent.kind === 'const' && parent.parent.declarations.length === 1 && parent.parent.declarations[0] === parent && parent.parent.parent.type === 'ExportNamedDeclaration' && @@ -281,7 +280,8 @@ function create(context) { variables: context.getDeclaredVariables(node), }); }, - ':matches(ExportNamedDeclaration,ExportDefaultDeclaration)[source][source.type="Literal"]'(node) { + // `ExportAllDeclaration` and `ExportDefaultDeclaration` can't be reused + 'ExportNamedDeclaration[source.type="Literal"]'(node) { exportDeclarations.push(node); }, * 'Program:exit'(program) { diff --git a/test/prefer-export-from.mjs b/test/prefer-export-from.mjs index 68d83ac13d..da09ad74ff 100644 --- a/test/prefer-export-from.mjs +++ b/test/prefer-export-from.mjs @@ -5,6 +5,33 @@ const {test} = getTester(import.meta); test.snapshot({ valid: [ + 'import "foo";', + 'import {} from "foo";', + 'import * as namespace from "foo";', + 'import defaultExport from "foo";', + 'import {named} from "foo";', + outdent` + const named = import(foo); + export {named}; + `, + 'export * from "foo";', + 'export {default} from "foo";', + 'export {named} from "foo";', + outdent` + const defaultExport = require('foo'); + export default defaultExport; + `, + + // Variable is not `const` + outdent` + import defaultExport from 'foo'; + export var variable = defaultExport; + `, + outdent` + import defaultExport from 'foo'; + export let variable = defaultExport; + `, + // Exported variable is reused outdent` import defaultExport from 'foo'; @@ -152,6 +179,11 @@ test.snapshot({ export {foo}; export {bar} from 'foo'; `, + outdent` + import foo from 'foo'; + export {foo}; + export {bar,} from 'foo'; + `, outdent` import foo from 'foo'; export {foo}; @@ -181,14 +213,35 @@ test.snapshot({ export {named2}; export {defaultExport}; `, - // Variable is not `const` + outdent` + import * as foo from 'foo'; + import * as bar from 'foo'; + export {foo, bar}; + `, + outdent` + import * as foo from 'foo'; + export {foo, foo as bar}; + `, outdent` import defaultExport from 'foo'; - export var variable = defaultExport; + export * from 'foo'; + export default defaultExport; `, outdent` import defaultExport from 'foo'; - export let variable = defaultExport; + export {named} from 'foo'; + export * from 'foo'; + export default defaultExport; + `, + outdent` + import defaultExport from './foo.js'; + export {named} from './foo.js'; + export default defaultExport; + `, + outdent` + import defaultExport from './foo.js'; + export {named} from './foo.js?query'; + export default defaultExport; `, ], }); diff --git a/test/snapshots/prefer-export-from.mjs.md b/test/snapshots/prefer-export-from.mjs.md index 70491640f2..41962418d2 100644 --- a/test/snapshots/prefer-export-from.mjs.md +++ b/test/snapshots/prefer-export-from.mjs.md @@ -542,6 +542,28 @@ Generated by [AVA](https://avajs.dev). ` ## Invalid #27 + 1 | import foo from 'foo'; + 2 | export {foo}; + 3 | export {bar,} from 'foo'; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export {bar, default as foo,} from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import foo from 'foo';␊ + | ^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export {foo};␊ + 3 | export {bar,} from 'foo';␊ + ` + +## Invalid #28 1 | import foo from 'foo'; 2 | export {foo}; 3 | export {} from 'foo'; @@ -563,7 +585,7 @@ Generated by [AVA](https://avajs.dev). 3 | export {} from 'foo';␊ ` -## Invalid #28 +## Invalid #29 1 | import foo from 'foo'; 2 | export {foo}; 3 | export * from 'foo'; @@ -586,7 +608,7 @@ Generated by [AVA](https://avajs.dev). 3 | export * from 'foo';␊ ` -## Invalid #29 +## Invalid #30 1 | import {named1, named2} from 'foo'; 2 | export {named1, named2}; @@ -614,7 +636,7 @@ Generated by [AVA](https://avajs.dev). 2 | export {named1, named2};␊ ` -## Invalid #30 +## Invalid #31 1 | import {named} from 'foo'; 2 | export {named as default, named}; @@ -634,7 +656,7 @@ Generated by [AVA](https://avajs.dev). 2 | export {named as default, named};␊ ` -## Invalid #31 +## Invalid #32 1 | import {named, named as renamed} from 'foo'; 2 | export {named, renamed}; @@ -662,7 +684,7 @@ Generated by [AVA](https://avajs.dev). 2 | export {named, renamed};␊ ` -## Invalid #32 +## Invalid #33 1 | import defaultExport, {named1, named2} from 'foo'; 2 | export {named1 as default}; 3 | export {named2}; @@ -708,16 +730,72 @@ Generated by [AVA](https://avajs.dev). 4 | export {defaultExport};␊ ` -## Invalid #33 - 1 | import defaultExport from 'foo'; - 2 | export var variable = defaultExport; +## Invalid #34 + 1 | import * as foo from 'foo'; + 2 | import * as bar from 'foo'; + 3 | export {foo, bar}; > Output `␊ 1 |␊ 2 |␊ - 3 | export {default as variable} from 'foo';␊ + 3 |␊ + 4 | export * as foo from 'foo';␊ + 5 | export * as bar from 'foo';␊ + ` + +> Error 1/2 + + `␊ + > 1 | import * as foo from 'foo';␊ + | ^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + 2 | import * as bar from 'foo';␊ + 3 | export {foo, bar};␊ + ` + +> Error 2/2 + + `␊ + 1 | import * as foo from 'foo';␊ + > 2 | import * as bar from 'foo';␊ + | ^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + 3 | export {foo, bar};␊ + ` + +## Invalid #35 + 1 | import * as foo from 'foo'; + 2 | export {foo, foo as bar}; + +> Output + + `␊ + 1 |␊ + 2 |␊ + 3 | export * as foo from 'foo';␊ + 4 | export * as bar from 'foo';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import * as foo from 'foo';␊ + | ^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + 2 | export {foo, foo as bar};␊ + ` + +## Invalid #36 + 1 | import defaultExport from 'foo'; + 2 | export * from 'foo'; + 3 | export default defaultExport; + +> Output + + `␊ + 1 |␊ + 2 | export * from 'foo';␊ + 3 |␊ + 4 | export {default} from 'foo';␊ ` > Error 1/1 @@ -725,19 +803,23 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from 'foo';␊ | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ - 2 | export var variable = defaultExport;␊ + 2 | export * from 'foo';␊ + 3 | export default defaultExport;␊ ` -## Invalid #34 +## Invalid #37 1 | import defaultExport from 'foo'; - 2 | export let variable = defaultExport; + 2 | export {named} from 'foo'; + 3 | export * from 'foo'; + 4 | export default defaultExport; > Output `␊ 1 |␊ - 2 |␊ - 3 | export {default as variable} from 'foo';␊ + 2 | export {named, default} from 'foo';␊ + 3 | export * from 'foo';␊ + 4 |␊ ` > Error 1/1 @@ -745,5 +827,52 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from 'foo';␊ | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ - 2 | export let variable = defaultExport;␊ + 2 | export {named} from 'foo';␊ + 3 | export * from 'foo';␊ + 4 | export default defaultExport;␊ + ` + +## Invalid #38 + 1 | import defaultExport from './foo.js'; + 2 | export {named} from './foo.js'; + 3 | export default defaultExport; + +> Output + + `␊ + 1 |␊ + 2 | export {named, default} from './foo.js';␊ + 3 |␊ + ` + +> Error 1/1 + + `␊ + > 1 | import defaultExport from './foo.js';␊ + | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export {named} from './foo.js';␊ + 3 | export default defaultExport;␊ + ` + +## Invalid #39 + 1 | import defaultExport from './foo.js'; + 2 | export {named} from './foo.js?query'; + 3 | export default defaultExport; + +> Output + + `␊ + 1 |␊ + 2 | export {named} from './foo.js?query';␊ + 3 |␊ + 4 | export {default} from './foo.js';␊ + ` + +> Error 1/1 + + `␊ + > 1 | import defaultExport from './foo.js';␊ + | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + 2 | export {named} from './foo.js?query';␊ + 3 | export default defaultExport;␊ ` diff --git a/test/snapshots/prefer-export-from.mjs.snap b/test/snapshots/prefer-export-from.mjs.snap index 8e4037109c2f0bdd3834a46472631d5899b74ea3..8cde7b35bbdf9b217475293c6f9fd8d07efd1068 100644 GIT binary patch literal 2114 zcmV-I2)*|~RzV8Tk!_(kz*y@dYUw3LlFI00000000B! zS_@PZRT#c|5z$rfjiweOi3qOf@(LBu5;K8B@D)CYRn|ZSgvERSJ`xcXG|DzKk*rgq zW~reT)+tfMw`7KIB}1_CQ9e*htGjmw*qNQVGYc!jIn6oW9{6Tw=Kuct-~ayipPgh4 zfHUau?R>b;p>n_jzu*bJtNd~yFdQ#3xQ5W_@^an2yqF(`&KTEv-;fg@L(KM8&^Uq6 zecgZszvPecxU>529iK#0gh9-9f;7$|IIIm^eVwwuUr<`~hB7ZF2x8X9ibl6)0QA`N zX=aws=&r+)^IyEVAh#>TY!U-+WUJGdW_hQR~&w&pG(Q$F|OWQ_P2zX4Pefh*qAzAj}1%;=}79NI}4N%g!g%A|{kKX-J)C#X* zeKJ}_RBVTs9ove=UkD*rGh%c-yaB8Zy*IDzj#nUNeOuG0KnVYF!KUp+g z&q;xp?PE)0FT%vB>4nkrr!G15n%%ZR3xlUX%v#&gID;@LxOsWd@Pf+xar3Q*jk??! zV%DJzjjs@5n@67N{jSY`xuv^9+xJfz1u^@C!TPr78+Lp2Cp z2J6}ZkWl7$HzCqvmgupctEJ8+caJB9E=Vm_4oO4a7&i99y z_32Eb3}Hp4{`~75whzsAq)N9rI_5#lcI-mqdxUrN|K_+{DBSzoFsF8Bj=3#?n6-U| z#%2V4*L&%gT9&y#SUJ+`y509zA!e%>eAX3!_YV#UNEu^&)#-M#u$!7EArQ0G3_k4! z!0uL60YOU!j~Jc%*5s0<CWIjV%a= zvbVnJwOqO9uC+}P~i9XOMboCPsk#vs)Jc`ZBr zc2$*az?`?c>^u@z@hik^34<64fJ=Ug7XN&`E8WU@(-d{+s_!6Xiy6%50l%>$hwW)Cr#<%mY|adhkP+Y^qRE3z-W;d_*_!t75BmOM{G-4lS@r~6K* zEGu!cAN>eaR<@lDF*}!mtrGx$UfKS5V@K8Bd%_(iYwx~M2r)Z?!9|2S;Wt+5A`+{s z7Wr9tPIC7mZ^G4>vsd@DEka^hE&^`ac}u;BST5cFr`uU@*2fium%9M|Lq4 zzh}+LaIBbLvJhhS0E6`|0Q}qK^UAYF)T!ZkBFxwmEH6f>YBX@IXN3j(lqb3s%SER-E@E3H zEgTx^37%mT6H#-jWJ)r8{%}$W~ov0tF75s%JxghZLB*q zN=3`H*_;Axpp+q(ko8x{Fy_2*%^my~q%CaZJoUExc`8}hJVk$TjRbK!n(!u8N(hIF zQq9Jg}x|c!0DU@*`+R zPOIJWGnT6e;m=ho$G*>C@>ARU<;Xw3rEKv?35{n+34*x=nM@-}7|@Yqtqq#Jyf5cv zn7w2VgeWPgF)2{X5CVYPi#4|g&%3FyKw-mO!^aEl@kM$YUX=7@0_HVhJQzR1bQ$(w zM~sT6?P0K%61CP}!owP@M}oDMYNpHkwostJbQ9A?5X9}LHLf7uxfaZht7L%|hk#Z! zLF_VKv67l77VH#p^^$txBm;>XdwHbQK2Bt%t4H_Bg6%2+D-{~0;F~G#%bmdqv$cuy sr2Ul0=!Fo=DTkZ%>npZGbIL;t{hE*XdS0$}PEEr456>*a9_cRt0K3s3p#T5? literal 1804 zcmV+n2lMzrRzV+dVn+u9if)pT|rb03@${;A442THsf{5U9Bs7i4C?QNk z4@i2-ghbPGAakMexTPcLalsHZk43$??+!YTw+%BioO{l@ zZIi5~IQFM$OJ?_}@oFf6i0ua{RFfFGd(x^~WwTsbx4t;^xmX?w5!;SYqX&S!Jo=Hn zOVGNu-yZDSQF+`DBGyEo!ch{VU5r1mn`YcF_FmHdotOH*1ra;QfI>A1rx^1&6AOK< zhR0{U`34Y|LBx*iMd30Dx0v+0uiT$xnZdH-xPqLn>n#E+wlNC4QWd^KlBbn>~xHWB*HGND$S0|JGbF_@=CkKX_*kQ zZe|qfNX!f9b;IAcvZ-wL3Im_uYXc!-`A7XrD0YFxP#KTYg)tcZ-L1wiNn}Z=@+b{|(0m#iO zygc8sV%l~);@kl{yJCpgix_MAlfN3=mVMQz(fQftK({-lCvHN-9>-We0DzsRyu34K z8QdJvq96J|@>dW=2cw9WU^$|JveIn%oj1wiZJ&kcBFx;#MWX+2LbS7>+Ks)^45(xe01K) zpK~(uA!17~{00N?%l7P+=H|ZMY1^z1pG}b8g@`S{7(axJ-H2uL7goxxZr3}M)xK>ElJm zAYw}~-0c8p4ZFWtCQg3ZymsQRkB^)k3=vy^;qW>De_J1H@-vgo^{X=7dybHh5v5?4 zVhkA$fF9_LvXaOE^b>g+6ND3yNq#z`PZuJSkSF+(C5!L0*}J@)9d9;ysy^h{R7-{5F!1 zr6;6FmJ=z7M6z@={w5OLEpiNHE4!5h^;A{cL@w+?9TcOJrPPgB#eF~%hej#J$dV)r zrR*BTDwj~L4vadfN4>O`F4B!hB(u3HGI#bQnH~S23!TIfwm1%yAr$$~g3hck+4&QN{6u!+}DGihaqrG$s7 z1vK5ET%oRNtShri$gerPv6bcx@+X`=&~&yH)=cKop`t#DQm-_QdzEqq21l5y_~TQq z=y2>>n$YSBQ71)o)C^@FW!Igp)0)PT=e4)!_v(JpFHB63r3hX2UVO8P%fGP6Eo7Wr zzFTz9bUU(4HZ0SEku0UE8_gC?;F~EYEWufgEX+BQsVu9d(1}^%%g6EbN@`fAftAkc zSt*L3)e7berj;VGhr3Ad=FWewI)w3b$_vO&L-906j@im$L9CJ-yooacYpl5i1D+V-6 za=UcDsx|FW$jERc1g~g%eb&W_CN1We(3s9zsjwwK-2`l*@mAfb^J^=v!;q^&cGp5q zAGBKLIw|So%Z_6S#!WQi{v6)cmR9A>7@;S$<*yj8 Date: Wed, 28 Jul 2021 11:22:23 +0800 Subject: [PATCH 05/21] Docs and messages --- docs/rules/prefer-export-from.md | 52 +++++++++++- readme.md | 2 + rules/prefer-export-from.js | 4 +- test/snapshots/prefer-export-from.mjs.md | 88 ++++++++++----------- test/snapshots/prefer-export-from.mjs.snap | Bin 2114 -> 2117 bytes 5 files changed, 96 insertions(+), 50 deletions(-) diff --git a/docs/rules/prefer-export-from.md b/docs/rules/prefer-export-from.md index c3a3b06003..a2f61efe7b 100644 --- a/docs/rules/prefer-export-from.md +++ b/docs/rules/prefer-export-from.md @@ -1,17 +1,61 @@ -# Prefer "export from" syntax when re-exporting. +# Prefer `export…from` syntax when re-exporting - +When re-exporting from module, it's unnecessary to import and then export, it can be done in one `export…from` declaration. This rule is fixable. ## Fail ```js -const foo = 'unicorn'; +import defaultExport from './foo.js'; +export default defaultExport; +``` + +```js +import {named} from './foo.js'; +export {named}; +``` + +```js +import defaultExport, {named} from './foo.js'; +export { + defaultExport as default, + defaultExport as renamedDefault, + named, + named as renamedNamed, +}; +``` + +```js +import * as namespace from './foo.js'; +export {namespace}; ``` ## Pass ```js -const foo = 'πŸ¦„'; +export {default} from './foo.js'; +``` + +```js +export {named} from './foo.js'; +``` + +```js +export * as namespace from './foo.js'; +``` + +```js +// There is no substitute +import * as namespace from './foo.js'; +export default namespace; +``` + +```js +export { + default, + default as renamedDefault, + named, + named as renamedNamed, +} from './foo.js'; ``` diff --git a/readme.md b/readme.md index 784f6080e1..58cb930c25 100644 --- a/readme.md +++ b/readme.md @@ -93,6 +93,7 @@ Configure it in `package.json`. "unicorn/prefer-dom-node-dataset": "error", "unicorn/prefer-dom-node-remove": "error", "unicorn/prefer-dom-node-text-content": "error", + "unicorn/prefer-export-from": "error", "unicorn/prefer-includes": "error", "unicorn/prefer-keyboard-event-key": "error", "unicorn/prefer-math-trunc": "error", @@ -210,6 +211,7 @@ Each rule has emojis denoting: | [prefer-dom-node-dataset](docs/rules/prefer-dom-node-dataset.md) | Prefer using `.dataset` on DOM elements over `.setAttribute(…)`. | βœ… | πŸ”§ | | | [prefer-dom-node-remove](docs/rules/prefer-dom-node-remove.md) | Prefer `childNode.remove()` over `parentNode.removeChild(childNode)`. | βœ… | πŸ”§ | πŸ’‘ | | [prefer-dom-node-text-content](docs/rules/prefer-dom-node-text-content.md) | Prefer `.textContent` over `.innerText`. | βœ… | | πŸ’‘ | +| [prefer-export-from](docs/rules/prefer-export-from.md) | Prefer `export…from` syntax when re-exporting. | βœ… | πŸ”§ | | | [prefer-includes](docs/rules/prefer-includes.md) | Prefer `.includes()` over `.indexOf()` and `Array#some()` when checking for existence or non-existence. | βœ… | πŸ”§ | πŸ’‘ | | [prefer-keyboard-event-key](docs/rules/prefer-keyboard-event-key.md) | Prefer `KeyboardEvent#key` over `KeyboardEvent#keyCode`. | βœ… | πŸ”§ | | | [prefer-math-trunc](docs/rules/prefer-math-trunc.md) | Enforce the use of `Math.trunc` instead of bitwise operators. | βœ… | πŸ”§ | πŸ’‘ | diff --git a/rules/prefer-export-from.js b/rules/prefer-export-from.js index f30a59ee43..3b2a1255de 100644 --- a/rules/prefer-export-from.js +++ b/rules/prefer-export-from.js @@ -6,7 +6,7 @@ const { } = require('eslint-utils'); const MESSAGE_ID = 'prefer-export-from'; const messages = { - [MESSAGE_ID]: 'Use `export from` syntax to re-export `{{imported}}`.', + [MESSAGE_ID]: 'Use `export…from` syntax to re-export `{{imported}}`.', }; function * removeSpecifier(node, options) { @@ -309,7 +309,7 @@ module.exports = { meta: { type: 'suggestion', docs: { - description: 'Prefer "export from" syntax when re-exporting.', + description: 'Prefer `export…from` syntax when re-exporting.', }, fixable: 'code', messages, diff --git a/test/snapshots/prefer-export-from.mjs.md b/test/snapshots/prefer-export-from.mjs.md index 41962418d2..76195496c7 100644 --- a/test/snapshots/prefer-export-from.mjs.md +++ b/test/snapshots/prefer-export-from.mjs.md @@ -20,7 +20,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export default defaultExport;␊ ` @@ -40,7 +40,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export {defaultExport as default};␊ ` @@ -60,7 +60,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export {defaultExport as named};␊ ` @@ -80,7 +80,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export const variable = defaultExport;␊ ` @@ -100,7 +100,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {default as defaultExport} from 'foo';␊ - | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export default defaultExport;␊ ` @@ -120,7 +120,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {default as defaultExport} from 'foo';␊ - | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export {defaultExport as default};␊ ` @@ -140,7 +140,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {default as defaultExport} from 'foo';␊ - | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export {defaultExport as named};␊ ` @@ -160,7 +160,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export const variable = defaultExport;␊ ` @@ -180,7 +180,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + | ^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ 2 | export default named;␊ ` @@ -200,7 +200,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + | ^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ 2 | export {named as default};␊ ` @@ -220,7 +220,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + | ^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ 2 | export {named as named};␊ ` @@ -240,7 +240,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + | ^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ 2 | export {named as renamed};␊ ` @@ -260,7 +260,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + | ^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ 2 | export const variable = named;␊ ` @@ -280,7 +280,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as namespace from 'foo';␊ - | ^^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ 2 | export {namespace as namespace};␊ ` @@ -300,7 +300,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as namespace from 'foo';␊ - | ^^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ 2 | export {namespace as renamed};␊ ` @@ -320,7 +320,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as namespace from 'foo';␊ - | ^^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ 2 | export const variable = namespace;␊ ` @@ -340,7 +340,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named1, named2} from 'foo';␊ - | ^^^^^^ Use \`export from\` syntax to re-export \`named1\`.␊ + | ^^^^^^ Use \`export…from\` syntax to re-export \`named1\`.␊ 2 | export {named1};␊ ` @@ -360,7 +360,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport, {named} from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export {defaultExport};␊ ` @@ -380,7 +380,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport, {named} from 'foo';␊ - | ^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + | ^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ 2 | export {named};␊ ` @@ -400,7 +400,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport, * as namespace from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export {defaultExport};␊ ` @@ -422,7 +422,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ 2 | export {foo};␊ 3 | export * as bar from 'foo';␊ ` @@ -445,7 +445,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ 2 | export {foo};␊ 3 | export {bar} from 'foo';␊ ` @@ -468,7 +468,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ 2 | export {foo};␊ 3 | export {} from 'foo';␊ ` @@ -491,7 +491,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ 2 | export {foo};␊ 3 | export * from 'foo';␊ ` @@ -514,7 +514,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import foo from 'foo';␊ - | ^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export {foo};␊ 3 | export * as bar from 'foo';␊ ` @@ -536,7 +536,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import foo from 'foo';␊ - | ^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export {foo};␊ 3 | export {bar} from 'foo';␊ ` @@ -558,7 +558,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import foo from 'foo';␊ - | ^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export {foo};␊ 3 | export {bar,} from 'foo';␊ ` @@ -580,7 +580,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import foo from 'foo';␊ - | ^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export {foo};␊ 3 | export {} from 'foo';␊ ` @@ -603,7 +603,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import foo from 'foo';␊ - | ^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export {foo};␊ 3 | export * from 'foo';␊ ` @@ -624,7 +624,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named1, named2} from 'foo';␊ - | ^^^^^^ Use \`export from\` syntax to re-export \`named1\`.␊ + | ^^^^^^ Use \`export…from\` syntax to re-export \`named1\`.␊ 2 | export {named1, named2};␊ ` @@ -632,7 +632,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named1, named2} from 'foo';␊ - | ^^^^^^ Use \`export from\` syntax to re-export \`named2\`.␊ + | ^^^^^^ Use \`export…from\` syntax to re-export \`named2\`.␊ 2 | export {named1, named2};␊ ` @@ -652,7 +652,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + | ^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ 2 | export {named as default, named};␊ ` @@ -672,7 +672,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named, named as renamed} from 'foo';␊ - | ^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + | ^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ 2 | export {named, renamed};␊ ` @@ -680,7 +680,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named, named as renamed} from 'foo';␊ - | ^^^^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`named\`.␊ + | ^^^^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ 2 | export {named, renamed};␊ ` @@ -704,7 +704,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport, {named1, named2} from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export {named1 as default};␊ 3 | export {named2};␊ 4 | export {defaultExport};␊ @@ -714,7 +714,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport, {named1, named2} from 'foo';␊ - | ^^^^^^ Use \`export from\` syntax to re-export \`named1\`.␊ + | ^^^^^^ Use \`export…from\` syntax to re-export \`named1\`.␊ 2 | export {named1 as default};␊ 3 | export {named2};␊ 4 | export {defaultExport};␊ @@ -724,7 +724,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport, {named1, named2} from 'foo';␊ - | ^^^^^^ Use \`export from\` syntax to re-export \`named2\`.␊ + | ^^^^^^ Use \`export…from\` syntax to re-export \`named2\`.␊ 2 | export {named1 as default};␊ 3 | export {named2};␊ 4 | export {defaultExport};␊ @@ -749,7 +749,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ 2 | import * as bar from 'foo';␊ 3 | export {foo, bar};␊ ` @@ -759,7 +759,7 @@ Generated by [AVA](https://avajs.dev). `␊ 1 | import * as foo from 'foo';␊ > 2 | import * as bar from 'foo';␊ - | ^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ 3 | export {foo, bar};␊ ` @@ -780,7 +780,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ 2 | export {foo, foo as bar};␊ ` @@ -802,7 +802,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export * from 'foo';␊ 3 | export default defaultExport;␊ ` @@ -826,7 +826,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export {named} from 'foo';␊ 3 | export * from 'foo';␊ 4 | export default defaultExport;␊ @@ -849,7 +849,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from './foo.js';␊ - | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export {named} from './foo.js';␊ 3 | export default defaultExport;␊ ` @@ -872,7 +872,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from './foo.js';␊ - | ^^^^^^^^^^^^^ Use \`export from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ 2 | export {named} from './foo.js?query';␊ 3 | export default defaultExport;␊ ` diff --git a/test/snapshots/prefer-export-from.mjs.snap b/test/snapshots/prefer-export-from.mjs.snap index 8cde7b35bbdf9b217475293c6f9fd8d07efd1068..97d2bd9be88704008e9eda759725f4555bd36809 100644 GIT binary patch literal 2117 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 From eee5ab627c70a24c8ac043de2d59b5bbca226c84 Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 28 Jul 2021 11:30:08 +0800 Subject: [PATCH 06/21] Minor tweak --- docs/rules/prefer-export-from.md | 24 ++++++++++++------------ rules/prefer-export-from.js | 1 + 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/rules/prefer-export-from.md b/docs/rules/prefer-export-from.md index a2f61efe7b..07edbce2c4 100644 --- a/docs/rules/prefer-export-from.md +++ b/docs/rules/prefer-export-from.md @@ -16,21 +16,21 @@ import {named} from './foo.js'; export {named}; ``` +```js +import * as namespace from './foo.js'; +export {namespace}; +``` + ```js import defaultExport, {named} from './foo.js'; +export default defaultExport; export { - defaultExport as default, defaultExport as renamedDefault, named, named as renamedNamed, }; ``` -```js -import * as namespace from './foo.js'; -export {namespace}; -``` - ## Pass ```js @@ -45,12 +45,6 @@ export {named} from './foo.js'; export * as namespace from './foo.js'; ``` -```js -// There is no substitute -import * as namespace from './foo.js'; -export default namespace; -``` - ```js export { default, @@ -59,3 +53,9 @@ export { named as renamedNamed, } from './foo.js'; ``` + +```js +// There is no substitute +import * as namespace from './foo.js'; +export default namespace; +``` diff --git a/rules/prefer-export-from.js b/rules/prefer-export-from.js index 3b2a1255de..72fee10ee4 100644 --- a/rules/prefer-export-from.js +++ b/rules/prefer-export-from.js @@ -4,6 +4,7 @@ const { isOpeningBraceToken, isClosingBraceToken, } = require('eslint-utils'); + const MESSAGE_ID = 'prefer-export-from'; const messages = { [MESSAGE_ID]: 'Use `export…from` syntax to re-export `{{imported}}`.', From 8bf20f88b42815b39d42c6583226287f426bee3c Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 28 Jul 2021 11:32:05 +0800 Subject: [PATCH 07/21] Word --- docs/rules/prefer-export-from.md | 2 +- rules/prefer-export-from.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/rules/prefer-export-from.md b/docs/rules/prefer-export-from.md index 07edbce2c4..8790a2c770 100644 --- a/docs/rules/prefer-export-from.md +++ b/docs/rules/prefer-export-from.md @@ -55,7 +55,7 @@ export { ``` ```js -// There is no substitute +// There is no substitution import * as namespace from './foo.js'; export default namespace; ``` diff --git a/rules/prefer-export-from.js b/rules/prefer-export-from.js index 72fee10ee4..c0dc8cce34 100644 --- a/rules/prefer-export-from.js +++ b/rules/prefer-export-from.js @@ -242,7 +242,7 @@ function getProblem({ const imported = getImported(identifier); /* - There is no substitute for + There is no substitution for ```js import * as foo from 'foo'; export default foo; From 66541fe47ed05b8371fefb92e77debb2111f2994 Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 28 Jul 2021 11:33:30 +0800 Subject: [PATCH 08/21] Revert package.json change --- package.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/package.json b/package.json index 5e85350070..35f0cbe6b4 100644 --- a/package.json +++ b/package.json @@ -61,12 +61,7 @@ "enquirer": "2.3.6", "eslint": "^7.28.0", "eslint-ava-rule-tester": "^4.0.0", - "eslint-plugin-ava": "12.0.0", - "eslint-plugin-eslint-comments": "3.2.0", "eslint-plugin-eslint-plugin": "^3.1.0", - "eslint-plugin-node": "11.1.0", - "eslint-plugin-promise": "5.1.0", - "eslint-plugin-unicorn": "34.0.1", "eslint-remote-tester": "^1.2.0", "execa": "^5.1.1", "listr": "^0.14.3", From 34f0d889549e9ccc66a2f9ccac5582c235486632 Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 28 Jul 2021 11:35:31 +0800 Subject: [PATCH 09/21] Docs and messages --- docs/rules/prefer-export-from.md | 2 +- readme.md | 2 +- rules/prefer-export-from.js | 4 +- test/snapshots/prefer-export-from.mjs.md | 88 ++++++++++----------- test/snapshots/prefer-export-from.mjs.snap | Bin 2117 -> 2112 bytes 5 files changed, 48 insertions(+), 48 deletions(-) diff --git a/docs/rules/prefer-export-from.md b/docs/rules/prefer-export-from.md index 8790a2c770..82a0c613ee 100644 --- a/docs/rules/prefer-export-from.md +++ b/docs/rules/prefer-export-from.md @@ -1,4 +1,4 @@ -# Prefer `export…from` syntax when re-exporting +# Prefer `export…from` when re-exporting When re-exporting from module, it's unnecessary to import and then export, it can be done in one `export…from` declaration. diff --git a/readme.md b/readme.md index 58cb930c25..af5962e469 100644 --- a/readme.md +++ b/readme.md @@ -211,7 +211,7 @@ Each rule has emojis denoting: | [prefer-dom-node-dataset](docs/rules/prefer-dom-node-dataset.md) | Prefer using `.dataset` on DOM elements over `.setAttribute(…)`. | βœ… | πŸ”§ | | | [prefer-dom-node-remove](docs/rules/prefer-dom-node-remove.md) | Prefer `childNode.remove()` over `parentNode.removeChild(childNode)`. | βœ… | πŸ”§ | πŸ’‘ | | [prefer-dom-node-text-content](docs/rules/prefer-dom-node-text-content.md) | Prefer `.textContent` over `.innerText`. | βœ… | | πŸ’‘ | -| [prefer-export-from](docs/rules/prefer-export-from.md) | Prefer `export…from` syntax when re-exporting. | βœ… | πŸ”§ | | +| [prefer-export-from](docs/rules/prefer-export-from.md) | Prefer `export…from` when re-exporting. | βœ… | πŸ”§ | | | [prefer-includes](docs/rules/prefer-includes.md) | Prefer `.includes()` over `.indexOf()` and `Array#some()` when checking for existence or non-existence. | βœ… | πŸ”§ | πŸ’‘ | | [prefer-keyboard-event-key](docs/rules/prefer-keyboard-event-key.md) | Prefer `KeyboardEvent#key` over `KeyboardEvent#keyCode`. | βœ… | πŸ”§ | | | [prefer-math-trunc](docs/rules/prefer-math-trunc.md) | Enforce the use of `Math.trunc` instead of bitwise operators. | βœ… | πŸ”§ | πŸ’‘ | diff --git a/rules/prefer-export-from.js b/rules/prefer-export-from.js index c0dc8cce34..3a250201df 100644 --- a/rules/prefer-export-from.js +++ b/rules/prefer-export-from.js @@ -7,7 +7,7 @@ const { const MESSAGE_ID = 'prefer-export-from'; const messages = { - [MESSAGE_ID]: 'Use `export…from` syntax to re-export `{{imported}}`.', + [MESSAGE_ID]: 'Use `export…from` to re-export `{{imported}}`.', }; function * removeSpecifier(node, options) { @@ -310,7 +310,7 @@ module.exports = { meta: { type: 'suggestion', docs: { - description: 'Prefer `export…from` syntax when re-exporting.', + description: 'Prefer `export…from` when re-exporting.', }, fixable: 'code', messages, diff --git a/test/snapshots/prefer-export-from.mjs.md b/test/snapshots/prefer-export-from.mjs.md index 76195496c7..687f3b7fe1 100644 --- a/test/snapshots/prefer-export-from.mjs.md +++ b/test/snapshots/prefer-export-from.mjs.md @@ -20,7 +20,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export default defaultExport;␊ ` @@ -40,7 +40,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export {defaultExport as default};␊ ` @@ -60,7 +60,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export {defaultExport as named};␊ ` @@ -80,7 +80,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export const variable = defaultExport;␊ ` @@ -100,7 +100,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {default as defaultExport} from 'foo';␊ - | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export default defaultExport;␊ ` @@ -120,7 +120,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {default as defaultExport} from 'foo';␊ - | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export {defaultExport as default};␊ ` @@ -140,7 +140,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {default as defaultExport} from 'foo';␊ - | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export {defaultExport as named};␊ ` @@ -160,7 +160,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export const variable = defaultExport;␊ ` @@ -180,7 +180,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ + | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ 2 | export default named;␊ ` @@ -200,7 +200,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ + | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ 2 | export {named as default};␊ ` @@ -220,7 +220,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ + | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ 2 | export {named as named};␊ ` @@ -240,7 +240,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ + | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ 2 | export {named as renamed};␊ ` @@ -260,7 +260,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ + | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ 2 | export const variable = named;␊ ` @@ -280,7 +280,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as namespace from 'foo';␊ - | ^^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ 2 | export {namespace as namespace};␊ ` @@ -300,7 +300,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as namespace from 'foo';␊ - | ^^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ 2 | export {namespace as renamed};␊ ` @@ -320,7 +320,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as namespace from 'foo';␊ - | ^^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ 2 | export const variable = namespace;␊ ` @@ -340,7 +340,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named1, named2} from 'foo';␊ - | ^^^^^^ Use \`export…from\` syntax to re-export \`named1\`.␊ + | ^^^^^^ Use \`export…from\` to re-export \`named1\`.␊ 2 | export {named1};␊ ` @@ -360,7 +360,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport, {named} from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export {defaultExport};␊ ` @@ -380,7 +380,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport, {named} from 'foo';␊ - | ^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ + | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ 2 | export {named};␊ ` @@ -400,7 +400,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport, * as namespace from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export {defaultExport};␊ ` @@ -422,7 +422,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ 2 | export {foo};␊ 3 | export * as bar from 'foo';␊ ` @@ -445,7 +445,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ 2 | export {foo};␊ 3 | export {bar} from 'foo';␊ ` @@ -468,7 +468,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ 2 | export {foo};␊ 3 | export {} from 'foo';␊ ` @@ -491,7 +491,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ 2 | export {foo};␊ 3 | export * from 'foo';␊ ` @@ -514,7 +514,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import foo from 'foo';␊ - | ^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export {foo};␊ 3 | export * as bar from 'foo';␊ ` @@ -536,7 +536,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import foo from 'foo';␊ - | ^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export {foo};␊ 3 | export {bar} from 'foo';␊ ` @@ -558,7 +558,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import foo from 'foo';␊ - | ^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export {foo};␊ 3 | export {bar,} from 'foo';␊ ` @@ -580,7 +580,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import foo from 'foo';␊ - | ^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export {foo};␊ 3 | export {} from 'foo';␊ ` @@ -603,7 +603,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import foo from 'foo';␊ - | ^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export {foo};␊ 3 | export * from 'foo';␊ ` @@ -624,7 +624,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named1, named2} from 'foo';␊ - | ^^^^^^ Use \`export…from\` syntax to re-export \`named1\`.␊ + | ^^^^^^ Use \`export…from\` to re-export \`named1\`.␊ 2 | export {named1, named2};␊ ` @@ -632,7 +632,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named1, named2} from 'foo';␊ - | ^^^^^^ Use \`export…from\` syntax to re-export \`named2\`.␊ + | ^^^^^^ Use \`export…from\` to re-export \`named2\`.␊ 2 | export {named1, named2};␊ ` @@ -652,7 +652,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ + | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ 2 | export {named as default, named};␊ ` @@ -672,7 +672,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named, named as renamed} from 'foo';␊ - | ^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ + | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ 2 | export {named, renamed};␊ ` @@ -680,7 +680,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import {named, named as renamed} from 'foo';␊ - | ^^^^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`named\`.␊ + | ^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`named\`.␊ 2 | export {named, renamed};␊ ` @@ -704,7 +704,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport, {named1, named2} from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export {named1 as default};␊ 3 | export {named2};␊ 4 | export {defaultExport};␊ @@ -714,7 +714,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport, {named1, named2} from 'foo';␊ - | ^^^^^^ Use \`export…from\` syntax to re-export \`named1\`.␊ + | ^^^^^^ Use \`export…from\` to re-export \`named1\`.␊ 2 | export {named1 as default};␊ 3 | export {named2};␊ 4 | export {defaultExport};␊ @@ -724,7 +724,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport, {named1, named2} from 'foo';␊ - | ^^^^^^ Use \`export…from\` syntax to re-export \`named2\`.␊ + | ^^^^^^ Use \`export…from\` to re-export \`named2\`.␊ 2 | export {named1 as default};␊ 3 | export {named2};␊ 4 | export {defaultExport};␊ @@ -749,7 +749,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ 2 | import * as bar from 'foo';␊ 3 | export {foo, bar};␊ ` @@ -759,7 +759,7 @@ Generated by [AVA](https://avajs.dev). `␊ 1 | import * as foo from 'foo';␊ > 2 | import * as bar from 'foo';␊ - | ^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ 3 | export {foo, bar};␊ ` @@ -780,7 +780,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export…from\` syntax to re-export \`*\`.␊ + | ^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ 2 | export {foo, foo as bar};␊ ` @@ -802,7 +802,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export * from 'foo';␊ 3 | export default defaultExport;␊ ` @@ -826,7 +826,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export {named} from 'foo';␊ 3 | export * from 'foo';␊ 4 | export default defaultExport;␊ @@ -849,7 +849,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from './foo.js';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export {named} from './foo.js';␊ 3 | export default defaultExport;␊ ` @@ -872,7 +872,7 @@ Generated by [AVA](https://avajs.dev). `␊ > 1 | import defaultExport from './foo.js';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` syntax to re-export \`default\`.␊ + | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ 2 | export {named} from './foo.js?query';␊ 3 | export default defaultExport;␊ ` diff --git a/test/snapshots/prefer-export-from.mjs.snap b/test/snapshots/prefer-export-from.mjs.snap index 97d2bd9be88704008e9eda759725f4555bd36809..2796aba4619fdf91691aa14e044f60a2936f9db2 100644 GIT binary patch literal 2112 zcmV-G2*3A1RzV!gF!OFBWU&lwy-nqce?98269=n{=obz$u+nqcA_y7O>?|<(w zr!@c$pv$r4@T6_E`y&s(*<*4%@*vP&<1i{|bi0u0TCOD(VMo_enzY9cU+4veE#XB(vnC;t{Gw%Vpz0caEyji zM5mb}HQv_!qtXTr03ihsvBS(6T&Cd`vFudP^GB`xzmF!Vg zTLS~e9QJ%*b3XajN{HBJ82Rl0@IJL5^NoD}Z0n%H;_oX`XhB-mO3t8&hOgfXjq{W6 zwQduKWLSh$9e{}KW5M7!4gVV%k?Ou90DKtm&$3PjUxkPT?HTN%5%k@P{Paaxv{9V5O20B?k)7e_1)TYYhs<-XA=esdvWk7KN}1YnL|n@V5r!s>$8m$#lc z?OJz;*zYjrcLX4+P3Xmeo6OzcDnAlnH9USAMC@LSNuB6#SQcr%aoKk7e#MYdP048= zh}bn4UY!Amt+2Zv8|pH3-x|#?UAsNhK*Vmt7-9v$%I;?`UpY6_GPmEF_|4CD3~q(k zofsKi7$kIM5Zw)cw9QHnpOBAJr~TmHvE)t-ZI_lkjS*%|-*L+CVTYglEP9-ka8vG7 z;0Y1?CB~fY0Ibc@{QPE@1LJe;sPcVwcH1Fhw_=R50brx%-z|eK7k~EqMElM^o^xCc z5u1Zy{}KS29{;3YZCBy^Xx&t|Tb5tkfQSvl=+^^)cTbOJ#_lJm$ z!m#NHz!8g@3BIenCQr{>6~H7i0wl$I6>ofbWhi} zhi{$|dp@n8@WW9K5V5`bGB`ow&a;U2GY`a``>Djb{Pvi$lo?|C+c7wgv9uomcfTJx zySk#x-g^2IP+i?=2}JBMj4AyA`1|^SXFIzpo)!h!2CMGRFNTQC#IUvp;9k(}b?T6~ zhczol{&fGy8M=CC*~J*L0RTMS_I$@*iY*ILC(IuHc(Sdh8Db}4T*pXt0N{CL*%Qmi zsz0(9XV_IOFH3=ly^B#Y5P*Me_E-CKRL}A`Y`L?XQqprl%eEWDU_T8rV2fVcg zorp$F7S_xWZIFEY3_T~Xo?S15Zz}^+(th zx!n0BX$YR_CBYwPApRs$2$V{=s|oBAr~=Jnu`Ha4Pp!e^%1o?{g!;zvQ64Fs6%AV& znyNG!vMd;owkvtlqM4JFu%eHVw%RRK#ziXUE>aPcy>HUm6c!V$j;}M5@*q~CU{0p< z2cbz)TtiNA(eN83w}V95y1B|Y;RR9GEA+<(lx+GdMB$B)t2IP#P3KXn=tEKk6KPc)htZ}vE>PDsV65mJmr%i2BQ$qs z$~D)JZflg3I7=w&X~tc!c=MPW@|UG8TI6c9&ZN~SkubN0i_0VE+S@WWo>Fo)K%@Zc zhsf2C`kum5oW-Kv;DW3Tx&jT)n8jUlBlNZ6jWR{KN$5H7PQpp&157y+lH-z;cEpK) zpysQ0x+3%@3N}Tc>)>r@U}aOuV@Et-5HHy8w19#w)_nRB;?7M~gT${lxp>lE#)BZ6_E+5w z9UHA6I);bI78aJCi?F;;%jdc9JkcgrT+ksw92gtF8}}=>lRJ` literal 2117 zcmV-L2)g${RzV1Gy^r-zis zG6gJ3OOnV(NoM%UM}%PIqwtZQe02BT0d{6*?##la72MZH^d}i*8b_WA~co!hnO@?s- zqTg1ZWxo|gdNyqM_tW>IYa;++djpIM5KeCfZ@5A`+%B#vpDi!k5&{tGXN57ynxY2o z`ye-O)Z{+n(~HJkTUO8qAU1JVB9fh1m5BylpV9Ln!0B zOc|ve?=U!V?a(1qbP+&oj4ej@_VAnWODdu+J~6D)Kho{VkG|;u5Ic>*-w;pdjqbKJ zB7AI#-)+b5Gq0=!h#k`b;~K>Hia9wi?Fh?rh$=2SS-t!)K0Ev|Z4o z3%vkheLG{EhDfxDIWhEgTc5>MrQzL1rcDBf?cW9C07RnwKJ5>l+Zt|G4?m6%^I;o zyJI-?z_9CyA$OptwVPDF!O@?rnDld4=kn|I&@LSt%fO}=MP*ln-syC9z`VP;i!RHR zMScLWvl!SoQq-%t+Oscr-~CL!GhMaI*|`uPHjqIB#76C-EyK>0eep+-OV?A!+*bp{ z`uD~-525XIE9-oRYL9=`P4vEE|8)&OY~MZ@H4txn8xWWg*{;UrhIPa>)q^mASVdoq z3lOCp>jOhp`%jo$uxdu-+9{m@VtxBzT!Hv zm%nqNcaD7D;Z8Gb_g>mr3=pdvfKd%`yy5bt+qtXU_k2G6(5dY7Jb>69P8j=SDL z%$uL>T)VV#IY6xAFpLI>M~)xY1$Wj=4KA_YUPY_mT+p#TZWxy#tSDQQM`i7(t};(K zO)KdP`00T@J?RWuy?B0dY8vfEt2A_~I!TqNj-zL#CMVLavyzit$H?_>0N$YFe!4r* z35m^D>8{btSItzjuA||RK{H1*>!4rIsOcE|;F=X5=&p*PHA|AxREz1fWN5_*#;6## z7{DLwRxBq~bDYGs zN?J&?-WNPWDJG-wRO6ts4Cgp8gwKiGdwQZTco~imA;d~7!FxPHjB!o?VYV@Gh7+h> zZW8v$7Ve~zbPJw2C*3XRe*7V&5Xh$BBNLb@kRcwc;j%b9T8(y-b2u@55>g<`Rqv5v zT+y;c#KhUtm<7a$SkC4RlD3IlLM1R(+VZ$im71W6ou?)UeAg1v*UaQ3OwE&MGmN&da zywMbEfB|;z|kR zaFJYXIAC5zECnEoFOiD{L2Hw@E(R3nDcC&jY8`K=nc14tw6}z!h1sSk^-eI92O(B2 zN~vd*{5N{+IZznWxKy`Fy+_-qmj#n@2|0;y zQv%DYo6VI(3`<|ZbtIxi+NCd~`IfMd67;uj9WAtkjj&-yxOsB0wE7!S^DD%f92?Bs z21!w=E~Ni*+?Z2vNX|U!#1WwGs)hy Date: Wed, 28 Jul 2021 11:40:17 +0800 Subject: [PATCH 10/21] Exclude `ExportSpecifier` --- rules/prefer-export-from.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rules/prefer-export-from.js b/rules/prefer-export-from.js index 3a250201df..9b48f42d46 100644 --- a/rules/prefer-export-from.js +++ b/rules/prefer-export-from.js @@ -26,13 +26,13 @@ function * removeSpecifier(node, options) { } switch (node.type) { - case 'ExportSpecifier': case 'ImportSpecifier': { const hasOtherSpecifiers = specifiers.some(specifier => specifier !== node && specifier.type === node.type); if (!hasOtherSpecifiers) { const closingBraceToken = sourceCode.getTokenAfter(node, isClosingBraceToken); - // If there are other specifiers, they have to be default import/export - // And default import/export has to write before the named import/export + + // If there are other specifiers, they have to be the default import specifier + // And the default import has to write before the named import specifiers // So there must be a comma before const commaToken = sourceCode.getTokenBefore(node, isCommaToken); yield fixer.replaceTextRange([commaToken.range[0], closingBraceToken.range[1]], ''); @@ -41,6 +41,7 @@ function * removeSpecifier(node, options) { // Fallthrough } + case 'ExportSpecifier': case 'ImportNamespaceSpecifier': case 'ImportDefaultSpecifier': { yield fixer.remove(node); From ffc3b7b3b04d5b7ed8c2e7aa41fb58dd65e2eba4 Mon Sep 17 00:00:00 2001 From: fisker Date: Fri, 30 Jul 2021 09:50:03 +0800 Subject: [PATCH 11/21] Move report to `Export*Declaration` --- rules/prefer-export-from.js | 42 ++-- test/snapshots/prefer-export-from.mjs.md | 274 +++++++++++---------- test/snapshots/prefer-export-from.mjs.snap | Bin 2112 -> 2194 bytes 3 files changed, 165 insertions(+), 151 deletions(-) diff --git a/rules/prefer-export-from.js b/rules/prefer-export-from.js index 9b48f42d46..5735b205bf 100644 --- a/rules/prefer-export-from.js +++ b/rules/prefer-export-from.js @@ -7,7 +7,7 @@ const { const MESSAGE_ID = 'prefer-export-from'; const messages = { - [MESSAGE_ID]: 'Use `export…from` to re-export `{{imported}}`.', + [MESSAGE_ID]: 'Use `export…from` to re-export `{{exported}}`.', }; function * removeSpecifier(node, options) { @@ -220,7 +220,7 @@ function isVariableUnused(node, context) { references[0].identifier === node.id; } -function getProblem({ +function * getProblems({ context, variable, importDeclaration, @@ -253,21 +253,23 @@ function getProblem({ return; } - return { - node: imported.node, - messageId: MESSAGE_ID, - data: { - imported: imported.name, - }, - fix: fix({ - context, - imported, - importDeclaration, - exported, - exportDeclarations, - program, - }), - }; + for (const {node, name} of exported) { + yield { + node: node, + messageId: MESSAGE_ID, + data: { + exported: name, + }, + fix: fix({ + context, + imported, + importDeclaration, + exported, + exportDeclarations, + program, + }), + }; + } } /** @param {import('eslint').Rule.RuleContext} context */ @@ -289,17 +291,13 @@ function create(context) { * 'Program:exit'(program) { for (const {node: importDeclaration, variables} of importDeclarations) { for (const variable of variables) { - const problem = getProblem({ + yield * getProblems({ context, variable, importDeclaration, exportDeclarations, program, }); - - if (problem) { - yield problem; - } } } }, diff --git a/test/snapshots/prefer-export-from.mjs.md b/test/snapshots/prefer-export-from.mjs.md index 687f3b7fe1..37e68eca96 100644 --- a/test/snapshots/prefer-export-from.mjs.md +++ b/test/snapshots/prefer-export-from.mjs.md @@ -19,9 +19,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ - 2 | export default defaultExport;␊ + 1 | import defaultExport from 'foo';␊ + > 2 | export default defaultExport;␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` ## Invalid #2 @@ -39,9 +39,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ - 2 | export {defaultExport as default};␊ + 1 | import defaultExport from 'foo';␊ + > 2 | export {defaultExport as default};␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` ## Invalid #3 @@ -59,9 +59,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ - 2 | export {defaultExport as named};␊ + 1 | import defaultExport from 'foo';␊ + > 2 | export {defaultExport as named};␊ + | ^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`named\`.␊ ` ## Invalid #4 @@ -79,9 +79,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ - 2 | export const variable = defaultExport;␊ + 1 | import defaultExport from 'foo';␊ + > 2 | export const variable = defaultExport;␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`variable\`.␊ ` ## Invalid #5 @@ -99,9 +99,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import {default as defaultExport} from 'foo';␊ - | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ - 2 | export default defaultExport;␊ + 1 | import {default as defaultExport} from 'foo';␊ + > 2 | export default defaultExport;␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` ## Invalid #6 @@ -119,9 +119,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import {default as defaultExport} from 'foo';␊ + 1 | import {default as defaultExport} from 'foo';␊ + > 2 | export {defaultExport as default};␊ | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ - 2 | export {defaultExport as default};␊ ` ## Invalid #7 @@ -139,9 +139,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import {default as defaultExport} from 'foo';␊ - | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ - 2 | export {defaultExport as named};␊ + 1 | import {default as defaultExport} from 'foo';␊ + > 2 | export {defaultExport as named};␊ + | ^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`named\`.␊ ` ## Invalid #8 @@ -159,9 +159,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ - 2 | export const variable = defaultExport;␊ + 1 | import defaultExport from 'foo';␊ + > 2 | export const variable = defaultExport;␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`variable\`.␊ ` ## Invalid #9 @@ -179,9 +179,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ - 2 | export default named;␊ + 1 | import {named} from 'foo';␊ + > 2 | export default named;␊ + | ^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` ## Invalid #10 @@ -199,9 +199,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ - 2 | export {named as default};␊ + 1 | import {named} from 'foo';␊ + > 2 | export {named as default};␊ + | ^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` ## Invalid #11 @@ -219,9 +219,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ - 2 | export {named as named};␊ + 1 | import {named} from 'foo';␊ + > 2 | export {named as named};␊ + | ^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`named\`.␊ ` ## Invalid #12 @@ -239,9 +239,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ - 2 | export {named as renamed};␊ + 1 | import {named} from 'foo';␊ + > 2 | export {named as renamed};␊ + | ^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`renamed\`.␊ ` ## Invalid #13 @@ -259,9 +259,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ - 2 | export const variable = named;␊ + 1 | import {named} from 'foo';␊ + > 2 | export const variable = named;␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`variable\`.␊ ` ## Invalid #14 @@ -279,9 +279,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import * as namespace from 'foo';␊ - | ^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ - 2 | export {namespace as namespace};␊ + 1 | import * as namespace from 'foo';␊ + > 2 | export {namespace as namespace};␊ + | ^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`namespace\`.␊ ` ## Invalid #15 @@ -299,9 +299,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import * as namespace from 'foo';␊ - | ^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ - 2 | export {namespace as renamed};␊ + 1 | import * as namespace from 'foo';␊ + > 2 | export {namespace as renamed};␊ + | ^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`renamed\`.␊ ` ## Invalid #16 @@ -319,9 +319,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import * as namespace from 'foo';␊ - | ^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ - 2 | export const variable = namespace;␊ + 1 | import * as namespace from 'foo';␊ + > 2 | export const variable = namespace;␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`variable\`.␊ ` ## Invalid #17 @@ -339,9 +339,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import {named1, named2} from 'foo';␊ + 1 | import {named1, named2} from 'foo';␊ + > 2 | export {named1};␊ | ^^^^^^ Use \`export…from\` to re-export \`named1\`.␊ - 2 | export {named1};␊ ` ## Invalid #18 @@ -359,9 +359,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import defaultExport, {named} from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ - 2 | export {defaultExport};␊ + 1 | import defaultExport, {named} from 'foo';␊ + > 2 | export {defaultExport};␊ + | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`defaultExport\`.␊ ` ## Invalid #19 @@ -379,9 +379,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import defaultExport, {named} from 'foo';␊ - | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ - 2 | export {named};␊ + 1 | import defaultExport, {named} from 'foo';␊ + > 2 | export {named};␊ + | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ ` ## Invalid #20 @@ -399,9 +399,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import defaultExport, * as namespace from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ - 2 | export {defaultExport};␊ + 1 | import defaultExport, * as namespace from 'foo';␊ + > 2 | export {defaultExport};␊ + | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`defaultExport\`.␊ ` ## Invalid #21 @@ -421,9 +421,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ - 2 | export {foo};␊ + 1 | import * as foo from 'foo';␊ + > 2 | export {foo};␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ 3 | export * as bar from 'foo';␊ ` @@ -444,9 +444,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ - 2 | export {foo};␊ + 1 | import * as foo from 'foo';␊ + > 2 | export {foo};␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ 3 | export {bar} from 'foo';␊ ` @@ -467,9 +467,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ - 2 | export {foo};␊ + 1 | import * as foo from 'foo';␊ + > 2 | export {foo};␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ 3 | export {} from 'foo';␊ ` @@ -490,9 +490,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ - 2 | export {foo};␊ + 1 | import * as foo from 'foo';␊ + > 2 | export {foo};␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ 3 | export * from 'foo';␊ ` @@ -513,9 +513,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import foo from 'foo';␊ - | ^^^ Use \`export…from\` to re-export \`default\`.␊ - 2 | export {foo};␊ + 1 | import foo from 'foo';␊ + > 2 | export {foo};␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ 3 | export * as bar from 'foo';␊ ` @@ -535,9 +535,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import foo from 'foo';␊ - | ^^^ Use \`export…from\` to re-export \`default\`.␊ - 2 | export {foo};␊ + 1 | import foo from 'foo';␊ + > 2 | export {foo};␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ 3 | export {bar} from 'foo';␊ ` @@ -557,9 +557,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import foo from 'foo';␊ - | ^^^ Use \`export…from\` to re-export \`default\`.␊ - 2 | export {foo};␊ + 1 | import foo from 'foo';␊ + > 2 | export {foo};␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ 3 | export {bar,} from 'foo';␊ ` @@ -579,9 +579,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import foo from 'foo';␊ - | ^^^ Use \`export…from\` to re-export \`default\`.␊ - 2 | export {foo};␊ + 1 | import foo from 'foo';␊ + > 2 | export {foo};␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ 3 | export {} from 'foo';␊ ` @@ -602,9 +602,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import foo from 'foo';␊ - | ^^^ Use \`export…from\` to re-export \`default\`.␊ - 2 | export {foo};␊ + 1 | import foo from 'foo';␊ + > 2 | export {foo};␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ 3 | export * from 'foo';␊ ` @@ -623,17 +623,17 @@ Generated by [AVA](https://avajs.dev). > Error 1/2 `␊ - > 1 | import {named1, named2} from 'foo';␊ + 1 | import {named1, named2} from 'foo';␊ + > 2 | export {named1, named2};␊ | ^^^^^^ Use \`export…from\` to re-export \`named1\`.␊ - 2 | export {named1, named2};␊ ` > Error 2/2 `␊ - > 1 | import {named1, named2} from 'foo';␊ + 1 | import {named1, named2} from 'foo';␊ + > 2 | export {named1, named2};␊ | ^^^^^^ Use \`export…from\` to re-export \`named2\`.␊ - 2 | export {named1, named2};␊ ` ## Invalid #31 @@ -648,12 +648,20 @@ Generated by [AVA](https://avajs.dev). 3 | export {named as default,named} from 'foo';␊ ` -> Error 1/1 +> Error 1/2 `␊ - > 1 | import {named} from 'foo';␊ - | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ - 2 | export {named as default, named};␊ + 1 | import {named} from 'foo';␊ + > 2 | export {named as default, named};␊ + | ^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ + ` + +> Error 2/2 + + `␊ + 1 | import {named} from 'foo';␊ + > 2 | export {named as default, named};␊ + | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ ` ## Invalid #32 @@ -671,17 +679,17 @@ Generated by [AVA](https://avajs.dev). > Error 1/2 `␊ - > 1 | import {named, named as renamed} from 'foo';␊ + 1 | import {named, named as renamed} from 'foo';␊ + > 2 | export {named, renamed};␊ | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ - 2 | export {named, renamed};␊ ` > Error 2/2 `␊ - > 1 | import {named, named as renamed} from 'foo';␊ - | ^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`named\`.␊ - 2 | export {named, renamed};␊ + 1 | import {named, named as renamed} from 'foo';␊ + > 2 | export {named, renamed};␊ + | ^^^^^^^ Use \`export…from\` to re-export \`renamed\`.␊ ` ## Invalid #33 @@ -703,9 +711,9 @@ Generated by [AVA](https://avajs.dev). > Error 1/3 `␊ - > 1 | import defaultExport, {named1, named2} from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ - 2 | export {named1 as default};␊ + 1 | import defaultExport, {named1, named2} from 'foo';␊ + > 2 | export {named1 as default};␊ + | ^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ 3 | export {named2};␊ 4 | export {defaultExport};␊ ` @@ -713,21 +721,21 @@ Generated by [AVA](https://avajs.dev). > Error 2/3 `␊ - > 1 | import defaultExport, {named1, named2} from 'foo';␊ - | ^^^^^^ Use \`export…from\` to re-export \`named1\`.␊ + 1 | import defaultExport, {named1, named2} from 'foo';␊ 2 | export {named1 as default};␊ - 3 | export {named2};␊ + > 3 | export {named2};␊ + | ^^^^^^ Use \`export…from\` to re-export \`named2\`.␊ 4 | export {defaultExport};␊ ` > Error 3/3 `␊ - > 1 | import defaultExport, {named1, named2} from 'foo';␊ - | ^^^^^^ Use \`export…from\` to re-export \`named2\`.␊ + 1 | import defaultExport, {named1, named2} from 'foo';␊ 2 | export {named1 as default};␊ 3 | export {named2};␊ - 4 | export {defaultExport};␊ + > 4 | export {defaultExport};␊ + | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`defaultExport\`.␊ ` ## Invalid #34 @@ -748,19 +756,19 @@ Generated by [AVA](https://avajs.dev). > Error 1/2 `␊ - > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ + 1 | import * as foo from 'foo';␊ 2 | import * as bar from 'foo';␊ - 3 | export {foo, bar};␊ + > 3 | export {foo, bar};␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ ` > Error 2/2 `␊ 1 | import * as foo from 'foo';␊ - > 2 | import * as bar from 'foo';␊ - | ^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ - 3 | export {foo, bar};␊ + 2 | import * as bar from 'foo';␊ + > 3 | export {foo, bar};␊ + | ^^^ Use \`export…from\` to re-export \`bar\`.␊ ` ## Invalid #35 @@ -776,12 +784,20 @@ Generated by [AVA](https://avajs.dev). 4 | export * as bar from 'foo';␊ ` -> Error 1/1 +> Error 1/2 + + `␊ + 1 | import * as foo from 'foo';␊ + > 2 | export {foo, foo as bar};␊ + | ^^^ Use \`export…from\` to re-export \`foo\`.␊ + ` + +> Error 2/2 `␊ - > 1 | import * as foo from 'foo';␊ - | ^^^^^^^^ Use \`export…from\` to re-export \`*\`.␊ - 2 | export {foo, foo as bar};␊ + 1 | import * as foo from 'foo';␊ + > 2 | export {foo, foo as bar};␊ + | ^^^^^^^^^^ Use \`export…from\` to re-export \`bar\`.␊ ` ## Invalid #36 @@ -801,10 +817,10 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ + 1 | import defaultExport from 'foo';␊ 2 | export * from 'foo';␊ - 3 | export default defaultExport;␊ + > 3 | export default defaultExport;␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` ## Invalid #37 @@ -825,11 +841,11 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import defaultExport from 'foo';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ + 1 | import defaultExport from 'foo';␊ 2 | export {named} from 'foo';␊ 3 | export * from 'foo';␊ - 4 | export default defaultExport;␊ + > 4 | export default defaultExport;␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` ## Invalid #38 @@ -848,10 +864,10 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import defaultExport from './foo.js';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ + 1 | import defaultExport from './foo.js';␊ 2 | export {named} from './foo.js';␊ - 3 | export default defaultExport;␊ + > 3 | export default defaultExport;␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` ## Invalid #39 @@ -871,8 +887,8 @@ Generated by [AVA](https://avajs.dev). > Error 1/1 `␊ - > 1 | import defaultExport from './foo.js';␊ - | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ + 1 | import defaultExport from './foo.js';␊ 2 | export {named} from './foo.js?query';␊ - 3 | export default defaultExport;␊ + > 3 | export default defaultExport;␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` diff --git a/test/snapshots/prefer-export-from.mjs.snap b/test/snapshots/prefer-export-from.mjs.snap index 2796aba4619fdf91691aa14e044f60a2936f9db2..5c596dc16644e97e7df336e1b9f9458fada10333 100644 GIT binary patch literal 2194 zcmV;D2yOR4RzVIr;X%j7QUCadP9MA8zZe45XFP+O2t6<6DGqK=JUQ{LS34aXcl<+$rJhza>Jj>F z8@2RuX|zxChKKt;j%|p7Sn398Tt;x*8oc2u<#4a8rgDz$_M#Aor4y}b3~mEJ|ME}r z3r0@u6O>sx{^ru+J`hV+F_?mEb%}1X{g!XViEq9&CH*QGmhlJjd;UrNt% zN?N!CVrdwI%LuQ}%Be_LJZsgd*X(zXSr$4IV(CzO8rGcwcq6o3T}V(_W9h4l+fI(S z*b8E52!j@cly-5a25q((^>)pH$Znn)5fDp9cA;?sA;rF2dEBR@xutf9-7a_Mnm1lg2^^0J68p{DWinERXm-ymRHPCS;#VdV)bxF933@LR;<5zL0!Bf8iBd zuhIaBrAHXV^#)*VzVhsw-SZa^* zIK)z)el+eN9O&3IDP&dPl&QrlXH;iT>kP3p;&~d)2;c0;YpU8`ylZKD-}$FrbUqKU zG~@*uO$a{~?polNXIuWW-3*&A>UNbuEcJGzaSY)^^Od@L`71p>|LToHf8=HsKrHP@ z(Kvu`x-jQ3WzlT`b%HSO* z0B+3f>$}Et%gbrUvP;W$j&_Au+RPwl006fhC3Kp$H|^+|N{5;oV}GHnvGh8FP0lm| zTmZQJ+tBHawbd>TQy+lF#xC8i>4iY44*CdbmF8(vGMxJRoa0F!&l{DOyMjgWalE?4=?Ov3$eA0B!`%@ePtg+N(5RLB`yy*tO z7H#nEc& zmw%#qLmZWnigXNRbjLC3;yhTkTKNf(NCE9Ge#>CLkC-II$1SZ*$|fNpY}fOKgYrAP7|DQEfK+y0%@B&IjpTq zcvr~cN$G;~?T&}gs*Rd^)(qwGZ7;^z!l@)g*oCxkXCOg$2AEa>Mfr)Sp_r4Cm(~}I z$eR$a7sQlTUi^x9%5d$s3-@Fsg)2{1_0G~$LuraV7T1$TaOK&EI9vnt*{ACQu}5Za zOj|U+OJ?P#$NvFD`^;Eu2a_@uIaP62JIjmt2IU7+me_i;Xp}*e#qY>#EP1dn(}qm! zq)6#Ai_U6B@5O-}y{gihM@29YL5mU5P_zA;pX0uWEBPjuMXU4ct+-H{ik7pN` z|98K{)yl*+kMIVx+2R|JP&FSy2n23fA&Gi{g{hOyh5iK6$Xl8|2xGE4A^f=|#U znEpD|YMQ?Gfj}F_j}o8wVUd_gr;n1_Be*)*M`heyF=>m3_XkC0GgE@CJZ&EnT^ks2 zZ7Q~aG(6XO2yv9qC6+);%(2DLZVQ~&?~ literal 2112 zcmV-G2*3A1RzV!gF!OFBWU&lwy-nqce?98269=n{=obz$u+nqcA_y7O>?|<(w zr!@c$pv$r4@T6_E`y&s(*<*4%@*vP&<1i{|bi0u0TCOD(VMo_enzY9cU+4veE#XB(vnC;t{Gw%Vpz0caEyji zM5mb}HQv_!qtXTr03ihsvBS(6T&Cd`vFudP^GB`xzmF!Vg zTLS~e9QJ%*b3XajN{HBJ82Rl0@IJL5^NoD}Z0n%H;_oX`XhB-mO3t8&hOgfXjq{W6 zwQduKWLSh$9e{}KW5M7!4gVV%k?Ou90DKtm&$3PjUxkPT?HTN%5%k@P{Paaxv{9V5O20B?k)7e_1)TYYhs<-XA=esdvWk7KN}1YnL|n@V5r!s>$8m$#lc z?OJz;*zYjrcLX4+P3Xmeo6OzcDnAlnH9USAMC@LSNuB6#SQcr%aoKk7e#MYdP048= zh}bn4UY!Amt+2Zv8|pH3-x|#?UAsNhK*Vmt7-9v$%I;?`UpY6_GPmEF_|4CD3~q(k zofsKi7$kIM5Zw)cw9QHnpOBAJr~TmHvE)t-ZI_lkjS*%|-*L+CVTYglEP9-ka8vG7 z;0Y1?CB~fY0Ibc@{QPE@1LJe;sPcVwcH1Fhw_=R50brx%-z|eK7k~EqMElM^o^xCc z5u1Zy{}KS29{;3YZCBy^Xx&t|Tb5tkfQSvl=+^^)cTbOJ#_lJm$ z!m#NHz!8g@3BIenCQr{>6~H7i0wl$I6>ofbWhi} zhi{$|dp@n8@WW9K5V5`bGB`ow&a;U2GY`a``>Djb{Pvi$lo?|C+c7wgv9uomcfTJx zySk#x-g^2IP+i?=2}JBMj4AyA`1|^SXFIzpo)!h!2CMGRFNTQC#IUvp;9k(}b?T6~ zhczol{&fGy8M=CC*~J*L0RTMS_I$@*iY*ILC(IuHc(Sdh8Db}4T*pXt0N{CL*%Qmi zsz0(9XV_IOFH3=ly^B#Y5P*Me_E-CKRL}A`Y`L?XQqprl%eEWDU_T8rV2fVcg zorp$F7S_xWZIFEY3_T~Xo?S15Zz}^+(th zx!n0BX$YR_CBYwPApRs$2$V{=s|oBAr~=Jnu`Ha4Pp!e^%1o?{g!;zvQ64Fs6%AV& znyNG!vMd;owkvtlqM4JFu%eHVw%RRK#ziXUE>aPcy>HUm6c!V$j;}M5@*q~CU{0p< z2cbz)TtiNA(eN83w}V95y1B|Y;RR9GEA+<(lx+GdMB$B)t2IP#P3KXn=tEKk6KPc)htZ}vE>PDsV65mJmr%i2BQ$qs z$~D)JZflg3I7=w&X~tc!c=MPW@|UG8TI6c9&ZN~SkubN0i_0VE+S@WWo>Fo)K%@Zc zhsf2C`kum5oW-Kv;DW3Tx&jT)n8jUlBlNZ6jWR{KN$5H7PQpp&157y+lH-z;cEpK) zpysQ0x+3%@3N}Tc>)>r@U}aOuV@Et-5HHy8w19#w)_nRB;?7M~gT${lxp>lE#)BZ6_E+5w z9UHA6I);bI78aJCi?F;;%jdc9JkcgrT+ksw92gtF8}}=>lRJ` From d41b586823d8c4a26efbb3eeec04f0942b0eaf26 Mon Sep 17 00:00:00 2001 From: fisker Date: Fri, 30 Jul 2021 10:30:12 +0800 Subject: [PATCH 12/21] Simplify fix --- rules/prefer-export-from.js | 62 ++++++++------------- test/snapshots/prefer-export-from.mjs.md | 2 +- test/snapshots/prefer-export-from.mjs.snap | Bin 2194 -> 2196 bytes 3 files changed, 24 insertions(+), 40 deletions(-) diff --git a/rules/prefer-export-from.js b/rules/prefer-export-from.js index 5735b205bf..35f669a458 100644 --- a/rules/prefer-export-from.js +++ b/rules/prefer-export-from.js @@ -10,18 +10,12 @@ const messages = { [MESSAGE_ID]: 'Use `export…from` to re-export `{{exported}}`.', }; -function * removeSpecifier(node, options) { - const {nodes, removedSpecifiers, fixer, sourceCode} = options; - +function * removeSpecifier(node, fixer, sourceCode) { const {parent} = node; const {specifiers} = parent; - if (specifiers.every(specifier => nodes.has(specifier))) { - for (const specifier of specifiers) { - removedSpecifiers.add(specifier); - } - - yield * removeImportOrExport(parent, options); + if (specifiers.length === 1) { + yield * removeImportOrExport(parent, fixer, sourceCode); return; } @@ -58,20 +52,20 @@ function * removeSpecifier(node, options) { } } -function * removeImportOrExport(node, options) { +function * removeImportOrExport(node, fixer, sourceCode) { switch (node.type) { case 'ImportSpecifier': case 'ExportSpecifier': case 'ImportDefaultSpecifier': case 'ImportNamespaceSpecifier': { - yield * removeSpecifier(node, options); + yield * removeSpecifier(node, fixer, sourceCode); return; } case 'ImportDeclaration': case 'ExportDefaultDeclaration': case 'ExportNamedDeclaration': { - yield options.fixer.remove(node); + yield fixer.remove(node); } // No default @@ -82,6 +76,7 @@ function fix({ context, imported, importDeclaration, + removeImportNode, exported, exportDeclarations, program, @@ -95,49 +90,37 @@ function fix({ /** @param {import('eslint').Rule.RuleFixer} fixer */ return function * (fixer) { if (imported.name === '*') { - for (const {name: exportedName} of exported) { - yield fixer.insertTextAfter( - program, - `\nexport * as ${exportedName} from ${sourceText};`, - ); - } + yield fixer.insertTextAfter( + program, + `\nexport * as ${exported.name} from ${sourceText};`, + ); } else { - const specifiers = exported.map(({name}) => name === imported.name ? name : `${imported.name} as ${name}`) - .join(','); + const specifier = exported.name === imported.name ? + exported.name : + `${imported.name} as ${exported.name}`; if (exportDeclaration) { const lastSpecifier = exportDeclaration.specifiers[exportDeclaration.specifiers.length - 1]; // `export {} from 'foo';` if (lastSpecifier) { - yield fixer.insertTextAfter(lastSpecifier, `, ${specifiers}`); + yield fixer.insertTextAfter(lastSpecifier, `, ${specifier}`); } else { const openingBraceToken = sourceCode.getFirstToken(exportDeclaration, isOpeningBraceToken); - yield fixer.insertTextAfter(openingBraceToken, specifiers); + yield fixer.insertTextAfter(openingBraceToken, specifier); } } else { yield fixer.insertTextAfter( program, - `\nexport {${specifiers}} from ${sourceText};`, + `\nexport {${specifier}} from ${sourceText};`, ); } } - const nodes = new Set([imported.node, ...exported.map(({node}) => node)]); - // Add this cache to prevent removing specifiers one by one and leave an empty `export {}` - const removedSpecifiers = new Set(); - for (const node of nodes) { - if (removedSpecifiers.has(node)) { - continue; - } - - yield * removeImportOrExport(node, { - fixer, - sourceCode, - removedSpecifiers, - nodes, - }); + if (removeImportNode) { + yield * removeImportOrExport(imported.node, fixer, sourceCode); } + yield * removeImportOrExport(exported.node, fixer, sourceCode); }; } @@ -255,7 +238,7 @@ function * getProblems({ for (const {node, name} of exported) { yield { - node: node, + node, messageId: MESSAGE_ID, data: { exported: name, @@ -264,7 +247,8 @@ function * getProblems({ context, imported, importDeclaration, - exported, + removeImportNode: exported.length === 1, + exported: {node, name}, exportDeclarations, program, }), diff --git a/test/snapshots/prefer-export-from.mjs.md b/test/snapshots/prefer-export-from.mjs.md index 37e68eca96..7a3437f012 100644 --- a/test/snapshots/prefer-export-from.mjs.md +++ b/test/snapshots/prefer-export-from.mjs.md @@ -645,7 +645,7 @@ Generated by [AVA](https://avajs.dev). `␊ 1 |␊ 2 |␊ - 3 | export {named as default,named} from 'foo';␊ + 3 | export {named as default, named} from 'foo';␊ ` > Error 1/2 diff --git a/test/snapshots/prefer-export-from.mjs.snap b/test/snapshots/prefer-export-from.mjs.snap index 5c596dc16644e97e7df336e1b9f9458fada10333..c15fe921ba06e48e405bcddfe136e1a704de07cb 100644 GIT binary patch delta 2195 zcmV;E2yFL~5tI>sK~_N^Q*L2!b7*gLAa*he0stAKF>3_iO}~#f#OJM;;D&mOzU=J!pZj` zmU`LHXhe8=TR_g0vKXJ%xBuDyVO&!*#L^Lv#uWtTts!q;rJU|m)K|~5FWnLfv2>y> z4fhTJ46gitsIbU?>VV+PvgdE+lnj7ax{|>ZWUFgThtgZVRdru{cJ63(qDQeUmTqP+ zx)Y5?1W7`V>Hf-Kr=cmi!-s*mGKi%yb~Nld1K^jixF+`Evm7 zvnwyTuzuCW^lX=;MOhF_!x>ybcy&%*Rl<@vD^JgG+%tA**ldWUqa112b_d|Kuuhjk zgDaYU%cd>qI63k{KZvEF4B8MnN7G$4FTE`%%9{~9^ zVeJmT3`)LNxafC#Nm&rY(qjyy{Q+20sQl&i-uosNyHNFeTwF>amTqSd^%MXbl#jNI z__gZuYm;4jo;~il(iTfg8B82N;|79qz~6c2yEJ&;T^sIq)$!{_h^6iWXRGx*ZTXVJB2Ge z4;+5&=-K?tB8a8kC>oUr=Zf=gx3oBaOj@+Q|AAxkoBn`UYBQL|y9nn4Z94yZ_+Xx` z+pgJ?sC8dKEWOJ>>4JPRf1vMbuT3wfoyaY#*geJ#Vrd(L)k6Td^&p|!^nGc^f39|_ zzcKCy$`(s+FxWVh#&}l%Zl4)7v$>(x)oJQ|(A?Z(A;i)=21AAc@YltC4|eu{@%X1Q z)_In^ZC(|`($^WZBecfeSgVLjZ*N)d|8v`+V*kkE+gFA{&2^i9$S)@O`7R- zZ;Eq}EtU=&PU9;E(h&eWyi|MNF|p}-(Sm%JrX{sYA(qxLD0c_oQU6bxL%J(wgdB9- zSx?E(-cU(f8I+DhyAasnylT^b5%je2v8N~rm4*I#a0Ih*aOnLm2>KVlX*&I3RxggaXYVDbi$2^`Udn{5$ zp+V|T9M6Y(MIoo8w3^0cAE{=LQW>d8$0$a(lu;-3WZ7!tCqS0pY!=;r_sv3A^B+-! zMN!tM1?Apk-`4T7pY=-<{ZZ}Y?ADUbu17)agb_a^;c@&v!+sek>7jboyaKVx-pc` zja=vW-~qn6OHPQaO5^;0$90d7b=@<8u+5lQqcf>iw$tyEV(xAer9wC3pht+Q)yO>s z-?O}Z>|9`c(vN3bO3K&*DUy)pSkC!?6wn^xj|}#F#3U&`ZfR|X91;eE?KYc5phSC&!EUu?a;L39lakvKQvrpFrVz12Jn6_ws z7cI(9kN<;+_F1sl4k2YMa;oC)c9s_ljmi(^EPt`}X3=P)D2qRlS6lO9VW9(=*hw*@ z&n!BtnS2%t_5pQMJi!6)7~fFg%wdMU3O{4G&0;p{ehkXM+@&!s7WZ4^1;~>N%>Ub8 z;)-QrpGWuv+GzC?NT{3-B?JPut}uvtk(H^FE{1^w(#TtyMhIiF2O<2qHO7-+8Q@rQZnONP6Fw*)?H1)Vuq7BnzU8dTYIaLsYi$nM7>oOVa0PzeJNr7 z_o+71_4N+~`Z#`+_{0ylh*@;{E~!0&tCM|K#_bie_IP-IQDiYQ4X~A`?_;L-1}3~W z6OA72T9@CshS2K3-e>^eyd>GqRsW3gIe zDl5%M^Rj~*EM}N-26}VdFVl8E`CZufw1x8Y#o~TOrS<-d<&P6)e?zCS%Ifdw%=AOX V?dIw!S?ITm{{eJ6oSX|W003{AM@0Yt delta 2193 zcmV;C2yXY35t0#qK~_N^Q*L2!b7*gLAa*he0sz=r3i#};^l2M{$)gF6YHA;g2mk;8 z00003?OJ(QR8w~OIH$Hr0r_=ip(yWYPT0@Y_cgPRCFFXkx@ZcjWp@vT=o9UOQ3Lx`oG zRy67n`fVGv^m1vmPxFR{`#z3sh=N$^25DSIaNHWa;VR{DudJqWj_vlM5QwD{t!WHy z13>@sPx1?YMo#S$lvz6d=F;Lm5KC7vn1XC|iEgv~mT$$0Z@xTzs4~&L&>BnMWiX;0 zjd}#Hgf7!YDuW!HQ?dsQ1hJ(MOQUUQ*t7@0FJVzt%%x#&)q&B2hkyEG2Z*I%46Y+g zC>Y&sTU6xO{Q>uSAIrMB0%ECO2O2F1K~+h4ukQ$dFK~z{tN5*U+0PJ5V{K{Jb_5_K z^oi2@LHt_3$wP8G#y0GQSenMbz7qi9^|^_P{=)%mjl8?4%f6Q&mPRnJu>&CH*QGmh zlJjd;UrNt%N?N!CVrdwI%LuQ}%Be_LJZsgd*X(zXSr$4IV(CzO8rGcwcq6o3T}V(_ zW9h4Zi`!0)xY!F~X$XTBgp_u1rv`1d8TEF}fyi#284(amM|Poc0wKk|TzTB5q`9Sb z$RTCr;b4fRc3o*yA*9thwWP)Qgza9f{If^TR;4wTI(MV7he1$x09N$+<=pwBL+uL( ztj^f-=zTQND(SZjcJ`o=*OSIV2LQ6S$ozwUWA`kN_&vOH<*g=UpGtayK~gUOa;rjH z?ascCd_RBT6;0EneW7{v7kU~Rtg?3>;9PAqhyYIZw0ZHHJ|!XWZF05&QAEpj_o z@%3MmUAq2p)MJ%3mX(1*r#1ZAJQITt$AdjGR7%THu#wTmG}%44W_Nc9lUa^>(Cj4BWxEx3WzlT`b%HSO*0B+3f>$}Et%gbrUvP;W$j&_Au+RPwl006fhC3Kp$H|^+|N{5;o zV}GHnvGh8FP0lm|TmZQJ+tBHawbd>TQy+lF#xC8i>4iY44*CdbmG-ERS)V zA#a&e0kJfe!99fLm>cU9vFWW%D@LAaIdBAJ6O}aFl|~)H{gTJ;|LtCsw0zQZ&-+sx z1FW&sWe|<;7`*8Qz~j2=2lj~#*9+$5IyEe=UIwxBID=0I1MqL}&l-a}D_#rUZ~s9J zB|~dNCB4I-WC&V?zy{}4tG1wjtCf!}MR`$6&|h!-*N0j{$={xrnw~)oreq2#T|QTq zB9EtLr>CY+uCr59UB}pJD}cp-)<7kuJbg;_jAEW_mYnrmfa)D;?U_%sTQA#Q~}ptG`nFp7koV7x}#>-ieG-t{X%6 z+{kr~4<6vFJLQDPDmTo3e_Z$YSk^t`2+NF#H9C`OWjp;oDdes;Q7UvZ4tj)`S`A!N z@ICX}$IbNCE9Ge#>CLkC-II$1SZ*$|fNpY}fOKg4Nj^j(>;Hs*Rd^)(qwGZ7;^z!l@)g*oCxkXCOg$2AEa>Mfr)Sp_r4Cm(~}I$eR$a z7sQlTUi^x9%5d$s3-@Fsg)2{1_0G~$LuraV7T1$TaOK&EI9vnt*{ACQu}5ZaOj|U+ zOJ?P#$NvFD`^;Eu2a_@uIaP62JIjmt2IU7+mVelKvuKn-l*RAJYb<%NFw=%i?4(HP zGmFk@M(@Re5>68CLj9C?4DY9~cM(&xRrm?RZDzAk_ai9*b7#i5P~2yh`;TWAm;ZOa z#MR2gHjnTIwAtbtkWe)rLI?zISs{sffrY7)&V~L2(#TtyJ_uv7J0bkJCC0O4s4~@T zr+;7WosP(LZHWUfDVgz1CxP@j%g!cYGQ-FmjasT3ExlC9)WgLFqTV8lFyq Date: Fri, 30 Jul 2021 10:34:50 +0800 Subject: [PATCH 13/21] Refactor --- rules/prefer-export-from.js | 42 +++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/rules/prefer-export-from.js b/rules/prefer-export-from.js index 35f669a458..d12017360d 100644 --- a/rules/prefer-export-from.js +++ b/rules/prefer-export-from.js @@ -120,6 +120,7 @@ function fix({ if (removeImportNode) { yield * removeImportOrExport(imported.node, fixer, sourceCode); } + yield * removeImportOrExport(exported.node, fixer, sourceCode); }; } @@ -217,38 +218,39 @@ function * getProblems({ } const [identifier] = identifiers; - const exported = references.map(({identifier}) => getExported(identifier, context)); - - if (!exported.every(Boolean)) { - return; - } const imported = getImported(identifier); - /* - There is no substitution for - ```js - import * as foo from 'foo'; - export default foo; - ```js - */ - if (imported.name === '*' && exported.some(({name}) => name === 'default')) { - return; - } + for (const {identifier} of references) { + const exported = getExported(identifier, context); + + if (!exported) { + continue; + } + + /* + There is no substitution for + ```js + import * as foo from 'foo'; + export default foo; + ``` + */ + if (imported.name === '*' && exported.name === 'default') { + return; + } - for (const {node, name} of exported) { yield { - node, + node: exported.node, messageId: MESSAGE_ID, data: { - exported: name, + exported: exported.name, }, fix: fix({ context, imported, importDeclaration, - removeImportNode: exported.length === 1, - exported: {node, name}, + removeImportNode: references.length === 1, + exported, exportDeclarations, program, }), From 5e6f62a2ee387041b472e62c45109d93396d8084 Mon Sep 17 00:00:00 2001 From: fisker Date: Fri, 30 Jul 2021 10:56:36 +0800 Subject: [PATCH 14/21] Simplify --- rules/prefer-export-from.js | 62 ++++++++++++++----------------------- 1 file changed, 23 insertions(+), 39 deletions(-) diff --git a/rules/prefer-export-from.js b/rules/prefer-export-from.js index d12017360d..53461202ef 100644 --- a/rules/prefer-export-from.js +++ b/rules/prefer-export-from.js @@ -75,14 +75,12 @@ function * removeImportOrExport(node, fixer, sourceCode) { function fix({ context, imported, - importDeclaration, - removeImportNode, exported, exportDeclarations, program, }) { const sourceCode = context.getSourceCode(); - const sourceNode = importDeclaration.source; + const sourceNode = imported.declaration.source; const sourceValue = sourceNode.value; const sourceText = sourceCode.getText(sourceNode); const exportDeclaration = exportDeclarations.find(({source}) => source.value === sourceValue); @@ -117,7 +115,7 @@ function fix({ } } - if (removeImportNode) { + if (imported.variable.references.length === 1) { yield * removeImportOrExport(imported.node, fixer, sourceCode); } @@ -125,26 +123,16 @@ function fix({ }; } -function getImported(identifier) { - const {parent} = identifier; - switch (parent.type) { +function getImportedName(specifier) { + switch (specifier.type) { case 'ImportDefaultSpecifier': - return { - node: parent, - name: 'default', - }; + return 'default'; case 'ImportSpecifier': - return { - node: parent, - name: parent.imported.name, - }; + return specifier.imported.name; case 'ImportNamespaceSpecifier': - return { - node: parent, - name: '*', - }; + return '*'; // No default } @@ -207,7 +195,6 @@ function isVariableUnused(node, context) { function * getProblems({ context, variable, - importDeclaration, program, exportDeclarations, }) { @@ -217,9 +204,14 @@ function * getProblems({ return; } - const [identifier] = identifiers; + const specifier = identifiers[0].parent; - const imported = getImported(identifier); + const imported = { + name: getImportedName(specifier), + node: specifier, + declaration: specifier.parent, + variable, + }; for (const {identifier} of references) { const exported = getExported(identifier, context); @@ -248,8 +240,6 @@ function * getProblems({ fix: fix({ context, imported, - importDeclaration, - removeImportNode: references.length === 1, exported, exportDeclarations, program, @@ -260,31 +250,25 @@ function * getProblems({ /** @param {import('eslint').Rule.RuleContext} context */ function create(context) { - const importDeclarations = new Set(); + const variables = []; const exportDeclarations = []; return { 'ImportDeclaration[specifiers.length>0]'(node) { - importDeclarations.add({ - node, - variables: context.getDeclaredVariables(node), - }); + variables.push(...context.getDeclaredVariables(node)); }, // `ExportAllDeclaration` and `ExportDefaultDeclaration` can't be reused 'ExportNamedDeclaration[source.type="Literal"]'(node) { exportDeclarations.push(node); }, * 'Program:exit'(program) { - for (const {node: importDeclaration, variables} of importDeclarations) { - for (const variable of variables) { - yield * getProblems({ - context, - variable, - importDeclaration, - exportDeclarations, - program, - }); - } + for (const variable of variables) { + yield * getProblems({ + context, + variable, + exportDeclarations, + program, + }); } }, }; From 6495540526106711f35e15e2405f52f262926988 Mon Sep 17 00:00:00 2001 From: fisker Date: Fri, 30 Jul 2021 11:30:29 +0800 Subject: [PATCH 15/21] Add a test (seems bug in ESLint) --- test/prefer-export-from.mjs | 10 +++++++ test/snapshots/prefer-export-from.mjs.md | 33 +++++++++++++++++---- test/snapshots/prefer-export-from.mjs.snap | Bin 2196 -> 2246 bytes 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/test/prefer-export-from.mjs b/test/prefer-export-from.mjs index da09ad74ff..36c125f041 100644 --- a/test/prefer-export-from.mjs +++ b/test/prefer-export-from.mjs @@ -218,6 +218,16 @@ test.snapshot({ import * as bar from 'foo'; export {foo, bar}; `, + outdent` + import * as namespace from 'foo'; + export default namespace; + export {namespace}; + `, + outdent` + import * as namespace from 'foo'; + export {namespace}; + export default namespace; + `, outdent` import * as foo from 'foo'; export {foo, foo as bar}; diff --git a/test/snapshots/prefer-export-from.mjs.md b/test/snapshots/prefer-export-from.mjs.md index 7a3437f012..3bad8c4ae4 100644 --- a/test/snapshots/prefer-export-from.mjs.md +++ b/test/snapshots/prefer-export-from.mjs.md @@ -771,7 +771,30 @@ Generated by [AVA](https://avajs.dev). | ^^^ Use \`export…from\` to re-export \`bar\`.␊ ` -## Invalid #35 +## Invalid #36 + 1 | import * as namespace from 'foo'; + 2 | export {namespace}; + 3 | export default namespace; + +> Output + + `␊ + 1 | import * as namespace from 'foo';␊ + 2 |␊ + 3 | export default namespace;␊ + 4 | export * as namespace from 'foo';␊ + ` + +> Error 1/1 + + `␊ + 1 | import * as namespace from 'foo';␊ + > 2 | export {namespace};␊ + | ^^^^^^^^^ Use \`export…from\` to re-export \`namespace\`.␊ + 3 | export default namespace;␊ + ` + +## Invalid #37 1 | import * as foo from 'foo'; 2 | export {foo, foo as bar}; @@ -800,7 +823,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^ Use \`export…from\` to re-export \`bar\`.␊ ` -## Invalid #36 +## Invalid #38 1 | import defaultExport from 'foo'; 2 | export * from 'foo'; 3 | export default defaultExport; @@ -823,7 +846,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` -## Invalid #37 +## Invalid #39 1 | import defaultExport from 'foo'; 2 | export {named} from 'foo'; 3 | export * from 'foo'; @@ -848,7 +871,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` -## Invalid #38 +## Invalid #40 1 | import defaultExport from './foo.js'; 2 | export {named} from './foo.js'; 3 | export default defaultExport; @@ -870,7 +893,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` -## Invalid #39 +## Invalid #41 1 | import defaultExport from './foo.js'; 2 | export {named} from './foo.js?query'; 3 | export default defaultExport; diff --git a/test/snapshots/prefer-export-from.mjs.snap b/test/snapshots/prefer-export-from.mjs.snap index c15fe921ba06e48e405bcddfe136e1a704de07cb..84e21e92b82fe8925b5c676fe15d0a63aa5aa9e1 100644 GIT binary patch literal 2246 zcmV;%2s!sbRzVC6sn-9+1cklU~d(XM&p8Ike zQ&bPC?RRs)0hj84`$6I319O840Hyo9%-|+O`>Wa71BG!X2fsbW;lRM-8vv4e+hJ5e zJhvub-nF7pzPCU4d&lR|*GB>*^#B;xAlybZDy;L{cVhoH7Y-K3Df1Las#0K_WRTW~ zqP%YOIq|XQ@~)9}^+A=Zoht#7{?4Ej>a3dTG`4U4Fz4&tyx@gRt z#vvoFb^u7~)Dq(xh=e9Fr+Tbt8ZfJDcVrvylo0?)A2V3#2wOPr$v^J9_ICZbo(J=b ze+mUidWyl~RunZS{?qoI3aj07Z)(o&F8ymLK+gHSP%oWS)ehq*L{>@oy_T0=h<}ii z`is4)C>S8AvOPvIMD~^y;6dTVw;Te}HUxGmfO_eq4$c@=5Q}s2FTK@v``|oRy6g*A z*Fu1#bO(&n5Xh+!iNxOE$C}EJ;iK14`8F#B_|HqeOoKhpTA0_InPuoY3^^%B?#AlJ;@II0bRy_Aixpa~67iwfD_~=dN&9xgI1f>q*u`&=_sUmi9Lp%$xw)S^KvKW% z7>6M09!+%^yM4ydi^a}mwSh-y1(No1!#KlW{)^E2&h#2zeXi8a`SpiXb+yw>fTX1i zV%;g~&x-Aj*0)psy(h|Lf~J1TK7gd_81(5uQMaRNmuRDt@6{~md$E4^&z%91<}q;f zfXvrEUiXJ`^|bjz#(O^)?h>p((kTomPmJ{tkLwj7Ps&$it{OZpPQ9_U79gozPmCK7 zPda{C9okAeE_9dU`Z8J#Jy0j@t;8sYP*6=#+8p!CDYweZ8$OP!5g&m z>J9btnx-8vW2Po~wtIg(eem1QcvW$q;m+JKj%C=3(dbz@S_K;}ss_hk_1|Da{-rJ5 zluV~wQ^vBXk;0Nl93c2I%bK5&tf`b97un+xBY|}D;NIj!LKzVtm)FBY{YlO?XSz=X zN{jaIsFUN=6XP`mn%g9}3lG^zNr~DNegAZj32q?A3=IQu?J$Ak5PXwlAy43DKpamH zUmnlU1)@YUpo!{aj)`~zt*#;bS%!`%Y~Uwi1O3_+q*r8O z5@_Tb`e&s3g&95}DgJRbQy%u2a^qjavO(>LOikYa`$^#@A?kf3mmKe$l37|}F8fG} z^JF*8vYngG6;{j6Tbvt#)Mg7DRBVyLh4E#>o}6ebn*8z@WRK*HoG`S_Gu)}hivn8$ ze)~(pe%l+7B7(e7d8&_vI%0DLr$era@04QuxP#0cnc&L zV3q0B4$c@BD0=WS25YRQqwz=94#l0CNRgu_H=-EFX5z^<-IUO*L``tlW(6$Plw_N< zO%QeAEE)-V!CovI4R%=N66D#1hX1RB()^HE1{2SbR@gj85{ndJgoVJ(d}UEzYGdl8 zxo`ZI9wDpb$9G5|%y@>m z7haZs?ZIxWPlu5_OV#5~PKG~%(l=fOQ_vU>i%W7)M(3K}2x6qxG z8F%thvv1QkDlajPGOlQ35R-E1Hr3t2Ia&!9P5Jn$2!t2%5|&Y7H?yd$l5^8W(v8Jx zvAL}DEiKCqEVr6srYY#dH9xDUD^lJxxFsVLe%S`NVA|~%|NA6@1GBCHY>_Nm=q=E- UmMVu@>BY}~0r)bTFKRLX0Q^m4DgXcg literal 2196 zcmV;F2y6F2RzVWDrknbxFLbL79{GIW_Rv;GtPVS=Ds(Z^H1}AKR!Kk-?`^^?z!ild)_2> z1i%gS{&ERC;@li?H!y7GxOIUg5U4)SGq{P+_dPF?KZUIs@RBu(&4n;7vnwyTuzuCW z^lX=;MOhF_!x>ybcy&%*Rl<@vD^JgG+%tA**ldWUqa112b_d|KuuhjkgDaZLrY-3> zIr2h3h^3(n+7MDYNly>oXczES{h_E{UKx=POZ|J$s6$9`tW=)#+1}dLF!HFf`r8nQ zr4Bu5)F7laxU{87eZu#wQeN)Uw_RzAr9*qs*vlZeHvr4~{qXB=$45C94_TG5>A?=P z&?@Pd40iXSQP7vhA}0WHH^~A+;`T0!{3)V)^{p0UpGsQCAgLb!`88qf4!;aazE`;D zcY8@$5X91B45a-5SW~F{<@MhCCKkI;^?O`gN+FhRXAt!i02`E#wv70->ho)pU3;EA z?zz$yOG_C{96;j+f^xv$dFQ({c;8(c?swJk>qdyB?gMFDL)iT7gh^R39UEP5cZj|z zdl&(+)c0u`tq6y@woD3LIeyC2k`=RRbEkKQSQ_;VjW&cYb``YL94sl%>Fm4k^ov7( zgIF3ih{jcf?~2Rc^eeEh{N7=f-KUqzD z>4JPRf1vMbuT3wfoyaY#*geJ#Vrd(L)k6Td^&p|!^nGc^f39|_zcKCy$`(s+FxWVh z#&}l%Zl4)7v$>(x)oJQ|(A?Z(A;i)=21AAc@YltC4|ewP_@^?~d6v9wUKPaB*BP`U zw8q|8tB6Z)Z&~jDbK9X~D4VFHk#00DBi!5maL1n>TauPdn(1|KigS=HmJSQ5Zchk8XJr=+x+ z#$_L=W{^@DsYu5tMz@qvC-r36YU3wBmfvg^-S^ExSMwiHghf%-sN|9k&`&xuUOrd0 zFgZhQQhc_4;^iFT+RrlooQ$<*6P&;r_;^;cIzeaEqqQBtT90@Swdri5Ig!Es$``3( zdFC9)Gi;LVhjlCvJ#mm~V)a*Q-?OGtdy(IJ;+@DS<+?GH&y8H?_}~G)x=T)otV-kj z$90d7b=@<8u+5lQqcf>iw$tyEV(xAer9wC3pht+Q)yO>s-?O}Z>|9`c(vN3bO3K&* zDUy)pSkC!?6wn^xj|}#F#3U&`ZfR|X91;eE?K6xU^6mu+kwIcE!OM~8WS8J5jE4MLX z)?UP^u+`AT=Z$%C6qqB{M~gcL$!RR#dTA_Ezgae3!rTa?cAMdjYmEqw5=h(J#bF&? z!lyzuPf8bDZx1|#R&CPSvsS2p?|3oI7EUE0!Y-tRy8;QiE5Ni0D9TSn4aMA?BwAlE zB5y*xo)=SIN%$4Yc5phSC&!EUu?a;L39lakvKQvrpFrVz12J zn6_ws7cI(9kN<;+_F1sl4k2YMa;oC)c9s_ljmi(^EV1=w(P*P6i$9T9Tk~RJp#z!N zNin3)EIO;1d=?A#0d-S6!2$0W-%#PqVTQg6KV!JfVm9i249dXVr7D#*<{I zGSy<&U+zmCk^9;jH(pXQ<5^Au>9y8fO~PV^lR28SRo7d4tCFclhz&%&RTg2zb4`6I zVgC22Hq-U>4+Q!+ew6sc54VU}bowr-J%X!~eOJcq6|?qucz;o3F*6OYm8b7xruPOW zyf+nFKpLNGJ%uCE&) W#_i_nDOu>Zi~j+1JDi*gF#rI$Sx1Nf From 0308b6b751914e23e079d6bccd2429991f2b9edb Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Mon, 1 Nov 2021 21:04:52 +0800 Subject: [PATCH 16/21] Update snapshot --- test/prefer-export-from.mjs | 10 +++++----- test/snapshots/prefer-export-from.mjs.md | 12 ++++++------ test/snapshots/prefer-export-from.mjs.snap | Bin 2246 -> 2257 bytes 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/test/prefer-export-from.mjs b/test/prefer-export-from.mjs index 36c125f041..b8534940ab 100644 --- a/test/prefer-export-from.mjs +++ b/test/prefer-export-from.mjs @@ -52,6 +52,11 @@ test.snapshot({ import * as namespace from 'foo'; export {namespace as default}; `, + outdent` + import * as namespace from 'foo'; + export default namespace; + export {namespace}; + `, // Cases we are not handled outdent` import defaultExport from 'foo'; @@ -218,11 +223,6 @@ test.snapshot({ import * as bar from 'foo'; export {foo, bar}; `, - outdent` - import * as namespace from 'foo'; - export default namespace; - export {namespace}; - `, outdent` import * as namespace from 'foo'; export {namespace}; diff --git a/test/snapshots/prefer-export-from.mjs.md b/test/snapshots/prefer-export-from.mjs.md index 3bad8c4ae4..6b7c6e4259 100644 --- a/test/snapshots/prefer-export-from.mjs.md +++ b/test/snapshots/prefer-export-from.mjs.md @@ -771,7 +771,7 @@ Generated by [AVA](https://avajs.dev). | ^^^ Use \`export…from\` to re-export \`bar\`.␊ ` -## Invalid #36 +## Invalid #35 1 | import * as namespace from 'foo'; 2 | export {namespace}; 3 | export default namespace; @@ -794,7 +794,7 @@ Generated by [AVA](https://avajs.dev). 3 | export default namespace;␊ ` -## Invalid #37 +## Invalid #36 1 | import * as foo from 'foo'; 2 | export {foo, foo as bar}; @@ -823,7 +823,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^ Use \`export…from\` to re-export \`bar\`.␊ ` -## Invalid #38 +## Invalid #37 1 | import defaultExport from 'foo'; 2 | export * from 'foo'; 3 | export default defaultExport; @@ -846,7 +846,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` -## Invalid #39 +## Invalid #38 1 | import defaultExport from 'foo'; 2 | export {named} from 'foo'; 3 | export * from 'foo'; @@ -871,7 +871,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` -## Invalid #40 +## Invalid #39 1 | import defaultExport from './foo.js'; 2 | export {named} from './foo.js'; 3 | export default defaultExport; @@ -893,7 +893,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` -## Invalid #41 +## Invalid #40 1 | import defaultExport from './foo.js'; 2 | export {named} from './foo.js?query'; 3 | export default defaultExport; diff --git a/test/snapshots/prefer-export-from.mjs.snap b/test/snapshots/prefer-export-from.mjs.snap index 84e21e92b82fe8925b5c676fe15d0a63aa5aa9e1..96fedb8b220d9eae510a973d1279b05a2b8878d0 100644 GIT binary patch literal 2257 zcmV;?2rl;=s&g7!aCo)TfaH^ zLIT9n`2;~-00@}YWy6*5#;^DO^VFdO>8eTvmM$Xjb!Tx9K{a6G=+>KOn#=0%KbD+( z`YgoK(5@_$-2hOh^+|lDYNGd$tdgNmgXCI>rNsnc-2sS5TYNaFb>y(7vD1P^eQ>Y` z#L^`MK0T1-t0ViaONfu!sk!BQtnlJeh^1NrKMw#V9?mHL%htHn-boFOCr-Zp1;o;o z1fzNaFgf;qRp>9NDo)Yn~VF@KM%3AfFP_l z07=J-ww7jAG_PpQDfG`+SOBqf34x~)fLXC!&rhD%&|W)ziTi}9=X@ZRCK5bA$hgv9 zSdutXa)dK zvQ`@%lf1on>UVLT2d;FWQ4P{60<|{)Wrt&L_dfGP=ADX#KYFNZ(aJJND+vO9kgqGM z&b-ub$8(kbO!J5S{u>~c>Ii&&0eHLWLG`d78bAGMLV(xzM}wCuuyihg$73u$L8uyd zv$Unh$H#c{!j=P?Bz7pv$NGAob@O&D8EBDfRCGJ>o^z;Gm z=1WmW7zLK*5)2At(S&gI#E6;gCz}GiU;G8MxA)0|SgIV#q7LDD>yCSy`m65lPV$?r zyYWgR#L^CeqG14ZCS6*kPtLjBvGkeKH+FqF5Mt>mg7hE&?yUc9<26-vM)CNWA$KPE zX%txc5y8aaEG{BE@cpPg##28dW~XvfGowY(V~~ziu{evM0Nrrrb#n(^Zebn_qh<=w z-%$KFj45Dri{@wN?|g5ZgzIyvmWLOU=3h3FzHzjdl~xZ z=WAcqar$WtV;HsPKWy`Gn8Ig~G6pp=ev$<~%%Al-CWTegR=mY9LJE_cjdYA4x>Ja{ zlwgjnZV@76h0W&Bea|6uP5($DEQzv7C7*PHIcbhLsVXK_H&>gNnOn#)oaY$sSK&w% z$0MhB9w90xu-&>fj!)lY031wt}HG&Z)8c%X|3%18pl(cOBnl>k0 zJ10{|p}AdhdE}6NIeVTy*QB3`wjm7UxWPCO-w(5S0U=zq9TExrjU+D;#Fxh-41pw( zjpQ6{j^(yV$T{e186kq2Q1}~k39y#H74<|6#c6PS5H8{a)7rI4uhz!Bv_))~`bdup zJ7Pjo{uA6-bJ&;4&40#agWFM=+Fk%7rErsw_5LQ8oZy_&Svq1a7fN1%0v<7+5YzGt z=Y@fUGvzkB&y?1)oy?P?7(b5lMoTM_^c+{_x*V5p-7L2dac&e+{28_7l;?{5Z<-}* za^z>22npq#oR8FIUl36!#ak^>D!*D-k-!eoe01?Mu`Fi^B*f4{E9Kp^58-hA#tyCm zM=2gxjWzo$T_E*f9Exd6=GW>}epdXiq1xxfeP9f24`g)%7(}w7^@yktstAvC_h&UR zCfGz-dOdi_P_U(P+BFgm?vd$K@4B?EYagWg+nQ6|$(Wb}@C@u_T&8 z8hOj~phrwrQIeexfMt_l(1ao+I&MvH&f^w z?J6d3xw@FpsmDo8l~&IIlo>Cv_eIC?@A}+bgSCUJ=-ape+1&hOGi+%t3EbcD%_;JptOjHiN}D z%6MgvK}^cMgRR*pmS>gqYf&M-Y6{_Hf`nyUqT6|GtmadtJr>byL$}kzgYYo1~?ETYBB%-PnTh< literal 2246 zcmV;%2s!sbRzVC6sn-9+1cklU~d(XM&p8Ike zQ&bPC?RRs)0hj84`$6I319O840Hyo9%-|+O`>Wa71BG!X2fsbW;lRM-8vv4e+hJ5e zJhvub-nF7pzPCU4d&lR|*GB>*^#B;xAlybZDy;L{cVhoH7Y-K3Df1Las#0K_WRTW~ zqP%YOIq|XQ@~)9}^+A=Zoht#7{?4Ej>a3dTG`4U4Fz4&tyx@gRt z#vvoFb^u7~)Dq(xh=e9Fr+Tbt8ZfJDcVrvylo0?)A2V3#2wOPr$v^J9_ICZbo(J=b ze+mUidWyl~RunZS{?qoI3aj07Z)(o&F8ymLK+gHSP%oWS)ehq*L{>@oy_T0=h<}ii z`is4)C>S8AvOPvIMD~^y;6dTVw;Te}HUxGmfO_eq4$c@=5Q}s2FTK@v``|oRy6g*A z*Fu1#bO(&n5Xh+!iNxOE$C}EJ;iK14`8F#B_|HqeOoKhpTA0_InPuoY3^^%B?#AlJ;@II0bRy_Aixpa~67iwfD_~=dN&9xgI1f>q*u`&=_sUmi9Lp%$xw)S^KvKW% z7>6M09!+%^yM4ydi^a}mwSh-y1(No1!#KlW{)^E2&h#2zeXi8a`SpiXb+yw>fTX1i zV%;g~&x-Aj*0)psy(h|Lf~J1TK7gd_81(5uQMaRNmuRDt@6{~md$E4^&z%91<}q;f zfXvrEUiXJ`^|bjz#(O^)?h>p((kTomPmJ{tkLwj7Ps&$it{OZpPQ9_U79gozPmCK7 zPda{C9okAeE_9dU`Z8J#Jy0j@t;8sYP*6=#+8p!CDYweZ8$OP!5g&m z>J9btnx-8vW2Po~wtIg(eem1QcvW$q;m+JKj%C=3(dbz@S_K;}ss_hk_1|Da{-rJ5 zluV~wQ^vBXk;0Nl93c2I%bK5&tf`b97un+xBY|}D;NIj!LKzVtm)FBY{YlO?XSz=X zN{jaIsFUN=6XP`mn%g9}3lG^zNr~DNegAZj32q?A3=IQu?J$Ak5PXwlAy43DKpamH zUmnlU1)@YUpo!{aj)`~zt*#;bS%!`%Y~Uwi1O3_+q*r8O z5@_Tb`e&s3g&95}DgJRbQy%u2a^qjavO(>LOikYa`$^#@A?kf3mmKe$l37|}F8fG} z^JF*8vYngG6;{j6Tbvt#)Mg7DRBVyLh4E#>o}6ebn*8z@WRK*HoG`S_Gu)}hivn8$ ze)~(pe%l+7B7(e7d8&_vI%0DLr$era@04QuxP#0cnc&L zV3q0B4$c@BD0=WS25YRQqwz=94#l0CNRgu_H=-EFX5z^<-IUO*L``tlW(6$Plw_N< zO%QeAEE)-V!CovI4R%=N66D#1hX1RB()^HE1{2SbR@gj85{ndJgoVJ(d}UEzYGdl8 zxo`ZI9wDpb$9G5|%y@>m z7haZs?ZIxWPlu5_OV#5~PKG~%(l=fOQ_vU>i%W7)M(3K}2x6qxG z8F%thvv1QkDlajPGOlQ35R-E1Hr3t2Ia&!9P5Jn$2!t2%5|&Y7H?yd$l5^8W(v8Jx zvAL}DEiKCqEVr6srYY#dH9xDUD^lJxxFsVLe%S`NVA|~%|NA6@1GBCHY>_Nm=q=E- UmMVu@>BY}~0r)bTFKRLX0Q^m4DgXcg From 840863777254f9803b5abc31a02dc8b681894ac3 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Mon, 1 Nov 2021 21:06:13 +0800 Subject: [PATCH 17/21] Apply suggestions from code review Co-authored-by: Sindre Sorhus --- docs/rules/prefer-export-from.md | 2 +- rules/prefer-export-from.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/rules/prefer-export-from.md b/docs/rules/prefer-export-from.md index 82a0c613ee..2930e5e168 100644 --- a/docs/rules/prefer-export-from.md +++ b/docs/rules/prefer-export-from.md @@ -1,6 +1,6 @@ # Prefer `export…from` when re-exporting -When re-exporting from module, it's unnecessary to import and then export, it can be done in one `export…from` declaration. +When re-exporting from a module, it's unnecessary to import and then export. It can be done in a single `export…from` declaration. This rule is fixable. diff --git a/rules/prefer-export-from.js b/rules/prefer-export-from.js index 53461202ef..8daf7462f5 100644 --- a/rules/prefer-export-from.js +++ b/rules/prefer-export-from.js @@ -221,7 +221,8 @@ function * getProblems({ } /* - There is no substitution for + There is no substitution for: + ```js import * as foo from 'foo'; export default foo; From a050784bbf3e7ce28402013ddb7dbb73bb6aae9e Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Mon, 1 Nov 2021 21:11:38 +0800 Subject: [PATCH 18/21] Add tests for used imports --- test/prefer-export-from.mjs | 21 +++ test/snapshots/prefer-export-from.mjs.md | 193 +++++++++++++++++---- test/snapshots/prefer-export-from.mjs.snap | Bin 2257 -> 2556 bytes 3 files changed, 183 insertions(+), 31 deletions(-) diff --git a/test/prefer-export-from.mjs b/test/prefer-export-from.mjs index b8534940ab..050458dd1e 100644 --- a/test/prefer-export-from.mjs +++ b/test/prefer-export-from.mjs @@ -102,6 +102,13 @@ test.snapshot({ import defaultExport from 'foo'; export const variable = defaultExport; `, + outdent` + import defaultExport from 'foo'; + defaultExport.bar = 1; + export {defaultExport as named}; + export {defaultExport as default}; + export const variable = defaultExport; + `, // `named` outdent` import {named} from 'foo'; @@ -123,6 +130,13 @@ test.snapshot({ import {named} from 'foo'; export const variable = named; `, + outdent` + import {named} from 'foo'; + named.bar = 1; + export {named as named}; + export {named as default}; + export const variable = named; + `, // Namespace outdent` import * as namespace from 'foo'; @@ -136,6 +150,13 @@ test.snapshot({ import * as namespace from 'foo'; export const variable = namespace; `, + outdent` + import * as namespace from 'foo'; + namespace.bar = 1; + export {namespace as named}; + export {namespace as default}; + export const variable = namespace; + `, // Some not exported outdent` import {named1, named2} from 'foo'; diff --git a/test/snapshots/prefer-export-from.mjs.md b/test/snapshots/prefer-export-from.mjs.md index 6b7c6e4259..0a337df28d 100644 --- a/test/snapshots/prefer-export-from.mjs.md +++ b/test/snapshots/prefer-export-from.mjs.md @@ -165,6 +165,57 @@ Generated by [AVA](https://avajs.dev). ` ## Invalid #9 + 1 | import defaultExport from 'foo'; + 2 | defaultExport.bar = 1; + 3 | export {defaultExport as named}; + 4 | export {defaultExport as default}; + 5 | export const variable = defaultExport; + +> Output + + `␊ + 1 | import defaultExport from 'foo';␊ + 2 | defaultExport.bar = 1;␊ + 3 |␊ + 4 |␊ + 5 |␊ + 6 | export {default as named, default, default as variable} from 'foo';␊ + ` + +> Error 1/3 + + `␊ + 1 | import defaultExport from 'foo';␊ + 2 | defaultExport.bar = 1;␊ + > 3 | export {defaultExport as named};␊ + | ^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`named\`.␊ + 4 | export {defaultExport as default};␊ + 5 | export const variable = defaultExport;␊ + ` + +> Error 2/3 + + `␊ + 1 | import defaultExport from 'foo';␊ + 2 | defaultExport.bar = 1;␊ + 3 | export {defaultExport as named};␊ + > 4 | export {defaultExport as default};␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ + 5 | export const variable = defaultExport;␊ + ` + +> Error 3/3 + + `␊ + 1 | import defaultExport from 'foo';␊ + 2 | defaultExport.bar = 1;␊ + 3 | export {defaultExport as named};␊ + 4 | export {defaultExport as default};␊ + > 5 | export const variable = defaultExport;␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`variable\`.␊ + ` + +## Invalid #10 1 | import {named} from 'foo'; 2 | export default named; @@ -184,7 +235,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` -## Invalid #10 +## Invalid #11 1 | import {named} from 'foo'; 2 | export {named as default}; @@ -204,7 +255,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` -## Invalid #11 +## Invalid #12 1 | import {named} from 'foo'; 2 | export {named as named}; @@ -224,7 +275,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`named\`.␊ ` -## Invalid #12 +## Invalid #13 1 | import {named} from 'foo'; 2 | export {named as renamed}; @@ -244,7 +295,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`renamed\`.␊ ` -## Invalid #13 +## Invalid #14 1 | import {named} from 'foo'; 2 | export const variable = named; @@ -264,7 +315,58 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`variable\`.␊ ` -## Invalid #14 +## Invalid #15 + 1 | import {named} from 'foo'; + 2 | named.bar = 1; + 3 | export {named as named}; + 4 | export {named as default}; + 5 | export const variable = named; + +> Output + + `␊ + 1 | import {named} from 'foo';␊ + 2 | named.bar = 1;␊ + 3 |␊ + 4 |␊ + 5 |␊ + 6 | export {named, named as default, named as variable} from 'foo';␊ + ` + +> Error 1/3 + + `␊ + 1 | import {named} from 'foo';␊ + 2 | named.bar = 1;␊ + > 3 | export {named as named};␊ + | ^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`named\`.␊ + 4 | export {named as default};␊ + 5 | export const variable = named;␊ + ` + +> Error 2/3 + + `␊ + 1 | import {named} from 'foo';␊ + 2 | named.bar = 1;␊ + 3 | export {named as named};␊ + > 4 | export {named as default};␊ + | ^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ + 5 | export const variable = named;␊ + ` + +> Error 3/3 + + `␊ + 1 | import {named} from 'foo';␊ + 2 | named.bar = 1;␊ + 3 | export {named as named};␊ + 4 | export {named as default};␊ + > 5 | export const variable = named;␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`variable\`.␊ + ` + +## Invalid #16 1 | import * as namespace from 'foo'; 2 | export {namespace as namespace}; @@ -284,7 +386,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`namespace\`.␊ ` -## Invalid #15 +## Invalid #17 1 | import * as namespace from 'foo'; 2 | export {namespace as renamed}; @@ -304,7 +406,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`renamed\`.␊ ` -## Invalid #16 +## Invalid #18 1 | import * as namespace from 'foo'; 2 | export const variable = namespace; @@ -324,7 +426,36 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`variable\`.␊ ` -## Invalid #17 +## Invalid #19 + 1 | import * as namespace from 'foo'; + 2 | namespace.bar = 1; + 3 | export {namespace as named}; + 4 | export {namespace as default}; + 5 | export const variable = namespace; + +> Output + + `␊ + 1 | import * as namespace from 'foo';␊ + 2 | namespace.bar = 1;␊ + 3 |␊ + 4 | export {namespace as default};␊ + 5 | export const variable = namespace;␊ + 6 | export * as named from 'foo';␊ + ` + +> Error 1/1 + + `␊ + 1 | import * as namespace from 'foo';␊ + 2 | namespace.bar = 1;␊ + > 3 | export {namespace as named};␊ + | ^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`named\`.␊ + 4 | export {namespace as default};␊ + 5 | export const variable = namespace;␊ + ` + +## Invalid #20 1 | import {named1, named2} from 'foo'; 2 | export {named1}; @@ -344,7 +475,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Use \`export…from\` to re-export \`named1\`.␊ ` -## Invalid #18 +## Invalid #21 1 | import defaultExport, {named} from 'foo'; 2 | export {defaultExport}; @@ -364,7 +495,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`defaultExport\`.␊ ` -## Invalid #19 +## Invalid #22 1 | import defaultExport, {named} from 'foo'; 2 | export {named}; @@ -384,7 +515,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ ` -## Invalid #20 +## Invalid #23 1 | import defaultExport, * as namespace from 'foo'; 2 | export {defaultExport}; @@ -404,7 +535,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`defaultExport\`.␊ ` -## Invalid #21 +## Invalid #24 1 | import * as foo from 'foo'; 2 | export {foo}; 3 | export * as bar from 'foo'; @@ -427,7 +558,7 @@ Generated by [AVA](https://avajs.dev). 3 | export * as bar from 'foo';␊ ` -## Invalid #22 +## Invalid #25 1 | import * as foo from 'foo'; 2 | export {foo}; 3 | export {bar} from 'foo'; @@ -450,7 +581,7 @@ Generated by [AVA](https://avajs.dev). 3 | export {bar} from 'foo';␊ ` -## Invalid #23 +## Invalid #26 1 | import * as foo from 'foo'; 2 | export {foo}; 3 | export {} from 'foo'; @@ -473,7 +604,7 @@ Generated by [AVA](https://avajs.dev). 3 | export {} from 'foo';␊ ` -## Invalid #24 +## Invalid #27 1 | import * as foo from 'foo'; 2 | export {foo}; 3 | export * from 'foo'; @@ -496,7 +627,7 @@ Generated by [AVA](https://avajs.dev). 3 | export * from 'foo';␊ ` -## Invalid #25 +## Invalid #28 1 | import foo from 'foo'; 2 | export {foo}; 3 | export * as bar from 'foo'; @@ -519,7 +650,7 @@ Generated by [AVA](https://avajs.dev). 3 | export * as bar from 'foo';␊ ` -## Invalid #26 +## Invalid #29 1 | import foo from 'foo'; 2 | export {foo}; 3 | export {bar} from 'foo'; @@ -541,7 +672,7 @@ Generated by [AVA](https://avajs.dev). 3 | export {bar} from 'foo';␊ ` -## Invalid #27 +## Invalid #30 1 | import foo from 'foo'; 2 | export {foo}; 3 | export {bar,} from 'foo'; @@ -563,7 +694,7 @@ Generated by [AVA](https://avajs.dev). 3 | export {bar,} from 'foo';␊ ` -## Invalid #28 +## Invalid #31 1 | import foo from 'foo'; 2 | export {foo}; 3 | export {} from 'foo'; @@ -585,7 +716,7 @@ Generated by [AVA](https://avajs.dev). 3 | export {} from 'foo';␊ ` -## Invalid #29 +## Invalid #32 1 | import foo from 'foo'; 2 | export {foo}; 3 | export * from 'foo'; @@ -608,7 +739,7 @@ Generated by [AVA](https://avajs.dev). 3 | export * from 'foo';␊ ` -## Invalid #30 +## Invalid #33 1 | import {named1, named2} from 'foo'; 2 | export {named1, named2}; @@ -636,7 +767,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^ Use \`export…from\` to re-export \`named2\`.␊ ` -## Invalid #31 +## Invalid #34 1 | import {named} from 'foo'; 2 | export {named as default, named}; @@ -664,7 +795,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^ Use \`export…from\` to re-export \`named\`.␊ ` -## Invalid #32 +## Invalid #35 1 | import {named, named as renamed} from 'foo'; 2 | export {named, renamed}; @@ -692,7 +823,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Use \`export…from\` to re-export \`renamed\`.␊ ` -## Invalid #33 +## Invalid #36 1 | import defaultExport, {named1, named2} from 'foo'; 2 | export {named1 as default}; 3 | export {named2}; @@ -738,7 +869,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^ Use \`export…from\` to re-export \`defaultExport\`.␊ ` -## Invalid #34 +## Invalid #37 1 | import * as foo from 'foo'; 2 | import * as bar from 'foo'; 3 | export {foo, bar}; @@ -771,7 +902,7 @@ Generated by [AVA](https://avajs.dev). | ^^^ Use \`export…from\` to re-export \`bar\`.␊ ` -## Invalid #35 +## Invalid #38 1 | import * as namespace from 'foo'; 2 | export {namespace}; 3 | export default namespace; @@ -794,7 +925,7 @@ Generated by [AVA](https://avajs.dev). 3 | export default namespace;␊ ` -## Invalid #36 +## Invalid #39 1 | import * as foo from 'foo'; 2 | export {foo, foo as bar}; @@ -823,7 +954,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^ Use \`export…from\` to re-export \`bar\`.␊ ` -## Invalid #37 +## Invalid #40 1 | import defaultExport from 'foo'; 2 | export * from 'foo'; 3 | export default defaultExport; @@ -846,7 +977,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` -## Invalid #38 +## Invalid #41 1 | import defaultExport from 'foo'; 2 | export {named} from 'foo'; 3 | export * from 'foo'; @@ -871,7 +1002,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` -## Invalid #39 +## Invalid #42 1 | import defaultExport from './foo.js'; 2 | export {named} from './foo.js'; 3 | export default defaultExport; @@ -893,7 +1024,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` -## Invalid #40 +## Invalid #43 1 | import defaultExport from './foo.js'; 2 | export {named} from './foo.js?query'; 3 | export default defaultExport; diff --git a/test/snapshots/prefer-export-from.mjs.snap b/test/snapshots/prefer-export-from.mjs.snap index 96fedb8b220d9eae510a973d1279b05a2b8878d0..a0ba64a891a9039e71d9bd662b1ff9005e83627c 100644 GIT binary patch literal 2556 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 From 02cc4d5fd89090172eb76a0d84e787f613f767f1 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Mon, 1 Nov 2021 21:13:42 +0800 Subject: [PATCH 19/21] Style --- rules/prefer-export-from.js | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/rules/prefer-export-from.js b/rules/prefer-export-from.js index 8daf7462f5..db03914d9f 100644 --- a/rules/prefer-export-from.js +++ b/rules/prefer-export-from.js @@ -93,9 +93,9 @@ function fix({ `\nexport * as ${exported.name} from ${sourceText};`, ); } else { - const specifier = exported.name === imported.name ? - exported.name : - `${imported.name} as ${exported.name}`; + const specifier = exported.name === imported.name + ? exported.name + : `${imported.name} as ${exported.name}`; if (exportDeclaration) { const lastSpecifier = exportDeclaration.specifiers[exportDeclaration.specifiers.length - 1]; @@ -155,14 +155,14 @@ function getExported(identifier, context) { case 'VariableDeclarator': { if ( - parent.init === identifier && - parent.id.type === 'Identifier' && - parent.parent.type === 'VariableDeclaration' && - parent.parent.kind === 'const' && - parent.parent.declarations.length === 1 && - parent.parent.declarations[0] === parent && - parent.parent.parent.type === 'ExportNamedDeclaration' && - isVariableUnused(parent, context) + parent.init === identifier + && parent.id.type === 'Identifier' + && parent.parent.type === 'VariableDeclaration' + && parent.parent.kind === 'const' + && parent.parent.declarations.length === 1 + && parent.parent.declarations[0] === parent + && parent.parent.parent.type === 'ExportNamedDeclaration' + && isVariableUnused(parent, context) ) { return { node: parent.parent.parent, @@ -186,10 +186,10 @@ function isVariableUnused(node, context) { } const [{identifiers, references}] = variables; - return identifiers.length === 1 && - identifiers[0] === node.id && - references.length === 1 && - references[0].identifier === node.id; + return identifiers.length === 1 + && identifiers[0] === node.id + && references.length === 1 + && references[0].identifier === node.id; } function * getProblems({ From 655ba25242d53a7c2535dedc19f34c232d35c31d Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Mon, 1 Nov 2021 21:15:13 +0800 Subject: [PATCH 20/21] Fix codebase --- test/utils/test.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utils/test.mjs b/test/utils/test.mjs index 303844d562..9ec01ca8ad 100644 --- a/test/utils/test.mjs +++ b/test/utils/test.mjs @@ -161,5 +161,5 @@ const avoidTestTitleConflict = (tests, comment) => { export { getTester, avoidTestTitleConflict, - parsers, }; +export {default as parsers} from './parsers.mjs'; From 7e55bd5c00bdf188912e7505432ddb92d7db6c0b Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Mon, 1 Nov 2021 21:17:25 +0800 Subject: [PATCH 21/21] Move strange case to a separate test --- test/prefer-export-from.mjs | 29 +++++++---- test/snapshots/prefer-export-from.mjs.md | 54 ++++++++++----------- test/snapshots/prefer-export-from.mjs.snap | Bin 2556 -> 2558 bytes 3 files changed, 46 insertions(+), 37 deletions(-) diff --git a/test/prefer-export-from.mjs b/test/prefer-export-from.mjs index 050458dd1e..fee5beb222 100644 --- a/test/prefer-export-from.mjs +++ b/test/prefer-export-from.mjs @@ -52,11 +52,6 @@ test.snapshot({ import * as namespace from 'foo'; export {namespace as default}; `, - outdent` - import * as namespace from 'foo'; - export default namespace; - export {namespace}; - `, // Cases we are not handled outdent` import defaultExport from 'foo'; @@ -244,11 +239,6 @@ test.snapshot({ import * as bar from 'foo'; export {foo, bar}; `, - outdent` - import * as namespace from 'foo'; - export {namespace}; - export default namespace; - `, outdent` import * as foo from 'foo'; export {foo, foo as bar}; @@ -276,3 +266,22 @@ test.snapshot({ `, ], }); + +// Strange case +// TODO: confirm how should this work +test.snapshot({ + valid: [ + outdent` + import * as namespace from 'foo'; + export default namespace; + export {namespace}; + `, + ], + invalid: [ + outdent` + import * as namespace from 'foo'; + export {namespace}; + export default namespace; + `, + ], +}); diff --git a/test/snapshots/prefer-export-from.mjs.md b/test/snapshots/prefer-export-from.mjs.md index 0a337df28d..19a478d4f4 100644 --- a/test/snapshots/prefer-export-from.mjs.md +++ b/test/snapshots/prefer-export-from.mjs.md @@ -903,29 +903,6 @@ Generated by [AVA](https://avajs.dev). ` ## Invalid #38 - 1 | import * as namespace from 'foo'; - 2 | export {namespace}; - 3 | export default namespace; - -> Output - - `␊ - 1 | import * as namespace from 'foo';␊ - 2 |␊ - 3 | export default namespace;␊ - 4 | export * as namespace from 'foo';␊ - ` - -> Error 1/1 - - `␊ - 1 | import * as namespace from 'foo';␊ - > 2 | export {namespace};␊ - | ^^^^^^^^^ Use \`export…from\` to re-export \`namespace\`.␊ - 3 | export default namespace;␊ - ` - -## Invalid #39 1 | import * as foo from 'foo'; 2 | export {foo, foo as bar}; @@ -954,7 +931,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^ Use \`export…from\` to re-export \`bar\`.␊ ` -## Invalid #40 +## Invalid #39 1 | import defaultExport from 'foo'; 2 | export * from 'foo'; 3 | export default defaultExport; @@ -977,7 +954,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` -## Invalid #41 +## Invalid #40 1 | import defaultExport from 'foo'; 2 | export {named} from 'foo'; 3 | export * from 'foo'; @@ -1002,7 +979,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` -## Invalid #42 +## Invalid #41 1 | import defaultExport from './foo.js'; 2 | export {named} from './foo.js'; 3 | export default defaultExport; @@ -1024,7 +1001,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` -## Invalid #43 +## Invalid #42 1 | import defaultExport from './foo.js'; 2 | export {named} from './foo.js?query'; 3 | export default defaultExport; @@ -1046,3 +1023,26 @@ Generated by [AVA](https://avajs.dev). > 3 | export default defaultExport;␊ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use \`export…from\` to re-export \`default\`.␊ ` + +## Invalid #1 + 1 | import * as namespace from 'foo'; + 2 | export {namespace}; + 3 | export default namespace; + +> Output + + `␊ + 1 | import * as namespace from 'foo';␊ + 2 |␊ + 3 | export default namespace;␊ + 4 | export * as namespace from 'foo';␊ + ` + +> Error 1/1 + + `␊ + 1 | import * as namespace from 'foo';␊ + > 2 | export {namespace};␊ + | ^^^^^^^^^ Use \`export…from\` to re-export \`namespace\`.␊ + 3 | export default namespace;␊ + ` diff --git a/test/snapshots/prefer-export-from.mjs.snap b/test/snapshots/prefer-export-from.mjs.snap index a0ba64a891a9039e71d9bd662b1ff9005e83627c..2b105207bbee6a01be8569ff67b7611402e64996 100644 GIT binary patch literal 2558 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 U8gso6vQRPqU!xi2@Mt^$0IZPi2><{9 literal 2556 zcmV)RzVZsAlhlAte(Iu4o%J8Y1ax3=ataE@f5zF~cOCUtW$4IGLX9 zYm1~!7`3((w%AdqBsKG@3|am|T})ut+K0Qg$6twtNZO9EX&?a4R}GlEH^e_TEhh5u zjD~qLA(D1rtgr`QTIoc$%IK)cO`+YM-{y6$gh<+oQQ!c;^tR6X6Bc$a%{p>XAuEnd zk|60#jB-Z`Q=I?^cXlWrQ{TA%MoeMHoC{HZfJj=8@y1gCL~WAY@N|59^8PgN;|C=} zw?QQRCr0%kvc-9~;Op5od853Gs+{6qeH|j{6^sqe0K7TMN0so$jk{m{sWwo3d}V|L zNxL!fpQhmH0>C^kgmHB)Escj;0T{4QOxh@M{Id z5J|f+8r=X$b8g;nJg}|D?B57CU06NzY@f z8cHJ7p)7dwwL6M;YImLbagMl~Tm5c|U-&tQq&qRzcmhzk ztnOOZ_j^{2Zkr!l@sGw>36h@1$b5#vh-U#PD%o&;{@|Uzf8U$I$?!AzbV*JUAoU>=|u4!{P8}LiIJ&ahJJu|E8Gz+gD%ZyGmwwLL{AqVKWMV=I-_>MTeKZJ^PY- zwtCLrdLWX{z_?E0i;at0-;26a?A=^jDZTZO3hGT`KRWX7E&utxw5|{$X)A^z2!O|)pI!@pT0JMc z$+`MFLP@T3jkFdcCKvz-7>MG(jU8~ciE<sCNY*!s)+^4 z3?eBbJ&o{9N>BHlM79{uXhF(pEp&&6<$xNWNKP}{BUJNj?U*^FEKlnkBYc%~8L}ogXp&EyKD#)G+nE)GT1SHZGq zOHwm6o$$|B&_8*GIoZbGgw{{Wr2w5M`tw*Q>-z{Gk2V@fBaNg;4vl#!(%6#7!N1`YG!;E3sINgn`a*SPuhpcUr~|{| z>n6>IVT(igRW(eBn019{5o`5r3t7!OL7_rarKn+2BAOuWz|5EvVt8lLjk&NG+_ZkeoZJk~ zK3ks$0jU-(qVT3V@B<;q7!^-+TQJ9@Zz7~js%c_U&PG#nOTVfqLRYdobKc?@*`vV- zZF<_sq(yX^)Q|b1QrDf?6G53DsiQ1KJ$3OCRmL*kNo-D^!-#I$K1^!96|nYo`ijwt z=0)0B6CWdtkB~t;1sZ#$K%-|X+kz5OVf3}p?O@(*4-LsQny)I=j|R+8$yxK|8B>%> zQ4?xt^98%V7*!y1>cW^4;{sclh~z`cn}n@5IR}vnOu39+Xt2^^I_iJKED*iCa6HfA z=uKt}PDh=Q0fDs=Kz)QKN+u*p{`|=zhYx;YhC;v^8$bky)yzag)Y)9AmCxpK3{RHL zYaB*vVxB2>ud}w@dIr!;pC}~q3Mhyw#KyBHu+HzbH$%m@#h6g$Y6myN-hzkXEOVJ> zfrgV@DkY|w`Hk6A-6tW*<;^y9&PVxO;eA$D;2VO)Ii%dKVeH}ZX3OhG_h924*R(B{ z^G%1C<2IoOQKoxhmf*~Yg%a)3p`}I4y-7g9#!OYj7i@-^5?Pk<*=I&?*=3QF+WvE$ z|DR=2Jj`HBBNf*I_z%TUJ2?k0t5^f4T*~?cmUt;Q-~~bhxtwY0T%J;l^X<8=Q)m)Q z;knHd^#Xl@Ft_Knu+VxIa+M*`T=Q#&i7l|^#2U0ZkjJZWt|0uV+PDKpp=r5k8O{{$ zO0zdT$CD}Ln9UL^I2f;VZ7B8>OJ zvD9udE>6oRCz)Z#(hH|BEEP;T-=wj=}0S?WoMfxo5f8m#$nAbC;eJAAN5@A;x zv*;Vj=Cu~T%)y!yuoos=w`~|}fX0uzdH7*n)%yH|3OC5?m6q`wdG#wtf+wB(ij{RL zH`=QPLmMIQTY8pt+-%%l$=nL9d`ihx>2Ot|G%AWrtzmmxnzxpPWfoJ+I0XYNbRTYw z*cS!5r(WEzLyUK=xAbk(-Cud{4Pox(`fsDTe6dZ)l_C)yAZiy78UFQVJAgad<}qwN zX@adR3A~&c%?;>h`~nT&P9d1~U9zZs2KeX52rPQR4DJ_x!q9g?8vVzb#j+njh`F%d zd)%*+2lpz)aa8ii42I}CAMMhXkkr