1use ide_assists::{Assist, AssistId, AssistResolveStrategy, GroupLabel};
6use ide_db::{FileRange, RootDatabase, label::Label, source_change::SourceChange};
7
8pub(crate) fn ssr_assists(
9 db: &RootDatabase,
10 resolve: &AssistResolveStrategy,
11 frange: FileRange,
12) -> Vec<Assist> {
13 let mut ssr_assists = Vec::with_capacity(2);
14
15 let (match_finder, comment_range) = match ide_ssr::ssr_from_comment(db, frange) {
16 Some(ssr_data) => ssr_data,
17 None => return ssr_assists,
18 };
19 let id = AssistId::refactor_rewrite("ssr");
20
21 let (source_change_for_file, source_change_for_workspace) = if resolve.should_resolve(&id) {
22 let edits = match_finder.edits();
23
24 let source_change_for_file = {
25 let text_edit_for_file = edits.get(&frange.file_id).cloned().unwrap_or_default();
26 SourceChange::from_text_edit(frange.file_id, text_edit_for_file)
27 };
28
29 let source_change_for_workspace = SourceChange::from_iter(match_finder.edits());
30
31 (Some(source_change_for_file), Some(source_change_for_workspace))
32 } else {
33 (None, None)
34 };
35
36 let assists = vec![
37 ("Apply SSR in file", source_change_for_file),
38 ("Apply SSR in workspace", source_change_for_workspace),
39 ];
40
41 for (label, source_change) in assists.into_iter() {
42 let assist = Assist {
43 id,
44 label: Label::new(label.to_owned()),
45 group: Some(GroupLabel("Apply SSR".into())),
46 target: comment_range,
47 source_change,
48 command: None,
49 };
50
51 ssr_assists.push(assist);
52 }
53
54 ssr_assists
55}
56
57#[cfg(test)]
58mod tests {
59 use expect_test::expect;
60 use ide_assists::{Assist, AssistResolveStrategy};
61 use ide_db::{FileRange, FxHashSet, LocalRoots, RootDatabase, base_db::salsa::Setter as _};
62 use test_fixture::WithFixture;
63
64 use super::ssr_assists;
65
66 fn get_assists(
67 #[rust_analyzer::rust_fixture] ra_fixture: &str,
68 resolve: AssistResolveStrategy,
69 ) -> Vec<Assist> {
70 let (mut db, file_id, range_or_offset) = RootDatabase::with_range_or_offset(ra_fixture);
71 let mut local_roots = FxHashSet::default();
72 local_roots.insert(test_fixture::WORKSPACE);
73 LocalRoots::get(&db).set_roots(&mut db).to(local_roots);
74 ssr_assists(
75 &db,
76 &resolve,
77 FileRange { file_id: file_id.file_id(&db), range: range_or_offset.into() },
78 )
79 }
80
81 #[test]
82 fn not_applicable_comment_not_ssr() {
83 let ra_fixture = r#"
84 //- /lib.rs
85
86 // This is foo $0
87 fn foo() {}
88 "#;
89 let assists = get_assists(ra_fixture, AssistResolveStrategy::All);
90
91 assert_eq!(0, assists.len());
92 }
93
94 #[test]
95 fn resolve_edits_true() {
96 let assists = get_assists(
97 r#"
98 //- /lib.rs
99 mod bar;
100
101 // 2 ==>> 3$0
102 fn foo() { 2 }
103
104 //- /bar.rs
105 fn bar() { 2 }
106 "#,
107 AssistResolveStrategy::All,
108 );
109
110 assert_eq!(2, assists.len());
111 let mut assists = assists.into_iter();
112
113 let apply_in_file_assist = assists.next().unwrap();
114 expect![[r#"
115 Assist {
116 id: AssistId(
117 "ssr",
118 RefactorRewrite,
119 None,
120 ),
121 label: "Apply SSR in file",
122 group: Some(
123 GroupLabel(
124 "Apply SSR",
125 ),
126 ),
127 target: 10..21,
128 source_change: Some(
129 SourceChange {
130 source_file_edits: {
131 FileId(
132 0,
133 ): (
134 TextEdit {
135 indels: [
136 Indel {
137 insert: "3",
138 delete: 33..34,
139 },
140 ],
141 annotation: None,
142 },
143 None,
144 ),
145 },
146 file_system_edits: [],
147 is_snippet: false,
148 annotations: {},
149 next_annotation_id: 0,
150 },
151 ),
152 command: None,
153 }
154 "#]]
155 .assert_debug_eq(&apply_in_file_assist);
156
157 let apply_in_workspace_assist = assists.next().unwrap();
158 expect![[r#"
159 Assist {
160 id: AssistId(
161 "ssr",
162 RefactorRewrite,
163 None,
164 ),
165 label: "Apply SSR in workspace",
166 group: Some(
167 GroupLabel(
168 "Apply SSR",
169 ),
170 ),
171 target: 10..21,
172 source_change: Some(
173 SourceChange {
174 source_file_edits: {
175 FileId(
176 0,
177 ): (
178 TextEdit {
179 indels: [
180 Indel {
181 insert: "3",
182 delete: 33..34,
183 },
184 ],
185 annotation: None,
186 },
187 None,
188 ),
189 FileId(
190 1,
191 ): (
192 TextEdit {
193 indels: [
194 Indel {
195 insert: "3",
196 delete: 11..12,
197 },
198 ],
199 annotation: None,
200 },
201 None,
202 ),
203 },
204 file_system_edits: [],
205 is_snippet: false,
206 annotations: {},
207 next_annotation_id: 0,
208 },
209 ),
210 command: None,
211 }
212 "#]]
213 .assert_debug_eq(&apply_in_workspace_assist);
214 }
215
216 #[test]
217 fn resolve_edits_false() {
218 let assists = get_assists(
219 r#"
220 //- /lib.rs
221 mod bar;
222
223 // 2 ==>> 3$0
224 fn foo() { 2 }
225
226 //- /bar.rs
227 fn bar() { 2 }
228 "#,
229 AssistResolveStrategy::None,
230 );
231
232 assert_eq!(2, assists.len());
233 let mut assists = assists.into_iter();
234
235 let apply_in_file_assist = assists.next().unwrap();
236 expect![[r#"
237 Assist {
238 id: AssistId(
239 "ssr",
240 RefactorRewrite,
241 None,
242 ),
243 label: "Apply SSR in file",
244 group: Some(
245 GroupLabel(
246 "Apply SSR",
247 ),
248 ),
249 target: 10..21,
250 source_change: None,
251 command: None,
252 }
253 "#]]
254 .assert_debug_eq(&apply_in_file_assist);
255
256 let apply_in_workspace_assist = assists.next().unwrap();
257 expect![[r#"
258 Assist {
259 id: AssistId(
260 "ssr",
261 RefactorRewrite,
262 None,
263 ),
264 label: "Apply SSR in workspace",
265 group: Some(
266 GroupLabel(
267 "Apply SSR",
268 ),
269 ),
270 target: 10..21,
271 source_change: None,
272 command: None,
273 }
274 "#]]
275 .assert_debug_eq(&apply_in_workspace_assist);
276 }
277}