diff --git a/Cargo.toml b/Cargo.toml index f55486ce3ac..79d42ea32a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,7 +73,8 @@ color = ["atty", "termcolor"] suggestions = ["strsim"] # Optional -deprecated = [] # Guided experience to prepare for next breaking release (at different stages of development, this may become default) +# note: this will always enable clap_derive, change this to `clap_derive?/unstable-v4` when MSRV is bigger than 1.60 +deprecated = ["clap_derive/deprecated"] # Guided experience to prepare for next breaking release (at different stages of development, this may become default) derive = ["clap_derive", "once_cell"] cargo = ["once_cell"] # Disable if you're not using Cargo, enables Cargo-env-var-dependent macros wrap_help = ["terminal_size", "textwrap/terminal_size"] diff --git a/clap_derive/Cargo.toml b/clap_derive/Cargo.toml index df26e253c81..4982d85c630 100644 --- a/clap_derive/Cargo.toml +++ b/clap_derive/Cargo.toml @@ -51,4 +51,6 @@ proc-macro-error = "1" [features] default = [] debug = [] -unstable-v4 = [] +unstable-v4 = ["deprecated"] +deprecated = [] +raw-deprecated = ["deprecated"] diff --git a/clap_derive/src/attrs.rs b/clap_derive/src/attrs.rs index 39f1735557a..fb35d31f2d1 100644 --- a/clap_derive/src/attrs.rs +++ b/clap_derive/src/attrs.rs @@ -825,6 +825,10 @@ impl Attrs { self.value_parser.is_some() || self.action.is_some() } + pub fn explicit_parser(&self) -> bool { + self.parser.is_some() + } + pub fn parser(&self, field_type: &Type) -> Sp { self.parser .clone() diff --git a/clap_derive/src/derives/args.rs b/clap_derive/src/derives/args.rs index 08ddcc91307..4195a081082 100644 --- a/clap_derive/src/derives/args.rs +++ b/clap_derive/src/derives/args.rs @@ -113,6 +113,7 @@ pub fn gen_from_arg_matches_for_struct( let constructor = gen_constructor(fields, &attrs); let updater = gen_updater(fields, &attrs, true); + let raw_deprecated = raw_deprecated(); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); @@ -136,6 +137,7 @@ pub fn gen_from_arg_matches_for_struct( } fn from_arg_matches_mut(__clap_arg_matches: &mut clap::ArgMatches) -> ::std::result::Result { + #raw_deprecated let v = #struct_name #constructor; ::std::result::Result::Ok(v) } @@ -145,6 +147,7 @@ pub fn gen_from_arg_matches_for_struct( } fn update_from_arg_matches_mut(&mut self, __clap_arg_matches: &mut clap::ArgMatches) -> ::std::result::Result<(), clap::Error> { + #raw_deprecated #updater ::std::result::Result::Ok(()) } @@ -272,6 +275,45 @@ pub fn gen_augment( quote!() } }; + let parse_deprecation = match *parser.kind { + _ if !attrs.explicit_parser() || cfg!(not(feature = "deprecated")) => quote!(), + ParserKind::FromStr => quote_spanned! { func.span()=> + #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(value_parser = ...)]`")] + fn parse_from_str() { + } + parse_from_str(); + }, + ParserKind::TryFromStr => quote_spanned! { func.span()=> + #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(value_parser = ...)]`")] + fn parse_try_from_str() { + } + parse_try_from_str(); + }, + ParserKind::FromOsStr => quote_spanned! { func.span()=> + #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(value_parser)]` for `PathBuf` or `#[clap(value_parser = ...)]` with a custom `TypedValueParser`")] + fn parse_from_os_str() { + } + parse_from_os_str(); + }, + ParserKind::TryFromOsStr => quote_spanned! { func.span()=> + #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(value_parser = ...)]` with a custom `TypedValueParser`")] + fn parse_try_from_os_str() { + } + parse_try_from_os_str(); + }, + ParserKind::FromFlag => quote_spanned! { func.span()=> + #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(action = ArgAction::SetTrue)]`")] + fn parse_from_flag() { + } + parse_from_flag(); + }, + ParserKind::FromOccurrences => quote_spanned! { func.span()=> + #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(action = ArgAction::Count)]` with a field type of `u8`")] + fn parse_from_occurrences() { + } + parse_from_occurrences(); + }, + }; let value_name = attrs.value_name(); let possible_values = if attrs.is_enum() && !attrs.ignore_parser() { @@ -280,7 +322,7 @@ pub fn gen_augment( quote!() }; - let modifier = match **ty { + let implicit_methods = match **ty { Ty::Option => { quote_spanned! { ty.span()=> .takes_value(true) @@ -401,14 +443,20 @@ pub fn gen_augment( }; let id = attrs.id(); - let methods = attrs.field_methods(true); + let explicit_methods = attrs.field_methods(true); Some(quote_spanned! { field.span()=> - let #app_var = #app_var.arg( - clap::Arg::new(#id) - #modifier - #methods - ); + let #app_var = #app_var.arg({ + #parse_deprecation + + #[allow(deprecated)] + let arg = clap::Arg::new(#id) + #implicit_methods; + + let arg = arg + #explicit_methods; + arg + }); }) } } @@ -733,3 +781,16 @@ fn gen_parsers( quote_spanned!(field.span()=> #field_name: #field_value ) } } + +#[cfg(feature = "raw-deprecated")] +pub fn raw_deprecated() -> TokenStream { + quote! {} +} + +#[cfg(not(feature = "raw-deprecated"))] +pub fn raw_deprecated() -> TokenStream { + quote! { + #![allow(deprecated)] // Assuming any deprecation in here will be related to a deprecation in `Args` + + } +} diff --git a/clap_derive/src/derives/subcommand.rs b/clap_derive/src/derives/subcommand.rs index 343c4e3e412..07bdce5ec1d 100644 --- a/clap_derive/src/derives/subcommand.rs +++ b/clap_derive/src/derives/subcommand.rs @@ -540,8 +540,11 @@ fn gen_from_arg_matches( }, }; + let raw_deprecated = args::raw_deprecated(); quote! { fn from_arg_matches_mut(__clap_arg_matches: &mut clap::ArgMatches) -> ::std::result::Result { + #raw_deprecated + #( #child_subcommands )else* if let Some((#subcommand_name_var, mut __clap_arg_sub_matches)) = __clap_arg_matches.remove_subcommand() { @@ -652,11 +655,14 @@ fn gen_update_from_arg_matches( } }); + let raw_deprecated = args::raw_deprecated(); quote! { fn update_from_arg_matches_mut<'b>( &mut self, __clap_arg_matches: &mut clap::ArgMatches, ) -> ::std::result::Result<(), clap::Error> { + #raw_deprecated + if let Some(__clap_name) = __clap_arg_matches.subcommand_name() { match self { #( #subcommands ),*