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(typescript): disallow newline after modifiers in generic parameter #1121

Closed
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: 4 additions & 0 deletions po/messages.pot
Original file line number Diff line number Diff line change
Expand Up @@ -1221,6 +1221,10 @@ msgstr ""
msgid "newline is not allowed before '<'"
msgstr ""

#: src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
msgid "newline is not allowed after '{0}' modifier in generic parameter"
msgstr ""

#: src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
msgid "number literal contains consecutive underscores"
msgstr ""
Expand Down
14 changes: 14 additions & 0 deletions src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3509,6 +3509,20 @@ const QLJS_CONSTINIT Diagnostic_Info all_diagnostic_infos[] = {
},
},

// Diag_Newline_Not_Allowed_After_In_Out_Const_Modifiers
{
.code = 433,
.severity = Diagnostic_Severity::error,
.message_formats = {
QLJS_TRANSLATABLE("newline is not allowed after '{0}' modifier in generic parameter"),
},
.message_args = {
{
Diagnostic_Message_Arg_Info(offsetof(Diag_Newline_Not_Allowed_After_In_Out_Const_Modifiers, modifier), Diagnostic_Arg_Type::source_code_span),
},
},
},

// Diag_Number_Literal_Contains_Consecutive_Underscores
{
.code = 28,
Expand Down
3 changes: 2 additions & 1 deletion src/quick-lint-js/diag/diagnostic-metadata-generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ namespace quick_lint_js {
QLJS_DIAG_TYPE_NAME(Diag_Newline_Not_Allowed_After_Type_Keyword) \
QLJS_DIAG_TYPE_NAME(Diag_Newline_Not_Allowed_Before_Assignment_Assertion_Operator) \
QLJS_DIAG_TYPE_NAME(Diag_Newline_Not_Allowed_Before_Generic_Arguments_In_Type) \
QLJS_DIAG_TYPE_NAME(Diag_Newline_Not_Allowed_After_In_Out_Const_Modifiers) \
QLJS_DIAG_TYPE_NAME(Diag_Number_Literal_Contains_Consecutive_Underscores) \
QLJS_DIAG_TYPE_NAME(Diag_Number_Literal_Contains_Trailing_Underscores) \
QLJS_DIAG_TYPE_NAME(Diag_Octal_Literal_May_Not_Have_Exponent) \
Expand Down Expand Up @@ -454,7 +455,7 @@ namespace quick_lint_js {
/* END */
// clang-format on

inline constexpr int Diag_Type_Count = 440;
inline constexpr int Diag_Type_Count = 441;

extern const Diagnostic_Info all_diagnostic_infos[Diag_Type_Count];
}
Expand Down
8 changes: 8 additions & 0 deletions src/quick-lint-js/diag/diagnostic-types-2.h
Original file line number Diff line number Diff line change
Expand Up @@ -1801,6 +1801,14 @@ struct Diag_Newline_Not_Allowed_Before_Generic_Arguments_In_Type {
Source_Code_Span less;
};

struct Diag_Newline_Not_Allowed_After_In_Out_Const_Modifiers {
[[qljs::diag("E0433", Diagnostic_Severity::error)]] //
[[qljs::message(
"newline is not allowed after '{0}' modifier in generic parameter",
ARG(modifier))]] //
Source_Code_Span modifier;
};

struct Diag_Number_Literal_Contains_Consecutive_Underscores {
[[qljs::diag("E0028", Diagnostic_Severity::error)]] //
[[qljs::message("number literal contains consecutive underscores",
Expand Down
5 changes: 5 additions & 0 deletions src/quick-lint-js/fe/parse-statement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1683,6 +1683,11 @@ void Parser::parse_and_visit_typescript_generic_parameters(
.token_type = this->peek().type,
});
this->skip();
if (this->lexer_.peek().has_leading_newline) {
this->diag_reporter_->report(
Diag_Newline_Not_Allowed_After_In_Out_Const_Modifiers{
.modifier = modifiers.back().identifier.span()});
}
Comment on lines +1686 to +1690
Copy link
Collaborator

Choose a reason for hiding this comment

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

👍

break;

default:
Expand Down
2 changes: 2 additions & 0 deletions src/quick-lint-js/i18n/translation-table-generated.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ const Translation_Table translation_data = {
{0, 0, 0, 52, 0, 41}, //
{0, 0, 0, 0, 0, 36}, //
{0, 0, 0, 0, 0, 35}, //
{0, 0, 0, 0, 0, 65}, //
{0, 0, 0, 47, 0, 34}, //
{52, 31, 25, 61, 21, 54}, //
{0, 0, 0, 0, 0, 73}, //
Expand Down Expand Up @@ -2240,6 +2241,7 @@ const Translation_Table translation_data = {
u8"newline is not allowed after 'interface'\0"
u8"newline is not allowed after 'type'\0"
u8"newline is not allowed after '{0}'\0"
u8"newline is not allowed after '{0}' modifier in generic parameter\0"
u8"newline is not allowed before '<'\0"
u8"newline is not allowed between 'async' and 'function'\0"
u8"newline is not allowed between 'async' and arrow function parameter list\0"
Expand Down
5 changes: 3 additions & 2 deletions src/quick-lint-js/i18n/translation-table-generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ namespace quick_lint_js {
using namespace std::literals::string_view_literals;

constexpr std::uint32_t translation_table_locale_count = 5;
constexpr std::uint16_t translation_table_mapping_table_size = 545;
constexpr std::size_t translation_table_string_table_size = 80903;
constexpr std::uint16_t translation_table_mapping_table_size = 546;
constexpr std::size_t translation_table_string_table_size = 80968;
constexpr std::size_t translation_table_locale_table_size = 35;

QLJS_CONSTEVAL std::uint16_t translation_table_const_look_up(
Expand Down Expand Up @@ -439,6 +439,7 @@ QLJS_CONSTEVAL std::uint16_t translation_table_const_look_up(
"newline is not allowed after 'interface'"sv,
"newline is not allowed after 'type'"sv,
"newline is not allowed after '{0}'"sv,
"newline is not allowed after '{0}' modifier in generic parameter"sv,
"newline is not allowed before '<'"sv,
"newline is not allowed between 'async' and 'function'"sv,
"newline is not allowed between 'async' and arrow function parameter list"sv,
Expand Down
13 changes: 12 additions & 1 deletion src/quick-lint-js/i18n/translation-table-test-generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ struct Translated_String {
};

// clang-format off
inline const Translated_String test_translation_table[544] = {
inline const Translated_String test_translation_table[545] = {
{
"\"global-groups\" entries must be strings"_translatable,
u8"\"global-groups\" entries must be strings",
Expand Down Expand Up @@ -4571,6 +4571,17 @@ inline const Translated_String test_translation_table[544] = {
u8"newline is not allowed after '{0}'",
},
},
{
"newline is not allowed after '{0}' modifier in generic parameter"_translatable,
u8"newline is not allowed after '{0}' modifier in generic parameter",
{
u8"newline is not allowed after '{0}' modifier in generic parameter",
u8"newline is not allowed after '{0}' modifier in generic parameter",
u8"newline is not allowed after '{0}' modifier in generic parameter",
u8"newline is not allowed after '{0}' modifier in generic parameter",
u8"newline is not allowed after '{0}' modifier in generic parameter",
},
},
{
"newline is not allowed before '<'"_translatable,
u8"newline is not allowed before '<'",
Expand Down
27 changes: 27 additions & 0 deletions test/test-parse-typescript-generic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1333,6 +1333,33 @@ TEST_F(Test_Parse_TypeScript_Generic,
typescript_options);
}
}

TEST_F(Test_Parse_TypeScript_Generic,
newline_is_not_allowed_after_in_out_const_modifiers) {
{
test_parse_and_visit_module(
u8"class C<in\nT> {}"_sv, //
u8" ^^ Diag_Newline_Not_Allowed_After_In_Out_Const_Modifiers.modifier"_diag, //
typescript_options);
test_parse_and_visit_module(
u8"class C<out\nT> {}"_sv, //
u8" ^^^ Diag_Newline_Not_Allowed_After_In_Out_Const_Modifiers.modifier"_diag, //
typescript_options);
test_parse_and_visit_module(
u8"class C<const\nT> {}"_sv, //
u8" ^^^^^ Diag_Newline_Not_Allowed_After_In_Out_Const_Modifiers.modifier"_diag, //
typescript_options);
}

{
test_parse_and_visit_module(u8"class C<in T> {}"_sv, no_diags,
typescript_options);
test_parse_and_visit_module(u8"class C<out T> {}"_sv, no_diags,
typescript_options);
test_parse_and_visit_module(u8"class C<const T> {}"_sv, no_diags,
typescript_options);
}
}
}
}

Expand Down
Loading