feat(linter/import): Add ignoreTypes option for the import/no-cycle rule (#2905)

Fixes: https://github.com/oxc-project/oxc/issues/2904

Adds an `ignoreTypes` option for the `import/no-cycle` rule, to ignore
imports that don't have any runtime effect.
This commit is contained in:
John Daly 2024-04-06 22:07:45 -07:00 committed by GitHub
parent 79e2c95e2d
commit 6de1b77b1b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 56 additions and 0 deletions

View file

@ -0,0 +1,2 @@
// @ts-ignore
import type { foo } from '../es6/depth-one';

View file

@ -0,0 +1,2 @@
// @ts-ignore
import { type foo, type bar } from '../depth-zero';

View file

@ -0,0 +1,2 @@
// @ts-ignore
import type { foo } from '../depth-zero';

View file

@ -0,0 +1,3 @@
// @ts-ignore
import { foo, type BarType } from '../depth-zero';

View file

@ -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,
@ -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,
}
@ -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)
@ -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;
}
@ -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),
@ -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)

View file

@ -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]
1 │ import { 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]
1 │ import { 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