1//===- unittest/Format/FormatTestJS.cpp - Formatting unit tests for JS ----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "FormatTestUtils.h"
10#include "clang/Format/Format.h"
11#include "llvm/Support/Debug.h"
12#include "gtest/gtest.h"
13
14#define DEBUG_TYPE "format-test"
15
16namespace clang {
17namespace format {
18
19class FormatTestJS : public ::testing::Test {
20protected:
21 static std::string format(llvm::StringRef Code, unsigned Offset,
22 unsigned Length, const FormatStyle &Style) {
23 LLVM_DEBUG(llvm::errs() << "---\n");
24 LLVM_DEBUG(llvm::errs() << Code << "\n\n");
25 std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
26 FormattingAttemptStatus Status;
27 tooling::Replacements Replaces =
28 reformat(Style, Code, Ranges, FileName: "<stdin>", Status: &Status);
29 EXPECT_TRUE(Status.FormatComplete);
30 auto Result = applyAllReplacements(Code, Replaces);
31 EXPECT_TRUE(static_cast<bool>(Result));
32 LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
33 return *Result;
34 }
35
36 static std::string format(
37 llvm::StringRef Code,
38 const FormatStyle &Style = getGoogleStyle(Language: FormatStyle::LK_JavaScript)) {
39 return format(Code, Offset: 0, Length: Code.size(), Style);
40 }
41
42 static FormatStyle getGoogleJSStyleWithColumns(unsigned ColumnLimit) {
43 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_JavaScript);
44 Style.ColumnLimit = ColumnLimit;
45 return Style;
46 }
47
48 static void verifyFormat(
49 llvm::StringRef Code,
50 const FormatStyle &Style = getGoogleStyle(Language: FormatStyle::LK_JavaScript)) {
51 EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable";
52 std::string Result = format(Code: test::messUp(Code), Style);
53 EXPECT_EQ(Code.str(), Result) << "Formatted:\n" << Result;
54 }
55
56 static void verifyFormat(
57 llvm::StringRef Expected, llvm::StringRef Code,
58 const FormatStyle &Style = getGoogleStyle(Language: FormatStyle::LK_JavaScript)) {
59 EXPECT_EQ(Expected.str(), format(Expected, Style))
60 << "Expected code is not stable";
61 std::string Result = format(Code, Style);
62 EXPECT_EQ(Expected.str(), Result) << "Formatted:\n" << Result;
63 }
64};
65
66TEST_F(FormatTestJS, BlockComments) {
67 verifyFormat(Code: "/* aaaaaaaaaaaaa */ aaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
68 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
69 // Breaks after a single line block comment.
70 EXPECT_EQ("aaaaa = bbbb.ccccccccccccccc(\n"
71 " /** @type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala} */\n"
72 " mediaMessage);",
73 format("aaaaa = bbbb.ccccccccccccccc(\n"
74 " /** "
75 "@type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala} */ "
76 "mediaMessage);",
77 getGoogleJSStyleWithColumns(70)));
78 // Breaks after a multiline block comment.
79 EXPECT_EQ(
80 "aaaaa = bbbb.ccccccccccccccc(\n"
81 " /**\n"
82 " * @type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala}\n"
83 " */\n"
84 " mediaMessage);",
85 format("aaaaa = bbbb.ccccccccccccccc(\n"
86 " /**\n"
87 " * @type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala}\n"
88 " */ mediaMessage);",
89 getGoogleJSStyleWithColumns(70)));
90}
91
92TEST_F(FormatTestJS, JSDocComments) {
93 // Break the first line of a multiline jsdoc comment.
94 EXPECT_EQ("/**\n"
95 " * jsdoc line 1\n"
96 " * jsdoc line 2\n"
97 " */",
98 format("/** jsdoc line 1\n"
99 " * jsdoc line 2\n"
100 " */",
101 getGoogleJSStyleWithColumns(20)));
102 // Both break after '/**' and break the line itself.
103 EXPECT_EQ("/**\n"
104 " * jsdoc line long\n"
105 " * long jsdoc line 2\n"
106 " */",
107 format("/** jsdoc line long long\n"
108 " * jsdoc line 2\n"
109 " */",
110 getGoogleJSStyleWithColumns(20)));
111 // Break a short first line if the ending '*/' is on a newline.
112 EXPECT_EQ("/**\n"
113 " * jsdoc line 1\n"
114 " */",
115 format("/** jsdoc line 1\n"
116 " */",
117 getGoogleJSStyleWithColumns(20)));
118 // Don't break the first line of a short single line jsdoc comment.
119 verifyFormat(Code: "/** jsdoc line 1 */", Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
120 // Don't break the first line of a single line jsdoc comment if it just fits
121 // the column limit.
122 verifyFormat(Code: "/** jsdoc line 12 */", Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
123 // Don't break after '/**' and before '*/' if there is no space between
124 // '/**' and the content.
125 EXPECT_EQ(
126 "/*** nonjsdoc long\n"
127 " * line */",
128 format("/*** nonjsdoc long line */", getGoogleJSStyleWithColumns(20)));
129 EXPECT_EQ(
130 "/**strange long long\n"
131 " * line */",
132 format("/**strange long long line */", getGoogleJSStyleWithColumns(20)));
133 // Break the first line of a single line jsdoc comment if it just exceeds the
134 // column limit.
135 EXPECT_EQ("/**\n"
136 " * jsdoc line 123\n"
137 " */",
138 format("/** jsdoc line 123 */", getGoogleJSStyleWithColumns(20)));
139 // Break also if the leading indent of the first line is more than 1 column.
140 EXPECT_EQ("/**\n"
141 " * jsdoc line 123\n"
142 " */",
143 format("/** jsdoc line 123 */", getGoogleJSStyleWithColumns(20)));
144 // Break also if the leading indent of the first line is more than 1 column.
145 EXPECT_EQ("/**\n"
146 " * jsdoc line 123\n"
147 " */",
148 format("/** jsdoc line 123 */", getGoogleJSStyleWithColumns(20)));
149 // Break after the content of the last line.
150 EXPECT_EQ("/**\n"
151 " * line 1\n"
152 " * line 2\n"
153 " */",
154 format("/**\n"
155 " * line 1\n"
156 " * line 2 */",
157 getGoogleJSStyleWithColumns(20)));
158 // Break both the content and after the content of the last line.
159 EXPECT_EQ("/**\n"
160 " * line 1\n"
161 " * line long long\n"
162 " * long\n"
163 " */",
164 format("/**\n"
165 " * line 1\n"
166 " * line long long long */",
167 getGoogleJSStyleWithColumns(20)));
168
169 // The comment block gets indented.
170 EXPECT_EQ("function f() {\n"
171 " /**\n"
172 " * comment about\n"
173 " * x\n"
174 " */\n"
175 " var x = 1;\n"
176 "}",
177 format("function f() {\n"
178 "/** comment about x */\n"
179 "var x = 1;\n"
180 "}",
181 getGoogleJSStyleWithColumns(20)));
182
183 // Don't break the first line of a single line short jsdoc comment pragma.
184 verifyFormat(Code: "/** @returns j */", Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
185
186 // Break a single line long jsdoc comment pragma.
187 EXPECT_EQ("/**\n"
188 " * @returns {string}\n"
189 " * jsdoc line 12\n"
190 " */",
191 format("/** @returns {string} jsdoc line 12 */",
192 getGoogleJSStyleWithColumns(20)));
193
194 // FIXME: this overcounts the */ as a continuation of the 12 when breaking.
195 // Cf. BreakableBlockComment::getRemainingLength.
196 EXPECT_EQ("/**\n"
197 " * @returns {string}\n"
198 " * jsdoc line line\n"
199 " * 12\n"
200 " */",
201 format("/** @returns {string} jsdoc line line 12*/",
202 getGoogleJSStyleWithColumns(25)));
203
204 // Fix a multiline jsdoc comment ending in a comment pragma.
205 EXPECT_EQ("/**\n"
206 " * line 1\n"
207 " * line 2\n"
208 " * @returns {string}\n"
209 " * jsdoc line 12\n"
210 " */",
211 format("/** line 1\n"
212 " * line 2\n"
213 " * @returns {string} jsdoc line 12 */",
214 getGoogleJSStyleWithColumns(20)));
215
216 EXPECT_EQ("/**\n"
217 " * line 1\n"
218 " * line 2\n"
219 " *\n"
220 " * @returns j\n"
221 " */",
222 format("/** line 1\n"
223 " * line 2\n"
224 " *\n"
225 " * @returns j */",
226 getGoogleJSStyleWithColumns(20)));
227}
228
229TEST_F(FormatTestJS, UnderstandsJavaScriptOperators) {
230 verifyFormat(Code: "a == = b;");
231 verifyFormat(Code: "a != = b;");
232
233 verifyFormat(Code: "a === b;");
234 verifyFormat(Code: "aaaaaaa ===\n b;", Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
235 verifyFormat(Code: "a !== b;");
236 verifyFormat(Code: "aaaaaaa !==\n b;", Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
237 verifyFormat(Code: "if (a + b + c +\n"
238 " d !==\n"
239 " e + f + g)\n"
240 " q();",
241 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
242
243 verifyFormat(Code: "a >> >= b;");
244
245 verifyFormat(Code: "a >>> b;");
246 verifyFormat(Code: "aaaaaaa >>>\n b;", Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
247 verifyFormat(Code: "a >>>= b;");
248 verifyFormat(Code: "aaaaaaa >>>=\n b;", Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
249 verifyFormat(Code: "if (a + b + c +\n"
250 " d >>>\n"
251 " e + f + g)\n"
252 " q();",
253 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
254 verifyFormat(Code: "var x = aaaaaaaaaa ?\n"
255 " bbbbbb :\n"
256 " ccc;",
257 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
258
259 verifyFormat(Code: "var b = a.map((x) => x + 1);");
260 verifyFormat(Code: "return ('aaa') in bbbb;");
261 verifyFormat(Code: "var x = aaaaaaaaaaaaaaaaaaaaaaaaa() in\n"
262 " aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;");
263 FormatStyle Style = getGoogleJSStyleWithColumns(ColumnLimit: 80);
264 Style.AlignOperands = FormatStyle::OAS_Align;
265 verifyFormat(Code: "var x = aaaaaaaaaaaaaaaaaaaaaaaaa() in\n"
266 " aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
267 Style);
268 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
269 verifyFormat(Code: "var x = aaaaaaaaaaaaaaaaaaaaaaaaa()\n"
270 " in aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
271 Style);
272
273 // ES6 spread operator.
274 verifyFormat(Code: "someFunction(...a);");
275 verifyFormat(Code: "var x = [1, ...a, 2];");
276
277 // "- -1" is legal JS syntax, but must not collapse into "--".
278 verifyFormat(Expected: "- -1;", Code: " - -1;");
279 verifyFormat(Expected: "-- -1;", Code: " -- -1;");
280 verifyFormat(Expected: "+ +1;", Code: " + +1;");
281 verifyFormat(Expected: "++ +1;", Code: " ++ +1;");
282}
283
284TEST_F(FormatTestJS, UnderstandsAmpAmp) {
285 verifyFormat(Code: "e && e.SomeFunction();");
286}
287
288TEST_F(FormatTestJS, LiteralOperatorsCanBeKeywords) {
289 verifyFormat(Code: "not.and.or.not_eq = 1;");
290}
291
292TEST_F(FormatTestJS, ReservedWords) {
293 // JavaScript reserved words (aka keywords) are only illegal when used as
294 // Identifiers, but are legal as IdentifierNames.
295 verifyFormat(Code: "x.class.struct = 1;");
296 verifyFormat(Code: "x.case = 1;");
297 verifyFormat(Code: "x.interface = 1;");
298 verifyFormat(Code: "x.for = 1;");
299 verifyFormat(Code: "x.of();");
300 verifyFormat(Code: "of(null);");
301 verifyFormat(Code: "return of(null);");
302 verifyFormat(Code: "import {of} from 'x';");
303 verifyFormat(Code: "x.in();");
304 verifyFormat(Code: "x.let();");
305 verifyFormat(Code: "x.var();");
306 verifyFormat(Code: "x.for();");
307 verifyFormat(Code: "x.as();");
308 verifyFormat(Code: "x.instanceof();");
309 verifyFormat(Code: "x.switch();");
310 verifyFormat(Code: "x.case();");
311 verifyFormat(Code: "x.delete();");
312 verifyFormat(Code: "x.throw();");
313 verifyFormat(Code: "x.throws();");
314 verifyFormat(Code: "x.if();");
315 verifyFormat(Code: "x = {\n"
316 " a: 12,\n"
317 " interface: 1,\n"
318 " switch: 1,\n"
319 "};");
320 verifyFormat(Code: "var struct = 2;");
321 verifyFormat(Code: "var union = 2;");
322 verifyFormat(Code: "var interface = 2;");
323 verifyFormat(Code: "var requires = {};");
324 verifyFormat(Code: "interface = 2;");
325 verifyFormat(Code: "x = interface instanceof y;");
326 verifyFormat(Code: "interface Test {\n"
327 " x: string;\n"
328 " switch: string;\n"
329 " case: string;\n"
330 " default: string;\n"
331 "}");
332 verifyFormat(Expected: "const Axis = {\n"
333 " for: 'for',\n"
334 " x: 'x'\n"
335 "};",
336 Code: "const Axis = {for: 'for', x: 'x'};");
337 verifyFormat(Code: "export class Foo extends Bar {\n"
338 " get case(): Case {\n"
339 " return (\n"
340 " (this.Bar$has('case')) ? (this.Bar$get('case')) :\n"
341 " (this.case = new Case()));\n"
342 " }\n"
343 "}");
344}
345
346TEST_F(FormatTestJS, ReservedWordsMethods) {
347 verifyFormat(Code: "class X {\n"
348 " delete() {\n"
349 " x();\n"
350 " }\n"
351 " interface() {\n"
352 " x();\n"
353 " }\n"
354 " let() {\n"
355 " x();\n"
356 " }\n"
357 "}");
358 verifyFormat(Code: "class KeywordNamedMethods {\n"
359 " do() {\n"
360 " }\n"
361 " for() {\n"
362 " }\n"
363 " while() {\n"
364 " }\n"
365 " if() {\n"
366 " }\n"
367 " else() {\n"
368 " }\n"
369 " try() {\n"
370 " }\n"
371 " catch() {\n"
372 " }\n"
373 "}");
374}
375
376TEST_F(FormatTestJS, ReservedWordsParenthesized) {
377 // All of these are statements using the keyword, not function calls.
378 verifyFormat(Code: "throw (x + y);\n"
379 "await (await x).y;\n"
380 "typeof (x) === 'string';\n"
381 "void (0);\n"
382 "delete (x.y);\n"
383 "return (x);");
384}
385
386TEST_F(FormatTestJS, ES6DestructuringAssignment) {
387 verifyFormat(Code: "var [a, b, c] = [1, 2, 3];");
388 verifyFormat(Code: "const [a, b, c] = [1, 2, 3];");
389 verifyFormat(Code: "let [a, b, c] = [1, 2, 3];");
390 verifyFormat(Code: "var {a, b} = {a: 1, b: 2};");
391 verifyFormat(Code: "let {a, b} = {a: 1, b: 2};");
392}
393
394TEST_F(FormatTestJS, ContainerLiterals) {
395 verifyFormat(Code: "var x = {\n"
396 " y: function(a) {\n"
397 " return a;\n"
398 " }\n"
399 "};");
400 verifyFormat(Code: "return {\n"
401 " link: function() {\n"
402 " f(); //\n"
403 " }\n"
404 "};");
405 verifyFormat(Code: "return {\n"
406 " a: a,\n"
407 " link: function() {\n"
408 " f(); //\n"
409 " }\n"
410 "};");
411 verifyFormat(Code: "return {\n"
412 " a: a,\n"
413 " link: function() {\n"
414 " f(); //\n"
415 " },\n"
416 " link: function() {\n"
417 " f(); //\n"
418 " }\n"
419 "};");
420 verifyFormat(Code: "var stuff = {\n"
421 " // comment for update\n"
422 " update: false,\n"
423 " // comment for modules\n"
424 " modules: false,\n"
425 " // comment for tasks\n"
426 " tasks: false\n"
427 "};");
428 verifyFormat(Code: "return {\n"
429 " 'finish':\n"
430 " //\n"
431 " a\n"
432 "};");
433 verifyFormat(Code: "var obj = {\n"
434 " fooooooooo: function(x) {\n"
435 " return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
436 " }\n"
437 "};");
438 // Simple object literal, as opposed to enum style below.
439 verifyFormat(Code: "var obj = {a: 123};");
440 // Enum style top level assignment.
441 verifyFormat(Code: "X = {\n a: 123\n};");
442 verifyFormat(Code: "X.Y = {\n a: 123\n};");
443 // But only on the top level, otherwise its a plain object literal assignment.
444 verifyFormat(Code: "function x() {\n"
445 " y = {z: 1};\n"
446 "}");
447 verifyFormat(Code: "x = foo && {a: 123};");
448
449 // Arrow functions in object literals.
450 verifyFormat(Code: "var x = {\n"
451 " y: (a) => {\n"
452 " x();\n"
453 " return a;\n"
454 " },\n"
455 "};");
456 verifyFormat(Code: "var x = {y: (a) => a};");
457
458 // Methods in object literals.
459 verifyFormat(Code: "var x = {\n"
460 " y(a: string): number {\n"
461 " return a;\n"
462 " }\n"
463 "};");
464 verifyFormat(Code: "var x = {\n"
465 " y(a: string) {\n"
466 " return a;\n"
467 " }\n"
468 "};");
469
470 // Computed keys.
471 verifyFormat(Code: "var x = {[a]: 1, b: 2, [c]: 3};");
472 verifyFormat(Code: "var x = {\n"
473 " [a]: 1,\n"
474 " b: 2,\n"
475 " [c]: 3,\n"
476 "};");
477
478 // Object literals can leave out labels.
479 verifyFormat(Code: "f({a}, () => {\n"
480 " x;\n"
481 " g();\n"
482 "});");
483
484 // Keys can be quoted.
485 verifyFormat(Code: "var x = {\n"
486 " a: a,\n"
487 " b: b,\n"
488 " 'c': c,\n"
489 "};");
490
491 // Dict literals can skip the label names.
492 verifyFormat(Code: "var x = {\n"
493 " aaa,\n"
494 " aaa,\n"
495 " aaa,\n"
496 "};");
497 verifyFormat(Code: "return {\n"
498 " a,\n"
499 " b: 'b',\n"
500 " c,\n"
501 "};");
502}
503
504TEST_F(FormatTestJS, MethodsInObjectLiterals) {
505 verifyFormat(Code: "var o = {\n"
506 " value: 'test',\n"
507 " get value() { // getter\n"
508 " return this.value;\n"
509 " }\n"
510 "};");
511 verifyFormat(Code: "var o = {\n"
512 " value: 'test',\n"
513 " set value(val) { // setter\n"
514 " this.value = val;\n"
515 " }\n"
516 "};");
517 verifyFormat(Code: "var o = {\n"
518 " value: 'test',\n"
519 " someMethod(val) { // method\n"
520 " doSomething(this.value + val);\n"
521 " }\n"
522 "};");
523 verifyFormat(Code: "var o = {\n"
524 " someMethod(val) { // method\n"
525 " doSomething(this.value + val);\n"
526 " },\n"
527 " someOtherMethod(val) { // method\n"
528 " doSomething(this.value + val);\n"
529 " }\n"
530 "};");
531}
532
533TEST_F(FormatTestJS, GettersSettersVisibilityKeywords) {
534 // Don't break after "protected"
535 verifyFormat(Code: "class X {\n"
536 " protected get getter():\n"
537 " number {\n"
538 " return 1;\n"
539 " }\n"
540 "}",
541 Style: getGoogleJSStyleWithColumns(ColumnLimit: 12));
542 // Don't break after "get"
543 verifyFormat(Code: "class X {\n"
544 " protected get someReallyLongGetterName():\n"
545 " number {\n"
546 " return 1;\n"
547 " }\n"
548 "}",
549 Style: getGoogleJSStyleWithColumns(ColumnLimit: 40));
550}
551
552TEST_F(FormatTestJS, SpacesInContainerLiterals) {
553 verifyFormat(Code: "var arr = [1, 2, 3];");
554 verifyFormat(Code: "f({a: 1, b: 2, c: 3});");
555
556 verifyFormat(Code: "var object_literal_with_long_name = {\n"
557 " a: 'aaaaaaaaaaaaaaaaaa',\n"
558 " b: 'bbbbbbbbbbbbbbbbbb'\n"
559 "};");
560
561 verifyFormat(Code: "f({a: 1, b: 2, c: 3});",
562 Style: getChromiumStyle(Language: FormatStyle::LK_JavaScript));
563 verifyFormat(Code: "f({'a': [{}]});");
564}
565
566TEST_F(FormatTestJS, SingleQuotedStrings) {
567 verifyFormat(Code: "this.function('', true);");
568}
569
570TEST_F(FormatTestJS, GoogScopes) {
571 verifyFormat(Code: "goog.scope(function() {\n"
572 "var x = a.b;\n"
573 "var y = c.d;\n"
574 "}); // goog.scope");
575 verifyFormat(Code: "goog.scope(function() {\n"
576 "// test\n"
577 "var x = 0;\n"
578 "// test\n"
579 "});");
580}
581
582TEST_F(FormatTestJS, IIFEs) {
583 // Internal calling parens; no semi.
584 verifyFormat(Code: "(function() {\n"
585 "var a = 1;\n"
586 "}())");
587 // External calling parens; no semi.
588 verifyFormat(Code: "(function() {\n"
589 "var b = 2;\n"
590 "})()");
591 // Internal calling parens; with semi.
592 verifyFormat(Code: "(function() {\n"
593 "var c = 3;\n"
594 "}());");
595 // External calling parens; with semi.
596 verifyFormat(Code: "(function() {\n"
597 "var d = 4;\n"
598 "})();");
599}
600
601TEST_F(FormatTestJS, GoogModules) {
602 verifyFormat(Code: "goog.module('this.is.really.absurdly.long');",
603 Style: getGoogleJSStyleWithColumns(ColumnLimit: 40));
604 verifyFormat(Code: "goog.require('this.is.really.absurdly.long');",
605 Style: getGoogleJSStyleWithColumns(ColumnLimit: 40));
606 verifyFormat(Code: "goog.provide('this.is.really.absurdly.long');",
607 Style: getGoogleJSStyleWithColumns(ColumnLimit: 40));
608 verifyFormat(Code: "var long = goog.require('this.is.really.absurdly.long');",
609 Style: getGoogleJSStyleWithColumns(ColumnLimit: 40));
610 verifyFormat(Code: "const X = goog.requireType('this.is.really.absurdly.long');",
611 Style: getGoogleJSStyleWithColumns(ColumnLimit: 40));
612 verifyFormat(Code: "goog.forwardDeclare('this.is.really.absurdly.long');",
613 Style: getGoogleJSStyleWithColumns(ColumnLimit: 40));
614
615 // These should be wrapped normally.
616 verifyFormat(
617 Code: "var MyLongClassName =\n"
618 " goog.module.get('my.long.module.name.followedBy.MyLongClassName');");
619 verifyFormat(Expected: "function a() {\n"
620 " goog.setTestOnly();\n"
621 "}",
622 Code: "function a() {\n"
623 "goog.setTestOnly();\n"
624 "}");
625}
626
627TEST_F(FormatTestJS, FormatsNamespaces) {
628 verifyFormat(Code: "namespace Foo {\n"
629 " export let x = 1;\n"
630 "}");
631 verifyFormat(Code: "declare namespace Foo {\n"
632 " export let x: number;\n"
633 "}");
634}
635
636TEST_F(FormatTestJS, NamespacesMayNotWrap) {
637 verifyFormat(Code: "declare namespace foobarbaz {\n"
638 "}",
639 Style: getGoogleJSStyleWithColumns(ColumnLimit: 18));
640 verifyFormat(Code: "declare module foobarbaz {\n"
641 "}",
642 Style: getGoogleJSStyleWithColumns(ColumnLimit: 15));
643 verifyFormat(Code: "namespace foobarbaz {\n"
644 "}",
645 Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
646 verifyFormat(Code: "module foobarbaz {\n"
647 "}",
648 Style: getGoogleJSStyleWithColumns(ColumnLimit: 7));
649}
650
651TEST_F(FormatTestJS, AmbientDeclarations) {
652 FormatStyle NineCols = getGoogleJSStyleWithColumns(ColumnLimit: 9);
653 verifyFormat(Code: "declare class\n"
654 " X {}",
655 Style: NineCols);
656 verifyFormat(Code: "declare function\n"
657 "x();", // TODO(martinprobst): should ideally be indented.
658 Style: NineCols);
659 verifyFormat(Code: "declare function foo();\n"
660 "let x = 1;");
661 verifyFormat(Code: "declare function foo(): string;\n"
662 "let x = 1;");
663 verifyFormat(Code: "declare function foo(): {x: number};\n"
664 "let x = 1;");
665 verifyFormat(Code: "declare class X {}\n"
666 "let x = 1;");
667 verifyFormat(Code: "declare interface Y {}\n"
668 "let x = 1;");
669 verifyFormat(Code: "declare enum X {\n"
670 "}",
671 Style: NineCols);
672 verifyFormat(Code: "declare let\n"
673 " x: number;",
674 Style: NineCols);
675}
676
677TEST_F(FormatTestJS, FormatsFreestandingFunctions) {
678 verifyFormat(Code: "function outer1(a, b) {\n"
679 " function inner1(a, b) {\n"
680 " return a;\n"
681 " }\n"
682 " inner1(a, b);\n"
683 "}\n"
684 "function outer2(a, b) {\n"
685 " function inner2(a, b) {\n"
686 " return a;\n"
687 " }\n"
688 " inner2(a, b);\n"
689 "}");
690 verifyFormat(Code: "function f() {}");
691 verifyFormat(Code: "function aFunction() {}\n"
692 "(function f() {\n"
693 " var x = 1;\n"
694 "}());");
695 verifyFormat(Code: "function aFunction() {}\n"
696 "{\n"
697 " let x = 1;\n"
698 " console.log(x);\n"
699 "}");
700 EXPECT_EQ("a = function(x) {}\n"
701 "\n"
702 "function f(x) {}",
703 format("a = function(x) {}\n"
704 "\n"
705 "function f(x) {}",
706 getGoogleJSStyleWithColumns(20)));
707}
708
709TEST_F(FormatTestJS, FormatsDecorators) {
710 // No line break after argument decorators.
711 verifyFormat(Code: "class A {\n"
712 " constructor(@arg(DECOR) private arg: Type) {}\n"
713 "}");
714 // Ensure that there is a break before functions, getters and setters.
715 EXPECT_EQ("class A {\n"
716 " private p = () => {}\n"
717 "\n"
718 " @decorated('a')\n"
719 " get f() {\n"
720 " return result;\n"
721 " }\n"
722 "}\n"
723 "\n"
724 "class B {\n"
725 " private p = () => {}\n"
726 "\n"
727 " @decorated('a')\n"
728 " set f() {\n"
729 " return result;\n"
730 " }\n"
731 "}\n"
732 "\n"
733 "class C {\n"
734 " private p = () => {}\n"
735 "\n"
736 " @decorated('a')\n"
737 " function f() {\n"
738 " return result;\n"
739 " }\n"
740 "}",
741 format("class A {\n"
742 " private p = () => {}\n"
743 "\n"
744 " @decorated('a')\n"
745 " get f() {\n"
746 " return result;\n"
747 " }\n"
748 "}\n"
749 "\n"
750 "class B {\n"
751 " private p = () => {}\n"
752 "\n"
753 " @decorated('a')\n"
754 " set f() {\n"
755 " return result;\n"
756 " }\n"
757 "}\n"
758 "\n"
759 "class C {\n"
760 " private p = () => {}\n"
761 "\n"
762 " @decorated('a')\n"
763 " function f() {\n"
764 " return result;\n"
765 " }\n"
766 "}",
767 getGoogleJSStyleWithColumns(50)));
768}
769
770TEST_F(FormatTestJS, GeneratorFunctions) {
771 verifyFormat(Code: "function* f() {\n"
772 " let x = 1;\n"
773 " yield x;\n"
774 " yield* something();\n"
775 " yield [1, 2];\n"
776 " yield {a: 1};\n"
777 "}");
778 verifyFormat(Code: "function*\n"
779 " f() {\n"
780 "}",
781 Style: getGoogleJSStyleWithColumns(ColumnLimit: 8));
782 verifyFormat(Code: "export function* f() {\n"
783 " yield 1;\n"
784 "}");
785 verifyFormat(Code: "class X {\n"
786 " * generatorMethod() {\n"
787 " yield x;\n"
788 " }\n"
789 "}");
790 verifyFormat(Code: "var x = {\n"
791 " a: function*() {\n"
792 " //\n"
793 " }\n"
794 "}");
795}
796
797TEST_F(FormatTestJS, AsyncFunctions) {
798 verifyFormat(Code: "async function f() {\n"
799 " let x = 1;\n"
800 " return fetch(x);\n"
801 "}");
802 verifyFormat(Expected: "async function f() {\n"
803 " return 1;\n"
804 "}\n"
805 "\n"
806 "function a() {\n"
807 " return 1;\n"
808 "}",
809 Code: " async function f() {\n"
810 " return 1;\n"
811 "}\n"
812 "\n"
813 " function a() {\n"
814 " return 1;\n"
815 "} ");
816 // clang-format must not insert breaks between async and function, otherwise
817 // automatic semicolon insertion may trigger (in particular in a class body).
818 verifyFormat(Expected: "async function\n"
819 "hello(\n"
820 " myparamnameiswaytooloooong) {\n"
821 "}",
822 Code: "async function hello(myparamnameiswaytooloooong) {}",
823 Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
824 verifyFormat(Expected: "class C {\n"
825 " async hello(\n"
826 " myparamnameiswaytooloooong) {\n"
827 " }\n"
828 "}",
829 Code: "class C {\n"
830 " async hello(myparamnameiswaytooloooong) {} }",
831 Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
832 verifyFormat(Code: "async function* f() {\n"
833 " yield fetch(x);\n"
834 "}");
835 verifyFormat(Code: "export async function f() {\n"
836 " return fetch(x);\n"
837 "}");
838 verifyFormat(Code: "let x = async () => f();");
839 verifyFormat(Code: "let x = async function() {\n"
840 " f();\n"
841 "};");
842 verifyFormat(Code: "let x = async();");
843 verifyFormat(Code: "class X {\n"
844 " async asyncMethod() {\n"
845 " return fetch(1);\n"
846 " }\n"
847 "}");
848 verifyFormat(Code: "function initialize() {\n"
849 " // Comment.\n"
850 " return async.then();\n"
851 "}");
852 verifyFormat(Code: "for await (const x of y) {\n"
853 " console.log(x);\n"
854 "}");
855 verifyFormat(Code: "function asyncLoop() {\n"
856 " for await (const x of y) {\n"
857 " console.log(x);\n"
858 " }\n"
859 "}");
860}
861
862TEST_F(FormatTestJS, OverriddenMembers) {
863 verifyFormat(
864 Code: "class C extends P {\n"
865 " protected override "
866 "anOverlyLongPropertyNameSoLongItHasToGoInASeparateLineWhenOverriden:\n"
867 " undefined;\n"
868 "}");
869 verifyFormat(
870 Code: "class C extends P {\n"
871 " protected override "
872 "anOverlyLongMethodNameSoLongItHasToGoInASeparateLineWhenOverriden() {\n"
873 " }\n"
874 "}");
875 verifyFormat(Code: "class C extends P {\n"
876 " protected override aMethodName<ATypeParam extends {},\n"
877 " BTypeParam "
878 "extends {}>() {}\n"
879 "}");
880}
881
882TEST_F(FormatTestJS, FunctionParametersTrailingComma) {
883 verifyFormat(Expected: "function trailingComma(\n"
884 " p1,\n"
885 " p2,\n"
886 " p3,\n"
887 ") {\n"
888 " a; //\n"
889 "}",
890 Code: "function trailingComma(p1, p2, p3,) {\n"
891 " a; //\n"
892 "}");
893 verifyFormat(Expected: "trailingComma(\n"
894 " p1,\n"
895 " p2,\n"
896 " p3,\n"
897 ");",
898 Code: "trailingComma(p1, p2, p3,);");
899 verifyFormat(Expected: "trailingComma(\n"
900 " p1 // hello\n"
901 ");",
902 Code: "trailingComma(p1 // hello\n"
903 ");");
904}
905
906TEST_F(FormatTestJS, ArrayLiterals) {
907 verifyFormat(Code: "var aaaaa: List<SomeThing> =\n"
908 " [new SomeThingAAAAAAAAAAAA(), new SomeThingBBBBBBBBB()];");
909 verifyFormat(Code: "return [\n"
910 " aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
911 " ccccccccccccccccccccccccccc\n"
912 "];");
913 verifyFormat(Code: "return [\n"
914 " aaaa().bbbbbbbb('A'),\n"
915 " aaaa().bbbbbbbb('B'),\n"
916 " aaaa().bbbbbbbb('C'),\n"
917 "];");
918 verifyFormat(Code: "var someVariable = SomeFunction([\n"
919 " aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
920 " ccccccccccccccccccccccccccc\n"
921 "]);");
922 verifyFormat(Code: "var someVariable = SomeFunction([\n"
923 " [aaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbb],\n"
924 "]);",
925 Style: getGoogleJSStyleWithColumns(ColumnLimit: 51));
926 verifyFormat(Code: "var someVariable = SomeFunction(aaaa, [\n"
927 " aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
928 " ccccccccccccccccccccccccccc\n"
929 "]);");
930 verifyFormat(Code: "var someVariable = SomeFunction(\n"
931 " aaaa,\n"
932 " [\n"
933 " aaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
934 " cccccccccccccccccccccccccc\n"
935 " ],\n"
936 " aaaa);");
937 verifyFormat(Code: "var aaaa = aaaaa || // wrap\n"
938 " [];");
939
940 verifyFormat(Code: "someFunction([], {a: a});");
941
942 verifyFormat(Code: "var string = [\n"
943 " 'aaaaaa',\n"
944 " 'bbbbbb',\n"
945 "].join('+');");
946}
947
948TEST_F(FormatTestJS, ColumnLayoutForArrayLiterals) {
949 verifyFormat(Code: "var array = [\n"
950 " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
951 " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
952 "];");
953 verifyFormat(Code: "var array = someFunction([\n"
954 " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
955 " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
956 "]);");
957}
958
959TEST_F(FormatTestJS, TrailingCommaInsertion) {
960 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_JavaScript);
961 Style.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
962 // Insert comma in wrapped array.
963 verifyFormat(Expected: "const x = [\n"
964 " 1, //\n"
965 " 2,\n"
966 "];",
967 Code: "const x = [\n"
968 " 1, //\n"
969 " 2];",
970 Style);
971 // Insert comma in newly wrapped array.
972 Style.ColumnLimit = 30;
973 verifyFormat(Expected: "const x = [\n"
974 " aaaaaaaaaaaaaaaaaaaaaaaaa,\n"
975 "];",
976 Code: "const x = [aaaaaaaaaaaaaaaaaaaaaaaaa];", Style);
977 // Do not insert trailing commas if they'd exceed the colum limit
978 verifyFormat(Expected: "const x = [\n"
979 " aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
980 "];",
981 Code: "const x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa];", Style);
982 // Object literals.
983 verifyFormat(Expected: "const x = {\n"
984 " a: aaaaaaaaaaaaaaaaa,\n"
985 "};",
986 Code: "const x = {a: aaaaaaaaaaaaaaaaa};", Style);
987 verifyFormat(Expected: "const x = {\n"
988 " a: aaaaaaaaaaaaaaaaaaaaaaaaa\n"
989 "};",
990 Code: "const x = {a: aaaaaaaaaaaaaaaaaaaaaaaaa};", Style);
991 // Object literal types.
992 verifyFormat(Expected: "let x: {\n"
993 " a: aaaaaaaaaaaaaaaaaaaaa,\n"
994 "};",
995 Code: "let x: {a: aaaaaaaaaaaaaaaaaaaaa};", Style);
996}
997
998TEST_F(FormatTestJS, FunctionLiterals) {
999 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_JavaScript);
1000 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
1001 verifyFormat(Code: "doFoo(function() {});");
1002 verifyFormat(Code: "doFoo(function() { return 1; });", Style);
1003 verifyFormat(Code: "var func = function() {\n"
1004 " return 1;\n"
1005 "};");
1006 verifyFormat(Code: "var func = //\n"
1007 " function() {\n"
1008 " return 1;\n"
1009 "};");
1010 verifyFormat(Code: "return {\n"
1011 " body: {\n"
1012 " setAttribute: function(key, val) { this[key] = val; },\n"
1013 " getAttribute: function(key) { return this[key]; },\n"
1014 " style: {direction: ''}\n"
1015 " }\n"
1016 "};",
1017 Style);
1018 verifyFormat(Code: "abc = xyz ? function() {\n"
1019 " return 1;\n"
1020 "} : function() {\n"
1021 " return -1;\n"
1022 "};");
1023
1024 verifyFormat(Code: "var closure = goog.bind(\n"
1025 " function() { // comment\n"
1026 " foo();\n"
1027 " bar();\n"
1028 " },\n"
1029 " this, arg1IsReallyLongAndNeedsLineBreaks,\n"
1030 " arg3IsReallyLongAndNeedsLineBreaks);");
1031 verifyFormat(Code: "var closure = goog.bind(function() { // comment\n"
1032 " foo();\n"
1033 " bar();\n"
1034 "}, this);");
1035 verifyFormat(Code: "return {\n"
1036 " a: 'E',\n"
1037 " b: function() {\n"
1038 " return function() {\n"
1039 " f(); //\n"
1040 " };\n"
1041 " }\n"
1042 "};");
1043 verifyFormat(Code: "{\n"
1044 " var someVariable = function(x) {\n"
1045 " return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
1046 " };\n"
1047 "}");
1048 verifyFormat(Code: "someLooooooooongFunction(\n"
1049 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
1050 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
1051 " function(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n"
1052 " // code\n"
1053 " });");
1054
1055 verifyFormat(Code: "return {\n"
1056 " a: function SomeFunction() {\n"
1057 " // ...\n"
1058 " return 1;\n"
1059 " }\n"
1060 "};");
1061 verifyFormat(Code: "this.someObject.doSomething(aaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
1062 " .then(goog.bind(function(aaaaaaaaaaa) {\n"
1063 " someFunction();\n"
1064 " someFunction();\n"
1065 " }, this), aaaaaaaaaaaaaaaaa);");
1066
1067 verifyFormat(Code: "someFunction(goog.bind(function() {\n"
1068 " doSomething();\n"
1069 " doSomething();\n"
1070 "}, this), goog.bind(function() {\n"
1071 " doSomething();\n"
1072 " doSomething();\n"
1073 "}, this));");
1074
1075 verifyFormat(Code: "SomeFunction(function() {\n"
1076 " foo();\n"
1077 " bar();\n"
1078 "}.bind(this));");
1079
1080 verifyFormat(Code: "SomeFunction((function() {\n"
1081 " foo();\n"
1082 " bar();\n"
1083 " }).bind(this));");
1084
1085 // FIXME: This is bad, we should be wrapping before "function() {".
1086 verifyFormat(Code: "someFunction(function() {\n"
1087 " doSomething(); // break\n"
1088 "})\n"
1089 " .doSomethingElse(\n"
1090 " // break\n"
1091 " );");
1092
1093 Style.ColumnLimit = 33;
1094 verifyFormat(Code: "f({a: function() { return 1; }});", Style);
1095 Style.ColumnLimit = 32;
1096 verifyFormat(Code: "f({\n"
1097 " a: function() { return 1; }\n"
1098 "});",
1099 Style);
1100}
1101
1102TEST_F(FormatTestJS, DontWrapEmptyLiterals) {
1103 verifyFormat(Code: "(aaaaaaaaaaaaaaaaaaaaa.getData as jasmine.Spy)\n"
1104 " .and.returnValue(Observable.of([]));");
1105 verifyFormat(Code: "(aaaaaaaaaaaaaaaaaaaaa.getData as jasmine.Spy)\n"
1106 " .and.returnValue(Observable.of({}));");
1107 verifyFormat(Code: "(aaaaaaaaaaaaaaaaaaaaa.getData as jasmine.Spy)\n"
1108 " .and.returnValue(Observable.of(()));");
1109}
1110
1111TEST_F(FormatTestJS, InliningFunctionLiterals) {
1112 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_JavaScript);
1113 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
1114 verifyFormat(Code: "var func = function() {\n"
1115 " return 1;\n"
1116 "};",
1117 Style);
1118 verifyFormat(Code: "var func = doSomething(function() { return 1; });", Style);
1119 verifyFormat(Code: "var outer = function() {\n"
1120 " var inner = function() { return 1; }\n"
1121 "};",
1122 Style);
1123 verifyFormat(Code: "function outer1(a, b) {\n"
1124 " function inner1(a, b) { return a; }\n"
1125 "}",
1126 Style);
1127
1128 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
1129 verifyFormat(Code: "var func = function() { return 1; };", Style);
1130 verifyFormat(Code: "var func = doSomething(function() { return 1; });", Style);
1131 verifyFormat(
1132 Code: "var outer = function() { var inner = function() { return 1; } };",
1133 Style);
1134 verifyFormat(Code: "function outer1(a, b) {\n"
1135 " function inner1(a, b) { return a; }\n"
1136 "}",
1137 Style);
1138
1139 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
1140 verifyFormat(Code: "var func = function() {\n"
1141 " return 1;\n"
1142 "};",
1143 Style);
1144 verifyFormat(Code: "var func = doSomething(function() {\n"
1145 " return 1;\n"
1146 "});",
1147 Style);
1148 verifyFormat(Code: "var outer = function() {\n"
1149 " var inner = function() {\n"
1150 " return 1;\n"
1151 " }\n"
1152 "};",
1153 Style);
1154 verifyFormat(Code: "function outer1(a, b) {\n"
1155 " function inner1(a, b) {\n"
1156 " return a;\n"
1157 " }\n"
1158 "}",
1159 Style);
1160
1161 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
1162 verifyFormat(Code: "var func = function() {\n"
1163 " return 1;\n"
1164 "};",
1165 Style);
1166}
1167
1168TEST_F(FormatTestJS, MultipleFunctionLiterals) {
1169 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_JavaScript);
1170 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
1171 verifyFormat(Code: "promise.then(\n"
1172 " function success() {\n"
1173 " doFoo();\n"
1174 " doBar();\n"
1175 " },\n"
1176 " function error() {\n"
1177 " doFoo();\n"
1178 " doBaz();\n"
1179 " },\n"
1180 " []);");
1181 verifyFormat(Code: "promise.then(\n"
1182 " function success() {\n"
1183 " doFoo();\n"
1184 " doBar();\n"
1185 " },\n"
1186 " [],\n"
1187 " function error() {\n"
1188 " doFoo();\n"
1189 " doBaz();\n"
1190 " });");
1191 verifyFormat(Code: "promise.then(\n"
1192 " [],\n"
1193 " function success() {\n"
1194 " doFoo();\n"
1195 " doBar();\n"
1196 " },\n"
1197 " function error() {\n"
1198 " doFoo();\n"
1199 " doBaz();\n"
1200 " });");
1201
1202 verifyFormat(Code: "getSomeLongPromise()\n"
1203 " .then(function(value) { body(); })\n"
1204 " .thenCatch(function(error) {\n"
1205 " body();\n"
1206 " body();\n"
1207 " });",
1208 Style);
1209 verifyFormat(Code: "getSomeLongPromise()\n"
1210 " .then(function(value) {\n"
1211 " body();\n"
1212 " body();\n"
1213 " })\n"
1214 " .thenCatch(function(error) {\n"
1215 " body();\n"
1216 " body();\n"
1217 " });");
1218
1219 verifyFormat(Code: "getSomeLongPromise()\n"
1220 " .then(function(value) { body(); })\n"
1221 " .thenCatch(function(error) { body(); });",
1222 Style);
1223
1224 verifyFormat(Code: "return [aaaaaaaaaaaaaaaaaaaaaa]\n"
1225 " .aaaaaaa(function() {\n"
1226 " //\n"
1227 " })\n"
1228 " .bbbbbb();");
1229}
1230
1231TEST_F(FormatTestJS, ArrowFunctions) {
1232 verifyFormat(Code: "var x = (a) => {\n"
1233 " x;\n"
1234 " return a;\n"
1235 "};");
1236 verifyFormat(Code: "var x = (a) => {\n"
1237 " function y() {\n"
1238 " return 42;\n"
1239 " }\n"
1240 " return a;\n"
1241 "};");
1242 verifyFormat(Code: "var x = (a: type): {some: type} => {\n"
1243 " y;\n"
1244 " return a;\n"
1245 "};");
1246 verifyFormat(Code: "var x = (a) => a;");
1247 verifyFormat(Code: "return () => [];");
1248 verifyFormat(Code: "var aaaaaaaaaaaaaaaaaaaa = {\n"
1249 " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n"
1250 " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
1251 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) =>\n"
1252 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
1253 "};");
1254 verifyFormat(Code: "var a = a.aaaaaaa(\n"
1255 " (a: a) => aaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) &&\n"
1256 " aaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
1257 verifyFormat(Code: "var a = a.aaaaaaa(\n"
1258 " (a: a) => aaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) ?\n"
1259 " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb) :\n"
1260 " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
1261
1262 // FIXME: This is bad, we should be wrapping before "() => {".
1263 verifyFormat(Code: "someFunction(() => {\n"
1264 " doSomething(); // break\n"
1265 "})\n"
1266 " .doSomethingElse(\n"
1267 " // break\n"
1268 " );");
1269 verifyFormat(Code: "const f = (x: string|null): string|null => {\n"
1270 " y;\n"
1271 " return x;\n"
1272 "}");
1273}
1274
1275TEST_F(FormatTestJS, ArrowFunctionStyle) {
1276 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_JavaScript);
1277 Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
1278 verifyFormat(Code: "const arr = () => { x; };", Style);
1279 verifyFormat(Code: "const arrInlineAll = () => {};", Style);
1280 Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_None;
1281 verifyFormat(Code: "const arr = () => {\n"
1282 " x;\n"
1283 "};",
1284 Style);
1285 verifyFormat(Code: "const arrInlineNone = () => {\n"
1286 "};",
1287 Style);
1288 Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
1289 verifyFormat(Code: "const arr = () => {\n"
1290 " x;\n"
1291 "};",
1292 Style);
1293 verifyFormat(Code: "const arrInlineEmpty = () => {};", Style);
1294 Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Inline;
1295 verifyFormat(Code: "const arr = () => {\n"
1296 " x;\n"
1297 "};",
1298 Style);
1299 verifyFormat(Code: "foo(() => {});", Style);
1300 verifyFormat(Code: "const arrInlineInline = () => {};", Style);
1301}
1302
1303TEST_F(FormatTestJS, ReturnStatements) {
1304 verifyFormat(Code: "function() {\n"
1305 " return [hello, world];\n"
1306 "}");
1307}
1308
1309TEST_F(FormatTestJS, ForLoops) {
1310 verifyFormat(Code: "for (var i in [2, 3]) {\n"
1311 "}");
1312 verifyFormat(Code: "for (var i of [2, 3]) {\n"
1313 "}");
1314 verifyFormat(Code: "for (let {a, b} of x) {\n"
1315 "}");
1316 verifyFormat(Code: "for (let {a, b} of [x]) {\n"
1317 "}");
1318 verifyFormat(Code: "for (let [a, b] of [x]) {\n"
1319 "}");
1320 verifyFormat(Code: "for (let {a, b} in x) {\n"
1321 "}");
1322}
1323
1324TEST_F(FormatTestJS, WrapRespectsAutomaticSemicolonInsertion) {
1325 // The following statements must not wrap, as otherwise the program meaning
1326 // would change due to automatic semicolon insertion.
1327 // See http://www.ecma-international.org/ecma-262/5.1/#sec-7.9.1.
1328 verifyFormat(Code: "return aaaaa;", Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
1329 verifyFormat(Code: "yield aaaaa;", Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
1330 verifyFormat(Code: "return /* hello! */ aaaaa;", Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
1331 verifyFormat(Code: "continue aaaaa;", Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
1332 verifyFormat(Code: "continue /* hello! */ aaaaa;", Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
1333 verifyFormat(Code: "break aaaaa;", Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
1334 verifyFormat(Code: "throw aaaaa;", Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
1335 verifyFormat(Code: "aaaaaaaaa++;", Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
1336 verifyFormat(Code: "aaaaaaaaa--;", Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
1337 verifyFormat(Code: "return [\n"
1338 " aaa\n"
1339 "];",
1340 Style: getGoogleJSStyleWithColumns(ColumnLimit: 12));
1341 verifyFormat(Expected: "class X {\n"
1342 " readonly ratherLongField =\n"
1343 " 1;\n"
1344 "}",
1345 Code: "class X {\n"
1346 " readonly ratherLongField = 1;\n"
1347 "}",
1348 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
1349 verifyFormat(Expected: "const x = (5 + 9)\n"
1350 "const y = 3",
1351 Code: "const x = ( 5 + 9)\n"
1352 "const y = 3");
1353 // Ideally the foo() bit should be indented relative to the async function().
1354 verifyFormat(Code: "async function\n"
1355 "foo() {}",
1356 Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
1357 verifyFormat(Code: "await theReckoning;", Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
1358 verifyFormat(Code: "some['a']['b']", Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
1359 verifyFormat(Code: "x = (a['a']\n"
1360 " ['b']);",
1361 Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
1362 verifyFormat(Code: "function f() {\n"
1363 " return foo.bar(\n"
1364 " (param): param is {\n"
1365 " a: SomeType\n"
1366 " }&ABC => 1)\n"
1367 "}",
1368 Style: getGoogleJSStyleWithColumns(ColumnLimit: 25));
1369}
1370
1371TEST_F(FormatTestJS, AddsIsTheDictKeyOnNewline) {
1372 // Do not confuse is, the dict key with is, the type matcher. Put is, the dict
1373 // key, on a newline.
1374 verifyFormat(Code: "Polymer({\n"
1375 " is: '', //\n"
1376 " rest: 1\n"
1377 "});",
1378 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
1379}
1380
1381TEST_F(FormatTestJS, AutomaticSemicolonInsertionHeuristic) {
1382 verifyFormat(Expected: "a\n"
1383 "b;",
1384 Code: " a \n"
1385 " b ;");
1386 verifyFormat(Expected: "a()\n"
1387 "b;",
1388 Code: " a ()\n"
1389 " b ;");
1390 verifyFormat(Expected: "a[b]\n"
1391 "c;",
1392 Code: "a [b]\n"
1393 "c ;");
1394 verifyFormat(Expected: "1\n"
1395 "a;",
1396 Code: "1 \n"
1397 "a ;");
1398 verifyFormat(Expected: "a\n"
1399 "1;",
1400 Code: "a \n"
1401 "1 ;");
1402 verifyFormat(Expected: "a\n"
1403 "'x';",
1404 Code: "a \n"
1405 " 'x';");
1406 verifyFormat(Expected: "a++\n"
1407 "b;",
1408 Code: "a ++\n"
1409 "b ;");
1410 verifyFormat(Expected: "a\n"
1411 "!b && c;",
1412 Code: "a \n"
1413 " ! b && c;");
1414 verifyFormat(Expected: "a\n"
1415 "if (1) f();",
1416 Code: " a\n"
1417 " if (1) f();");
1418 verifyFormat(Expected: "a\n"
1419 "class X {}",
1420 Code: " a\n"
1421 " class X {}");
1422 verifyFormat(Expected: "var a", Code: "var\n"
1423 "a");
1424 verifyFormat(Expected: "x instanceof String", Code: "x\n"
1425 "instanceof\n"
1426 "String");
1427 verifyFormat(Expected: "function f(@Foo bar) {}", Code: "function f(@Foo\n"
1428 " bar) {}");
1429 verifyFormat(Expected: "function f(@Foo(Param) bar) {}", Code: "function f(@Foo(Param)\n"
1430 " bar) {}");
1431 verifyFormat(Expected: "a = true\n"
1432 "return 1",
1433 Code: "a = true\n"
1434 " return 1");
1435 verifyFormat(Expected: "a = 's'\n"
1436 "return 1",
1437 Code: "a = 's'\n"
1438 " return 1");
1439 verifyFormat(Expected: "a = null\n"
1440 "return 1",
1441 Code: "a = null\n"
1442 " return 1");
1443 // Below "class Y {}" should ideally be on its own line.
1444 verifyFormat(Expected: "x = {\n"
1445 " a: 1\n"
1446 "} class Y {}",
1447 Code: " x = {a : 1}\n"
1448 " class Y { }");
1449 verifyFormat(Expected: "if (x) {\n"
1450 "}\n"
1451 "return 1",
1452 Code: "if (x) {}\n"
1453 " return 1");
1454 verifyFormat(Expected: "if (x) {\n"
1455 "}\n"
1456 "class X {}",
1457 Code: "if (x) {}\n"
1458 " class X {}");
1459}
1460
1461TEST_F(FormatTestJS, ImportExportASI) {
1462 verifyFormat(Expected: "import {x} from 'y'\n"
1463 "export function z() {}",
1464 Code: "import {x} from 'y'\n"
1465 " export function z() {}");
1466 // Below "class Y {}" should ideally be on its own line.
1467 verifyFormat(Expected: "export {x} class Y {}", Code: " export {x}\n"
1468 " class Y {\n}");
1469 verifyFormat(Expected: "if (x) {\n"
1470 "}\n"
1471 "export class Y {}",
1472 Code: "if ( x ) { }\n"
1473 " export class Y {}");
1474}
1475
1476TEST_F(FormatTestJS, ImportExportType) {
1477 verifyFormat(Code: "import type {x, y} from 'y';\n"
1478 "import type * as x from 'y';\n"
1479 "import type x from 'y';\n"
1480 "import {x, type yu, z} from 'y';");
1481 verifyFormat(Code: "export type {x, y} from 'y';\n"
1482 "export {x, type yu, z} from 'y';\n"
1483 "export type {x, y};\n"
1484 "export {x, type yu, z};");
1485}
1486
1487TEST_F(FormatTestJS, ClosureStyleCasts) {
1488 verifyFormat(Code: "var x = /** @type {foo} */ (bar);");
1489}
1490
1491TEST_F(FormatTestJS, TryCatch) {
1492 verifyFormat(Code: "try {\n"
1493 " f();\n"
1494 "} catch (e) {\n"
1495 " g();\n"
1496 "} finally {\n"
1497 " h();\n"
1498 "}");
1499
1500 // But, of course, "catch" is a perfectly fine function name in JavaScript.
1501 verifyFormat(Code: "someObject.catch();");
1502 verifyFormat(Code: "someObject.new();");
1503}
1504
1505TEST_F(FormatTestJS, StringLiteralConcatenation) {
1506 verifyFormat(Code: "var literal = 'hello ' +\n"
1507 " 'world';");
1508
1509 // String breaking is disabled for now.
1510 verifyFormat(Expected: "var literal =\n"
1511 " 'xxxxxxxx xxxxxxxx';",
1512 Code: "var literal = 'xxxxxxxx xxxxxxxx';",
1513 Style: getGoogleJSStyleWithColumns(ColumnLimit: 17));
1514}
1515
1516TEST_F(FormatTestJS, RegexLiteralClassification) {
1517 // Regex literals.
1518 verifyFormat(Code: "var regex = /abc/;");
1519 verifyFormat(Code: "f(/abc/);");
1520 verifyFormat(Code: "f(abc, /abc/);");
1521 verifyFormat(Code: "some_map[/abc/];");
1522 verifyFormat(Code: "var x = a ? /abc/ : /abc/;");
1523 verifyFormat(Code: "for (var i = 0; /abc/.test(s[i]); i++) {\n}");
1524 verifyFormat(Code: "var x = !/abc/.test(y);");
1525 verifyFormat(Code: "var x = foo()! / 10;");
1526 verifyFormat(Code: "var x = a && /abc/.test(y);");
1527 verifyFormat(Code: "var x = a || /abc/.test(y);");
1528 verifyFormat(Code: "var x = a + /abc/.search(y);");
1529 verifyFormat(Code: "/abc/.search(y);");
1530 verifyFormat(Code: "var regexs = {/abc/, /abc/};");
1531 verifyFormat(Code: "return /abc/;");
1532
1533 // Not regex literals.
1534 verifyFormat(Code: "var a = a / 2 + b / 3;");
1535 verifyFormat(Code: "var a = a++ / 2;");
1536 // Prefix unary can operate on regex literals, not that it makes sense.
1537 verifyFormat(Code: "var a = ++/a/;");
1538
1539 // This is a known issue, regular expressions are incorrectly detected if
1540 // directly following a closing parenthesis.
1541 verifyFormat(Code: "if (foo) / bar /.exec(baz);");
1542}
1543
1544TEST_F(FormatTestJS, RegexLiteralSpecialCharacters) {
1545 verifyFormat(Code: "var regex = /=/;");
1546 verifyFormat(Code: "var regex = /a*/;");
1547 verifyFormat(Code: "var regex = /a+/;");
1548 verifyFormat(Code: "var regex = /a?/;");
1549 verifyFormat(Code: "var regex = /.a./;");
1550 verifyFormat(Code: "var regex = /a\\*/;");
1551 verifyFormat(Code: "var regex = /^a$/;");
1552 verifyFormat(Code: "var regex = /\\/a/;");
1553 verifyFormat(Code: "var regex = /(?:x)/;");
1554 verifyFormat(Code: "var regex = /x(?=y)/;");
1555 verifyFormat(Code: "var regex = /x(?!y)/;");
1556 verifyFormat(Code: "var regex = /x|y/;");
1557 verifyFormat(Code: "var regex = /a{2}/;");
1558 verifyFormat(Code: "var regex = /a{1,3}/;");
1559
1560 verifyFormat(Code: "var regex = /[abc]/;");
1561 verifyFormat(Code: "var regex = /[^abc]/;");
1562 verifyFormat(Code: "var regex = /[\\b]/;");
1563 verifyFormat(Code: "var regex = /[/]/;");
1564 verifyFormat(Code: "var regex = /[\\/]/;");
1565 verifyFormat(Code: "var regex = /\\[/;");
1566 verifyFormat(Code: "var regex = /\\\\[/]/;");
1567 verifyFormat(Code: "var regex = /}[\"]/;");
1568 verifyFormat(Code: "var regex = /}[/\"]/;");
1569 verifyFormat(Code: "var regex = /}[\"/]/;");
1570
1571 verifyFormat(Code: "var regex = /\\b/;");
1572 verifyFormat(Code: "var regex = /\\B/;");
1573 verifyFormat(Code: "var regex = /\\d/;");
1574 verifyFormat(Code: "var regex = /\\D/;");
1575 verifyFormat(Code: "var regex = /\\f/;");
1576 verifyFormat(Code: "var regex = /\\n/;");
1577 verifyFormat(Code: "var regex = /\\r/;");
1578 verifyFormat(Code: "var regex = /\\s/;");
1579 verifyFormat(Code: "var regex = /\\S/;");
1580 verifyFormat(Code: "var regex = /\\t/;");
1581 verifyFormat(Code: "var regex = /\\v/;");
1582 verifyFormat(Code: "var regex = /\\w/;");
1583 verifyFormat(Code: "var regex = /\\W/;");
1584 verifyFormat(Code: "var regex = /a(a)\\1/;");
1585 verifyFormat(Code: "var regex = /\\0/;");
1586 verifyFormat(Code: "var regex = /\\\\/g;");
1587 verifyFormat(Code: "var regex = /\\a\\\\/g;");
1588 verifyFormat(Code: "var regex = /\a\\//g;");
1589 verifyFormat(Code: "var regex = /a\\//;\n"
1590 "var x = 0;");
1591 verifyFormat(Expected: "var regex = /'/g;", Code: "var regex = /'/g ;");
1592 verifyFormat(Expected: "var regex = /'/g; //'", Code: "var regex = /'/g ; //'");
1593 verifyFormat(Expected: "var regex = /\\/*/;\n"
1594 "var x = 0;",
1595 Code: "var regex = /\\/*/;\n"
1596 "var x=0;");
1597 verifyFormat(Expected: "var x = /a\\//;", Code: "var x = /a\\// \n;");
1598 verifyFormat(Code: "var regex = /\"/;", Style: getGoogleJSStyleWithColumns(ColumnLimit: 16));
1599 verifyFormat(Code: "var regex =\n"
1600 " /\"/;",
1601 Style: getGoogleJSStyleWithColumns(ColumnLimit: 15));
1602 verifyFormat(Code: "var regex = //\n"
1603 " /a/;");
1604 verifyFormat(Code: "var regexs = [\n"
1605 " /d/, //\n"
1606 " /aa/, //\n"
1607 "];");
1608}
1609
1610TEST_F(FormatTestJS, RegexLiteralModifiers) {
1611 verifyFormat(Code: "var regex = /abc/g;");
1612 verifyFormat(Code: "var regex = /abc/i;");
1613 verifyFormat(Code: "var regex = /abc/m;");
1614 verifyFormat(Code: "var regex = /abc/y;");
1615}
1616
1617TEST_F(FormatTestJS, RegexLiteralLength) {
1618 verifyFormat(Code: "var regex = /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
1619 Style: getGoogleJSStyleWithColumns(ColumnLimit: 60));
1620 verifyFormat(Code: "var regex =\n"
1621 " /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
1622 Style: getGoogleJSStyleWithColumns(ColumnLimit: 60));
1623 verifyFormat(Code: "var regex = /\\xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
1624 Style: getGoogleJSStyleWithColumns(ColumnLimit: 50));
1625}
1626
1627TEST_F(FormatTestJS, RegexLiteralExamples) {
1628 verifyFormat(Code: "var regex = search.match(/(?:\?|&)times=([^?&]+)/i);");
1629}
1630
1631TEST_F(FormatTestJS, IgnoresMpegTS) {
1632 std::string MpegTS(200, ' ');
1633 MpegTS.replace(pos: 0, n1: strlen(s: "nearlyLooks + like + ts + code; "),
1634 s: "nearlyLooks + like + ts + code; ");
1635 MpegTS[0] = 0x47;
1636 MpegTS[188] = 0x47;
1637 verifyFormat(Expected: MpegTS, Code: MpegTS);
1638}
1639
1640TEST_F(FormatTestJS, TypeAnnotations) {
1641 verifyFormat(Code: "var x: string;");
1642 verifyFormat(Code: "var x: {a: string; b: number;} = {};");
1643 verifyFormat(Code: "function x(): string {\n return 'x';\n}");
1644 verifyFormat(Code: "function x(): {x: string} {\n return {x: 'x'};\n}");
1645 verifyFormat(Code: "function x(y: string): string {\n return 'x';\n}");
1646 verifyFormat(Code: "for (var y: string in x) {\n x();\n}");
1647 verifyFormat(Code: "for (var y: string of x) {\n x();\n}");
1648 verifyFormat(Code: "function x(y: {a?: number;} = {}): number {\n"
1649 " return 12;\n"
1650 "}");
1651 verifyFormat(Code: "const x: Array<{a: number; b: string;}> = [];");
1652 verifyFormat(Code: "((a: string, b: number): string => a + b);");
1653 verifyFormat(Code: "var x: (y: number) => string;");
1654 verifyFormat(Code: "var x: P<string, (a: number) => string>;");
1655 verifyFormat(Code: "var x = {\n"
1656 " y: function(): z {\n"
1657 " return 1;\n"
1658 " }\n"
1659 "};");
1660 verifyFormat(Code: "var x = {\n"
1661 " y: function(): {a: number} {\n"
1662 " return 1;\n"
1663 " }\n"
1664 "};");
1665 verifyFormat(Code: "function someFunc(args: string[]):\n"
1666 " {longReturnValue: string[]} {}",
1667 Style: getGoogleJSStyleWithColumns(ColumnLimit: 60));
1668 verifyFormat(
1669 Code: "var someValue = (v as aaaaaaaaaaaaaaaaaaaa<T>[])\n"
1670 " .someFunction(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
1671 verifyFormat(Code: "const xIsALongIdent:\n"
1672 " YJustBarelyFitsLinex[];",
1673 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
1674 verifyFormat(Code: "const x = {\n"
1675 " y: 1\n"
1676 "} as const;");
1677}
1678
1679TEST_F(FormatTestJS, UnionIntersectionTypes) {
1680 verifyFormat(Code: "let x: A|B = A | B;");
1681 verifyFormat(Code: "let x: A&B|C = A & B;");
1682 verifyFormat(Code: "let x: Foo<A|B> = new Foo<A|B>();");
1683 verifyFormat(Code: "function(x: A|B): C&D {}");
1684 verifyFormat(Code: "function(x: A|B = A | B): C&D {}");
1685 verifyFormat(Code: "function x(path: number|string) {}");
1686 verifyFormat(Code: "function x(): string|number {}");
1687 verifyFormat(Code: "type Foo = Bar|Baz;");
1688 verifyFormat(Code: "type Foo = Bar<X>|Baz;");
1689 verifyFormat(Code: "type Foo = (Bar<X>|Baz);");
1690 verifyFormat(Code: "let x: Bar|Baz;");
1691 verifyFormat(Code: "let x: Bar<X>|Baz;");
1692 verifyFormat(Code: "let x: (Foo|Bar)[];");
1693 verifyFormat(Code: "type X = {\n"
1694 " a: Foo|Bar;\n"
1695 "};");
1696 verifyFormat(Code: "export type X = {\n"
1697 " a: Foo|Bar;\n"
1698 "};");
1699}
1700
1701TEST_F(FormatTestJS, UnionIntersectionTypesInObjectType) {
1702 verifyFormat(Code: "let x: {x: number|null} = {x: number | null};");
1703 verifyFormat(Code: "let nested: {x: {y: number|null}};");
1704 verifyFormat(Code: "let mixed: {x: [number|null, {w: number}]};");
1705 verifyFormat(Code: "class X {\n"
1706 " contructor(x: {\n"
1707 " a: a|null,\n"
1708 " b: b|null,\n"
1709 " }) {}\n"
1710 "}");
1711}
1712
1713TEST_F(FormatTestJS, ClassDeclarations) {
1714 verifyFormat(Code: "class C {\n x: string = 12;\n}");
1715 verifyFormat(Code: "class C {\n x(): string => 12;\n}");
1716 verifyFormat(Code: "class C {\n ['x' + 2]: string = 12;\n}");
1717 verifyFormat(Code: "class C {\n"
1718 " foo() {}\n"
1719 " [bar]() {}\n"
1720 "}");
1721 verifyFormat(Code: "class C {\n private x: string = 12;\n}");
1722 verifyFormat(Code: "class C {\n private static x: string = 12;\n}");
1723 verifyFormat(Code: "class C {\n static x(): string {\n return 'asd';\n }\n}");
1724 verifyFormat(Code: "class C extends P implements I {}");
1725 verifyFormat(Code: "class C extends p.P implements i.I {}");
1726 verifyFormat(Code: "x(class {\n"
1727 " a(): A {}\n"
1728 "});");
1729 verifyFormat(Code: "class Test {\n"
1730 " aaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaaa):\n"
1731 " aaaaaaaaaaaaaaaaaaaaaa {}\n"
1732 "}");
1733 verifyFormat(Code: "foo = class Name {\n"
1734 " constructor() {}\n"
1735 "};");
1736 verifyFormat(Code: "foo = class {\n"
1737 " constructor() {}\n"
1738 "};");
1739 verifyFormat(Code: "class C {\n"
1740 " x: {y: Z;} = {};\n"
1741 " private y: {y: Z;} = {};\n"
1742 "}");
1743
1744 // ':' is not a type declaration here.
1745 verifyFormat(Code: "class X {\n"
1746 " subs = {\n"
1747 " 'b': {\n"
1748 " 'c': 1,\n"
1749 " },\n"
1750 " };\n"
1751 "}");
1752 verifyFormat(Code: "@Component({\n"
1753 " moduleId: module.id,\n"
1754 "})\n"
1755 "class SessionListComponent implements OnDestroy, OnInit {\n"
1756 "}");
1757}
1758
1759TEST_F(FormatTestJS, StrictPropInitWrap) {
1760 const FormatStyle &Style = getGoogleJSStyleWithColumns(ColumnLimit: 22);
1761 verifyFormat(Code: "class X {\n"
1762 " strictPropInitField!:\n"
1763 " string;\n"
1764 "}",
1765 Style);
1766}
1767
1768TEST_F(FormatTestJS, InterfaceDeclarations) {
1769 verifyFormat(Code: "interface I {\n"
1770 " x: string;\n"
1771 " enum: string[];\n"
1772 " enum?: string[];\n"
1773 "}\n"
1774 "var y;");
1775 // Ensure that state is reset after parsing the interface.
1776 verifyFormat(Code: "interface a {}\n"
1777 "export function b() {}\n"
1778 "var x;");
1779
1780 // Arrays of object type literals.
1781 verifyFormat(Code: "interface I {\n"
1782 " o: {}[];\n"
1783 "}");
1784}
1785
1786TEST_F(FormatTestJS, ObjectTypesInExtendsImplements) {
1787 verifyFormat(Code: "class C extends {} {}");
1788 verifyFormat(Code: "class C implements {bar: number} {}");
1789 // Somewhat odd, but probably closest to reasonable formatting?
1790 verifyFormat(Code: "class C implements {\n"
1791 " bar: number,\n"
1792 " baz: string,\n"
1793 "} {}");
1794 verifyFormat(Code: "class C<P extends {}> {}");
1795}
1796
1797TEST_F(FormatTestJS, EnumDeclarations) {
1798 verifyFormat(Code: "enum Foo {\n"
1799 " A = 1,\n"
1800 " B\n"
1801 "}");
1802 verifyFormat(Code: "export /* somecomment*/ enum Foo {\n"
1803 " A = 1,\n"
1804 " B\n"
1805 "}");
1806 verifyFormat(Code: "enum Foo {\n"
1807 " A = 1, // comment\n"
1808 " B\n"
1809 "}\n"
1810 "var x = 1;");
1811 verifyFormat(Code: "const enum Foo {\n"
1812 " A = 1,\n"
1813 " B\n"
1814 "}");
1815 verifyFormat(Code: "export const enum Foo {\n"
1816 " A = 1,\n"
1817 " B\n"
1818 "}");
1819}
1820
1821TEST_F(FormatTestJS, Decorators) {
1822 verifyFormat(Code: "@A\nclass C {\n}");
1823 verifyFormat(Code: "@A({arg: 'value'})\nclass C {\n}");
1824 verifyFormat(Code: "@A\n@B\nclass C {\n}");
1825 verifyFormat(Code: "class C {\n @A x: string;\n}");
1826 verifyFormat(Code: "class C {\n"
1827 " @A\n"
1828 " private x(): string {\n"
1829 " return 'y';\n"
1830 " }\n"
1831 "}");
1832 verifyFormat(Code: "class C {\n"
1833 " private x(@A x: string) {}\n"
1834 "}");
1835 verifyFormat(Code: "class X {}\n"
1836 "class Y {}");
1837 verifyFormat(Code: "class X {\n"
1838 " @property() private isReply = false;\n"
1839 "}");
1840}
1841
1842TEST_F(FormatTestJS, TypeAliases) {
1843 verifyFormat(Code: "type X = number;\n"
1844 "class C {}");
1845 verifyFormat(Code: "type X<Y> = Z<Y>;");
1846 verifyFormat(Code: "type X = {\n"
1847 " y: number\n"
1848 "};\n"
1849 "class C {}");
1850 verifyFormat(Code: "export type X = {\n"
1851 " a: string,\n"
1852 " b?: string,\n"
1853 "};");
1854}
1855
1856TEST_F(FormatTestJS, TypeInterfaceLineWrapping) {
1857 const FormatStyle &Style = getGoogleJSStyleWithColumns(ColumnLimit: 20);
1858 verifyFormat(Expected: "type LongTypeIsReallyUnreasonablyLong =\n"
1859 " string;",
1860 Code: "type LongTypeIsReallyUnreasonablyLong = string;", Style);
1861 verifyFormat(Expected: "interface AbstractStrategyFactoryProvider {\n"
1862 " a: number\n"
1863 "}",
1864 Code: "interface AbstractStrategyFactoryProvider { a: number }",
1865 Style);
1866}
1867
1868TEST_F(FormatTestJS, RemoveEmptyLinesInArrowFunctions) {
1869 verifyFormat(Expected: "x = () => {\n"
1870 " foo();\n"
1871 " bar();\n"
1872 "};",
1873 Code: "x = () => {\n"
1874 "\n"
1875 " foo();\n"
1876 " bar();\n"
1877 "\n"
1878 "};");
1879}
1880
1881TEST_F(FormatTestJS, Modules) {
1882 verifyFormat(Code: "import SomeThing from 'some/module.js';");
1883 verifyFormat(Code: "import {X, Y} from 'some/module.js';");
1884 verifyFormat(Code: "import a, {X, Y} from 'some/module.js';");
1885 verifyFormat(Code: "import {X, Y,} from 'some/module.js';");
1886 verifyFormat(Code: "import {X as myLocalX, Y as myLocalY} from 'some/module.js';");
1887 // Ensure Automatic Semicolon Insertion does not break on "as\n".
1888 verifyFormat(Expected: "import {X as myX} from 'm';", Code: "import {X as\n"
1889 " myX} from 'm';");
1890 verifyFormat(Code: "import * as lib from 'some/module.js';");
1891 verifyFormat(Code: "var x = {import: 1};\nx.import = 2;");
1892 // Ensure an import statement inside a block is at the correct level.
1893 verifyFormat(Code: "function() {\n"
1894 " var x;\n"
1895 " import 'some/module.js';\n"
1896 "}");
1897
1898 verifyFormat(Code: "export function fn() {\n"
1899 " return 'fn';\n"
1900 "}");
1901 verifyFormat(Code: "export function A() {}\n"
1902 "export default function B() {}\n"
1903 "export function C() {}");
1904 verifyFormat(Code: "export default () => {\n"
1905 " let x = 1;\n"
1906 " return x;\n"
1907 "}");
1908 verifyFormat(Code: "export const x = 12;");
1909 verifyFormat(Code: "export default class X {}");
1910 verifyFormat(Code: "export {X, Y} from 'some/module.js';");
1911 verifyFormat(Code: "export {X, Y,} from 'some/module.js';");
1912 verifyFormat(Code: "export {SomeVeryLongExport as X, "
1913 "SomeOtherVeryLongExport as Y} from 'some/module.js';");
1914 // export without 'from' is wrapped.
1915 verifyFormat(Code: "export let someRatherLongVariableName =\n"
1916 " someSurprisinglyLongVariable + someOtherRatherLongVar;");
1917 // ... but not if from is just an identifier.
1918 verifyFormat(Code: "export {\n"
1919 " from as from,\n"
1920 " someSurprisinglyLongVariable as\n"
1921 " from\n"
1922 "};",
1923 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
1924 verifyFormat(Code: "export class C {\n"
1925 " x: number;\n"
1926 " y: string;\n"
1927 "}");
1928 verifyFormat(Code: "export class X {\n"
1929 " y: number;\n"
1930 "}");
1931 verifyFormat(Code: "export abstract class X {\n"
1932 " y: number;\n"
1933 "}");
1934 verifyFormat(Code: "export default class X {\n"
1935 " y: number\n"
1936 "}");
1937 verifyFormat(Code: "export default function() {\n return 1;\n}");
1938 verifyFormat(Code: "export var x = 12;");
1939 verifyFormat(Code: "class C {}\n"
1940 "export function f() {}\n"
1941 "var v;");
1942 verifyFormat(Code: "export var x: number = 12;");
1943 verifyFormat(Code: "export const y = {\n"
1944 " a: 1,\n"
1945 " b: 2\n"
1946 "};");
1947 verifyFormat(Code: "export enum Foo {\n"
1948 " BAR,\n"
1949 " // adsdasd\n"
1950 " BAZ\n"
1951 "}");
1952 verifyFormat(Code: "export default [\n"
1953 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
1954 " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"
1955 "];");
1956 verifyFormat(Code: "export default [];");
1957 verifyFormat(Code: "export default () => {};");
1958 verifyFormat(Code: "export default () => {\n"
1959 " x;\n"
1960 " x;\n"
1961 "};");
1962 verifyFormat(Code: "export interface Foo {\n"
1963 " foo: number;\n"
1964 "}\n"
1965 "export class Bar {\n"
1966 " blah(): string {\n"
1967 " return this.blah;\n"
1968 " };\n"
1969 "}");
1970}
1971
1972TEST_F(FormatTestJS, ImportWrapping) {
1973 verifyFormat(Code: "import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,"
1974 " VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying"
1975 "} from 'some/module.js';");
1976 FormatStyle Style = getGoogleJSStyleWithColumns(ColumnLimit: 80);
1977 Style.JavaScriptWrapImports = true;
1978 verifyFormat(Code: "import {\n"
1979 " VeryLongImportsAreAnnoying,\n"
1980 " VeryLongImportsAreAnnoying,\n"
1981 " VeryLongImportsAreAnnoying,\n"
1982 "} from 'some/module.js';",
1983 Style);
1984 verifyFormat(Code: "import {\n"
1985 " A,\n"
1986 " A,\n"
1987 "} from 'some/module.js';",
1988 Style);
1989 verifyFormat(Code: "export {\n"
1990 " A,\n"
1991 " A,\n"
1992 "} from 'some/module.js';",
1993 Style);
1994 Style.ColumnLimit = 40;
1995 // Using this version of verifyFormat because test::messUp hides the issue.
1996 verifyFormat(Expected: "import {\n"
1997 " A,\n"
1998 "} from\n"
1999 " 'some/path/longer/than/column/limit/module.js';",
2000 Code: " import { \n"
2001 " A, \n"
2002 " } from\n"
2003 " 'some/path/longer/than/column/limit/module.js' ; ",
2004 Style);
2005}
2006
2007TEST_F(FormatTestJS, TemplateStrings) {
2008 // Keeps any whitespace/indentation within the template string.
2009 verifyFormat(Expected: "var x = `hello\n"
2010 " ${name}\n"
2011 " !`;",
2012 Code: "var x = `hello\n"
2013 " ${ name }\n"
2014 " !`;");
2015
2016 verifyFormat(Code: "var x =\n"
2017 " `hello ${world}` >= some();",
2018 Style: getGoogleJSStyleWithColumns(ColumnLimit: 34)); // Barely doesn't fit.
2019 verifyFormat(Code: "var x = `hello ${world}` >= some();",
2020 Style: getGoogleJSStyleWithColumns(ColumnLimit: 35)); // Barely fits.
2021 verifyFormat(Code: "var x = `hellö ${wörld}` >= söme();",
2022 Style: getGoogleJSStyleWithColumns(ColumnLimit: 35)); // Fits due to UTF-8.
2023 verifyFormat(Expected: "var x = `hello\n"
2024 " ${world}` >=\n"
2025 " some();",
2026 Code: "var x =\n"
2027 " `hello\n"
2028 " ${world}` >= some();",
2029 Style: getGoogleJSStyleWithColumns(ColumnLimit: 21)); // Barely doesn't fit.
2030 verifyFormat(Expected: "var x = `hello\n"
2031 " ${world}` >= some();",
2032 Code: "var x =\n"
2033 " `hello\n"
2034 " ${world}` >= some();",
2035 Style: getGoogleJSStyleWithColumns(ColumnLimit: 22)); // Barely fits.
2036
2037 verifyFormat(Code: "var x =\n"
2038 " `h`;",
2039 Style: getGoogleJSStyleWithColumns(ColumnLimit: 11));
2040 verifyFormat(Expected: "var x =\n `multi\n line`;", Code: "var x = `multi\n line`;",
2041 Style: getGoogleJSStyleWithColumns(ColumnLimit: 13));
2042 verifyFormat(Code: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
2043 " `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`);");
2044 // Repro for an obscure width-miscounting issue with template strings.
2045 verifyFormat(
2046 Expected: "someLongVariable =\n"
2047 " "
2048 "`${logPrefix[11]}/${logPrefix[12]}/${logPrefix[13]}${logPrefix[14]}`;",
2049 Code: "someLongVariable = "
2050 "`${logPrefix[11]}/${logPrefix[12]}/${logPrefix[13]}${logPrefix[14]}`;");
2051
2052 // Make sure template strings get a proper ColumnWidth assigned, even if they
2053 // are first token in line.
2054 verifyFormat(Code: "var a = aaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n"
2055 " `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`;");
2056
2057 // Two template strings.
2058 verifyFormat(Code: "var x = `hello` == `hello`;");
2059
2060 // Comments in template strings.
2061 verifyFormat(Expected: "var x = `//a`;\n"
2062 "var y;",
2063 Code: "var x =\n `//a`;\n"
2064 "var y ;");
2065 verifyFormat(Expected: "var x = `/*a`;\n"
2066 "var y;",
2067 Code: "var x =\n `/*a`;\n"
2068 "var y;");
2069 // Unterminated string literals in a template string.
2070 verifyFormat(Code: "var x = `'`; // comment with matching quote '\n"
2071 "var y;");
2072 verifyFormat(Code: "var x = `\"`; // comment with matching quote \"\n"
2073 "var y;");
2074 verifyFormat(Expected: "it(`'aaaaaaaaaaaaaaa `, aaaaaaaaa);",
2075 Code: "it(`'aaaaaaaaaaaaaaa `, aaaaaaaaa) ;",
2076 Style: getGoogleJSStyleWithColumns(ColumnLimit: 40));
2077 // Backticks in a comment - not a template string.
2078 verifyFormat(Expected: "var x = 1 // `/*a`;\n"
2079 " ;",
2080 Code: "var x =\n 1 // `/*a`;\n"
2081 " ;");
2082 verifyFormat(Expected: "/* ` */ var x = 1; /* ` */", Code: "/* ` */ var x\n= 1; /* ` */");
2083 // Comment spans multiple template strings.
2084 verifyFormat(Expected: "var x = `/*a`;\n"
2085 "var y = ` */ `;",
2086 Code: "var x =\n `/*a`;\n"
2087 "var y =\n ` */ `;");
2088 // Escaped backtick.
2089 verifyFormat(Expected: "var x = ` \\` a`;\n"
2090 "var y;",
2091 Code: "var x = ` \\` a`;\n"
2092 "var y;");
2093 // Escaped dollar.
2094 verifyFormat(Code: "var x = ` \\${foo}`;");
2095
2096 // The token stream can contain two string_literals in sequence, but that
2097 // doesn't mean that they are implicitly concatenated in JavaScript.
2098 verifyFormat(Code: "var f = `aaaa ${a ? 'a' : 'b'}`;");
2099
2100 // Ensure that scopes are appropriately set around evaluated expressions in
2101 // template strings.
2102 verifyFormat(Expected: "var f = `aaaaaaaaaaaaa:${aaaaaaa.aaaaa} aaaaaaaa\n"
2103 " aaaaaaaaaaaaa:${aaaaaaa.aaaaa} aaaaaaaa`;",
2104 Code: "var f = `aaaaaaaaaaaaa:${aaaaaaa. aaaaa} aaaaaaaa\n"
2105 " aaaaaaaaaaaaa:${ aaaaaaa. aaaaa} aaaaaaaa`;");
2106 verifyFormat(Code: "var x = someFunction(`${})`) //\n"
2107 " .oooooooooooooooooon();");
2108 verifyFormat(Code: "var x = someFunction(`${aaaa}${\n"
2109 " aaaaa( //\n"
2110 " aaaaa)})`);");
2111}
2112
2113TEST_F(FormatTestJS, TemplateStringMultiLineExpression) {
2114 verifyFormat(Expected: "var f = `aaaaaaaaaaaaaaaaaa: ${\n"
2115 " aaaaa + //\n"
2116 " bbbb}`;",
2117 Code: "var f = `aaaaaaaaaaaaaaaaaa: ${aaaaa + //\n"
2118 " bbbb}`;");
2119 verifyFormat(Expected: "var f = `\n"
2120 " aaaaaaaaaaaaaaaaaa: ${\n"
2121 " aaaaa + //\n"
2122 " bbbb}`;",
2123 Code: "var f = `\n"
2124 " aaaaaaaaaaaaaaaaaa: ${ aaaaa + //\n"
2125 " bbbb }`;");
2126 verifyFormat(Expected: "var f = `\n"
2127 " aaaaaaaaaaaaaaaaaa: ${\n"
2128 " someFunction(\n"
2129 " aaaaa + //\n"
2130 " bbbb)}`;",
2131 Code: "var f = `\n"
2132 " aaaaaaaaaaaaaaaaaa: ${someFunction (\n"
2133 " aaaaa + //\n"
2134 " bbbb)}`;");
2135
2136 // It might be preferable to wrap before "someFunction".
2137 verifyFormat(Expected: "var f = `\n"
2138 " aaaaaaaaaaaaaaaaaa: ${someFunction({\n"
2139 " aaaa: aaaaa,\n"
2140 " bbbb: bbbbb,\n"
2141 "})}`;",
2142 Code: "var f = `\n"
2143 " aaaaaaaaaaaaaaaaaa: ${someFunction ({\n"
2144 " aaaa: aaaaa,\n"
2145 " bbbb: bbbbb,\n"
2146 " })}`;");
2147}
2148
2149TEST_F(FormatTestJS, TemplateStringASI) {
2150 verifyFormat(Expected: "var x = `hello${world}`;", Code: "var x = `hello${\n"
2151 " world\n"
2152 "}`;");
2153}
2154
2155TEST_F(FormatTestJS, NestedTemplateStrings) {
2156 verifyFormat(
2157 Code: "var x = `<ul>${xs.map(x => `<li>${x}</li>`).join('\\n')}</ul>`;");
2158 verifyFormat(Code: "var x = `he${({text: 'll'}.text)}o`;");
2159
2160 // Crashed at some point.
2161 verifyFormat(Code: "}");
2162 verifyFormat(Code: "`");
2163 // FIXME: still crashing?
2164 // verifyFormat("`\\");
2165}
2166
2167TEST_F(FormatTestJS, TaggedTemplateStrings) {
2168 verifyFormat(Code: "var x = html`<ul>`;");
2169 verifyFormat(Code: "yield `hello`;");
2170 verifyFormat(Expected: "var f = {\n"
2171 " param: longTagName`This is a ${\n"
2172 " 'really'} long line`\n"
2173 "};",
2174 Code: "var f = {param: longTagName`This is a ${'really'} long line`};",
2175 Style: getGoogleJSStyleWithColumns(ColumnLimit: 40));
2176}
2177
2178TEST_F(FormatTestJS, CastSyntax) {
2179 verifyFormat(Code: "var x = <type>foo;");
2180 verifyFormat(Code: "var x = foo as type;");
2181 verifyFormat(Code: "let x = (a + b) as\n"
2182 " LongTypeIsLong;",
2183 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
2184 verifyFormat(Code: "foo = <Bar[]>[\n"
2185 " 1, //\n"
2186 " 2\n"
2187 "];");
2188 verifyFormat(Code: "var x = [{x: 1} as type];");
2189 verifyFormat(Code: "x = x as [a, b];");
2190 verifyFormat(Code: "x = x as {a: string};");
2191 verifyFormat(Code: "x = x as (string);");
2192 verifyFormat(Code: "x = x! as (string);");
2193 verifyFormat(Code: "x = y! in z;");
2194 verifyFormat(Code: "var x = something.someFunction() as\n"
2195 " something;",
2196 Style: getGoogleJSStyleWithColumns(ColumnLimit: 40));
2197}
2198
2199TEST_F(FormatTestJS, TypeArguments) {
2200 verifyFormat(Code: "class X<Y> {}");
2201 verifyFormat(Code: "new X<Y>();");
2202 verifyFormat(Code: "foo<Y>(a);");
2203 verifyFormat(Code: "var x: X<Y>[];");
2204 verifyFormat(Code: "class C extends D<E> implements F<G>, H<I> {}");
2205 verifyFormat(Code: "function f(a: List<any> = null) {}");
2206 verifyFormat(Code: "function f(): List<any> {}");
2207 verifyFormat(Code: "function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa():\n"
2208 " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {}");
2209 verifyFormat(Code: "function aaaaaaaaaa(\n"
2210 " aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaa,\n"
2211 " aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaa):\n"
2212 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {}");
2213}
2214
2215TEST_F(FormatTestJS, UserDefinedTypeGuards) {
2216 verifyFormat(
2217 Code: "function foo(check: Object):\n"
2218 " check is {foo: string, bar: string, baz: string, foobar: string} {\n"
2219 " return 'bar' in check;\n"
2220 "}");
2221}
2222
2223TEST_F(FormatTestJS, OptionalTypes) {
2224 verifyFormat(Code: "function x(a?: b, c?, d?) {}");
2225 verifyFormat(Code: "class X {\n"
2226 " y?: z;\n"
2227 " z?;\n"
2228 "}");
2229 verifyFormat(Code: "interface X {\n"
2230 " y?(): z;\n"
2231 "}");
2232 verifyFormat(Code: "constructor({aa}: {\n"
2233 " aa?: string,\n"
2234 " aaaaaaaa?: string,\n"
2235 " aaaaaaaaaaaaaaa?: boolean,\n"
2236 " aaaaaa?: List<string>\n"
2237 "}) {}");
2238 verifyFormat(Code: "type X = [y?];");
2239}
2240
2241TEST_F(FormatTestJS, IndexSignature) {
2242 verifyFormat(Code: "var x: {[k: string]: v};");
2243}
2244
2245TEST_F(FormatTestJS, WrapAfterParen) {
2246 verifyFormat(Code: "xxxxxxxxxxx(\n"
2247 " aaa, aaa);",
2248 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
2249 verifyFormat(Code: "xxxxxxxxxxx(\n"
2250 " aaa, aaa, aaa,\n"
2251 " aaa, aaa, aaa);",
2252 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
2253 verifyFormat(Code: "xxxxxxxxxxx(\n"
2254 " aaaaaaaaaaaaaaaaaaaaaaaa,\n"
2255 " function(x) {\n"
2256 " y(); //\n"
2257 " });",
2258 Style: getGoogleJSStyleWithColumns(ColumnLimit: 40));
2259 verifyFormat(Code: "while (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n"
2260 " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n}");
2261}
2262
2263TEST_F(FormatTestJS, JSDocAnnotations) {
2264 verifyFormat(Expected: "/**\n"
2265 " * @exports {this.is.a.long.path.to.a.Type}\n"
2266 " */",
2267 Code: "/**\n"
2268 " * @exports {this.is.a.long.path.to.a.Type}\n"
2269 " */",
2270 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
2271 verifyFormat(Expected: "/**\n"
2272 " * @mods {this.is.a.long.path.to.a.Type}\n"
2273 " */",
2274 Code: "/**\n"
2275 " * @mods {this.is.a.long.path.to.a.Type}\n"
2276 " */",
2277 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
2278 verifyFormat(Expected: "/**\n"
2279 " * @mods {this.is.a.long.path.to.a.Type}\n"
2280 " */",
2281 Code: "/**\n"
2282 " * @mods {this.is.a.long.path.to.a.Type}\n"
2283 " */",
2284 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
2285 verifyFormat(Expected: "/**\n"
2286 " * @param {canWrap\n"
2287 " * onSpace}\n"
2288 " */",
2289 Code: "/**\n"
2290 " * @param {canWrap onSpace}\n"
2291 " */",
2292 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
2293 // make sure clang-format doesn't break before *any* '{'
2294 verifyFormat(Expected: "/**\n"
2295 " * @lala {lala {lalala\n"
2296 " */",
2297 Code: "/**\n"
2298 " * @lala {lala {lalala\n"
2299 " */",
2300 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
2301 // cases where '{' is around the column limit
2302 for (int ColumnLimit = 6; ColumnLimit < 13; ++ColumnLimit) {
2303 verifyFormat(Expected: "/**\n"
2304 " * @param {type}\n"
2305 " */",
2306 Code: "/**\n"
2307 " * @param {type}\n"
2308 " */",
2309 Style: getGoogleJSStyleWithColumns(ColumnLimit));
2310 }
2311 // don't break before @tags
2312 verifyFormat(Expected: "/**\n"
2313 " * This\n"
2314 " * tag @param\n"
2315 " * stays.\n"
2316 " */",
2317 Code: "/**\n"
2318 " * This tag @param stays.\n"
2319 " */",
2320 Style: getGoogleJSStyleWithColumns(ColumnLimit: 13));
2321 verifyFormat(Expected: "/**\n"
2322 " * @see http://very/very/long/url/is/long\n"
2323 " */",
2324 Code: "/**\n"
2325 " * @see http://very/very/long/url/is/long\n"
2326 " */",
2327 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
2328 verifyFormat(Expected: "/**\n"
2329 " * @param This is a\n"
2330 " * long comment\n"
2331 " * but no type\n"
2332 " */",
2333 Code: "/**\n"
2334 " * @param This is a long comment but no type\n"
2335 " */",
2336 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
2337 // Break and reindent @param line and reflow unrelated lines.
2338 EXPECT_EQ("{\n"
2339 " /**\n"
2340 " * long long long\n"
2341 " * long\n"
2342 " * @param {this.is.a.long.path.to.a.Type}\n"
2343 " * a\n"
2344 " * long long long\n"
2345 " * long long\n"
2346 " */\n"
2347 " function f(a) {}\n"
2348 "}",
2349 format("{\n"
2350 "/**\n"
2351 " * long long long long\n"
2352 " * @param {this.is.a.long.path.to.a.Type} a\n"
2353 " * long long long long\n"
2354 " * long\n"
2355 " */\n"
2356 " function f(a) {}\n"
2357 "}",
2358 getGoogleJSStyleWithColumns(20)));
2359}
2360
2361TEST_F(FormatTestJS, TslintComments) {
2362 // tslint uses pragma comments that must be on their own line.
2363 verifyFormat(Expected: "// Comment that needs wrapping. Comment that needs wrapping. "
2364 "Comment that needs\n"
2365 "// wrapping. Trailing line.\n"
2366 "// tslint:disable-next-line:must-be-on-own-line",
2367 Code: "// Comment that needs wrapping. Comment that needs wrapping. "
2368 "Comment that needs wrapping.\n"
2369 "// Trailing line.\n"
2370 "// tslint:disable-next-line:must-be-on-own-line");
2371}
2372
2373TEST_F(FormatTestJS, TscComments) {
2374 // As above, @ts-ignore and @ts-check comments must be on their own line.
2375 verifyFormat(Expected: "// Comment that needs wrapping. Comment that needs wrapping. "
2376 "Comment that needs\n"
2377 "// wrapping. Trailing line.\n"
2378 "// @ts-ignore",
2379 Code: "// Comment that needs wrapping. Comment that needs wrapping. "
2380 "Comment that needs wrapping.\n"
2381 "// Trailing line.\n"
2382 "// @ts-ignore");
2383 verifyFormat(Expected: "// Comment that needs wrapping. Comment that needs wrapping. "
2384 "Comment that needs\n"
2385 "// wrapping. Trailing line.\n"
2386 "// @ts-check",
2387 Code: "// Comment that needs wrapping. Comment that needs wrapping. "
2388 "Comment that needs wrapping.\n"
2389 "// Trailing line.\n"
2390 "// @ts-check");
2391}
2392
2393TEST_F(FormatTestJS, RequoteStringsSingle) {
2394 verifyFormat(Expected: "var x = 'foo';", Code: "var x = \"foo\";");
2395 verifyFormat(Expected: "var x = 'fo\\'o\\'';", Code: "var x = \"fo'o'\";");
2396 verifyFormat(Expected: "var x = 'fo\\'o\\'';", Code: "var x = \"fo\\'o'\";");
2397 verifyFormat(Expected: "var x =\n"
2398 " 'foo\\'';",
2399 // Code below is 15 chars wide, doesn't fit into the line with
2400 // the \ escape added.
2401 Code: "var x = \"foo'\";", Style: getGoogleJSStyleWithColumns(ColumnLimit: 15));
2402 // Removes no-longer needed \ escape from ".
2403 verifyFormat(Expected: "var x = 'fo\"o';", Code: "var x = \"fo\\\"o\";");
2404 // Code below fits into 15 chars *after* removing the \ escape.
2405 verifyFormat(Expected: "var x = 'fo\"o';", Code: "var x = \"fo\\\"o\";",
2406 Style: getGoogleJSStyleWithColumns(ColumnLimit: 15));
2407 verifyFormat(Expected: "// clang-format off\n"
2408 "let x = \"double\";\n"
2409 "// clang-format on\n"
2410 "let x = 'single';",
2411 Code: "// clang-format off\n"
2412 "let x = \"double\";\n"
2413 "// clang-format on\n"
2414 "let x = \"single\";");
2415}
2416
2417TEST_F(FormatTestJS, RequoteAndIndent) {
2418 verifyFormat(Expected: "let x = someVeryLongFunctionThatGoesOnAndOn(\n"
2419 " 'double quoted string that needs wrapping');",
2420 Code: "let x = someVeryLongFunctionThatGoesOnAndOn("
2421 "\"double quoted string that needs wrapping\");");
2422
2423 verifyFormat(Expected: "let x =\n"
2424 " 'foo\\'oo';\n"
2425 "let x =\n"
2426 " 'foo\\'oo';",
2427 Code: "let x=\"foo'oo\";\n"
2428 "let x=\"foo'oo\";",
2429 Style: getGoogleJSStyleWithColumns(ColumnLimit: 15));
2430}
2431
2432TEST_F(FormatTestJS, RequoteStringsDouble) {
2433 FormatStyle DoubleQuotes = getGoogleStyle(Language: FormatStyle::LK_JavaScript);
2434 DoubleQuotes.JavaScriptQuotes = FormatStyle::JSQS_Double;
2435 verifyFormat(Code: "var x = \"foo\";", Style: DoubleQuotes);
2436 verifyFormat(Expected: "var x = \"foo\";", Code: "var x = 'foo';", Style: DoubleQuotes);
2437 verifyFormat(Expected: "var x = \"fo'o\";", Code: "var x = 'fo\\'o';", Style: DoubleQuotes);
2438}
2439
2440TEST_F(FormatTestJS, RequoteStringsLeave) {
2441 FormatStyle LeaveQuotes = getGoogleStyle(Language: FormatStyle::LK_JavaScript);
2442 LeaveQuotes.JavaScriptQuotes = FormatStyle::JSQS_Leave;
2443 verifyFormat(Code: "var x = \"foo\";", Style: LeaveQuotes);
2444 verifyFormat(Code: "var x = 'foo';", Style: LeaveQuotes);
2445}
2446
2447TEST_F(FormatTestJS, SupportShebangLines) {
2448 verifyFormat(Expected: "#!/usr/bin/env node\n"
2449 "var x = hello();",
2450 Code: "#!/usr/bin/env node\n"
2451 "var x = hello();");
2452}
2453
2454TEST_F(FormatTestJS, NonNullAssertionOperator) {
2455 verifyFormat(Code: "let x = foo!.bar();");
2456 verifyFormat(Code: "let x = foo ? bar! : baz;");
2457 verifyFormat(Code: "let x = !foo;");
2458 verifyFormat(Code: "if (!+a) {\n}");
2459 verifyFormat(Code: "let x = foo[0]!;");
2460 verifyFormat(Code: "let x = (foo)!;");
2461 verifyFormat(Code: "let x = x(foo!);");
2462 verifyFormat(Code: "a.aaaaaa(a.a!).then(\n"
2463 " x => x(x));",
2464 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
2465 verifyFormat(Code: "let x = foo! - 1;");
2466 verifyFormat(Code: "let x = {foo: 1}!;");
2467 verifyFormat(Code: "let x = hello.foo()!\n"
2468 " .foo()!\n"
2469 " .foo()!\n"
2470 " .foo()!;",
2471 Style: getGoogleJSStyleWithColumns(ColumnLimit: 20));
2472 verifyFormat(Code: "let x = namespace!;");
2473 verifyFormat(Code: "return !!x;");
2474}
2475
2476TEST_F(FormatTestJS, CppKeywords) {
2477 // Make sure we don't mess stuff up because of C++ keywords.
2478 verifyFormat(Code: "return operator && (aa);");
2479 // .. or QT ones.
2480 verifyFormat(Code: "const slots: Slot[];");
2481 // use the "!" assertion operator to validate that clang-format understands
2482 // these C++ keywords aren't keywords in JS/TS.
2483 verifyFormat(Code: "auto!;");
2484 verifyFormat(Code: "char!;");
2485 verifyFormat(Code: "concept!;");
2486 verifyFormat(Code: "double!;");
2487 verifyFormat(Code: "extern!;");
2488 verifyFormat(Code: "float!;");
2489 verifyFormat(Code: "inline!;");
2490 verifyFormat(Code: "int!;");
2491 verifyFormat(Code: "long!;");
2492 verifyFormat(Code: "register!;");
2493 verifyFormat(Code: "restrict!;");
2494 verifyFormat(Code: "sizeof!;");
2495 verifyFormat(Code: "struct!;");
2496 verifyFormat(Code: "typedef!;");
2497 verifyFormat(Code: "union!;");
2498 verifyFormat(Code: "unsigned!;");
2499 verifyFormat(Code: "volatile!;");
2500 verifyFormat(Code: "_Alignas!;");
2501 verifyFormat(Code: "_Alignof!;");
2502 verifyFormat(Code: "_Atomic!;");
2503 verifyFormat(Code: "_Bool!;");
2504 verifyFormat(Code: "_Complex!;");
2505 verifyFormat(Code: "_Generic!;");
2506 verifyFormat(Code: "_Imaginary!;");
2507 verifyFormat(Code: "_Noreturn!;");
2508 verifyFormat(Code: "_Static_assert!;");
2509 verifyFormat(Code: "_Thread_local!;");
2510 verifyFormat(Code: "__func__!;");
2511 verifyFormat(Code: "__objc_yes!;");
2512 verifyFormat(Code: "__objc_no!;");
2513 verifyFormat(Code: "asm!;");
2514 verifyFormat(Code: "bool!;");
2515 verifyFormat(Code: "const_cast!;");
2516 verifyFormat(Code: "dynamic_cast!;");
2517 verifyFormat(Code: "explicit!;");
2518 verifyFormat(Code: "friend!;");
2519 verifyFormat(Code: "mutable!;");
2520 verifyFormat(Code: "operator!;");
2521 verifyFormat(Code: "reinterpret_cast!;");
2522 verifyFormat(Code: "static_cast!;");
2523 verifyFormat(Code: "template!;");
2524 verifyFormat(Code: "typename!;");
2525 verifyFormat(Code: "typeid!;");
2526 verifyFormat(Code: "using!;");
2527 verifyFormat(Code: "virtual!;");
2528 verifyFormat(Code: "wchar_t!;");
2529
2530 // Positive tests:
2531 verifyFormat(Code: "x.type!;");
2532 verifyFormat(Code: "x.get!;");
2533 verifyFormat(Code: "x.set!;");
2534}
2535
2536TEST_F(FormatTestJS, NullPropagatingOperator) {
2537 verifyFormat(Code: "let x = foo?.bar?.baz();");
2538 verifyFormat(Code: "let x = foo?.(foo);");
2539 verifyFormat(Code: "let x = foo?.['arr'];");
2540}
2541
2542TEST_F(FormatTestJS, NullishCoalescingOperator) {
2543 verifyFormat(Code: "const val = something ?? 'some other default';");
2544 verifyFormat(Expected: "const val = something ?? otherDefault ??\n"
2545 " evenMore ?? evenMore;",
2546 Code: "const val = something ?? otherDefault ?? evenMore ?? evenMore;",
2547 Style: getGoogleJSStyleWithColumns(ColumnLimit: 40));
2548}
2549
2550TEST_F(FormatTestJS, AssignmentOperators) {
2551 verifyFormat(Code: "a &&= b;");
2552 verifyFormat(Code: "a ||= b;");
2553 // NB: need to split ? ?= to avoid it being interpreted by C++ as a trigraph
2554 // for #.
2555 verifyFormat(Code: "a ?"
2556 "?= b;");
2557}
2558
2559TEST_F(FormatTestJS, Conditional) {
2560 verifyFormat(Code: "y = x ? 1 : 2;");
2561 verifyFormat(Code: "x ? 1 : 2;");
2562 verifyFormat(Code: "class Foo {\n"
2563 " field = true ? 1 : 2;\n"
2564 " method(a = true ? 1 : 2) {}\n"
2565 "}");
2566}
2567
2568TEST_F(FormatTestJS, ImportComments) {
2569 verifyFormat(Code: "import {x} from 'x'; // from some location",
2570 Style: getGoogleJSStyleWithColumns(ColumnLimit: 25));
2571 verifyFormat(Code: "// taze: x from 'location'", Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
2572 verifyFormat(Code: "/// <reference path=\"some/location\" />",
2573 Style: getGoogleJSStyleWithColumns(ColumnLimit: 10));
2574}
2575
2576TEST_F(FormatTestJS, Exponentiation) {
2577 verifyFormat(Code: "squared = x ** 2;");
2578 verifyFormat(Code: "squared **= 2;");
2579}
2580
2581TEST_F(FormatTestJS, NestedLiterals) {
2582 FormatStyle FourSpaces = getGoogleJSStyleWithColumns(ColumnLimit: 15);
2583 FourSpaces.IndentWidth = 4;
2584 verifyFormat(Code: "var l = [\n"
2585 " [\n"
2586 " 1,\n"
2587 " ],\n"
2588 "];",
2589 Style: FourSpaces);
2590 verifyFormat(Code: "var l = [\n"
2591 " {\n"
2592 " 1: 1,\n"
2593 " },\n"
2594 "];",
2595 Style: FourSpaces);
2596 verifyFormat(Code: "someFunction(\n"
2597 " p1,\n"
2598 " [\n"
2599 " 1,\n"
2600 " ],\n"
2601 ");",
2602 Style: FourSpaces);
2603 verifyFormat(Code: "someFunction(\n"
2604 " p1,\n"
2605 " {\n"
2606 " 1: 1,\n"
2607 " },\n"
2608 ");",
2609 Style: FourSpaces);
2610 verifyFormat(Code: "var o = {\n"
2611 " 1: 1,\n"
2612 " 2: {\n"
2613 " 3: 3,\n"
2614 " },\n"
2615 "};",
2616 Style: FourSpaces);
2617 verifyFormat(Code: "var o = {\n"
2618 " 1: 1,\n"
2619 " 2: [\n"
2620 " 3,\n"
2621 " ],\n"
2622 "};",
2623 Style: FourSpaces);
2624}
2625
2626TEST_F(FormatTestJS, BackslashesInComments) {
2627 verifyFormat(Expected: "// hello \\\n"
2628 "if (x) foo();",
2629 Code: "// hello \\\n"
2630 " if ( x) \n"
2631 " foo();");
2632 verifyFormat(Expected: "/* ignore \\\n"
2633 " */\n"
2634 "if (x) foo();",
2635 Code: "/* ignore \\\n"
2636 " */\n"
2637 " if ( x) foo();");
2638 verifyFormat(Expected: "// st \\ art\\\n"
2639 "// comment"
2640 "// continue \\\n"
2641 "formatMe();",
2642 Code: "// st \\ art\\\n"
2643 "// comment"
2644 "// continue \\\n"
2645 "formatMe( );");
2646}
2647
2648TEST_F(FormatTestJS, AddsLastLinePenaltyIfEndingIsBroken) {
2649 EXPECT_EQ(
2650 "a = function() {\n"
2651 " b = function() {\n"
2652 " this.aaaaaaaaaaaaaaaaaaa[aaaaaaaaaaa] = aaaa.aaaaaa ?\n"
2653 " aaaa.aaaaaa : /** @type "
2654 "{aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaaaaaaaa} */\n"
2655 " (aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaa.aaaaaaaaaaaaaaaaa);\n"
2656 " };\n"
2657 "};",
2658 format("a = function() {\n"
2659 " b = function() {\n"
2660 " this.aaaaaaaaaaaaaaaaaaa[aaaaaaaaaaa] = aaaa.aaaaaa ? "
2661 "aaaa.aaaaaa : /** @type "
2662 "{aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaaaaaaaa} */\n"
2663 " (aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaa.aaaaaaaaaaaaaaaaa);\n"
2664 " };\n"
2665 "};"));
2666}
2667
2668TEST_F(FormatTestJS, ParameterNamingComment) {
2669 verifyFormat(Code: "callFoo(/*spaceAfterParameterNamingComment=*/ 1);");
2670}
2671
2672TEST_F(FormatTestJS, ConditionalTypes) {
2673 // Formatting below is not necessarily intentional, this just ensures that
2674 // clang-format does not break the code.
2675 verifyFormat( // wrap
2676 Code: "type UnionToIntersection<U> =\n"
2677 " (U extends any ? (k: U) => void :\n"
2678 " never) extends((k: infer I) => void) ? I : never;");
2679}
2680
2681TEST_F(FormatTestJS, SupportPrivateFieldsAndMethods) {
2682 verifyFormat(Code: "class Example {\n"
2683 " pub = 1;\n"
2684 " #priv = 2;\n"
2685 " static pub2 = 'foo';\n"
2686 " static #priv2 = 'bar';\n"
2687 " method() {\n"
2688 " this.#priv = 5;\n"
2689 " }\n"
2690 " static staticMethod() {\n"
2691 " switch (this.#priv) {\n"
2692 " case '1':\n"
2693 " #priv = 3;\n"
2694 " break;\n"
2695 " }\n"
2696 " }\n"
2697 " #privateMethod() {\n"
2698 " this.#privateMethod(); // infinite loop\n"
2699 " }\n"
2700 " static #staticPrivateMethod() {}");
2701}
2702
2703TEST_F(FormatTestJS, DeclaredFields) {
2704 verifyFormat(Code: "class Example {\n"
2705 " declare pub: string;\n"
2706 " declare private priv: string;\n"
2707 "}");
2708}
2709
2710TEST_F(FormatTestJS, NoBreakAfterAsserts) {
2711 verifyFormat(
2712 Expected: "interface Assertable<State extends {}> {\n"
2713 " assert<ExportedState extends {}, DependencyState extends State = "
2714 "State>(\n"
2715 " callback: Callback<ExportedState, DependencyState>):\n"
2716 " asserts this is ExtendedState<DependencyState&ExportedState>;\n"
2717 "}",
2718 Code: "interface Assertable<State extends {}> {\n"
2719 " assert<ExportedState extends {}, DependencyState extends State = "
2720 "State>(callback: Callback<ExportedState, DependencyState>): asserts "
2721 "this is ExtendedState<DependencyState&ExportedState>;\n"
2722 "}");
2723}
2724
2725TEST_F(FormatTestJS, NumericSeparators) {
2726 verifyFormat(Expected: "x = 1_000_000 + 12;", Code: "x = 1_000_000 + 12;");
2727}
2728
2729TEST_F(FormatTestJS, AlignConsecutiveDeclarations) {
2730 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_JavaScript);
2731 Style.AlignConsecutiveDeclarations.Enabled = true;
2732 verifyFormat(Code: "let letVariable = 5;\n"
2733 "double constVariable = 10;",
2734 Style);
2735
2736 verifyFormat(Code: "let letVariable = 5;\n"
2737 "const constVariable = 10;",
2738 Style);
2739
2740 verifyFormat(Code: "let letVariable = 5;\n"
2741 "static const constVariable = 10;",
2742 Style);
2743
2744 verifyFormat(Code: "let letVariable = 5;\n"
2745 "static var constVariable = 10;",
2746 Style);
2747
2748 verifyFormat(Code: "let letVariable = 5;\n"
2749 "var constVariable = 10;",
2750 Style);
2751
2752 verifyFormat(Code: "double letVariable = 5;\n"
2753 "var constVariable = 10;",
2754 Style);
2755
2756 verifyFormat(Code: "const letVariable = 5;\n"
2757 "var constVariable = 10;",
2758 Style);
2759
2760 verifyFormat(Code: "int letVariable = 5;\n"
2761 "int constVariable = 10;",
2762 Style);
2763}
2764
2765TEST_F(FormatTestJS, AlignConsecutiveAssignments) {
2766 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_JavaScript);
2767
2768 Style.AlignConsecutiveAssignments.Enabled = true;
2769 verifyFormat(Code: "let letVariable = 5;\n"
2770 "double constVariable = 10;",
2771 Style);
2772
2773 verifyFormat(Code: "let letVariable = 5;\n"
2774 "const constVariable = 10;",
2775 Style);
2776
2777 verifyFormat(Code: "let letVariable = 5;\n"
2778 "static const constVariable = 10;",
2779 Style);
2780
2781 verifyFormat(Code: "let letVariable = 5;\n"
2782 "static var constVariable = 10;",
2783 Style);
2784
2785 verifyFormat(Code: "let letVariable = 5;\n"
2786 "var constVariable = 10;",
2787 Style);
2788
2789 verifyFormat(Code: "double letVariable = 5;\n"
2790 "var constVariable = 10;",
2791 Style);
2792
2793 verifyFormat(Code: "const letVariable = 5;\n"
2794 "var constVariable = 10;",
2795 Style);
2796
2797 verifyFormat(Code: "int letVariable = 5;\n"
2798 "int constVariable = 10;",
2799 Style);
2800}
2801
2802TEST_F(FormatTestJS, AlignConsecutiveAssignmentsAndDeclarations) {
2803 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_JavaScript);
2804 Style.AlignConsecutiveDeclarations.Enabled = true;
2805 Style.AlignConsecutiveAssignments.Enabled = true;
2806 verifyFormat(Code: "let letVariable = 5;\n"
2807 "double constVariable = 10;",
2808 Style);
2809
2810 verifyFormat(Code: "let letVariable = 5;\n"
2811 "const constVariable = 10;",
2812 Style);
2813
2814 verifyFormat(Code: "let letVariable = 5;\n"
2815 "static const constVariable = 10;",
2816 Style);
2817
2818 verifyFormat(Code: "let letVariable = 5;\n"
2819 "static var constVariable = 10;",
2820 Style);
2821
2822 verifyFormat(Code: "let letVariable = 5;\n"
2823 "var constVariable = 10;",
2824 Style);
2825
2826 verifyFormat(Code: "double letVariable = 5;\n"
2827 "var constVariable = 10;",
2828 Style);
2829
2830 verifyFormat(Code: "const letVariable = 5;\n"
2831 "var constVariable = 10;",
2832 Style);
2833
2834 verifyFormat(Code: "int letVariable = 5;\n"
2835 "int constVariable = 10;",
2836 Style);
2837}
2838
2839TEST_F(FormatTestJS, DontBreakFieldsAsGoToLabels) {
2840 verifyFormat(Code: "export type Params = Config&{\n"
2841 " columns: Column[];\n"
2842 "};");
2843}
2844
2845} // namespace format
2846} // end namespace clang
2847

source code of clang/unittests/Format/FormatTestJS.cpp