diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 328dea87ac..fe191a456a 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -63,7 +63,7 @@ pub struct HirFormatter<'a> { buf: String, curr_size: usize, pub(crate) max_size: Option, - pub limited_size: Option, + pub entity_limit: Option, omit_verbose_types: bool, closure_style: ClosureStyle, display_target: DisplayTarget, @@ -148,8 +148,8 @@ pub trait HirDisplay { } } - /// Returns a `Display`able type that is human-readable and tries to limit the item inside this type. - /// Use this for showing types which may contain two many item when user hover on, like `trait`, `struct`, `enum` + /// Returns a `Display`able type that is human-readable and tries to limit the number of items inside. + /// Use this for showing definitions which may contain too many items, like `trait`, `struct`, `enum` fn display_limited<'a>( &'a self, db: &'a dyn HirDatabase, @@ -184,7 +184,7 @@ pub trait HirDisplay { buf: String::with_capacity(20), curr_size: 0, max_size: None, - limited_size: None, + entity_limit: None, omit_verbose_types: false, closure_style: ClosureStyle::ImplFn, display_target: DisplayTarget::SourceCode { module_id, allow_opaque }, @@ -352,7 +352,7 @@ impl HirDisplayWrapper<'_, T> { buf: String::with_capacity(20), curr_size: 0, max_size: self.max_size, - limited_size: self.limited_size, + entity_limit: self.limited_size, omit_verbose_types: self.omit_verbose_types, display_target: self.display_target, closure_style: self.closure_style, diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 20ba72d998..cdc0db8653 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -596,33 +596,32 @@ impl HirDisplay for Trait { write_generic_params(def_id, f)?; write_where_clause(def_id, f)?; - let assoc_items = self.items(f.db); - let assoc_items_size = assoc_items.len(); - let limited_size = f.limited_size.unwrap_or(assoc_items_size); - if assoc_items.is_empty() { - f.write_str(" {}")?; - } else { - f.write_str(" {\n")?; - for (index, item) in assoc_items.iter().enumerate() { - f.write_str(" ")?; - match item { - AssocItem::Function(func) => { - func.hir_fmt(f)?; - } - AssocItem::Const(cst) => { - cst.hir_fmt(f)?; - } - AssocItem::TypeAlias(type_alias) => { - type_alias.hir_fmt(f)?; - } - }; - f.write_str(",\n")?; - if index + 1 == limited_size && index + 1 != assoc_items_size { - f.write_str(" ...\n")?; - break; + if let Some(limit) = f.entity_limit { + let assoc_items = self.items(f.db); + let count = assoc_items.len().min(limit); + if count == 0 { + if assoc_items.is_empty() { + f.write_str(" {}")?; + } else { + f.write_str(" { /* … */ }")?; } + } else { + f.write_str(" {\n")?; + for item in &assoc_items[..count] { + f.write_str(" ")?; + match item { + AssocItem::Function(func) => func.hir_fmt(f), + AssocItem::Const(cst) => cst.hir_fmt(f), + AssocItem::TypeAlias(type_alias) => type_alias.hir_fmt(f), + }?; + f.write_str(";\n")?; + } + + if assoc_items.len() > count { + f.write_str(" /* … */\n")?; + } + f.write_str("}")?; } - f.write_str("}")?; } Ok(()) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index b6877c5e8c..8f4c629b58 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -32,7 +32,7 @@ pub struct HoverConfig { pub documentation: bool, pub keywords: bool, pub format: HoverDocFormat, - pub trait_assoc_items_size: Option, + pub max_trait_assoc_items_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 f528bd512c..d1d039534d 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -408,7 +408,7 @@ pub(super) fn definition( let mod_path = definition_mod_path(db, &def); let label = match def { Definition::Trait(trait_) => { - trait_.display_limited(db, config.trait_assoc_items_size).to_string() + trait_.display_limited(db, config.max_trait_assoc_items_count).to_string() } _ => def.label(db), }; diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index cec1375271..c3cd6513dc 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -17,7 +17,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig { documentation: true, format: HoverDocFormat::Markdown, keywords: true, - trait_assoc_items_size: None, + max_trait_assoc_items_count: None, }; fn check_hover_no_result(ra_fixture: &str) { @@ -49,6 +49,28 @@ fn check(ra_fixture: &str, expect: Expect) { expect.assert_eq(&actual) } +#[track_caller] +fn check_assoc_count(count: usize, ra_fixture: &str, expect: Expect) { + let (analysis, position) = fixture::position(ra_fixture); + let hover = analysis + .hover( + &HoverConfig { + links_in_hover: true, + max_trait_assoc_items_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) +} + fn check_hover_no_links(ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); let hover = analysis @@ -412,7 +434,7 @@ fn main() { name: "FnOnce", kind: Trait, container_name: "function", - description: "pub trait FnOnce\nwhere\n Args: Tuple, {\n pub type Output,\n pub extern \"rust-call\" fn call_once(self, args: Args) -> Self::Output,\n}", + description: "pub trait FnOnce\nwhere\n Args: Tuple,", }, }, ], @@ -2673,26 +2695,26 @@ fn foo() -> impl Foo {} fn main() { let s$0t = foo(); } "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..12, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..12, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -2707,39 +2729,39 @@ fn foo() -> impl Foo {} fn main() { let s$0t = foo(); } "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..15, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..15, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - HoverGotoTypeData { - mod_path: "test::S", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 16..25, - focus_range: 23..24, - name: "S", - kind: Struct, - description: "struct S", - }, + }, + HoverGotoTypeData { + mod_path: "test::S", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 16..25, + focus_range: 23..24, + name: "S", + kind: Struct, + description: "struct S", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -2767,7 +2789,7 @@ fn main() { let s$0t = foo(); } focus_range: 19..22, name: "Bar", kind: Trait, - description: "trait Bar {}", + description: "trait Bar", }, }, HoverGotoTypeData { @@ -2780,7 +2802,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo {}", + description: "trait Foo", }, }, ], @@ -2817,7 +2839,7 @@ fn main() { let s$0t = foo(); } focus_range: 22..25, name: "Bar", kind: Trait, - description: "trait Bar {}", + description: "trait Bar", }, }, HoverGotoTypeData { @@ -2830,7 +2852,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo {}", + description: "trait Foo", }, }, HoverGotoTypeData { @@ -2874,26 +2896,26 @@ trait Foo {} fn foo(ar$0g: &impl Foo) {} "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..12, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..12, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -2921,7 +2943,7 @@ fn foo(ar$0g: &impl Foo + Bar) {} focus_range: 19..22, name: "Bar", kind: Trait, - description: "trait Bar {}", + description: "trait Bar", }, }, HoverGotoTypeData { @@ -2934,7 +2956,7 @@ fn foo(ar$0g: &impl Foo + Bar) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo {}", + description: "trait Foo", }, }, HoverGotoTypeData { @@ -2989,7 +3011,7 @@ pub mod future { name: "Future", kind: Trait, container_name: "future", - description: "pub trait Future {}", + description: "pub trait Future", }, }, HoverGotoTypeData { @@ -3021,39 +3043,39 @@ struct S {} fn foo(ar$0g: &impl Foo) {} "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..15, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..15, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - HoverGotoTypeData { - mod_path: "test::S", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 16..27, - focus_range: 23..24, - name: "S", - kind: Struct, - description: "struct S {}", - }, + }, + HoverGotoTypeData { + mod_path: "test::S", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 16..27, + focus_range: 23..24, + name: "S", + kind: Struct, + description: "struct S {}", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3071,39 +3093,39 @@ fn foo() -> B {} fn main() { let s$0t = foo(); } "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::B", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 42..55, - focus_range: 49..50, - name: "B", - kind: Struct, - description: "struct B {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::B", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 42..55, + focus_range: 49..50, + name: "B", + kind: Struct, + description: "struct B {}", }, - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..12, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + }, + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..12, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3115,26 +3137,26 @@ trait Foo {} fn foo(ar$0g: &dyn Foo) {} "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..12, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..12, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3147,39 +3169,39 @@ struct S {} fn foo(ar$0g: &dyn Foo) {} "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..15, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..15, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - HoverGotoTypeData { - mod_path: "test::S", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 16..27, - focus_range: 23..24, - name: "S", - kind: Struct, - description: "struct S {}", - }, + }, + HoverGotoTypeData { + mod_path: "test::S", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 16..27, + focus_range: 23..24, + name: "S", + kind: Struct, + description: "struct S {}", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3221,7 +3243,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 28..36, name: "DynTrait", kind: Trait, - description: "trait DynTrait {}", + description: "trait DynTrait", }, }, HoverGotoTypeData { @@ -3234,7 +3256,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 6..15, name: "ImplTrait", kind: Trait, - description: "trait ImplTrait {}", + description: "trait ImplTrait", }, }, HoverGotoTypeData { @@ -3276,26 +3298,26 @@ fn test() -> impl Foo { S {} } fn main() { let s$0t = test().get(); } "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..62, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {\n type Item,\n fn get(self) -> Self::Item,\n}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..62, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3341,26 +3363,26 @@ trait Foo {} fn foo(t: T$0){} "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::Foo", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..12, - focus_range: 6..9, - name: "Foo", - kind: Trait, - description: "trait Foo {}", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::Foo", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..12, + focus_range: 6..9, + name: "Foo", + kind: Trait, + description: "trait Foo", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -6330,71 +6352,46 @@ impl T for () { #[test] fn hover_trait_show_assoc_items() { - check( + check_assoc_count( + 0, r#" trait T {} impl T$0 for () {} "#, expect![[r#" - *T* + *T* - ```rust - test - ``` + ```rust + test + ``` - ```rust - trait T {} - ``` + ```rust + trait T {} + ``` "#]], ); - check( + check_assoc_count( + 1, r#" -trait T { - fn func() {} -} +trait T {} impl T$0 for () {} "#, expect![[r#" - *T* + *T* - ```rust - test - ``` + ```rust + test + ``` - ```rust - trait T { - fn func(), - } - ``` + ```rust + trait T {} + ``` "#]], ); - check( - r#" -trait T { - fn func() {} - const FLAG: i32 = 34; -} -impl T$0 for () {} -"#, - expect![[r#" - *T* - - ```rust - test - ``` - - ```rust - trait T { - fn func(), - const FLAG: i32, - } - ``` - "#]], - ); - - check( + check_assoc_count( + 0, r#" trait T { fn func() {} @@ -6404,19 +6401,96 @@ trait T { impl T$0 for () {} "#, expect![[r#" - *T* + *T* - ```rust - test - ``` + ```rust + test + ``` - ```rust - trait T { - fn func(), - const FLAG: i32, - type Bar, - } - ``` + ```rust + trait T { /* … */ } + ``` + "#]], + ); + + check_assoc_count( + 2, + r#" +trait T { + fn func() {} + const FLAG: i32 = 34; + type Bar; +} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T { + fn func(); + const FLAG: i32; + /* … */ + } + ``` + "#]], + ); + + check_assoc_count( + 3, + r#" +trait T { + fn func() {} + const FLAG: i32 = 34; + type Bar; +} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T { + fn func(); + const FLAG: i32; + type Bar; + } + ``` + "#]], + ); + + check_assoc_count( + 4, + r#" +trait T { + fn func() {} + const FLAG: i32 = 34; + type Bar; +} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T { + fn func(); + const FLAG: i32; + type Bar; + } + ``` "#]], ); } @@ -7532,7 +7606,7 @@ impl Iterator for S { name: "Future", kind: Trait, container_name: "future", - description: "pub trait Future {\n pub type Output,\n pub fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll,\n}", + description: "pub trait Future", }, }, HoverGotoTypeData { @@ -7546,7 +7620,7 @@ impl Iterator for S { name: "Iterator", kind: Trait, container_name: "iterator", - description: "pub trait Iterator {\n pub type Item,\n pub fn next(&mut self) -> Option,\n pub fn nth(&mut self, n: usize) -> Option,\n pub fn by_ref(&mut self) -> &mut Self\nwhere\n Self: Sized,,\n}", + description: "pub trait Iterator", }, }, HoverGotoTypeData { @@ -7559,7 +7633,7 @@ impl Iterator for S { focus_range: 49..56, name: "Notable", kind: Trait, - description: "trait Notable {}", + description: "trait Notable", }, }, HoverGotoTypeData { diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 0f19da0ac5..fe063081f7 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -166,7 +166,7 @@ impl StaticIndex<'_> { documentation: true, keywords: true, format: crate::HoverDocFormat::Markdown, - trait_assoc_items_size: None, + max_trait_assoc_items_count: None, }; let tokens = tokens.filter(|token| { matches!( diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 21a106bc77..ad3721a995 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -1682,7 +1682,7 @@ impl Config { } }, keywords: self.data.hover_documentation_keywords_enable, - trait_assoc_items_size: self.data.hover_show_traitAssocItems, + max_trait_assoc_items_count: self.data.hover_show_traitAssocItems, } }