cargo-up 0.0.3

Upgrade your dependencies by automatically fixing your code
Documentation
use crate::{
    ra_ap_syntax::ast,
    semver::{SemVerError, Version as SemverVersion},
    utils::normalize,
    Semantics, Upgrader,
};
use std::collections::HashMap as Map;

macro_rules! alias {
    ($node:ident) => {
        type $node = dyn Fn(&mut Upgrader, &ast::$node, &Semantics);
    };
}

macro_rules! hook {
    ($method:ident, $node:ident) => {
        pub fn $method<F>(mut self, f: F) -> Self
        where
            F: Fn(&mut Upgrader, &ast::$node, &Semantics) + 'static,
        {
            self.$method.push(Box::new(f));
            self
        }
    };
}

alias!(MethodCallExpr);
alias!(CallExpr);
alias!(IdentPat);
alias!(PathExpr);
alias!(PathPat);
alias!(FieldExpr);
alias!(RecordPat);
alias!(RecordExpr);
alias!(RecordExprField);
alias!(RecordPatField);
alias!(TupleStructPat);

pub struct Version {
    pub(crate) version: SemverVersion,
    pub(crate) peers: Vec<String>,
    pub(crate) rename_methods: Map<String, Map<String, String>>,
    pub(crate) rename_members: Map<String, Map<String, String>>,
    pub(crate) rename_variants: Map<String, Map<String, String>>,
    pub(crate) hook_method_call_expr: Vec<Box<MethodCallExpr>>,
    pub(crate) hook_call_expr: Vec<Box<CallExpr>>,
    pub(crate) hook_ident_pat: Vec<Box<IdentPat>>,
    pub(crate) hook_path_expr: Vec<Box<PathExpr>>,
    pub(crate) hook_path_pat: Vec<Box<PathPat>>,
    pub(crate) hook_field_expr: Vec<Box<FieldExpr>>,
    pub(crate) hook_record_pat: Vec<Box<RecordPat>>,
    pub(crate) hook_record_expr: Vec<Box<RecordExpr>>,
    pub(crate) hook_record_expr_field: Vec<Box<RecordExprField>>,
    pub(crate) hook_record_pat_field: Vec<Box<RecordPatField>>,
    pub(crate) hook_tuple_struct_pat: Vec<Box<TupleStructPat>>,
}

impl Version {
    pub fn new(version: &str) -> Result<Self, SemVerError> {
        Ok(Self {
            version: SemverVersion::parse(version)?,
            peers: vec![],
            rename_methods: Map::new(),
            rename_members: Map::new(),
            rename_variants: Map::new(),
            hook_method_call_expr: vec![],
            hook_call_expr: vec![],
            hook_ident_pat: vec![],
            hook_path_expr: vec![],
            hook_path_pat: vec![],
            hook_field_expr: vec![],
            hook_record_pat: vec![],
            hook_record_expr: vec![],
            hook_record_expr_field: vec![],
            hook_record_pat_field: vec![],
            hook_tuple_struct_pat: vec![],
        })
    }

    pub fn peers(mut self, peers: &[&str]) -> Self {
        self.peers = peers.to_vec().iter().map(|x| normalize(*x)).collect();
        self
    }

    pub fn rename_methods(mut self, name: &str, map: &[[&str; 2]]) -> Self {
        self.rename_methods.insert(
            name.to_string(),
            map.iter()
                .map(|x| (x[0].to_string(), x[1].to_string()))
                .collect(),
        );
        self
    }

    pub fn rename_members(mut self, name: &str, map: &[[&str; 2]]) -> Self {
        self.rename_members.insert(
            name.to_string(),
            map.iter()
                .map(|x| (x[0].to_string(), x[1].to_string()))
                .collect(),
        );
        self
    }

    pub fn rename_variants(mut self, name: &str, map: &[[&str; 2]]) -> Self {
        self.rename_variants.insert(
            name.to_string(),
            map.iter()
                .map(|x| (x[0].to_string(), x[1].to_string()))
                .collect(),
        );
        self
    }

    hook!(hook_method_call_expr, MethodCallExpr);
    hook!(hook_call_expr, CallExpr);
    hook!(hook_ident_pat, IdentPat);
    hook!(hook_path_expr, PathExpr);
    hook!(hook_path_pat, PathPat);
    hook!(hook_field_expr, FieldExpr);
    hook!(hook_record_pat, RecordPat);
    hook!(hook_record_expr, RecordExpr);
    hook!(hook_record_expr_field, RecordExprField);
    hook!(hook_record_pat_field, RecordPatField);
    hook!(hook_tuple_struct_pat, TupleStructPat);
}