Skip to content

Commit

Permalink
refactor(semantic): distinguish whether requested_modules is type imp…
Browse files Browse the repository at this point in the history
…orts/exports (#2848)
  • Loading branch information
Dunqing authored Mar 29, 2024
1 parent 6177c2f commit 1b5e544
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 25 deletions.
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/import/no_cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ impl Rule for NoCycle {
let mut state = State::default();
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].span();
let help = stack
.iter()
.map(|(specifier, path)| {
Expand Down
27 changes: 15 additions & 12 deletions crates/oxc_linter/src/rules/import/no_duplicates.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use itertools::Itertools;
use oxc_diagnostics::miette::{miette, LabeledSpan, Severity};
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use oxc_syntax::module_record::ImportImportName;
use oxc_syntax::module_record::{ImportImportName, RequestedModule};

use crate::{context::LintContext, rule::Rule};

Expand Down Expand Up @@ -36,20 +35,22 @@ impl Rule for NoDuplicates {
let groups = module_record
.requested_modules
.iter()
.map(|(source, spans)| {
.map(|(source, requested_modules)| {
let resolved_absolute_path = module_record.loaded_modules.get(source).map_or_else(
|| source.to_string(),
|module| module.resolved_absolute_path.to_string_lossy().to_string(),
);
(resolved_absolute_path, spans)
(resolved_absolute_path, requested_modules)
})
.group_by(|r| r.0.clone());

let check_duplicates = |spans: Option<&Vec<&Span>>| {
if let Some(spans) = spans {
if spans.len() > 1 {
let labels =
spans.iter().map(|span| LabeledSpan::underline(**span)).collect::<Vec<_>>();
let check_duplicates = |requested_modules: Option<&Vec<&RequestedModule>>| {
if let Some(requested_modules) = requested_modules {
if requested_modules.len() > 1 {
let labels = requested_modules
.iter()
.map(|requested_module| LabeledSpan::underline(requested_module.span()))
.collect::<Vec<_>>();
ctx.diagnostic(miette!(
severity = Severity::Warning,
labels = labels,
Expand All @@ -63,14 +64,16 @@ impl Rule for NoDuplicates {
let has_type_import = module_record.import_entries.iter().any(|entry| entry.is_type);
// When prefer_inline is false, 0 is value, 1 is type named, 2 is type default or type namespace
// When prefer_inline is true, 0 is value and type named, 2 is type default or type namespace
let import_entries_maps =
group.into_iter().flat_map(|(_path, spans)| spans).into_group_map_by(|span| {
let import_entries_maps = group
.into_iter()
.flat_map(|(_path, requested_modules)| requested_modules)
.into_group_map_by(|requested_module| {
// We should early return if there is no type import
if !has_type_import {
return 0;
};
for entry in &module_record.import_entries {
if entry.module_request.span() != **span {
if entry.module_request.span() != requested_module.span() {
continue;
}

Expand Down
6 changes: 3 additions & 3 deletions crates/oxc_linter/src/rules/import/no_self_import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ impl Rule for NoSelfImport {
fn run_once(&self, ctx: &LintContext<'_>) {
let module_record = ctx.semantic().module_record();
let resolved_absolute_path = &module_record.resolved_absolute_path;
for (request, spans) in &module_record.requested_modules {
for (request, requested_modules) in &module_record.requested_modules {
let Some(remote_module_record_ref) = module_record.loaded_modules.get(request) else {
continue;
};
if remote_module_record_ref.value().resolved_absolute_path == *resolved_absolute_path {
for span in spans {
ctx.diagnostic(NoSelfImportDiagnostic(*span));
for requested_module in requested_modules {
ctx.diagnostic(NoSelfImportDiagnostic(requested_module.span()));
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions crates/oxc_linter/src/rules/import/no_unresolved.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl Rule for NoUnresolved {
fn run_once(&self, ctx: &LintContext<'_>) {
let module_record = ctx.semantic().module_record();

for (specifier, spans) in &module_record.requested_modules {
for (specifier, requested_modules) in &module_record.requested_modules {
if module_record.loaded_modules.contains_key(specifier) {
continue;
}
Expand All @@ -53,8 +53,9 @@ impl Rule for NoUnresolved {
{
continue;
}
for span in spans {
ctx.diagnostic(NoUnresolvedDiagnostic(*span));

for requested_module in requested_modules {
ctx.diagnostic(NoUnresolvedDiagnostic(requested_module.span()));
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions crates/oxc_semantic/src/module_record/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ impl ModuleRecordBuilder {
self.module_record
}

fn add_module_request(&mut self, name_span: &NameSpan) {
fn add_module_request(&mut self, name_span: &NameSpan, is_type: bool) {
self.module_record
.requested_modules
.entry(name_span.name().clone())
.or_default()
.push(name_span.span());
.push(RequestedModule::new(name_span.span(), is_type));
}

fn add_import_entry(&mut self, entry: ImportEntry) {
Expand Down Expand Up @@ -202,7 +202,7 @@ impl ModuleRecordBuilder {
});
}
}
self.add_module_request(&module_request);
self.add_module_request(&module_request, decl.import_kind.is_type());
}

fn visit_export_all_declaration(&mut self, decl: &ExportAllDeclaration) {
Expand All @@ -226,7 +226,7 @@ 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);
self.add_module_request(&module_request, decl.export_kind.is_type());
}

fn visit_export_default_declaration(&mut self, decl: &ExportDefaultDeclaration) {
Expand Down Expand Up @@ -273,7 +273,7 @@ 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);
self.add_module_request(module_request, decl.export_kind.is_type());
}

if let Some(decl) = &decl.declaration {
Expand Down
22 changes: 21 additions & 1 deletion crates/oxc_syntax/src/module_record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub struct ModuleRecord {
/// import ModuleSpecifier
/// export ExportFromClause FromClause
/// Keyed by ModuleSpecifier, valued by all node occurrences
pub requested_modules: IndexMap<CompactStr, Vec<Span>, BuildHasherDefault<FxHasher>>,
pub requested_modules: IndexMap<CompactStr, Vec<RequestedModule>, BuildHasherDefault<FxHasher>>,

/// `[[LoadedModules]]`
///
Expand Down Expand Up @@ -267,6 +267,26 @@ pub struct FunctionMeta {
pub deprecated: bool,
}

#[derive(Debug, Clone)]
pub struct RequestedModule {
span: Span,
is_type: bool,
}

impl RequestedModule {
pub fn new(span: Span, is_type: bool) -> Self {
Self { span, is_type }
}

pub fn span(&self) -> Span {
self.span
}

pub fn is_type(&self) -> bool {
self.is_type
}
}

#[cfg(test)]
mod test {
use super::{ExportExportName, ExportLocalName, ImportImportName, NameSpan};
Expand Down

0 comments on commit 1b5e544

Please sign in to comment.