Skip to content

Commit fcf15cc

Browse files
bors[bot]adamrk
andauthored
Merge #3169
3169: Show record field names in Enum completion r=flodiebold a=adamrk Adresses #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]>
2 parents 334f534 + 0e260aa commit fcf15cc

File tree

5 files changed

+111
-14
lines changed

5 files changed

+111
-14
lines changed

crates/ra_hir/src/code_model.rs

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::sync::Arc;
33

44
use either::Either;
55
use hir_def::{
6+
adt::StructKind,
67
adt::VariantData,
78
builtin_type::BuiltinType,
89
docs::Documentation,
@@ -424,6 +425,10 @@ impl EnumVariant {
424425
.collect()
425426
}
426427

428+
pub fn kind(self, db: &impl HirDatabase) -> StructKind {
429+
self.variant_data(db).kind()
430+
}
431+
427432
pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
428433
db.enum_data(self.parent.id).variants[self.id].variant_data.clone()
429434
}

crates/ra_hir/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ pub use crate::{
5050
};
5151

5252
pub use hir_def::{
53+
adt::StructKind,
5354
body::scope::ExprScopes,
5455
builtin_type::BuiltinType,
5556
docs::Documentation,

crates/ra_hir_def/src/adt.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,11 @@ impl VariantData {
140140
self.fields().iter().find_map(|(id, data)| if &data.name == name { Some(id) } else { None })
141141
}
142142

143-
pub fn is_unit(&self) -> bool {
143+
pub fn kind(&self) -> StructKind {
144144
match self {
145-
VariantData::Unit => true,
146-
_ => false,
145+
VariantData::Record(_) => StructKind::Record,
146+
VariantData::Tuple(_) => StructKind::Tuple,
147+
VariantData::Unit => StructKind::Unit,
147148
}
148149
}
149150
}
@@ -173,7 +174,7 @@ impl HasChildSource for VariantId {
173174
}
174175
}
175176

176-
enum StructKind {
177+
pub enum StructKind {
177178
Tuple,
178179
Record,
179180
Unit,

crates/ra_hir_ty/src/lower.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::iter;
99
use std::sync::Arc;
1010

1111
use hir_def::{
12+
adt::StructKind,
1213
builtin_type::BuiltinType,
1314
generics::{TypeParamProvenance, WherePredicate, WherePredicateTarget},
1415
path::{GenericArg, Path, PathSegment, PathSegments},
@@ -805,8 +806,8 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> PolyFn
805806
/// Build the type of a tuple struct constructor.
806807
fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Binders<Ty> {
807808
let struct_data = db.struct_data(def.into());
808-
if struct_data.variant_data.is_unit() {
809-
return type_for_adt(db, def.into()); // Unit struct
809+
if let StructKind::Unit = struct_data.variant_data.kind() {
810+
return type_for_adt(db, def.into());
810811
}
811812
let generics = generics(db, def.into());
812813
let substs = Substs::bound_vars(&generics);
@@ -830,8 +831,8 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId
830831
fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Binders<Ty> {
831832
let enum_data = db.enum_data(def.parent);
832833
let var_data = &enum_data.variants[def.local_id].variant_data;
833-
if var_data.is_unit() {
834-
return type_for_adt(db, def.parent.into()); // Unit variant
834+
if let StructKind::Unit = var_data.kind() {
835+
return type_for_adt(db, def.parent.into());
835836
}
836837
let generics = generics(db, def.parent.into());
837838
let substs = Substs::bound_vars(&generics);

crates/ra_ide/src/completion/presentation.rs

+95-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! This modules takes care of rendering various definitions as completion items.
22
3-
use hir::{db::HirDatabase, Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, Type};
3+
use hir::{db::HirDatabase, Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, StructKind, Type};
44
use join_to_string::join;
55
use ra_syntax::ast::NameOwner;
66
use test_utils::tested_by;
@@ -268,11 +268,22 @@ impl Completions {
268268
pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) {
269269
let is_deprecated = is_deprecated(variant, ctx.db);
270270
let name = variant.name(ctx.db);
271-
let detail_types = variant.fields(ctx.db).into_iter().map(|field| field.ty(ctx.db));
272-
let detail = join(detail_types.map(|t| t.display(ctx.db).to_string()))
273-
.separator(", ")
274-
.surround_with("(", ")")
275-
.to_string();
271+
let detail_types =
272+
variant.fields(ctx.db).into_iter().map(|field| (field.name(ctx.db), field.ty(ctx.db)));
273+
let detail = match variant.kind(ctx.db) {
274+
StructKind::Tuple | StructKind::Unit => {
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+
};
276287
CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string())
277288
.kind(CompletionItemKind::EnumVariant)
278289
.set_documentation(variant.docs(ctx.db))
@@ -297,6 +308,84 @@ mod tests {
297308
do_completion(code, CompletionKind::Reference)
298309
}
299310

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+
300389
#[test]
301390
fn sets_deprecated_flag_in_completion_items() {
302391
assert_debug_snapshot!(

0 commit comments

Comments
 (0)