From 65baf3fcd3e9ee1c6b55b620fb09cb0b1a621bb5 Mon Sep 17 00:00:00 2001 From: TheAwiteb Date: Thu, 2 Mar 2023 15:07:03 +0300 Subject: [PATCH] Replace `#[doc = ".."]` with `#[command(description = "...")]` --- crates/teloxide-macros/src/command_attr.rs | 36 ++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/crates/teloxide-macros/src/command_attr.rs b/crates/teloxide-macros/src/command_attr.rs index 1e01aed1..dcc9f148 100644 --- a/crates/teloxide-macros/src/command_attr.rs +++ b/crates/teloxide-macros/src/command_attr.rs @@ -7,7 +7,8 @@ use crate::{ }; use proc_macro2::Span; -use syn::Attribute; +use quote::quote_spanned; +use syn::{parse::Parser, spanned::Spanned, Attribute}; /// All attributes that can be used for `derive(BotCommands)` pub(crate) struct CommandAttrs { @@ -48,9 +49,40 @@ enum CommandAttrKind { impl CommandAttrs { pub fn from_attributes(attributes: &[Attribute]) -> Result { use CommandAttrKind::*; + // Convert the `doc` attribute into `command(description = "...")` + let attributes = attributes + .iter() + .map(|attr| { + if attr.path.is_ident("doc") { + // Extract the token literal from the doc attribute. + let description = attr + .tokens + .clone() + .into_iter() + .nth(1) + .map(|t| { + // remove first and last quotes only, is expected to be a string literal + let mut s = t.to_string(); + s.remove(0); + s.pop(); + s.trim().replace(r"\\n", "\n") + }) + .unwrap_or_default(); + // Convert the doc attribute into a command description attribute. + let sp = attr.span(); + let attr = Attribute::parse_outer + .parse2(quote_spanned!(sp => #[command(description = #description)])) + .unwrap(); + // SAFETY: `parse_outer` always returns a single attribute. + attr.into_iter().next().unwrap() + } else { + attr.clone() + } + }) + .collect::>(); fold_attrs( - attributes, + attributes.iter(), is_command_attribute, CommandAttr::parse, Self {