mirror of
https://github.com/dtolnay/thiserror.git
synced 2025-04-03 21:07:38 +03:00
Locate field that has the #[source] attribute
This commit is contained in:
parent
f1dcfe0f0a
commit
4cdeec15e5
3 changed files with 33 additions and 13 deletions
12
impl/src/attr.rs
Normal file
12
impl/src/attr.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
use syn::parse::Nothing;
|
||||
use syn::{Field, Result};
|
||||
|
||||
pub fn is_source(field: &Field) -> Result<bool> {
|
||||
for attr in &field.attrs {
|
||||
if attr.path.is_ident("source") {
|
||||
syn::parse2::<Nothing>(attr.tokens.clone())?;
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
Ok(false)
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
use crate::attr;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{
|
||||
Data, DataEnum, DataStruct, DeriveInput, Error, Fields, FieldsNamed, FieldsUnnamed, Member,
|
||||
Result,
|
||||
Data, DataEnum, DataStruct, DeriveInput, Error, Fields, FieldsNamed, FieldsUnnamed, Index,
|
||||
Member, Result,
|
||||
};
|
||||
|
||||
pub fn derive(input: &DeriveInput) -> Result<TokenStream> {
|
||||
|
@ -21,8 +22,8 @@ fn struct_error(input: &DeriveInput, data: &DataStruct) -> Result<TokenStream> {
|
|||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||
|
||||
let source = match &data.fields {
|
||||
Fields::Named(fields) => braced_struct_source(input, fields)?,
|
||||
Fields::Unnamed(fields) => tuple_struct_source(input, fields)?,
|
||||
Fields::Named(fields) => braced_struct_source(fields)?,
|
||||
Fields::Unnamed(fields) => tuple_struct_source(fields)?,
|
||||
Fields::Unit => None,
|
||||
};
|
||||
|
||||
|
@ -41,16 +42,22 @@ fn struct_error(input: &DeriveInput, data: &DataStruct) -> Result<TokenStream> {
|
|||
})
|
||||
}
|
||||
|
||||
fn braced_struct_source(input: &DeriveInput, fields: &FieldsNamed) -> Result<Option<Member>> {
|
||||
let _ = input;
|
||||
let _ = fields;
|
||||
unimplemented!()
|
||||
fn braced_struct_source(fields: &FieldsNamed) -> Result<Option<Member>> {
|
||||
for field in &fields.named {
|
||||
if attr::is_source(field)? {
|
||||
return Ok(Some(Member::Named(field.ident.as_ref().unwrap().clone())));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn tuple_struct_source(input: &DeriveInput, fields: &FieldsUnnamed) -> Result<Option<Member>> {
|
||||
let _ = input;
|
||||
let _ = fields;
|
||||
unimplemented!()
|
||||
fn tuple_struct_source(fields: &FieldsUnnamed) -> Result<Option<Member>> {
|
||||
for (i, field) in fields.unnamed.iter().enumerate() {
|
||||
if attr::is_source(field)? {
|
||||
return Ok(Some(Member::Unnamed(Index::from(i))));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn enum_error(input: &DeriveInput, data: &DataEnum) -> Result<TokenStream> {
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
extern crate proc_macro;
|
||||
|
||||
mod attr;
|
||||
mod expand;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use syn::{parse_macro_input, DeriveInput};
|
||||
|
||||
#[proc_macro_derive(Error)]
|
||||
#[proc_macro_derive(Error, attributes(source))]
|
||||
pub fn derive_error(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
expand::derive(&input)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue