diff options
Diffstat (limited to 'crates/ide_completion/src/lib.rs')
-rw-r--r-- | crates/ide_completion/src/lib.rs | 123 |
1 files changed, 5 insertions, 118 deletions
diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs index 18983aa01..bf73818dc 100644 --- a/crates/ide_completion/src/lib.rs +++ b/crates/ide_completion/src/lib.rs | |||
@@ -1,14 +1,14 @@ | |||
1 | //! `completions` crate provides utilities for generating completions of user input. | 1 | //! `completions` crate provides utilities for generating completions of user input. |
2 | 2 | ||
3 | mod completions; | ||
3 | mod config; | 4 | mod config; |
4 | mod item; | ||
5 | mod context; | 5 | mod context; |
6 | mod item; | ||
6 | mod patterns; | 7 | mod patterns; |
7 | #[cfg(test)] | ||
8 | mod test_utils; | ||
9 | mod render; | 8 | mod render; |
10 | 9 | ||
11 | mod completions; | 10 | #[cfg(test)] |
11 | mod tests; | ||
12 | 12 | ||
13 | use completions::flyimport::position_for_import; | 13 | use completions::flyimport::position_for_import; |
14 | use ide_db::{ | 14 | use ide_db::{ |
@@ -141,6 +141,7 @@ pub fn completions( | |||
141 | let ctx = CompletionContext::new(db, position, config)?; | 141 | let ctx = CompletionContext::new(db, position, config)?; |
142 | 142 | ||
143 | if ctx.no_completion_required() { | 143 | if ctx.no_completion_required() { |
144 | cov_mark::hit!(no_completion_required); | ||
144 | // No work required here. | 145 | // No work required here. |
145 | return None; | 146 | return None; |
146 | } | 147 | } |
@@ -200,117 +201,3 @@ pub fn resolve_completion_edits( | |||
200 | 201 | ||
201 | ImportEdit { import, scope }.to_text_edit(config.insert_use).map(|edit| vec![edit]) | 202 | ImportEdit { import, scope }.to_text_edit(config.insert_use).map(|edit| vec![edit]) |
202 | } | 203 | } |
203 | |||
204 | #[cfg(test)] | ||
205 | mod tests { | ||
206 | use crate::test_utils::{self, TEST_CONFIG}; | ||
207 | |||
208 | struct DetailAndDocumentation<'a> { | ||
209 | detail: &'a str, | ||
210 | documentation: &'a str, | ||
211 | } | ||
212 | |||
213 | fn check_detail_and_documentation(ra_fixture: &str, expected: DetailAndDocumentation) { | ||
214 | let (db, position) = test_utils::position(ra_fixture); | ||
215 | let config = TEST_CONFIG; | ||
216 | let completions: Vec<_> = crate::completions(&db, &config, position).unwrap().into(); | ||
217 | for item in completions { | ||
218 | if item.detail() == Some(expected.detail) { | ||
219 | let opt = item.documentation(); | ||
220 | let doc = opt.as_ref().map(|it| it.as_str()); | ||
221 | assert_eq!(doc, Some(expected.documentation)); | ||
222 | return; | ||
223 | } | ||
224 | } | ||
225 | panic!("completion detail not found: {}", expected.detail) | ||
226 | } | ||
227 | |||
228 | fn check_no_completion(ra_fixture: &str) { | ||
229 | let (db, position) = test_utils::position(ra_fixture); | ||
230 | let config = TEST_CONFIG; | ||
231 | |||
232 | let completions: Option<Vec<String>> = crate::completions(&db, &config, position) | ||
233 | .and_then(|completions| { | ||
234 | let completions: Vec<_> = completions.into(); | ||
235 | if completions.is_empty() { | ||
236 | None | ||
237 | } else { | ||
238 | Some(completions) | ||
239 | } | ||
240 | }) | ||
241 | .map(|completions| { | ||
242 | completions.into_iter().map(|completion| format!("{:?}", completion)).collect() | ||
243 | }); | ||
244 | |||
245 | // `assert_eq` instead of `assert!(completions.is_none())` to get the list of completions if test will panic. | ||
246 | assert_eq!(completions, None, "Completions were generated, but weren't expected"); | ||
247 | } | ||
248 | |||
249 | #[test] | ||
250 | fn test_completion_detail_from_macro_generated_struct_fn_doc_attr() { | ||
251 | check_detail_and_documentation( | ||
252 | r#" | ||
253 | macro_rules! bar { | ||
254 | () => { | ||
255 | struct Bar; | ||
256 | impl Bar { | ||
257 | #[doc = "Do the foo"] | ||
258 | fn foo(&self) {} | ||
259 | } | ||
260 | } | ||
261 | } | ||
262 | |||
263 | bar!(); | ||
264 | |||
265 | fn foo() { | ||
266 | let bar = Bar; | ||
267 | bar.fo$0; | ||
268 | } | ||
269 | "#, | ||
270 | DetailAndDocumentation { detail: "fn(&self)", documentation: "Do the foo" }, | ||
271 | ); | ||
272 | } | ||
273 | |||
274 | #[test] | ||
275 | fn test_completion_detail_from_macro_generated_struct_fn_doc_comment() { | ||
276 | check_detail_and_documentation( | ||
277 | r#" | ||
278 | macro_rules! bar { | ||
279 | () => { | ||
280 | struct Bar; | ||
281 | impl Bar { | ||
282 | /// Do the foo | ||
283 | fn foo(&self) {} | ||
284 | } | ||
285 | } | ||
286 | } | ||
287 | |||
288 | bar!(); | ||
289 | |||
290 | fn foo() { | ||
291 | let bar = Bar; | ||
292 | bar.fo$0; | ||
293 | } | ||
294 | "#, | ||
295 | DetailAndDocumentation { detail: "fn(&self)", documentation: "Do the foo" }, | ||
296 | ); | ||
297 | } | ||
298 | |||
299 | #[test] | ||
300 | fn test_no_completions_required() { | ||
301 | // There must be no hint for 'in' keyword. | ||
302 | check_no_completion(r#"fn foo() { for i i$0 }"#); | ||
303 | // After 'in' keyword hints may be spawned. | ||
304 | check_detail_and_documentation( | ||
305 | r#" | ||
306 | /// Do the foo | ||
307 | fn foo() -> &'static str { "foo" } | ||
308 | |||
309 | fn bar() { | ||
310 | for c in fo$0 | ||
311 | } | ||
312 | "#, | ||
313 | DetailAndDocumentation { detail: "fn() -> &str", documentation: "Do the foo" }, | ||
314 | ); | ||
315 | } | ||
316 | } | ||