1 // Internal
2 use crate::builder::{AppSettings, Arg, ArgPredicate, Command, PossibleValue};
3 use crate::error::{Error, Result as ClapResult};
4 use crate::output::fmt::Stream;
5 use crate::output::Usage;
6 use crate::parser::{ArgMatcher, MatchedArg, ParseState};
7 use crate::util::ChildGraph;
8 use crate::util::Id;
9 use crate::{INTERNAL_ERROR_MSG, INVALID_UTF8};
10
11 pub(crate) struct Validator<'help, 'cmd> {
12 cmd: &'cmd Command<'help>,
13 required: ChildGraph<Id>,
14 }
15
16 impl<'help, 'cmd> Validator<'help, 'cmd> {
new(cmd: &'cmd Command<'help>) -> Self17 pub(crate) fn new(cmd: &'cmd Command<'help>) -> Self {
18 let required = cmd.required_graph();
19 Validator { cmd, required }
20 }
21
validate( &mut self, parse_state: ParseState, matcher: &mut ArgMatcher, ) -> ClapResult<()>22 pub(crate) fn validate(
23 &mut self,
24 parse_state: ParseState,
25 matcher: &mut ArgMatcher,
26 ) -> ClapResult<()> {
27 debug!("Validator::validate");
28 let mut conflicts = Conflicts::new();
29 let has_subcmd = matcher.subcommand_name().is_some();
30
31 if let ParseState::Opt(a) = parse_state {
32 debug!("Validator::validate: needs_val_of={:?}", a);
33
34 let o = &self.cmd[&a];
35 let should_err = if let Some(v) = matcher.args.get(&o.id) {
36 v.all_val_groups_empty() && !(o.min_vals.is_some() && o.min_vals.unwrap() == 0)
37 } else {
38 true
39 };
40 if should_err {
41 return Err(Error::empty_value(
42 self.cmd,
43 &get_possible_values(o)
44 .iter()
45 .filter(|pv| !pv.is_hide_set())
46 .map(PossibleValue::get_name)
47 .collect::<Vec<_>>(),
48 o.to_string(),
49 ));
50 }
51 }
52
53 if !has_subcmd && self.cmd.is_arg_required_else_help_set() {
54 let num_user_values = matcher
55 .arg_ids()
56 .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent))
57 .count();
58 if num_user_values == 0 {
59 let message = self.cmd.write_help_err(false, Stream::Stderr)?;
60 return Err(Error::display_help_error(self.cmd, message));
61 }
62 }
63 #[allow(deprecated)]
64 if !has_subcmd && self.cmd.is_subcommand_required_set() {
65 let bn = self
66 .cmd
67 .get_bin_name()
68 .unwrap_or_else(|| self.cmd.get_name());
69 return Err(Error::missing_subcommand(
70 self.cmd,
71 bn.to_string(),
72 Usage::new(self.cmd)
73 .required(&self.required)
74 .create_usage_with_title(&[]),
75 ));
76 } else if !has_subcmd && self.cmd.is_set(AppSettings::SubcommandRequiredElseHelp) {
77 debug!("Validator::new::get_matches_with: SubcommandRequiredElseHelp=true");
78 let message = self.cmd.write_help_err(false, Stream::Stderr)?;
79 return Err(Error::display_help_error(self.cmd, message));
80 }
81
82 self.validate_conflicts(matcher, &mut conflicts)?;
83 if !(self.cmd.is_subcommand_negates_reqs_set() && has_subcmd) {
84 self.validate_required(matcher, &mut conflicts)?;
85 }
86 self.validate_matched_args(matcher)?;
87
88 Ok(())
89 }
90
validate_arg_values(&self, arg: &Arg, ma: &MatchedArg) -> ClapResult<()>91 fn validate_arg_values(&self, arg: &Arg, ma: &MatchedArg) -> ClapResult<()> {
92 debug!("Validator::validate_arg_values: arg={:?}", arg.name);
93 for val in ma.raw_vals_flatten() {
94 if !arg.possible_vals.is_empty() {
95 debug!(
96 "Validator::validate_arg_values: possible_vals={:?}",
97 arg.possible_vals
98 );
99 let val_str = val.to_string_lossy();
100 let ok = arg
101 .possible_vals
102 .iter()
103 .any(|pv| pv.matches(&val_str, arg.is_ignore_case_set()));
104 if !ok {
105 return Err(Error::invalid_value(
106 self.cmd,
107 val_str.into_owned(),
108 &arg.possible_vals
109 .iter()
110 .filter(|pv| !pv.is_hide_set())
111 .map(PossibleValue::get_name)
112 .collect::<Vec<_>>(),
113 arg.to_string(),
114 ));
115 }
116 }
117 {
118 #![allow(deprecated)]
119 if arg.is_forbid_empty_values_set() && val.is_empty() {
120 debug!("Validator::validate_arg_values: illegal empty val found");
121 return Err(Error::empty_value(
122 self.cmd,
123 &get_possible_values(arg)
124 .iter()
125 .filter(|pv| !pv.is_hide_set())
126 .map(PossibleValue::get_name)
127 .collect::<Vec<_>>(),
128 arg.to_string(),
129 ));
130 }
131 }
132
133 if let Some(ref vtor) = arg.validator {
134 debug!("Validator::validate_arg_values: checking validator...");
135 let mut vtor = vtor.lock().unwrap();
136 if let Err(e) = vtor(&*val.to_string_lossy()) {
137 debug!("error");
138 return Err(Error::value_validation(
139 arg.to_string(),
140 val.to_string_lossy().into_owned(),
141 e,
142 )
143 .with_cmd(self.cmd));
144 } else {
145 debug!("good");
146 }
147 }
148 if let Some(ref vtor) = arg.validator_os {
149 debug!("Validator::validate_arg_values: checking validator_os...");
150 let mut vtor = vtor.lock().unwrap();
151 if let Err(e) = vtor(val) {
152 debug!("error");
153 return Err(Error::value_validation(
154 arg.to_string(),
155 val.to_string_lossy().into(),
156 e,
157 )
158 .with_cmd(self.cmd));
159 } else {
160 debug!("good");
161 }
162 }
163 }
164 Ok(())
165 }
166
validate_conflicts( &mut self, matcher: &ArgMatcher, conflicts: &mut Conflicts, ) -> ClapResult<()>167 fn validate_conflicts(
168 &mut self,
169 matcher: &ArgMatcher,
170 conflicts: &mut Conflicts,
171 ) -> ClapResult<()> {
172 debug!("Validator::validate_conflicts");
173
174 self.validate_exclusive(matcher)?;
175
176 for arg_id in matcher
177 .arg_ids()
178 .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent))
179 .filter(|arg_id| self.cmd.find(arg_id).is_some())
180 {
181 debug!("Validator::validate_conflicts::iter: id={:?}", arg_id);
182 let conflicts = conflicts.gather_conflicts(self.cmd, matcher, arg_id);
183 self.build_conflict_err(arg_id, &conflicts, matcher)?;
184 }
185
186 Ok(())
187 }
188
validate_exclusive(&self, matcher: &ArgMatcher) -> ClapResult<()>189 fn validate_exclusive(&self, matcher: &ArgMatcher) -> ClapResult<()> {
190 debug!("Validator::validate_exclusive");
191 let args_count = matcher
192 .arg_ids()
193 .filter(|arg_id| {
194 matcher.check_explicit(arg_id, crate::builder::ArgPredicate::IsPresent)
195 })
196 .count();
197 if args_count <= 1 {
198 // Nothing present to conflict with
199 return Ok(());
200 }
201
202 matcher
203 .arg_ids()
204 .filter(|arg_id| {
205 matcher.check_explicit(arg_id, crate::builder::ArgPredicate::IsPresent)
206 })
207 .filter_map(|name| {
208 debug!("Validator::validate_exclusive:iter:{:?}", name);
209 self.cmd
210 .find(name)
211 // Find `arg`s which are exclusive but also appear with other args.
212 .filter(|&arg| arg.is_exclusive_set() && args_count > 1)
213 })
214 // Throw an error for the first conflict found.
215 .try_for_each(|arg| {
216 Err(Error::argument_conflict(
217 self.cmd,
218 arg.to_string(),
219 Vec::new(),
220 Usage::new(self.cmd)
221 .required(&self.required)
222 .create_usage_with_title(&[]),
223 ))
224 })
225 }
226
build_conflict_err( &self, name: &Id, conflict_ids: &[Id], matcher: &ArgMatcher, ) -> ClapResult<()>227 fn build_conflict_err(
228 &self,
229 name: &Id,
230 conflict_ids: &[Id],
231 matcher: &ArgMatcher,
232 ) -> ClapResult<()> {
233 if conflict_ids.is_empty() {
234 return Ok(());
235 }
236
237 debug!("Validator::build_conflict_err: name={:?}", name);
238 let mut seen = std::collections::HashSet::new();
239 let conflicts = conflict_ids
240 .iter()
241 .flat_map(|c_id| {
242 if self.cmd.find_group(c_id).is_some() {
243 self.cmd.unroll_args_in_group(c_id)
244 } else {
245 vec![c_id.clone()]
246 }
247 })
248 .filter_map(|c_id| {
249 seen.insert(c_id.clone()).then(|| {
250 let c_arg = self.cmd.find(&c_id).expect(INTERNAL_ERROR_MSG);
251 c_arg.to_string()
252 })
253 })
254 .collect();
255
256 let former_arg = self.cmd.find(name).expect(INTERNAL_ERROR_MSG);
257 let usg = self.build_conflict_err_usage(matcher, conflict_ids);
258 Err(Error::argument_conflict(
259 self.cmd,
260 former_arg.to_string(),
261 conflicts,
262 usg,
263 ))
264 }
265
build_conflict_err_usage(&self, matcher: &ArgMatcher, conflicting_keys: &[Id]) -> String266 fn build_conflict_err_usage(&self, matcher: &ArgMatcher, conflicting_keys: &[Id]) -> String {
267 let used_filtered: Vec<Id> = matcher
268 .arg_ids()
269 .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent))
270 .filter(|n| {
271 // Filter out the args we don't want to specify.
272 self.cmd.find(n).map_or(true, |a| !a.is_hide_set())
273 })
274 .filter(|key| !conflicting_keys.contains(key))
275 .cloned()
276 .collect();
277 let required: Vec<Id> = used_filtered
278 .iter()
279 .filter_map(|key| self.cmd.find(key))
280 .flat_map(|arg| arg.requires.iter().map(|item| &item.1))
281 .filter(|key| !used_filtered.contains(key) && !conflicting_keys.contains(key))
282 .chain(used_filtered.iter())
283 .cloned()
284 .collect();
285 Usage::new(self.cmd)
286 .required(&self.required)
287 .create_usage_with_title(&required)
288 }
289
gather_requires(&mut self, matcher: &ArgMatcher)290 fn gather_requires(&mut self, matcher: &ArgMatcher) {
291 debug!("Validator::gather_requires");
292 for name in matcher
293 .arg_ids()
294 .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent))
295 {
296 debug!("Validator::gather_requires:iter:{:?}", name);
297 if let Some(arg) = self.cmd.find(name) {
298 let is_relevant = |(val, req_arg): &(ArgPredicate<'_>, Id)| -> Option<Id> {
299 let required = matcher.check_explicit(&arg.id, *val);
300 required.then(|| req_arg.clone())
301 };
302
303 for req in self.cmd.unroll_arg_requires(is_relevant, &arg.id) {
304 self.required.insert(req);
305 }
306 } else if let Some(g) = self.cmd.find_group(name) {
307 debug!("Validator::gather_requires:iter:{:?}:group", name);
308 for r in &g.requires {
309 self.required.insert(r.clone());
310 }
311 }
312 }
313 }
314
validate_matched_args(&self, matcher: &ArgMatcher) -> ClapResult<()>315 fn validate_matched_args(&self, matcher: &ArgMatcher) -> ClapResult<()> {
316 debug!("Validator::validate_matched_args");
317 matcher.iter().try_for_each(|(name, ma)| {
318 debug!(
319 "Validator::validate_matched_args:iter:{:?}: vals={:#?}",
320 name,
321 ma.vals_flatten()
322 );
323 if let Some(arg) = self.cmd.find(name) {
324 self.validate_arg_num_vals(arg, ma)?;
325 self.validate_arg_values(arg, ma)?;
326 self.validate_arg_num_occurs(arg, ma)?;
327 }
328 Ok(())
329 })
330 }
331
validate_arg_num_occurs(&self, a: &Arg, ma: &MatchedArg) -> ClapResult<()>332 fn validate_arg_num_occurs(&self, a: &Arg, ma: &MatchedArg) -> ClapResult<()> {
333 #![allow(deprecated)]
334 debug!(
335 "Validator::validate_arg_num_occurs: {:?}={}",
336 a.name,
337 ma.get_occurrences()
338 );
339 // Occurrence of positional argument equals to number of values rather
340 // than number of grouped values.
341 if ma.get_occurrences() > 1 && !a.is_multiple_occurrences_set() && !a.is_positional() {
342 // Not the first time, and we don't allow multiples
343 return Err(Error::unexpected_multiple_usage(
344 self.cmd,
345 a.to_string(),
346 Usage::new(self.cmd)
347 .required(&self.required)
348 .create_usage_with_title(&[]),
349 ));
350 }
351 if let Some(max_occurs) = a.max_occurs {
352 debug!(
353 "Validator::validate_arg_num_occurs: max_occurs set...{}",
354 max_occurs
355 );
356 let occurs = ma.get_occurrences() as usize;
357 if occurs > max_occurs {
358 return Err(Error::too_many_occurrences(
359 self.cmd,
360 a.to_string(),
361 max_occurs,
362 occurs,
363 Usage::new(self.cmd)
364 .required(&self.required)
365 .create_usage_with_title(&[]),
366 ));
367 }
368 }
369
370 Ok(())
371 }
372
validate_arg_num_vals(&self, a: &Arg, ma: &MatchedArg) -> ClapResult<()>373 fn validate_arg_num_vals(&self, a: &Arg, ma: &MatchedArg) -> ClapResult<()> {
374 debug!("Validator::validate_arg_num_vals");
375 if let Some(num) = a.num_vals {
376 let total_num = ma.num_vals();
377 debug!("Validator::validate_arg_num_vals: num_vals set...{}", num);
378 #[allow(deprecated)]
379 let should_err = if a.is_multiple_occurrences_set() {
380 total_num % num != 0
381 } else {
382 num != total_num
383 };
384 if should_err {
385 debug!("Validator::validate_arg_num_vals: Sending error WrongNumberOfValues");
386 return Err(Error::wrong_number_of_values(
387 self.cmd,
388 a.to_string(),
389 num,
390 #[allow(deprecated)]
391 if a.is_multiple_occurrences_set() {
392 total_num % num
393 } else {
394 total_num
395 },
396 Usage::new(self.cmd)
397 .required(&self.required)
398 .create_usage_with_title(&[]),
399 ));
400 }
401 }
402 if let Some(num) = a.max_vals {
403 debug!("Validator::validate_arg_num_vals: max_vals set...{}", num);
404 if ma.num_vals() > num {
405 debug!("Validator::validate_arg_num_vals: Sending error TooManyValues");
406 return Err(Error::too_many_values(
407 self.cmd,
408 ma.raw_vals_flatten()
409 .last()
410 .expect(INTERNAL_ERROR_MSG)
411 .to_str()
412 .expect(INVALID_UTF8)
413 .to_string(),
414 a.to_string(),
415 Usage::new(self.cmd)
416 .required(&self.required)
417 .create_usage_with_title(&[]),
418 ));
419 }
420 }
421 let min_vals_zero = if let Some(num) = a.min_vals {
422 debug!("Validator::validate_arg_num_vals: min_vals set: {}", num);
423 if ma.num_vals() < num && num != 0 {
424 debug!("Validator::validate_arg_num_vals: Sending error TooFewValues");
425 return Err(Error::too_few_values(
426 self.cmd,
427 a.to_string(),
428 num,
429 ma.num_vals(),
430 Usage::new(self.cmd)
431 .required(&self.required)
432 .create_usage_with_title(&[]),
433 ));
434 }
435 num == 0
436 } else {
437 false
438 };
439 // Issue 665 (https://github.com/clap-rs/clap/issues/665)
440 // Issue 1105 (https://github.com/clap-rs/clap/issues/1105)
441 if a.is_takes_value_set() && !min_vals_zero && ma.all_val_groups_empty() {
442 return Err(Error::empty_value(
443 self.cmd,
444 &get_possible_values(a)
445 .iter()
446 .filter(|pv| !pv.is_hide_set())
447 .map(PossibleValue::get_name)
448 .collect::<Vec<_>>(),
449 a.to_string(),
450 ));
451 }
452 Ok(())
453 }
454
validate_required( &mut self, matcher: &ArgMatcher, conflicts: &mut Conflicts, ) -> ClapResult<()>455 fn validate_required(
456 &mut self,
457 matcher: &ArgMatcher,
458 conflicts: &mut Conflicts,
459 ) -> ClapResult<()> {
460 debug!("Validator::validate_required: required={:?}", self.required);
461 self.gather_requires(matcher);
462
463 let is_exclusive_present = matcher
464 .arg_ids()
465 .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent))
466 .any(|id| {
467 self.cmd
468 .find(id)
469 .map(|arg| arg.is_exclusive_set())
470 .unwrap_or_default()
471 });
472 debug!(
473 "Validator::validate_required: is_exclusive_present={}",
474 is_exclusive_present
475 );
476
477 for arg_or_group in self
478 .required
479 .iter()
480 .filter(|r| !matcher.check_explicit(r, ArgPredicate::IsPresent))
481 {
482 debug!("Validator::validate_required:iter:aog={:?}", arg_or_group);
483 if let Some(arg) = self.cmd.find(arg_or_group) {
484 debug!("Validator::validate_required:iter: This is an arg");
485 if !is_exclusive_present && !self.is_missing_required_ok(arg, matcher, conflicts) {
486 return self.missing_required_error(matcher, vec![]);
487 }
488 } else if let Some(group) = self.cmd.find_group(arg_or_group) {
489 debug!("Validator::validate_required:iter: This is a group");
490 if !self
491 .cmd
492 .unroll_args_in_group(&group.id)
493 .iter()
494 .any(|a| matcher.check_explicit(a, ArgPredicate::IsPresent))
495 {
496 return self.missing_required_error(matcher, vec![]);
497 }
498 }
499 }
500
501 // Validate the conditionally required args
502 for a in self.cmd.get_arguments() {
503 for (other, val) in &a.r_ifs {
504 if matcher.check_explicit(other, ArgPredicate::Equals(std::ffi::OsStr::new(*val)))
505 && !matcher.check_explicit(&a.id, ArgPredicate::IsPresent)
506 {
507 return self.missing_required_error(matcher, vec![a.id.clone()]);
508 }
509 }
510
511 let match_all = a.r_ifs_all.iter().all(|(other, val)| {
512 matcher.check_explicit(other, ArgPredicate::Equals(std::ffi::OsStr::new(*val)))
513 });
514 if match_all
515 && !a.r_ifs_all.is_empty()
516 && !matcher.check_explicit(&a.id, ArgPredicate::IsPresent)
517 {
518 return self.missing_required_error(matcher, vec![a.id.clone()]);
519 }
520 }
521
522 self.validate_required_unless(matcher)?;
523
524 Ok(())
525 }
526
is_missing_required_ok( &self, a: &Arg<'help>, matcher: &ArgMatcher, conflicts: &mut Conflicts, ) -> bool527 fn is_missing_required_ok(
528 &self,
529 a: &Arg<'help>,
530 matcher: &ArgMatcher,
531 conflicts: &mut Conflicts,
532 ) -> bool {
533 debug!("Validator::is_missing_required_ok: {}", a.name);
534 let conflicts = conflicts.gather_conflicts(self.cmd, matcher, &a.id);
535 !conflicts.is_empty()
536 }
537
validate_required_unless(&self, matcher: &ArgMatcher) -> ClapResult<()>538 fn validate_required_unless(&self, matcher: &ArgMatcher) -> ClapResult<()> {
539 debug!("Validator::validate_required_unless");
540 let failed_args: Vec<_> = self
541 .cmd
542 .get_arguments()
543 .filter(|&a| {
544 (!a.r_unless.is_empty() || !a.r_unless_all.is_empty())
545 && !matcher.check_explicit(&a.id, ArgPredicate::IsPresent)
546 && self.fails_arg_required_unless(a, matcher)
547 })
548 .map(|a| a.id.clone())
549 .collect();
550 if failed_args.is_empty() {
551 Ok(())
552 } else {
553 self.missing_required_error(matcher, failed_args)
554 }
555 }
556
557 // Failing a required unless means, the arg's "unless" wasn't present, and neither were they
fails_arg_required_unless(&self, a: &Arg<'help>, matcher: &ArgMatcher) -> bool558 fn fails_arg_required_unless(&self, a: &Arg<'help>, matcher: &ArgMatcher) -> bool {
559 debug!("Validator::fails_arg_required_unless: a={:?}", a.name);
560 let exists = |id| matcher.check_explicit(id, ArgPredicate::IsPresent);
561
562 (a.r_unless_all.is_empty() || !a.r_unless_all.iter().all(exists))
563 && !a.r_unless.iter().any(exists)
564 }
565
566 // `incl`: an arg to include in the error even if not used
missing_required_error(&self, matcher: &ArgMatcher, incl: Vec<Id>) -> ClapResult<()>567 fn missing_required_error(&self, matcher: &ArgMatcher, incl: Vec<Id>) -> ClapResult<()> {
568 debug!("Validator::missing_required_error; incl={:?}", incl);
569 debug!(
570 "Validator::missing_required_error: reqs={:?}",
571 self.required
572 );
573
574 let usg = Usage::new(self.cmd).required(&self.required);
575
576 let req_args = usg
577 .get_required_usage_from(&incl, Some(matcher), true)
578 .into_iter()
579 .collect::<Vec<_>>();
580
581 debug!(
582 "Validator::missing_required_error: req_args={:#?}",
583 req_args
584 );
585
586 let used: Vec<Id> = matcher
587 .arg_ids()
588 .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent))
589 .filter(|n| {
590 // Filter out the args we don't want to specify.
591 self.cmd.find(n).map_or(true, |a| !a.is_hide_set())
592 })
593 .cloned()
594 .chain(incl)
595 .collect();
596
597 Err(Error::missing_required_argument(
598 self.cmd,
599 req_args,
600 usg.create_usage_with_title(&used),
601 ))
602 }
603 }
604
605 #[derive(Default, Clone, Debug)]
606 struct Conflicts {
607 potential: std::collections::HashMap<Id, Vec<Id>>,
608 }
609
610 impl Conflicts {
new() -> Self611 fn new() -> Self {
612 Self::default()
613 }
614
gather_conflicts(&mut self, cmd: &Command, matcher: &ArgMatcher, arg_id: &Id) -> Vec<Id>615 fn gather_conflicts(&mut self, cmd: &Command, matcher: &ArgMatcher, arg_id: &Id) -> Vec<Id> {
616 debug!("Conflicts::gather_conflicts: arg={:?}", arg_id);
617 let mut conflicts = Vec::new();
618 for other_arg_id in matcher
619 .arg_ids()
620 .filter(|arg_id| matcher.check_explicit(arg_id, ArgPredicate::IsPresent))
621 {
622 if arg_id == other_arg_id {
623 continue;
624 }
625
626 if self
627 .gather_direct_conflicts(cmd, arg_id)
628 .contains(other_arg_id)
629 {
630 conflicts.push(other_arg_id.clone());
631 }
632 if self
633 .gather_direct_conflicts(cmd, other_arg_id)
634 .contains(arg_id)
635 {
636 conflicts.push(other_arg_id.clone());
637 }
638 }
639 debug!("Conflicts::gather_conflicts: conflicts={:?}", conflicts);
640 conflicts
641 }
642
gather_direct_conflicts(&mut self, cmd: &Command, arg_id: &Id) -> &[Id]643 fn gather_direct_conflicts(&mut self, cmd: &Command, arg_id: &Id) -> &[Id] {
644 self.potential.entry(arg_id.clone()).or_insert_with(|| {
645 let conf = if let Some(arg) = cmd.find(arg_id) {
646 let mut conf = arg.blacklist.clone();
647 for group_id in cmd.groups_for_arg(arg_id) {
648 let group = cmd.find_group(&group_id).expect(INTERNAL_ERROR_MSG);
649 conf.extend(group.conflicts.iter().cloned());
650 if !group.multiple {
651 for member_id in &group.args {
652 if member_id != arg_id {
653 conf.push(member_id.clone());
654 }
655 }
656 }
657 }
658
659 // Overrides are implicitly conflicts
660 conf.extend(arg.overrides.iter().cloned());
661
662 conf
663 } else if let Some(group) = cmd.find_group(arg_id) {
664 group.conflicts.clone()
665 } else {
666 debug_assert!(false, "id={:?} is unknown", arg_id);
667 Vec::new()
668 };
669 debug!(
670 "Conflicts::gather_direct_conflicts id={:?}, conflicts={:?}",
671 arg_id, conf
672 );
673 conf
674 })
675 }
676 }
677
get_possible_values<'help>(a: &Arg<'help>) -> Vec<PossibleValue<'help>>678 fn get_possible_values<'help>(a: &Arg<'help>) -> Vec<PossibleValue<'help>> {
679 #![allow(deprecated)]
680 if !a.is_takes_value_set() {
681 vec![]
682 } else if let Some(pvs) = a.get_possible_values() {
683 // Check old first in case the user explicitly set possible values and the derive inferred
684 // a `ValueParser` with some.
685 pvs.to_vec()
686 } else {
687 a.get_value_parser()
688 .possible_values()
689 .map(|pvs| pvs.collect())
690 .unwrap_or_default()
691 }
692 }
693