dprint_core/formatting/tokens/
token_finder.rs1pub trait TokenCollection<'a> {
3 type TPos: PartialOrd + Copy;
5 type TToken: 'a;
7
8 fn get_start_at_index(&self, index: usize) -> Self::TPos;
10 fn get_end_at_index(&self, index: usize) -> Self::TPos;
12 fn get_token_at_index(&self, index: usize) -> &'a Self::TToken;
14 fn len(&self) -> usize;
16 fn is_empty(&self) -> bool;
18}
19
20pub struct TokenFinder<TTokenCollection> {
22 tokens: TTokenCollection,
23 token_index: usize,
24}
25
26impl<'a, TTokenCollection> TokenFinder<TTokenCollection>
27where
28 TTokenCollection: TokenCollection<'a>,
29{
30 pub fn new(tokens: TTokenCollection) -> TokenFinder<TTokenCollection> {
31 TokenFinder { tokens, token_index: 0 }
32 }
33
34 #[inline]
35 pub fn get_next_token_if(
36 &mut self,
37 end: TTokenCollection::TPos,
38 is_match: impl FnOnce(&'a TTokenCollection::TToken) -> bool,
39 ) -> Option<&'a TTokenCollection::TToken> {
40 let next_token = self.get_next_token(end)?;
41 if is_match(next_token) {
42 Some(next_token)
43 } else {
44 None
45 }
46 }
47
48 #[inline]
49 pub fn get_next_token(&mut self, end: TTokenCollection::TPos) -> Option<&'a TTokenCollection::TToken> {
50 self.get_first_token_after(end, |_| true)
51 }
52
53 #[inline]
54 pub fn get_previous_token_if(
55 &mut self,
56 start: TTokenCollection::TPos,
57 is_match: impl FnOnce(&'a TTokenCollection::TToken) -> bool,
58 ) -> Option<&'a TTokenCollection::TToken> {
59 let previous_token = self.get_previous_token(start)?;
60 if is_match(previous_token) {
61 Some(previous_token)
62 } else {
63 None
64 }
65 }
66
67 #[inline]
68 pub fn get_previous_token(&mut self, start: TTokenCollection::TPos) -> Option<&'a TTokenCollection::TToken> {
69 self.get_first_token_before(start, |_| true)
70 }
71
72 pub fn get_first_token_within(
73 &mut self,
74 start: TTokenCollection::TPos,
75 end: TTokenCollection::TPos,
76 is_match: impl Fn(&'a TTokenCollection::TToken) -> bool,
77 ) -> Option<&'a TTokenCollection::TToken> {
78 if self.tokens.is_empty() {
79 return None;
80 }
81 self.move_to_node_start(start);
82
83 loop {
84 let token_start = self.tokens.get_start_at_index(self.token_index);
85 if token_start >= end {
86 break;
87 } else {
88 let current_token = self.tokens.get_token_at_index(self.token_index);
89 if is_match(current_token) {
90 return Some(current_token);
91 }
92 }
93
94 if !self.try_increment_index() {
95 break;
96 }
97 }
98
99 None
100 }
101
102 pub fn get_last_token_within(
103 &mut self,
104 start: TTokenCollection::TPos,
105 end: TTokenCollection::TPos,
106 is_match: impl Fn(&'a TTokenCollection::TToken) -> bool,
107 ) -> Option<&'a TTokenCollection::TToken> {
108 if self.tokens.is_empty() {
109 return None;
110 }
111
112 self.move_to_node_end(end);
113
114 loop {
115 let token_start = self.tokens.get_start_at_index(self.token_index);
116 if token_start >= end || token_start < start {
117 break;
118 } else {
119 let current_token = self.tokens.get_token_at_index(self.token_index);
120 if is_match(current_token) {
121 return Some(current_token);
122 }
123 }
124
125 if !self.try_decrement_index() {
126 break;
127 }
128 }
129
130 None
131 }
132
133 pub fn get_first_token_before(
134 &mut self,
135 start: TTokenCollection::TPos,
136 is_match: impl Fn(&'a TTokenCollection::TToken) -> bool,
137 ) -> Option<&'a TTokenCollection::TToken> {
138 if self.tokens.is_empty() {
139 return None;
140 }
141 self.move_to_node_start(start);
142
143 if self.tokens.get_start_at_index(self.token_index) < start {
144 let current_token = self.tokens.get_token_at_index(self.token_index);
145 if is_match(current_token) {
146 return Some(current_token);
147 }
148 }
149
150 while self.try_decrement_index() {
151 let current_token = self.tokens.get_token_at_index(self.token_index);
152 if is_match(current_token) {
153 return Some(current_token);
154 }
155 }
156
157 None
158 }
159
160 pub fn get_first_token_after(
161 &mut self,
162 end: TTokenCollection::TPos,
163 is_match: impl Fn(&'a TTokenCollection::TToken) -> bool,
164 ) -> Option<&'a TTokenCollection::TToken> {
165 if self.tokens.is_empty() {
166 return None;
167 }
168 self.move_to_node_end(end);
169
170 while self.try_increment_index() {
171 let current_token = self.tokens.get_token_at_index(self.token_index);
172 if is_match(current_token) {
173 return Some(current_token);
174 }
175 }
176
177 None
178 }
179
180 fn move_to_node_start(&mut self, start: TTokenCollection::TPos) {
181 while self.tokens.get_start_at_index(self.token_index) < start {
182 if !self.try_increment_index() {
183 break;
184 }
185 }
186
187 while self.tokens.get_start_at_index(self.token_index) > start {
188 if !self.try_decrement_index() {
189 break;
190 }
191 }
192 }
193
194 fn move_to_node_end(&mut self, end: TTokenCollection::TPos) {
195 while self.tokens.get_end_at_index(self.token_index) < end {
196 if !self.try_increment_index() {
197 break;
198 }
199 }
200
201 while self.tokens.get_end_at_index(self.token_index) > end {
202 if !self.try_decrement_index() {
203 break;
204 }
205 }
206 }
207
208 fn try_increment_index(&mut self) -> bool {
209 if self.token_index == self.tokens.len() - 1 {
210 false
211 } else {
212 self.token_index += 1;
213 true
214 }
215 }
216
217 fn try_decrement_index(&mut self) -> bool {
218 if self.token_index == 0 {
219 false
220 } else {
221 self.token_index -= 1;
222 true
223 }
224 }
225}