Skip to content

Commit b3a00ae

Browse files
committed
refactor(test): use test_parse_and_analyze for more tests
Tidy up the test code. Add an option to test_parse_and_analyze to allow parse errors. This is needed for a few of the tests.
1 parent 2ad2c57 commit b3a00ae

File tree

4 files changed

+93
-187
lines changed

4 files changed

+93
-187
lines changed

src/quick-lint-js/util/cast.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@ Derived_Reference derived_cast(Base& base) {
7878
"Derived should not be the same type as Base");
7979
return static_cast<Derived_Reference>(base);
8080
}
81+
82+
// Cast a pointer or reference to a pointer/reference to a base class.
83+
//
84+
// In the presence of multiple inheritance, perform pointer adjustments (like
85+
// what static_cast does).
86+
template <class Base_Pointer, class Derived>
87+
Base_Pointer base_cast(Derived* base) {
88+
using Base = std::remove_pointer_t<Base_Pointer>;
89+
static_assert(std::is_base_of_v<Base, Derived>,
90+
"Derived should derive from Base");
91+
static_assert(!std::is_base_of_v<Derived, Base>,
92+
"Derived should not be the same type as Base");
93+
return base;
94+
}
8195
}
8296

8397
// quick-lint-js finds bugs in JavaScript programs.

