Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: TsImportType - support import attributes #9796

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion crates/swc_ecma_ast/src/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use swc_common::{ast_node, EqIgnoreSpan, Span};

use crate::{
class::Decorator,
expr::Expr,
expr::{Expr, ObjectLit},
ident::Ident,
lit::{Bool, Number, Str},
module::ModuleItem,
Expand Down Expand Up @@ -546,6 +546,8 @@ pub struct TsImportType {
pub qualifier: Option<TsEntityName>,
#[cfg_attr(feature = "serde-impl", serde(rename = "typeArguments"))]
pub type_args: Option<Box<TsTypeParamInstantiation>>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub with: Option<Box<ObjectLit>>,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure about this name because this is the full { with: { "module-resolution": "import" } } (which I need for dprint-plugin-typescript). Maybe something else would be better here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll wait to update the failing tests until getting feedback on this.

Copy link
Member

Choose a reason for hiding this comment

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

So annotation? I think we may need to use separate type for this kind of annotations. How do you think? cc @swc-project/core-es

Copy link
Member

Choose a reason for hiding this comment

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

Is with hardcoded?
I hope there is no situation like { with: { "foo": "bar" }, other: "value" }.

Copy link
Member

@CPunisher CPunisher Dec 14, 2024

Choose a reason for hiding this comment

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

From https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html

The expected type of that second argument is defined by a type called ImportCallOptions, which by default just expects a property called with.

And typescript playground throws Object literal may only specify known properties, and 'xxx' does not exist in type 'ImportCallOptions'.

So I think some names related to ImportCallOptions or just attributes are ok as well.

Copy link
Member

@kdy1 kdy1 Dec 14, 2024

Choose a reason for hiding this comment

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

I think we need a breaking change anyway if there's a situation like { with: { "foo": "bar" }, other: "value" }, and I like the idea of

ImportCallOptions or just attributes

}

#[ast_node("TsTypeLiteral")]
Expand Down
5 changes: 5 additions & 0 deletions crates/swc_ecma_codegen/src/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,11 @@ where
keyword!("import");
punct!("(");
emit!(n.arg);
if let Some(with) = &n.with {
punct!(",");
formatting_space!();
emit!(with);
}
punct!(")");

if let Some(n) = &n.qualifier {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
type Vite = typeof import("vite", { with: { "resolution-mode": "import" } });
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type Vite = typeof import("vite", {
with: {
"resolution-mode": "import"
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
type Vite=typeof import("vite",{with:{"resolution-mode":"import"}});
12 changes: 12 additions & 0 deletions crates/swc_ecma_parser/src/parser/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,17 @@ impl<I: Tokens> Parser<I> {
}
};

// the "assert" keyword is deprecated and this syntax is niche, so
// don't support it
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think we should support the "assert" keyword for these reasons.

let with = if eat!(self, ',') && self.input.syntax().import_attributes() && is!(self, '{') {
match *self.parse_object::<Box<Expr>>()? {
Expr::Object(v) => Some(Box::new(v)),
_ => unreachable!(),
}
} else {
None
};

expect!(self, ')');

let qualifier = if eat!(self, '.') {
Expand All @@ -335,6 +346,7 @@ impl<I: Tokens> Parser<I> {
arg,
qualifier,
type_args,
with,
})
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
type Vite = typeof import("vite", {
with: {
"resolution-mode": "import"
}
});
type Vite2 = typeof import("vite",);
type Vite3 = typeof import("vite");
197 changes: 197 additions & 0 deletions crates/swc_ecma_parser/tests/typescript/ts-import-type/input.ts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
{
"type": "Script",
"span": {
"start": 1,
"end": 161
},
"body": [
{
"type": "TsTypeAliasDeclaration",
"span": {
"start": 1,
"end": 88
},
"declare": false,
"id": {
"type": "Identifier",
"span": {
"start": 6,
"end": 10
},
"ctxt": 0,
"value": "Vite",
"optional": false
},
"typeParams": null,
"typeAnnotation": {
"type": "TsTypeQuery",
"span": {
"start": 13,
"end": 87
},
"exprName": {
"type": "TsImportType",
"span": {
"start": 20,
"end": 87
},
"argument": {
"type": "StringLiteral",
"span": {
"start": 27,
"end": 33
},
"value": "vite",
"raw": "\"vite\""
},
"qualifier": null,
"typeArguments": null,
"with": {
"type": "ObjectExpression",
"span": {
"start": 35,
"end": 86
},
"properties": [
{
"type": "KeyValueProperty",
"key": {
"type": "Identifier",
"span": {
"start": 39,
"end": 43
},
"value": "with"
},
"value": {
"type": "ObjectExpression",
"span": {
"start": 45,
"end": 84
},
"properties": [
{
"type": "KeyValueProperty",
"key": {
"type": "StringLiteral",
"span": {
"start": 53,
"end": 70
},
"value": "resolution-mode",
"raw": "\"resolution-mode\""
},
"value": {
"type": "StringLiteral",
"span": {
"start": 72,
"end": 80
},
"value": "import",
"raw": "\"import\""
}
}
]
}
}
]
}
},
"typeArguments": null
}
},
{
"type": "TsTypeAliasDeclaration",
"span": {
"start": 89,
"end": 125
},
"declare": false,
"id": {
"type": "Identifier",
"span": {
"start": 94,
"end": 99
},
"ctxt": 0,
"value": "Vite2",
"optional": false
},
"typeParams": null,
"typeAnnotation": {
"type": "TsTypeQuery",
"span": {
"start": 102,
"end": 124
},
"exprName": {
"type": "TsImportType",
"span": {
"start": 109,
"end": 124
},
"argument": {
"type": "StringLiteral",
"span": {
"start": 116,
"end": 122
},
"value": "vite",
"raw": "\"vite\""
},
"qualifier": null,
"typeArguments": null,
"with": null
},
"typeArguments": null
}
},
{
"type": "TsTypeAliasDeclaration",
"span": {
"start": 126,
"end": 161
},
"declare": false,
"id": {
"type": "Identifier",
"span": {
"start": 131,
"end": 136
},
"ctxt": 0,
"value": "Vite3",
"optional": false
},
"typeParams": null,
"typeAnnotation": {
"type": "TsTypeQuery",
"span": {
"start": 139,
"end": 160
},
"exprName": {
"type": "TsImportType",
"span": {
"start": 146,
"end": 160
},
"argument": {
"type": "StringLiteral",
"span": {
"start": 153,
"end": 159
},
"value": "vite",
"raw": "\"vite\""
},
"qualifier": null,
"typeArguments": null,
"with": null
},
"typeArguments": null
}
}
],
"interpreter": null
}
Loading
Loading