Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
multiversion-macros 0.6.1 - Docs.rs
[go: Go Back, main page]

multiversion-macros 0.6.1

Implementation crate for multiversion
Documentation
use crate::dispatcher::feature_fn_name;
use crate::target::Target;
use syn::{
    spanned::Spanned,
    visit_mut::{self, VisitMut},
    Error, Expr, ItemFn, Result,
};

struct StaticDispatchVisitor<'a> {
    target: Option<&'a Target>,
    status: Result<()>,
}

impl<'a> StaticDispatchVisitor<'a> {
    pub fn new(target: Option<&'a Target>) -> Self {
        Self {
            target,
            status: Ok(()),
        }
    }

    pub fn status(self) -> Result<()> {
        self.status
    }
}

fn dispatch_impl(expr: &mut Expr, target: Option<&Target>) -> Result<()> {
    if let Expr::Macro(macro_expr) = expr {
        if let Some(path_ident) = macro_expr.mac.path.get_ident() {
            if path_ident.to_string().as_str() == "dispatch" {
                let mut call = macro_expr.mac.parse_body::<Expr>()?;
                let ident = match &mut call {
                    Expr::Call(ref mut call) => {
                        if let Expr::Path(ref mut function) = *call.func {
                            Ok(&mut function.path.segments.last_mut().unwrap().ident)
                        } else {
                            Err(Error::new(
                                call.func.span(),
                                "dispatching a function requires a direct function call",
                            ))
                        }
                    }
                    Expr::MethodCall(call) => Ok(&mut call.method),
                    Expr::Path(ref mut path) => {
                        Ok(&mut path.path.segments.last_mut().unwrap().ident)
                    }
                    _ => Err(Error::new(
                        call.span(),
                        "expected a function or method call",
                    )),
                }?;
                *ident = feature_fn_name(ident, target).1;
                *expr = call;
            }
        }
    }
    Ok(())
}

impl VisitMut for StaticDispatchVisitor<'_> {
    fn visit_expr_mut(&mut self, i: &mut Expr) {
        if self.status.as_ref().ok().is_some() {
            if let Err(error) = dispatch_impl(i, self.target) {
                self.status = Err(error);
            }
            visit_mut::visit_expr_mut(self, i);
        }
    }
}

pub(crate) fn process_static_dispatch(item: &mut ItemFn, target: Option<&Target>) -> Result<()> {
    let mut visitor = StaticDispatchVisitor::new(target);
    visitor.visit_item_fn_mut(item);
    visitor.status()
}