dprint_swc_ext/common/
comments.rs

1use super::pos::*;
2use super::text_info::*;
3use super::tokens::*;
4use crate::swc::common::comments::Comment;
5use crate::swc::common::comments::SingleThreadedCommentsMapInner;
6
7pub struct CommentContainer<'a> {
8  pub leading: &'a SingleThreadedCommentsMapInner,
9  pub trailing: &'a SingleThreadedCommentsMapInner,
10  tokens: &'a TokenContainer<'a>,
11  text_info: &'a SourceTextInfo,
12}
13
14impl<'a> CommentContainer<'a> {
15  pub fn new(
16    leading: &'a SingleThreadedCommentsMapInner,
17    trailing: &'a SingleThreadedCommentsMapInner,
18    tokens: &'a TokenContainer<'a>,
19    text_info: &'a SourceTextInfo,
20  ) -> Self {
21    CommentContainer {
22      leading,
23      trailing,
24      tokens,
25      text_info,
26    }
27  }
28
29  pub fn all_comments(&'a self) -> CommentsIterator<'a> {
30    let approx_cap = self.leading.len() + self.trailing.len();
31    let mut v = Vec::with_capacity(approx_cap);
32    v.extend(self.leading.values());
33    v.extend(self.trailing.values());
34    CommentsIterator::new(v)
35  }
36
37  pub fn leading_comments(&'a self, start: SourcePos) -> CommentsIterator<'a> {
38    let previous_token_hi = self.tokens.get_token_index_at_start(start).map(|index| {
39      if index == 0 {
40        self.text_info.range().start.as_source_pos()
41      } else {
42        self.tokens.get_token_at_index(index - 1).unwrap().end()
43      }
44    });
45    let leading = self.get_leading(start);
46    if let Some(previous_token_hi) = previous_token_hi {
47      let trailing = self.get_trailing(previous_token_hi);
48      combine_comment_vecs(trailing, leading)
49    } else {
50      leading.map(|l| CommentsIterator::new(vec![l])).unwrap_or_default()
51    }
52  }
53
54  pub fn trailing_comments(&'a self, end: SourcePos) -> CommentsIterator<'a> {
55    let next_token_lo = self.tokens.get_token_index_at_end(end).map(|index| {
56      self
57        .tokens
58        .get_token_at_index(index + 1)
59        .map(|t| t.start())
60        .unwrap_or_else(|| self.text_info.range().end)
61    });
62    let trailing = self.get_trailing(end);
63    if let Some(next_token_lo) = next_token_lo {
64      let leading = self.get_leading(next_token_lo);
65      combine_comment_vecs(trailing, leading)
66    } else {
67      trailing.map(|t| CommentsIterator::new(vec![t])).unwrap_or_default()
68    }
69  }
70
71  fn get_leading(&'a self, start: SourcePos) -> Option<&'a Vec<Comment>> {
72    self.leading.get(&start.as_byte_pos())
73  }
74
75  fn get_trailing(&'a self, end: SourcePos) -> Option<&'a Vec<Comment>> {
76    self.trailing.get(&end.as_byte_pos())
77  }
78}
79
80fn combine_comment_vecs<'a>(a: Option<&'a Vec<Comment>>, b: Option<&'a Vec<Comment>>) -> CommentsIterator<'a> {
81  let length = if a.is_some() { 1 } else { 0 } + if b.is_some() { 1 } else { 0 };
82  let mut comment_vecs = Vec::with_capacity(length);
83  if let Some(a) = a {
84    comment_vecs.push(a);
85  }
86  if let Some(b) = b {
87    comment_vecs.push(b);
88  }
89  CommentsIterator::new(comment_vecs)
90}
91
92#[derive(Clone)]
93pub struct CommentsIterator<'a> {
94  comment_vecs: Vec<&'a Vec<Comment>>,
95  outer_index: usize,
96  inner_index: usize,
97  outer_index_back: usize,
98  inner_index_back: usize,
99}
100
101impl<'a> CommentsIterator<'a> {
102  pub fn empty() -> Self {
103    Self::new(Vec::with_capacity(0))
104  }
105
106  pub fn new(comment_vecs: Vec<&'a Vec<Comment>>) -> Self {
107    let outer_index_back = comment_vecs.len();
108    CommentsIterator {
109      comment_vecs,
110      outer_index: 0,
111      inner_index: 0,
112      outer_index_back,
113      inner_index_back: 0,
114    }
115  }
116
117  pub fn reset(&mut self) {
118    self.outer_index = 0;
119    self.inner_index = 0;
120  }
121
122  pub fn extend(&mut self, iterator: CommentsIterator<'a>) {
123    self.comment_vecs.extend(iterator.comment_vecs);
124
125    // reset the back iterator
126    self.outer_index_back = self.comment_vecs.len();
127    self.inner_index_back = 0;
128  }
129
130  pub fn is_empty(&self) -> bool {
131    for comments in self.comment_vecs.iter() {
132      if !comments.is_empty() {
133        return false;
134      }
135    }
136
137    true
138  }
139
140  pub fn peek_last_comment(&self) -> Option<&'a Comment> {
141    if let Some(comments) = self.comment_vecs.last() {
142      comments.last()
143    } else {
144      None
145    }
146  }
147}
148
149impl<'a> Default for CommentsIterator<'a> {
150  fn default() -> Self {
151    Self::empty()
152  }
153}
154
155impl<'a> Iterator for CommentsIterator<'a> {
156  type Item = &'a Comment;
157
158  fn next(&mut self) -> Option<&'a Comment> {
159    loop {
160      if let Some(comments) = self.comment_vecs.get(self.outer_index) {
161        if let Some(comment) = comments.get(self.inner_index) {
162          self.inner_index += 1;
163          return Some(comment);
164        } else {
165          self.inner_index = 0;
166          self.outer_index += 1;
167        }
168      } else {
169        return None;
170      }
171    }
172  }
173
174  fn size_hint(&self) -> (usize, Option<usize>) {
175    let mut next_inner_index = self.inner_index;
176    let mut count = 0;
177    for comment_vec in &self.comment_vecs[self.outer_index..] {
178      count += comment_vec.len() - next_inner_index;
179      next_inner_index = 0;
180    }
181    (count, Some(count))
182  }
183}
184
185impl<'a> DoubleEndedIterator for CommentsIterator<'a> {
186  fn next_back(&mut self) -> Option<&'a Comment> {
187    if self.inner_index_back == 0 {
188      if self.outer_index_back == 0 {
189        return None;
190      }
191      self.outer_index_back -= 1;
192      self.inner_index_back = self.comment_vecs.get(self.outer_index_back).unwrap().len() - 1;
193    } else {
194      self.inner_index_back -= 1;
195    }
196
197    self.comment_vecs.get(self.outer_index_back).and_then(|inner| inner.get(self.inner_index_back))
198  }
199}