git.delta.rocks / jrsonnet / refs/commits / c368769dca4a

difftreelog

source

crates/jrsonnet-rowan-parser/src/ast.rs2.2 KiBsourcehistory
1use std::marker::PhantomData;23use crate::{SyntaxKind, SyntaxNode, SyntaxNodeChildren, SyntaxToken};45/// The main trait to go from untyped `SyntaxNode`  to a typed ast. The6/// conversion itself has zero runtime cost: ast and syntax nodes have exactly7/// the same representation: a pointer to the tree root and a pointer to the8/// node itself.9pub trait AstNode {10	fn can_cast(kind: SyntaxKind) -> bool11	where12		Self: Sized;1314	fn cast(syntax: SyntaxNode) -> Option<Self>15	where16		Self: Sized;1718	fn syntax(&self) -> &SyntaxNode;19	#[must_use]20	fn clone_for_update(&self) -> Self21	where22		Self: Sized,23	{24		Self::cast(self.syntax().clone_for_update()).unwrap()25	}26	#[must_use]27	fn clone_subtree(&self) -> Self28	where29		Self: Sized,30	{31		Self::cast(self.syntax().clone_subtree()).unwrap()32	}33}3435/// Like `AstNode`, but wraps tokens rather than interior nodes.36pub trait AstToken {37	fn can_cast(token: SyntaxKind) -> bool38	where39		Self: Sized;4041	fn cast(syntax: SyntaxToken) -> Option<Self>42	where43		Self: Sized;4445	fn syntax(&self) -> &SyntaxToken;4647	fn text(&self) -> &str {48		self.syntax().text()49	}50}5152#[derive(Debug, Clone)]53pub struct AstChildren<N> {54	inner: SyntaxNodeChildren,55	ph: PhantomData<N>,56}5758impl<N> AstChildren<N> {59	fn new(parent: &SyntaxNode) -> Self {60		AstChildren {61			inner: parent.children(),62			ph: PhantomData,63		}64	}65}6667impl<N: AstNode> Iterator for AstChildren<N> {68	type Item = N;69	fn next(&mut self) -> Option<N> {70		self.inner.find_map(N::cast)71	}72}7374pub mod support {75	use rowan::NodeOrToken;7677	use super::{AstChildren, AstNode, AstToken, SyntaxKind, SyntaxNode, SyntaxToken};7879	pub fn child<N: AstNode>(parent: &SyntaxNode) -> Option<N> {80		parent.children().find_map(N::cast)81	}82	pub fn token_child<N: AstToken>(parent: &SyntaxNode) -> Option<N> {83		parent.children_with_tokens().find_map(|n| match n {84			rowan::NodeOrToken::Node(_) => None,85			rowan::NodeOrToken::Token(t) => N::cast(t),86		})87	}8889	pub fn children<N: AstNode>(parent: &SyntaxNode) -> AstChildren<N> {90		AstChildren::new(parent)91	}9293	pub fn token(parent: &SyntaxNode, kind: SyntaxKind) -> Option<SyntaxToken> {94		parent95			.children_with_tokens()96			.filter_map(NodeOrToken::into_token)97			.find(|it| it.kind() == kind)98	}99}