Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: no-restricted-imports to check re-export (fixes #9678) #11064

Merged
merged 2 commits into from Nov 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 15 additions & 1 deletion 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?

Expand Down Expand Up @@ -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"] }]*/

Expand Down Expand Up @@ -135,13 +147,15 @@ Examples of **correct** code for this rule:
/*eslint no-restricted-imports: ["error", "fs"]*/

import crypto from 'crypto';
export { foo } from "bar";
```

```js
/*eslint no-restricted-imports: ["error", { "paths": ["fs"], "patterns": ["eslint/*"] }]*/

import crypto from 'crypto';
import eslint from 'eslint';
export * from "path";
```

```js
Expand Down
60 changes: 38 additions & 22 deletions lib/rules/no-restricted-imports.js
Expand Up @@ -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
};
}
};
18 changes: 18 additions & 0 deletions tests/lib/rules/no-restricted-imports.js
Expand Up @@ -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: [{
Expand Down