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
use fxhash::FxHashSet;
use rnode::{Fold, FoldWith};
use stc_ts_types::{CallSignature, ConstructorSignature, Function, Id, MethodSignature, Type, TypeParam, TypeParamDecl};
use swc_common::util::move_map::MoveMap;
#[derive(Debug)]
pub struct TypeParamRemover<'a> {
scope: Scope<'a>,
}
impl TypeParamRemover<'static> {
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
Self { scope: Default::default() }
}
}
macro_rules! noop {
($T:ident) => {
impl Fold<$T> for TypeParamRemover<'_> {
#[inline]
fn fold(&mut self, node: $T) -> $T {
node
}
}
};
}
noop!(CallSignature);
noop!(ConstructorSignature);
noop!(MethodSignature);
impl Fold<Option<TypeParamDecl>> for TypeParamRemover<'_> {
fn fold(&mut self, node: Option<TypeParamDecl>) -> Option<TypeParamDecl> {
let mut node = node?;
node.params = node.params.move_flat_map(|param| {
if self.scope.has(¶m.name) {
return None;
}
Some(param)
});
node = node.fold_children_with(self);
if node.params.is_empty() {
return None;
}
Some(node)
}
}
impl Fold<TypeParam> for TypeParamRemover<'_> {
fn fold(&mut self, node: TypeParam) -> TypeParam {
self.scope.params.insert(node.name.clone());
node
}
}
impl Fold<Function> for TypeParamRemover<'_> {
fn fold(&mut self, node: Function) -> Function {
let mut v = TypeParamRemover {
scope: Scope {
parent: Some(&self.scope),
params: Default::default(),
},
};
node.fold_children_with(&mut v)
}
}
impl Fold<Type> for TypeParamRemover<'_> {
fn fold(&mut self, mut ty: Type) -> Type {
ty.normalize_mut();
ty.fold_children_with(self)
}
}
#[derive(Debug, Default)]
struct Scope<'a> {
parent: Option<&'a Scope<'a>>,
params: FxHashSet<Id>,
}
impl Scope<'_> {
fn has(&self, name: &Id) -> bool {
if self.params.contains(name) {
return true;
}
self.parent.map(|parent| parent.has(name)).unwrap_or(false)
}
}