From 777e9c4c70ef00b8e132142ec1df277e39f7c509 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Sat, 20 Jul 2019 12:41:54 +0200 Subject: [PATCH] Stop throwing away span information when parsing metadata --- src/api/metadata.rs | 98 ++++++++++++++++++++------------------------- src/api/mod.rs | 11 +++-- 2 files changed, 50 insertions(+), 59 deletions(-) diff --git a/src/api/metadata.rs b/src/api/metadata.rs index 69fc7523..3d7b6a29 100644 --- a/src/api/metadata.rs +++ b/src/api/metadata.rs @@ -1,21 +1,22 @@ //! Details of the `metadata` section of the procedural macro. -use syn::{punctuated::Pair, Expr, FieldValue, Lit, Member}; +use proc_macro2::Ident; +use syn::{Expr, ExprLit, FieldValue, Lit, LitBool, LitStr, Member}; /// The result of processing the `metadata` section of the macro. pub struct Metadata { /// The description field. - pub description: String, + pub description: LitStr, /// The method field. - pub method: String, + pub method: Ident, /// The name field. - pub name: String, + pub name: LitStr, /// The path field. - pub path: String, + pub path: LitStr, /// The rate_limited field. - pub rate_limited: bool, + pub rate_limited: LitBool, /// The description field. - pub requires_authentication: bool, + pub requires_authentication: LitBool, } impl From> for Metadata { @@ -35,15 +36,13 @@ impl From> for Metadata { match &identifier.to_string()[..] { "description" => { - let expr_lit = match field_value.expr { - Expr::Lit(expr_lit) => expr_lit, - _ => panic!("expected Expr::Lit"), + let literal = match field_value.expr { + Expr::Lit(ExprLit { + lit: Lit::Str(s), .. + }) => s, + _ => panic!("expected string literal"), }; - let lit_str = match expr_lit.lit { - Lit::Str(lit_str) => lit_str, - _ => panic!("expected Lit::Str"), - }; - description = Some(lit_str.value()); + description = Some(literal); } "method" => { let expr_path = match field_value.expr { @@ -51,60 +50,49 @@ impl From> for Metadata { _ => panic!("expected Expr::Path"), }; let path = expr_path.path; - let segments = path.segments; - if segments.len() != 1 { - panic!("ruma_api! expects a one component path for `metadata` `method`"); - } - let pair = segments.first().unwrap(); // safe because we just checked - let method_name = match pair { - Pair::End(method_name) => method_name, - _ => panic!("expected Pair::End"), - }; - method = Some(method_name.ident.to_string()); + let mut segments = path.segments.iter(); + let method_name = segments.next().expect("expected non-empty path"); + assert!( + segments.next().is_none(), + "ruma_api! expects a one-component path for `metadata` `method`" + ); + method = Some(method_name.ident.clone()); } "name" => { - let expr_lit = match field_value.expr { - Expr::Lit(expr_lit) => expr_lit, - _ => panic!("expected Expr::Lit"), + let literal = match field_value.expr { + Expr::Lit(ExprLit { + lit: Lit::Str(s), .. + }) => s, + _ => panic!("expected string literal"), }; - let lit_str = match expr_lit.lit { - Lit::Str(lit_str) => lit_str, - _ => panic!("expected Lit::Str"), - }; - name = Some(lit_str.value()); + name = Some(literal); } "path" => { - let expr_lit = match field_value.expr { - Expr::Lit(expr_lit) => expr_lit, - _ => panic!("expected Expr::Lit"), + let literal = match field_value.expr { + Expr::Lit(ExprLit { + lit: Lit::Str(s), .. + }) => s, + _ => panic!("expected string literal"), }; - let lit_str = match expr_lit.lit { - Lit::Str(lit_str) => lit_str, - _ => panic!("expected Lit::Str"), - }; - path = Some(lit_str.value()); + path = Some(literal); } "rate_limited" => { - let expr_lit = match field_value.expr { - Expr::Lit(expr_lit) => expr_lit, + let literal = match field_value.expr { + Expr::Lit(ExprLit { + lit: Lit::Bool(b), .. + }) => b, _ => panic!("expected Expr::Lit"), }; - let lit_bool = match expr_lit.lit { - Lit::Bool(lit_bool) => lit_bool, - _ => panic!("expected Lit::Bool"), - }; - rate_limited = Some(lit_bool.value) + rate_limited = Some(literal) } "requires_authentication" => { - let expr_lit = match field_value.expr { - Expr::Lit(expr_lit) => expr_lit, + let literal = match field_value.expr { + Expr::Lit(ExprLit { + lit: Lit::Bool(b), .. + }) => b, _ => panic!("expected Expr::Lit"), }; - let lit_bool = match expr_lit.lit { - Lit::Bool(lit_bool) => lit_bool, - _ => panic!("expected Lit::Bool"), - }; - requires_authentication = Some(lit_bool.value) + requires_authentication = Some(literal) } _ => panic!("ruma_api! metadata included unexpected field"), } diff --git a/src/api/mod.rs b/src/api/mod.rs index 0fc84677..00d6eac8 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -65,8 +65,11 @@ impl From for Api { impl ToTokens for Api { fn to_tokens(&self, tokens: &mut TokenStream) { let description = &self.metadata.description; - let method = Ident::new(self.metadata.method.as_ref(), Span::call_site()); - let name = &self.metadata.name; + let method = &self.metadata.method; + // We don't (currently) use this literal as a literal in the generated code. Instead we just + // put it into doc comments, for which the span information is irrelevant. So we can work + // with only the literal's value from here on. + let name = &self.metadata.name.value(); let path = &self.metadata.path; let rate_limited = &self.metadata.rate_limited; let requires_authentication = &self.metadata.requires_authentication; @@ -85,7 +88,7 @@ impl ToTokens for Api { }; let (set_request_path, parse_request_path) = if self.request.has_path_fields() { - let path_str = path.as_str(); + let path_str = path.value(); assert!(path_str.starts_with('/'), "path needs to start with '/'"); assert!( @@ -313,7 +316,7 @@ impl ToTokens for Api { } }; - let endpoint_doc = format!("The `{}` API endpoint.\n\n{}", name, description); + let endpoint_doc = format!("The `{}` API endpoint.\n\n{}", name, description.value()); let request_doc = format!("Data for a request to the `{}` API endpoint.", name); let response_doc = format!("Data in the response from the `{}` API endpoint.", name);