Skip to content

Commit

Permalink
feat(syntax): add statement span to ImportEntry and ExportEntry (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Dec 2, 2024
1 parent a784a82 commit 33e5a49
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 36 deletions.
94 changes: 65 additions & 29 deletions crates/oxc_parser/src/module_record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ impl<'a> ModuleRecordBuilder<'a> {
errors
}

fn add_module_request(&mut self, name_span: &NameSpan<'a>, is_type: bool, is_import: bool) {
fn add_module_request(&mut self, name: &Atom<'a>, requested_module: RequestedModule) {
self.module_record
.requested_modules
.entry(name_span.name.clone())
.entry(name.clone())
.or_insert_with(|| oxc_allocator::Vec::new_in(self.allocator))
.push(RequestedModule::new(name_span.span, is_type, is_import));
.push(requested_module);
}

fn add_import_entry(&mut self, entry: ImportEntry<'a>) {
Expand Down Expand Up @@ -137,6 +137,8 @@ impl<'a> ModuleRecordBuilder<'a> {
// to indirectExportEntries.
ImportImportName::Name(_) | ImportImportName::Default(_) => {
let export_entry = ExportEntry {
statement_span: ie.statement_span,
span: ee.span,
module_request: Some(ie.module_request.clone()),
import_name: match &ie.import_name {
ImportImportName::Name(name) => {
Expand All @@ -151,8 +153,7 @@ impl<'a> ModuleRecordBuilder<'a> {
ImportImportName::NamespaceObject => unreachable!(),
},
export_name: ee.export_name.clone(),
span: ee.span,
..ExportEntry::default()
local_name: ExportLocalName::default(),
};
self.append_indirect_export_entry(export_entry);
}
Expand Down Expand Up @@ -218,6 +219,7 @@ impl<'a> ModuleRecordBuilder<'a> {
),
};
self.add_import_entry(ImportEntry {
statement_span: decl.span,
module_request: module_request.clone(),
import_name,
local_name,
Expand All @@ -226,15 +228,21 @@ impl<'a> ModuleRecordBuilder<'a> {
}
}
self.add_module_request(
&module_request,
decl.import_kind.is_type(),
/* is_import */ true,
&module_request.name,
RequestedModule {
statement_span: decl.span,
span: module_request.span,
is_type: decl.import_kind.is_type(),
is_import: true,
},
);
}

fn visit_export_all_declaration(&mut self, decl: &ExportAllDeclaration<'a>) {
let module_request = NameSpan::new(decl.source.value.clone(), decl.source.span);
let export_entry = ExportEntry {
statement_span: decl.span,
span: decl.span,
module_request: Some(module_request.clone()),
import_name: decl
.exported
Expand All @@ -243,17 +251,20 @@ impl<'a> ModuleRecordBuilder<'a> {
export_name: decl.exported.as_ref().map_or(ExportExportName::Null, |exported_name| {
ExportExportName::Name(NameSpan::new(exported_name.name(), exported_name.span()))
}),
span: decl.span,
..ExportEntry::default()
local_name: ExportLocalName::default(),
};
self.add_export_entry(export_entry);
if let Some(exported_name) = &decl.exported {
self.add_export_binding(exported_name.name(), exported_name.span());
}
self.add_module_request(
&module_request,
decl.export_kind.is_type(),
/* is_import */ false,
&module_request.name,
RequestedModule {
statement_span: decl.span,
span: module_request.span,
is_type: decl.export_kind.is_type(),
is_import: false,
},
);
}

Expand Down Expand Up @@ -281,10 +292,12 @@ impl<'a> ModuleRecordBuilder<'a> {
_ => ExportLocalName::Null,
};
let export_entry = ExportEntry {
statement_span: decl.span,
span: decl.declaration.span(),
module_request: None,
import_name: ExportImportName::default(),
export_name: ExportExportName::Default(exported_name.span()),
local_name,
span: decl.declaration.span(),
..ExportEntry::default()
};
self.add_export_entry(export_entry);
}
Expand All @@ -303,20 +316,25 @@ impl<'a> ModuleRecordBuilder<'a> {

if let Some(module_request) = &module_request {
self.add_module_request(
module_request,
decl.export_kind.is_type(),
/* is_import */ false,
&module_request.name,
RequestedModule {
statement_span: decl.span,
span: module_request.span,
is_type: decl.export_kind.is_type(),
is_import: false,
},
);
}

if let Some(decl) = &decl.declaration {
decl.bound_names(&mut |ident| {
if let Some(d) = &decl.declaration {
d.bound_names(&mut |ident| {
let export_name =
ExportExportName::Name(NameSpan::new(ident.name.clone(), ident.span));
let local_name =
ExportLocalName::Name(NameSpan::new(ident.name.clone(), ident.span));
let export_entry = ExportEntry {
span: decl.span(),
statement_span: decl.span,
span: d.span(),
module_request: module_request.clone(),
import_name: ExportImportName::Null,
export_name,
Expand Down Expand Up @@ -349,6 +367,7 @@ impl<'a> ModuleRecordBuilder<'a> {
))
};
let export_entry = ExportEntry {
statement_span: decl.span,
span: specifier.span,
module_request: module_request.clone(),
import_name,
Expand Down Expand Up @@ -383,6 +402,7 @@ mod module_record_tests {
let allocator = Allocator::default();
let module_record = build(&allocator, "import v from 'mod'");
let import_entry = ImportEntry {
statement_span: Span::new(0, 19),
module_request: NameSpan::new("mod".into(), Span::new(14, 19)),
import_name: ImportImportName::Default(Span::new(7, 8)),
local_name: NameSpan::new("v".into(), Span::new(7, 8)),
Expand All @@ -397,6 +417,7 @@ mod module_record_tests {
let allocator = Allocator::default();
let module_record = build(&allocator, "import * as ns from 'mod'");
let import_entry = ImportEntry {
statement_span: Span::new(0, 25),
module_request: NameSpan::new("mod".into(), Span::new(20, 25)),
import_name: ImportImportName::NamespaceObject,
local_name: NameSpan::new("ns".into(), Span::new(12, 14)),
Expand All @@ -411,6 +432,7 @@ mod module_record_tests {
let allocator = Allocator::default();
let module_record = build(&allocator, "import { x } from 'mod'");
let import_entry = ImportEntry {
statement_span: Span::new(0, 23),
module_request: NameSpan::new("mod".into(), Span::new(18, 23)),
import_name: ImportImportName::Name(NameSpan::new("x".into(), Span::new(9, 10))),
local_name: NameSpan::new("x".into(), Span::new(9, 10)),
Expand All @@ -425,6 +447,7 @@ mod module_record_tests {
let allocator = Allocator::default();
let module_record = build(&allocator, "import { x as v } from 'mod'");
let import_entry = ImportEntry {
statement_span: Span::new(0, 28),
module_request: NameSpan::new("mod".into(), Span::new(23, 28)),
import_name: ImportImportName::Name(NameSpan::new("x".into(), Span::new(9, 10))),
local_name: NameSpan::new("v".into(), Span::new(14, 15)),
Expand All @@ -451,6 +474,7 @@ mod module_record_tests {
let allocator = Allocator::default();
let module_record = build(&allocator, "export * from 'mod'");
let export_entry = ExportEntry {
statement_span: Span::new(0, 19),
module_request: Some(NameSpan::new("mod".into(), Span::new(14, 19))),
import_name: ExportImportName::AllButDefault,
span: Span::new(0, 19),
Expand All @@ -467,6 +491,7 @@ mod module_record_tests {
let allocator = Allocator::default();
let module_record = build(&allocator, "export * as ns from 'mod'");
let export_entry = ExportEntry {
statement_span: Span::new(0, 25),
module_request: Some(NameSpan::new("mod".into(), Span::new(20, 25))),
import_name: ExportImportName::All,
export_name: ExportExportName::Name(NameSpan::new("ns".into(), Span::new(12, 14))),
Expand All @@ -484,9 +509,10 @@ mod module_record_tests {
let allocator = Allocator::default();
let module_record = build(&allocator, "export { x }");
let export_entry = ExportEntry {
statement_span: Span::new(0, 12),
span: Span::new(9, 10),
export_name: ExportExportName::Name(NameSpan::new("x".into(), Span::new(9, 10))),
local_name: ExportLocalName::Name(NameSpan::new("x".into(), Span::new(9, 10))),
span: Span::new(9, 10),
..ExportEntry::default()
};
assert_eq!(module_record.local_export_entries.len(), 1);
Expand All @@ -500,9 +526,10 @@ mod module_record_tests {
let allocator = Allocator::default();
let module_record = build(&allocator, "export { x as v }");
let export_entry = ExportEntry {
statement_span: Span::new(0, 17),
span: Span::new(9, 15),
export_name: ExportExportName::Name(NameSpan::new("v".into(), Span::new(14, 15))),
local_name: ExportLocalName::Name(NameSpan::new("x".into(), Span::new(9, 10))),
span: Span::new(9, 15),
..ExportEntry::default()
};
assert_eq!(module_record.local_export_entries.len(), 1);
Expand All @@ -516,6 +543,7 @@ mod module_record_tests {
let allocator = Allocator::default();
let module_record = build(&allocator, "export { x } from 'mod'");
let export_entry = ExportEntry {
statement_span: Span::new(0, 23),
module_request: Some(NameSpan::new("mod".into(), Span::new(18, 23))),
export_name: ExportExportName::Name(NameSpan::new("x".into(), Span::new(9, 10))),
import_name: ExportImportName::Name(NameSpan::new("x".into(), Span::new(9, 10))),
Expand All @@ -533,6 +561,7 @@ mod module_record_tests {
let allocator = Allocator::default();
let module_record = build(&allocator, "export { x as v } from 'mod'");
let export_entry = ExportEntry {
statement_span: Span::new(0, 28),
module_request: Some(NameSpan::new("mod".into(), Span::new(23, 28))),
export_name: ExportExportName::Name(NameSpan::new("v".into(), Span::new(14, 15))),
import_name: ExportImportName::Name(NameSpan::new("x".into(), Span::new(9, 10))),
Expand All @@ -549,6 +578,7 @@ mod module_record_tests {
let allocator = Allocator::default();
let module_record = build(&allocator, "export var v");
let export_entry = ExportEntry {
statement_span: Span::new(0, 12),
export_name: ExportExportName::Name(NameSpan::new("v".into(), Span::new(11, 12))),
local_name: ExportLocalName::Name(NameSpan::new("v".into(), Span::new(11, 12))),
span: Span::new(7, 12),
Expand All @@ -564,9 +594,10 @@ mod module_record_tests {
let allocator = Allocator::default();
let module_record = build(&allocator, "export default function f() {}");
let export_entry = ExportEntry {
statement_span: Span::new(0, 30),
span: Span::new(15, 30),
export_name: ExportExportName::Default(Span::new(7, 14)),
local_name: ExportLocalName::Name(NameSpan::new("f".into(), Span::new(24, 25))),
span: Span::new(15, 30),
..ExportEntry::default()
};
assert_eq!(module_record.local_export_entries.len(), 1);
Expand All @@ -579,9 +610,10 @@ mod module_record_tests {
let allocator = Allocator::default();
let module_record = build(&allocator, "export default function() {}");
let export_entry = ExportEntry {
statement_span: Span::new(0, 28),
span: Span::new(15, 28),
export_name: ExportExportName::Default(Span::new(7, 14)),
local_name: ExportLocalName::Null,
span: Span::new(15, 28),
..ExportEntry::default()
};
assert_eq!(module_record.local_export_entries.len(), 1);
Expand All @@ -594,9 +626,10 @@ mod module_record_tests {
let allocator = Allocator::default();
let module_record = build(&allocator, "export default 42");
let export_entry = ExportEntry {
statement_span: Span::new(0, 17),
span: Span::new(15, 17),
export_name: ExportExportName::Default(Span::new(7, 14)),
local_name: ExportLocalName::Null,
span: Span::new(15, 17),
..ExportEntry::default()
};
assert_eq!(module_record.local_export_entries.len(), 1);
Expand All @@ -608,9 +641,10 @@ mod module_record_tests {
let allocator = Allocator::default();
let module_record = build(&allocator, "export { default }");
let export_entry = ExportEntry {
statement_span: Span::new(0, 18),
span: Span::new(9, 16),
export_name: ExportExportName::Name(NameSpan::new("default".into(), Span::new(9, 16))),
local_name: ExportLocalName::Name(NameSpan::new("default".into(), Span::new(9, 16))),
span: Span::new(9, 16),
..ExportEntry::default()
};
assert_eq!(module_record.local_export_entries.len(), 1);
Expand All @@ -626,8 +660,9 @@ mod module_record_tests {
assert_eq!(
module_record.indirect_export_entries[0],
ExportEntry {
module_request: Some(NameSpan::new("mod".into(), Span::new(18, 23))),
statement_span: Span::new(0, 24),
span: Span::new(33, 34),
module_request: Some(NameSpan::new("mod".into(), Span::new(18, 23))),
import_name: ExportImportName::Name(NameSpan::new("x".into(), Span::new(9, 10))),
export_name: ExportExportName::Name(NameSpan::new("x".into(), Span::new(33, 34))),
local_name: ExportLocalName::Null,
Expand All @@ -636,8 +671,9 @@ mod module_record_tests {
assert_eq!(
module_record.indirect_export_entries[1],
ExportEntry {
module_request: Some(NameSpan::new("mod".into(), Span::new(57, 62))),
statement_span: Span::new(37, 63),
span: Span::new(37, 63),
module_request: Some(NameSpan::new("mod".into(), Span::new(57, 62))),
import_name: ExportImportName::All,
export_name: ExportExportName::Name(NameSpan::new("ns".into(), Span::new(49, 51))),
local_name: ExportLocalName::Null,
Expand Down
17 changes: 10 additions & 7 deletions crates/oxc_syntax/src/module_record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub struct ModuleRecord<'a> {
/// import ImportClause FromClause
/// import ModuleSpecifier
/// export ExportFromClause FromClause
///
/// Keyed by ModuleSpecifier, valued by all node occurrences
pub requested_modules: FxHashMap<Atom<'a>, Vec<'a, RequestedModule>>,

Expand Down Expand Up @@ -106,6 +107,9 @@ impl<'a> NameSpan<'a> {
/// ```
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ImportEntry<'a> {
/// Span of the import statement.
pub statement_span: Span,

/// String value of the ModuleSpecifier of the ImportDeclaration.
///
/// ## Examples
Expand Down Expand Up @@ -203,6 +207,9 @@ impl ImportImportName<'_> {
/// ```
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct ExportEntry<'a> {
/// Span of the import statement.
pub statement_span: Span,

/// Span for the entire export entry
pub span: Span,

Expand Down Expand Up @@ -330,6 +337,9 @@ impl<'a> ExportLocalName<'a> {
/// RequestedModule
#[derive(Debug, Clone, Copy)]
pub struct RequestedModule {
/// Span of the import statement.
pub statement_span: Span,

/// Span
pub span: Span,

Expand All @@ -347,13 +357,6 @@ pub struct RequestedModule {
pub is_import: bool,
}

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

#[cfg(test)]
mod test {
use oxc_span::Span;
Expand Down

0 comments on commit 33e5a49

Please sign in to comment.