fix(es/transforms/typescript): Fix strip (#2496)

swc_ecma_transforms_typescript:
 - Visit the RHS of import equals declaration properly.
This commit is contained in:
Nayeem Rahman 2021-10-21 07:12:51 +01:00 committed by GitHub
parent 7af0f8c81b
commit c29a6e11c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 98 additions and 76 deletions

2
Cargo.lock generated
View File

@ -2981,7 +2981,7 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_typescript"
version = "0.54.0"
version = "0.54.1"
dependencies = [
"serde",
"swc_atoms 0.2.9",

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms_typescript"
repository = "https://github.com/swc-project/swc.git"
version = "0.54.0"
version = "0.54.1"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@ -280,6 +280,10 @@ struct DeclInfo {
has_type: bool,
/// Var, Fn, Class
has_concrete: bool,
/// In `import foo = bar.baz`, `foo`'s dependency is `bar`. This means that
/// when setting `has_concrete` for `foo`, it must also be set for
/// `bar`.
maybe_dependency: Option<Ident>,
}
impl<C> Strip<C>
@ -1370,10 +1374,22 @@ where
}
fn visit_ident(&mut self, n: &Ident, _: &dyn Node) {
let is_type_only_export = self.is_type_only_export;
let entry = self.scope.referenced_idents.entry(n.to_id()).or_default();
entry.has_concrete |= !is_type_only_export;
if self.is_type_only_export {
entry.has_type = true;
} else {
entry.has_concrete = true;
}
if let Some(i) = &entry.maybe_dependency {
let id = i.to_id();
if let Some(entry) = self.scope.referenced_idents.get_mut(&id) {
if self.is_type_only_export {
entry.has_type = true;
} else {
entry.has_concrete = true;
}
}
}
n.visit_children_with(self);
}
@ -1439,14 +1455,41 @@ where
fn visit_ts_entity_name(&mut self, name: &TsEntityName, _: &dyn Node) {
match *name {
TsEntityName::Ident(ref i) => {
let entry = self.scope.referenced_idents.entry(i.to_id()).or_default();
entry.has_type = true;
if let Some(i) = &entry.maybe_dependency {
let id = i.to_id();
if let Some(entry) = self.scope.referenced_idents.get_mut(&id) {
entry.has_type = true;
}
}
}
TsEntityName::TsQualifiedName(ref q) => q.left.visit_with(&*q, self),
}
}
fn visit_ts_import_equals_decl(&mut self, n: &TsImportEqualsDecl, _: &dyn Node) {
match &n.module_ref {
TsModuleRef::TsEntityName(name) => {
let entry = self
.scope
.referenced_idents
.entry((i.sym.clone(), i.span.ctxt()))
.entry(n.id.to_id())
.or_default();
entry.has_type = true;
let mut name = name;
loop {
match name {
TsEntityName::Ident(ref i) => {
entry.maybe_dependency = Some(i.clone());
break;
}
TsEntityName::TsQualifiedName(ref q) => name = &q.left,
}
}
}
_ => {
n.visit_children_with(self);
}
TsEntityName::TsQualifiedName(ref q) => q.left.visit_with(&*q, self),
}
}
}
@ -2080,7 +2123,16 @@ where
}
ModuleItem::ModuleDecl(ModuleDecl::TsImportEquals(import)) => {
if !import.is_type_only {
let maybe_entry = self.scope.referenced_idents.get(&import.id.to_id());
let has_concrete = if let Some(entry) = maybe_entry {
entry.has_concrete
} else {
true
};
// TODO(nayeemrmn): For some reason TSC preserves `import foo = bar.baz`
// when `bar.baz` is not defined, even if `foo` goes unused. We can't currently
// identify that case so we strip it anyway.
if !import.is_type_only && (has_concrete || import.is_export) {
let var = Decl::Var(VarDecl {
span: DUMMY_SP,
kind: VarDeclKind::Var,

View File

@ -462,8 +462,6 @@ to!(module_01, "module 'foo'{ }", "");
to!(declare_01, "declare var env: FOO", "");
to!(import_equals, "import A = B.C", "var A = B.C;");
to!(
issue_757,
"// test.ts
@ -4076,7 +4074,7 @@ to!(
export { TestInfo }
",
"
"
);
@ -4116,6 +4114,32 @@ Foo.identifier = 5;
"
);
to!(
deno_12395_import_equals_1,
"
import * as mongo from 'https://deno.land/x/mongo@v0.27.0/mod.ts';
import MongoClient = mongo.MongoClient;
const mongoClient = new MongoClient();
",
"
import * as mongo from 'https://deno.land/x/mongo@v0.27.0/mod.ts';
var MongoClient = mongo.MongoClient;
const mongoClient = new MongoClient();
"
);
to!(
deno_12395_import_equals_2,
"
import * as mongo from 'https://deno.land/x/mongo@v0.27.0/mod.ts';
import MongoClient = mongo.MongoClient;
const mongoClient: MongoClient = {};
",
"
const mongoClient = {};
"
);
#[testing::fixture("tests/fixture/**/input.ts")]
#[testing::fixture("tests/fixture/**/input.tsx")]
fn exec(input: PathBuf) {

View File

@ -16,7 +16,6 @@ export { E11 as E1 };
}));
// @Filename: foo_1.ts
const foo = require("./foo_0");
var f = foo.M1;
var i;
var x = {
};

View File

@ -5,6 +5,4 @@ export class C1 {
}
}
C1.s1 = !0, (E1 = E11 || (E11 = {
}))[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1.C = 2] = "C";
const foo = require("./foo_0");
foo.M1;
}))[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1.C = 2] = "C", require("./foo_0");

