aboutsummaryrefslogtreecommitdiff
path: root/crates/rust-analyzer/src/cargo_target_spec.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-06-02 15:30:26 +0100
committerAleksey Kladov <[email protected]>2020-06-02 15:30:47 +0100
commit31f282636bb1b1d701d41f7c7fedb11a5511cabd (patch)
tree0c9581f425b6bf38b79a7f0adfb090adef716461 /crates/rust-analyzer/src/cargo_target_spec.rs
parent61e8f392191037acefddc5793e814f93d01b114a (diff)
Minor
Diffstat (limited to 'crates/rust-analyzer/src/cargo_target_spec.rs')
-rw-r--r--crates/rust-analyzer/src/cargo_target_spec.rs85
1 files changed, 80 insertions, 5 deletions
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs
index 441fb61df..008518a08 100644
--- a/crates/rust-analyzer/src/cargo_target_spec.rs
+++ b/crates/rust-analyzer/src/cargo_target_spec.rs
@@ -1,10 +1,10 @@
1//! See `CargoTargetSpec` 1//! See `CargoTargetSpec`
2 2
3use ra_cfg::CfgExpr;
3use ra_ide::{FileId, RunnableKind, TestId}; 4use ra_ide::{FileId, RunnableKind, TestId};
4use ra_project_model::{self, ProjectWorkspace, TargetKind}; 5use ra_project_model::{self, ProjectWorkspace, TargetKind};
5 6
6use crate::{world::WorldSnapshot, Result}; 7use crate::{world::WorldSnapshot, Result};
7use ra_syntax::SmolStr;
8 8
9/// Abstract representation of Cargo target. 9/// Abstract representation of Cargo target.
10/// 10///
@@ -21,7 +21,7 @@ impl CargoTargetSpec {
21 pub(crate) fn runnable_args( 21 pub(crate) fn runnable_args(
22 spec: Option<CargoTargetSpec>, 22 spec: Option<CargoTargetSpec>,
23 kind: &RunnableKind, 23 kind: &RunnableKind,
24 features_needed: &Vec<SmolStr>, 24 cfgs: &[CfgExpr],
25 ) -> Result<(Vec<String>, Vec<String>)> { 25 ) -> Result<(Vec<String>, Vec<String>)> {
26 let mut args = Vec::new(); 26 let mut args = Vec::new();
27 let mut extra_args = Vec::new(); 27 let mut extra_args = Vec::new();
@@ -76,10 +76,14 @@ impl CargoTargetSpec {
76 } 76 }
77 } 77 }
78 78
79 features_needed.iter().for_each(|feature| { 79 let mut features = Vec::new();
80 for cfg in cfgs {
81 required_features(cfg, &mut features);
82 }
83 for feature in features {
80 args.push("--features".to_string()); 84 args.push("--features".to_string());
81 args.push(feature.to_string()); 85 args.push(feature);
82 }); 86 }
83 87
84 Ok((args, extra_args)) 88 Ok((args, extra_args))
85 } 89 }
@@ -140,3 +144,74 @@ impl CargoTargetSpec {
140 } 144 }
141 } 145 }
142} 146}
147
148/// Fill minimal features needed
149fn required_features(cfg_expr: &CfgExpr, features: &mut Vec<String>) {
150 match cfg_expr {
151 CfgExpr::KeyValue { key, value } if key == "feature" => features.push(value.to_string()),
152 CfgExpr::All(preds) => {
153 preds.iter().for_each(|cfg| required_features(cfg, features));
154 }
155 CfgExpr::Any(preds) => {
156 for cfg in preds {
157 let len_features = features.len();
158 required_features(cfg, features);
159 if len_features != features.len() {
160 break;
161 }
162 }
163 }
164 _ => {}
165 }
166}
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171
172 use mbe::{ast_to_token_tree, TokenMap};
173 use ra_cfg::parse_cfg;
174 use ra_syntax::{
175 ast::{self, AstNode},
176 SmolStr,
177 };
178
179 fn get_token_tree_generated(input: &str) -> (tt::Subtree, TokenMap) {
180 let source_file = ast::SourceFile::parse(input).ok().unwrap();
181 let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
182 ast_to_token_tree(&tt).unwrap()
183 }
184
185 #[test]
186 fn test_cfg_expr_minimal_features_needed() {
187 let (subtree, _) = get_token_tree_generated(r#"#![cfg(feature = "baz")]"#);
188 let cfg_expr = parse_cfg(&subtree);
189 let mut min_features = vec![];
190 required_features(&cfg_expr, &mut min_features);
191
192 assert_eq!(min_features, vec![SmolStr::new("baz")]);
193
194 let (subtree, _) =
195 get_token_tree_generated(r#"#![cfg(all(feature = "baz", feature = "foo"))]"#);
196 let cfg_expr = parse_cfg(&subtree);
197
198 let mut min_features = vec![];
199 required_features(&cfg_expr, &mut min_features);
200 assert_eq!(min_features, vec![SmolStr::new("baz"), SmolStr::new("foo")]);
201
202 let (subtree, _) =
203 get_token_tree_generated(r#"#![cfg(any(feature = "baz", feature = "foo", unix))]"#);
204 let cfg_expr = parse_cfg(&subtree);
205
206 let mut min_features = vec![];
207 required_features(&cfg_expr, &mut min_features);
208 assert_eq!(min_features, vec![SmolStr::new("baz")]);
209
210 let (subtree, _) = get_token_tree_generated(r#"#![cfg(foo)]"#);
211 let cfg_expr = parse_cfg(&subtree);
212
213 let mut min_features = vec![];
214 required_features(&cfg_expr, &mut min_features);
215 assert!(min_features.is_empty());
216 }
217}