aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ide_completion/src/completions.rs1
-rw-r--r--crates/ide_completion/src/completions/macro_in_item_position.rs48
-rw-r--r--crates/ide_completion/src/completions/qualified_path.rs11
-rw-r--r--crates/ide_completion/src/completions/unqualified_path.rs22
-rw-r--r--crates/ide_completion/src/context.rs36
-rw-r--r--crates/ide_completion/src/lib.rs1
-rw-r--r--crates/ide_db/src/call_info.rs3
7 files changed, 32 insertions, 90 deletions
diff --git a/crates/ide_completion/src/completions.rs b/crates/ide_completion/src/completions.rs
index ffdcdc930..7a4d71e91 100644
--- a/crates/ide_completion/src/completions.rs
+++ b/crates/ide_completion/src/completions.rs
@@ -6,7 +6,6 @@ pub(crate) mod flyimport;
6pub(crate) mod fn_param; 6pub(crate) mod fn_param;
7pub(crate) mod keyword; 7pub(crate) mod keyword;
8pub(crate) mod lifetime; 8pub(crate) mod lifetime;
9pub(crate) mod macro_in_item_position;
10pub(crate) mod mod_; 9pub(crate) mod mod_;
11pub(crate) mod pattern; 10pub(crate) mod pattern;
12pub(crate) mod postfix; 11pub(crate) mod postfix;
diff --git a/crates/ide_completion/src/completions/macro_in_item_position.rs b/crates/ide_completion/src/completions/macro_in_item_position.rs
deleted file mode 100644
index 781b96ff1..000000000
--- a/crates/ide_completion/src/completions/macro_in_item_position.rs
+++ /dev/null
@@ -1,48 +0,0 @@
1//! Completes macro invocations used in item position.
2
3use crate::{CompletionContext, Completions};
4
5// Ideally this should be removed and moved into `(un)qualified_path` respectively
6pub(crate) fn complete_macro_in_item_position(acc: &mut Completions, ctx: &CompletionContext) {
7 // Show only macros in top level.
8 if !ctx.expects_item() {
9 return;
10 }
11
12 ctx.scope.process_all_names(&mut |name, res| {
13 if let hir::ScopeDef::MacroDef(mac) = res {
14 acc.add_macro(ctx, Some(name.clone()), mac);
15 }
16 // FIXME: This should be done in qualified_path/unqualified_path instead?
17 if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
18 acc.add_resolution(ctx, name, &res);
19 }
20 })
21}
22
23#[cfg(test)]
24mod tests {
25 use expect_test::{expect, Expect};
26
27 use crate::{test_utils::completion_list, CompletionKind};
28
29 fn check(ra_fixture: &str, expect: Expect) {
30 let actual = completion_list(ra_fixture, CompletionKind::Reference);
31 expect.assert_eq(&actual)
32 }
33
34 #[test]
35 fn completes_macros_as_item() {
36 check(
37 r#"
38macro_rules! foo { () => {} }
39fn foo() {}
40
41$0
42"#,
43 expect![[r#"
44 ma foo!(…) macro_rules! foo
45 "#]],
46 )
47 }
48}
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs
index c072de7b5..d58745fb4 100644
--- a/crates/ide_completion/src/completions/qualified_path.rs
+++ b/crates/ide_completion/src/completions/qualified_path.rs
@@ -7,7 +7,7 @@ use syntax::AstNode;
7use crate::{CompletionContext, Completions}; 7use crate::{CompletionContext, Completions};
8 8
9pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) { 9pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
10 if ctx.is_path_disallowed() || ctx.expects_item() { 10 if ctx.is_path_disallowed() {
11 return; 11 return;
12 } 12 }
13 let path = match ctx.path_qual() { 13 let path = match ctx.path_qual() {
@@ -20,7 +20,8 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
20 None => return, 20 None => return,
21 }; 21 };
22 let context_module = ctx.scope.module(); 22 let context_module = ctx.scope.module();
23 if ctx.expects_assoc_item() { 23
24 if ctx.expects_item() || ctx.expects_assoc_item() {
24 if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution { 25 if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
25 let module_scope = module.scope(ctx.db, context_module); 26 let module_scope = module.scope(ctx.db, context_module);
26 for (name, def) in module_scope { 27 for (name, def) in module_scope {
@@ -631,17 +632,17 @@ impl MyStruct {
631"#, 632"#,
632 expect![[r##" 633 expect![[r##"
633 md bar 634 md bar
634 ma foo! #[macro_export] macro_rules! foo 635 ma foo!(…) #[macro_export] macro_rules! foo
635 "##]], 636 "##]],
636 ); 637 );
637 } 638 }
638 639
639 #[test] 640 #[test]
640 #[ignore] // FIXME doesn't complete anything atm
641 fn completes_in_item_list() { 641 fn completes_in_item_list() {
642 check( 642 check(
643 r#" 643 r#"
644struct MyStruct {} 644struct MyStruct {}
645#[macro_export]
645macro_rules! foo {} 646macro_rules! foo {}
646mod bar {} 647mod bar {}
647 648
@@ -649,7 +650,7 @@ crate::$0
649"#, 650"#,
650 expect![[r#" 651 expect![[r#"
651 md bar 652 md bar
652 ma foo! macro_rules! foo 653 ma foo!(…) #[macro_export] macro_rules! foo
653 "#]], 654 "#]],
654 ) 655 )
655 } 656 }
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs
index f321ed52b..8b22933e0 100644
--- a/crates/ide_completion/src/completions/unqualified_path.rs
+++ b/crates/ide_completion/src/completions/unqualified_path.rs
@@ -5,26 +5,25 @@ use hir::ScopeDef;
5use crate::{CompletionContext, Completions}; 5use crate::{CompletionContext, Completions};
6 6
7pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { 7pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
8 if !ctx.is_trivial_path() { 8 if ctx.is_path_disallowed() || !ctx.is_trivial_path() {
9 return;
10 }
11 if ctx.is_path_disallowed() || ctx.expects_item() {
12 return; 9 return;
13 } 10 }
14 11
15 if ctx.expects_assoc_item() { 12 if ctx.expects_item() || ctx.expects_assoc_item() {
16 ctx.scope.process_all_names(&mut |name, def| { 13 // only show macros in {Assoc}ItemList
17 if let ScopeDef::MacroDef(macro_def) = def { 14 ctx.scope.process_all_names(&mut |name, res| {
18 acc.add_macro(ctx, Some(name.clone()), macro_def); 15 if let hir::ScopeDef::MacroDef(mac) = res {
16 acc.add_macro(ctx, Some(name.clone()), mac);
19 } 17 }
20 if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = def { 18 if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
21 acc.add_resolution(ctx, name, &def); 19 acc.add_resolution(ctx, name, &res);
22 } 20 }
23 }); 21 });
24 return; 22 return;
25 } 23 }
26 24
27 if ctx.expects_use_tree() { 25 if ctx.expects_use_tree() {
26 // only show modules in a fresh UseTree
28 cov_mark::hit!(only_completes_modules_in_import); 27 cov_mark::hit!(only_completes_modules_in_import);
29 ctx.scope.process_all_names(&mut |name, res| { 28 ctx.scope.process_all_names(&mut |name, res| {
30 if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res { 29 if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
@@ -693,12 +692,11 @@ impl MyStruct {
693"#, 692"#,
694 expect![[r#" 693 expect![[r#"
695 md bar 694 md bar
696 ma foo! macro_rules! foo 695 ma foo!(…) macro_rules! foo
697 "#]], 696 "#]],
698 ) 697 )
699 } 698 }
700 699
701 // FIXME: The completions here currently come from `macro_in_item_position`, but they shouldn't
702 #[test] 700 #[test]
703 fn completes_in_item_list() { 701 fn completes_in_item_list() {
704 check( 702 check(
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 20e033d31..7e4b14926 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -67,14 +67,13 @@ pub(crate) struct CompletionContext<'a> {
67 pub(super) krate: Option<hir::Crate>, 67 pub(super) krate: Option<hir::Crate>,
68 pub(super) expected_name: Option<NameOrNameRef>, 68 pub(super) expected_name: Option<NameOrNameRef>,
69 pub(super) expected_type: Option<Type>, 69 pub(super) expected_type: Option<Type>,
70 pub(super) name_ref_syntax: Option<ast::NameRef>,
71
72 pub(super) use_item_syntax: Option<ast::Use>,
73 70
74 /// The parent function of the cursor position if it exists. 71 /// The parent function of the cursor position if it exists.
75 pub(super) function_def: Option<ast::Fn>, 72 pub(super) function_def: Option<ast::Fn>,
76 /// The parent impl of the cursor position if it exists. 73 /// The parent impl of the cursor position if it exists.
77 pub(super) impl_def: Option<ast::Impl>, 74 pub(super) impl_def: Option<ast::Impl>,
75 pub(super) name_ref_syntax: Option<ast::NameRef>,
76 pub(super) use_item_syntax: Option<ast::Use>,
78 77
79 // potentially set if we are completing a lifetime 78 // potentially set if we are completing a lifetime
80 pub(super) lifetime_syntax: Option<ast::Lifetime>, 79 pub(super) lifetime_syntax: Option<ast::Lifetime>,
@@ -89,13 +88,12 @@ pub(crate) struct CompletionContext<'a> {
89 pub(super) completion_location: Option<ImmediateLocation>, 88 pub(super) completion_location: Option<ImmediateLocation>,
90 pub(super) prev_sibling: Option<ImmediatePrevSibling>, 89 pub(super) prev_sibling: Option<ImmediatePrevSibling>,
91 pub(super) attribute_under_caret: Option<ast::Attr>, 90 pub(super) attribute_under_caret: Option<ast::Attr>,
91 pub(super) previous_token: Option<SyntaxToken>,
92 92
93 pub(super) path_context: Option<PathCompletionContext>, 93 pub(super) path_context: Option<PathCompletionContext>,
94 /// FIXME: `ActiveParameter` is string-based, which is very very wrong
95 pub(super) active_parameter: Option<ActiveParameter>, 94 pub(super) active_parameter: Option<ActiveParameter>,
96 pub(super) locals: Vec<(String, Local)>, 95 pub(super) locals: Vec<(String, Local)>,
97 96
98 pub(super) previous_token: Option<SyntaxToken>,
99 pub(super) in_loop_body: bool, 97 pub(super) in_loop_body: bool,
100 pub(super) incomplete_let: bool, 98 pub(super) incomplete_let: bool,
101 99
@@ -143,28 +141,28 @@ impl<'a> CompletionContext<'a> {
143 original_token, 141 original_token,
144 token, 142 token,
145 krate, 143 krate,
146 lifetime_allowed: false,
147 expected_name: None, 144 expected_name: None,
148 expected_type: None, 145 expected_type: None,
146 function_def: None,
147 impl_def: None,
149 name_ref_syntax: None, 148 name_ref_syntax: None,
149 use_item_syntax: None,
150 lifetime_syntax: None, 150 lifetime_syntax: None,
151 lifetime_param_syntax: None, 151 lifetime_param_syntax: None,
152 function_def: None, 152 lifetime_allowed: false,
153 use_item_syntax: None,
154 impl_def: None,
155 active_parameter: ActiveParameter::at(db, position),
156 is_label_ref: false, 153 is_label_ref: false,
157 is_param: false,
158 is_pat_or_const: None, 154 is_pat_or_const: None,
159 path_context: None, 155 is_param: false,
160 previous_token: None,
161 in_loop_body: false,
162 completion_location: None, 156 completion_location: None,
163 prev_sibling: None, 157 prev_sibling: None,
164 no_completion_required: false,
165 incomplete_let: false,
166 attribute_under_caret: None, 158 attribute_under_caret: None,
159 previous_token: None,
160 path_context: None,
161 active_parameter: ActiveParameter::at(db, position),
167 locals, 162 locals,
163 in_loop_body: false,
164 incomplete_let: false,
165 no_completion_required: false,
168 }; 166 };
169 167
170 let mut original_file = original_file.syntax().clone(); 168 let mut original_file = original_file.syntax().clone();
@@ -563,10 +561,6 @@ impl<'a> CompletionContext<'a> {
563 self.name_ref_syntax = 561 self.name_ref_syntax =
564 find_node_at_offset(original_file, name_ref.syntax().text_range().start()); 562 find_node_at_offset(original_file, name_ref.syntax().text_range().start());
565 563
566 if matches!(self.completion_location, Some(ImmediateLocation::ItemList)) {
567 return;
568 }
569
570 self.use_item_syntax = 564 self.use_item_syntax =
571 self.sema.token_ancestors_with_macros(self.token.clone()).find_map(ast::Use::cast); 565 self.sema.token_ancestors_with_macros(self.token.clone()).find_map(ast::Use::cast);
572 566
@@ -597,7 +591,7 @@ impl<'a> CompletionContext<'a> {
597 path_ctx.call_kind = match_ast! { 591 path_ctx.call_kind = match_ast! {
598 match p { 592 match p {
599 ast::PathExpr(it) => it.syntax().parent().and_then(ast::CallExpr::cast).map(|_| CallKind::Expr), 593 ast::PathExpr(it) => it.syntax().parent().and_then(ast::CallExpr::cast).map(|_| CallKind::Expr),
600 ast::MacroCall(_it) => Some(CallKind::Mac), 594 ast::MacroCall(it) => it.excl_token().and(Some(CallKind::Mac)),
601 ast::TupleStructPat(_it) => Some(CallKind::Pat), 595 ast::TupleStructPat(_it) => Some(CallKind::Pat),
602 _ => None 596 _ => None
603 } 597 }
diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs
index 6fb38f50d..18983aa01 100644
--- a/crates/ide_completion/src/lib.rs
+++ b/crates/ide_completion/src/lib.rs
@@ -158,7 +158,6 @@ pub fn completions(
158 completions::record::complete_record(&mut acc, &ctx); 158 completions::record::complete_record(&mut acc, &ctx);
159 completions::pattern::complete_pattern(&mut acc, &ctx); 159 completions::pattern::complete_pattern(&mut acc, &ctx);
160 completions::postfix::complete_postfix(&mut acc, &ctx); 160 completions::postfix::complete_postfix(&mut acc, &ctx);
161 completions::macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx);
162 completions::trait_impl::complete_trait_impl(&mut acc, &ctx); 161 completions::trait_impl::complete_trait_impl(&mut acc, &ctx);
163 completions::mod_::complete_mod(&mut acc, &ctx); 162 completions::mod_::complete_mod(&mut acc, &ctx);
164 completions::flyimport::import_on_the_fly(&mut acc, &ctx); 163 completions::flyimport::import_on_the_fly(&mut acc, &ctx);
diff --git a/crates/ide_db/src/call_info.rs b/crates/ide_db/src/call_info.rs
index bad277a95..933bcad55 100644
--- a/crates/ide_db/src/call_info.rs
+++ b/crates/ide_db/src/call_info.rs
@@ -223,9 +223,8 @@ impl FnCallNode {
223 ast::Expr::PathExpr(path_expr) => path_expr.path()?.segment()?.name_ref()?, 223 ast::Expr::PathExpr(path_expr) => path_expr.path()?.segment()?.name_ref()?,
224 _ => return None, 224 _ => return None,
225 }), 225 }),
226
227 FnCallNode::MethodCallExpr(call_expr) => { 226 FnCallNode::MethodCallExpr(call_expr) => {
228 call_expr.syntax().children().filter_map(ast::NameRef::cast).next() 227 call_expr.syntax().children().find_map(ast::NameRef::cast)
229 } 228 }
230 } 229 }
231 } 230 }