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

difftreelog

source

crates/jrsonnet-rowan-parser/src/ast.rs2.1 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	fn clone_for_update(&self) -> Self20	where21		Self: Sized,22	{23		Self::cast(self.syntax().clone_for_update()).unwrap()24	}25	fn clone_subtree(&self) -> Self26	where27		Self: Sized,28	{29		Self::cast(self.syntax().clone_subtree()).unwrap()30	}31}3233/// Like `AstNode`, but wraps tokens rather than interior nodes.34pub trait AstToken {35	fn can_cast(token: SyntaxKind) -> bool36	where37		Self: Sized;3839	fn cast(syntax: SyntaxToken) -> Option<Self>40	where41		Self: Sized;4243	fn syntax(&self) -> &SyntaxToken;4445	fn text(&self) -> &str {46		self.syntax().text()47	}48}4950#[derive(Debug, Clone)]51pub struct AstChildren<N> {52	inner: SyntaxNodeChildren,53	ph: PhantomData<N>,54}5556impl<N> AstChildren<N> {57	fn new(parent: &SyntaxNode) -> Self {58		AstChildren {59			inner: parent.children(),60			ph: PhantomData,61		}62	}63}6465impl<N: AstNode> Iterator for AstChildren<N> {66	type Item = N;67	fn next(&mut self) -> Option<N> {68		self.inner.find_map(N::cast)69	}70}7172pub mod support {73	use super::{AstChildren, AstNode, AstToken, SyntaxKind, SyntaxNode, SyntaxToken};7475	pub fn child<N: AstNode>(parent: &SyntaxNode) -> Option<N> {76		parent.children().find_map(N::cast)77	}78	pub fn token_child<N: AstToken>(parent: &SyntaxNode) -> Option<N> {79		parent.children_with_tokens().find_map(|n| match n {80			rowan::NodeOrToken::Node(_) => None,81			rowan::NodeOrToken::Token(t) => N::cast(t),82		})83	}8485	pub fn children<N: AstNode>(parent: &SyntaxNode) -> AstChildren<N> {86		AstChildren::new(parent)87	}8889	pub fn token(parent: &SyntaxNode, kind: SyntaxKind) -> Option<SyntaxToken> {90		parent91			.children_with_tokens()92			.filter_map(|it| it.into_token())93			.find(|it| it.kind() == kind)94	}95}