Skip to content

Commit d94bf5f

Browse files
committed
refactor(test): require '{' and '}' to be escaped in assertions
I want to allow diagnostic assertions to contain multiple string members. For example: u8"Diag_Foo{.bar=asdf}{.baz=qwer}"_diag This isn't possible right now because we parse .bar's value as "asdf}{.baz=qwer". Change parsing to parse only until the first '}'. Allow '}' inside the value by requiring it to be escaped. For consistency, also require '{' to be escaped.
1 parent 7b96e74 commit d94bf5f

File tree

3 files changed

+42
-15
lines changed

3 files changed

+42
-15
lines changed

test/quick-lint-js/diagnostic-assertion.cpp

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ namespace quick_lint_js {
2828
static_assert(std::is_trivially_destructible_v<Diagnostic_Assertion>);
2929

3030
namespace {
31+
Monotonic_Allocator* diagnostic_assertion_allocator() {
32+
static Monotonic_Allocator allocator{"diagnostic_assertion_allocator"};
33+
return &allocator;
34+
}
35+
3136
#define QLJS_DIAG_TYPE_NAME(name) \
3237
{QLJS_CPP_QUOTE_U8_SV(name), ::quick_lint_js::Diag_Type::name},
3338
Hash_Map<String8_View, Diag_Type> diag_type_name_to_diag_type =
@@ -131,17 +136,34 @@ Diagnostic_Assertion::parse(const Char8* specification) {
131136
return make_string_view(begin, end);
132137
}
133138

134-
String8_View parse_to_closing_curly_at_end_of_line() {
135-
const Char8* begin = p;
136-
for (; *p != u8'\0'; ++p) {
137-
}
138-
if (p == begin || p[-1] != u8'}') {
139-
errors.push_back("expected closing '}'");
140-
return String8_View();
139+
String8_View parse_extra_member_value() {
140+
Vector<Char8> string("parse_extra_member_value",
141+
diagnostic_assertion_allocator());
142+
for (;;) {
143+
if (p[0] == u8'{') {
144+
if (p[1] == u8'{') {
145+
string += u8'{';
146+
p += 2; // Skip '{{'.
147+
} else {
148+
errors.push_back("'{' must be escaped with '{'");
149+
p += 1; // Skip '{'.
150+
}
151+
} else if (p[0] == u8'}') {
152+
if (p[1] == u8'}') {
153+
string += u8'}';
154+
p += 2; // Skip '}}'.
155+
} else {
156+
// Found the terminating '}'.
157+
return string.release_to_string_view();
158+
}
159+
} else if (p[0] == u8'\0') {
160+
errors.push_back("expected closing '}'");
161+
return String8_View();
162+
} else {
163+
string += p[0];
164+
p += 1;
165+
}
141166
}
142-
const Char8* end = p - 1;
143-
QLJS_ASSERT(*p == u8'\0');
144-
return make_string_view(begin, end);
145167
}
146168

147169
const Char8* p;
@@ -225,7 +247,12 @@ Diagnostic_Assertion::parse(const Char8* specification) {
225247
}
226248
++lexer.p;
227249

228-
extra_member_value_span = lexer.parse_to_closing_curly_at_end_of_line();
250+
extra_member_value_span = lexer.parse_extra_member_value();
251+
if (*lexer.p == u8'}') {
252+
++lexer.p;
253+
} else {
254+
// parse_extra_member_value reported an error already.
255+
}
229256
}
230257

231258
if (*lexer.p != u8'\0') {

test/test-diagnostic-assertion.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ TEST(Test_Diagnostic_Assertion, diag_type_with_string8_view_member_explicit) {
337337
{
338338
Diagnostic_Assertion da = parse_or_fail(
339339
u8"^ Diag_Integer_Literal_Will_Lose_Precision.characters"
340-
u8"{.rounded_val=hello{world}smiley}");
340+
u8"{.rounded_val=hello{{world}}smiley}");
341341
ASSERT_EQ(da.members.size(), 2);
342342
EXPECT_EQ(da.members[1].string, u8"hello{world}smiley"_sv);
343343
}

test/test-parse-jsx.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,19 +365,19 @@ TEST_F(Test_Parse_JSX,
365365
test_parse_and_visit_module(
366366
u8"c = <d\\u{69}v></x>;"_sv, //
367367
u8" ^ Diag_Mismatched_JSX_Tags.closing_tag_name"_diag
368-
u8"{.opening_tag_name_pretty=d\\u{69}v}"_diag, //
368+
u8"{.opening_tag_name_pretty=d\\u{{69}}v}"_diag, //
369369
jsx_options);
370370

371371
test_parse_and_visit_module(
372372
u8"c = <s\\u{76}g:p\\u{69}th></x>;"_sv, //
373373
u8" ^ Diag_Mismatched_JSX_Tags.closing_tag_name"_diag
374-
u8"{.opening_tag_name_pretty=s\\u{76}g:p\\u{69}th}"_diag, //
374+
u8"{.opening_tag_name_pretty=s\\u{{76}}g:p\\u{{69}}th}"_diag, //
375375
jsx_options);
376376

377377
test_parse_and_visit_module(
378378
u8"c = <m\\u{79}.Com\\u{70}onent></x>;"_sv, //
379379
u8" ^ Diag_Mismatched_JSX_Tags.closing_tag_name"_diag
380-
u8"{.opening_tag_name_pretty=m\\u{79}.Com\\u{70}onent}"_diag, //
380+
u8"{.opening_tag_name_pretty=m\\u{{79}}.Com\\u{{70}}onent}"_diag, //
381381
jsx_options);
382382
}
383383

0 commit comments

Comments
 (0)