From d69a81fddbbe3c06c135ca7ae596ffc02b24cf8e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 16 Mar 2024 17:49:59 +0100 Subject: [PATCH] fix: Fix wrong where clause rendering on hover --- crates/hir/src/display.rs | 90 +++++++------ crates/ide/src/hover/tests.rs | 230 ++++++++++++++++++++++++---------- 2 files changed, 211 insertions(+), 109 deletions(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index cdc0db8653c..c5d44c11f2c 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -159,6 +159,7 @@ impl HirDisplay for Adt { impl HirDisplay for Struct { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { let module_id = self.module(f.db).id; + // FIXME: Render repr if its set explicitly? write_visibility(module_id, self.visibility(f.db), f)?; f.write_str("struct ")?; write!(f, "{}", self.name(f.db).display(f.db.upcast()))?; @@ -166,37 +167,40 @@ impl HirDisplay for Struct { write_generic_params(def_id, f)?; let variant_data = self.variant_data(f.db); - if let StructKind::Tuple = variant_data.kind() { - f.write_char('(')?; - let mut it = variant_data.fields().iter().peekable(); + match variant_data.kind() { + StructKind::Tuple => { + f.write_char('(')?; + let mut it = variant_data.fields().iter().peekable(); - while let Some((id, _)) = it.next() { - let field = Field { parent: (*self).into(), id }; - write_visibility(module_id, field.visibility(f.db), f)?; - field.ty(f.db).hir_fmt(f)?; - if it.peek().is_some() { - f.write_str(", ")?; + while let Some((id, _)) = it.next() { + let field = Field { parent: (*self).into(), id }; + write_visibility(module_id, field.visibility(f.db), f)?; + field.ty(f.db).hir_fmt(f)?; + if it.peek().is_some() { + f.write_str(", ")?; + } + } + + f.write_char(')')?; + write_where_clause(def_id, f)?; + } + StructKind::Record => { + let has_where_clause = write_where_clause(def_id, f)?; + let fields = self.fields(f.db); + f.write_char(if !has_where_clause { ' ' } else { '\n' })?; + if fields.is_empty() { + f.write_str("{}")?; + } else { + f.write_str("{\n")?; + for field in self.fields(f.db) { + f.write_str(" ")?; + field.hir_fmt(f)?; + f.write_str(",\n")?; + } + f.write_str("}")?; } } - - f.write_str(");")?; - } - - write_where_clause(def_id, f)?; - - if let StructKind::Record = variant_data.kind() { - let fields = self.fields(f.db); - if fields.is_empty() { - f.write_str(" {}")?; - } else { - f.write_str(" {\n")?; - for field in self.fields(f.db) { - f.write_str(" ")?; - field.hir_fmt(f)?; - f.write_str(",\n")?; - } - f.write_str("}")?; - } + StructKind::Unit => _ = write_where_clause(def_id, f)?, } Ok(()) @@ -210,11 +214,12 @@ impl HirDisplay for Enum { write!(f, "{}", self.name(f.db).display(f.db.upcast()))?; let def_id = GenericDefId::AdtId(AdtId::EnumId(self.id)); write_generic_params(def_id, f)?; - write_where_clause(def_id, f)?; + let has_where_clause = write_where_clause(def_id, f)?; let variants = self.variants(f.db); if !variants.is_empty() { - f.write_str(" {\n")?; + f.write_char(if !has_where_clause { ' ' } else { '\n' })?; + f.write_str("{\n")?; for variant in variants { f.write_str(" ")?; variant.hir_fmt(f)?; @@ -234,11 +239,12 @@ impl HirDisplay for Union { write!(f, "{}", self.name(f.db).display(f.db.upcast()))?; let def_id = GenericDefId::AdtId(AdtId::UnionId(self.id)); write_generic_params(def_id, f)?; - write_where_clause(def_id, f)?; + let has_where_clause = write_where_clause(def_id, f)?; let fields = self.fields(f.db); if !fields.is_empty() { - f.write_str(" {\n")?; + f.write_char(if !has_where_clause { ' ' } else { '\n' })?; + f.write_str("{\n")?; for field in self.fields(f.db) { f.write_str(" ")?; field.hir_fmt(f)?; @@ -446,7 +452,10 @@ fn write_generic_params( Ok(()) } -fn write_where_clause(def: GenericDefId, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { +fn write_where_clause( + def: GenericDefId, + f: &mut HirFormatter<'_>, +) -> Result { let params = f.db.generic_params(def); // unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`. @@ -465,7 +474,7 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter<'_>) -> Result<(), }); if !has_displayable_predicate { - return Ok(()); + return Ok(false); } let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter<'_>| match target { @@ -543,7 +552,7 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter<'_>) -> Result<(), // End of final predicate. There must be at least one predicate here. f.write_char(',')?; - Ok(()) + Ok(true) } impl HirDisplay for Const { @@ -594,19 +603,20 @@ impl HirDisplay for Trait { write!(f, "trait {}", data.name.display(f.db.upcast()))?; let def_id = GenericDefId::TraitId(self.id); write_generic_params(def_id, f)?; - write_where_clause(def_id, f)?; + let has_where_clause = write_where_clause(def_id, f)?; if let Some(limit) = f.entity_limit { let assoc_items = self.items(f.db); let count = assoc_items.len().min(limit); + f.write_char(if !has_where_clause { ' ' } else { '\n' })?; if count == 0 { if assoc_items.is_empty() { - f.write_str(" {}")?; + f.write_str("{}")?; } else { - f.write_str(" { /* … */ }")?; + f.write_str("{ /* … */ }")?; } } else { - f.write_str(" {\n")?; + f.write_str("{\n")?; for item in &assoc_items[..count] { f.write_str(" ")?; match item { @@ -651,7 +661,6 @@ impl HirDisplay for TypeAlias { write!(f, "type {}", data.name.display(f.db.upcast()))?; let def_id = GenericDefId::TypeAliasId(self.id); write_generic_params(def_id, f)?; - write_where_clause(def_id, f)?; if !data.bounds.is_empty() { f.write_str(": ")?; f.write_joined(data.bounds.iter(), " + ")?; @@ -660,6 +669,7 @@ impl HirDisplay for TypeAlias { f.write_str(" = ")?; ty.hir_fmt(f)?; } + write_where_clause(def_id, f)?; Ok(()) } } diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 051a96233a0..4451e31870f 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -819,7 +819,7 @@ fn foo(foo: Foo) { fn hover_tuple_struct() { check( r#" -struct Foo$0(pub u32) +struct Foo$0(pub u32) where u32: Copy; "#, expect![[r#" *Foo* @@ -830,7 +830,99 @@ struct Foo$0(pub u32) ```rust // size = 4, align = 4 - struct Foo(pub u32); + struct Foo(pub u32) + where + u32: Copy, + ``` + "#]], + ); +} + +#[test] +fn hover_record_struct() { + check( + r#" +struct Foo$0 { field: u32 } +"#, + expect![[r#" + *Foo* + + ```rust + test + ``` + + ```rust + // size = 4, align = 4 + struct Foo { + field: u32, + } + ``` + "#]], + ); + check( + r#" +struct Foo$0 where u32: Copy { field: u32 } +"#, + expect![[r#" + *Foo* + + ```rust + test + ``` + + ```rust + // size = 4, align = 4 + struct Foo + where + u32: Copy, + { + field: u32, + } + ``` + "#]], + ); +} + +#[test] +fn hover_unit_struct() { + check( + r#" +struct Foo$0 where u32: Copy; +"#, + expect![[r#" + *Foo* + + ```rust + test + ``` + + ```rust + // size = 0, align = 1 + struct Foo + where + u32: Copy, + ``` + "#]], + ); +} + +#[test] +fn hover_type_alias() { + check( + r#" +type Fo$0o: Trait = S where T: Trait; +"#, + expect![[r#" + *Foo* + + ```rust + test + ``` + + ```rust + type Foo: Trait = S + where + T: Trait, ``` "#]], ); @@ -2540,7 +2632,7 @@ fn main() { let s$0t = S{ f1:Arg(0) }; } focus_range: 7..10, name: "Arg", kind: Struct, - description: "struct Arg(u32);", + description: "struct Arg(u32)", }, }, HoverGotoTypeData { @@ -2599,7 +2691,7 @@ fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; } focus_range: 7..10, name: "Arg", kind: Struct, - description: "struct Arg(u32);", + description: "struct Arg(u32)", }, }, HoverGotoTypeData { @@ -2648,7 +2740,7 @@ fn main() { let s$0t = (A(1), B(2), M::C(3) ); } focus_range: 7..8, name: "A", kind: Struct, - description: "struct A(u32);", + description: "struct A(u32)", }, }, HoverGotoTypeData { @@ -2661,7 +2753,7 @@ fn main() { let s$0t = (A(1), B(2), M::C(3) ); } focus_range: 22..23, name: "B", kind: Struct, - description: "struct B(u32);", + description: "struct B(u32)", }, }, HoverGotoTypeData { @@ -2675,7 +2767,7 @@ fn main() { let s$0t = (A(1), B(2), M::C(3) ); } name: "C", kind: Struct, container_name: "M", - description: "pub struct C(u32);", + description: "pub struct C(u32)", }, }, ], @@ -3331,26 +3423,26 @@ struct Foo; impl Foo {} "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Bar", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..11, - focus_range: 7..10, - name: "Bar", - kind: Struct, - description: "struct Bar", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Bar", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..11, + focus_range: 7..10, + name: "Bar", + kind: Struct, + description: "struct Bar", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3396,26 +3488,26 @@ impl Foo { } "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..11, - focus_range: 7..10, - name: "Foo", - kind: Struct, - description: "struct Foo", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..11, + focus_range: 7..10, + name: "Foo", + kind: Struct, + description: "struct Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3498,7 +3590,7 @@ struct S$0T(T); ``` ```rust - struct ST(T); + struct ST(T) ``` "#]], ); @@ -3519,7 +3611,7 @@ struct S$0T(T); ``` ```rust - struct ST(T); + struct ST(T) ``` "#]], ); @@ -3541,7 +3633,7 @@ struct S$0T(T); ``` ```rust - struct ST(T); + struct ST(T) ``` "#]], ); @@ -5931,26 +6023,26 @@ fn foo() { } "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..11, - focus_range: 7..10, - name: "Foo", - kind: Struct, - description: "struct Foo", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..11, + focus_range: 7..10, + name: "Foo", + kind: Struct, + description: "struct Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -6166,7 +6258,7 @@ pub struct Foo(i32); ```rust // size = 4, align = 4 - pub struct Foo(i32); + pub struct Foo(i32) ``` --- @@ -6191,7 +6283,7 @@ pub struct Foo(T); ``` ```rust - pub struct Foo(T); + pub struct Foo(T) ``` ---