use rowan::GreenNode;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Parse<T> {
green_node: GreenNode,
positioned_errors: Vec<crate::PositionedParseError>,
_ty: std::marker::PhantomData<fn() -> T>,
}
impl<T> Parse<T> {
pub(crate) fn new(
green_node: GreenNode,
positioned_errors: Vec<crate::PositionedParseError>,
) -> Self {
Parse {
green_node,
positioned_errors,
_ty: std::marker::PhantomData,
}
}
pub fn tree(&self) -> T
where
T: rowan::ast::AstNode<Language = crate::Lang>,
{
let syntax_node = rowan::SyntaxNode::new_root_mut(self.green_node.clone());
T::cast(syntax_node)
.expect("Parse<T> always holds a green node whose root kind matches T::can_cast")
}
pub fn positioned_errors(&self) -> &[crate::PositionedParseError] {
&self.positioned_errors
}
pub fn errors(&self) -> Vec<String> {
let text = self.green_node.to_string();
self.positioned_errors
.iter()
.map(|e| format!("{}: {}", e.start_position(&text), e.message))
.collect()
}
pub fn to_result(self) -> Result<T, crate::YamlError>
where
T: rowan::ast::AstNode<Language = crate::Lang>,
{
if let Some(first) = self.positioned_errors.first() {
let pos = first.start_position(&self.green_node.to_string());
Err(crate::YamlError::Parse {
message: first.message.clone(),
line: Some(pos.line),
column: Some(pos.column),
})
} else {
Ok(self.tree())
}
}
pub fn has_errors(&self) -> bool {
!self.positioned_errors.is_empty()
}
pub fn ok(&self) -> bool {
self.positioned_errors.is_empty()
}
}
impl Parse<crate::YamlFile> {
pub fn parse_yaml(text: &str) -> Self {
let parsed = crate::yaml::parse(text);
Parse::new(parsed.green_node, parsed.positioned_errors)
}
}