pub(crate) use rowan::{GreenNode, GreenToken, NodeOrToken, SyntaxKind as RSyntaxKind};
macro_rules! quote_impl_ {
( @append $children:ident ) => {};
( @append $children:ident
$node:ident {
$($tree:tt)*
}
$($rest:tt)*
) => {
{
#[allow(unused_mut)]
let mut inner_children = ::std::vec::Vec::<$crate::ast::make::quote::NodeOrToken<
$crate::ast::make::quote::GreenNode,
$crate::ast::make::quote::GreenToken,
>>::new();
$crate::ast::make::quote::quote_impl!( @append inner_children
$($tree)*
);
let kind = <$crate::ast::$node as $crate::ast::AstNode>::kind();
let node = $crate::ast::make::quote::GreenNode::new($crate::ast::make::quote::RSyntaxKind(kind as u16), inner_children);
$children.push($crate::ast::make::quote::NodeOrToken::Node(node));
}
$crate::ast::make::quote::quote_impl!( @append $children $($rest)* );
};
( @append $children:ident
[ $token_kind:ident $token_text:expr ]
$($rest:tt)*
) => {
$children.push($crate::ast::make::quote::NodeOrToken::Token(
$crate::ast::make::quote::GreenToken::new(
$crate::ast::make::quote::RSyntaxKind($crate::SyntaxKind::$token_kind as u16),
&$token_text,
),
));
$crate::ast::make::quote::quote_impl!( @append $children $($rest)* );
};
( @append $children:ident
[$($token:tt)+]
$($rest:tt)*
) => {
$children.push($crate::ast::make::quote::NodeOrToken::Token(
$crate::ast::make::quote::GreenToken::new(
$crate::ast::make::quote::RSyntaxKind($crate::T![ $($token)+ ] as u16),
const { $crate::T![ $($token)+ ].text() },
),
));
$crate::ast::make::quote::quote_impl!( @append $children $($rest)* );
};
( @append $children:ident
$whitespace:literal
$($rest:tt)*
) => {
const { $crate::ast::make::quote::verify_only_whitespaces($whitespace) };
$children.push($crate::ast::make::quote::NodeOrToken::Token(
$crate::ast::make::quote::GreenToken::new(
$crate::ast::make::quote::RSyntaxKind($crate::SyntaxKind::WHITESPACE as u16),
$whitespace,
),
));
$crate::ast::make::quote::quote_impl!( @append $children $($rest)* );
};
( @append $children:ident
# $var:ident
$($rest:tt)*
) => {
$crate::ast::make::quote::ToNodeChild::append_node_child($var, &mut $children);
$crate::ast::make::quote::quote_impl!( @append $children $($rest)* );
};
( @append $children:ident
#( $($repetition:tt)+ )*
$($rest:tt)*
) => {
$crate::ast::make::quote::quote_impl!( @extract_pounded_in_repetition $children
[] [] $($repetition)*
);
$crate::ast::make::quote::quote_impl!( @append $children $($rest)* );
};
( @extract_pounded_in_repetition $children:ident
[ $($repetition:tt)* ] [ ]
) => {
::std::compile_error!("repetition in `ast::make::quote!()` without variable");
};
( @extract_pounded_in_repetition $children:ident
[ $($repetition:tt)* ] [ $repetition_var:ident ]
) => {
::std::iter::IntoIterator::into_iter($repetition_var).for_each(|$repetition_var| {
$crate::ast::make::quote::quote_impl!( @append $children $($repetition)* );
});
};
( @extract_pounded_in_repetition $children:ident
[ $($repetition:tt)* ] [ $repetition_var1:ident ] # $repetition_var2:ident $($rest:tt)*
) => {
::std::compile_error!("repetition in `ast::make::quote!()` with more than one variable");
};
( @extract_pounded_in_repetition $children:ident
[ $($repetition:tt)* ] [ ] # $repetition_var:ident $($rest:tt)*
) => {
$crate::ast::make::quote::quote_impl!( @extract_pounded_in_repetition $children
[ $($repetition)* # $repetition_var ] [ $repetition_var ] $($rest)*
);
};
( @extract_pounded_in_repetition $children:ident
[ $($repetition:tt)* ] [ $($repetition_var:tt)* ] $non_repetition_var:tt $($rest:tt)*
) => {
$crate::ast::make::quote::quote_impl!( @extract_pounded_in_repetition $children
[ $($repetition)* $non_repetition_var ] [ $($repetition_var)* ] $($rest)*
);
};
}
pub(crate) use quote_impl_ as quote_impl;
macro_rules! quote_ {
( $root:ident { $($tree:tt)* } ) => {{
#[allow(unused_mut)]
let mut root = ::std::vec::Vec::<$crate::ast::make::quote::NodeOrToken<
$crate::ast::make::quote::GreenNode,
$crate::ast::make::quote::GreenToken,
>>::with_capacity(1);
$crate::ast::make::quote::quote_impl!( @append root $root { $($tree)* } );
let root = root.into_iter().next().unwrap();
let root = $crate::SyntaxNode::new_root(root.into_node().unwrap());
<$crate::ast::$root as $crate::ast::AstNode>::cast(root).unwrap()
}};
}
pub(crate) use quote_ as quote;
use crate::AstNode;
pub(crate) trait ToNodeChild {
fn append_node_child(self, children: &mut Vec<NodeOrToken<GreenNode, GreenToken>>);
}
impl<N: AstNode> ToNodeChild for N {
fn append_node_child(self, children: &mut Vec<NodeOrToken<GreenNode, GreenToken>>) {
children.push((*self.syntax().clone_subtree().green()).to_owned().into());
}
}
impl<C: ToNodeChild> ToNodeChild for Option<C> {
fn append_node_child(self, children: &mut Vec<NodeOrToken<GreenNode, GreenToken>>) {
if let Some(child) = self {
child.append_node_child(children);
}
}
}
impl ToNodeChild for () {
fn append_node_child(self, _children: &mut Vec<NodeOrToken<GreenNode, GreenToken>>) {}
}
pub(crate) const fn verify_only_whitespaces(text: &str) {
let text = text.as_bytes();
let mut i = 0;
while i < text.len() {
if !text[i].is_ascii_whitespace() {
panic!("non-whitespace found in whitespace token");
}
i += 1;
}
}