Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/syntax/src/ast/node_ext.rs')
-rw-r--r--crates/syntax/src/ast/node_ext.rs38
1 files changed, 37 insertions, 1 deletions
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index af741d100f..901d17bb14 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -10,7 +10,7 @@ use parser::SyntaxKind;
use rowan::{GreenNodeData, GreenTokenData};
use crate::{
- NodeOrToken, SmolStr, SyntaxElement, SyntaxToken, T, TokenText,
+ NodeOrToken, SmolStr, SyntaxElement, SyntaxElementChildren, SyntaxToken, T, TokenText,
ast::{
self, AstNode, AstToken, HasAttrs, HasGenericArgs, HasGenericParams, HasName,
HasTypeBounds, SyntaxNode, support,
@@ -1114,3 +1114,39 @@ impl ast::OrPat {
.filter(|it| it.kind() == T![|])
}
}
+
+/// An iterator over the elements in an [`ast::TokenTree`].
+///
+/// Does not yield trivia or the delimiters.
+#[derive(Clone)]
+pub struct TokenTreeChildren {
+ iter: SyntaxElementChildren,
+}
+
+impl TokenTreeChildren {
+ #[inline]
+ pub fn new(tt: &ast::TokenTree) -> Self {
+ let mut iter = tt.syntax.children_with_tokens();
+ iter.next(); // Bump the opening delimiter.
+ Self { iter }
+ }
+}
+
+impl Iterator for TokenTreeChildren {
+ type Item = NodeOrToken<ast::TokenTree, SyntaxToken>;
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.find_map(|item| match item {
+ NodeOrToken::Node(node) => ast::TokenTree::cast(node).map(NodeOrToken::Node),
+ NodeOrToken::Token(token) => {
+ let kind = token.kind();
+ (!matches!(
+ kind,
+ SyntaxKind::WHITESPACE | SyntaxKind::COMMENT | T![')'] | T![']'] | T!['}']
+ ))
+ .then_some(NodeOrToken::Token(token))
+ }
+ })
+ }
+}