diff options
Diffstat (limited to 'syntax/attrs.rs')
-rw-r--r-- | syntax/attrs.rs | 73 |
1 files changed, 62 insertions, 11 deletions
diff --git a/syntax/attrs.rs b/syntax/attrs.rs index fa6c8097..46d010e0 100644 --- a/syntax/attrs.rs +++ b/syntax/attrs.rs @@ -1,11 +1,12 @@ +use crate::syntax::cfg::CfgExpr; use crate::syntax::namespace::Namespace; use crate::syntax::report::Errors; use crate::syntax::Atom::{self, *}; -use crate::syntax::{Derive, Doc, ForeignName}; +use crate::syntax::{cfg, Derive, Doc, ForeignName}; use proc_macro2::{Ident, TokenStream}; use quote::ToTokens; use syn::parse::{Nothing, Parse, ParseStream, Parser as _}; -use syn::{Attribute, Error, LitStr, Path, Result, Token}; +use syn::{parenthesized, token, Attribute, Error, LitStr, Path, Result, Token}; // Intended usage: // @@ -27,6 +28,7 @@ use syn::{Attribute, Error, LitStr, Path, Result, Token}; // #[derive(Default)] pub struct Parser<'a> { + pub cfg: Option<&'a mut CfgExpr>, pub doc: Option<&'a mut Doc>, pub derives: Option<&'a mut Vec<Derive>>, pub repr: Option<&'a mut Option<Atom>>, @@ -34,6 +36,7 @@ pub struct Parser<'a> { pub cxx_name: Option<&'a mut Option<ForeignName>>, pub rust_name: Option<&'a mut Option<Ident>>, pub variants_from_header: Option<&'a mut Option<Attribute>>, + pub ignore_unrecognized: bool, // Suppress clippy needless_update lint ("struct update has no effect, all // the fields in the struct have already been specified") when preemptively @@ -46,9 +49,12 @@ pub fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> Othe for attr in attrs { if attr.path.is_ident("doc") { match parse_doc_attribute.parse2(attr.tokens.clone()) { - Ok(lit) => { + Ok(attr) => { if let Some(doc) = &mut parser.doc { - doc.push(lit); + match attr { + DocAttribute::Doc(lit) => doc.push(lit), + DocAttribute::Hidden => doc.hidden = true, + } continue; } } @@ -122,7 +128,23 @@ pub fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> Othe break; } } - } else if attr.path.is_ident("variants_from_header") && cfg!(feature = "experimental") { + } else if attr.path.is_ident("cfg") { + match cfg::parse_attribute.parse2(attr.tokens.clone()) { + Ok(cfg_expr) => { + if let Some(cfg) = &mut parser.cfg { + cfg.merge(cfg_expr); + passthrough_attrs.push(attr); + continue; + } + } + Err(err) => { + cx.push(err); + break; + } + } + } else if attr.path.is_ident("variants_from_header") + && cfg!(feature = "experimental-enum-variants-from-header") + { if let Err(err) = Nothing::parse.parse2(attr.tokens.clone()) { cx.push(err); } @@ -140,6 +162,9 @@ pub fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> Othe // https://doc.rust-lang.org/reference/attributes/diagnostics.html passthrough_attrs.push(attr); continue; + } else if attr.path.is_ident("serde") { + passthrough_attrs.push(attr); + continue; } else if attr.path.segments.len() > 1 { let tool = &attr.path.segments.first().unwrap().ident; if tool == "rustfmt" { @@ -150,16 +175,37 @@ pub fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> Othe continue; } } - cx.error(attr, "unsupported attribute"); - break; + if !parser.ignore_unrecognized { + cx.error(attr, "unsupported attribute"); + break; + } } OtherAttrs(passthrough_attrs) } -fn parse_doc_attribute(input: ParseStream) -> Result<LitStr> { - input.parse::<Token![=]>()?; - let lit: LitStr = input.parse()?; - Ok(lit) +enum DocAttribute { + Doc(LitStr), + Hidden, +} + +mod kw { + syn::custom_keyword!(hidden); +} + +fn parse_doc_attribute(input: ParseStream) -> Result<DocAttribute> { + let lookahead = input.lookahead1(); + if lookahead.peek(Token![=]) { + input.parse::<Token![=]>()?; + let lit: LitStr = input.parse()?; + Ok(DocAttribute::Doc(lit)) + } else if lookahead.peek(token::Paren) { + let content; + parenthesized!(content in input); + content.parse::<kw::hidden>()?; + Ok(DocAttribute::Hidden) + } else { + Err(lookahead.error()) + } } fn parse_derive_attribute(cx: &mut Errors, input: ParseStream) -> Result<Vec<Derive>> { @@ -222,12 +268,17 @@ fn parse_rust_name_attribute(input: ParseStream) -> Result<Ident> { } } +#[derive(Clone)] pub struct OtherAttrs(Vec<Attribute>); impl OtherAttrs { pub fn none() -> Self { OtherAttrs(Vec::new()) } + + pub fn extend(&mut self, other: Self) { + self.0.extend(other.0); + } } impl ToTokens for OtherAttrs { |