internal: Adjust a few things for trait assoc item hovers

This commit is contained in:
Lukas Wirth 2024-03-05 11:06:36 +01:00
parent ce3216e0ae
commit b20e467373
7 changed files with 397 additions and 324 deletions

View file

@ -63,7 +63,7 @@ pub struct HirFormatter<'a> {
buf: String, buf: String,
curr_size: usize, curr_size: usize,
pub(crate) max_size: Option<usize>, pub(crate) max_size: Option<usize>,
pub limited_size: Option<usize>, pub entity_limit: Option<usize>,
omit_verbose_types: bool, omit_verbose_types: bool,
closure_style: ClosureStyle, closure_style: ClosureStyle,
display_target: DisplayTarget, 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. /// Returns a `Display`able type that is human-readable and tries to limit the number of items inside.
/// Use this for showing types which may contain two many item when user hover on, like `trait`, `struct`, `enum` /// Use this for showing definitions which may contain too many items, like `trait`, `struct`, `enum`
fn display_limited<'a>( fn display_limited<'a>(
&'a self, &'a self,
db: &'a dyn HirDatabase, db: &'a dyn HirDatabase,
@ -184,7 +184,7 @@ pub trait HirDisplay {
buf: String::with_capacity(20), buf: String::with_capacity(20),
curr_size: 0, curr_size: 0,
max_size: None, max_size: None,
limited_size: None, entity_limit: None,
omit_verbose_types: false, omit_verbose_types: false,
closure_style: ClosureStyle::ImplFn, closure_style: ClosureStyle::ImplFn,
display_target: DisplayTarget::SourceCode { module_id, allow_opaque }, display_target: DisplayTarget::SourceCode { module_id, allow_opaque },
@ -352,7 +352,7 @@ impl<T: HirDisplay> HirDisplayWrapper<'_, T> {
buf: String::with_capacity(20), buf: String::with_capacity(20),
curr_size: 0, curr_size: 0,
max_size: self.max_size, max_size: self.max_size,
limited_size: self.limited_size, entity_limit: self.limited_size,
omit_verbose_types: self.omit_verbose_types, omit_verbose_types: self.omit_verbose_types,
display_target: self.display_target, display_target: self.display_target,
closure_style: self.closure_style, closure_style: self.closure_style,

View file

@ -596,33 +596,32 @@ impl HirDisplay for Trait {
write_generic_params(def_id, f)?; write_generic_params(def_id, f)?;
write_where_clause(def_id, f)?; write_where_clause(def_id, f)?;
let assoc_items = self.items(f.db); if let Some(limit) = f.entity_limit {
let assoc_items_size = assoc_items.len(); let assoc_items = self.items(f.db);
let limited_size = f.limited_size.unwrap_or(assoc_items_size); let count = assoc_items.len().min(limit);
if assoc_items.is_empty() { if count == 0 {
f.write_str(" {}")?; if assoc_items.is_empty() {
} else { f.write_str(" {}")?;
f.write_str(" {\n")?; } else {
for (index, item) in assoc_items.iter().enumerate() { f.write_str(" { /* … */ }")?;
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;
} }
} 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(()) Ok(())

View file

@ -32,7 +32,7 @@ pub struct HoverConfig {
pub documentation: bool, pub documentation: bool,
pub keywords: bool, pub keywords: bool,
pub format: HoverDocFormat, pub format: HoverDocFormat,
pub trait_assoc_items_size: Option<usize>, pub max_trait_assoc_items_count: Option<usize>,
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]

View file

@ -408,7 +408,7 @@ pub(super) fn definition(
let mod_path = definition_mod_path(db, &def); let mod_path = definition_mod_path(db, &def);
let label = match def { let label = match def {
Definition::Trait(trait_) => { 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), _ => def.label(db),
}; };

View file

@ -17,7 +17,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig {
documentation: true, documentation: true,
format: HoverDocFormat::Markdown, format: HoverDocFormat::Markdown,
keywords: true, keywords: true,
trait_assoc_items_size: None, max_trait_assoc_items_count: None,
}; };
fn check_hover_no_result(ra_fixture: &str) { fn check_hover_no_result(ra_fixture: &str) {
@ -49,6 +49,28 @@ fn check(ra_fixture: &str, expect: Expect) {
expect.assert_eq(&actual) 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) { fn check_hover_no_links(ra_fixture: &str, expect: Expect) {
let (analysis, position) = fixture::position(ra_fixture); let (analysis, position) = fixture::position(ra_fixture);
let hover = analysis let hover = analysis
@ -412,7 +434,7 @@ fn main() {
name: "FnOnce", name: "FnOnce",
kind: Trait, kind: Trait,
container_name: "function", container_name: "function",
description: "pub trait FnOnce<Args>\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<Args>\nwhere\n Args: Tuple,",
}, },
}, },
], ],
@ -2673,26 +2695,26 @@ fn foo() -> impl Foo {}
fn main() { let s$0t = foo(); } fn main() { let s$0t = foo(); }
"#, "#,
expect![[r#" expect![[r#"
[ [
GoToType( GoToType(
[ [
HoverGotoTypeData { HoverGotoTypeData {
mod_path: "test::Foo", mod_path: "test::Foo",
nav: NavigationTarget { nav: NavigationTarget {
file_id: FileId( file_id: FileId(
0, 0,
), ),
full_range: 0..12, full_range: 0..12,
focus_range: 6..9, focus_range: 6..9,
name: "Foo", name: "Foo",
kind: Trait, kind: Trait,
description: "trait Foo {}", description: "trait Foo",
},
}, },
], },
), ],
] ),
"#]], ]
"#]],
); );
} }
@ -2707,39 +2729,39 @@ fn foo() -> impl Foo<S> {}
fn main() { let s$0t = foo(); } fn main() { let s$0t = foo(); }
"#, "#,
expect![[r#" expect![[r#"
[ [
GoToType( GoToType(
[ [
HoverGotoTypeData { HoverGotoTypeData {
mod_path: "test::Foo", mod_path: "test::Foo",
nav: NavigationTarget { nav: NavigationTarget {
file_id: FileId( file_id: FileId(
0, 0,
), ),
full_range: 0..15, full_range: 0..15,
focus_range: 6..9, focus_range: 6..9,
name: "Foo", name: "Foo",
kind: Trait, kind: Trait,
description: "trait Foo<T> {}", description: "trait Foo<T>",
},
}, },
HoverGotoTypeData { },
mod_path: "test::S", HoverGotoTypeData {
nav: NavigationTarget { mod_path: "test::S",
file_id: FileId( nav: NavigationTarget {
0, file_id: FileId(
), 0,
full_range: 16..25, ),
focus_range: 23..24, full_range: 16..25,
name: "S", focus_range: 23..24,
kind: Struct, name: "S",
description: "struct S", kind: Struct,
}, description: "struct S",
}, },
], },
), ],
] ),
"#]], ]
"#]],
); );
} }
@ -2767,7 +2789,7 @@ fn main() { let s$0t = foo(); }
focus_range: 19..22, focus_range: 19..22,
name: "Bar", name: "Bar",
kind: Trait, kind: Trait,
description: "trait Bar {}", description: "trait Bar",
}, },
}, },
HoverGotoTypeData { HoverGotoTypeData {
@ -2780,7 +2802,7 @@ fn main() { let s$0t = foo(); }
focus_range: 6..9, focus_range: 6..9,
name: "Foo", name: "Foo",
kind: Trait, kind: Trait,
description: "trait Foo {}", description: "trait Foo",
}, },
}, },
], ],
@ -2817,7 +2839,7 @@ fn main() { let s$0t = foo(); }
focus_range: 22..25, focus_range: 22..25,
name: "Bar", name: "Bar",
kind: Trait, kind: Trait,
description: "trait Bar<T> {}", description: "trait Bar<T>",
}, },
}, },
HoverGotoTypeData { HoverGotoTypeData {
@ -2830,7 +2852,7 @@ fn main() { let s$0t = foo(); }
focus_range: 6..9, focus_range: 6..9,
name: "Foo", name: "Foo",
kind: Trait, kind: Trait,
description: "trait Foo<T> {}", description: "trait Foo<T>",
}, },
}, },
HoverGotoTypeData { HoverGotoTypeData {
@ -2874,26 +2896,26 @@ trait Foo {}
fn foo(ar$0g: &impl Foo) {} fn foo(ar$0g: &impl Foo) {}
"#, "#,
expect![[r#" expect![[r#"
[ [
GoToType( GoToType(
[ [
HoverGotoTypeData { HoverGotoTypeData {
mod_path: "test::Foo", mod_path: "test::Foo",
nav: NavigationTarget { nav: NavigationTarget {
file_id: FileId( file_id: FileId(
0, 0,
), ),
full_range: 0..12, full_range: 0..12,
focus_range: 6..9, focus_range: 6..9,
name: "Foo", name: "Foo",
kind: Trait, kind: Trait,
description: "trait Foo {}", description: "trait Foo",
},
}, },
], },
), ],
] ),
"#]], ]
"#]],
); );
} }
@ -2921,7 +2943,7 @@ fn foo(ar$0g: &impl Foo + Bar<S>) {}
focus_range: 19..22, focus_range: 19..22,
name: "Bar", name: "Bar",
kind: Trait, kind: Trait,
description: "trait Bar<T> {}", description: "trait Bar<T>",
}, },
}, },
HoverGotoTypeData { HoverGotoTypeData {
@ -2934,7 +2956,7 @@ fn foo(ar$0g: &impl Foo + Bar<S>) {}
focus_range: 6..9, focus_range: 6..9,
name: "Foo", name: "Foo",
kind: Trait, kind: Trait,
description: "trait Foo {}", description: "trait Foo",
}, },
}, },
HoverGotoTypeData { HoverGotoTypeData {
@ -2989,7 +3011,7 @@ pub mod future {
name: "Future", name: "Future",
kind: Trait, kind: Trait,
container_name: "future", container_name: "future",
description: "pub trait Future {}", description: "pub trait Future",
}, },
}, },
HoverGotoTypeData { HoverGotoTypeData {
@ -3021,39 +3043,39 @@ struct S {}
fn foo(ar$0g: &impl Foo<S>) {} fn foo(ar$0g: &impl Foo<S>) {}
"#, "#,
expect![[r#" expect![[r#"
[ [
GoToType( GoToType(
[ [
HoverGotoTypeData { HoverGotoTypeData {
mod_path: "test::Foo", mod_path: "test::Foo",
nav: NavigationTarget { nav: NavigationTarget {
file_id: FileId( file_id: FileId(
0, 0,
), ),
full_range: 0..15, full_range: 0..15,
focus_range: 6..9, focus_range: 6..9,
name: "Foo", name: "Foo",
kind: Trait, kind: Trait,
description: "trait Foo<T> {}", description: "trait Foo<T>",
},
}, },
HoverGotoTypeData { },
mod_path: "test::S", HoverGotoTypeData {
nav: NavigationTarget { mod_path: "test::S",
file_id: FileId( nav: NavigationTarget {
0, file_id: FileId(
), 0,
full_range: 16..27, ),
focus_range: 23..24, full_range: 16..27,
name: "S", focus_range: 23..24,
kind: Struct, name: "S",
description: "struct S {}", kind: Struct,
}, description: "struct S {}",
}, },
], },
), ],
] ),
"#]], ]
"#]],
); );
} }
@ -3071,39 +3093,39 @@ fn foo() -> B<dyn Foo> {}
fn main() { let s$0t = foo(); } fn main() { let s$0t = foo(); }
"#, "#,
expect![[r#" expect![[r#"
[ [
GoToType( GoToType(
[ [
HoverGotoTypeData { HoverGotoTypeData {
mod_path: "test::B", mod_path: "test::B",
nav: NavigationTarget { nav: NavigationTarget {
file_id: FileId( file_id: FileId(
0, 0,
), ),
full_range: 42..55, full_range: 42..55,
focus_range: 49..50, focus_range: 49..50,
name: "B", name: "B",
kind: Struct, kind: Struct,
description: "struct B<T> {}", description: "struct B<T> {}",
},
}, },
HoverGotoTypeData { },
mod_path: "test::Foo", HoverGotoTypeData {
nav: NavigationTarget { mod_path: "test::Foo",
file_id: FileId( nav: NavigationTarget {
0, file_id: FileId(
), 0,
full_range: 0..12, ),
focus_range: 6..9, full_range: 0..12,
name: "Foo", focus_range: 6..9,
kind: Trait, name: "Foo",
description: "trait Foo {}", kind: Trait,
}, description: "trait Foo",
}, },
], },
), ],
] ),
"#]], ]
"#]],
); );
} }
@ -3115,26 +3137,26 @@ trait Foo {}
fn foo(ar$0g: &dyn Foo) {} fn foo(ar$0g: &dyn Foo) {}
"#, "#,
expect![[r#" expect![[r#"
[ [
GoToType( GoToType(
[ [
HoverGotoTypeData { HoverGotoTypeData {
mod_path: "test::Foo", mod_path: "test::Foo",
nav: NavigationTarget { nav: NavigationTarget {
file_id: FileId( file_id: FileId(
0, 0,
), ),
full_range: 0..12, full_range: 0..12,
focus_range: 6..9, focus_range: 6..9,
name: "Foo", name: "Foo",
kind: Trait, kind: Trait,
description: "trait Foo {}", description: "trait Foo",
},
}, },
], },
), ],
] ),
"#]], ]
"#]],
); );
} }
@ -3147,39 +3169,39 @@ struct S {}
fn foo(ar$0g: &dyn Foo<S>) {} fn foo(ar$0g: &dyn Foo<S>) {}
"#, "#,
expect![[r#" expect![[r#"
[ [
GoToType( GoToType(
[ [
HoverGotoTypeData { HoverGotoTypeData {
mod_path: "test::Foo", mod_path: "test::Foo",
nav: NavigationTarget { nav: NavigationTarget {
file_id: FileId( file_id: FileId(
0, 0,
), ),
full_range: 0..15, full_range: 0..15,
focus_range: 6..9, focus_range: 6..9,
name: "Foo", name: "Foo",
kind: Trait, kind: Trait,
description: "trait Foo<T> {}", description: "trait Foo<T>",
},
}, },
HoverGotoTypeData { },
mod_path: "test::S", HoverGotoTypeData {
nav: NavigationTarget { mod_path: "test::S",
file_id: FileId( nav: NavigationTarget {
0, file_id: FileId(
), 0,
full_range: 16..27, ),
focus_range: 23..24, full_range: 16..27,
name: "S", focus_range: 23..24,
kind: Struct, name: "S",
description: "struct S {}", kind: Struct,
}, description: "struct S {}",
}, },
], },
), ],
] ),
"#]], ]
"#]],
); );
} }
@ -3221,7 +3243,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
focus_range: 28..36, focus_range: 28..36,
name: "DynTrait", name: "DynTrait",
kind: Trait, kind: Trait,
description: "trait DynTrait<T> {}", description: "trait DynTrait<T>",
}, },
}, },
HoverGotoTypeData { HoverGotoTypeData {
@ -3234,7 +3256,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
focus_range: 6..15, focus_range: 6..15,
name: "ImplTrait", name: "ImplTrait",
kind: Trait, kind: Trait,
description: "trait ImplTrait<T> {}", description: "trait ImplTrait<T>",
}, },
}, },
HoverGotoTypeData { HoverGotoTypeData {
@ -3276,26 +3298,26 @@ fn test() -> impl Foo { S {} }
fn main() { let s$0t = test().get(); } fn main() { let s$0t = test().get(); }
"#, "#,
expect![[r#" expect![[r#"
[ [
GoToType( GoToType(
[ [
HoverGotoTypeData { HoverGotoTypeData {
mod_path: "test::Foo", mod_path: "test::Foo",
nav: NavigationTarget { nav: NavigationTarget {
file_id: FileId( file_id: FileId(
0, 0,
), ),
full_range: 0..62, full_range: 0..62,
focus_range: 6..9, focus_range: 6..9,
name: "Foo", name: "Foo",
kind: Trait, kind: Trait,
description: "trait Foo {\n type Item,\n fn get(self) -> Self::Item,\n}", description: "trait Foo",
},
}, },
], },
), ],
] ),
"#]], ]
"#]],
); );
} }
@ -3341,26 +3363,26 @@ trait Foo {}
fn foo<T: Foo>(t: T$0){} fn foo<T: Foo>(t: T$0){}
"#, "#,
expect![[r#" expect![[r#"
[ [
GoToType( GoToType(
[ [
HoverGotoTypeData { HoverGotoTypeData {
mod_path: "test::Foo", mod_path: "test::Foo",
nav: NavigationTarget { nav: NavigationTarget {
file_id: FileId( file_id: FileId(
0, 0,
), ),
full_range: 0..12, full_range: 0..12,
focus_range: 6..9, focus_range: 6..9,
name: "Foo", name: "Foo",
kind: Trait, kind: Trait,
description: "trait Foo {}", description: "trait Foo",
},
}, },
], },
), ],
] ),
"#]], ]
"#]],
); );
} }
@ -6330,71 +6352,46 @@ impl T for () {
#[test] #[test]
fn hover_trait_show_assoc_items() { fn hover_trait_show_assoc_items() {
check( check_assoc_count(
0,
r#" r#"
trait T {} trait T {}
impl T$0 for () {} impl T$0 for () {}
"#, "#,
expect![[r#" expect![[r#"
*T* *T*
```rust ```rust
test test
``` ```
```rust ```rust
trait T {} trait T {}
``` ```
"#]], "#]],
); );
check( check_assoc_count(
1,
r#" r#"
trait T { trait T {}
fn func() {}
}
impl T$0 for () {} impl T$0 for () {}
"#, "#,
expect![[r#" expect![[r#"
*T* *T*
```rust ```rust
test test
``` ```
```rust ```rust
trait T { trait T {}
fn func(), ```
}
```
"#]], "#]],
); );
check( check_assoc_count(
r#" 0,
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(
r#" r#"
trait T { trait T {
fn func() {} fn func() {}
@ -6404,19 +6401,96 @@ trait T {
impl T$0 for () {} impl T$0 for () {}
"#, "#,
expect![[r#" expect![[r#"
*T* *T*
```rust ```rust
test test
``` ```
```rust ```rust
trait T { trait T { /**/ }
fn func(), ```
const FLAG: i32, "#]],
type Bar, );
}
``` 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", name: "Future",
kind: Trait, kind: Trait,
container_name: "future", container_name: "future",
description: "pub trait Future {\n pub type Output,\n pub fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>,\n}", description: "pub trait Future",
}, },
}, },
HoverGotoTypeData { HoverGotoTypeData {
@ -7546,7 +7620,7 @@ impl Iterator for S {
name: "Iterator", name: "Iterator",
kind: Trait, kind: Trait,
container_name: "iterator", container_name: "iterator",
description: "pub trait Iterator {\n pub type Item,\n pub fn next(&mut self) -> Option<Self::Item>,\n pub fn nth(&mut self, n: usize) -> Option<Self::Item>,\n pub fn by_ref(&mut self) -> &mut Self\nwhere\n Self: Sized,,\n}", description: "pub trait Iterator",
}, },
}, },
HoverGotoTypeData { HoverGotoTypeData {
@ -7559,7 +7633,7 @@ impl Iterator for S {
focus_range: 49..56, focus_range: 49..56,
name: "Notable", name: "Notable",
kind: Trait, kind: Trait,
description: "trait Notable {}", description: "trait Notable",
}, },
}, },
HoverGotoTypeData { HoverGotoTypeData {

View file

@ -166,7 +166,7 @@ impl StaticIndex<'_> {
documentation: true, documentation: true,
keywords: true, keywords: true,
format: crate::HoverDocFormat::Markdown, format: crate::HoverDocFormat::Markdown,
trait_assoc_items_size: None, max_trait_assoc_items_count: None,
}; };
let tokens = tokens.filter(|token| { let tokens = tokens.filter(|token| {
matches!( matches!(

View file

@ -1682,7 +1682,7 @@ impl Config {
} }
}, },
keywords: self.data.hover_documentation_keywords_enable, 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,
} }
} }