Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/tests/PrettyPrinter.test.cpp
2723 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
#include "Luau/Parser.h"
3
#include "Luau/PrettyPrinter.h"
4
#include "Luau/TypeAttach.h"
5
#include "Luau/TypeInfer.h"
6
#include "Luau/Type.h"
7
8
#include "Fixture.h"
9
#include "ScopedFlags.h"
10
11
#include "doctest.h"
12
13
LUAU_FASTFLAG(DebugLuauNoInline)
14
15
using namespace Luau;
16
17
TEST_SUITE_BEGIN("PrettyPrinterTests");
18
19
TEST_CASE("test_1")
20
{
21
const std::string example = R"(
22
local function isPortal(element)
23
if type(element)~='table'then
24
return false
25
end
26
27
return element.component == Core.Portal
28
end
29
)";
30
31
CHECK_EQ(example, prettyPrint(example).code);
32
}
33
34
TEST_CASE("string_literals")
35
{
36
const std::string code = R"( local S='abcdef\n\f\a\020' )";
37
38
CHECK_EQ(code, prettyPrint(code).code);
39
}
40
41
TEST_CASE("string_literals_containing_utf8")
42
{
43
const std::string code = R"( local S='lalala こんにちは' )"; // Konichiwa!
44
CHECK_EQ(code, prettyPrint(code).code);
45
}
46
47
TEST_CASE("if_stmt_spaces_around_tokens")
48
{
49
const std::string one = R"( if This then Once() end)";
50
CHECK_EQ(one, prettyPrint(one).code);
51
52
const std::string two = R"( if This then Once() end)";
53
CHECK_EQ(two, prettyPrint(two).code);
54
55
const std::string three = R"( if This then Once() end)";
56
CHECK_EQ(three, prettyPrint(three).code);
57
58
const std::string four = R"( if This then Once() end)";
59
CHECK_EQ(four, prettyPrint(four).code);
60
61
const std::string five = R"( if This then Once() else Other() end)";
62
CHECK_EQ(five, prettyPrint(five).code);
63
64
const std::string six = R"( if This then Once() else Other() end)";
65
CHECK_EQ(six, prettyPrint(six).code);
66
67
const std::string seven = R"( if This then Once() elseif true then Other() end)";
68
CHECK_EQ(seven, prettyPrint(seven).code);
69
70
const std::string eight = R"( if This then Once() elseif true then Other() end)";
71
CHECK_EQ(eight, prettyPrint(eight).code);
72
73
const std::string nine = R"( if This then Once() elseif true then Other() end)";
74
CHECK_EQ(nine, prettyPrint(nine).code);
75
}
76
77
TEST_CASE("elseif_chains_indent_sensibly")
78
{
79
const std::string code = R"(
80
if This then
81
Once()
82
elseif That then
83
Another()
84
elseif SecondLast then
85
Third()
86
else
87
IfAllElseFails()
88
end
89
)";
90
91
CHECK_EQ(code, prettyPrint(code).code);
92
}
93
94
TEST_CASE("strips_type_annotations")
95
{
96
const std::string code = R"( local s: string= 'hello there' )";
97
const std::string expected = R"( local s = 'hello there' )";
98
CHECK_EQ(expected, prettyPrint(code).code);
99
}
100
101
TEST_CASE("strips_type_assertion_expressions")
102
{
103
const std::string code = R"( local s= some_function() :: any+ something_else() :: number )";
104
const std::string expected = R"( local s= some_function() + something_else() )";
105
CHECK_EQ(expected, prettyPrint(code).code);
106
}
107
108
TEST_CASE("function_taking_ellipsis")
109
{
110
const std::string code = R"( function F(...) end )";
111
112
CHECK_EQ(code, prettyPrint(code).code);
113
}
114
115
TEST_CASE("omit_decimal_place_for_integers")
116
{
117
const std::string code = R"( local a=5, 6, 7, 3.141, 1.1290000000000002e+45 )";
118
CHECK_EQ(code, prettyPrint(code).code);
119
}
120
121
TEST_CASE("for_loop")
122
{
123
const std::string one = R"( for i=1,10 do end )";
124
CHECK_EQ(one, prettyPrint(one).code);
125
126
const std::string code = R"( for i=5,6,7 do end )";
127
CHECK_EQ(code, prettyPrint(code).code);
128
}
129
130
TEST_CASE("for_loop_spaces_around_tokens")
131
{
132
const std::string one = R"( for index = 1, 10 do call(index) end )";
133
CHECK_EQ(one, prettyPrint(one).code);
134
135
const std::string two = R"( for index = 1 , 10 do call(index) end )";
136
CHECK_EQ(two, prettyPrint(two).code);
137
138
const std::string three = R"( for index = 1, 10 , 3 do call(index) end )";
139
CHECK_EQ(three, prettyPrint(three).code);
140
141
const std::string four = R"( for index = 1, 10 do call(index) end )";
142
CHECK_EQ(four, prettyPrint(four).code);
143
144
const std::string five = R"( for index = 1, 10 do call(index) end )";
145
CHECK_EQ(five, prettyPrint(five).code);
146
}
147
148
TEST_CASE("for_in_loop")
149
{
150
const std::string code = R"( for k, v in ipairs(x)do end )";
151
CHECK_EQ(code, prettyPrint(code).code);
152
}
153
154
TEST_CASE("for_in_loop_spaces_around_tokens")
155
{
156
const std::string one = R"( for k, v in ipairs(x) do end )";
157
CHECK_EQ(one, prettyPrint(one).code);
158
159
const std::string two = R"( for k, v in ipairs(x) do end )";
160
CHECK_EQ(two, prettyPrint(two).code);
161
162
const std::string three = R"( for k , v in ipairs(x) do end )";
163
CHECK_EQ(three, prettyPrint(three).code);
164
165
const std::string four = R"( for k, v in next , t do end )";
166
CHECK_EQ(four, prettyPrint(four).code);
167
168
const std::string five = R"( for k, v in ipairs(x) do end )";
169
CHECK_EQ(five, prettyPrint(five).code);
170
}
171
172
TEST_CASE("for_in_single_variable")
173
{
174
const std::string one = R"( for key in pairs(x) do end )";
175
CHECK_EQ(one, prettyPrint(one).code);
176
}
177
178
TEST_CASE("while_loop")
179
{
180
const std::string code = R"( while f(x)do print() end )";
181
CHECK_EQ(code, prettyPrint(code).code);
182
}
183
184
TEST_CASE("while_loop_spaces_around_tokens")
185
{
186
const std::string one = R"( while f(x) do print() end )";
187
CHECK_EQ(one, prettyPrint(one).code);
188
189
const std::string two = R"( while f(x) do print() end )";
190
CHECK_EQ(two, prettyPrint(two).code);
191
192
const std::string three = R"( while f(x) do print() end )";
193
CHECK_EQ(three, prettyPrint(three).code);
194
195
const std::string four = R"( while f(x) do print() end )";
196
CHECK_EQ(four, prettyPrint(four).code);
197
}
198
199
TEST_CASE("repeat_until_loop")
200
{
201
const std::string code = R"( repeat print() until f(x) )";
202
CHECK_EQ(code, prettyPrint(code).code);
203
}
204
205
TEST_CASE("repeat_until_loop_condition_on_new_line")
206
{
207
const std::string code = R"(
208
repeat
209
print()
210
until
211
f(x) )";
212
CHECK_EQ(code, prettyPrint(code).code);
213
}
214
215
TEST_CASE("lambda")
216
{
217
const std::string one = R"( local p=function(o, m, g) return 77 end )";
218
CHECK_EQ(one, prettyPrint(one).code);
219
220
const std::string two = R"( local p=function(o, m, g,...) return 77 end )";
221
CHECK_EQ(two, prettyPrint(two).code);
222
}
223
224
TEST_CASE("local_assignment")
225
{
226
const std::string one = R"( local x = 1 )";
227
CHECK_EQ(one, prettyPrint(one).code);
228
229
const std::string two = R"( local x, y, z = 1, 2, 3 )";
230
CHECK_EQ(two, prettyPrint(two).code);
231
232
const std::string three = R"( local x )";
233
CHECK_EQ(three, prettyPrint(three).code);
234
}
235
236
TEST_CASE("local_assignment_spaces_around_tokens")
237
{
238
const std::string one = R"( local x = 1 )";
239
CHECK_EQ(one, prettyPrint(one).code);
240
241
const std::string two = R"( local x = 1 )";
242
CHECK_EQ(two, prettyPrint(two).code);
243
244
const std::string three = R"( local x = 1 )";
245
CHECK_EQ(three, prettyPrint(three).code);
246
247
const std::string four = R"( local x , y = 1, 2 )";
248
CHECK_EQ(four, prettyPrint(four).code);
249
250
const std::string five = R"( local x, y = 1, 2 )";
251
CHECK_EQ(five, prettyPrint(five).code);
252
253
const std::string six = R"( local x, y = 1 , 2 )";
254
CHECK_EQ(six, prettyPrint(six).code);
255
256
const std::string seven = R"( local x, y = 1, 2 )";
257
CHECK_EQ(seven, prettyPrint(seven).code);
258
}
259
260
TEST_CASE("local_function")
261
{
262
const std::string one = R"( local function p(o, m, g) return 77 end )";
263
CHECK_EQ(one, prettyPrint(one).code);
264
265
const std::string two = R"( local function p(o, m, g,...) return 77 end )";
266
CHECK_EQ(two, prettyPrint(two).code);
267
}
268
269
TEST_CASE("local_function_spaces_around_tokens")
270
{
271
const std::string one = R"( local function p(o, m, ...) end )";
272
CHECK_EQ(one, prettyPrint(one).code);
273
274
const std::string two = R"( local function p(o, m, ...) end )";
275
CHECK_EQ(two, prettyPrint(two).code);
276
}
277
278
TEST_CASE("function")
279
{
280
const std::string one = R"( function p(o, m, g) return 77 end )";
281
CHECK_EQ(one, prettyPrint(one).code);
282
283
const std::string two = R"( function p(o, m, g,...) return 77 end )";
284
CHECK_EQ(two, prettyPrint(two).code);
285
}
286
287
TEST_CASE("function_spaces_around_tokens")
288
{
289
const std::string two = R"( function p(o, m, ...) end )";
290
CHECK_EQ(two, prettyPrint(two).code);
291
292
const std::string three = R"( function p( o, m, ...) end )";
293
CHECK_EQ(three, prettyPrint(three).code);
294
295
const std::string four = R"( function p(o , m, ...) end )";
296
CHECK_EQ(four, prettyPrint(four).code);
297
298
const std::string five = R"( function p(o, m, ...) end )";
299
CHECK_EQ(five, prettyPrint(five).code);
300
301
const std::string six = R"( function p(o, m , ...) end )";
302
CHECK_EQ(six, prettyPrint(six).code);
303
304
const std::string seven = R"( function p(o, m, ...) end )";
305
CHECK_EQ(seven, prettyPrint(seven).code);
306
307
const std::string eight = R"( function p(o, m, ... ) end )";
308
CHECK_EQ(eight, prettyPrint(eight).code);
309
310
const std::string nine = R"( function p(o, m, ...) end )";
311
CHECK_EQ(nine, prettyPrint(nine).code);
312
}
313
314
TEST_CASE("function_with_types_spaces_around_tokens")
315
{
316
std::string code = R"( function p<X, Y, Z...>(o: string, m: number, ...: any): string end )";
317
CHECK_EQ(code, prettyPrint(code, {}, true).code);
318
319
code = R"( function p <X, Y, Z...>(o: string, m: number, ...: any): string end )";
320
CHECK_EQ(code, prettyPrint(code, {}, true).code);
321
322
code = R"( function p<X , Y, Z...>(o: string, m: number, ...: any): string end )";
323
CHECK_EQ(code, prettyPrint(code, {}, true).code);
324
325
code = R"( function p<X, Y, Z...>(o: string, m: number, ...: any): string end )";
326
CHECK_EQ(code, prettyPrint(code, {}, true).code);
327
328
code = R"( function p<X, Y, Z...>(o: string, m: number, ...: any): string end )";
329
CHECK_EQ(code, prettyPrint(code, {}, true).code);
330
331
code = R"( function p<X, Y, Z ...>(o: string, m: number, ...: any): string end )";
332
CHECK_EQ(code, prettyPrint(code, {}, true).code);
333
334
code = R"( function p<X, Y, Z... >(o: string, m: number, ...: any): string end )";
335
CHECK_EQ(code, prettyPrint(code, {}, true).code);
336
337
code = R"( function p<X, Y, Z...> (o: string, m: number, ...: any): string end )";
338
CHECK_EQ(code, prettyPrint(code, {}, true).code);
339
340
code = R"( function p<X, Y, Z...>(o : string, m: number, ...: any): string end )";
341
CHECK_EQ(code, prettyPrint(code, {}, true).code);
342
343
code = R"( function p<X, Y, Z...>(o: string, m: number, ...: any): string end )";
344
CHECK_EQ(code, prettyPrint(code, {}, true).code);
345
346
code = R"( function p<X, Y, Z...>(o: string , m: number, ...: any): string end )";
347
CHECK_EQ(code, prettyPrint(code, {}, true).code);
348
349
code = R"( function p<X, Y, Z...>(o: string, m: number, ...: any): string end )";
350
CHECK_EQ(code, prettyPrint(code, {}, true).code);
351
352
code = R"( function p<X, Y, Z...>(o: string, m: number, ...: any): string end )";
353
CHECK_EQ(code, prettyPrint(code, {}, true).code);
354
355
code = R"( function p<X, Y, Z...>(o: string, m: number, ... : any): string end )";
356
CHECK_EQ(code, prettyPrint(code, {}, true).code);
357
358
code = R"( function p<X, Y, Z...>(o: string, m: number, ...: any): string end )";
359
CHECK_EQ(code, prettyPrint(code, {}, true).code);
360
361
code = R"( function p<X, Y, Z...>(o: string, m: number, ...: any ): string end )";
362
CHECK_EQ(code, prettyPrint(code, {}, true).code);
363
364
code = R"( function p<X, Y, Z...>(o: string, m: number, ...: any) :string end )";
365
CHECK_EQ(code, prettyPrint(code, {}, true).code);
366
367
code = R"( function p<X, Y, Z...>(o: string, m: number, ...: any): string end )";
368
CHECK_EQ(code, prettyPrint(code, {}, true).code);
369
}
370
371
TEST_CASE("returns_spaces_around_tokens")
372
{
373
const std::string one = R"( return 1 )";
374
CHECK_EQ(one, prettyPrint(one).code);
375
376
const std::string two = R"( return 1 , 2 )";
377
CHECK_EQ(two, prettyPrint(two).code);
378
379
const std::string three = R"( return 1, 2 )";
380
CHECK_EQ(three, prettyPrint(three).code);
381
}
382
383
TEST_CASE_FIXTURE(Fixture, "type_alias_spaces_around_tokens")
384
{
385
std::string code = R"( type Foo = string )";
386
CHECK_EQ(code, prettyPrint(code, {}, true).code);
387
388
code = R"( type Foo = string )";
389
CHECK_EQ(code, prettyPrint(code, {}, true).code);
390
391
code = R"( type Foo = string )";
392
CHECK_EQ(code, prettyPrint(code, {}, true).code);
393
394
code = R"( type Foo = string )";
395
CHECK_EQ(code, prettyPrint(code, {}, true).code);
396
397
code = R"( export type Foo = string )";
398
CHECK_EQ(code, prettyPrint(code, {}, true).code);
399
400
code = R"( export type Foo = string )";
401
CHECK_EQ(code, prettyPrint(code, {}, true).code);
402
403
code = R"( type Foo<X, Y, Z...> = string )";
404
CHECK_EQ(code, prettyPrint(code, {}, true).code);
405
406
code = R"( type Foo <X, Y, Z...> = string )";
407
CHECK_EQ(code, prettyPrint(code, {}, true).code);
408
409
code = R"( type Foo< X, Y, Z...> = string )";
410
CHECK_EQ(code, prettyPrint(code, {}, true).code);
411
412
code = R"( type Foo<X , Y, Z...> = string )";
413
CHECK_EQ(code, prettyPrint(code, {}, true).code);
414
415
code = R"( type Foo<X, Y, Z...> = string )";
416
CHECK_EQ(code, prettyPrint(code, {}, true).code);
417
418
code = R"( type Foo<X, Y , Z...> = string )";
419
CHECK_EQ(code, prettyPrint(code, {}, true).code);
420
421
code = R"( type Foo<X, Y, Z...> = string )";
422
CHECK_EQ(code, prettyPrint(code, {}, true).code);
423
424
code = R"( type Foo<X, Y, Z ...> = string )";
425
CHECK_EQ(code, prettyPrint(code, {}, true).code);
426
427
code = R"( type Foo<X, Y, Z... > = string )";
428
CHECK_EQ(code, prettyPrint(code, {}, true).code);
429
}
430
431
TEST_CASE_FIXTURE(Fixture, "type_alias_with_defaults_spaces_around_tokens")
432
{
433
std::string code = R"( type Foo<X = string, Z... = ...any> = string )";
434
CHECK_EQ(code, prettyPrint(code, {}, true).code);
435
436
code = R"( type Foo<X = string, Z... = ...any> = string )";
437
CHECK_EQ(code, prettyPrint(code, {}, true).code);
438
439
code = R"( type Foo<X = string, Z... = ...any> = string )";
440
CHECK_EQ(code, prettyPrint(code, {}, true).code);
441
442
code = R"( type Foo<X = string, Z... = ...any> = string )";
443
CHECK_EQ(code, prettyPrint(code, {}, true).code);
444
445
code = R"( type Foo<X = string, Z... = ...any> = string )";
446
CHECK_EQ(code, prettyPrint(code, {}, true).code);
447
}
448
449
TEST_CASE("table_literals")
450
{
451
const std::string code = R"( local t={1, 2, 3, foo='bar', baz=99,[5.5]='five point five', 'end'} )";
452
CHECK_EQ(code, prettyPrint(code).code);
453
}
454
455
TEST_CASE("more_table_literals")
456
{
457
const std::string code = R"( local t={['Content-Type']='text/plain'} )";
458
CHECK_EQ(code, prettyPrint(code).code);
459
}
460
461
TEST_CASE("table_literal_preserves_record_vs_general")
462
{
463
const std::string code = R"( local t={['foo']='bar',quux=42} )";
464
CHECK_EQ(code, prettyPrint(code).code);
465
}
466
467
TEST_CASE("table_literal_with_numeric_key")
468
{
469
const std::string code = R"( local t={[5]='five',[6]='six'} )";
470
CHECK_EQ(code, prettyPrint(code).code);
471
}
472
473
TEST_CASE("table_literal_with_keyword_key")
474
{
475
const std::string code = R"( local t={['nil']=nil,['true']=true} )";
476
CHECK_EQ(code, prettyPrint(code).code);
477
}
478
479
TEST_CASE("table_literal_closing_brace_at_correct_position")
480
{
481
const std::string code = R"(
482
local t={
483
eggs='Tasty',
484
avocado='more like awesomecavo amirite'
485
}
486
)";
487
488
CHECK_EQ(code, prettyPrint(code).code);
489
}
490
491
TEST_CASE("table_literal_with_semicolon_separators")
492
{
493
const std::string code = R"(
494
local t = { x = 1; y = 2 }
495
)";
496
497
CHECK_EQ(code, prettyPrint(code).code);
498
}
499
500
TEST_CASE("table_literal_with_trailing_separators")
501
{
502
const std::string code = R"(
503
local t = { x = 1, y = 2, }
504
)";
505
506
CHECK_EQ(code, prettyPrint(code).code);
507
}
508
509
TEST_CASE("table_literal_with_spaces_around_separator")
510
{
511
const std::string code = R"(
512
local t = { x = 1 , y = 2 }
513
)";
514
515
CHECK_EQ(code, prettyPrint(code).code);
516
}
517
518
TEST_CASE("table_literal_with_spaces_around_equals")
519
{
520
const std::string code = R"(
521
local t = { x = 1 }
522
)";
523
524
CHECK_EQ(code, prettyPrint(code).code);
525
}
526
527
TEST_CASE("table_literal_multiline_with_indexers")
528
{
529
const std::string code = R"(
530
local t = {
531
["my first value"] = "x";
532
["my second value"] = "y";
533
}
534
)";
535
536
CHECK_EQ(code, prettyPrint(code).code);
537
}
538
539
TEST_CASE("method_calls")
540
{
541
const std::string code = R"( foo.bar.baz:quux() )";
542
CHECK_EQ(code, prettyPrint(code).code);
543
}
544
545
TEST_CASE("method_definitions")
546
{
547
const std::string code = R"( function foo.bar.baz:quux() end )";
548
CHECK_EQ(code, prettyPrint(code).code);
549
}
550
551
TEST_CASE("spaces_between_keywords_even_if_it_pushes_the_line_estimation_off")
552
{
553
const std::string code = R"( if math.abs(raySlope) < .01 then return 0 end )";
554
CHECK_EQ(code, prettyPrint(code).code);
555
}
556
557
TEST_CASE("numbers")
558
{
559
const std::string code = R"( local a=2510238627 )";
560
CHECK_EQ(code, prettyPrint(code).code);
561
}
562
563
TEST_CASE("infinity")
564
{
565
const std::string code = R"( local a = 1e500 local b = 1e400 )";
566
CHECK_EQ(code, prettyPrint(code).code);
567
}
568
569
TEST_CASE("numbers_with_separators")
570
{
571
const std::string code = R"( local a = 123_456_789 )";
572
CHECK_EQ(code, prettyPrint(code).code);
573
}
574
575
TEST_CASE("hexadecimal_numbers")
576
{
577
const std::string code = R"( local a = 0xFFFF )";
578
CHECK_EQ(code, prettyPrint(code).code);
579
}
580
581
TEST_CASE("binary_numbers")
582
{
583
const std::string code = R"( local a = 0b0101 )";
584
CHECK_EQ(code, prettyPrint(code).code);
585
}
586
587
TEST_CASE("single_quoted_strings")
588
{
589
const std::string code = R"( local a = 'hello world' )";
590
CHECK_EQ(code, prettyPrint(code).code);
591
}
592
593
TEST_CASE("double_quoted_strings")
594
{
595
const std::string code = R"( local a = "hello world" )";
596
CHECK_EQ(code, prettyPrint(code).code);
597
}
598
599
TEST_CASE("simple_interp_string")
600
{
601
const std::string code = R"( local a = `hello world` )";
602
CHECK_EQ(code, prettyPrint(code).code);
603
}
604
605
TEST_CASE("raw_strings")
606
{
607
const std::string code = R"( local a = [[ hello world ]] )";
608
CHECK_EQ(code, prettyPrint(code).code);
609
}
610
611
TEST_CASE("raw_strings_with_blocks")
612
{
613
const std::string code = R"( local a = [==[ hello world ]==] )";
614
CHECK_EQ(code, prettyPrint(code).code);
615
}
616
617
TEST_CASE("escaped_strings")
618
{
619
const std::string code = R"( local s='\\b\\t\\n\\\\' )";
620
CHECK_EQ(code, prettyPrint(code).code);
621
}
622
623
TEST_CASE("escaped_strings_2")
624
{
625
const std::string code = R"( local s="\a\b\f\n\r\t\v\'\"\\" )";
626
CHECK_EQ(code, prettyPrint(code).code);
627
}
628
629
TEST_CASE("escaped_strings_newline")
630
{
631
const std::string code = R"(
632
print("foo \
633
bar")
634
)";
635
CHECK_EQ(code, prettyPrint(code).code);
636
}
637
638
TEST_CASE("escaped_strings_raw")
639
{
640
const std::string code = R"( local x = [=[\v<((do|load)file|require)\s*\(?['"]\zs[^'"]+\ze['"]]=] )";
641
CHECK_EQ(code, prettyPrint(code).code);
642
}
643
644
TEST_CASE("position_correctly_updated_when_writing_multiline_string")
645
{
646
const std::string code = R"(
647
call([[
648
testing
649
]]) )";
650
CHECK_EQ(code, prettyPrint(code).code);
651
}
652
653
TEST_CASE("need_a_space_between_number_literals_and_dots")
654
{
655
const std::string code = R"( return point and math.ceil(point* 100000* 100)/ 100000 .. '%'or '' )";
656
CHECK_EQ(code, prettyPrint(code).code);
657
}
658
659
TEST_CASE("binary_keywords")
660
{
661
const std::string code = "local c = a0 ._ or b0 ._";
662
CHECK_EQ(code, prettyPrint(code).code);
663
}
664
665
TEST_CASE("function_call_parentheses_no_args")
666
{
667
const std::string code = R"( call() )";
668
CHECK_EQ(code, prettyPrint(code).code);
669
}
670
671
TEST_CASE("function_call_parentheses_one_arg")
672
{
673
const std::string code = R"( call(arg) )";
674
CHECK_EQ(code, prettyPrint(code).code);
675
}
676
677
TEST_CASE("function_call_parentheses_multiple_args")
678
{
679
const std::string code = R"( call(arg1, arg3, arg3) )";
680
CHECK_EQ(code, prettyPrint(code).code);
681
}
682
683
TEST_CASE("function_call_parentheses_multiple_args_no_space")
684
{
685
const std::string code = R"( call(arg1,arg3,arg3) )";
686
CHECK_EQ(code, prettyPrint(code).code);
687
}
688
689
TEST_CASE("function_call_parentheses_multiple_args_space_before_commas")
690
{
691
const std::string code = R"( call(arg1 ,arg3 ,arg3) )";
692
CHECK_EQ(code, prettyPrint(code).code);
693
}
694
695
TEST_CASE("function_call_spaces_before_parentheses")
696
{
697
const std::string code = R"( call () )";
698
CHECK_EQ(code, prettyPrint(code).code);
699
}
700
701
TEST_CASE("function_call_spaces_within_parentheses")
702
{
703
const std::string code = R"( call( ) )";
704
CHECK_EQ(code, prettyPrint(code).code);
705
}
706
707
TEST_CASE("function_call_string_double_quotes")
708
{
709
const std::string code = R"( call "string" )";
710
CHECK_EQ(code, prettyPrint(code).code);
711
}
712
713
TEST_CASE("function_call_string_single_quotes")
714
{
715
const std::string code = R"( call 'string' )";
716
CHECK_EQ(code, prettyPrint(code).code);
717
}
718
719
TEST_CASE("function_call_string_no_space")
720
{
721
const std::string code = R"( call'string' )";
722
CHECK_EQ(code, prettyPrint(code).code);
723
}
724
725
TEST_CASE("function_call_table_literal")
726
{
727
const std::string code = R"( call { x = 1 } )";
728
CHECK_EQ(code, prettyPrint(code).code);
729
}
730
731
TEST_CASE("function_call_table_literal_no_space")
732
{
733
const std::string code = R"( call{x=1} )";
734
CHECK_EQ(code, prettyPrint(code).code);
735
}
736
737
TEST_CASE("do_blocks")
738
{
739
const std::string code = R"(
740
foo()
741
742
do
743
local bar=baz()
744
quux()
745
end
746
747
foo2()
748
)";
749
750
CHECK_EQ(code, prettyPrint(code).code);
751
}
752
753
TEST_CASE("nested_do_block")
754
{
755
const std::string code = R"(
756
do
757
do
758
local x = 1
759
end
760
end
761
)";
762
763
CHECK_EQ(code, prettyPrint(code).code);
764
}
765
766
TEST_CASE("emit_a_do_block_in_cases_of_potentially_ambiguous_syntax")
767
{
768
const std::string code = R"(
769
f();
770
(g or f)()
771
)";
772
CHECK_EQ(code, prettyPrint(code).code);
773
}
774
775
TEST_CASE_FIXTURE(Fixture, "parentheses_multiline")
776
{
777
std::string code = R"(
778
local test = (
779
x
780
)
781
)";
782
783
CHECK_EQ(code, prettyPrint(code, {}, true).code);
784
}
785
786
TEST_CASE_FIXTURE(Fixture, "stmt_semicolon")
787
{
788
std::string code = R"( local test = 1; )";
789
CHECK_EQ(code, prettyPrint(code, {}, true).code);
790
791
code = R"( local test = 1 ; )";
792
CHECK_EQ(code, prettyPrint(code, {}, true).code);
793
}
794
795
TEST_CASE_FIXTURE(Fixture, "do_block_ending_with_semicolon")
796
{
797
std::string code = R"(
798
do
799
return;
800
end;
801
)";
802
CHECK_EQ(code, prettyPrint(code, {}, true).code);
803
}
804
805
TEST_CASE_FIXTURE(Fixture, "if_stmt_semicolon")
806
{
807
std::string code = R"(
808
if init then
809
x = string.sub(x, utf8.offset(x, init));
810
end;
811
)";
812
CHECK_EQ(code, prettyPrint(code, {}, true).code);
813
}
814
815
TEST_CASE_FIXTURE(Fixture, "if_stmt_semicolon_2")
816
{
817
std::string code = R"(
818
if (t < 1) then return c/2*t*t + b end;
819
)";
820
CHECK_EQ(code, prettyPrint(code, {}, true).code);
821
}
822
823
TEST_CASE_FIXTURE(Fixture, "for_loop_stmt_semicolon")
824
{
825
std::string code = R"(
826
for i,v in ... do
827
end;
828
)";
829
CHECK_EQ(code, prettyPrint(code, {}, true).code);
830
}
831
832
TEST_CASE_FIXTURE(Fixture, "while_do_semicolon")
833
{
834
std::string code = R"(
835
while true do
836
end;
837
)";
838
CHECK_EQ(code, prettyPrint(code, {}, true).code);
839
}
840
841
TEST_CASE_FIXTURE(Fixture, "function_definition_semicolon")
842
{
843
std::string code = R"(
844
function foo()
845
end;
846
)";
847
CHECK_EQ(code, prettyPrint(code, {}, true).code);
848
}
849
850
TEST_CASE("roundtrip_types")
851
{
852
const std::string code = R"(
853
local s:string='str'
854
local t:{a:string,b:number,[string]:number}
855
local fn:(string,string)->(number,number)
856
local s2:typeof(s)='foo'
857
local os:string?
858
local sn:string|number
859
local it:{x:number}&{y:number}
860
)";
861
auto allocator = Allocator{};
862
auto names = AstNameTable{allocator};
863
864
ParseOptions options;
865
866
ParseResult parseResult = Parser::parse(code.data(), code.size(), names, allocator, options);
867
REQUIRE(parseResult.errors.empty());
868
869
CHECK_EQ(code, prettyPrintWithTypes(*parseResult.root));
870
}
871
872
TEST_CASE("roundtrip_generic_types")
873
{
874
const std::string code = R"(
875
export type A<T> = {v:T, next:A<T>}
876
)";
877
auto allocator = Allocator{};
878
auto names = AstNameTable{allocator};
879
880
ParseOptions options;
881
882
ParseResult parseResult = Parser::parse(code.data(), code.size(), names, allocator, options);
883
REQUIRE(parseResult.errors.empty());
884
885
CHECK_EQ(code, prettyPrintWithTypes(*parseResult.root));
886
}
887
888
TEST_CASE_FIXTURE(Fixture, "attach_types")
889
{
890
const std::string code = R"(
891
local s='str'
892
local t={a=1,b=false}
893
local function fn()
894
return 10
895
end
896
)";
897
const std::string expected = R"(
898
local s:string='str'
899
local t:{a:number,b:boolean}={a=1,b=false}
900
local function fn(): number
901
return 10
902
end
903
)";
904
905
CHECK_EQ(expected, decorateWithTypes(code));
906
}
907
908
TEST_CASE("a_table_key_can_be_the_empty_string")
909
{
910
std::string code = "local T = {[''] = true}";
911
912
CHECK_EQ(code, prettyPrint(code).code);
913
}
914
915
// There's a bit of login in the prettyPrintr that always adds a space before a dot if the previous symbol ends in a digit.
916
// This was surfacing an issue where we might not insert a space after the 'local' keyword.
917
TEST_CASE("always_emit_a_space_after_local_keyword")
918
{
919
std::string code = "do local aZZZZ = Workspace.P1.Shape local bZZZZ = Enum.PartType.Cylinder end";
920
CHECK_EQ(code, prettyPrint(code).code);
921
}
922
923
TEST_CASE_FIXTURE(Fixture, "types_should_not_be_considered_cyclic_if_they_are_not_recursive")
924
{
925
std::string code = R"(
926
local common: {foo:string} = {foo = 'foo'}
927
928
local t = {}
929
t.x = common
930
t.y = common
931
)";
932
933
std::string expected = R"(
934
local common: {foo:string} = {foo = 'foo'}
935
936
local t:{x:{foo:string},y:{foo:string}}={}
937
t.x = common
938
t.y = common
939
)";
940
941
CHECK_EQ(expected, decorateWithTypes(code));
942
}
943
944
TEST_CASE_FIXTURE(Fixture, "type_lists_should_be_emitted_correctly")
945
{
946
std::string code = R"(
947
local a = function(a: string, b: number, ...: string): (string, ...number)
948
end
949
950
local b = function(...: string): ...number
951
end
952
953
local c = function()
954
end
955
)";
956
957
std::string expected = R"(
958
local a:(a:string,b:number,...string)->(string,...number)=function(a:string,b:number,...:string): (string,...number)
959
end
960
961
local b:(...string)->(...number)=function(...:string): ...number
962
end
963
964
local c:()->()=function(): ()
965
end
966
)";
967
968
std::string actual = decorateWithTypes(code);
969
970
CHECK_EQ(expected, actual);
971
}
972
973
TEST_CASE_FIXTURE(Fixture, "function_type_location")
974
{
975
std::string code = R"(
976
local function foo(x: number): number
977
return x
978
end
979
local g: (number)->number = foo
980
)";
981
982
std::string expected = R"(
983
local function foo(x: number): number
984
return x
985
end
986
local g: (number)->(number)=foo
987
)";
988
989
std::string actual = decorateWithTypes(code);
990
991
CHECK_EQ(expected, actual);
992
}
993
994
TEST_CASE_FIXTURE(Fixture, "prettyPrint_type_assertion")
995
{
996
std::string code = "local a = 5 :: number";
997
998
CHECK_EQ(code, prettyPrint(code, {}, true).code);
999
}
1000
1001
TEST_CASE_FIXTURE(Fixture, "type_assertion_spaces_around_tokens")
1002
{
1003
std::string code = "local a = 5 :: number";
1004
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1005
1006
code = "local a = 5 :: number";
1007
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1008
}
1009
1010
TEST_CASE_FIXTURE(Fixture, "prettyPrint_if_then_else")
1011
{
1012
std::string code = "local a = if 1 then 2 else 3";
1013
1014
CHECK_EQ(code, prettyPrint(code).code);
1015
}
1016
1017
TEST_CASE_FIXTURE(Fixture, "prettyPrint_if_then_else_multiple_conditions")
1018
{
1019
std::string code = "local a = if 1 then 2 elseif 3 then 4 else 5";
1020
1021
CHECK_EQ(code, prettyPrint(code).code);
1022
}
1023
1024
TEST_CASE_FIXTURE(Fixture, "prettyPrint_if_then_else_multiple_conditions_2")
1025
{
1026
std::string code = R"(
1027
local x = if yes
1028
then nil
1029
else if no
1030
then if this
1031
then that
1032
else other
1033
else nil
1034
)";
1035
1036
CHECK_EQ(code, prettyPrint(code).code);
1037
}
1038
1039
TEST_CASE_FIXTURE(Fixture, "if_then_else_spaces_around_tokens")
1040
{
1041
std::string code = "local a = if 1 then 2 else 3";
1042
CHECK_EQ(code, prettyPrint(code).code);
1043
1044
code = "local a = if 1 then 2 else 3";
1045
CHECK_EQ(code, prettyPrint(code).code);
1046
1047
code = "local a = if 1 then 2 else 3";
1048
CHECK_EQ(code, prettyPrint(code).code);
1049
1050
code = "local a = if 1 then 2 else 3";
1051
CHECK_EQ(code, prettyPrint(code).code);
1052
1053
code = "local a = if 1 then 2 else 3";
1054
CHECK_EQ(code, prettyPrint(code).code);
1055
1056
code = "local a = if 1 then 2 elseif 3 then 4 else 5";
1057
CHECK_EQ(code, prettyPrint(code).code);
1058
1059
code = "local a = if 1 then 2 elseif 3 then 4 else 5";
1060
CHECK_EQ(code, prettyPrint(code).code);
1061
1062
code = "local a = if 1 then 2 elseif 3 then 4 else 5";
1063
CHECK_EQ(code, prettyPrint(code).code);
1064
1065
code = "local a = if 1 then 2 elseif 3 then 4 else 5";
1066
CHECK_EQ(code, prettyPrint(code).code);
1067
1068
code = "local a = if 1 then 2 elseif 3 then 4 else 5";
1069
CHECK_EQ(code, prettyPrint(code).code);
1070
1071
code = "local a = if 1 then 2 elseif 3 then 4 else 5";
1072
CHECK_EQ(code, prettyPrint(code).code);
1073
}
1074
1075
TEST_CASE_FIXTURE(Fixture, "if_then_else_spaces_between_else_if")
1076
{
1077
std::string code = R"(
1078
return
1079
if a then "was a" else
1080
if b then "was b" else
1081
if c then "was c" else
1082
"was nothing!"
1083
)";
1084
CHECK_EQ(code, prettyPrint(code).code);
1085
}
1086
1087
TEST_CASE_FIXTURE(Fixture, "prettyPrint_type_reference_import")
1088
{
1089
fileResolver.source["game/A"] = R"(
1090
export type Type = { a: number }
1091
return {}
1092
)";
1093
1094
std::string code = R"(
1095
local Import = require(game.A)
1096
local a: Import.Type
1097
)";
1098
1099
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1100
}
1101
1102
TEST_CASE_FIXTURE(Fixture, "prettyPrint_type_reference_spaces_around_tokens")
1103
{
1104
std::string code = R"( local _: Foo.Type )";
1105
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1106
1107
code = R"( local _: Foo .Type )";
1108
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1109
1110
code = R"( local _: Foo. Type )";
1111
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1112
1113
code = R"( local _: Type <> )";
1114
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1115
1116
code = R"( local _: Type< > )";
1117
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1118
1119
code = R"( local _: Type< number> )";
1120
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1121
1122
code = R"( local _: Type<number ,string> )";
1123
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1124
1125
code = R"( local _: Type<number, string > )";
1126
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1127
}
1128
1129
TEST_CASE_FIXTURE(Fixture, "prettyPrint_type_annotation_spaces_around_tokens")
1130
{
1131
std::string code = R"( local _: Type )";
1132
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1133
1134
code = R"( local _ : Type )";
1135
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1136
1137
code = R"( local _: Type )";
1138
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1139
1140
code = R"( local x: Type, y = 1 )";
1141
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1142
1143
code = R"( local x : Type, y = 1 )";
1144
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1145
}
1146
1147
TEST_CASE_FIXTURE(Fixture, "prettyPrint_for_loop_annotation_spaces_around_tokens")
1148
{
1149
std::string code = R"( for i: number = 1, 10 do end )";
1150
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1151
1152
code = R"( for i : number = 1, 10 do end )";
1153
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1154
1155
code = R"( for i: number = 1, 10 do end )";
1156
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1157
1158
code = R"( for x: number, y: number in ... do end )";
1159
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1160
1161
code = R"( for x : number, y: number in ... do end )";
1162
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1163
1164
code = R"( for x: number, y: number in ... do end )";
1165
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1166
1167
code = R"( for x: number, y : number in ... do end )";
1168
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1169
1170
code = R"( for x: number, y: number in ... do end )";
1171
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1172
}
1173
1174
TEST_CASE_FIXTURE(Fixture, "prettyPrint_type_packs")
1175
{
1176
std::string code = R"(
1177
type Packed<T...> = (T...)->(T...)
1178
local a: Packed<>
1179
local b: Packed<(number, string)>
1180
)";
1181
1182
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1183
}
1184
1185
TEST_CASE_FIXTURE(Fixture, "type_packs_spaces_around_tokens")
1186
{
1187
std::string code = R"( type _ = Packed< T...> )";
1188
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1189
1190
code = R"( type _ = Packed<T ...> )";
1191
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1192
1193
code = R"( type _ = Packed< ...T> )";
1194
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1195
1196
code = R"( type _ = Packed<... T> )";
1197
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1198
1199
code = R"( type _ = Packed< ()> )";
1200
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1201
1202
code = R"( type _ = Packed< (string, number)> )";
1203
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1204
1205
code = R"( type _ = Packed<( string, number)> )";
1206
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1207
1208
code = R"( type _ = Packed<(string , number)> )";
1209
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1210
1211
code = R"( type _ = Packed<(string, number)> )";
1212
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1213
1214
code = R"( type _ = Packed<(string, number )> )";
1215
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1216
1217
code = R"( type _ = Packed<(string, number) > )";
1218
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1219
1220
code = R"( type _ = Packed<( )> )";
1221
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1222
1223
code = R"( type _ = Packed<() > )";
1224
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1225
}
1226
1227
TEST_CASE_FIXTURE(Fixture, "prettyPrint_union_type_nested")
1228
{
1229
std::string code = "local a: ((number)->(string))|((string)->(string))";
1230
1231
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1232
}
1233
1234
TEST_CASE_FIXTURE(Fixture, "prettyPrint_union_type_nested_2")
1235
{
1236
std::string code = "local a: (number&string)|(string&boolean)";
1237
1238
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1239
}
1240
1241
TEST_CASE_FIXTURE(Fixture, "prettyPrint_union_type_nested_3")
1242
{
1243
std::string code = "local a: nil | (string & number)";
1244
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1245
}
1246
1247
TEST_CASE_FIXTURE(Fixture, "prettyPrint_intersection_type_nested")
1248
{
1249
std::string code = "local a: ((number)->(string))&((string)->(string))";
1250
1251
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1252
}
1253
1254
TEST_CASE_FIXTURE(Fixture, "prettyPrint_intersection_type_nested_2")
1255
{
1256
std::string code = "local a: (number|string)&(string|boolean)";
1257
1258
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1259
}
1260
1261
TEST_CASE_FIXTURE(Fixture, "prettyPrint_intersection_type_with_function")
1262
{
1263
std::string code = "type FnB<U...> = () -> U... & T";
1264
1265
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1266
}
1267
1268
TEST_CASE_FIXTURE(Fixture, "prettyPrint_leading_union_pipe")
1269
{
1270
std::string code = "local a: | string | number";
1271
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1272
1273
code = "local a: | string";
1274
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1275
}
1276
1277
TEST_CASE_FIXTURE(Fixture, "prettyPrint_union_spaces_around_tokens")
1278
{
1279
std::string code = "local a: string | number";
1280
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1281
1282
code = "local a: string | number";
1283
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1284
}
1285
1286
TEST_CASE_FIXTURE(Fixture, "prettyPrint_leading_intersection_ampersand")
1287
{
1288
std::string code = "local a: & string & number";
1289
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1290
1291
code = "local a: & string";
1292
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1293
}
1294
1295
TEST_CASE_FIXTURE(Fixture, "prettyPrint_intersection_spaces_around_tokens")
1296
{
1297
std::string code = "local a: string & number";
1298
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1299
1300
code = "local a: string & number";
1301
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1302
}
1303
1304
TEST_CASE_FIXTURE(Fixture, "prettyPrint_mixed_union_intersection")
1305
{
1306
std::string code = "local a: string | (Foo & Bar)";
1307
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1308
1309
code = "local a: string | (Foo & Bar)";
1310
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1311
1312
code = "local a: string | ( Foo & Bar)";
1313
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1314
1315
code = "local a: string | (Foo & Bar )";
1316
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1317
1318
code = "local a: string & (Foo | Bar)";
1319
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1320
1321
code = "local a: string & ( Foo | Bar)";
1322
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1323
1324
code = "local a: string & (Foo | Bar )";
1325
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1326
}
1327
1328
TEST_CASE_FIXTURE(Fixture, "prettyPrint_preserve_union_optional_style")
1329
{
1330
std::string code = "local a: string | nil";
1331
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1332
1333
code = "local a: string?";
1334
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1335
1336
code = "local a: string???";
1337
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1338
1339
code = "local a: string? | nil";
1340
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1341
1342
code = "local a: string | nil | number";
1343
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1344
1345
code = "local a: string | nil | number?";
1346
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1347
1348
code = "local a: string? | number?";
1349
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1350
}
1351
1352
TEST_CASE_FIXTURE(Fixture, "prettyPrint_varargs")
1353
{
1354
std::string code = "local function f(...) return ... end";
1355
1356
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1357
}
1358
1359
TEST_CASE_FIXTURE(Fixture, "index_name_spaces_around_tokens")
1360
{
1361
std::string one = "local _ = a.name";
1362
CHECK_EQ(one, prettyPrint(one, {}, true).code);
1363
1364
std::string two = "local _ = a .name";
1365
CHECK_EQ(two, prettyPrint(two, {}, true).code);
1366
1367
std::string three = "local _ = a. name";
1368
CHECK_EQ(three, prettyPrint(three, {}, true).code);
1369
}
1370
1371
TEST_CASE_FIXTURE(Fixture, "index_name_ends_with_digit")
1372
{
1373
std::string code = "sparkles.Color = Color3.new()";
1374
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1375
}
1376
1377
TEST_CASE_FIXTURE(Fixture, "prettyPrint_index_expr")
1378
{
1379
std::string code = "local a = {1, 2, 3} local b = a[2]";
1380
1381
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1382
}
1383
1384
TEST_CASE_FIXTURE(Fixture, "index_expr_spaces_around_tokens")
1385
{
1386
std::string one = "local _ = a[2]";
1387
CHECK_EQ(one, prettyPrint(one, {}, true).code);
1388
1389
std::string two = "local _ = a [2]";
1390
CHECK_EQ(two, prettyPrint(two, {}, true).code);
1391
1392
std::string three = "local _ = a[ 2]";
1393
CHECK_EQ(three, prettyPrint(three, {}, true).code);
1394
1395
std::string four = "local _ = a[2 ]";
1396
CHECK_EQ(four, prettyPrint(four, {}, true).code);
1397
}
1398
1399
TEST_CASE_FIXTURE(Fixture, "prettyPrint_unary")
1400
{
1401
std::string code = R"(
1402
local a = 1
1403
local b = -1
1404
local c = true
1405
local d = not c
1406
local e = 'hello'
1407
local d = #e
1408
)";
1409
1410
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1411
}
1412
1413
TEST_CASE_FIXTURE(Fixture, "unary_spaces_around_tokens")
1414
{
1415
std::string code = R"(
1416
local _ = -1
1417
local _ = - 1
1418
local _ = not true
1419
local _ = not true
1420
local _ = #e
1421
local _ = # e
1422
)";
1423
1424
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1425
}
1426
1427
TEST_CASE_FIXTURE(Fixture, "binary_spaces_around_tokens")
1428
{
1429
std::string code = R"(
1430
local _ = 1+1
1431
local _ = 1 +1
1432
local _ = 1+ 1
1433
)";
1434
1435
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1436
}
1437
1438
TEST_CASE_FIXTURE(Fixture, "prettyPrint_break_continue")
1439
{
1440
std::string code = R"(
1441
local a, b, c
1442
repeat
1443
if a then break end
1444
if b then continue end
1445
until c
1446
)";
1447
1448
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1449
}
1450
1451
TEST_CASE_FIXTURE(Fixture, "prettyPrint_compound_assignment")
1452
{
1453
std::string code = R"(
1454
local a = 1
1455
a += 2
1456
a -= 3
1457
a *= 4
1458
a /= 5
1459
a //= 5
1460
a %= 6
1461
a ^= 7
1462
a ..= ' - result'
1463
)";
1464
1465
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1466
}
1467
1468
TEST_CASE_FIXTURE(Fixture, "compound_assignment_spaces_around_tokens")
1469
{
1470
std::string one = R"( a += 1 )";
1471
CHECK_EQ(one, prettyPrint(one, {}, true).code);
1472
1473
std::string two = R"( a += 1 )";
1474
CHECK_EQ(two, prettyPrint(two, {}, true).code);
1475
}
1476
1477
TEST_CASE_FIXTURE(Fixture, "prettyPrint_assign_multiple")
1478
{
1479
std::string code = "a, b, c = 1, 2, 3";
1480
1481
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1482
}
1483
1484
TEST_CASE_FIXTURE(Fixture, "prettyPrint_assign_spaces_around_tokens")
1485
{
1486
std::string one = "a = 1";
1487
CHECK_EQ(one, prettyPrint(one).code);
1488
1489
std::string two = "a = 1";
1490
CHECK_EQ(two, prettyPrint(two).code);
1491
1492
std::string three = "a = 1";
1493
CHECK_EQ(three, prettyPrint(three).code);
1494
1495
std::string four = "a , b = 1, 2";
1496
CHECK_EQ(four, prettyPrint(four).code);
1497
1498
std::string five = "a, b = 1, 2";
1499
CHECK_EQ(five, prettyPrint(five).code);
1500
1501
std::string six = "a, b = 1 , 2";
1502
CHECK_EQ(six, prettyPrint(six).code);
1503
1504
std::string seven = "a, b = 1, 2";
1505
CHECK_EQ(seven, prettyPrint(seven).code);
1506
}
1507
1508
TEST_CASE_FIXTURE(Fixture, "prettyPrint_generic_function")
1509
{
1510
std::string code = R"(
1511
local function foo<T,S...>(a: T, ...: S...) return 1 end
1512
local f: <T,S...>(T, S...)->(number) = foo
1513
)";
1514
1515
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1516
}
1517
1518
TEST_CASE_FIXTURE(Fixture, "prettyPrint_union_reverse")
1519
{
1520
std::string code = "local a: nil | number";
1521
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1522
}
1523
1524
TEST_CASE_FIXTURE(Fixture, "prettyPrint_for_in_multiple")
1525
{
1526
std::string code = "for k,v in next,{}do print(k,v) end";
1527
1528
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1529
}
1530
1531
TEST_CASE_FIXTURE(Fixture, "prettyPrint_error_expr")
1532
{
1533
std::string code = "local a = f:-";
1534
1535
auto allocator = Allocator{};
1536
auto names = AstNameTable{allocator};
1537
ParseResult parseResult = Parser::parse(code.data(), code.size(), names, allocator, {});
1538
1539
CHECK_EQ("local a = (error-expr: f:%error-id%)-(error-expr)", prettyPrintWithTypes(*parseResult.root));
1540
}
1541
1542
TEST_CASE_FIXTURE(Fixture, "prettyPrint_error_stat")
1543
{
1544
std::string code = "-";
1545
1546
auto allocator = Allocator{};
1547
auto names = AstNameTable{allocator};
1548
ParseResult parseResult = Parser::parse(code.data(), code.size(), names, allocator, {});
1549
1550
CHECK_EQ("(error-stat: (error-expr))", prettyPrintWithTypes(*parseResult.root));
1551
}
1552
1553
TEST_CASE_FIXTURE(Fixture, "prettyPrint_error_type")
1554
{
1555
std::string code = "local a: ";
1556
1557
auto allocator = Allocator{};
1558
auto names = AstNameTable{allocator};
1559
ParseResult parseResult = Parser::parse(code.data(), code.size(), names, allocator, {});
1560
1561
CHECK_EQ("local a:%error-type%", prettyPrintWithTypes(*parseResult.root));
1562
}
1563
1564
TEST_CASE_FIXTURE(Fixture, "prettyPrint_parse_error")
1565
{
1566
std::string code = "local a = -";
1567
1568
auto result = prettyPrint(code);
1569
CHECK_EQ("", result.code);
1570
CHECK_EQ("Expected identifier when parsing expression, got <eof>", result.parseError);
1571
}
1572
1573
TEST_CASE_FIXTURE(Fixture, "prettyPrint_declare_global_stat")
1574
{
1575
std::string code = "declare _G: any";
1576
1577
ParseOptions options;
1578
options.allowDeclarationSyntax = true;
1579
1580
auto allocator = Allocator{};
1581
auto names = AstNameTable{allocator};
1582
ParseResult parseResult = Parser::parse(code.data(), code.size(), names, allocator, options);
1583
1584
auto result = prettyPrintWithTypes(*parseResult.root);
1585
1586
CHECK_EQ(result, code);
1587
}
1588
1589
TEST_CASE_FIXTURE(Fixture, "prettyPrint_to_string")
1590
{
1591
std::string code = "local a: string = 'hello'";
1592
1593
auto allocator = Allocator{};
1594
auto names = AstNameTable{allocator};
1595
ParseResult parseResult = Parser::parse(code.data(), code.size(), names, allocator, {});
1596
1597
REQUIRE(parseResult.root);
1598
REQUIRE(parseResult.root->body.size == 1);
1599
AstStatLocal* statLocal = parseResult.root->body.data[0]->as<AstStatLocal>();
1600
REQUIRE(statLocal);
1601
CHECK_EQ("local a: string = 'hello'", toString(statLocal));
1602
REQUIRE(statLocal->vars.size == 1);
1603
AstLocal* local = statLocal->vars.data[0];
1604
REQUIRE(local->annotation);
1605
CHECK_EQ("string", toString(local->annotation));
1606
REQUIRE(statLocal->values.size == 1);
1607
AstExpr* expr = statLocal->values.data[0];
1608
CHECK_EQ("'hello'", toString(expr));
1609
}
1610
1611
TEST_CASE_FIXTURE(Fixture, "prettyPrint_type_alias_default_type_parameters")
1612
{
1613
std::string code = R"(
1614
type Packed<T = string, U = T, V... = ...boolean, W... = (T, U, V...)> = (T, U, V...)->(W...)
1615
local a: Packed<number>
1616
)";
1617
1618
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1619
}
1620
1621
TEST_CASE_FIXTURE(Fixture, "prettyPrint_singleton_types")
1622
{
1623
std::string code = R"(
1624
type t1 = 'hello'
1625
type t2 = true
1626
type t3 = ''
1627
type t4 = false
1628
)";
1629
1630
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1631
}
1632
1633
TEST_CASE_FIXTURE(Fixture, "prettyPrint_array_types")
1634
{
1635
std::string code = R"(
1636
type t1 = {number}
1637
type t2 = {[string]: number}
1638
)";
1639
1640
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1641
}
1642
1643
TEST_CASE_FIXTURE(Fixture, "prettyPrint_for_in_multiple_types")
1644
{
1645
std::string code = "for k:string,v:boolean in next,{}do end";
1646
1647
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1648
}
1649
1650
TEST_CASE_FIXTURE(Fixture, "prettyPrint_string_interp")
1651
{
1652
std::string code = R"( local _ = `hello {name}` )";
1653
1654
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1655
}
1656
1657
TEST_CASE_FIXTURE(Fixture, "prettyPrint_string_interp_multiline")
1658
{
1659
std::string code = R"( local _ = `hello {
1660
name
1661
}!` )";
1662
1663
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1664
}
1665
1666
TEST_CASE_FIXTURE(Fixture, "prettyPrint_string_interp_on_new_line")
1667
{
1668
std::string code = R"(
1669
error(
1670
`a {b} c`
1671
)
1672
)";
1673
1674
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1675
}
1676
1677
TEST_CASE_FIXTURE(Fixture, "prettyPrint_string_interp_multiline_escape")
1678
{
1679
std::string code = R"( local _ = `hello \
1680
world!` )";
1681
1682
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1683
}
1684
1685
TEST_CASE_FIXTURE(Fixture, "prettyPrint_string_literal_escape")
1686
{
1687
std::string code = R"( local _ = ` bracket = \{, backtick = \` = {'ok'} ` )";
1688
1689
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1690
}
1691
1692
TEST_CASE_FIXTURE(Fixture, "prettyPrint_type_functions")
1693
{
1694
std::string code = R"( type function foo(arg1, arg2) if arg1 == arg2 then return arg1 end return arg2 end )";
1695
1696
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1697
}
1698
1699
TEST_CASE_FIXTURE(Fixture, "prettyPrint_type_functions_spaces_around_tokens")
1700
{
1701
std::string code = R"( type function foo() end )";
1702
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1703
1704
code = R"( type function foo() end )";
1705
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1706
1707
code = R"( type function foo () end )";
1708
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1709
1710
code = R"( export type function foo() end )";
1711
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1712
}
1713
1714
TEST_CASE_FIXTURE(Fixture, "prettyPrint_typeof_spaces_around_tokens")
1715
{
1716
std::string code = R"( type X = typeof(x) )";
1717
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1718
1719
code = R"( type X = typeof(x) )";
1720
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1721
1722
code = R"( type X = typeof (x) )";
1723
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1724
1725
code = R"( type X = typeof( x) )";
1726
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1727
1728
code = R"( type X = typeof(x ) )";
1729
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1730
}
1731
1732
TEST_CASE("prettyPrint_single_quoted_string_types")
1733
{
1734
const std::string code = R"( type a = 'hello world' )";
1735
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1736
}
1737
1738
TEST_CASE("prettyPrint_double_quoted_string_types")
1739
{
1740
const std::string code = R"( type a = "hello world" )";
1741
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1742
}
1743
1744
TEST_CASE("prettyPrint_raw_string_types")
1745
{
1746
std::string code = R"( type a = [[ hello world ]] )";
1747
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1748
1749
code = R"( type a = [==[ hello world ]==] )";
1750
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1751
}
1752
1753
TEST_CASE("prettyPrint_escaped_string_types")
1754
{
1755
const std::string code = R"( type a = "\\b\\t\\n\\\\" )";
1756
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1757
}
1758
1759
TEST_CASE("prettyPrint_type_table_semicolon_separators")
1760
{
1761
const std::string code = R"(
1762
type Foo = {
1763
bar: number;
1764
baz: number;
1765
}
1766
)";
1767
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1768
}
1769
1770
TEST_CASE("prettyPrint_type_table_access_modifiers")
1771
{
1772
std::string code = R"(
1773
type Foo = {
1774
read bar: number,
1775
write baz: number,
1776
}
1777
)";
1778
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1779
1780
code = R"( type Foo = { read string } )";
1781
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1782
1783
code = R"( type Foo = {
1784
read [string]: number,
1785
read ["property"]: number
1786
} )";
1787
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1788
}
1789
1790
TEST_CASE("prettyPrint_type_table_spaces_between_tokens")
1791
{
1792
std::string code = R"( type Foo = { bar: number, } )";
1793
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1794
1795
code = R"( type Foo = { bar: number, } )";
1796
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1797
1798
code = R"( type Foo = { bar : number, } )";
1799
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1800
1801
code = R"( type Foo = { bar: number, } )";
1802
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1803
1804
code = R"( type Foo = { bar: number , } )";
1805
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1806
1807
code = R"( type Foo = { bar: number, } )";
1808
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1809
1810
code = R"( type Foo = { bar: number } )";
1811
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1812
1813
code = R"( type Foo = { [string]: number } )";
1814
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1815
1816
code = R"( type Foo = { [string]: number } )";
1817
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1818
1819
code = R"( type Foo = { [ string]: number } )";
1820
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1821
1822
code = R"( type Foo = { [string ]: number } )";
1823
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1824
1825
code = R"( type Foo = { [string] : number } )";
1826
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1827
1828
code = R"( type Foo = { [string]: number } )";
1829
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1830
}
1831
1832
TEST_CASE("prettyPrint_type_table_preserve_original_indexer_style")
1833
{
1834
std::string code = R"(
1835
type Foo = {
1836
[number]: string
1837
}
1838
)";
1839
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1840
1841
code = R"(
1842
type Foo = { { number } }
1843
)";
1844
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1845
}
1846
1847
TEST_CASE("prettyPrint_type_table_preserve_indexer_location")
1848
{
1849
std::string code = R"(
1850
type Foo = {
1851
[number]: string,
1852
property: number,
1853
}
1854
)";
1855
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1856
1857
code = R"(
1858
type Foo = {
1859
property: number,
1860
[number]: string,
1861
}
1862
)";
1863
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1864
1865
code = R"(
1866
type Foo = {
1867
property: number,
1868
[number]: string,
1869
property2: number,
1870
}
1871
)";
1872
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1873
}
1874
1875
TEST_CASE("prettyPrint_type_table_preserve_property_definition_style")
1876
{
1877
std::string code = R"(
1878
type Foo = {
1879
["$$typeof1"]: string,
1880
['$$typeof2']: string,
1881
}
1882
)";
1883
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1884
}
1885
1886
TEST_CASE("prettyPrint_type_table_string_properties_spaces_between_tokens")
1887
{
1888
std::string code = R"(
1889
type Foo = {
1890
[ "$$typeof1"]: string,
1891
['$$typeof2' ]: string,
1892
}
1893
)";
1894
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1895
}
1896
1897
TEST_CASE("prettyPrint_types_preserve_parentheses_style")
1898
{
1899
std::string code = R"( type Foo = number )";
1900
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1901
1902
code = R"( type Foo = (number) )";
1903
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1904
1905
code = R"( type Foo = ((number)) )";
1906
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1907
1908
code = R"( type Foo = ( (number) ) )";
1909
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1910
}
1911
1912
TEST_CASE("fuzzer_prettyPrint_with_zero_location")
1913
{
1914
const std::string example = R"(
1915
if _ then
1916
elseif _ then
1917
elseif l0 then
1918
else
1919
local function l0<t0>(...):(t0<t0...>,(any)|(<t0>((any)|(<t0>(""[[[[[[[[[[[[[[[[[[[[[[[[!*t")->()))->()))
1920
end
1921
end
1922
)";
1923
1924
Luau::ParseOptions parseOptions;
1925
parseOptions.captureComments = true;
1926
1927
auto allocator = std::make_unique<Luau::Allocator>();
1928
auto names = std::make_unique<Luau::AstNameTable>(*allocator);
1929
ParseResult parseResult = Parser::parse(example.data(), example.size(), *names, *allocator, parseOptions);
1930
1931
prettyPrintWithTypes(*parseResult.root);
1932
}
1933
1934
TEST_CASE("prettyPrint_type_function_unnamed_arguments")
1935
{
1936
std::string code = R"( type Foo = () -> () )";
1937
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1938
1939
code = R"( type Foo = () -> () )";
1940
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1941
1942
code = R"( type Foo = (string) -> () )";
1943
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1944
1945
code = R"( type Foo = (string, number) -> () )";
1946
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1947
1948
code = R"( type Foo = ( string, number) -> () )";
1949
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1950
1951
code = R"( type Foo = (string , number) -> () )";
1952
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1953
1954
code = R"( type Foo = (string, number) -> () )";
1955
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1956
1957
code = R"( type Foo = (string, number ) -> () )";
1958
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1959
1960
code = R"( type Foo = (string, number) -> () )";
1961
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1962
1963
code = R"( type Foo = (string, number) -> () )";
1964
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1965
}
1966
1967
TEST_CASE("prettyPrint_type_function_named_arguments")
1968
{
1969
std::string code = R"( type Foo = (x: string) -> () )";
1970
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1971
1972
code = R"( type Foo = (x: string, y: number) -> () )";
1973
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1974
1975
code = R"( type Foo = ( x: string, y: number) -> () )";
1976
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1977
1978
code = R"( type Foo = (x : string, y: number) -> () )";
1979
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1980
1981
code = R"( type Foo = (x: string, y: number) -> () )";
1982
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1983
1984
code = R"( type Foo = (x: string, y: number) -> () )";
1985
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1986
1987
code = R"( type Foo = (number, info: string) -> () )";
1988
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1989
1990
code = R"( type Foo = (first: string, second: string, ...string) -> () )";
1991
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1992
}
1993
1994
TEST_CASE("prettyPrint_type_function_generics")
1995
{
1996
std::string code = R"( type Foo = <X, Y, Z...>() -> () )";
1997
CHECK_EQ(code, prettyPrint(code, {}, true).code);
1998
1999
code = R"( type Foo = <X, Y, Z...>() -> () )";
2000
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2001
2002
code = R"( type Foo = < X, Y, Z...>() -> () )";
2003
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2004
2005
code = R"( type Foo = <X , Y, Z...>() -> () )";
2006
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2007
2008
code = R"( type Foo = <X, Y, Z...>() -> () )";
2009
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2010
2011
code = R"( type Foo = <X, Y , Z...>() -> () )";
2012
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2013
2014
code = R"( type Foo = <X, Y, Z...>() -> () )";
2015
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2016
2017
code = R"( type Foo = <X, Y, Z ...>() -> () )";
2018
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2019
2020
code = R"( type Foo = <X, Y, Z... >() -> () )";
2021
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2022
2023
code = R"( type Foo = <X, Y, Z...> () -> () )";
2024
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2025
}
2026
2027
TEST_CASE("prettyPrint_type_function_return_types")
2028
{
2029
std::string code = R"( type Foo = () -> () )";
2030
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2031
2032
code = R"( type Foo = () -> ( ) )";
2033
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2034
2035
code = R"( type Foo = () -> string )";
2036
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2037
2038
code = R"( type Foo = () -> string )";
2039
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2040
2041
code = R"( type Foo = () -> (string) )";
2042
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2043
2044
code = R"( type Foo = () -> (string) )";
2045
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2046
2047
code = R"( type Foo = () -> ...any )";
2048
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2049
2050
code = R"( type Foo = () -> ...any )";
2051
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2052
2053
code = R"( type Foo = () -> ... any )";
2054
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2055
2056
code = R"( type Foo = () -> (...any) )";
2057
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2058
2059
code = R"( type Foo = () -> ( string, number) )";
2060
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2061
2062
code = R"( type Foo = () -> (string , number) )";
2063
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2064
2065
code = R"( type Foo = () -> (string, number) )";
2066
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2067
2068
code = R"( type Foo = () -> (string, number ) )";
2069
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2070
}
2071
2072
TEST_CASE("prettyPrint_chained_function_types")
2073
{
2074
std::string code = R"( type Foo = () -> () -> () )";
2075
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2076
2077
code = R"( type Foo = () -> () -> () )";
2078
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2079
2080
code = R"( type Foo = () -> () -> () )";
2081
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2082
}
2083
2084
TEST_CASE("fuzzer_nil_optional")
2085
{
2086
const std::string code = R"( local x: nil? )";
2087
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2088
}
2089
2090
TEST_CASE("prettyPrint_function_attributes")
2091
{
2092
std::string code = R"(
2093
@native
2094
function foo()
2095
end
2096
)";
2097
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2098
2099
code = R"(
2100
@native
2101
local function foo()
2102
end
2103
)";
2104
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2105
2106
code = R"(
2107
@checked local function foo()
2108
end
2109
)";
2110
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2111
2112
code = R"(
2113
local foo = @native function() end
2114
)";
2115
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2116
2117
code = R"(
2118
@native
2119
function foo:bar()
2120
end
2121
)";
2122
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2123
2124
code = R"(
2125
@native @checked
2126
function foo:bar()
2127
end
2128
)";
2129
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2130
2131
{
2132
2133
ScopedFastFlag noInline{FFlag::DebugLuauNoInline, true};
2134
code = R"(
2135
@debugnoinline
2136
local function t() end
2137
)";
2138
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2139
}
2140
}
2141
2142
TEST_CASE("transpile_explicit_type_instantiations")
2143
{
2144
std::string code = "f<<A, B, C...>>() t.f<<A, B, C...>>() t:f<<A, B, C>>()";
2145
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2146
2147
Allocator allocator;
2148
AstNameTable names = {allocator};
2149
ParseResult parseResult = Parser::parse(code.data(), code.size(), names, allocator, {});
2150
REQUIRE(parseResult.errors.empty());
2151
CHECK_EQ(code, prettyPrintWithTypes(*parseResult.root));
2152
2153
// No types
2154
CHECK_EQ("f () t.f () t:f ()", prettyPrint(code).code);
2155
2156
code = "f < < A , B , C... > >( ) t.f < < A, B, C... > > ( ) t:f< < A, B, C > > ( )";
2157
CHECK_EQ(code, prettyPrint(code, {}, true).code);
2158
}
2159
2160
TEST_SUITE_END();
2161
2162