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