Add #[from_ref(skip)] (#1537)

For skipping individual fields.
This commit is contained in:
David Pedersen
2022-11-18 12:05:10 +01:00
committed by GitHub
parent 64960bb19c
commit 7d58d49817
5 changed files with 84 additions and 2 deletions
+52 -1
View File
@@ -1,6 +1,12 @@
use proc_macro2::{Ident, TokenStream};
use quote::quote_spanned;
use syn::{spanned::Spanned, Field, ItemStruct};
use syn::{
parse::{Parse, ParseStream},
spanned::Spanned,
Field, ItemStruct, Token,
};
use crate::attr_parsing::{combine_unary_attribute, parse_attrs, Combine};
pub(crate) fn expand(item: ItemStruct) -> TokenStream {
item.fields
@@ -11,6 +17,15 @@ pub(crate) fn expand(item: ItemStruct) -> TokenStream {
}
fn expand_field(state: &Ident, idx: usize, field: &Field) -> TokenStream {
let FieldAttrs { skip } = match parse_attrs("from_ref", &field.attrs) {
Ok(attrs) => attrs,
Err(err) => return err.into_compile_error(),
};
if skip.is_some() {
return TokenStream::default();
}
let field_ty = &field.ty;
let span = field.ty.span();
@@ -33,6 +48,42 @@ fn expand_field(state: &Ident, idx: usize, field: &Field) -> TokenStream {
}
}
mod kw {
syn::custom_keyword!(skip);
}
#[derive(Default)]
pub(super) struct FieldAttrs {
pub(super) skip: Option<kw::skip>,
}
impl Parse for FieldAttrs {
fn parse(input: ParseStream) -> syn::Result<Self> {
let mut skip = None;
while !input.is_empty() {
let lh = input.lookahead1();
if lh.peek(kw::skip) {
skip = Some(input.parse()?);
} else {
return Err(lh.error());
}
let _ = input.parse::<Token![,]>();
}
Ok(Self { skip })
}
}
impl Combine for FieldAttrs {
fn combine(mut self, other: Self) -> syn::Result<Self> {
let Self { skip } = other;
combine_unary_attribute(&mut self.skip, skip)?;
Ok(self)
}
}
#[test]
fn ui() {
crate::run_ui_tests("from_ref");