about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-ty/src/display.rs30
-rw-r--r--crates/hir/src/display.rs38
-rw-r--r--crates/ide/src/hover.rs1
-rw-r--r--crates/ide/src/hover/render.rs7
-rw-r--r--crates/ide/src/hover/tests.rs138
-rw-r--r--crates/ide/src/static_index.rs1
-rw-r--r--crates/rust-analyzer/src/config.rs5
-rw-r--r--docs/user/generated_config.adoc5
-rw-r--r--editors/code/package.json9
9 files changed, 206 insertions, 28 deletions
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index fe51ec3f821..328dea87ac1 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -63,6 +63,7 @@ pub struct HirFormatter<'a> {
     buf: String,
     curr_size: usize,
     pub(crate) max_size: Option<usize>,
+    pub limited_size: Option<usize>,
     omit_verbose_types: bool,
     closure_style: ClosureStyle,
     display_target: DisplayTarget,
@@ -86,6 +87,7 @@ pub trait HirDisplay {
         &'a self,
         db: &'a dyn HirDatabase,
         max_size: Option<usize>,
+        limited_size: Option<usize>,
         omit_verbose_types: bool,
         display_target: DisplayTarget,
         closure_style: ClosureStyle,
@@ -101,6 +103,7 @@ pub trait HirDisplay {
             db,
             t: self,
             max_size,
+            limited_size,
             omit_verbose_types,
             display_target,
             closure_style,
@@ -117,6 +120,7 @@ pub trait HirDisplay {
             db,
             t: self,
             max_size: None,
+            limited_size: None,
             omit_verbose_types: false,
             closure_style: ClosureStyle::ImplFn,
             display_target: DisplayTarget::Diagnostics,
@@ -137,6 +141,28 @@ pub trait HirDisplay {
             db,
             t: self,
             max_size,
+            limited_size: None,
+            omit_verbose_types: true,
+            closure_style: ClosureStyle::ImplFn,
+            display_target: DisplayTarget::Diagnostics,
+        }
+    }
+
+    ///  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`
+    fn display_limited<'a>(
+        &'a self,
+        db: &'a dyn HirDatabase,
+        limited_size: Option<usize>,
+    ) -> HirDisplayWrapper<'a, Self>
+    where
+        Self: Sized,
+    {
+        HirDisplayWrapper {
+            db,
+            t: self,
+            max_size: None,
+            limited_size,
             omit_verbose_types: true,
             closure_style: ClosureStyle::ImplFn,
             display_target: DisplayTarget::Diagnostics,
@@ -158,6 +184,7 @@ pub trait HirDisplay {
             buf: String::with_capacity(20),
             curr_size: 0,
             max_size: None,
+            limited_size: None,
             omit_verbose_types: false,
             closure_style: ClosureStyle::ImplFn,
             display_target: DisplayTarget::SourceCode { module_id, allow_opaque },
@@ -178,6 +205,7 @@ pub trait HirDisplay {
             db,
             t: self,
             max_size: None,
+            limited_size: None,
             omit_verbose_types: false,
             closure_style: ClosureStyle::ImplFn,
             display_target: DisplayTarget::Test,
@@ -295,6 +323,7 @@ pub struct HirDisplayWrapper<'a, T> {
     db: &'a dyn HirDatabase,
     t: &'a T,
     max_size: Option<usize>,
+    limited_size: Option<usize>,
     omit_verbose_types: bool,
     closure_style: ClosureStyle,
     display_target: DisplayTarget,
@@ -323,6 +352,7 @@ impl<T: HirDisplay> HirDisplayWrapper<'_, T> {
             buf: String::with_capacity(20),
             curr_size: 0,
             max_size: self.max_size,
+            limited_size: 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 30f402a79f3..20ba72d998c 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -17,10 +17,10 @@ use hir_ty::{
 };
 
 use crate::{
-    Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field,
-    Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, SelfParam,
-    Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias, TypeOrConstParam,
-    TypeParam, Union, Variant,
+    Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl,
+    Field, Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module,
+    SelfParam, Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias,
+    TypeOrConstParam, TypeParam, Union, Variant,
 };
 
 impl HirDisplay for Function {
@@ -595,6 +595,36 @@ impl HirDisplay for Trait {
         let def_id = GenericDefId::TraitId(self.id);
         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;
+                }
+            }
+            f.write_str("}")?;
+        }
+
         Ok(())
     }
 }
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 4a7350feb38..b6877c5e8ce 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -32,6 +32,7 @@ pub struct HoverConfig {
     pub documentation: bool,
     pub keywords: bool,
     pub format: HoverDocFormat,
+    pub trait_assoc_items_size: Option<usize>,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index 563e78253a8..f528bd512cc 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -406,7 +406,12 @@ pub(super) fn definition(
     config: &HoverConfig,
 ) -> Markup {
     let mod_path = definition_mod_path(db, &def);
-    let label = def.label(db);
+    let label = match def {
+        Definition::Trait(trait_) => {
+            trait_.display_limited(db, config.trait_assoc_items_size).to_string()
+        }
+        _ => def.label(db),
+    };
     let docs = def.docs(db, famous_defs);
     let value = (|| match def {
         Definition::Variant(it) => {
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index e63717e35a3..cec1375271e 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -17,6 +17,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig {
     documentation: true,
     format: HoverDocFormat::Markdown,
     keywords: true,
+    trait_assoc_items_size: None,
 };
 
 fn check_hover_no_result(ra_fixture: &str) {
@@ -411,7 +412,7 @@ fn main() {
                                 name: "FnOnce",
                                 kind: Trait,
                                 container_name: "function",
-                                description: "pub trait FnOnce<Args>\nwhere\n    Args: Tuple,",
+                                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}",
                             },
                         },
                     ],
@@ -2685,7 +2686,7 @@ fn main() { let s$0t = foo(); }
                                     focus_range: 6..9,
                                     name: "Foo",
                                     kind: Trait,
-                                    description: "trait Foo",
+                                    description: "trait Foo {}",
                                 },
                             },
                         ],
@@ -2719,7 +2720,7 @@ fn main() { let s$0t = foo(); }
                                     focus_range: 6..9,
                                     name: "Foo",
                                     kind: Trait,
-                                    description: "trait Foo<T>",
+                                    description: "trait Foo<T> {}",
                                 },
                             },
                             HoverGotoTypeData {
@@ -2766,7 +2767,7 @@ fn main() { let s$0t = foo(); }
                                 focus_range: 19..22,
                                 name: "Bar",
                                 kind: Trait,
-                                description: "trait Bar",
+                                description: "trait Bar {}",
                             },
                         },
                         HoverGotoTypeData {
@@ -2779,7 +2780,7 @@ fn main() { let s$0t = foo(); }
                                 focus_range: 6..9,
                                 name: "Foo",
                                 kind: Trait,
-                                description: "trait Foo",
+                                description: "trait Foo {}",
                             },
                         },
                     ],
