blob: f48a210e1f19929a931867e9d904934de3be163b [file] [log] [blame]
David Tolnay3e628882020-05-10 15:30:14 -07001use crate::syntax::report::Errors;
David Tolnay7db73692019-10-20 14:51:12 -04002use crate::syntax::{Derive, Doc};
David Tolnayb129ea72020-05-10 14:29:30 -07003use syn::parse::{ParseStream, Parser as _};
David Tolnay7db73692019-10-20 14:51:12 -04004use syn::{Attribute, Error, LitStr, Path, Result, Token};
5
David Tolnayb129ea72020-05-10 14:29:30 -07006#[derive(Default)]
7pub struct Parser<'a> {
8 pub doc: Option<&'a mut Doc>,
9 pub derives: Option<&'a mut Vec<Derive>>,
10}
11
David Tolnay3e628882020-05-10 15:30:14 -070012pub(super) fn parse_doc(cx: &mut Errors, attrs: &[Attribute]) -> Doc {
David Tolnay7db73692019-10-20 14:51:12 -040013 let mut doc = Doc::new();
David Tolnayb129ea72020-05-10 14:29:30 -070014 parse(
David Tolnay3e628882020-05-10 15:30:14 -070015 cx,
David Tolnayb129ea72020-05-10 14:29:30 -070016 attrs,
17 Parser {
18 doc: Some(&mut doc),
19 ..Parser::default()
20 },
David Tolnay3e628882020-05-10 15:30:14 -070021 );
22 doc
David Tolnay7db73692019-10-20 14:51:12 -040023}
24
David Tolnay3e628882020-05-10 15:30:14 -070025pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
David Tolnay7db73692019-10-20 14:51:12 -040026 for attr in attrs {
27 if attr.path.is_ident("doc") {
David Tolnay3e628882020-05-10 15:30:14 -070028 match parse_doc_attribute.parse2(attr.tokens.clone()) {
29 Ok(lit) => {
30 if let Some(doc) = &mut parser.doc {
31 doc.push(lit);
32 continue;
33 }
34 }
35 Err(err) => return cx.push(err),
David Tolnayb129ea72020-05-10 14:29:30 -070036 }
David Tolnay7db73692019-10-20 14:51:12 -040037 } else if attr.path.is_ident("derive") {
David Tolnay3e628882020-05-10 15:30:14 -070038 match attr.parse_args_with(parse_derive_attribute) {
39 Ok(attr) => {
40 if let Some(derives) = &mut parser.derives {
41 derives.extend(attr);
42 continue;
43 }
44 }
45 Err(err) => return cx.push(err),
David Tolnay7db73692019-10-20 14:51:12 -040046 }
47 }
David Tolnay3e628882020-05-10 15:30:14 -070048 return cx.error(attr, "unsupported attribute");
David Tolnay7db73692019-10-20 14:51:12 -040049 }
David Tolnay7db73692019-10-20 14:51:12 -040050}
51
52fn parse_doc_attribute(input: ParseStream) -> Result<LitStr> {
53 input.parse::<Token![=]>()?;
54 let lit: LitStr = input.parse()?;
55 Ok(lit)
56}
57
David Tolnaye86b9cf2020-05-10 14:24:29 -070058fn parse_derive_attribute(input: ParseStream) -> Result<Vec<Derive>> {
David Tolnay7db73692019-10-20 14:51:12 -040059 input
60 .parse_terminated::<Path, Token![,]>(Path::parse_mod_style)?
61 .into_iter()
David Tolnaye86b9cf2020-05-10 14:24:29 -070062 .map(|path| {
63 if let Some(ident) = path.get_ident() {
64 if let Some(derive) = Derive::from(ident) {
65 return Ok(derive);
66 }
67 }
68 Err(Error::new_spanned(path, "unsupported derive"))
David Tolnay7db73692019-10-20 14:51:12 -040069 })
70 .collect()
71}