Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 25 additions & 15 deletions crates/oxc_linter/src/rules/import/no_cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ fn format_cycle(stack: &[(CompactStr, PathBuf)], cwd: &Path) -> String {

// <https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/no-cycle.md>
#[derive(Debug, Clone, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", default)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct NoCycle {
/// Maximum dependency depth to traverse
max_depth: u32,
Expand Down Expand Up @@ -91,8 +91,8 @@ declare_oxc_lint!(
///
/// Ensures that there is no resolvable path back to this module via its dependencies.
///
/// This includes cycles of depth 1 (imported module imports me) to "∞" (or Infinity),
/// if the `maxDepth` option is not set.
/// This includes cycles of depth 1 (imported module imports me) to an effectively
/// infinite value, if the `maxDepth` option is not set.
///
/// ### Why is this bad?
///
Expand Down Expand Up @@ -136,9 +136,7 @@ declare_oxc_lint!(

impl Rule for NoCycle {
fn from_configuration(value: serde_json::Value) -> Result<Self, serde_json::error::Error> {
Ok(serde_json::from_value::<DefaultRuleConfig<Self>>(value)
.unwrap_or_default()
.into_inner())
serde_json::from_value::<DefaultRuleConfig<Self>>(value).map(DefaultRuleConfig::into_inner)
}

fn run_once(&self, ctx: &LintContext<'_>) {
Expand Down Expand Up @@ -329,8 +327,13 @@ fn test() {
(r#"import one, { two, three } from "./es6/depth-three-star""#, None),
(r#"import { bar } from "./es6/depth-three-indirect""#, None),
(r#"import { bar } from "./es6/depth-three-indirect""#, None),
(r#"import { foo } from "./es6/depth-two""#, Some(json!([{"maxDepth":null}]))),
(r#"import { foo } from "./es6/depth-two""#, Some(json!([{"maxDepth":"∞"}]))),
// effectively unlimited:
(r#"import { foo } from "./es6/depth-two""#, None),
// Use default value, effectively unlimited:
(r#"import { foo } from "./es6/depth-two""#, Some(json!([]))),
// These are not valid config options and just fell back to the default value previously:
// (r#"import { foo } from "./es6/depth-two""#, Some(json!([{"maxDepth":null}]))),
// (r#"import { foo } from "./es6/depth-two""#, Some(json!([{"maxDepth":"∞"}]))),
(
r#"import { foo } from "./es6/depth-one""#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true}])),
Expand Down Expand Up @@ -384,19 +387,26 @@ fn test() {
r#"import { bar } from "./es6/depth-three-indirect""#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true}])),
),
// Equivalent to the commented tests below.
(
r#"import { foo } from "./es6/depth-two""#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true,"maxDepth":null}])),
),
(
r#"import { foo } from "./es6/depth-two""#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true,"maxDepth":"∞"}])),
Some(json!([{"allowUnsafeDynamicCyclicDependency":true}])),
),
// These are not valid config options and just fell back to the default value previously:
// (
// r#"import { foo } from "./es6/depth-two""#,
// Some(json!([{"allowUnsafeDynamicCyclicDependency":true,"maxDepth":null}])),
// ),
// (
// r#"import { foo } from "./es6/depth-two""#,
// Some(json!([{"allowUnsafeDynamicCyclicDependency":true,"maxDepth":"∞"}])),
// ),
// TODO: dynamic import
// (r#"import("./es6/depth-three-star")"#, None),
// (r#"import("./es6/depth-three-indirect")"#, None),
(r#"import { foo } from "./es6/depth-two""#, Some(json!([{"maxDepth":null}]))),
(r#"import { foo } from "./es6/depth-two""#, Some(json!([{"maxDepth":"∞"}]))),
// These are not valid config options and just fell back to the default value previously:
// (r#"import { foo } from "./es6/depth-two""#, Some(json!([{"maxDepth":null}]))),
// (r#"import { foo } from "./es6/depth-two""#, Some(json!([{"maxDepth":"∞"}]))),
// TODO: dynamic import
// (r#"function bar(){ return import("./es6/depth-one"); } // #2265 5"#, None),
// (r#"import { foo } from "./es6/depth-one-dynamic"; // #2265 6"#, None),
Expand Down
42 changes: 0 additions & 42 deletions crates/oxc_linter/src/snapshots/import_no_cycle.snap
Original file line number Diff line number Diff line change
Expand Up @@ -299,48 +299,6 @@ source: crates/oxc_linter/src/tester.rs
│ ../depth-zero (fixtures/import/cycles/depth-zero.js)
╰─────────╯ imports the current file

⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from "./es6/depth-two"
· ─────────────────
╰────
help: Refactor to remove the cycle. Consider extracting shared code into a separate module that both files can import.
note: These paths form a cycle:
╭──▶ ./es6/depth-two (fixtures/import/cycles/es6/depth-two.js)
│ ⬇ imports
│ ./depth-one (fixtures/import/cycles/es6/depth-one.js)
│ ⬇ imports
│ ../depth-zero (fixtures/import/cycles/depth-zero.js)
╰─────────╯ imports the current file

⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from "./es6/depth-two"
· ─────────────────
╰────
help: Refactor to remove the cycle. Consider extracting shared code into a separate module that both files can import.
note: These paths form a cycle:
╭──▶ ./es6/depth-two (fixtures/import/cycles/es6/depth-two.js)
│ ⬇ imports
│ ./depth-one (fixtures/import/cycles/es6/depth-one.js)
│ ⬇ imports
│ ../depth-zero (fixtures/import/cycles/depth-zero.js)
╰─────────╯ imports the current file

⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from "./es6/depth-two"
· ─────────────────
╰────
help: Refactor to remove the cycle. Consider extracting shared code into a separate module that both files can import.
note: These paths form a cycle:
╭──▶ ./es6/depth-two (fixtures/import/cycles/es6/depth-two.js)
│ ⬇ imports
│ ./depth-one (fixtures/import/cycles/es6/depth-one.js)
│ ⬇ imports
│ ../depth-zero (fixtures/import/cycles/depth-zero.js)
╰─────────╯ imports the current file

⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from "./intermediate-ignore"
Expand Down
Loading