From 2a22cf8efca9cdf70dc849f974f9ee858171853e Mon Sep 17 00:00:00 2001 From: Morgan Thomas Date: Fri, 11 Mar 2022 18:26:01 -0800 Subject: [PATCH] Complete enum variants identically to structures. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In particular: - unit variants now display in the menu as "Variant", complete to "Variant", and display a detail of "Variant" (was "()") - tuple variants now display in the menu as "Variant(…)", complete to "Variant(${1:()})$0" (was "Variant($0)"), and display a detail of "Variant(type)" (was "(type)") - record variants now display in the menu as "Variant {…}", complete to "Variant { x: ${1:()} }$0" (was "Variant"), and display a detail of "Variant { x: type }" (was "{x: type}") This behavior is identical to that of struct completions. In addition, tuple variants no longer set triggers_call_info, as to my understanding it's unnecessary now that we're emitting placeholders. Tests have been updated to match, and the render::enum_variant::tests::inserts_parens_for_tuple_enums test has been removed entirely as it's covered by other tests (render::enum_detail_includes_{record, tuple}_fields, render::enum_detail_just_name_for_unit, render::pattern::enum_qualified). --- .../src/completions/qualified_path.rs | 6 +- crates/ide_completion/src/render.rs | 35 ++++--- .../ide_completion/src/render/builder_ext.rs | 1 + .../ide_completion/src/render/enum_variant.rs | 95 ++++++++----------- crates/ide_completion/src/tests/expression.rs | 12 +-- crates/ide_completion/src/tests/pattern.rs | 8 +- crates/ide_completion/src/tests/use_tree.rs | 2 +- 7 files changed, 69 insertions(+), 90 deletions(-) diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs index acd02616b1..86b1f534b2 100644 --- a/crates/ide_completion/src/completions/qualified_path.rs +++ b/crates/ide_completion/src/completions/qualified_path.rs @@ -580,8 +580,8 @@ impl Foo { } "#, expect![[r#" - ev Bar () - ev Baz () + ev Bar Bar + ev Baz Baz me foo(…) fn(self) "#]], ); @@ -626,7 +626,7 @@ fn main() { } "#, expect![[r#" - ev Bar () + ev Bar Bar "#]], ); } diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs index 8003d200f9..e8ebb3e337 100644 --- a/crates/ide_completion/src/render.rs +++ b/crates/ide_completion/src/render.rs @@ -429,14 +429,14 @@ fn main() { Foo::Fo$0 } expect![[r#" [ CompletionItem { - label: "Foo", + label: "Foo {…}", source_range: 54..56, delete: 54..56, - insert: "Foo", + insert: "Foo { x: ${1:()}, y: ${2:()} }$0", kind: SymbolKind( Variant, ), - detail: "{x: i32, y: i32}", + detail: "Foo { x: i32, y: i32 }", }, ] "#]], @@ -444,7 +444,7 @@ fn main() { Foo::Fo$0 } } #[test] - fn enum_detail_doesnt_include_tuple_fields() { + fn enum_detail_includes_tuple_fields() { check( r#" enum Foo { Foo (i32, i32) } @@ -458,13 +458,11 @@ fn main() { Foo::Fo$0 } label: "Foo(…)", source_range: 46..48, delete: 46..48, - insert: "Foo($0)", + insert: "Foo(${1:()}, ${2:()})$0", kind: SymbolKind( Variant, ), - lookup: "Foo", - detail: "(i32, i32)", - trigger_call_info: true, + detail: "Foo(i32, i32)", }, ] "#]], @@ -511,7 +509,7 @@ fn main() { fo$0 } } #[test] - fn enum_detail_just_parentheses_for_unit() { + fn enum_detail_just_name_for_unit() { check( r#" enum Foo { Foo } @@ -525,11 +523,11 @@ fn main() { Foo::Fo$0 } label: "Foo", source_range: 35..37, delete: 35..37, - insert: "Foo", + insert: "Foo$0", kind: SymbolKind( Variant, ), - detail: "()", + detail: "Foo", }, ] "#]], @@ -573,15 +571,15 @@ fn main() { let _: m::Spam = S$0 } ), }, CompletionItem { - label: "Spam::Bar(…)", + label: "m::Spam::Bar(…)", source_range: 75..76, delete: 75..76, - insert: "Spam::Bar($0)", + insert: "m::Spam::Bar(${1:()})$0", kind: SymbolKind( Variant, ), lookup: "Spam::Bar", - detail: "(i32)", + detail: "m::Spam::Bar(i32)", relevance: CompletionRelevance { exact_name_match: false, type_match: Some( @@ -592,18 +590,17 @@ fn main() { let _: m::Spam = S$0 } is_private_editable: false, exact_postfix_snippet_match: false, }, - trigger_call_info: true, }, CompletionItem { label: "m::Spam::Foo", source_range: 75..76, delete: 75..76, - insert: "m::Spam::Foo", + insert: "m::Spam::Foo$0", kind: SymbolKind( Variant, ), lookup: "Spam::Foo", - detail: "()", + detail: "m::Spam::Foo", relevance: CompletionRelevance { exact_name_match: false, type_match: Some( @@ -788,11 +785,11 @@ use self::E::*; label: "V", source_range: 10..12, delete: 10..12, - insert: "V", + insert: "V$0", kind: SymbolKind( Variant, ), - detail: "()", + detail: "V", documentation: Documentation( "variant docs", ), diff --git a/crates/ide_completion/src/render/builder_ext.rs b/crates/ide_completion/src/render/builder_ext.rs index 653515fec2..70767a2a9c 100644 --- a/crates/ide_completion/src/render/builder_ext.rs +++ b/crates/ide_completion/src/render/builder_ext.rs @@ -8,6 +8,7 @@ use crate::{context::PathKind, item::Builder, patterns::ImmediateLocation, Compl #[derive(Debug)] pub(super) enum Params { Named(Option, Vec), + #[allow(dead_code)] Anonymous(usize), } diff --git a/crates/ide_completion/src/render/enum_variant.rs b/crates/ide_completion/src/render/enum_variant.rs index 914ace910d..6f358bfd4c 100644 --- a/crates/ide_completion/src/render/enum_variant.rs +++ b/crates/ide_completion/src/render/enum_variant.rs @@ -1,13 +1,15 @@ //! Renderer for `enum` variants. -use hir::{db::HirDatabase, HasAttrs, HirDisplay, StructKind}; +use hir::{HasAttrs, StructKind}; use ide_db::SymbolKind; -use itertools::Itertools; use syntax::SmolStr; use crate::{ item::{CompletionItem, ImportEdit}, - render::{builder_ext::Params, compute_ref_match, compute_type_match, RenderContext}, + render::{ + compound::{render_record, render_tuple, RenderedCompound}, + compute_ref_match, compute_type_match, RenderContext, + }, CompletionRelevance, }; @@ -46,20 +48,46 @@ fn render( let qualified_name = qualified_name.to_string(); let short_qualified_name: SmolStr = short_qualified_name.to_string().into(); - let mut item = CompletionItem::new(SymbolKind::Variant, ctx.source_range(), qualified_name); + let mut rendered = match variant_kind { + StructKind::Tuple => { + render_tuple(db, ctx.snippet_cap(), &variant.fields(db), Some(&qualified_name)) + } + StructKind::Record => { + render_record(db, ctx.snippet_cap(), &variant.fields(db), Some(&qualified_name)) + } + StructKind::Unit => { + RenderedCompound { literal: qualified_name.clone(), detail: qualified_name.clone() } + } + }; + + if ctx.snippet_cap().is_some() { + rendered.literal.push_str("$0"); + } + + let mut item = CompletionItem::new( + SymbolKind::Variant, + ctx.source_range(), + match variant_kind { + StructKind::Tuple => SmolStr::from_iter([&qualified_name, "(…)"]), + StructKind::Record => SmolStr::from_iter([&qualified_name, " {…}"]), + StructKind::Unit => qualified_name.into(), + }, + ); + item.set_documentation(variant.docs(db)) .set_deprecated(ctx.is_deprecated(variant)) - .detail(detail(db, variant, variant_kind)); + .detail(rendered.detail); + + match ctx.snippet_cap() { + Some(snippet_cap) => item.insert_snippet(snippet_cap, rendered.literal), + None => item.insert_text(rendered.literal), + }; if let Some(import_to_add) = import_to_add { item.add_import(import_to_add); } - if variant_kind == hir::StructKind::Tuple { - cov_mark::hit!(inserts_parens_for_tuple_enums); - let params = Params::Anonymous(variant.fields(db).len()); - item.add_call_parens(completion, short_qualified_name, params); - } else if qualified { + if qualified { item.lookup_by(short_qualified_name); } @@ -75,50 +103,3 @@ fn render( item.build() } - -fn detail(db: &dyn HirDatabase, variant: hir::Variant, variant_kind: StructKind) -> String { - let detail_types = variant.fields(db).into_iter().map(|field| (field.name(db), field.ty(db))); - - match variant_kind { - hir::StructKind::Tuple | hir::StructKind::Unit => { - format!("({})", detail_types.format_with(", ", |(_, t), f| f(&t.display(db)))) - } - hir::StructKind::Record => { - format!( - "{{{}}}", - detail_types.format_with(", ", |(n, t), f| { - f(&n)?; - f(&": ")?; - f(&t.display(db)) - }), - ) - } - } -} - -#[cfg(test)] -mod tests { - use crate::tests::check_edit; - - #[test] - fn inserts_parens_for_tuple_enums() { - cov_mark::check!(inserts_parens_for_tuple_enums); - check_edit( - "Some", - r#" -enum Option { Some(T), None } -use Option::*; -fn main() -> Option { - Som$0 -} -"#, - r#" -enum Option { Some(T), None } -use Option::*; -fn main() -> Option { - Some($0) -} -"#, - ); - } -} diff --git a/crates/ide_completion/src/tests/expression.rs b/crates/ide_completion/src/tests/expression.rs index a841605e49..bb8b34b79a 100644 --- a/crates/ide_completion/src/tests/expression.rs +++ b/crates/ide_completion/src/tests/expression.rs @@ -61,7 +61,7 @@ fn baz() { fn function() fn() sc STATIC un Union - ev TupleV(…) (u32) + ev TupleV(…) TupleV(u32) ct CONST "#]], ) @@ -171,7 +171,7 @@ impl Unit { fn function() fn() sc STATIC un Union - ev TupleV(…) (u32) + ev TupleV(…) TupleV(u32) ct CONST "#]], ); @@ -200,7 +200,7 @@ impl Unit { fn function() fn() sc STATIC un Union - ev TupleV(…) (u32) + ev TupleV(…) TupleV(u32) ct CONST "#]], ); @@ -543,9 +543,9 @@ fn func() { } "#, expect![[r#" - ev TupleV(…) (u32) - ev RecordV {field: u32} - ev UnitV () + ev TupleV(…) TupleV(u32) + ev RecordV {…} RecordV { field: u32 } + ev UnitV UnitV ct ASSOC_CONST const ASSOC_CONST: () fn assoc_fn() fn() ta AssocType type AssocType = () diff --git a/crates/ide_completion/src/tests/pattern.rs b/crates/ide_completion/src/tests/pattern.rs index 0ca20f93b5..7767f24632 100644 --- a/crates/ide_completion/src/tests/pattern.rs +++ b/crates/ide_completion/src/tests/pattern.rs @@ -218,7 +218,7 @@ fn foo() { expect![[r#" kw ref kw mut - ev E::X () + ev E::X E::X en E ma m!(…) macro_rules! m "#]], @@ -291,9 +291,9 @@ fn func() { } "#, expect![[r#" - ev TupleV(…) (u32) - ev RecordV {field: u32} - ev UnitV () + ev TupleV(…) TupleV(u32) + ev RecordV {…} RecordV { field: u32 } + ev UnitV UnitV "#]], ); } diff --git a/crates/ide_completion/src/tests/use_tree.rs b/crates/ide_completion/src/tests/use_tree.rs index 73cb83957f..ca06cc376f 100644 --- a/crates/ide_completion/src/tests/use_tree.rs +++ b/crates/ide_completion/src/tests/use_tree.rs @@ -167,7 +167,7 @@ impl Foo { } "#, expect![[r#" - ev Variant () + ev Variant Variant "#]], ); }