test/quick-lint-js/variable-analyzer-support.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,15 @@ void test_parse_and_analyze(String8_View input,
6060
Source_Location caller) {
6161
Padded_String code(input);
6262

63-
// Our variable analyzer tests should have valid code as input. We don't want
64-
// to accidentally test parse errors when we're testing the variable analyzer.
65-
Failing_Diag_Reporter parse_diag_reporter;
66-
Parser p(&code, &parse_diag_reporter, options.parse_options);
67-
63+
Failing_Diag_Reporter failing_diag_reporter;
6864
Diag_Collector diag_collector;
65+
66+
Parser p(&code,
67+
options.allow_parse_errors
68+
? base_cast<Diag_Reporter*>(&diag_collector)
69+
: base_cast<Diag_Reporter*>(&failing_diag_reporter),
70+
options.parse_options);
71+
6972
Variable_Analyzer var_analyzer(&diag_collector, &globals,
7073
options.analyze_options);
7174

test/quick-lint-js/variable-analyzer-support.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ constexpr Variable_Analyzer_Options typescript_var_options =
3333
struct Test_Parse_And_Analyze_Options {
3434
Parser_Options parse_options;
3535
Variable_Analyzer_Options analyze_options;
36+
37+
// Our variable analyzer tests should have valid code as input. By default we
38+
// don't want to accidentally test parse errors when we're testing the
39+
// variable analyzer.
40+
bool allow_parse_errors = false;
41+
42+
Test_Parse_And_Analyze_Options with_allow_parse_errors() const {
43+
Test_Parse_And_Analyze_Options o = *this;
44+
o.allow_parse_errors = true;
45+
return o;
46+
}
3647
};
3748

3849
extern const Test_Parse_And_Analyze_Options javascript_analyze_options;

test/test-variable-analyzer-parse.cpp

Lines changed: 60 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// See end of file for extended copyright information.
33

44
#include <cstring>
5-
#include <gmock/gmock.h>
65
#include <gtest/gtest.h>
76
#include <quick-lint-js/container/padded-string.h>
87
#include <quick-lint-js/diag-collector.h>
@@ -14,56 +13,30 @@
1413
#include <quick-lint-js/port/char8.h>
1514
#include <quick-lint-js/variable-analyzer-support.h>
1615

17-
using ::testing::ElementsAreArray;
18-
using ::testing::IsEmpty;
19-
2016
namespace quick_lint_js {
2117
namespace {
2218
TEST(Test_Variable_Analyzer_Parse,
2319
let_variable_use_before_declaration_with_parsing) {
24-
Padded_String input(u8"let x = y, y = x;"_sv);
25-
Diag_Collector v;
26-
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
27-
Parser p(&input, &v, javascript_options);
28-
EXPECT_TRUE(p.parse_and_visit_statement(l));
29-
l.visit_end_of_module();
30-
31-
EXPECT_THAT(
32-
v.errors,
33-
ElementsAreArray({
34-
DIAG_TYPE_2_OFFSETS(&input, Diag_Variable_Used_Before_Declaration, //
35-
use, 8, u8"y"_sv, declaration, 11, u8"y"_sv),
36-
}));
20+
test_parse_and_analyze(
21+
u8"let x = y, y = x;"_sv, //
22+
u8" ^ Diag_Variable_Used_Before_Declaration.declaration\n"_diag //
23+
u8" ^ .use"_diag,
24+
javascript_analyze_options, default_globals);
3725
}
3826

3927
TEST(Test_Variable_Analyzer_Parse, generic_parameter_use_before_declaration) {
40-
Padded_String input(u8"function f<T extends T>() {}"_sv);
41-
Diag_Collector v;
42-
Variable_Analyzer l(&v, &default_globals, typescript_var_options);
43-
Parser p(&input, &v, typescript_options);
44-
EXPECT_TRUE(p.parse_and_visit_statement(l));
45-
l.visit_end_of_module();
46-
47-
EXPECT_THAT(v.errors,
48-
ElementsAreArray({
49-
DIAG_TYPE_2_OFFSETS(
50-
&input, Diag_Cyclic_TypeScript_Type_Definition, //
51-
use, u8"function f<T extends "_sv.size(), u8"T"_sv, //
52-
declaration, u8"function f<"_sv.size(), u8"T"_sv),
53-
}));
28+
test_parse_and_analyze(
29+
u8"function f<T extends T>() {}"_sv,
30+
u8" ^ Diag_Cyclic_TypeScript_Type_Definition.use\n"_diag
31+
u8" ^ .declaration"_diag,
32+
typescript_analyze_options.with_allow_parse_errors(), default_globals);
5433
}
5534

5635
TEST(
5736
Test_Variable_Analyzer_Parse,
5837
variables_with_different_escape_sequences_are_equivalent_after_normalization) {
59-
Padded_String input(u8"let \\u{69} = 0; i += 1; \\u0069;"_sv);
60-
Diag_Collector v;
61-
62-
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
63-
Parser p(&input, &v, javascript_options);
64-
p.parse_and_visit_module(l);
65-
66-
EXPECT_THAT(v.errors, IsEmpty());
38+
test_parse_and_analyze(u8"let \\u{69} = 0; i += 1; \\u0069;"_sv, no_diags,
39+
javascript_analyze_options, default_globals);
6740
}
6841

6942
TEST(Test_Variable_Analyzer_Parse,
@@ -77,38 +50,19 @@ TEST(Test_Variable_Analyzer_Parse,
7750

7851
TEST(Test_Variable_Analyzer_Parse,
7952
escape_sequences_are_allowed_for_arguments_variable) {
80-
Padded_String input(u8R"(function f() { return \u{61}rgument\u{73}; })"_sv);
81-
Diag_Collector v;
82-
83-
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
84-
Parser p(&input, &v, javascript_options);
85-
p.parse_and_visit_module(l);
86-
87-
EXPECT_THAT(v.errors, IsEmpty());
53+
test_parse_and_analyze(u8R"(function f() { return \u{61}rgument\u{73}; })"_sv,
54+
no_diags, javascript_analyze_options, default_globals);
8855
}
8956

9057
TEST(Test_Variable_Analyzer_Parse,
9158
function_statement_inside_if_does_not_conflict_with_let_variable) {
92-
Padded_String input(u8"let f;\nif (true)\n function f() {}"_sv);
93-
94-
Diag_Collector v;
95-
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
96-
Parser p(&input, &v, javascript_options);
97-
p.parse_and_visit_module(l);
98-
99-
EXPECT_THAT(v.errors, IsEmpty());
59+
test_parse_and_analyze(u8"let f;\nif (true)\n function f() {}"_sv, no_diags,
60+
javascript_analyze_options, default_globals);
10061
}
10162

10263
TEST(Test_Variable_Analyzer_Parse, typeof_with_conditional_operator) {
103-
{
104-
Padded_String input(u8"typeof x ? 10 : 20;"_sv);
105-
Diag_Collector v;
106-
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
107-
Parser p(&input, &v, javascript_options);
108-
p.parse_and_visit_module(l);
109-
110-
EXPECT_THAT(v.errors, IsEmpty());
111-
}
64+
test_parse_and_analyze(u8"typeof x ? 10 : 20;"_sv, no_diags,
65+
javascript_analyze_options, default_globals);
11266
}
11367

11468
TEST(Test_Variable_Analyzer_Parse, prefix_plusplus_on_const_variable) {
@@ -118,27 +72,13 @@ TEST(Test_Variable_Analyzer_Parse, prefix_plusplus_on_const_variable) {
11872
u8" ^ .declaration"_diag,
11973
javascript_analyze_options, default_globals);
12074

121-
{
122-
Padded_String input(u8"const x = {y : 10};\n ++x.y;"_sv);
123-
Diag_Collector v;
124-
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
125-
Parser p(&input, &v, javascript_options);
126-
p.parse_and_visit_module(l);
127-
128-
EXPECT_THAT(v.errors, IsEmpty());
129-
}
75+
test_parse_and_analyze(u8"const x = {y : 10};\n ++x.y;"_sv, no_diags,
76+
javascript_analyze_options, default_globals);
13077
}
13178

13279
TEST(Test_Variable_Analyzer_Parse, prefix_plusplus_plus_operand) {
133-
{
134-
Padded_String input(u8"const x = [42]; ++x[0];"_sv);
135-
Diag_Collector v;
136-
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
137-
Parser p(&input, &v, javascript_options);
138-
p.parse_and_visit_module(l);
139-
140-
EXPECT_THAT(v.errors, IsEmpty());
141-
}
80+
test_parse_and_analyze(u8"const x = [42]; ++x[0];"_sv, no_diags,
81+
javascript_analyze_options, default_globals);
14282

14383
test_parse_and_analyze(
14484
u8"const x = 42;\n const y =10;\n ++x + y;"_sv, //
@@ -148,124 +88,62 @@ TEST(Test_Variable_Analyzer_Parse, prefix_plusplus_plus_operand) {
14888
}
14989

15090
TEST(Test_Variable_Analyzer_Parse, use_await_label_in_non_async_function) {
151-
Padded_String input(u8"function f() {await: for(;;){break await;}}"_sv);
152-
Diag_Collector v;
153-
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
154-
Parser p(&input, &v, javascript_options);
155-
p.parse_and_visit_module(l);
156-
157-
EXPECT_THAT(v.errors, IsEmpty());
91+
test_parse_and_analyze(u8"function f() {await: for(;;){break await;}}"_sv,
92+
no_diags, javascript_analyze_options, default_globals);
15893
}
15994

16095
TEST(Test_Variable_Analyzer_Parse, use_yield_label_in_non_generator_function) {
161-
Padded_String input(u8"function f() {yield: for(;;){break yield;}}"_sv);
162-
Diag_Collector v;
163-
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
164-
Parser p(&input, &v, javascript_options);
165-
p.parse_and_visit_module(l);
166-
167-
EXPECT_THAT(v.errors, IsEmpty());
96+
test_parse_and_analyze(u8"function f() {yield: for(;;){break yield;}}"_sv,
97+
no_diags, javascript_analyze_options, default_globals);
16898
}
16999

170100
TEST(Test_Variable_Analyzer_Parse, escape_sequence_in_keyword_identifier) {
171101
// The parser should not report a stray 'finally' keyword.
172102
// The linter should not report that 'finally' is undeclared.
173-
Padded_String input(u8"let which = \\u{66}inally;"_sv);
174-
Diag_Collector v;
175-
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
176-
Parser p(&input, &v, javascript_options);
177-
p.parse_and_visit_module(l);
178-
179-
EXPECT_THAT(v.errors,
180-
ElementsAreArray({
181-
DIAG_TYPE(Diag_Keywords_Cannot_Contain_Escape_Sequences),
182-
}));
103+
test_parse_and_analyze(u8"let which = \\u{66}inally;"_sv,
104+
u8"Diag_Keywords_Cannot_Contain_Escape_Sequences"_diag,
105+
javascript_analyze_options.with_allow_parse_errors(),
106+
default_globals);
183107
}
184108

185109
TEST(Test_Variable_Analyzer_Parse, delete_local_variable) {
186-
Padded_String input(
187-
u8"function f(param) { let v; delete v; delete param; }"_sv);
188-
Diag_Collector v;
189-
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
190-
Parser p(&input, &v, javascript_options);
191-
p.parse_and_visit_module(l);
192-
193-
EXPECT_THAT(v.errors,
194-
ElementsAreArray({
195-
DIAG_TYPE(Diag_Redundant_Delete_Statement_On_Variable),
196-
DIAG_TYPE(Diag_Redundant_Delete_Statement_On_Variable),
197-
}));
110+
test_parse_and_analyze(
111+
u8"function f(param) { let v; delete v; delete param; }"_sv,
112+
u8"Diag_Redundant_Delete_Statement_On_Variable"_diag,
113+
u8"Diag_Redundant_Delete_Statement_On_Variable"_diag,
114+
javascript_analyze_options, default_globals);
198115
}
199116

200117
TEST(Test_Variable_Analyzer_Parse, extends_self) {
201-
{
202-
Padded_String input(
203-
u8"function C() {}\n"_sv
204-
u8"{\n"_sv
205-
u8" class C extends C {}"_sv
206-
u8"}"_sv);
207-
Diag_Collector v;
208-
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
209-
Parser p(&input, &v, javascript_options);
210-
p.parse_and_visit_module(l);
211-
212-
EXPECT_THAT(v.errors, ElementsAreArray({
213-
DIAG_TYPE(Diag_Variable_Used_Before_Declaration),
214-
}));
215-
}
216-
217-
{
218-
Padded_String input(
219-
u8"function C() {}\n"_sv
220-
u8"{\n"_sv
221-
u8" class C extends (null, [C][0], Object) {}"_sv
222-
u8"}"_sv);
223-
Diag_Collector v;
224-
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
225-
Parser p(&input, &v, javascript_options);
226-
p.parse_and_visit_module(l);
227-
228-
EXPECT_THAT(v.errors, ElementsAreArray({
229-
DIAG_TYPE(Diag_Variable_Used_Before_Declaration),
230-
}));
231-
}
232-
233-
{
234-
Padded_String input(
235-
u8"function C() {}\n"_sv
236-
u8"{\n"_sv
237-
u8" (class C extends C {})"_sv
238-
u8"}"_sv);
239-
Diag_Collector v;
240-
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
241-
Parser p(&input, &v, javascript_options);
242-
p.parse_and_visit_module(l);
243-
244-
EXPECT_THAT(v.errors, ElementsAreArray({
245-
DIAG_TYPE(Diag_Variable_Used_Before_Declaration),
246-
}));
247-
}
118+
test_parse_and_analyze(
119+
u8"function C() {}\n"_sv
120+
u8"{\n"_sv
121+
u8" class C extends C {}"_sv
122+
u8"}"_sv,
123+
u8"Diag_Variable_Used_Before_Declaration"_diag,
124+
javascript_analyze_options, default_globals);
125+
test_parse_and_analyze(
126+
u8"function C() {}\n"_sv
127+
u8"{\n"_sv
128+
u8" class C extends (null, [C][0], Object) {}"_sv
129+
u8"}"_sv,
130+
u8"Diag_Variable_Used_Before_Declaration"_diag,
131+
javascript_analyze_options, default_globals);
132+
test_parse_and_analyze(
133+
u8"function C() {}\n"_sv
134+
u8"{\n"_sv
135+
u8" (class C extends C {})"_sv
136+
u8"}"_sv,
137+
u8"Diag_Variable_Used_Before_Declaration"_diag,
138+
javascript_analyze_options, default_globals);
248139
}
249140

250141
TEST(Test_Variable_Analyzer_Parse,
251142
typescript_static_block_can_reference_class) {
252-
{
253-
Padded_String input(u8"class C { static { C; } }"_sv);
254-
Diag_Collector v;
255-
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
256-
Parser p(&input, &v, typescript_options);
257-
p.parse_and_visit_module(l);
258-
EXPECT_THAT(v.errors, IsEmpty());
259-
}
260-
261-
{
262-
Padded_String input(u8"(class C { static { C; } });"_sv);
263-
Diag_Collector v;
264-
Variable_Analyzer l(&v, &default_globals, javascript_var_options);
265-
Parser p(&input, &v, typescript_options);
266-
p.parse_and_visit_module(l);
267-
EXPECT_THAT(v.errors, IsEmpty());
268-
}
143+
test_parse_and_analyze(u8"class C { static { C; } }"_sv, no_diags,
144+
javascript_analyze_options, default_globals);
145+
test_parse_and_analyze(u8"(class C { static { C; } });"_sv, no_diags,
146+
javascript_analyze_options, default_globals);
269147
}
270148
}
271149
}

0 commit comments

Comments
 (0)