From b090f92c6d33b78477400aadf9ebaa862631e159 Mon Sep 17 00:00:00 2001 From: Igor Gnatenko Date: Tue, 17 Dec 2019 09:07:44 +0100 Subject: [PATCH] Update proc-macro-error to 0.4 Signed-off-by: Igor Gnatenko --- 0001-Update-proc-macro-error-to-v0.4.patch | 413 +++++++++++++++++++++ rust-structopt-derive.spec | 5 + structopt-derive-fix-metadata.diff | 11 + 3 files changed, 429 insertions(+) create mode 100644 0001-Update-proc-macro-error-to-v0.4.patch create mode 100644 structopt-derive-fix-metadata.diff diff --git a/0001-Update-proc-macro-error-to-v0.4.patch b/0001-Update-proc-macro-error-to-v0.4.patch new file mode 100644 index 0000000..fcd826c --- /dev/null +++ b/0001-Update-proc-macro-error-to-v0.4.patch @@ -0,0 +1,413 @@ +From 3f2fea5caf6986078a1e9e33106d63c982b67663 Mon Sep 17 00:00:00 2001 +From: CreepySkeleton +Date: Tue, 3 Dec 2019 16:06:26 +0300 +Subject: [PATCH] Update proc-macro-error to v0.4 + +(cherry picked from commit 39535cac8c40dd79c53f6603525e2af00594747d) +--- + src/attrs.rs | 62 +++++++++++++++++++++++++--------------------------- + src/lib.rs | 23 ++++++++++--------- + src/parse.rs | 59 +++++++++++++++++++++++++++++++------------------ + 3 files changed, 79 insertions(+), 65 deletions(-) + +diff --git a/src/attrs.rs b/src/attrs.rs +index c53628b..5256475 100644 +--- a/src/attrs.rs ++++ b/src/attrs.rs +@@ -12,7 +12,7 @@ use std::env; + + use heck::{CamelCase, KebabCase, MixedCase, ShoutySnakeCase, SnakeCase}; + use proc_macro2::{Span, TokenStream}; +-use proc_macro_error::span_error; ++use proc_macro_error::abort; + use quote::{quote, quote_spanned, ToTokens}; + use syn::{ + self, ext::IdentExt, spanned::Spanned, AngleBracketedGenericArguments, Attribute, Expr, +@@ -109,8 +109,10 @@ impl Method { + None => match env::var(env_var) { + Ok(val) => LitStr::new(&val, ident.span()), + Err(_) => { +- span_error!(ident.span(), +- "`{}` environment variable is not defined, use `{} = \"{}\"` to set it manually", env_var, ident, ident ++ abort!(ident.span(), ++ "cannot derive `{}` from Cargo.toml", ident; ++ note = "`{}` environment variable is not set", env_var; ++ help = "use `{} = \"{}\"` to set {} manually", ident, ident, ident; + ); + } + }, +@@ -149,7 +151,7 @@ impl Parser { + "try_from_os_str" => TryFromOsStr, + "from_occurrences" => FromOccurrences, + "from_flag" => FromFlag, +- s => span_error!(spec.kind.span(), "unsupported parser `{}`", s), ++ s => abort!(spec.kind.span(), "unsupported parser `{}`", s), + }; + + let func = match spec.parse_func { +@@ -158,9 +160,9 @@ impl Parser { + quote_spanned!(spec.kind.span()=> ::std::convert::From::from) + } + TryFromStr => quote_spanned!(spec.kind.span()=> ::std::str::FromStr::from_str), +- TryFromOsStr => span_error!( ++ TryFromOsStr => abort!( + spec.kind.span(), +- "cannot omit parser function name with `try_from_os_str`" ++ "parser's function name for `try_from_os_str` mut be set explicitly" + ), + FromOccurrences => quote_spanned!(spec.kind.span()=> { |v| v as _ }), + FromFlag => quote_spanned!(spec.kind.span()=> ::std::convert::From::from), +@@ -168,7 +170,7 @@ impl Parser { + + Some(func) => match func { + syn::Expr::Path(_) => quote!(#func), +- _ => span_error!(func.span(), "`parse` argument must be a function path"), ++ _ => abort!(func.span(), "`parse` argument must be a function path"), + }, + }; + +@@ -192,7 +194,7 @@ impl CasingStyle { + "screamingsnake" | "screamingsnakecase" => cs(ScreamingSnake), + "snake" | "snakecase" => cs(Snake), + "verbatim" | "verbatimcase" => cs(Verbatim), +- s => span_error!(name.span(), "unsupported casing: `{}`", s), ++ s => abort!(name.span(), "unsupported casing: `{}`", s), + } + } + } +@@ -407,19 +409,15 @@ impl Attrs { + res.push_doc_comment(attrs, "about"); + + if res.has_custom_parser { +- span_error!( ++ abort!( + res.parser.span(), +- "parse attribute is only allowed on fields" ++ "`parse` attribute is only allowed on fields" + ); + } + match &*res.kind { +- Kind::Subcommand(_) => { +- span_error!(res.kind.span(), "subcommand is only allowed on fields") +- } +- Kind::FlattenStruct => { +- span_error!(res.kind.span(), "flatten is only allowed on fields") +- } +- Kind::Skip(_) => span_error!(res.kind.span(), "skip is only allowed on fields"), ++ Kind::Subcommand(_) => abort!(res.kind.span(), "subcommand is only allowed on fields"), ++ Kind::FlattenStruct => abort!(res.kind.span(), "flatten is only allowed on fields"), ++ Kind::Skip(_) => abort!(res.kind.span(), "skip is only allowed on fields"), + Kind::Arg(_) => res, + } + } +@@ -459,13 +457,13 @@ impl Attrs { + match &*res.kind { + Kind::FlattenStruct => { + if res.has_custom_parser { +- span_error!( ++ abort!( + res.parser.span(), + "parse attribute is not allowed for flattened entry" + ); + } + if res.has_explicit_methods() || res.has_doc_methods() { +- span_error!( ++ abort!( + res.kind.span(), + "methods and doc comments are not allowed for flattened entry" + ); +@@ -473,13 +471,13 @@ impl Attrs { + } + Kind::Subcommand(_) => { + if res.has_custom_parser { +- span_error!( ++ abort!( + res.parser.span(), + "parse attribute is not allowed for subcommand" + ); + } + if res.has_explicit_methods() { +- span_error!( ++ abort!( + res.kind.span(), + "methods in attributes are not allowed for subcommand" + ); +@@ -488,13 +486,13 @@ impl Attrs { + let ty = Self::ty_from_field(&field.ty); + match *ty { + Ty::OptionOption => { +- span_error!( ++ abort!( + ty.span(), + "Option> type is not allowed for subcommand" + ); + } + Ty::OptionVec => { +- span_error!( ++ abort!( + ty.span(), + "Option> type is not allowed for subcommand" + ); +@@ -506,7 +504,7 @@ impl Attrs { + } + Kind::Skip(_) => { + if res.has_explicit_methods() { +- span_error!( ++ abort!( + res.kind.span(), + "methods are not allowed for skipped fields" + ); +@@ -524,23 +522,23 @@ impl Attrs { + match *ty { + Ty::Bool => { + if let Some(m) = res.find_method("default_value") { +- span_error!(m.name.span(), "default_value is meaningless for bool") ++ abort!(m.name.span(), "default_value is meaningless for bool") + } + if let Some(m) = res.find_method("required") { +- span_error!(m.name.span(), "required is meaningless for bool") ++ abort!(m.name.span(), "required is meaningless for bool") + } + } + Ty::Option => { + if let Some(m) = res.find_method("default_value") { +- span_error!(m.name.span(), "default_value is meaningless for Option") ++ abort!(m.name.span(), "default_value is meaningless for Option") + } + if let Some(m) = res.find_method("required") { +- span_error!(m.name.span(), "required is meaningless for Option") ++ abort!(m.name.span(), "required is meaningless for Option") + } + } + Ty::OptionOption => { + if res.is_positional() { +- span_error!( ++ abort!( + ty.span(), + "Option> type is meaningless for positional argument" + ) +@@ -548,7 +546,7 @@ impl Attrs { + } + Ty::OptionVec => { + if res.is_positional() { +- span_error!( ++ abort!( + ty.span(), + "Option> type is meaningless for positional argument" + ) +@@ -568,7 +566,7 @@ impl Attrs { + if let Kind::Arg(_) = *self.kind { + self.kind = kind; + } else { +- span_error!( ++ abort!( + kind.span(), + "subcommand, flatten and skip cannot be used together" + ); +@@ -586,7 +584,7 @@ impl Attrs { + /// generate methods from attributes on top of struct or enum + pub fn top_level_methods(&self) -> TokenStream { + let version = match (&self.no_version, &self.version) { +- (Some(no_version), Some(_)) => span_error!( ++ (Some(no_version), Some(_)) => abort!( + no_version.span(), + "`no_version` and `version = \"version\"` can't be used together" + ), +diff --git a/src/lib.rs b/src/lib.rs +index 80fbc9e..83a4377 100644 +--- a/src/lib.rs ++++ b/src/lib.rs +@@ -22,7 +22,7 @@ use crate::{ + }; + + use proc_macro2::{Span, TokenStream}; +-use proc_macro_error::{call_site_error, filter_macro_errors, set_dummy, span_error}; ++use proc_macro_error::{abort, abort_call_site, proc_macro_error, set_dummy}; + use quote::{quote, quote_spanned}; + use syn::{punctuated::Punctuated, spanned::Spanned, token::Comma, *}; + +@@ -41,12 +41,11 @@ struct GenOutput { + + /// Generates the `StructOpt` impl. + #[proc_macro_derive(StructOpt, attributes(structopt))] ++#[proc_macro_error] + pub fn structopt(input: proc_macro::TokenStream) -> proc_macro::TokenStream { +- filter_macro_errors! { +- let input: DeriveInput = syn::parse(input).unwrap(); +- let gen = impl_structopt(&input); +- gen.into() +- } ++ let input: DeriveInput = syn::parse(input).unwrap(); ++ let gen = impl_structopt(&input); ++ gen.into() + } + + /// Generate a block of code to add arguments/subcommands corresponding to +@@ -87,7 +86,7 @@ fn gen_augmentation( + + let subcmd = subcmds.next().map(|(_, ts)| ts); + if let Some((span, _)) = subcmds.next() { +- span_error!( ++ abort!( + span, + "multiple subcommand sets are not allowed, that's the second" + ); +@@ -446,7 +445,7 @@ fn gen_augment_clap_enum( + } + } + } +- Unnamed(..) => call_site_error!("{}: tuple enums are not supported", variant.ident), ++ Unnamed(..) => abort_call_site!("{}: tuple enums are not supported", variant.ident), + }; + + let name = attrs.cased_name(); +@@ -502,7 +501,7 @@ fn gen_from_subcommand( + let ty = &fields.unnamed[0]; + quote!( ( <#ty as ::structopt::StructOpt>::from_clap(matches) ) ) + } +- Unnamed(..) => call_site_error!("{}: tuple enums are not supported", variant.ident), ++ Unnamed(..) => abort_call_site!("{}: tuple enums are not supported", variant.ident), + }; + + quote! { +@@ -613,7 +612,7 @@ fn impl_structopt(input: &DeriveInput) -> TokenStream { + + let struct_name = &input.ident; + +- set_dummy(Some(quote! { ++ set_dummy(quote! { + impl ::structopt::StructOpt for #struct_name { + fn clap<'a, 'b>() -> ::structopt::clap::App<'a, 'b> { + unimplemented!() +@@ -622,7 +621,7 @@ fn impl_structopt(input: &DeriveInput) -> TokenStream { + unimplemented!() + } + } +- })); ++ }); + + match input.data { + Struct(DataStruct { +@@ -630,6 +629,6 @@ fn impl_structopt(input: &DeriveInput) -> TokenStream { + .. + }) => impl_structopt_for_struct(struct_name, &fields.named, &input.attrs), + Enum(ref e) => impl_structopt_for_enum(struct_name, &e.variants, &input.attrs), +- _ => call_site_error!("structopt only supports non-tuple structs and enums"), ++ _ => abort_call_site!("structopt only supports non-tuple structs and enums"), + } + } +diff --git a/src/parse.rs b/src/parse.rs +index 7e52699..cd040e5 100644 +--- a/src/parse.rs ++++ b/src/parse.rs +@@ -1,6 +1,6 @@ + use std::iter::FromIterator; + +-use proc_macro_error::{span_error, ResultExt}; ++use proc_macro_error::{abort, ResultExt}; + use syn::{ + self, parenthesized, + parse::{Parse, ParseStream}, +@@ -73,7 +73,12 @@ impl Parse for StructOptAttr { + + let check_empty_lit = |s| { + if lit_str.is_empty() { +- span_error!(lit.span(), "`#[structopt({} = \"\") is deprecated in structopt 0.3, now it's default behavior", s); ++ abort!( ++ lit.span(), ++ "`#[structopt({} = \"\") is deprecated in structopt 0.3, \ ++ now it's default behavior", ++ s ++ ); + } + }; + +@@ -116,7 +121,7 @@ impl Parse for StructOptAttr { + } + } + +- Err(_) => span_error! { ++ Err(_) => abort! { + assign_token.span(), + "expected `string literal` or `expression` after `=`" + }, +@@ -135,25 +140,35 @@ impl Parse for StructOptAttr { + if parser_specs.len() == 1 { + Ok(Parse(name, parser_specs[0].clone())) + } else { +- span_error!(name.span(), "parse must have exactly one argument") ++ abort!(name.span(), "parse must have exactly one argument") + } + } + +- "raw" => { +- match nested.parse::() { +- Ok(bool_token) => { +- let expr = ExprLit { attrs: vec![], lit: Lit::Bool(bool_token) }; +- let expr = Expr::Lit(expr); +- Ok(MethodCall(name, vec![expr])) +- } ++ "raw" => match nested.parse::() { ++ Ok(bool_token) => { ++ let expr = ExprLit { ++ attrs: vec![], ++ lit: Lit::Bool(bool_token), ++ }; ++ let expr = Expr::Lit(expr); ++ Ok(MethodCall(name, vec![expr])) ++ } + +- Err(_) => span_error!(name.span(), +- "`#[structopt(raw(...))` attributes are removed in structopt 0.3, they are replaced with raw methods\nhelp: if you meant to call `clap::Arg::raw()` method you should use bool literal, like `raw(true)` or `raw(false)`") ++ Err(_) => { ++ abort!(name.span(), ++ "`#[structopt(raw(...))` attributes are removed in structopt 0.3, \ ++ they are replaced with raw methods"; ++ help = "if you meant to call `clap::Arg::raw()` method \ ++ you should use bool literal, like `raw(true)` or `raw(false)`"; ++ note = "if you need to call some method from `clap::Arg/App` you \ ++ should use raw method"; ++ ); + } +- } ++ }, + + _ => { +- let method_args: Punctuated<_, Token![,]> = nested.parse_terminated(Expr::parse)?; ++ let method_args: Punctuated<_, Token![,]> = ++ nested.parse_terminated(Expr::parse)?; + Ok(MethodCall(name, Vec::from_iter(method_args))) + } + } +@@ -171,12 +186,14 @@ impl Parse for StructOptAttr { + + "skip" => Ok(Skip(name, None)), + +- "version" => { +- span_error!(name.span(), +- "#[structopt(version)] is invalid attribute, structopt 0.3 inherits version from Cargo.toml by default, no attribute needed") +- }, ++ "version" => abort!( ++ name.span(), ++ "#[structopt(version)] is invalid attribute, \ ++ structopt 0.3 inherits version from Cargo.toml by default, \ ++ no attribute needed" ++ ), + +- _ => span_error!(name.span(), "unexpected attribute: {}", name_str), ++ _ => abort!(name.span(), "unexpected attribute: {}", name_str), + } + } + } +@@ -223,7 +240,7 @@ pub fn parse_structopt_attributes(all_attrs: &[Attribute]) -> Vec + } + _ => e, + }) +- .unwrap_or_exit(); ++ .unwrap_or_abort(); + attrs.attrs + }) + .collect() +-- +2.24.1 + diff --git a/rust-structopt-derive.spec b/rust-structopt-derive.spec index 9700e58..bead734 100644 --- a/rust-structopt-derive.spec +++ b/rust-structopt-derive.spec @@ -13,6 +13,11 @@ Summary: Parse command line argument by defining a struct, derive crate License: ASL 2.0 or MIT URL: https://crates.io/crates/structopt-derive Source: %{crates_source} +# Initial patched metadata +# * Update proc-macro-error to 0.4 +Patch0: structopt-derive-fix-metadata.diff +# https://github.com/TeXitoi/structopt/commit/39535cac8c40dd79c53f6603525e2af00594747d +Patch0001: 0001-Update-proc-macro-error-to-v0.4.patch ExclusiveArch: %{rust_arches} %if %{__cargo_skip_build} diff --git a/structopt-derive-fix-metadata.diff b/structopt-derive-fix-metadata.diff new file mode 100644 index 0000000..a2b1980 --- /dev/null +++ b/structopt-derive-fix-metadata.diff @@ -0,0 +1,11 @@ +--- structopt-derive-0.3.5/Cargo.toml 1970-01-01T00:00:00+00:00 ++++ structopt-derive-0.3.5/Cargo.toml 2019-12-17T08:08:12.839000+00:00 +@@ -28,7 +28,7 @@ + version = "0.3.0" + + [dependencies.proc-macro-error] +-version = "0.2.6" ++version = "0.4.3" + + [dependencies.proc-macro2] + version = "1"