diff options
Diffstat (limited to 'crates/ide_completion')
-rw-r--r-- | crates/ide_completion/src/completions.rs | 56 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/pattern.rs | 6 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/postfix.rs | 5 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/postfix/format_like.rs | 2 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/qualified_path.rs | 73 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/unqualified_path.rs | 6 | ||||
-rw-r--r-- | crates/ide_completion/src/context.rs | 208 | ||||
-rw-r--r-- | crates/ide_completion/src/render/enum_variant.rs | 2 |
8 files changed, 190 insertions, 168 deletions
diff --git a/crates/ide_completion/src/completions.rs b/crates/ide_completion/src/completions.rs index e2994eed4..78154bf3e 100644 --- a/crates/ide_completion/src/completions.rs +++ b/crates/ide_completion/src/completions.rs | |||
@@ -203,41 +203,37 @@ impl Completions { | |||
203 | fn complete_enum_variants( | 203 | fn complete_enum_variants( |
204 | acc: &mut Completions, | 204 | acc: &mut Completions, |
205 | ctx: &CompletionContext, | 205 | ctx: &CompletionContext, |
206 | ty: &hir::Type, | 206 | enum_data: hir::Enum, |
207 | cb: impl Fn(&mut Completions, &CompletionContext, hir::Variant, hir::ModPath), | 207 | cb: impl Fn(&mut Completions, &CompletionContext, hir::Variant, hir::ModPath), |
208 | ) { | 208 | ) { |
209 | if let Some(hir::Adt::Enum(enum_data)) = | 209 | let variants = enum_data.variants(ctx.db); |
210 | iter::successors(Some(ty.clone()), |ty| ty.remove_ref()).last().and_then(|ty| ty.as_adt()) | 210 | |
211 | { | 211 | let module = if let Some(module) = ctx.scope.module() { |
212 | let variants = enum_data.variants(ctx.db); | 212 | // Compute path from the completion site if available. |
213 | 213 | module | |
214 | let module = if let Some(module) = ctx.scope.module() { | 214 | } else { |
215 | // Compute path from the completion site if available. | 215 | // Otherwise fall back to the enum's definition site. |
216 | module | 216 | enum_data.module(ctx.db) |
217 | } else { | 217 | }; |
218 | // Otherwise fall back to the enum's definition site. | 218 | |
219 | enum_data.module(ctx.db) | 219 | if let Some(impl_) = ctx.impl_def.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) { |
220 | }; | 220 | if impl_.self_ty(ctx.db).as_adt() == Some(hir::Adt::Enum(enum_data)) { |
221 | 221 | for &variant in &variants { | |
222 | if let Some(impl_) = ctx.impl_def.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) { | 222 | let self_path = hir::ModPath::from_segments( |
223 | if impl_.self_ty(ctx.db) == *ty { | 223 | hir::PathKind::Plain, |
224 | for &variant in &variants { | 224 | iter::once(known::SELF_TYPE).chain(iter::once(variant.name(ctx.db))), |
225 | let self_path = hir::ModPath::from_segments( | 225 | ); |
226 | hir::PathKind::Plain, | 226 | cb(acc, ctx, variant, self_path); |
227 | iter::once(known::SELF_TYPE).chain(iter::once(variant.name(ctx.db))), | ||
228 | ); | ||
229 | cb(acc, ctx, variant, self_path); | ||
230 | } | ||
231 | } | 227 | } |
232 | } | 228 | } |
229 | } | ||
233 | 230 | ||
234 | for variant in variants { | 231 | for variant in variants { |
235 | if let Some(path) = module.find_use_path(ctx.db, hir::ModuleDef::from(variant)) { | 232 | if let Some(path) = module.find_use_path(ctx.db, hir::ModuleDef::from(variant)) { |
236 | // Variants with trivial paths are already added by the existing completion logic, | 233 | // Variants with trivial paths are already added by the existing completion logic, |
237 | // so we should avoid adding these twice | 234 | // so we should avoid adding these twice |
238 | if path.segments().len() > 1 { | 235 | if path.segments().len() > 1 { |
239 | cb(acc, ctx, variant, path); | 236 | cb(acc, ctx, variant, path); |
240 | } | ||
241 | } | 237 | } |
242 | } | 238 | } |
243 | } | 239 | } |
diff --git a/crates/ide_completion/src/completions/pattern.rs b/crates/ide_completion/src/completions/pattern.rs index 808d7ff7e..8dc9ab73c 100644 --- a/crates/ide_completion/src/completions/pattern.rs +++ b/crates/ide_completion/src/completions/pattern.rs | |||
@@ -12,8 +12,10 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { | |||
12 | } | 12 | } |
13 | 13 | ||
14 | if !ctx.is_irrefutable_pat_binding { | 14 | if !ctx.is_irrefutable_pat_binding { |
15 | if let Some(ty) = ctx.expected_type.as_ref() { | 15 | if let Some(hir::Adt::Enum(e)) = |
16 | super::complete_enum_variants(acc, ctx, ty, |acc, ctx, variant, path| { | 16 | ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) |
17 | { | ||
18 | super::complete_enum_variants(acc, ctx, e, |acc, ctx, variant, path| { | ||
17 | acc.add_qualified_variant_pat(ctx, variant, path.clone()); | 19 | acc.add_qualified_variant_pat(ctx, variant, path.clone()); |
18 | acc.add_qualified_enum_variant(ctx, variant, path); | 20 | acc.add_qualified_enum_variant(ctx, variant, path); |
19 | }); | 21 | }); |
diff --git a/crates/ide_completion/src/completions/postfix.rs b/crates/ide_completion/src/completions/postfix.rs index ac69b720a..962aaf0df 100644 --- a/crates/ide_completion/src/completions/postfix.rs +++ b/crates/ide_completion/src/completions/postfix.rs | |||
@@ -35,14 +35,11 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
35 | None => return, | 35 | None => return, |
36 | }; | 36 | }; |
37 | 37 | ||
38 | let ref_removed_ty = | ||
39 | std::iter::successors(Some(receiver_ty.clone()), |ty| ty.remove_ref()).last().unwrap(); | ||
40 | |||
41 | let cap = match ctx.config.snippet_cap { | 38 | let cap = match ctx.config.snippet_cap { |
42 | Some(it) => it, | 39 | Some(it) => it, |
43 | None => return, | 40 | None => return, |
44 | }; | 41 | }; |
45 | let try_enum = TryEnum::from_ty(&ctx.sema, &ref_removed_ty); | 42 | let try_enum = TryEnum::from_ty(&ctx.sema, &receiver_ty.strip_references()); |
46 | if let Some(try_enum) = &try_enum { | 43 | if let Some(try_enum) = &try_enum { |
47 | match try_enum { | 44 | match try_enum { |
48 | TryEnum::Result => { | 45 | TryEnum::Result => { |
diff --git a/crates/ide_completion/src/completions/postfix/format_like.rs b/crates/ide_completion/src/completions/postfix/format_like.rs index e86ffa8f8..0dcb3e898 100644 --- a/crates/ide_completion/src/completions/postfix/format_like.rs +++ b/crates/ide_completion/src/completions/postfix/format_like.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | // Feature: Format String Completion. | 1 | // Feature: Format String Completion |
2 | // | 2 | // |
3 | // `"Result {result} is {2 + 2}"` is expanded to the `"Result {} is {}", result, 2 + 2`. | 3 | // `"Result {result} is {2 + 2}"` is expanded to the `"Result {} is {}", result, 2 + 2`. |
4 | // | 4 | // |
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs index 969249df6..eedb44873 100644 --- a/crates/ide_completion/src/completions/qualified_path.rs +++ b/crates/ide_completion/src/completions/qualified_path.rs | |||
@@ -52,18 +52,24 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
52 | | PathResolution::Def(def @ hir::ModuleDef::TypeAlias(_)) | 52 | | PathResolution::Def(def @ hir::ModuleDef::TypeAlias(_)) |
53 | | PathResolution::Def(def @ hir::ModuleDef::BuiltinType(_)) => { | 53 | | PathResolution::Def(def @ hir::ModuleDef::BuiltinType(_)) => { |
54 | if let hir::ModuleDef::Adt(Adt::Enum(e)) = def { | 54 | if let hir::ModuleDef::Adt(Adt::Enum(e)) = def { |
55 | for variant in e.variants(ctx.db) { | 55 | add_enum_variants(ctx, acc, e); |
56 | acc.add_enum_variant(ctx, variant, None); | ||
57 | } | ||
58 | } | 56 | } |
59 | let ty = match def { | 57 | let ty = match def { |
60 | hir::ModuleDef::Adt(adt) => adt.ty(ctx.db), | 58 | hir::ModuleDef::Adt(adt) => adt.ty(ctx.db), |
61 | hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), | 59 | hir::ModuleDef::TypeAlias(a) => { |
60 | let ty = a.ty(ctx.db); | ||
61 | if let Some(Adt::Enum(e)) = ty.as_adt() { | ||
62 | cov_mark::hit!(completes_variant_through_alias); | ||
63 | add_enum_variants(ctx, acc, e); | ||
64 | } | ||
65 | ty | ||
66 | } | ||
62 | hir::ModuleDef::BuiltinType(builtin) => { | 67 | hir::ModuleDef::BuiltinType(builtin) => { |
63 | let module = match ctx.scope.module() { | 68 | let module = match ctx.scope.module() { |
64 | Some(it) => it, | 69 | Some(it) => it, |
65 | None => return, | 70 | None => return, |
66 | }; | 71 | }; |
72 | cov_mark::hit!(completes_primitive_assoc_const); | ||
67 | builtin.ty(ctx.db, module) | 73 | builtin.ty(ctx.db, module) |
68 | } | 74 | } |
69 | _ => unreachable!(), | 75 | _ => unreachable!(), |
@@ -92,9 +98,8 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
92 | if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { | 98 | if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { |
93 | return None; | 99 | return None; |
94 | } | 100 | } |
95 | match item { | 101 | if let hir::AssocItem::TypeAlias(ty) = item { |
96 | hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {} | 102 | acc.add_type_alias(ctx, ty) |
97 | hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), | ||
98 | } | 103 | } |
99 | None::<()> | 104 | None::<()> |
100 | }); | 105 | }); |
@@ -122,9 +127,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
122 | }; | 127 | }; |
123 | 128 | ||
124 | if let Some(Adt::Enum(e)) = ty.as_adt() { | 129 | if let Some(Adt::Enum(e)) = ty.as_adt() { |
125 | for variant in e.variants(ctx.db) { | 130 | add_enum_variants(ctx, acc, e); |
126 | acc.add_enum_variant(ctx, variant, None); | ||
127 | } | ||
128 | } | 131 | } |
129 | 132 | ||
130 | let traits_in_scope = ctx.scope.traits_in_scope(); | 133 | let traits_in_scope = ctx.scope.traits_in_scope(); |
@@ -151,6 +154,12 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
151 | } | 154 | } |
152 | } | 155 | } |
153 | 156 | ||
157 | fn add_enum_variants(ctx: &CompletionContext, acc: &mut Completions, e: hir::Enum) { | ||
158 | for variant in e.variants(ctx.db) { | ||
159 | acc.add_enum_variant(ctx, variant, None); | ||
160 | } | ||
161 | } | ||
162 | |||
154 | #[cfg(test)] | 163 | #[cfg(test)] |
155 | mod tests { | 164 | mod tests { |
156 | use expect_test::{expect, Expect}; | 165 | use expect_test::{expect, Expect}; |
@@ -737,29 +746,7 @@ fn f() {} | |||
737 | } | 746 | } |
738 | 747 | ||
739 | #[test] | 748 | #[test] |
740 | fn completes_function() { | 749 | fn completes_variant_through_self() { |
741 | check( | ||
742 | r#" | ||
743 | fn foo( | ||
744 | a: i32, | ||
745 | b: i32 | ||
746 | ) { | ||
747 | |||
748 | } | ||
749 | |||
750 | fn main() { | ||
751 | fo$0 | ||
752 | } | ||
753 | "#, | ||
754 | expect![[r#" | ||
755 | fn main() fn() | ||
756 | fn foo(…) fn(i32, i32) | ||
757 | "#]], | ||
758 | ); | ||
759 | } | ||
760 | |||
761 | #[test] | ||
762 | fn completes_self_enum() { | ||
763 | check( | 750 | check( |
764 | r#" | 751 | r#" |
765 | enum Foo { | 752 | enum Foo { |
@@ -783,6 +770,7 @@ impl Foo { | |||
783 | 770 | ||
784 | #[test] | 771 | #[test] |
785 | fn completes_primitive_assoc_const() { | 772 | fn completes_primitive_assoc_const() { |
773 | cov_mark::check!(completes_primitive_assoc_const); | ||
786 | check( | 774 | check( |
787 | r#" | 775 | r#" |
788 | //- /lib.rs crate:lib deps:core | 776 | //- /lib.rs crate:lib deps:core |
@@ -804,4 +792,23 @@ impl u8 { | |||
804 | "#]], | 792 | "#]], |
805 | ); | 793 | ); |
806 | } | 794 | } |
795 | |||
796 | #[test] | ||
797 | fn completes_variant_through_alias() { | ||
798 | cov_mark::check!(completes_variant_through_alias); | ||
799 | check( | ||
800 | r#" | ||
801 | enum Foo { | ||
802 | Bar | ||
803 | } | ||
804 | type Foo2 = Foo; | ||
805 | fn main() { | ||
806 | Foo2::$0 | ||
807 | } | ||
808 | "#, | ||
809 | expect![[r#" | ||
810 | ev Bar () | ||
811 | "#]], | ||
812 | ); | ||
813 | } | ||
807 | } | 814 | } |
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index 1b8b063e7..7875500c1 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs | |||
@@ -17,8 +17,10 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC | |||
17 | return; | 17 | return; |
18 | } | 18 | } |
19 | 19 | ||
20 | if let Some(ty) = &ctx.expected_type { | 20 | if let Some(hir::Adt::Enum(e)) = |
21 | super::complete_enum_variants(acc, ctx, ty, |acc, ctx, variant, path| { | 21 | ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) |
22 | { | ||
23 | super::complete_enum_variants(acc, ctx, e, |acc, ctx, variant, path| { | ||
22 | acc.add_qualified_enum_variant(ctx, variant, path) | 24 | acc.add_qualified_enum_variant(ctx, variant, path) |
23 | }); | 25 | }); |
24 | } | 26 | } |
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index 32f81aec1..f3fcb712c 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs | |||
@@ -301,103 +301,108 @@ impl<'a> CompletionContext<'a> { | |||
301 | .find_map(ast::Impl::cast); | 301 | .find_map(ast::Impl::cast); |
302 | } | 302 | } |
303 | 303 | ||
304 | fn expected_type_and_name(&self) -> (Option<Type>, Option<NameOrNameRef>) { | ||
305 | let mut node = match self.token.parent() { | ||
306 | Some(it) => it, | ||
307 | None => return (None, None), | ||
308 | }; | ||
309 | loop { | ||
310 | break match_ast! { | ||
311 | match node { | ||
312 | ast::LetStmt(it) => { | ||
313 | cov_mark::hit!(expected_type_let_with_leading_char); | ||
314 | cov_mark::hit!(expected_type_let_without_leading_char); | ||
315 | let ty = it.pat() | ||
316 | .and_then(|pat| self.sema.type_of_pat(&pat)); | ||
317 | let name = if let Some(ast::Pat::IdentPat(ident)) = it.pat() { | ||
318 | ident.name().map(NameOrNameRef::Name) | ||
319 | } else { | ||
320 | None | ||
321 | }; | ||
322 | |||
323 | (ty, name) | ||
324 | }, | ||
325 | ast::ArgList(_it) => { | ||
326 | cov_mark::hit!(expected_type_fn_param_with_leading_char); | ||
327 | cov_mark::hit!(expected_type_fn_param_without_leading_char); | ||
328 | ActiveParameter::at_token( | ||
329 | &self.sema, | ||
330 | self.token.clone(), | ||
331 | ).map(|ap| { | ||
332 | let name = ap.ident().map(NameOrNameRef::Name); | ||
333 | (Some(ap.ty), name) | ||
334 | }) | ||
335 | .unwrap_or((None, None)) | ||
336 | }, | ||
337 | ast::RecordExprFieldList(_it) => { | ||
338 | cov_mark::hit!(expected_type_struct_field_without_leading_char); | ||
339 | self.token.prev_sibling_or_token() | ||
340 | .and_then(|se| se.into_node()) | ||
341 | .and_then(|node| ast::RecordExprField::cast(node)) | ||
342 | .and_then(|rf| self.sema.resolve_record_field(&rf).zip(Some(rf))) | ||
343 | .map(|(f, rf)|( | ||
344 | Some(f.0.ty(self.db)), | ||
345 | rf.field_name().map(NameOrNameRef::NameRef), | ||
346 | )) | ||
347 | .unwrap_or((None, None)) | ||
348 | }, | ||
349 | ast::RecordExprField(it) => { | ||
350 | cov_mark::hit!(expected_type_struct_field_with_leading_char); | ||
351 | self.sema | ||
352 | .resolve_record_field(&it) | ||
353 | .map(|f|( | ||
354 | Some(f.0.ty(self.db)), | ||
355 | it.field_name().map(NameOrNameRef::NameRef), | ||
356 | )) | ||
357 | .unwrap_or((None, None)) | ||
358 | }, | ||
359 | ast::MatchExpr(it) => { | ||
360 | cov_mark::hit!(expected_type_match_arm_without_leading_char); | ||
361 | let ty = it.expr() | ||
362 | .and_then(|e| self.sema.type_of_expr(&e)); | ||
363 | (ty, None) | ||
364 | }, | ||
365 | ast::IfExpr(it) => { | ||
366 | cov_mark::hit!(expected_type_if_let_without_leading_char); | ||
367 | let ty = it.condition() | ||
368 | .and_then(|cond| cond.expr()) | ||
369 | .and_then(|e| self.sema.type_of_expr(&e)); | ||
370 | (ty, None) | ||
371 | }, | ||
372 | ast::IdentPat(it) => { | ||
373 | cov_mark::hit!(expected_type_if_let_with_leading_char); | ||
374 | cov_mark::hit!(expected_type_match_arm_with_leading_char); | ||
375 | let ty = self.sema.type_of_pat(&ast::Pat::from(it)); | ||
376 | (ty, None) | ||
377 | }, | ||
378 | ast::Fn(it) => { | ||
379 | cov_mark::hit!(expected_type_fn_ret_with_leading_char); | ||
380 | cov_mark::hit!(expected_type_fn_ret_without_leading_char); | ||
381 | let def = self.sema.to_def(&it); | ||
382 | (def.map(|def| def.ret_type(self.db)), None) | ||
383 | }, | ||
384 | ast::Stmt(it) => (None, None), | ||
385 | _ => { | ||
386 | match node.parent() { | ||
387 | Some(n) => { | ||
388 | node = n; | ||
389 | continue; | ||
390 | }, | ||
391 | None => (None, None), | ||
392 | } | ||
393 | }, | ||
394 | } | ||
395 | }; | ||
396 | } | ||
397 | } | ||
398 | |||
304 | fn fill( | 399 | fn fill( |
305 | &mut self, | 400 | &mut self, |
306 | original_file: &SyntaxNode, | 401 | original_file: &SyntaxNode, |
307 | file_with_fake_ident: SyntaxNode, | 402 | file_with_fake_ident: SyntaxNode, |
308 | offset: TextSize, | 403 | offset: TextSize, |
309 | ) { | 404 | ) { |
310 | let (expected_type, expected_name) = { | 405 | let (expected_type, expected_name) = self.expected_type_and_name(); |
311 | let mut node = match self.token.parent() { | ||
312 | Some(it) => it, | ||
313 | None => return, | ||
314 | }; | ||
315 | loop { | ||
316 | break match_ast! { | ||
317 | match node { | ||
318 | ast::LetStmt(it) => { | ||
319 | cov_mark::hit!(expected_type_let_with_leading_char); | ||
320 | cov_mark::hit!(expected_type_let_without_leading_char); | ||
321 | let ty = it.pat() | ||
322 | .and_then(|pat| self.sema.type_of_pat(&pat)); | ||
323 | let name = if let Some(ast::Pat::IdentPat(ident)) = it.pat() { | ||
324 | ident.name().map(NameOrNameRef::Name) | ||
325 | } else { | ||
326 | None | ||
327 | }; | ||
328 | |||
329 | (ty, name) | ||
330 | }, | ||
331 | ast::ArgList(_it) => { | ||
332 | cov_mark::hit!(expected_type_fn_param_with_leading_char); | ||
333 | cov_mark::hit!(expected_type_fn_param_without_leading_char); | ||
334 | ActiveParameter::at_token( | ||
335 | &self.sema, | ||
336 | self.token.clone(), | ||
337 | ).map(|ap| { | ||
338 | let name = ap.ident().map(NameOrNameRef::Name); | ||
339 | (Some(ap.ty), name) | ||
340 | }) | ||
341 | .unwrap_or((None, None)) | ||
342 | }, | ||
343 | ast::RecordExprFieldList(_it) => { | ||
344 | cov_mark::hit!(expected_type_struct_field_without_leading_char); | ||
345 | self.token.prev_sibling_or_token() | ||
346 | .and_then(|se| se.into_node()) | ||
347 | .and_then(|node| ast::RecordExprField::cast(node)) | ||
348 | .and_then(|rf| self.sema.resolve_record_field(&rf).zip(Some(rf))) | ||
349 | .map(|(f, rf)|( | ||
350 | Some(f.0.signature_ty(self.db)), | ||
351 | rf.field_name().map(NameOrNameRef::NameRef), | ||
352 | )) | ||
353 | .unwrap_or((None, None)) | ||
354 | }, | ||
355 | ast::RecordExprField(it) => { | ||
356 | cov_mark::hit!(expected_type_struct_field_with_leading_char); | ||
357 | self.sema | ||
358 | .resolve_record_field(&it) | ||
359 | .map(|f|( | ||
360 | Some(f.0.signature_ty(self.db)), | ||
361 | it.field_name().map(NameOrNameRef::NameRef), | ||
362 | )) | ||
363 | .unwrap_or((None, None)) | ||
364 | }, | ||
365 | ast::MatchExpr(it) => { | ||
366 | cov_mark::hit!(expected_type_match_arm_without_leading_char); | ||
367 | let ty = it.expr() | ||
368 | .and_then(|e| self.sema.type_of_expr(&e)); | ||
369 | |||
370 | (ty, None) | ||
371 | }, | ||
372 | ast::IdentPat(it) => { | ||
373 | cov_mark::hit!(expected_type_if_let_with_leading_char); | ||
374 | cov_mark::hit!(expected_type_match_arm_with_leading_char); | ||
375 | let ty = self.sema.type_of_pat(&ast::Pat::from(it)); | ||
376 | |||
377 | (ty, None) | ||
378 | }, | ||
379 | ast::Fn(_it) => { | ||
380 | cov_mark::hit!(expected_type_fn_ret_with_leading_char); | ||
381 | cov_mark::hit!(expected_type_fn_ret_without_leading_char); | ||
382 | let ty = self.token.ancestors() | ||
383 | .find_map(|ancestor| ast::Expr::cast(ancestor)) | ||
384 | .and_then(|expr| self.sema.type_of_expr(&expr)); | ||
385 | |||
386 | (ty, None) | ||
387 | }, | ||
388 | _ => { | ||
389 | match node.parent() { | ||
390 | Some(n) => { | ||
391 | node = n; | ||
392 | continue; | ||
393 | }, | ||
394 | None => (None, None), | ||
395 | } | ||
396 | }, | ||
397 | } | ||
398 | }; | ||
399 | } | ||
400 | }; | ||
401 | self.expected_type = expected_type; | 406 | self.expected_type = expected_type; |
402 | self.expected_name = expected_name; | 407 | self.expected_name = expected_name; |
403 | self.attribute_under_caret = find_node_at_offset(&file_with_fake_ident, offset); | 408 | self.attribute_under_caret = find_node_at_offset(&file_with_fake_ident, offset); |
@@ -802,6 +807,7 @@ fn foo() { | |||
802 | 807 | ||
803 | #[test] | 808 | #[test] |
804 | fn expected_type_if_let_without_leading_char() { | 809 | fn expected_type_if_let_without_leading_char() { |
810 | cov_mark::check!(expected_type_if_let_without_leading_char); | ||
805 | check_expected_type_and_name( | 811 | check_expected_type_and_name( |
806 | r#" | 812 | r#" |
807 | enum Foo { Bar, Baz, Quux } | 813 | enum Foo { Bar, Baz, Quux } |
@@ -811,8 +817,8 @@ fn foo() { | |||
811 | if let $0 = f { } | 817 | if let $0 = f { } |
812 | } | 818 | } |
813 | "#, | 819 | "#, |
814 | expect![[r#"ty: (), name: ?"#]], | 820 | expect![[r#"ty: Foo, name: ?"#]], |
815 | ) // FIXME should be `ty: u32, name: ?` | 821 | ) |
816 | } | 822 | } |
817 | 823 | ||
818 | #[test] | 824 | #[test] |
@@ -840,8 +846,8 @@ fn foo() -> u32 { | |||
840 | $0 | 846 | $0 |
841 | } | 847 | } |
842 | "#, | 848 | "#, |
843 | expect![[r#"ty: (), name: ?"#]], | 849 | expect![[r#"ty: u32, name: ?"#]], |
844 | ) // FIXME this should be `ty: u32, name: ?` | 850 | ) |
845 | } | 851 | } |
846 | 852 | ||
847 | #[test] | 853 | #[test] |
@@ -856,4 +862,16 @@ fn foo() -> u32 { | |||
856 | expect![[r#"ty: u32, name: ?"#]], | 862 | expect![[r#"ty: u32, name: ?"#]], |
857 | ) | 863 | ) |
858 | } | 864 | } |
865 | |||
866 | #[test] | ||
867 | fn expected_type_fn_ret_fn_ref_fully_typed() { | ||
868 | check_expected_type_and_name( | ||
869 | r#" | ||
870 | fn foo() -> u32 { | ||
871 | foo$0 | ||
872 | } | ||
873 | "#, | ||
874 | expect![[r#"ty: u32, name: ?"#]], | ||
875 | ) | ||
876 | } | ||
859 | } | 877 | } |
diff --git a/crates/ide_completion/src/render/enum_variant.rs b/crates/ide_completion/src/render/enum_variant.rs index 832f5ced1..0c0c71134 100644 --- a/crates/ide_completion/src/render/enum_variant.rs +++ b/crates/ide_completion/src/render/enum_variant.rs | |||
@@ -93,7 +93,7 @@ impl<'a> EnumRender<'a> { | |||
93 | .variant | 93 | .variant |
94 | .fields(self.ctx.db()) | 94 | .fields(self.ctx.db()) |
95 | .into_iter() | 95 | .into_iter() |
96 | .map(|field| (field.name(self.ctx.db()), field.signature_ty(self.ctx.db()))); | 96 | .map(|field| (field.name(self.ctx.db()), field.ty(self.ctx.db()))); |
97 | 97 | ||
98 | match self.variant_kind { | 98 | match self.variant_kind { |
99 | StructKind::Tuple | StructKind::Unit => format!( | 99 | StructKind::Tuple | StructKind::Unit => format!( |