diff options
-rw-r--r-- | crates/hir/src/lib.rs | 12 | ||||
-rw-r--r-- | crates/hir/src/semantics.rs | 3 | ||||
-rw-r--r-- | crates/ide_completion/src/completions.rs | 48 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/attribute.rs | 4 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/flyimport.rs | 3 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/unqualified_path.rs | 4 | ||||
-rw-r--r-- | crates/ide_completion/src/context.rs | 42 | ||||
-rw-r--r-- | crates/ide_completion/src/render.rs | 15 |
8 files changed, 76 insertions, 55 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index c2b68a853..589641760 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -2496,6 +2496,18 @@ impl ScopeDef { | |||
2496 | 2496 | ||
2497 | items | 2497 | items |
2498 | } | 2498 | } |
2499 | |||
2500 | pub fn is_value_def(&self) -> bool { | ||
2501 | matches!( | ||
2502 | self, | ||
2503 | ScopeDef::ModuleDef(ModuleDef::Function(_)) | ||
2504 | | ScopeDef::ModuleDef(ModuleDef::Variant(_)) | ||
2505 | | ScopeDef::ModuleDef(ModuleDef::Const(_)) | ||
2506 | | ScopeDef::ModuleDef(ModuleDef::Static(_)) | ||
2507 | | ScopeDef::GenericParam(GenericParam::ConstParam(_)) | ||
2508 | | ScopeDef::Local(_) | ||
2509 | ) | ||
2510 | } | ||
2499 | } | 2511 | } |
2500 | 2512 | ||
2501 | impl From<ItemInNs> for ScopeDef { | 2513 | impl From<ItemInNs> for ScopeDef { |
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 2d08a7704..827e23e2b 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs | |||
@@ -35,8 +35,9 @@ pub enum PathResolution { | |||
35 | Def(ModuleDef), | 35 | Def(ModuleDef), |
36 | /// A local binding (only value namespace) | 36 | /// A local binding (only value namespace) |
37 | Local(Local), | 37 | Local(Local), |
38 | /// A generic parameter | 38 | /// A type parameter |
39 | TypeParam(TypeParam), | 39 | TypeParam(TypeParam), |
40 | /// A const parameter | ||
40 | ConstParam(ConstParam), | 41 | ConstParam(ConstParam), |
41 | SelfType(Impl), | 42 | SelfType(Impl), |
42 | Macro(MacroDef), | 43 | Macro(MacroDef), |
diff --git a/crates/ide_completion/src/completions.rs b/crates/ide_completion/src/completions.rs index 7a4d71e91..e07a4c403 100644 --- a/crates/ide_completion/src/completions.rs +++ b/crates/ide_completion/src/completions.rs | |||
@@ -56,10 +56,16 @@ impl Builder { | |||
56 | } | 56 | } |
57 | 57 | ||
58 | impl Completions { | 58 | impl Completions { |
59 | pub(crate) fn add(&mut self, item: CompletionItem) { | 59 | fn add(&mut self, item: CompletionItem) { |
60 | self.buf.push(item) | 60 | self.buf.push(item) |
61 | } | 61 | } |
62 | 62 | ||
63 | fn add_opt(&mut self, item: Option<CompletionItem>) { | ||
64 | if let Some(item) = item { | ||
65 | self.buf.push(item) | ||
66 | } | ||
67 | } | ||
68 | |||
63 | pub(crate) fn add_all<I>(&mut self, items: I) | 69 | pub(crate) fn add_all<I>(&mut self, items: I) |
64 | where | 70 | where |
65 | I: IntoIterator, | 71 | I: IntoIterator, |
@@ -103,9 +109,10 @@ impl Completions { | |||
103 | local_name: hir::Name, | 109 | local_name: hir::Name, |
104 | resolution: &hir::ScopeDef, | 110 | resolution: &hir::ScopeDef, |
105 | ) { | 111 | ) { |
106 | if let Some(item) = render_resolution(RenderContext::new(ctx), local_name, resolution) { | 112 | if ctx.expects_type() && resolution.is_value_def() { |
107 | self.add(item); | 113 | return; |
108 | } | 114 | } |
115 | self.add_opt(render_resolution(RenderContext::new(ctx), local_name, resolution)); | ||
109 | } | 116 | } |
110 | 117 | ||
111 | pub(crate) fn add_macro( | 118 | pub(crate) fn add_macro( |
@@ -118,9 +125,7 @@ impl Completions { | |||
118 | Some(it) => it, | 125 | Some(it) => it, |
119 | None => return, | 126 | None => return, |
120 | }; | 127 | }; |
121 | if let Some(item) = render_macro(RenderContext::new(ctx), None, name, macro_) { | 128 | self.add_opt(render_macro(RenderContext::new(ctx), None, name, macro_)); |
122 | self.add(item); | ||
123 | } | ||
124 | } | 129 | } |
125 | 130 | ||
126 | pub(crate) fn add_function( | 131 | pub(crate) fn add_function( |
@@ -129,9 +134,10 @@ impl Completions { | |||
129 | func: hir::Function, | 134 | func: hir::Function, |
130 | local_name: Option<hir::Name>, | 135 | local_name: Option<hir::Name>, |
131 | ) { | 136 | ) { |
132 | if let Some(item) = render_fn(RenderContext::new(ctx), None, local_name, func) { | 137 | if ctx.expects_type() { |
133 | self.add(item) | 138 | return; |
134 | } | 139 | } |
140 | self.add_opt(render_fn(RenderContext::new(ctx), None, local_name, func)); | ||
135 | } | 141 | } |
136 | 142 | ||
137 | pub(crate) fn add_method( | 143 | pub(crate) fn add_method( |
@@ -141,10 +147,7 @@ impl Completions { | |||
141 | receiver: Option<hir::Name>, | 147 | receiver: Option<hir::Name>, |
142 | local_name: Option<hir::Name>, | 148 | local_name: Option<hir::Name>, |
143 | ) { | 149 | ) { |
144 | if let Some(item) = render_method(RenderContext::new(ctx), None, receiver, local_name, func) | 150 | self.add_opt(render_method(RenderContext::new(ctx), None, receiver, local_name, func)); |
145 | { | ||
146 | self.add(item) | ||
147 | } | ||
148 | } | 151 | } |
149 | 152 | ||
150 | pub(crate) fn add_variant_pat( | 153 | pub(crate) fn add_variant_pat( |
@@ -153,9 +156,7 @@ impl Completions { | |||
153 | variant: hir::Variant, | 156 | variant: hir::Variant, |
154 | local_name: Option<hir::Name>, | 157 | local_name: Option<hir::Name>, |
155 | ) { | 158 | ) { |
156 | if let Some(item) = render_variant_pat(RenderContext::new(ctx), variant, local_name, None) { | 159 | self.add_opt(render_variant_pat(RenderContext::new(ctx), variant, local_name, None)); |
157 | self.add(item); | ||
158 | } | ||
159 | } | 160 | } |
160 | 161 | ||
161 | pub(crate) fn add_qualified_variant_pat( | 162 | pub(crate) fn add_qualified_variant_pat( |
@@ -164,9 +165,7 @@ impl Completions { | |||
164 | variant: hir::Variant, | 165 | variant: hir::Variant, |
165 | path: hir::ModPath, | 166 | path: hir::ModPath, |
166 | ) { | 167 | ) { |
167 | if let Some(item) = render_variant_pat(RenderContext::new(ctx), variant, None, Some(path)) { | 168 | self.add_opt(render_variant_pat(RenderContext::new(ctx), variant, None, Some(path))); |
168 | self.add(item); | ||
169 | } | ||
170 | } | 169 | } |
171 | 170 | ||
172 | pub(crate) fn add_struct_pat( | 171 | pub(crate) fn add_struct_pat( |
@@ -175,21 +174,18 @@ impl Completions { | |||
175 | strukt: hir::Struct, | 174 | strukt: hir::Struct, |
176 | local_name: Option<hir::Name>, | 175 | local_name: Option<hir::Name>, |
177 | ) { | 176 | ) { |
178 | if let Some(item) = render_struct_pat(RenderContext::new(ctx), strukt, local_name) { | 177 | self.add_opt(render_struct_pat(RenderContext::new(ctx), strukt, local_name)); |
179 | self.add(item); | ||
180 | } | ||
181 | } | 178 | } |
182 | 179 | ||
183 | pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const) { | 180 | pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const) { |
184 | if let Some(item) = render_const(RenderContext::new(ctx), constant) { | 181 | if ctx.expects_type() { |
185 | self.add(item); | 182 | return; |
186 | } | 183 | } |
184 | self.add_opt(render_const(RenderContext::new(ctx), constant)); | ||
187 | } | 185 | } |
188 | 186 | ||
189 | pub(crate) fn add_type_alias(&mut self, ctx: &CompletionContext, type_alias: hir::TypeAlias) { | 187 | pub(crate) fn add_type_alias(&mut self, ctx: &CompletionContext, type_alias: hir::TypeAlias) { |
190 | if let Some(item) = render_type_alias(RenderContext::new(ctx), type_alias) { | 188 | self.add_opt(render_type_alias(RenderContext::new(ctx), type_alias)); |
191 | self.add(item) | ||
192 | } | ||
193 | } | 189 | } |
194 | 190 | ||
195 | pub(crate) fn add_qualified_enum_variant( | 191 | pub(crate) fn add_qualified_enum_variant( |
diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs index d3392100d..7f76e357e 100644 --- a/crates/ide_completion/src/completions/attribute.rs +++ b/crates/ide_completion/src/completions/attribute.rs | |||
@@ -69,7 +69,7 @@ fn complete_new_attribute(acc: &mut Completions, ctx: &CompletionContext, attrib | |||
69 | } | 69 | } |
70 | 70 | ||
71 | if is_inner || !attr_completion.prefer_inner { | 71 | if is_inner || !attr_completion.prefer_inner { |
72 | acc.add(item.build()); | 72 | item.add_to(acc); |
73 | } | 73 | } |
74 | }; | 74 | }; |
75 | 75 | ||
@@ -96,7 +96,7 @@ fn complete_new_attribute(acc: &mut Completions, ctx: &CompletionContext, attrib | |||
96 | if let Some(docs) = mac.docs(ctx.sema.db) { | 96 | if let Some(docs) = mac.docs(ctx.sema.db) { |
97 | item.documentation(docs); | 97 | item.documentation(docs); |
98 | } | 98 | } |
99 | acc.add(item.build()); | 99 | item.add_to(acc); |
100 | } | 100 | } |
101 | } | 101 | } |
102 | }); | 102 | }); |
diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs index 7bf47bf75..c010cbbca 100644 --- a/crates/ide_completion/src/completions/flyimport.rs +++ b/crates/ide_completion/src/completions/flyimport.rs | |||
@@ -90,7 +90,6 @@ | |||
90 | //! Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corredponding | 90 | //! Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corredponding |
91 | //! capability enabled. | 91 | //! capability enabled. |
92 | 92 | ||
93 | use hir::ModPath; | ||
94 | use ide_db::helpers::{ | 93 | use ide_db::helpers::{ |
95 | import_assets::{ImportAssets, ImportCandidate}, | 94 | import_assets::{ImportAssets, ImportCandidate}, |
96 | insert_use::ImportScope, | 95 | insert_use::ImportScope, |
@@ -208,7 +207,7 @@ fn import_assets(ctx: &CompletionContext, fuzzy_name: String) -> Option<ImportAs | |||
208 | } | 207 | } |
209 | 208 | ||
210 | fn compute_fuzzy_completion_order_key( | 209 | fn compute_fuzzy_completion_order_key( |
211 | proposed_mod_path: &ModPath, | 210 | proposed_mod_path: &hir::ModPath, |
212 | user_input_lowercased: &str, | 211 | user_input_lowercased: &str, |
213 | ) -> usize { | 212 | ) -> usize { |
214 | cov_mark::hit!(certain_fuzzy_order_test); | 213 | cov_mark::hit!(certain_fuzzy_order_test); |
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index 8b22933e0..f370dbdf0 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs | |||
@@ -339,7 +339,6 @@ fn x() -> $0 | |||
339 | "#, | 339 | "#, |
340 | expect![[r#" | 340 | expect![[r#" |
341 | st Foo | 341 | st Foo |
342 | fn x() fn() | ||
343 | "#]], | 342 | "#]], |
344 | ); | 343 | ); |
345 | } | 344 | } |
@@ -391,7 +390,6 @@ pub mod prelude { | |||
391 | } | 390 | } |
392 | "#, | 391 | "#, |
393 | expect![[r#" | 392 | expect![[r#" |
394 | fn foo() fn() | ||
395 | md std | 393 | md std |
396 | st Option | 394 | st Option |
397 | "#]], | 395 | "#]], |
@@ -448,7 +446,6 @@ pub mod prelude { | |||
448 | } | 446 | } |
449 | "#, | 447 | "#, |
450 | expect![[r#" | 448 | expect![[r#" |
451 | fn foo() fn() | ||
452 | md std | 449 | md std |
453 | md core | 450 | md core |
454 | st String | 451 | st String |
@@ -509,7 +506,6 @@ macro_rules! foo { () => {} } | |||
509 | fn main() { let x: $0 } | 506 | fn main() { let x: $0 } |
510 | "#, | 507 | "#, |
511 | expect![[r#" | 508 | expect![[r#" |
512 | fn main() fn() | ||
513 | ma foo!(…) macro_rules! foo | 509 | ma foo!(…) macro_rules! foo |
514 | "#]], | 510 | "#]], |
515 | ); | 511 | ); |
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index 6177caa12..2c2a4aa6b 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs | |||
@@ -30,19 +30,24 @@ pub(crate) enum PatternRefutability { | |||
30 | } | 30 | } |
31 | 31 | ||
32 | #[derive(Debug)] | 32 | #[derive(Debug)] |
33 | pub(super) enum PathKind { | ||
34 | Expr, | ||
35 | Type, | ||
36 | } | ||
37 | |||
38 | #[derive(Debug)] | ||
33 | pub(crate) struct PathCompletionContext { | 39 | pub(crate) struct PathCompletionContext { |
34 | /// If this is a call with () already there | 40 | /// If this is a call with () already there |
35 | call_kind: Option<CallKind>, | 41 | call_kind: Option<CallKind>, |
36 | /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path. | 42 | /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path. |
37 | pub(super) is_trivial_path: bool, | 43 | pub(super) is_trivial_path: bool, |
38 | /// If not a trivial path, the prefix (qualifier). | 44 | /// If not a trivial path, the prefix (qualifier). |
39 | pub(super) path_qual: Option<ast::Path>, | 45 | pub(super) qualifier: Option<ast::Path>, |
40 | pub(super) is_path_type: bool, | 46 | pub(super) kind: Option<PathKind>, |
47 | /// Whether the path segment has type args or not. | ||
41 | pub(super) has_type_args: bool, | 48 | pub(super) has_type_args: bool, |
42 | /// `true` if we are a statement or a last expr in the block. | 49 | /// `true` if we are a statement or a last expr in the block. |
43 | pub(super) can_be_stmt: bool, | 50 | pub(super) can_be_stmt: bool, |
44 | /// `true` if we expect an expression at the cursor position. | ||
45 | pub(super) is_expr: bool, | ||
46 | pub(super) in_loop_body: bool, | 51 | pub(super) in_loop_body: bool, |
47 | } | 52 | } |
48 | 53 | ||
@@ -308,7 +313,11 @@ impl<'a> CompletionContext<'a> { | |||
308 | } | 313 | } |
309 | 314 | ||
310 | pub(crate) fn expects_expression(&self) -> bool { | 315 | pub(crate) fn expects_expression(&self) -> bool { |
311 | self.path_context.as_ref().map_or(false, |it| it.is_expr) | 316 | matches!(self.path_context, Some(PathCompletionContext { kind: Some(PathKind::Expr), .. })) |
317 | } | ||
318 | |||
319 | pub(crate) fn expects_type(&self) -> bool { | ||
320 | matches!(self.path_context, Some(PathCompletionContext { kind: Some(PathKind::Type), .. })) | ||
312 | } | 321 | } |
313 | 322 | ||
314 | pub(crate) fn path_call_kind(&self) -> Option<CallKind> { | 323 | pub(crate) fn path_call_kind(&self) -> Option<CallKind> { |
@@ -316,11 +325,11 @@ impl<'a> CompletionContext<'a> { | |||
316 | } | 325 | } |
317 | 326 | ||
318 | pub(crate) fn is_trivial_path(&self) -> bool { | 327 | pub(crate) fn is_trivial_path(&self) -> bool { |
319 | self.path_context.as_ref().map_or(false, |it| it.is_trivial_path) | 328 | matches!(self.path_context, Some(PathCompletionContext { is_trivial_path: true, .. })) |
320 | } | 329 | } |
321 | 330 | ||
322 | pub(crate) fn path_qual(&self) -> Option<&ast::Path> { | 331 | pub(crate) fn path_qual(&self) -> Option<&ast::Path> { |
323 | self.path_context.as_ref().and_then(|it| it.path_qual.as_ref()) | 332 | self.path_context.as_ref().and_then(|it| it.qualifier.as_ref()) |
324 | } | 333 | } |
325 | 334 | ||
326 | fn fill_impl_def(&mut self) { | 335 | fn fill_impl_def(&mut self) { |
@@ -573,12 +582,11 @@ impl<'a> CompletionContext<'a> { | |||
573 | let path_ctx = self.path_context.get_or_insert(PathCompletionContext { | 582 | let path_ctx = self.path_context.get_or_insert(PathCompletionContext { |
574 | call_kind: None, | 583 | call_kind: None, |
575 | is_trivial_path: false, | 584 | is_trivial_path: false, |
576 | path_qual: None, | 585 | qualifier: None, |
577 | has_type_args: false, | 586 | has_type_args: false, |
578 | is_path_type: false, | ||
579 | can_be_stmt: false, | 587 | can_be_stmt: false, |
580 | is_expr: false, | ||
581 | in_loop_body: false, | 588 | in_loop_body: false, |
589 | kind: None, | ||
582 | }); | 590 | }); |
583 | path_ctx.in_loop_body = is_in_loop_body(name_ref.syntax()); | 591 | path_ctx.in_loop_body = is_in_loop_body(name_ref.syntax()); |
584 | let path = segment.parent_path(); | 592 | let path = segment.parent_path(); |
@@ -593,11 +601,20 @@ impl<'a> CompletionContext<'a> { | |||
593 | } | 601 | } |
594 | }; | 602 | }; |
595 | } | 603 | } |
596 | path_ctx.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); | 604 | |
605 | if let Some(parent) = path.syntax().parent() { | ||
606 | path_ctx.kind = match_ast! { | ||
607 | match parent { | ||
608 | ast::PathType(_it) => Some(PathKind::Type), | ||
609 | ast::PathExpr(_it) => Some(PathKind::Expr), | ||
610 | _ => None, | ||
611 | } | ||
612 | }; | ||
613 | } | ||
597 | path_ctx.has_type_args = segment.generic_arg_list().is_some(); | 614 | path_ctx.has_type_args = segment.generic_arg_list().is_some(); |
598 | 615 | ||
599 | if let Some(path) = path_or_use_tree_qualifier(&path) { | 616 | if let Some(path) = path_or_use_tree_qualifier(&path) { |
600 | path_ctx.path_qual = path | 617 | path_ctx.qualifier = path |
601 | .segment() | 618 | .segment() |
602 | .and_then(|it| { | 619 | .and_then(|it| { |
603 | find_node_with_range::<ast::PathSegment>( | 620 | find_node_with_range::<ast::PathSegment>( |
@@ -635,7 +652,6 @@ impl<'a> CompletionContext<'a> { | |||
635 | None | 652 | None |
636 | }) | 653 | }) |
637 | .unwrap_or(false); | 654 | .unwrap_or(false); |
638 | path_ctx.is_expr = path.syntax().parent().and_then(ast::PathExpr::cast).is_some(); | ||
639 | } | 655 | } |
640 | } | 656 | } |
641 | } | 657 | } |
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs index 750694432..7118183fe 100644 --- a/crates/ide_completion/src/render.rs +++ b/crates/ide_completion/src/render.rs | |||
@@ -18,6 +18,7 @@ use ide_db::{ | |||
18 | use syntax::TextRange; | 18 | use syntax::TextRange; |
19 | 19 | ||
20 | use crate::{ | 20 | use crate::{ |
21 | context::{PathCompletionContext, PathKind}, | ||
21 | item::{CompletionRelevanceTypeMatch, ImportEdit}, | 22 | item::{CompletionRelevanceTypeMatch, ImportEdit}, |
22 | render::{enum_variant::render_variant, function::render_fn, macro_::render_macro}, | 23 | render::{enum_variant::render_variant, function::render_fn, macro_::render_macro}, |
23 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, CompletionRelevance, | 24 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, CompletionRelevance, |
@@ -54,6 +55,9 @@ pub(crate) fn render_resolution_with_import<'a>( | |||
54 | import_edit: ImportEdit, | 55 | import_edit: ImportEdit, |
55 | ) -> Option<CompletionItem> { | 56 | ) -> Option<CompletionItem> { |
56 | let resolution = hir::ScopeDef::from(import_edit.import.original_item); | 57 | let resolution = hir::ScopeDef::from(import_edit.import.original_item); |
58 | if ctx.completion.expects_type() && resolution.is_value_def() { | ||
59 | return None; | ||
60 | } | ||
57 | let local_name = match resolution { | 61 | let local_name = match resolution { |
58 | hir::ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db), | 62 | hir::ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db), |
59 | hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?, | 63 | hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?, |
@@ -275,13 +279,10 @@ impl<'a> Render<'a> { | |||
275 | }; | 279 | }; |
276 | 280 | ||
277 | // Add `<>` for generic types | 281 | // Add `<>` for generic types |
278 | if self | 282 | if matches!( |
279 | .ctx | 283 | self.ctx.completion.path_context, |
280 | .completion | 284 | Some(PathCompletionContext { kind: Some(PathKind::Type), has_type_args: false, .. }) |
281 | .path_context | 285 | ) && self.ctx.completion.config.add_call_parenthesis |
282 | .as_ref() | ||
283 | .map_or(false, |it| it.is_path_type && !it.has_type_args) | ||
284 | && self.ctx.completion.config.add_call_parenthesis | ||
285 | { | 286 | { |
286 | if let Some(cap) = self.ctx.snippet_cap() { | 287 | if let Some(cap) = self.ctx.snippet_cap() { |
287 | let has_non_default_type_params = match resolution { | 288 | let has_non_default_type_params = match resolution { |