|
4 | 4 | //! including efficient range-based queries and iteration over comment collections. |
5 | 5 |
|
6 | 6 | use std::{ |
| 7 | + cmp::Ordering, |
7 | 8 | iter::FusedIterator, |
8 | 9 | ops::{Bound, RangeBounds}, |
9 | 10 | }; |
@@ -57,6 +58,39 @@ pub fn has_comments_between(comments: &[Comment], span: Span) -> bool { |
57 | 58 | comments_range(comments, span.start..span.end).count() > 0 |
58 | 59 | } |
59 | 60 |
|
| 61 | +/// Check if a position falls within any comment |
| 62 | +/// |
| 63 | +/// Returns `true` if the specified position is inside any comment's span, |
| 64 | +/// including the start and end positions. |
| 65 | +/// |
| 66 | +/// Uses binary search for efficient lookup in O(log n) time. |
| 67 | +/// |
| 68 | +/// # Arguments |
| 69 | +/// |
| 70 | +/// * `comments` - A slice of comments sorted by starting position |
| 71 | +/// * `pos` - The position to check |
| 72 | +/// |
| 73 | +/// # Examples |
| 74 | +/// |
| 75 | +/// ```ignore |
| 76 | +/// // Comment spans from position 10 to 20 |
| 77 | +/// assert!(is_inside_comment(&comments, 15)); // Inside comment |
| 78 | +/// assert!(!is_inside_comment(&comments, 25)); // Outside comment |
| 79 | +/// ``` |
| 80 | +pub fn is_inside_comment(comments: &[Comment], pos: u32) -> bool { |
| 81 | + comments |
| 82 | + .binary_search_by(|c| { |
| 83 | + if pos < c.span.start { |
| 84 | + Ordering::Greater |
| 85 | + } else if pos > c.span.end { |
| 86 | + Ordering::Less |
| 87 | + } else { |
| 88 | + Ordering::Equal |
| 89 | + } |
| 90 | + }) |
| 91 | + .is_ok() |
| 92 | +} |
| 93 | + |
60 | 94 | /// Double-ended iterator over a range of comments, by starting position |
61 | 95 | /// |
62 | 96 | /// This iterator efficiently filters comments based on their starting positions, |
@@ -162,4 +196,18 @@ mod test { |
162 | 196 | assert_eq!(comments_range(&comments, ..18).count(), full_len.saturating_sub(1)); |
163 | 197 | assert_eq!(comments_range(&comments, ..=18).count(), full_len); |
164 | 198 | } |
| 199 | + |
| 200 | + #[test] |
| 201 | + fn test_is_inside_comment() { |
| 202 | + let comments = vec![ |
| 203 | + Comment::new(0, 4, CommentKind::Line), |
| 204 | + Comment::new(10, 20, CommentKind::Block), |
| 205 | + ] |
| 206 | + .into_boxed_slice(); |
| 207 | + |
| 208 | + assert!(is_inside_comment(&comments, 2)); |
| 209 | + assert!(!is_inside_comment(&comments, 5)); |
| 210 | + assert!(is_inside_comment(&comments, 15)); |
| 211 | + assert!(!is_inside_comment(&comments, 21)); |
| 212 | + } |
165 | 213 | } |
0 commit comments