1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
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); }