Skip to main content

makepad_gen_plugin/visitor/fn/
special_event.rs

1use gen_utils::error::{CompilerError, Error};
2use quote::ToTokens;
3use syn::{parse_quote, FnArg, ImplItemFn, Signature, Type};
4
5pub struct SpecialEventVisitor;
6
7impl SpecialEventVisitor {
8    pub fn visit<S>(item_fn: &mut ImplItemFn, special: S) -> Result<SpecialEvent, Error>
9    where
10        S: Into<SpecialEvent>,
11    {
12        let special: SpecialEvent = special.into();
13        match special {
14            SpecialEvent::HttpResponse => Self::http_response(item_fn),
15        }?;
16
17        Ok(special)
18    }
19    /// 访问http的响应
20    /// ```rust
21    /// #[http_response]
22    /// fn http_response1(response: &HttpResponse) -> (){
23    ///     // ...
24    /// }
25    ///
26    /// // http_response2 ...
27    /// ```
28    /// ```rust
29    /// fn  http_response1(response: &HttpResponse) -> (){//...}
30    ///
31    /// match request_id {
32    ///     live_id!(http_response1) => http_response1(response),
33    ///     // http_response2 ...
34    ///     _ => {}
35    /// }
36    /// ```
37    fn http_response(item_fn: &mut ImplItemFn) -> Result<(), Error> {
38        // 检查方法的参数是否有2个参数且第二个类型为 &HttpResponse
39        if !is_response_param(&item_fn.sig) {
40            return Err(CompilerError::runtime(
41                "Makepad Plugin - Script",
42                "http_response method must have only one parameter and the type is &HttpResponse",
43            )
44            .into());
45        }
46        // 移除宏
47        item_fn.attrs.clear();
48        // 给方法添加cx参数
49        item_fn.sig.inputs.insert(1, parse_quote! {cx: &mut Cx});
50
51        Ok(())
52    }
53}
54
55fn is_response_param(sig: &Signature) -> bool {
56    if sig.inputs.len() != 2 {
57        return false;
58    }
59
60    if let FnArg::Typed(arg_ty) = &sig.inputs[1] {
61        if let Type::Reference(ty_ref) = &*arg_ty.ty {
62            return ty_ref.mutability.is_none()
63                && ty_ref.elem.to_token_stream().to_string() == "HttpResponse";
64        }
65    }
66    false
67}
68
69pub enum SpecialEvent {
70    HttpResponse,
71}
72
73impl From<&str> for SpecialEvent {
74    fn from(value: &str) -> Self {
75        match value {
76            "http_response" => SpecialEvent::HttpResponse,
77            _ => unreachable!(),
78        }
79    }
80}
81
82impl From<String> for SpecialEvent {
83    fn from(value: String) -> Self {
84        value.as_str().into()
85    }
86}