@@ -4,7 +4,7 @@ use triomphe::{Arc, ThinArc};
4
4
5
5
use crate :: {
6
6
green:: { GreenElement , GreenElementRef , SyntaxKind } ,
7
- GreenToken , NodeOrToken , TextSize ,
7
+ GreenToken , NodeOrToken , TextRange , TextSize ,
8
8
} ;
9
9
10
10
#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
@@ -43,6 +43,16 @@ impl GreenChild {
43
43
GreenChild :: Token { token, .. } => NodeOrToken :: Token ( token) ,
44
44
}
45
45
}
46
+ fn offset_in_parent ( & self ) -> TextSize {
47
+ match self {
48
+ GreenChild :: Node { offset_in_parent, .. }
49
+ | GreenChild :: Token { offset_in_parent, .. } => * offset_in_parent,
50
+ }
51
+ }
52
+ fn range_in_parent ( & self ) -> TextRange {
53
+ let len = self . as_ref ( ) . text_len ( ) ;
54
+ TextRange :: at ( self . offset_in_parent ( ) , len)
55
+ }
46
56
}
47
57
48
58
#[ cfg( target_pointer_width = "64" ) ]
@@ -101,6 +111,24 @@ impl GreenNode {
101
111
Children { inner : self . data . slice . iter ( ) }
102
112
}
103
113
114
+ pub ( crate ) fn child_at_range (
115
+ & self ,
116
+ range : TextRange ,
117
+ ) -> Option < ( usize , TextSize , GreenElementRef < ' _ > ) > {
118
+ let idx = self
119
+ . data
120
+ . slice
121
+ . binary_search_by ( |it| {
122
+ let child_range = it. range_in_parent ( ) ;
123
+ TextRange :: ordering ( child_range, range)
124
+ } )
125
+ // XXX: this handles empty ranges
126
+ . unwrap_or_else ( |it| it. saturating_sub ( 1 ) ) ;
127
+ let child =
128
+ & self . data . slice . get ( idx) . filter ( |it| it. range_in_parent ( ) . contains_range ( range) ) ?;
129
+ Some ( ( idx, child. offset_in_parent ( ) , child. as_ref ( ) ) )
130
+ }
131
+
104
132
pub fn ptr ( & self ) -> * const c_void {
105
133
self . data . heap_ptr ( )
106
134
}
0 commit comments