1use crate::core::compiler::CompileMode;
4
5use crate::core::{Target, TargetKind};
6use crate::util::restricted_names::is_glob_pattern;
7
8#[derive(Debug, PartialEq, Eq, Clone)]
9pub enum LibRule {
11 True,
13 Default,
15 False,
17}
18
19#[derive(Debug, Clone)]
20pub enum FilterRule {
22 All,
24 Just(Vec<String>),
26}
27
28#[derive(Debug, Clone)]
38pub enum CompileFilter {
39 Default {
41 required_features_filterable: bool,
43 },
44 Only {
46 all_targets: bool,
48 lib: LibRule,
49 bins: FilterRule,
50 examples: FilterRule,
51 tests: FilterRule,
52 benches: FilterRule,
53 },
54}
55
56impl FilterRule {
57 pub fn new(targets: Vec<String>, all: bool) -> FilterRule {
58 if all {
59 FilterRule::All
60 } else {
61 FilterRule::Just(targets)
62 }
63 }
64
65 pub fn none() -> FilterRule {
70 FilterRule::Just(Vec::new())
71 }
72
73 fn matches(&self, target: &Target) -> bool {
75 match *self {
76 FilterRule::All => true,
77 FilterRule::Just(ref targets) => targets.iter().any(|x| *x == target.name()),
78 }
79 }
80
81 fn is_specific(&self) -> bool {
85 match *self {
86 FilterRule::All => true,
87 FilterRule::Just(ref targets) => !targets.is_empty(),
88 }
89 }
90
91 pub(crate) fn contains_glob_patterns(&self) -> bool {
93 match self {
94 FilterRule::All => false,
95 FilterRule::Just(targets) => targets.iter().any(is_glob_pattern),
96 }
97 }
98}
99
100impl CompileFilter {
101 pub fn from_raw_arguments(
103 lib_only: bool,
104 bins: Vec<String>,
105 all_bins: bool,
106 tsts: Vec<String>,
107 all_tsts: bool,
108 exms: Vec<String>,
109 all_exms: bool,
110 bens: Vec<String>,
111 all_bens: bool,
112 all_targets: bool,
113 ) -> CompileFilter {
114 if all_targets {
115 return CompileFilter::new_all_targets();
116 }
117 let rule_lib = if lib_only {
118 LibRule::True
119 } else {
120 LibRule::False
121 };
122 let rule_bins = FilterRule::new(bins, all_bins);
123 let rule_tsts = FilterRule::new(tsts, all_tsts);
124 let rule_exms = FilterRule::new(exms, all_exms);
125 let rule_bens = FilterRule::new(bens, all_bens);
126
127 CompileFilter::new(rule_lib, rule_bins, rule_tsts, rule_exms, rule_bens)
128 }
129
130 pub fn new(
132 rule_lib: LibRule,
133 rule_bins: FilterRule,
134 rule_tsts: FilterRule,
135 rule_exms: FilterRule,
136 rule_bens: FilterRule,
137 ) -> CompileFilter {
138 if rule_lib == LibRule::True
139 || rule_bins.is_specific()
140 || rule_tsts.is_specific()
141 || rule_exms.is_specific()
142 || rule_bens.is_specific()
143 {
144 CompileFilter::Only {
145 all_targets: false,
146 lib: rule_lib,
147 bins: rule_bins,
148 examples: rule_exms,
149 benches: rule_bens,
150 tests: rule_tsts,
151 }
152 } else {
153 CompileFilter::Default {
154 required_features_filterable: true,
155 }
156 }
157 }
158
159 pub fn new_all_targets() -> CompileFilter {
161 CompileFilter::Only {
162 all_targets: true,
163 lib: LibRule::Default,
164 bins: FilterRule::All,
165 examples: FilterRule::All,
166 benches: FilterRule::All,
167 tests: FilterRule::All,
168 }
169 }
170
171 pub fn all_test_targets() -> Self {
184 Self::Only {
185 all_targets: false,
186 lib: LibRule::Default,
187 bins: FilterRule::none(),
188 examples: FilterRule::none(),
189 tests: FilterRule::All,
190 benches: FilterRule::none(),
191 }
192 }
193
194 pub fn lib_only() -> Self {
196 Self::Only {
197 all_targets: false,
198 lib: LibRule::True,
199 bins: FilterRule::none(),
200 examples: FilterRule::none(),
201 tests: FilterRule::none(),
202 benches: FilterRule::none(),
203 }
204 }
205
206 pub fn single_bin(bin: String) -> Self {
208 Self::Only {
209 all_targets: false,
210 lib: LibRule::False,
211 bins: FilterRule::new(vec![bin], false),
212 examples: FilterRule::none(),
213 tests: FilterRule::none(),
214 benches: FilterRule::none(),
215 }
216 }
217
218 pub fn need_dev_deps(&self, mode: CompileMode) -> bool {
220 match mode {
221 CompileMode::Test | CompileMode::Doctest | CompileMode::Bench => true,
222 CompileMode::Check { test: true } => true,
223 CompileMode::Build
224 | CompileMode::Doc { .. }
225 | CompileMode::Docscrape
226 | CompileMode::Check { test: false } => match *self {
227 CompileFilter::Default { .. } => false,
228 CompileFilter::Only {
229 ref examples,
230 ref tests,
231 ref benches,
232 ..
233 } => examples.is_specific() || tests.is_specific() || benches.is_specific(),
234 },
235 CompileMode::RunCustomBuild => panic!("Invalid mode"),
236 }
237 }
238
239 pub fn target_run(&self, target: &Target) -> bool {
245 match *self {
246 CompileFilter::Default { .. } => true,
247 CompileFilter::Only {
248 ref lib,
249 ref bins,
250 ref examples,
251 ref tests,
252 ref benches,
253 ..
254 } => {
255 let rule = match *target.kind() {
256 TargetKind::Bin => bins,
257 TargetKind::Test => tests,
258 TargetKind::Bench => benches,
259 TargetKind::ExampleBin | TargetKind::ExampleLib(..) => examples,
260 TargetKind::Lib(..) => {
261 return match *lib {
262 LibRule::True => true,
263 LibRule::Default => true,
264 LibRule::False => false,
265 };
266 }
267 TargetKind::CustomBuild => return false,
268 };
269 rule.matches(target)
270 }
271 }
272 }
273
274 pub fn is_specific(&self) -> bool {
275 match *self {
276 CompileFilter::Default { .. } => false,
277 CompileFilter::Only { .. } => true,
278 }
279 }
280
281 pub fn is_all_targets(&self) -> bool {
282 matches!(
283 *self,
284 CompileFilter::Only {
285 all_targets: true,
286 ..
287 }
288 )
289 }
290
291 pub(crate) fn contains_glob_patterns(&self) -> bool {
293 match self {
294 CompileFilter::Default { .. } => false,
295 CompileFilter::Only {
296 bins,
297 examples,
298 tests,
299 benches,
300 ..
301 } => {
302 bins.contains_glob_patterns()
303 || examples.contains_glob_patterns()
304 || tests.contains_glob_patterns()
305 || benches.contains_glob_patterns()
306 }
307 }
308 }
309}