use std::ops::ControlFlow;
use crate::{
expression::Identifier,
visitor::{VisitWith, Visitor, VisitorMut},
};
use boa_interner::Sym;
use super::ModuleSpecifier;
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ImportKind {
DefaultOrUnnamed,
Namespaced {
binding: Identifier,
},
Named {
names: Box<[ImportSpecifier]>,
},
}
impl VisitWith for ImportKind {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
match self {
Self::DefaultOrUnnamed => ControlFlow::Continue(()),
Self::Namespaced { binding } => visitor.visit_identifier(binding),
Self::Named { names } => {
for name in &**names {
visitor.visit_import_specifier(name)?;
}
ControlFlow::Continue(())
}
}
}
fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
match self {
Self::DefaultOrUnnamed => ControlFlow::Continue(()),
Self::Namespaced { binding } => visitor.visit_identifier_mut(binding),
Self::Named { names } => {
for name in &mut **names {
visitor.visit_import_specifier_mut(name)?;
}
ControlFlow::Continue(())
}
}
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ImportDeclaration {
default: Option<Identifier>,
kind: ImportKind,
specifier: ModuleSpecifier,
}
impl ImportDeclaration {
#[inline]
#[must_use]
pub const fn new(
default: Option<Identifier>,
kind: ImportKind,
specifier: ModuleSpecifier,
) -> Self {
Self {
default,
kind,
specifier,
}
}
#[inline]
#[must_use]
pub const fn default(&self) -> Option<Identifier> {
self.default
}
#[inline]
#[must_use]
pub const fn specifier(&self) -> ModuleSpecifier {
self.specifier
}
#[inline]
#[must_use]
pub const fn kind(&self) -> &ImportKind {
&self.kind
}
}
impl VisitWith for ImportDeclaration {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
if let Some(default) = &self.default {
visitor.visit_identifier(default)?;
}
visitor.visit_import_kind(&self.kind)?;
visitor.visit_module_specifier(&self.specifier)
}
fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
if let Some(default) = &mut self.default {
visitor.visit_identifier_mut(default)?;
}
visitor.visit_import_kind_mut(&mut self.kind)?;
visitor.visit_module_specifier_mut(&mut self.specifier)
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ImportSpecifier {
binding: Identifier,
export_name: Sym,
}
impl ImportSpecifier {
#[inline]
#[must_use]
pub const fn new(binding: Identifier, export_name: Sym) -> Self {
Self {
binding,
export_name,
}
}
#[inline]
#[must_use]
pub const fn binding(self) -> Identifier {
self.binding
}
#[inline]
#[must_use]
pub const fn export_name(self) -> Sym {
self.export_name
}
}
impl VisitWith for ImportSpecifier {
fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: Visitor<'a>,
{
visitor.visit_identifier(&self.binding)?;
visitor.visit_sym(&self.export_name)
}
fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
where
V: VisitorMut<'a>,
{
visitor.visit_identifier_mut(&mut self.binding)?;
visitor.visit_sym_mut(&mut self.export_name)
}
}
#[derive(Debug, Clone, Copy)]
pub enum ImportName {
Namespace,
Name(Sym),
}
#[derive(Debug, Clone, Copy)]
pub struct ImportEntry {
module_request: Sym,
import_name: ImportName,
local_name: Identifier,
}
impl ImportEntry {
#[must_use]
pub const fn new(module_request: Sym, import_name: ImportName, local_name: Identifier) -> Self {
Self {
module_request,
import_name,
local_name,
}
}
#[must_use]
pub const fn module_request(&self) -> Sym {
self.module_request
}
#[must_use]
pub const fn import_name(&self) -> ImportName {
self.import_name
}
#[must_use]
pub const fn local_name(&self) -> Identifier {
self.local_name
}
}