aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/code_model.rs5
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir_def/src/adt.rs9
-rw-r--r--crates/ra_hir_ty/src/lower.rs9
-rw-r--r--crates/ra_ide/src/completion/presentation.rs101
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
4use either::Either; 4use either::Either;
5use hir_def::{ 5use 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
52pub use hir_def::{ 52pub 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
176enum StructKind { 177pub 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;
9use std::sync::Arc; 9use std::sync::Arc;
10 10
11use hir_def::{ 11use 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.
806fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Binders<Ty> { 807fn 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
830fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Binders<Ty> { 831fn 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
3use hir::{db::HirDatabase, Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, Type}; 3use hir::{db::HirDatabase, Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, StructKind, Type};
4use join_to_string::join; 4use join_to_string::join;
5use ra_syntax::ast::NameOwner; 5use ra_syntax::ast::NameOwner;
6use test_utils::tested_by; 6use 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(