From df628289fffea44914e2912dfb1a2dd7a0b294d8 Mon Sep 17 00:00:00 2001 From: Dunqing Date: Sat, 30 Mar 2024 12:57:43 +0800 Subject: [PATCH] fix(linter/import): ignore export declaration in no-duplicates (#2863) --- .../src/rules/import/no_duplicates.rs | 2 ++ .../oxc_semantic/src/module_record/builder.rs | 22 ++++++++++++++----- crates/oxc_syntax/src/module_record.rs | 10 +++++++-- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/crates/oxc_linter/src/rules/import/no_duplicates.rs b/crates/oxc_linter/src/rules/import/no_duplicates.rs index 370c9cdcd..2d3a2f4ac 100644 --- a/crates/oxc_linter/src/rules/import/no_duplicates.rs +++ b/crates/oxc_linter/src/rules/import/no_duplicates.rs @@ -67,6 +67,7 @@ impl Rule for NoDuplicates { let import_entries_maps = group .into_iter() .flat_map(|(_path, requested_modules)| requested_modules) + .filter(|requested_module| requested_module.is_import()) .into_group_map_by(|requested_module| { // We should early return if there is no type import if !has_type_import { @@ -136,6 +137,7 @@ fn test() { (r"import { type x } from './foo'; import y from './foo'", None), (r"import { type x } from './foo'; import { y } from './foo'", None), (r"import { type x } from './foo'; import type y from 'foo'", None), + (r"import { x } from './foo'; export { x } from './foo'", None), ]; let fail = vec![ diff --git a/crates/oxc_semantic/src/module_record/builder.rs b/crates/oxc_semantic/src/module_record/builder.rs index 454ba269a..6c6c93ea8 100644 --- a/crates/oxc_semantic/src/module_record/builder.rs +++ b/crates/oxc_semantic/src/module_record/builder.rs @@ -37,12 +37,12 @@ impl ModuleRecordBuilder { self.module_record } - fn add_module_request(&mut self, name_span: &NameSpan, is_type: bool) { + fn add_module_request(&mut self, name_span: &NameSpan, is_type: bool, is_import: bool) { self.module_record .requested_modules .entry(name_span.name().clone()) .or_default() - .push(RequestedModule::new(name_span.span(), is_type)); + .push(RequestedModule::new(name_span.span(), is_type, is_import)); } fn add_import_entry(&mut self, entry: ImportEntry) { @@ -202,7 +202,11 @@ impl ModuleRecordBuilder { }); } } - self.add_module_request(&module_request, decl.import_kind.is_type()); + self.add_module_request( + &module_request, + decl.import_kind.is_type(), + /* is_import */ true, + ); } fn visit_export_all_declaration(&mut self, decl: &ExportAllDeclaration) { @@ -226,7 +230,11 @@ impl ModuleRecordBuilder { if let Some(exported_name) = &decl.exported { self.add_export_binding(exported_name.name().to_compact_str(), exported_name.span()); } - self.add_module_request(&module_request, decl.export_kind.is_type()); + self.add_module_request( + &module_request, + decl.export_kind.is_type(), + /* is_import */ false, + ); } fn visit_export_default_declaration(&mut self, decl: &ExportDefaultDeclaration) { @@ -273,7 +281,11 @@ impl ModuleRecordBuilder { .map(|source| NameSpan::new(source.value.to_compact_str(), source.span)); if let Some(module_request) = &module_request { - self.add_module_request(module_request, decl.export_kind.is_type()); + self.add_module_request( + module_request, + decl.export_kind.is_type(), + /* is_import */ false, + ); } if let Some(decl) = &decl.declaration { diff --git a/crates/oxc_syntax/src/module_record.rs b/crates/oxc_syntax/src/module_record.rs index cb742c78f..2c6e29520 100644 --- a/crates/oxc_syntax/src/module_record.rs +++ b/crates/oxc_syntax/src/module_record.rs @@ -271,11 +271,13 @@ pub struct FunctionMeta { pub struct RequestedModule { span: Span, is_type: bool, + /// is_import is true if the module is requested by an import statement. + is_import: bool, } impl RequestedModule { - pub fn new(span: Span, is_type: bool) -> Self { - Self { span, is_type } + pub fn new(span: Span, is_type: bool, is_import: bool) -> Self { + Self { span, is_type, is_import } } pub fn span(&self) -> Span { @@ -285,6 +287,10 @@ impl RequestedModule { pub fn is_type(&self) -> bool { self.is_type } + + pub fn is_import(&self) -> bool { + self.is_import + } } #[cfg(test)]