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.rs | 38 |
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)) + } + }) + } +} |