feat(linter): continue working on no_cycle (#2471)

This commit is contained in:
Boshen 2024-02-23 13:16:30 +08:00 committed by GitHub
parent 2628c97eda
commit 2714a32970
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 450 additions and 64 deletions

View file

@ -1,7 +1,9 @@
#![allow(clippy::cast_possible_truncation)]
use std::{ use std::{
collections::HashSet, collections::HashSet,
path::{Path, PathBuf}, ffi::OsStr,
sync::Arc, path::{Component, Path, PathBuf},
}; };
use oxc_diagnostics::{ use oxc_diagnostics::{
@ -20,8 +22,27 @@ use crate::{context::LintContext, rule::Rule};
struct NoCycleDiagnostic(#[label] Span, String); struct NoCycleDiagnostic(#[label] Span, String);
/// <https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-cycle.md> /// <https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-cycle.md>
#[derive(Debug, Default, Clone)] #[derive(Debug, Clone)]
pub struct NoCycle; pub struct NoCycle {
/// maximum dependency depth to traverse
max_depth: u32,
/// ignore external modules
#[allow(unused)]
ignore_external: bool,
/// Allow cyclic dependency if there is at least one dynamic import in the chain
#[allow(unused)]
allow_unsafe_dynamic_cyclic_dependency: bool,
}
impl Default for NoCycle {
fn default() -> Self {
Self {
max_depth: u32::MAX,
ignore_external: false,
allow_unsafe_dynamic_cyclic_dependency: false,
}
}
}
declare_oxc_lint!( declare_oxc_lint!(
/// ### What it does /// ### What it does
@ -53,18 +74,37 @@ declare_oxc_lint!(
); );
impl Rule for NoCycle { impl Rule for NoCycle {
fn from_configuration(value: serde_json::Value) -> Self {
let obj = value.get(0);
Self {
max_depth: obj
.and_then(|v| v.get("maxDepth"))
.and_then(serde_json::Value::as_number)
.and_then(serde_json::Number::as_u64)
.map_or(u32::MAX, |n| n as u32),
ignore_external: obj
.and_then(|v| v.get("ignoreExternal"))
.and_then(serde_json::Value::as_bool)
.unwrap_or_default(),
allow_unsafe_dynamic_cyclic_dependency: obj
.and_then(|v| v.get("allowUnsafeDynamicCyclicDependency"))
.and_then(serde_json::Value::as_bool)
.unwrap_or_default(),
}
}
fn run_once(&self, ctx: &LintContext<'_>) { fn run_once(&self, ctx: &LintContext<'_>) {
let module_record = ctx.semantic().module_record(); let module_record = ctx.semantic().module_record();
let mut visited: HashSet<PathBuf> = HashSet::new(); let needle = &module_record.resolved_absolute_path;
let mut stack: Vec<(Atom, PathBuf)> = Vec::new();
let cwd = std::env::current_dir().unwrap(); let cwd = std::env::current_dir().unwrap();
let needle = &module_record.resolved_absolute_path; let mut state = State::default();
if visit(module_record, &mut visited, &mut stack, needle) { if self.detect_cycle(&mut state, module_record, needle) {
let stack = &state.stack;
let span = module_record.requested_modules.get(&stack[0].0).unwrap()[0]; let span = module_record.requested_modules.get(&stack[0].0).unwrap()[0];
let help = stack let help = stack
.into_iter() .iter()
.map(|(specifier, path)| { .map(|(specifier, path)| {
let path = let path =
path.strip_prefix(&cwd).unwrap().to_string_lossy().replace('\\', "/"); path.strip_prefix(&cwd).unwrap().to_string_lossy().replace('\\', "/");
@ -77,64 +117,198 @@ impl Rule for NoCycle {
} }
} }
/// Walks ModuleRecord and returns the path stack #[derive(Debug, Default)]
/// if there is a cycle struct State {
fn visit( traversed: HashSet<PathBuf>,
module_record: &Arc<ModuleRecord>, stack: Vec<(Atom, PathBuf)>,
visited: &mut HashSet<PathBuf>, }
stack: &mut Vec<(Atom, PathBuf)>,
needle: &Path, impl NoCycle {
) -> bool { fn detect_cycle(&self, state: &mut State, module_record: &ModuleRecord, needle: &Path) -> bool {
let path = &module_record.resolved_absolute_path; let path = &module_record.resolved_absolute_path;
if path.components().any(|c| match c {
std::path::Component::Normal(p) => p == std::ffi::OsStr::new("node_modules"), if state.stack.len() as u32 > self.max_depth {
_ => false,
}) {
return false; return false;
} }
if path
.components()
.any(|c| matches!(c, Component::Normal(p) if p == OsStr::new("node_modules")))
{
return false;
}
for module_record_ref in &module_record.loaded_modules { for module_record_ref in &module_record.loaded_modules {
let resolved_absolute_path = &module_record_ref.resolved_absolute_path; let resolved_absolute_path = &module_record_ref.resolved_absolute_path;
if !visited.insert(resolved_absolute_path.clone()) { if !state.traversed.insert(resolved_absolute_path.clone()) {
continue; continue;
} }
stack.push((module_record_ref.key().clone(), resolved_absolute_path.clone())); state.stack.push((module_record_ref.key().clone(), resolved_absolute_path.clone()));
if needle == resolved_absolute_path { if needle == resolved_absolute_path {
return true; return true;
} }
if visit(module_record_ref.value(), visited, stack, needle) { if self.detect_cycle(state, module_record_ref.value(), needle) {
return true; return true;
} }
stack.pop(); state.stack.pop();
} }
false false
} }
}
#[test] #[test]
fn test() { fn test() {
use serde_json::json;
use crate::tester::Tester; use crate::tester::Tester;
let pass = vec![ let pass = vec![
"import foo from './foo.js'", (r#"import foo from "./foo.js""#, None),
"import _ from 'lodash'", (r#"import _ from "lodash""#, None),
"import foo from '@scope/foo'", (r#"import foo from "@scope/foo""#, None),
"require('./foo')", (r#"var _ = require("lodash")"#, None),
"require('../foo')", (r#"var find = require("lodash.find")"#, None),
"require('foo')", (r#"var foo = require("./foo")"#, None),
"require('./')", (r#"var foo = require("../foo")"#, None),
"require('@scope/foo')", (r#"var foo = require("foo")"#, None),
"require('./bar/index')", (r#"var foo = require("./")"#, None),
"require('./bar')", (r#"var foo = require("@scope/foo")"#, None),
(r#"var bar = require("./bar/index")"#, None),
(r#"var bar = require("./bar")"#, None),
(r#"var bar = require("./bar")"#, None),
// TODO: settings 'import/external-module-folders': ['cycles/external'],
// (r#"import { foo } from "./external-depth-two""#, Some(json!([[{"ignoreExternal":true}]))),
// (
// r#"import { foo } from "cycles/external/depth-one""#,
// Some(json!([[{"ignoreExternal":true}])),
// ),
(r#"import { foo } from "./es6/depth-two""#, Some(json!([{"maxDepth":1}]))),
(r#"import { foo, bar } from "./es6/depth-two""#, Some(json!([{"maxDepth":1}]))),
(r#"import("./es6/depth-two").then(function({ foo }) {})"#, Some(json!([{"maxDepth":1}]))),
// parser: parsers.BABEL_OLD
// (r#"import type { FooType } from "./es6/depth-one""#, None),
// (r#"import type { FooType, BarType } from "./es6/depth-one""#, None),
(
r#"function bar(){ return import("./es6/depth-one"); } // #2265 1"#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true}])),
),
(
r#"import { foo } from "./es6/depth-one-dynamic"; // #2265 2"#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true}])),
),
(
r#"function bar(){ return import("./es6/depth-one"); } // #2265 3"#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true}])),
),
(
r#"import { foo } from "./es6/depth-one-dynamic"; // #2265 4"#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true}])),
),
// Flow not supported
// (r#"import { bar } from "./flow-types""#, None),
// (r#"import { bar } from "./flow-types-only-importing-type""#, None),
// (r#"import { bar } from "./flow-types-only-importing-multiple-types""#, None),
// (r#"import { bar } from "./flow-typeof""#, None),
]; ];
let fail = vec![ let fail = vec![
"import { foo } from './es6/depth-one'", // (r#"import { bar } from "./flow-types-some-type-imports""#, None),
"const { foo } = require('./es6/depth-one')", // TODO: settings 'import/resolver': 'webpack', 'import/external-module-folders': ['cycles/external'],
"import { foo } from './es6/depth-one-reexport'", // (r#"import { foo } from "cycles/external/depth-one""#, None),
"import { foo } from './es6/depth-two'", // TODO: settings 'import/external-module-folders': ['cycles/external'],
"import { foo } from './es6/depth-three-star'", // (r#"import { foo } from "./external-depth-two""#, None),
"import { foo } from './es6/depth-three-indirect'", // (r#"import { foo } from "./es6/depth-one""#, None),
"import { foo } from './intermediate-ignore'", (r#"import { foo } from "./es6/depth-one""#, Some(json!([{"maxDepth":1}]))),
"import { foo } from './ignore'", (r#"const { foo } = require("./es6/depth-one")"#, Some(json!([{"commonjs":true}]))),
// TODO: amd
// (r#"require(["./es6/depth-one"], d1 => {})"#, Some(json!([{"amd":true}]))),
// (r#"define(["./es6/depth-one"], d1 => {})"#, Some(json!([{"amd":true}]))),
(r#"import { foo } from "./es6/depth-one-reexport""#, None),
(r#"import { foo } from "./es6/depth-two""#, None),
(r#"import { foo } from "./es6/depth-two""#, Some(json!([{"maxDepth":2}]))),
(r#"const { foo } = require("./es6/depth-two")"#, Some(json!([{"commonjs":true}]))),
(r#"import { two } from "./es6/depth-three-star""#, None),
(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":""}]))),
(
r#"import { foo } from "./es6/depth-one""#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true}])),
),
(
r#"import { foo } from "./es6/depth-one""#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true,"maxDepth":1}])),
),
(
r#"const { foo } = require("./es6/depth-one")"#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true,"commonjs":true}])),
),
// TODO: amd
// (
// r#"require(["./es6/depth-one"], d1 => {})"#,
// Some(json!([{"allowUnsafeDynamicCyclicDependency":true,"amd":true}])),
// ),
// (
// r#"define(["./es6/depth-one"], d1 => {})"#,
// Some(json!([{"allowUnsafeDynamicCyclicDependency":true,"amd":true}])),
// ),
(
r#"import { foo } from "./es6/depth-one-reexport""#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true}])),
),
(
r#"import { foo } from "./es6/depth-two""#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true}])),
),
(
r#"import { foo } from "./es6/depth-two""#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true,"maxDepth":2}])),
),
(
r#"const { foo } = require("./es6/depth-two")"#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true,"commonjs":true}])),
),
(
r#"import { two } from "./es6/depth-three-star""#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true}])),
),
(
r#"import one, { two, three } from "./es6/depth-three-star""#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true}])),
),
(
r#"import { bar } from "./es6/depth-three-indirect""#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true}])),
),
(
r#"import { bar } from "./es6/depth-three-indirect""#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true}])),
),
(
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":""}]))),
// 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),
// (r#"function bar(){ return import("./es6/depth-one"); } // #2265 7"#, None),
// (r#"import { foo } from "./es6/depth-one-dynamic"; // #2265 8"#, None),
// // Flow not supported
// (r#"import { bar } from "./flow-types-depth-one""#, None),
(r#"import { foo } from "./intermediate-ignore""#, None),
(r#"import { foo } from "./ignore""#, None),
]; ];
Tester::new(NoCycle::NAME, pass, fail) Tester::new(NoCycle::NAME, pass, fail)

View file

@ -5,7 +5,7 @@ expression: no_cycle
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected ⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21] ╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from './es6/depth-one' 1 │ import { foo } from "./es6/depth-one"
· ───────────────── · ─────────────────
╰──── ╰────
help: These paths form a cycle: help: These paths form a cycle:
@ -14,7 +14,7 @@ expression: no_cycle
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected ⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:25] ╭─[cycles/depth-zero.js:1:25]
1 │ const { foo } = require('./es6/depth-one') 1 │ const { foo } = require("./es6/depth-one")
· ───────────────── · ─────────────────
╰──── ╰────
help: These paths form a cycle: help: These paths form a cycle:
@ -23,7 +23,7 @@ expression: no_cycle
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected ⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21] ╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from './es6/depth-one-reexport' 1 │ import { foo } from "./es6/depth-one-reexport"
· ────────────────────────── · ──────────────────────────
╰──── ╰────
help: These paths form a cycle: help: These paths form a cycle:
@ -32,7 +32,7 @@ expression: no_cycle
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected ⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21] ╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from './es6/depth-two' 1 │ import { foo } from "./es6/depth-two"
· ───────────────── · ─────────────────
╰──── ╰────
help: These paths form a cycle: help: These paths form a cycle:
@ -42,7 +42,38 @@ expression: no_cycle
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected ⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21] ╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from './es6/depth-three-star' 1 │ import { foo } from "./es6/depth-two"
· ─────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-two - fixtures/import/cycles/es6/depth-two.js
-> ./depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:25]
1 │ const { foo } = require("./es6/depth-two")
· ─────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-two - fixtures/import/cycles/es6/depth-two.js
-> ./depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { two } from "./es6/depth-three-star"
· ────────────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-three-star - fixtures/import/cycles/es6/depth-three-star.js
-> ./depth-two - fixtures/import/cycles/es6/depth-two.js
-> ./depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:33]
1 │ import one, { two, three } from "./es6/depth-three-star"
· ──────────────────────── · ────────────────────────
╰──── ╰────
help: These paths form a cycle: help: These paths form a cycle:
@ -53,7 +84,7 @@ expression: no_cycle
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected ⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21] ╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from './es6/depth-three-indirect' 1 │ import { bar } from "./es6/depth-three-indirect"
· ──────────────────────────── · ────────────────────────────
╰──── ╰────
help: These paths form a cycle: help: These paths form a cycle:
@ -64,7 +95,188 @@ expression: no_cycle
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected ⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21] ╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from './intermediate-ignore' 1 │ import { bar } from "./es6/depth-three-indirect"
· ────────────────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-three-indirect - fixtures/import/cycles/es6/depth-three-indirect.js
-> ./depth-two - fixtures/import/cycles/es6/depth-two.js
-> ./depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from "./es6/depth-two"
· ─────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-two - fixtures/import/cycles/es6/depth-two.js
-> ./depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from "./es6/depth-two"
· ─────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-two - fixtures/import/cycles/es6/depth-two.js
-> ./depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from "./es6/depth-one"
· ─────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from "./es6/depth-one"
· ─────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:25]
1 │ const { foo } = require("./es6/depth-one")
· ─────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from "./es6/depth-one-reexport"
· ──────────────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-one-reexport - fixtures/import/cycles/es6/depth-one-reexport.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from "./es6/depth-two"
· ─────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-two - fixtures/import/cycles/es6/depth-two.js
-> ./depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from "./es6/depth-two"
· ─────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-two - fixtures/import/cycles/es6/depth-two.js
-> ./depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:25]
1 │ const { foo } = require("./es6/depth-two")
· ─────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-two - fixtures/import/cycles/es6/depth-two.js
-> ./depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { two } from "./es6/depth-three-star"
· ────────────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-three-star - fixtures/import/cycles/es6/depth-three-star.js
-> ./depth-two - fixtures/import/cycles/es6/depth-two.js
-> ./depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:33]
1 │ import one, { two, three } from "./es6/depth-three-star"
· ────────────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-three-star - fixtures/import/cycles/es6/depth-three-star.js
-> ./depth-two - fixtures/import/cycles/es6/depth-two.js
-> ./depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { bar } from "./es6/depth-three-indirect"
· ────────────────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-three-indirect - fixtures/import/cycles/es6/depth-three-indirect.js
-> ./depth-two - fixtures/import/cycles/es6/depth-two.js
-> ./depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { bar } from "./es6/depth-three-indirect"
· ────────────────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-three-indirect - fixtures/import/cycles/es6/depth-three-indirect.js
-> ./depth-two - fixtures/import/cycles/es6/depth-two.js
-> ./depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from "./es6/depth-two"
· ─────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-two - fixtures/import/cycles/es6/depth-two.js
-> ./depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from "./es6/depth-two"
· ─────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-two - fixtures/import/cycles/es6/depth-two.js
-> ./depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from "./es6/depth-two"
· ─────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-two - fixtures/import/cycles/es6/depth-two.js
-> ./depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from "./es6/depth-two"
· ─────────────────
╰────
help: These paths form a cycle:
-> ./es6/depth-two - fixtures/import/cycles/es6/depth-two.js
-> ./depth-one - fixtures/import/cycles/es6/depth-one.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from "./intermediate-ignore"
· ─────────────────────── · ───────────────────────
╰──── ╰────
help: These paths form a cycle: help: These paths form a cycle:
@ -74,7 +286,7 @@ expression: no_cycle
⚠ eslint-plugin-import(no-cycle): Dependency cycle detected ⚠ eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21] ╭─[cycles/depth-zero.js:1:21]
1 │ import { foo } from './ignore' 1 │ import { foo } from "./ignore"
· ────────── · ──────────
╰──── ╰────
help: These paths form a cycle: help: These paths form a cycle: