Snap for 8358640 from b2b6c71ccacfd14c177c4a3053a675489a1d88c6 to mainline-go-media-release
Change-Id: I875ce76e617bc6f1c192e2c2a7352cf15cbac8f3
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 7d10f0d..d24b4cf 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
{
"git": {
- "sha1": "8bda3b64daf53f0ed6bb6bee2c767a63c7c477fc"
+ "sha1": "da1fff81aded1c239ffcbd0a27ccdc7f28f74ff2"
}
}
diff --git a/Android.bp b/Android.bp
index edcebb2..e008611 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,4 +1,5 @@
-// This file is generated by cargo2android.py --run --tests --dependencies.
+// This file is generated by cargo2android.py --config cargo2android.json.
+// Do not modify this file as changes will be overridden on upgrade.
package {
default_applicable_licenses: [
@@ -41,6 +42,8 @@
rust_proc_macro {
name: "libstructopt_derive",
crate_name: "structopt_derive",
+ cargo_env_compat: true,
+ cargo_pkg_version: "0.4.18",
srcs: ["src/lib.rs"],
edition: "2018",
rustlibs: [
@@ -51,30 +54,3 @@
"libsyn",
],
}
-
-rust_test_host {
- name: "structopt-derive_host_test_src_lib",
- crate_name: "structopt_derive",
- srcs: ["src/lib.rs"],
- test_suites: ["general-tests"],
- auto_gen_config: true,
- edition: "2018",
- rustlibs: [
- "libheck",
- "libproc_macro2",
- "libproc_macro_error",
- "libquote",
- "libsyn",
- ],
-}
-
-// dependent_library ["feature_list"]
-// heck-0.3.1
-// 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
diff --git a/Cargo.toml b/Cargo.toml
index adfbce9..5a9f8b4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,17 +3,16 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "structopt-derive"
-version = "0.4.14"
+version = "0.4.18"
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..e081f89 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "structopt-derive"
-version = "0.4.14"
+version = "0.4.18"
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..d4549b4 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.18.crate"
}
- version: "0.4.14"
+ version: "0.4.18"
license_type: NOTICE
last_upgrade_date {
- year: 2020
- month: 11
- day: 30
+ year: 2022
+ month: 3
+ day: 1
}
}
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 0000000..8029a19
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,18 @@
+// Generated by update_crate_tests.py for tests that depend on this crate.
+{
+ "imports": [
+ {
+ "path": "external/rust/crates/base64"
+ }
+ ],
+ "presubmit": [
+ {
+ "name": "authfs_device_test_src_lib"
+ }
+ ],
+ "presubmit-rust": [
+ {
+ "name": "authfs_device_test_src_lib"
+ }
+ ]
+}
diff --git a/cargo2android.json b/cargo2android.json
new file mode 100644
index 0000000..341300b
--- /dev/null
+++ b/cargo2android.json
@@ -0,0 +1,4 @@
+{
+ "run": true,
+ "tests": true
+}
\ No newline at end of file
diff --git a/src/attrs.rs b/src/attrs.rs
index 11655b8..35acd5a 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) => {
@@ -401,6 +405,7 @@
parent_attrs: Option<&Attrs>,
argument_casing: Sp<CasingStyle>,
env_casing: Sp<CasingStyle>,
+ allow_skip: bool,
) -> Self {
let mut res = Self::new(span, name, parent_attrs, None, argument_casing, env_casing);
res.push_attrs(attrs);
@@ -414,8 +419,10 @@
}
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::Arg(_) | Kind::ExternalSubcommand | Kind::Flatten => res,
+ Kind::Skip(_) if !allow_skip => {
+ abort!(res.kind.span(), "skip is only allowed on fields")
+ }
+ Kind::Arg(_) | Kind::ExternalSubcommand | Kind::Flatten | Kind::Skip(_) => res,
}
}
diff --git a/src/lib.rs b/src/lib.rs
index b818386..0838f50 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -330,6 +330,13 @@
let flag = *attrs.parser().kind == ParserKind::FromFlag;
let occurrences = *attrs.parser().kind == ParserKind::FromOccurrences;
let name = attrs.cased_name();
+ let convert_type = match **ty {
+ Ty::Vec | Ty::Option => sub_type(&field.ty).unwrap_or(&field.ty),
+ Ty::OptionOption | Ty::OptionVec => {
+ sub_type(&field.ty).and_then(sub_type).unwrap_or(&field.ty)
+ }
+ _ => &field.ty,
+ };
let field_value = match **ty {
Ty::Bool => quote_spanned!(ty.span()=> #matches.is_present(#name)),
@@ -349,7 +356,7 @@
Ty::OptionVec => quote_spanned! { ty.span()=>
if #matches.is_present(#name) {
Some(#matches.#values_of(#name)
- .map_or_else(Vec::new, |v| v.map(#parse).collect()))
+ .map_or_else(Vec::new, |v| v.map::<#convert_type, _>(#parse).collect()))
} else {
None
}
@@ -357,7 +364,7 @@
Ty::Vec => quote_spanned! { ty.span()=>
#matches.#values_of(#name)
- .map_or_else(Vec::new, |v| v.map(#parse).collect())
+ .map_or_else(Vec::new, |v| v.map::<#convert_type, _>(#parse).collect())
},
Ty::Other if occurrences => quote_spanned! { ty.span()=>
@@ -409,6 +416,7 @@
None,
Sp::call_site(DEFAULT_CASING),
Sp::call_site(DEFAULT_ENV_CASING),
+ false,
);
let tokens = {
let name = attrs.cased_name();
@@ -471,7 +479,7 @@
) -> TokenStream {
use syn::Fields::*;
- let subcommands = variants.iter().map(|variant| {
+ let subcommands = variants.iter().filter_map(|variant| {
let attrs = Attrs::from_struct(
variant.span(),
&variant.attrs,
@@ -479,26 +487,29 @@
Some(parent_attribute),
parent_attribute.casing(),
parent_attribute.env_casing(),
+ true,
);
let kind = attrs.kind();
match &*kind {
+ Kind::Skip(_) => None,
+
Kind::ExternalSubcommand => {
let app_var = Ident::new("app", Span::call_site());
- quote_spanned! { attrs.kind().span()=>
+ Some(quote_spanned! { attrs.kind().span()=>
let #app_var = #app_var.setting(
::structopt::clap::AppSettings::AllowExternalSubcommands
);
- }
+ })
},
Kind::Flatten => {
match variant.fields {
Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
let ty = &unnamed[0];
- quote! {
+ Some(quote! {
let app = <#ty as ::structopt::StructOptInternal>::augment_clap(app);
- }
+ })
},
_ => abort!(
variant,
@@ -509,9 +520,14 @@
_ => {
let app_var = Ident::new("subcommand", Span::call_site());
+ let from_attrs = attrs.top_level_methods();
+ let version = attrs.version();
+
let arg_block = match variant.fields {
+ // If the variant is named, then gen_augmentation already generates the
+ // top level methods (#from_attrs) and version.
Named(ref fields) => gen_augmentation(&fields.named, &app_var, &attrs),
- Unit => quote!( #app_var ),
+ Unit => quote!( #app_var#from_attrs#version ),
Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
let ty = &unnamed[0];
quote_spanned! { ty.span()=>
@@ -525,7 +541,7 @@
)
} else {
#app_var
- }
+ }#from_attrs#version
}
}
}
@@ -533,15 +549,12 @@
};
let name = attrs.cased_name();
- let from_attrs = attrs.top_level_methods();
- let version = attrs.version();
- quote! {
+ Some(quote! {
let app = app.subcommand({
let #app_var = ::structopt::clap::SubCommand::with_name(#name);
- let #app_var = #arg_block;
- #app_var#from_attrs#version
+ #arg_block
});
- }
+ })
},
}
});
@@ -559,10 +572,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.")
}
@@ -588,58 +601,61 @@
Some(parent_attribute),
parent_attribute.casing(),
parent_attribute.env_casing(),
+ true,
);
let variant_name = &variant.ident;
- if let Kind::ExternalSubcommand = *attrs.kind() {
- if ext_subcmd.is_some() {
- abort!(
- attrs.kind().span(),
- "Only one variant can be marked with `external_subcommand`, \
+ match *attrs.kind() {
+ Kind::ExternalSubcommand => {
+ if ext_subcmd.is_some() {
+ abort!(
+ attrs.kind().span(),
+ "Only one variant can be marked with `external_subcommand`, \
this is the second"
- );
- }
-
- let ty = match variant.fields {
- Unnamed(ref fields) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty,
-
- _ => abort!(
- variant,
- "The enum variant marked with `external_attribute` must be \
- a single-typed tuple, and the type must be either `Vec<String>` \
- or `Vec<OsString>`."
- ),
- };
-
- let (span, str_ty, values_of) = match subty_if_name(ty, "Vec") {
- Some(subty) => {
- if is_simple_ty(subty, "String") {
- (
- subty.span(),
- quote!(::std::string::String),
- quote!(values_of),
- )
- } else {
- (
- subty.span(),
- quote!(::std::ffi::OsString),
- quote!(values_of_os),
- )
- }
+ );
}
- None => abort!(
- ty,
- "The type must be either `Vec<String>` or `Vec<OsString>` \
- to be used with `external_subcommand`."
- ),
- };
+ let ty = match variant.fields {
+ Unnamed(ref fields) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty,
- ext_subcmd = Some((span, variant_name, str_ty, values_of));
- None
- } else {
- Some((variant, attrs))
+ _ => abort!(
+ variant,
+ "The enum variant marked with `external_attribute` must be \
+ a single-typed tuple, and the type must be either `Vec<String>` \
+ or `Vec<OsString>`."
+ ),
+ };
+
+ let (span, str_ty, values_of) = match subty_if_name(ty, "Vec") {
+ Some(subty) => {
+ if is_simple_ty(subty, "String") {
+ (
+ subty.span(),
+ quote!(::std::string::String),
+ quote!(values_of),
+ )
+ } else {
+ (
+ subty.span(),
+ quote!(::std::ffi::OsString),
+ quote!(values_of_os),
+ )
+ }
+ }
+
+ None => abort!(
+ ty,
+ "The type must be either `Vec<String>` or `Vec<OsString>` \
+ to be used with `external_subcommand`."
+ ),
+ };
+
+ ext_subcmd = Some((span, variant_name, str_ty, values_of));
+ None
+ }
+ Kind::Skip(_) => None,
+ _ => Some((variant, attrs)),
}
})
.partition(|(_, attrs)| match &*attrs.kind() {
@@ -736,9 +752,14 @@
}
#[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 +769,117 @@
}
}
#[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 +897,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 +916,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 +929,18 @@
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 +956,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 +975,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 +1007,10 @@
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"),
}
}