diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-09-11 15:49:57 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2019-09-11 15:49:57 +0100 |
commit | 6ce6744e18f25ebcde387178125d820686692df5 (patch) | |
tree | e1861982356f9905980537f962dff9560423f901 /crates/ra_ide_api/src/completion | |
parent | 7bbb039fbdd124cb6549eb67bbe7316f03ff40e8 (diff) | |
parent | 6353b1621f44e1b0db65ebbe414aa7c5f1864b9d (diff) |
Merge #1796
1796: Support completion for macros r=matklad a=uHOOCCOOHu
This is based on #1795 , and fixes #1727
Also prettify hover text of macros.
Some screenshorts below:
Completion in item place.
<img width="416" alt="Screenshot_20190910_134056" src="https://user-images.githubusercontent.com/14816024/64587159-fa72da00-d3d0-11e9-86bb-c98f169ec08d.png">
After pressing `tab`.
<img width="313" alt="Screenshot_20190910_134111" src="https://user-images.githubusercontent.com/14816024/64587160-fa72da00-d3d0-11e9-9464-21e3f6957bd7.png">
Complete macros from `std`.
<img width="588" alt="Screenshot_20190910_134147" src="https://user-images.githubusercontent.com/14816024/64587161-fb0b7080-d3d0-11e9-866e-5161f0d1b546.png">
Hover text.
<img width="521" alt="Screenshot_20190910_134242" src="https://user-images.githubusercontent.com/14816024/64587162-fb0b7080-d3d0-11e9-8f09-ad17e3f6702a.png">
Co-authored-by: uHOOCCOOHu <[email protected]>
Diffstat (limited to 'crates/ra_ide_api/src/completion')
4 files changed, 301 insertions, 1 deletions
diff --git a/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs b/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs new file mode 100644 index 000000000..708dc9777 --- /dev/null +++ b/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs | |||
@@ -0,0 +1,50 @@ | |||
1 | use crate::completion::{CompletionContext, Completions}; | ||
2 | |||
3 | pub(super) fn complete_macro_in_item_position(acc: &mut Completions, ctx: &CompletionContext) { | ||
4 | // Show only macros in top level. | ||
5 | if ctx.is_new_item { | ||
6 | for (name, res) in ctx.analyzer.all_names(ctx.db) { | ||
7 | if res.get_macros().is_some() { | ||
8 | acc.add_resolution(ctx, name.to_string(), &res.only_macros()); | ||
9 | } | ||
10 | } | ||
11 | } | ||
12 | } | ||
13 | |||
14 | #[cfg(test)] | ||
15 | mod tests { | ||
16 | use crate::completion::{do_completion, CompletionItem, CompletionKind}; | ||
17 | use insta::assert_debug_snapshot; | ||
18 | |||
19 | fn do_reference_completion(code: &str) -> Vec<CompletionItem> { | ||
20 | do_completion(code, CompletionKind::Reference) | ||
21 | } | ||
22 | |||
23 | #[test] | ||
24 | fn completes_macros_as_item() { | ||
25 | assert_debug_snapshot!( | ||
26 | do_reference_completion( | ||
27 | " | ||
28 | //- /main.rs | ||
29 | macro_rules! foo { | ||
30 | () => {} | ||
31 | } | ||
32 | |||
33 | fn foo() {} | ||
34 | |||
35 | <|> | ||
36 | " | ||
37 | ), | ||
38 | @r##"[ | ||
39 | CompletionItem { | ||
40 | label: "foo", | ||
41 | source_range: [46; 46), | ||
42 | delete: [46; 46), | ||
43 | insert: "foo!", | ||
44 | kind: Macro, | ||
45 | detail: "macro_rules! foo", | ||
46 | }, | ||
47 | ]"## | ||
48 | ); | ||
49 | } | ||
50 | } | ||
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index d6b5ac9ad..31e7dffe8 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs | |||
@@ -587,4 +587,40 @@ mod tests { | |||
587 | ]"### | 587 | ]"### |
588 | ); | 588 | ); |
589 | } | 589 | } |
590 | |||
591 | #[test] | ||
592 | fn completes_qualified_macros() { | ||
593 | assert_debug_snapshot!( | ||
594 | do_reference_completion( | ||
595 | " | ||
596 | #[macro_export] | ||
597 | macro_rules! foo { | ||
598 | () => {} | ||
599 | } | ||
600 | |||
601 | fn main() { | ||
602 | let _ = crate::<|> | ||
603 | } | ||
604 | " | ||
605 | ), | ||
606 | @r###"[ | ||
607 | CompletionItem { | ||
608 | label: "foo", | ||
609 | source_range: [179; 179), | ||
610 | delete: [179; 179), | ||
611 | insert: "foo!", | ||
612 | kind: Macro, | ||
613 | detail: "#[macro_export]\nmacro_rules! foo", | ||
614 | }, | ||
615 | CompletionItem { | ||
616 | label: "main", | ||
617 | source_range: [179; 179), | ||
618 | delete: [179; 179), | ||
619 | insert: "main()$0", | ||
620 | kind: Function, | ||
621 | detail: "fn main()", | ||
622 | }, | ||
623 | ]"### | ||
624 | ); | ||
625 | } | ||
590 | } | 626 | } |
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs index 67fb7ba4e..2062e7300 100644 --- a/crates/ra_ide_api/src/completion/complete_scope.rs +++ b/crates/ra_ide_api/src/completion/complete_scope.rs | |||
@@ -532,4 +532,196 @@ mod tests { | |||
532 | ]"# | 532 | ]"# |
533 | ); | 533 | ); |
534 | } | 534 | } |
535 | |||
536 | #[test] | ||
537 | fn completes_macros_as_value() { | ||
538 | assert_debug_snapshot!( | ||
539 | do_reference_completion( | ||
540 | " | ||
541 | //- /main.rs | ||
542 | macro_rules! foo { | ||
543 | () => {} | ||
544 | } | ||
545 | |||
546 | #[macro_use] | ||
547 | mod m1 { | ||
548 | macro_rules! bar { | ||
549 | () => {} | ||
550 | } | ||
551 | } | ||
552 | |||
553 | mod m2 { | ||
554 | macro_rules! nope { | ||
555 | () => {} | ||
556 | } | ||
557 | |||
558 | #[macro_export] | ||
559 | macro_rules! baz { | ||
560 | () => {} | ||
561 | } | ||
562 | } | ||
563 | |||
564 | fn main() { | ||
565 | let v = <|> | ||
566 | } | ||
567 | " | ||
568 | ), | ||
569 | @r##"[ | ||
570 | CompletionItem { | ||
571 | label: "bar", | ||
572 | source_range: [252; 252), | ||
573 | delete: [252; 252), | ||
574 | insert: "bar!", | ||
575 | kind: Macro, | ||
576 | detail: "macro_rules! bar", | ||
577 | }, | ||
578 | CompletionItem { | ||
579 | label: "baz", | ||
580 | source_range: [252; 252), | ||
581 | delete: [252; 252), | ||
582 | insert: "baz!", | ||
583 | kind: Macro, | ||
584 | detail: "#[macro_export]\nmacro_rules! baz", | ||
585 | }, | ||
586 | CompletionItem { | ||
587 | label: "foo", | ||
588 | source_range: [252; 252), | ||
589 | delete: [252; 252), | ||
590 | insert: "foo!", | ||
591 | kind: Macro, | ||
592 | detail: "macro_rules! foo", | ||
593 | }, | ||
594 | CompletionItem { | ||
595 | label: "m1", | ||
596 | source_range: [252; 252), | ||
597 | delete: [252; 252), | ||
598 | insert: "m1", | ||
599 | kind: Module, | ||
600 | }, | ||
601 | CompletionItem { | ||
602 | label: "m2", | ||
603 | source_range: [252; 252), | ||
604 | delete: [252; 252), | ||
605 | insert: "m2", | ||
606 | kind: Module, | ||
607 | }, | ||
608 | CompletionItem { | ||
609 | label: "main", | ||
610 | source_range: [252; 252), | ||
611 | delete: [252; 252), | ||
612 | insert: "main()$0", | ||
613 | kind: Function, | ||
614 | detail: "fn main()", | ||
615 | }, | ||
616 | ]"## | ||
617 | ); | ||
618 | } | ||
619 | |||
620 | #[test] | ||
621 | fn completes_both_macro_and_value() { | ||
622 | assert_debug_snapshot!( | ||
623 | do_reference_completion( | ||
624 | " | ||
625 | //- /main.rs | ||
626 | macro_rules! foo { | ||
627 | () => {} | ||
628 | } | ||
629 | |||
630 | fn foo() { | ||
631 | <|> | ||
632 | } | ||
633 | " | ||
634 | ), | ||
635 | @r##"[ | ||
636 | CompletionItem { | ||
637 | label: "foo", | ||
638 | source_range: [49; 49), | ||
639 | delete: [49; 49), | ||
640 | insert: "foo!", | ||
641 | kind: Macro, | ||
642 | detail: "macro_rules! foo", | ||
643 | }, | ||
644 | CompletionItem { | ||
645 | label: "foo", | ||
646 | source_range: [49; 49), | ||
647 | delete: [49; 49), | ||
648 | insert: "foo()$0", | ||
649 | kind: Function, | ||
650 | detail: "fn foo()", | ||
651 | }, | ||
652 | ]"## | ||
653 | ); | ||
654 | } | ||
655 | |||
656 | #[test] | ||
657 | fn completes_macros_as_type() { | ||
658 | assert_debug_snapshot!( | ||
659 | do_reference_completion( | ||
660 | " | ||
661 | //- /main.rs | ||
662 | macro_rules! foo { | ||
663 | () => {} | ||
664 | } | ||
665 | |||
666 | fn main() { | ||
667 | let x: <|> | ||
668 | } | ||
669 | " | ||
670 | ), | ||
671 | @r##"[ | ||
672 | CompletionItem { | ||
673 | label: "foo", | ||
674 | source_range: [57; 57), | ||
675 | delete: [57; 57), | ||
676 | insert: "foo!", | ||
677 | kind: Macro, | ||
678 | detail: "macro_rules! foo", | ||
679 | }, | ||
680 | CompletionItem { | ||
681 | label: "main", | ||
682 | source_range: [57; 57), | ||
683 | delete: [57; 57), | ||
684 | insert: "main()$0", | ||
685 | kind: Function, | ||
686 | detail: "fn main()", | ||
687 | }, | ||
688 | ]"## | ||
689 | ); | ||
690 | } | ||
691 | |||
692 | #[test] | ||
693 | fn completes_macros_as_stmt() { | ||
694 | assert_debug_snapshot!( | ||
695 | do_reference_completion( | ||
696 | " | ||
697 | //- /main.rs | ||
698 | macro_rules! foo { | ||
699 | () => {} | ||
700 | } | ||
701 | |||
702 | fn main() { | ||
703 | <|> | ||
704 | } | ||
705 | " | ||
706 | ), | ||
707 | @r##"[ | ||
708 | CompletionItem { | ||
709 | label: "foo", | ||
710 | source_range: [50; 50), | ||
711 | delete: [50; 50), | ||
712 | insert: "foo!", | ||
713 | kind: Macro, | ||
714 | detail: "macro_rules! foo", | ||
715 | }, | ||
716 | CompletionItem { | ||
717 | label: "main", | ||
718 | source_range: [50; 50), | ||
719 | delete: [50; 50), | ||
720 | insert: "main()$0", | ||
721 | kind: Function, | ||
722 | detail: "fn main()", | ||
723 | }, | ||
724 | ]"## | ||
725 | ); | ||
726 | } | ||
535 | } | 727 | } |
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs index db7e8348e..1b706bb13 100644 --- a/crates/ra_ide_api/src/completion/presentation.rs +++ b/crates/ra_ide_api/src/completion/presentation.rs | |||
@@ -8,7 +8,7 @@ use crate::completion::{ | |||
8 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, | 8 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | use crate::display::{const_label, function_label, type_label}; | 11 | use crate::display::{const_label, function_label, macro_label, type_label}; |
12 | 12 | ||
13 | impl Completions { | 13 | impl Completions { |
14 | pub(crate) fn add_field( | 14 | pub(crate) fn add_field( |
@@ -43,8 +43,14 @@ impl Completions { | |||
43 | ) { | 43 | ) { |
44 | use hir::ModuleDef::*; | 44 | use hir::ModuleDef::*; |
45 | 45 | ||
46 | if let Some(macro_) = resolution.get_macros() { | ||
47 | self.add_macro(ctx, Some(local_name.clone()), macro_); | ||
48 | } | ||
49 | |||
46 | let def = resolution.as_ref().take_types().or_else(|| resolution.as_ref().take_values()); | 50 | let def = resolution.as_ref().take_types().or_else(|| resolution.as_ref().take_values()); |
47 | let def = match def { | 51 | let def = match def { |
52 | // Only insert once if it is just a macro name | ||
53 | None if resolution.get_macros().is_some() => return, | ||
48 | None => { | 54 | None => { |
49 | self.add(CompletionItem::new( | 55 | self.add(CompletionItem::new( |
50 | CompletionKind::Reference, | 56 | CompletionKind::Reference, |
@@ -98,6 +104,22 @@ impl Completions { | |||
98 | self.add_function_with_name(ctx, None, func) | 104 | self.add_function_with_name(ctx, None, func) |
99 | } | 105 | } |
100 | 106 | ||
107 | fn add_macro(&mut self, ctx: &CompletionContext, name: Option<String>, macro_: hir::MacroDef) { | ||
108 | let ast_node = macro_.source(ctx.db).ast; | ||
109 | if let Some(name) = name { | ||
110 | let detail = macro_label(&ast_node); | ||
111 | |||
112 | let builder = | ||
113 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone()) | ||
114 | .kind(CompletionItemKind::Macro) | ||
115 | .set_documentation(macro_.docs(ctx.db)) | ||
116 | .detail(detail) | ||
117 | .insert_snippet(format!("{}!", name)); | ||
118 | |||
119 | self.add(builder); | ||
120 | } | ||
121 | } | ||
122 | |||
101 | fn add_function_with_name( | 123 | fn add_function_with_name( |
102 | &mut self, | 124 | &mut self, |
103 | ctx: &CompletionContext, | 125 | ctx: &CompletionContext, |