1#[cfg(not(feature = "std"))]
18use alloc::{string::String, vec::Vec};
19
20use core::{
21 ops::{Bound, Deref, RangeBounds},
22 slice,
23};
24
25use crate::tokenizer::{Location, Span};
26
27#[derive(#[automatically_derived]
impl ::core::default::Default for Comments {
#[inline]
fn default() -> Comments { Comments(::core::default::Default::default()) }
}Default, #[automatically_derived]
impl ::core::fmt::Debug for Comments {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Comments",
&&self.0)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for Comments {
#[inline]
fn clone(&self) -> Comments {
Comments(::core::clone::Clone::clone(&self.0))
}
}Clone)]
29pub struct Comments(Vec<CommentWithSpan>);
30
31impl Comments {
32 pub(crate) fn offer(&mut self, comment: CommentWithSpan) {
37 if self
38 .0
39 .last()
40 .map(|last| last.span < comment.span)
41 .unwrap_or(true)
42 {
43 self.0.push(comment);
44 }
45 }
46
47 pub fn find<R: RangeBounds<Location>>(&self, range: R) -> Iter<'_> {
90 let (start, end) = (
91 self.start_index(range.start_bound()),
92 self.end_index(range.end_bound()),
93 );
94 if true {
if !(0..=self.0.len()).contains(&start) {
::core::panicking::panic("assertion failed: (0..=self.0.len()).contains(&start)")
};
};debug_assert!((0..=self.0.len()).contains(&start));
95 if true {
if !(0..=self.0.len()).contains(&end) {
::core::panicking::panic("assertion failed: (0..=self.0.len()).contains(&end)")
};
};debug_assert!((0..=self.0.len()).contains(&end));
96 Iter(if start <= end {
98 self.0[start..end].iter()
99 } else {
100 self.0[0..0].iter()
101 })
102 }
103
104 fn start_index(&self, location: Bound<&Location>) -> usize {
108 match location {
109 Bound::Included(location) => {
110 match self.0.binary_search_by(|c| c.span.start.cmp(location)) {
111 Ok(i) => i,
112 Err(i) => i,
113 }
114 }
115 Bound::Excluded(location) => {
116 match self.0.binary_search_by(|c| c.span.start.cmp(location)) {
117 Ok(i) => i + 1,
118 Err(i) => i,
119 }
120 }
121 Bound::Unbounded => 0,
122 }
123 }
124
125 fn end_index(&self, location: Bound<&Location>) -> usize {
129 match location {
130 Bound::Included(location) => {
131 match self.0.binary_search_by(|c| c.span.start.cmp(location)) {
132 Ok(i) => i + 1,
133 Err(i) => i,
134 }
135 }
136 Bound::Excluded(location) => {
137 match self.0.binary_search_by(|c| c.span.start.cmp(location)) {
138 Ok(i) => i,
139 Err(i) => i,
140 }
141 }
142 Bound::Unbounded => self.0.len(),
143 }
144 }
145}
146
147impl From<Comments> for Vec<CommentWithSpan> {
148 fn from(comments: Comments) -> Self {
149 comments.0
150 }
151}
152
153#[derive(#[automatically_derived]
impl ::core::fmt::Debug for CommentWithSpan {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"CommentWithSpan", "comment", &self.comment, "span", &&self.span)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for CommentWithSpan {
#[inline]
fn clone(&self) -> CommentWithSpan {
CommentWithSpan {
comment: ::core::clone::Clone::clone(&self.comment),
span: ::core::clone::Clone::clone(&self.span),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for CommentWithSpan {
#[inline]
fn eq(&self, other: &CommentWithSpan) -> bool {
self.comment == other.comment && self.span == other.span
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for CommentWithSpan {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Comment>;
let _: ::core::cmp::AssertParamIsEq<Span>;
}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for CommentWithSpan {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.comment, state);
::core::hash::Hash::hash(&self.span, state)
}
}Hash)]
155pub struct CommentWithSpan {
156 pub comment: Comment,
158 pub span: Span,
160}
161
162impl Deref for CommentWithSpan {
163 type Target = Comment;
164
165 fn deref(&self) -> &Self::Target {
166 &self.comment
167 }
168}
169
170#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Comment {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Comment::SingleLine { content: __self_0, prefix: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"SingleLine", "content", __self_0, "prefix", &__self_1),
Comment::MultiLine(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"MultiLine", &__self_0),
}
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for Comment {
#[inline]
fn clone(&self) -> Comment {
match self {
Comment::SingleLine { content: __self_0, prefix: __self_1 } =>
Comment::SingleLine {
content: ::core::clone::Clone::clone(__self_0),
prefix: ::core::clone::Clone::clone(__self_1),
},
Comment::MultiLine(__self_0) =>
Comment::MultiLine(::core::clone::Clone::clone(__self_0)),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for Comment {
#[inline]
fn eq(&self, other: &Comment) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(Comment::SingleLine { content: __self_0, prefix: __self_1 },
Comment::SingleLine { content: __arg1_0, prefix: __arg1_1 })
=> __self_0 == __arg1_0 && __self_1 == __arg1_1,
(Comment::MultiLine(__self_0), Comment::MultiLine(__arg1_0))
=> __self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Comment {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<String>;
}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for Comment {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
Comment::SingleLine { content: __self_0, prefix: __self_1 } => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
Comment::MultiLine(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
}
}
}Hash)]
172pub enum Comment {
173 SingleLine {
182 content: String,
184 prefix: String,
186 },
187
188 MultiLine(String),
191}
192
193impl Comment {
194 pub fn as_str(&self) -> &str {
196 match self {
197 Comment::SingleLine { content, prefix: _ } => content.as_str(),
198 Comment::MultiLine(content) => content.as_str(),
199 }
200 }
201}
202
203impl Deref for Comment {
204 type Target = str;
205
206 fn deref(&self) -> &Self::Target {
207 self.as_str()
208 }
209}
210
211pub struct Iter<'a>(slice::Iter<'a, CommentWithSpan>);
213
214impl<'a> Iterator for Iter<'a> {
215 type Item = &'a CommentWithSpan;
216
217 fn next(&mut self) -> Option<Self::Item> {
218 self.0.next()
219 }
220}
221
222#[cfg(test)]
223mod tests {
224 use super::*;
225
226 #[test]
227 fn test_find() {
228 let comments = {
229 let mut c = Comments(Vec::new());
238 c.offer(CommentWithSpan {
239 comment: Comment::SingleLine {
240 content: " abc".into(),
241 prefix: "--".into(),
242 },
243 span: Span::new((1, 1).into(), (1, 7).into()),
244 });
245 c.offer(CommentWithSpan {
246 comment: Comment::MultiLine(" hello ".into()),
247 span: Span::new((2, 3).into(), (2, 14).into()),
248 });
249 c.offer(CommentWithSpan {
250 comment: Comment::SingleLine {
251 content: ", world".into(),
252 prefix: "--".into(),
253 },
254 span: Span::new((2, 14).into(), (2, 21).into()),
255 });
256 c.offer(CommentWithSpan {
257 comment: Comment::MultiLine(" def\n ghi\n jkl\n".into()),
258 span: Span::new((3, 3).into(), (7, 1).into()),
259 });
260 c
261 };
262
263 fn find<R: RangeBounds<Location>>(comments: &Comments, range: R) -> Vec<&str> {
264 comments.find(range).map(|c| c.as_str()).collect::<Vec<_>>()
265 }
266
267 assert_eq!(find(&comments, ..Location::new(0, 0)), Vec::<&str>::new());
269 assert_eq!(find(&comments, ..Location::new(2, 1)), vec![" abc"]);
270 assert_eq!(find(&comments, ..Location::new(2, 3)), vec![" abc"]);
271 assert_eq!(
272 find(&comments, ..=Location::new(2, 3)),
273 vec![" abc", " hello "]
274 );
275 assert_eq!(
276 find(&comments, ..=Location::new(2, 3)),
277 vec![" abc", " hello "]
278 );
279 assert_eq!(
280 find(&comments, ..Location::new(2, 15)),
281 vec![" abc", " hello ", ", world"]
282 );
283
284 assert_eq!(
286 find(&comments, Location::new(1000, 1000)..),
287 Vec::<&str>::new()
288 );
289 assert_eq!(
290 find(&comments, Location::new(2, 14)..),
291 vec![", world", " def\n ghi\n jkl\n"]
292 );
293 assert_eq!(
294 find(&comments, Location::new(2, 15)..),
295 vec![" def\n ghi\n jkl\n"]
296 );
297 assert_eq!(
298 find(&comments, Location::new(0, 0)..),
299 vec![" abc", " hello ", ", world", " def\n ghi\n jkl\n"]
300 );
301 assert_eq!(
302 find(&comments, Location::new(1, 1)..),
303 vec![" abc", " hello ", ", world", " def\n ghi\n jkl\n"]
304 );
305
306 assert_eq!(
308 find(&comments, Location::new(2, 1)..Location::new(1, 1)),
309 Vec::<&str>::new()
310 );
311 assert_eq!(
312 find(&comments, Location::new(1, 1)..Location::new(2, 3)),
313 vec![" abc"]
314 );
315 assert_eq!(
316 find(&comments, Location::new(1, 1)..=Location::new(2, 3)),
317 vec![" abc", " hello "]
318 );
319 assert_eq!(
320 find(&comments, Location::new(1, 1)..=Location::new(2, 10)),
321 vec![" abc", " hello "]
322 );
323 assert_eq!(
324 find(&comments, Location::new(1, 1)..=Location::new(2, 14)),
325 vec![" abc", " hello ", ", world"]
326 );
327 assert_eq!(
328 find(&comments, Location::new(1, 1)..Location::new(2, 15)),
329 vec![" abc", " hello ", ", world"]
330 );
331
332 assert_eq!(
334 find(&comments, ..),
335 vec![" abc", " hello ", ", world", " def\n ghi\n jkl\n"]
336 );
337 }
338}