Unnamed repository; edit this file 'description' to name the repository.
Add const generics to doctest names for structt
Jonas Marcello 2023-02-28
parent 8bc75c4 · commit 9957bb3
-rw-r--r--crates/hir/src/lib.rs35
-rw-r--r--crates/ide/src/runnables.rs108
2 files changed, 141 insertions, 2 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 883838293e..369f9192d1 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -42,7 +42,7 @@ use hir_def::{
adt::VariantData,
body::{BodyDiagnostic, SyntheticSyntax},
expr::{BindingAnnotation, ExprOrPatId, LabelId, Pat, PatId},
- generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
+ generics::{ConstParamData, LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
item_tree::ItemTreeNode,
lang_item::{LangItem, LangItemTarget},
layout::{Layout, LayoutError, ReprOptions},
@@ -1189,6 +1189,31 @@ impl Adt {
.map(|arena| arena.1.clone())
}
+ /// Returns an iterator of all `const` generic paramaters
+ ///
+ /// This method is not well optimized, I could not statisfy the borrow
+ /// checker. I'm sure there are smarter ways to return the consts names
+ pub fn consts(&self, db: &dyn HirDatabase) -> impl Iterator<Item = ConstParamData> {
+ let resolver = match self {
+ Adt::Struct(s) => s.id.resolver(db.upcast()),
+ Adt::Union(u) => u.id.resolver(db.upcast()),
+ Adt::Enum(e) => e.id.resolver(db.upcast()),
+ };
+ resolver
+ .generic_params()
+ .map_or(vec![], |gp| {
+ gp.as_ref()
+ .type_or_consts
+ .iter()
+ .filter_map(|arena| match arena.1 {
+ TypeOrConstParamData::ConstParamData(consts) => Some(consts.clone()),
+ _ => None,
+ })
+ .collect::<Vec<ConstParamData>>()
+ })
+ .into_iter()
+ }
+
pub fn as_enum(&self) -> Option<Enum> {
if let Self::Enum(v) = self {
Some(*v)
@@ -3358,15 +3383,21 @@ impl Type {
.map(move |ty| self.derived(ty))
}
- /// Combines lifetime indicators and type arguments into a single `Iterator`
+ /// Combines lifetime indicators, type and constant parameters into a single `Iterator`
pub fn lifetime_and_type_arguments<'a>(
&'a self,
db: &'a dyn HirDatabase,
) -> impl Iterator<Item = SmolStr> + 'a {
+ // iterate the lifetime
self.as_adt()
.and_then(|a| a.lifetime(db).and_then(|lt| Some((&lt.name).to_smol_str())))
.into_iter()
+ // add the type paramaters
.chain(self.type_arguments().map(|ty| SmolStr::new(ty.display(db).to_string())))
+ // add const paramameters
+ .chain(self.as_adt().map_or(vec![], |a| {
+ a.consts(db).map(|cs| cs.name.to_smol_str()).collect::<Vec<SmolStr>>()
+ }))
}
pub fn iterate_method_candidates_with_traits<T>(
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index b0477e9678..7af969c5d0 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -1102,6 +1102,114 @@ impl<T, U> Data<'a, T, U> {
"#]],
);
}
+
+ #[test]
+ fn test_runnables_doc_test_in_impl_with_const() {
+ check(
+ r#"
+//- /lib.rs
+$0
+fn main() {}
+
+struct Data<const N: usize>;
+impl<const N: usize> Data<N> {
+ /// ```
+ /// let x = 5;
+ /// ```
+ fn foo() {}
+}
+"#,
+ &[Bin, DocTest],
+ expect![[r#"
+ [
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 1..13,
+ focus_range: 4..8,
+ name: "main",
+ kind: Function,
+ },
+ kind: Bin,
+ cfg: None,
+ },
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 79..133,
+ name: "foo",
+ },
+ kind: DocTest {
+ test_id: Path(
+ "Data<N>::foo",
+ ),
+ },
+ cfg: None,
+ },
+ ]
+ "#]],
+ );
+ }
+
+ #[test]
+ fn test_runnables_doc_test_in_impl_with_lifetime_types_and_const() {
+ check(
+ r#"
+//- /lib.rs
+$0
+fn main() {}
+
+struct Data<'a, T, const N: usize>;
+impl<'a, T, const N: usize> Data<'a, T, N> {
+ /// ```
+ /// let x = 5;
+ /// ```
+ fn foo() {}
+}
+"#,
+ &[Bin, DocTest],
+ expect![[r#"
+ [
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 1..13,
+ focus_range: 4..8,
+ name: "main",
+ kind: Function,
+ },
+ kind: Bin,
+ cfg: None,
+ },
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 100..154,
+ name: "foo",
+ },
+ kind: DocTest {
+ test_id: Path(
+ "Data<'a,T,N>::foo",
+ ),
+ },
+ cfg: None,
+ },
+ ]
+ "#]],
+ );
+ }
#[test]
fn test_runnables_module() {
check(