Skip to content

Commit

Permalink
feat(fe): parse decorators on class members
Browse files Browse the repository at this point in the history
  • Loading branch information
strager committed Sep 23, 2023
1 parent 8087a6c commit e36a5be
Show file tree
Hide file tree
Showing 10 changed files with 740 additions and 13 deletions.
48 changes: 48 additions & 0 deletions po/messages.pot
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,42 @@ msgstr ""
msgid "TypeScript 'declare {1}' is not allowed in JavaScript"
msgstr ""

#: src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
msgid "decorators must appear before '{1}"
msgstr ""

#: src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
msgid "write the decorator before here"
msgstr ""

#: src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
msgid "static blocks cannot have a decorator"
msgstr ""

#: src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
msgid "static block starts here"
msgstr ""

#: src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
msgid "decorators are not allowed inside TypeScript interfaces"
msgstr ""

#: src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
msgid "decorators are not allowed on abstract properties"
msgstr ""

#: src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
msgid "property declared 'abstract' here"
msgstr ""

#: src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
msgid "decorators must appear after overload signatures"
msgstr ""

#: src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
msgid "decorator belongs immediately before this overloaded method"
msgstr ""

#: src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
msgid "'function async' is not allowed; write 'async function' instead"
msgstr ""
Expand Down Expand Up @@ -941,6 +977,14 @@ msgstr ""
msgid "unexpected expression; missing key for object entry"
msgstr ""

#: src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
msgid "missing class method or field after decorator"
msgstr ""

#: src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
msgid "decorator starts here"
msgstr ""

#: src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
msgid "missing name for class method"
msgstr ""
Expand Down Expand Up @@ -1733,6 +1777,10 @@ msgstr ""
msgid "unexpected '?' when destructuring"
msgstr ""

#: src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
msgid "semicolon is not allowed after decorators"
msgstr ""

#: src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
msgid "TypeScript overload signature can only have one semicolon"
msgstr ""
Expand Down
123 changes: 123 additions & 0 deletions src/quick-lint-js/diag/diagnostic-metadata-generated.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,93 @@ const QLJS_CONSTINIT Diagnostic_Info all_diagnostic_infos[] = {
},
},

// Diag_Decorator_After_Class_Member_Modifiers
{
.code = 408,
.severity = Diagnostic_Severity::error,
.message_formats = {
QLJS_TRANSLATABLE("decorators must appear before '{1}"),
QLJS_TRANSLATABLE("write the decorator before here"),
},
.message_args = {
{
Diagnostic_Message_Arg_Info(offsetof(Diag_Decorator_After_Class_Member_Modifiers, decorator_at), Diagnostic_Arg_Type::source_code_span),
Diagnostic_Message_Arg_Info(offsetof(Diag_Decorator_After_Class_Member_Modifiers, modifier), Diagnostic_Arg_Type::source_code_span),
},
{
Diagnostic_Message_Arg_Info(offsetof(Diag_Decorator_After_Class_Member_Modifiers, modifier), Diagnostic_Arg_Type::source_code_span),
},
},
},

// Diag_Decorator_Not_Allowed_On_Class_Static_Block
{
.code = 407,
.severity = Diagnostic_Severity::error,
.message_formats = {
QLJS_TRANSLATABLE("static blocks cannot have a decorator"),
QLJS_TRANSLATABLE("static block starts here"),
},
.message_args = {
{
Diagnostic_Message_Arg_Info(offsetof(Diag_Decorator_Not_Allowed_On_Class_Static_Block, decorator_at), Diagnostic_Arg_Type::source_code_span),
},
{
Diagnostic_Message_Arg_Info(offsetof(Diag_Decorator_Not_Allowed_On_Class_Static_Block, static_keyword), Diagnostic_Arg_Type::source_code_span),
},
},
},

// Diag_Decorator_In_TypeScript_Interface
{
.code = 411,
.severity = Diagnostic_Severity::error,
.message_formats = {
QLJS_TRANSLATABLE("decorators are not allowed inside TypeScript interfaces"),
},
.message_args = {
{
Diagnostic_Message_Arg_Info(offsetof(Diag_Decorator_In_TypeScript_Interface, decorator_at), Diagnostic_Arg_Type::source_code_span),
},
},
},

// Diag_Decorator_On_Abstract_Class_Member
{
.code = 412,
.severity = Diagnostic_Severity::error,
.message_formats = {
QLJS_TRANSLATABLE("decorators are not allowed on abstract properties"),
QLJS_TRANSLATABLE("property declared 'abstract' here"),
},
.message_args = {
{
Diagnostic_Message_Arg_Info(offsetof(Diag_Decorator_On_Abstract_Class_Member, decorator_at), Diagnostic_Arg_Type::source_code_span),
},
{
Diagnostic_Message_Arg_Info(offsetof(Diag_Decorator_On_Abstract_Class_Member, abstract_keyword), Diagnostic_Arg_Type::source_code_span),
},
},
},

