rust/crates/rust-analyzer/src/cargo_target_spec.rs
Hannes De Valkeneer e903fd0d97 feat: add debug code lens
Refs #3539
2020-03-11 22:26:47 +01:00

117 lines
3.9 KiB
Rust

//! See `CargoTargetSpec`
use ra_ide::{FileId, RunnableKind, TestId};
use ra_project_model::{self, ProjectWorkspace, TargetKind};
use crate::{world::WorldSnapshot, Result};
/// Abstract representation of Cargo target.
///
/// We use it to cook up the set of cli args we need to pass to Cargo to
/// build/test/run the target.
pub(crate) struct CargoTargetSpec {
pub(crate) package: String,
pub(crate) target: String,
pub(crate) target_kind: TargetKind,
}
impl CargoTargetSpec {
pub(crate) fn runnable_args(
spec: Option<CargoTargetSpec>,
kind: &RunnableKind,
) -> Result<(Vec<String>, Vec<String>)> {
let mut args = Vec::new();
let mut extra_args = Vec::new();
match kind {
RunnableKind::Test { test_id } => {
args.push("test".to_string());
if let Some(spec) = spec {
spec.push_to(&mut args);
}
extra_args.push(test_id.to_string());
if let TestId::Path(_) = test_id {
extra_args.push("--exact".to_string());
}
extra_args.push("--nocapture".to_string());
}
RunnableKind::TestMod { path } => {
args.push("test".to_string());
if let Some(spec) = spec {
spec.push_to(&mut args);
}
extra_args.push(path.to_string());
extra_args.push("--nocapture".to_string());
}
RunnableKind::Bench { test_id } => {
args.push("bench".to_string());
if let Some(spec) = spec {
spec.push_to(&mut args);
}
extra_args.push(test_id.to_string());
if let TestId::Path(_) = test_id {
extra_args.push("--exact".to_string());
}
extra_args.push("--nocapture".to_string());
}
RunnableKind::Bin => {
args.push("run".to_string());
if let Some(spec) = spec {
spec.push_to(&mut args);
}
}
}
Ok((args, extra_args))
}
pub(crate) fn for_file(
world: &WorldSnapshot,
file_id: FileId,
) -> Result<Option<CargoTargetSpec>> {
let &crate_id = match world.analysis().crate_for(file_id)?.first() {
Some(crate_id) => crate_id,
None => return Ok(None),
};
let file_id = world.analysis().crate_root(crate_id)?;
let path = world.file_id_to_path(file_id);
let res = world.workspaces.iter().find_map(|ws| match ws {
ProjectWorkspace::Cargo { cargo, .. } => {
let tgt = cargo.target_by_root(&path)?;
Some(CargoTargetSpec {
package: tgt.package(&cargo).name(&cargo).to_string(),
target: tgt.name(&cargo).to_string(),
target_kind: tgt.kind(&cargo),
})
}
ProjectWorkspace::Json { .. } => None,
});
Ok(res)
}
pub(crate) fn push_to(self, buf: &mut Vec<String>) {
buf.push("--package".to_string());
buf.push(self.package);
match self.target_kind {
TargetKind::Bin => {
buf.push("--bin".to_string());
buf.push(self.target);
}
TargetKind::Test => {
buf.push("--test".to_string());
buf.push(self.target);
}
TargetKind::Bench => {
buf.push("--bench".to_string());
buf.push(self.target);
}
TargetKind::Example => {
buf.push("--example".to_string());
buf.push(self.target);
}
TargetKind::Lib => {
buf.push("--lib".to_string());
}
TargetKind::Other => (),
}
}
}