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.rs142
1 files changed, 138 insertions, 4 deletions
diff --git a/crates/ra_ssr/src/tests.rs b/crates/ra_ssr/src/tests.rs
index 63d527894..33742dc8e 100644
--- a/crates/ra_ssr/src/tests.rs
+++ b/crates/ra_ssr/src/tests.rs
@@ -85,7 +85,7 @@ fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) {
85 let mut match_finder = MatchFinder::in_context(&db, position); 85 let mut match_finder = MatchFinder::in_context(&db, position);
86 for rule in rules { 86 for rule in rules {
87 let rule: SsrRule = rule.parse().unwrap(); 87 let rule: SsrRule = rule.parse().unwrap();
88 match_finder.add_rule(rule); 88 match_finder.add_rule(rule).unwrap();
89 } 89 }
90 let edits = match_finder.edits(); 90 let edits = match_finder.edits();
91 if edits.is_empty() { 91 if edits.is_empty() {
@@ -114,7 +114,7 @@ fn print_match_debug_info(match_finder: &MatchFinder, file_id: FileId, snippet:
114fn assert_matches(pattern: &str, code: &str, expected: &[&str]) { 114fn assert_matches(pattern: &str, code: &str, expected: &[&str]) {
115 let (db, position) = single_file(code); 115 let (db, position) = single_file(code);
116 let mut match_finder = MatchFinder::in_context(&db, position); 116 let mut match_finder = MatchFinder::in_context(&db, position);
117 match_finder.add_search_pattern(pattern.parse().unwrap()); 117 match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
118 let matched_strings: Vec<String> = 118 let matched_strings: Vec<String> =
119 match_finder.matches().flattened().matches.iter().map(|m| m.matched_text()).collect(); 119 match_finder.matches().flattened().matches.iter().map(|m| m.matched_text()).collect();
120 if matched_strings != expected && !expected.is_empty() { 120 if matched_strings != expected && !expected.is_empty() {
@@ -126,7 +126,7 @@ fn assert_matches(pattern: &str, code: &str, expected: &[&str]) {
126fn assert_no_match(pattern: &str, code: &str) { 126fn assert_no_match(pattern: &str, code: &str) {
127 let (db, position) = single_file(code); 127 let (db, position) = single_file(code);
128 let mut match_finder = MatchFinder::in_context(&db, position); 128 let mut match_finder = MatchFinder::in_context(&db, position);
129 match_finder.add_search_pattern(pattern.parse().unwrap()); 129 match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
130 let matches = match_finder.matches().flattened().matches; 130 let matches = match_finder.matches().flattened().matches;
131 if !matches.is_empty() { 131 if !matches.is_empty() {
132 print_match_debug_info(&match_finder, position.file_id, &matches[0].matched_text()); 132 print_match_debug_info(&match_finder, position.file_id, &matches[0].matched_text());
@@ -137,7 +137,7 @@ fn assert_no_match(pattern: &str, code: &str) {
137fn assert_match_failure_reason(pattern: &str, code: &str, snippet: &str, expected_reason: &str) { 137fn assert_match_failure_reason(pattern: &str, code: &str, snippet: &str, expected_reason: &str) {
138 let (db, position) = single_file(code); 138 let (db, position) = single_file(code);
139 let mut match_finder = MatchFinder::in_context(&db, position); 139 let mut match_finder = MatchFinder::in_context(&db, position);
140 match_finder.add_search_pattern(pattern.parse().unwrap()); 140 match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
141 let mut reasons = Vec::new(); 141 let mut reasons = Vec::new();
142 for d in match_finder.debug_where_text_equal(position.file_id, snippet) { 142 for d in match_finder.debug_where_text_equal(position.file_id, snippet) {
143 if let Some(reason) = d.match_failure_reason() { 143 if let Some(reason) = d.match_failure_reason() {
@@ -350,6 +350,60 @@ fn match_pattern() {
350 assert_matches("Some($a)", "struct Some(); fn f() {if let Some(x) = foo() {}}", &["Some(x)"]); 350 assert_matches("Some($a)", "struct Some(); fn f() {if let Some(x) = foo() {}}", &["Some(x)"]);
351} 351}
352 352
353// If our pattern has a full path, e.g. a::b::c() and the code has c(), but c resolves to
354// a::b::c, then we should match.
355#[test]
356fn match_fully_qualified_fn_path() {
357 let code = r#"
358 mod a {
359 pub mod b {
360 pub fn c(_: i32) {}
361 }
362 }
363 use a::b::c;
364 fn f1() {
365 c(42);
366 }
367 "#;
368 assert_matches("a::b::c($a)", code, &["c(42)"]);
369}
370
371#[test]
372fn match_resolved_type_name() {
373 let code = r#"
374 mod m1 {
375 pub mod m2 {
376 pub trait Foo<T> {}
377 }
378 }
379 mod m3 {
380 trait Foo<T> {}
381 fn f1(f: Option<&dyn Foo<bool>>) {}
382 }
383 mod m4 {
384 use crate::m1::m2::Foo;
385 fn f1(f: Option<&dyn Foo<i32>>) {}
386 }
387 "#;
388 assert_matches("m1::m2::Foo<$t>", code, &["Foo<i32>"]);
389}
390
391#[test]
392fn type_arguments_within_path() {
393 mark::check!(type_arguments_within_path);
394 let code = r#"
395 mod foo {
396 pub struct Bar<T> {t: T}
397 impl<T> Bar<T> {
398 pub fn baz() {}
399 }
400 }
401 fn f1() {foo::Bar::<i32>::baz();}
402 "#;
403 assert_no_match("foo::Bar::<i64>::baz()", code);
404 assert_matches("foo::Bar::<i32>::baz()", code, &["foo::Bar::<i32>::baz()"]);
405}
406
353#[test] 407#[test]
354fn literal_constraint() { 408fn literal_constraint() {
355 mark::check!(literal_constraint); 409 mark::check!(literal_constraint);
@@ -483,6 +537,86 @@ fn replace_associated_function_call() {
483} 537}
484 538
485#[test] 539#[test]
540fn replace_path_in_different_contexts() {
541 // Note the <|> inside module a::b which marks the point where the rule is interpreted. We
542 // replace foo with bar, but both need different path qualifiers in different contexts. In f4,
543 // foo is unqualified because of a use statement, however the replacement needs to be fully
544 // qualified.
545 assert_ssr_transform(
546 "c::foo() ==>> c::bar()",
547 r#"
548 mod a {
549 pub mod b {<|>
550 pub mod c {
551 pub fn foo() {}
552 pub fn bar() {}
553 fn f1() { foo() }
554 }
555 fn f2() { c::foo() }
556 }
557 fn f3() { b::c::foo() }
558 }
559 use a::b::c::foo;
560 fn f4() { foo() }
561 "#,
562 expect![[r#"
563 mod a {
564 pub mod b {
565 pub mod c {
566 pub fn foo() {}
567 pub fn bar() {}
568 fn f1() { bar() }
569 }
570 fn f2() { c::bar() }
571 }
572 fn f3() { b::c::bar() }
573 }
574 use a::b::c::foo;
575 fn f4() { a::b::c::bar() }
576 "#]],
577 );
578}
579
580#[test]
581fn replace_associated_function_with_generics() {
582 assert_ssr_transform(
583 "c::Foo::<$a>::new() ==>> d::Bar::<$a>::default()",
584 r#"
585 mod c {
586 pub struct Foo<T> {v: T}
587 impl<T> Foo<T> { pub fn new() {} }
588 fn f1() {
589 Foo::<i32>::new();
590 }
591 }
592 mod d {
593 pub struct Bar<T> {v: T}
594 impl<T> Bar<T> { pub fn default() {} }
595 fn f1() {
596 super::c::Foo::<i32>::new();
597 }
598 }
599 "#,
600 expect![[r#"
601 mod c {
602 pub struct Foo<T> {v: T}
603 impl<T> Foo<T> { pub fn new() {} }
604 fn f1() {
605 crate::d::Bar::<i32>::default();
606 }
607 }
608 mod d {
609 pub struct Bar<T> {v: T}
610 impl<T> Bar<T> { pub fn default() {} }
611 fn f1() {
612 Bar::<i32>::default();
613 }
614 }
615 "#]],
616 );
617}
618
619#[test]
486fn replace_type() { 620fn replace_type() {
487 assert_ssr_transform( 621 assert_ssr_transform(
488 "Result<(), $a> ==>> Option<$a>", 622 "Result<(), $a> ==>> Option<$a>",