refactor(derive): Generalize Kind based error checks

This commit is contained in:
Ed Page 2022-09-02 12:51:25 -05:00
parent 59a4578898
commit 97ce0c44f7
3 changed files with 56 additions and 33 deletions

View file

@ -104,14 +104,16 @@ impl Item {
); );
} }
match &*res.kind { match &*res.kind {
Kind::Subcommand(_) => abort!(res.kind.span(), "subcommand is only allowed on fields"),
Kind::Skip(_) => abort!(res.kind.span(), "skip is only allowed on fields"),
Kind::Command(_) | Kind::Value(_) | Kind::Arg(_) => res, Kind::Command(_) | Kind::Value(_) | Kind::Arg(_) => res,
Kind::FromGlobal(_) => abort!(res.kind.span(), "from_global is only allowed on fields"), Kind::Subcommand(_) | Kind::Skip(_) | Kind::FromGlobal(_) | Kind::Flatten => abort!(
Kind::Flatten => abort!(res.kind.span(), "flatten is only allowed on fields"), res.kind.span(),
"`{}` is only allowed on fields",
res.kind.name(),
),
Kind::ExternalSubcommand => abort!( Kind::ExternalSubcommand => abort!(
res.kind.span(), res.kind.span(),
"external_subcommand is only allowed on fields" "`{}` is only allowed on variants",
res.kind.name(),
), ),
} }
} }
@ -207,7 +209,11 @@ impl Item {
} }
Kind::Skip(_) => (), Kind::Skip(_) => (),
Kind::FromGlobal(_) => { Kind::FromGlobal(_) => {
abort!(res.kind.span(), "from_global is not supported on variants"); abort!(
res.kind.span(),
"`{}` is only allowed on fields",
res.kind.name(),
)
} }
Kind::Command(_) | Kind::Value(_) | Kind::Arg(_) => (), Kind::Command(_) | Kind::Value(_) | Kind::Arg(_) => (),
} }
@ -245,14 +251,17 @@ impl Item {
); );
} }
match &*res.kind { match &*res.kind {
Kind::Subcommand(_) => abort!(res.kind.span(), "subcommand is only allowed on fields"),
Kind::Skip(_) => res,
Kind::Command(_) | Kind::Value(_) | Kind::Arg(_) => res, Kind::Command(_) | Kind::Value(_) | Kind::Arg(_) => res,
Kind::FromGlobal(_) => abort!(res.kind.span(), "from_global is only allowed on fields"), Kind::Skip(_) => res,
Kind::Flatten => abort!(res.kind.span(), "flatten is only allowed on fields"), Kind::Subcommand(_) | Kind::FromGlobal(_) | Kind::Flatten => abort!(
res.kind.span(),
"`{}` is only allowed on fields",
res.kind.name(),
),
Kind::ExternalSubcommand => abort!( Kind::ExternalSubcommand => abort!(
res.kind.span(), res.kind.span(),
"external_subcommand is only allowed on fields" "`{}` is only allowed on variants",
res.kind.name(),
), ),
} }
} }
@ -300,11 +309,11 @@ impl Item {
res.doc_comment = vec![]; res.doc_comment = vec![];
} }
Kind::ExternalSubcommand => { Kind::ExternalSubcommand => abort!(
abort! { res.kind.span(), res.kind.span(),
"`external_subcommand` can be used only on enum variants" "`{}` is only allowed on variants",
} res.kind.name(),
} ),
Kind::Subcommand(_) => { Kind::Subcommand(_) => {
if let Some(value_parser) = res.value_parser.as_ref() { if let Some(value_parser) = res.value_parser.as_ref() {
@ -886,10 +895,24 @@ impl Item {
} }
fn set_kind(&mut self, kind: Sp<Kind>) { fn set_kind(&mut self, kind: Sp<Kind>) {
if let (Some(old), Some(new)) = (self.kind.name(), kind.name()) { match (self.kind.get(), kind.get()) {
abort!(kind.span(), "`{}` cannot be used with `{}`", new, old); (Kind::Arg(_), Kind::FromGlobal(_))
} else { | (Kind::Arg(_), Kind::Subcommand(_))
self.kind = kind; | (Kind::Arg(_), Kind::Flatten)
| (Kind::Arg(_), Kind::Skip(_))
| (Kind::Command(_), Kind::Subcommand(_))
| (Kind::Command(_), Kind::Flatten)
| (Kind::Command(_), Kind::Skip(_))
| (Kind::Command(_), Kind::ExternalSubcommand)
| (Kind::Value(_), Kind::Skip(_)) => {
self.kind = kind;
}
(_, _) => {
let old = self.kind.name();
let new = kind.name();
abort!(kind.span(), "`{}` cannot be used with `{}`", new, old);
}
} }
} }
@ -1130,16 +1153,16 @@ pub enum Kind {
} }
impl Kind { impl Kind {
fn name(&self) -> Option<&'static str> { fn name(&self) -> &'static str {
match self { match self {
Self::Arg(_) => None, Self::Arg(_) => "arg",
Self::Command(_) => None, Self::Command(_) => "command",
Self::Value(_) => None, Self::Value(_) => "value",
Self::FromGlobal(_) => Some("from_global"), Self::FromGlobal(_) => "from_global",
Self::Subcommand(_) => Some("subcommand"), Self::Subcommand(_) => "subcommand",
Self::Flatten => Some("flatten"), Self::Flatten => "flatten",
Self::Skip(_) => Some("skip"), Self::Skip(_) => "skip",
Self::ExternalSubcommand => Some("external_subcommand"), Self::ExternalSubcommand => "external_subcommand",
} }
} }
} }

View file

@ -1,5 +1,5 @@
error: `external_subcommand` can be used only on enum variants error: `external_subcommand` cannot be used with `arg`
--> $DIR/external_subcommand_misuse.rs:5:12 --> tests/derive_ui/external_subcommand_misuse.rs:5:12
| |
5 | #[clap(external_subcommand)] 5 | #[clap(external_subcommand)]
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^

View file

@ -1,5 +1,5 @@
error: subcommand is only allowed on fields error: `subcommand` is only allowed on fields
--> $DIR/struct_subcommand.rs:12:24 --> tests/derive_ui/struct_subcommand.rs:12:24
| |
12 | #[clap(name = "basic", subcommand)] 12 | #[clap(name = "basic", subcommand)]
| ^^^^^^^^^^ | ^^^^^^^^^^