@@ -2816,7 +2817,7 @@ fn main() { let s$0t = foo(); }
                                 focus_range: 22..25,
                                 name: "Bar",
                                 kind: Trait,
-                                description: "trait Bar<T>",
+                                description: "trait Bar<T> {}",
                             },
                         },
                         HoverGotoTypeData {
@@ -2829,7 +2830,7 @@ fn main() { let s$0t = foo(); }
                                 focus_range: 6..9,
                                 name: "Foo",
                                 kind: Trait,
-                                description: "trait Foo<T>",
+                                description: "trait Foo<T> {}",
                             },
                         },
                         HoverGotoTypeData {
@@ -2886,7 +2887,7 @@ fn foo(ar$0g: &impl Foo) {}
                                     focus_range: 6..9,
                                     name: "Foo",
                                     kind: Trait,
-                                    description: "trait Foo",
+                                    description: "trait Foo {}",
                                 },
                             },
                         ],
@@ -2920,7 +2921,7 @@ fn foo(ar$0g: &impl Foo + Bar<S>) {}
                                 focus_range: 19..22,
                                 name: "Bar",
                                 kind: Trait,
-                                description: "trait Bar<T>",
+                                description: "trait Bar<T> {}",
                             },
                         },
                         HoverGotoTypeData {
@@ -2933,7 +2934,7 @@ fn foo(ar$0g: &impl Foo + Bar<S>) {}
                                 focus_range: 6..9,
                                 name: "Foo",
                                 kind: Trait,
-                                description: "trait Foo",
+                                description: "trait Foo {}",
                             },
                         },
                         HoverGotoTypeData {
@@ -2988,7 +2989,7 @@ pub mod future {
                                 name: "Future",
                                 kind: Trait,
                                 container_name: "future",
-                                description: "pub trait Future",
+                                description: "pub trait Future {}",
                             },
                         },
                         HoverGotoTypeData {
@@ -3033,7 +3034,7 @@ fn foo(ar$0g: &impl Foo<S>) {}
                                     focus_range: 6..9,
                                     name: "Foo",
                                     kind: Trait,
-                                    description: "trait Foo<T>",
+                                    description: "trait Foo<T> {}",
                                 },
                             },
                             HoverGotoTypeData {
@@ -3096,7 +3097,7 @@ fn main() { let s$0t = foo(); }
                                     focus_range: 6..9,
                                     name: "Foo",
                                     kind: Trait,
-                                    description: "trait Foo",
+                                    description: "trait Foo {}",
                                 },
                             },
                         ],
