mirror of
https://github.com/swc-project/swc.git
synced 2024-12-26 15:12:08 +03:00
feat(es/typescript): Improve fast TS strip (#9154)
**Description:** It's almost done, but it need some more adjustment for arrow functions.
This commit is contained in:
parent
2daee6fa7e
commit
05c721030a
@ -1 +1 @@
|
|||||||
Subproject commit a03c69227413dfcac8a1e9f89d93554fa3b8b7fe
|
Subproject commit 8e9c0b0fb3d548f378420aabbd351087efb5d5e5
|
@ -7,9 +7,12 @@ use swc_common::{
|
|||||||
BytePos, FileName, SourceMap, Span, Spanned,
|
BytePos, FileName, SourceMap, Span, Spanned,
|
||||||
};
|
};
|
||||||
use swc_ecma_ast::{
|
use swc_ecma_ast::{
|
||||||
BindingIdent, Decorator, EsVersion, Ident, ImportDecl, ImportSpecifier, Param, Pat, Program,
|
ArrowExpr, BindingIdent, Class, ClassMethod, ClassProp, Decorator, EsVersion, ExportAll,
|
||||||
TsAsExpr, TsConstAssertion, TsEnumDecl, TsInstantiation, TsModuleDecl, TsModuleName,
|
ExportDecl, ExportSpecifier, FnDecl, Ident, ImportDecl, ImportSpecifier, MethodKind,
|
||||||
TsNamespaceDecl, TsNonNullExpr, TsParamPropParam, TsSatisfiesExpr, TsTypeAliasDecl, TsTypeAnn,
|
NamedExport, Param, Pat, Program, TsAsExpr, TsConstAssertion, TsEnumDecl, TsInstantiation,
|
||||||
|
TsInterfaceDecl, TsModuleDecl, TsModuleName, TsNamespaceDecl, TsNonNullExpr, TsParamPropParam,
|
||||||
|
TsSatisfiesExpr, TsTypeAliasDecl, TsTypeAnn, TsTypeAssertion, TsTypeParamDecl,
|
||||||
|
TsTypeParamInstantiation, VarDecl,
|
||||||
};
|
};
|
||||||
use swc_ecma_parser::{
|
use swc_ecma_parser::{
|
||||||
parse_file_as_module, parse_file_as_program, parse_file_as_script, Syntax, TsSyntax,
|
parse_file_as_module, parse_file_as_program, parse_file_as_script, Syntax, TsSyntax,
|
||||||
@ -83,7 +86,7 @@ pub fn operate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Strip typescript types
|
// Strip typescript types
|
||||||
let mut ts_strip = TsStrip::new(fm.src.clone());
|
let mut ts_strip = TsStrip::new(cm.clone(), fm.src.clone());
|
||||||
program.visit_with(&mut ts_strip);
|
program.visit_with(&mut ts_strip);
|
||||||
|
|
||||||
let replacements = ts_strip.replacements;
|
let replacements = ts_strip.replacements;
|
||||||
@ -98,19 +101,48 @@ pub fn operate(
|
|||||||
code[(r.0 .0 - 1) as usize..(r.1 .0 - 1) as usize].fill(b' ');
|
code[(r.0 .0 - 1) as usize..(r.1 .0 - 1) as usize].fill(b' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assert that removal does not overlap with each other
|
||||||
|
|
||||||
|
for removal in ts_strip.removals.iter() {
|
||||||
|
for r in &ts_strip.removals {
|
||||||
|
if removal == r {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
r.0 < removal.0 || r.1 < removal.0 || r.0 > removal.1 || r.1 > removal.1,
|
||||||
|
"removal {:?} overlaps with replacement {:?}",
|
||||||
|
removal,
|
||||||
|
r
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for removal in ts_strip.removals.iter().copied().rev() {
|
||||||
|
code.drain((removal.0 .0 - 1) as usize..(removal.1 .0 - 1) as usize);
|
||||||
|
}
|
||||||
|
|
||||||
String::from_utf8(code).map_err(|_| anyhow::anyhow!("failed to convert to utf-8"))
|
String::from_utf8(code).map_err(|_| anyhow::anyhow!("failed to convert to utf-8"))
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TsStrip {
|
struct TsStrip {
|
||||||
|
cm: Lrc<SourceMap>,
|
||||||
src: Lrc<String>,
|
src: Lrc<String>,
|
||||||
|
|
||||||
|
/// Replaced with whitespace
|
||||||
replacements: Vec<(BytePos, BytePos)>,
|
replacements: Vec<(BytePos, BytePos)>,
|
||||||
|
|
||||||
|
/// Applied after replacements. Used for arrow functions.
|
||||||
|
removals: Vec<(BytePos, BytePos)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TsStrip {
|
impl TsStrip {
|
||||||
fn new(src: Lrc<String>) -> Self {
|
fn new(cm: Lrc<SourceMap>, src: Lrc<String>) -> Self {
|
||||||
TsStrip {
|
TsStrip {
|
||||||
|
cm,
|
||||||
src,
|
src,
|
||||||
replacements: Default::default(),
|
replacements: Default::default(),
|
||||||
|
removals: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,15 +151,208 @@ impl TsStrip {
|
|||||||
fn add_replacement(&mut self, span: Span) {
|
fn add_replacement(&mut self, span: Span) {
|
||||||
self.replacements.push((span.lo, span.hi));
|
self.replacements.push((span.lo, span.hi));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_removal(&mut self, span: Span) {
|
||||||
|
self.removals.push((span.lo, span.hi));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Visit for TsStrip {
|
impl Visit for TsStrip {
|
||||||
|
fn visit_arrow_expr(&mut self, n: &ArrowExpr) {
|
||||||
|
if let Some(ret) = &n.return_type {
|
||||||
|
let mut sp = self.cm.span_extend_to_prev_char(ret.span, ')');
|
||||||
|
|
||||||
|
let pos = self.src[(sp.hi.0 as usize - 1)..].find("=>").unwrap();
|
||||||
|
|
||||||
|
sp.hi.0 += pos as u32;
|
||||||
|
|
||||||
|
self.add_removal(sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
n.type_params.visit_with(self);
|
||||||
|
n.params.visit_with(self);
|
||||||
|
n.body.visit_with(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_binding_ident(&mut self, n: &BindingIdent) {
|
||||||
|
n.visit_children_with(self);
|
||||||
|
|
||||||
|
if n.optional {
|
||||||
|
self.add_replacement(span(n.id.span.hi, n.id.span.hi + BytePos(1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_class(&mut self, n: &Class) {
|
||||||
|
n.visit_children_with(self);
|
||||||
|
|
||||||
|
let lo = match &n.super_class {
|
||||||
|
Some(v) => v.span().hi,
|
||||||
|
None => n.span.lo,
|
||||||
|
};
|
||||||
|
let hi = skip_until(self.src.as_bytes(), lo.0, b'{');
|
||||||
|
self.add_replacement(span(lo, BytePos(hi)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_class_method(&mut self, n: &ClassMethod) {
|
||||||
|
if n.function.body.is_none() {
|
||||||
|
self.add_replacement(n.span);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let hi = match n.kind {
|
||||||
|
MethodKind::Method => {
|
||||||
|
if n.is_static {
|
||||||
|
self.cm
|
||||||
|
.span_extend_to_next_str(span(n.span.lo, n.span.lo), "static", false)
|
||||||
|
.hi
|
||||||
|
} else {
|
||||||
|
n.key.span().lo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MethodKind::Getter => {
|
||||||
|
self.cm
|
||||||
|
.span_extend_to_next_str(span(n.span.lo, n.span.lo), "get", false)
|
||||||
|
.hi
|
||||||
|
}
|
||||||
|
MethodKind::Setter => {
|
||||||
|
self.cm
|
||||||
|
.span_extend_to_next_str(span(n.span.lo, n.span.lo), "set", false)
|
||||||
|
.hi
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.add_replacement(span(n.span.lo, hi));
|
||||||
|
|
||||||
|
n.visit_children_with(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_class_prop(&mut self, n: &ClassProp) {
|
||||||
|
if n.declare {
|
||||||
|
self.add_replacement(n.span);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let hi = if n.is_static {
|
||||||
|
self.cm
|
||||||
|
.span_extend_to_next_str(span(n.span.lo, n.span.lo), "static", false)
|
||||||
|
.hi
|
||||||
|
} else {
|
||||||
|
n.key.span().lo
|
||||||
|
};
|
||||||
|
|
||||||
|
self.add_replacement(span(n.span.lo, hi));
|
||||||
|
|
||||||
|
n.visit_children_with(self);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_decorator(&mut self, n: &Decorator) {
|
fn visit_decorator(&mut self, n: &Decorator) {
|
||||||
HANDLER.with(|handler| {
|
HANDLER.with(|handler| {
|
||||||
handler.span_err(n.span, "Decorators are not supported");
|
handler.span_err(n.span, "Decorators are not supported");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_export_all(&mut self, n: &ExportAll) {
|
||||||
|
if n.type_only {
|
||||||
|
self.add_replacement(n.span);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
n.visit_children_with(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_export_decl(&mut self, n: &ExportDecl) {
|
||||||
|
match n.decl {
|
||||||
|
swc_ecma_ast::Decl::TsInterface(_)
|
||||||
|
| swc_ecma_ast::Decl::TsTypeAlias(_)
|
||||||
|
| swc_ecma_ast::Decl::TsEnum(_)
|
||||||
|
| swc_ecma_ast::Decl::TsModule(_) => {
|
||||||
|
self.add_replacement(n.span);
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
n.visit_children_with(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_fn_decl(&mut self, n: &FnDecl) {
|
||||||
|
if n.function.body.is_none() {
|
||||||
|
self.add_replacement(n.function.span);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
n.visit_children_with(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_import_decl(&mut self, n: &ImportDecl) {
|
||||||
|
if n.type_only {
|
||||||
|
self.add_replacement(n.span);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
n.visit_children_with(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_import_specifiers(&mut self, n: &[ImportSpecifier]) {
|
||||||
|
for (i, import) in n.iter().enumerate() {
|
||||||
|
let ImportSpecifier::Named(import) = import else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
if import.is_type_only {
|
||||||
|
let mut span = import.span;
|
||||||
|
span.hi.0 = n.get(i + 1).map(|x| x.span_lo().0).unwrap_or_else(|| {
|
||||||
|
let bytes = self.src.as_bytes();
|
||||||
|
skip_until(bytes, span.hi.0, b'}')
|
||||||
|
});
|
||||||
|
self.add_replacement(span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_named_export(&mut self, n: &NamedExport) {
|
||||||
|
if n.type_only {
|
||||||
|
self.add_replacement(n.span);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for export in n.specifiers.iter() {
|
||||||
|
if let ExportSpecifier::Named(e) = export {
|
||||||
|
if e.is_type_only {
|
||||||
|
let sp = self.cm.span_extend_to_next_char(e.span, ',');
|
||||||
|
self.add_replacement(span(sp.lo, sp.hi + BytePos(1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_params(&mut self, n: &[Param]) {
|
||||||
|
if let Some(p) = n.first().filter(|param| {
|
||||||
|
matches!(
|
||||||
|
¶m.pat,
|
||||||
|
Pat::Ident(BindingIdent {
|
||||||
|
id: Ident { sym, .. },
|
||||||
|
..
|
||||||
|
}) if &**sym == "this"
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
let mut span = p.span;
|
||||||
|
|
||||||
|
if n.len() == 1 {
|
||||||
|
let bytes = self.src.as_bytes();
|
||||||
|
span.hi.0 = skip_until(bytes, span.hi.0, b')');
|
||||||
|
} else {
|
||||||
|
span.hi = n[1].span.lo;
|
||||||
|
n[1..].visit_children_with(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.add_replacement(span);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
n.visit_children_with(self);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_ts_as_expr(&mut self, n: &TsAsExpr) {
|
fn visit_ts_as_expr(&mut self, n: &TsAsExpr) {
|
||||||
self.add_replacement(span(n.expr.span().hi, n.span.hi));
|
self.add_replacement(span(n.expr.span().hi, n.span.hi));
|
||||||
|
|
||||||
@ -160,6 +385,10 @@ impl Visit for TsStrip {
|
|||||||
n.expr.visit_children_with(self);
|
n.expr.visit_children_with(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_ts_interface_decl(&mut self, n: &TsInterfaceDecl) {
|
||||||
|
self.add_replacement(n.span);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_ts_module_decl(&mut self, n: &TsModuleDecl) {
|
fn visit_ts_module_decl(&mut self, n: &TsModuleDecl) {
|
||||||
if n.declare || matches!(n.id, TsModuleName::Str(..)) {
|
if n.declare || matches!(n.id, TsModuleName::Str(..)) {
|
||||||
self.add_replacement(n.span);
|
self.add_replacement(n.span);
|
||||||
@ -217,67 +446,28 @@ impl Visit for TsStrip {
|
|||||||
self.add_replacement(n.span);
|
self.add_replacement(n.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_binding_ident(&mut self, n: &BindingIdent) {
|
fn visit_ts_type_assertion(&mut self, n: &TsTypeAssertion) {
|
||||||
n.visit_children_with(self);
|
self.add_replacement(span(n.span.lo, n.expr.span().lo));
|
||||||
|
|
||||||
if n.optional {
|
n.expr.visit_children_with(self);
|
||||||
self.add_replacement(span(n.id.span.hi, n.id.span.hi + BytePos(1)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_params(&mut self, n: &[Param]) {
|
fn visit_ts_type_param_decl(&mut self, n: &TsTypeParamDecl) {
|
||||||
if let Some(p) = n.first().filter(|param| {
|
self.add_replacement(n.span);
|
||||||
matches!(
|
|
||||||
¶m.pat,
|
|
||||||
Pat::Ident(BindingIdent {
|
|
||||||
id: Ident { sym, .. },
|
|
||||||
..
|
|
||||||
}) if &**sym == "this"
|
|
||||||
)
|
|
||||||
}) {
|
|
||||||
let mut span = p.span;
|
|
||||||
|
|
||||||
if n.len() == 1 {
|
|
||||||
let bytes = self.src.as_bytes();
|
|
||||||
span.hi.0 = skip_until(bytes, span.hi.0, b')');
|
|
||||||
} else {
|
|
||||||
span.hi = n[1].span.lo;
|
|
||||||
n[1..].visit_children_with(self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.add_replacement(span);
|
fn visit_ts_type_param_instantiation(&mut self, n: &TsTypeParamInstantiation) {
|
||||||
|
self.add_replacement(span(n.span.lo, n.span.hi));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n.visit_children_with(self);
|
fn visit_var_decl(&mut self, n: &VarDecl) {
|
||||||
}
|
if n.declare {
|
||||||
|
|
||||||
fn visit_import_decl(&mut self, n: &ImportDecl) {
|
|
||||||
if n.type_only {
|
|
||||||
self.add_replacement(n.span);
|
self.add_replacement(n.span);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
n.visit_children_with(self);
|
n.visit_children_with(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_import_specifiers(&mut self, n: &[ImportSpecifier]) {
|
|
||||||
for (i, import) in n.iter().enumerate() {
|
|
||||||
let ImportSpecifier::Named(import) = import else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
if import.is_type_only {
|
|
||||||
let mut span = import.span;
|
|
||||||
span.hi.0 = n.get(i + 1).map(|x| x.span_lo().0).unwrap_or_else(|| {
|
|
||||||
let bytes = self.src.as_bytes();
|
|
||||||
skip_until(bytes, span.hi.0, b'}')
|
|
||||||
});
|
|
||||||
self.add_replacement(span);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span(lo: BytePos, hi: BytePos) -> Span {
|
fn span(lo: BytePos, hi: BytePos) -> Span {
|
||||||
|
171
crates/swc_fast_ts_strip/tests/fixture/test-case-1.js
Normal file
171
crates/swc_fast_ts_strip/tests/fixture/test-case-1.js
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
let x /**/ /**/ = 1 ;
|
||||||
|
// ^^^^^^^^ ^
|
||||||
|
|
||||||
|
[] ;
|
||||||
|
// ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
( "test");
|
||||||
|
//^^^^^^^^
|
||||||
|
|
||||||
|
class C /**/ /*︎*/ extends Array {
|
||||||
|
// ^^^^^ ^^^ ^^^^^^^^^^^^^^
|
||||||
|
field/**/ /**/ = "";
|
||||||
|
// ^^^^^^^^ ^^^^^^^^
|
||||||
|
static accessor f1;
|
||||||
|
f2/**/!/**/ /*︎*/;
|
||||||
|
// ^^^^^^^ ^ ^^^^^^^^
|
||||||
|
|
||||||
|
// ^^^^^^^^^^^^^^^^ declared property
|
||||||
|
|
||||||
|
method/**/ /*︎*/(/*︎*/ a /*︎*/ /**/)/*︎*/ /*︎*/ {
|
||||||
|
// ^^^^^^ ^^^ ^^^^^^^^ ^ ^^^^^^^^ ^^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
[key ] ;
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^ index signature
|
||||||
|
|
||||||
|
get g() { return 1 };
|
||||||
|
// ^^^^^
|
||||||
|
set g(v ) { };
|
||||||
|
// ^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
class D extends C {
|
||||||
|
// ^^^^^
|
||||||
|
method(...args) { }
|
||||||
|
// ^^^^^^^^ ^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// ^^^^^^^^
|
||||||
|
a;
|
||||||
|
// ^^^^^^^^^^^ abstract property
|
||||||
|
b;
|
||||||
|
|
||||||
|
// ^^^^^^^^^^^^^^^^^^ abstract method
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let m = new (Map ) ([] );
|
||||||
|
// ^ ^^^^^^^^^^^^^^^^ ^
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let a = (foo ) ;
|
||||||
|
// ^ ^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let a = (foo ) ([] );
|
||||||
|
// ^ ^^^^^ ^
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let f = function (p ) { }
|
||||||
|
// ^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overload
|
||||||
|
function overload() { }
|
||||||
|
// ^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @doc */
|
||||||
|
|
||||||
|
// ^^^^^^^^^^^ interface
|
||||||
|
|
||||||
|
void 0;
|
||||||
|
|
||||||
|
/** @doc */
|
||||||
|
|
||||||
|
// ^^^^^^^^ type alias
|
||||||
|
|
||||||
|
/**/
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `import type`
|
||||||
|
|
||||||
|
/**/
|
||||||
|
// ^^^^^^^^^^^^^^^^^^ `export type`
|
||||||
|
|
||||||
|
/**/
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `export type *`
|
||||||
|
|
||||||
|
import { deepEqual } from "node:assert";
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
export {
|
||||||
|
C,
|
||||||
|
|
||||||
|
// ^^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
function foo (p = ()=> 1) {
|
||||||
|
// ^^^ ^^^^^ ^^^^^ ^^^^^
|
||||||
|
return p ;
|
||||||
|
// ^^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
// ^^^^^^^^^^^^^^^^^^ `declare enum`
|
||||||
|
|
||||||
|
void 0;
|
||||||
|
|
||||||
|
/**/
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^ `declare namespace`
|
||||||
|
|
||||||
|
void 0;
|
||||||
|
|
||||||
|
/**/
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^ `declare module`
|
||||||
|
|
||||||
|
void 0;
|
||||||
|
|
||||||
|
/**/
|
||||||
|
// ^^^^^^^^^^^^^^ `declare let`
|
||||||
|
|
||||||
|
void 0;
|
||||||
|
|
||||||
|
/**/ { }
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `declare class`
|
||||||
|
|
||||||
|
void 0;
|
||||||
|
|
||||||
|
/**/
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `declare function`
|
||||||
|
|
||||||
|
void 0;
|
||||||
|
|
||||||
|
// `=>` spanning line cases:
|
||||||
|
{
|
||||||
|
()
|
||||||
|
=>
|
||||||
|
1
|
||||||
|
};
|
||||||
|
{
|
||||||
|
()=>
|
||||||
|
1
|
||||||
|
};
|
||||||
|
{
|
||||||
|
(
|
||||||
|
)
|
||||||
|
=>
|
||||||
|
1
|
||||||
|
};
|
||||||
|
{
|
||||||
|
(
|
||||||
|
)=>
|
||||||
|
1
|
||||||
|
};
|
||||||
|
{
|
||||||
|
(
|
||||||
|
)=>
|
||||||
|
1
|
||||||
|
};
|
||||||
|
{
|
||||||
|
(a, b, c = [] /*comment-1*/)=>
|
||||||
|
1
|
||||||
|
};
|
177
crates/swc_fast_ts_strip/tests/fixture/test-case-1.ts
Normal file
177
crates/swc_fast_ts_strip/tests/fixture/test-case-1.ts
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
let x /**/: number/**/ = 1!;
|
||||||
|
// ^^^^^^^^ ^
|
||||||
|
|
||||||
|
[] as [] satisfies [];
|
||||||
|
// ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
(<string>"test");
|
||||||
|
//^^^^^^^^
|
||||||
|
|
||||||
|
class C /**/<T>/*︎*/ extends Array/**/<T> /*︎*/ implements I, J/*︎*/ {
|
||||||
|
// ^^^^^ ^^^ ^^^^^^^^^^^^^^
|
||||||
|
readonly field/**/: string/**/ = "";
|
||||||
|
// ^^^^^^^^ ^^^^^^^^
|
||||||
|
static accessor f1;
|
||||||
|
private f2/**/!/**/: string/*︎*/;
|
||||||
|
// ^^^^^^^ ^ ^^^^^^^^
|
||||||
|
declare f3: any;
|
||||||
|
// ^^^^^^^^^^^^^^^^ declared property
|
||||||
|
|
||||||
|
public method/**/<T>/*︎*/(/*︎*/this: T,/**/ a? /*︎*/: string/**/)/*︎*/: void/*︎*/ {
|
||||||
|
// ^^^^^^ ^^^ ^^^^^^^^ ^ ^^^^^^^^ ^^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
[key: string]: any;
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^ index signature
|
||||||
|
|
||||||
|
get g(): any { return 1 };
|
||||||
|
// ^^^^^
|
||||||
|
set g(v: any) { };
|
||||||
|
// ^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
class D extends C<any> {
|
||||||
|
// ^^^^^
|
||||||
|
override method(...args): any { }
|
||||||
|
// ^^^^^^^^ ^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class A {
|
||||||
|
// ^^^^^^^^
|
||||||
|
abstract a;
|
||||||
|
// ^^^^^^^^^^^ abstract property
|
||||||
|
b;
|
||||||
|
abstract method();
|
||||||
|
// ^^^^^^^^^^^^^^^^^^ abstract method
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let m = new (Map!)<string, number>([]!);
|
||||||
|
// ^ ^^^^^^^^^^^^^^^^ ^
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let a = (foo!)<any>;
|
||||||
|
// ^ ^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let a = (foo!)<any>([]!);
|
||||||
|
// ^ ^^^^^ ^
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let f = function (p: any) { }
|
||||||
|
// ^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
function overload(): number;
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overload
|
||||||
|
function overload(): any { }
|
||||||
|
// ^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @doc */
|
||||||
|
interface I { }
|
||||||
|
// ^^^^^^^^^^^ interface
|
||||||
|
|
||||||
|
void 0;
|
||||||
|
|
||||||
|
/** @doc */
|
||||||
|
type J = I;
|
||||||
|
// ^^^^^^^^ type alias
|
||||||
|
|
||||||
|
/**/import type T from "node:assert";
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `import type`
|
||||||
|
|
||||||
|
/**/export type { I };
|
||||||
|
// ^^^^^^^^^^^^^^^^^^ `export type`
|
||||||
|
|
||||||
|
/**/export type * from "node:buffer";
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `export type *`
|
||||||
|
|
||||||
|
import { type AssertPredicate/**/, deepEqual } from "node:assert";
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
export {
|
||||||
|
C,
|
||||||
|
type T,
|
||||||
|
// ^^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/export type T2 = 1;
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
function foo<T>(p: any = (): any => 1): any {
|
||||||
|
// ^^^ ^^^^^ ^^^^^ ^^^^^
|
||||||
|
return p as any;
|
||||||
|
// ^^^^^^
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/declare enum E1 { }
|
||||||
|
// ^^^^^^^^^^^^^^^^^^ `declare enum`
|
||||||
|
|
||||||
|
void 0;
|
||||||
|
|
||||||
|
/**/declare namespace N { }
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^ `declare namespace`
|
||||||
|
|
||||||
|
void 0;
|
||||||
|
|
||||||
|
/**/declare module M { }
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^ `declare module`
|
||||||
|
|
||||||
|
void 0;
|
||||||
|
|
||||||
|
/**/declare let a;
|
||||||
|
// ^^^^^^^^^^^^^^ `declare let`
|
||||||
|
|
||||||
|
void 0;
|
||||||
|
|
||||||
|
/**/declare class DeclaredClass { }
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `declare class`
|
||||||
|
|
||||||
|
void 0;
|
||||||
|
|
||||||
|
/**/declare function DeclaredFunction(): void;
|
||||||
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `declare function`
|
||||||
|
|
||||||
|
void 0;
|
||||||
|
|
||||||
|
// `=>` spanning line cases:
|
||||||
|
{
|
||||||
|
()
|
||||||
|
: any =>
|
||||||
|
1
|
||||||
|
};
|
||||||
|
{
|
||||||
|
():
|
||||||
|
any =>
|
||||||
|
1
|
||||||
|
};
|
||||||
|
{
|
||||||
|
(
|
||||||
|
)
|
||||||
|
: any =>
|
||||||
|
1
|
||||||
|
};
|
||||||
|
{
|
||||||
|
(
|
||||||
|
): (
|
||||||
|
| any
|
||||||
|
) =>
|
||||||
|
1
|
||||||
|
};
|
||||||
|
{
|
||||||
|
(
|
||||||
|
):
|
||||||
|
NonNullable<any
|
||||||
|
> =>
|
||||||
|
1
|
||||||
|
};
|
||||||
|
{
|
||||||
|
(a, b, c: D = [] as any/*comment-1*/)/*comment-2*/:
|
||||||
|
any =>
|
||||||
|
1
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user