mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
fix(linter): improve prefer_namespace_keyword rule (#4751)
fix: #4651 This commit enhances the `prefer_namespace_keyword` rule in the TypeScript linter: Add support for detecting and fixing nested module declarations (e.g., module A.B {}) - Introduce helper functions `is_nest_module`, `is_valid_module`, and `is_invalid_module` to improve code readability and maintainability - Refactor the main `run` function to use these new helper functions - Update test cases to cover nested module scenarios - Improve error reporting for nested modules
This commit is contained in:
parent
c15c931a3f
commit
b22ed4512d
2 changed files with 69 additions and 32 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::{TSModuleDeclarationKind, TSModuleDeclarationName},
|
ast::{TSModuleDeclaration, TSModuleDeclarationKind, TSModuleDeclarationName},
|
||||||
AstKind,
|
AstKind,
|
||||||
};
|
};
|
||||||
use oxc_diagnostics::OxcDiagnostic;
|
use oxc_diagnostics::OxcDiagnostic;
|
||||||
|
|
@ -34,13 +34,27 @@ declare_oxc_lint!(
|
||||||
fix
|
fix
|
||||||
);
|
);
|
||||||
|
|
||||||
|
fn is_nest_module(node: &AstNode, ctx: &LintContext<'_>) -> bool {
|
||||||
|
ctx.nodes()
|
||||||
|
.parent_node(node.id())
|
||||||
|
.map_or(false, |parent_node| is_valid_module_node(parent_node))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_valid_module_node(node: &AstNode) -> bool {
|
||||||
|
matches!(node.kind(), AstKind::TSModuleDeclaration(module) if is_valid_module(module))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_valid_module(module: &TSModuleDeclaration) -> bool {
|
||||||
|
!module.id.is_string_literal()
|
||||||
|
&& matches!(module.id, TSModuleDeclarationName::Identifier(_))
|
||||||
|
&& module.kind == TSModuleDeclarationKind::Module
|
||||||
|
}
|
||||||
|
|
||||||
impl Rule for PreferNamespaceKeyword {
|
impl Rule for PreferNamespaceKeyword {
|
||||||
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
|
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
|
||||||
let AstKind::TSModuleDeclaration(module) = node.kind() else { return };
|
let AstKind::TSModuleDeclaration(module) = node.kind() else { return };
|
||||||
if module.id.is_string_literal()
|
|
||||||
|| !matches!(module.id, TSModuleDeclarationName::Identifier(_))
|
if !is_valid_module(module) || is_nest_module(node, ctx) {
|
||||||
|| module.kind != TSModuleDeclarationKind::Module
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,13 +88,15 @@ fn test() {
|
||||||
|
|
||||||
let fail = vec![
|
let fail = vec![
|
||||||
"module foo {}",
|
"module foo {}",
|
||||||
|
"module A.B {}",
|
||||||
"declare module foo {}",
|
"declare module foo {}",
|
||||||
"
|
"
|
||||||
declare module foo {
|
declare module foo {
|
||||||
declare module bar {}
|
declare module bar {}
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
"declare global {
|
"
|
||||||
|
declare global {
|
||||||
module foo {}
|
module foo {}
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
|
|
@ -88,6 +104,20 @@ fn test() {
|
||||||
|
|
||||||
let fix = vec![
|
let fix = vec![
|
||||||
("module foo {}", "namespace foo {}", None),
|
("module foo {}", "namespace foo {}", None),
|
||||||
|
("module A.B {}", "namespace A.B {}", None),
|
||||||
|
(
|
||||||
|
"
|
||||||
|
module A {
|
||||||
|
module B {}
|
||||||
|
}
|
||||||
|
",
|
||||||
|
"
|
||||||
|
namespace A {
|
||||||
|
namespace B {}
|
||||||
|
}
|
||||||
|
",
|
||||||
|
None,
|
||||||
|
),
|
||||||
("declare module foo {}", "declare namespace foo {}", None),
|
("declare module foo {}", "declare namespace foo {}", None),
|
||||||
(
|
(
|
||||||
"
|
"
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,13 @@ source: crates/oxc_linter/src/tester.rs
|
||||||
╰────
|
╰────
|
||||||
help: Replace `module` with `namespace`.
|
help: Replace `module` with `namespace`.
|
||||||
|
|
||||||
|
⚠ typescript-eslint(prefer-namespace-keyword): Use 'namespace' instead of 'module' to declare custom TypeScript modules.
|
||||||
|
╭─[prefer_namespace_keyword.tsx:1:1]
|
||||||
|
1 │ module A.B {}
|
||||||
|
· ─────────────
|
||||||
|
╰────
|
||||||
|
help: Replace `module` with `namespace`.
|
||||||
|
|
||||||
⚠ typescript-eslint(prefer-namespace-keyword): Use 'namespace' instead of 'module' to declare custom TypeScript modules.
|
⚠ typescript-eslint(prefer-namespace-keyword): Use 'namespace' instead of 'module' to declare custom TypeScript modules.
|
||||||
╭─[prefer_namespace_keyword.tsx:1:1]
|
╭─[prefer_namespace_keyword.tsx:1:1]
|
||||||
1 │ declare module foo {}
|
1 │ declare module foo {}
|
||||||
|
|
@ -16,7 +23,7 @@ source: crates/oxc_linter/src/tester.rs
|
||||||
help: Replace `module` with `namespace`.
|
help: Replace `module` with `namespace`.
|
||||||
|
|
||||||
⚠ typescript-eslint(prefer-namespace-keyword): Use 'namespace' instead of 'module' to declare custom TypeScript modules.
|
⚠ typescript-eslint(prefer-namespace-keyword): Use 'namespace' instead of 'module' to declare custom TypeScript modules.
|
||||||
╭─[prefer_namespace_keyword.tsx:2:4]
|
╭─[prefer_namespace_keyword.tsx:2:9]
|
||||||
1 │
|
1 │
|
||||||
2 │ ╭─▶ declare module foo {
|
2 │ ╭─▶ declare module foo {
|
||||||
3 │ │ declare module bar {}
|
3 │ │ declare module bar {}
|
||||||
|
|
@ -26,7 +33,7 @@ source: crates/oxc_linter/src/tester.rs
|
||||||
help: Replace `module` with `namespace`.
|
help: Replace `module` with `namespace`.
|
||||||
|
|
||||||
⚠ typescript-eslint(prefer-namespace-keyword): Use 'namespace' instead of 'module' to declare custom TypeScript modules.
|
⚠ typescript-eslint(prefer-namespace-keyword): Use 'namespace' instead of 'module' to declare custom TypeScript modules.
|
||||||
╭─[prefer_namespace_keyword.tsx:3:6]
|
╭─[prefer_namespace_keyword.tsx:3:11]
|
||||||
2 │ declare module foo {
|
2 │ declare module foo {
|
||||||
3 │ declare module bar {}
|
3 │ declare module bar {}
|
||||||
· ─────────────────────
|
· ─────────────────────
|
||||||
|
|
@ -35,10 +42,10 @@ source: crates/oxc_linter/src/tester.rs
|
||||||
help: Replace `module` with `namespace`.
|
help: Replace `module` with `namespace`.
|
||||||
|
|
||||||
⚠ typescript-eslint(prefer-namespace-keyword): Use 'namespace' instead of 'module' to declare custom TypeScript modules.
|
⚠ typescript-eslint(prefer-namespace-keyword): Use 'namespace' instead of 'module' to declare custom TypeScript modules.
|
||||||
╭─[prefer_namespace_keyword.tsx:2:13]
|
╭─[prefer_namespace_keyword.tsx:3:13]
|
||||||
1 │ declare global {
|
2 │ declare global {
|
||||||
2 │ module foo {}
|
3 │ module foo {}
|
||||||
· ─────────────
|
· ─────────────
|
||||||
3 │ }
|
4 │ }
|
||||||
╰────
|
╰────
|
||||||
help: Replace `module` with `namespace`.
|
help: Replace `module` with `namespace`.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue