@@ -21,6 +21,12 @@ pub use difference::Changeset as __Changeset;
21
21
22
22
pub const CURSOR_MARKER : & str = "<|>" ;
23
23
24
+ /// Asserts that two strings are equal, otherwise displays a rich diff between them.
25
+ ///
26
+ /// The diff shows changes from the "original" left string to the "actual" right string.
27
+ ///
28
+ /// All arguments starting from and including the 3rd one are passed to
29
+ /// `eprintln!()` macro in case of text inequality.
24
30
#[ macro_export]
25
31
macro_rules! assert_eq_text {
26
32
( $left: expr, $right: expr) => {
@@ -42,13 +48,16 @@ macro_rules! assert_eq_text {
42
48
} } ;
43
49
}
44
50
51
+ /// Infallible version of `try_extract_offset()`.
45
52
pub fn extract_offset ( text : & str ) -> ( TextUnit , String ) {
46
53
match try_extract_offset ( text) {
47
54
None => panic ! ( "text should contain cursor marker" ) ,
48
55
Some ( result) => result,
49
56
}
50
57
}
51
58
59
+ /// Returns the offset of the first occurence of `<|>` marker and the copy of `text`
60
+ /// without the marker.
52
61
fn try_extract_offset ( text : & str ) -> Option < ( TextUnit , String ) > {
53
62
let cursor_pos = text. find ( CURSOR_MARKER ) ?;
54
63
let mut new_text = String :: with_capacity ( text. len ( ) - CURSOR_MARKER . len ( ) ) ;
@@ -58,13 +67,16 @@ fn try_extract_offset(text: &str) -> Option<(TextUnit, String)> {
58
67
Some ( ( cursor_pos, new_text) )
59
68
}
60
69
70
+ /// Infallible version of `try_extract_range()`.
61
71
pub fn extract_range ( text : & str ) -> ( TextRange , String ) {
62
72
match try_extract_range ( text) {
63
73
None => panic ! ( "text should contain cursor marker" ) ,
64
74
Some ( result) => result,
65
75
}
66
76
}
67
77
78
+ /// Returns `TextRange` between the first two markers `<|>...<|>` and the copy
79
+ /// of `text` without both of these markers.
68
80
fn try_extract_range ( text : & str ) -> Option < ( TextRange , String ) > {
69
81
let ( start, text) = try_extract_offset ( text) ?;
70
82
let ( end, text) = try_extract_offset ( & text) ?;
@@ -85,6 +97,11 @@ impl From<RangeOrOffset> for TextRange {
85
97
}
86
98
}
87
99
100
+ /// Extracts `TextRange` or `TextUnit` depending on the amount of `<|>` markers
101
+ /// found in `text`.
102
+ ///
103
+ /// # Panics
104
+ /// Panics if no `<|>` marker is present in the `text`.
88
105
pub fn extract_range_or_offset ( text : & str ) -> ( RangeOrOffset , String ) {
89
106
if let Some ( ( range, text) ) = try_extract_range ( text) {
90
107
return ( RangeOrOffset :: Range ( range) , text) ;
@@ -93,7 +110,7 @@ pub fn extract_range_or_offset(text: &str) -> (RangeOrOffset, String) {
93
110
( RangeOrOffset :: Offset ( offset) , text)
94
111
}
95
112
96
- /// Extracts ranges, marked with `<tag> </tag>` paris from the `text`
113
+ /// Extracts ranges, marked with `<tag> </tag>` pairs from the `text`
97
114
pub fn extract_ranges ( mut text : & str , tag : & str ) -> ( Vec < TextRange > , String ) {
98
115
let open = format ! ( "<{}>" , tag) ;
99
116
let close = format ! ( "</{}>" , tag) ;
@@ -127,9 +144,9 @@ pub fn extract_ranges(mut text: &str, tag: &str) -> (Vec<TextRange>, String) {
127
144
( ranges, res)
128
145
}
129
146
147
+ /// Inserts `<|>` marker into the `text` at `offset`.
130
148
pub fn add_cursor ( text : & str , offset : TextUnit ) -> String {
131
- let offset: u32 = offset. into ( ) ;
132
- let offset: usize = offset as usize ;
149
+ let offset: usize = offset. to_usize ( ) ;
133
150
let mut res = String :: new ( ) ;
134
151
res. push_str ( & text[ ..offset] ) ;
135
152
res. push_str ( "<|>" ) ;
@@ -152,19 +169,6 @@ pub struct FixtureEntry {
152
169
/// // - other meta
153
170
/// ```
154
171
pub fn parse_fixture ( fixture : & str ) -> Vec < FixtureEntry > {
155
- let mut res = Vec :: new ( ) ;
156
- let mut buf = String :: new ( ) ;
157
- let mut meta: Option < & str > = None ;
158
-
159
- macro_rules! flush {
160
- ( ) => {
161
- if let Some ( meta) = meta {
162
- res. push( FixtureEntry { meta: meta. to_string( ) , text: buf. clone( ) } ) ;
163
- buf. clear( ) ;
164
- }
165
- } ;
166
- } ;
167
-
168
172
let margin = fixture
169
173
. lines ( )
170
174
. filter ( |it| it. trim_start ( ) . starts_with ( "//-" ) )
@@ -184,6 +188,19 @@ pub fn parse_fixture(fixture: &str) -> Vec<FixtureEntry> {
184
188
}
185
189
} ) ;
186
190
191
+ let mut res = Vec :: new ( ) ;
192
+ let mut buf = String :: new ( ) ;
193
+ let mut meta: Option < & str > = None ;
194
+
195
+ macro_rules! flush {
196
+ ( ) => {
197
+ if let Some ( meta) = meta {
198
+ res. push( FixtureEntry { meta: meta. to_string( ) , text: buf. clone( ) } ) ;
199
+ buf. clear( ) ;
200
+ }
201
+ } ;
202
+ } ;
203
+
187
204
for line in lines {
188
205
if line. starts_with ( "//-" ) {
189
206
flush ! ( ) ;
@@ -236,11 +253,10 @@ fn lines_match_works() {
236
253
assert ! ( !lines_match( "b" , "cb" ) ) ;
237
254
}
238
255
239
- // Compares JSON object for approximate equality.
240
- // You can use `[..]` wildcard in strings (useful for OS dependent things such
241
- // as paths). You can use a `"{...}"` string literal as a wildcard for
242
- // arbitrary nested JSON (useful for parts of object emitted by other programs
243
- // (e.g. rustc) rather than Cargo itself). Arrays are sorted before comparison.
256
+ /// Compares JSON object for approximate equality.
257
+ /// You can use `[..]` wildcard in strings (useful for OS dependent things such
258
+ /// as paths). You can use a `"{...}"` string literal as a wildcard for
259
+ /// arbitrary nested JSON. Arrays are sorted before comparison.
244
260
pub fn find_mismatch < ' a > ( expected : & ' a Value , actual : & ' a Value ) -> Option < ( & ' a Value , & ' a Value ) > {
245
261
use serde_json:: Value :: * ;
246
262
match ( expected, actual) {
@@ -286,6 +302,14 @@ pub fn find_mismatch<'a>(expected: &'a Value, actual: &'a Value) -> Option<(&'a
286
302
}
287
303
}
288
304
305
+ /// Calls callback `f` with input code and file paths of all `.rs` files from `test_data_dir`
306
+ /// subdirectories defined by `paths`.
307
+ ///
308
+ /// If the content of the matching `.txt` file differs from the output of `f()`
309
+ /// the test will fail.
310
+ ///
311
+ /// If there is no matching `.txt` file it will be created and filled with the
312
+ /// output of `f()`, but the test will fail.
289
313
pub fn dir_tests < F > ( test_data_dir : & Path , paths : & [ & str ] , f : F )
290
314
where
291
315
F : Fn ( & str , & Path ) -> String ,
@@ -307,6 +331,7 @@ where
307
331
}
308
332
}
309
333
334
+ /// Collects all `.rs` files from `test_data_dir` subdirectories defined by `paths`.
310
335
pub fn collect_tests ( test_data_dir : & Path , paths : & [ & str ] ) -> Vec < ( PathBuf , String ) > {
311
336
paths
312
337
. iter ( )
@@ -321,6 +346,7 @@ pub fn collect_tests(test_data_dir: &Path, paths: &[&str]) -> Vec<(PathBuf, Stri
321
346
. collect ( )
322
347
}
323
348
349
+ /// Collects paths to all `.rs` files from `dir` in a sorted `Vec<PathBuf>`.
324
350
fn test_from_dir ( dir : & Path ) -> Vec < PathBuf > {
325
351
let mut acc = Vec :: new ( ) ;
326
352
for file in fs:: read_dir ( & dir) . unwrap ( ) {
@@ -334,6 +360,7 @@ fn test_from_dir(dir: &Path) -> Vec<PathBuf> {
334
360
acc
335
361
}
336
362
363
+ /// Returns the path to the root directory of `rust-analyzer` project.
337
364
pub fn project_dir ( ) -> PathBuf {
338
365
let dir = env ! ( "CARGO_MANIFEST_DIR" ) ;
339
366
PathBuf :: from ( dir) . parent ( ) . unwrap ( ) . parent ( ) . unwrap ( ) . to_owned ( )
@@ -356,6 +383,9 @@ pub fn read_text(path: &Path) -> String {
356
383
. replace ( "\r \n " , "\n " )
357
384
}
358
385
386
+ /// Returns `false` if slow tests should not run, otherwise returns `true` and
387
+ /// also creates a file at `./target/.slow_tests_cookie` which serves as a flag
388
+ /// that slow tests did run.
359
389
pub fn skip_slow_tests ( ) -> bool {
360
390
let should_skip = std:: env:: var ( "CI" ) . is_err ( ) && std:: env:: var ( "RUN_SLOW_TESTS" ) . is_err ( ) ;
361
391
if should_skip {
@@ -367,8 +397,9 @@ pub fn skip_slow_tests() -> bool {
367
397
should_skip
368
398
}
369
399
370
- const REWRITE : bool = false ;
371
-
400
+ /// Asserts that `expected` and `actual` strings are equal. If they differ only
401
+ /// in trailing or leading whitespace the test won't fail and
402
+ /// the contents of `actual` will be written to the file located at `path`.
372
403
fn assert_equal_text ( expected : & str , actual : & str , path : & Path ) {
373
404
if expected == actual {
374
405
return ;
@@ -381,6 +412,7 @@ fn assert_equal_text(expected: &str, actual: &str, path: &Path) {
381
412
fs:: write ( path, actual) . unwrap ( ) ;
382
413
return ;
383
414
}
415
+ const REWRITE : bool = false ;
384
416
if REWRITE {
385
417
println ! ( "rewriting {}" , pretty_path. display( ) ) ;
386
418
fs:: write ( path, actual) . unwrap ( ) ;
0 commit comments