From d837a5d5a7514afb89fed7ac9c9971f0c3337ba4 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 13 Jul 2021 18:55:06 +0200 Subject: [PATCH] Show test mod runnable in outline modules --- crates/ide/src/runnables.rs | 118 +++++++++++++++++- crates/rust-analyzer/tests/slow-tests/main.rs | 43 +++++++ 2 files changed, 155 insertions(+), 6 deletions(-) diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index 51c01ea31dd..ff9b203e9f7 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs @@ -16,7 +16,10 @@ use rustc_hash::{FxHashMap, FxHashSet}; use stdx::{always, format_to}; use syntax::ast::{self, AstNode, AttrsOwner}; -use crate::{display::TryToNav, references, FileId, NavigationTarget}; +use crate::{ + display::{ToNav, TryToNav}, + references, FileId, NavigationTarget, +}; #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Runnable { @@ -176,6 +179,10 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec { } }); + sema.to_module_defs(file_id) + .map(|it| runnable_mod_outline_definition(&sema, it)) + .for_each(|it| add_opt(it, None)); + res.extend(in_macro_expansion.into_iter().flat_map(|(_, runnables)| { let use_name_in_title = runnables.len() != 1; runnables.into_iter().map(move |mut r| { @@ -351,6 +358,30 @@ pub(crate) fn runnable_impl(sema: &Semantics, def: &hir::Impl) -> Some(Runnable { use_name_in_title: false, nav, kind: RunnableKind::DocTest { test_id }, cfg }) } +/// Creates a test mod runnable for outline modules at the top of their definition. +fn runnable_mod_outline_definition( + sema: &Semantics, + def: hir::Module, +) -> Option { + if !has_test_function_or_multiple_test_submodules(sema, &def) { + return None; + } + let path = + def.path_to_root(sema.db).into_iter().rev().filter_map(|it| it.name(sema.db)).join("::"); + + let attrs = def.attrs(sema.db); + let cfg = attrs.cfg(); + match def.definition_source(sema.db).value { + hir::ModuleSource::SourceFile(_) => Some(Runnable { + use_name_in_title: false, + nav: def.to_nav(sema.db), + kind: RunnableKind::TestMod { path }, + cfg, + }), + _ => None, + } +} + fn module_def_doctest(sema: &Semantics, def: hir::ModuleDef) -> Option { let attrs = match def { hir::ModuleDef::Module(it) => it.attrs(sema.db), @@ -541,7 +572,7 @@ mod not_a_root { fn main() {} } "#, - &[Bin, Test, Test, Bench], + &[Bin, Test, Test, Bench, TestMod], expect![[r#" [ Runnable { @@ -618,6 +649,21 @@ mod not_a_root { }, cfg: None, }, + Runnable { + use_name_in_title: false, + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..137, + name: "", + kind: Module, + }, + kind: TestMod { + path: "", + }, + cfg: None, + }, ] "#]], ); @@ -1143,7 +1189,7 @@ $0 #[cfg(feature = "foo")] fn test_foo1() {} "#, - &[Test], + &[Test, TestMod], expect![[r#" [ Runnable { @@ -1174,6 +1220,21 @@ fn test_foo1() {} ), ), }, + Runnable { + use_name_in_title: false, + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..51, + name: "", + kind: Module, + }, + kind: TestMod { + path: "", + }, + cfg: None, + }, ] "#]], ); @@ -1189,7 +1250,7 @@ $0 #[cfg(all(feature = "foo", feature = "bar"))] fn test_foo1() {} "#, - &[Test], + &[Test, TestMod], expect![[r#" [ Runnable { @@ -1230,6 +1291,21 @@ fn test_foo1() {} ), ), }, + Runnable { + use_name_in_title: false, + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..73, + name: "", + kind: Module, + }, + kind: TestMod { + path: "", + }, + cfg: None, + }, ] "#]], ); @@ -1316,7 +1392,7 @@ mod tests { } gen2!(); "#, - &[TestMod, TestMod, Test, Test], + &[TestMod, TestMod, TestMod, Test, Test], expect![[r#" [ Runnable { @@ -1336,6 +1412,21 @@ gen2!(); }, cfg: None, }, + Runnable { + use_name_in_title: false, + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..237, + name: "", + kind: Module, + }, + kind: TestMod { + path: "", + }, + cfg: None, + }, Runnable { use_name_in_title: true, nav: NavigationTarget { @@ -1579,7 +1670,7 @@ fn t0() {} #[test] fn t1() {} "#, - &[Test, Test], + &[Test, Test, TestMod], expect![[r#" [ Runnable { @@ -1624,6 +1715,21 @@ fn t1() {} }, cfg: None, }, + Runnable { + use_name_in_title: false, + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..39, + name: "m", + kind: Module, + }, + kind: TestMod { + path: "m", + }, + cfg: None, + }, ] "#]], ); diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs index cfc7ca0a37e..f92902e2e74 100644 --- a/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/crates/rust-analyzer/tests/slow-tests/main.rs @@ -133,6 +133,49 @@ fn main() {} "targetUri": "file:///[..]/tests/spam.rs" } }, + { + "args": { + "overrideCargo": null, + "workspaceRoot": server.path().join("foo"), + "cargoArgs": [ + "test", + "--package", + "foo", + "--test", + "spam" + ], + "cargoExtraArgs": [], + "executableArgs": [ + "", + "--nocapture" + ] + }, + "kind": "cargo", + "label": "test-mod ", + "location": { + "targetUri": "file:///[..]/tests/spam.rs", + "targetRange": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 3, + "character": 0 + } + }, + "targetSelectionRange": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 3, + "character": 0 + } + } + }, + }, { "args": { "cargoArgs": ["check", "--package", "foo", "--all-targets"],