Skip to content

Commit

Permalink
Merge pull request #3438 from epage/flatten
Browse files Browse the repository at this point in the history
refactor: Flatten directory heirarcy
  • Loading branch information
epage committed Feb 10, 2022
2 parents 727c453 + 60a8747 commit c422ed2
Show file tree
Hide file tree
Showing 15 changed files with 183 additions and 183 deletions.
18 changes: 7 additions & 11 deletions src/build/app/mod.rs → src/build/app.rs
@@ -1,11 +1,3 @@
#[cfg(debug_assertions)]
mod debug_asserts;
mod settings;
#[cfg(test)]
mod tests;

pub use self::settings::{AppFlags, AppSettings};

// Std
use std::{
collections::HashMap,
Expand All @@ -23,6 +15,7 @@ use os_str_bytes::RawOsStr;
use yaml_rust::Yaml;

// Internal
use crate::build::app_settings::{AppFlags, AppSettings};
use crate::build::{arg::ArgProvider, Arg, ArgGroup, ArgPredicate};
use crate::error::ErrorKind;
use crate::error::Result as ClapResult;
Expand All @@ -32,6 +25,9 @@ use crate::parse::{ArgMatcher, ArgMatches, Input, Parser};
use crate::util::{color::ColorChoice, Id, Key};
use crate::{Error, INTERNAL_ERROR_MSG};

#[cfg(debug_assertions)]
use crate::build::debug_asserts::assert_app;

/// Build a command-line interface.
///
/// This includes defining arguments, subcommands, parser behavior, and help output.
Expand Down Expand Up @@ -2802,14 +2798,14 @@ impl<'help> App<'help> {
self.args._build();

#[cfg(debug_assertions)]
self::debug_asserts::assert_app(self);
assert_app(self);
self.settings.set(AppSettings::Built);
} else {
debug!("App::_build: already built");
}
}

