mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 06:11:35 +00:00
If possible, use --exact flag when running tests
This commit is contained in:
parent
9ba801befd
commit
426c0f26fe
4 changed files with 101 additions and 32 deletions
|
@ -71,7 +71,7 @@ pub use crate::{
|
||||||
references::{
|
references::{
|
||||||
Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult, SearchScope,
|
Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult, SearchScope,
|
||||||
},
|
},
|
||||||
runnables::{Runnable, RunnableKind},
|
runnables::{Runnable, RunnableKind, TestId},
|
||||||
source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
|
source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
|
||||||
syntax_highlighting::HighlightedRange,
|
syntax_highlighting::HighlightedRange,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! FIXME: write short doc here
|
//! FIXME: write short doc here
|
||||||
|
|
||||||
use hir::InFile;
|
use hir::{InFile, SourceBinder};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use ra_db::SourceDatabase;
|
use ra_db::SourceDatabase;
|
||||||
use ra_ide_db::RootDatabase;
|
use ra_ide_db::RootDatabase;
|
||||||
|
@ -10,6 +10,7 @@ use ra_syntax::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::FileId;
|
use crate::FileId;
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Runnable {
|
pub struct Runnable {
|
||||||
|
@ -17,39 +18,87 @@ pub struct Runnable {
|
||||||
pub kind: RunnableKind,
|
pub kind: RunnableKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum TestId {
|
||||||
|
Name(String),
|
||||||
|
Path(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for TestId {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
TestId::Name(name) => write!(f, "{}", name),
|
||||||
|
TestId::Path(path) => write!(f, "{}", path),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum RunnableKind {
|
pub enum RunnableKind {
|
||||||
Test { name: String },
|
Test { test_id: TestId },
|
||||||
TestMod { path: String },
|
TestMod { path: String },
|
||||||
Bench { name: String },
|
Bench { test_id: TestId },
|
||||||
Bin,
|
Bin,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
|
pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
|
||||||
let parse = db.parse(file_id);
|
let parse = db.parse(file_id);
|
||||||
parse.tree().syntax().descendants().filter_map(|i| runnable(db, file_id, i)).collect()
|
let mut sb = SourceBinder::new(db);
|
||||||
|
parse.tree().syntax().descendants().filter_map(|i| runnable(db, &mut sb, file_id, i)).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runnable(db: &RootDatabase, file_id: FileId, item: SyntaxNode) -> Option<Runnable> {
|
fn runnable(
|
||||||
|
db: &RootDatabase,
|
||||||
|
source_binder: &mut SourceBinder<RootDatabase>,
|
||||||
|
file_id: FileId,
|
||||||
|
item: SyntaxNode,
|
||||||
|
) -> Option<Runnable> {
|
||||||
match_ast! {
|
match_ast! {
|
||||||
match item {
|
match item {
|
||||||
ast::FnDef(it) => { runnable_fn(it) },
|
ast::FnDef(it) => { runnable_fn(db, source_binder, file_id, it) },
|
||||||
ast::Module(it) => { runnable_mod(db, file_id, it) },
|
ast::Module(it) => { runnable_mod(db, source_binder, file_id, it) },
|
||||||
_ => { None },
|
_ => { None },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runnable_fn(fn_def: ast::FnDef) -> Option<Runnable> {
|
fn runnable_fn(
|
||||||
let name = fn_def.name()?.text().clone();
|
db: &RootDatabase,
|
||||||
let kind = if name == "main" {
|
source_binder: &mut SourceBinder<RootDatabase>,
|
||||||
|
file_id: FileId,
|
||||||
|
fn_def: ast::FnDef,
|
||||||
|
) -> Option<Runnable> {
|
||||||
|
let name_string = fn_def.name()?.text().to_string();
|
||||||
|
|
||||||
|
let kind = if name_string == "main" {
|
||||||
RunnableKind::Bin
|
RunnableKind::Bin
|
||||||
} else if has_test_related_attribute(&fn_def) {
|
|
||||||
RunnableKind::Test { name: name.to_string() }
|
|
||||||
} else if fn_def.has_atom_attr("bench") {
|
|
||||||
RunnableKind::Bench { name: name.to_string() }
|
|
||||||
} else {
|
} else {
|
||||||
return None;
|
let test_id = if let Some(module) = fn_def
|
||||||
|
.syntax()
|
||||||
|
.ancestors()
|
||||||
|
.find_map(ast::Module::cast)
|
||||||
|
.and_then(|module| source_binder.to_def(InFile::new(file_id.into(), module)))
|
||||||
|
{
|
||||||
|
let path = module
|
||||||
|
.path_to_root(db)
|
||||||
|
.into_iter()
|
||||||
|
.rev()
|
||||||
|
.filter_map(|it| it.name(db))
|
||||||
|
.map(|name| name.to_string())
|
||||||
|
.chain(std::iter::once(name_string))
|
||||||
|
.join("::");
|
||||||
|
TestId::Path(path)
|
||||||
|
} else {
|
||||||
|
TestId::Name(name_string)
|
||||||
|
};
|
||||||
|
|
||||||
|
if has_test_related_attribute(&fn_def) {
|
||||||
|
RunnableKind::Test { test_id }
|
||||||
|
} else if fn_def.has_atom_attr("bench") {
|
||||||
|
RunnableKind::Bench { test_id }
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Some(Runnable { range: fn_def.syntax().text_range(), kind })
|
Some(Runnable { range: fn_def.syntax().text_range(), kind })
|
||||||
}
|
}
|
||||||
|
@ -68,7 +117,12 @@ fn has_test_related_attribute(fn_def: &ast::FnDef) -> bool {
|
||||||
.any(|attribute_text| attribute_text.contains("test"))
|
.any(|attribute_text| attribute_text.contains("test"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runnable_mod(db: &RootDatabase, file_id: FileId, module: ast::Module) -> Option<Runnable> {
|
fn runnable_mod(
|
||||||
|
db: &RootDatabase,
|
||||||
|
source_binder: &mut SourceBinder<RootDatabase>,
|
||||||
|
file_id: FileId,
|
||||||
|
module: ast::Module,
|
||||||
|
) -> Option<Runnable> {
|
||||||
let has_test_function = module
|
let has_test_function = module
|
||||||
.item_list()?
|
.item_list()?
|
||||||
.items()
|
.items()
|
||||||
|
@ -76,13 +130,12 @@ fn runnable_mod(db: &RootDatabase, file_id: FileId, module: ast::Module) -> Opti
|
||||||
ast::ModuleItem::FnDef(it) => Some(it),
|
ast::ModuleItem::FnDef(it) => Some(it),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.any(|f| f.has_atom_attr("test"));
|
.any(|f| has_test_related_attribute(&f));
|
||||||
if !has_test_function {
|
if !has_test_function {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let range = module.syntax().text_range();
|
let range = module.syntax().text_range();
|
||||||
let mut sb = hir::SourceBinder::new(db);
|
let module = source_binder.to_def(InFile::new(file_id.into(), module))?;
|
||||||
let module = sb.to_def(InFile::new(file_id.into(), module))?;
|
|
||||||
|
|
||||||
let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::");
|
let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::");
|
||||||
Some(Runnable { range, kind: RunnableKind::TestMod { path } })
|
Some(Runnable { range, kind: RunnableKind::TestMod { path } })
|
||||||
|
@ -121,13 +174,17 @@ mod tests {
|
||||||
Runnable {
|
Runnable {
|
||||||
range: [22; 46),
|
range: [22; 46),
|
||||||
kind: Test {
|
kind: Test {
|
||||||
name: "test_foo",
|
test_id: Name(
|
||||||
|
"test_foo",
|
||||||
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Runnable {
|
Runnable {
|
||||||
range: [47; 81),
|
range: [47; 81),
|
||||||
kind: Test {
|
kind: Test {
|
||||||
name: "test_foo",
|
test_id: Name(
|
||||||
|
"test_foo",
|
||||||
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -160,7 +217,9 @@ mod tests {
|
||||||
Runnable {
|
Runnable {
|
||||||
range: [28; 57),
|
range: [28; 57),
|
||||||
kind: Test {
|
kind: Test {
|
||||||
name: "test_foo1",
|
test_id: Path(
|
||||||
|
"test_mod::test_foo1",
|
||||||
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -195,7 +254,9 @@ mod tests {
|
||||||
Runnable {
|
Runnable {
|
||||||
range: [46; 79),
|
range: [46; 79),
|
||||||
kind: Test {
|
kind: Test {
|
||||||
name: "test_foo1",
|
test_id: Path(
|
||||||
|
"foo::test_mod::test_foo1",
|
||||||
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -232,7 +293,9 @@ mod tests {
|
||||||
Runnable {
|
Runnable {
|
||||||
range: [68; 105),
|
range: [68; 105),
|
||||||
kind: Test {
|
kind: Test {
|
||||||
name: "test_foo1",
|
test_id: Path(
|
||||||
|
"foo::bar::test_mod::test_foo1",
|
||||||
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! FIXME: write short doc here
|
//! FIXME: write short doc here
|
||||||
|
|
||||||
use ra_ide::{FileId, RunnableKind};
|
use ra_ide::{FileId, RunnableKind, TestId};
|
||||||
use ra_project_model::{self, ProjectWorkspace, TargetKind};
|
use ra_project_model::{self, ProjectWorkspace, TargetKind};
|
||||||
|
|
||||||
use crate::{world::WorldSnapshot, Result};
|
use crate::{world::WorldSnapshot, Result};
|
||||||
|
@ -13,13 +13,16 @@ pub(crate) fn runnable_args(
|
||||||
let spec = CargoTargetSpec::for_file(world, file_id)?;
|
let spec = CargoTargetSpec::for_file(world, file_id)?;
|
||||||
let mut res = Vec::new();
|
let mut res = Vec::new();
|
||||||
match kind {
|
match kind {
|
||||||
RunnableKind::Test { name } => {
|
RunnableKind::Test { test_id } => {
|
||||||
res.push("test".to_string());
|
res.push("test".to_string());
|
||||||
if let Some(spec) = spec {
|
if let Some(spec) = spec {
|
||||||
spec.push_to(&mut res);
|
spec.push_to(&mut res);
|
||||||
}
|
}
|
||||||
res.push("--".to_string());
|
res.push("--".to_string());
|
||||||
res.push(name.to_string());
|
res.push(test_id.to_string());
|
||||||
|
if let TestId::Path(_) = test_id {
|
||||||
|
res.push("--exact".to_string());
|
||||||
|
}
|
||||||
res.push("--nocapture".to_string());
|
res.push("--nocapture".to_string());
|
||||||
}
|
}
|
||||||
RunnableKind::TestMod { path } => {
|
RunnableKind::TestMod { path } => {
|
||||||
|
@ -31,13 +34,16 @@ pub(crate) fn runnable_args(
|
||||||
res.push(path.to_string());
|
res.push(path.to_string());
|
||||||
res.push("--nocapture".to_string());
|
res.push("--nocapture".to_string());
|
||||||
}
|
}
|
||||||
RunnableKind::Bench { name } => {
|
RunnableKind::Bench { test_id } => {
|
||||||
res.push("bench".to_string());
|
res.push("bench".to_string());
|
||||||
if let Some(spec) = spec {
|
if let Some(spec) = spec {
|
||||||
spec.push_to(&mut res);
|
spec.push_to(&mut res);
|
||||||
}
|
}
|
||||||
res.push("--".to_string());
|
res.push("--".to_string());
|
||||||
res.push(name.to_string());
|
res.push(test_id.to_string());
|
||||||
|
if let TestId::Path(_) = test_id {
|
||||||
|
res.push("--exact".to_string());
|
||||||
|
}
|
||||||
res.push("--nocapture".to_string());
|
res.push("--nocapture".to_string());
|
||||||
}
|
}
|
||||||
RunnableKind::Bin => {
|
RunnableKind::Bin => {
|
||||||
|
|
|
@ -918,9 +918,9 @@ fn to_lsp_runnable(
|
||||||
let args = runnable_args(world, file_id, &runnable.kind)?;
|
let args = runnable_args(world, file_id, &runnable.kind)?;
|
||||||
let line_index = world.analysis().file_line_index(file_id)?;
|
let line_index = world.analysis().file_line_index(file_id)?;
|
||||||
let label = match &runnable.kind {
|
let label = match &runnable.kind {
|
||||||
RunnableKind::Test { name } => format!("test {}", name),
|
RunnableKind::Test { test_id } => format!("test {}", test_id),
|
||||||
RunnableKind::TestMod { path } => format!("test-mod {}", path),
|
RunnableKind::TestMod { path } => format!("test-mod {}", path),
|
||||||
RunnableKind::Bench { name } => format!("bench {}", name),
|
RunnableKind::Bench { test_id } => format!("bench {}", test_id),
|
||||||
RunnableKind::Bin => "run binary".to_string(),
|
RunnableKind::Bin => "run binary".to_string(),
|
||||||
};
|
};
|
||||||
Ok(req::Runnable {
|
Ok(req::Runnable {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue