From 3d93945bf1a613ccdcd9584ee595d691fb6b3f57 Mon Sep 17 00:00:00 2001 From: Theodore Luo Wang Date: Sun, 3 Oct 2021 15:03:23 -0400 Subject: [PATCH 01/13] Attempt to reduce the allocations needed to iterate through the children of SyntaxNode/SyntaxElement --- src/api.rs | 18 +++++++++++++ src/cursor.rs | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/src/api.rs b/src/api.rs index 6e2cd61..51c6544 100644 --- a/src/api.rs +++ b/src/api.rs @@ -137,6 +137,10 @@ impl SyntaxNode { SyntaxNodeChildren { raw: self.raw.children(), _p: PhantomData } } + pub fn children_matching(&self, matcher: impl Fn(L::Kind) -> bool) -> SyntaxNodeChildrenMatching bool> { + SyntaxNodeChildrenMatching { raw: self.raw.children_matching(move |kind| matcher(L::kind_from_raw(kind))), _p: PhantomData, _p2: PhantomData } + } + pub fn children_with_tokens(&self) -> SyntaxElementChildren { SyntaxElementChildren { raw: self.raw.children_with_tokens(), _p: PhantomData } } @@ -388,6 +392,20 @@ impl Iterator for SyntaxNodeChildren { } } +#[derive(Debug, Clone)] +pub struct SyntaxNodeChildrenMatching bool> { + raw: cursor::SyntaxNodeChildrenMatching, + _p: PhantomData, + _p2: PhantomData, +} + +impl bool> Iterator for SyntaxNodeChildrenMatching { + type Item = SyntaxNode; + fn next(&mut self) -> Option { + self.raw.next().map(SyntaxNode::from) + } +} + #[derive(Debug, Clone)] pub struct SyntaxElementChildren { raw: cursor::SyntaxElementChildren, diff --git a/src/cursor.rs b/src/cursor.rs index 39b0c96..3a57abd 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -388,6 +388,24 @@ impl NodeData { }) }) } + + fn next_sibling_matching(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { + let mut siblings = self.green_siblings().enumerate(); + let index = self.index() as usize; + + siblings.nth(index); + siblings.find_map(|(index, child)| { + if !matcher(child.as_ref().kind()) { + return None; + } + child.as_ref().into_node().and_then(|green| { + let parent = self.parent_node()?; + let offset = parent.offset() + child.rel_offset(); + Some(SyntaxNode::new_child(green, parent, index as u32, offset)) + }) + }) + } + fn prev_sibling(&self) -> Option { let mut rev_siblings = self.green_siblings().enumerate().rev(); let index = rev_siblings.len() - (self.index() as usize); @@ -412,6 +430,7 @@ impl NodeData { Some(SyntaxElement::new(child.as_ref(), parent, index as u32, offset)) }) } + fn prev_sibling_or_token(&self) -> Option { let mut siblings = self.green_siblings().enumerate(); let index = self.index().checked_sub(1)? as usize; @@ -630,6 +649,11 @@ impl SyntaxNode { SyntaxNodeChildren::new(self.clone()) } + #[inline] + pub fn children_matching(&self, matcher: F) -> SyntaxNodeChildrenMatching where F: Fn(SyntaxKind) -> bool { + SyntaxNodeChildrenMatching::new(self.clone(), matcher) + } + #[inline] pub fn children_with_tokens(&self) -> SyntaxElementChildren { SyntaxElementChildren::new(self.clone()) @@ -647,6 +671,23 @@ impl SyntaxNode { }) }) } + + pub fn first_child_matching(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { + self.green_ref().children().raw.enumerate().find_map(|(index, child)| { + if !matcher(child.as_ref().kind()) { + return None; + } + child.as_ref().into_node().map(|green| { + SyntaxNode::new_child( + green, + self.clone(), + index as u32, + self.offset() + child.rel_offset(), + ) + }) + }) + } + pub fn last_child(&self) -> Option { self.green_ref().children().raw.enumerate().rev().find_map(|(index, child)| { child.as_ref().into_node().map(|green| { @@ -679,6 +720,11 @@ impl SyntaxNode { pub fn next_sibling(&self) -> Option { self.data().next_sibling() } + + pub fn next_sibling_matching(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { + self.data().next_sibling_matching(matcher) + } + pub fn prev_sibling(&self) -> Option { self.data().prev_sibling() } @@ -1152,6 +1198,28 @@ impl Iterator for SyntaxNodeChildren { } } +#[derive(Clone, Debug)] +pub struct SyntaxNodeChildrenMatching where F: Fn(SyntaxKind) -> bool { + next: Option, + matcher: F, +} + +impl SyntaxNodeChildrenMatching where F: Fn(SyntaxKind) -> bool { + fn new(parent: SyntaxNode, matcher: F) -> SyntaxNodeChildrenMatching { + SyntaxNodeChildrenMatching { next: parent.first_child_matching(&matcher), matcher } + } +} + +impl Iterator for SyntaxNodeChildrenMatching where F: Fn(SyntaxKind) -> bool { + type Item = SyntaxNode; + fn next(&mut self) -> Option { + self.next.take().map(|next| { + self.next = next.next_sibling_matching(&self.matcher); + next + }) + } +} + #[derive(Clone, Debug)] pub struct SyntaxElementChildren { next: Option, @@ -1173,6 +1241,11 @@ impl Iterator for SyntaxElementChildren { } } +#[derive(Clone, Debug)] +pub struct SyntaxElementChildrenMatching { + next: Option +} + pub struct Preorder { start: SyntaxNode, next: Option>, From fd63d90cf00f4ec8db3df2d53357198691700b9e Mon Sep 17 00:00:00 2001 From: Theodore Luo Wang Date: Sun, 3 Oct 2021 19:23:22 -0400 Subject: [PATCH 02/13] Reduce allocations when looking through children with tokens, remove the generic parameter over Fn(SyntaxKind) from the outwards facing api --- src/api.rs | 29 ++++++++++++++----- src/cursor.rs | 77 +++++++++++++++++++++++++++++++++++++++++++++++---- src/lib.rs | 2 +- 3 files changed, 94 insertions(+), 14 deletions(-) diff --git a/src/api.rs b/src/api.rs index 51c6544..5b17268 100644 --- a/src/api.rs +++ b/src/api.rs @@ -94,7 +94,7 @@ impl From> for SyntaxElement { } } -impl SyntaxNode { +impl<'a, L: Language> SyntaxNode { pub fn new_root(green: GreenNode) -> SyntaxNode { SyntaxNode::from(cursor::SyntaxNode::new_root(green)) } @@ -137,14 +137,18 @@ impl SyntaxNode { SyntaxNodeChildren { raw: self.raw.children(), _p: PhantomData } } - pub fn children_matching(&self, matcher: impl Fn(L::Kind) -> bool) -> SyntaxNodeChildrenMatching bool> { - SyntaxNodeChildrenMatching { raw: self.raw.children_matching(move |kind| matcher(L::kind_from_raw(kind))), _p: PhantomData, _p2: PhantomData } + pub fn children_matching(&self, matcher: fn(SyntaxKind) -> bool) -> SyntaxNodeChildrenMatching { + SyntaxNodeChildrenMatching { raw: self.raw.children_matching(matcher), _p: PhantomData } } pub fn children_with_tokens(&self) -> SyntaxElementChildren { SyntaxElementChildren { raw: self.raw.children_with_tokens(), _p: PhantomData } } + pub fn children_with_tokens_matching(&self, matcher: &'a impl Fn(SyntaxKind) -> bool) -> SyntaxElementChildrenMatching<'a, L> { + SyntaxElementChildrenMatching { raw: self.raw.children_with_tokens_matching(matcher), _p: PhantomData } + } + pub fn first_child(&self) -> Option> { self.raw.first_child().map(Self::from) } @@ -393,13 +397,12 @@ impl Iterator for SyntaxNodeChildren { } #[derive(Debug, Clone)] -pub struct SyntaxNodeChildrenMatching bool> { - raw: cursor::SyntaxNodeChildrenMatching, +pub struct SyntaxNodeChildrenMatching { + raw: cursor::SyntaxNodeChildrenMatching bool>, _p: PhantomData, - _p2: PhantomData, } -impl bool> Iterator for SyntaxNodeChildrenMatching { +impl Iterator for SyntaxNodeChildrenMatching { type Item = SyntaxNode; fn next(&mut self) -> Option { self.raw.next().map(SyntaxNode::from) @@ -419,6 +422,18 @@ impl Iterator for SyntaxElementChildren { } } +pub struct SyntaxElementChildrenMatching<'a, L: Language> { + raw: cursor::SyntaxElementChildrenMatching<&'a dyn Fn(SyntaxKind) -> bool>, + _p: PhantomData, +} + +impl<'a, L: Language> Iterator for SyntaxElementChildrenMatching<'a, L> { + type Item = SyntaxElement; + fn next(&mut self) -> Option { + self.raw.next().map(NodeOrToken::from) + } +} + pub struct Preorder { raw: cursor::Preorder, _p: PhantomData, diff --git a/src/cursor.rs b/src/cursor.rs index 3a57abd..a76f0ff 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -431,6 +431,21 @@ impl NodeData { }) } + fn next_sibling_or_token_matching(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { + let mut siblings = self.green_siblings().enumerate(); + let index = self.index() as usize + 1; + + siblings.nth(index); + siblings.find_map(|(index, child)| { + if !matcher(child.as_ref().kind()) { + return None; + } + let parent = self.parent_node()?; + let offset = parent.offset() + child.rel_offset(); + Some(SyntaxElement::new(child.as_ref(), parent, index as u32, offset)) + }) + } + fn prev_sibling_or_token(&self) -> Option { let mut siblings = self.green_siblings().enumerate(); let index = self.index().checked_sub(1)? as usize; @@ -650,7 +665,7 @@ impl SyntaxNode { } #[inline] - pub fn children_matching(&self, matcher: F) -> SyntaxNodeChildrenMatching where F: Fn(SyntaxKind) -> bool { + pub fn children_matching bool>(&self, matcher: F) -> SyntaxNodeChildrenMatching { SyntaxNodeChildrenMatching::new(self.clone(), matcher) } @@ -659,6 +674,11 @@ impl SyntaxNode { SyntaxElementChildren::new(self.clone()) } + #[inline] + pub fn children_with_tokens_matching bool>(&self, matcher: F) -> SyntaxElementChildrenMatching { + SyntaxElementChildrenMatching::new(self.clone(), matcher) + } + pub fn first_child(&self) -> Option { self.green_ref().children().raw.enumerate().find_map(|(index, child)| { child.as_ref().into_node().map(|green| { @@ -706,6 +726,16 @@ impl SyntaxNode { SyntaxElement::new(child.as_ref(), self.clone(), 0, self.offset() + child.rel_offset()) }) } + + pub fn first_child_or_token_matching(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { + self.green_ref().children().raw.find_map(|child| { + if !matcher(child.as_ref().kind()) { + return None; + } + Some(SyntaxElement::new(child.as_ref(), self.clone(), 0, self.offset() + child.rel_offset())) + }) + } + pub fn last_child_or_token(&self) -> Option { self.green_ref().children().raw.enumerate().next_back().map(|(index, child)| { SyntaxElement::new( @@ -732,6 +762,11 @@ impl SyntaxNode { pub fn next_sibling_or_token(&self) -> Option { self.data().next_sibling_or_token() } + + pub fn next_sibling_or_token_matching(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { + self.data().next_sibling_or_token_matching(matcher) + } + pub fn prev_sibling_or_token(&self) -> Option { self.data().prev_sibling_or_token() } @@ -956,6 +991,11 @@ impl SyntaxToken { pub fn next_sibling_or_token(&self) -> Option { self.data().next_sibling_or_token() } + + pub fn next_sibling_or_token_matching(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { + self.data().next_sibling_or_token_matching(matcher) + } + pub fn prev_sibling_or_token(&self) -> Option { self.data().prev_sibling_or_token() } @@ -1074,6 +1114,14 @@ impl SyntaxElement { NodeOrToken::Token(it) => it.next_sibling_or_token(), } } + + pub fn next_sibling_or_token_matching(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { + match self { + NodeOrToken::Node(it) => it.next_sibling_or_token_matching(matcher), + NodeOrToken::Token(it) => it.next_sibling_or_token_matching(matcher), + } + } + pub fn prev_sibling_or_token(&self) -> Option { match self { NodeOrToken::Node(it) => it.prev_sibling_or_token(), @@ -1199,18 +1247,18 @@ impl Iterator for SyntaxNodeChildren { } #[derive(Clone, Debug)] -pub struct SyntaxNodeChildrenMatching where F: Fn(SyntaxKind) -> bool { +pub struct SyntaxNodeChildrenMatching bool> { next: Option, matcher: F, } -impl SyntaxNodeChildrenMatching where F: Fn(SyntaxKind) -> bool { +impl bool> SyntaxNodeChildrenMatching { fn new(parent: SyntaxNode, matcher: F) -> SyntaxNodeChildrenMatching { SyntaxNodeChildrenMatching { next: parent.first_child_matching(&matcher), matcher } } } -impl Iterator for SyntaxNodeChildrenMatching where F: Fn(SyntaxKind) -> bool { +impl bool> Iterator for SyntaxNodeChildrenMatching { type Item = SyntaxNode; fn next(&mut self) -> Option { self.next.take().map(|next| { @@ -1242,8 +1290,25 @@ impl Iterator for SyntaxElementChildren { } #[derive(Clone, Debug)] -pub struct SyntaxElementChildrenMatching { - next: Option +pub struct SyntaxElementChildrenMatching bool> { + next: Option, + matcher: F, +} + +impl bool> SyntaxElementChildrenMatching { + fn new(parent: SyntaxNode, matcher: F) -> SyntaxElementChildrenMatching { + SyntaxElementChildrenMatching { next: parent.first_child_or_token_matching(&matcher), matcher } + } +} + +impl bool> Iterator for SyntaxElementChildrenMatching { + type Item = SyntaxElement; + fn next(&mut self) -> Option { + self.next.take().map(|next| { + self.next = next.next_sibling_or_token_matching(&self.matcher); + next + }) + } } pub struct Preorder { diff --git a/src/lib.rs b/src/lib.rs index bab6cd9..610fd20 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,7 +29,7 @@ pub use text_size::{TextLen, TextRange, TextSize}; pub use crate::{ api::{ - Language, SyntaxElement, SyntaxElementChildren, SyntaxNode, SyntaxNodeChildren, SyntaxToken, + Language, SyntaxElement, SyntaxElementChildren, SyntaxNode, SyntaxNodeChildren, SyntaxNodeChildrenMatching, SyntaxToken, }, green::{ Checkpoint, Children, GreenNode, GreenNodeBuilder, GreenNodeData, GreenToken, From 05e47e989e6dd27804b37e53e647babef3d8a777 Mon Sep 17 00:00:00 2001 From: Teddy_Wang Date: Sun, 3 Oct 2021 19:26:51 -0400 Subject: [PATCH 03/13] Run cargo fmt --- src/api.rs | 15 +++++++++++--- src/cursor.rs | 57 +++++++++++++++++++++++++++++++++++++++++---------- src/lib.rs | 3 ++- 3 files changed, 60 insertions(+), 15 deletions(-) diff --git a/src/api.rs b/src/api.rs index 5b17268..43830fd 100644 --- a/src/api.rs +++ b/src/api.rs @@ -137,7 +137,10 @@ impl<'a, L: Language> SyntaxNode { SyntaxNodeChildren { raw: self.raw.children(), _p: PhantomData } } - pub fn children_matching(&self, matcher: fn(SyntaxKind) -> bool) -> SyntaxNodeChildrenMatching { + pub fn children_matching( + &self, + matcher: fn(SyntaxKind) -> bool, + ) -> SyntaxNodeChildrenMatching { SyntaxNodeChildrenMatching { raw: self.raw.children_matching(matcher), _p: PhantomData } } @@ -145,8 +148,14 @@ impl<'a, L: Language> SyntaxNode { SyntaxElementChildren { raw: self.raw.children_with_tokens(), _p: PhantomData } } - pub fn children_with_tokens_matching(&self, matcher: &'a impl Fn(SyntaxKind) -> bool) -> SyntaxElementChildrenMatching<'a, L> { - SyntaxElementChildrenMatching { raw: self.raw.children_with_tokens_matching(matcher), _p: PhantomData } + pub fn children_with_tokens_matching( + &self, + matcher: &'a impl Fn(SyntaxKind) -> bool, + ) -> SyntaxElementChildrenMatching<'a, L> { + SyntaxElementChildrenMatching { + raw: self.raw.children_with_tokens_matching(matcher), + _p: PhantomData, + } } pub fn first_child(&self) -> Option> { diff --git a/src/cursor.rs b/src/cursor.rs index a76f0ff..87a47b3 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -431,7 +431,10 @@ impl NodeData { }) } - fn next_sibling_or_token_matching(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { + fn next_sibling_or_token_matching( + &self, + matcher: &impl Fn(SyntaxKind) -> bool, + ) -> Option { let mut siblings = self.green_siblings().enumerate(); let index = self.index() as usize + 1; @@ -665,7 +668,10 @@ impl SyntaxNode { } #[inline] - pub fn children_matching bool>(&self, matcher: F) -> SyntaxNodeChildrenMatching { + pub fn children_matching bool>( + &self, + matcher: F, + ) -> SyntaxNodeChildrenMatching { SyntaxNodeChildrenMatching::new(self.clone(), matcher) } @@ -675,7 +681,10 @@ impl SyntaxNode { } #[inline] - pub fn children_with_tokens_matching bool>(&self, matcher: F) -> SyntaxElementChildrenMatching { + pub fn children_with_tokens_matching bool>( + &self, + matcher: F, + ) -> SyntaxElementChildrenMatching { SyntaxElementChildrenMatching::new(self.clone(), matcher) } @@ -692,7 +701,10 @@ impl SyntaxNode { }) } - pub fn first_child_matching(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { + pub fn first_child_matching( + &self, + matcher: &impl Fn(SyntaxKind) -> bool, + ) -> Option { self.green_ref().children().raw.enumerate().find_map(|(index, child)| { if !matcher(child.as_ref().kind()) { return None; @@ -727,12 +739,20 @@ impl SyntaxNode { }) } - pub fn first_child_or_token_matching(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { + pub fn first_child_or_token_matching( + &self, + matcher: &impl Fn(SyntaxKind) -> bool, + ) -> Option { self.green_ref().children().raw.find_map(|child| { if !matcher(child.as_ref().kind()) { return None; } - Some(SyntaxElement::new(child.as_ref(), self.clone(), 0, self.offset() + child.rel_offset())) + Some(SyntaxElement::new( + child.as_ref(), + self.clone(), + 0, + self.offset() + child.rel_offset(), + )) }) } @@ -751,7 +771,10 @@ impl SyntaxNode { self.data().next_sibling() } - pub fn next_sibling_matching(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { + pub fn next_sibling_matching( + &self, + matcher: &impl Fn(SyntaxKind) -> bool, + ) -> Option { self.data().next_sibling_matching(matcher) } @@ -763,7 +786,10 @@ impl SyntaxNode { self.data().next_sibling_or_token() } - pub fn next_sibling_or_token_matching(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { + pub fn next_sibling_or_token_matching( + &self, + matcher: &impl Fn(SyntaxKind) -> bool, + ) -> Option { self.data().next_sibling_or_token_matching(matcher) } @@ -992,7 +1018,10 @@ impl SyntaxToken { self.data().next_sibling_or_token() } - pub fn next_sibling_or_token_matching(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { + pub fn next_sibling_or_token_matching( + &self, + matcher: &impl Fn(SyntaxKind) -> bool, + ) -> Option { self.data().next_sibling_or_token_matching(matcher) } @@ -1115,7 +1144,10 @@ impl SyntaxElement { } } - pub fn next_sibling_or_token_matching(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { + pub fn next_sibling_or_token_matching( + &self, + matcher: &impl Fn(SyntaxKind) -> bool, + ) -> Option { match self { NodeOrToken::Node(it) => it.next_sibling_or_token_matching(matcher), NodeOrToken::Token(it) => it.next_sibling_or_token_matching(matcher), @@ -1297,7 +1329,10 @@ pub struct SyntaxElementChildrenMatching bool> { impl bool> SyntaxElementChildrenMatching { fn new(parent: SyntaxNode, matcher: F) -> SyntaxElementChildrenMatching { - SyntaxElementChildrenMatching { next: parent.first_child_or_token_matching(&matcher), matcher } + SyntaxElementChildrenMatching { + next: parent.first_child_or_token_matching(&matcher), + matcher, + } } } diff --git a/src/lib.rs b/src/lib.rs index 610fd20..dd84412 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,7 +29,8 @@ pub use text_size::{TextLen, TextRange, TextSize}; pub use crate::{ api::{ - Language, SyntaxElement, SyntaxElementChildren, SyntaxNode, SyntaxNodeChildren, SyntaxNodeChildrenMatching, SyntaxToken, + Language, SyntaxElement, SyntaxElementChildren, SyntaxNode, SyntaxNodeChildren, + SyntaxNodeChildrenMatching, SyntaxToken, }, green::{ Checkpoint, Children, GreenNode, GreenNodeBuilder, GreenNodeData, GreenToken, From 9b9691594c087db5f2566722c36d5dc1517b244d Mon Sep 17 00:00:00 2001 From: Theodore Luo Wang Date: Sun, 3 Oct 2021 19:59:37 -0400 Subject: [PATCH 04/13] Moved 'a to children_with_tokens_matching --- src/api.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api.rs b/src/api.rs index 43830fd..2a393cf 100644 --- a/src/api.rs +++ b/src/api.rs @@ -94,7 +94,7 @@ impl From> for SyntaxElement { } } -impl<'a, L: Language> SyntaxNode { +impl SyntaxNode { pub fn new_root(green: GreenNode) -> SyntaxNode { SyntaxNode::from(cursor::SyntaxNode::new_root(green)) } @@ -148,7 +148,7 @@ impl<'a, L: Language> SyntaxNode { SyntaxElementChildren { raw: self.raw.children_with_tokens(), _p: PhantomData } } - pub fn children_with_tokens_matching( + pub fn children_with_tokens_matching<'a>( &self, matcher: &'a impl Fn(SyntaxKind) -> bool, ) -> SyntaxElementChildrenMatching<'a, L> { From 5d62e454eea6850ebbd3c41ac4acc8f5ab00c1c0 Mon Sep 17 00:00:00 2001 From: Theodore Luo Wang Date: Sat, 23 Oct 2021 16:45:11 -0400 Subject: [PATCH 05/13] Expose the api as children().by_kind --- src/api.rs | 50 ++++++++++++++++++++++-------------------- src/cursor.rs | 60 +++++++++++++++++++++++++-------------------------- 2 files changed, 56 insertions(+), 54 deletions(-) diff --git a/src/api.rs b/src/api.rs index 2a393cf..5c9d4f7 100644 --- a/src/api.rs +++ b/src/api.rs @@ -137,27 +137,10 @@ impl SyntaxNode { SyntaxNodeChildren { raw: self.raw.children(), _p: PhantomData } } - pub fn children_matching( - &self, - matcher: fn(SyntaxKind) -> bool, - ) -> SyntaxNodeChildrenMatching { - SyntaxNodeChildrenMatching { raw: self.raw.children_matching(matcher), _p: PhantomData } - } - pub fn children_with_tokens(&self) -> SyntaxElementChildren { SyntaxElementChildren { raw: self.raw.children_with_tokens(), _p: PhantomData } } - pub fn children_with_tokens_matching<'a>( - &self, - matcher: &'a impl Fn(SyntaxKind) -> bool, - ) -> SyntaxElementChildrenMatching<'a, L> { - SyntaxElementChildrenMatching { - raw: self.raw.children_with_tokens_matching(matcher), - _p: PhantomData, - } - } - pub fn first_child(&self) -> Option> { self.raw.first_child().map(Self::from) } @@ -405,13 +388,22 @@ impl Iterator for SyntaxNodeChildren { } } +impl SyntaxNodeChildren { + pub fn by_kind bool>( + self, + matcher: F, + ) -> SyntaxNodeChildrenMatching { + SyntaxNodeChildrenMatching { raw: self.raw.by_kind(matcher), _p: PhantomData } + } +} + #[derive(Debug, Clone)] -pub struct SyntaxNodeChildrenMatching { - raw: cursor::SyntaxNodeChildrenMatching bool>, +pub struct SyntaxNodeChildrenMatching bool, L: Language> { + raw: cursor::SyntaxNodeChildrenMatching, _p: PhantomData, } -impl Iterator for SyntaxNodeChildrenMatching { +impl bool, L: Language> Iterator for SyntaxNodeChildrenMatching { type Item = SyntaxNode; fn next(&mut self) -> Option { self.raw.next().map(SyntaxNode::from) @@ -431,12 +423,24 @@ impl Iterator for SyntaxElementChildren { } } -pub struct SyntaxElementChildrenMatching<'a, L: Language> { - raw: cursor::SyntaxElementChildrenMatching<&'a dyn Fn(SyntaxKind) -> bool>, +impl SyntaxElementChildren { + pub fn by_kind bool>( + self, + matcher: F, + ) -> SyntaxElementChildrenMatching { + SyntaxElementChildrenMatching { raw: self.raw.by_kind(matcher), _p: PhantomData } + } +} + +#[derive(Debug, Clone)] +pub struct SyntaxElementChildrenMatching bool, L: Language> { + raw: cursor::SyntaxElementChildrenMatching, _p: PhantomData, } -impl<'a, L: Language> Iterator for SyntaxElementChildrenMatching<'a, L> { +impl bool, L: Language> Iterator + for SyntaxElementChildrenMatching +{ type Item = SyntaxElement; fn next(&mut self) -> Option { self.raw.next().map(NodeOrToken::from) diff --git a/src/cursor.rs b/src/cursor.rs index 87a47b3..3d99d18 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -667,27 +667,11 @@ impl SyntaxNode { SyntaxNodeChildren::new(self.clone()) } - #[inline] - pub fn children_matching bool>( - &self, - matcher: F, - ) -> SyntaxNodeChildrenMatching { - SyntaxNodeChildrenMatching::new(self.clone(), matcher) - } - #[inline] pub fn children_with_tokens(&self) -> SyntaxElementChildren { SyntaxElementChildren::new(self.clone()) } - #[inline] - pub fn children_with_tokens_matching bool>( - &self, - matcher: F, - ) -> SyntaxElementChildrenMatching { - SyntaxElementChildrenMatching::new(self.clone(), matcher) - } - pub fn first_child(&self) -> Option { self.green_ref().children().raw.enumerate().find_map(|(index, child)| { child.as_ref().into_node().map(|green| { @@ -1266,6 +1250,19 @@ impl SyntaxNodeChildren { fn new(parent: SyntaxNode) -> SyntaxNodeChildren { SyntaxNodeChildren { next: parent.first_child() } } + + pub fn by_kind bool>(self, matcher: F) -> SyntaxNodeChildrenMatching { + SyntaxNodeChildrenMatching { + next: self.next.and_then(|node| { + if matcher(node.kind()) { + Some(node) + } else { + node.next_sibling_matching(&matcher) + } + }), + matcher, + } + } } impl Iterator for SyntaxNodeChildren { @@ -1284,12 +1281,6 @@ pub struct SyntaxNodeChildrenMatching bool> { matcher: F, } -impl bool> SyntaxNodeChildrenMatching { - fn new(parent: SyntaxNode, matcher: F) -> SyntaxNodeChildrenMatching { - SyntaxNodeChildrenMatching { next: parent.first_child_matching(&matcher), matcher } - } -} - impl bool> Iterator for SyntaxNodeChildrenMatching { type Item = SyntaxNode; fn next(&mut self) -> Option { @@ -1309,6 +1300,22 @@ impl SyntaxElementChildren { fn new(parent: SyntaxNode) -> SyntaxElementChildren { SyntaxElementChildren { next: parent.first_child_or_token() } } + + pub fn by_kind bool>( + self, + matcher: F, + ) -> SyntaxElementChildrenMatching { + SyntaxElementChildrenMatching { + next: self.next.and_then(|node| { + if matcher(node.kind()) { + Some(node) + } else { + node.next_sibling_or_token_matching(&matcher) + } + }), + matcher, + } + } } impl Iterator for SyntaxElementChildren { @@ -1327,15 +1334,6 @@ pub struct SyntaxElementChildrenMatching bool> { matcher: F, } -impl bool> SyntaxElementChildrenMatching { - fn new(parent: SyntaxNode, matcher: F) -> SyntaxElementChildrenMatching { - SyntaxElementChildrenMatching { - next: parent.first_child_or_token_matching(&matcher), - matcher, - } - } -} - impl bool> Iterator for SyntaxElementChildrenMatching { type Item = SyntaxElement; fn next(&mut self) -> Option { From 0dad0881fc36608487c57a12bcf451c1f463337a Mon Sep 17 00:00:00 2001 From: Theodore Luo Wang Date: Sat, 23 Oct 2021 18:12:38 -0400 Subject: [PATCH 06/13] Remove unnecessary functions, fix off-by-one error --- src/cursor.rs | 38 +------------------------------------- 1 file changed, 1 insertion(+), 37 deletions(-) diff --git a/src/cursor.rs b/src/cursor.rs index 3d99d18..1d6f87c 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -436,7 +436,7 @@ impl NodeData { matcher: &impl Fn(SyntaxKind) -> bool, ) -> Option { let mut siblings = self.green_siblings().enumerate(); - let index = self.index() as usize + 1; + let index = self.index() as usize; siblings.nth(index); siblings.find_map(|(index, child)| { @@ -685,25 +685,6 @@ impl SyntaxNode { }) } - pub fn first_child_matching( - &self, - matcher: &impl Fn(SyntaxKind) -> bool, - ) -> Option { - self.green_ref().children().raw.enumerate().find_map(|(index, child)| { - if !matcher(child.as_ref().kind()) { - return None; - } - child.as_ref().into_node().map(|green| { - SyntaxNode::new_child( - green, - self.clone(), - index as u32, - self.offset() + child.rel_offset(), - ) - }) - }) - } - pub fn last_child(&self) -> Option { self.green_ref().children().raw.enumerate().rev().find_map(|(index, child)| { child.as_ref().into_node().map(|green| { @@ -723,23 +704,6 @@ impl SyntaxNode { }) } - pub fn first_child_or_token_matching( - &self, - matcher: &impl Fn(SyntaxKind) -> bool, - ) -> Option { - self.green_ref().children().raw.find_map(|child| { - if !matcher(child.as_ref().kind()) { - return None; - } - Some(SyntaxElement::new( - child.as_ref(), - self.clone(), - 0, - self.offset() + child.rel_offset(), - )) - }) - } - pub fn last_child_or_token(&self) -> Option { self.green_ref().children().raw.enumerate().next_back().map(|(index, child)| { SyntaxElement::new( From 94b039c9d1113367b29f62ef21aff205833edd46 Mon Sep 17 00:00:00 2001 From: Theodore Luo Wang Date: Sat, 23 Oct 2021 23:20:47 -0400 Subject: [PATCH 07/13] Lazily create SyntaxNodeChildren::next and SyntaxElementChildren::next (i.e, only if we start iterating through them) to avoid some unnecessary allocations when calling by_kind --- src/cursor.rs | 102 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 20 deletions(-) diff --git a/src/cursor.rs b/src/cursor.rs index 1d6f87c..4c6d7cb 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -685,6 +685,25 @@ impl SyntaxNode { }) } + pub fn first_child_matching( + &self, + matcher: &impl Fn(SyntaxKind) -> bool, + ) -> Option { + self.green_ref().children().raw.enumerate().find_map(|(index, child)| { + if !matcher(child.as_ref().kind()) { + return None; + } + child.as_ref().into_node().map(|green| { + SyntaxNode::new_child( + green, + self.clone(), + index as u32, + self.offset() + child.rel_offset(), + ) + }) + }) + } + pub fn last_child(&self) -> Option { self.green_ref().children().raw.enumerate().rev().find_map(|(index, child)| { child.as_ref().into_node().map(|green| { @@ -704,6 +723,23 @@ impl SyntaxNode { }) } + pub fn first_child_or_token_matching( + &self, + matcher: &impl Fn(SyntaxKind) -> bool, + ) -> Option { + self.green_ref().children().raw.enumerate().find_map(|(index, child)| { + if !matcher(child.as_ref().kind()) { + return None; + } + Some(SyntaxElement::new( + child.as_ref(), + self.clone(), + index as u32, + self.offset() + child.rel_offset(), + )) + }) + } + pub fn last_child_or_token(&self) -> Option { self.green_ref().children().raw.enumerate().next_back().map(|(index, child)| { SyntaxElement::new( @@ -1207,24 +1243,33 @@ impl From for SyntaxElement { #[derive(Clone, Debug)] pub struct SyntaxNodeChildren { + parent: SyntaxNode, next: Option, + next_initialized: bool } impl SyntaxNodeChildren { fn new(parent: SyntaxNode) -> SyntaxNodeChildren { - SyntaxNodeChildren { next: parent.first_child() } + SyntaxNodeChildren { parent, next: None, next_initialized: false } } pub fn by_kind bool>(self, matcher: F) -> SyntaxNodeChildrenMatching { - SyntaxNodeChildrenMatching { - next: self.next.and_then(|node| { - if matcher(node.kind()) { - Some(node) - } else { - node.next_sibling_matching(&matcher) - } - }), - matcher, + if !self.next_initialized { + SyntaxNodeChildrenMatching { + next: self.parent.first_child_matching(&matcher), + matcher, + } + } else { + SyntaxNodeChildrenMatching { + next: self.next.and_then(|node| { + if matcher(node.kind()) { + Some(node) + } else { + node.next_sibling_matching(&matcher) + } + }), + matcher, + } } } } @@ -1232,6 +1277,10 @@ impl SyntaxNodeChildren { impl Iterator for SyntaxNodeChildren { type Item = SyntaxNode; fn next(&mut self) -> Option { + if !self.next_initialized { + self.next = self.parent.first_child(); + self.next_initialized = true; + } self.next.take().map(|next| { self.next = next.next_sibling(); next @@ -1257,27 +1306,36 @@ impl bool> Iterator for SyntaxNodeChildrenMatching { #[derive(Clone, Debug)] pub struct SyntaxElementChildren { + parent: SyntaxNode, next: Option, + next_initialized: bool } impl SyntaxElementChildren { fn new(parent: SyntaxNode) -> SyntaxElementChildren { - SyntaxElementChildren { next: parent.first_child_or_token() } + SyntaxElementChildren { parent, next: None, next_initialized: false } } pub fn by_kind bool>( self, matcher: F, ) -> SyntaxElementChildrenMatching { - SyntaxElementChildrenMatching { - next: self.next.and_then(|node| { - if matcher(node.kind()) { - Some(node) - } else { - node.next_sibling_or_token_matching(&matcher) - } - }), - matcher, + if !self.next_initialized { + SyntaxElementChildrenMatching { + next: self.parent.first_child_or_token_matching(&matcher), + matcher, + } + } else { + SyntaxElementChildrenMatching { + next: self.next.and_then(|node| { + if matcher(node.kind()) { + Some(node) + } else { + node.next_sibling_or_token_matching(&matcher) + } + }), + matcher, + } } } } @@ -1285,6 +1343,10 @@ impl SyntaxElementChildren { impl Iterator for SyntaxElementChildren { type Item = SyntaxElement; fn next(&mut self) -> Option { + if !self.next_initialized { + self.next = self.parent.first_child_or_token(); + self.next_initialized = true; + } self.next.take().map(|next| { self.next = next.next_sibling_or_token(); next From bff5da8b05d73bdd8decc7b7e3973e983ad09aa2 Mon Sep 17 00:00:00 2001 From: Theodore Luo Wang Date: Sat, 23 Oct 2021 23:21:07 -0400 Subject: [PATCH 08/13] Run cargo fmt --- src/cursor.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/cursor.rs b/src/cursor.rs index 4c6d7cb..da52d9c 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -1245,7 +1245,7 @@ impl From for SyntaxElement { pub struct SyntaxNodeChildren { parent: SyntaxNode, next: Option, - next_initialized: bool + next_initialized: bool, } impl SyntaxNodeChildren { @@ -1255,10 +1255,7 @@ impl SyntaxNodeChildren { pub fn by_kind bool>(self, matcher: F) -> SyntaxNodeChildrenMatching { if !self.next_initialized { - SyntaxNodeChildrenMatching { - next: self.parent.first_child_matching(&matcher), - matcher, - } + SyntaxNodeChildrenMatching { next: self.parent.first_child_matching(&matcher), matcher } } else { SyntaxNodeChildrenMatching { next: self.next.and_then(|node| { @@ -1308,7 +1305,7 @@ impl bool> Iterator for SyntaxNodeChildrenMatching { pub struct SyntaxElementChildren { parent: SyntaxNode, next: Option, - next_initialized: bool + next_initialized: bool, } impl SyntaxElementChildren { @@ -1321,7 +1318,7 @@ impl SyntaxElementChildren { matcher: F, ) -> SyntaxElementChildrenMatching { if !self.next_initialized { - SyntaxElementChildrenMatching { + SyntaxElementChildrenMatching { next: self.parent.first_child_or_token_matching(&matcher), matcher, } From 8ba46a78d6d59e04ab88117ff473fd8d82191b6c Mon Sep 17 00:00:00 2001 From: Theodore Luo Wang Date: Sun, 24 Oct 2021 11:45:48 -0400 Subject: [PATCH 09/13] Change Syntax*ChildrenMatching -> Syntax*ChildrenByKind --- src/api.rs | 20 ++++++++++---------- src/cursor.rs | 20 ++++++++++---------- src/lib.rs | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/api.rs b/src/api.rs index 5c9d4f7..7525f5a 100644 --- a/src/api.rs +++ b/src/api.rs @@ -392,18 +392,18 @@ impl SyntaxNodeChildren { pub fn by_kind bool>( self, matcher: F, - ) -> SyntaxNodeChildrenMatching { - SyntaxNodeChildrenMatching { raw: self.raw.by_kind(matcher), _p: PhantomData } + ) -> SyntaxNodeChildrenByKind { + SyntaxNodeChildrenByKind { raw: self.raw.by_kind(matcher), _p: PhantomData } } } #[derive(Debug, Clone)] -pub struct SyntaxNodeChildrenMatching bool, L: Language> { - raw: cursor::SyntaxNodeChildrenMatching, +pub struct SyntaxNodeChildrenByKind bool, L: Language> { + raw: cursor::SyntaxNodeChildrenByKind, _p: PhantomData, } -impl bool, L: Language> Iterator for SyntaxNodeChildrenMatching { +impl bool, L: Language> Iterator for SyntaxNodeChildrenByKind { type Item = SyntaxNode; fn next(&mut self) -> Option { self.raw.next().map(SyntaxNode::from) @@ -427,19 +427,19 @@ impl SyntaxElementChildren { pub fn by_kind bool>( self, matcher: F, - ) -> SyntaxElementChildrenMatching { - SyntaxElementChildrenMatching { raw: self.raw.by_kind(matcher), _p: PhantomData } + ) -> SyntaxElementChildrenByKind { + SyntaxElementChildrenByKind { raw: self.raw.by_kind(matcher), _p: PhantomData } } } #[derive(Debug, Clone)] -pub struct SyntaxElementChildrenMatching bool, L: Language> { - raw: cursor::SyntaxElementChildrenMatching, +pub struct SyntaxElementChildrenByKind bool, L: Language> { + raw: cursor::SyntaxElementChildrenByKind, _p: PhantomData, } impl bool, L: Language> Iterator - for SyntaxElementChildrenMatching + for SyntaxElementChildrenByKind { type Item = SyntaxElement; fn next(&mut self) -> Option { diff --git a/src/cursor.rs b/src/cursor.rs index da52d9c..6987b61 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -1253,11 +1253,11 @@ impl SyntaxNodeChildren { SyntaxNodeChildren { parent, next: None, next_initialized: false } } - pub fn by_kind bool>(self, matcher: F) -> SyntaxNodeChildrenMatching { + pub fn by_kind bool>(self, matcher: F) -> SyntaxNodeChildrenByKind { if !self.next_initialized { - SyntaxNodeChildrenMatching { next: self.parent.first_child_matching(&matcher), matcher } + SyntaxNodeChildrenByKind { next: self.parent.first_child_matching(&matcher), matcher } } else { - SyntaxNodeChildrenMatching { + SyntaxNodeChildrenByKind { next: self.next.and_then(|node| { if matcher(node.kind()) { Some(node) @@ -1286,12 +1286,12 @@ impl Iterator for SyntaxNodeChildren { } #[derive(Clone, Debug)] -pub struct SyntaxNodeChildrenMatching bool> { +pub struct SyntaxNodeChildrenByKind bool> { next: Option, matcher: F, } -impl bool> Iterator for SyntaxNodeChildrenMatching { +impl bool> Iterator for SyntaxNodeChildrenByKind { type Item = SyntaxNode; fn next(&mut self) -> Option { self.next.take().map(|next| { @@ -1316,14 +1316,14 @@ impl SyntaxElementChildren { pub fn by_kind bool>( self, matcher: F, - ) -> SyntaxElementChildrenMatching { + ) -> SyntaxElementChildrenByKind { if !self.next_initialized { - SyntaxElementChildrenMatching { + SyntaxElementChildrenByKind { next: self.parent.first_child_or_token_matching(&matcher), matcher, } } else { - SyntaxElementChildrenMatching { + SyntaxElementChildrenByKind { next: self.next.and_then(|node| { if matcher(node.kind()) { Some(node) @@ -1352,12 +1352,12 @@ impl Iterator for SyntaxElementChildren { } #[derive(Clone, Debug)] -pub struct SyntaxElementChildrenMatching bool> { +pub struct SyntaxElementChildrenByKind bool> { next: Option, matcher: F, } -impl bool> Iterator for SyntaxElementChildrenMatching { +impl bool> Iterator for SyntaxElementChildrenByKind { type Item = SyntaxElement; fn next(&mut self) -> Option { self.next.take().map(|next| { diff --git a/src/lib.rs b/src/lib.rs index dd84412..2994b05 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,7 +30,7 @@ pub use text_size::{TextLen, TextRange, TextSize}; pub use crate::{ api::{ Language, SyntaxElement, SyntaxElementChildren, SyntaxNode, SyntaxNodeChildren, - SyntaxNodeChildrenMatching, SyntaxToken, + SyntaxNodeChildrenByKind, SyntaxToken, }, green::{ Checkpoint, Children, GreenNode, GreenNodeBuilder, GreenNodeData, GreenToken, From 2b94548ea7a2cc53db746767d4125535550ee3b8 Mon Sep 17 00:00:00 2001 From: Theodore Luo Wang Date: Sun, 24 Oct 2021 11:46:09 -0400 Subject: [PATCH 10/13] Run cargo fmt --- src/cursor.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cursor.rs b/src/cursor.rs index 6987b61..6739dba 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -1313,10 +1313,7 @@ impl SyntaxElementChildren { SyntaxElementChildren { parent, next: None, next_initialized: false } } - pub fn by_kind bool>( - self, - matcher: F, - ) -> SyntaxElementChildrenByKind { + pub fn by_kind bool>(self, matcher: F) -> SyntaxElementChildrenByKind { if !self.next_initialized { SyntaxElementChildrenByKind { next: self.parent.first_child_or_token_matching(&matcher), From 3f283c954af90a7c90b1d746f8695bf03dc47bf6 Mon Sep 17 00:00:00 2001 From: Theodore Luo Wang Date: Sun, 24 Oct 2021 13:25:42 -0400 Subject: [PATCH 11/13] Change function names to use by_kind instead of matching. Use &dyn Fn instead of generic impl Fn. --- src/api.rs | 42 ++++++++++++++++++++++++++---------------- src/cursor.rs | 41 +++++++++++++++++++---------------------- 2 files changed, 45 insertions(+), 38 deletions(-) diff --git a/src/api.rs b/src/api.rs index 7525f5a..20ee5ac 100644 --- a/src/api.rs +++ b/src/api.rs @@ -389,27 +389,33 @@ impl Iterator for SyntaxNodeChildren { } impl SyntaxNodeChildren { - pub fn by_kind bool>( + pub fn by_kind<'a>( self, - matcher: F, - ) -> SyntaxNodeChildrenByKind { + matcher: &'a impl Fn(SyntaxKind) -> bool, + ) -> SyntaxNodeChildrenByKind<'a, L> { SyntaxNodeChildrenByKind { raw: self.raw.by_kind(matcher), _p: PhantomData } } } -#[derive(Debug, Clone)] -pub struct SyntaxNodeChildrenByKind bool, L: Language> { - raw: cursor::SyntaxNodeChildrenByKind, +#[derive(Clone)] +pub struct SyntaxNodeChildrenByKind<'a, L: Language> { + raw: cursor::SyntaxNodeChildrenByKind<&'a dyn Fn(SyntaxKind) -> bool>, _p: PhantomData, } -impl bool, L: Language> Iterator for SyntaxNodeChildrenByKind { +impl<'a, L: Language> Iterator for SyntaxNodeChildrenByKind<'a, L> { type Item = SyntaxNode; fn next(&mut self) -> Option { self.raw.next().map(SyntaxNode::from) } } +impl<'a, L: Language> fmt::Debug for SyntaxNodeChildrenByKind<'a, L> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SyntaxNodeChildrenByKind").finish() + } +} + #[derive(Debug, Clone)] pub struct SyntaxElementChildren { raw: cursor::SyntaxElementChildren, @@ -424,29 +430,33 @@ impl Iterator for SyntaxElementChildren { } impl SyntaxElementChildren { - pub fn by_kind bool>( + pub fn by_kind<'a>( self, - matcher: F, - ) -> SyntaxElementChildrenByKind { + matcher: &'a impl Fn(SyntaxKind) -> bool, + ) -> SyntaxElementChildrenByKind<'a, L> { SyntaxElementChildrenByKind { raw: self.raw.by_kind(matcher), _p: PhantomData } } } -#[derive(Debug, Clone)] -pub struct SyntaxElementChildrenByKind bool, L: Language> { - raw: cursor::SyntaxElementChildrenByKind, +#[derive(Clone)] +pub struct SyntaxElementChildrenByKind<'a, L: Language> { + raw: cursor::SyntaxElementChildrenByKind<&'a dyn Fn(SyntaxKind) -> bool>, _p: PhantomData, } -impl bool, L: Language> Iterator - for SyntaxElementChildrenByKind -{ +impl<'a, L: Language> Iterator for SyntaxElementChildrenByKind<'a, L> { type Item = SyntaxElement; fn next(&mut self) -> Option { self.raw.next().map(NodeOrToken::from) } } +impl<'a, L: Language> fmt::Debug for SyntaxElementChildrenByKind<'a, L> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SyntaxElementChildrenByKind").finish() + } +} + pub struct Preorder { raw: cursor::Preorder, _p: PhantomData, diff --git a/src/cursor.rs b/src/cursor.rs index 6739dba..e486fe4 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -389,7 +389,7 @@ impl NodeData { }) } - fn next_sibling_matching(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { + fn next_sibling_by_kind(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { let mut siblings = self.green_siblings().enumerate(); let index = self.index() as usize; @@ -431,7 +431,7 @@ impl NodeData { }) } - fn next_sibling_or_token_matching( + fn next_sibling_or_token_by_kind( &self, matcher: &impl Fn(SyntaxKind) -> bool, ) -> Option { @@ -685,10 +685,7 @@ impl SyntaxNode { }) } - pub fn first_child_matching( - &self, - matcher: &impl Fn(SyntaxKind) -> bool, - ) -> Option { + pub fn first_child_by_kind(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { self.green_ref().children().raw.enumerate().find_map(|(index, child)| { if !matcher(child.as_ref().kind()) { return None; @@ -723,7 +720,7 @@ impl SyntaxNode { }) } - pub fn first_child_or_token_matching( + pub fn first_child_or_token_by_kind( &self, matcher: &impl Fn(SyntaxKind) -> bool, ) -> Option { @@ -755,11 +752,11 @@ impl SyntaxNode { self.data().next_sibling() } - pub fn next_sibling_matching( + pub fn next_sibling_by_kind( &self, matcher: &impl Fn(SyntaxKind) -> bool, ) -> Option { - self.data().next_sibling_matching(matcher) + self.data().next_sibling_by_kind(matcher) } pub fn prev_sibling(&self) -> Option { @@ -770,11 +767,11 @@ impl SyntaxNode { self.data().next_sibling_or_token() } - pub fn next_sibling_or_token_matching( + pub fn next_sibling_or_token_by_kind( &self, matcher: &impl Fn(SyntaxKind) -> bool, ) -> Option { - self.data().next_sibling_or_token_matching(matcher) + self.data().next_sibling_or_token_by_kind(matcher) } pub fn prev_sibling_or_token(&self) -> Option { @@ -1002,11 +999,11 @@ impl SyntaxToken { self.data().next_sibling_or_token() } - pub fn next_sibling_or_token_matching( + pub fn next_sibling_or_token_by_kind( &self, matcher: &impl Fn(SyntaxKind) -> bool, ) -> Option { - self.data().next_sibling_or_token_matching(matcher) + self.data().next_sibling_or_token_by_kind(matcher) } pub fn prev_sibling_or_token(&self) -> Option { @@ -1128,13 +1125,13 @@ impl SyntaxElement { } } - pub fn next_sibling_or_token_matching( + pub fn next_sibling_or_token_by_kind( &self, matcher: &impl Fn(SyntaxKind) -> bool, ) -> Option { match self { - NodeOrToken::Node(it) => it.next_sibling_or_token_matching(matcher), - NodeOrToken::Token(it) => it.next_sibling_or_token_matching(matcher), + NodeOrToken::Node(it) => it.next_sibling_or_token_by_kind(matcher), + NodeOrToken::Token(it) => it.next_sibling_or_token_by_kind(matcher), } } @@ -1255,14 +1252,14 @@ impl SyntaxNodeChildren { pub fn by_kind bool>(self, matcher: F) -> SyntaxNodeChildrenByKind { if !self.next_initialized { - SyntaxNodeChildrenByKind { next: self.parent.first_child_matching(&matcher), matcher } + SyntaxNodeChildrenByKind { next: self.parent.first_child_by_kind(&matcher), matcher } } else { SyntaxNodeChildrenByKind { next: self.next.and_then(|node| { if matcher(node.kind()) { Some(node) } else { - node.next_sibling_matching(&matcher) + node.next_sibling_by_kind(&matcher) } }), matcher, @@ -1295,7 +1292,7 @@ impl bool> Iterator for SyntaxNodeChildrenByKind { type Item = SyntaxNode; fn next(&mut self) -> Option { self.next.take().map(|next| { - self.next = next.next_sibling_matching(&self.matcher); + self.next = next.next_sibling_by_kind(&self.matcher); next }) } @@ -1316,7 +1313,7 @@ impl SyntaxElementChildren { pub fn by_kind bool>(self, matcher: F) -> SyntaxElementChildrenByKind { if !self.next_initialized { SyntaxElementChildrenByKind { - next: self.parent.first_child_or_token_matching(&matcher), + next: self.parent.first_child_or_token_by_kind(&matcher), matcher, } } else { @@ -1325,7 +1322,7 @@ impl SyntaxElementChildren { if matcher(node.kind()) { Some(node) } else { - node.next_sibling_or_token_matching(&matcher) + node.next_sibling_or_token_by_kind(&matcher) } }), matcher, @@ -1358,7 +1355,7 @@ impl bool> Iterator for SyntaxElementChildrenByKind { type Item = SyntaxElement; fn next(&mut self) -> Option { self.next.take().map(|next| { - self.next = next.next_sibling_or_token_matching(&self.matcher); + self.next = next.next_sibling_or_token_by_kind(&self.matcher); next }) } From 04e1a2a3baf826746d2793c9cd0dc797aac64f10 Mon Sep 17 00:00:00 2001 From: Theodore Luo Wang Date: Sun, 24 Oct 2021 21:55:11 -0400 Subject: [PATCH 12/13] Expose SyntaxNodeChildrenByKind --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2994b05..c398811 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,8 +29,8 @@ pub use text_size::{TextLen, TextRange, TextSize}; pub use crate::{ api::{ - Language, SyntaxElement, SyntaxElementChildren, SyntaxNode, SyntaxNodeChildren, - SyntaxNodeChildrenByKind, SyntaxToken, + Language, SyntaxElement, SyntaxElementChildren, SyntaxElementChildrenByKind, SyntaxNode, + SyntaxNodeChildren, SyntaxNodeChildrenByKind, SyntaxToken, }, green::{ Checkpoint, Children, GreenNode, GreenNodeBuilder, GreenNodeData, GreenToken, From 39b541049b81b0522beae073ab36ef28adf5cb9e Mon Sep 17 00:00:00 2001 From: Theodore Luo Wang Date: Tue, 9 Nov 2021 00:43:28 -0500 Subject: [PATCH 13/13] Changes per Veykril's comments --- src/api.rs | 4 ++-- src/cursor.rs | 20 ++++++++------------ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/api.rs b/src/api.rs index 20ee5ac..8fb8687 100644 --- a/src/api.rs +++ b/src/api.rs @@ -391,7 +391,7 @@ impl Iterator for SyntaxNodeChildren { impl SyntaxNodeChildren { pub fn by_kind<'a>( self, - matcher: &'a impl Fn(SyntaxKind) -> bool, + matcher: &'a dyn Fn(SyntaxKind) -> bool, ) -> SyntaxNodeChildrenByKind<'a, L> { SyntaxNodeChildrenByKind { raw: self.raw.by_kind(matcher), _p: PhantomData } } @@ -432,7 +432,7 @@ impl Iterator for SyntaxElementChildren { impl SyntaxElementChildren { pub fn by_kind<'a>( self, - matcher: &'a impl Fn(SyntaxKind) -> bool, + matcher: &'a dyn Fn(SyntaxKind) -> bool, ) -> SyntaxElementChildrenByKind<'a, L> { SyntaxElementChildrenByKind { raw: self.raw.by_kind(matcher), _p: PhantomData } } diff --git a/src/cursor.rs b/src/cursor.rs index e486fe4..be028f8 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -376,11 +376,10 @@ impl NodeData { } fn next_sibling(&self) -> Option { - let mut siblings = self.green_siblings().enumerate(); + let siblings = self.green_siblings().enumerate(); let index = self.index() as usize; - siblings.nth(index); - siblings.find_map(|(index, child)| { + siblings.skip(index + 1).find_map(|(index, child)| { child.as_ref().into_node().and_then(|green| { let parent = self.parent_node()?; let offset = parent.offset() + child.rel_offset(); @@ -390,11 +389,10 @@ impl NodeData { } fn next_sibling_by_kind(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option { - let mut siblings = self.green_siblings().enumerate(); + let siblings = self.green_siblings().enumerate(); let index = self.index() as usize; - siblings.nth(index); - siblings.find_map(|(index, child)| { + siblings.skip(index + 1).find_map(|(index, child)| { if !matcher(child.as_ref().kind()) { return None; } @@ -407,11 +405,10 @@ impl NodeData { } fn prev_sibling(&self) -> Option { - let mut rev_siblings = self.green_siblings().enumerate().rev(); + let rev_siblings = self.green_siblings().enumerate().rev(); let index = rev_siblings.len() - (self.index() as usize); - rev_siblings.nth(index); - rev_siblings.find_map(|(index, child)| { + rev_siblings.skip(index + 1).find_map(|(index, child)| { child.as_ref().into_node().and_then(|green| { let parent = self.parent_node()?; let offset = parent.offset() + child.rel_offset(); @@ -435,11 +432,10 @@ impl NodeData { &self, matcher: &impl Fn(SyntaxKind) -> bool, ) -> Option { - let mut siblings = self.green_siblings().enumerate(); + let siblings = self.green_siblings().enumerate(); let index = self.index() as usize; - siblings.nth(index); - siblings.find_map(|(index, child)| { + siblings.skip(index + 1).find_map(|(index, child)| { if !matcher(child.as_ref().kind()) { return None; }