Skip to content

Commit

Permalink
Parse inner attrs on structs, enums, unions, variants
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Apr 22, 2021
1 parent 2fcb301 commit 8ad9561
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 15 deletions.
16 changes: 14 additions & 2 deletions src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,11 +246,12 @@ pub mod parsing {
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Variant {
fn parse(input: ParseStream) -> Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
let mut attrs = input.call(Attribute::parse_outer)?;
let _visibility: Visibility = input.parse()?;
let ident: Ident = input.parse()?;
let fields = if input.peek(token::Brace) {
Fields::Named(input.parse()?)
let fields = parse_braced(input, &mut attrs)?;
Fields::Named(fields)
} else if input.peek(token::Paren) {
Fields::Unnamed(input.parse()?)
} else {
Expand Down Expand Up @@ -294,6 +295,17 @@ pub mod parsing {
}
}

pub(crate) fn parse_braced(
input: ParseStream,
attrs: &mut Vec<Attribute>,
) -> Result<FieldsNamed> {
let content;
let brace_token = braced!(content in input);
attr::parsing::parse_inner(&content, attrs)?;
let named = content.parse_terminated(Field::parse_named)?;
Ok(FieldsNamed { brace_token, named })
}

impl Field {
/// Parses a named (braced struct) field.
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
Expand Down
20 changes: 13 additions & 7 deletions src/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,15 @@ pub mod parsing {
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for DeriveInput {
fn parse(input: ParseStream) -> Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
let mut attrs = input.call(Attribute::parse_outer)?;
let vis = input.parse::<Visibility>()?;

let lookahead = input.lookahead1();
if lookahead.peek(Token![struct]) {
let struct_token = input.parse::<Token![struct]>()?;
let ident = input.parse::<Ident>()?;
let generics = input.parse::<Generics>()?;
let (where_clause, fields, semi) = data_struct(input)?;
let (where_clause, fields, semi) = data_struct(input, &mut attrs)?;
Ok(DeriveInput {
attrs,
vis,
Expand All @@ -122,7 +122,7 @@ pub mod parsing {
let enum_token = input.parse::<Token![enum]>()?;
let ident = input.parse::<Ident>()?;
let generics = input.parse::<Generics>()?;
let (where_clause, brace, variants) = data_enum(input)?;
let (where_clause, brace, variants) = data_enum(input, &mut attrs)?;
Ok(DeriveInput {
attrs,
vis,
Expand All @@ -141,7 +141,7 @@ pub mod parsing {
let union_token = input.parse::<Token![union]>()?;
let ident = input.parse::<Ident>()?;
let generics = input.parse::<Generics>()?;
let (where_clause, fields) = data_union(input)?;
let (where_clause, fields) = data_union(input, &mut attrs)?;
Ok(DeriveInput {
attrs,
vis,
Expand All @@ -163,6 +163,7 @@ pub mod parsing {

pub fn data_struct(
input: ParseStream,
attrs: &mut Vec<Attribute>,
) -> Result<(Option<WhereClause>, Fields, Option<Token![;]>)> {
let mut lookahead = input.lookahead1();
let mut where_clause = None;
Expand All @@ -187,7 +188,7 @@ pub mod parsing {
Err(lookahead.error())
}
} else if lookahead.peek(token::Brace) {
let fields = input.parse()?;
let fields = data::parsing::parse_braced(input, attrs)?;
Ok((where_clause, Fields::Named(fields), None))
} else if lookahead.peek(Token![;]) {
let semi = input.parse()?;
Expand All @@ -199,6 +200,7 @@ pub mod parsing {

pub fn data_enum(
input: ParseStream,
attrs: &mut Vec<Attribute>,
) -> Result<(
Option<WhereClause>,
token::Brace,
Expand All @@ -208,14 +210,18 @@ pub mod parsing {

let content;
let brace = braced!(content in input);
attr::parsing::parse_inner(&content, attrs)?;
let variants = content.parse_terminated(Variant::parse)?;

Ok((where_clause, brace, variants))
}

pub fn data_union(input: ParseStream) -> Result<(Option<WhereClause>, FieldsNamed)> {
pub fn data_union(
input: ParseStream,
attrs: &mut Vec<Attribute>,
) -> Result<(Option<WhereClause>, FieldsNamed)> {
let where_clause = input.parse()?;
let fields = input.parse()?;
let fields = data::parsing::parse_braced(input, attrs)?;
Ok((where_clause, fields))
}
}
Expand Down
14 changes: 8 additions & 6 deletions src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2009,12 +2009,13 @@ pub mod parsing {
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for ItemStruct {
fn parse(input: ParseStream) -> Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
let mut attrs = input.call(Attribute::parse_outer)?;
let vis = input.parse::<Visibility>()?;
let struct_token = input.parse::<Token![struct]>()?;
let ident = input.parse::<Ident>()?;
let generics = input.parse::<Generics>()?;
let (where_clause, fields, semi_token) = derive::parsing::data_struct(input)?;
let (where_clause, fields, semi_token) =
derive::parsing::data_struct(input, &mut attrs)?;
Ok(ItemStruct {
attrs,
vis,
Expand All @@ -2033,12 +2034,13 @@ pub mod parsing {
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for ItemEnum {
fn parse(input: ParseStream) -> Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
let mut attrs = input.call(Attribute::parse_outer)?;
let vis = input.parse::<Visibility>()?;
let enum_token = input.parse::<Token![enum]>()?;
let ident = input.parse::<Ident>()?;
let generics = input.parse::<Generics>()?;
let (where_clause, brace_token, variants) = derive::parsing::data_enum(input)?;
let (where_clause, brace_token, variants) =
derive::parsing::data_enum(input, &mut attrs)?;
Ok(ItemEnum {
attrs,
vis,
Expand All @@ -2057,12 +2059,12 @@ pub mod parsing {
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for ItemUnion {
fn parse(input: ParseStream) -> Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
let mut attrs = input.call(Attribute::parse_outer)?;
let vis = input.parse::<Visibility>()?;
let union_token = input.parse::<Token![union]>()?;
let ident = input.parse::<Ident>()?;
let generics = input.parse::<Generics>()?;
let (where_clause, fields) = derive::parsing::data_union(input)?;
let (where_clause, fields) = derive::parsing::data_union(input, &mut attrs)?;
Ok(ItemUnion {
attrs,
vis,
Expand Down

0 comments on commit 8ad9561

Please sign in to comment.