diff options
Diffstat (limited to 'crates/libsyntax2/src/algo')
-rw-r--r-- | crates/libsyntax2/src/algo/mod.rs | 48 |
1 files changed, 29 insertions, 19 deletions
diff --git a/crates/libsyntax2/src/algo/mod.rs b/crates/libsyntax2/src/algo/mod.rs index 263b58d97..6efdff12f 100644 --- a/crates/libsyntax2/src/algo/mod.rs +++ b/crates/libsyntax2/src/algo/mod.rs | |||
@@ -74,7 +74,6 @@ impl<'f> Iterator for LeafAtOffset<'f> { | |||
74 | } | 74 | } |
75 | } | 75 | } |
76 | 76 | ||
77 | |||
78 | pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRef { | 77 | pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRef { |
79 | assert!(is_subrange(root.range(), range)); | 78 | assert!(is_subrange(root.range(), range)); |
80 | let (left, right) = match ( | 79 | let (left, right) = match ( |
@@ -88,31 +87,33 @@ pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRe | |||
88 | common_ancestor(left, right) | 87 | common_ancestor(left, right) |
89 | } | 88 | } |
90 | 89 | ||
91 | fn common_ancestor<'a>(n1: SyntaxNodeRef<'a>, n2: SyntaxNodeRef<'a>) -> SyntaxNodeRef<'a> { | ||
92 | for p in ancestors(n1) { | ||
93 | if ancestors(n2).any(|a| a == p) { | ||
94 | return p; | ||
95 | } | ||
96 | } | ||
97 | panic!("Can't find common ancestor of {:?} and {:?}", n1, n2) | ||
98 | } | ||
99 | |||
100 | pub fn ancestors<'a>(node: SyntaxNodeRef<'a>) -> impl Iterator<Item=SyntaxNodeRef<'a>> { | 90 | pub fn ancestors<'a>(node: SyntaxNodeRef<'a>) -> impl Iterator<Item=SyntaxNodeRef<'a>> { |
101 | Ancestors(Some(node)) | 91 | generate(Some(node), |&node| node.parent()) |
102 | } | 92 | } |
103 | 93 | ||
104 | #[derive(Debug)] | 94 | #[derive(Debug)] |
105 | struct Ancestors<'a>(Option<SyntaxNodeRef<'a>>); | 95 | pub enum Direction { |
96 | Forward, | ||
97 | Backward, | ||
98 | } | ||
106 | 99 | ||
107 | impl<'a> Iterator for Ancestors<'a> { | 100 | pub fn siblings<'a>( |
108 | type Item = SyntaxNodeRef<'a>; | 101 | node: SyntaxNodeRef<'a>, |
102 | direction: Direction | ||
103 | ) -> impl Iterator<Item=SyntaxNodeRef<'a>> { | ||
104 | generate(Some(node), move |&node| match direction { | ||
105 | Direction::Forward => node.next_sibling(), | ||
106 | Direction::Backward => node.prev_sibling(), | ||
107 | }) | ||
108 | } | ||
109 | 109 | ||
110 | fn next(&mut self) -> Option<Self::Item> { | 110 | fn common_ancestor<'a>(n1: SyntaxNodeRef<'a>, n2: SyntaxNodeRef<'a>) -> SyntaxNodeRef<'a> { |
111 | self.0.take().map(|n| { | 111 | for p in ancestors(n1) { |
112 | self.0 = n.parent(); | 112 | if ancestors(n2).any(|a| a == p) { |
113 | n | 113 | return p; |
114 | }) | 114 | } |
115 | } | 115 | } |
116 | panic!("Can't find common ancestor of {:?} and {:?}", n1, n2) | ||
116 | } | 117 | } |
117 | 118 | ||
118 | fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool { | 119 | fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool { |
@@ -122,3 +123,12 @@ fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool { | |||
122 | fn is_subrange(range: TextRange, subrange: TextRange) -> bool { | 123 | fn is_subrange(range: TextRange, subrange: TextRange) -> bool { |
123 | range.start() <= subrange.start() && subrange.end() <= range.end() | 124 | range.start() <= subrange.start() && subrange.end() <= range.end() |
124 | } | 125 | } |
126 | |||
127 | fn generate<T>(seed: Option<T>, step: impl Fn(&T) -> Option<T>) -> impl Iterator<Item=T> { | ||
128 | ::itertools::unfold(seed, move |slot| { | ||
129 | slot.take().map(|curr| { | ||
130 | *slot = step(&curr); | ||
131 | curr | ||
132 | }) | ||
133 | }) | ||
134 | } | ||