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
use fxhash::{FxHashMap, FxHashSet};
use rnode::{Fold, FoldWith};
use stc_ts_types::{Function, Id, MethodSignature, Type, TypeParamDecl};

#[derive(Debug)]
pub struct TypeParamRenamer {
    pub inferred: FxHashMap<Id, Type>,
    /// Declared type parameters. Only type parameters in this set will be
    /// replaced.
    ///
    /// This is filled by visitor itself.
    pub declared: Option<FxHashSet<Id>>,
}

impl Fold<TypeParamDecl> for TypeParamRenamer {
    fn fold(&mut self, decl: TypeParamDecl) -> TypeParamDecl {
        if self.declared.is_none() {
            self.declared = Some(Default::default())
        }

        self.declared.as_mut().unwrap().extend(decl.params.iter().map(|v| v.name.clone()));
        decl.fold_children_with(self)
    }
}

impl Fold<MethodSignature> for TypeParamRenamer {
    fn fold(&mut self, m: MethodSignature) -> MethodSignature {
        let key = m.key.fold_with(self);
        let type_params = m.type_params.fold_with(self);
        let params = m.params.fold_with(self);
        let ret_ty = m.ret_ty.fold_with(self);

        MethodSignature {
            accessibility: m.accessibility,
            span: m.span,
            readonly: m.readonly,
            key,
            optional: m.optional,
            params,
            ret_ty,
            type_params,
            metadata: m.metadata,
        }
    }
}

impl Fold<Function> for TypeParamRenamer {
    fn fold(&mut self, f: Function) -> Function {
        let type_params = f.type_params.fold_with(self);
        let params = f.params.fold_with(self);
        let ret_ty = f.ret_ty.fold_with(self);

        Function {
            type_params,
            params,
            ret_ty,
            ..f
        }
    }
}

impl Fold<Type> for TypeParamRenamer {
    fn fold(&mut self, mut ty: Type) -> Type {
        ty.normalize_mut();
        ty = ty.fold_children_with(self);

        if let Type::Param(ref param) = ty.normalize() {
            if let Some(declared) = &self.declared {
                if !declared.contains(&param.name) {
                    return ty;
                }
            }

            if let Some(mapped) = self.inferred.get(&param.name) {
                if self.declared.is_none() && mapped.is_type_param() {
                    return ty;
                }
                return mapped.clone();
            }
        }

        ty
    }
}