Skip to content

Commit 7d297be

Browse files
dsherretkdy1
andauthored
feat(es/ast): Add import attributes to TsImportType (#9796)
**Description:** This parses, emits, and visits import attributes in TsImportType. **BREAKING CHANGE:** - Adds an additional property to `TsImportType` **Related issue:** - Closes #9377 --------- Co-authored-by: 강동윤 (Donny) <kdy1997.dev@gmail.com>
1 parent 76c2cba commit 7d297be

30 files changed

+1354
-72
lines changed

Diff for: .changeset/modern-deers-sparkle.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
swc_ecma_ast: major
3+
---
4+
5+
feat: TsImportType - support import attributes

Diff for: crates/swc_ecma_ast/src/lib.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,17 @@ pub use self::{
6060
TsConditionalType, TsConstAssertion, TsConstructSignatureDecl, TsConstructorType,
6161
TsEntityName, TsEnumDecl, TsEnumMember, TsEnumMemberId, TsExportAssignment,
6262
TsExprWithTypeArgs, TsExternalModuleRef, TsFnOrConstructorType, TsFnParam, TsFnType,
63-
TsGetterSignature, TsImportEqualsDecl, TsImportType, TsIndexSignature, TsIndexedAccessType,
64-
TsInferType, TsInstantiation, TsInterfaceBody, TsInterfaceDecl, TsIntersectionType,
65-
TsKeywordType, TsKeywordTypeKind, TsLit, TsLitType, TsMappedType, TsMethodSignature,
66-
TsModuleBlock, TsModuleDecl, TsModuleName, TsModuleRef, TsNamespaceBody, TsNamespaceDecl,
67-
TsNamespaceExportDecl, TsNonNullExpr, TsOptionalType, TsParamProp, TsParamPropParam,
68-
TsParenthesizedType, TsPropertySignature, TsQualifiedName, TsRestType, TsSatisfiesExpr,
69-
TsSetterSignature, TsThisType, TsThisTypeOrIdent, TsTplLitType, TsTupleElement,
70-
TsTupleType, TsType, TsTypeAliasDecl, TsTypeAnn, TsTypeAssertion, TsTypeElement, TsTypeLit,
71-
TsTypeOperator, TsTypeOperatorOp, TsTypeParam, TsTypeParamDecl, TsTypeParamInstantiation,
72-
TsTypePredicate, TsTypeQuery, TsTypeQueryExpr, TsTypeRef, TsUnionOrIntersectionType,
73-
TsUnionType,
63+
TsGetterSignature, TsImportCallOptions, TsImportEqualsDecl, TsImportType, TsIndexSignature,
64+
TsIndexedAccessType, TsInferType, TsInstantiation, TsInterfaceBody, TsInterfaceDecl,
65+
TsIntersectionType, TsKeywordType, TsKeywordTypeKind, TsLit, TsLitType, TsMappedType,
66+
TsMethodSignature, TsModuleBlock, TsModuleDecl, TsModuleName, TsModuleRef, TsNamespaceBody,
67+
TsNamespaceDecl, TsNamespaceExportDecl, TsNonNullExpr, TsOptionalType, TsParamProp,
68+
TsParamPropParam, TsParenthesizedType, TsPropertySignature, TsQualifiedName, TsRestType,
69+
TsSatisfiesExpr, TsSetterSignature, TsThisType, TsThisTypeOrIdent, TsTplLitType,
70+
TsTupleElement, TsTupleType, TsType, TsTypeAliasDecl, TsTypeAnn, TsTypeAssertion,
71+
TsTypeElement, TsTypeLit, TsTypeOperator, TsTypeOperatorOp, TsTypeParam, TsTypeParamDecl,
72+
TsTypeParamInstantiation, TsTypePredicate, TsTypeQuery, TsTypeQueryExpr, TsTypeRef,
73+
TsUnionOrIntersectionType, TsUnionType,
7474
},
7575
};
7676

Diff for: crates/swc_ecma_ast/src/typescript.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use swc_common::{ast_node, EqIgnoreSpan, Span};
1616

