aboutsummaryrefslogtreecommitdiff
path: root/crates/assists/src/tests.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/assists/src/tests.rs')
-rw-r--r--crates/assists/src/tests.rs179
1 files changed, 179 insertions, 0 deletions
diff --git a/crates/assists/src/tests.rs b/crates/assists/src/tests.rs
new file mode 100644
index 000000000..ba1fb543b
--- /dev/null
+++ b/crates/assists/src/tests.rs
@@ -0,0 +1,179 @@
1mod generated;
2
3use base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt};
4use hir::Semantics;
5use ide_db::RootDatabase;
6use syntax::TextRange;
7use test_utils::{assert_eq_text, extract_offset, extract_range};
8
9use crate::{handlers::Handler, Assist, AssistConfig, AssistContext, AssistKind, Assists};
10use stdx::trim_indent;
11
12pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) {
13 RootDatabase::with_single_file(text)
14}
15
16pub(crate) fn check_assist(assist: Handler, ra_fixture_before: &str, ra_fixture_after: &str) {
17 let ra_fixture_after = trim_indent(ra_fixture_after);
18 check(assist, ra_fixture_before, ExpectedResult::After(&ra_fixture_after));
19}
20
21// FIXME: instead of having a separate function here, maybe use
22// `extract_ranges` and mark the target as `<target> </target>` in the
23// fixture?
24pub(crate) fn check_assist_target(assist: Handler, ra_fixture: &str, target: &str) {
25 check(assist, ra_fixture, ExpectedResult::Target(target));
26}
27
28pub(crate) fn check_assist_not_applicable(assist: Handler, ra_fixture: &str) {
29 check(assist, ra_fixture, ExpectedResult::NotApplicable);
30}
31
32fn check_doc_test(assist_id: &str, before: &str, after: &str) {
33 let after = trim_indent(after);
34 let (db, file_id, selection) = RootDatabase::with_range_or_offset(&before);
35 let before = db.file_text(file_id).to_string();
36 let frange = FileRange { file_id, range: selection.into() };
37
38 let mut assist = Assist::resolved(&db, &AssistConfig::default(), frange)
39 .into_iter()
40 .find(|assist| assist.assist.id.0 == assist_id)
41 .unwrap_or_else(|| {
42 panic!(
43 "\n\nAssist is not applicable: {}\nAvailable assists: {}",
44 assist_id,
45 Assist::resolved(&db, &AssistConfig::default(), frange)
46 .into_iter()
47 .map(|assist| assist.assist.id.0)
48 .collect::<Vec<_>>()
49 .join(", ")
50 )
51 });
52
53 let actual = {
54 let change = assist.source_change.source_file_edits.pop().unwrap();
55 let mut actual = before;
56 change.edit.apply(&mut actual);
57 actual
58 };
59 assert_eq_text!(&after, &actual);
60}
61
62enum ExpectedResult<'a> {
63 NotApplicable,
64 After(&'a str),
65 Target(&'a str),
66}
67
68fn check(handler: Handler, before: &str, expected: ExpectedResult) {
69 let (db, file_with_caret_id, range_or_offset) = RootDatabase::with_range_or_offset(before);
70 let text_without_caret = db.file_text(file_with_caret_id).to_string();
71
72 let frange = FileRange { file_id: file_with_caret_id, range: range_or_offset.into() };
73
74 let sema = Semantics::new(&db);
75 let config = AssistConfig::default();
76 let ctx = AssistContext::new(sema, &config, frange);
77 let mut acc = Assists::new_resolved(&ctx);
78 handler(&mut acc, &ctx);
79 let mut res = acc.finish_resolved();
80 let assist = res.pop();
81 match (assist, expected) {
82 (Some(assist), ExpectedResult::After(after)) => {
83 let mut source_change = assist.source_change;
84 let change = source_change.source_file_edits.pop().unwrap();
85
86 let mut actual = db.file_text(change.file_id).as_ref().to_owned();
87 change.edit.apply(&mut actual);
88 assert_eq_text!(after, &actual);
89 }
90 (Some(assist), ExpectedResult::Target(target)) => {
91 let range = assist.assist.target;
92 assert_eq_text!(&text_without_caret[range], target);
93 }
94 (Some(_), ExpectedResult::NotApplicable) => panic!("assist should not be applicable!"),
95 (None, ExpectedResult::After(_)) | (None, ExpectedResult::Target(_)) => {
96 panic!("code action is not applicable")
97 }
98 (None, ExpectedResult::NotApplicable) => (),
99 };
100}
101
102#[test]
103fn assist_order_field_struct() {
104 let before = "struct Foo { <|>bar: u32 }";
105 let (before_cursor_pos, before) = extract_offset(before);
106 let (db, file_id) = with_single_file(&before);
107 let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) };
108 let assists = Assist::resolved(&db, &AssistConfig::default(), frange);
109 let mut assists = assists.iter();
110
111 assert_eq!(
112 assists.next().expect("expected assist").assist.label,
113 "Change visibility to pub(crate)"
114 );
115 assert_eq!(assists.next().expect("expected assist").assist.label, "Add `#[derive]`");
116}
117
118#[test]
119fn assist_order_if_expr() {
120 let before = "
121 pub fn test_some_range(a: int) -> bool {
122 if let 2..6 = <|>5<|> {
123 true
124 } else {
125 false
126 }
127 }";
128 let (range, before) = extract_range(before);
129 let (db, file_id) = with_single_file(&before);
130 let frange = FileRange { file_id, range };
131 let assists = Assist::resolved(&db, &AssistConfig::default(), frange);
132 let mut assists = assists.iter();
133
134 assert_eq!(assists.next().expect("expected assist").assist.label, "Extract into variable");
135 assert_eq!(assists.next().expect("expected assist").assist.label, "Replace with match");
136}
137
138#[test]
139fn assist_filter_works() {
140 let before = "
141 pub fn test_some_range(a: int) -> bool {
142 if let 2..6 = <|>5<|> {
143 true
144 } else {
145 false
146 }
147 }";
148 let (range, before) = extract_range(before);
149 let (db, file_id) = with_single_file(&before);
150 let frange = FileRange { file_id, range };
151
152 {
153 let mut cfg = AssistConfig::default();
154 cfg.allowed = Some(vec![AssistKind::Refactor]);
155
156 let assists = Assist::resolved(&db, &cfg, frange);
157 let mut assists = assists.iter();
158
159 assert_eq!(assists.next().expect("expected assist").assist.label, "Extract into variable");
160 assert_eq!(assists.next().expect("expected assist").assist.label, "Replace with match");
161 }
162
163 {
164 let mut cfg = AssistConfig::default();
165 cfg.allowed = Some(vec![AssistKind::RefactorExtract]);
166 let assists = Assist::resolved(&db, &cfg, frange);
167 assert_eq!(assists.len(), 1);
168
169 let mut assists = assists.iter();
170 assert_eq!(assists.next().expect("expected assist").assist.label, "Extract into variable");
171 }
172
173 {
174 let mut cfg = AssistConfig::default();
175 cfg.allowed = Some(vec![AssistKind::QuickFix]);
176 let assists = Assist::resolved(&db, &cfg, frange);
177 assert!(assists.is_empty(), "All asserts but quickfixes should be filtered out");
178 }
179}