diff options
Diffstat (limited to 'crates/ra_ide_api/src/completion/complete_struct_literal.rs')
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_struct_literal.rs | 103 |
1 files changed, 88 insertions, 15 deletions
diff --git a/crates/ra_ide_api/src/completion/complete_struct_literal.rs b/crates/ra_ide_api/src/completion/complete_struct_literal.rs index 35fb21113..b6216f857 100644 --- a/crates/ra_ide_api/src/completion/complete_struct_literal.rs +++ b/crates/ra_ide_api/src/completion/complete_struct_literal.rs | |||
@@ -1,28 +1,24 @@ | |||
1 | use hir::AdtDef; | 1 | use hir::{Substs, Ty}; |
2 | 2 | ||
3 | use crate::completion::{CompletionContext, Completions}; | 3 | use crate::completion::{CompletionContext, Completions}; |
4 | 4 | ||
5 | /// Complete fields in fields literals. | 5 | /// Complete fields in fields literals. |
6 | pub(super) fn complete_struct_literal(acc: &mut Completions, ctx: &CompletionContext) { | 6 | pub(super) fn complete_struct_literal(acc: &mut Completions, ctx: &CompletionContext) { |
7 | let ty = match ctx.struct_lit_syntax.and_then(|it| ctx.analyzer.type_of(ctx.db, it.into())) { | 7 | let (ty, variant) = match ctx.struct_lit_syntax.and_then(|it| { |
8 | Some((ctx.analyzer.type_of(ctx.db, it.into())?, ctx.analyzer.resolve_variant(it)?)) | ||
9 | }) { | ||
8 | Some(it) => it, | 10 | Some(it) => it, |
9 | None => return, | ||
10 | }; | ||
11 | let (adt, substs) = match ty.as_adt() { | ||
12 | Some(res) => res, | ||
13 | _ => return, | 11 | _ => return, |
14 | }; | 12 | }; |
15 | match adt { | ||
16 | AdtDef::Struct(s) => { | ||
17 | for field in s.fields(ctx.db) { | ||
18 | acc.add_field(ctx, field, substs); | ||
19 | } | ||
20 | } | ||
21 | 13 | ||
22 | // FIXME unions | 14 | let ty_substs = match ty { |
23 | AdtDef::Union(_) => (), | 15 | Ty::Apply(it) => it.parameters, |
24 | AdtDef::Enum(_) => (), | 16 | _ => Substs::empty(), |
25 | }; | 17 | }; |
18 | |||
19 | for field in variant.fields(ctx.db) { | ||
20 | acc.add_field(ctx, field, &ty_substs); | ||
21 | } | ||
26 | } | 22 | } |
27 | 23 | ||
28 | #[cfg(test)] | 24 | #[cfg(test)] |
@@ -57,4 +53,81 @@ mod tests { | |||
57 | ⋮] | 53 | ⋮] |
58 | "###); | 54 | "###); |
59 | } | 55 | } |
56 | |||
57 | #[test] | ||
58 | fn test_struct_literal_enum_variant() { | ||
59 | let completions = complete( | ||
60 | r" | ||
61 | enum E { | ||
62 | A { a: u32 } | ||
63 | } | ||
64 | fn foo() { | ||
65 | let _ = E::A { <|> } | ||
66 | } | ||
67 | ", | ||
68 | ); | ||
69 | assert_debug_snapshot_matches!(completions, @r###" | ||
70 | ⋮[ | ||
71 | ⋮ CompletionItem { | ||
72 | ⋮ label: "a", | ||
73 | ⋮ source_range: [119; 119), | ||
74 | ⋮ delete: [119; 119), | ||
75 | ⋮ insert: "a", | ||
76 | ⋮ kind: Field, | ||
77 | ⋮ detail: "u32", | ||
78 | ⋮ }, | ||
79 | ⋮] | ||
80 | "###); | ||
81 | } | ||
82 | |||
83 | #[test] | ||
84 | fn test_struct_literal_two_structs() { | ||
85 | let completions = complete( | ||
86 | r" | ||
87 | struct A { a: u32 } | ||
88 | struct B { b: u32 } | ||
89 | |||
90 | fn foo() { | ||
91 | let _: A = B { <|> } | ||
92 | } | ||
93 | ", | ||
94 | ); | ||
95 | assert_debug_snapshot_matches!(completions, @r###" | ||
96 | ⋮[ | ||
97 | ⋮ CompletionItem { | ||
98 | ⋮ label: "b", | ||
99 | ⋮ source_range: [119; 119), | ||
100 | ⋮ delete: [119; 119), | ||
101 | ⋮ insert: "b", | ||
102 | ⋮ kind: Field, | ||
103 | ⋮ detail: "u32", | ||
104 | ⋮ }, | ||
105 | ⋮] | ||
106 | "###); | ||
107 | } | ||
108 | |||
109 | #[test] | ||
110 | fn test_struct_literal_generic_struct() { | ||
111 | let completions = complete( | ||
112 | r" | ||
113 | struct A<T> { a: T } | ||
114 | |||
115 | fn foo() { | ||
116 | let _: A<u32> = A { <|> } | ||
117 | } | ||
118 | ", | ||
119 | ); | ||
120 | assert_debug_snapshot_matches!(completions, @r###" | ||
121 | ⋮[ | ||
122 | ⋮ CompletionItem { | ||
123 | ⋮ label: "a", | ||
124 | ⋮ source_range: [93; 93), | ||
125 | ⋮ delete: [93; 93), | ||
126 | ⋮ insert: "a", | ||
127 | ⋮ kind: Field, | ||
128 | ⋮ detail: "u32", | ||
129 | ⋮ }, | ||
130 | ⋮] | ||
131 | "###); | ||
132 | } | ||
60 | } | 133 | } |