diff --git a/docs/rules/no-restricted-imports.md b/docs/rules/no-restricted-imports.md index 66b8095a02b..62747ebcecb 100644 --- a/docs/rules/no-restricted-imports.md +++ b/docs/rules/no-restricted-imports.md @@ -1,6 +1,6 @@ # Disallow specific imports (no-restricted-imports) -Imports are an ES6/ES2015 standard for making the functionality of other modules available in your current module. In CommonJS this is implemented through the require() call which makes this ESLint rule roughly equivalent to its CommonJS counterpart `no-restricted-modules`. +Imports are an ES6/ES2015 standard for making the functionality of other modules available in your current module. In CommonJS this is implemented through the `require()` call which makes this ESLint rule roughly equivalent to its CommonJS counterpart `no-restricted-modules`. Why would you want to restrict imports? @@ -87,6 +87,18 @@ Examples of **incorrect** code for this rule: import fs from 'fs'; ``` +```js +/*eslint no-restricted-imports: ["error", "fs"]*/ + +export { fs } from 'fs'; +``` + +```js +/*eslint no-restricted-imports: ["error", "fs"]*/ + +export * from 'fs'; +``` + ```js /*eslint no-restricted-imports: ["error", { "paths": ["cluster"] }]*/ @@ -135,6 +147,7 @@ Examples of **correct** code for this rule: /*eslint no-restricted-imports: ["error", "fs"]*/ import crypto from 'crypto'; +export { foo } from "bar"; ``` ```js @@ -142,6 +155,7 @@ import crypto from 'crypto'; import crypto from 'crypto'; import eslint from 'eslint'; +export * from "path"; ``` ```js diff --git a/lib/rules/no-restricted-imports.js b/lib/rules/no-restricted-imports.js index e4563172e0b..b8fcca1aaf8 100644 --- a/lib/rules/no-restricted-imports.js +++ b/lib/rules/no-restricted-imports.js @@ -236,31 +236,47 @@ module.exports = { return restrictedPatterns.length > 0 && restrictedPatternsMatcher.ignores(importSource); } - return { - ImportDeclaration(node) { - const importSource = node.source.value.trim(); - const importNames = node.specifiers.reduce((set, specifier) => { - if (specifier.type === "ImportDefaultSpecifier") { - set.add("default"); - } else if (specifier.type === "ImportNamespaceSpecifier") { - set.add("*"); - } else { - set.add(specifier.imported.name); - } - return set; - }, new Set()); - - if (isRestrictedForEverythingImported(importSource, importNames)) { - reportPathForEverythingImported(importSource, node); + /** + * Checks a node to see if any problems should be reported. + * @param {ASTNode} node The node to check. + * @returns {void} + * @private + */ + function checkNode(node) { + const importSource = node.source.value.trim(); + const importNames = node.specifiers ? node.specifiers.reduce((set, specifier) => { + if (specifier.type === "ImportDefaultSpecifier") { + set.add("default"); + } else if (specifier.type === "ImportNamespaceSpecifier") { + set.add("*"); + } else if (specifier.imported) { + set.add(specifier.imported.name); + } else if (specifier.local) { + set.add(specifier.local.name); } + return set; + }, new Set()) : new Set(); - if (isRestrictedPath(importSource, importNames)) { - reportPath(node); - } - if (isRestrictedPattern(importSource)) { - reportPathForPatterns(node); - } + if (isRestrictedForEverythingImported(importSource, importNames)) { + reportPathForEverythingImported(importSource, node); + } + + if (isRestrictedPath(importSource, importNames)) { + reportPath(node); + } + if (isRestrictedPattern(importSource)) { + reportPathForPatterns(node); } + } + + return { + ImportDeclaration: checkNode, + ExportNamedDeclaration(node) { + if (node.source) { + checkNode(node); + } + }, + ExportAllDeclaration: checkNode }; } }; diff --git a/tests/lib/rules/no-restricted-imports.js b/tests/lib/rules/no-restricted-imports.js index 5d279d5a31b..c4f2abb602b 100644 --- a/tests/lib/rules/no-restricted-imports.js +++ b/tests/lib/rules/no-restricted-imports.js @@ -193,6 +193,24 @@ ruleTester.run("no-restricted-imports", rule, { code: "import withGitignores from \"foo/bar\";", options: [{ patterns: ["foo/*", "!foo/baz"] }], errors: [{ message: "'foo/bar' import is restricted from being used by a pattern.", type: "ImportDeclaration" }] + }, { + code: "export * from \"fs\";", + options: ["fs"], + errors: [{ message: "'fs' import is restricted from being used.", type: "ExportAllDeclaration" }] + }, { + code: "export {a} from \"fs\";", + options: ["fs"], + errors: [{ message: "'fs' import is restricted from being used.", type: "ExportNamedDeclaration" }] + }, { + code: "export {foo as b} from \"fs\";", + options: [{ + paths: [{ + name: "fs", + importNames: ["foo"], + message: "Don't import 'foo'." + }] + }], + errors: [{ message: "'fs' import is restricted from being used. Don't import 'foo'.", type: "ExportNamedDeclaration" }] }, { code: "import withGitignores from \"foo\";", options: [{