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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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