diff options
Diffstat (limited to 'crates/assists/src/handlers/auto_import.rs')
-rw-r--r-- | crates/assists/src/handlers/auto_import.rs | 965 |
1 files changed, 0 insertions, 965 deletions
diff --git a/crates/assists/src/handlers/auto_import.rs b/crates/assists/src/handlers/auto_import.rs deleted file mode 100644 index 4e2a4fcd9..000000000 --- a/crates/assists/src/handlers/auto_import.rs +++ /dev/null | |||
@@ -1,965 +0,0 @@ | |||
1 | use ide_db::helpers::{ | ||
2 | import_assets::{ImportAssets, ImportCandidate}, | ||
3 | insert_use::{insert_use, ImportScope}, | ||
4 | mod_path_to_ast, | ||
5 | }; | ||
6 | use syntax::ast; | ||
7 | |||
8 | use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel}; | ||
9 | |||
10 | // Feature: Auto Import | ||
11 | // | ||
12 | // Using the `auto-import` assist it is possible to insert missing imports for unresolved items. | ||
13 | // When inserting an import it will do so in a structured manner by keeping imports grouped, | ||
14 | // separated by a newline in the following order: | ||
15 | // | ||
16 | // - `std` and `core` | ||
17 | // - External Crates | ||
18 | // - Current Crate, paths prefixed by `crate` | ||
19 | // - Current Module, paths prefixed by `self` | ||
20 | // - Super Module, paths prefixed by `super` | ||
21 | // | ||
22 | // Example: | ||
23 | // ```rust | ||
24 | // use std::fs::File; | ||
25 | // | ||
26 | // use itertools::Itertools; | ||
27 | // use syntax::ast; | ||
28 | // | ||
29 | // use crate::utils::insert_use; | ||
30 | // | ||
31 | // use self::auto_import; | ||
32 | // | ||
33 | // use super::AssistContext; | ||
34 | // ``` | ||
35 | // | ||
36 | // .Merge Behaviour | ||
37 | // | ||
38 | // It is possible to configure how use-trees are merged with the `importMergeBehaviour` setting. | ||
39 | // It has the following configurations: | ||
40 | // | ||
41 | // - `full`: This setting will cause auto-import to always completely merge use-trees that share the | ||
42 | // same path prefix while also merging inner trees that share the same path-prefix. This kind of | ||
43 | // nesting is only supported in Rust versions later than 1.24. | ||
44 | // - `last`: This setting will cause auto-import to merge use-trees as long as the resulting tree | ||
45 | // will only contain a nesting of single segment paths at the very end. | ||
46 | // - `none`: This setting will cause auto-import to never merge use-trees keeping them as simple | ||
47 | // paths. | ||
48 | // | ||
49 | // In `VS Code` the configuration for this is `rust-analyzer.assist.importMergeBehaviour`. | ||
50 | // | ||
51 | // .Import Prefix | ||
52 | // | ||
53 | // The style of imports in the same crate is configurable through the `importPrefix` setting. | ||
54 | // It has the following configurations: | ||
55 | // | ||
56 | // - `by_crate`: This setting will force paths to be always absolute, starting with the `crate` | ||
57 | // prefix, unless the item is defined outside of the current crate. | ||
58 | // - `by_self`: This setting will force paths that are relative to the current module to always | ||
59 | // start with `self`. This will result in paths that always start with either `crate`, `self`, | ||
60 | // `super` or an extern crate identifier. | ||
61 | // - `plain`: This setting does not impose any restrictions in imports. | ||
62 | // | ||
63 | // In `VS Code` the configuration for this is `rust-analyzer.assist.importPrefix`. | ||
64 | |||
65 | // Assist: auto_import | ||
66 | // | ||
67 | // If the name is unresolved, provides all possible imports for it. | ||
68 | // | ||
69 | // ``` | ||
70 | // fn main() { | ||
71 | // let map = HashMap$0::new(); | ||
72 | // } | ||
73 | // # pub mod std { pub mod collections { pub struct HashMap { } } } | ||
74 | // ``` | ||
75 | // -> | ||
76 | // ``` | ||
77 | // use std::collections::HashMap; | ||
78 | // | ||
79 | // fn main() { | ||
80 | // let map = HashMap::new(); | ||
81 | // } | ||
82 | // # pub mod std { pub mod collections { pub struct HashMap { } } } | ||
83 | // ``` | ||
84 | pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | ||
85 | let import_assets = | ||
86 | if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::<ast::Path>() { | ||
87 | ImportAssets::for_regular_path(path_under_caret, &ctx.sema) | ||
88 | } else if let Some(method_under_caret) = | ||
89 | ctx.find_node_at_offset_with_descend::<ast::MethodCallExpr>() | ||
90 | { | ||
91 | ImportAssets::for_method_call(method_under_caret, &ctx.sema) | ||
92 | } else { | ||
93 | None | ||
94 | }?; | ||
95 | let proposed_imports = import_assets.search_for_imports(&ctx.sema, &ctx.config.insert_use); | ||
96 | if proposed_imports.is_empty() { | ||
97 | return None; | ||
98 | } | ||
99 | |||
100 | let range = ctx.sema.original_range(import_assets.syntax_under_caret()).range; | ||
101 | let group = import_group_message(import_assets.import_candidate()); | ||
102 | let scope = | ||
103 | ImportScope::find_insert_use_container(import_assets.syntax_under_caret(), &ctx.sema)?; | ||
104 | for (import, _) in proposed_imports { | ||
105 | acc.add_group( | ||
106 | &group, | ||
107 | AssistId("auto_import", AssistKind::QuickFix), | ||
108 | format!("Import `{}`", &import), | ||
109 | range, | ||
110 | |builder| { | ||
111 | let rewriter = | ||
112 | insert_use(&scope, mod_path_to_ast(&import), ctx.config.insert_use.merge); | ||
113 | builder.rewrite(rewriter); | ||
114 | }, | ||
115 | ); | ||
116 | } | ||
117 | Some(()) | ||
118 | } | ||
119 | |||
120 | fn import_group_message(import_candidate: &ImportCandidate) -> GroupLabel { | ||
121 | let name = match import_candidate { | ||
122 | ImportCandidate::Path(candidate) => format!("Import {}", &candidate.name), | ||
123 | ImportCandidate::TraitAssocItem(candidate) => { | ||
124 | format!("Import a trait for item {}", &candidate.name) | ||
125 | } | ||
126 | ImportCandidate::TraitMethod(candidate) => { | ||
127 | format!("Import a trait for method {}", &candidate.name) | ||
128 | } | ||
129 | }; | ||
130 | GroupLabel(name) | ||
131 | } | ||
132 | |||
133 | #[cfg(test)] | ||
134 | mod tests { | ||
135 | use super::*; | ||
136 | use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target}; | ||
137 | |||
138 | #[test] | ||
139 | fn applicable_when_found_an_import_partial() { | ||
140 | check_assist( | ||
141 | auto_import, | ||
142 | r" | ||
143 | mod std { | ||
144 | pub mod fmt { | ||
145 | pub struct Formatter; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | use std::fmt; | ||
150 | |||
151 | $0Formatter | ||
152 | ", | ||
153 | r" | ||
154 | mod std { | ||
155 | pub mod fmt { | ||
156 | pub struct Formatter; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | use std::fmt::{self, Formatter}; | ||
161 | |||
162 | Formatter | ||
163 | ", | ||
164 | ); | ||
165 | } | ||
166 | |||
167 | #[test] | ||
168 | fn applicable_when_found_an_import() { | ||
169 | check_assist( | ||
170 | auto_import, | ||
171 | r" | ||
172 | $0PubStruct | ||
173 | |||
174 | pub mod PubMod { | ||
175 | pub struct PubStruct; | ||
176 | } | ||
177 | ", | ||
178 | r" | ||
179 | use PubMod::PubStruct; | ||
180 | |||
181 | PubStruct | ||
182 | |||
183 | pub mod PubMod { | ||
184 | pub struct PubStruct; | ||
185 | } | ||
186 | ", | ||
187 | ); | ||
188 | } | ||
189 | |||
190 | #[test] | ||
191 | fn applicable_when_found_an_import_in_macros() { | ||
192 | check_assist( | ||
193 | auto_import, | ||
194 | r" | ||
195 | macro_rules! foo { | ||
196 | ($i:ident) => { fn foo(a: $i) {} } | ||
197 | } | ||
198 | foo!(Pub$0Struct); | ||
199 | |||
200 | pub mod PubMod { | ||
201 | pub struct PubStruct; | ||
202 | } | ||
203 | ", | ||
204 | r" | ||
205 | use PubMod::PubStruct; | ||
206 | |||
207 | macro_rules! foo { | ||
208 | ($i:ident) => { fn foo(a: $i) {} } | ||
209 | } | ||
210 | foo!(PubStruct); | ||
211 | |||
212 | pub mod PubMod { | ||
213 | pub struct PubStruct; | ||
214 | } | ||
215 | ", | ||
216 | ); | ||
217 | } | ||
218 | |||
219 | #[test] | ||
220 | fn auto_imports_are_merged() { | ||
221 | check_assist( | ||
222 | auto_import, | ||
223 | r" | ||
224 | use PubMod::PubStruct1; | ||
225 | |||
226 | struct Test { | ||
227 | test: Pub$0Struct2<u8>, | ||
228 | } | ||
229 | |||
230 | pub mod PubMod { | ||
231 | pub struct PubStruct1; | ||
232 | pub struct PubStruct2<T> { | ||
233 | _t: T, | ||
234 | } | ||
235 | } | ||
236 | ", | ||
237 | r" | ||
238 | use PubMod::{PubStruct1, PubStruct2}; | ||
239 | |||
240 | struct Test { | ||
241 | test: PubStruct2<u8>, | ||
242 | } | ||
243 | |||
244 | pub mod PubMod { | ||
245 | pub struct PubStruct1; | ||
246 | pub struct PubStruct2<T> { | ||
247 | _t: T, | ||
248 | } | ||
249 | } | ||
250 | ", | ||
251 | ); | ||
252 | } | ||
253 | |||
254 | #[test] | ||
255 | fn applicable_when_found_multiple_imports() { | ||
256 | check_assist( | ||
257 | auto_import, | ||
258 | r" | ||
259 | PubSt$0ruct | ||
260 | |||
261 | pub mod PubMod1 { | ||
262 | pub struct PubStruct; | ||
263 | } | ||
264 | pub mod PubMod2 { | ||
265 | pub struct PubStruct; | ||
266 | } | ||
267 | pub mod PubMod3 { | ||
268 | pub struct PubStruct; | ||
269 | } | ||
270 | ", | ||
271 | r" | ||
272 | use PubMod3::PubStruct; | ||
273 | |||
274 | PubStruct | ||
275 | |||
276 | pub mod PubMod1 { | ||
277 | pub struct PubStruct; | ||
278 | } | ||
279 | pub mod PubMod2 { | ||
280 | pub struct PubStruct; | ||
281 | } | ||
282 | pub mod PubMod3 { | ||
283 | pub struct PubStruct; | ||
284 | } | ||
285 | ", | ||
286 | ); | ||
287 | } | ||
288 | |||
289 | #[test] | ||
290 | fn not_applicable_for_already_imported_types() { | ||
291 | check_assist_not_applicable( | ||
292 | auto_import, | ||
293 | r" | ||
294 | use PubMod::PubStruct; | ||
295 | |||
296 | PubStruct$0 | ||
297 | |||
298 | pub mod PubMod { | ||
299 | pub struct PubStruct; | ||
300 | } | ||
301 | ", | ||
302 | ); | ||
303 | } | ||
304 | |||
305 | #[test] | ||
306 | fn not_applicable_for_types_with_private_paths() { | ||
307 | check_assist_not_applicable( | ||
308 | auto_import, | ||
309 | r" | ||
310 | PrivateStruct$0 | ||
311 | |||
312 | pub mod PubMod { | ||
313 | struct PrivateStruct; | ||
314 | } | ||
315 | ", | ||
316 | ); | ||
317 | } | ||
318 | |||
319 | #[test] | ||
320 | fn not_applicable_when_no_imports_found() { | ||
321 | check_assist_not_applicable( | ||
322 | auto_import, | ||
323 | " | ||
324 | PubStruct$0", | ||
325 | ); | ||
326 | } | ||
327 | |||
328 | #[test] | ||
329 | fn not_applicable_in_import_statements() { | ||
330 | check_assist_not_applicable( | ||
331 | auto_import, | ||
332 | r" | ||
333 | use PubStruct$0; | ||
334 | |||
335 | pub mod PubMod { | ||
336 | pub struct PubStruct; | ||
337 | }", | ||
338 | ); | ||
339 | } | ||
340 | |||
341 | #[test] | ||
342 | fn function_import() { | ||
343 | check_assist( | ||
344 | auto_import, | ||
345 | r" | ||
346 | test_function$0 | ||
347 | |||
348 | pub mod PubMod { | ||
349 | pub fn test_function() {}; | ||
350 | } | ||
351 | ", | ||
352 | r" | ||
353 | use PubMod::test_function; | ||
354 | |||
355 | test_function | ||
356 | |||
357 | pub mod PubMod { | ||
358 | pub fn test_function() {}; | ||
359 | } | ||
360 | ", | ||
361 | ); | ||
362 | } | ||
363 | |||
364 | #[test] | ||
365 | fn macro_import() { | ||
366 | check_assist( | ||
367 | auto_import, | ||
368 | r" | ||
369 | //- /lib.rs crate:crate_with_macro | ||
370 | #[macro_export] | ||
371 | macro_rules! foo { | ||
372 | () => () | ||
373 | } | ||
374 | |||
375 | //- /main.rs crate:main deps:crate_with_macro | ||
376 | fn main() { | ||
377 | foo$0 | ||
378 | } | ||
379 | ", | ||
380 | r"use crate_with_macro::foo; | ||
381 | |||
382 | fn main() { | ||
383 | foo | ||
384 | } | ||
385 | ", | ||
386 | ); | ||
387 | } | ||
388 | |||
389 | #[test] | ||
390 | fn auto_import_target() { | ||
391 | check_assist_target( | ||
392 | auto_import, | ||
393 | r" | ||
394 | struct AssistInfo { | ||
395 | group_label: Option<$0GroupLabel>, | ||
396 | } | ||
397 | |||
398 | mod m { pub struct GroupLabel; } | ||
399 | ", | ||
400 | "GroupLabel", | ||
401 | ) | ||
402 | } | ||
403 | |||
404 | #[test] | ||
405 | fn not_applicable_when_path_start_is_imported() { | ||
406 | check_assist_not_applicable( | ||
407 | auto_import, | ||
408 | r" | ||
409 | pub mod mod1 { | ||
410 | pub mod mod2 { | ||
411 | pub mod mod3 { | ||
412 | pub struct TestStruct; | ||
413 | } | ||
414 | } | ||
415 | } | ||
416 | |||
417 | use mod1::mod2; | ||
418 | fn main() { | ||
419 | mod2::mod3::TestStruct$0 | ||
420 | } | ||
421 | ", | ||
422 | ); | ||
423 | } | ||
424 | |||
425 | #[test] | ||
426 | fn not_applicable_for_imported_function() { | ||
427 | check_assist_not_applicable( | ||
428 | auto_import, | ||
429 | r" | ||
430 | pub mod test_mod { | ||
431 | pub fn test_function() {} | ||
432 | } | ||
433 | |||
434 | use test_mod::test_function; | ||
435 | fn main() { | ||
436 | test_function$0 | ||
437 | } | ||
438 | ", | ||
439 | ); | ||
440 | } | ||
441 | |||
442 | #[test] | ||
443 | fn associated_struct_function() { | ||
444 | check_assist( | ||
445 | auto_import, | ||
446 | r" | ||
447 | mod test_mod { | ||
448 | pub struct TestStruct {} | ||
449 | impl TestStruct { | ||
450 | pub fn test_function() {} | ||
451 | } | ||
452 | } | ||
453 | |||
454 | fn main() { | ||
455 | TestStruct::test_function$0 | ||
456 | } | ||
457 | ", | ||
458 | r" | ||
459 | use test_mod::TestStruct; | ||
460 | |||
461 | mod test_mod { | ||
462 | pub struct TestStruct {} | ||
463 | impl TestStruct { | ||
464 | pub fn test_function() {} | ||
465 | } | ||
466 | } | ||
467 | |||
468 | fn main() { | ||
469 | TestStruct::test_function | ||
470 | } | ||
471 | ", | ||
472 | ); | ||
473 | } | ||
474 | |||
475 | #[test] | ||
476 | fn associated_struct_const() { | ||
477 | check_assist( | ||
478 | auto_import, | ||
479 | r" | ||
480 | mod test_mod { | ||
481 | pub struct TestStruct {} | ||
482 | impl TestStruct { | ||
483 | const TEST_CONST: u8 = 42; | ||
484 | } | ||
485 | } | ||
486 | |||
487 | fn main() { | ||
488 | TestStruct::TEST_CONST$0 | ||
489 | } | ||
490 | ", | ||
491 | r" | ||
492 | use test_mod::TestStruct; | ||
493 | |||
494 | mod test_mod { | ||
495 | pub struct TestStruct {} | ||
496 | impl TestStruct { | ||
497 | const TEST_CONST: u8 = 42; | ||
498 | } | ||
499 | } | ||
500 | |||
501 | fn main() { | ||
502 | TestStruct::TEST_CONST | ||
503 | } | ||
504 | ", | ||
505 | ); | ||
506 | } | ||
507 | |||
508 | #[test] | ||
509 | fn associated_trait_function() { | ||
510 | check_assist( | ||
511 | auto_import, | ||
512 | r" | ||
513 | mod test_mod { | ||
514 | pub trait TestTrait { | ||
515 | fn test_function(); | ||
516 | } | ||
517 | pub struct TestStruct {} | ||
518 | impl TestTrait for TestStruct { | ||
519 | fn test_function() {} | ||
520 | } | ||
521 | } | ||
522 | |||
523 | fn main() { | ||
524 | test_mod::TestStruct::test_function$0 | ||
525 | } | ||
526 | ", | ||
527 | r" | ||
528 | use test_mod::TestTrait; | ||
529 | |||
530 | mod test_mod { | ||
531 | pub trait TestTrait { | ||
532 | fn test_function(); | ||
533 | } | ||
534 | pub struct TestStruct {} | ||
535 | impl TestTrait for TestStruct { | ||
536 | fn test_function() {} | ||
537 | } | ||
538 | } | ||
539 | |||
540 | fn main() { | ||
541 | test_mod::TestStruct::test_function | ||
542 | } | ||
543 | ", | ||
544 | ); | ||
545 | } | ||
546 | |||
547 | #[test] | ||
548 | fn not_applicable_for_imported_trait_for_function() { | ||
549 | check_assist_not_applicable( | ||
550 | auto_import, | ||
551 | r" | ||
552 | mod test_mod { | ||
553 | pub trait TestTrait { | ||
554 | fn test_function(); | ||
555 | } | ||
556 | pub trait TestTrait2 { | ||
557 | fn test_function(); | ||
558 | } | ||
559 | pub enum TestEnum { | ||
560 | One, | ||
561 | Two, | ||
562 | } | ||
563 | impl TestTrait2 for TestEnum { | ||
564 | fn test_function() {} | ||
565 | } | ||
566 | impl TestTrait for TestEnum { | ||
567 | fn test_function() {} | ||
568 | } | ||
569 | } | ||
570 | |||
571 | use test_mod::TestTrait2; | ||
572 | fn main() { | ||
573 | test_mod::TestEnum::test_function$0; | ||
574 | } | ||
575 | ", | ||
576 | ) | ||
577 | } | ||
578 | |||
579 | #[test] | ||
580 | fn associated_trait_const() { | ||
581 | check_assist( | ||
582 | auto_import, | ||
583 | r" | ||
584 | mod test_mod { | ||
585 | pub trait TestTrait { | ||
586 | const TEST_CONST: u8; | ||
587 | } | ||
588 | pub struct TestStruct {} | ||
589 | impl TestTrait for TestStruct { | ||
590 | const TEST_CONST: u8 = 42; | ||
591 | } | ||
592 | } | ||
593 | |||
594 | fn main() { | ||
595 | test_mod::TestStruct::TEST_CONST$0 | ||
596 | } | ||
597 | ", | ||
598 | r" | ||
599 | use test_mod::TestTrait; | ||
600 | |||
601 | mod test_mod { | ||
602 | pub trait TestTrait { | ||
603 | const TEST_CONST: u8; | ||
604 | } | ||
605 | pub struct TestStruct {} | ||
606 | impl TestTrait for TestStruct { | ||
607 | const TEST_CONST: u8 = 42; | ||
608 | } | ||
609 | } | ||
610 | |||
611 | fn main() { | ||
612 | test_mod::TestStruct::TEST_CONST | ||
613 | } | ||
614 | ", | ||
615 | ); | ||
616 | } | ||
617 | |||
618 | #[test] | ||
619 | fn not_applicable_for_imported_trait_for_const() { | ||
620 | check_assist_not_applicable( | ||
621 | auto_import, | ||
622 | r" | ||
623 | mod test_mod { | ||
624 | pub trait TestTrait { | ||
625 | const TEST_CONST: u8; | ||
626 | } | ||
627 | pub trait TestTrait2 { | ||
628 | const TEST_CONST: f64; | ||
629 | } | ||
630 | pub enum TestEnum { | ||
631 | One, | ||
632 | Two, | ||
633 | } | ||
634 | impl TestTrait2 for TestEnum { | ||
635 | const TEST_CONST: f64 = 42.0; | ||
636 | } | ||
637 | impl TestTrait for TestEnum { | ||
638 | const TEST_CONST: u8 = 42; | ||
639 | } | ||
640 | } | ||
641 | |||
642 | use test_mod::TestTrait2; | ||
643 | fn main() { | ||
644 | test_mod::TestEnum::TEST_CONST$0; | ||
645 | } | ||
646 | ", | ||
647 | ) | ||
648 | } | ||
649 | |||
650 | #[test] | ||
651 | fn trait_method() { | ||
652 | check_assist( | ||
653 | auto_import, | ||
654 | r" | ||
655 | mod test_mod { | ||
656 | pub trait TestTrait { | ||
657 | fn test_method(&self); | ||
658 | } | ||
659 | pub struct TestStruct {} | ||
660 | impl TestTrait for TestStruct { | ||
661 | fn test_method(&self) {} | ||
662 | } | ||
663 | } | ||
664 | |||
665 | fn main() { | ||
666 | let test_struct = test_mod::TestStruct {}; | ||
667 | test_struct.test_meth$0od() | ||
668 | } | ||
669 | ", | ||
670 | r" | ||
671 | use test_mod::TestTrait; | ||
672 | |||
673 | mod test_mod { | ||
674 | pub trait TestTrait { | ||
675 | fn test_method(&self); | ||
676 | } | ||
677 | pub struct TestStruct {} | ||
678 | impl TestTrait for TestStruct { | ||
679 | fn test_method(&self) {} | ||
680 | } | ||
681 | } | ||
682 | |||
683 | fn main() { | ||
684 | let test_struct = test_mod::TestStruct {}; | ||
685 | test_struct.test_method() | ||
686 | } | ||
687 | ", | ||
688 | ); | ||
689 | } | ||
690 | |||
691 | #[test] | ||
692 | fn trait_method_cross_crate() { | ||
693 | check_assist( | ||
694 | auto_import, | ||
695 | r" | ||
696 | //- /main.rs crate:main deps:dep | ||
697 | fn main() { | ||
698 | let test_struct = dep::test_mod::TestStruct {}; | ||
699 | test_struct.test_meth$0od() | ||
700 | } | ||
701 | //- /dep.rs crate:dep | ||
702 | pub mod test_mod { | ||
703 | pub trait TestTrait { | ||
704 | fn test_method(&self); | ||
705 | } | ||
706 | pub struct TestStruct {} | ||
707 | impl TestTrait for TestStruct { | ||
708 | fn test_method(&self) {} | ||
709 | } | ||
710 | } | ||
711 | ", | ||
712 | r" | ||
713 | use dep::test_mod::TestTrait; | ||
714 | |||
715 | fn main() { | ||
716 | let test_struct = dep::test_mod::TestStruct {}; | ||
717 | test_struct.test_method() | ||
718 | } | ||
719 | ", | ||
720 | ); | ||
721 | } | ||
722 | |||
723 | #[test] | ||
724 | fn assoc_fn_cross_crate() { | ||
725 | check_assist( | ||
726 | auto_import, | ||
727 | r" | ||
728 | //- /main.rs crate:main deps:dep | ||
729 | fn main() { | ||
730 | dep::test_mod::TestStruct::test_func$0tion | ||
731 | } | ||
732 | //- /dep.rs crate:dep | ||
733 | pub mod test_mod { | ||
734 | pub trait TestTrait { | ||
735 | fn test_function(); | ||
736 | } | ||
737 | pub struct TestStruct {} | ||
738 | impl TestTrait for TestStruct { | ||
739 | fn test_function() {} | ||
740 | } | ||
741 | } | ||
742 | ", | ||
743 | r" | ||
744 | use dep::test_mod::TestTrait; | ||
745 | |||
746 | fn main() { | ||
747 | dep::test_mod::TestStruct::test_function | ||
748 | } | ||
749 | ", | ||
750 | ); | ||
751 | } | ||
752 | |||
753 | #[test] | ||
754 | fn assoc_const_cross_crate() { | ||
755 | check_assist( | ||
756 | auto_import, | ||
757 | r" | ||
758 | //- /main.rs crate:main deps:dep | ||
759 | fn main() { | ||
760 | dep::test_mod::TestStruct::CONST$0 | ||
761 | } | ||
762 | //- /dep.rs crate:dep | ||
763 | pub mod test_mod { | ||
764 | pub trait TestTrait { | ||
765 | const CONST: bool; | ||
766 | } | ||
767 | pub struct TestStruct {} | ||
768 | impl TestTrait for TestStruct { | ||
769 | const CONST: bool = true; | ||
770 | } | ||
771 | } | ||
772 | ", | ||
773 | r" | ||
774 | use dep::test_mod::TestTrait; | ||
775 | |||
776 | fn main() { | ||
777 | dep::test_mod::TestStruct::CONST | ||
778 | } | ||
779 | ", | ||
780 | ); | ||
781 | } | ||
782 | |||
783 | #[test] | ||
784 | fn assoc_fn_as_method_cross_crate() { | ||
785 | check_assist_not_applicable( | ||
786 | auto_import, | ||
787 | r" | ||
788 | //- /main.rs crate:main deps:dep | ||
789 | fn main() { | ||
790 | let test_struct = dep::test_mod::TestStruct {}; | ||
791 | test_struct.test_func$0tion() | ||
792 | } | ||
793 | //- /dep.rs crate:dep | ||
794 | pub mod test_mod { | ||
795 | pub trait TestTrait { | ||
796 | fn test_function(); | ||
797 | } | ||
798 | pub struct TestStruct {} | ||
799 | impl TestTrait for TestStruct { | ||
800 | fn test_function() {} | ||
801 | } | ||
802 | } | ||
803 | ", | ||
804 | ); | ||
805 | } | ||
806 | |||
807 | #[test] | ||
808 | fn private_trait_cross_crate() { | ||
809 | check_assist_not_applicable( | ||
810 | auto_import, | ||
811 | r" | ||
812 | //- /main.rs crate:main deps:dep | ||
813 | fn main() { | ||
814 | let test_struct = dep::test_mod::TestStruct {}; | ||
815 | test_struct.test_meth$0od() | ||
816 | } | ||
817 | //- /dep.rs crate:dep | ||
818 | pub mod test_mod { | ||
819 | trait TestTrait { | ||
820 | fn test_method(&self); | ||
821 | } | ||
822 | pub struct TestStruct {} | ||
823 | impl TestTrait for TestStruct { | ||
824 | fn test_method(&self) {} | ||
825 | } | ||
826 | } | ||
827 | ", | ||
828 | ); | ||
829 | } | ||
830 | |||
831 | #[test] | ||
832 | fn not_applicable_for_imported_trait_for_method() { | ||
833 | check_assist_not_applicable( | ||
834 | auto_import, | ||
835 | r" | ||
836 | mod test_mod { | ||
837 | pub trait TestTrait { | ||
838 | fn test_method(&self); | ||
839 | } | ||
840 | pub trait TestTrait2 { | ||
841 | fn test_method(&self); | ||
842 | } | ||
843 | pub enum TestEnum { | ||
844 | One, | ||
845 | Two, | ||
846 | } | ||
847 | impl TestTrait2 for TestEnum { | ||
848 | fn test_method(&self) {} | ||
849 | } | ||
850 | impl TestTrait for TestEnum { | ||
851 | fn test_method(&self) {} | ||
852 | } | ||
853 | } | ||
854 | |||
855 | use test_mod::TestTrait2; | ||
856 | fn main() { | ||
857 | let one = test_mod::TestEnum::One; | ||
858 | one.test$0_method(); | ||
859 | } | ||
860 | ", | ||
861 | ) | ||
862 | } | ||
863 | |||
864 | #[test] | ||
865 | fn dep_import() { | ||
866 | check_assist( | ||
867 | auto_import, | ||
868 | r" | ||
869 | //- /lib.rs crate:dep | ||
870 | pub struct Struct; | ||
871 | |||
872 | //- /main.rs crate:main deps:dep | ||
873 | fn main() { | ||
874 | Struct$0 | ||
875 | } | ||
876 | ", | ||
877 | r"use dep::Struct; | ||
878 | |||
879 | fn main() { | ||
880 | Struct | ||
881 | } | ||
882 | ", | ||
883 | ); | ||
884 | } | ||
885 | |||
886 | #[test] | ||
887 | fn whole_segment() { | ||
888 | // Tests that only imports whose last segment matches the identifier get suggested. | ||
889 | check_assist( | ||
890 | auto_import, | ||
891 | r" | ||
892 | //- /lib.rs crate:dep | ||
893 | pub mod fmt { | ||
894 | pub trait Display {} | ||
895 | } | ||
896 | |||
897 | pub fn panic_fmt() {} | ||
898 | |||
899 | //- /main.rs crate:main deps:dep | ||
900 | struct S; | ||
901 | |||
902 | impl f$0mt::Display for S {} | ||
903 | ", | ||
904 | r"use dep::fmt; | ||
905 | |||
906 | struct S; | ||
907 | |||
908 | impl fmt::Display for S {} | ||
909 | ", | ||
910 | ); | ||
911 | } | ||
912 | |||
913 | #[test] | ||
914 | fn macro_generated() { | ||
915 | // Tests that macro-generated items are suggested from external crates. | ||
916 | check_assist( | ||
917 | auto_import, | ||
918 | r" | ||
919 | //- /lib.rs crate:dep | ||
920 | macro_rules! mac { | ||
921 | () => { | ||
922 | pub struct Cheese; | ||
923 | }; | ||
924 | } | ||
925 | |||
926 | mac!(); | ||
927 | |||
928 | //- /main.rs crate:main deps:dep | ||
929 | fn main() { | ||
930 | Cheese$0; | ||
931 | } | ||
932 | ", | ||
933 | r"use dep::Cheese; | ||
934 | |||
935 | fn main() { | ||
936 | Cheese; | ||
937 | } | ||
938 | ", | ||
939 | ); | ||
940 | } | ||
941 | |||
942 | #[test] | ||
943 | fn casing() { | ||
944 | // Tests that differently cased names don't interfere and we only suggest the matching one. | ||
945 | check_assist( | ||
946 | auto_import, | ||
947 | r" | ||
948 | //- /lib.rs crate:dep | ||
949 | pub struct FMT; | ||
950 | pub struct fmt; | ||
951 | |||
952 | //- /main.rs crate:main deps:dep | ||
953 | fn main() { | ||
954 | FMT$0; | ||
955 | } | ||
956 | ", | ||
957 | r"use dep::FMT; | ||
958 | |||
959 | fn main() { | ||
960 | FMT; | ||
961 | } | ||
962 | ", | ||
963 | ); | ||
964 | } | ||
965 | } | ||