diff --git a/Cargo.toml b/Cargo.toml index baebad17..4c2c4c6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ quote = "0.6.10" ruma-api = "0.6.0" [dependencies.syn] -version = "0.14" +version = "0.15.22" features = ["full"] [dependencies.proc-macro2] diff --git a/src/api/metadata.rs b/src/api/metadata.rs index 2684aab3..300eb44b 100644 --- a/src/api/metadata.rs +++ b/src/api/metadata.rs @@ -25,7 +25,7 @@ impl From> for Metadata { _ => panic!("expected Member::Named"), }; - match identifier.to_string().as_ref() { + match &identifier.to_string()[..] { "description" => { let expr_lit = match field_value.expr { Expr::Lit(expr_lit) => expr_lit, diff --git a/src/api/mod.rs b/src/api/mod.rs index 4ed3ddec..7287d397 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,8 +1,7 @@ use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, TokenStreamExt}; -use syn::punctuated::Punctuated; -use syn::synom::Synom; -use syn::{Field, FieldValue, Ident, Meta}; +use syn::{braced, Field, FieldValue, Ident, Meta, Token}; +use syn::parse::{Parse, ParseStream, Result}; mod metadata; mod request; @@ -24,7 +23,7 @@ pub fn strip_serde_attrs(field: &Field) -> Field { _ => return true, }; - if meta_list.ident == "serde" { + if &meta_list.ident.to_string() == "serde" { return false; } @@ -446,8 +445,13 @@ impl ToTokens for Api { } } -type ParseMetadata = Punctuated; -type ParseFields = Punctuated; +mod kw { + use syn::custom_keyword; + + custom_keyword!(metadata); + custom_keyword!(request); + custom_keyword!(response); +} pub struct RawApi { pub metadata: Vec, @@ -455,18 +459,33 @@ pub struct RawApi { pub response: Vec, } -impl Synom for RawApi { - named!(parse -> Self, do_parse!( - custom_keyword!(metadata) >> - metadata: braces!(ParseMetadata::parse_terminated) >> - custom_keyword!(request) >> - request: braces!(call!(ParseFields::parse_terminated_with, Field::parse_named)) >> - custom_keyword!(response) >> - response: braces!(call!(ParseFields::parse_terminated_with, Field::parse_named)) >> - (RawApi { - metadata: metadata.1.into_iter().collect(), - request: request.1.into_iter().collect(), - response: response.1.into_iter().collect(), +impl Parse for RawApi { + fn parse(input: ParseStream) -> Result { + input.parse::()?; + let metadata; + braced!(metadata in input); + + input.parse::()?; + let request; + braced!(request in input); + + input.parse::()?; + let response; + braced!(response in input); + + Ok(RawApi { + metadata: metadata + .parse_terminated::(FieldValue::parse)? + .into_iter() + .collect(), + request: request + .parse_terminated::(Field::parse_named)? + .into_iter() + .collect(), + response: response + .parse_terminated::(Field::parse_named)? + .into_iter() + .collect(), }) - )); + } } diff --git a/src/api/request.rs b/src/api/request.rs index 7ff4e54c..01fea4d7 100644 --- a/src/api/request.rs +++ b/src/api/request.rs @@ -1,5 +1,5 @@ use proc_macro2::{Span, TokenStream}; -use quote::{TokenStreamExt, ToTokens}; +use quote::{ToTokens, TokenStreamExt}; use syn::spanned::Spanned; use syn::{Field, Ident, Lit, Meta, NestedMeta}; @@ -153,7 +153,7 @@ impl From> for Request { _ => return true, }; - if meta_list.ident != "ruma_api" { + if &meta_list.ident.to_string() != "ruma_api" { return true; } @@ -162,7 +162,7 @@ impl From> for Request { NestedMeta::Meta(meta_item) => { match meta_item { Meta::Word(ident) => { - match ident.to_string().as_ref() { + match &ident.to_string()[..] { "body" => { has_newtype_body = true; field_kind = RequestFieldKind::NewtypeBody; @@ -173,7 +173,7 @@ impl From> for Request { } } Meta::NameValue(name_value) => { - match name_value.ident.to_string().as_ref() { + match &name_value.ident.to_string()[..] { "header" => { match name_value.lit { Lit::Str(lit_str) => header = Some(lit_str.value()), diff --git a/src/api/response.rs b/src/api/response.rs index 7b5d7ec1..a926913d 100644 --- a/src/api/response.rs +++ b/src/api/response.rs @@ -32,7 +32,10 @@ impl Response { for response_field in self.fields.iter() { match *response_field { ResponseField::Body(ref field) => { - let field_name = field.ident.as_ref().expect("expected field to have an identifier"); + let field_name = field + .ident + .clone() + .expect("expected field to have an identifier"); let span = field.span(); tokens.append_all(quote_spanned! {span=> @@ -40,7 +43,10 @@ impl Response { }); } ResponseField::Header(ref field, ref header) => { - let field_name = field.ident.as_ref().expect("expected field to have an identifier"); + let field_name = field + .ident + .clone() + .expect("expected field to have an identifier"); let header_name = Ident::new(header.as_ref(), Span::call_site()); let span = field.span(); @@ -53,7 +59,10 @@ impl Response { }); } ResponseField::NewtypeBody(ref field) => { - let field_name = field.ident.as_ref().expect("expected field to have an identifier"); + let field_name = field + .ident + .clone() + .expect("expected field to have an identifier"); let span = field.span(); tokens.append_all(quote_spanned! {span=> @@ -140,7 +149,7 @@ impl From> for Response { _ => return true, }; - if meta_list.ident != "ruma_api" { + if &meta_list.ident.to_string() != "ruma_api" { return true; } @@ -149,7 +158,7 @@ impl From> for Response { NestedMeta::Meta(meta_item) => { match meta_item { Meta::Word(ident) => { - match ident.to_string().as_ref() { + match &ident.to_string()[..] { "body" => { has_newtype_body = true; field_kind = ResponseFieldKind::NewtypeBody; @@ -158,7 +167,7 @@ impl From> for Response { } } Meta::NameValue(name_value) => { - match name_value.ident.to_string().as_ref() { + match &name_value.ident.to_string()[..] { "header" => { match name_value.lit { Lit::Str(lit_str) => header = Some(lit_str.value()), diff --git a/src/lib.rs b/src/lib.rs index 0a5966b0..1bd72a3c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,7 @@ extern crate proc_macro; extern crate proc_macro2; #[macro_use] extern crate quote; extern crate ruma_api; -#[macro_use] extern crate syn; +extern crate syn; use proc_macro::TokenStream; @@ -203,7 +203,7 @@ mod api; /// ``` #[proc_macro] pub fn ruma_api(input: TokenStream) -> TokenStream { - let raw_api: RawApi = syn::parse(input).expect("ruma_api! failed to parse input"); + let raw_api = syn::parse_macro_input!(input as RawApi); let api = Api::from(raw_api);