From 144eb73aaf39145bf8f6b57eec5c76730961c2f1 Mon Sep 17 00:00:00 2001 From: Hirrolot Date: Thu, 24 Mar 2022 15:04:38 +0600 Subject: [PATCH 1/2] Remove support for the old dispatching --- src/dialogue_state.rs | 4 +- src/lib.rs | 172 +----------------------------------------- 2 files changed, 4 insertions(+), 172 deletions(-) diff --git a/src/dialogue_state.rs b/src/dialogue_state.rs index 9aa22c12..5178c754 100644 --- a/src/dialogue_state.rs +++ b/src/dialogue_state.rs @@ -99,9 +99,9 @@ pub fn expand(item: ItemEnum) -> Result { fn assert_clone() {} use teloxide::dptree; - use teloxide::dispatching2::dialogue::Dialogue; + use teloxide::dispatching::dialogue::Dialogue; - impl #self_params_with_bounds teloxide::dispatching2::HandlerFactory for #enum_ident #self_params #where_clause { + impl #self_params_with_bounds teloxide::dispatching::HandlerFactory for #enum_ident #self_params #where_clause { type Out = #out; fn handler() -> dptree::Handler<'static, dptree::di::DependencyMap, Self::Out> { diff --git a/src/lib.rs b/src/lib.rs index c17bbfa6..ab3d04f8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,185 +18,17 @@ use crate::{ }; use proc_macro::TokenStream; use quote::{quote, ToTokens}; -use syn::{ - parse_macro_input, DeriveInput, Fields, FnArg, ItemEnum, ItemFn, - ReturnType, Type, -}; - -use std::fmt::Write; +use syn::{parse_macro_input, DeriveInput, Fields, ItemEnum}; #[proc_macro_derive(DialogueState, attributes(handler, handler_out, store))] pub fn derive_dialogue_state(item: TokenStream) -> TokenStream { let input = parse_macro_input!(item as ItemEnum); match dialogue_state::expand(input) { Ok(s) => s.into(), - Err(e) => e.into_compile_error().into(), + Err(e) => e.to_compile_error().into(), } } -/// The docs is below. -/// -/// The only accepted form at the current moment is `#[teloxide(subtransition)]` -/// on an asynchronous function. Either this: -/// -/// ```no_compile -/// #[teloxide(subtransition)] -/// async fn my_transition(state: MyState, cx: TransitionIn, ans: T) -> TransitionOut { -/// todo!() -/// } -/// ``` -/// -/// Or this: -/// -/// ```no_compile -/// #[teloxide(subtransition)] -/// async fn my_transition(state: MyState, cx: TransitionIn) -> TransitionOut { -/// todo!() -/// } -/// ``` -/// -/// Notice the presence/absence of `ans: T`. In the first case, it generates -/// `impl SubTransition for MyState { type Aux = T; type Dialogue = MyDialogue; -/// ... }`. In the second case, the `Aux` type defaults to `()`. -#[proc_macro_attribute] -pub fn teloxide(attr: TokenStream, item: TokenStream) -> TokenStream { - match attr.to_string().as_ref() { - "subtransition" => { - let item_cloned = item.clone(); - let input = parse_macro_input!(item as ItemFn); - let params = input.sig.inputs.iter().collect::>(); - - if params.len() != 2 && params.len() != 3 { - panic!( - "An transition function must accept two/three parameters: \ - a state type, TransitionIn, and an optional data." - ); - } - - // This is actually used inside the quite! { ... } below. - #[allow(unused_variables)] - let state_type = match params[0] { - FnArg::Typed(pat_type) => &pat_type.ty, - _ => unreachable!(), - }; - let fn_name = input.sig.ident; - let fn_return_type = match input.sig.output { - ReturnType::Type(_arrow, _type) => _type, - _ => panic!( - "A subtransition must return TransitionOut" - ), - }; - let requester_param_type = match params - .get(1) - .expect("A requester parameter must be specified") - { - FnArg::Typed(typed) => typed.ty.clone(), - _ => unreachable!(), - }; - let aux_param_type = match params.get(2) { - Some(data_param_type) => match *data_param_type { - FnArg::Typed(typed) => typed.ty.clone(), - _ => unreachable!(), - }, - None => { - let unit_type = proc_macro::TokenStream::from(quote! {()}); - Box::new(parse_macro_input!(unit_type as Type)) - } - }; - let call_fn = match params.get(2) { - Some(_) => { - quote! { #fn_name(self, cx, aux) } - } - None => quote! { #fn_name(self, cx) }, - }; - - let item = proc_macro2::TokenStream::from(item_cloned); - - let impl_transition = quote! { - impl teloxide::dispatching::dialogue::Subtransition for #state_type { - type Aux = #aux_param_type; - type Dialogue = <#fn_return_type as teloxide::dispatching::dialogue::SubtransitionOutputType>::Output; - type Error = <#fn_return_type as teloxide::dispatching::dialogue::SubtransitionOutputType>::Error; - type Requester = <#requester_param_type as teloxide::dispatching::UpdateWithCxRequesterType>::Requester; - - fn react(self, cx: teloxide::dispatching::dialogue::TransitionIn, aux: #aux_param_type) - -> futures::future::BoxFuture<'static, #fn_return_type> { - #item - futures::future::FutureExt::boxed(#call_fn) - } - } - }; - - impl_transition.into() - } - _ => { - panic!("Unrecognised attribute '{}'", attr); - } - } -} - -/// The docs is below. -/// -/// All the variants must be of the form `VariantName(MyStateType)`, and -/// `MyStateType` must implement `Subtransition`. All `MyStateType`s must have -/// the same `Subtransition::Aux` and `Subtransition::Error`, which will be also -/// used in the generated implementation. -#[proc_macro_derive(Transition)] -pub fn derive_transition(item: TokenStream) -> TokenStream { - let input = parse_macro_input!(item as ItemEnum); - let mut dispatch_fn = "".to_owned(); - - let enum_name = input.ident; - let field_type_of_first_variant = - match &input.variants.iter().next().unwrap().fields { - Fields::Unnamed(fields) => { - fields - .unnamed - .iter() - .next() - // .unwrap() because empty enumerations are not yet allowed - // in stable Rust. - .unwrap() - .ty - .to_token_stream() - .to_string() - } - _ => panic!("Only one unnamed field per variant is allowed"), - }; - - write!( - dispatch_fn, - "impl teloxide::dispatching::dialogue::Transition for {1} {{type Aux \ - = <{0} as teloxide::dispatching::dialogue::Subtransition>::Aux;type \ - Error = <{0} as \ - teloxide::dispatching::dialogue::Subtransition>::Error;type \ - Requester = <{0} as \ - teloxide::dispatching::dialogue::Subtransition>::Requester;fn \ - react(self, cx: \ - teloxide::dispatching::dialogue::TransitionIn, aux: \ - Self::Aux) -> futures::future::BoxFuture<'static, \ - teloxide::dispatching::dialogue::TransitionOut> \ - {{ futures::future::FutureExt::boxed(async move {{ match self {{", - field_type_of_first_variant, enum_name - ) - .unwrap(); - - for variant in input.variants.iter() { - write!( - dispatch_fn, - "{}::{}(state) => \ - teloxide::dispatching::dialogue::Subtransition::react(state, cx, \ - aux).await,", - enum_name, variant.ident - ) - .unwrap(); - } - - write!(dispatch_fn, "}} }}) }} }}").unwrap(); - dispatch_fn.parse().unwrap() -} - macro_rules! get_or_return { ($($some:tt)*) => { match $($some)* { From eac51495942b6c723a565f7ad6b2750e89b8d126 Mon Sep 17 00:00:00 2001 From: Hirrolot Date: Thu, 24 Mar 2022 17:40:30 +0600 Subject: [PATCH 2/2] Update the changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e39758e2..d2e70ea6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## unreleased +### Removed + + - Support for the old dispatching: `#[teloxide(subtransition)]`. + ## 0.5.1 - 2022-03-23 ### Fixed