@@ -64,6 +64,27 @@ void Parser::parse_and_visit_typescript_type_expression(
6464 this ->skip ();
6565 }
6666
67+ auto maybe_parse_dots_after_generic_arguments = [this ]() -> void {
68+ while (this ->peek ().type == Token_Type::dot) {
69+ Source_Code_Span dot_span = this ->peek ().span ();
70+ this ->skip ();
71+ switch (this ->peek ().type ) {
72+ QLJS_CASE_KEYWORD:
73+ case Token_Type::identifier:
74+ this ->diag_reporter_ ->report (
75+ Diag_Dot_Not_Allowed_After_Generic_Arguments_In_Type{
76+ .dot = dot_span,
77+ .property_name = this ->peek ().span (),
78+ });
79+ this ->skip ();
80+ break ;
81+ default :
82+ QLJS_PARSER_UNIMPLEMENTED ();
83+ break ;
84+ }
85+ }
86+ };
87+
6788again:
6889 std::optional<Source_Code_Span> readonly_keyword;
6990 if (this ->peek ().type == Token_Type::kw_readonly) {
@@ -439,31 +460,51 @@ void Parser::parse_and_visit_typescript_type_expression(
439460 if (this ->peek ().type == Token_Type::less) {
440461 this ->parse_and_visit_typescript_generic_arguments (v);
441462 }
463+ maybe_parse_dots_after_generic_arguments ();
464+ break ;
465+
466+ // keyof Type
467+ case Token_Type::kw_keyof:
468+ this ->skip ();
469+ this ->parse_and_visit_typescript_type_expression (v, parse_options);
470+ break ;
471+
472+ // import("module").Name
473+ case Token_Type::kw_import: {
474+ Source_Code_Span import_keyword_span = this ->peek ().span ();
475+ this ->skip ();
476+ QLJS_PARSER_UNIMPLEMENTED_IF_NOT_TOKEN (Token_Type::left_paren);
477+ this ->skip ();
478+ QLJS_PARSER_UNIMPLEMENTED_IF_NOT_TOKEN (Token_Type::string);
479+ this ->skip ();
480+ QLJS_PARSER_UNIMPLEMENTED_IF_NOT_TOKEN (Token_Type::right_paren);
481+ const Char8 *right_paren_end = this ->peek ().end ;
482+ this ->skip ();
483+ if (this ->peek ().type != Token_Type::dot) {
484+ this ->diag_reporter_ ->report (
485+ Diag_TypeScript_Import_Type_Missing_Export_Name{
486+ .expected_export_name = Source_Code_Span::unit (right_paren_end),
487+ .import_keyword = import_keyword_span,
488+ });
489+ }
442490 while (this ->peek ().type == Token_Type::dot) {
443- Source_Code_Span dot_span = this ->peek ().span ();
444491 this ->skip ();
445492 switch (this ->peek ().type ) {
446493 QLJS_CASE_KEYWORD:
447494 case Token_Type::identifier:
448- this ->diag_reporter_ ->report (
449- Diag_Dot_Not_Allowed_After_Generic_Arguments_In_Type{
450- .dot = dot_span,
451- .property_name = this ->peek ().span (),
452- });
453495 this ->skip ();
454496 break ;
455497 default :
456498 QLJS_PARSER_UNIMPLEMENTED ();
457499 break ;
458500 }
459501 }
502+ if (this ->peek ().type == Token_Type::less) {
503+ this ->parse_and_visit_typescript_generic_arguments (v);
504+ }
505+ maybe_parse_dots_after_generic_arguments ();
460506 break ;
461-
462- // keyof Type
463- case Token_Type::kw_keyof:
464- this ->skip ();
465- this ->parse_and_visit_typescript_type_expression (v, parse_options);
466- break ;
507+ }
467508
468509 case Token_Type::comma:
469510 case Token_Type::end_of_file:
0 commit comments