diff options
author | Aleksey Kladov <[email protected]> | 2020-06-02 15:30:26 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-06-02 15:30:47 +0100 |
commit | 31f282636bb1b1d701d41f7c7fedb11a5511cabd (patch) | |
tree | 0c9581f425b6bf38b79a7f0adfb090adef716461 /crates/rust-analyzer/src/cargo_target_spec.rs | |
parent | 61e8f392191037acefddc5793e814f93d01b114a (diff) |
Minor
Diffstat (limited to 'crates/rust-analyzer/src/cargo_target_spec.rs')
-rw-r--r-- | crates/rust-analyzer/src/cargo_target_spec.rs | 85 |
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 | ||
3 | use ra_cfg::CfgExpr; | ||
3 | use ra_ide::{FileId, RunnableKind, TestId}; | 4 | use ra_ide::{FileId, RunnableKind, TestId}; |
4 | use ra_project_model::{self, ProjectWorkspace, TargetKind}; | 5 | use ra_project_model::{self, ProjectWorkspace, TargetKind}; |
5 | 6 | ||
6 | use crate::{world::WorldSnapshot, Result}; | 7 | use crate::{world::WorldSnapshot, Result}; |
7 | use 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 | ||
149 | fn 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)] | ||
169 | mod 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 | } | ||