1717
use crate::{
1818
class::Decorator,
19-
expr::Expr,
19+
expr::{Expr, ObjectLit},
2020
ident::Ident,
2121
lit::{Bool, Number, Str},
2222
module::ModuleItem,
@@ -565,6 +565,16 @@ pub enum TsTypeQueryExpr {
565565
Import(TsImportType),
566566
}
567567

568+
#[ast_node("TsImportCallOptions")]
569+
#[derive(Eq, Hash, EqIgnoreSpan)]
570+
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
571+
#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
572+
pub struct TsImportCallOptions {
573+
pub span: Span,
574+
#[cfg_attr(feature = "serde-impl", serde(default))]
575+
pub with: Box<ObjectLit>,
576+
}
577+
568578
#[ast_node("TsImportType")]
569579
#[derive(Eq, Hash, EqIgnoreSpan)]
570580
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
@@ -576,6 +586,8 @@ pub struct TsImportType {
576586
pub qualifier: Option<TsEntityName>,
577587
#[cfg_attr(feature = "serde-impl", serde(rename = "typeArguments"))]
578588
pub type_args: Option<Box<TsTypeParamInstantiation>>,
589+
#[cfg_attr(feature = "serde-impl", serde(default))]
590+
pub attributes: Option<TsImportCallOptions>,
579591
}
580592

581593
#[ast_node("TsTypeLiteral")]

Diff for: crates/swc_ecma_codegen/src/typescript.rs

+25
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,11 @@ where
845845
keyword!("import");
846846
punct!("(");
847847
emit!(n.arg);
848+
if let Some(attributes) = &n.attributes {
849+
punct!(",");
850+
formatting_space!();
851+
emit!(attributes);
852+
}
848853
punct!(")");
849854

850855
if let Some(n) = &n.qualifier {
@@ -855,6 +860,26 @@ where
855860
emit!(n.type_args);
856861
}
857862

863+
#[emitter]
864+
fn emit_ts_import_call_options(&mut self, n: &TsImportCallOptions) -> Result {
865+
punct!("{");
866+
if !self.cfg.minify {
867+
self.wr.write_line()?;
868+
self.wr.increase_indent()?;
869+
}
870+
871+
keyword!("with");
872+
punct!(":");
873+
formatting_space!();
874+
emit!(n.with);
875+
876+
if !self.cfg.minify {
877+
self.wr.decrease_indent()?;
878+
self.wr.write_line()?;
879+
}
880+
punct!("}");
881+
}
882+
858883
#[emitter]
859884
fn emit_ts_type_alias_decl(&mut self, n: &TsTypeAliasDecl) -> Result {
860885
self.emit_leading_comments_of_span(n.span(), false)?;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
type Vite = typeof import("vite", { with: { "resolution-mode": "import" } });
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
type Vite = typeof import("vite", {
2+
with: {
3+
"resolution-mode": "import"
4+
}
5+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
type Vite=typeof import("vite",{with:{"resolution-mode":"import"}});

Diff for: crates/swc_ecma_parser/src/parser/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ impl<I: Tokens> Parser<I> {
308308
}
309309

310310
tok!('{') => {
311-
return self.parse_object();
311+
return self.parse_object::<Expr>().map(Box::new);
312312
}
313313

314314
// Handle FunctionExpression and GeneratorExpression

Diff for: crates/swc_ecma_parser/src/parser/object.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -122,15 +122,15 @@ impl<I: Tokens> Parser<I> {
122122
}
123123
}
124124

125-
impl<I: Tokens> ParseObject<Box<Expr>> for Parser<I> {
125+
impl<I: Tokens> ParseObject<Expr> for Parser<I> {
126126
type Prop = PropOrSpread;
127127

128128
fn make_object(
129129
&mut self,
130130
span: Span,
131131
props: Vec<Self::Prop>,
132132
trailing_comma: Option<Span>,
133-
) -> PResult<Box<Expr>> {
133+
) -> PResult<Expr> {
134134
if let Some(trailing_comma) = trailing_comma {
135135
self.state.trailing_commas.insert(span.lo, trailing_comma);
136136
}

Diff for: crates/swc_ecma_parser/src/parser/stmt/module_item.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ impl<I: Tokens> Parser<I> {
5858
&& !self.input.had_line_break_before_cur()
5959
&& (eat!(self, "assert") || eat!(self, "with"))
6060
{
61-
match *self.parse_object::<Box<Expr>>()? {
61+
match self.parse_object::<Expr>()? {
6262
Expr::Object(v) => Some(Box::new(v)),
6363
_ => unreachable!(),
6464
}
@@ -183,7 +183,7 @@ impl<I: Tokens> Parser<I> {
183183
&& !self.input.had_line_break_before_cur()
184184
&& (eat!(self, "assert") || eat!(self, "with"))
185185
{
186-
match *self.parse_object::<Box<Expr>>()? {
186+
match self.parse_object::<Expr>()? {
187187
Expr::Object(v) => Some(Box::new(v)),
188188
_ => unreachable!(),
189189
}
@@ -858,7 +858,7 @@ impl<I: Tokens> Parser<I> {
858858
&& !self.input.had_line_break_before_cur()
859859
&& (eat!(self, "assert") || eat!(self, "with"))
860860
{
861-
match *self.parse_object::<Box<Expr>>()? {
861+
match self.parse_object::<Expr>()? {
862862
Expr::Object(v) => Some(Box::new(v)),
863863
_ => unreachable!(),
864864
}

Diff for: crates/swc_ecma_parser/src/parser/typescript.rs

+30
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,15 @@ impl<I: Tokens> Parser<I> {
316316
}
317317
};
318318

319+
// the "assert" keyword is deprecated and this syntax is niche, so
320+
// don't support it
321+
let attributes =
322+
if eat!(self, ',') && self.input.syntax().import_attributes() && is!(self, '{') {
323+
Some(self.parse_ts_call_options()?)
324+
} else {
325+
None
326+
};
327+
319328
expect!(self, ')');
320329

321330
let qualifier = if eat!(self, '.') {
@@ -340,6 +349,27 @@ impl<I: Tokens> Parser<I> {
340349
arg,
341350
qualifier,
342351
type_args,
352+
attributes,
353+
})
354+
}
355+
356+
fn parse_ts_call_options(&mut self) -> PResult<TsImportCallOptions> {
357+
debug_assert!(self.input.syntax().typescript());
358+
let start = cur_pos!(self);
359+
assert_and_bump!(self, '{');
360+
361+
expect!(self, "with");
362+
expect!(self, ':');
363+
364+
let value = match self.parse_object::<Expr>()? {
365+
Expr::Object(v) => v,
366+
_ => unreachable!(),
367+
};
368+
eat!(self, ',');
369+
expect!(self, '}');
370+
Ok(TsImportCallOptions {
371+
span: span!(self, start),
372+
with: Box::new(value),
343373
})
344374
}
345375

Diff for: crates/swc_ecma_parser/tests/tsc/allowImportingTypesDtsExtension.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,8 @@
332332
"value": "User",
333333
"optional": false
334334
},
335-
"typeArguments": null
335+
"typeArguments": null,
336+
"attributes": null
336337
}
337338
}
338339
}

Diff for: crates/swc_ecma_parser/tests/tsc/allowsImportingTsExtension.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@
223223
"value": "A",
224224
"optional": false
225225
},
226-
"typeArguments": null
226+
"typeArguments": null,
227+
"attributes": null
227228
}
228229
},
229230
{
@@ -440,7 +441,8 @@
440441
"value": "A",
441442
"optional": false
442443
},
443-
"typeArguments": null
444+
"typeArguments": null,
445+
"attributes": null
444446
}
445447
},
446448
{

Diff for: crates/swc_ecma_parser/tests/tsc/importTypeAmbient.json

+6-3
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@
196196
"raw": "\"foo\""
197197
},
198198
"qualifier": null,
199-
"typeArguments": null
199+
"typeArguments": null,
200+
"attributes": null
200201
}
201202
}
202203
},
@@ -779,7 +780,8 @@
779780
"value": "I"
780781
}
781782
},
782-
"typeArguments": null
783+
"typeArguments": null,
784+
"attributes": null
783785
}
784786
}
785787
},
@@ -1124,7 +1126,8 @@
11241126
"raw": "\"foo2\""
11251127
},
11261128
"qualifier": null,
1127-
"typeArguments": null
1129+
"typeArguments": null,
1130+
"attributes": null
11281131
},
11291132
"typeArguments": null
11301133
}

