use super::{
NativeAttribute, NativeAttributeExpression, NativeAttributeExpressionFailure,
NativeAttributeOperandError, NativeConditionKind, NativeTemplateComponent, Origin,
observe_conditional,
};
use crate::dialect::vue3::operand::conditional_parts;
use crate::embed::SourceError;
use crate::markup::{DirectiveName, DirectiveSyntax, VueDirectives};
use vize_l0::{SourceBlock, SourceRoot};
pub struct NativeAttributeHead<'o, 'a> {
selected: &'o NativeTemplateComponent<'a>,
attribute: NativeAttribute<'o, 'a>,
name: SourceBlock<'a>,
directive: Option<DirectiveName>,
condition: Option<NativeConditionKind>,
}
impl<'a> NativeTemplateComponent<'a> {
pub fn observe_attribute_head<'o>(
&'o self,
attribute: NativeAttribute<'o, 'a>,
) -> Result<NativeAttributeHead<'o, 'a>, NativeAttributeOperandError> {
Origin::check_original_header(self, &attribute)?;
let block = self.component().block();
let raw = attribute.surface().name.text;
let offset = block
.offset_of(raw)
.ok_or(NativeAttributeOperandError::Source(
SourceError::InvalidAuthoredSpan,
))?;
let name = SourceRoot::new(block.root_source())
.and_then(|root| root.block(raw, offset))
.map_err(|_| NativeAttributeOperandError::Source(SourceError::InvalidAuthoredSpan))?;
let directive = VueDirectives
.decompose(raw, offset)
.map_err(NativeAttributeOperandError::Directive)?;
let condition = conditional_parts(directive, name.end(), name.root_source());
Ok(NativeAttributeHead {
selected: self,
attribute,
name,
directive,
condition,
})
}
}
impl<'o, 'a> NativeAttributeHead<'o, 'a> {
#[must_use]
pub fn selected(&self) -> &'o NativeTemplateComponent<'a> {
self.selected
}
#[must_use]
pub fn attribute(&self) -> &NativeAttribute<'o, 'a> {
&self.attribute
}
#[must_use]
pub const fn name_block(&self) -> SourceBlock<'a> {
self.name
}
#[must_use]
pub const fn directive(&self) -> Option<DirectiveName> {
self.directive
}
#[must_use]
pub const fn condition_kind(&self) -> Option<NativeConditionKind> {
self.condition
}
pub fn observe_expression(
&self,
) -> Result<NativeAttributeExpression<'a>, NativeAttributeExpressionFailure<'a>> {
let kind = self
.condition
.ok_or(NativeAttributeOperandError::UnsupportedDirective)?;
observe_conditional(self.selected, self.attribute.reborrow(), kind)
}
}
#[cfg(test)]
mod tests;