@@ -3127,7 +3128,7 @@ fn foo(ar$0g: &dyn Foo) {}
                                     focus_range: 6..9,
                                     name: "Foo",
                                     kind: Trait,
-                                    description: "trait Foo",
+                                    description: "trait Foo {}",
                                 },
                             },
                         ],
@@ -3159,7 +3160,7 @@ fn foo(ar$0g: &dyn Foo<S>) {}
                                     focus_range: 6..9,
                                     name: "Foo",
                                     kind: Trait,
-                                    description: "trait Foo<T>",
+                                    description: "trait Foo<T> {}",
                                 },
                             },
                             HoverGotoTypeData {
@@ -3220,7 +3221,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
                                 focus_range: 28..36,
                                 name: "DynTrait",
                                 kind: Trait,
-                                description: "trait DynTrait<T>",
+                                description: "trait DynTrait<T> {}",
                             },
                         },
                         HoverGotoTypeData {
@@ -3233,7 +3234,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
                                 focus_range: 6..15,
                                 name: "ImplTrait",
                                 kind: Trait,
-                                description: "trait ImplTrait<T>",
+                                description: "trait ImplTrait<T> {}",
                             },
                         },
                         HoverGotoTypeData {
@@ -3288,7 +3289,7 @@ fn main() { let s$0t = test().get(); }
                                     focus_range: 6..9,
                                     name: "Foo",
                                     kind: Trait,
-                                    description: "trait Foo",
+                                    description: "trait Foo {\n    type Item,\n    fn get(self) -> Self::Item,\n}",
                                 },
                             },
                         ],
@@ -3353,7 +3354,7 @@ fn foo<T: Foo>(t: T$0){}
                                     focus_range: 6..9,
                                     name: "Foo",
                                     kind: Trait,
-                                    description: "trait Foo",
+                                    description: "trait Foo {}",
                                 },
                             },
                         ],
@@ -6328,6 +6329,99 @@ impl T for () {
 }
 
 #[test]
