eslint-plugin-import
eslint-plugin-import copied to clipboard
`import/no-cycle` does not detect cycles when using named exports with a source
Overview
I am facing an issue where the no-cycle
rule fails to detect cycles when using named exports with a source (ex: export { bar } from "./bar.js"
). The issue does not occur when using "export all" (ex: export * from "./bar.js"
).
How to reproduce
$ cat .eslintrc.js
module.exports = {
plugins: ["import"],
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
},
rules: {
"import/no-cycle": "error",
},
};
$ cat index.js
export { bar } from "./reexport.js";
export const foo = 1;
$ cat reexport.js
export { bar } from "./bar.js";
$ cat bar.js
import { foo } from "./index.js";
export const bar = foo + 1;
$ npx eslint .
(no output)
Actual result
The dependency cycle is not detected
Expected result
The dependency cycle is detected. For example, when changing reexport.js
to an "export all", the dependency loop is correctly detected:
$ cat reexport.js
export * from "./bar.js"
$ npx eslint .
/.../index.js
1:1 error Dependency cycle via ./bar.js:1 import/no-cycle
✖ 1 problem (1 error, 0 warnings)
Fix suggestion
It seems we don't capture dependencies of ExportNamedDeclaration
nodes. This patch seems to fix the issue:
diff --git src/ExportMap.js src/ExportMap.js
index e18797a..fdaecec 100644
--- src/ExportMap.js
+++ src/ExportMap.js
@@ -611,6 +611,9 @@ ExportMap.parse = function (path, content, context) {
}
if (n.type === 'ExportNamedDeclaration') {
+ const getter = captureDependency(n, n.exportKind === 'type');
+ if (getter) m.dependencies.add(getter);
+
// capture declaration
if (n.declaration != null) {
switch (n.declaration.type) {
Can you raise a PR and add the test case?
See https://github.com/import-js/eslint-plugin-import/pull/2511