aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/algo/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/algo/mod.rs')
-rw-r--r--crates/ra_syntax/src/algo/mod.rs54
1 files changed, 33 insertions, 21 deletions
diff --git a/crates/ra_syntax/src/algo/mod.rs b/crates/ra_syntax/src/algo/mod.rs
index e686a5704..b4896c482 100644
--- a/crates/ra_syntax/src/algo/mod.rs
+++ b/crates/ra_syntax/src/algo/mod.rs
@@ -1,16 +1,18 @@
1pub mod walk;
2pub mod visit; 1pub mod visit;
2pub mod walk;
3 3
4use crate::{ 4use crate::{
5 SyntaxNodeRef, TextUnit, TextRange,
6 text_utils::{contains_offset_nonstrict, is_subrange}, 5 text_utils::{contains_offset_nonstrict, is_subrange},
6 SyntaxNodeRef, TextRange, TextUnit,
7}; 7};
8 8
9pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffset { 9pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffset {
10 let range = node.range(); 10 let range = node.range();
11 assert!( 11 assert!(
12 contains_offset_nonstrict(range, offset), 12 contains_offset_nonstrict(range, offset),
13 "Bad offset: range {:?} offset {:?}", range, offset 13 "Bad offset: range {:?} offset {:?}",
14 range,
15 offset
14 ); 16 );
15 if range.is_empty() { 17 if range.is_empty() {
16 return LeafAtOffset::None; 18 return LeafAtOffset::None;
@@ -20,20 +22,23 @@ pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffse
20 return LeafAtOffset::Single(node); 22 return LeafAtOffset::Single(node);
21 } 23 }
22 24
23 let mut children = node.children() 25 let mut children = node.children().filter(|child| {
24 .filter(|child| { 26 let child_range = child.range();
25 let child_range = child.range(); 27 !child_range.is_empty() && contains_offset_nonstrict(child_range, offset)
26 !child_range.is_empty() && contains_offset_nonstrict(child_range, offset) 28 });
27 });
28 29
29 let left = children.next().unwrap(); 30 let left = children.next().unwrap();
30 let right = children.next(); 31 let right = children.next();
31 assert!(children.next().is_none()); 32 assert!(children.next().is_none());
32 return if let Some(right) = right { 33 return if let Some(right) = right {
33 match (find_leaf_at_offset(left, offset), find_leaf_at_offset(right, offset)) { 34 match (
34 (LeafAtOffset::Single(left), LeafAtOffset::Single(right)) => 35 find_leaf_at_offset(left, offset),
35 LeafAtOffset::Between(left, right), 36 find_leaf_at_offset(right, offset),
36 _ => unreachable!() 37 ) {
38 (LeafAtOffset::Single(left), LeafAtOffset::Single(right)) => {
39 LeafAtOffset::Between(left, right)
40 }
41 _ => unreachable!(),
37 } 42 }
38 } else { 43 } else {
39 find_leaf_at_offset(left, offset) 44 find_leaf_at_offset(left, offset)
@@ -44,7 +49,7 @@ pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffse
44pub enum LeafAtOffset<'a> { 49pub enum LeafAtOffset<'a> {
45 None, 50 None,
46 Single(SyntaxNodeRef<'a>), 51 Single(SyntaxNodeRef<'a>),
47 Between(SyntaxNodeRef<'a>, SyntaxNodeRef<'a>) 52 Between(SyntaxNodeRef<'a>, SyntaxNodeRef<'a>),
48} 53}
49 54
50impl<'a> LeafAtOffset<'a> { 55impl<'a> LeafAtOffset<'a> {
@@ -52,7 +57,7 @@ impl<'a> LeafAtOffset<'a> {
52 match self { 57 match self {
53 LeafAtOffset::None => None, 58 LeafAtOffset::None => None,
54 LeafAtOffset::Single(node) => Some(node), 59 LeafAtOffset::Single(node) => Some(node),
55 LeafAtOffset::Between(_, right) => Some(right) 60 LeafAtOffset::Between(_, right) => Some(right),
56 } 61 }
57 } 62 }
58 63
@@ -60,7 +65,7 @@ impl<'a> LeafAtOffset<'a> {
60 match self { 65 match self {
61 LeafAtOffset::None => None, 66 LeafAtOffset::None => None,
62 LeafAtOffset::Single(node) => Some(node), 67 LeafAtOffset::Single(node) => Some(node),
63 LeafAtOffset::Between(left, _) => Some(left) 68 LeafAtOffset::Between(left, _) => Some(left),
64 } 69 }
65 } 70 }
66} 71}
@@ -71,8 +76,14 @@ impl<'f> Iterator for LeafAtOffset<'f> {
71 fn next(&mut self) -> Option<SyntaxNodeRef<'f>> { 76 fn next(&mut self) -> Option<SyntaxNodeRef<'f>> {
72 match *self { 77 match *self {
73 LeafAtOffset::None => None, 78 LeafAtOffset::None => None,
74 LeafAtOffset::Single(node) => { *self = LeafAtOffset::None; Some(node) } 79 LeafAtOffset::Single(node) => {
75 LeafAtOffset::Between(left, right) => { *self = LeafAtOffset::Single(right); Some(left) } 80 *self = LeafAtOffset::None;
81 Some(node)
82 }
83 LeafAtOffset::Between(left, right) => {
84 *self = LeafAtOffset::Single(right);
85 Some(left)
86 }
76 } 87 }
77 } 88 }
78} 89}
@@ -81,14 +92,15 @@ pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRe
81 assert!( 92 assert!(
82 is_subrange(root.range(), range), 93 is_subrange(root.range(), range),
83 "node range: {:?}, target range: {:?}", 94 "node range: {:?}, target range: {:?}",
84 root.range(), range, 95 root.range(),
96 range,
85 ); 97 );
86 let (left, right) = match ( 98 let (left, right) = match (
87 find_leaf_at_offset(root, range.start()).right_biased(), 99 find_leaf_at_offset(root, range.start()).right_biased(),
88 find_leaf_at_offset(root, range.end()).left_biased() 100 find_leaf_at_offset(root, range.end()).left_biased(),
89 ) { 101 ) {
90 (Some(l), Some(r)) => (l, r), 102 (Some(l), Some(r)) => (l, r),
91 _ => return root 103 _ => return root,
92 }; 104 };
93 105
94 common_ancestor(left, right) 106 common_ancestor(left, right)
@@ -103,7 +115,7 @@ fn common_ancestor<'a>(n1: SyntaxNodeRef<'a>, n2: SyntaxNodeRef<'a>) -> SyntaxNo
103 panic!("Can't find common ancestor of {:?} and {:?}", n1, n2) 115 panic!("Can't find common ancestor of {:?} and {:?}", n1, n2)
104} 116}
105 117
106pub fn generate<T>(seed: Option<T>, step: impl Fn(&T) -> Option<T>) -> impl Iterator<Item=T> { 118pub fn generate<T>(seed: Option<T>, step: impl Fn(&T) -> Option<T>) -> impl Iterator<Item = T> {
107 ::itertools::unfold(seed, move |slot| { 119 ::itertools::unfold(seed, move |slot| {
108 slot.take().map(|curr| { 120 slot.take().map(|curr| {
109 *slot = step(&curr); 121 *slot = step(&curr);