use crate::parse::google::kind::GoogleSectionKind;
use crate::syntax::{SyntaxKind, SyntaxNode, SyntaxToken};
macro_rules! define_node {
($name:ident, $kind:ident) => {
#[doc = concat!("Typed wrapper for `", stringify!($kind), "` syntax nodes.")]
#[derive(Debug)]
pub struct $name<'a>(pub(crate) &'a SyntaxNode);
impl<'a> $name<'a> {
pub fn cast(node: &'a SyntaxNode) -> Option<Self> {
(node.kind() == SyntaxKind::$kind).then(|| Self(node))
}
pub fn syntax(&self) -> &'a SyntaxNode {
self.0
}
}
};
}
define_node!(GoogleDocstring, GOOGLE_DOCSTRING);
impl<'a> GoogleDocstring<'a> {
pub fn summary(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::SUMMARY)
}
pub fn extended_summary(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::EXTENDED_SUMMARY)
}
pub fn sections(&self) -> impl Iterator<Item = GoogleSection<'a>> {
self.0.nodes(SyntaxKind::GOOGLE_SECTION).filter_map(GoogleSection::cast)
}
pub fn stray_lines(&self) -> impl Iterator<Item = &'a SyntaxToken> {
self.0.tokens(SyntaxKind::STRAY_LINE)
}
}
define_node!(GoogleSection, GOOGLE_SECTION);
impl<'a> GoogleSection<'a> {
pub fn header(&self) -> GoogleSectionHeader<'a> {
GoogleSectionHeader::cast(
self.0
.find_node(SyntaxKind::GOOGLE_SECTION_HEADER)
.expect("GOOGLE_SECTION must have a GOOGLE_SECTION_HEADER child"),
)
.unwrap()
}
pub fn section_kind(&self, source: &str) -> GoogleSectionKind {
let name_text = self.header().name().text(source);
GoogleSectionKind::from_name(&name_text.to_ascii_lowercase())
}
pub fn args(&self) -> impl Iterator<Item = GoogleArg<'a>> {
self.0.nodes(SyntaxKind::GOOGLE_ARG).filter_map(GoogleArg::cast)
}
pub fn returns(&self) -> Option<GoogleReturn<'a>> {
self.0
.find_node(SyntaxKind::GOOGLE_RETURNS)
.and_then(GoogleReturn::cast)
}
pub fn yields(&self) -> Option<GoogleYield<'a>> {
self.0.find_node(SyntaxKind::GOOGLE_YIELDS).and_then(GoogleYield::cast)
}
pub fn exceptions(&self) -> impl Iterator<Item = GoogleException<'a>> {
self.0
.nodes(SyntaxKind::GOOGLE_EXCEPTION)
.filter_map(GoogleException::cast)
}
pub fn warnings(&self) -> impl Iterator<Item = GoogleWarning<'a>> {
self.0.nodes(SyntaxKind::GOOGLE_WARNING).filter_map(GoogleWarning::cast)
}
pub fn see_also_items(&self) -> impl Iterator<Item = GoogleSeeAlsoItem<'a>> {
self.0
.nodes(SyntaxKind::GOOGLE_SEE_ALSO_ITEM)
.filter_map(GoogleSeeAlsoItem::cast)
}
pub fn attributes(&self) -> impl Iterator<Item = GoogleAttribute<'a>> {
self.0
.nodes(SyntaxKind::GOOGLE_ATTRIBUTE)
.filter_map(GoogleAttribute::cast)
}
pub fn methods(&self) -> impl Iterator<Item = GoogleMethod<'a>> {
self.0.nodes(SyntaxKind::GOOGLE_METHOD).filter_map(GoogleMethod::cast)
}
pub fn body_text(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::BODY_TEXT)
}
}
define_node!(GoogleSectionHeader, GOOGLE_SECTION_HEADER);
impl<'a> GoogleSectionHeader<'a> {
pub fn name(&self) -> &'a SyntaxToken {
self.0.required_token(SyntaxKind::NAME)
}
pub fn colon(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::COLON)
}
}
define_node!(GoogleArg, GOOGLE_ARG);
impl<'a> GoogleArg<'a> {
pub fn name(&self) -> &'a SyntaxToken {
self.0.required_token(SyntaxKind::NAME)
}
pub fn open_bracket(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::OPEN_BRACKET)
}
pub fn r#type(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::TYPE)
}
pub fn close_bracket(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::CLOSE_BRACKET)
}
pub fn colon(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::COLON)
}
pub fn description(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::DESCRIPTION)
}
pub fn optional(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::OPTIONAL)
}
}
define_node!(GoogleReturn, GOOGLE_RETURNS);
impl<'a> GoogleReturn<'a> {
pub fn return_type(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::RETURN_TYPE)
}
pub fn colon(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::COLON)
}
pub fn description(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::DESCRIPTION)
}
}
define_node!(GoogleYield, GOOGLE_YIELDS);
impl<'a> GoogleYield<'a> {
pub fn return_type(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::RETURN_TYPE)
}
pub fn colon(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::COLON)
}
pub fn description(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::DESCRIPTION)
}
}
define_node!(GoogleException, GOOGLE_EXCEPTION);
impl<'a> GoogleException<'a> {
pub fn r#type(&self) -> &'a SyntaxToken {
self.0.required_token(SyntaxKind::TYPE)
}
pub fn colon(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::COLON)
}
pub fn description(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::DESCRIPTION)
}
}
define_node!(GoogleWarning, GOOGLE_WARNING);
impl<'a> GoogleWarning<'a> {
pub fn warning_type(&self) -> &'a SyntaxToken {
self.0.required_token(SyntaxKind::WARNING_TYPE)
}
pub fn colon(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::COLON)
}
pub fn description(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::DESCRIPTION)
}
}
define_node!(GoogleSeeAlsoItem, GOOGLE_SEE_ALSO_ITEM);
impl<'a> GoogleSeeAlsoItem<'a> {
pub fn names(&self) -> impl Iterator<Item = &'a SyntaxToken> {
self.0.tokens(SyntaxKind::NAME)
}
pub fn colon(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::COLON)
}
pub fn description(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::DESCRIPTION)
}
}
define_node!(GoogleAttribute, GOOGLE_ATTRIBUTE);
impl<'a> GoogleAttribute<'a> {
pub fn name(&self) -> &'a SyntaxToken {
self.0.required_token(SyntaxKind::NAME)
}
pub fn open_bracket(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::OPEN_BRACKET)
}
pub fn r#type(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::TYPE)
}
pub fn close_bracket(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::CLOSE_BRACKET)
}
pub fn colon(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::COLON)
}
pub fn description(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::DESCRIPTION)
}
}
define_node!(GoogleMethod, GOOGLE_METHOD);
impl<'a> GoogleMethod<'a> {
pub fn name(&self) -> &'a SyntaxToken {
self.0.required_token(SyntaxKind::NAME)
}
pub fn open_bracket(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::OPEN_BRACKET)
}
pub fn r#type(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::TYPE)
}
pub fn close_bracket(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::CLOSE_BRACKET)
}
pub fn colon(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::COLON)
}
pub fn description(&self) -> Option<&'a SyntaxToken> {
self.0.find_token(SyntaxKind::DESCRIPTION)
}
}