@@ -40,8 +40,13 @@ impl ModuleExtra {
4040 self . first_comment_between ( start, end) . is_some ( )
4141 }
4242
43+ // TODO: this won't necessarily find the first comment, just any comment
44+ /// Returns the first comment overlapping the given source locations (inclusive)
45+ /// Note that the returned span covers the text of the comment, not the `//`
4346 pub fn first_comment_between ( & self , start : u32 , end : u32 ) -> Option < SrcSpan > {
44- self . comments
47+ // Index of a comment, but not necessarily the first one.
48+ let index = self
49+ . comments
4550 . binary_search_by ( |comment| {
4651 if comment. end < start {
4752 Ordering :: Less
@@ -51,8 +56,18 @@ impl ModuleExtra {
5156 Ordering :: Equal
5257 }
5358 } )
54- . ok ( )
55- . and_then ( |index| self . comments . get ( index) . copied ( ) )
59+ . ok ( ) ?;
60+
61+ self . comments
62+ . get ( 0 ..=index) ?
63+ . iter ( )
64+ . rev ( )
65+ . take_while ( |comment| {
66+ // comment overlaps span (inclusive of endpoints)
67+ comment. end >= start && comment. start <= end
68+ } )
69+ . last ( )
70+ . copied ( )
5671 }
5772}
5873
@@ -81,3 +96,69 @@ impl<'a> From<(&SrcSpan, &'a str)> for Comment<'a> {
8196 }
8297 }
8398}
99+
100+ #[ cfg( test) ]
101+ mod tests {
102+ use crate :: { ast:: SrcSpan , parse:: extra:: ModuleExtra } ;
103+
104+ fn set_up_extra ( ) -> ModuleExtra {
105+ let mut extra = ModuleExtra :: new ( ) ;
106+ extra. comments = vec ! [
107+ SrcSpan { start: 0 , end: 10 } ,
108+ SrcSpan { start: 20 , end: 30 } ,
109+ SrcSpan { start: 40 , end: 50 } ,
110+ SrcSpan { start: 60 , end: 70 } ,
111+ SrcSpan { start: 80 , end: 90 } ,
112+ SrcSpan {
113+ start: 90 ,
114+ end: 100 ,
115+ } ,
116+ ] ;
117+ extra
118+ }
119+
120+ #[ test]
121+ fn first_comment_between ( ) {
122+ let extra = set_up_extra ( ) ;
123+ assert ! ( matches!(
124+ extra. first_comment_between( 15 , 85 ) ,
125+ Some ( SrcSpan { start: 20 , end: 30 } )
126+ ) ) ;
127+ }
128+
129+ #[ test]
130+ fn first_comment_between_equal_to_range ( ) {
131+ let extra = set_up_extra ( ) ;
132+ assert ! ( matches!(
133+ extra. first_comment_between( 40 , 50 ) ,
134+ Some ( SrcSpan { start: 40 , end: 50 } )
135+ ) ) ;
136+ }
137+
138+ #[ test]
139+ fn first_comment_between_overlapping_start_of_range ( ) {
140+ let extra = set_up_extra ( ) ;
141+ assert ! ( matches!(
142+ extra. first_comment_between( 45 , 80 ) ,
143+ Some ( SrcSpan { start: 40 , end: 50 } )
144+ ) ) ;
145+ }
146+
147+ #[ test]
148+ fn first_comment_between_overlapping_end_of_range ( ) {
149+ let extra = set_up_extra ( ) ;
150+ assert ! ( matches!(
151+ extra. first_comment_between( 35 , 45 ) ,
152+ Some ( SrcSpan { start: 40 , end: 50 } )
153+ ) ) ;
154+ }
155+
156+ #[ test]
157+ fn first_comment_between_at_end_of_range ( ) {
158+ let extra = set_up_extra ( ) ;
159+ assert ! ( matches!(
160+ dbg!( extra. first_comment_between( 55 , 60 ) ) ,
161+ Some ( SrcSpan { start: 60 , end: 70 } )
162+ ) ) ;
163+ }
164+ }
0 commit comments