Skip to content

Commit

Permalink
[Fix]: no-cycle: check cycle for require even if option is set
Browse files Browse the repository at this point in the history
  • Loading branch information
GerkinDev committed Mar 7, 2022
1 parent d2ab3c1 commit 0fe7fc1
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 99 deletions.
5 changes: 4 additions & 1 deletion src/rules/no-cycle.js
Expand Up @@ -58,7 +58,10 @@ module.exports = {
return; // ignore external modules
}
if (options.allowUnsafeDynamicCyclicDependency && (
importer.type === 'ImportExpression' || importer.type === 'CallExpression')) {
// Ignore `import()`
importer.type === 'ImportExpression' ||
// `require()` calls are always checked (if possible)
(importer.type === 'CallExpression' && importer.callee.name !== 'require'))) {
return; // cycle via dynamic import allowed by config
}

Expand Down
209 changes: 111 additions & 98 deletions tests/src/rules/no-cycle.js
Expand Up @@ -136,104 +136,117 @@ ruleTester.run('no-cycle', rule, {
},
}),

flatMap(testDialects, (testDialect) => [
test({
code: `import { foo } from "./${testDialect}/depth-one"`,
errors: [error(`Dependency cycle detected.`)],
}),
test({
code: `import { foo } from "./${testDialect}/depth-one"`,
options: [{ maxDepth: 1 }],
errors: [error(`Dependency cycle detected.`)],
}),
test({
code: `const { foo } = require("./${testDialect}/depth-one")`,
errors: [error(`Dependency cycle detected.`)],
options: [{ commonjs: true }],
}),
test({
code: `require(["./${testDialect}/depth-one"], d1 => {})`,
errors: [error(`Dependency cycle detected.`)],
options: [{ amd: true }],
}),
test({
code: `define(["./${testDialect}/depth-one"], d1 => {})`,
errors: [error(`Dependency cycle detected.`)],
options: [{ amd: true }],
}),
test({
code: `import { foo } from "./${testDialect}/depth-two"`,
errors: [error(`Dependency cycle via ./depth-one:1`)],
}),
test({
code: `import { foo } from "./${testDialect}/depth-two"`,
options: [{ maxDepth: 2 }],
errors: [error(`Dependency cycle via ./depth-one:1`)],
}),
test({
code: `const { foo } = require("./${testDialect}/depth-two")`,
errors: [error(`Dependency cycle via ./depth-one:1`)],
options: [{ commonjs: true }],
}),
test({
code: `import { two } from "./${testDialect}/depth-three-star"`,
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
}),
test({
code: `import one, { two, three } from "./${testDialect}/depth-three-star"`,
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
}),
test({
code: `import { bar } from "./${testDialect}/depth-three-indirect"`,
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
}),
test({
code: `import { bar } from "./${testDialect}/depth-three-indirect"`,
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
parser: parsers.BABEL_OLD,
}),
test({
code: `import("./${testDialect}/depth-three-star")`,
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
parser: parsers.BABEL_OLD,
}),
test({
code: `import("./${testDialect}/depth-three-indirect")`,
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
parser: parsers.BABEL_OLD,
}),
test({
code: `import { foo } from "./${testDialect}/depth-two"`,
options: [{ maxDepth: Infinity }],
errors: [error(`Dependency cycle via ./depth-one:1`)],
}),
test({
code: `import { foo } from "./${testDialect}/depth-two"`,
options: [{ maxDepth: '∞' }],
errors: [error(`Dependency cycle via ./depth-one:1`)],
}),
test({
code: `function bar(){ return import("./${testDialect}/depth-one"); } // #2265 5`,
errors: [error(`Dependency cycle detected.`)],
parser: parsers.BABEL_OLD,
}),
testVersion('> 3', () => ({ // Dynamic import is not properly caracterized with eslint < 4
code: `import { foo } from "./${testDialect}/depth-one-dynamic"; // #2265 6`,
errors: [error(`Dependency cycle detected.`)],
parser: parsers.BABEL_OLD,
})),
].concat(parsers.TS_NEW ? [
test({
code: `function bar(){ return import("./${testDialect}/depth-one"); } // #2265 7`,
errors: [error(`Dependency cycle detected.`)],
parser: parsers.TS_NEW,
}),
test({
code: `import { foo } from "./${testDialect}/depth-one-dynamic"; // #2265 8`,
errors: [error(`Dependency cycle detected.`)],
parser: parsers.TS_NEW,
}),
] : [])),
flatMap(testDialects, (testDialect) =>
// Ensure behavior does not change for those tests, with or without `
flatMap([
{},
{ allowUnsafeDynamicCyclicDependency: true },
], (opts) => [
test({
code: `import { foo } from "./${testDialect}/depth-one"`,
options: [{ ...opts }],
errors: [error(`Dependency cycle detected.`)],
}),
test({
code: `import { foo } from "./${testDialect}/depth-one"`,
options: [{ ...opts, maxDepth: 1 }],
errors: [error(`Dependency cycle detected.`)],
}),
test({
code: `const { foo } = require("./${testDialect}/depth-one")`,
errors: [error(`Dependency cycle detected.`)],
options: [{ ...opts, commonjs: true }],
}),
test({
code: `require(["./${testDialect}/depth-one"], d1 => {})`,
errors: [error(`Dependency cycle detected.`)],
options: [{ ...opts, amd: true }],
}),
test({
code: `define(["./${testDialect}/depth-one"], d1 => {})`,
errors: [error(`Dependency cycle detected.`)],
options: [{ ...opts, amd: true }],
}),
test({
code: `import { foo } from "./${testDialect}/depth-two"`,
options: [{ ...opts }],
errors: [error(`Dependency cycle via ./depth-one:1`)],
}),
test({
code: `import { foo } from "./${testDialect}/depth-two"`,
options: [{ ...opts, maxDepth: 2 }],
errors: [error(`Dependency cycle via ./depth-one:1`)],
}),
test({
code: `const { foo } = require("./${testDialect}/depth-two")`,
errors: [error(`Dependency cycle via ./depth-one:1`)],
options: [{ ...opts, commonjs: true }],
}),
test({
code: `import { two } from "./${testDialect}/depth-three-star"`,
options: [{ ...opts }],
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
}),
test({
code: `import one, { two, three } from "./${testDialect}/depth-three-star"`,
options: [{ ...opts }],
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
}),
test({
code: `import { bar } from "./${testDialect}/depth-three-indirect"`,
options: [{ ...opts }],
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
}),
test({
code: `import { bar } from "./${testDialect}/depth-three-indirect"`,
options: [{ ...opts }],
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
parser: parsers.BABEL_OLD,
}),
test({
code: `import { foo } from "./${testDialect}/depth-two"`,
options: [{ ...opts, maxDepth: Infinity }],
errors: [error(`Dependency cycle via ./depth-one:1`)],
}),
test({
code: `import { foo } from "./${testDialect}/depth-two"`,
options: [{ ...opts, maxDepth: '∞' }],
errors: [error(`Dependency cycle via ./depth-one:1`)],
}),
]).concat([
test({
code: `import("./${testDialect}/depth-three-star")`,
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
parser: parsers.BABEL_OLD,
}),
test({
code: `import("./${testDialect}/depth-three-indirect")`,
errors: [error(`Dependency cycle via ./depth-two:1=>./depth-one:1`)],
parser: parsers.BABEL_OLD,
}),
test({
code: `function bar(){ return import("./${testDialect}/depth-one"); } // #2265 5`,
errors: [error(`Dependency cycle detected.`)],
parser: parsers.BABEL_OLD,
}),
]).concat(
testVersion('> 3', () => ({ // Dynamic import is not properly caracterized with eslint < 4
code: `import { foo } from "./${testDialect}/depth-one-dynamic"; // #2265 6`,
errors: [error(`Dependency cycle detected.`)],
parser: parsers.BABEL_OLD,
})),
).concat(parsers.TS_NEW ? [
test({
code: `function bar(){ return import("./${testDialect}/depth-one"); } // #2265 7`,
errors: [error(`Dependency cycle detected.`)],
parser: parsers.TS_NEW,
}),
test({
code: `import { foo } from "./${testDialect}/depth-one-dynamic"; // #2265 8`,
errors: [error(`Dependency cycle detected.`)],
parser: parsers.TS_NEW,
}),
] : [])),

test({
code: 'import { bar } from "./flow-types-depth-one"',
Expand Down

0 comments on commit 0fe7fc1

Please sign in to comment.