Skip to content

Commit c480604

Browse files
authored
feat(ts/isolated-dts): Distinguish js value and ts type (#10316)
**Description:** 1. I mixed up the types and values with the same identifier in the usage graph before. Now, I define a flag to distinguish them. 2. Also add many docs to `TypeUsageAnalyzer` **Related issue:** - Closes #10276
1 parent bdde843 commit c480604

File tree

8 files changed

+234
-80
lines changed

8 files changed

+234
-80
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/swc_typescript/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ repository = { workspace = true }
99
version = "11.0.0"
1010

1111
[dependencies]
12+
bitflags = {workspace = true }
1213
petgraph = { workspace = true }
1314
rustc-hash = { workspace = true }
1415
thiserror = { workspace = true }

crates/swc_typescript/src/fast_dts/decl.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ impl FastDts {
2020
return;
2121
}
2222

23-
if check_binding && !self.used_refs.contains(&class_decl.ident.to_id()) {
23+
if check_binding && !self.used_refs.used(&class_decl.ident.to_id()) {
2424
return;
2525
}
2626

@@ -32,7 +32,7 @@ impl FastDts {
3232
return;
3333
}
3434

35-
if check_binding && !self.used_refs.contains(&fn_decl.ident.to_id()) {
35+
if check_binding && !self.used_refs.used_as_value(&fn_decl.ident.to_id()) {
3636
return;
3737
}
3838

@@ -50,7 +50,7 @@ impl FastDts {
5050
&& decl
5151
.name
5252
.as_ident()
53-
.map_or(false, |ident| !self.used_refs.contains(&ident.to_id()))
53+
.map_or(false, |ident| !self.used_refs.used_as_value(&ident.to_id()))
5454
{
5555
return;
5656
}
@@ -63,7 +63,7 @@ impl FastDts {
6363
&& decl
6464
.name
6565
.as_ident()
66-
.map_or(false, |ident| !self.used_refs.contains(&ident.to_id()))
66+
.map_or(false, |ident| !self.used_refs.used_as_value(&ident.to_id()))
6767
{
6868
return;
6969
}
@@ -72,7 +72,7 @@ impl FastDts {
7272
}
7373
Decl::TsEnum(ts_enum) => {
7474
ts_enum.declare = is_declare;
75-
if check_binding && !self.used_refs.contains(&ts_enum.id.to_id()) {
75+
if check_binding && !self.used_refs.used(&ts_enum.id.to_id()) {
7676
return;
7777
}
7878
self.transform_enum(ts_enum.as_mut());
@@ -88,7 +88,7 @@ impl FastDts {
8888
&& ts_module
8989
.id
9090
.as_ident()
91-
.map_or(false, |ident| !self.used_refs.contains(&ident.to_id()))
91+
.map_or(false, |ident| !self.used_refs.used_as_type(&ident.to_id()))
9292
{
9393
return;
9494
}
@@ -139,7 +139,7 @@ impl FastDts {
139139

140140
if matches!(pat, Pat::Array(_) | Pat::Object(_)) {
141141
pat.bound_names(&mut |ident| {
142-
if !check_binding || self.used_refs.contains(&ident.to_id()) {
142+
if !check_binding || self.used_refs.used_as_value(&ident.to_id()) {
143143
self.binding_element_export(ident.span);
144144
}
145145
});

crates/swc_typescript/src/fast_dts/mod.rs

+18-21
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ use swc_common::{
77
DUMMY_SP,
88
};
99
use swc_ecma_ast::{
10-
BindingIdent, Decl, DefaultDecl, ExportDefaultExpr, Id, Ident, ImportSpecifier, ModuleDecl,
10+
BindingIdent, Decl, DefaultDecl, ExportDefaultExpr, Ident, ImportSpecifier, ModuleDecl,
1111
ModuleItem, NamedExport, Pat, Program, Script, Stmt, TsExportAssignment, VarDecl, VarDeclKind,
1212
VarDeclarator,
1313
};
1414
use type_usage::TypeUsageAnalyzer;
1515
use util::{
1616
ast_ext::MemberPropExt, expando_function_collector::ExpandoFunctionCollector, types::type_ann,
1717
};
18-
use visitors::type_usage;
18+
use visitors::type_usage::{self, SymbolFlags, UsedRefs};
1919

2020
use crate::diagnostic::{DtsIssue, SourceRange};
2121

@@ -44,7 +44,7 @@ pub struct FastDts {
4444
// states
4545
id_counter: u32,
4646
is_top_level: bool,
47-
used_refs: FxHashSet<Id>,
47+
used_refs: UsedRefs,
4848
internal_annotations: Option<FxHashSet<BytePos>>,
4949
}
5050

@@ -63,7 +63,7 @@ impl FastDts {
6363
diagnostics: Vec::new(),
6464
id_counter: 0,
6565
is_top_level: true,
66-
used_refs: FxHashSet::default(),
66+
used_refs: UsedRefs::default(),
6767
internal_annotations,
6868
}
6969
}
@@ -241,7 +241,8 @@ impl FastDts {
241241

242242
let name_ident = Ident::new_no_ctxt(self.gen_unique_name("_default"), DUMMY_SP);
243243
let type_ann = self.infer_type_from_expr(expr).map(type_ann);
244-
self.used_refs.insert(name_ident.to_id());
244+
self.used_refs
245+
.add_usage(name_ident.to_id(), SymbolFlags::Value);
245246

246247
if type_ann.is_none() {
247248
self.default_export_inferred(expr.span());
@@ -460,12 +461,12 @@ impl FastDts {
460461
let used_refs = &self.used_refs;
461462
items.retain_mut(|node| match node {
462463
ModuleItem::Stmt(Stmt::Decl(decl)) if !in_global_or_lit_module => match decl {
463-
Decl::Class(class_decl) => used_refs.contains(&class_decl.ident.to_id()),
464-
Decl::Fn(fn_decl) => used_refs.contains(&fn_decl.ident.to_id()),
464+
Decl::Class(class_decl) => used_refs.used(&class_decl.ident.to_id()),
465+
Decl::Fn(fn_decl) => used_refs.used_as_value(&fn_decl.ident.to_id()),
465466
Decl::Var(var_decl) => {
466467
var_decl.decls.retain(|decl| {
467468
if let Some(ident) = decl.name.as_ident() {
468-
used_refs.contains(&ident.to_id())
469+
used_refs.used_as_value(&ident.to_id())
469470
} else {
470471
false
471472
}
@@ -475,27 +476,27 @@ impl FastDts {
475476
Decl::Using(using_decl) => {
476477
using_decl.decls.retain(|decl| {
477478
if let Some(ident) = decl.name.as_ident() {
478-
used_refs.contains(&ident.to_id())
479+
used_refs.used_as_value(&ident.to_id())
479480
} else {
480481
false
481482
}
482483
});
483484
!using_decl.decls.is_empty()
484485
}
485486
Decl::TsInterface(ts_interface_decl) => {
486-
used_refs.contains(&ts_interface_decl.id.to_id())
487+
used_refs.used_as_type(&ts_interface_decl.id.to_id())
487488
}
488489
Decl::TsTypeAlias(ts_type_alias_decl) => {
489-
used_refs.contains(&ts_type_alias_decl.id.to_id())
490+
used_refs.used_as_type(&ts_type_alias_decl.id.to_id())
490491
}
491-
Decl::TsEnum(ts_enum) => used_refs.contains(&ts_enum.id.to_id()),
492+
Decl::TsEnum(ts_enum) => used_refs.used(&ts_enum.id.to_id()),
492493
Decl::TsModule(ts_module_decl) => {
493494
ts_module_decl.global
494495
|| ts_module_decl.id.is_str()
495496
|| ts_module_decl
496497
.id
497498
.as_ident()
498-
.map_or(true, |ident| used_refs.contains(&ident.to_id()))
499+
.map_or(true, |ident| used_refs.used_as_type(&ident.to_id()))
499500
}
500501
},
501502
ModuleItem::ModuleDecl(ModuleDecl::Import(import_decl)) => {
@@ -504,21 +505,17 @@ impl FastDts {
504505
}
505506

506507
import_decl.specifiers.retain(|specifier| match specifier {
507-
ImportSpecifier::Named(specifier) => {
508-
used_refs.contains(&specifier.local.to_id())
509-
}
510-
ImportSpecifier::Default(specifier) => {
511-
used_refs.contains(&specifier.local.to_id())
512-
}
508+
ImportSpecifier::Named(specifier) => used_refs.used(&specifier.local.to_id()),
509+
ImportSpecifier::Default(specifier) => used_refs.used(&specifier.local.to_id()),
513510
ImportSpecifier::Namespace(specifier) => {
514-
used_refs.contains(&specifier.local.to_id())
511+
used_refs.used(&specifier.local.to_id())
515512
}
516513
});
517514

518515
!import_decl.specifiers.is_empty()
519516
}
520517
ModuleItem::ModuleDecl(ModuleDecl::TsImportEquals(ts_import_equals)) => {
521-
used_refs.contains(&ts_import_equals.id.to_id())
518+
used_refs.used(&ts_import_equals.id.to_id())
522519
}
523520
_ => true,
524521
});

crates/swc_typescript/src/fast_dts/util/expando_function_collector.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
use rustc_hash::FxHashSet;
22
use swc_atoms::Atom;
3-
use swc_ecma_ast::{FnDecl, FnExpr, Id, VarDecl};
3+
use swc_ecma_ast::{FnDecl, FnExpr, VarDecl};
44

55
use super::ast_ext::PatExt;
6+
use crate::fast_dts::visitors::type_usage::UsedRefs;
67

78
pub(crate) struct ExpandoFunctionCollector<'a> {
89
declared_function_names: FxHashSet<Atom>,
9-
used_refs: &'a FxHashSet<Id>,
10+
used_refs: &'a UsedRefs,
1011
}
1112

1213
impl<'a> ExpandoFunctionCollector<'a> {
13-
pub(crate) fn new(used_refs: &'a FxHashSet<Id>) -> Self {
14+
pub(crate) fn new(used_refs: &'a UsedRefs) -> Self {
1415
Self {
1516
declared_function_names: FxHashSet::default(),
1617
used_refs,
@@ -24,7 +25,7 @@ impl<'a> ExpandoFunctionCollector<'a> {
2425
}
2526

2627
pub(crate) fn add_fn_decl(&mut self, fn_decl: &FnDecl, check_binding: bool) {
27-
if !check_binding || self.used_refs.contains(&fn_decl.ident.to_id()) {
28+
if !check_binding || self.used_refs.used_as_value(&fn_decl.ident.to_id()) {
2829
self.declared_function_names
2930
.insert(fn_decl.ident.sym.clone());
3031
}
@@ -39,7 +40,7 @@ impl<'a> ExpandoFunctionCollector<'a> {
3940
.is_some_and(|type_ann| type_ann.type_ann.is_ts_fn_or_constructor_type())
4041
{
4142
if let Some(name) = decl.name.as_ident() {
42-
if !check_binding || self.used_refs.contains(&name.to_id()) {
43+
if !check_binding || self.used_refs.used_as_value(&name.to_id()) {
4344
self.declared_function_names.insert(name.sym.clone());
4445
}
4546
}

0 commit comments

Comments
 (0)