Skip to content

Commit

Permalink
feat(es/typescript): Follow TypeScript error report (#5114)
Browse files Browse the repository at this point in the history
  • Loading branch information
magic-akari committed Jul 5, 2022
1 parent fa66ee8 commit f952a61
Show file tree
Hide file tree
Showing 17 changed files with 192 additions and 22 deletions.
1 change: 1 addition & 0 deletions crates/swc/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ impl Options {
);

let import_export_assign_config = match cfg.module {
Some(ModuleConfig::Es6) => TsImportExportAssignConfig::EsNext,
Some(ModuleConfig::CommonJs(..))
| Some(ModuleConfig::Amd(..))
| Some(ModuleConfig::Umd(..)) => TsImportExportAssignConfig::Preserve,
Expand Down
11 changes: 11 additions & 0 deletions crates/swc/tests/errors/lints/duplicate-exports/4/.swcrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "http://json.schemastore.org/swcrc",
"jsc": {
"parser": {
"syntax": "typescript"
}
},
"module": {
"type": "commonjs"
}
}
3 changes: 3 additions & 0 deletions crates/swc/tests/errors/lints/duplicate-exports/4/input.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default 1;

export = {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

x An export assignment cannot be used in a module with other exported elements.
,----
3 | export = {};
: ^^^^^^^^^^^^
`----
11 changes: 11 additions & 0 deletions crates/swc/tests/errors/lints/duplicate-exports/5/.swcrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "http://json.schemastore.org/swcrc",
"jsc": {
"parser": {
"syntax": "typescript"
}
},
"module": {
"type": "commonjs"
}
}
3 changes: 3 additions & 0 deletions crates/swc/tests/errors/lints/duplicate-exports/5/input.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export = 1;
export = 2;
export = 3;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

x multiple `export =` found
,-[1:1]
1 | export = 1;
: ^^^^^|^^^^^
: `-- previous `export =` declared here
2 | export = 2;
: ^^^^^^^^^^^
`----

x multiple `export =` found
,-[2:1]
2 | export = 2;
: ^^^^^|^^^^^
: `-- previous `export =` declared here
3 | export = 3;
: ^^^^^^^^^^^
`----
12 changes: 12 additions & 0 deletions crates/swc/tests/errors/module/esnext/export-assign/.swcrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"$schema": "http://json.schemastore.org/swcrc",
"jsc": {
"parser": {
"syntax": "typescript"
},
"target": "es2020"
},
"module": {
"type": "es6"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export = 42;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

x Export assignment cannot be used when targeting ECMAScript modules. Consider using `export default` or another module format instead.
,----
1 | export = 42;
: ^^^^^^^^^^^^
`----
12 changes: 12 additions & 0 deletions crates/swc/tests/errors/module/esnext/import-assign/.swcrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"$schema": "http://json.schemastore.org/swcrc",
"jsc": {
"parser": {
"syntax": "typescript"
},
"target": "es2020"
},
"module": {
"type": "es6"
}
}
3 changes: 3 additions & 0 deletions crates/swc/tests/errors/module/esnext/import-assign/input.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import homura = require("homura");

export import madoka = require("madoka");
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

x Import assignment cannot be used when targeting ECMAScript modules. Consider using `import * as ns from "mod"`, `import {a} from "mod"`, `import d from "mod"`, or another module format instead.
,----
1 | import homura = require("homura");
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
`----

x Import assignment cannot be used when targeting ECMAScript modules. Consider using `import * as ns from "mod"`, `import {a} from "mod"`, `import d from "mod"`, or another module format instead.
,----
3 | export import madoka = require("madoka");
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
`----
36 changes: 36 additions & 0 deletions crates/swc_ecma_lints/src/rules/duplicate_exports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub fn duplicate_exports() -> Box<dyn Rule> {
#[derive(Debug, Default)]
struct DuplicateExports {
exports: AHashMap<JsWord, Span>,
export_assign: Option<Span>,
}

impl DuplicateExports {
Expand Down Expand Up @@ -42,6 +43,37 @@ impl DuplicateExports {
e.insert(id.span);
}
}

self.check_no_coexist();
}

fn add_export_assign(&mut self, span: Span) {
if let Some(prev_span) = self.export_assign {
// TS2300
HANDLER.with(|handler| {
handler
.struct_span_err(span, "multiple `export =` found")
.span_label(prev_span, "previous `export =` declared here")
.emit()
});
}

self.export_assign = Some(span);

self.check_no_coexist();
}

fn check_no_coexist(&self) {
if let Some(span) = self.export_assign {
if !self.exports.is_empty() {
// TS2309
HANDLER.with(|handler| {
handler
.struct_span_err(span, r#"An export assignment cannot be used in a module with other exported elements."#)
.emit()
});
}
}
}
}

Expand Down Expand Up @@ -103,4 +135,8 @@ impl Visit for DuplicateExports {
ModuleExportName::Str(..) => {}
};
}

