diff --git a/crates/cairo-lang-defs/src/patcher.rs b/crates/cairo-lang-defs/src/patcher.rs index 4fcf615f8c8..66f5268acba 100644 --- a/crates/cairo-lang-defs/src/patcher.rs +++ b/crates/cairo-lang-defs/src/patcher.rs @@ -65,7 +65,10 @@ impl<'db> RewriteNode<'db> { match self { RewriteNode::Copied(syntax_node) => { *self = RewriteNode::new_modified( - syntax_node.get_children(db).map(RewriteNode::Copied).collect(), + syntax_node + .get_children(db) + .map(|child| RewriteNode::Copied(child.build(db))) + .collect(), ); extract_matches!(self, RewriteNode::Modified) } @@ -75,16 +78,17 @@ impl<'db> RewriteNode<'db> { let mut new_children = Vec::new(); // Get the index of the leftmost nonempty child. - let Some((left_idx, first_syntax)) = + let Some((left_idx, first_syntax_builder)) = children.find(|(_, child)| child.width(db) != TextWidth::default()) else { *self = RewriteNode::Modified(ModifiedNode { children: None }); return extract_matches!(self, RewriteNode::Modified); }; + let first_syntax = first_syntax_builder.build(db); // Get the index of the rightmost nonempty child. - let (right_idx, last_syntax) = children + let (right_idx, last_syntax_builder) = children .rfind(|(_, child)| child.width(db) != TextWidth::default()) - .unwrap_or((left_idx, first_syntax)); + .unwrap_or((left_idx, first_syntax_builder)); new_children.extend(itertools::repeat_n( RewriteNode::Modified(ModifiedNode { children: None }), left_idx, @@ -107,10 +111,10 @@ impl<'db> RewriteNode<'db> { trim_right: false, }); for (_, child) in children { - new_children.push(RewriteNode::Copied(child)); + new_children.push(RewriteNode::Copied(child.build(db))); } new_children.push(RewriteNode::Trimmed { - node: last_syntax, + node: last_syntax_builder.build(db), trim_left: false, trim_right: *trim_right, }); diff --git a/crates/cairo-lang-defs/src/test.rs b/crates/cairo-lang-defs/src/test.rs index 01b6976ea06..e6f3162cfaa 100644 --- a/crates/cairo-lang-defs/src/test.rs +++ b/crates/cairo-lang-defs/src/test.rs @@ -92,7 +92,7 @@ fn test_generic_item_id( } _ => {} } - for child in node.get_children(db) { + for child in node.get_children(db).nodes(db) { find_generics(db, module_id, &child, output); } } diff --git a/crates/cairo-lang-doc/src/documentable_formatter.rs b/crates/cairo-lang-doc/src/documentable_formatter.rs index 97df4c6445d..820b6015513 100644 --- a/crates/cairo-lang-doc/src/documentable_formatter.rs +++ b/crates/cairo-lang-doc/src/documentable_formatter.rs @@ -866,7 +866,8 @@ fn write_function_signature<'db>( /// Retrieves [`SyntaxKind::TypeClause`] text from [`SyntaxNode`]. fn get_type_clause<'db>(syntax_node: SyntaxNode<'db>, db: &'db dyn Database) -> Option { for child in syntax_node.get_children(db) { - if child.kind(db) == SyntaxKind::TypeClause { + if child.kind() == SyntaxKind::TypeClause { + let child = child.build(db); return Some(child.get_text_without_all_comment_trivia(db)); } } @@ -960,7 +961,7 @@ fn write_struct_attributes_syntax<'db>( for attribute in attributes { let syntax_node = attribute.stable_ptr.lookup(f.db).as_syntax_node(); for child in syntax_node.get_children(f.db) { - let to_text = child.get_text_without_all_comment_trivia(f.db); + let to_text = child.build(f.db).get_text_without_all_comment_trivia(f.db); let cleaned_text = to_text.replace("\n", ""); f.write_str(&cleaned_text)?; } @@ -979,20 +980,20 @@ fn write_syntactic_evaluation<'db>( if matches!(&syntax_node.green_node(f.db).details, green::GreenNodeDetails::Node { .. }) { let mut is_after_evaluation_value = false; for child in syntax_node.get_children(f.db) { - let kind = child.kind(f.db); - if !matches!(kind, SyntaxKind::Trivia) { - if matches!(kind, SyntaxKind::TerminalSemicolon) { - f.buf.write_str(";")?; - return Ok(()); - } - if is_after_evaluation_value { - f.buf.write_str(&SyntaxNode::get_text_without_all_comment_trivia( - &child, f.db, - ))?; - }; - if matches!(kind, SyntaxKind::TerminalEq) { - is_after_evaluation_value = true; - } + let kind = child.kind(); + if matches!(kind, SyntaxKind::Trivia) { + continue; + } + if matches!(kind, SyntaxKind::TerminalSemicolon) { + f.buf.write_str(";")?; + return Ok(()); + } + if is_after_evaluation_value { + f.buf + .write_str(&child.build(f.db).get_text_without_all_comment_trivia(f.db))?; + } + if matches!(kind, SyntaxKind::TerminalEq) { + is_after_evaluation_value = true; } } }; diff --git a/crates/cairo-lang-doc/src/location_links.rs b/crates/cairo-lang-doc/src/location_links.rs index e0d251a9423..1b747450676 100644 --- a/crates/cairo-lang-doc/src/location_links.rs +++ b/crates/cairo-lang-doc/src/location_links.rs @@ -30,17 +30,25 @@ fn collect_green_nodes<'db>( syntax_node: &SyntaxNode<'db>, green_nodes: &mut Vec<(SyntaxKind, String)>, ) -> Vec<(SyntaxKind, String)> { - let green_node = syntax_node.green_node(db); - - match &green_node.details { - GreenNodeDetails::Token(text) => green_nodes.push((green_node.kind, text.to_string(db))), - GreenNodeDetails::Node { .. } => { - let syntax_node_children = syntax_node.get_children(db); - syntax_node_children.for_each(|child| { - collect_green_nodes(db, &child, green_nodes); - }); + fn collect_from_green<'db>( + db: &'db dyn Database, + green_node: &cairo_lang_syntax::node::green::GreenNode<'db>, + green_nodes: &mut Vec<(SyntaxKind, String)>, + ) { + match &green_node.details { + GreenNodeDetails::Token(text) => { + green_nodes.push((green_node.kind, text.to_string(db))); + } + GreenNodeDetails::Node { children, .. } => { + for child in children { + collect_from_green(db, child.long(db), green_nodes); + } + } } } + + let green_node = syntax_node.green_node(db); + collect_from_green(db, green_node, green_nodes); green_nodes.to_owned() } diff --git a/crates/cairo-lang-formatter/src/formatter_impl.rs b/crates/cairo-lang-formatter/src/formatter_impl.rs index 4440873dfd9..b6d3e12a368 100644 --- a/crates/cairo-lang-formatter/src/formatter_impl.rs +++ b/crates/cairo-lang-formatter/src/formatter_impl.rs @@ -1033,7 +1033,7 @@ impl<'a> FormatterImpl<'a> { let internal_break_line_points_positions = syntax_node.get_internal_break_line_point_properties(self.db, &self.config); // TODO(ilya): consider not copying here. - let mut children: Vec<_> = syntax_node.get_children(self.db).collect(); + let mut children: Vec<_> = syntax_node.get_children(self.db).nodes(self.db).collect(); let n_children = children.len(); if self.config.merge_use_items { @@ -1119,7 +1119,7 @@ impl<'a> FormatterImpl<'a> { // Add merged children to the new_children list. if let Some(child) = merged_node.get_children(self.db).next() { - new_children.extend(child.get_children(self.db)); + new_children.extend(child.build(self.db).get_children(self.db).nodes(self.db)); } } } @@ -1217,11 +1217,11 @@ impl<'a> FormatterImpl<'a> { }; // The first newlines is the leading trivia correspond exactly to empty lines. - self.format_trivia(ast::Trivia::from_syntax_node(self.db, leading), true); + self.format_trivia(ast::Trivia::from_syntax_node(self.db, leading.build(self.db)), true); if !syntax_node.should_skip_terminal(self.db) { - self.format_token(&token); + self.format_token(&token.build(self.db)); } - self.format_trivia(ast::Trivia::from_syntax_node(self.db, trailing), false); + self.format_trivia(ast::Trivia::from_syntax_node(self.db, trailing.build(self.db)), false); } /// Appends a trivia node (if needed) to the result. fn format_trivia(&mut self, trivia: syntax::node::ast::Trivia<'a>, is_leading: bool) { diff --git a/crates/cairo-lang-formatter/src/node_properties.rs b/crates/cairo-lang-formatter/src/node_properties.rs index 09592a8d423..c79f5933a59 100644 --- a/crates/cairo-lang-formatter/src/node_properties.rs +++ b/crates/cairo-lang-formatter/src/node_properties.rs @@ -140,7 +140,7 @@ impl<'a> SyntaxNodeFormat for SyntaxNode<'a> { .parent(db) .unwrap() .get_children(db) - .any(|c| c.kind(db) == SyntaxKind::PatternEnumInnerPattern) => + .any(|c| c.kind() == SyntaxKind::PatternEnumInnerPattern) => { true } @@ -952,7 +952,7 @@ impl<'a> SyntaxNodeFormat for SyntaxNode<'a> { ) { let parent_node = self.parent(db).unwrap(); - let children = parent_node.get_children(db); + let mut children = parent_node.get_children(db); // Check if it's an ExprList or PatternList with len > 2, or any other list type. let is_expr_or_pattern_list = matches!( self.parent_kind(db), @@ -960,7 +960,7 @@ impl<'a> SyntaxNodeFormat for SyntaxNode<'a> { ); if (!is_expr_or_pattern_list || children.len() > 2) // Ensure that this node is the last element in the list. - && children.last() == Some(*self) + && children.next_back().map(|c| c.build(db)) == Some(*self) { return true; } @@ -975,8 +975,9 @@ impl<'a> SyntaxNodeFormat for SyntaxNode<'a> { let statements_node = statement_node.parent(db).unwrap(); // Checking if not the last statement, as `;` may be there to prevent the block from // returning the value of the current block. - let statements_children = statements_node.get_children(db); - let not_last = statements_children.last() != Some(statement_node); + let mut statements_children = statements_node.get_children(db); + let not_last = + statements_children.next_back().map(|c| c.build(db)) != Some(statement_node); if not_last && matches!( statement_node.get_child(db, 1).kind(db), @@ -996,7 +997,9 @@ impl<'a> SyntaxNodeFormat for SyntaxNode<'a> { { let path_segment_node = self.parent(db).unwrap(); let path_node = path_segment_node.parent(db).unwrap(); - if path_node.get_children(db).last() != Some(path_segment_node) { + if path_node.get_children(db).next_back().map(|c| c.build(db)) + != Some(path_segment_node) + { false } else { matches!( diff --git a/crates/cairo-lang-parser/src/colored_printer.rs b/crates/cairo-lang-parser/src/colored_printer.rs index a1aee7af783..48d8ea8d93f 100644 --- a/crates/cairo-lang-parser/src/colored_printer.rs +++ b/crates/cairo-lang-parser/src/colored_printer.rs @@ -29,6 +29,7 @@ impl ColoredPrinter<'_> { self.result.push_str(format!("{}", "".red()).as_str()); } else { for child in syntax_node.get_children(self.db) { + let child = child.build(self.db); self.print(&child); } } diff --git a/crates/cairo-lang-parser/src/printer.rs b/crates/cairo-lang-parser/src/printer.rs index f47a3077aa5..f1d143c8753 100644 --- a/crates/cairo-lang-parser/src/printer.rs +++ b/crates/cairo-lang-parser/src/printer.rs @@ -209,14 +209,14 @@ impl<'a> Printer<'a> { NodeKind::Struct { members: expected_children } | NodeKind::Terminal { members: expected_children, .. } => { self.print_internal_struct( - syntax_node.get_children(self.db), + syntax_node.get_children(self.db).nodes(self.db), &expected_children, indent.as_str(), under_top_level, ); } NodeKind::List { .. } => { - for (i, child) in syntax_node.get_children(self.db).enumerate() { + for (i, child) in syntax_node.get_children(self.db).nodes(self.db).enumerate() { self.print_tree( format!("child #{i}").as_str(), &child, @@ -227,7 +227,7 @@ impl<'a> Printer<'a> { } } NodeKind::SeparatedList { .. } => { - for (i, child) in syntax_node.get_children(self.db).enumerate() { + for (i, child) in syntax_node.get_children(self.db).nodes(self.db).enumerate() { let description = if i.is_multiple_of(2) { "item" } else { "separator" }; self.print_tree( format!("{description} #{}", i / 2).as_str(), diff --git a/crates/cairo-lang-plugins/src/plugins/generate_trait.rs b/crates/cairo-lang-plugins/src/plugins/generate_trait.rs index fc30854ccbc..9c19d41fdd4 100644 --- a/crates/cairo-lang-plugins/src/plugins/generate_trait.rs +++ b/crates/cairo-lang-plugins/src/plugins/generate_trait.rs @@ -184,7 +184,7 @@ fn generate_trait_for_impl<'db>( builder.add_node(decl.name(db).as_syntax_node()); builder.add_node(decl.generic_params(db).as_syntax_node()); builder.add_node(signature.lparen(db).as_syntax_node()); - for node in signature.parameters(db).node.get_children(db) { + for node in signature.parameters(db).node.get_children(db).nodes(db) { if let Some(param) = ast::Param::cast(db, node) { for modifier in param.modifiers(db).elements(db) { // `mut` modifiers are only relevant for impls, not traits. diff --git a/crates/cairo-lang-semantic/src/items/macro_declaration.rs b/crates/cairo-lang-semantic/src/items/macro_declaration.rs index 36ec04c5314..9b617f33b8c 100644 --- a/crates/cairo-lang-semantic/src/items/macro_declaration.rs +++ b/crates/cairo-lang-semantic/src/items/macro_declaration.rs @@ -227,7 +227,7 @@ fn collect_expansion_placeholders<'db>( return placeholders; } if !node.kind(db).is_terminal() { - for child in node.get_children(db) { + for child in node.get_children(db).nodes(db) { placeholders.extend(collect_expansion_placeholders(db, child)); } } @@ -571,7 +571,7 @@ fn expand_macro_rule_ex( return Ok(()); } - for child in node.get_children(db) { + for child in node.get_children(db).nodes(db) { expand_macro_rule_ex(db, child, matcher_ctx, res_buffer, code_mappings)?; } return Ok(()); @@ -581,7 +581,7 @@ fn expand_macro_rule_ex( res_buffer.push_str(node.get_text(db)); return Ok(()); } - for child in node.get_children(db) { + for child in node.get_children(db).nodes(db) { expand_macro_rule_ex(db, child, matcher_ctx, res_buffer, code_mappings)?; } Ok(()) diff --git a/crates/cairo-lang-syntax/src/node/element_list.rs b/crates/cairo-lang-syntax/src/node/element_list.rs index 913e4e6e3e6..b410a832f8f 100644 --- a/crates/cairo-lang-syntax/src/node/element_list.rs +++ b/crates/cairo-lang-syntax/src/node/element_list.rs @@ -25,7 +25,7 @@ impl<'db, T: TypedSyntaxNode<'db>> ElementList<'db, T, 1> { &self, db: &'db dyn Database, ) -> impl ExactSizeIterator + DoubleEndedIterator + use<'db, T> + 'db { - self.node.get_children(db).map(|x| T::from_syntax_node(db, x)) + self.node.get_children(db).map(move |x| T::from_syntax_node(db, x.build(db))) } pub fn has_tail(&self, _db: &dyn Database) -> bool { false @@ -39,7 +39,7 @@ impl<'db, T: TypedSyntaxNode<'db>> ElementList<'db, T, 2> { &self, db: &'db dyn Database, ) -> impl ExactSizeIterator + DoubleEndedIterator + use<'db, T> + 'db { - self.node.get_children(db).step_by(2).map(|x| T::from_syntax_node(db, x)) + self.node.get_children(db).step_by(2).map(move |x| T::from_syntax_node(db, x.build(db))) } pub fn has_tail(&self, db: &dyn Database) -> bool { !self.node.get_children(db).len().is_multiple_of(2) diff --git a/crates/cairo-lang-syntax/src/node/iter.rs b/crates/cairo-lang-syntax/src/node/iter.rs index 6e19776c256..47864b2b395 100644 --- a/crates/cairo-lang-syntax/src/node/iter.rs +++ b/crates/cairo-lang-syntax/src/node/iter.rs @@ -76,7 +76,8 @@ impl<'a> Iterator for Preorder<'a> { // emitted. Some(WalkEvent::Leave(layer.start)) } - Some(start) => { + Some(start_builder) => { + let start = start_builder.build(self.db); // #3: Otherwise the iterator is just in the middle of visiting a child, so // push a new layer to iterate it. To avoid // recursion, step #1 is duplicated and diff --git a/crates/cairo-lang-syntax/src/node/mod.rs b/crates/cairo-lang-syntax/src/node/mod.rs index be8c730c9a4..0dcfca688b3 100644 --- a/crates/cairo-lang-syntax/src/node/mod.rs +++ b/crates/cairo-lang-syntax/src/node/mod.rs @@ -62,6 +62,14 @@ struct ChildKeyData<'db> { key_fields: ArcGreenIds<'db>, } +/// Provides green-level access to a child node and constructs a `SyntaxNode` only when needed. +#[derive(Copy, Clone)] +pub struct SyntaxNodeBuilder<'a> { + parent: SyntaxNode<'a>, + metadata: &'a ChildKeyData<'a>, + parent_offset: TextOffset, +} + /// Private tracked struct containing the actual SyntaxNode data. /// This is kept private so the public `new` function generated by salsa can't be called directly. #[salsa::tracked] @@ -82,7 +90,6 @@ struct SyntaxNodeData<'a> { /// This struct holds all the state needed to lazily iterate through children. pub struct ChildrenIter<'a> { parent: SyntaxNode<'a>, - db: &'a dyn Database, parent_offset: TextOffset, metadata: &'a [ChildKeyData<'a>], front: usize, @@ -90,7 +97,7 @@ pub struct ChildrenIter<'a> { } impl<'a> Iterator for ChildrenIter<'a> { - type Item = SyntaxNode<'a>; + type Item = SyntaxNodeBuilder<'a>; fn next(&mut self) -> Option { if self.front == self.back { @@ -98,7 +105,7 @@ impl<'a> Iterator for ChildrenIter<'a> { } let index = self.front; self.front += 1; - Some(self.build_child(index)) + Some(self.child_builder(index)) } fn size_hint(&self) -> (usize, Option) { @@ -119,7 +126,7 @@ impl<'a> DoubleEndedIterator for ChildrenIter<'a> { return None; } self.back -= 1; - Some(self.build_child(self.back)) + Some(self.child_builder(self.back)) } } @@ -128,22 +135,79 @@ impl<'a> ChildrenIter<'a> { self.back - self.front } - fn build_child(&self, index: usize) -> SyntaxNode<'a> { + fn child_builder(&self, index: usize) -> SyntaxNodeBuilder<'a> { let entry = &self.metadata[index]; - let offset = self.parent_offset.add_width(entry.start); + SyntaxNodeBuilder::new(self.parent, entry, self.parent_offset) + } + + /// Eagerly builds syntax nodes for the remaining children. + pub fn nodes( + self, + db: &'a dyn Database, + ) -> impl ExactSizeIterator> + DoubleEndedIterator + 'a { + self.map(move |child| child.build(db)) + } +} + +impl<'a> SyntaxNodeBuilder<'a> { + fn new( + parent: SyntaxNode<'a>, + metadata: &'a ChildKeyData<'a>, + parent_offset: TextOffset, + ) -> Self { + Self { parent, metadata, parent_offset } + } + + /// Returns the underlying green id. + pub fn green_id(&self) -> GreenId<'a> { + self.metadata.green_id + } + + /// Returns the offset of the child relative to the file start. + pub fn offset(&self) -> TextOffset { + self.parent_offset.add_width(self.metadata.start) + } + + /// Returns the index of this child among siblings with the same key fields. + pub fn key_index(&self) -> usize { + self.metadata.key_index + } + + /// Returns the underlying green node. + pub fn green(&self, db: &'a dyn Database) -> &'a GreenNode<'a> { + self.metadata.green_id.long(db) + } + + /// Returns the kind of the child without constructing a syntax node. + pub fn kind(&self) -> SyntaxKind { + self.metadata.kind + } + + /// Returns the width of the child in characters. + pub fn width(&self, db: &'a dyn Database) -> TextWidth { + self.metadata.green_id.width(db) + } + + /// Constructs a [SyntaxNode] for this child. + pub fn build(&self, db: &'a dyn Database) -> SyntaxNode<'a> { new_syntax_node( - self.db, - entry.green_id, - offset, + db, + self.metadata.green_id, + self.offset(), SyntaxNodeId::Child { parent: self.parent, - index: entry.key_index, - key_fields: entry.key_fields.clone(), + index: self.metadata.key_index, + key_fields: self.metadata.key_fields.clone(), }, - entry.kind, + self.metadata.kind, ) } + + /// Returns the parent syntax node. + pub fn parent(&self) -> SyntaxNode<'a> { + self.parent + } } impl<'db> SyntaxNodeData<'db> { @@ -395,7 +459,6 @@ impl<'a> SyntaxNode<'a> { let metadata = syntax_node_children_key_data(db, green_id); ChildrenIter { parent: self, - db, parent_offset: offset, metadata, front: 0, @@ -409,23 +472,11 @@ impl<'a> SyntaxNode<'a> { db: &'a dyn Database, target_index: usize, ) -> SyntaxNode<'a> { - let green_id = self.data.green(db); - let metadata = syntax_node_children_key_data(db, green_id); - if let Some(entry) = metadata.get(target_index) { - let offset = self.offset(db).add_width(entry.start); - return new_syntax_node( - db, - entry.green_id, - offset, - SyntaxNodeId::Child { - parent: *self, - index: entry.key_index, - key_fields: entry.key_fields.clone(), - }, - entry.kind, - ); + let metadata = syntax_node_children_key_data(db, self.data.green(db)); + match metadata.get(target_index) { + Some(entry) => SyntaxNodeBuilder::new(*self, entry, self.offset(db)).build(db), + _ => panic!("Child index {} out of bounds", target_index), } - panic!("Child index {} out of bounds", target_index) } // Text and span utilities @@ -447,8 +498,8 @@ impl<'a> SyntaxNode<'a> { /// Lookups a syntax node using an offset. pub fn lookup_offset(&self, db: &'a dyn Database, offset: TextOffset) -> SyntaxNode<'a> { for child in self.get_children(db) { - if child.offset(db).add_width(child.width(db)) > offset { - return child.lookup_offset(db, offset); + if child.offset().add_width(child.width(db)) > offset { + return child.build(db).lookup_offset(db, offset); } } *self @@ -484,7 +535,7 @@ impl<'a> SyntaxNode<'a> { green::GreenNodeDetails::Token(text) => buffer.push_str(text.long(db)), green::GreenNodeDetails::Node { .. } => { for child in self.get_children(db) { - let kind = child.kind(db); + let kind = child.kind(); // Checks all the items that the inner comment can be bubbled to (implementation // function is also a FunctionWithBody). @@ -494,9 +545,9 @@ impl<'a> SyntaxNode<'a> { | SyntaxKind::ItemModule | SyntaxKind::TraitItemFunction ) { - buffer.push_str(&SyntaxNode::get_text_without_inner_commentable_children( - &child, db, - )); + // TODO(eytan-starkware): Add this function to Builder and use that instead. + let child = child.build(db); + buffer.push_str(&child.get_text_without_inner_commentable_children(db)); } } } @@ -512,7 +563,7 @@ impl<'a> SyntaxNode<'a> { match &self.green_node(db).details { green::GreenNodeDetails::Token(text) => buffer.push_str(text.long(db)), green::GreenNodeDetails::Node { .. } => { - for child in self.get_children(db) { + for child in self.get_children(db).nodes(db) { if let Some(trivia) = ast::Trivia::cast(db, child) { trivia.elements(db).for_each(|element| { if !matches!( @@ -529,8 +580,7 @@ impl<'a> SyntaxNode<'a> { } }); } else { - buffer - .push_str(&SyntaxNode::get_text_without_all_comment_trivia(&child, db)); + buffer.push_str(&child.get_text_without_all_comment_trivia(db)); } } } diff --git a/crates/cairo-lang-syntax/src/node/with_db.rs b/crates/cairo-lang-syntax/src/node/with_db.rs index 4d5b1d4226b..abf57ce5bb1 100644 --- a/crates/cairo-lang-syntax/src/node/with_db.rs +++ b/crates/cairo-lang-syntax/src/node/with_db.rs @@ -43,6 +43,8 @@ impl<'a> SyntaxNodeWithDbIterator<'a> { impl<'a> Iterator for SyntaxNodeWithDbIterator<'a> { type Item = PrimitiveToken; + // TODO(eytan-starkware): We can remove syntaxnode build here and work directly with + // green/syntaxnodebuilder. fn next(&mut self) -> Option { // If the buffer is empty, perform a single step of the depth-first traversal. // This will fill the buffer with up to three tokens from the current node. @@ -61,7 +63,7 @@ impl<'a> Iterator for SyntaxNodeWithDbIterator<'a> { if node.green_node(self.db).kind.is_terminal() { token_from_syntax_node(&node, self.db, &mut self.buffer); } else { - for child in node.get_children(self.db).rev() { + for child in node.get_children(self.db).nodes(self.db).rev() { self.iter_stack.push(child); } }