fn _panic_on_missing_help(&self, help_required_globally: bool) {
pub(crate) fn _panic_on_missing_help(&self, help_required_globally: bool) {
if self.is_set(AppSettings::HelpExpected) || help_required_globally {
let args_missing_help: Vec<String> = self
.args
Expand All @@ -2831,7 +2827,7 @@ impl<'help> App<'help> {
}

#[cfg(debug_assertions)]
fn two_args_of<F>(&self, condition: F) -> Option<(&Arg<'help>, &Arg<'help>)>
pub(crate) fn two_args_of<F>(&self, condition: F) -> Option<(&Arg<'help>, &Arg<'help>)>
where
F: Fn(&Arg) -> bool,
{
Expand Down
File renamed without changes.
File renamed without changes.
31 changes: 8 additions & 23 deletions src/build/arg/mod.rs → src/build/arg.rs
@@ -1,17 +1,3 @@
mod arg_predicate;
#[cfg(debug_assertions)]
pub mod debug_asserts;
mod possible_value;
mod settings;
#[cfg(test)]
mod tests;
mod value_hint;

pub use self::possible_value::PossibleValue;
pub use self::settings::{ArgFlags, ArgSettings};
pub use self::value_hint::ValueHint;
pub(crate) use arg_predicate::ArgPredicate;

// Std
use std::{
borrow::Cow,
Expand All @@ -29,17 +15,16 @@ use std::{env, ffi::OsString};
use yaml_rust::Yaml;

// Internal
use crate::{
build::usage_parser::UsageParser,
util::{Id, Key},
INTERNAL_ERROR_MSG,
};

#[cfg(feature = "regex")]
mod regex;
use crate::build::usage_parser::UsageParser;
use crate::build::ArgPredicate;
use crate::util::{Id, Key};
use crate::PossibleValue;
use crate::ValueHint;
use crate::INTERNAL_ERROR_MSG;
use crate::{ArgFlags, ArgSettings};

#[cfg(feature = "regex")]
pub use self::regex::RegexRef;
use crate::build::RegexRef;

/// The abstract representation of a command line argument. Used to set all the options and
/// relationships that define a valid argument for the program.
Expand Down
135 changes: 0 additions & 135 deletions src/build/arg/debug_asserts.rs

This file was deleted.

File renamed without changes.
File renamed without changes.
File renamed without changes.
145 changes: 139 additions & 6 deletions src/build/app/debug_asserts.rs → src/build/debug_asserts.rs
@@ -1,11 +1,10 @@
use crate::{
build::arg::{debug_asserts::assert_arg, ArgProvider},
mkeymap::KeyType,
util::Id,
App, AppSettings, Arg, ValueHint,
};
use std::cmp::Ordering;

use crate::build::arg::ArgProvider;
use crate::mkeymap::KeyType;
use crate::util::Id;
use crate::{App, AppSettings, Arg, ValueHint};

pub(crate) fn assert_app(app: &App) {
debug!("App::_debug_asserts");

Expand Down Expand Up @@ -577,3 +576,137 @@ fn _verify_positionals(app: &App) -> bool {

true
}

fn assert_arg(arg: &Arg) {
debug!("Arg::_debug_asserts:{}", arg.name);

// Self conflict
// TODO: this check should be recursive
assert!(
!arg.blacklist.iter().any(|x| *x == arg.id),
"Argument '{}' cannot conflict with itself",
arg.name,
);

if arg.value_hint != ValueHint::Unknown {
assert!(
arg.is_takes_value_set(),
"Argument '{}' has value hint but takes no value",
arg.name
);

if arg.value_hint == ValueHint::CommandWithArguments {
assert!(
arg.is_multiple_values_set(),
"Argument '{}' uses hint CommandWithArguments and must accept multiple values",
arg.name
)
}
}

if arg.index.is_some() {
assert!(
arg.is_positional(),
"Argument '{}' is a positional argument and can't have short or long name versions",
arg.name
);
}

if arg.is_required_set() {
assert!(
arg.default_vals.is_empty(),
"Argument '{}' is required and can't have a default value",
arg.name
);
}

assert_arg_flags(arg);

assert_defaults(arg, "default_value", arg.default_vals.iter().copied());
assert_defaults(
arg,
"default_missing_value",
arg.default_missing_vals.iter().copied(),
);
assert_defaults(
arg,
"default_value_if",
arg.default_vals_ifs
.iter()
.filter_map(|(_, _, default)| *default),
);
}

fn assert_arg_flags(arg: &Arg) {
macro_rules! checker {
($a:ident requires $($b:ident)|+) => {
if arg.$a() {
let mut s = String::new();

$(
if !arg.$b() {
s.push_str(&format!(" Arg::{} is required when Arg::{} is set.\n", std::stringify!($b), std::stringify!($a)));
}
)+

if !s.is_empty() {
panic!("Argument {:?}\n{}", arg.get_name(), s)
}
}
}
}

checker!(is_forbid_empty_values_set requires is_takes_value_set);
checker!(is_require_value_delimiter_set requires is_takes_value_set);
checker!(is_require_value_delimiter_set requires is_use_value_delimiter_set);
checker!(is_hide_possible_values_set requires is_takes_value_set);
checker!(is_allow_hyphen_values_set requires is_takes_value_set);
checker!(is_require_equals_set requires is_takes_value_set);
checker!(is_last_set requires is_takes_value_set);
checker!(is_hide_default_value_set requires is_takes_value_set);
checker!(is_multiple_values_set requires is_takes_value_set);
checker!(is_ignore_case_set requires is_takes_value_set);
checker!(is_allow_invalid_utf8_set requires is_takes_value_set);
}

fn assert_defaults<'d>(
arg: &Arg,
field: &'static str,
defaults: impl IntoIterator<Item = &'d std::ffi::OsStr>,
) {
for default_os in defaults {
if let Some(default_s) = default_os.to_str() {
if !arg.possible_vals.is_empty() {
assert!(
arg.possible_vals.iter().any(|possible_val| {
possible_val.matches(default_s, arg.is_ignore_case_set())
}),
"Argument `{}`'s {}={} doesn't match possible values",
arg.name,
field,
default_s
);
}

if let Some(validator) = arg.validator.as_ref() {
let mut validator = validator.lock().unwrap();
if let Err(err) = validator(default_s) {
panic!(
"Argument `{}`'s {}={} failed validation: {}",
arg.name, field, default_s, err
);
}
}
}

if let Some(validator) = arg.validator_os.as_ref() {
let mut validator = validator.lock().unwrap();
if let Err(err) = validator(default_os) {
panic!(
"Argument `{}`'s {}={:?} failed validation: {}",
arg.name, field, default_os, err
);
}
}
}
}

0 comments on commit c422ed2

Please sign in to comment.