diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-02-17 10:54:32 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-02-17 10:54:32 +0000 |
commit | fcf15cc05afaeda6880664777ff2a3db342ea088 (patch) | |
tree | ac34e90a9884d7166daa5022ea402196483c26c0 /crates | |
parent | 334f53465f5baf5094844ab3ca2d28e477d07b24 (diff) | |
parent | 0e260aa6b15d9dc8c067adb05f3774aec3fb66ec (diff) |
Merge #3169
3169: Show record field names in Enum completion r=flodiebold a=adamrk
Adresses https://github.com/rust-analyzer/rust-analyzer/issues/2947.
Previously the details shown when autocompleting an Enum variant would look like the variant was a tuple even if it was a record:
![2020-02-16-15:59:32_crop](https://user-images.githubusercontent.com/16367467/74607233-64f21980-50d7-11ea-99db-e973e29c71d7.png)
This change will show the names of the fields for a record and use curly braces instead of parentheses:
![2020-02-16-15:33:00_crop](https://user-images.githubusercontent.com/16367467/74607251-8ce17d00-50d7-11ea-9d4d-38d198a4aec0.png)
This required exposing the type `adt::StructKind` from `ra_hir` and adding a function
```
kind(self, db: &impl HirDatabase) -> StructKind
```
in the `impl` of `EnumVariant`.
There was also a previously existing function `is_unit(self, db: &impl HirDatabase) -> bool` for `EnumVariant` which I removed because it seemed redundant after adding `kind`.
Co-authored-by: adamrk <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_def/src/adt.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 9 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/presentation.rs | 101 |
5 files changed, 111 insertions, 14 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index a56b8ab04..b6adb7589 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -3,6 +3,7 @@ use std::sync::Arc; | |||
3 | 3 | ||
4 | use either::Either; | 4 | use either::Either; |
5 | use hir_def::{ | 5 | use hir_def::{ |
6 | adt::StructKind, | ||
6 | adt::VariantData, | 7 | adt::VariantData, |
7 | builtin_type::BuiltinType, | 8 | builtin_type::BuiltinType, |
8 | docs::Documentation, | 9 | docs::Documentation, |
@@ -424,6 +425,10 @@ impl EnumVariant { | |||
424 | .collect() | 425 | .collect() |
425 | } | 426 | } |
426 | 427 | ||
428 | pub fn kind(self, db: &impl HirDatabase) -> StructKind { | ||
429 | self.variant_data(db).kind() | ||
430 | } | ||
431 | |||
427 | pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { | 432 | pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { |
428 | db.enum_data(self.parent.id).variants[self.id].variant_data.clone() | 433 | db.enum_data(self.parent.id).variants[self.id].variant_data.clone() |
429 | } | 434 | } |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 5cd965f7a..7a9745ebe 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -50,6 +50,7 @@ pub use crate::{ | |||
50 | }; | 50 | }; |
51 | 51 | ||
52 | pub use hir_def::{ | 52 | pub use hir_def::{ |
53 | adt::StructKind, | ||
53 | body::scope::ExprScopes, | 54 | body::scope::ExprScopes, |
54 | builtin_type::BuiltinType, | 55 | builtin_type::BuiltinType, |
55 | docs::Documentation, | 56 | docs::Documentation, |
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index aac5f3e15..985f409e8 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs | |||
@@ -140,10 +140,11 @@ impl VariantData { | |||
140 | self.fields().iter().find_map(|(id, data)| if &data.name == name { Some(id) } else { None }) | 140 | self.fields().iter().find_map(|(id, data)| if &data.name == name { Some(id) } else { None }) |
141 | } | 141 | } |
142 | 142 | ||
143 | pub fn is_unit(&self) -> bool { | 143 | pub fn kind(&self) -> StructKind { |
144 | match self { | 144 | match self { |
145 | VariantData::Unit => true, | 145 | VariantData::Record(_) => StructKind::Record, |
146 | _ => false, | 146 | VariantData::Tuple(_) => StructKind::Tuple, |
147 | VariantData::Unit => StructKind::Unit, | ||
147 | } | 148 | } |
148 | } | 149 | } |
149 | } | 150 | } |
@@ -173,7 +174,7 @@ impl HasChildSource for VariantId { | |||
173 | } | 174 | } |
174 | } | 175 | } |
175 | 176 | ||
176 | enum StructKind { | 177 | pub enum StructKind { |
177 | Tuple, | 178 | Tuple, |
178 | Record, | 179 | Record, |
179 | Unit, | 180 | Unit, |
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 6a2aded02..c2a3703fa 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -9,6 +9,7 @@ use std::iter; | |||
9 | use std::sync::Arc; | 9 | use std::sync::Arc; |
10 | 10 | ||
11 | use hir_def::{ | 11 | use hir_def::{ |
12 | adt::StructKind, | ||
12 | builtin_type::BuiltinType, | 13 | builtin_type::BuiltinType, |
13 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTarget}, | 14 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTarget}, |
14 | path::{GenericArg, Path, PathSegment, PathSegments}, | 15 | path::{GenericArg, Path, PathSegment, PathSegments}, |
@@ -805,8 +806,8 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> PolyFn | |||
805 | /// Build the type of a tuple struct constructor. | 806 | /// Build the type of a tuple struct constructor. |
806 | fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Binders<Ty> { | 807 | fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Binders<Ty> { |
807 | let struct_data = db.struct_data(def.into()); | 808 | let struct_data = db.struct_data(def.into()); |
808 | if struct_data.variant_data.is_unit() { | 809 | if let StructKind::Unit = struct_data.variant_data.kind() { |
809 | return type_for_adt(db, def.into()); // Unit struct | 810 | return type_for_adt(db, def.into()); |
810 | } | 811 | } |
811 | let generics = generics(db, def.into()); | 812 | let generics = generics(db, def.into()); |
812 | let substs = Substs::bound_vars(&generics); | 813 | let substs = Substs::bound_vars(&generics); |
@@ -830,8 +831,8 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId | |||
830 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Binders<Ty> { | 831 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Binders<Ty> { |
831 | let enum_data = db.enum_data(def.parent); | 832 | let enum_data = db.enum_data(def.parent); |
832 | let var_data = &enum_data.variants[def.local_id].variant_data; | 833 | let var_data = &enum_data.variants[def.local_id].variant_data; |
833 | if var_data.is_unit() { | 834 | if let StructKind::Unit = var_data.kind() { |
834 | return type_for_adt(db, def.parent.into()); // Unit variant | 835 | return type_for_adt(db, def.parent.into()); |
835 | } | 836 | } |
836 | let generics = generics(db, def.parent.into()); | 837 | let generics = generics(db, def.parent.into()); |
837 | let substs = Substs::bound_vars(&generics); | 838 | let substs = Substs::bound_vars(&generics); |
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 97475fc0b..1a3bcffae 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! This modules takes care of rendering various definitions as completion items. | 1 | //! This modules takes care of rendering various definitions as completion items. |
2 | 2 | ||
3 | use hir::{db::HirDatabase, Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, Type}; | 3 | use hir::{db::HirDatabase, Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, StructKind, Type}; |
4 | use join_to_string::join; | 4 | use join_to_string::join; |
5 | use ra_syntax::ast::NameOwner; | 5 | use ra_syntax::ast::NameOwner; |
6 | use test_utils::tested_by; | 6 | use test_utils::tested_by; |
@@ -268,11 +268,22 @@ impl Completions { | |||
268 | pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) { | 268 | pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) { |
269 | let is_deprecated = is_deprecated(variant, ctx.db); | 269 | let is_deprecated = is_deprecated(variant, ctx.db); |
270 | let name = variant.name(ctx.db); | 270 | let name = variant.name(ctx.db); |
271 | let detail_types = variant.fields(ctx.db).into_iter().map(|field| field.ty(ctx.db)); | 271 | let detail_types = |
272 | let detail = join(detail_types.map(|t| t.display(ctx.db).to_string())) | 272 | variant.fields(ctx.db).into_iter().map(|field| (field.name(ctx.db), field.ty(ctx.db))); |
273 | .separator(", ") | 273 | let detail = match variant.kind(ctx.db) { |
274 | .surround_with("(", ")") | 274 | StructKind::Tuple | StructKind::Unit => { |
275 | .to_string(); | 275 | join(detail_types.map(|(_, t)| t.display(ctx.db).to_string())) |
276 | .separator(", ") | ||
277 | .surround_with("(", ")") | ||
278 | .to_string() | ||
279 | } | ||
280 | StructKind::Record => { | ||
281 | join(detail_types.map(|(n, t)| format!("{}: {}", n, t.display(ctx.db).to_string()))) | ||
282 | .separator(", ") | ||
283 | .surround_with("{ ", " }") | ||
284 | .to_string() | ||
285 | } | ||
286 | }; | ||
276 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) | 287 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) |
277 | .kind(CompletionItemKind::EnumVariant) | 288 | .kind(CompletionItemKind::EnumVariant) |
278 | .set_documentation(variant.docs(ctx.db)) | 289 | .set_documentation(variant.docs(ctx.db)) |
@@ -298,6 +309,84 @@ mod tests { | |||
298 | } | 309 | } |
299 | 310 | ||
300 | #[test] | 311 | #[test] |
312 | fn enum_detail_includes_names_for_record() { | ||
313 | assert_debug_snapshot!( | ||
314 | do_reference_completion( | ||
315 | r#" | ||
316 | enum Foo { | ||
317 | Foo {x: i32, y: i32} | ||
318 | } | ||
319 | |||
320 | fn main() { Foo::Fo<|> } | ||
321 | "#, | ||
322 | ), | ||
323 | @r###" | ||
324 | [ | ||
325 | CompletionItem { | ||
326 | label: "Foo", | ||
327 | source_range: [121; 123), | ||
328 | delete: [121; 123), | ||
329 | insert: "Foo", | ||
330 | kind: EnumVariant, | ||
331 | detail: "{ x: i32, y: i32 }", | ||
332 | }, | ||
333 | ]"### | ||
334 | ); | ||
335 | } | ||
336 | |||
337 | #[test] | ||
338 | fn enum_detail_doesnt_include_names_for_tuple() { | ||
339 | assert_debug_snapshot!( | ||
340 | do_reference_completion( | ||
341 | r#" | ||
342 | enum Foo { | ||
343 | Foo (i32, i32) | ||
344 | } | ||
345 | |||
346 | fn main() { Foo::Fo<|> } | ||
347 | "#, | ||
348 | ), | ||
349 | @r###" | ||
350 | [ | ||
351 | CompletionItem { | ||
352 | label: "Foo", | ||
353 | source_range: [115; 117), | ||
354 | delete: [115; 117), | ||
355 | insert: "Foo", | ||
356 | kind: EnumVariant, | ||
357 | detail: "(i32, i32)", | ||
358 | }, | ||
359 | ]"### | ||
360 | ); | ||
361 | } | ||
362 | |||
363 | #[test] | ||
364 | fn enum_detail_just_parentheses_for_unit() { | ||
365 | assert_debug_snapshot!( | ||
366 | do_reference_completion( | ||
367 | r#" | ||
368 | enum Foo { | ||
369 | Foo | ||
370 | } | ||
371 | |||
372 | fn main() { Foo::Fo<|> } | ||
373 | "#, | ||
374 | ), | ||
375 | @r###" | ||
376 | [ | ||
377 | CompletionItem { | ||
378 | label: "Foo", | ||
379 | source_range: [104; 106), | ||
380 | delete: [104; 106), | ||
381 | insert: "Foo", | ||
382 | kind: EnumVariant, | ||
383 | detail: "()", | ||
384 | }, | ||
385 | ]"### | ||
386 | ); | ||
387 | } | ||
388 | |||
389 | #[test] | ||
301 | fn sets_deprecated_flag_in_completion_items() { | 390 | fn sets_deprecated_flag_in_completion_items() { |
302 | assert_debug_snapshot!( | 391 | assert_debug_snapshot!( |
303 | do_reference_completion( | 392 | do_reference_completion( |