use crate::expression::{Expression, PropertyKey};
use crate::identifier::Identifier;
use crate::span::Spanned;
pub type Pattern = Spanned<PatternKind>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PatternKind {
Identifier(Identifier),
Array {
elements: Vec<Option<Pattern>>,
},
Object {
properties: Vec<ObjectPatternMember>,
},
Rest {
argument: Box<Pattern>,
},
Assignment {
left: Box<Pattern>,
right: Box<Expression>,
},
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ObjectPatternMember {
Property {
key: PropertyKey,
value: Pattern,
computed: bool,
shorthand: bool,
},
Rest {
argument: Pattern,
},
}
impl std::fmt::Display for PatternKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Identifier(name) => write!(f, "{name}"),
Self::Array { elements } => write_array_pattern(f, elements),
Self::Object { properties } => write_object_pattern(f, properties),
Self::Rest { argument } => write!(f, "...{argument}"),
Self::Assignment { left, right } => write!(f, "{left} = {right}"),
}
}
}
fn write_array_pattern(
f: &mut std::fmt::Formatter<'_>,
elements: &[Option<Pattern>],
) -> std::fmt::Result {
let body = elements
.iter()
.map(|element| {
element
.as_ref()
.map_or_else(String::new, |pat| format!("{pat}"))
})
.collect::<Vec<_>>()
.join(", ");
write!(f, "[{body}]")
}
fn write_object_pattern(
f: &mut std::fmt::Formatter<'_>,
properties: &[ObjectPatternMember],
) -> std::fmt::Result {
let body = properties
.iter()
.map(|member| format!("{member}"))
.collect::<Vec<_>>()
.join(", ");
write!(f, "{{{body}}}")
}
impl std::fmt::Display for ObjectPatternMember {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Property {
key,
value,
computed,
shorthand,
} => write_object_pattern_property(f, key, value, *computed, *shorthand),
Self::Rest { argument } => write!(f, "...{argument}"),
}
}
}
fn write_object_pattern_property(
f: &mut std::fmt::Formatter<'_>,
key: &PropertyKey,
value: &Pattern,
computed: bool,
shorthand: bool,
) -> std::fmt::Result {
if shorthand {
write!(f, "{value}")
} else if computed {
write!(f, "[{key}]: {value}")
} else {
write!(f, "{key}: {value}")
}
}