use proc_macro2::TokenStream;
use syn::{Error, Fields, Item, ItemStruct};
use crate::utils::format_error_output;
pub(crate) type Ast = ItemStruct;
pub(crate) fn parse(input: TokenStream) -> syn::Result<Ast> {
let item = match syn::parse2::<Item>(input.clone()) {
Ok(Item::Struct(item)) => Ok(item),
Ok(_) => {
Err(Error::new_spanned(
&input,
format_error_output(
"item is not a struct",
"`#[derive(Fields)]` can only be used on structs",
),
))
}
Err(_) => unreachable!(), }?;
if let Fields::Unnamed(ref fields) = item.fields {
if !fields.unnamed.is_empty() {
return Err(Error::new_spanned(
&input,
format_error_output("item is a tuple-like struct",
"`#[derive(Fields)]` can only be used on structs with named fields or unit structs")
));
}
}
Ok(item)
}
#[cfg(test)]
mod tests {
use quote::quote;
use super::*;
#[test]
fn valid_syntax_struct_named_fields() {
assert!(parse(quote!(
struct NamedFields {
first: u32,
second: String,
}
))
.is_ok());
}
#[test]
fn valid_syntax_unit_struct_no_braces() {
assert!(parse(quote!(
struct UnitStruct;
))
.is_ok());
}
#[test]
fn valid_syntax_unit_struct_parentheses() {
assert!(parse(quote!(
struct UnitStruct();
))
.is_ok());
}
#[test]
fn valid_syntax_unit_struct_curly_braces() {
assert!(parse(quote!(
struct UnitStruct {}
))
.is_ok());
}
}