From 94b2330f55af69d3cada685a9beff0236c9d92ee Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Tue, 27 Oct 2020 10:07:33 +0100 Subject: add doctest runnables on struct #6356 Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/ide/src/runnables.rs | 70 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 3 deletions(-) (limited to 'crates') diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index eb82456ad..876ee4c5e 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs @@ -102,6 +102,7 @@ pub(crate) fn runnable( ) -> Option { match_ast! { match item { + ast::Struct(it) => runnable_struct(sema, it, file_id), ast::Fn(it) => runnable_fn(sema, it, file_id), ast::Module(it) => runnable_mod(sema, it, file_id), _ => None, @@ -182,6 +183,43 @@ fn runnable_fn( Some(Runnable { nav, kind, cfg }) } +fn runnable_struct( + sema: &Semantics, + struct_def: ast::Struct, + file_id: FileId, +) -> Option { + if !has_runnable_doc_test(&struct_def) { + return None; + } + let name_string = struct_def.name()?.text().to_string(); + + let attrs = + Attrs::from_attrs_owner(sema.db, InFile::new(HirFileId::from(file_id), &struct_def)); + let cfg = attrs.cfg(); + + let test_id = match sema.to_def(&struct_def).map(|def| def.module(sema.db)) { + Some(module) => { + let path_iter = module + .path_to_root(sema.db) + .into_iter() + .rev() + .filter_map(|it| it.name(sema.db)) + .map(|name| name.to_string()); + let path = path_iter.chain(std::iter::once(name_string)).join("::"); + + TestId::Path(path) + } + None => TestId::Name(name_string), + }; + + let nav = NavigationTarget::from_doc_commented( + sema.db, + InFile::new(file_id.into(), &struct_def), + InFile::new(file_id.into(), &struct_def), + ); + Some(Runnable { nav, kind: RunnableKind::DocTest { test_id }, cfg }) +} + #[derive(Debug, Copy, Clone)] pub struct TestAttr { pub ignore: bool, @@ -215,8 +253,8 @@ const RUSTDOC_FENCE: &str = "```"; const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE: &[&str] = &["", "rust", "should_panic", "edition2015", "edition2018"]; -fn has_runnable_doc_test(fn_def: &ast::Fn) -> bool { - fn_def.doc_comment_text().map_or(false, |comments_text| { +fn has_runnable_doc_test(def: &T) -> bool { + def.doc_comment_text().map_or(false, |comments_text| { let mut in_code_block = false; for line in comments_text.lines() { @@ -487,8 +525,14 @@ fn should_have_no_runnable_5() {} /// let z = 55; /// ``` fn should_have_no_runnable_6() {} + +/// ``` +/// let x = 5; +/// ``` +struct StructWithRunnable(String); + "#, - &[&BIN, &DOCTEST, &DOCTEST, &DOCTEST], + &[&BIN, &DOCTEST, &DOCTEST, &DOCTEST, &DOCTEST], expect![[r#" [ Runnable { @@ -569,6 +613,26 @@ fn should_have_no_runnable_6() {} }, cfg: None, }, + Runnable { + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 756..821, + focus_range: None, + name: "StructWithRunnable", + kind: STRUCT, + container_name: None, + description: None, + docs: None, + }, + kind: DocTest { + test_id: Path( + "StructWithRunnable", + ), + }, + cfg: None, + }, ] "#]], ); -- cgit v1.2.3