Upgrade rust/crates/structopt-derive to 0.4.15
Test: make
Change-Id: I6c0f440b3a56a4d7d5d502845d134218cd8471be
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 7d10f0d..887fa2d 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
{
"git": {
- "sha1": "8bda3b64daf53f0ed6bb6bee2c767a63c7c477fc"
+ "sha1": "004cfc218e7fbfdbecc4088f9e3fa5061f36cb4d"
}
}
diff --git a/Android.bp b/Android.bp
index edcebb2..eec57d9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,4 +1,5 @@
// This file is generated by cargo2android.py --run --tests --dependencies.
+// Do not modify this file as changes will be overridden on upgrade.
package {
default_applicable_licenses: [
@@ -58,6 +59,9 @@
srcs: ["src/lib.rs"],
test_suites: ["general-tests"],
auto_gen_config: true,
+ test_options: {
+ unit_test: true,
+ },
edition: "2018",
rustlibs: [
"libheck",
@@ -69,12 +73,12 @@
}
// dependent_library ["feature_list"]
-// heck-0.3.1
+// heck-0.3.3
// 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.53 "clone-impls,default,derive,full,parsing,printing,proc-macro,quote"
-// unicode-segmentation-1.7.1
-// unicode-xid-0.2.1 "default"
-// version_check-0.9.2
+// proc-macro2-1.0.28 "default,proc-macro"
+// quote-1.0.9 "default,proc-macro"
+// syn-1.0.74 "clone-impls,default,derive,full,parsing,printing,proc-macro,quote"
+// unicode-segmentation-1.8.0
+// unicode-xid-0.2.2 "default"
+// version_check-0.9.3
diff --git a/Cargo.toml b/Cargo.toml
index adfbce9..6a9c2b1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
[package]
edition = "2018"
name = "structopt-derive"
-version = "0.4.14"
+version = "0.4.15"
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 c346198..db7e295 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "structopt-derive"
-version = "0.4.14"
+version = "0.4.15"
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 03f0e52..e5e5980 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/structopt-derive/structopt-derive-0.4.14.crate"
+ value: "https://static.crates.io/crates/structopt-derive/structopt-derive-0.4.15.crate"
}
- version: "0.4.14"
+ version: "0.4.15"
license_type: NOTICE
last_upgrade_date {
- year: 2020
- month: 11
- day: 30
+ year: 2021
+ month: 8
+ day: 9
}
}
diff --git a/src/attrs.rs b/src/attrs.rs
index 11655b8..aa16145 100644
--- a/src/attrs.rs
+++ b/src/attrs.rs
@@ -100,7 +100,7 @@
Method { name, args }
}
- fn from_lit_or_env(ident: Ident, lit: Option<LitStr>, env_var: &str) -> Option<Self> {
+ fn from_lit_or_env(ident: Ident, lit: Option<LitStr>, env_var: &str) -> Self {
let mut lit = match lit {
Some(lit) => lit,
@@ -121,7 +121,7 @@
lit = LitStr::new(&edited, lit.span());
}
- Some(Method::new(ident, quote!(#lit)))
+ Method::new(ident, quote!(#lit))
}
}
@@ -335,11 +335,15 @@
}
About(ident, about) => {
- self.about = Method::from_lit_or_env(ident, about, "CARGO_PKG_DESCRIPTION");
+ self.about = Some(Method::from_lit_or_env(
+ ident,
+ about,
+ "CARGO_PKG_DESCRIPTION",
+ ));
}
Author(ident, author) => {
- self.author = Method::from_lit_or_env(ident, author, "CARGO_PKG_AUTHORS");
+ self.author = Some(Method::from_lit_or_env(ident, author, "CARGO_PKG_AUTHORS"));
}
Version(ident, version) => {
diff --git a/src/lib.rs b/src/lib.rs
index b818386..cf4dbba 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -559,10 +559,10 @@
}
}
-fn gen_from_clap_enum(name: &Ident) -> TokenStream {
+fn gen_from_clap_enum() -> TokenStream {
quote! {
fn from_clap(matches: &::structopt::clap::ArgMatches) -> Self {
- <#name as ::structopt::StructOptInternal>::from_subcommand(matches.subcommand())
+ <Self as ::structopt::StructOptInternal>::from_subcommand(matches.subcommand())
.expect("structopt misuse: You likely tried to #[flatten] a struct \
that contains #[subcommand]. This is forbidden.")
}
@@ -736,9 +736,9 @@
}
#[cfg(feature = "paw")]
-fn gen_paw_impl(name: &Ident) -> TokenStream {
+fn gen_paw_impl(impl_generics: &ImplGenerics, name: &Ident, ty_generics: &TypeGenerics, where_clause: &TokenStream) -> TokenStream {
quote! {
- impl ::structopt::paw::ParseArgs for #name {
+ impl #impl_generics ::structopt::paw::ParseArgs for #name #ty_generics #where_clause {
type Error = std::io::Error;
fn parse_args() -> std::result::Result<Self, Self::Error> {
@@ -748,19 +748,109 @@
}
}
#[cfg(not(feature = "paw"))]
-fn gen_paw_impl(_: &Ident) -> TokenStream {
+fn gen_paw_impl(_: &ImplGenerics, _: &Ident, _: &TypeGenerics, _: &TokenStream) -> TokenStream {
TokenStream::new()
}
+fn split_structopt_generics_for_impl(generics: &Generics) -> (ImplGenerics, TypeGenerics, TokenStream) {
+ use syn::{ token::Add, TypeParamBound::Trait };
+
+ fn path_ends_with(path: &Path, ident: &str) -> bool {
+ path.segments.last().unwrap().ident == ident
+ }
+
+ fn type_param_bounds_contains(bounds: &Punctuated<TypeParamBound, Add>, ident: &str) -> bool {
+ for bound in bounds {
+ if let Trait(bound) = bound {
+ if path_ends_with(&bound.path, ident) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ struct TraitBoundAmendments{
+ tokens: TokenStream,
+ need_where: bool,
+ need_comma: bool,
+ }
+
+ impl TraitBoundAmendments {
+ fn new(where_clause: Option<&WhereClause>) -> Self {
+ let tokens = TokenStream::new();
+ let (need_where,need_comma) = if let Some(where_clause) = where_clause {
+ if where_clause.predicates.trailing_punct() {
+ (false, false)
+ } else {
+ (false, true)
+ }
+ } else {
+ (true, false)
+ };
+ Self{tokens, need_where, need_comma}
+ }
+
+ fn add(&mut self, amendment: TokenStream) {
+ if self.need_where {
+ self.tokens.extend(quote!{ where });
+ self.need_where = false;
+ }
+ if self.need_comma {
+ self.tokens.extend(quote!{ , });
+ }
+ self.tokens.extend(amendment);
+ self.need_comma = true;
+ }
+
+ fn into_tokens(self) -> TokenStream {
+ self.tokens
+ }
+ }
+
+ let mut trait_bound_amendments = TraitBoundAmendments::new(generics.where_clause.as_ref());
+
+ for param in &generics.params {
+ if let GenericParam::Type(param) = param {
+ let param_ident = ¶m.ident;
+ if type_param_bounds_contains(¶m.bounds, "StructOpt") {
+ trait_bound_amendments.add(quote!{ #param_ident : ::structopt::StructOptInternal });
+ }
+ }
+ }
+
+ if let Some(where_clause) = &generics.where_clause {
+ for predicate in &where_clause.predicates {
+ if let WherePredicate::Type(predicate) = predicate {
+ let predicate_bounded_ty = &predicate.bounded_ty;
+ if type_param_bounds_contains(&predicate.bounds, "StructOpt") {
+ trait_bound_amendments.add(quote!{ #predicate_bounded_ty : ::structopt::StructOptInternal });
+ }
+ }
+ }
+ }
+
+ let trait_bound_amendments = trait_bound_amendments.into_tokens();
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ let where_clause = quote!{ #where_clause #trait_bound_amendments };
+
+ (impl_generics, ty_generics, where_clause)
+}
+
fn impl_structopt_for_struct(
name: &Ident,
fields: &Punctuated<Field, Comma>,
attrs: &[Attribute],
+ generics: &Generics,
) -> TokenStream {
+ let (impl_generics, ty_generics, where_clause) = split_structopt_generics_for_impl(&generics);
+
let basic_clap_app_gen = gen_clap_struct(attrs);
let augment_clap = gen_augment_clap(fields, &basic_clap_app_gen.attrs);
let from_clap = gen_from_clap(name, fields, &basic_clap_app_gen.attrs);
- let paw_impl = gen_paw_impl(name);
+ let paw_impl = gen_paw_impl(&impl_generics, name, &ty_generics, &where_clause);
let clap_tokens = basic_clap_app_gen.tokens;
quote! {
@@ -778,7 +868,7 @@
)]
#[deny(clippy::correctness)]
#[allow(dead_code, unreachable_code)]
- impl ::structopt::StructOpt for #name {
+ impl #impl_generics ::structopt::StructOpt for #name #ty_generics #where_clause {
#clap_tokens
#from_clap
}
@@ -797,7 +887,7 @@
)]
#[deny(clippy::correctness)]
#[allow(dead_code, unreachable_code)]
- impl ::structopt::StructOptInternal for #name {
+ impl #impl_generics ::structopt::StructOptInternal for #name #ty_generics #where_clause {
#augment_clap
fn is_subcommand() -> bool { false }
}
@@ -810,15 +900,19 @@
name: &Ident,
variants: &Punctuated<Variant, Comma>,
attrs: &[Attribute],
+ generics: &Generics,
) -> TokenStream {
+
+ let (impl_generics, ty_generics, where_clause) = split_structopt_generics_for_impl(&generics);
+
let basic_clap_app_gen = gen_clap_enum(attrs);
let clap_tokens = basic_clap_app_gen.tokens;
let attrs = basic_clap_app_gen.attrs;
let augment_clap = gen_augment_clap_enum(variants, &attrs);
- let from_clap = gen_from_clap_enum(name);
+ let from_clap = gen_from_clap_enum();
let from_subcommand = gen_from_subcommand(name, variants, &attrs);
- let paw_impl = gen_paw_impl(name);
+ let paw_impl = gen_paw_impl(&impl_generics, name, &ty_generics, &where_clause);
quote! {
#[allow(unknown_lints)]
@@ -834,7 +928,7 @@
clippy::cargo
)]
#[deny(clippy::correctness)]
- impl ::structopt::StructOpt for #name {
+ impl #impl_generics ::structopt::StructOpt for #name #ty_generics #where_clause {
#clap_tokens
#from_clap
}
@@ -853,7 +947,7 @@
)]
#[deny(clippy::correctness)]
#[allow(dead_code, unreachable_code)]
- impl ::structopt::StructOptInternal for #name {
+ impl #impl_generics ::structopt::StructOptInternal for #name #ty_generics #where_clause {
#augment_clap
#from_subcommand
fn is_subcommand() -> bool { true }
@@ -885,8 +979,8 @@
Struct(DataStruct {
fields: syn::Fields::Named(ref fields),
..
- }) => impl_structopt_for_struct(struct_name, &fields.named, &input.attrs),
- Enum(ref e) => impl_structopt_for_enum(struct_name, &e.variants, &input.attrs),
+ }) => impl_structopt_for_struct(struct_name, &fields.named, &input.attrs, &input.generics),
+ Enum(ref e) => impl_structopt_for_enum(struct_name, &e.variants, &input.attrs, &input.generics),
_ => abort_call_site!("structopt only supports non-tuple structs and enums"),
}
}