From d81148a0095e97f00720d6bbeee098130b304696 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Thu, 21 Mar 2024 17:56:49 +0800 Subject: [PATCH 1/5] expose config for hover struct field display --- crates/rust-analyzer/src/config.rs | 3 +++ docs/user/generated_config.adoc | 5 +++++ editors/code/package.json | 9 +++++++++ 3 files changed, 17 insertions(+) diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index e6b60f690659..a5545e798474 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -375,6 +375,8 @@ config_data! { /// How to render the size information in a memory layout hover. hover_memoryLayout_size: Option = "\"both\"", + /// How many fields of a struct to display when hovering a struct. + hover_show_structFields: Option = "null", /// How many associated items of a trait to display when hovering a trait. hover_show_traitAssocItems: Option = "null", @@ -1690,6 +1692,7 @@ impl Config { }, keywords: self.data.hover_documentation_keywords_enable, max_trait_assoc_items_count: self.data.hover_show_traitAssocItems, + max_struct_field_count: self.data.hover_show_structFields, } } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 5e782b783111..c4024f6d282b 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -520,6 +520,11 @@ How to render the offset information in a memory layout hover. -- How to render the size information in a memory layout hover. -- +[[rust-analyzer.hover.show.structFields]]rust-analyzer.hover.show.structFields (default: `null`):: ++ +-- +How many fields of a struct to display when hovering a struct. +-- [[rust-analyzer.hover.show.traitAssocItems]]rust-analyzer.hover.show.traitAssocItems (default: `null`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index c34b8e25de02..c3ea1ceeb692 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -1144,6 +1144,15 @@ } ] }, + "rust-analyzer.hover.show.structFields": { + "markdownDescription": "How many fields of a struct to display when hovering a struct.", + "default": null, + "type": [ + "null", + "integer" + ], + "minimum": 0 + }, "rust-analyzer.hover.show.traitAssocItems": { "markdownDescription": "How many associated items of a trait to display when hovering a trait.", "default": null, From 1c85234bcdbc7c863e737e9f3329518beeb436c3 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Thu, 21 Mar 2024 17:58:29 +0800 Subject: [PATCH 2/5] limit struct field hover display nums --- crates/hir/src/display.rs | 35 ++++++++++++++++++++++------------ crates/ide/src/hover.rs | 1 + crates/ide/src/hover/render.rs | 3 +++ crates/ide/src/static_index.rs | 1 + 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index c5d44c11f2c1..0fa2d803467a 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -185,19 +185,30 @@ impl HirDisplay for Struct { 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")?; + if let Some(limit) = f.entity_limit { + let has_where_clause = write_where_clause(def_id, f)?; + let fields = self.fields(f.db); + let count = fields.len().min(limit); + f.write_char(if !has_where_clause { ' ' } else { '\n' })?; + if count == 0 { + if fields.is_empty() { + f.write_str("{}")?; + } else { + f.write_str("{ /* … */ }")?; + } + } else { + f.write_str(" {\n")?; + for field in &fields[..count] { + f.write_str(" ")?; + field.hir_fmt(f)?; + f.write_str(",\n")?; + } + + if fields.len() > count { + f.write_str(" /* … */\n")?; + } + f.write_str("}")?; } - f.write_str("}")?; } } StructKind::Unit => _ = write_where_clause(def_id, f)?, diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 8f4c629b5813..822751c0e4ce 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -33,6 +33,7 @@ pub struct HoverConfig { pub keywords: bool, pub format: HoverDocFormat, pub max_trait_assoc_items_count: Option, + pub max_struct_field_count: Option, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index 63777d491050..abedbff831a5 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -410,6 +410,9 @@ pub(super) fn definition( Definition::Trait(trait_) => { trait_.display_limited(db, config.max_trait_assoc_items_count).to_string() } + Definition::Adt(Adt::Struct(struct_)) => { + struct_.display_limited(db, config.max_struct_field_count).to_string() + } _ => def.label(db), }; let docs = def.docs(db, famous_defs); diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index fe063081f799..3fef16df25e3 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -167,6 +167,7 @@ impl StaticIndex<'_> { keywords: true, format: crate::HoverDocFormat::Markdown, max_trait_assoc_items_count: None, + max_struct_field_count: None, }; let tokens = tokens.filter(|token| { matches!( From a89e417ce5b23b304ec17d05ca2786ba364f1d67 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Thu, 21 Mar 2024 17:58:44 +0800 Subject: [PATCH 3/5] adjust test --- crates/ide/src/hover/tests.rs | 40 +++++++++++++---------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 466e5570b337..289c2ad945da 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -18,6 +18,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig { format: HoverDocFormat::Markdown, keywords: true, max_trait_assoc_items_count: None, + max_struct_field_count: None, }; fn check_hover_no_result(ra_fixture: &str) { @@ -853,9 +854,7 @@ struct Foo$0 { field: u32 } ```rust // size = 4, align = 4 - struct Foo { - field: u32, - } + struct Foo ``` "#]], ); @@ -873,11 +872,6 @@ struct Foo$0 where u32: Copy { field: u32 } ```rust // size = 4, align = 4 struct Foo - where - u32: Copy, - { - field: u32, - } ``` "#]], ); @@ -1344,9 +1338,7 @@ impl Thing { ``` ```rust - struct Thing { - x: u32, - } + struct Thing ``` "#]], ); @@ -1365,9 +1357,7 @@ impl Thing { ``` ```rust - struct Thing { - x: u32, - } + struct Thing ``` "#]], ); @@ -2599,7 +2589,7 @@ fn main() { let s$0t = S{ f1:0 }; } focus_range: 7..8, name: "S", kind: Struct, - description: "struct S {\n f1: u32,\n}", + description: "struct S", }, }, ], @@ -2645,7 +2635,7 @@ fn main() { let s$0t = S{ f1:Arg(0) }; } focus_range: 24..25, name: "S", kind: Struct, - description: "struct S {\n f1: T,\n}", + description: "struct S", }, }, ], @@ -2704,7 +2694,7 @@ fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; } focus_range: 24..25, name: "S", kind: Struct, - description: "struct S {\n f1: T,\n}", + description: "struct S", }, }, ], @@ -2957,7 +2947,7 @@ fn main() { let s$0t = foo(); } focus_range: 39..41, name: "S1", kind: Struct, - description: "struct S1 {}", + description: "struct S1", }, }, HoverGotoTypeData { @@ -2970,7 +2960,7 @@ fn main() { let s$0t = foo(); } focus_range: 52..54, name: "S2", kind: Struct, - description: "struct S2 {}", + description: "struct S2", }, }, ], @@ -3061,7 +3051,7 @@ fn foo(ar$0g: &impl Foo + Bar) {} focus_range: 36..37, name: "S", kind: Struct, - description: "struct S {}", + description: "struct S", }, }, ], @@ -3161,7 +3151,7 @@ fn foo(ar$0g: &impl Foo) {} focus_range: 23..24, name: "S", kind: Struct, - description: "struct S {}", + description: "struct S", }, }, ], @@ -3198,7 +3188,7 @@ fn main() { let s$0t = foo(); } focus_range: 49..50, name: "B", kind: Struct, - description: "struct B {}", + description: "struct B", }, }, HoverGotoTypeData { @@ -3287,7 +3277,7 @@ fn foo(ar$0g: &dyn Foo) {} focus_range: 23..24, name: "S", kind: Struct, - description: "struct S {}", + description: "struct S", }, }, ], @@ -3322,7 +3312,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 50..51, name: "B", kind: Struct, - description: "struct B {}", + description: "struct B", }, }, HoverGotoTypeData { @@ -3361,7 +3351,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 65..66, name: "S", kind: Struct, - description: "struct S {}", + description: "struct S", }, }, ], From ba8c9810aadc2e2773ba1c89b621d100a39e35df Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Sat, 23 Mar 2024 08:42:45 +0800 Subject: [PATCH 4/5] review update --- crates/hir/src/display.rs | 2 +- crates/ide/src/hover/tests.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 0fa2d803467a..23c6b078b969 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -185,8 +185,8 @@ impl HirDisplay for Struct { write_where_clause(def_id, f)?; } StructKind::Record => { + let has_where_clause = write_where_clause(def_id, f)?; if let Some(limit) = f.entity_limit { - let has_where_clause = write_where_clause(def_id, f)?; let fields = self.fields(f.db); let count = fields.len().min(limit); f.write_char(if !has_where_clause { ' ' } else { '\n' })?; diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 289c2ad945da..463f0951eafc 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -872,6 +872,8 @@ struct Foo$0 where u32: Copy { field: u32 } ```rust // size = 4, align = 4 struct Foo + where + u32: Copy, ``` "#]], ); From 58013ad70d2c8a204d311fdacb40a80ba87f37c4 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Mon, 25 Mar 2024 19:55:09 +0800 Subject: [PATCH 5/5] add test for struct field hover display limit --- crates/ide/src/hover/tests.rs | 91 +++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 463f0951eafc..192f6c0272ba 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -50,6 +50,28 @@ fn check(ra_fixture: &str, expect: Expect) { expect.assert_eq(&actual) } +#[track_caller] +fn check_hover_struct_limit(count: usize, ra_fixture: &str, expect: Expect) { + let (analysis, position) = fixture::position(ra_fixture); + let hover = analysis + .hover( + &HoverConfig { + links_in_hover: true, + max_struct_field_count: Some(count), + ..HOVER_BASE_CONFIG + }, + FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) }, + ) + .unwrap() + .unwrap(); + + let content = analysis.db.file_text(position.file_id); + let hovered_element = &content[hover.range]; + + let actual = format!("*{hovered_element}*\n{}\n", hover.info.markup); + expect.assert_eq(&actual) +} + #[track_caller] fn check_assoc_count(count: usize, ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); @@ -879,6 +901,75 @@ struct Foo$0 where u32: Copy { field: u32 } ); } +#[test] +fn hover_record_struct_limit() { + check_hover_struct_limit( + 3, + r#" + struct Foo$0 { a: u32, b: i32, c: i32 } + "#, + expect![[r#" + *Foo* + + ```rust + test + ``` + + ```rust + // size = 12 (0xC), align = 4 + struct Foo { + a: u32, + b: i32, + c: i32, + } + ``` + "#]], + ); + check_hover_struct_limit( + 3, + r#" + struct Foo$0 { a: u32 } + "#, + expect![[r#" + *Foo* + + ```rust + test + ``` + + ```rust + // size = 4, align = 4 + struct Foo { + a: u32, + } + ``` + "#]], + ); + check_hover_struct_limit( + 3, + r#" + struct Foo$0 { a: u32, b: i32, c: i32, d: u32 } + "#, + expect![[r#" + *Foo* + + ```rust + test + ``` + + ```rust + // size = 16 (0x10), align = 4 + struct Foo { + a: u32, + b: i32, + c: i32, + /* … */ + } + ``` + "#]], + ); +} + #[test] fn hover_unit_struct() { check(