aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ssr/src/tests.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ssr/src/tests.rs')
-rw-r--r--crates/ra_ssr/src/tests.rs191
1 files changed, 118 insertions, 73 deletions
diff --git a/crates/ra_ssr/src/tests.rs b/crates/ra_ssr/src/tests.rs
index 9568d4432..f20ae2cdf 100644
--- a/crates/ra_ssr/src/tests.rs
+++ b/crates/ra_ssr/src/tests.rs
@@ -91,6 +91,18 @@ fn assert_ssr_transforms(rules: &[&str], input: &str, result: &str) {
91 } 91 }
92} 92}
93 93
94fn print_match_debug_info(match_finder: &MatchFinder, file_id: FileId, snippet: &str) {
95 let debug_info = match_finder.debug_where_text_equal(file_id, snippet);
96 println!(
97 "Match debug info: {} nodes had text exactly equal to '{}'",
98 debug_info.len(),
99 snippet
100 );
101 for (index, d) in debug_info.iter().enumerate() {
102 println!("Node #{}\n{:#?}\n", index, d);
103 }
104}
105
94fn assert_matches(pattern: &str, code: &str, expected: &[&str]) { 106fn assert_matches(pattern: &str, code: &str, expected: &[&str]) {
95 let (db, file_id) = single_file(code); 107 let (db, file_id) = single_file(code);
96 let mut match_finder = MatchFinder::new(&db); 108 let mut match_finder = MatchFinder::new(&db);
@@ -103,17 +115,20 @@ fn assert_matches(pattern: &str, code: &str, expected: &[&str]) {
103 .map(|m| m.matched_text()) 115 .map(|m| m.matched_text())
104 .collect(); 116 .collect();
105 if matched_strings != expected && !expected.is_empty() { 117 if matched_strings != expected && !expected.is_empty() {
106 let debug_info = match_finder.debug_where_text_equal(file_id, &expected[0]); 118 print_match_debug_info(&match_finder, file_id, &expected[0]);
107 eprintln!("Test is about to fail. Some possibly useful info: {} nodes had text exactly equal to '{}'", debug_info.len(), &expected[0]);
108 for d in debug_info {
109 eprintln!("{:#?}", d);
110 }
111 } 119 }
112 assert_eq!(matched_strings, expected); 120 assert_eq!(matched_strings, expected);
113} 121}
114 122
115fn assert_no_match(pattern: &str, code: &str) { 123fn assert_no_match(pattern: &str, code: &str) {
116 assert_matches(pattern, code, &[]); 124 let (db, file_id) = single_file(code);
125 let mut match_finder = MatchFinder::new(&db);
126 match_finder.add_search_pattern(pattern.parse().unwrap());
127 let matches = match_finder.find_matches_in_file(file_id).flattened().matches;
128 if !matches.is_empty() {
129 print_match_debug_info(&match_finder, file_id, &matches[0].matched_text());
130 panic!("Got {} matches when we expected none: {:#?}", matches.len(), matches);
131 }
117} 132}
118 133
119fn assert_match_failure_reason(pattern: &str, code: &str, snippet: &str, expected_reason: &str) { 134fn assert_match_failure_reason(pattern: &str, code: &str, snippet: &str, expected_reason: &str) {
@@ -133,8 +148,8 @@ fn assert_match_failure_reason(pattern: &str, code: &str, snippet: &str, expecte
133fn ssr_function_to_method() { 148fn ssr_function_to_method() {
134 assert_ssr_transform( 149 assert_ssr_transform(
135 "my_function($a, $b) ==>> ($a).my_method($b)", 150 "my_function($a, $b) ==>> ($a).my_method($b)",
136 "loop { my_function( other_func(x, y), z + w) }", 151 "fn my_function() {} fn main() { loop { my_function( other_func(x, y), z + w) } }",
137 "loop { (other_func(x, y)).my_method(z + w) }", 152 "fn my_function() {} fn main() { loop { (other_func(x, y)).my_method(z + w) } }",
138 ) 153 )
139} 154}
140 155
@@ -142,8 +157,8 @@ fn ssr_function_to_method() {
142fn ssr_nested_function() { 157fn ssr_nested_function() {
143 assert_ssr_transform( 158 assert_ssr_transform(
144 "foo($a, $b, $c) ==>> bar($c, baz($a, $b))", 159 "foo($a, $b, $c) ==>> bar($c, baz($a, $b))",
145 "fn main { foo (x + value.method(b), x+y-z, true && false) }", 160 "fn foo() {} fn main { foo (x + value.method(b), x+y-z, true && false) }",
146 "fn main { bar(true && false, baz(x + value.method(b), x+y-z)) }", 161 "fn foo() {} fn main { bar(true && false, baz(x + value.method(b), x+y-z)) }",
147 ) 162 )
148} 163}
149 164
@@ -151,8 +166,8 @@ fn ssr_nested_function() {
151fn ssr_expected_spacing() { 166fn ssr_expected_spacing() {
152 assert_ssr_transform( 167 assert_ssr_transform(
153 "foo($x) + bar() ==>> bar($x)", 168 "foo($x) + bar() ==>> bar($x)",
154 "fn main() { foo(5) + bar() }", 169 "fn foo() {} fn bar() {} fn main() { foo(5) + bar() }",
155 "fn main() { bar(5) }", 170 "fn foo() {} fn bar() {} fn main() { bar(5) }",
156 ); 171 );
157} 172}
158 173
@@ -160,8 +175,8 @@ fn ssr_expected_spacing() {
160fn ssr_with_extra_space() { 175fn ssr_with_extra_space() {
161 assert_ssr_transform( 176 assert_ssr_transform(
162 "foo($x ) + bar() ==>> bar($x)", 177 "foo($x ) + bar() ==>> bar($x)",
163 "fn main() { foo( 5 ) +bar( ) }", 178 "fn foo() {} fn bar() {} fn main() { foo( 5 ) +bar( ) }",
164 "fn main() { bar(5) }", 179 "fn foo() {} fn bar() {} fn main() { bar(5) }",
165 ); 180 );
166} 181}
167 182
@@ -169,8 +184,8 @@ fn ssr_with_extra_space() {
169fn ssr_keeps_nested_comment() { 184fn ssr_keeps_nested_comment() {
170 assert_ssr_transform( 185 assert_ssr_transform(
171 "foo($x) ==>> bar($x)", 186 "foo($x) ==>> bar($x)",
172 "fn main() { foo(other(5 /* using 5 */)) }", 187 "fn foo() {} fn main() { foo(other(5 /* using 5 */)) }",
173 "fn main() { bar(other(5 /* using 5 */)) }", 188 "fn foo() {} fn main() { bar(other(5 /* using 5 */)) }",
174 ) 189 )
175} 190}
176 191
@@ -178,8 +193,8 @@ fn ssr_keeps_nested_comment() {
178fn ssr_keeps_comment() { 193fn ssr_keeps_comment() {
179 assert_ssr_transform( 194 assert_ssr_transform(
180 "foo($x) ==>> bar($x)", 195 "foo($x) ==>> bar($x)",
181 "fn main() { foo(5 /* using 5 */) }", 196 "fn foo() {} fn main() { foo(5 /* using 5 */) }",
182 "fn main() { bar(5)/* using 5 */ }", 197 "fn foo() {} fn main() { bar(5)/* using 5 */ }",
183 ) 198 )
184} 199}
185 200
@@ -187,8 +202,8 @@ fn ssr_keeps_comment() {
187fn ssr_struct_lit() { 202fn ssr_struct_lit() {
188 assert_ssr_transform( 203 assert_ssr_transform(
189 "foo{a: $a, b: $b} ==>> foo::new($a, $b)", 204 "foo{a: $a, b: $b} ==>> foo::new($a, $b)",
190 "fn main() { foo{b:2, a:1} }", 205 "fn foo() {} fn main() { foo{b:2, a:1} }",
191 "fn main() { foo::new(1, 2) }", 206 "fn foo() {} fn main() { foo::new(1, 2) }",
192 ) 207 )
193} 208}
194 209
@@ -210,16 +225,18 @@ fn match_fn_definition() {
210 225
211#[test] 226#[test]
212fn match_struct_definition() { 227fn match_struct_definition() {
213 assert_matches( 228 let code = r#"
214 "struct $n {$f: Option<String>}", 229 struct Option<T> {}
215 "struct Bar {} struct Foo {name: Option<String>}", 230 struct Bar {}
216 &["struct Foo {name: Option<String>}"], 231 struct Foo {name: Option<String>}"#;
217 ); 232 assert_matches("struct $n {$f: Option<String>}", code, &["struct Foo {name: Option<String>}"]);
218} 233}
219 234
220#[test] 235#[test]
221fn match_expr() { 236fn match_expr() {
222 let code = "fn f() -> i32 {foo(40 + 2, 42)}"; 237 let code = r#"
238 fn foo() {}
239 fn f() -> i32 {foo(40 + 2, 42)}"#;
223 assert_matches("foo($a, $b)", code, &["foo(40 + 2, 42)"]); 240 assert_matches("foo($a, $b)", code, &["foo(40 + 2, 42)"]);
224 assert_no_match("foo($a, $b, $c)", code); 241 assert_no_match("foo($a, $b, $c)", code);
225 assert_no_match("foo($a)", code); 242 assert_no_match("foo($a)", code);
@@ -248,7 +265,9 @@ fn match_nested_method_calls_with_macro_call() {
248 265
249#[test] 266#[test]
250fn match_complex_expr() { 267fn match_complex_expr() {
251 let code = "fn f() -> i32 {foo(bar(40, 2), 42)}"; 268 let code = r#"
269 fn foo() {} fn bar() {}
270 fn f() -> i32 {foo(bar(40, 2), 42)}"#;
252 assert_matches("foo($a, $b)", code, &["foo(bar(40, 2), 42)"]); 271 assert_matches("foo($a, $b)", code, &["foo(bar(40, 2), 42)"]);
253 assert_no_match("foo($a, $b, $c)", code); 272 assert_no_match("foo($a, $b, $c)", code);
254 assert_no_match("foo($a)", code); 273 assert_no_match("foo($a)", code);
@@ -259,53 +278,62 @@ fn match_complex_expr() {
259#[test] 278#[test]
260fn match_with_trailing_commas() { 279fn match_with_trailing_commas() {
261 // Code has comma, pattern doesn't. 280 // Code has comma, pattern doesn't.
262 assert_matches("foo($a, $b)", "fn f() {foo(1, 2,);}", &["foo(1, 2,)"]); 281 assert_matches("foo($a, $b)", "fn foo() {} fn f() {foo(1, 2,);}", &["foo(1, 2,)"]);
263 assert_matches("Foo{$a, $b}", "fn f() {Foo{1, 2,};}", &["Foo{1, 2,}"]); 282 assert_matches("Foo{$a, $b}", "struct Foo {} fn f() {Foo{1, 2,};}", &["Foo{1, 2,}"]);
264 283
265 // Pattern has comma, code doesn't. 284 // Pattern has comma, code doesn't.
266 assert_matches("foo($a, $b,)", "fn f() {foo(1, 2);}", &["foo(1, 2)"]); 285 assert_matches("foo($a, $b,)", "fn foo() {} fn f() {foo(1, 2);}", &["foo(1, 2)"]);
267 assert_matches("Foo{$a, $b,}", "fn f() {Foo{1, 2};}", &["Foo{1, 2}"]); 286 assert_matches("Foo{$a, $b,}", "struct Foo {} fn f() {Foo{1, 2};}", &["Foo{1, 2}"]);
268} 287}
269 288
270#[test] 289#[test]
271fn match_type() { 290fn match_type() {
272 assert_matches("i32", "fn f() -> i32 {1 + 2}", &["i32"]); 291 assert_matches("i32", "fn f() -> i32 {1 + 2}", &["i32"]);
273 assert_matches("Option<$a>", "fn f() -> Option<i32> {42}", &["Option<i32>"]); 292 assert_matches(
274 assert_no_match("Option<$a>", "fn f() -> Result<i32, ()> {42}"); 293 "Option<$a>",
294 "struct Option<T> {} fn f() -> Option<i32> {42}",
295 &["Option<i32>"],
296 );
297 assert_no_match(
298 "Option<$a>",
299 "struct Option<T> {} struct Result<T, E> {} fn f() -> Result<i32, ()> {42}",
300 );
275} 301}
276 302
277#[test] 303#[test]
278fn match_struct_instantiation() { 304fn match_struct_instantiation() {
279 assert_matches( 305 let code = r#"
280 "Foo {bar: 1, baz: 2}", 306 struct Foo {bar: i32, baz: i32}
281 "fn f() {Foo {bar: 1, baz: 2}}", 307 fn f() {Foo {bar: 1, baz: 2}}"#;
282 &["Foo {bar: 1, baz: 2}"], 308 assert_matches("Foo {bar: 1, baz: 2}", code, &["Foo {bar: 1, baz: 2}"]);
283 );
284 // Now with placeholders for all parts of the struct. 309 // Now with placeholders for all parts of the struct.
285 assert_matches( 310 assert_matches("Foo {$a: $b, $c: $d}", code, &["Foo {bar: 1, baz: 2}"]);
286 "Foo {$a: $b, $c: $d}", 311 assert_matches("Foo {}", "struct Foo {} fn f() {Foo {}}", &["Foo {}"]);
287 "fn f() {Foo {bar: 1, baz: 2}}",
288 &["Foo {bar: 1, baz: 2}"],
289 );
290 assert_matches("Foo {}", "fn f() {Foo {}}", &["Foo {}"]);
291} 312}
292 313
293#[test] 314#[test]
294fn match_path() { 315fn match_path() {
295 assert_matches("foo::bar", "fn f() {foo::bar(42)}", &["foo::bar"]); 316 let code = r#"
296 assert_matches("$a::bar", "fn f() {foo::bar(42)}", &["foo::bar"]); 317 mod foo {
297 assert_matches("foo::$b", "fn f() {foo::bar(42)}", &["foo::bar"]); 318 fn bar() {}
319 }
320 fn f() {foo::bar(42)}"#;
321 assert_matches("foo::bar", code, &["foo::bar"]);
322 assert_matches("$a::bar", code, &["foo::bar"]);
323 assert_matches("foo::$b", code, &["foo::bar"]);
298} 324}
299 325
300#[test] 326#[test]
301fn match_pattern() { 327fn match_pattern() {
302 assert_matches("Some($a)", "fn f() {if let Some(x) = foo() {}}", &["Some(x)"]); 328 assert_matches("Some($a)", "struct Some(); fn f() {if let Some(x) = foo() {}}", &["Some(x)"]);
303} 329}
304 330
305#[test] 331#[test]
306fn literal_constraint() { 332fn literal_constraint() {
307 mark::check!(literal_constraint); 333 mark::check!(literal_constraint);
308 let code = r#" 334 let code = r#"
335 enum Option<T> { Some(T), None }
336 use Option::Some;
309 fn f1() { 337 fn f1() {
310 let x1 = Some(42); 338 let x1 = Some(42);
311 let x2 = Some("foo"); 339 let x2 = Some("foo");
@@ -322,24 +350,36 @@ fn literal_constraint() {
322fn match_reordered_struct_instantiation() { 350fn match_reordered_struct_instantiation() {
323 assert_matches( 351 assert_matches(
324 "Foo {aa: 1, b: 2, ccc: 3}", 352 "Foo {aa: 1, b: 2, ccc: 3}",
325 "fn f() {Foo {b: 2, ccc: 3, aa: 1}}", 353 "struct Foo {} fn f() {Foo {b: 2, ccc: 3, aa: 1}}",
326 &["Foo {b: 2, ccc: 3, aa: 1}"], 354 &["Foo {b: 2, ccc: 3, aa: 1}"],
327 ); 355 );
328 assert_no_match("Foo {a: 1}", "fn f() {Foo {b: 1}}"); 356 assert_no_match("Foo {a: 1}", "struct Foo {} fn f() {Foo {b: 1}}");
329 assert_no_match("Foo {a: 1}", "fn f() {Foo {a: 2}}"); 357 assert_no_match("Foo {a: 1}", "struct Foo {} fn f() {Foo {a: 2}}");
330 assert_no_match("Foo {a: 1, b: 2}", "fn f() {Foo {a: 1}}"); 358 assert_no_match("Foo {a: 1, b: 2}", "struct Foo {} fn f() {Foo {a: 1}}");
331 assert_no_match("Foo {a: 1, b: 2}", "fn f() {Foo {b: 2}}"); 359 assert_no_match("Foo {a: 1, b: 2}", "struct Foo {} fn f() {Foo {b: 2}}");
332 assert_no_match("Foo {a: 1, }", "fn f() {Foo {a: 1, b: 2}}"); 360 assert_no_match("Foo {a: 1, }", "struct Foo {} fn f() {Foo {a: 1, b: 2}}");
333 assert_no_match("Foo {a: 1, z: 9}", "fn f() {Foo {a: 1}}"); 361 assert_no_match("Foo {a: 1, z: 9}", "struct Foo {} fn f() {Foo {a: 1}}");
334} 362}
335 363
336#[test] 364#[test]
337fn match_macro_invocation() { 365fn match_macro_invocation() {
338 assert_matches("foo!($a)", "fn() {foo(foo!(foo()))}", &["foo!(foo())"]); 366 assert_matches(
339 assert_matches("foo!(41, $a, 43)", "fn() {foo!(41, 42, 43)}", &["foo!(41, 42, 43)"]); 367 "foo!($a)",
340 assert_no_match("foo!(50, $a, 43)", "fn() {foo!(41, 42, 43}"); 368 "macro_rules! foo {() => {}} fn() {foo(foo!(foo()))}",
341 assert_no_match("foo!(41, $a, 50)", "fn() {foo!(41, 42, 43}"); 369 &["foo!(foo())"],
342 assert_matches("foo!($a())", "fn() {foo!(bar())}", &["foo!(bar())"]); 370 );
371 assert_matches(
372 "foo!(41, $a, 43)",
373 "macro_rules! foo {() => {}} fn() {foo!(41, 42, 43)}",
374 &["foo!(41, 42, 43)"],
375 );
376 assert_no_match("foo!(50, $a, 43)", "macro_rules! foo {() => {}} fn() {foo!(41, 42, 43}");
377 assert_no_match("foo!(41, $a, 50)", "macro_rules! foo {() => {}} fn() {foo!(41, 42, 43}");
378 assert_matches(
379 "foo!($a())",
380 "macro_rules! foo {() => {}} fn() {foo!(bar())}",
381 &["foo!(bar())"],
382 );
343} 383}
344 384
345// When matching within a macro expansion, we only allow matches of nodes that originated from 385// When matching within a macro expansion, we only allow matches of nodes that originated from
@@ -374,15 +414,19 @@ fn no_match_split_expression() {
374 414
375#[test] 415#[test]
376fn replace_function_call() { 416fn replace_function_call() {
377 assert_ssr_transform("foo() ==>> bar()", "fn f1() {foo(); foo();}", "fn f1() {bar(); bar();}"); 417 assert_ssr_transform(
418 "foo() ==>> bar()",
419 "fn foo() {} fn f1() {foo(); foo();}",
420 "fn foo() {} fn f1() {bar(); bar();}",
421 );
378} 422}
379 423
380#[test] 424#[test]
381fn replace_function_call_with_placeholders() { 425fn replace_function_call_with_placeholders() {
382 assert_ssr_transform( 426 assert_ssr_transform(
383 "foo($a, $b) ==>> bar($b, $a)", 427 "foo($a, $b) ==>> bar($b, $a)",
384 "fn f1() {foo(5, 42)}", 428 "fn foo() {} fn f1() {foo(5, 42)}",
385 "fn f1() {bar(42, 5)}", 429 "fn foo() {} fn f1() {bar(42, 5)}",
386 ); 430 );
387} 431}
388 432
@@ -390,8 +434,8 @@ fn replace_function_call_with_placeholders() {
390fn replace_nested_function_calls() { 434fn replace_nested_function_calls() {
391 assert_ssr_transform( 435 assert_ssr_transform(
392 "foo($a) ==>> bar($a)", 436 "foo($a) ==>> bar($a)",
393 "fn f1() {foo(foo(42))}", 437 "fn foo() {} fn f1() {foo(foo(42))}",
394 "fn f1() {bar(bar(42))}", 438 "fn foo() {} fn f1() {bar(bar(42))}",
395 ); 439 );
396} 440}
397 441
@@ -399,8 +443,8 @@ fn replace_nested_function_calls() {
399fn replace_type() { 443fn replace_type() {
400 assert_ssr_transform( 444 assert_ssr_transform(
401 "Result<(), $a> ==>> Option<$a>", 445 "Result<(), $a> ==>> Option<$a>",
402 "fn f1() -> Result<(), Vec<Error>> {foo()}", 446 "struct Result<T, E> {} fn f1() -> Result<(), Vec<Error>> {foo()}",
403 "fn f1() -> Option<Vec<Error>> {foo()}", 447 "struct Result<T, E> {} fn f1() -> Option<Vec<Error>> {foo()}",
404 ); 448 );
405} 449}
406 450
@@ -408,8 +452,8 @@ fn replace_type() {
408fn replace_struct_init() { 452fn replace_struct_init() {
409 assert_ssr_transform( 453 assert_ssr_transform(
410 "Foo {a: $a, b: $b} ==>> Foo::new($a, $b)", 454 "Foo {a: $a, b: $b} ==>> Foo::new($a, $b)",
411 "fn f1() {Foo{b: 1, a: 2}}", 455 "struct Foo {} fn f1() {Foo{b: 1, a: 2}}",
412 "fn f1() {Foo::new(2, 1)}", 456 "struct Foo {} fn f1() {Foo::new(2, 1)}",
413 ); 457 );
414} 458}
415 459
@@ -417,13 +461,13 @@ fn replace_struct_init() {
417fn replace_macro_invocations() { 461fn replace_macro_invocations() {
418 assert_ssr_transform( 462 assert_ssr_transform(
419 "try!($a) ==>> $a?", 463 "try!($a) ==>> $a?",
420 "fn f1() -> Result<(), E> {bar(try!(foo()));}", 464 "macro_rules! try {() => {}} fn f1() -> Result<(), E> {bar(try!(foo()));}",
421 "fn f1() -> Result<(), E> {bar(foo()?);}", 465 "macro_rules! try {() => {}} fn f1() -> Result<(), E> {bar(foo()?);}",
422 ); 466 );
423 assert_ssr_transform( 467 assert_ssr_transform(
424 "foo!($a($b)) ==>> foo($b, $a)", 468 "foo!($a($b)) ==>> foo($b, $a)",
425 "fn f1() {foo!(abc(def() + 2));}", 469 "macro_rules! foo {() => {}} fn f1() {foo!(abc(def() + 2));}",
426 "fn f1() {foo(def() + 2, abc);}", 470 "macro_rules! foo {() => {}} fn f1() {foo(def() + 2, abc);}",
427 ); 471 );
428} 472}
429 473
@@ -512,6 +556,7 @@ fn preserves_whitespace_within_macro_expansion() {
512#[test] 556#[test]
513fn match_failure_reasons() { 557fn match_failure_reasons() {
514 let code = r#" 558 let code = r#"
559 fn bar() {}
515 macro_rules! foo { 560 macro_rules! foo {
516 ($a:expr) => { 561 ($a:expr) => {
517 1 + $a + 2 562 1 + $a + 2