diff options
| author | Jonas Marcello <jonas.marcello@esbme.com> | 2023-02-19 22:07:33 +0100 |
|---|---|---|
| committer | Jonas Marcello <jonas.marcello@esbme.com> | 2023-02-27 18:08:17 +0100 |
| commit | 9942cc425ba31cf47ebf9498ed3cd58f064b2b89 (patch) | |
| tree | 94034fcbe184759f728f29a409da6586e7aea42c | |
| parent | c867cbf9b6aea8d73c433ed85c6619e7714f3f7f (diff) | |
| download | rust-9942cc425ba31cf47ebf9498ed3cd58f064b2b89.tar.gz rust-9942cc425ba31cf47ebf9498ed3cd58f064b2b89.zip | |
Fix 14142: Annotate lifetime paramaters in doctest runnables
| -rw-r--r-- | crates/hir-def/src/resolver.rs | 7 | ||||
| -rw-r--r-- | crates/hir/src/lib.rs | 37 | ||||
| -rw-r--r-- | crates/ide/src/runnables.rs | 117 |
3 files changed, 155 insertions, 6 deletions
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 86958e3daea..b2323915c1f 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -459,6 +459,13 @@ impl Resolver { }) } + pub fn generic_params(&self) -> Option<&Interned<GenericParams>> { + self.scopes().find_map(|scope| match scope { + Scope::GenericParams { params, .. } => Some(params), + _ => None, + }) + } + pub fn body_owner(&self) -> Option<DefWithBodyId> { self.scopes().find_map(|scope| match scope { Scope::ExprScope(it) => Some(it.owner), diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 6206a541c1e..28d87e14e15 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::{TypeOrConstParamData, TypeParamProvenance}, + generics::{TypeOrConstParamData, TypeParamProvenance, LifetimeParamData}, item_tree::ItemTreeNode, lang_item::{LangItem, LangItemTarget}, layout::{Layout, LayoutError, ReprOptions}, @@ -1170,6 +1170,22 @@ impl Adt { } } + /// Returns the lifetime of the DataType + pub fn lifetime(&self, db: &dyn HirDatabase) -> Option<LifetimeParamData> { + 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().and_then(|gp| { + (&gp.lifetimes) + .iter() + // there should only be a single lifetime + // but `Arena` requires to use an iterator + .nth(0) + }).map(|arena| arena.1.clone()) + } + pub fn as_enum(&self) -> Option<Enum> { if let Self::Enum(v) = self { Some(*v) @@ -3339,6 +3355,25 @@ impl Type { .map(move |ty| self.derived(ty)) } + /// Combines lifetime indicators and type arguments into a single `Vec<SmolStr>` + pub fn lifetime_and_type_arguments<'a>(&'a self, db: &'a dyn HirDatabase) -> Vec<SmolStr> { + let mut names = if let Some(lt) = self + .as_adt() + .and_then(|a| { + a.lifetime(db) + .and_then(|lt| Some((<.name).to_smol_str().clone())) + }) { + vec![lt] + } else { + vec![] + }; + + for ty in self.type_arguments() { + names.push(SmolStr::new(ty.display(db).to_string())) + } + names + } + pub fn iterate_method_candidates_with_traits<T>( &self, db: &dyn HirDatabase, diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index af53adee898..2e8f3906afc 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs @@ -2,7 +2,7 @@ use std::fmt; use ast::HasName; use cfg::CfgExpr; -use hir::{AsAssocItem, HasAttrs, HasSource, HirDisplay, Semantics}; +use hir::{AsAssocItem, HasAttrs, HasSource, Semantics}; use ide_assists::utils::test_related_attribute; use ide_db::{ base_db::{FilePosition, FileRange}, @@ -370,9 +370,9 @@ pub(crate) fn runnable_impl( let nav = def.try_to_nav(sema.db)?; let ty = def.self_ty(sema.db); let adt_name = ty.as_adt()?.name(sema.db); - let mut ty_args = ty.type_arguments().peekable(); + let mut ty_args = ty.lifetime_and_type_arguments(sema.db).into_iter().peekable(); let params = if ty_args.peek().is_some() { - format!("<{}>", ty_args.format_with(",", |ty, cb| cb(&ty.display(sema.db)))) + format!("<{}>", ty_args.format_with(",", |ty, cb| cb(&ty))) } else { String::new() }; @@ -436,13 +436,13 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option<Runnable> { let ty = imp.self_ty(db); if let Some(adt) = ty.as_adt() { let name = adt.name(db); - let mut ty_args = ty.type_arguments().peekable(); + let mut ty_args = ty.lifetime_and_type_arguments(db).into_iter().peekable(); format_to!(path, "{}", name); if ty_args.peek().is_some() { format_to!( path, "<{}>", - ty_args.format_with(",", |ty, cb| cb(&ty.display(db))) + ty_args.format_with(",", |ty, cb| cb(&ty)) ); } format_to!(path, "::{}", def_name); @@ -1000,6 +1000,113 @@ impl Data { } #[test] + fn test_runnables_doc_test_in_impl_with_lifetime() { + check( + r#" +//- /lib.rs +$0 +fn main() {} + +struct Data<'a>; +impl Data<'a> { + /// ``` + /// 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: 52..106, + name: "foo", + }, + kind: DocTest { + test_id: Path( + "Data<'a>::foo", + ), + }, + cfg: None, + }, + ] + "#]], + ); + } + + #[test] + fn test_runnables_doc_test_in_impl_with_lifetime_and_types() { + check( + r#" +//- /lib.rs +$0 +fn main() {} + +struct Data<'a, T, U>; +impl<T, U> Data<'a, T, U> { + /// ``` + /// 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: 70..124, + name: "foo", + }, + kind: DocTest { + test_id: Path( + "Data<'a,T,U>::foo", + ), + }, + cfg: None, + }, + ] + "#]], + ); + } + #[test] fn test_runnables_module() { check( r#" |
