Skip to content

Commit c471886

Browse files
committed
fix first_comment_between
previously this could have returned any comment in the span rather than guaranteeing the first
1 parent 90df9ed commit c471886

1 file changed

Lines changed: 84 additions & 3 deletions

File tree

compiler-core/src/parse/extra.rs

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)