mirror of
https://github.com/swc-project/swc.git
synced 2024-11-28 02:29:04 +03:00
type-only import, exports (#662)
This commit is contained in:
parent
f344caa4fa
commit
1fc09caa2f
@ -62,6 +62,9 @@ pub struct ImportDecl {
|
||||
|
||||
#[serde(rename = "source")]
|
||||
pub src: Str,
|
||||
|
||||
#[serde(rename = "typeOnly")]
|
||||
pub type_only: bool,
|
||||
}
|
||||
|
||||
/// `export * from 'mod'`
|
||||
@ -83,6 +86,9 @@ pub struct NamedExport {
|
||||
|
||||
#[serde(rename = "source")]
|
||||
pub src: Option<Str>,
|
||||
|
||||
#[serde(rename = "typeOnly")]
|
||||
pub type_only: bool,
|
||||
}
|
||||
|
||||
#[ast_node("ExportDefaultDeclaration")]
|
||||
|
@ -344,6 +344,9 @@ macro_rules! tok {
|
||||
("meta") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(swc_atoms::js_word!("meta")))
|
||||
};
|
||||
("type") => {
|
||||
crate::token::Token::Word(crate::token::Word::Ident(swc_atoms::js_word!("type")))
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! token_including_semi {
|
||||
|
@ -55,10 +55,13 @@ impl<'a, I: Tokens> Parser<'a, I> {
|
||||
span: span!(start),
|
||||
src,
|
||||
specifiers: vec![],
|
||||
type_only: false,
|
||||
}))
|
||||
.map(ModuleItem::from);
|
||||
}
|
||||
|
||||
let type_only = self.syntax().typescript() && eat!("type");
|
||||
|
||||
let mut specifiers = vec![];
|
||||
|
||||
if is!(BindingIdent) {
|
||||
@ -103,6 +106,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
|
||||
span: span!(start),
|
||||
specifiers,
|
||||
src,
|
||||
type_only,
|
||||
}))
|
||||
.map(ModuleItem::from)
|
||||
}
|
||||
@ -181,7 +185,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
// TODO: remove clone
|
||||
if let Some(decl) = self.try_parse_ts_export_decl(decorators.clone(), sym)? {
|
||||
if let Some(decl) = self.try_parse_ts_export_decl(decorators.clone(), sym) {
|
||||
return Ok(ModuleDecl::ExportDecl(ExportDecl {
|
||||
span: span!(start),
|
||||
decl,
|
||||
@ -249,10 +253,12 @@ impl<'a, I: Tokens> Parser<'a, I> {
|
||||
}
|
||||
}
|
||||
|
||||
let type_only = self.input.syntax().typescript() && eat!("type");
|
||||
|
||||
// Some("default") if default is exported from 'src'
|
||||
let mut export_default = None;
|
||||
|
||||
if export_ns.is_none() && eat!("default") {
|
||||
if !type_only && export_ns.is_none() && eat!("default") {
|
||||
if self.input.syntax().typescript() {
|
||||
if is!("abstract") && peeked_is!("class") {
|
||||
let class_start = cur_pos!();
|
||||
@ -311,17 +317,22 @@ impl<'a, I: Tokens> Parser<'a, I> {
|
||||
}
|
||||
}
|
||||
|
||||
let decl = if is!("class") {
|
||||
let decl = if !type_only && is!("class") {
|
||||
let class_start = cur_pos!();
|
||||
self.parse_class_decl(start, class_start, decorators)?
|
||||
} else if is!("async")
|
||||
} else if !type_only
|
||||
&& is!("async")
|
||||
&& peeked_is!("function")
|
||||
&& !self.input.has_linebreak_between_cur_and_peeked()
|
||||
{
|
||||
self.parse_async_fn_decl(decorators)?
|
||||
} else if is!("function") {
|
||||
} else if !type_only && is!("function") {
|
||||
self.parse_fn_decl(decorators)?
|
||||
} else if self.input.syntax().typescript() && is!("const") && peeked_is!("enum") {
|
||||
} else if !type_only
|
||||
&& self.input.syntax().typescript()
|
||||
&& is!("const")
|
||||
&& peeked_is!("enum")
|
||||
{
|
||||
let start = cur_pos!();
|
||||
assert_and_bump!("const");
|
||||
let _ = cur!(true);
|
||||
@ -335,15 +346,16 @@ impl<'a, I: Tokens> Parser<'a, I> {
|
||||
decl,
|
||||
})
|
||||
});
|
||||
} else if is!("var")
|
||||
|| is!("const")
|
||||
|| (is!("let")
|
||||
&& peek!()
|
||||
.map(|t| {
|
||||
// module code is always in strict mode.
|
||||
t.follows_keyword_let(true)
|
||||
})
|
||||
.unwrap_or(false))
|
||||
} else if !type_only
|
||||
&& (is!("var")
|
||||
|| is!("const")
|
||||
|| (is!("let"))
|
||||
&& peek!()
|
||||
.map(|t| {
|
||||
// module code is always in strict mode.
|
||||
t.follows_keyword_let(true)
|
||||
})
|
||||
.unwrap_or(false))
|
||||
{
|
||||
self.parse_var_stmt(false).map(Decl::Var)?
|
||||
} else {
|
||||
@ -357,6 +369,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
|
||||
span: Span::new(start, src.span.hi(), Default::default()),
|
||||
specifiers: vec![s],
|
||||
src: Some(src),
|
||||
type_only,
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -381,6 +394,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
|
||||
exported: default,
|
||||
})],
|
||||
src: Some(src),
|
||||
type_only,
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -438,6 +452,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
|
||||
span: span!(start),
|
||||
specifiers,
|
||||
src,
|
||||
type_only,
|
||||
}));
|
||||
};
|
||||
|
||||
|
@ -2014,10 +2014,15 @@ impl<'a, I: Tokens> Parser<'a, I> {
|
||||
&mut self,
|
||||
decorators: Vec<Decorator>,
|
||||
value: JsWord,
|
||||
) -> PResult<'a, Option<Decl>> {
|
||||
let start = cur_pos!();
|
||||
|
||||
self.parse_ts_decl(start, decorators, value, true)
|
||||
) -> Option<Decl> {
|
||||
self.try_parse_ts(|p| {
|
||||
let start = cur_pos!();
|
||||
let opt = p.parse_ts_decl(start, decorators, value, true)?;
|
||||
Ok(match opt {
|
||||
Some(v) => Some(v),
|
||||
None => None,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Common to tsTryParseDeclare, tsTryParseExportDeclaration, and
|
||||
|
@ -43,7 +43,8 @@
|
||||
},
|
||||
"value": "react",
|
||||
"hasEscape": false
|
||||
}
|
||||
},
|
||||
"typeOnly": false
|
||||
},
|
||||
{
|
||||
"type": "FunctionDeclaration",
|
||||
|
@ -43,7 +43,8 @@
|
||||
},
|
||||
"value": "react",
|
||||
"hasEscape": false
|
||||
}
|
||||
},
|
||||
"typeOnly": false
|
||||
},
|
||||
{
|
||||
"type": "FunctionDeclaration",
|
||||
|
@ -150,7 +150,8 @@
|
||||
"exported": null
|
||||
}
|
||||
],
|
||||
"source": null
|
||||
"source": null,
|
||||
"typeOnly": false
|
||||
}
|
||||
],
|
||||
"interpreter": null
|
||||
|
@ -41,7 +41,8 @@
|
||||
},
|
||||
"value": "test",
|
||||
"hasEscape": false
|
||||
}
|
||||
},
|
||||
"typeOnly": false
|
||||
},
|
||||
{
|
||||
"type": "ImportDeclaration",
|
||||
@ -80,7 +81,8 @@
|
||||
},
|
||||
"value": "test",
|
||||
"hasEscape": false
|
||||
}
|
||||
},
|
||||
"typeOnly": false
|
||||
}
|
||||
],
|
||||
"interpreter": null
|
||||
|
@ -43,7 +43,8 @@
|
||||
},
|
||||
"value": "react",
|
||||
"hasEscape": false
|
||||
}
|
||||
},
|
||||
"typeOnly": false
|
||||
},
|
||||
{
|
||||
"type": "FunctionDeclaration",
|
||||
|
@ -0,0 +1 @@
|
||||
export type { Foo as Bar };
|
@ -0,0 +1,53 @@
|
||||
{
|
||||
"type": "Module",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 27,
|
||||
"ctxt": 0
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "ExportNamedDeclaration",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 27,
|
||||
"ctxt": 0
|
||||
},
|
||||
"specifiers": [
|
||||
{
|
||||
"type": "ExportSpecifier",
|
||||
"span": {
|
||||
"start": 14,
|
||||
"end": 24,
|
||||
"ctxt": 0
|
||||
},
|
||||
"orig": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 14,
|
||||
"end": 17,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "Foo",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
},
|
||||
"exported": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 21,
|
||||
"end": 24,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "Bar",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"source": null,
|
||||
"typeOnly": true
|
||||
}
|
||||
],
|
||||
"interpreter": null
|
||||
}
|
@ -0,0 +1 @@
|
||||
export type { Foo };
|
@ -0,0 +1,43 @@
|
||||
{
|
||||
"type": "Module",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 20,
|
||||
"ctxt": 0
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "ExportNamedDeclaration",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 20,
|
||||
"ctxt": 0
|
||||
},
|
||||
"specifiers": [
|
||||
{
|
||||
"type": "ExportSpecifier",
|
||||
"span": {
|
||||
"start": 14,
|
||||
"end": 17,
|
||||
"ctxt": 0
|
||||
},
|
||||
"orig": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 14,
|
||||
"end": 17,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "Foo",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
},
|
||||
"exported": null
|
||||
}
|
||||
],
|
||||
"source": null,
|
||||
"typeOnly": true
|
||||
}
|
||||
],
|
||||
"interpreter": null
|
||||
}
|
@ -0,0 +1 @@
|
||||
import type { Foo as Bar } from 'foo';
|
@ -0,0 +1,62 @@
|
||||
{
|
||||
"type": "Module",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 38,
|
||||
"ctxt": 0
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "ImportDeclaration",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 38,
|
||||
"ctxt": 0
|
||||
},
|
||||
"specifiers": [
|
||||
{
|
||||
"type": "ImportSpecifier",
|
||||
"span": {
|
||||
"start": 14,
|
||||
"end": 24,
|
||||
"ctxt": 0
|
||||
},
|
||||
"local": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 21,
|
||||
"end": 24,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "Bar",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
},
|
||||
"imported": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 14,
|
||||
"end": 17,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "Foo",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"source": {
|
||||
"type": "StringLiteral",
|
||||
"span": {
|
||||
"start": 32,
|
||||
"end": 37,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "foo",
|
||||
"hasEscape": false
|
||||
},
|
||||
"typeOnly": true
|
||||
}
|
||||
],
|
||||
"interpreter": null
|
||||
}
|
@ -0,0 +1 @@
|
||||
import type Foo from 'foo';
|
@ -0,0 +1,51 @@
|
||||
{
|
||||
"type": "Module",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 27,
|
||||
"ctxt": 0
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "ImportDeclaration",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 27,
|
||||
"ctxt": 0
|
||||
},
|
||||
"specifiers": [
|
||||
{
|
||||
"type": "ImportDefaultSpecifier",
|
||||
"span": {
|
||||
"start": 12,
|
||||
"end": 15,
|
||||
"ctxt": 0
|
||||
},
|
||||
"local": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 12,
|
||||
"end": 15,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "Foo",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"source": {
|
||||
"type": "StringLiteral",
|
||||
"span": {
|
||||
"start": 21,
|
||||
"end": 26,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "foo",
|
||||
"hasEscape": false
|
||||
},
|
||||
"typeOnly": true
|
||||
}
|
||||
],
|
||||
"interpreter": null
|
||||
}
|
@ -0,0 +1 @@
|
||||
import type { Foo } from 'foo';
|
@ -0,0 +1,52 @@
|
||||
{
|
||||
"type": "Module",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 31,
|
||||
"ctxt": 0
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "ImportDeclaration",
|
||||
"span": {
|
||||
"start": 0,
|
||||
"end": 31,
|
||||
"ctxt": 0
|
||||
},
|
||||
"specifiers": [
|
||||
{
|
||||
"type": "ImportSpecifier",
|
||||
"span": {
|
||||
"start": 14,
|
||||
"end": 17,
|
||||
"ctxt": 0
|
||||
},
|
||||
"local": {
|
||||
"type": "Identifier",
|
||||
"span": {
|
||||
"start": 14,
|
||||
"end": 17,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "Foo",
|
||||
"typeAnnotation": null,
|
||||
"optional": false
|
||||
},
|
||||
"imported": null
|
||||
}
|
||||
],
|
||||
"source": {
|
||||
"type": "StringLiteral",
|
||||
"span": {
|
||||
"start": 25,
|
||||
"end": 30,
|
||||
"ctxt": 0
|
||||
},
|
||||
"value": "foo",
|
||||
"hasEscape": false
|
||||
},
|
||||
"typeOnly": true
|
||||
}
|
||||
],
|
||||
"interpreter": null
|
||||
}
|
@ -43,7 +43,8 @@
|
||||
},
|
||||
"value": "package",
|
||||
"hasEscape": false
|
||||
}
|
||||
},
|
||||
"typeOnly": false
|
||||
}
|
||||
],
|
||||
"interpreter": null
|
||||
|
@ -70,7 +70,8 @@
|
||||
},
|
||||
"value": "a",
|
||||
"hasEscape": false
|
||||
}
|
||||
},
|
||||
"typeOnly": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -289,6 +289,7 @@ impl Fold<Module> for Polyfills {
|
||||
value: src,
|
||||
has_escape: false,
|
||||
},
|
||||
type_only: false,
|
||||
}))
|
||||
}),
|
||||
);
|
||||
@ -304,6 +305,7 @@ impl Fold<Module> for Polyfills {
|
||||
value: src,
|
||||
has_escape: false,
|
||||
},
|
||||
type_only: false,
|
||||
}))
|
||||
}),
|
||||
);
|
||||
|
@ -105,6 +105,7 @@ where
|
||||
}
|
||||
.into()],
|
||||
src: None,
|
||||
type_only: false,
|
||||
},
|
||||
)) {
|
||||
Ok(t) => t,
|
||||
|
@ -365,6 +365,7 @@ impl Fold<ModuleDecl> for RestFolder {
|
||||
span,
|
||||
specifiers,
|
||||
src: None,
|
||||
type_only: false,
|
||||
};
|
||||
|
||||
let mut var_decl = var_decl.fold_with(self);
|
||||
|
@ -239,6 +239,7 @@ impl InjectHelpers {
|
||||
local: quote_ident!(DUMMY_SP.apply_mark(mark), "swcHelpers"),
|
||||
})],
|
||||
src: quote_str!("@swc/helpers"),
|
||||
type_only: false,
|
||||
}))]
|
||||
} else {
|
||||
vec![]
|
||||
|
@ -32,6 +32,7 @@ impl<'a> Fold<Vec<ModuleItem>> for Operator<'a> {
|
||||
exported: Some($orig),
|
||||
})],
|
||||
src: None,
|
||||
type_only: false,
|
||||
},
|
||||
)));
|
||||
};
|
||||
@ -133,6 +134,7 @@ impl<'a> Fold<Vec<ModuleItem>> for Operator<'a> {
|
||||
span,
|
||||
specifiers: renamed,
|
||||
src: None,
|
||||
type_only: false,
|
||||
},
|
||||
)));
|
||||
}
|
||||
|
@ -82,6 +82,7 @@ where
|
||||
}
|
||||
.into()],
|
||||
src: None,
|
||||
type_only: false,
|
||||
},
|
||||
)) {
|
||||
Ok(t) => t,
|
||||
|
@ -136,6 +136,7 @@ impl Fold<Vec<ModuleItem>> for Decorators {
|
||||
}
|
||||
.into()],
|
||||
src: None,
|
||||
type_only: false,
|
||||
},
|
||||
)));
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ impl Fold<Module> for Legacy {
|
||||
span: DUMMY_SP,
|
||||
specifiers: replace(&mut self.exports, Default::default()),
|
||||
src: None,
|
||||
type_only: false,
|
||||
});
|
||||
|
||||
m.body.push(decl.into());
|
||||
|
@ -46,6 +46,7 @@ impl Fold<Vec<ModuleItem>> for ExportDefaultFrom {
|
||||
.src
|
||||
.clone()
|
||||
.expect("`export default from` requires source"),
|
||||
type_only: false,
|
||||
})));
|
||||
extra_stmts.push(ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(
|
||||
NamedExport {
|
||||
@ -58,6 +59,7 @@ impl Fold<Vec<ModuleItem>> for ExportDefaultFrom {
|
||||
},
|
||||
)],
|
||||
src: None,
|
||||
type_only: false,
|
||||
},
|
||||
)));
|
||||
}
|
||||
@ -74,6 +76,7 @@ impl Fold<Vec<ModuleItem>> for ExportDefaultFrom {
|
||||
.src
|
||||
.clone()
|
||||
.expect("`export default from` requires source"),
|
||||
type_only: false,
|
||||
})));
|
||||
extra_stmts.push(ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(
|
||||
NamedExport {
|
||||
@ -86,6 +89,7 @@ impl Fold<Vec<ModuleItem>> for ExportDefaultFrom {
|
||||
},
|
||||
)],
|
||||
src: None,
|
||||
type_only: false,
|
||||
},
|
||||
)));
|
||||
}
|
||||
|
@ -210,7 +210,14 @@ impl Fold<Vec<ModuleItem>> for Strip {
|
||||
for item in items {
|
||||
self.was_side_effect_import = false;
|
||||
match item {
|
||||
ModuleItem::Stmt(Stmt::Empty(..)) => continue,
|
||||
ModuleItem::Stmt(Stmt::Empty(..))
|
||||
| ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl {
|
||||
type_only: true, ..
|
||||
}))
|
||||
| ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(NamedExport {
|
||||
type_only: true,
|
||||
..
|
||||
})) => continue,
|
||||
|
||||
ModuleItem::ModuleDecl(ModuleDecl::Import(i)) => {
|
||||
let i = i.fold_with(self);
|
||||
|
@ -330,3 +330,7 @@ test!(
|
||||
"export const x = { text: 'hello' };",
|
||||
ok_if_code_eq
|
||||
);
|
||||
|
||||
to!(import_type, "import type foo from 'foo'", "");
|
||||
|
||||
to!(export_type, "export type { foo }", "");
|
||||
|
Loading…
Reference in New Issue
Block a user