aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-02-17 08:52:45 +0000
committerGitHub <[email protected]>2020-02-17 08:52:45 +0000
commitc9989a524caa3379aac4f451a452c7ac9b247ae8 (patch)
tree28029f0406b5c5d734a36a515d1d036cc0b59333 /crates
parentdd8fc5a61adf557afa2cd971039be10a83f6d503 (diff)
parentf0338cea5b3a214fe5e72eec68670b161530e1a6 (diff)
Merge #3153
3153: When a single test is run, do not run others with overlapping names r=matklad a=SomeoneToIgnore Co-authored-by: Kirill Bulatov <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_ide/src/lib.rs2
-rw-r--r--crates/ra_ide/src/runnables.rs109
-rw-r--r--crates/ra_lsp_server/src/cargo_target_spec.rs16
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs4
-rw-r--r--crates/ra_lsp_server/tests/heavy_tests/main.rs2
5 files changed, 100 insertions, 33 deletions
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index 689921f3f..9d66c365b 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -71,7 +71,7 @@ pub use crate::{
71 references::{ 71 references::{
72 Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult, SearchScope, 72 Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult, SearchScope,
73 }, 73 },
74 runnables::{Runnable, RunnableKind}, 74 runnables::{Runnable, RunnableKind, TestId},
75 source_change::{FileSystemEdit, SourceChange, SourceFileEdit}, 75 source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
76 syntax_highlighting::HighlightedRange, 76 syntax_highlighting::HighlightedRange,
77}; 77};
diff --git a/crates/ra_ide/src/runnables.rs b/crates/ra_ide/src/runnables.rs
index b6b0c70f9..be2a67d0a 100644
--- a/crates/ra_ide/src/runnables.rs
+++ b/crates/ra_ide/src/runnables.rs
@@ -1,6 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::InFile; 3use hir::{InFile, SourceBinder};
4use itertools::Itertools; 4use itertools::Itertools;
5use ra_db::SourceDatabase; 5use ra_db::SourceDatabase;
6use ra_ide_db::RootDatabase; 6use ra_ide_db::RootDatabase;
@@ -10,6 +10,7 @@ use ra_syntax::{
10}; 10};
11 11
12use crate::FileId; 12use crate::FileId;
13use std::fmt::Display;
13 14
14#[derive(Debug)] 15#[derive(Debug)]
15pub struct Runnable { 16pub struct Runnable {
@@ -18,38 +19,84 @@ pub struct Runnable {
18} 19}
19 20
20#[derive(Debug)] 21#[derive(Debug)]
22pub enum TestId {
23 Name(String),
24 Path(String),
25}
26
27impl Display for TestId {
28 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
29 match self {
30 TestId::Name(name) => write!(f, "{}", name),
31 TestId::Path(path) => write!(f, "{}", path),
32 }
33 }
34}
35
36#[derive(Debug)]
21pub enum RunnableKind { 37pub enum RunnableKind {
22 Test { name: String }, 38 Test { test_id: TestId },
23 TestMod { path: String }, 39 TestMod { path: String },
24 Bench { name: String }, 40 Bench { test_id: TestId },
25 Bin, 41 Bin,
26} 42}
27 43
28pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> { 44pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
29 let parse = db.parse(file_id); 45 let parse = db.parse(file_id);
30 parse.tree().syntax().descendants().filter_map(|i| runnable(db, file_id, i)).collect() 46 let mut sb = SourceBinder::new(db);
47 parse.tree().syntax().descendants().filter_map(|i| runnable(db, &mut sb, file_id, i)).collect()
31} 48}
32 49
33fn runnable(db: &RootDatabase, file_id: FileId, item: SyntaxNode) -> Option<Runnable> { 50fn runnable(
51 db: &RootDatabase,
52 source_binder: &mut SourceBinder<RootDatabase>,
53 file_id: FileId,
54 item: SyntaxNode,
55) -> Option<Runnable> {
34 match_ast! { 56 match_ast! {
35 match item { 57 match item {
36 ast::FnDef(it) => { runnable_fn(it) }, 58 ast::FnDef(it) => { runnable_fn(db, source_binder, file_id, it) },
37 ast::Module(it) => { runnable_mod(db, file_id, it) }, 59 ast::Module(it) => { runnable_mod(db, source_binder, file_id, it) },
38 _ => { None }, 60 _ => { None },
39 } 61 }
40 } 62 }
41} 63}
42 64
43fn runnable_fn(fn_def: ast::FnDef) -> Option<Runnable> { 65fn runnable_fn(
44 let name = fn_def.name()?.text().clone(); 66 db: &RootDatabase,
45 let kind = if name == "main" { 67 source_binder: &mut SourceBinder<RootDatabase>,
68 file_id: FileId,
69 fn_def: ast::FnDef,
70) -> Option<Runnable> {
71 let name_string = fn_def.name()?.text().to_string();
72
73 let kind = if name_string == "main" {
46 RunnableKind::Bin 74 RunnableKind::Bin
47 } else if has_test_related_attribute(&fn_def) {
48 RunnableKind::Test { name: name.to_string() }
49 } else if fn_def.has_atom_attr("bench") {
50 RunnableKind::Bench { name: name.to_string() }
51 } else { 75 } else {
52 return None; 76 let test_id = if let Some(module) = source_binder
77 .to_def(InFile::new(file_id.into(), fn_def.clone()))
78 .map(|def| def.module(db))
79 {
80 let path = module
81 .path_to_root(db)
82 .into_iter()
83 .rev()
84 .filter_map(|it| it.name(db))
85 .map(|name| name.to_string())
86 .chain(std::iter::once(name_string))
87 .join("::");
88 TestId::Path(path)
89 } else {
90 TestId::Name(name_string)
91 };
92
93 if has_test_related_attribute(&fn_def) {
94 RunnableKind::Test { test_id }
95 } else if fn_def.has_atom_attr("bench") {
96 RunnableKind::Bench { test_id }
97 } else {
98 return None;
99 }
53 }; 100 };
54 Some(Runnable { range: fn_def.syntax().text_range(), kind }) 101 Some(Runnable { range: fn_def.syntax().text_range(), kind })
55} 102}
@@ -68,7 +115,12 @@ fn has_test_related_attribute(fn_def: &ast::FnDef) -> bool {
68 .any(|attribute_text| attribute_text.contains("test")) 115 .any(|attribute_text| attribute_text.contains("test"))
69} 116}
70 117
71fn runnable_mod(db: &RootDatabase, file_id: FileId, module: ast::Module) -> Option<Runnable> { 118fn runnable_mod(
119 db: &RootDatabase,
120 source_binder: &mut SourceBinder<RootDatabase>,
121 file_id: FileId,
122 module: ast::Module,
123) -> Option<Runnable> {
72 let has_test_function = module 124 let has_test_function = module
73 .item_list()? 125 .item_list()?
74 .items() 126 .items()
@@ -76,13 +128,12 @@ fn runnable_mod(db: &RootDatabase, file_id: FileId, module: ast::Module) -> Opti
76 ast::ModuleItem::FnDef(it) => Some(it), 128 ast::ModuleItem::FnDef(it) => Some(it),
77 _ => None, 129 _ => None,
78 }) 130 })
79 .any(|f| f.has_atom_attr("test")); 131 .any(|f| has_test_related_attribute(&f));
80 if !has_test_function { 132 if !has_test_function {
81 return None; 133 return None;
82 } 134 }
83 let range = module.syntax().text_range(); 135 let range = module.syntax().text_range();
84 let mut sb = hir::SourceBinder::new(db); 136 let module = source_binder.to_def(InFile::new(file_id.into(), module))?;
85 let module = sb.to_def(InFile::new(file_id.into(), module))?;
86 137
87 let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::"); 138 let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::");
88 Some(Runnable { range, kind: RunnableKind::TestMod { path } }) 139 Some(Runnable { range, kind: RunnableKind::TestMod { path } })
@@ -121,13 +172,17 @@ mod tests {
121 Runnable { 172 Runnable {
122 range: [22; 46), 173 range: [22; 46),
123 kind: Test { 174 kind: Test {
124 name: "test_foo", 175 test_id: Path(
176 "test_foo",
177 ),
125 }, 178 },
126 }, 179 },
127 Runnable { 180 Runnable {
128 range: [47; 81), 181 range: [47; 81),
129 kind: Test { 182 kind: Test {
130 name: "test_foo", 183 test_id: Path(
184 "test_foo",
185 ),
131 }, 186 },
132 }, 187 },
133 ] 188 ]
@@ -160,7 +215,9 @@ mod tests {
160 Runnable { 215 Runnable {
161 range: [28; 57), 216 range: [28; 57),
162 kind: Test { 217 kind: Test {
163 name: "test_foo1", 218 test_id: Path(
219 "test_mod::test_foo1",
220 ),
164 }, 221 },
165 }, 222 },
166 ] 223 ]
@@ -195,7 +252,9 @@ mod tests {
195 Runnable { 252 Runnable {
196 range: [46; 79), 253 range: [46; 79),
197 kind: Test { 254 kind: Test {
198 name: "test_foo1", 255 test_id: Path(
256 "foo::test_mod::test_foo1",
257 ),
199 }, 258 },
200 }, 259 },
201 ] 260 ]
@@ -232,7 +291,9 @@ mod tests {
232 Runnable { 291 Runnable {
233 range: [68; 105), 292 range: [68; 105),
234 kind: Test { 293 kind: Test {
235 name: "test_foo1", 294 test_id: Path(
295 "foo::bar::test_mod::test_foo1",
296 ),
236 }, 297 },
237 }, 298 },
238 ] 299 ]
diff --git a/crates/ra_lsp_server/src/cargo_target_spec.rs b/crates/ra_lsp_server/src/cargo_target_spec.rs
index 594caffe2..5fd1e7b6b 100644
--- a/crates/ra_lsp_server/src/cargo_target_spec.rs
+++ b/crates/ra_lsp_server/src/cargo_target_spec.rs
@@ -1,6 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use ra_ide::{FileId, RunnableKind}; 3use ra_ide::{FileId, RunnableKind, TestId};
4use ra_project_model::{self, ProjectWorkspace, TargetKind}; 4use ra_project_model::{self, ProjectWorkspace, TargetKind};
5 5
6use crate::{world::WorldSnapshot, Result}; 6use crate::{world::WorldSnapshot, Result};
@@ -13,13 +13,16 @@ pub(crate) fn runnable_args(
13 let spec = CargoTargetSpec::for_file(world, file_id)?; 13 let spec = CargoTargetSpec::for_file(world, file_id)?;
14 let mut res = Vec::new(); 14 let mut res = Vec::new();
15 match kind { 15 match kind {
16 RunnableKind::Test { name } => { 16 RunnableKind::Test { test_id } => {
17 res.push("test".to_string()); 17 res.push("test".to_string());
18 if let Some(spec) = spec { 18 if let Some(spec) = spec {
19 spec.push_to(&mut res); 19 spec.push_to(&mut res);
20 } 20 }
21 res.push("--".to_string()); 21 res.push("--".to_string());
22 res.push(name.to_string()); 22 res.push(test_id.to_string());
23 if let TestId::Path(_) = test_id {
24 res.push("--exact".to_string());
25 }
23 res.push("--nocapture".to_string()); 26 res.push("--nocapture".to_string());
24 } 27 }
25 RunnableKind::TestMod { path } => { 28 RunnableKind::TestMod { path } => {
@@ -31,13 +34,16 @@ pub(crate) fn runnable_args(
31 res.push(path.to_string()); 34 res.push(path.to_string());
32 res.push("--nocapture".to_string()); 35 res.push("--nocapture".to_string());
33 } 36 }
34 RunnableKind::Bench { name } => { 37 RunnableKind::Bench { test_id } => {
35 res.push("bench".to_string()); 38 res.push("bench".to_string());
36 if let Some(spec) = spec { 39 if let Some(spec) = spec {
37 spec.push_to(&mut res); 40 spec.push_to(&mut res);
38 } 41 }
39 res.push("--".to_string()); 42 res.push("--".to_string());
40 res.push(name.to_string()); 43 res.push(test_id.to_string());
44 if let TestId::Path(_) = test_id {
45 res.push("--exact".to_string());
46 }
41 res.push("--nocapture".to_string()); 47 res.push("--nocapture".to_string());
42 } 48 }
43 RunnableKind::Bin => { 49 RunnableKind::Bin => {
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 2e598fdcd..5879a1f7a 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -918,9 +918,9 @@ fn to_lsp_runnable(
918 let args = runnable_args(world, file_id, &runnable.kind)?; 918 let args = runnable_args(world, file_id, &runnable.kind)?;
919 let line_index = world.analysis().file_line_index(file_id)?; 919 let line_index = world.analysis().file_line_index(file_id)?;
920 let label = match &runnable.kind { 920 let label = match &runnable.kind {
921 RunnableKind::Test { name } => format!("test {}", name), 921 RunnableKind::Test { test_id } => format!("test {}", test_id),
922 RunnableKind::TestMod { path } => format!("test-mod {}", path), 922 RunnableKind::TestMod { path } => format!("test-mod {}", path),
923 RunnableKind::Bench { name } => format!("bench {}", name), 923 RunnableKind::Bench { test_id } => format!("bench {}", test_id),
924 RunnableKind::Bin => "run binary".to_string(), 924 RunnableKind::Bin => "run binary".to_string(),
925 }; 925 };
926 Ok(req::Runnable { 926 Ok(req::Runnable {
diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs
index dff63a12d..9ca31cbcc 100644
--- a/crates/ra_lsp_server/tests/heavy_tests/main.rs
+++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs
@@ -147,7 +147,7 @@ fn main() {}
147 }, 147 },
148 json!([ 148 json!([
149 { 149 {
150 "args": [ "test", "--package", "foo", "--test", "spam", "--", "test_eggs", "--nocapture" ], 150 "args": [ "test", "--package", "foo", "--test", "spam", "--", "test_eggs", "--exact", "--nocapture" ],
151 "bin": "cargo", 151 "bin": "cargo",
152 "env": { "RUST_BACKTRACE": "short" }, 152 "env": { "RUST_BACKTRACE": "short" },
153 "label": "test test_eggs", 153 "label": "test test_eggs",