// Diag_Decorator_On_Overload_Signature
{
.code = 413,
.severity = Diagnostic_Severity::error,
.message_formats = {
QLJS_TRANSLATABLE("decorators must appear after overload signatures"),
QLJS_TRANSLATABLE("decorator belongs immediately before this overloaded method"),
},
.message_args = {
{
Diagnostic_Message_Arg_Info(offsetof(Diag_Decorator_On_Overload_Signature, decorator_at), Diagnostic_Arg_Type::source_code_span),
},
{
Diagnostic_Message_Arg_Info(offsetof(Diag_Decorator_On_Overload_Signature, expected_location), Diagnostic_Arg_Type::source_code_span),
},
},
},

// Diag_Function_Async_Function
{
.code = 327,
Expand Down Expand Up @@ -2767,6 +2854,24 @@ const QLJS_CONSTINIT Diagnostic_Info all_diagnostic_infos[] = {
},
},

// Diag_Missing_Class_Member_After_Decorator
{
.code = 409,
.severity = Diagnostic_Severity::error,
.message_formats = {
QLJS_TRANSLATABLE("missing class method or field after decorator"),
QLJS_TRANSLATABLE("decorator starts here"),
},
.message_args = {
{
Diagnostic_Message_Arg_Info(offsetof(Diag_Missing_Class_Member_After_Decorator, expected_member), Diagnostic_Arg_Type::source_code_span),
},
{
Diagnostic_Message_Arg_Info(offsetof(Diag_Missing_Class_Member_After_Decorator, decorator_at), Diagnostic_Arg_Type::source_code_span),
},
},
},

// Diag_Missing_Class_Method_Name
{
.code = 229,
Expand Down Expand Up @@ -5255,6 +5360,24 @@ const QLJS_CONSTINIT Diagnostic_Info all_diagnostic_infos[] = {
},
},

// Diag_Unexpected_Semicolon_After_Decorator
{
.code = 410,
.severity = Diagnostic_Severity::error,
.message_formats = {
QLJS_TRANSLATABLE("semicolon is not allowed after decorators"),
QLJS_TRANSLATABLE("decorator starts here"),
},
.message_args = {
{
Diagnostic_Message_Arg_Info(offsetof(Diag_Unexpected_Semicolon_After_Decorator, semicolon), Diagnostic_Arg_Type::source_code_span),
},
{
Diagnostic_Message_Arg_Info(offsetof(Diag_Unexpected_Semicolon_After_Decorator, decorator_at), Diagnostic_Arg_Type::source_code_span),
},
},
},

