X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=crates%2Frust-analyzer%2Fsrc%2Fcargo_target_spec.rs;h=ec5dd16d001cdd38e0ea649b9619713f7af9f7c7;hb=0b53744f2d7e0694cd7207cca632fd6de1dc5bff;hp=3041915e1866028d96d6b69f82e355d27e46fe6b;hpb=178c3e135a2a249692f7784712492e7884ae0c00;p=rust.git diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs index 3041915e186..ec5dd16d001 100644 --- a/crates/rust-analyzer/src/cargo_target_spec.rs +++ b/crates/rust-analyzer/src/cargo_target_spec.rs @@ -1,8 +1,10 @@ //! See `CargoTargetSpec` -use cfg::CfgExpr; +use std::mem; + +use cfg::{CfgAtom, CfgExpr}; use ide::{FileId, RunnableKind, TestId}; -use project_model::{self, TargetKind}; +use project_model::{self, ManifestPath, TargetKind}; use vfs::AbsPathBuf; use crate::{global_state::GlobalStateSnapshot, Result}; @@ -14,20 +16,26 @@ #[derive(Clone)] pub(crate) struct CargoTargetSpec { pub(crate) workspace_root: AbsPathBuf, + pub(crate) cargo_toml: ManifestPath, pub(crate) package: String, pub(crate) target: String, pub(crate) target_kind: TargetKind, + pub(crate) required_features: Vec, } impl CargoTargetSpec { pub(crate) fn runnable_args( snap: &GlobalStateSnapshot, - spec: Option, + mut spec: Option, kind: &RunnableKind, - cfgs: &[CfgExpr], + cfg: &Option, ) -> Result<(Vec, Vec)> { let mut args = Vec::new(); let mut extra_args = Vec::new(); + + let target_required_features = + spec.as_mut().map(|spec| mem::take(&mut spec.required_features)).unwrap_or(Vec::new()); + match kind { RunnableKind::Test { test_id, attr } => { args.push("test".to_string()); @@ -72,23 +80,34 @@ pub(crate) fn runnable_args( extra_args.push("--nocapture".to_string()); } RunnableKind::Bin => { - args.push("run".to_string()); + let subcommand = match spec { + Some(CargoTargetSpec { target_kind: TargetKind::Test, .. }) => "test", + _ => "run", + }; + args.push(subcommand.to_string()); if let Some(spec) = spec { spec.push_to(&mut args, kind); } } } - if snap.config.cargo.all_features { + let cargo_config = snap.config.cargo(); + if cargo_config.all_features { args.push("--all-features".to_string()); + + for feature in target_required_features { + args.push("--features".to_string()); + args.push(feature); + } } else { let mut features = Vec::new(); - for cfg in cfgs { + if let Some(cfg) = cfg.as_ref() { required_features(cfg, &mut features); } - for feature in &snap.config.cargo.features { - features.push(feature.clone()); - } + + features.extend(cargo_config.features); + features.extend(target_required_features); + features.dedup(); for feature in features { args.push("--features".to_string()); @@ -111,12 +130,18 @@ pub(crate) fn for_file( Some(it) => it, None => return Ok(None), }; + + let target_data = &cargo_ws[target]; + let package_data = &cargo_ws[target_data.package]; let res = CargoTargetSpec { workspace_root: cargo_ws.workspace_root().to_path_buf(), - package: cargo_ws.package_flag(&cargo_ws[cargo_ws[target].package]), - target: cargo_ws[target].name.clone(), - target_kind: cargo_ws[target].kind, + cargo_toml: package_data.manifest.clone(), + package: cargo_ws.package_flag(package_data), + target: target_data.name.clone(), + target_kind: target_data.kind, + required_features: target_data.required_features.clone(), }; + Ok(Some(res)) } @@ -148,7 +173,7 @@ pub(crate) fn push_to(self, buf: &mut Vec, kind: &RunnableKind) { TargetKind::Lib => { buf.push("--lib".to_string()); } - TargetKind::Other => (), + TargetKind::Other | TargetKind::BuildScript => (), } } } @@ -156,7 +181,9 @@ pub(crate) fn push_to(self, buf: &mut Vec, kind: &RunnableKind) { /// Fill minimal features needed fn required_features(cfg_expr: &CfgExpr, features: &mut Vec) { match cfg_expr { - CfgExpr::KeyValue { key, value } if key == "feature" => features.push(value.to_string()), + CfgExpr::Atom(CfgAtom::KeyValue { key, value }) if key == "feature" => { + features.push(value.to_string()) + } CfgExpr::All(preds) => { preds.iter().for_each(|cfg| required_features(cfg, features)); } @@ -178,7 +205,7 @@ mod tests { use super::*; use cfg::CfgExpr; - use mbe::ast_to_token_tree; + use mbe::syntax_node_to_token_tree; use syntax::{ ast::{self, AstNode}, SmolStr, @@ -188,7 +215,7 @@ fn check(cfg: &str, expected_features: &[&str]) { let cfg_expr = { let source_file = ast::SourceFile::parse(cfg).ok().unwrap(); let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); - let (tt, _) = ast_to_token_tree(&tt).unwrap(); + let (tt, _) = syntax_node_to_token_tree(tt.syntax()); CfgExpr::parse(&tt) };