Skip to content

Commit 59d630b

Browse files
authored
7$: Error with nice message when trying to use TypeScript-style const fields
- Reporting a `typescript_style_const_error` when a const field is used: ``` class C { const f = null; } ``` quick-lint-js reported: ``` hello.js:2:3: error: unexpected token [E054] ``` quick-lint-js now reports: ``` a.js:3:3: error: const fields within classes are only allowed in TypeScript, not Javascript [E165] ``` Fixes #235
1 parent d1bc9f8 commit 59d630b

File tree

4 files changed

+60
-3
lines changed

4 files changed

+60
-3
lines changed

docs/errors/E165.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# E165: TypeScript style const field
2+
3+
`const` fields are only allowed in TypeScript, not JavaScript
4+
5+
class C {
6+
const f = null;
7+
}
8+
9+
To fix this error, remove the `const` declarator from the field
10+
11+
class C {
12+
f = null;
13+
}

src/quick-lint-js/error.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,13 @@
938938
"implemented by quick-lint-js"), \
939939
enum_keyword)) \
940940
\
941+
QLJS_ERROR_TYPE( \
942+
error_typescript_style_const_field, "E165", \
943+
{ source_code_span const_token; }, \
944+
.error(QLJS_TRANSLATABLE("const fields within classes are only " \
945+
"allowed in TypeScript, not JavaScript"), \
946+
const_token)) \
947+
\
941948
QLJS_ERROR_TYPE( \
942949
error_unclosed_block_comment, "E037", \
943950
{ source_code_span comment_open; }, \

src/quick-lint-js/parse.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,9 +1538,18 @@ class parser {
15381538
// }
15391539
v.visit_property_declaration(property_name);
15401540
} else {
1541-
this->error_reporter_->report(error_unexpected_token{
1542-
.token = property_name_span,
1543-
});
1541+
// class C {
1542+
// const field
1543+
// }
1544+
if (u8"const" == property_name_span.string_view()) {
1545+
this->error_reporter_->report(error_typescript_style_const_field{
1546+
.const_token = property_name_span,
1547+
});
1548+
} else {
1549+
this->error_reporter_->report(error_unexpected_token{
1550+
.token = property_name_span,
1551+
});
1552+
}
15441553
}
15451554
break;
15461555

test/test-parse-class.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,34 @@ TEST(test_parse, async_method_prohibits_newline_after_async_keyword) {
11821182
EXPECT_EQ(v.property_declarations[0].name, u8"async");
11831183
}
11841184
}
1185+
TEST(test_parse, typescript_style_const_field) {
1186+
{
1187+
spy_visitor v;
1188+
padded_string code(u8"class C { const f = null }"_sv);
1189+
parser p(&code, &v);
1190+
EXPECT_TRUE(p.parse_and_visit_statement(v));
1191+
EXPECT_THAT(v.property_declarations,
1192+
ElementsAre(spy_visitor::visited_property_declaration{u8"f"}));
1193+
EXPECT_THAT(
1194+
v.errors,
1195+
ElementsAre(ERROR_TYPE_FIELD(
1196+
error_typescript_style_const_field, const_token,
1197+
offsets_matcher(&code, strlen(u8"class C { "), u8"const"))));
1198+
}
1199+
{
1200+
spy_visitor v;
1201+
padded_string code(u8"class C { const f }"_sv);
1202+
parser p(&code, &v);
1203+
EXPECT_TRUE(p.parse_and_visit_statement(v));
1204+
EXPECT_THAT(v.property_declarations,
1205+
ElementsAre(spy_visitor::visited_property_declaration{u8"f"}));
1206+
EXPECT_THAT(
1207+
v.errors,
1208+
ElementsAre(ERROR_TYPE_FIELD(
1209+
error_typescript_style_const_field, const_token,
1210+
offsets_matcher(&code, strlen(u8"class C { "), u8"const"))));
1211+
}
1212+
}
11851213
}
11861214
}
11871215

0 commit comments

Comments
 (0)