#![forbid(unsafe_code)]
#![doc(html_root_url = "https://docs.rs/cyrs-ast/0.0.1")]
use cyrs_syntax::{SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken};
pub mod generated;
pub use generated::*;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MapProjectionItem {
syntax: SyntaxNode,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MapProjectionItemKind {
PropertySelector,
Literal,
AllPropertiesSpread,
AllBoundVarsSpread,
}
impl MapProjectionItem {
pub fn cast(syntax: SyntaxNode) -> Option<Self> {
(syntax.kind() == SyntaxKind::MAP_PROJECTION_ITEM).then_some(Self { syntax })
}
pub fn syntax(&self) -> &SyntaxNode {
&self.syntax
}
pub fn kind(&self) -> MapProjectionItemKind {
let mut toks = self
.syntax
.children_with_tokens()
.filter_map(SyntaxElement::into_token)
.filter(|t| !t.kind().is_trivia());
match toks.next().map(|t| t.kind()) {
Some(SyntaxKind::DOT) => match toks.next().map(|t| t.kind()) {
Some(SyntaxKind::STAR) => MapProjectionItemKind::AllPropertiesSpread,
_ => MapProjectionItemKind::PropertySelector,
},
Some(SyntaxKind::STAR) => MapProjectionItemKind::AllBoundVarsSpread,
_ => MapProjectionItemKind::Literal,
}
}
pub fn key_token(&self) -> Option<SyntaxToken> {
self.syntax
.children_with_tokens()
.filter_map(SyntaxElement::into_token)
.find(|t| matches!(t.kind(), SyntaxKind::IDENT | SyntaxKind::QUOTED_IDENT))
}
pub fn value(&self) -> Option<Expr> {
if matches!(self.kind(), MapProjectionItemKind::Literal) {
self.syntax.children().find_map(Expr::cast)
} else {
None
}
}
}
impl MapProjection {
pub fn items(&self) -> impl Iterator<Item = MapProjectionItem> + '_ {
self.syntax().children().filter_map(MapProjectionItem::cast)
}
}
pub trait AstNode: Sized {
fn can_cast(kind: SyntaxKind) -> bool;
fn cast(syntax: SyntaxNode) -> Option<Self>;
fn syntax(&self) -> &SyntaxNode;
}
#[cfg(test)]
mod tests {
use super::*;
use cyrs_syntax::parse;
#[test]
fn cast_source_file_from_generated() {
let parse = parse("");
let src = SourceFile::cast(parse.syntax()).expect("SOURCE_FILE root");
assert_eq!(src.syntax().kind(), SyntaxKind::SOURCE_FILE);
}
}