fix(rslint_parser): Add type-arguments to `TsImportType`
TypeScript's import type can have type arguments:
```ts
type A = import("./test")<string>;
type B = import("./test").X<string>;
```
This PR adds the type arguments field to the `TsImportType` and changes the parser as well.
MODIFY
crates/rslint_parser/src/ast/generated/nodes.rs
crates/rslint_parser/src/ast/generated/nodes.rs
@@ -3844,6 +3844,7 @@ impl TsImportType {
pub fn qualifier_clause(&self) -> Option<TsImportTypeQualifier> {
support::node(&self.syntax, 5usize)
}
+ pub fn type_arguments(&self) -> Option<TsTypeArguments> { support::node(&self.syntax, 6usize) }
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct TsImportTypeQualifier {
@@ -11154,6 +11155,10 @@ impl std::fmt::Debug for TsImportType {
"qualifier_clause",
&support::DebugOptionalElement(self.qualifier_clause()),
)
+ .field(
+ "type_arguments",
+ &support::DebugOptionalElement(self.type_arguments()),
+ )
.finish()
}
}

MODIFY
crates/rslint_parser/src/ast/generated/syntax_factory.rs
crates/rslint_parser/src/ast/generated/syntax_factory.rs
@@ -6407,7 +6407,7 @@ impl SyntaxFactory for JsSyntaxFactory {
}
TS_IMPORT_TYPE => {
let mut elements = (&children).into_iter();
- let mut slots: RawNodeSlots<6usize> = RawNodeSlots::default();
+ let mut slots: RawNodeSlots<7usize> = RawNodeSlots::default();
let mut current_element = elements.next();
if let Some(element) = &current_element {
if element.kind() == T![typeof] {
@@ -6451,6 +6451,13 @@ impl SyntaxFactory for JsSyntaxFactory {
}
}
slots.next_slot();
+ if let Some(element) = &current_element {
+ if TsTypeArguments::can_cast(element.kind()) {
+ slots.mark_present();
+ current_element = elements.next();
+ }
+ }
+ slots.next_slot();
if current_element.is_some() {
return RawSyntaxNode::new(
TS_IMPORT_TYPE.to_unknown(),

MODIFY
crates/rslint_parser/src/syntax/typescript/types.rs
crates/rslint_parser/src/syntax/typescript/types.rs
@@ -637,6 +637,8 @@ fn parse_ts_mapped_type_optional_modifier_clause(p: &mut Parser) -> ParsedSyntax
// type A = typeof import("test");
// type B = import("test");
// type C = typeof import("test").a.b.c.d.e.f;
+// type D = import("test")<string>;
+// type E = import("test").C<string>;
fn parse_ts_import_type(p: &mut Parser) -> ParsedSyntax {
if !p.at(T![typeof]) && !p.at(T![import]) {
return Absent;
@@ -656,6 +658,8 @@ fn parse_ts_import_type(p: &mut Parser) -> ParsedSyntax {
qualifier.complete(p, TS_IMPORT_TYPE_QUALIFIER);
}
+ parse_ts_type_arguments(p).ok();
+
Present(m.complete(p, TS_IMPORT_TYPE))
}

MODIFY
crates/rslint_parser/test_data/inline/ok/ts_import_type.rast
crates/rslint_parser/test_data/inline/ok/ts_import_type.rast
@@ -16,6 +16,7 @@ JsModule {
argument_token: JS_STRING_LITERAL@23..29 "\"test\"" [] [],
r_paren_token: R_PAREN@29..30 ")" [] [],
qualifier_clause: missing (optional),
+ type_arguments: missing (optional),
},
semicolon_token: SEMICOLON@30..31 ";" [] [],
},
@@ -33,6 +34,7 @@ JsModule {
argument_token: JS_STRING_LITERAL@48..54 "\"test\"" [] [],
r_paren_token: R_PAREN@54..55 ")" [] [],
qualifier_clause: missing (optional),
+ type_arguments: missing (optional),
},
semicolon_token: SEMICOLON@55..56 ";" [] [],
},
@@ -85,17 +87,75 @@ JsModule {
},
},
},
+ type_arguments: missing (optional),
},
semicolon_token: SEMICOLON@99..100 ";" [] [],
},
+ TsTypeAliasDeclaration {
+ type_token: TYPE_KW@100..106 "type" [Newline("\n")] [Whitespace(" ")],
+ binding_identifier: TsIdentifierBinding {
+ name_token: IDENT@106..108 "D" [] [Whitespace(" ")],
+ },
+ type_parameters: missing (optional),
+ eq_token: EQ@108..110 "=" [] [Whitespace(" ")],
+ ty: TsImportType {
+ typeof_token: missing (optional),
+ import_token: IMPORT_KW@110..116 "import" [] [],
+ l_paren_token: L_PAREN@116..117 "(" [] [],
+ argument_token: JS_STRING_LITERAL@117..123 "\"test\"" [] [],
+ r_paren_token: R_PAREN@123..124 ")" [] [],
+ qualifier_clause: missing (optional),
+ type_arguments: TsTypeArguments {
+ l_angle_token: L_ANGLE@124..125 "<" [] [],
+ ts_type_argument_list: TsTypeArgumentList [
+ TsStringType {
+ string_token: STRING_KW@125..131 "string" [] [],
+ },
],
- eof_token: EOF@100..101 "" [Newline("\n")] [],
+ r_angle_token: R_ANGLE@131..132 ">" [] [],
+ },
+ },
+ semicolon_token: SEMICOLON@132..133 ";" [] [],
+ },
+ TsTypeAliasDeclaration {
+ type_token: TYPE_KW@133..139 "type" [Newline("\n")] [Whitespace(" ")],
+ binding_identifier: TsIdentifierBinding {
+ name_token: IDENT@139..141 "E" [] [Whitespace(" ")],
+ },
+ type_parameters: missing (optional),
+ eq_token: EQ@141..143 "=" [] [Whitespace(" ")],
+ ty: TsImportType {
+ typeof_token: missing (optional),
+ import_token: IMPORT_KW@143..149 "import" [] [],
+ l_paren_token: L_PAREN@149..150 "(" [] [],
+ argument_token: JS_STRING_LITERAL@150..156 "\"test\"" [] [],
+ r_paren_token: R_PAREN@156..157 ")" [] [],
+ qualifier_clause: TsImportTypeQualifier {
+ dot_token: DOT@157..158 "." [] [],
+ right: JsReferenceIdentifier {
+ value_token: IDENT@158..159 "C" [] [],
+ },
+ },
+ type_arguments: TsTypeArguments {
+ l_angle_token: L_ANGLE@159..160 "<" [] [],
+ ts_type_argument_list: TsTypeArgumentList [
+ TsStringType {
+ string_token: STRING_KW@160..166 "string" [] [],
+ },
+ ],
+ r_angle_token: R_ANGLE@166..167 ">" [] [],
+ },
+ },
+ semicolon_token: SEMICOLON@167..168 ";" [] [],
+ },
+ ],
+ eof_token: EOF@168..169 "" [Newline("\n")] [],
}
-0: JS_MODULE@0..101
+0: JS_MODULE@0..169
0: (empty)
1: JS_DIRECTIVE_LIST@0..0
- 2: JS_MODULE_ITEM_LIST@0..100
+ 2: JS_MODULE_ITEM_LIST@0..168
0: TS_TYPE_ALIAS_DECLARATION@0..31
0: TYPE_KW@0..5 "type" [] [Whitespace(" ")]
1: TS_IDENTIFIER_BINDING@5..7
@@ -109,6 +169,7 @@ JsModule {
3: JS_STRING_LITERAL@23..29 "\"test\"" [] []
4: R_PAREN@29..30 ")" [] []
5: (empty)
+ 6: (empty)
5: SEMICOLON@30..31 ";" [] []
1: TS_TYPE_ALIAS_DECLARATION@31..56
0: TYPE_KW@31..37 "type" [Newline("\n")] [Whitespace(" ")]
@@ -123,6 +184,7 @@ JsModule {
3: JS_STRING_LITERAL@48..54 "\"test\"" [] []
4: R_PAREN@54..55 ")" [] []
5: (empty)
+ 6: (empty)
5: SEMICOLON@55..56 ";" [] []
2: TS_TYPE_ALIAS_DECLARATION@56..100
0: TYPE_KW@56..62 "type" [Newline("\n")] [Whitespace(" ")]
@@ -160,5 +222,49 @@ JsModule {
1: DOT@97..98 "." [] []
2: JS_NAME@98..99
0: IDENT@98..99 "f" [] []
+ 6: (empty)
5: SEMICOLON@99..100 ";" [] []
- 3: EOF@100..101 "" [Newline("\n")] []
+ 3: TS_TYPE_ALIAS_DECLARATION@100..133
+ 0: TYPE_KW@100..106 "type" [Newline("\n")] [Whitespace(" ")]
+ 1: TS_IDENTIFIER_BINDING@106..108
+ 0: IDENT@106..108 "D" [] [Whitespace(" ")]
+ 2: (empty)
+ 3: EQ@108..110 "=" [] [Whitespace(" ")]
+ 4: TS_IMPORT_TYPE@110..132
+ 0: (empty)
+ 1: IMPORT_KW@110..116 "import" [] []
+ 2: L_PAREN@116..117 "(" [] []
+ 3: JS_STRING_LITERAL@117..123 "\"test\"" [] []
+ 4: R_PAREN@123..124 ")" [] []
+ 5: (empty)
+ 6: TS_TYPE_ARGUMENTS@124..132
+ 0: L_ANGLE@124..125 "<" [] []
+ 1: TS_TYPE_ARGUMENT_LIST@125..131
+ 0: TS_STRING_TYPE@125..131
+ 0: STRING_KW@125..131 "string" [] []
+ 2: R_ANGLE@131..132 ">" [] []
+ 5: SEMICOLON@132..133 ";" [] []
+ 4: TS_TYPE_ALIAS_DECLARATION@133..168
+ 0: TYPE_KW@133..139 "type" [Newline("\n")] [Whitespace(" ")]
+ 1: TS_IDENTIFIER_BINDING@139..141
+ 0: IDENT@139..141 "E" [] [Whitespace(" ")]
+ 2: (empty)
+ 3: EQ@141..143 "=" [] [Whitespace(" ")]
+ 4: TS_IMPORT_TYPE@143..167
+ 0: (empty)
+ 1: IMPORT_KW@143..149 "import" [] []
+ 2: L_PAREN@149..150 "(" [] []
+ 3: JS_STRING_LITERAL@150..156 "\"test\"" [] []
+ 4: R_PAREN@156..157 ")" [] []
+ 5: TS_IMPORT_TYPE_QUALIFIER@157..159
+ 0: DOT@157..158 "." [] []
+ 1: JS_REFERENCE_IDENTIFIER@158..159
+ 0: IDENT@158..159 "C" [] []
+ 6: TS_TYPE_ARGUMENTS@159..167
+ 0: L_ANGLE@159..160 "<" [] []
+ 1: TS_TYPE_ARGUMENT_LIST@160..166
+ 0: TS_STRING_TYPE@160..166
+ 0: STRING_KW@160..166 "string" [] []
+ 2: R_ANGLE@166..167 ">" [] []
+ 5: SEMICOLON@167..168 ";" [] []
+ 3: EOF@168..169 "" [Newline("\n")] []

MODIFY
crates/rslint_parser/test_data/inline/ok/ts_import_type.ts
crates/rslint_parser/test_data/inline/ok/ts_import_type.ts
type A = typeof import("test");
type B = import("test");
type C = typeof import("test").a.b.c.d.e.f;
+type D = import("test")<string>;
+type E = import("test").C<string>;

MODIFY
xtask/codegen/js.ungram
xtask/codegen/js.ungram
@@ -1880,6 +1880,10 @@ TsMappedTypeReadonlyModifierClause =
operator_token: ('+' | '-')
'readonly'
+// a: import("./test").T<typeof X>
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// a: import("./test")<string>
+// ^^^^^^^^^^^^^^^^^^^^^^^^^
TsImportType =
'typeof'?
'import'
@@ -1887,6 +1891,7 @@ TsImportType =
argument: 'js_string_literal'
')'
qualifier_clause: TsImportTypeQualifier?
+ type_arguments: TsTypeArguments?
TsImportTypeQualifier =
'.'

fix(rslint_parser): Add type-arguments to `TsImportType` (#2132)

TypeScript's import type can have type arguments:

```ts
type A = import("./test")<string>;
type B = import("./test").X<string>;
```

This PR adds the type arguments field to the `TsImportType` and changes the parser as well.