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.rs96
1 files changed, 79 insertions, 17 deletions
diff --git a/crates/ra_ssr/src/tests.rs b/crates/ra_ssr/src/tests.rs
index 18ef2506a..6a44ef378 100644
--- a/crates/ra_ssr/src/tests.rs
+++ b/crates/ra_ssr/src/tests.rs
@@ -1,9 +1,9 @@
1use crate::{MatchFinder, SsrRule}; 1use crate::{MatchFinder, SsrRule};
2use expect::{expect, Expect}; 2use expect::{expect, Expect};
3use ra_db::{salsa::Durability, FileId, FilePosition, SourceDatabaseExt}; 3use ra_db::{salsa::Durability, FileId, FilePosition, FileRange, SourceDatabaseExt};
4use rustc_hash::FxHashSet; 4use rustc_hash::FxHashSet;
5use std::sync::Arc; 5use std::sync::Arc;
6use test_utils::mark; 6use test_utils::{mark, RangeOrOffset};
7 7
8fn parse_error_text(query: &str) -> String { 8fn parse_error_text(query: &str) -> String {
9 format!("{}", query.parse::<SsrRule>().unwrap_err()) 9 format!("{}", query.parse::<SsrRule>().unwrap_err())
@@ -60,20 +60,32 @@ fn parser_undefined_placeholder_in_replacement() {
60} 60}
61 61
62/// `code` may optionally contain a cursor marker `<|>`. If it doesn't, then the position will be 62/// `code` may optionally contain a cursor marker `<|>`. If it doesn't, then the position will be
63/// the start of the file. 63/// the start of the file. If there's a second cursor marker, then we'll return a single range.
64pub(crate) fn single_file(code: &str) -> (ra_ide_db::RootDatabase, FilePosition) { 64pub(crate) fn single_file(code: &str) -> (ra_ide_db::RootDatabase, FilePosition, Vec<FileRange>) {
65 use ra_db::fixture::WithFixture; 65 use ra_db::fixture::WithFixture;
66 use ra_ide_db::symbol_index::SymbolsDatabase; 66 use ra_ide_db::symbol_index::SymbolsDatabase;
67 let (mut db, position) = if code.contains(test_utils::CURSOR_MARKER) { 67 let (mut db, file_id, range_or_offset) = if code.contains(test_utils::CURSOR_MARKER) {
68 ra_ide_db::RootDatabase::with_position(code) 68 ra_ide_db::RootDatabase::with_range_or_offset(code)
69 } else { 69 } else {
70 let (db, file_id) = ra_ide_db::RootDatabase::with_single_file(code); 70 let (db, file_id) = ra_ide_db::RootDatabase::with_single_file(code);
71 (db, FilePosition { file_id, offset: 0.into() }) 71 (db, file_id, RangeOrOffset::Offset(0.into()))
72 }; 72 };
73 let selections;
74 let position;
75 match range_or_offset {
76 RangeOrOffset::Range(range) => {
77 position = FilePosition { file_id, offset: range.start() };
78 selections = vec![FileRange { file_id, range: range }];
79 }
80 RangeOrOffset::Offset(offset) => {
81 position = FilePosition { file_id, offset };
82 selections = vec![];
83 }
84 }
73 let mut local_roots = FxHashSet::default(); 85 let mut local_roots = FxHashSet::default();
74 local_roots.insert(ra_db::fixture::WORKSPACE); 86 local_roots.insert(ra_db::fixture::WORKSPACE);
75 db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH); 87 db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
76 (db, position) 88 (db, position, selections)
77} 89}
78 90
79fn assert_ssr_transform(rule: &str, input: &str, expected: Expect) { 91fn assert_ssr_transform(rule: &str, input: &str, expected: Expect) {
@@ -81,8 +93,8 @@ fn assert_ssr_transform(rule: &str, input: &str, expected: Expect) {
81} 93}
82 94
83fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) { 95fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) {
84 let (db, position) = single_file(input); 96 let (db, position, selections) = single_file(input);
85 let mut match_finder = MatchFinder::in_context(&db, position); 97 let mut match_finder = MatchFinder::in_context(&db, position, selections);
86 for rule in rules { 98 for rule in rules {
87 let rule: SsrRule = rule.parse().unwrap(); 99 let rule: SsrRule = rule.parse().unwrap();
88 match_finder.add_rule(rule).unwrap(); 100 match_finder.add_rule(rule).unwrap();
@@ -112,8 +124,8 @@ fn print_match_debug_info(match_finder: &MatchFinder, file_id: FileId, snippet:
112} 124}
113 125
114fn assert_matches(pattern: &str, code: &str, expected: &[&str]) { 126fn assert_matches(pattern: &str, code: &str, expected: &[&str]) {
115 let (db, position) = single_file(code); 127 let (db, position, selections) = single_file(code);
116 let mut match_finder = MatchFinder::in_context(&db, position); 128 let mut match_finder = MatchFinder::in_context(&db, position, selections);
117 match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap(); 129 match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
118 let matched_strings: Vec<String> = 130 let matched_strings: Vec<String> =
119 match_finder.matches().flattened().matches.iter().map(|m| m.matched_text()).collect(); 131 match_finder.matches().flattened().matches.iter().map(|m| m.matched_text()).collect();
@@ -124,8 +136,8 @@ fn assert_matches(pattern: &str, code: &str, expected: &[&str]) {
124} 136}
125 137
126fn assert_no_match(pattern: &str, code: &str) { 138fn assert_no_match(pattern: &str, code: &str) {
127 let (db, position) = single_file(code); 139 let (db, position, selections) = single_file(code);
128 let mut match_finder = MatchFinder::in_context(&db, position); 140 let mut match_finder = MatchFinder::in_context(&db, position, selections);
129 match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap(); 141 match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
130 let matches = match_finder.matches().flattened().matches; 142 let matches = match_finder.matches().flattened().matches;
131 if !matches.is_empty() { 143 if !matches.is_empty() {
@@ -135,8 +147,8 @@ fn assert_no_match(pattern: &str, code: &str) {
135} 147}
136 148
137fn assert_match_failure_reason(pattern: &str, code: &str, snippet: &str, expected_reason: &str) { 149fn assert_match_failure_reason(pattern: &str, code: &str, snippet: &str, expected_reason: &str) {
138 let (db, position) = single_file(code); 150 let (db, position, selections) = single_file(code);
139 let mut match_finder = MatchFinder::in_context(&db, position); 151 let mut match_finder = MatchFinder::in_context(&db, position, selections);
140 match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap(); 152 match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
141 let mut reasons = Vec::new(); 153 let mut reasons = Vec::new();
142 for d in match_finder.debug_where_text_equal(position.file_id, snippet) { 154 for d in match_finder.debug_where_text_equal(position.file_id, snippet) {
@@ -490,9 +502,10 @@ fn no_match_split_expression() {
490 502
491#[test] 503#[test]
492fn replace_function_call() { 504fn replace_function_call() {
505 // This test also makes sure that we ignore empty-ranges.
493 assert_ssr_transform( 506 assert_ssr_transform(
494 "foo() ==>> bar()", 507 "foo() ==>> bar()",
495 "fn foo() {} fn bar() {} fn f1() {foo(); foo();}", 508 "fn foo() {<|><|>} fn bar() {} fn f1() {foo(); foo();}",
496 expect![["fn foo() {} fn bar() {} fn f1() {bar(); bar();}"]], 509 expect![["fn foo() {} fn bar() {} fn f1() {bar(); bar();}"]],
497 ); 510 );
498} 511}
@@ -922,3 +935,52 @@ fn replace_local_variable_reference() {
922 "#]], 935 "#]],
923 ) 936 )
924} 937}
938
939#[test]
940fn replace_path_within_selection() {
941 assert_ssr_transform(
942 "foo ==>> bar",
943 r#"
944 fn main() {
945 let foo = 41;
946 let bar = 42;
947 do_stuff(foo);
948 do_stuff(foo);<|>
949 do_stuff(foo);
950 do_stuff(foo);<|>
951 do_stuff(foo);
952 }"#,
953 expect![[r#"
954 fn main() {
955 let foo = 41;
956 let bar = 42;
957 do_stuff(foo);
958 do_stuff(foo);
959 do_stuff(bar);
960 do_stuff(bar);
961 do_stuff(foo);
962 }"#]],
963 );
964}
965
966#[test]
967fn replace_nonpath_within_selection() {
968 mark::check!(replace_nonpath_within_selection);
969 assert_ssr_transform(
970 "$a + $b ==>> $b * $a",
971 r#"
972 fn main() {
973 let v = 1 + 2;<|>
974 let v2 = 3 + 3;
975 let v3 = 4 + 5;<|>
976 let v4 = 6 + 7;
977 }"#,
978 expect![[r#"
979 fn main() {
980 let v = 1 + 2;
981 let v2 = 3 * 3;
982 let v3 = 5 * 4;
983 let v4 = 6 + 7;
984 }"#]],
985 );
986}