View File

@ -21,7 +21,6 @@ export { E11 as E1 };
}));
// @Filename: foo_1.ts
var foo = require("./foo_0");
var f = foo.M1;
var i;
var x = {
};

View File

@ -1,4 +1,4 @@
var E1, foo, E11, i, z, C1 = function() {
var E1, E11, i, z, C1 = function() {
"use strict";
!function(instance, Constructor) {
if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
@ -6,4 +6,4 @@ var E1, foo, E11, i, z, C1 = function() {
};
export { E11 as E1 };
C1.s1 = !0, (E1 = E11 || (E11 = {
}))[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1.C = 2] = "C", require("./foo_0").M1;
}))[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1.C = 2] = "C", require("./foo_0");

View File

@ -16,7 +16,6 @@ export { E11 as E1 };
}));
// @Filename: foo_1.ts
const foo = require("./foo_0");
var f = foo.M1;
var i;
var x = {
};

View File

@ -5,6 +5,4 @@ export class C1 {
}
}
C1.s1 = !0, (E1 = E11 || (E11 = {
}))[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1.C = 2] = "C";
const foo = require("./foo_0");
foo.M1;
}))[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1.C = 2] = "C", require("./foo_0");

View File

@ -21,7 +21,6 @@ export { E11 as E1 };
}));
// @Filename: foo_1.ts
var foo = require("./foo_0");
var f = foo.M1;
var i;
var x = {
};

View File

@ -1,4 +1,4 @@
var E1, foo, E11, i, z, C1 = function() {
var E1, E11, i, z, C1 = function() {
"use strict";
!function(instance, Constructor) {
if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
@ -6,4 +6,4 @@ var E1, foo, E11, i, z, C1 = function() {
};
export { E11 as E1 };
C1.s1 = !0, (E1 = E11 || (E11 = {
}))[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1.C = 2] = "C", require("./foo_0").M1;
}))[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1.C = 2] = "C", require("./foo_0");

View File

