diff options
Diffstat (limited to 'crates/ide_completion/src/completions')
-rw-r--r-- | crates/ide_completion/src/completions/qualified_path.rs | 85 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/unqualified_path.rs | 58 |
2 files changed, 90 insertions, 53 deletions
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs index 6083537b7..1643eeed4 100644 --- a/crates/ide_completion/src/completions/qualified_path.rs +++ b/crates/ide_completion/src/completions/qualified_path.rs | |||
@@ -19,6 +19,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
19 | Some(res) => res, | 19 | Some(res) => res, |
20 | None => return, | 20 | None => return, |
21 | }; | 21 | }; |
22 | |||
22 | let context_module = ctx.scope.module(); | 23 | let context_module = ctx.scope.module(); |
23 | 24 | ||
24 | if ctx.expects_item() || ctx.expects_assoc_item() { | 25 | if ctx.expects_item() || ctx.expects_assoc_item() { |
@@ -60,21 +61,31 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
60 | } | 61 | } |
61 | } | 62 | } |
62 | 63 | ||
63 | if let hir::ScopeDef::MacroDef(macro_def) = def { | 64 | let add_resolution = match def { |
64 | if !macro_def.is_fn_like() { | 65 | // Don't suggest attribute macros and derives. |
65 | // Don't suggest attribute macros and derives. | 66 | hir::ScopeDef::MacroDef(mac) => mac.is_fn_like(), |
66 | continue; | 67 | // no values in type places |
68 | hir::ScopeDef::ModuleDef(hir::ModuleDef::Function(_)) | ||
69 | | hir::ScopeDef::ModuleDef(hir::ModuleDef::Variant(_)) | ||
70 | | hir::ScopeDef::ModuleDef(hir::ModuleDef::Static(_)) | ||
71 | | hir::ScopeDef::Local(_) => !ctx.expects_type(), | ||
72 | // unless its a constant in a generic arg list position | ||
73 | hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(_)) => { | ||
74 | !ctx.expects_type() || ctx.expects_generic_arg() | ||
67 | } | 75 | } |
68 | } | 76 | _ => true, |
77 | }; | ||
69 | 78 | ||
70 | acc.add_resolution(ctx, name, &def); | 79 | if add_resolution { |
80 | acc.add_resolution(ctx, name, &def); | ||
81 | } | ||
71 | } | 82 | } |
72 | } | 83 | } |
73 | hir::PathResolution::Def(def @ hir::ModuleDef::Adt(_)) | 84 | hir::PathResolution::Def(def @ hir::ModuleDef::Adt(_)) |
74 | | hir::PathResolution::Def(def @ hir::ModuleDef::TypeAlias(_)) | 85 | | hir::PathResolution::Def(def @ hir::ModuleDef::TypeAlias(_)) |
75 | | hir::PathResolution::Def(def @ hir::ModuleDef::BuiltinType(_)) => { | 86 | | hir::PathResolution::Def(def @ hir::ModuleDef::BuiltinType(_)) => { |
76 | if let hir::ModuleDef::Adt(hir::Adt::Enum(e)) = def { | 87 | if let hir::ModuleDef::Adt(hir::Adt::Enum(e)) = def { |
77 | add_enum_variants(ctx, acc, e); | 88 | add_enum_variants(acc, ctx, e); |
78 | } | 89 | } |
79 | let ty = match def { | 90 | let ty = match def { |
80 | hir::ModuleDef::Adt(adt) => adt.ty(ctx.db), | 91 | hir::ModuleDef::Adt(adt) => adt.ty(ctx.db), |
@@ -82,7 +93,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
82 | let ty = a.ty(ctx.db); | 93 | let ty = a.ty(ctx.db); |
83 | if let Some(hir::Adt::Enum(e)) = ty.as_adt() { | 94 | if let Some(hir::Adt::Enum(e)) = ty.as_adt() { |
84 | cov_mark::hit!(completes_variant_through_alias); | 95 | cov_mark::hit!(completes_variant_through_alias); |
85 | add_enum_variants(ctx, acc, e); | 96 | add_enum_variants(acc, ctx, e); |
86 | } | 97 | } |
87 | ty | 98 | ty |
88 | } | 99 | } |
@@ -107,11 +118,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
107 | if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { | 118 | if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { |
108 | return None; | 119 | return None; |
109 | } | 120 | } |
110 | match item { | 121 | add_assoc_item(acc, ctx, item); |
111 | hir::AssocItem::Function(func) => acc.add_function(ctx, func, None), | ||
112 | hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), | ||
113 | hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), | ||
114 | } | ||
115 | None::<()> | 122 | None::<()> |
116 | }); | 123 | }); |
117 | 124 | ||
@@ -133,11 +140,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
133 | if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { | 140 | if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { |
134 | continue; | 141 | continue; |
135 | } | 142 | } |
136 | match item { | 143 | add_assoc_item(acc, ctx, item); |
137 | hir::AssocItem::Function(func) => acc.add_function(ctx, func, None), | ||
138 | hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), | ||
139 | hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), | ||
140 | } | ||
141 | } | 144 | } |
142 | } | 145 | } |
143 | hir::PathResolution::TypeParam(_) | hir::PathResolution::SelfType(_) => { | 146 | hir::PathResolution::TypeParam(_) | hir::PathResolution::SelfType(_) => { |
@@ -149,7 +152,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
149 | }; | 152 | }; |
150 | 153 | ||
151 | if let Some(hir::Adt::Enum(e)) = ty.as_adt() { | 154 | if let Some(hir::Adt::Enum(e)) = ty.as_adt() { |
152 | add_enum_variants(ctx, acc, e); | 155 | add_enum_variants(acc, ctx, e); |
153 | } | 156 | } |
154 | 157 | ||
155 | let traits_in_scope = ctx.scope.traits_in_scope(); | 158 | let traits_in_scope = ctx.scope.traits_in_scope(); |
@@ -162,11 +165,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
162 | // We might iterate candidates of a trait multiple times here, so deduplicate | 165 | // We might iterate candidates of a trait multiple times here, so deduplicate |
163 | // them. | 166 | // them. |
164 | if seen.insert(item) { | 167 | if seen.insert(item) { |
165 | match item { | 168 | add_assoc_item(acc, ctx, item); |
166 | hir::AssocItem::Function(func) => acc.add_function(ctx, func, None), | ||
167 | hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), | ||
168 | hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), | ||
169 | } | ||
170 | } | 169 | } |
171 | None::<()> | 170 | None::<()> |
172 | }); | 171 | }); |
@@ -176,10 +175,22 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
176 | } | 175 | } |
177 | } | 176 | } |
178 | 177 | ||
179 | fn add_enum_variants(ctx: &CompletionContext, acc: &mut Completions, e: hir::Enum) { | 178 | fn add_assoc_item(acc: &mut Completions, ctx: &CompletionContext, item: hir::AssocItem) { |
180 | for variant in e.variants(ctx.db) { | 179 | match item { |
181 | acc.add_enum_variant(ctx, variant, None); | 180 | hir::AssocItem::Function(func) if !ctx.expects_type() => acc.add_function(ctx, func, None), |
181 | hir::AssocItem::Const(ct) if !ctx.expects_type() || ctx.expects_generic_arg() => { | ||
182 | acc.add_const(ctx, ct) | ||
183 | } | ||
184 | hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), | ||
185 | _ => (), | ||
186 | } | ||
187 | } | ||
188 | |||
189 | fn add_enum_variants(acc: &mut Completions, ctx: &CompletionContext, e: hir::Enum) { | ||
190 | if ctx.expects_type() { | ||
191 | return; | ||
182 | } | 192 | } |
193 | e.variants(ctx.db).into_iter().for_each(|variant| acc.add_enum_variant(ctx, variant, None)); | ||
183 | } | 194 | } |
184 | 195 | ||
185 | #[cfg(test)] | 196 | #[cfg(test)] |
@@ -927,4 +938,24 @@ fn main() { | |||
927 | "#]], | 938 | "#]], |
928 | ); | 939 | ); |
929 | } | 940 | } |
941 | |||
942 | #[test] | ||
943 | fn completes_types_and_const_in_arg_list() { | ||
944 | check( | ||
945 | r#" | ||
946 | mod foo { | ||
947 | pub const CONST: () = (); | ||
948 | pub type Type = (); | ||
949 | } | ||
950 | |||
951 | struct Foo<T>(t); | ||
952 | |||
953 | fn foo(_: Foo<foo::$0>) {} | ||
954 | "#, | ||
955 | expect![[r#" | ||
956 | ta Type | ||
957 | ct CONST | ||
958 | "#]], | ||
959 | ); | ||
960 | } | ||
930 | } | 961 | } |
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index f86b2d3f3..b5af1c810 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs | |||
@@ -36,12 +36,14 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC | |||
36 | return; | 36 | return; |
37 | } | 37 | } |
38 | 38 | ||
39 | if let Some(hir::Adt::Enum(e)) = | 39 | if !ctx.expects_type() { |
40 | ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) | 40 | if let Some(hir::Adt::Enum(e)) = |
41 | { | 41 | ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) |
42 | super::complete_enum_variants(acc, ctx, e, |acc, ctx, variant, path| { | 42 | { |
43 | acc.add_qualified_enum_variant(ctx, variant, path) | 43 | super::complete_enum_variants(acc, ctx, e, |acc, ctx, variant, path| { |
44 | }); | 44 | acc.add_qualified_enum_variant(ctx, variant, path) |
45 | }); | ||
46 | } | ||
45 | } | 47 | } |
46 | 48 | ||
47 | if let Some(ImmediateLocation::GenericArgList(arg_list)) = &ctx.completion_location { | 49 | if let Some(ImmediateLocation::GenericArgList(arg_list)) = &ctx.completion_location { |
@@ -59,12 +61,25 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC | |||
59 | } | 61 | } |
60 | 62 | ||
61 | ctx.scope.process_all_names(&mut |name, res| { | 63 | ctx.scope.process_all_names(&mut |name, res| { |
62 | if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res { | 64 | if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) | ScopeDef::Label(_) = |
65 | res | ||
66 | { | ||
63 | cov_mark::hit!(skip_lifetime_completion); | 67 | cov_mark::hit!(skip_lifetime_completion); |
64 | return; | 68 | return; |
65 | } | 69 | } |
66 | let add_resolution = match res { | 70 | let add_resolution = match res { |
71 | // Don't suggest attribute macros and derives. | ||
67 | ScopeDef::MacroDef(mac) => mac.is_fn_like(), | 72 | ScopeDef::MacroDef(mac) => mac.is_fn_like(), |
73 | // no values in type places | ||
74 | ScopeDef::ModuleDef(hir::ModuleDef::Function(_)) | ||
75 | | ScopeDef::ModuleDef(hir::ModuleDef::Variant(_)) | ||
76 | | ScopeDef::ModuleDef(hir::ModuleDef::Static(_)) | ||
77 | | ScopeDef::Local(_) => !ctx.expects_type(), | ||
78 | // unless its a constant in a generic arg list position | ||
79 | ScopeDef::ModuleDef(hir::ModuleDef::Const(_)) | ||
80 | | ScopeDef::GenericParam(hir::GenericParam::ConstParam(_)) => { | ||
81 | !ctx.expects_type() || ctx.expects_generic_arg() | ||
82 | } | ||
68 | _ => true, | 83 | _ => true, |
69 | }; | 84 | }; |
70 | if add_resolution { | 85 | if add_resolution { |
@@ -794,36 +809,27 @@ $0 | |||
794 | } | 809 | } |
795 | 810 | ||
796 | #[test] | 811 | #[test] |
797 | fn completes_assoc_types_in_dynimpl_trait() { | 812 | fn completes_types_and_const_in_arg_list() { |
798 | check( | 813 | check( |
799 | r#" | 814 | r#" |
800 | trait Foo { | 815 | enum Bar { |
801 | type Bar; | 816 | Baz |
802 | } | 817 | } |
803 | |||
804 | fn foo(_: impl Foo<B$0>) {} | ||
805 | "#, | ||
806 | expect![[r#" | ||
807 | ta Bar = type Bar; | ||
808 | tt Foo | ||
809 | "#]], | ||
810 | ); | ||
811 | } | ||
812 | |||
813 | #[test] | ||
814 | fn completes_assoc_types_in_trait_bound() { | ||
815 | check( | ||
816 | r#" | ||
817 | trait Foo { | 818 | trait Foo { |
818 | type Bar; | 819 | type Bar; |
819 | } | 820 | } |
820 | 821 | ||
821 | fn foo<T: Foo<B$0>>(_: T) {} | 822 | const CONST: () = (); |
823 | |||
824 | fn foo<T: Foo<$0>, const CONST_PARAM: usize>(_: T) {} | ||
822 | "#, | 825 | "#, |
823 | expect![[r#" | 826 | expect![[r#" |
824 | ta Bar = type Bar; | 827 | ta Bar = type Bar; |
825 | tp T | 828 | tp T |
829 | cp CONST_PARAM | ||
826 | tt Foo | 830 | tt Foo |
831 | en Bar | ||
832 | ct CONST | ||
827 | "#]], | 833 | "#]], |
828 | ); | 834 | ); |
829 | } | 835 | } |