// Diag_Unexpected_Semicolon_After_Overload_Signature
{
.code = 400,
Expand Down
9 changes: 8 additions & 1 deletion src/quick-lint-js/diag/diagnostic-metadata-generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ namespace quick_lint_js {
QLJS_DIAG_TYPE_NAME(Diag_Declare_Namespace_Cannot_Import_Module) \
QLJS_DIAG_TYPE_NAME(Diag_Declare_Var_Cannot_Have_Initializer) \
QLJS_DIAG_TYPE_NAME(Diag_Declare_Var_Not_Allowed_In_JavaScript) \
QLJS_DIAG_TYPE_NAME(Diag_Decorator_After_Class_Member_Modifiers) \
QLJS_DIAG_TYPE_NAME(Diag_Decorator_Not_Allowed_On_Class_Static_Block) \
QLJS_DIAG_TYPE_NAME(Diag_Decorator_In_TypeScript_Interface) \
QLJS_DIAG_TYPE_NAME(Diag_Decorator_On_Abstract_Class_Member) \
QLJS_DIAG_TYPE_NAME(Diag_Decorator_On_Overload_Signature) \
QLJS_DIAG_TYPE_NAME(Diag_Function_Async_Function) \
QLJS_DIAG_TYPE_NAME(Diag_Big_Int_Literal_Contains_Decimal_Point) \
QLJS_DIAG_TYPE_NAME(Diag_Big_Int_Literal_Contains_Exponent) \
Expand Down Expand Up @@ -196,6 +201,7 @@ namespace quick_lint_js {
QLJS_DIAG_TYPE_NAME(Diag_Missing_Header_Of_For_Loop) \
QLJS_DIAG_TYPE_NAME(Diag_Missing_Initializer_In_Const_Declaration) \
QLJS_DIAG_TYPE_NAME(Diag_Missing_Key_For_Object_Entry) \
QLJS_DIAG_TYPE_NAME(Diag_Missing_Class_Member_After_Decorator) \
QLJS_DIAG_TYPE_NAME(Diag_Missing_Class_Method_Name) \
QLJS_DIAG_TYPE_NAME(Diag_Missing_Name_In_Function_Statement) \
QLJS_DIAG_TYPE_NAME(Diag_Missing_Name_In_Class_Statement) \
Expand Down Expand Up @@ -362,6 +368,7 @@ namespace quick_lint_js {
QLJS_DIAG_TYPE_NAME(Diag_Unexpected_Right_Curly_In_JSX_Text) \
QLJS_DIAG_TYPE_NAME(Diag_Unexpected_Question_In_Expression) \
QLJS_DIAG_TYPE_NAME(Diag_Unexpected_Question_When_Destructuring) \
QLJS_DIAG_TYPE_NAME(Diag_Unexpected_Semicolon_After_Decorator) \
QLJS_DIAG_TYPE_NAME(Diag_Unexpected_Semicolon_After_Overload_Signature) \
QLJS_DIAG_TYPE_NAME(Diag_Unexpected_Semicolon_In_C_Style_For_Loop) \
QLJS_DIAG_TYPE_NAME(Diag_Unexpected_Semicolon_In_For_In_Loop) \
Expand Down Expand Up @@ -424,7 +431,7 @@ namespace quick_lint_js {
/* END */
// clang-format on

inline constexpr int Diag_Type_Count = 410;
inline constexpr int Diag_Type_Count = 417;

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

struct Diag_Decorator_After_Class_Member_Modifiers {
[[qljs::diag("E0408", Diagnostic_Severity::error)]] //
[[qljs::message("decorators must appear before '{1}", ARG(decorator_at),
ARG(modifier))]] //
[[qljs::message("write the decorator before here", ARG(modifier))]] //
Source_Code_Span decorator_at;
Source_Code_Span modifier;
};

struct Diag_Decorator_Not_Allowed_On_Class_Static_Block {
[[qljs::diag("E0407", Diagnostic_Severity::error)]] //
[[qljs::message("static blocks cannot have a decorator",
ARG(decorator_at))]] //
[[qljs::message("static block starts here",
ARG(static_keyword))]] //
Source_Code_Span decorator_at;
Source_Code_Span static_keyword;
};

struct Diag_Decorator_In_TypeScript_Interface {
[[qljs::diag("E0411", Diagnostic_Severity::error)]] //
[[qljs::message("decorators are not allowed inside TypeScript interfaces",
ARG(decorator_at))]] //
Source_Code_Span decorator_at;
};

struct Diag_Decorator_On_Abstract_Class_Member {
[[qljs::diag("E0412", Diagnostic_Severity::error)]] //
[[qljs::message("decorators are not allowed on abstract properties",
ARG(decorator_at))]] //
[[qljs::message("property declared 'abstract' here",
ARG(abstract_keyword))]] //
Source_Code_Span decorator_at;
Source_Code_Span abstract_keyword;
};

struct Diag_Decorator_On_Overload_Signature {
[[qljs::diag("E0413", Diagnostic_Severity::error)]] //
[[qljs::message("decorators must appear after overload signatures",
ARG(decorator_at))]] //
[[qljs::message("decorator belongs immediately before this overloaded method",
ARG(expected_location))]] //
Source_Code_Span decorator_at;
Source_Code_Span expected_location;
};

struct Diag_Function_Async_Function {
[[qljs::diag("E0327", Diagnostic_Severity::error)]] //
[[qljs::message(
Expand Down Expand Up @@ -1421,6 +1467,15 @@ struct Diag_Missing_Key_For_Object_Entry {
Source_Code_Span expression;
};

struct Diag_Missing_Class_Member_After_Decorator {
[[qljs::diag("E0409", Diagnostic_Severity::error)]] //
[[qljs::message("missing class method or field after decorator",
ARG(expected_member))]] //
[[qljs::message("decorator starts here", ARG(decorator_at))]] //
Source_Code_Span expected_member;
Source_Code_Span decorator_at;
};

struct Diag_Missing_Class_Method_Name {
[[qljs::diag("E0229", Diagnostic_Severity::error)]] //
[[qljs::message("missing name for class method", ARG(expected_name))]] //
Expand Down Expand Up @@ -2711,6 +2766,16 @@ struct Diag_Unexpected_Question_When_Destructuring {
Source_Code_Span question;
};

struct Diag_Unexpected_Semicolon_After_Decorator {
[[qljs::diag("E0410", Diagnostic_Severity::error)]] //
[[qljs::message("semicolon is not allowed after decorators",
ARG(semicolon))]] //
[[qljs::message("decorator starts here",
ARG(decorator_at))]] //
Source_Code_Span semicolon;
Source_Code_Span decorator_at;
};

struct Diag_Unexpected_Semicolon_After_Overload_Signature {
[[qljs::diag("E0400", Diagnostic_Severity::error)]] //
[[qljs::message("TypeScript overload signature can only have one semicolon",
Expand Down
Loading

0 comments on commit e36a5be

Please sign in to comment.