use serde::Deserialize;
use serde::Serialize;
use strum::Display;
use mago_interner::StringIdentifier;
use mago_span::HasSpan;
use mago_span::Span;
use crate::ast::expression::Expression;
use crate::sequence::Sequence;
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
#[serde(tag = "type", content = "value")]
pub enum CompositeString {
ShellExecute(ShellExecuteString),
Interpolated(InterpolatedString),
Document(DocumentString),
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
pub struct ShellExecuteString {
pub left_backtick: Span,
pub parts: Sequence<StringPart>,
pub right_backtick: Span,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
pub struct InterpolatedString {
pub left_double_quote: Span,
pub parts: Sequence<StringPart>,
pub right_double_quote: Span,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
#[serde(tag = "type", content = "value")]
pub enum DocumentKind {
Heredoc,
Nowdoc,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
#[serde(tag = "type", content = "value")]
pub enum DocumentIndentation {
None,
Whitespace(usize),
Tab(usize),
Mixed(usize, usize),
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
pub struct DocumentString {
pub open: Span,
pub kind: DocumentKind,
pub indentation: DocumentIndentation,
pub label: StringIdentifier,
pub parts: Sequence<StringPart>,
pub close: Span,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
#[serde(tag = "type", content = "value")]
pub enum StringPart {
Literal(LiteralStringPart),
Expression(Box<Expression>),
BracedExpression(BracedExpressionStringPart),
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
pub struct LiteralStringPart {
pub span: Span,
pub value: StringIdentifier,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
pub struct BracedExpressionStringPart {
pub left_brace: Span,
pub expression: Box<Expression>,
pub right_brace: Span,
}
impl HasSpan for CompositeString {
fn span(&self) -> Span {
match self {
CompositeString::ShellExecute(s) => s.span(),
CompositeString::Interpolated(i) => i.span(),
CompositeString::Document(d) => d.span(),
}
}
}
impl HasSpan for ShellExecuteString {
fn span(&self) -> Span {
self.left_backtick.join(self.right_backtick)
}
}
impl HasSpan for InterpolatedString {
fn span(&self) -> Span {
self.left_double_quote.join(self.right_double_quote)
}
}
impl HasSpan for DocumentString {
fn span(&self) -> Span {
self.open
}
}
impl HasSpan for StringPart {
fn span(&self) -> Span {
match self {
StringPart::Literal(l) => l.span(),
StringPart::Expression(e) => e.span(),
StringPart::BracedExpression(b) => b.span(),
}
}
}
impl HasSpan for LiteralStringPart {
fn span(&self) -> Span {
self.span
}
}
impl HasSpan for BracedExpressionStringPart {
fn span(&self) -> Span {
self.left_brace.join(self.right_brace)
}
}