Merge remote-tracking branch 'fest-im/master'

This commit is contained in:
Jimmy Cuadra 2018-12-03 18:26:57 -08:00
commit 1ac3236a9e
6 changed files with 61 additions and 33 deletions

View File

@ -15,7 +15,7 @@ quote = "0.6.10"
ruma-api = "0.6.0" ruma-api = "0.6.0"
[dependencies.syn] [dependencies.syn]
version = "0.14" version = "0.15.22"
features = ["full"] features = ["full"]
[dependencies.proc-macro2] [dependencies.proc-macro2]

View File

@ -25,7 +25,7 @@ impl From<Vec<FieldValue>> for Metadata {
_ => panic!("expected Member::Named"), _ => panic!("expected Member::Named"),
}; };
match identifier.to_string().as_ref() { match &identifier.to_string()[..] {
"description" => { "description" => {
let expr_lit = match field_value.expr { let expr_lit = match field_value.expr {
Expr::Lit(expr_lit) => expr_lit, Expr::Lit(expr_lit) => expr_lit,

View File

@ -1,8 +1,7 @@
use proc_macro2::{Span, TokenStream}; use proc_macro2::{Span, TokenStream};
use quote::{ToTokens, TokenStreamExt}; use quote::{ToTokens, TokenStreamExt};
use syn::punctuated::Punctuated; use syn::{braced, Field, FieldValue, Ident, Meta, Token};
use syn::synom::Synom; use syn::parse::{Parse, ParseStream, Result};
use syn::{Field, FieldValue, Ident, Meta};
mod metadata; mod metadata;
mod request; mod request;
@ -24,7 +23,7 @@ pub fn strip_serde_attrs(field: &Field) -> Field {
_ => return true, _ => return true,
}; };
if meta_list.ident == "serde" { if &meta_list.ident.to_string() == "serde" {
return false; return false;
} }
@ -446,8 +445,13 @@ impl ToTokens for Api {
} }
} }
type ParseMetadata = Punctuated<FieldValue, Token![,]>; mod kw {
type ParseFields = Punctuated<Field, Token![,]>; use syn::custom_keyword;
custom_keyword!(metadata);
custom_keyword!(request);
custom_keyword!(response);
}
pub struct RawApi { pub struct RawApi {
pub metadata: Vec<FieldValue>, pub metadata: Vec<FieldValue>,
@ -455,18 +459,33 @@ pub struct RawApi {
pub response: Vec<Field>, pub response: Vec<Field>,
} }
impl Synom for RawApi { impl Parse for RawApi {
named!(parse -> Self, do_parse!( fn parse(input: ParseStream) -> Result<Self> {
custom_keyword!(metadata) >> input.parse::<kw::metadata>()?;
metadata: braces!(ParseMetadata::parse_terminated) >> let metadata;
custom_keyword!(request) >> braced!(metadata in input);
request: braces!(call!(ParseFields::parse_terminated_with, Field::parse_named)) >>
custom_keyword!(response) >> input.parse::<kw::request>()?;
response: braces!(call!(ParseFields::parse_terminated_with, Field::parse_named)) >> let request;
(RawApi { braced!(request in input);
metadata: metadata.1.into_iter().collect(),
request: request.1.into_iter().collect(), input.parse::<kw::response>()?;
response: response.1.into_iter().collect(), let response;
braced!(response in input);
Ok(RawApi {
metadata: metadata
.parse_terminated::<FieldValue, Token![,]>(FieldValue::parse)?
.into_iter()
.collect(),
request: request
.parse_terminated::<Field, Token![,]>(Field::parse_named)?
.into_iter()
.collect(),
response: response
.parse_terminated::<Field, Token![,]>(Field::parse_named)?
.into_iter()
.collect(),
}) })
)); }
} }

View File

@ -1,5 +1,5 @@
use proc_macro2::{Span, TokenStream}; use proc_macro2::{Span, TokenStream};
use quote::{TokenStreamExt, ToTokens}; use quote::{ToTokens, TokenStreamExt};
use syn::spanned::Spanned; use syn::spanned::Spanned;
use syn::{Field, Ident, Lit, Meta, NestedMeta}; use syn::{Field, Ident, Lit, Meta, NestedMeta};
@ -153,7 +153,7 @@ impl From<Vec<Field>> for Request {
_ => return true, _ => return true,
}; };
if meta_list.ident != "ruma_api" { if &meta_list.ident.to_string() != "ruma_api" {
return true; return true;
} }
@ -162,7 +162,7 @@ impl From<Vec<Field>> for Request {
NestedMeta::Meta(meta_item) => { NestedMeta::Meta(meta_item) => {
match meta_item { match meta_item {
Meta::Word(ident) => { Meta::Word(ident) => {
match ident.to_string().as_ref() { match &ident.to_string()[..] {
"body" => { "body" => {
has_newtype_body = true; has_newtype_body = true;
field_kind = RequestFieldKind::NewtypeBody; field_kind = RequestFieldKind::NewtypeBody;
@ -173,7 +173,7 @@ impl From<Vec<Field>> for Request {
} }
} }
Meta::NameValue(name_value) => { Meta::NameValue(name_value) => {
match name_value.ident.to_string().as_ref() { match &name_value.ident.to_string()[..] {
"header" => { "header" => {
match name_value.lit { match name_value.lit {
Lit::Str(lit_str) => header = Some(lit_str.value()), Lit::Str(lit_str) => header = Some(lit_str.value()),

View File

@ -32,7 +32,10 @@ impl Response {
for response_field in self.fields.iter() { for response_field in self.fields.iter() {
match *response_field { match *response_field {
ResponseField::Body(ref 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(); let span = field.span();
tokens.append_all(quote_spanned! {span=> tokens.append_all(quote_spanned! {span=>
@ -40,7 +43,10 @@ impl Response {
}); });
} }
ResponseField::Header(ref field, ref header) => { 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 header_name = Ident::new(header.as_ref(), Span::call_site());
let span = field.span(); let span = field.span();
@ -53,7 +59,10 @@ impl Response {
}); });
} }
ResponseField::NewtypeBody(ref field) => { 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(); let span = field.span();
tokens.append_all(quote_spanned! {span=> tokens.append_all(quote_spanned! {span=>
@ -140,7 +149,7 @@ impl From<Vec<Field>> for Response {
_ => return true, _ => return true,
}; };
if meta_list.ident != "ruma_api" { if &meta_list.ident.to_string() != "ruma_api" {
return true; return true;
} }
@ -149,7 +158,7 @@ impl From<Vec<Field>> for Response {
NestedMeta::Meta(meta_item) => { NestedMeta::Meta(meta_item) => {
match meta_item { match meta_item {
Meta::Word(ident) => { Meta::Word(ident) => {
match ident.to_string().as_ref() { match &ident.to_string()[..] {
"body" => { "body" => {
has_newtype_body = true; has_newtype_body = true;
field_kind = ResponseFieldKind::NewtypeBody; field_kind = ResponseFieldKind::NewtypeBody;
@ -158,7 +167,7 @@ impl From<Vec<Field>> for Response {
} }
} }
Meta::NameValue(name_value) => { Meta::NameValue(name_value) => {
match name_value.ident.to_string().as_ref() { match &name_value.ident.to_string()[..] {
"header" => { "header" => {
match name_value.lit { match name_value.lit {
Lit::Str(lit_str) => header = Some(lit_str.value()), Lit::Str(lit_str) => header = Some(lit_str.value()),

View File

@ -10,7 +10,7 @@ extern crate proc_macro;
extern crate proc_macro2; extern crate proc_macro2;
#[macro_use] extern crate quote; #[macro_use] extern crate quote;
extern crate ruma_api; extern crate ruma_api;
#[macro_use] extern crate syn; extern crate syn;
use proc_macro::TokenStream; use proc_macro::TokenStream;
@ -203,7 +203,7 @@ mod api;
/// ``` /// ```
#[proc_macro] #[proc_macro]
pub fn ruma_api(input: TokenStream) -> TokenStream { 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); let api = Api::from(raw_api);