aboutsummaryrefslogtreecommitdiff
path: root/syntax/attrs.rs
diff options
context:
space:
mode:
Diffstat (limited to 'syntax/attrs.rs')
-rw-r--r--syntax/attrs.rs73
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 {