git.delta.rocks / jrsonnet / refs/heads / master

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.6///7/// The conversion itself has zero runtime cost: ast and syntax nodes have exactly8/// the same representation: a pointer to the tree root and a pointer to the9/// node itself.10pub trait AstNode {11	fn can_cast(kind: SyntaxKind) -> bool12	where13		Self: Sized;1415	fn cast(syntax: SyntaxNode) -> Option<Self>16	where17		Self: Sized;1819	fn syntax(&self) -> &SyntaxNode;20	#[must_use]21	fn clone_for_update(&self) -> Self22	where23		Self: Sized,24	{25		Self::cast(self.syntax().clone_for_update()).unwrap()26	}27	#[must_use]28	fn clone_subtree(&self) -> Self29	where30		Self: Sized,31	{32		Self::cast(self.syntax().clone_subtree()).unwrap()33	}34}3536/// Like `AstNode`, but wraps tokens rather than interior nodes.37pub trait AstToken {38	fn can_cast(token: SyntaxKind) -> bool39	where40		Self: Sized;4142	fn cast(syntax: SyntaxToken) -> Option<Self>43	where44		Self: Sized;4546	fn syntax(&self) -> &SyntaxToken;4748	fn text(&self) -> &str {49		self.syntax().text()50	}51}5253#[derive(Debug, Clone)]54pub struct AstChildren<N> {55	inner: SyntaxNodeChildren,56	ph: PhantomData<N>,57}5859impl<N> AstChildren<N> {60	fn new(parent: &SyntaxNode) -> Self {61		AstChildren {62			inner: parent.children(),63			ph: PhantomData,64		}65	}66}6768impl<N: AstNode> Iterator for AstChildren<N> {69	type Item = N;70	fn next(&mut self) -> Option<N> {71		self.inner.find_map(N::cast)72	}73}7475pub mod support {76	use rowan::NodeOrToken;7778	use super::{AstChildren, AstNode, AstToken, SyntaxKind, SyntaxNode, SyntaxToken};7980	pub fn token_child<N: AstToken>(parent: &SyntaxNode) -> Option<N> {81		parent.children_with_tokens().find_map(|n| match n {82			rowan::NodeOrToken::Node(_) => None,83			rowan::NodeOrToken::Token(t) => N::cast(t),84		})85	}8687	pub fn children<N: AstNode>(parent: &SyntaxNode) -> AstChildren<N> {88		AstChildren::new(parent)89	}9091	pub fn token(parent: &SyntaxNode, kind: SyntaxKind) -> Option<SyntaxToken> {92		parent93			.children_with_tokens()94			.filter_map(NodeOrToken::into_token)95			.find(|it| it.kind() == kind)96	}97}