]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/crates/ide/src/ssr.rs
Rollup merge of #99714 - ouz-a:issue_57961, r=oli-obk
[rust.git] / src / tools / rust-analyzer / crates / ide / src / ssr.rs
1 //! This module provides an SSR assist. It is not desirable to include this
2 //! assist in ide_assists because that would require the ide_assists crate
3 //! depend on the ide_ssr crate.
4
5 use ide_assists::{Assist, AssistId, AssistKind, AssistResolveStrategy, GroupLabel};
6 use ide_db::{base_db::FileRange, label::Label, source_change::SourceChange, RootDatabase};
7
8 pub(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("ssr", AssistKind::RefactorRewrite);
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(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_string()),
45             group: Some(GroupLabel("Apply SSR".into())),
46             target: comment_range,
47             source_change,
48             trigger_signature_help: false,
49         };
50
51         ssr_assists.push(assist);
52     }
53
54     ssr_assists
55 }
56
57 #[cfg(test)]
58 mod tests {
59     use std::sync::Arc;
60
61     use expect_test::expect;
62     use ide_assists::{Assist, AssistResolveStrategy};
63     use ide_db::{
64         base_db::{fixture::WithFixture, salsa::Durability, FileRange},
65         symbol_index::SymbolsDatabase,
66         FxHashSet, RootDatabase,
67     };
68
69     use super::ssr_assists;
70
71     fn get_assists(ra_fixture: &str, resolve: AssistResolveStrategy) -> Vec<Assist> {
72         let (mut db, file_id, range_or_offset) = RootDatabase::with_range_or_offset(ra_fixture);
73         let mut local_roots = FxHashSet::default();
74         local_roots.insert(ide_db::base_db::fixture::WORKSPACE);
75         db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
76         ssr_assists(&db, &resolve, FileRange { file_id, range: range_or_offset.into() })
77     }
78
79     #[test]
80     fn not_applicable_comment_not_ssr() {
81         let ra_fixture = r#"
82             //- /lib.rs
83
84             // This is foo $0
85             fn foo() {}
86             "#;
87         let assists = get_assists(ra_fixture, AssistResolveStrategy::All);
88
89         assert_eq!(0, assists.len());
90     }
91
92     #[test]
93     fn resolve_edits_true() {
94         let assists = get_assists(
95             r#"
96             //- /lib.rs
97             mod bar;
98
99             // 2 ==>> 3$0
100             fn foo() { 2 }
101
102             //- /bar.rs
103             fn bar() { 2 }
104             "#,
105             AssistResolveStrategy::All,
106         );
107
108         assert_eq!(2, assists.len());
109         let mut assists = assists.into_iter();
110
111         let apply_in_file_assist = assists.next().unwrap();
112         expect![[r#"
113             Assist {
114                 id: AssistId(
115                     "ssr",
116                     RefactorRewrite,
117                 ),
118                 label: "Apply SSR in file",
119                 group: Some(
120                     GroupLabel(
121                         "Apply SSR",
122                     ),
123                 ),
124                 target: 10..21,
125                 source_change: Some(
126                     SourceChange {
127                         source_file_edits: {
128                             FileId(
129                                 0,
130                             ): TextEdit {
131                                 indels: [
132                                     Indel {
133                                         insert: "3",
134                                         delete: 33..34,
135                                     },
136                                 ],
137                             },
138                         },
139                         file_system_edits: [],
140                         is_snippet: false,
141                     },
142                 ),
143                 trigger_signature_help: false,
144             }
145         "#]]
146         .assert_debug_eq(&apply_in_file_assist);
147
148         let apply_in_workspace_assist = assists.next().unwrap();
149         expect![[r#"
150             Assist {
151                 id: AssistId(
152                     "ssr",
153                     RefactorRewrite,
154                 ),
155                 label: "Apply SSR in workspace",
156                 group: Some(
157                     GroupLabel(
158                         "Apply SSR",
159                     ),
160                 ),
161                 target: 10..21,
162                 source_change: Some(
163                     SourceChange {
164                         source_file_edits: {
165                             FileId(
166                                 0,
167                             ): TextEdit {
168                                 indels: [
169                                     Indel {
170                                         insert: "3",
171                                         delete: 33..34,
172                                     },
173                                 ],
174                             },
175                             FileId(
176                                 1,
177                             ): TextEdit {
178                                 indels: [
179                                     Indel {
180                                         insert: "3",
181                                         delete: 11..12,
182                                     },
183                                 ],
184                             },
185                         },
186                         file_system_edits: [],
187                         is_snippet: false,
188                     },
189                 ),
190                 trigger_signature_help: false,
191             }
192         "#]]
193         .assert_debug_eq(&apply_in_workspace_assist);
194     }
195
196     #[test]
197     fn resolve_edits_false() {
198         let assists = get_assists(
199             r#"
200             //- /lib.rs
201             mod bar;
202
203             // 2 ==>> 3$0
204             fn foo() { 2 }
205
206             //- /bar.rs
207             fn bar() { 2 }
208             "#,
209             AssistResolveStrategy::None,
210         );
211
212         assert_eq!(2, assists.len());
213         let mut assists = assists.into_iter();
214
215         let apply_in_file_assist = assists.next().unwrap();
216         expect![[r#"
217             Assist {
218                 id: AssistId(
219                     "ssr",
220                     RefactorRewrite,
221                 ),
222                 label: "Apply SSR in file",
223                 group: Some(
224                     GroupLabel(
225                         "Apply SSR",
226                     ),
227                 ),
228                 target: 10..21,
229                 source_change: None,
230                 trigger_signature_help: false,
231             }
232         "#]]
233         .assert_debug_eq(&apply_in_file_assist);
234
235         let apply_in_workspace_assist = assists.next().unwrap();
236         expect![[r#"
237             Assist {
238                 id: AssistId(
239                     "ssr",
240                     RefactorRewrite,
241                 ),
242                 label: "Apply SSR in workspace",
243                 group: Some(
244                     GroupLabel(
245                         "Apply SSR",
246                     ),
247                 ),
248                 target: 10..21,
249                 source_change: None,
250                 trigger_signature_help: false,
251             }
252         "#]]
253         .assert_debug_eq(&apply_in_workspace_assist);
254     }
255 }