aboutsummaryrefslogtreecommitdiff
path: root/crates/test_utils
diff options
context:
space:
mode:
Diffstat (limited to 'crates/test_utils')
-rw-r--r--crates/test_utils/src/lib.rs47
1 files changed, 38 insertions, 9 deletions
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index ac5a9509d..b2fe25f82 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -190,10 +190,21 @@ pub fn add_cursor(text: &str, offset: TextSize) -> String {
190 res 190 res
191} 191}
192 192
193/// Extracts `//^ some text` annotations 193/// Extracts `//^^^ some text` annotations.
194///
195/// A run of `^^^` can be arbitrary long and points to the corresponding range
196/// in the line above.
197///
198/// The `// ^file text` syntax can be used to attach `text` to the entirety of
199/// the file.
200///
201/// Multiline string values are supported:
202///
203/// // ^^^ first line
204/// // | second line
194pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { 205pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
195 let mut res = Vec::new(); 206 let mut res = Vec::new();
196 let mut prev_line_start: Option<TextSize> = None; 207 let mut prev_line_start: Option<TextSize> = Some(0.into());
197 let mut line_start: TextSize = 0.into(); 208 let mut line_start: TextSize = 0.into();
198 let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new(); 209 let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new();
199 for line in text.split_inclusive('\n') { 210 for line in text.split_inclusive('\n') {
@@ -202,10 +213,15 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
202 let annotation_offset = TextSize::of(&line[..idx + "//".len()]); 213 let annotation_offset = TextSize::of(&line[..idx + "//".len()]);
203 for annotation in extract_line_annotations(&line[idx + "//".len()..]) { 214 for annotation in extract_line_annotations(&line[idx + "//".len()..]) {
204 match annotation { 215 match annotation {
205 LineAnnotation::Annotation { mut range, content } => { 216 LineAnnotation::Annotation { mut range, content, file } => {
206 range += annotation_offset; 217 range += annotation_offset;
207 this_line_annotations.push((range.end(), res.len())); 218 this_line_annotations.push((range.end(), res.len()));
208 res.push((range + prev_line_start.unwrap(), content)) 219 let range = if file {
220 TextRange::up_to(TextSize::of(text))
221 } else {
222 range + prev_line_start.unwrap()
223 };
224 res.push((range, content))
209 } 225 }
210 LineAnnotation::Continuation { mut offset, content } => { 226 LineAnnotation::Continuation { mut offset, content } => {
211 offset += annotation_offset; 227 offset += annotation_offset;
@@ -226,11 +242,12 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
226 242
227 prev_line_annotations = this_line_annotations; 243 prev_line_annotations = this_line_annotations;
228 } 244 }
245
229 res 246 res
230} 247}
231 248
232enum LineAnnotation { 249enum LineAnnotation {
233 Annotation { range: TextRange, content: String }, 250 Annotation { range: TextRange, content: String, file: bool },
234 Continuation { offset: TextSize, content: String }, 251 Continuation { offset: TextSize, content: String },
235} 252}
236 253
@@ -251,12 +268,20 @@ fn extract_line_annotations(mut line: &str) -> Vec<LineAnnotation> {
251 } 268 }
252 let range = TextRange::at(offset, len.try_into().unwrap()); 269 let range = TextRange::at(offset, len.try_into().unwrap());
253 let next = line[len..].find(marker).map_or(line.len(), |it| it + len); 270 let next = line[len..].find(marker).map_or(line.len(), |it| it + len);
254 let content = line[len..][..next - len].trim().to_string(); 271 let mut content = &line[len..][..next - len];
272
273 let mut file = false;
274 if !continuation && content.starts_with("file") {
275 file = true;
276 content = &content["file".len()..]
277 }
278
279 let content = content.trim().to_string();
255 280
256 let annotation = if continuation { 281 let annotation = if continuation {
257 LineAnnotation::Continuation { offset: range.end(), content } 282 LineAnnotation::Continuation { offset: range.end(), content }
258 } else { 283 } else {
259 LineAnnotation::Annotation { range, content } 284 LineAnnotation::Annotation { range, content, file }
260 }; 285 };
261 res.push(annotation); 286 res.push(annotation);
262 287
@@ -277,16 +302,20 @@ fn main() {
277 zoo + 1 302 zoo + 1
278} //^^^ type: 303} //^^^ type:
279 // | i32 304 // | i32
305
306// ^file
280 "#, 307 "#,
281 ); 308 );
282 let res = extract_annotations(&text) 309 let res = extract_annotations(&text)
283 .into_iter() 310 .into_iter()
284 .map(|(range, ann)| (&text[range], ann)) 311 .map(|(range, ann)| (&text[range], ann))
285 .collect::<Vec<_>>(); 312 .collect::<Vec<_>>();
313
286 assert_eq!( 314 assert_eq!(
287 res, 315 res[..3],
288 vec![("x", "def".into()), ("y", "def".into()), ("zoo", "type:\ni32\n".into()),] 316 [("x", "def".into()), ("y", "def".into()), ("zoo", "type:\ni32\n".into())]
289 ); 317 );
318 assert_eq!(res[3].0.len(), 115);
290} 319}
291 320
292/// Returns `false` if slow tests should not run, otherwise returns `true` and 321/// Returns `false` if slow tests should not run, otherwise returns `true` and