Skip to content

Commit

Permalink
feat(linter/import): Add ignoreTypes option for the `import/no-cycl…
Browse files Browse the repository at this point in the history
…e` rule (#2905)

Fixes: #2904

Adds an `ignoreTypes` option for the `import/no-cycle` rule, to ignore
imports that don't have any runtime effect.
  • Loading branch information
JohnDaly authored Apr 7, 2024
1 parent 79e2c95 commit 6de1b77
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// @ts-ignore
import type { foo } from '../es6/depth-one';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// @ts-ignore
import { type foo, type bar } from '../depth-zero';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// @ts-ignore
import type { foo } from '../depth-zero';
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// @ts-ignore

import { foo, type BarType } from '../depth-zero';
29 changes: 29 additions & 0 deletions crates/oxc_linter/src/rules/import/no_cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ struct NoCycleDiagnostic(#[label] Span, String);
pub struct NoCycle {
/// maximum dependency depth to traverse
max_depth: u32,
/// ignore type only imports
ignore_types: bool,
/// ignore external modules
#[allow(unused)]
ignore_external: bool,
Expand All @@ -38,6 +40,7 @@ impl Default for NoCycle {
fn default() -> Self {
Self {
max_depth: u32::MAX,
ignore_types: false,
ignore_external: false,
allow_unsafe_dynamic_cyclic_dependency: false,
}
Expand Down Expand Up @@ -82,6 +85,10 @@ impl Rule for NoCycle {
.and_then(serde_json::Value::as_number)
.and_then(serde_json::Number::as_u64)
.map_or(u32::MAX, |n| n as u32),
ignore_types: obj
.and_then(|v| v.get("ignoreTypes"))
.and_then(serde_json::Value::as_bool)
.unwrap_or_default(),
ignore_external: obj
.and_then(|v| v.get("ignoreExternal"))
.and_then(serde_json::Value::as_bool)
Expand Down Expand Up @@ -140,6 +147,11 @@ impl NoCycle {

for module_record_ref in &module_record.loaded_modules {
let resolved_absolute_path = &module_record_ref.resolved_absolute_path;
let was_imported_as_type =
&module_record_ref.import_entries.iter().all(|entry| entry.is_type);
if self.ignore_types && *was_imported_as_type {
continue;
}
if !state.traversed.insert(resolved_absolute_path.clone()) {
continue;
}
Expand Down Expand Up @@ -205,6 +217,18 @@ fn test() {
r#"import { foo } from "./es6/depth-one-dynamic"; // #2265 4"#,
Some(json!([{"allowUnsafeDynamicCyclicDependency":true}])),
),
(
r#"import { foo } from "./typescript/ts-types-only-importing-type";"#,
Some(json!([{"ignoreTypes":true}])),
),
(
r#"import { foo } from "./typescript/ts-types-only-importing-multiple-types";"#,
Some(json!([{"ignoreTypes":true}])),
),
(
r#"import { foo } from "./typescript/ts-types-depth-two";"#,
Some(json!([{"ignoreTypes":true}])),
),
// Flow not supported
// (r#"import { bar } from "./flow-types""#, None),
// (r#"import { bar } from "./flow-types-only-importing-type""#, None),
Expand Down Expand Up @@ -309,6 +333,11 @@ fn test() {
// (r#"import { bar } from "./flow-types-depth-one""#, None),
(r#"import { foo } from "./intermediate-ignore""#, None),
(r#"import { foo } from "./ignore""#, None),
(r#"import { foo } from "./typescript/ts-types-only-importing-type";"#, None),
(
r#"import { foo } from "./typescript/ts-types-some-type-imports";"#,
Some(json!([{"ignoreTypes":true}])),
),
];

Tester::new(NoCycle::NAME, pass, fail)
Expand Down
18 changes: 18 additions & 0 deletions crates/oxc_linter/src/snapshots/no_cycle.snap
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,21 @@ expression: no_cycle
help: These paths form a cycle:
-> ./ignore - fixtures/import/cycles/ignore/index.js
-> ../depth-zero - fixtures/import/cycles/depth-zero.js

eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1import { foo } from "./typescript/ts-types-only-importing-type";
· ───────────────────────────────────────────
╰────
help: These paths form a cycle:
-> ./typescript/ts-types-only-importing-type - fixtures/import/cycles/typescript/ts-types-only-importing-type.ts
-> ../depth-zero - fixtures/import/cycles/depth-zero.js

eslint-plugin-import(no-cycle): Dependency cycle detected
╭─[cycles/depth-zero.js:1:21]
1import { foo } from "./typescript/ts-types-some-type-imports";
· ─────────────────────────────────────────
╰────
help: These paths form a cycle:
-> ./typescript/ts-types-some-type-imports - fixtures/import/cycles/typescript/ts-types-some-type-imports.ts
-> ../depth-zero - fixtures/import/cycles/depth-zero.js

0 comments on commit 6de1b77

Please sign in to comment.