Skip to content

Commit

Permalink
Merge pull request #3832 from epage/derive
Browse files Browse the repository at this point in the history
fix(derive): Provide derive-friendly deprecation messages
  • Loading branch information
epage authored Jun 14, 2022
2 parents 63a17a4 + 5881bd0 commit ffd24af
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 9 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
4 changes: 3 additions & 1 deletion clap_derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,6 @@ proc-macro-error = "1"
[features]
default = []
debug = []
unstable-v4 = []
unstable-v4 = ["deprecated"]
deprecated = []
raw-deprecated = ["deprecated"]
4 changes: 4 additions & 0 deletions clap_derive/src/attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Parser> {
self.parser
.clone()
Expand Down
75 changes: 68 additions & 7 deletions clap_derive/src/derives/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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<Self, clap::Error> {
#raw_deprecated
let v = #struct_name #constructor;
::std::result::Result::Ok(v)
}
Expand All @@ -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(())
}
Expand Down Expand Up @@ -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() {
Expand All @@ -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)
Expand Down Expand Up @@ -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
});
})
}
}
Expand Down Expand Up @@ -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`

}
}
6 changes: 6 additions & 0 deletions clap_derive/src/derives/subcommand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Self, clap::Error> {
#raw_deprecated

#( #child_subcommands )else*

if let Some((#subcommand_name_var, mut __clap_arg_sub_matches)) = __clap_arg_matches.remove_subcommand() {
Expand Down Expand Up @@ -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 ),*
Expand Down

0 comments on commit ffd24af

Please sign in to comment.