aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/completion
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-09-11 15:49:57 +0100
committerGitHub <[email protected]>2019-09-11 15:49:57 +0100
commit6ce6744e18f25ebcde387178125d820686692df5 (patch)
treee1861982356f9905980537f962dff9560423f901 /crates/ra_ide_api/src/completion
parent7bbb039fbdd124cb6549eb67bbe7316f03ff40e8 (diff)
parent6353b1621f44e1b0db65ebbe414aa7c5f1864b9d (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')
-rw-r--r--crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs50
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs36
-rw-r--r--crates/ra_ide_api/src/completion/complete_scope.rs192
-rw-r--r--crates/ra_ide_api/src/completion/presentation.rs24
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 @@
1use crate::completion::{CompletionContext, Completions};
2
3pub(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)]
15mod 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
11use crate::display::{const_label, function_label, type_label}; 11use crate::display::{const_label, function_label, macro_label, type_label};
12 12
13impl Completions { 13impl 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,