Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 26 additions & 16 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion clap_derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ proc-macro = true
bench = false

[dependencies]
syn = { version = "2.0.8", features = ["full"] }
syn = { git = "https://github.com/DJMcNab/syn.git", branch = "with-default-fields", features = ["full"] }
quote = "1.0.9"
proc-macro2 = "1.0.69"
heck = "0.5.0"
Expand Down
33 changes: 18 additions & 15 deletions clap_derive/src/derives/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,35 @@

use proc_macro2::{Ident, Span, TokenStream};
use quote::{format_ident, quote, quote_spanned};
use syn::{punctuated::Punctuated, spanned::Spanned, token::Comma, Generics};
use syn::{
punctuated::Punctuated, spanned::Spanned, token::Comma, Data, DataStruct, DeriveInput, Field,
Fields, FieldsNamed, Generics,
DataStructWithDefault, DataWithDefault, DeriveInputWithDefault, FieldWithDefault,
FieldsNamedWithDefault, FieldsWithDefault,
};

use crate::item::{Item, Kind, Name};
use crate::utils::{inner_type, sub_type, Sp, Ty};

pub(crate) fn derive_args(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
pub(crate) fn derive_args(input: &DeriveInputWithDefault) -> Result<TokenStream, syn::Error> {
let ident = &input.ident;

match input.data {
Data::Struct(DataStruct {
fields: Fields::Named(ref fields),
DataWithDefault::Struct(DataStructWithDefault {
fields: FieldsWithDefault::Named(ref fields),
..
}) => {
let name = Name::Derived(ident.clone());
let item = Item::from_args_struct(input, name)?;
let fields = collect_args_fields(&item, fields)?;
gen_for_struct(&item, ident, &input.generics, &fields)
}
Data::Struct(DataStruct {
fields: Fields::Unit,
DataWithDefault::Struct(DataStructWithDefault {
fields: FieldsWithDefault::Unit,
..
}) => {
let name = Name::Derived(ident.clone());
let item = Item::from_args_struct(input, name)?;
let fields = Punctuated::<Field, Comma>::new();
let fields = Punctuated::<FieldWithDefault, Comma>::new();
let fields = fields
.iter()
.map(|field| {
Expand All @@ -59,7 +60,7 @@ pub(crate) fn gen_for_struct(
item: &Item,
item_name: &Ident,
generics: &Generics,
fields: &[(&Field, Item)],
fields: &[(&FieldWithDefault, Item)],
) -> Result<TokenStream, syn::Error> {
if !matches!(&*item.kind(), Kind::Command(_)) {
abort! { item.kind().span(),
Expand Down Expand Up @@ -167,7 +168,7 @@ pub(crate) fn gen_for_struct(
/// Generate a block of code to add arguments/subcommands corresponding to
/// the `fields` to an cmd.
pub(crate) fn gen_augment(
fields: &[(&Field, Item)],
fields: &[(&FieldWithDefault, Item)],
app_var: &Ident,
parent_item: &Item,
override_required: bool,
Expand Down Expand Up @@ -440,7 +441,9 @@ pub(crate) fn gen_augment(
}})
}

pub(crate) fn gen_constructor(fields: &[(&Field, Item)]) -> Result<TokenStream, syn::Error> {
pub(crate) fn gen_constructor(
fields: &[(&FieldWithDefault, Item)],
) -> Result<TokenStream, syn::Error> {
let fields = fields.iter().map(|(field, item)| {
let field_name = field.ident.as_ref().unwrap();
let kind = item.kind();
Expand Down Expand Up @@ -552,7 +555,7 @@ pub(crate) fn gen_constructor(fields: &[(&Field, Item)]) -> Result<TokenStream,
}

pub(crate) fn gen_updater(
fields: &[(&Field, Item)],
fields: &[(&FieldWithDefault, Item)],
use_self: bool,
) -> Result<TokenStream, syn::Error> {
let mut genned_fields = Vec::new();
Expand Down Expand Up @@ -661,7 +664,7 @@ fn gen_parsers(
item: &Item,
ty: &Sp<Ty>,
field_name: &Ident,
field: &Field,
field: &FieldWithDefault,
update: Option<&TokenStream>,
) -> Result<TokenStream, syn::Error> {
let span = ty.span();
Expand Down Expand Up @@ -776,8 +779,8 @@ pub(crate) fn raw_deprecated() -> TokenStream {

pub(crate) fn collect_args_fields<'a>(
item: &'a Item,
fields: &'a FieldsNamed,
) -> Result<Vec<(&'a Field, Item)>, syn::Error> {
fields: &'a FieldsNamedWithDefault,
) -> Result<Vec<(&'a FieldWithDefault, Item)>, syn::Error> {
fields
.named
.iter()
Expand Down
30 changes: 16 additions & 14 deletions clap_derive/src/derives/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,39 +14,41 @@

use proc_macro2::TokenStream;
use quote::quote;
use syn::DataStructWithDefault;
use syn::DataWithDefault;
use syn::DeriveInputWithDefault;
use syn::FieldWithDefault;
use syn::FieldsWithDefault;
use syn::Ident;
use syn::Variant;
use syn::{
self, punctuated::Punctuated, token::Comma, Data, DataStruct, DeriveInput, Field, Fields,
Generics,
};
use syn::VariantWithDefault;
use syn::{self, punctuated::Punctuated, token::Comma, Generics};

use crate::derives::args::collect_args_fields;
use crate::derives::{args, into_app, subcommand};
use crate::item::Item;
use crate::item::Name;

pub(crate) fn derive_parser(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
pub(crate) fn derive_parser(input: &DeriveInputWithDefault) -> Result<TokenStream, syn::Error> {
let ident = &input.ident;
let pkg_name = std::env::var("CARGO_PKG_NAME").ok().unwrap_or_default();

match input.data {
Data::Struct(DataStruct {
fields: Fields::Named(ref fields),
DataWithDefault::Struct(DataStructWithDefault {
fields: FieldsWithDefault::Named(ref fields),
..
}) => {
let name = Name::Assigned(quote!(#pkg_name));
let item = Item::from_args_struct(input, name)?;
let fields = collect_args_fields(&item, fields)?;
gen_for_struct(&item, ident, &input.generics, &fields)
}
Data::Struct(DataStruct {
fields: Fields::Unit,
DataWithDefault::Struct(DataStructWithDefault {
fields: FieldsWithDefault::Unit,
..
}) => {
let name = Name::Assigned(quote!(#pkg_name));
let item = Item::from_args_struct(input, name)?;
let fields = Punctuated::<Field, Comma>::new();
let fields = Punctuated::<FieldWithDefault, Comma>::new();
let fields = fields
.iter()
.map(|field| {
Expand All @@ -56,7 +58,7 @@ pub(crate) fn derive_parser(input: &DeriveInput) -> Result<TokenStream, syn::Err
.collect::<Result<Vec<_>, syn::Error>>()?;
gen_for_struct(&item, ident, &input.generics, &fields)
}
Data::Enum(ref e) => {
DataWithDefault::Enum(ref e) => {
let name = Name::Assigned(quote!(#pkg_name));
let item = Item::from_subcommand_enum(input, name)?;
let variants = e
Expand All @@ -78,7 +80,7 @@ fn gen_for_struct(
item: &Item,
item_name: &Ident,
generics: &Generics,
fields: &[(&Field, Item)],
fields: &[(&FieldWithDefault, Item)],
) -> Result<TokenStream, syn::Error> {
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

Expand All @@ -102,7 +104,7 @@ fn gen_for_enum(
item: &Item,
item_name: &Ident,
generics: &Generics,
variants: &[(&Variant, Item)],
variants: &[(&VariantWithDefault, Item)],
) -> Result<TokenStream, syn::Error> {
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

Expand Down
Loading
Loading