diff options
Diffstat (limited to 'crates/ra_assists/src/tests.rs')
-rw-r--r-- | crates/ra_assists/src/tests.rs | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/crates/ra_assists/src/tests.rs b/crates/ra_assists/src/tests.rs new file mode 100644 index 000000000..ca3096a43 --- /dev/null +++ b/crates/ra_assists/src/tests.rs | |||
@@ -0,0 +1,137 @@ | |||
1 | use std::sync::Arc; | ||
2 | |||
3 | use hir::Semantics; | ||
4 | use ra_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt}; | ||
5 | use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase}; | ||
6 | use ra_syntax::TextRange; | ||
7 | use test_utils::{ | ||
8 | add_cursor, assert_eq_text, extract_offset, extract_range, extract_range_or_offset, | ||
9 | RangeOrOffset, | ||
10 | }; | ||
11 | |||
12 | use crate::{handlers::Handler, resolved_assists, AssistCtx, AssistFile}; | ||
13 | |||
14 | pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { | ||
15 | let (mut db, file_id) = RootDatabase::with_single_file(text); | ||
16 | // FIXME: ideally, this should be done by the above `RootDatabase::with_single_file`, | ||
17 | // but it looks like this might need specialization? :( | ||
18 | db.set_local_roots(Arc::new(vec![db.file_source_root(file_id)])); | ||
19 | (db, file_id) | ||
20 | } | ||
21 | |||
22 | pub(crate) fn check_assist(assist: Handler, ra_fixture_before: &str, ra_fixture_after: &str) { | ||
23 | check(assist, ra_fixture_before, ExpectedResult::After(ra_fixture_after)); | ||
24 | } | ||
25 | |||
26 | // FIXME: instead of having a separate function here, maybe use | ||
27 | // `extract_ranges` and mark the target as `<target> </target>` in the | ||
28 | // fixuture? | ||
29 | pub(crate) fn check_assist_target(assist: Handler, ra_fixture: &str, target: &str) { | ||
30 | check(assist, ra_fixture, ExpectedResult::Target(target)); | ||
31 | } | ||
32 | |||
33 | pub(crate) fn check_assist_not_applicable(assist: Handler, ra_fixture: &str) { | ||
34 | check(assist, ra_fixture, ExpectedResult::NotApplicable); | ||
35 | } | ||
36 | |||
37 | enum ExpectedResult<'a> { | ||
38 | NotApplicable, | ||
39 | After(&'a str), | ||
40 | Target(&'a str), | ||
41 | } | ||
42 | |||
43 | fn check(assist: Handler, before: &str, expected: ExpectedResult) { | ||
44 | let (text_without_caret, file_with_caret_id, range_or_offset, db) = if before.contains("//-") { | ||
45 | let (mut db, position) = RootDatabase::with_position(before); | ||
46 | db.set_local_roots(Arc::new(vec![db.file_source_root(position.file_id)])); | ||
47 | ( | ||
48 | db.file_text(position.file_id).as_ref().to_owned(), | ||
49 | position.file_id, | ||
50 | RangeOrOffset::Offset(position.offset), | ||
51 | db, | ||
52 | ) | ||
53 | } else { | ||
54 | let (range_or_offset, text_without_caret) = extract_range_or_offset(before); | ||
55 | let (db, file_id) = with_single_file(&text_without_caret); | ||
56 | (text_without_caret, file_id, range_or_offset, db) | ||
57 | }; | ||
58 | |||
59 | let frange = FileRange { file_id: file_with_caret_id, range: range_or_offset.into() }; | ||
60 | |||
61 | let sema = Semantics::new(&db); | ||
62 | let assist_ctx = AssistCtx::new(&sema, frange, true); | ||
63 | |||
64 | match (assist(assist_ctx), expected) { | ||
65 | (Some(assist), ExpectedResult::After(after)) => { | ||
66 | let action = assist.0[0].action.clone().unwrap(); | ||
67 | |||
68 | let mut actual = if let AssistFile::TargetFile(file_id) = action.file { | ||
69 | db.file_text(file_id).as_ref().to_owned() | ||
70 | } else { | ||
71 | text_without_caret | ||
72 | }; | ||
73 | action.edit.apply(&mut actual); | ||
74 | |||
75 | match action.cursor_position { | ||
76 | None => { | ||
77 | if let RangeOrOffset::Offset(before_cursor_pos) = range_or_offset { | ||
78 | let off = action | ||
79 | .edit | ||
80 | .apply_to_offset(before_cursor_pos) | ||
81 | .expect("cursor position is affected by the edit"); | ||
82 | actual = add_cursor(&actual, off) | ||
83 | } | ||
84 | } | ||
85 | Some(off) => actual = add_cursor(&actual, off), | ||
86 | }; | ||
87 | |||
88 | assert_eq_text!(after, &actual); | ||
89 | } | ||
90 | (Some(assist), ExpectedResult::Target(target)) => { | ||
91 | let action = assist.0[0].action.clone().unwrap(); | ||
92 | let range = action.target.expect("expected target on action"); | ||
93 | assert_eq_text!(&text_without_caret[range], target); | ||
94 | } | ||
95 | (Some(_), ExpectedResult::NotApplicable) => panic!("assist should not be applicable!"), | ||
96 | (None, ExpectedResult::After(_)) | (None, ExpectedResult::Target(_)) => { | ||
97 | panic!("code action is not applicable") | ||
98 | } | ||
99 | (None, ExpectedResult::NotApplicable) => (), | ||
100 | }; | ||
101 | } | ||
102 | |||
103 | #[test] | ||
104 | fn assist_order_field_struct() { | ||
105 | let before = "struct Foo { <|>bar: u32 }"; | ||
106 | let (before_cursor_pos, before) = extract_offset(before); | ||
107 | let (db, file_id) = with_single_file(&before); | ||
108 | let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) }; | ||
109 | let assists = resolved_assists(&db, frange); | ||
110 | let mut assists = assists.iter(); | ||
111 | |||
112 | assert_eq!( | ||
113 | assists.next().expect("expected assist").label.label, | ||
114 | "Change visibility to pub(crate)" | ||
115 | ); | ||
116 | assert_eq!(assists.next().expect("expected assist").label.label, "Add `#[derive]`"); | ||
117 | } | ||
118 | |||
119 | #[test] | ||
120 | fn assist_order_if_expr() { | ||
121 | let before = " | ||
122 | pub fn test_some_range(a: int) -> bool { | ||
123 | if let 2..6 = <|>5<|> { | ||
124 | true | ||
125 | } else { | ||
126 | false | ||
127 | } | ||
128 | }"; | ||
129 | let (range, before) = extract_range(before); | ||
130 | let (db, file_id) = with_single_file(&before); | ||
131 | let frange = FileRange { file_id, range }; | ||
132 | let assists = resolved_assists(&db, frange); | ||
133 | let mut assists = assists.iter(); | ||
134 | |||
135 | assert_eq!(assists.next().expect("expected assist").label.label, "Extract into variable"); | ||
136 | assert_eq!(assists.next().expect("expected assist").label.label, "Replace with match"); | ||
137 | } | ||