Skip ab/6749736 in stage.
Merged-In: Ib48578a9cade614fe5e9d342be775a775a40d541
Change-Id: Ie3ce841177da3f16eba18f769763a287d1bac5b0
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 2df1587..bb978e8 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
{
"git": {
- "sha1": "203c6bc19e561da1734873794bbd420e0bfc79b9"
+ "sha1": "ff542c67023cbddbb2198df4087abc6aa6c8d5b7"
}
}
diff --git a/Android.bp b/Android.bp
index 9074bac..0c11915 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,4 +1,4 @@
-// This file is generated by cargo2android.py --run --device --tests --dependencies.
+// This file is generated by cargo2android.py --run --tests --dependencies.
rust_proc_macro {
name: "libstructopt_derive",
@@ -32,12 +32,11 @@
// dependent_library ["feature_list"]
// heck-0.3.1
-// proc-macro-error-1.0.3
-// proc-macro-error-attr-1.0.3
-// proc-macro2-1.0.19 "default,proc-macro"
+// proc-macro-error-1.0.4 "default,syn,syn-error"
+// proc-macro-error-attr-1.0.4
+// proc-macro2-1.0.24 "default,proc-macro"
// quote-1.0.7 "default,proc-macro"
-// syn-1.0.36 "clone-impls,default,derive,full,parsing,printing,proc-macro,quote"
-// syn-mid-0.5.0
+// syn-1.0.42 "clone-impls,default,derive,full,parsing,printing,proc-macro,quote"
// unicode-segmentation-1.6.0
// unicode-xid-0.2.1 "default"
// version_check-0.9.2
diff --git a/Cargo.toml b/Cargo.toml
index 301f046..5afdc79 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
[package]
edition = "2018"
name = "structopt-derive"
-version = "0.4.7"
+version = "0.4.11"
authors = ["Guillaume Pinot <[email protected]>"]
description = "Parse command line argument by defining a struct, derive crate."
documentation = "https://docs.rs/structopt-derive"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 4e97528..ff14f47 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "structopt-derive"
-version = "0.4.7"
+version = "0.4.11"
edition = "2018"
authors = ["Guillaume Pinot <[email protected]>"]
description = "Parse command line argument by defining a struct, derive crate."
diff --git a/METADATA b/METADATA
index bb03db3..b40e4df 100644
--- a/METADATA
+++ b/METADATA
@@ -1,4 +1,4 @@
-name: structopt-derive
+name: "structopt-derive"
description: "Parse command line argument by defining a struct, derive crate."
third_party {
url {
@@ -6,14 +6,14 @@
value: "https://crates.io/crates/structopt-derive"
}
url {
- type: GIT
- value: "https://github.com/TeXitoi/structopt"
+ type: ARCHIVE
+ value: "https://static.crates.io/crates/structopt-derive/structopt-derive-0.4.11.crate"
}
- version: "0.4.7"
+ version: "0.4.11"
license_type: NOTICE
last_upgrade_date {
year: 2020
- month: 5
+ month: 10
day: 6
}
-}
\ No newline at end of file
+}
diff --git a/src/attrs.rs b/src/attrs.rs
index d75b50c..11655b8 100644
--- a/src/attrs.rs
+++ b/src/attrs.rs
@@ -65,6 +65,10 @@
Snake,
/// Use the original attribute name defined in the code.
Verbatim,
+ /// Keep all letters lowercase and remove word boundaries.
+ Lower,
+ /// Keep all letters uppercase and remove word boundaries.
+ Upper,
}
#[derive(Clone)]
@@ -188,6 +192,8 @@
"screamingsnake" | "screamingsnakecase" => cs(ScreamingSnake),
"snake" | "snakecase" => cs(Snake),
"verbatim" | "verbatimcase" => cs(Verbatim),
+ "lower" | "lowercase" => cs(Lower),
+ "upper" | "uppercase" => cs(Upper),
s => abort!(name, "unsupported casing: `{}`", s),
}
}
@@ -208,6 +214,8 @@
ScreamingSnake => s.to_shouty_snake_case(),
Snake => s.to_snake_case(),
Verbatim => s,
+ Lower => s.to_snake_case().replace("_", ""),
+ Upper => s.to_shouty_snake_case().replace("_", ""),
};
quote_spanned!(ident.span()=> #s)
}
@@ -437,12 +445,16 @@
"parse attribute is not allowed for flattened entry"
);
}
- if res.has_explicit_methods() || res.has_doc_methods() {
+ if res.has_explicit_methods() {
abort!(
res.kind.span(),
- "methods and doc comments are not allowed for flattened entry"
+ "methods are not allowed for flattened entry"
);
}
+
+ if res.has_doc_methods() {
+ res.doc_comment = vec![];
+ }
}
Kind::ExternalSubcommand => {}
diff --git a/src/lib.rs b/src/lib.rs
index 5e49468..6cc415b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -11,6 +11,7 @@
//! for the usage of `#[derive(StructOpt)]`.
#![allow(clippy::large_enum_variant)]
+#![forbid(unsafe_code)]
extern crate proc_macro;
@@ -28,7 +29,7 @@
use proc_macro2::{Span, TokenStream};
use proc_macro_error::{abort, abort_call_site, proc_macro_error, set_dummy};
-use quote::{quote, quote_spanned};
+use quote::{format_ident, quote, quote_spanned};
use syn::{punctuated::Punctuated, spanned::Spanned, token::Comma, *};
/// Default casing style for generated arguments.
@@ -239,6 +240,16 @@
}
fn gen_constructor(fields: &Punctuated<Field, Comma>, parent_attribute: &Attrs) -> TokenStream {
+ // This ident is used in several match branches below,
+ // and the `quote[_spanned]` invocations have different spans.
+ //
+ // Given that this ident is used in several places and
+ // that the branches are located inside of a loop, it is possible that
+ // this ident will be given _different_ spans in different places, and
+ // thus will not be the _same_ ident anymore. To make sure the `matches`
+ // is always the same, we factor it out.
+ let matches = format_ident!("matches");
+
let fields = fields.iter().map(|field| {
let attrs = Attrs::from_field(
field,
@@ -265,13 +276,13 @@
};
quote_spanned! { kind.span()=>
#field_name: <#subcmd_type as ::structopt::StructOptInternal>::from_subcommand(
- matches.subcommand())
+ #matches.subcommand())
#unwrapper
}
}
Kind::Flatten => quote_spanned! { kind.span()=>
- #field_name: ::structopt::StructOpt::from_clap(matches)
+ #field_name: ::structopt::StructOpt::from_clap(#matches)
},
Kind::Skip(val) => match val {
@@ -318,24 +329,24 @@
let occurrences = *attrs.parser().kind == ParserKind::FromOccurrences;
let name = attrs.cased_name();
let field_value = match **ty {
- Ty::Bool => quote_spanned!(ty.span()=> matches.is_present(#name)),
+ Ty::Bool => quote_spanned!(ty.span()=> #matches.is_present(#name)),
Ty::Option => quote_spanned! { ty.span()=>
- matches.#value_of(#name)
+ #matches.#value_of(#name)
.map(#parse)
},
Ty::OptionOption => quote_spanned! { ty.span()=>
- if matches.is_present(#name) {
- Some(matches.#value_of(#name).map(#parse))
+ if #matches.is_present(#name) {
+ Some(#matches.#value_of(#name).map(#parse))
} else {
None
}
},
Ty::OptionVec => quote_spanned! { ty.span()=>
- if matches.is_present(#name) {
- Some(matches.#values_of(#name)
+ if #matches.is_present(#name) {
+ Some(#matches.#values_of(#name)
.map_or_else(Vec::new, |v| v.map(#parse).collect()))
} else {
None
@@ -343,20 +354,20 @@
},
Ty::Vec => quote_spanned! { ty.span()=>
- matches.#values_of(#name)
+ #matches.#values_of(#name)
.map_or_else(Vec::new, |v| v.map(#parse).collect())
},
Ty::Other if occurrences => quote_spanned! { ty.span()=>
- #parse(matches.#value_of(#name))
+ #parse(#matches.#value_of(#name))
},
Ty::Other if flag => quote_spanned! { ty.span()=>
- #parse(matches.is_present(#name))
+ #parse(#matches.is_present(#name))
},
Ty::Other => quote_spanned! { ty.span()=>
- matches.#value_of(#name)
+ #matches.#value_of(#name)
.map(#parse)
.unwrap()
},
@@ -471,8 +482,9 @@
let kind = attrs.kind();
match &*kind {
Kind::ExternalSubcommand => {
+ let app_var = Ident::new("app", Span::call_site());
quote_spanned! { attrs.kind().span()=>
- let app = app.setting(
+ let #app_var = #app_var.setting(
::structopt::clap::AppSettings::AllowExternalSubcommands
);
}
@@ -549,7 +561,8 @@
quote! {
fn from_clap(matches: &::structopt::clap::ArgMatches) -> Self {
<#name as ::structopt::StructOptInternal>::from_subcommand(matches.subcommand())
- .unwrap()
+ .expect("structopt misuse: You likely tried to #[flatten] a struct \
+ that contains #[subcommand]. This is forbidden.")
}
}
}
@@ -648,10 +661,10 @@
}
(external, None) => {
- ::std::option::Option::Some(#name::#var_name({
+ ::std::option::Option::Some(#name::#var_name(
::std::iter::once(#str_ty::from(external))
.collect::<::std::vec::Vec<_>>()
- }))
+ ))
}
}
},
@@ -720,7 +733,7 @@
#[cfg(feature = "paw")]
fn gen_paw_impl(name: &Ident) -> TokenStream {
quote! {
- impl paw::ParseArgs for #name {
+ impl ::structopt::paw::ParseArgs for #name {
type Error = std::io::Error;
fn parse_args() -> std::result::Result<Self, Self::Error> {
diff --git a/src/spanned.rs b/src/spanned.rs
index 19dbe47..1c02a82 100644
--- a/src/spanned.rs
+++ b/src/spanned.rs
@@ -88,7 +88,7 @@
// this is the simplest way out of correct ones to change span on
// arbitrary token tree I can come up with
let tt = self.val.to_token_stream().into_iter().map(|mut tt| {
- tt.set_span(self.span.clone());
+ tt.set_span(self.span);
tt
});