fn visit_ts_export_assignment(&mut self, n: &TsExportAssignment) {
self.add_export_assign(n.span);
}
}
4 changes: 3 additions & 1 deletion crates/swc_ecma_transforms_module/src/module_decl_strip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ impl VisitMut for ModuleDeclStrip {
/// export = expr;
/// ```
fn visit_mut_ts_export_assignment(&mut self, n: &mut TsExportAssignment) {
self.export_assign = Some(n.expr.take());
self.export_assign.get_or_insert(n.expr.take());
}
}

Expand Down Expand Up @@ -527,6 +527,7 @@ impl From<&ImportSpecifier> for LinkFlag {

ImportSpecifier::Default(ImportDefaultSpecifier { .. })
| ImportSpecifier::Named(ImportNamedSpecifier {
is_type_only: false,
imported:
Some(ModuleExportName::Ident(Ident {
sym: js_word!("default"),
Expand Down Expand Up @@ -557,6 +558,7 @@ impl From<&ExportSpecifier> for LinkFlag {
// https://github.com/tc39/proposal-export-default-from
ExportSpecifier::Default(..)
| ExportSpecifier::Named(ExportNamedSpecifier {
is_type_only: false,
orig:
ModuleExportName::Ident(Ident {
sym: js_word!("default"),
Expand Down
67 changes: 46 additions & 21 deletions crates/swc_ecma_transforms_typescript/src/import_export_assign.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use swc_common::{Mark, DUMMY_SP};
use swc_common::{errors::HANDLER, Mark, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_utils::{member_expr, private_ident, quote_ident, quote_str, ExprFactory};
use swc_ecma_visit::{
Expand Down Expand Up @@ -115,6 +115,17 @@ impl VisitMut for ImportExportAssign {
)
}
}
TsImportExportAssignConfig::EsNext => {
// TS1202
HANDLER.with(|handler| {
handler
.struct_span_err(
span,
r#"Import assignment cannot be used when targeting ECMAScript modules. Consider using `import * as ns from "mod"`, `import {a} from "mod"`, `import d from "mod"`, or another module format instead."#,
)
.emit()
});
}
TsImportExportAssignConfig::NodeNext => {
// const foo = __require("foo")
stmts.push(
Expand Down Expand Up @@ -160,27 +171,41 @@ impl VisitMut for ImportExportAssign {
}

if let Some(export_assign) = self.export_assign.take() {
if self.config == TsImportExportAssignConfig::Classic {
let TsExportAssignment { expr, span } = export_assign;

stmts.push(
Stmt::Expr(ExprStmt {
span,
expr: Box::new(
expr.make_assign_to(
op!("="),
member_expr!(
DUMMY_SP.apply_mark(self.unresolved_mark),
module.exports
)
.as_pat_or_expr(),
match self.config {
TsImportExportAssignConfig::Classic => {
let TsExportAssignment { expr, span } = export_assign;

stmts.push(
Stmt::Expr(ExprStmt {
span,
expr: Box::new(
expr.make_assign_to(
op!("="),
member_expr!(
DUMMY_SP.apply_mark(self.unresolved_mark),
module.exports
)
.as_pat_or_expr(),
),
),
),
})
.into(),
)
} else {
stmts.push(ModuleDecl::TsExportAssignment(export_assign).into())
})
.into(),
)
}
TsImportExportAssignConfig::Preserve => {
stmts.push(ModuleDecl::TsExportAssignment(export_assign).into())
}
TsImportExportAssignConfig::EsNext | TsImportExportAssignConfig::NodeNext => {
// TS1203
HANDLER.with(|handler| {
handler
.struct_span_err(
export_assign.span,
r#"Export assignment cannot be used when targeting ECMAScript modules. Consider using `export default` or another module format instead."#,
)
.emit()
});
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions crates/swc_ecma_transforms_typescript/src/strip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,23 @@ pub enum TsImportExportAssignConfig {
/// Note: This option is deprecated as all CJS/AMD/UMD can handle it
/// themselves.
Classic,

/// preserve for CJS/AMD/UMD
Preserve,

/// Rewrite `import foo = require("foo")` to
/// ```javascript
/// import { createRequire as _createRequire } from "module";
/// const __require = _createRequire(import.meta.url);
/// const foo = __require("foo");
/// ```
///
/// Report error for `export =`
NodeNext,

/// Both `import =` and `export =` are disabled.
/// An error will be reported if an import/export assignment is found.
EsNext,
}

impl Default for TsImportExportAssignConfig {
Expand Down

1 comment on commit f952a61

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: f952a61 Previous: bef8aeb Ratio
es/full/minify/libraries/antd 1786169866 ns/iter (± 114204135) 1758186947 ns/iter (± 68279867) 1.02
es/full/minify/libraries/d3 446747396 ns/iter (± 37105310) 462142462 ns/iter (± 25284067) 0.97
es/full/minify/libraries/echarts 1771580421 ns/iter (± 154631986) 1757346507 ns/iter (± 115085655) 1.01
es/full/minify/libraries/jquery 109026497 ns/iter (± 12684919) 113878937 ns/iter (± 8570440) 0.96
es/full/minify/libraries/lodash 144098234 ns/iter (± 24390314) 143956466 ns/iter (± 9064548) 1.00
es/full/minify/libraries/moment 63348313 ns/iter (± 2143507) 62069206 ns/iter (± 4302931) 1.02
es/full/minify/libraries/react 20510033 ns/iter (± 4704088) 20700405 ns/iter (± 4261479) 0.99
es/full/minify/libraries/terser 649541915 ns/iter (± 43724176) 641719397 ns/iter (± 51612064) 1.01
es/full/minify/libraries/three 612941308 ns/iter (± 98882614) 566688370 ns/iter (± 47401752) 1.08
es/full/minify/libraries/typescript 3806066704 ns/iter (± 253310375) 3754294522 ns/iter (± 133172812) 1.01
es/full/minify/libraries/victory 782409336 ns/iter (± 93927600) 776367455 ns/iter (± 48976443) 1.01
es/full/minify/libraries/vue 169646197 ns/iter (± 3503812) 134794816 ns/iter (± 5204243) 1.26
es/full/codegen/es3 33785 ns/iter (± 3313) 32501 ns/iter (± 1482) 1.04
es/full/codegen/es5 33206 ns/iter (± 1961) 32199 ns/iter (± 488) 1.03
es/full/codegen/es2015 33757 ns/iter (± 1810) 32293 ns/iter (± 1207) 1.05
es/full/codegen/es2016 32308 ns/iter (± 440) 32415 ns/iter (± 2238) 1.00
es/full/codegen/es2017 32349 ns/iter (± 631) 32441 ns/iter (± 1463) 1.00
es/full/codegen/es2018 32363 ns/iter (± 1679) 32372 ns/iter (± 1194) 1.00
es/full/codegen/es2019 32393 ns/iter (± 2240) 32288 ns/iter (± 1363) 1.00
es/full/codegen/es2020 32562 ns/iter (± 1168) 32009 ns/iter (± 573) 1.02
es/full/all/es3 211461222 ns/iter (± 15372153) 190552070 ns/iter (± 13749926) 1.11
es/full/all/es5 199556462 ns/iter (± 13351772) 169022391 ns/iter (± 6954254) 1.18
es/full/all/es2015 153561301 ns/iter (± 11863103) 141433629 ns/iter (± 9119774) 1.09
es/full/all/es2016 147012169 ns/iter (± 16109374) 137862944 ns/iter (± 3938258) 1.07
es/full/all/es2017 149891256 ns/iter (± 11582520) 152248735 ns/iter (± 15489252) 0.98
es/full/all/es2018 145951194 ns/iter (± 13584130) 141493556 ns/iter (± 11115415) 1.03
es/full/all/es2019 153206771 ns/iter (± 13002580) 134962649 ns/iter (± 5065972) 1.14
es/full/all/es2020 145877834 ns/iter (± 13970615) 132009184 ns/iter (± 6439143) 1.11
es/full/parser 718437 ns/iter (± 33157) 708755 ns/iter (± 22784) 1.01
es/full/base/fixer 29593 ns/iter (± 8246) 29651 ns/iter (± 553) 1.00
es/full/base/resolver_and_hygiene 88694 ns/iter (± 8881) 88205 ns/iter (± 1764) 1.01
serialization of ast node 217 ns/iter (± 10) 214 ns/iter (± 2) 1.01
serialization of serde 228 ns/iter (± 5) 227 ns/iter (± 1) 1.00

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.