+fn hover_trait_show_assoc_items() {
+    check(
+        r#"
+trait T {}
+impl T$0 for () {}
+"#,
+        expect![[r#"
+        *T*
+
+        ```rust
+        test
+        ```
+
+        ```rust
+        trait T {}
+        ```
+        "#]],
+    );
+
+    check(
+        r#"
+trait T {
+    fn func() {}
+}
+impl T$0 for () {}
+"#,
+        expect![[r#"
+        *T*
+
+        ```rust
+        test
+        ```
+
+        ```rust
+        trait T {
+            fn func(),
+        }
+        ```
+        "#]],
+    );
+
+    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(
+        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,
+        }
+        ```
+        "#]],
+    );
+}
+
+#[test]
 fn hover_ranged_macro_call() {
     check_hover_range(
         r#"
@@ -7438,7 +7532,7 @@ impl Iterator for S {
                                 name: "Future",
                                 kind: Trait,
                                 container_name: "future",
-                                description: "pub trait Future",
+                                description: "pub trait Future {\n    pub type Output,\n    pub fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>,\n}",
                             },
                         },
                         HoverGotoTypeData {
@@ -7452,7 +7546,7 @@ impl Iterator for S {
                                 name: "Iterator",
                                 kind: Trait,
                                 container_name: "iterator",
-                                description: "pub trait 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}",
                             },
                         },
                         HoverGotoTypeData {
@@ -7465,7 +7559,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 2929a7522e5..0f19da0ac5f 100644
--- a/crates/ide/src/static_index.rs
+++ b/crates/ide/src/static_index.rs
@@ -166,6 +166,7 @@ impl StaticIndex<'_> {
             documentation: true,
             keywords: true,
             format: crate::HoverDocFormat::Markdown,
+            trait_assoc_items_size: None,
         };
         let tokens = tokens.filter(|token| {
             matches!(
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 0da6101b350..21a106bc770 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -375,6 +375,9 @@ config_data! {
         /// How to render the size information in a memory layout hover.
         hover_memoryLayout_size: Option<MemoryLayoutHoverRenderKindDef> = "\"both\"",
 
+        /// How many associated items of a trait to display when hovering a trait.
+        hover_show_traitAssocItems: Option<usize> = "null",
+
         /// Whether to enforce the import granularity setting for all files. If set to false rust-analyzer will try to keep import styles consistent per file.
         imports_granularity_enforce: bool              = "false",
         /// How imports should be grouped into use statements.
@@ -518,7 +521,6 @@ config_data! {
         /// Exclude tests from find-all-references.
         references_excludeTests: bool = "false",
 
-
         /// Command to be executed instead of 'cargo' for runnables.
         runnables_command: Option<String> = "null",
         /// Additional arguments to be passed to cargo for runnables such as
@@ -1680,6 +1682,7 @@ impl Config {
                 }
             },
             keywords: self.data.hover_documentation_keywords_enable,
+            trait_assoc_items_size: self.data.hover_show_traitAssocItems,
         }
     }
 
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index d4ba5af9231..0fb275961be 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -515,6 +515,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.traitAssocItems]]rust-analyzer.hover.show.traitAssocItems (default: `null`)::
++
+--
+How many associated items of a trait to display when hovering a trait.
+--
 [[rust-analyzer.imports.granularity.enforce]]rust-analyzer.imports.granularity.enforce (default: `false`)::
 +
 --
diff --git a/editors/code/package.json b/editors/code/package.json
index d86365591a6..3a276409fb6 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -1134,6 +1134,15 @@
                         }
                     ]
                 },
+                "rust-analyzer.hover.show.traitAssocItems": {
+                    "markdownDescription": "How many associated items of a trait to display when hovering a trait.",
+                    "default": null,
+                    "type": [
+                        "null",
+                        "integer"
+                    ],
+                    "minimum": 0
+                },
                 "rust-analyzer.imports.granularity.enforce": {
                     "markdownDescription": "Whether to enforce the import granularity setting for all files. If set to false rust-analyzer will try to keep import styles consistent per file.",
                     "default": false,