@ -1,14 +1,6 @@
// no code gen expected
var B;
(function(B) {
var a = A;
})(B || (B = {
}));
// no code gen expected
var C;
(function(C) {
var a = A;
var b = a.inA;
var m;
var p;
var p = {
@ -21,14 +13,12 @@ var C;
// no code gen expected
var D;
(function(D) {
var a = A;
var p;
})(D || (D = {
}));
// no code gen expected
var E1;
(function(E) {
var a = A.inA;
function xDist(x) {
return 0 - x.x;
}

View File

@ -1,14 +1,6 @@
// no code gen expected
var B;
(function(B) {
var a = A;
})(B || (B = {
}));
// no code gen expected
var C;
(function(C) {
var a = A;
var b = a.inA;
var m;
var p;
var p = {
@ -21,7 +13,6 @@ var C;
// no code gen expected
var D;
(function(D) {
var a = A;
var p;
})(D || (D = {
}));
@ -31,7 +22,6 @@ var E1;
var xDist = function xDist(x) {
return 0 - x.x;
};
var a = A.inA;
E.xDist = xDist;
})(E1 || (E1 = {
}));

View File

@ -9,7 +9,6 @@ var moduleA1;
moduleA.Point = Point;
})(moduleA1 || (moduleA1 = {
}));
var alias = moduleA1;
var p;
var p;
var p;
@ -22,7 +21,6 @@ class clodule {
};
})(clodule || (clodule = {
}));
var clolias = clodule;
var p;
var p;
var p;
@ -39,7 +37,6 @@ function fundule() {
};
})(fundule || (fundule = {
}));
var funlias = fundule;
var p;
var p;
var p;

View File

@ -14,7 +14,6 @@ var moduleA1;
moduleA.Point = Point;
})(moduleA1 || (moduleA1 = {
}));
var alias = moduleA1;
var p;
var p;
var p;
@ -29,7 +28,6 @@ var clodule = function clodule() {
};
})(clodule || (clodule = {
}));
var clolias = clodule;
var p;
var p;
var p;
@ -46,7 +44,6 @@ function fundule() {
};
})(fundule || (fundule = {
}));
var funlias = fundule;
var p;
var p;
var p;

View File

@ -1,15 +1,11 @@
// none of these should work, since non are actually modules
var V = 12;
var v = V;
class C {
}
var c = C;
var E1;
(function(E) {
E[E["Red"] = 0] = "Red";
E[E["Blue"] = 1] = "Blue";
})(E1 || (E1 = {
}));
var e = E1;
var i = I;
export { };

View File

@ -5,18 +5,14 @@ function _classCallCheck(instance, Constructor) {
}
// none of these should work, since non are actually modules
var V = 12;
var v = V;
var C = function C() {
"use strict";
_classCallCheck(this, C);
};
var c = C;
var E1;
(function(E) {
E[E["Red"] = 0] = "Red";
E[E["Blue"] = 1] = "Blue";
})(E1 || (E1 = {
}));
var e = E1;
var i = I;
export { };

View File

@ -13,7 +13,6 @@ var B;
x: 0,
y: 0
};
var Point = A;
})(B || (B = {
}));
var X1;
@ -25,7 +24,6 @@ var X1;
}));
var Z;
(function(Z) {
var Y = X1.Y;
var Y = 12;
})(Z || (Z = {
}));

View File

@ -1,9 +1,8 @@
var A, X, Z;
var A, X;
(A || (A = {
})).Point = {
x: 0,
y: 0
}, (X || (X = {
})).Y = class {
}, Z || (Z = {
}), X.Y;
};

View File

@ -18,7 +18,6 @@ var B;
x: 0,
y: 0
};
var Point = A;
})(B || (B = {
}));
var X1;
@ -32,7 +31,6 @@ var X1;
}));
var Z;
(function(Z) {
var Y = X1.Y;
var Y = 12;
})(Z || (Z = {
}));

View File

@ -1,4 +1,4 @@
var A, X1, Z;
var A, X1;
(A || (A = {
})).Point = {
x: 0,
@ -12,5 +12,4 @@ var A, X1, Z;
};
X.Y = Y;
})(X1 || (X1 = {
})), Z || (Z = {
}), X1.Y;
}));

View File

@ -1,2 +1 @@
var TypeScript = TypeScriptServices.TypeScript;
export { };

View File

@ -1,2 +1 @@
var TypeScript = TypeScriptServices.TypeScript;
export { };

View File

@ -1,2 +1 @@
var TypeScript = TypeScriptServices.TypeScript;
export { };

View File

@ -1,2 +1 @@
var TypeScript = TypeScriptServices.TypeScript;
export { };

View File

@ -25,7 +25,6 @@ var M1;
}));
export var r6;
export var r7;
var Z = M1;
export var r8;
export var r9;
var E1;

View File

@ -34,7 +34,6 @@ var M1;
}));
export var r6;
export var r7;
var Z = M1;
export var r8;
export var r9;
var E1;