Skip to content

Commit

Permalink
Fix #439
Browse files Browse the repository at this point in the history
If memory serves, a patch like this was submitted to clap_derive,
but not to structopt. Oops.
  • Loading branch information
CreepySkeleton committed Oct 12, 2020
1 parent 1cc5b05 commit ae9fd6f
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 0 deletions.
19 changes: 19 additions & 0 deletions structopt-derive/src/ty.rs
Expand Up @@ -63,6 +63,8 @@ fn subty_if<F>(ty: &syn::Type, f: F) -> Option<&syn::Type>
where
F: FnOnce(&PathSegment) -> bool,
{
let ty = strip_group(ty);

only_last_segment(ty)
.filter(|segment| f(segment))
.and_then(|segment| {
Expand Down Expand Up @@ -96,6 +98,23 @@ pub fn is_simple_ty(ty: &syn::Type, name: &str) -> bool {
.unwrap_or(false)
}

// If the struct is placed inside of a macro_rules! declaration,
// in some circumstances, the tokens inside will be enclosed
// in `proc_macro::Group` delimited by invisible `proc_macro::Delimiter::None`.
//
// In syn speak, this is encoded via `*::Group` variants. We don't really care about
// that, so let's just strip it.
//
// Details: https://doc.rust-lang.org/proc_macro/enum.Delimiter.html#variant.None
// See also: https://github.com/TeXitoi/structopt/issues/439
fn strip_group(mut ty: &syn::Type) -> &syn::Type {
while let Type::Group(group) = ty {
ty = &*group.elem;
}

ty
}

fn is_generic_ty(ty: &syn::Type, name: &str) -> bool {
subty_if_name(ty, name).is_some()
}
Expand Down
25 changes: 25 additions & 0 deletions tests/regressions.rs
@@ -0,0 +1,25 @@
use structopt::StructOpt;

mod utils;
use utils::*;

#[test]
fn invisible_group_issue_439() {
macro_rules! m {
($bool:ty) => {
#[derive(Debug, StructOpt)]
struct Opts {
#[structopt(long = "x")]
x: $bool
}
};
}

m!(bool);

let help = get_long_help::<Opts>();

assert!(help.contains("--x"));
assert!(!help.contains("--x <x>"));
Opts::from_iter_safe(&["test", "--x"]).unwrap();
}

0 comments on commit ae9fd6f

Please sign in to comment.