Skip to content

Commit 02d4abb

Browse files
committed
fix Node::descendants and add Node::next_token
1 parent 4b36aef commit 02d4abb

File tree

1 file changed

+55
-15
lines changed

1 file changed

+55
-15
lines changed

crates/postgresql-cst-parser/src/tree_sitter.rs

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -225,37 +225,60 @@ impl<'a> Node<'a> {
225225
}
226226
}
227227

228-
/// Returns an iterator over all descendant nodes (not including tokens)
228+
/// Returns the next token in the tree.
229+
/// This is not necessarily a direct sibling of this node/token,
230+
/// but will always be further right in the tree.
229231
/// this is not tree-sitter's API
230-
pub fn descendants(&self) -> impl Iterator<Item = Node<'a>> {
232+
pub fn next_token(&self) -> Option<Node<'a>> {
233+
match &self.node_or_token {
234+
NodeOrToken::Token(token) => token.next_token().map(|next_token| Node {
235+
input: self.input,
236+
range_map: Rc::clone(&self.range_map),
237+
node_or_token: NodeOrToken::Token(next_token),
238+
}),
239+
NodeOrToken::Node(node) => {
240+
// For a node, find its last token and then get the next token
241+
node.last_token()
242+
.and_then(|last_token| last_token.next_token())
243+
.map(|next_token| Node {
244+
input: self.input,
245+
range_map: Rc::clone(&self.range_map),
246+
node_or_token: NodeOrToken::Token(next_token),
247+
})
248+
}
249+
}
250+
}
251+
252+
/// Returns an iterator over all descendant nodes (including tokens)
253+
/// this is not tree-sitter's API
254+
pub fn descendants(&self) -> impl Iterator<Item = Node<'a>> + '_ {
231255
struct Descendants<'a> {
232-
input: &'a str,
233-
range_map: Rc<HashMap<TextRange, Range>>,
234-
iter: Box<dyn Iterator<Item = &'a ResolvedNode> + 'a>,
256+
iter: Box<dyn Iterator<Item = Node<'a>> + 'a>,
235257
}
236258

237259
impl<'a> Iterator for Descendants<'a> {
238260
type Item = Node<'a>;
239261

240262
fn next(&mut self) -> Option<Self::Item> {
241-
self.iter.next().map(|node| Node {
242-
input: self.input,
243-
range_map: Rc::clone(&self.range_map),
244-
node_or_token: NodeOrToken::Node(node),
245-
})
263+
self.iter.next()
246264
}
247265
}
248266

249267
if let Some(node) = self.node_or_token.as_node() {
268+
let input = self.input;
269+
let range_map = Rc::clone(&self.range_map);
250270
Descendants {
251-
input: self.input,
252-
range_map: Rc::clone(&self.range_map),
253-
iter: Box::new(node.descendants()),
271+
iter: Box::new(
272+
node.descendants_with_tokens()
273+
.map(move |node_or_token| Node {
274+
input,
275+
range_map: Rc::clone(&range_map),
276+
node_or_token,
277+
}),
278+
),
254279
}
255280
} else {
256281
Descendants {
257-
input: self.input,
258-
range_map: Rc::clone(&self.range_map),
259282
iter: Box::new(std::iter::empty()),
260283
}
261284
}
@@ -598,4 +621,21 @@ from
598621
assert_eq!(last_nodes.next().unwrap().text(), "name");
599622
assert!(last_nodes.next().is_none());
600623
}
624+
625+
#[test]
626+
fn test_next_token() {
627+
let src = "SELECT tbl.name as n from TBL;";
628+
let tree = parse(src).unwrap();
629+
let root = tree.root_node();
630+
631+
let name = root
632+
.descendants()
633+
.find(|node| node.kind() == SyntaxKind::NAME_P)
634+
.expect("should find NAME_P");
635+
636+
// Even if not a direct sibling or not belonging to the same subtree, the next_token can retrieve the next token.
637+
let next_token = name.next_token().expect("should have next token");
638+
assert_eq!(next_token.text(), "as");
639+
assert_eq!(next_token.kind(), SyntaxKind::AS);
640+
}
601641
}

0 commit comments

Comments
 (0)