Diff for: crates/swc_ecma_parser/tests/tsc/importTypeAmbientMissing.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@
196196
"raw": "\"fo\""
197197
},
198198
"qualifier": null,
199-
"typeArguments": null
199+
"typeArguments": null,
200+
"attributes": null
200201
}
201202
}
202203
},

Diff for: crates/swc_ecma_parser/tests/tsc/importTypeAmdBundleRewrite.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@
140140
"value": "Foo",
141141
"optional": false
142142
},
143-
"typeArguments": null
143+
"typeArguments": null,
144+
"attributes": null
144145
}
145146
}
146147
},
@@ -268,7 +269,8 @@
268269
"raw": "\"./a/inner\""
269270
},
270271
"qualifier": null,
271-
"typeArguments": null
272+
"typeArguments": null,
273+
"attributes": null
272274
},
273275
"typeArguments": null
274276
},

Diff for: crates/swc_ecma_parser/tests/tsc/importTypeGenericTypes.json

+6-3
Original file line numberDiff line numberDiff line change
@@ -1020,7 +1020,8 @@
10201020
]
10211021
}
10221022
]
1023-
}
1023+
},
1024+
"attributes": null
10241025
}
10251026
}
10261027
},
@@ -1247,7 +1248,8 @@
12471248
]
12481249
}
12491250
]
1250-
}
1251+
},
1252+
"attributes": null
12511253
}
12521254
}
12531255
},
@@ -1721,7 +1723,8 @@
17211723
"raw": "\"./foo2\""
17221724
},
17231725
"qualifier": null,
1724-
"typeArguments": null
1726+
"typeArguments": null,
1727+
"attributes": null
17251728
},
17261729
"typeArguments": null
17271730
}

Diff for: crates/swc_ecma_parser/tests/tsc/importTypeLocal.json

+6-3
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,8 @@
661661
"raw": "\"./foo\""
662662
},
663663
"qualifier": null,
664-
"typeArguments": null
664+
"typeArguments": null,
665+
"attributes": null
665666
}
666667
}
667668
},
@@ -796,7 +797,8 @@
796797
"value": "I"
797798
}
798799
},
799-
"typeArguments": null
800+
"typeArguments": null,
801+
"attributes": null
800802
}
801803
}
802804
},
@@ -1155,7 +1157,8 @@
11551157
"raw": "\"./foo2\""
11561158
},
11571159
"qualifier": null,
1158-
"typeArguments": null
1160+
"typeArguments": null,
1161+
"attributes": null
11591162
},
11601163
"typeArguments": null
11611164
}

0 commit comments

Comments
 (0)