diff --git a/crates/biome_grit_patterns/src/grit_node.rs b/crates/biome_grit_patterns/src/grit_node.rs index 131cf450fe0b..f59b15c66be9 100644 --- a/crates/biome_grit_patterns/src/grit_node.rs +++ b/crates/biome_grit_patterns/src/grit_node.rs @@ -1,3 +1,4 @@ +use crate::util::TextRangeGritExt; use biome_grit_syntax::GritSyntaxNode; use grit_util::{AstCursor, AstNode as GritAstNode, ByteRange, CodeRange}; use std::{borrow::Cow, ops::Deref, str::Utf8Error}; @@ -27,84 +28,173 @@ impl From<&GritSyntaxNode> for GritNode { impl GritAstNode for GritNode { fn ancestors(&self) -> impl Iterator { - TodoIterator + AncestorIterator::new(self) } fn children(&self) -> impl Iterator { - TodoIterator + ChildrenIterator::new(self) } fn parent(&self) -> Option { - todo!() + self.0.parent().map(Into::into) } fn next_named_node(&self) -> Option { - todo!() + let mut current_node = Cow::Borrowed(&self.0); + loop { + if let Some(sibling) = current_node.next_sibling() { + return Some(sibling.into()); + } + current_node = Cow::Owned(current_node.parent()?); + } } fn previous_named_node(&self) -> Option { - todo!() + let mut current_node = Cow::Borrowed(&self.0); + loop { + if let Some(sibling) = current_node.prev_sibling() { + return Some(sibling.into()); + } + current_node = Cow::Owned(current_node.parent()?); + } } fn next_sibling(&self) -> Option { - todo!() + self.0.next_sibling().map(Into::into) } fn previous_sibling(&self) -> Option { - todo!() + self.0.prev_sibling().map(Into::into) } fn text(&self) -> Result, Utf8Error> { - todo!() + Ok(Cow::Owned(self.0.text_trimmed().to_string())) } fn byte_range(&self) -> ByteRange { - todo!() + self.0.text_trimmed_range().to_byte_range() } fn code_range(&self) -> CodeRange { - todo!() + let range = self.0.text_trimmed_range(); + CodeRange { + start: range.start().into(), + end: range.end().into(), + // Code ranges contain an address so they can quickly check whether + // a particular binding belongs to a given range or not. + address: self + .0 + .first_token() + .map(|token| token.text().as_ptr() as usize) + .unwrap_or_default(), + } } fn full_source(&self) -> &str { - todo!() + // This should not be a problem anytime soon, though we may want to + // reconsider when we implement rewrites. + unimplemented!("Full source of file not available") } fn walk(&self) -> impl AstCursor { - TodoCursor + GritNodeCursor::new(self) } } #[derive(Clone)] -struct TodoIterator; +pub struct AncestorIterator { + node: Option, +} -impl Iterator for TodoIterator { +impl AncestorIterator { + fn new(node: &GritNode) -> Self { + Self { + node: Some(node.clone()), + } + } +} + +impl Iterator for AncestorIterator { type Item = GritNode; fn next(&mut self) -> Option { - todo!() + let node = self.node.as_ref().cloned()?; + self.node = node.parent(); + Some(node) + } +} + +pub struct ChildrenIterator { + cursor: Option, +} + +impl ChildrenIterator { + fn new(node: &GritNode) -> Self { + let mut cursor = GritNodeCursor::new(node); + Self { + cursor: cursor.goto_first_child().then_some(cursor), + } + } +} + +impl Iterator for ChildrenIterator { + type Item = GritNode; + + fn next(&mut self) -> Option { + let c = self.cursor.as_mut()?; + let node = c.node(); + if !c.goto_next_sibling() { + self.cursor = None; + } + Some(node) } } #[derive(Clone)] -struct TodoCursor; +struct GritNodeCursor { + node: GritNode, +} + +impl GritNodeCursor { + fn new(node: &GritNode) -> Self { + Self { node: node.clone() } + } +} -impl AstCursor for TodoCursor { +impl AstCursor for GritNodeCursor { type Node = GritNode; fn goto_first_child(&mut self) -> bool { - todo!() + match self.node.first_child() { + Some(child) => { + self.node = child.into(); + true + } + None => false, + } } fn goto_parent(&mut self) -> bool { - todo!() + match self.node.parent() { + Some(parent) => { + self.node = parent; + true + } + None => false, + } } fn goto_next_sibling(&mut self) -> bool { - todo!() + match self.node.next_sibling() { + Some(sibling) => { + self.node = sibling; + true + } + None => false, + } } fn node(&self) -> Self::Node { - todo!() + self.node.clone() } }