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
use fxhash::FxBuildHasher;
use indexmap::IndexSet;
use itertools::Itertools;
use rnode::{Visit, VisitWith};
use stc_ts_types::{Id, Type, TypeParam, TypeParamDecl};
use swc_common::DUMMY_SP;
use crate::analyzer::Analyzer;
impl Analyzer<'_, '_> {
pub(crate) fn add_required_type_params(&self, ty: &mut Type) {
if let Some(instance) = ty.as_instance_mut() {
self.add_required_type_params(&mut instance.ty);
return;
}
let mut finder = TypeParamUsageFinder::default();
ty.visit_with(&mut finder);
if finder.used.is_empty() {
if let Some(f) = ty.as_fn_type_mut() {
f.type_params = None;
}
return;
}
let params = finder
.used
.into_iter()
.map(|name| TypeParam {
span: DUMMY_SP,
name,
constraint: None,
default: None,
metadata: Default::default(),
tracker: Default::default(),
})
.collect_vec();
if let Some(f) = ty.as_fn_type_mut() {
match &mut f.type_params {
Some(v) => {
v.params = params;
}
None => {
f.type_params = Some(TypeParamDecl {
span: DUMMY_SP,
params,
tracker: Default::default(),
})
}
}
}
}
}
#[derive(Default)]
struct TypeParamUsageFinder {
used: IndexSet<Id, FxBuildHasher>,
}
impl Visit<TypeParam> for TypeParamUsageFinder {
fn visit(&mut self, ty: &TypeParam) {
ty.default.visit_with(self);
}
}
impl Visit<Type> for TypeParamUsageFinder {
fn visit(&mut self, ty: &Type) {
ty.visit_children_with(self);
if let Type::Param(p) = ty.normalize() {
self.used.insert(p.name.clone());
}
}
}