1 //===- unittest/Format/FormatTestJS.cpp - Formatting unit tests for JS ----===//
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
7 //===----------------------------------------------------------------------===//
9 #include "FormatTestUtils.h"
10 #include "clang/Format/Format.h"
11 #include "llvm/Support/Debug.h"
12 #include "gtest/gtest.h"
14 #define DEBUG_TYPE "format-test"
19 class FormatTestJS
: public ::testing::Test
{
21 static std::string
format(llvm::StringRef Code
, unsigned Offset
,
22 unsigned Length
, const FormatStyle
&Style
) {
23 LLVM_DEBUG(llvm::errs() << "---\n");
24 LLVM_DEBUG(llvm::errs() << Code
<< "\n\n");
25 std::vector
<tooling::Range
> Ranges(1, tooling::Range(Offset
, Length
));
26 FormattingAttemptStatus Status
;
27 tooling::Replacements Replaces
=
28 reformat(Style
, Code
, Ranges
, "<stdin>", &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");
36 static std::string
format(
38 const FormatStyle
&Style
= getGoogleStyle(FormatStyle::LK_JavaScript
)) {
39 return format(Code
, 0, Code
.size(), Style
);
42 static FormatStyle
getGoogleJSStyleWithColumns(unsigned ColumnLimit
) {
43 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_JavaScript
);
44 Style
.ColumnLimit
= ColumnLimit
;
48 static void verifyFormat(
50 const FormatStyle
&Style
= getGoogleStyle(FormatStyle::LK_JavaScript
)) {
51 EXPECT_EQ(Code
.str(), format(Code
, Style
)) << "Expected code is not stable";
52 std::string Result
= format(test::messUp(Code
), Style
);
53 EXPECT_EQ(Code
.str(), Result
) << "Formatted:\n" << Result
;
56 static void verifyFormat(
57 llvm::StringRef Expected
, llvm::StringRef Code
,
58 const FormatStyle
&Style
= getGoogleStyle(FormatStyle::LK_JavaScript
)) {
59 EXPECT_EQ(Expected
.str(), format(Expected
, Style
))
60 << "Expected code is not stable";
61 std::string Result
= format(Code
, Style
);
62 EXPECT_EQ(Expected
.str(), Result
) << "Formatted:\n" << Result
;
66 TEST_F(FormatTestJS
, BlockComments
) {
67 verifyFormat("/* aaaaaaaaaaaaa */ aaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
68 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
69 // Breaks after a single line block comment.
70 EXPECT_EQ("aaaaa = bbbb.ccccccccccccccc(\n"
71 " /** @type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala} */\n"
73 format("aaaaa = bbbb.ccccccccccccccc(\n"
75 "@type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala} */ "
77 getGoogleJSStyleWithColumns(70)));
78 // Breaks after a multiline block comment.
80 "aaaaa = bbbb.ccccccccccccccc(\n"
82 " * @type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala}\n"
85 format("aaaaa = bbbb.ccccccccccccccc(\n"
87 " * @type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala}\n"
89 getGoogleJSStyleWithColumns(70)));
92 TEST_F(FormatTestJS
, JSDocComments
) {
93 // Break the first line of a multiline jsdoc comment.
98 format("/** jsdoc line 1\n"
101 getGoogleJSStyleWithColumns(20)));
102 // Both break after '/**' and break the line itself.
104 " * jsdoc line long\n"
105 " * long jsdoc line 2\n"
107 format("/** jsdoc line long long\n"
110 getGoogleJSStyleWithColumns(20)));
111 // Break a short first line if the ending '*/' is on a newline.
115 format("/** jsdoc line 1\n"
117 getGoogleJSStyleWithColumns(20)));
118 // Don't break the first line of a short single line jsdoc comment.
119 verifyFormat("/** jsdoc line 1 */", getGoogleJSStyleWithColumns(20));
120 // Don't break the first line of a single line jsdoc comment if it just fits
122 verifyFormat("/** jsdoc line 12 */", getGoogleJSStyleWithColumns(20));
123 // Don't break after '/**' and before '*/' if there is no space between
124 // '/**' and the content.
126 "/*** nonjsdoc long\n"
128 format("/*** nonjsdoc long line */", getGoogleJSStyleWithColumns(20)));
130 "/**strange long long\n"
132 format("/**strange long long line */", getGoogleJSStyleWithColumns(20)));
133 // Break the first line of a single line jsdoc comment if it just exceeds the
136 " * jsdoc line 123\n"
138 format("/** jsdoc line 123 */", getGoogleJSStyleWithColumns(20)));
139 // Break also if the leading indent of the first line is more than 1 column.
141 " * jsdoc line 123\n"
143 format("/** jsdoc line 123 */", getGoogleJSStyleWithColumns(20)));
144 // Break also if the leading indent of the first line is more than 1 column.
146 " * jsdoc line 123\n"
148 format("/** jsdoc line 123 */", getGoogleJSStyleWithColumns(20)));
149 // Break after the content of the last line.
157 getGoogleJSStyleWithColumns(20)));
158 // Break both the content and after the content of the last line.
161 " * line long long\n"
166 " * line long long long */",
167 getGoogleJSStyleWithColumns(20)));
169 // The comment block gets indented.
170 EXPECT_EQ("function f() {\n"
177 format("function f() {\n"
178 "/** comment about x */\n"
181 getGoogleJSStyleWithColumns(20)));
183 // Don't break the first line of a single line short jsdoc comment pragma.
184 verifyFormat("/** @returns j */", getGoogleJSStyleWithColumns(20));
186 // Break a single line long jsdoc comment pragma.
188 " * @returns {string}\n"
191 format("/** @returns {string} jsdoc line 12 */",
192 getGoogleJSStyleWithColumns(20)));
194 // FIXME: this overcounts the */ as a continuation of the 12 when breaking.
195 // Cf. BreakableBlockComment::getRemainingLength.
197 " * @returns {string}\n"
198 " * jsdoc line line\n"
201 format("/** @returns {string} jsdoc line line 12*/",
202 getGoogleJSStyleWithColumns(25)));
204 // Fix a multiline jsdoc comment ending in a comment pragma.
208 " * @returns {string}\n"
211 format("/** line 1\n"
213 " * @returns {string} jsdoc line 12 */",
214 getGoogleJSStyleWithColumns(20)));
222 format("/** line 1\n"
226 getGoogleJSStyleWithColumns(20)));
229 TEST_F(FormatTestJS
, UnderstandsJavaScriptOperators
) {
230 verifyFormat("a == = b;");
231 verifyFormat("a != = b;");
233 verifyFormat("a === b;");
234 verifyFormat("aaaaaaa ===\n b;", getGoogleJSStyleWithColumns(10));
235 verifyFormat("a !== b;");
236 verifyFormat("aaaaaaa !==\n b;", getGoogleJSStyleWithColumns(10));
237 verifyFormat("if (a + b + c +\n"
241 getGoogleJSStyleWithColumns(20));
243 verifyFormat("a >> >= b;");
245 verifyFormat("a >>> b;");
246 verifyFormat("aaaaaaa >>>\n b;", getGoogleJSStyleWithColumns(10));
247 verifyFormat("a >>>= b;");
248 verifyFormat("aaaaaaa >>>=\n b;", getGoogleJSStyleWithColumns(10));
249 verifyFormat("if (a + b + c +\n"
253 getGoogleJSStyleWithColumns(20));
254 verifyFormat("var x = aaaaaaaaaa ?\n"
257 getGoogleJSStyleWithColumns(20));
259 verifyFormat("var b = a.map((x) => x + 1);");
260 verifyFormat("return ('aaa') in bbbb;");
261 verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa() in\n"
262 " aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;");
263 FormatStyle Style
= getGoogleJSStyleWithColumns(80);
264 Style
.AlignOperands
= FormatStyle::OAS_Align
;
265 verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa() in\n"
266 " aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
268 Style
.BreakBeforeBinaryOperators
= FormatStyle::BOS_All
;
269 verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa()\n"
270 " in aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
273 // ES6 spread operator.
274 verifyFormat("someFunction(...a);");
275 verifyFormat("var x = [1, ...a, 2];");
277 // "- -1" is legal JS syntax, but must not collapse into "--".
278 verifyFormat("- -1;", " - -1;");
279 verifyFormat("-- -1;", " -- -1;");
280 verifyFormat("+ +1;", " + +1;");
281 verifyFormat("++ +1;", " ++ +1;");
284 TEST_F(FormatTestJS
, UnderstandsAmpAmp
) {
285 verifyFormat("e && e.SomeFunction();");
288 TEST_F(FormatTestJS
, LiteralOperatorsCanBeKeywords
) {
289 verifyFormat("not.and.or.not_eq = 1;");
292 TEST_F(FormatTestJS
, ReservedWords
) {
293 // JavaScript reserved words (aka keywords) are only illegal when used as
294 // Identifiers, but are legal as IdentifierNames.
295 verifyFormat("x.class.struct = 1;");
296 verifyFormat("x.case = 1;");
297 verifyFormat("x.interface = 1;");
298 verifyFormat("x.for = 1;");
299 verifyFormat("x.of();");
300 verifyFormat("of(null);");
301 verifyFormat("return of(null);");
302 verifyFormat("import {of} from 'x';");
303 verifyFormat("x.in();");
304 verifyFormat("x.let();");
305 verifyFormat("x.var();");
306 verifyFormat("x.for();");
307 verifyFormat("x.as();");
308 verifyFormat("x.instanceof();");
309 verifyFormat("x.switch();");
310 verifyFormat("x.case();");
311 verifyFormat("x.delete();");
312 verifyFormat("x.throw();");
313 verifyFormat("x.throws();");
314 verifyFormat("x.if();");
315 verifyFormat("x = {\n"
320 verifyFormat("var struct = 2;");
321 verifyFormat("var union = 2;");
322 verifyFormat("var interface = 2;");
323 verifyFormat("var requires = {};");
324 verifyFormat("interface = 2;");
325 verifyFormat("x = interface instanceof y;");
326 verifyFormat("interface Test {\n"
330 " default: string;\n"
332 verifyFormat("const Axis = {\n"
336 "const Axis = {for: 'for', x: 'x'};");
337 verifyFormat("export class Foo extends Bar {\n"
338 " get case(): Case {\n"
340 " (this.Bar$has('case')) ? (this.Bar$get('case')) :\n"
341 " (this.case = new Case()));\n"
346 TEST_F(FormatTestJS
, ReservedWordsMethods
) {
347 verifyFormat("class X {\n"
358 verifyFormat("class KeywordNamedMethods {\n"
376 TEST_F(FormatTestJS
, ReservedWordsParenthesized
) {
377 // All of these are statements using the keyword, not function calls.
378 verifyFormat("throw (x + y);\n"
379 "await (await x).y;\n"
380 "typeof (x) === 'string';\n"
386 TEST_F(FormatTestJS
, ES6DestructuringAssignment
) {
387 verifyFormat("var [a, b, c] = [1, 2, 3];");
388 verifyFormat("const [a, b, c] = [1, 2, 3];");
389 verifyFormat("let [a, b, c] = [1, 2, 3];");
390 verifyFormat("var {a, b} = {a: 1, b: 2};");
391 verifyFormat("let {a, b} = {a: 1, b: 2};");
394 TEST_F(FormatTestJS
, ContainerLiterals
) {
395 verifyFormat("var x = {\n"
396 " y: function(a) {\n"
400 verifyFormat("return {\n"
401 " link: function() {\n"
405 verifyFormat("return {\n"
407 " link: function() {\n"
411 verifyFormat("return {\n"
413 " link: function() {\n"
416 " link: function() {\n"
420 verifyFormat("var stuff = {\n"
421 " // comment for update\n"
423 " // comment for modules\n"
425 " // comment for tasks\n"
428 verifyFormat("return {\n"
433 verifyFormat("var obj = {\n"
434 " fooooooooo: function(x) {\n"
435 " return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
438 // Simple object literal, as opposed to enum style below.
439 verifyFormat("var obj = {a: 123};");
440 // Enum style top level assignment.
441 verifyFormat("X = {\n a: 123\n};");
442 verifyFormat("X.Y = {\n a: 123\n};");
443 // But only on the top level, otherwise its a plain object literal assignment.
444 verifyFormat("function x() {\n"
447 verifyFormat("x = foo && {a: 123};");
449 // Arrow functions in object literals.
450 verifyFormat("var x = {\n"
456 verifyFormat("var x = {y: (a) => a};");
458 // Methods in object literals.
459 verifyFormat("var x = {\n"
460 " y(a: string): number {\n"
464 verifyFormat("var x = {\n"
471 verifyFormat("var x = {[a]: 1, b: 2, [c]: 3};");
472 verifyFormat("var x = {\n"
478 // Object literals can leave out labels.
479 verifyFormat("f({a}, () => {\n"
484 // Keys can be quoted.
485 verifyFormat("var x = {\n"
491 // Dict literals can skip the label names.
492 verifyFormat("var x = {\n"
497 verifyFormat("return {\n"
504 TEST_F(FormatTestJS
, MethodsInObjectLiterals
) {
505 verifyFormat("var o = {\n"
507 " get value() { // getter\n"
508 " return this.value;\n"
511 verifyFormat("var o = {\n"
513 " set value(val) { // setter\n"
514 " this.value = val;\n"
517 verifyFormat("var o = {\n"
519 " someMethod(val) { // method\n"
520 " doSomething(this.value + val);\n"
523 verifyFormat("var o = {\n"
524 " someMethod(val) { // method\n"
525 " doSomething(this.value + val);\n"
527 " someOtherMethod(val) { // method\n"
528 " doSomething(this.value + val);\n"
533 TEST_F(FormatTestJS
, GettersSettersVisibilityKeywords
) {
534 // Don't break after "protected"
535 verifyFormat("class X {\n"
536 " protected get getter():\n"
541 getGoogleJSStyleWithColumns(12));
542 // Don't break after "get"
543 verifyFormat("class X {\n"
544 " protected get someReallyLongGetterName():\n"
549 getGoogleJSStyleWithColumns(40));
552 TEST_F(FormatTestJS
, SpacesInContainerLiterals
) {
553 verifyFormat("var arr = [1, 2, 3];");
554 verifyFormat("f({a: 1, b: 2, c: 3});");
556 verifyFormat("var object_literal_with_long_name = {\n"
557 " a: 'aaaaaaaaaaaaaaaaaa',\n"
558 " b: 'bbbbbbbbbbbbbbbbbb'\n"
561 verifyFormat("f({a: 1, b: 2, c: 3});",
562 getChromiumStyle(FormatStyle::LK_JavaScript
));
563 verifyFormat("f({'a': [{}]});");
566 TEST_F(FormatTestJS
, SingleQuotedStrings
) {
567 verifyFormat("this.function('', true);");
570 TEST_F(FormatTestJS
, GoogScopes
) {
571 verifyFormat("goog.scope(function() {\n"
574 "}); // goog.scope");
575 verifyFormat("goog.scope(function() {\n"
582 TEST_F(FormatTestJS
, IIFEs
) {
583 // Internal calling parens; no semi.
584 verifyFormat("(function() {\n"
587 // External calling parens; no semi.
588 verifyFormat("(function() {\n"
591 // Internal calling parens; with semi.
592 verifyFormat("(function() {\n"
595 // External calling parens; with semi.
596 verifyFormat("(function() {\n"
601 TEST_F(FormatTestJS
, GoogModules
) {
602 verifyFormat("goog.module('this.is.really.absurdly.long');",
603 getGoogleJSStyleWithColumns(40));
604 verifyFormat("goog.require('this.is.really.absurdly.long');",
605 getGoogleJSStyleWithColumns(40));
606 verifyFormat("goog.provide('this.is.really.absurdly.long');",
607 getGoogleJSStyleWithColumns(40));
608 verifyFormat("var long = goog.require('this.is.really.absurdly.long');",
609 getGoogleJSStyleWithColumns(40));
610 verifyFormat("const X = goog.requireType('this.is.really.absurdly.long');",
611 getGoogleJSStyleWithColumns(40));
612 verifyFormat("goog.forwardDeclare('this.is.really.absurdly.long');",
613 getGoogleJSStyleWithColumns(40));
615 // These should be wrapped normally.
617 "var MyLongClassName =\n"
618 " goog.module.get('my.long.module.name.followedBy.MyLongClassName');");
619 verifyFormat("function a() {\n"
620 " goog.setTestOnly();\n"
623 "goog.setTestOnly();\n"
627 TEST_F(FormatTestJS
, FormatsNamespaces
) {
628 verifyFormat("namespace Foo {\n"
629 " export let x = 1;\n"
631 verifyFormat("declare namespace Foo {\n"
632 " export let x: number;\n"
636 TEST_F(FormatTestJS
, NamespacesMayNotWrap
) {
637 verifyFormat("declare namespace foobarbaz {\n"
639 getGoogleJSStyleWithColumns(18));
640 verifyFormat("declare module foobarbaz {\n"
642 getGoogleJSStyleWithColumns(15));
643 verifyFormat("namespace foobarbaz {\n"
645 getGoogleJSStyleWithColumns(10));
646 verifyFormat("module foobarbaz {\n"
648 getGoogleJSStyleWithColumns(7));
651 TEST_F(FormatTestJS
, AmbientDeclarations
) {
652 FormatStyle NineCols
= getGoogleJSStyleWithColumns(9);
653 verifyFormat("declare class\n"
656 verifyFormat("declare function\n"
657 "x();", // TODO(martinprobst): should ideally be indented.
659 verifyFormat("declare function foo();\n"
661 verifyFormat("declare function foo(): string;\n"
663 verifyFormat("declare function foo(): {x: number};\n"
665 verifyFormat("declare class X {}\n"
667 verifyFormat("declare interface Y {}\n"
669 verifyFormat("declare enum X {\n"
672 verifyFormat("declare let\n"
677 TEST_F(FormatTestJS
, FormatsFreestandingFunctions
) {
678 verifyFormat("function outer1(a, b) {\n"
679 " function inner1(a, b) {\n"
684 "function outer2(a, b) {\n"
685 " function inner2(a, b) {\n"
690 verifyFormat("function f() {}");
691 verifyFormat("function aFunction() {}\n"
695 verifyFormat("function aFunction() {}\n"
700 EXPECT_EQ("a = function(x) {}\n"
703 format("a = function(x) {}\n"
706 getGoogleJSStyleWithColumns(20)));
709 TEST_F(FormatTestJS
, FormatsDecorators
) {
710 // No line break after argument decorators.
711 verifyFormat("class A {\n"
712 " constructor(@arg(DECOR) private arg: Type) {}\n"
714 // Ensure that there is a break before functions, getters and setters.
715 EXPECT_EQ("class A {\n"
716 " private p = () => {}\n"
725 " private p = () => {}\n"
734 " private p = () => {}\n"
742 " private p = () => {}\n"
751 " private p = () => {}\n"
760 " private p = () => {}\n"
767 getGoogleJSStyleWithColumns(50)));
770 TEST_F(FormatTestJS
, GeneratorFunctions
) {
771 verifyFormat("function* f() {\n"
774 " yield* something();\n"
778 verifyFormat("function*\n"
781 getGoogleJSStyleWithColumns(8));
782 verifyFormat("export function* f() {\n"
785 verifyFormat("class X {\n"
786 " * generatorMethod() {\n"
790 verifyFormat("var x = {\n"
791 " a: function*() {\n"
797 TEST_F(FormatTestJS
, AsyncFunctions
) {
798 verifyFormat("async function f() {\n"
800 " return fetch(x);\n"
802 verifyFormat("async function f() {\n"
809 " async function f() {\n"
816 // clang-format must not insert breaks between async and function, otherwise
817 // automatic semicolon insertion may trigger (in particular in a class body).
818 verifyFormat("async function\n"
820 " myparamnameiswaytooloooong) {\n"
822 "async function hello(myparamnameiswaytooloooong) {}",
823 getGoogleJSStyleWithColumns(10));
824 verifyFormat("class C {\n"
826 " myparamnameiswaytooloooong) {\n"
830 " async hello(myparamnameiswaytooloooong) {} }",
831 getGoogleJSStyleWithColumns(10));
832 verifyFormat("async function* f() {\n"
835 verifyFormat("export async function f() {\n"
836 " return fetch(x);\n"
838 verifyFormat("let x = async () => f();");
839 verifyFormat("let x = async function() {\n"
842 verifyFormat("let x = async();");
843 verifyFormat("class X {\n"
844 " async asyncMethod() {\n"
845 " return fetch(1);\n"
848 verifyFormat("function initialize() {\n"
850 " return async.then();\n"
852 verifyFormat("for await (const x of y) {\n"
855 verifyFormat("function asyncLoop() {\n"
856 " for await (const x of y) {\n"
862 TEST_F(FormatTestJS
, OverriddenMembers
) {
864 "class C extends P {\n"
865 " protected override "
866 "anOverlyLongPropertyNameSoLongItHasToGoInASeparateLineWhenOverriden:\n"
870 "class C extends P {\n"
871 " protected override "
872 "anOverlyLongMethodNameSoLongItHasToGoInASeparateLineWhenOverriden() {\n"
875 verifyFormat("class C extends P {\n"
876 " protected override aMethodName<ATypeParam extends {},\n"
882 TEST_F(FormatTestJS
, FunctionParametersTrailingComma
) {
883 verifyFormat("function trailingComma(\n"
890 "function trailingComma(p1, p2, p3,) {\n"
893 verifyFormat("trailingComma(\n"
898 "trailingComma(p1, p2, p3,);");
899 verifyFormat("trailingComma(\n"
902 "trailingComma(p1 // hello\n"
906 TEST_F(FormatTestJS
, ArrayLiterals
) {
907 verifyFormat("var aaaaa: List<SomeThing> =\n"
908 " [new SomeThingAAAAAAAAAAAA(), new SomeThingBBBBBBBBB()];");
909 verifyFormat("return [\n"
910 " aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
911 " ccccccccccccccccccccccccccc\n"
913 verifyFormat("return [\n"
914 " aaaa().bbbbbbbb('A'),\n"
915 " aaaa().bbbbbbbb('B'),\n"
916 " aaaa().bbbbbbbb('C'),\n"
918 verifyFormat("var someVariable = SomeFunction([\n"
919 " aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
920 " ccccccccccccccccccccccccccc\n"
922 verifyFormat("var someVariable = SomeFunction([\n"
923 " [aaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbb],\n"
925 getGoogleJSStyleWithColumns(51));
926 verifyFormat("var someVariable = SomeFunction(aaaa, [\n"
927 " aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
928 " ccccccccccccccccccccccccccc\n"
930 verifyFormat("var someVariable = SomeFunction(\n"
933 " aaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
934 " cccccccccccccccccccccccccc\n"
937 verifyFormat("var aaaa = aaaaa || // wrap\n"
940 verifyFormat("someFunction([], {a: a});");
942 verifyFormat("var string = [\n"
948 TEST_F(FormatTestJS
, ColumnLayoutForArrayLiterals
) {
949 verifyFormat("var array = [\n"
950 " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
951 " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
953 verifyFormat("var array = someFunction([\n"
954 " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
955 " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
959 TEST_F(FormatTestJS
, TrailingCommaInsertion
) {
960 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_JavaScript
);
961 Style
.InsertTrailingCommas
= FormatStyle::TCS_Wrapped
;
962 // Insert comma in wrapped array.
963 verifyFormat("const x = [\n"
971 // Insert comma in newly wrapped array.
972 Style
.ColumnLimit
= 30;
973 verifyFormat("const x = [\n"
974 " aaaaaaaaaaaaaaaaaaaaaaaaa,\n"
976 "const x = [aaaaaaaaaaaaaaaaaaaaaaaaa];", Style
);
977 // Do not insert trailing commas if they'd exceed the colum limit
978 verifyFormat("const x = [\n"
979 " aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
981 "const x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa];", Style
);
983 verifyFormat("const x = {\n"
984 " a: aaaaaaaaaaaaaaaaa,\n"
986 "const x = {a: aaaaaaaaaaaaaaaaa};", Style
);
987 verifyFormat("const x = {\n"
988 " a: aaaaaaaaaaaaaaaaaaaaaaaaa\n"
990 "const x = {a: aaaaaaaaaaaaaaaaaaaaaaaaa};", Style
);
991 // Object literal types.
992 verifyFormat("let x: {\n"
993 " a: aaaaaaaaaaaaaaaaaaaaa,\n"
995 "let x: {a: aaaaaaaaaaaaaaaaaaaaa};", Style
);
998 TEST_F(FormatTestJS
, FunctionLiterals
) {
999 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_JavaScript
);
1000 Style
.AllowShortFunctionsOnASingleLine
= FormatStyle::SFS_Inline
;
1001 verifyFormat("doFoo(function() {});");
1002 verifyFormat("doFoo(function() { return 1; });", Style
);
1003 verifyFormat("var func = function() {\n"
1006 verifyFormat("var func = //\n"
1010 verifyFormat("return {\n"
1012 " setAttribute: function(key, val) { this[key] = val; },\n"
1013 " getAttribute: function(key) { return this[key]; },\n"
1014 " style: {direction: ''}\n"
1018 verifyFormat("abc = xyz ? function() {\n"
1020 "} : function() {\n"
1024 verifyFormat("var closure = goog.bind(\n"
1025 " function() { // comment\n"
1029 " this, arg1IsReallyLongAndNeedsLineBreaks,\n"
1030 " arg3IsReallyLongAndNeedsLineBreaks);");
1031 verifyFormat("var closure = goog.bind(function() { // comment\n"
1035 verifyFormat("return {\n"
1037 " b: function() {\n"
1038 " return function() {\n"
1044 " var someVariable = function(x) {\n"
1045 " return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
1048 verifyFormat("someLooooooooongFunction(\n"
1049 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
1050 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
1051 " function(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n"
1055 verifyFormat("return {\n"
1056 " a: function SomeFunction() {\n"
1061 verifyFormat("this.someObject.doSomething(aaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
1062 " .then(goog.bind(function(aaaaaaaaaaa) {\n"
1063 " someFunction();\n"
1064 " someFunction();\n"
1065 " }, this), aaaaaaaaaaaaaaaaa);");
1067 verifyFormat("someFunction(goog.bind(function() {\n"
1070 "}, this), goog.bind(function() {\n"
1075 verifyFormat("SomeFunction(function() {\n"
1080 verifyFormat("SomeFunction((function() {\n"
1083 " }).bind(this));");
1085 // FIXME: This is bad, we should be wrapping before "function() {".
1086 verifyFormat("someFunction(function() {\n"
1087 " doSomething(); // break\n"
1089 " .doSomethingElse(\n"
1093 Style
.ColumnLimit
= 33;
1094 verifyFormat("f({a: function() { return 1; }});", Style
);
1095 Style
.ColumnLimit
= 32;
1096 verifyFormat("f({\n"
1097 " a: function() { return 1; }\n"
1102 TEST_F(FormatTestJS
, DontWrapEmptyLiterals
) {
1103 verifyFormat("(aaaaaaaaaaaaaaaaaaaaa.getData as jasmine.Spy)\n"
1104 " .and.returnValue(Observable.of([]));");
1105 verifyFormat("(aaaaaaaaaaaaaaaaaaaaa.getData as jasmine.Spy)\n"
1106 " .and.returnValue(Observable.of({}));");
1107 verifyFormat("(aaaaaaaaaaaaaaaaaaaaa.getData as jasmine.Spy)\n"
1108 " .and.returnValue(Observable.of(()));");
1111 TEST_F(FormatTestJS
, InliningFunctionLiterals
) {
1112 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_JavaScript
);
1113 Style
.AllowShortFunctionsOnASingleLine
= FormatStyle::SFS_Inline
;
1114 verifyFormat("var func = function() {\n"
1118 verifyFormat("var func = doSomething(function() { return 1; });", Style
);
1119 verifyFormat("var outer = function() {\n"
1120 " var inner = function() { return 1; }\n"
1123 verifyFormat("function outer1(a, b) {\n"
1124 " function inner1(a, b) { return a; }\n"
1128 Style
.AllowShortFunctionsOnASingleLine
= FormatStyle::SFS_All
;
1129 verifyFormat("var func = function() { return 1; };", Style
);
1130 verifyFormat("var func = doSomething(function() { return 1; });", Style
);
1132 "var outer = function() { var inner = function() { return 1; } };",
1134 verifyFormat("function outer1(a, b) {\n"
1135 " function inner1(a, b) { return a; }\n"
1139 Style
.AllowShortFunctionsOnASingleLine
= FormatStyle::SFS_None
;
1140 verifyFormat("var func = function() {\n"
1144 verifyFormat("var func = doSomething(function() {\n"
1148 verifyFormat("var outer = function() {\n"
1149 " var inner = function() {\n"
1154 verifyFormat("function outer1(a, b) {\n"
1155 " function inner1(a, b) {\n"
1161 Style
.AllowShortFunctionsOnASingleLine
= FormatStyle::SFS_Empty
;
1162 verifyFormat("var func = function() {\n"
1168 TEST_F(FormatTestJS
, MultipleFunctionLiterals
) {
1169 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_JavaScript
);
1170 Style
.AllowShortFunctionsOnASingleLine
= FormatStyle::SFS_All
;
1171 verifyFormat("promise.then(\n"
1172 " function success() {\n"
1176 " function error() {\n"
1181 verifyFormat("promise.then(\n"
1182 " function success() {\n"
1187 " function error() {\n"
1191 verifyFormat("promise.then(\n"
1193 " function success() {\n"
1197 " function error() {\n"
1202 verifyFormat("getSomeLongPromise()\n"
1203 " .then(function(value) { body(); })\n"
1204 " .thenCatch(function(error) {\n"
1209 verifyFormat("getSomeLongPromise()\n"
1210 " .then(function(value) {\n"
1214 " .thenCatch(function(error) {\n"
1219 verifyFormat("getSomeLongPromise()\n"
1220 " .then(function(value) { body(); })\n"
1221 " .thenCatch(function(error) { body(); });",
1224 verifyFormat("return [aaaaaaaaaaaaaaaaaaaaaa]\n"
1225 " .aaaaaaa(function() {\n"
1231 TEST_F(FormatTestJS
, ArrowFunctions
) {
1232 verifyFormat("var x = (a) => {\n"
1236 verifyFormat("var x = (a) => {\n"
1242 verifyFormat("var x = (a: type): {some: type} => {\n"
1246 verifyFormat("var x = (a) => a;");
1247 verifyFormat("return () => [];");
1248 verifyFormat("var aaaaaaaaaaaaaaaaaaaa = {\n"
1249 " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n"
1250 " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
1251 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) =>\n"
1252 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
1254 verifyFormat("var a = a.aaaaaaa(\n"
1255 " (a: a) => aaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) &&\n"
1256 " aaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
1257 verifyFormat("var a = a.aaaaaaa(\n"
1258 " (a: a) => aaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) ?\n"
1259 " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb) :\n"
1260 " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
1262 // FIXME: This is bad, we should be wrapping before "() => {".
1263 verifyFormat("someFunction(() => {\n"
1264 " doSomething(); // break\n"
1266 " .doSomethingElse(\n"
1269 verifyFormat("const f = (x: string|null): string|null => {\n"
1275 TEST_F(FormatTestJS
, ArrowFunctionStyle
) {
1276 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_JavaScript
);
1277 Style
.AllowShortLambdasOnASingleLine
= FormatStyle::SLS_All
;
1278 verifyFormat("const arr = () => { x; };", Style
);
1279 verifyFormat("const arrInlineAll = () => {};", Style
);
1280 Style
.AllowShortLambdasOnASingleLine
= FormatStyle::SLS_None
;
1281 verifyFormat("const arr = () => {\n"
1285 verifyFormat("const arrInlineNone = () => {\n"
1288 Style
.AllowShortLambdasOnASingleLine
= FormatStyle::SLS_Empty
;
1289 verifyFormat("const arr = () => {\n"
1293 verifyFormat("const arrInlineEmpty = () => {};", Style
);
1294 Style
.AllowShortLambdasOnASingleLine
= FormatStyle::SLS_Inline
;
1295 verifyFormat("const arr = () => {\n"
1299 verifyFormat("foo(() => {});", Style
);
1300 verifyFormat("const arrInlineInline = () => {};", Style
);
1303 TEST_F(FormatTestJS
, ReturnStatements
) {
1304 verifyFormat("function() {\n"
1305 " return [hello, world];\n"
1309 TEST_F(FormatTestJS
, ForLoops
) {
1310 verifyFormat("for (var i in [2, 3]) {\n"
1312 verifyFormat("for (var i of [2, 3]) {\n"
1314 verifyFormat("for (let {a, b} of x) {\n"
1316 verifyFormat("for (let {a, b} of [x]) {\n"
1318 verifyFormat("for (let [a, b] of [x]) {\n"
1320 verifyFormat("for (let {a, b} in x) {\n"
1324 TEST_F(FormatTestJS
, WrapRespectsAutomaticSemicolonInsertion
) {
1325 // The following statements must not wrap, as otherwise the program meaning
1326 // would change due to automatic semicolon insertion.
1327 // See http://www.ecma-international.org/ecma-262/5.1/#sec-7.9.1.
1328 verifyFormat("return aaaaa;", getGoogleJSStyleWithColumns(10));
1329 verifyFormat("yield aaaaa;", getGoogleJSStyleWithColumns(10));
1330 verifyFormat("return /* hello! */ aaaaa;", getGoogleJSStyleWithColumns(10));
1331 verifyFormat("continue aaaaa;", getGoogleJSStyleWithColumns(10));
1332 verifyFormat("continue /* hello! */ aaaaa;", getGoogleJSStyleWithColumns(10));
1333 verifyFormat("break aaaaa;", getGoogleJSStyleWithColumns(10));
1334 verifyFormat("throw aaaaa;", getGoogleJSStyleWithColumns(10));
1335 verifyFormat("aaaaaaaaa++;", getGoogleJSStyleWithColumns(10));
1336 verifyFormat("aaaaaaaaa--;", getGoogleJSStyleWithColumns(10));
1337 verifyFormat("return [\n"
1340 getGoogleJSStyleWithColumns(12));
1341 verifyFormat("class X {\n"
1342 " readonly ratherLongField =\n"
1346 " readonly ratherLongField = 1;\n"
1348 getGoogleJSStyleWithColumns(20));
1349 verifyFormat("const x = (5 + 9)\n"
1351 "const x = ( 5 + 9)\n"
1353 // Ideally the foo() bit should be indented relative to the async function().
1354 verifyFormat("async function\n"
1356 getGoogleJSStyleWithColumns(10));
1357 verifyFormat("await theReckoning;", getGoogleJSStyleWithColumns(10));
1358 verifyFormat("some['a']['b']", getGoogleJSStyleWithColumns(10));
1359 verifyFormat("x = (a['a']\n"
1361 getGoogleJSStyleWithColumns(10));
1362 verifyFormat("function f() {\n"
1363 " return foo.bar(\n"
1364 " (param): param is {\n"
1368 getGoogleJSStyleWithColumns(25));
1371 TEST_F(FormatTestJS
, AddsIsTheDictKeyOnNewline
) {
1372 // Do not confuse is, the dict key with is, the type matcher. Put is, the dict
1373 // key, on a newline.
1374 verifyFormat("Polymer({\n"
1378 getGoogleJSStyleWithColumns(20));
1381 TEST_F(FormatTestJS
, AutomaticSemicolonInsertionHeuristic
) {
1386 verifyFormat("a()\n"
1390 verifyFormat("a[b]\n"
1406 verifyFormat("a++\n"
1422 verifyFormat("var a", "var\n"
1424 verifyFormat("x instanceof String", "x\n"
1427 verifyFormat("function f(@Foo bar) {}", "function f(@Foo\n"
1429 verifyFormat("function f(@Foo(Param) bar) {}", "function f(@Foo(Param)\n"
1431 verifyFormat("a = true\n"
1435 verifyFormat("a = 's'\n"
1439 verifyFormat("a = null\n"
1443 // Below "class Y {}" should ideally be on its own line.
1444 verifyFormat("x = {\n"
1449 verifyFormat("if (x) {\n"
1454 verifyFormat("if (x) {\n"
1461 TEST_F(FormatTestJS
, ImportExportASI
) {
1462 verifyFormat("import {x} from 'y'\n"
1463 "export function z() {}",
1464 "import {x} from 'y'\n"
1465 " export function z() {}");
1466 // Below "class Y {}" should ideally be on its own line.
1467 verifyFormat("export {x} class Y {}", " export {x}\n"
1469 verifyFormat("if (x) {\n"
1471 "export class Y {}",
1473 " export class Y {}");
1476 TEST_F(FormatTestJS
, ImportExportType
) {
1477 verifyFormat("import type {x, y} from 'y';\n"
1478 "import type * as x from 'y';\n"
1479 "import type x from 'y';\n"
1480 "import {x, type yu, z} from 'y';");
1481 verifyFormat("export type {x, y} from 'y';\n"
1482 "export {x, type yu, z} from 'y';\n"
1483 "export type {x, y};\n"
1484 "export {x, type yu, z};");
1487 TEST_F(FormatTestJS
, ClosureStyleCasts
) {
1488 verifyFormat("var x = /** @type {foo} */ (bar);");
1491 TEST_F(FormatTestJS
, TryCatch
) {
1492 verifyFormat("try {\n"
1500 // But, of course, "catch" is a perfectly fine function name in JavaScript.
1501 verifyFormat("someObject.catch();");
1502 verifyFormat("someObject.new();");
1505 TEST_F(FormatTestJS
, StringLiteralConcatenation
) {
1506 verifyFormat("var literal = 'hello ' +\n"
1509 // String breaking is disabled for now.
1510 verifyFormat("var literal =\n"
1511 " 'xxxxxxxx xxxxxxxx';",
1512 "var literal = 'xxxxxxxx xxxxxxxx';",
1513 getGoogleJSStyleWithColumns(17));
1516 TEST_F(FormatTestJS
, RegexLiteralClassification
) {
1518 verifyFormat("var regex = /abc/;");
1519 verifyFormat("f(/abc/);");
1520 verifyFormat("f(abc, /abc/);");
1521 verifyFormat("some_map[/abc/];");
1522 verifyFormat("var x = a ? /abc/ : /abc/;");
1523 verifyFormat("for (var i = 0; /abc/.test(s[i]); i++) {\n}");
1524 verifyFormat("var x = !/abc/.test(y);");
1525 verifyFormat("var x = foo()! / 10;");
1526 verifyFormat("var x = a && /abc/.test(y);");
1527 verifyFormat("var x = a || /abc/.test(y);");
1528 verifyFormat("var x = a + /abc/.search(y);");
1529 verifyFormat("/abc/.search(y);");
1530 verifyFormat("var regexs = {/abc/, /abc/};");
1531 verifyFormat("return /abc/;");
1533 // Not regex literals.
1534 verifyFormat("var a = a / 2 + b / 3;");
1535 verifyFormat("var a = a++ / 2;");
1536 // Prefix unary can operate on regex literals, not that it makes sense.
1537 verifyFormat("var a = ++/a/;");
1539 // This is a known issue, regular expressions are incorrectly detected if
1540 // directly following a closing parenthesis.
1541 verifyFormat("if (foo) / bar /.exec(baz);");
1544 TEST_F(FormatTestJS
, RegexLiteralSpecialCharacters
) {
1545 verifyFormat("var regex = /=/;");
1546 verifyFormat("var regex = /a*/;");
1547 verifyFormat("var regex = /a+/;");
1548 verifyFormat("var regex = /a?/;");
1549 verifyFormat("var regex = /.a./;");
1550 verifyFormat("var regex = /a\\*/;");
1551 verifyFormat("var regex = /^a$/;");
1552 verifyFormat("var regex = /\\/a/;");
1553 verifyFormat("var regex = /(?:x)/;");
1554 verifyFormat("var regex = /x(?=y)/;");
1555 verifyFormat("var regex = /x(?!y)/;");
1556 verifyFormat("var regex = /x|y/;");
1557 verifyFormat("var regex = /a{2}/;");
1558 verifyFormat("var regex = /a{1,3}/;");
1560 verifyFormat("var regex = /[abc]/;");
1561 verifyFormat("var regex = /[^abc]/;");
1562 verifyFormat("var regex = /[\\b]/;");
1563 verifyFormat("var regex = /[/]/;");
1564 verifyFormat("var regex = /[\\/]/;");
1565 verifyFormat("var regex = /\\[/;");
1566 verifyFormat("var regex = /\\\\[/]/;");
1567 verifyFormat("var regex = /}[\"]/;");
1568 verifyFormat("var regex = /}[/\"]/;");
1569 verifyFormat("var regex = /}[\"/]/;");
1571 verifyFormat("var regex = /\\b/;");
1572 verifyFormat("var regex = /\\B/;");
1573 verifyFormat("var regex = /\\d/;");
1574 verifyFormat("var regex = /\\D/;");
1575 verifyFormat("var regex = /\\f/;");
1576 verifyFormat("var regex = /\\n/;");
1577 verifyFormat("var regex = /\\r/;");
1578 verifyFormat("var regex = /\\s/;");
1579 verifyFormat("var regex = /\\S/;");
1580 verifyFormat("var regex = /\\t/;");
1581 verifyFormat("var regex = /\\v/;");
1582 verifyFormat("var regex = /\\w/;");
1583 verifyFormat("var regex = /\\W/;");
1584 verifyFormat("var regex = /a(a)\\1/;");
1585 verifyFormat("var regex = /\\0/;");
1586 verifyFormat("var regex = /\\\\/g;");
1587 verifyFormat("var regex = /\\a\\\\/g;");
1588 verifyFormat("var regex = /\a\\//g;");
1589 verifyFormat("var regex = /a\\//;\n"
1591 verifyFormat("var regex = /'/g;", "var regex = /'/g ;");
1592 verifyFormat("var regex = /'/g; //'", "var regex = /'/g ; //'");
1593 verifyFormat("var regex = /\\/*/;\n"
1595 "var regex = /\\/*/;\n"
1597 verifyFormat("var x = /a\\//;", "var x = /a\\// \n;");
1598 verifyFormat("var regex = /\"/;", getGoogleJSStyleWithColumns(16));
1599 verifyFormat("var regex =\n"
1601 getGoogleJSStyleWithColumns(15));
1602 verifyFormat("var regex = //\n"
1604 verifyFormat("var regexs = [\n"
1610 TEST_F(FormatTestJS
, RegexLiteralModifiers
) {
1611 verifyFormat("var regex = /abc/g;");
1612 verifyFormat("var regex = /abc/i;");
1613 verifyFormat("var regex = /abc/m;");
1614 verifyFormat("var regex = /abc/y;");
1617 TEST_F(FormatTestJS
, RegexLiteralLength
) {
1618 verifyFormat("var regex = /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
1619 getGoogleJSStyleWithColumns(60));
1620 verifyFormat("var regex =\n"
1621 " /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
1622 getGoogleJSStyleWithColumns(60));
1623 verifyFormat("var regex = /\\xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
1624 getGoogleJSStyleWithColumns(50));
1627 TEST_F(FormatTestJS
, RegexLiteralExamples
) {
1628 verifyFormat("var regex = search.match(/(?:\?|&)times=([^?&]+)/i);");
1631 TEST_F(FormatTestJS
, IgnoresMpegTS
) {
1632 std::string
MpegTS(200, ' ');
1633 MpegTS
.replace(0, strlen("nearlyLooks + like + ts + code; "),
1634 "nearlyLooks + like + ts + code; ");
1637 verifyFormat(MpegTS
, MpegTS
);
1640 TEST_F(FormatTestJS
, TypeAnnotations
) {
1641 verifyFormat("var x: string;");
1642 verifyFormat("var x: {a: string; b: number;} = {};");
1643 verifyFormat("function x(): string {\n return 'x';\n}");
1644 verifyFormat("function x(): {x: string} {\n return {x: 'x'};\n}");
1645 verifyFormat("function x(y: string): string {\n return 'x';\n}");
1646 verifyFormat("for (var y: string in x) {\n x();\n}");
1647 verifyFormat("for (var y: string of x) {\n x();\n}");
1648 verifyFormat("function x(y: {a?: number;} = {}): number {\n"
1651 verifyFormat("const x: Array<{a: number; b: string;}> = [];");
1652 verifyFormat("((a: string, b: number): string => a + b);");
1653 verifyFormat("var x: (y: number) => string;");
1654 verifyFormat("var x: P<string, (a: number) => string>;");
1655 verifyFormat("var x = {\n"
1656 " y: function(): z {\n"
1660 verifyFormat("var x = {\n"
1661 " y: function(): {a: number} {\n"
1665 verifyFormat("function someFunc(args: string[]):\n"
1666 " {longReturnValue: string[]} {}",
1667 getGoogleJSStyleWithColumns(60));
1669 "var someValue = (v as aaaaaaaaaaaaaaaaaaaa<T>[])\n"
1670 " .someFunction(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
1671 verifyFormat("const xIsALongIdent:\n"
1672 " YJustBarelyFitsLinex[];",
1673 getGoogleJSStyleWithColumns(20));
1674 verifyFormat("const x = {\n"
1679 TEST_F(FormatTestJS
, UnionIntersectionTypes
) {
1680 verifyFormat("let x: A|B = A | B;");
1681 verifyFormat("let x: A&B|C = A & B;");
1682 verifyFormat("let x: Foo<A|B> = new Foo<A|B>();");
1683 verifyFormat("function(x: A|B): C&D {}");
1684 verifyFormat("function(x: A|B = A | B): C&D {}");
1685 verifyFormat("function x(path: number|string) {}");
1686 verifyFormat("function x(): string|number {}");
1687 verifyFormat("type Foo = Bar|Baz;");
1688 verifyFormat("type Foo = Bar<X>|Baz;");
1689 verifyFormat("type Foo = (Bar<X>|Baz);");
1690 verifyFormat("let x: Bar|Baz;");
1691 verifyFormat("let x: Bar<X>|Baz;");
1692 verifyFormat("let x: (Foo|Bar)[];");
1693 verifyFormat("type X = {\n"
1696 verifyFormat("export type X = {\n"
1701 TEST_F(FormatTestJS
, UnionIntersectionTypesInObjectType
) {
1702 verifyFormat("let x: {x: number|null} = {x: number | null};");
1703 verifyFormat("let nested: {x: {y: number|null}};");
1704 verifyFormat("let mixed: {x: [number|null, {w: number}]};");
1705 verifyFormat("class X {\n"
1706 " contructor(x: {\n"
1713 TEST_F(FormatTestJS
, ClassDeclarations
) {
1714 verifyFormat("class C {\n x: string = 12;\n}");
1715 verifyFormat("class C {\n x(): string => 12;\n}");
1716 verifyFormat("class C {\n ['x' + 2]: string = 12;\n}");
1717 verifyFormat("class C {\n"
1721 verifyFormat("class C {\n private x: string = 12;\n}");
1722 verifyFormat("class C {\n private static x: string = 12;\n}");
1723 verifyFormat("class C {\n static x(): string {\n return 'asd';\n }\n}");
1724 verifyFormat("class C extends P implements I {}");
1725 verifyFormat("class C extends p.P implements i.I {}");
1726 verifyFormat("x(class {\n"
1729 verifyFormat("class Test {\n"
1730 " aaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaaa):\n"
1731 " aaaaaaaaaaaaaaaaaaaaaa {}\n"
1733 verifyFormat("foo = class Name {\n"
1734 " constructor() {}\n"
1736 verifyFormat("foo = class {\n"
1737 " constructor() {}\n"
1739 verifyFormat("class C {\n"
1740 " x: {y: Z;} = {};\n"
1741 " private y: {y: Z;} = {};\n"
1744 // ':' is not a type declaration here.
1745 verifyFormat("class X {\n"
1752 verifyFormat("@Component({\n"
1753 " moduleId: module.id,\n"
1755 "class SessionListComponent implements OnDestroy, OnInit {\n"
1759 TEST_F(FormatTestJS
, StrictPropInitWrap
) {
1760 const FormatStyle
&Style
= getGoogleJSStyleWithColumns(22);
1761 verifyFormat("class X {\n"
1762 " strictPropInitField!:\n"
1768 TEST_F(FormatTestJS
, InterfaceDeclarations
) {
1769 verifyFormat("interface I {\n"
1771 " enum: string[];\n"
1772 " enum?: string[];\n"
1775 // Ensure that state is reset after parsing the interface.
1776 verifyFormat("interface a {}\n"
1777 "export function b() {}\n"
1780 // Arrays of object type literals.
1781 verifyFormat("interface I {\n"
1786 TEST_F(FormatTestJS
, ObjectTypesInExtendsImplements
) {
1787 verifyFormat("class C extends {} {}");
1788 verifyFormat("class C implements {bar: number} {}");
1789 // Somewhat odd, but probably closest to reasonable formatting?
1790 verifyFormat("class C implements {\n"
1794 verifyFormat("class C<P extends {}> {}");
1797 TEST_F(FormatTestJS
, EnumDeclarations
) {
1798 verifyFormat("enum Foo {\n"
1802 verifyFormat("export /* somecomment*/ enum Foo {\n"
1806 verifyFormat("enum Foo {\n"
1807 " A = 1, // comment\n"
1811 verifyFormat("const enum Foo {\n"
1815 verifyFormat("export const enum Foo {\n"
1821 TEST_F(FormatTestJS
, Decorators
) {
1822 verifyFormat("@A\nclass C {\n}");
1823 verifyFormat("@A({arg: 'value'})\nclass C {\n}");
1824 verifyFormat("@A\n@B\nclass C {\n}");
1825 verifyFormat("class C {\n @A x: string;\n}");
1826 verifyFormat("class C {\n"
1828 " private x(): string {\n"
1832 verifyFormat("class C {\n"
1833 " private x(@A x: string) {}\n"
1835 verifyFormat("class X {}\n"
1837 verifyFormat("class X {\n"
1838 " @property() private isReply = false;\n"
1842 TEST_F(FormatTestJS
, TypeAliases
) {
1843 verifyFormat("type X = number;\n"
1845 verifyFormat("type X<Y> = Z<Y>;");
1846 verifyFormat("type X = {\n"
1850 verifyFormat("export type X = {\n"
1856 TEST_F(FormatTestJS
, TypeInterfaceLineWrapping
) {
1857 const FormatStyle
&Style
= getGoogleJSStyleWithColumns(20);
1858 verifyFormat("type LongTypeIsReallyUnreasonablyLong =\n"
1860 "type LongTypeIsReallyUnreasonablyLong = string;", Style
);
1861 verifyFormat("interface AbstractStrategyFactoryProvider {\n"
1864 "interface AbstractStrategyFactoryProvider { a: number }",
1868 TEST_F(FormatTestJS
, RemoveEmptyLinesInArrowFunctions
) {
1869 verifyFormat("x = () => {\n"
1881 TEST_F(FormatTestJS
, Modules
) {
1882 verifyFormat("import SomeThing from 'some/module.js';");
1883 verifyFormat("import {X, Y} from 'some/module.js';");
1884 verifyFormat("import a, {X, Y} from 'some/module.js';");
1885 verifyFormat("import {X, Y,} from 'some/module.js';");
1886 verifyFormat("import {X as myLocalX, Y as myLocalY} from 'some/module.js';");
1887 // Ensure Automatic Semicolon Insertion does not break on "as\n".
1888 verifyFormat("import {X as myX} from 'm';", "import {X as\n"
1890 verifyFormat("import * as lib from 'some/module.js';");
1891 verifyFormat("var x = {import: 1};\nx.import = 2;");
1892 // Ensure an import statement inside a block is at the correct level.
1893 verifyFormat("function() {\n"
1895 " import 'some/module.js';\n"
1898 verifyFormat("export function fn() {\n"
1901 verifyFormat("export function A() {}\n"
1902 "export default function B() {}\n"
1903 "export function C() {}");
1904 verifyFormat("export default () => {\n"
1908 verifyFormat("export const x = 12;");
1909 verifyFormat("export default class X {}");
1910 verifyFormat("export {X, Y} from 'some/module.js';");
1911 verifyFormat("export {X, Y,} from 'some/module.js';");
1912 verifyFormat("export {SomeVeryLongExport as X, "
1913 "SomeOtherVeryLongExport as Y} from 'some/module.js';");
1914 // export without 'from' is wrapped.
1915 verifyFormat("export let someRatherLongVariableName =\n"
1916 " someSurprisinglyLongVariable + someOtherRatherLongVar;");
1917 // ... but not if from is just an identifier.
1918 verifyFormat("export {\n"
1920 " someSurprisinglyLongVariable as\n"
1923 getGoogleJSStyleWithColumns(20));
1924 verifyFormat("export class C {\n"
1928 verifyFormat("export class X {\n"
1931 verifyFormat("export abstract class X {\n"
1934 verifyFormat("export default class X {\n"
1937 verifyFormat("export default function() {\n return 1;\n}");
1938 verifyFormat("export var x = 12;");
1939 verifyFormat("class C {}\n"
1940 "export function f() {}\n"
1942 verifyFormat("export var x: number = 12;");
1943 verifyFormat("export const y = {\n"
1947 verifyFormat("export enum Foo {\n"
1952 verifyFormat("export default [\n"
1953 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
1954 " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"
1956 verifyFormat("export default [];");
1957 verifyFormat("export default () => {};");
1958 verifyFormat("export default () => {\n"
1962 verifyFormat("export interface Foo {\n"
1965 "export class Bar {\n"
1966 " blah(): string {\n"
1967 " return this.blah;\n"
1972 TEST_F(FormatTestJS
, ImportWrapping
) {
1973 verifyFormat("import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,"
1974 " VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying"
1975 "} from 'some/module.js';");
1976 FormatStyle Style
= getGoogleJSStyleWithColumns(80);
1977 Style
.JavaScriptWrapImports
= true;
1978 verifyFormat("import {\n"
1979 " VeryLongImportsAreAnnoying,\n"
1980 " VeryLongImportsAreAnnoying,\n"
1981 " VeryLongImportsAreAnnoying,\n"
1982 "} from 'some/module.js';",
1984 verifyFormat("import {\n"
1987 "} from 'some/module.js';",
1989 verifyFormat("export {\n"
1992 "} from 'some/module.js';",
1994 Style
.ColumnLimit
= 40;
1995 // Using this version of verifyFormat because test::messUp hides the issue.
1996 verifyFormat("import {\n"
1999 " 'some/path/longer/than/column/limit/module.js';",
2003 " 'some/path/longer/than/column/limit/module.js' ; ",
2007 TEST_F(FormatTestJS
, TemplateStrings
) {
2008 // Keeps any whitespace/indentation within the template string.
2009 verifyFormat("var x = `hello\n"
2016 verifyFormat("var x =\n"
2017 " `hello ${world}` >= some();",
2018 getGoogleJSStyleWithColumns(34)); // Barely doesn't fit.
2019 verifyFormat("var x = `hello ${world}` >= some();",
2020 getGoogleJSStyleWithColumns(35)); // Barely fits.
2021 verifyFormat("var x = `hellö ${wörld}` >= söme();",
2022 getGoogleJSStyleWithColumns(35)); // Fits due to UTF-8.
2023 verifyFormat("var x = `hello\n"
2028 " ${world}` >= some();",
2029 getGoogleJSStyleWithColumns(21)); // Barely doesn't fit.
2030 verifyFormat("var x = `hello\n"
2031 " ${world}` >= some();",
2034 " ${world}` >= some();",
2035 getGoogleJSStyleWithColumns(22)); // Barely fits.
2037 verifyFormat("var x =\n"
2039 getGoogleJSStyleWithColumns(11));
2040 verifyFormat("var x =\n `multi\n line`;", "var x = `multi\n line`;",
2041 getGoogleJSStyleWithColumns(13));
2042 verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
2043 " `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`);");
2044 // Repro for an obscure width-miscounting issue with template strings.
2046 "someLongVariable =\n"
2048 "`${logPrefix[11]}/${logPrefix[12]}/${logPrefix[13]}${logPrefix[14]}`;",
2049 "someLongVariable = "
2050 "`${logPrefix[11]}/${logPrefix[12]}/${logPrefix[13]}${logPrefix[14]}`;");
2052 // Make sure template strings get a proper ColumnWidth assigned, even if they
2053 // are first token in line.
2054 verifyFormat("var a = aaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n"
2055 " `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`;");
2057 // Two template strings.
2058 verifyFormat("var x = `hello` == `hello`;");
2060 // Comments in template strings.
2061 verifyFormat("var x = `//a`;\n"
2063 "var x =\n `//a`;\n"
2065 verifyFormat("var x = `/*a`;\n"
2067 "var x =\n `/*a`;\n"
2069 // Unterminated string literals in a template string.
2070 verifyFormat("var x = `'`; // comment with matching quote '\n"
2072 verifyFormat("var x = `\"`; // comment with matching quote \"\n"
2074 verifyFormat("it(`'aaaaaaaaaaaaaaa `, aaaaaaaaa);",
2075 "it(`'aaaaaaaaaaaaaaa `, aaaaaaaaa) ;",
2076 getGoogleJSStyleWithColumns(40));
2077 // Backticks in a comment - not a template string.
2078 verifyFormat("var x = 1 // `/*a`;\n"
2080 "var x =\n 1 // `/*a`;\n"
2082 verifyFormat("/* ` */ var x = 1; /* ` */", "/* ` */ var x\n= 1; /* ` */");
2083 // Comment spans multiple template strings.
2084 verifyFormat("var x = `/*a`;\n"
2086 "var x =\n `/*a`;\n"
2087 "var y =\n ` */ `;");
2088 // Escaped backtick.
2089 verifyFormat("var x = ` \\` a`;\n"
2091 "var x = ` \\` a`;\n"
2094 verifyFormat("var x = ` \\${foo}`;");
2096 // The token stream can contain two string_literals in sequence, but that
2097 // doesn't mean that they are implicitly concatenated in JavaScript.
2098 verifyFormat("var f = `aaaa ${a ? 'a' : 'b'}`;");
2100 // Ensure that scopes are appropriately set around evaluated expressions in
2101 // template strings.
2102 verifyFormat("var f = `aaaaaaaaaaaaa:${aaaaaaa.aaaaa} aaaaaaaa\n"
2103 " aaaaaaaaaaaaa:${aaaaaaa.aaaaa} aaaaaaaa`;",
2104 "var f = `aaaaaaaaaaaaa:${aaaaaaa. aaaaa} aaaaaaaa\n"
2105 " aaaaaaaaaaaaa:${ aaaaaaa. aaaaa} aaaaaaaa`;");
2106 verifyFormat("var x = someFunction(`${})`) //\n"
2107 " .oooooooooooooooooon();");
2108 verifyFormat("var x = someFunction(`${aaaa}${\n"
2113 TEST_F(FormatTestJS
, TemplateStringMultiLineExpression
) {
2114 verifyFormat("var f = `aaaaaaaaaaaaaaaaaa: ${\n"
2117 "var f = `aaaaaaaaaaaaaaaaaa: ${aaaaa + //\n"
2119 verifyFormat("var f = `\n"
2120 " aaaaaaaaaaaaaaaaaa: ${\n"
2124 " aaaaaaaaaaaaaaaaaa: ${ aaaaa + //\n"
2126 verifyFormat("var f = `\n"
2127 " aaaaaaaaaaaaaaaaaa: ${\n"
2132 " aaaaaaaaaaaaaaaaaa: ${someFunction (\n"
2136 // It might be preferable to wrap before "someFunction".
2137 verifyFormat("var f = `\n"
2138 " aaaaaaaaaaaaaaaaaa: ${someFunction({\n"
2143 " aaaaaaaaaaaaaaaaaa: ${someFunction ({\n"
2149 TEST_F(FormatTestJS
, TemplateStringASI
) {
2150 verifyFormat("var x = `hello${world}`;", "var x = `hello${\n"
2155 TEST_F(FormatTestJS
, NestedTemplateStrings
) {
2157 "var x = `<ul>${xs.map(x => `<li>${x}</li>`).join('\\n')}</ul>`;");
2158 verifyFormat("var x = `he${({text: 'll'}.text)}o`;");
2160 // Crashed at some point.
2163 // FIXME: still crashing?
2164 // verifyFormat("`\\");
2167 TEST_F(FormatTestJS
, TaggedTemplateStrings
) {
2168 verifyFormat("var x = html`<ul>`;");
2169 verifyFormat("yield `hello`;");
2170 verifyFormat("var f = {\n"
2171 " param: longTagName`This is a ${\n"
2172 " 'really'} long line`\n"
2174 "var f = {param: longTagName`This is a ${'really'} long line`};",
2175 getGoogleJSStyleWithColumns(40));
2178 TEST_F(FormatTestJS
, CastSyntax
) {
2179 verifyFormat("var x = <type>foo;");
2180 verifyFormat("var x = foo as type;");
2181 verifyFormat("let x = (a + b) as\n"
2183 getGoogleJSStyleWithColumns(20));
2184 verifyFormat("foo = <Bar[]>[\n"
2188 verifyFormat("var x = [{x: 1} as type];");
2189 verifyFormat("x = x as [a, b];");
2190 verifyFormat("x = x as {a: string};");
2191 verifyFormat("x = x as (string);");
2192 verifyFormat("x = x! as (string);");
2193 verifyFormat("x = y! in z;");
2194 verifyFormat("var x = something.someFunction() as\n"
2196 getGoogleJSStyleWithColumns(40));
2199 TEST_F(FormatTestJS
, TypeArguments
) {
2200 verifyFormat("class X<Y> {}");
2201 verifyFormat("new X<Y>();");
2202 verifyFormat("foo<Y>(a);");
2203 verifyFormat("var x: X<Y>[];");
2204 verifyFormat("class C extends D<E> implements F<G>, H<I> {}");
2205 verifyFormat("function f(a: List<any> = null) {}");
2206 verifyFormat("function f(): List<any> {}");
2207 verifyFormat("function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa():\n"
2208 " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {}");
2209 verifyFormat("function aaaaaaaaaa(\n"
2210 " aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaa,\n"
2211 " aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaa):\n"
2212 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {}");
2215 TEST_F(FormatTestJS
, UserDefinedTypeGuards
) {
2217 "function foo(check: Object):\n"
2218 " check is {foo: string, bar: string, baz: string, foobar: string} {\n"
2219 " return 'bar' in check;\n"
2223 TEST_F(FormatTestJS
, OptionalTypes
) {
2224 verifyFormat("function x(a?: b, c?, d?) {}");
2225 verifyFormat("class X {\n"
2229 verifyFormat("interface X {\n"
2232 verifyFormat("constructor({aa}: {\n"
2234 " aaaaaaaa?: string,\n"
2235 " aaaaaaaaaaaaaaa?: boolean,\n"
2236 " aaaaaa?: List<string>\n"
2238 verifyFormat("type X = [y?];");
2241 TEST_F(FormatTestJS
, IndexSignature
) {
2242 verifyFormat("var x: {[k: string]: v};");
2245 TEST_F(FormatTestJS
, WrapAfterParen
) {
2246 verifyFormat("xxxxxxxxxxx(\n"
2248 getGoogleJSStyleWithColumns(20));
2249 verifyFormat("xxxxxxxxxxx(\n"
2252 getGoogleJSStyleWithColumns(20));
2253 verifyFormat("xxxxxxxxxxx(\n"
2254 " aaaaaaaaaaaaaaaaaaaaaaaa,\n"
2258 getGoogleJSStyleWithColumns(40));
2259 verifyFormat("while (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n"
2260 " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n}");
2263 TEST_F(FormatTestJS
, JSDocAnnotations
) {
2264 verifyFormat("/**\n"
2265 " * @exports {this.is.a.long.path.to.a.Type}\n"
2268 " * @exports {this.is.a.long.path.to.a.Type}\n"
2270 getGoogleJSStyleWithColumns(20));
2271 verifyFormat("/**\n"
2272 " * @mods {this.is.a.long.path.to.a.Type}\n"
2275 " * @mods {this.is.a.long.path.to.a.Type}\n"
2277 getGoogleJSStyleWithColumns(20));
2278 verifyFormat("/**\n"
2279 " * @mods {this.is.a.long.path.to.a.Type}\n"
2282 " * @mods {this.is.a.long.path.to.a.Type}\n"
2284 getGoogleJSStyleWithColumns(20));
2285 verifyFormat("/**\n"
2286 " * @param {canWrap\n"
2290 " * @param {canWrap onSpace}\n"
2292 getGoogleJSStyleWithColumns(20));
2293 // make sure clang-format doesn't break before *any* '{'
2294 verifyFormat("/**\n"
2295 " * @lala {lala {lalala\n"
2298 " * @lala {lala {lalala\n"
2300 getGoogleJSStyleWithColumns(20));
2301 // cases where '{' is around the column limit
2302 for (int ColumnLimit
= 6; ColumnLimit
< 13; ++ColumnLimit
) {
2303 verifyFormat("/**\n"
2304 " * @param {type}\n"
2307 " * @param {type}\n"
2309 getGoogleJSStyleWithColumns(ColumnLimit
));
2311 // don't break before @tags
2312 verifyFormat("/**\n"
2318 " * This tag @param stays.\n"
2320 getGoogleJSStyleWithColumns(13));
2321 verifyFormat("/**\n"
2322 " * @see http://very/very/long/url/is/long\n"
2325 " * @see http://very/very/long/url/is/long\n"
2327 getGoogleJSStyleWithColumns(20));
2328 verifyFormat("/**\n"
2329 " * @param This is a\n"
2334 " * @param This is a long comment but no type\n"
2336 getGoogleJSStyleWithColumns(20));
2337 // Break and reindent @param line and reflow unrelated lines.
2340 " * long long long\n"
2342 " * @param {this.is.a.long.path.to.a.Type}\n"
2344 " * long long long\n"
2347 " function f(a) {}\n"
2351 " * long long long long\n"
2352 " * @param {this.is.a.long.path.to.a.Type} a\n"
2353 " * long long long long\n"
2356 " function f(a) {}\n"
2358 getGoogleJSStyleWithColumns(20)));
2361 TEST_F(FormatTestJS
, TslintComments
) {
2362 // tslint uses pragma comments that must be on their own line.
2363 verifyFormat("// Comment that needs wrapping. Comment that needs wrapping. "
2364 "Comment that needs\n"
2365 "// wrapping. Trailing line.\n"
2366 "// tslint:disable-next-line:must-be-on-own-line",
2367 "// Comment that needs wrapping. Comment that needs wrapping. "
2368 "Comment that needs wrapping.\n"
2369 "// Trailing line.\n"
2370 "// tslint:disable-next-line:must-be-on-own-line");
2373 TEST_F(FormatTestJS
, TscComments
) {
2374 // As above, @ts-ignore and @ts-check comments must be on their own line.
2375 verifyFormat("// Comment that needs wrapping. Comment that needs wrapping. "
2376 "Comment that needs\n"
2377 "// wrapping. Trailing line.\n"
2379 "// Comment that needs wrapping. Comment that needs wrapping. "
2380 "Comment that needs wrapping.\n"
2381 "// Trailing line.\n"
2383 verifyFormat("// Comment that needs wrapping. Comment that needs wrapping. "
2384 "Comment that needs\n"
2385 "// wrapping. Trailing line.\n"
2387 "// Comment that needs wrapping. Comment that needs wrapping. "
2388 "Comment that needs wrapping.\n"
2389 "// Trailing line.\n"
2393 TEST_F(FormatTestJS
, RequoteStringsSingle
) {
2394 verifyFormat("var x = 'foo';", "var x = \"foo\";");
2395 verifyFormat("var x = 'fo\\'o\\'';", "var x = \"fo'o'\";");
2396 verifyFormat("var x = 'fo\\'o\\'';", "var x = \"fo\\'o'\";");
2397 verifyFormat("var x =\n"
2399 // Code below is 15 chars wide, doesn't fit into the line with
2400 // the \ escape added.
2401 "var x = \"foo'\";", getGoogleJSStyleWithColumns(15));
2402 // Removes no-longer needed \ escape from ".
2403 verifyFormat("var x = 'fo\"o';", "var x = \"fo\\\"o\";");
2404 // Code below fits into 15 chars *after* removing the \ escape.
2405 verifyFormat("var x = 'fo\"o';", "var x = \"fo\\\"o\";",
2406 getGoogleJSStyleWithColumns(15));
2407 verifyFormat("// clang-format off\n"
2408 "let x = \"double\";\n"
2409 "// clang-format on\n"
2410 "let x = 'single';",
2411 "// clang-format off\n"
2412 "let x = \"double\";\n"
2413 "// clang-format on\n"
2414 "let x = \"single\";");
2417 TEST_F(FormatTestJS
, RequoteAndIndent
) {
2418 verifyFormat("let x = someVeryLongFunctionThatGoesOnAndOn(\n"
2419 " 'double quoted string that needs wrapping');",
2420 "let x = someVeryLongFunctionThatGoesOnAndOn("
2421 "\"double quoted string that needs wrapping\");");
2423 verifyFormat("let x =\n"
2427 "let x=\"foo'oo\";\n"
2428 "let x=\"foo'oo\";",
2429 getGoogleJSStyleWithColumns(15));
2432 TEST_F(FormatTestJS
, RequoteStringsDouble
) {
2433 FormatStyle DoubleQuotes
= getGoogleStyle(FormatStyle::LK_JavaScript
);
2434 DoubleQuotes
.JavaScriptQuotes
= FormatStyle::JSQS_Double
;
2435 verifyFormat("var x = \"foo\";", DoubleQuotes
);
2436 verifyFormat("var x = \"foo\";", "var x = 'foo';", DoubleQuotes
);
2437 verifyFormat("var x = \"fo'o\";", "var x = 'fo\\'o';", DoubleQuotes
);
2440 TEST_F(FormatTestJS
, RequoteStringsLeave
) {
2441 FormatStyle LeaveQuotes
= getGoogleStyle(FormatStyle::LK_JavaScript
);
2442 LeaveQuotes
.JavaScriptQuotes
= FormatStyle::JSQS_Leave
;
2443 verifyFormat("var x = \"foo\";", LeaveQuotes
);
2444 verifyFormat("var x = 'foo';", LeaveQuotes
);
2447 TEST_F(FormatTestJS
, SupportShebangLines
) {
2448 verifyFormat("#!/usr/bin/env node\n"
2450 "#!/usr/bin/env node\n"
2451 "var x = hello();");
2454 TEST_F(FormatTestJS
, NonNullAssertionOperator
) {
2455 verifyFormat("let x = foo!.bar();");
2456 verifyFormat("let x = foo ? bar! : baz;");
2457 verifyFormat("let x = !foo;");
2458 verifyFormat("if (!+a) {\n}");
2459 verifyFormat("let x = foo[0]!;");
2460 verifyFormat("let x = (foo)!;");
2461 verifyFormat("let x = x(foo!);");
2462 verifyFormat("a.aaaaaa(a.a!).then(\n"
2464 getGoogleJSStyleWithColumns(20));
2465 verifyFormat("let x = foo! - 1;");
2466 verifyFormat("let x = {foo: 1}!;");
2467 verifyFormat("let x = hello.foo()!\n"
2471 getGoogleJSStyleWithColumns(20));
2472 verifyFormat("let x = namespace!;");
2473 verifyFormat("return !!x;");
2476 TEST_F(FormatTestJS
, CppKeywords
) {
2477 // Make sure we don't mess stuff up because of C++ keywords.
2478 verifyFormat("return operator && (aa);");
2480 verifyFormat("const slots: Slot[];");
2481 // use the "!" assertion operator to validate that clang-format understands
2482 // these C++ keywords aren't keywords in JS/TS.
2483 verifyFormat("auto!;");
2484 verifyFormat("char!;");
2485 verifyFormat("concept!;");
2486 verifyFormat("double!;");
2487 verifyFormat("extern!;");
2488 verifyFormat("float!;");
2489 verifyFormat("inline!;");
2490 verifyFormat("int!;");
2491 verifyFormat("long!;");
2492 verifyFormat("register!;");
2493 verifyFormat("restrict!;");
2494 verifyFormat("sizeof!;");
2495 verifyFormat("struct!;");
2496 verifyFormat("typedef!;");
2497 verifyFormat("union!;");
2498 verifyFormat("unsigned!;");
2499 verifyFormat("volatile!;");
2500 verifyFormat("_Alignas!;");
2501 verifyFormat("_Alignof!;");
2502 verifyFormat("_Atomic!;");
2503 verifyFormat("_Bool!;");
2504 verifyFormat("_Complex!;");
2505 verifyFormat("_Generic!;");
2506 verifyFormat("_Imaginary!;");
2507 verifyFormat("_Noreturn!;");
2508 verifyFormat("_Static_assert!;");
2509 verifyFormat("_Thread_local!;");
2510 verifyFormat("__func__!;");
2511 verifyFormat("__objc_yes!;");
2512 verifyFormat("__objc_no!;");
2513 verifyFormat("asm!;");
2514 verifyFormat("bool!;");
2515 verifyFormat("const_cast!;");
2516 verifyFormat("dynamic_cast!;");
2517 verifyFormat("explicit!;");
2518 verifyFormat("friend!;");
2519 verifyFormat("mutable!;");
2520 verifyFormat("operator!;");
2521 verifyFormat("reinterpret_cast!;");
2522 verifyFormat("static_cast!;");
2523 verifyFormat("template!;");
2524 verifyFormat("typename!;");
2525 verifyFormat("typeid!;");
2526 verifyFormat("using!;");
2527 verifyFormat("virtual!;");
2528 verifyFormat("wchar_t!;");
2531 verifyFormat("x.type!;");
2532 verifyFormat("x.get!;");
2533 verifyFormat("x.set!;");
2536 TEST_F(FormatTestJS
, NullPropagatingOperator
) {
2537 verifyFormat("let x = foo?.bar?.baz();");
2538 verifyFormat("let x = foo?.(foo);");
2539 verifyFormat("let x = foo?.['arr'];");
2542 TEST_F(FormatTestJS
, NullishCoalescingOperator
) {
2543 verifyFormat("const val = something ?? 'some other default';");
2544 verifyFormat("const val = something ?? otherDefault ??\n"
2545 " evenMore ?? evenMore;",
2546 "const val = something ?? otherDefault ?? evenMore ?? evenMore;",
2547 getGoogleJSStyleWithColumns(40));
2550 TEST_F(FormatTestJS
, AssignmentOperators
) {
2551 verifyFormat("a &&= b;");
2552 verifyFormat("a ||= b;");
2553 // NB: need to split ? ?= to avoid it being interpreted by C++ as a trigraph
2559 TEST_F(FormatTestJS
, Conditional
) {
2560 verifyFormat("y = x ? 1 : 2;");
2561 verifyFormat("x ? 1 : 2;");
2562 verifyFormat("class Foo {\n"
2563 " field = true ? 1 : 2;\n"
2564 " method(a = true ? 1 : 2) {}\n"
2568 TEST_F(FormatTestJS
, ImportComments
) {
2569 verifyFormat("import {x} from 'x'; // from some location",
2570 getGoogleJSStyleWithColumns(25));
2571 verifyFormat("// taze: x from 'location'", getGoogleJSStyleWithColumns(10));
2572 verifyFormat("/// <reference path=\"some/location\" />",
2573 getGoogleJSStyleWithColumns(10));
2576 TEST_F(FormatTestJS
, Exponentiation
) {
2577 verifyFormat("squared = x ** 2;");
2578 verifyFormat("squared **= 2;");
2581 TEST_F(FormatTestJS
, NestedLiterals
) {
2582 FormatStyle FourSpaces
= getGoogleJSStyleWithColumns(15);
2583 FourSpaces
.IndentWidth
= 4;
2584 verifyFormat("var l = [\n"
2590 verifyFormat("var l = [\n"
2596 verifyFormat("someFunction(\n"
2603 verifyFormat("someFunction(\n"
2610 verifyFormat("var o = {\n"
2617 verifyFormat("var o = {\n"
2626 TEST_F(FormatTestJS
, BackslashesInComments
) {
2627 verifyFormat("// hello \\\n"
2632 verifyFormat("/* ignore \\\n"
2638 verifyFormat("// st \\ art\\\n"
2648 TEST_F(FormatTestJS
, AddsLastLinePenaltyIfEndingIsBroken
) {
2650 "a = function() {\n"
2651 " b = function() {\n"
2652 " this.aaaaaaaaaaaaaaaaaaa[aaaaaaaaaaa] = aaaa.aaaaaa ?\n"
2653 " aaaa.aaaaaa : /** @type "
2654 "{aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaaaaaaaa} */\n"
2655 " (aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaa.aaaaaaaaaaaaaaaaa);\n"
2658 format("a = function() {\n"
2659 " b = function() {\n"
2660 " this.aaaaaaaaaaaaaaaaaaa[aaaaaaaaaaa] = aaaa.aaaaaa ? "
2661 "aaaa.aaaaaa : /** @type "
2662 "{aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaaaaaaaa} */\n"
2663 " (aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaa.aaaaaaaaaaaaaaaaa);\n"
2668 TEST_F(FormatTestJS
, ParameterNamingComment
) {
2669 verifyFormat("callFoo(/*spaceAfterParameterNamingComment=*/ 1);");
2672 TEST_F(FormatTestJS
, ConditionalTypes
) {
2673 // Formatting below is not necessarily intentional, this just ensures that
2674 // clang-format does not break the code.
2675 verifyFormat( // wrap
2676 "type UnionToIntersection<U> =\n"
2677 " (U extends any ? (k: U) => void :\n"
2678 " never) extends((k: infer I) => void) ? I : never;");
2681 TEST_F(FormatTestJS
, SupportPrivateFieldsAndMethods
) {
2682 verifyFormat("class Example {\n"
2685 " static pub2 = 'foo';\n"
2686 " static #priv2 = 'bar';\n"
2688 " this.#priv = 5;\n"
2690 " static staticMethod() {\n"
2691 " switch (this.#priv) {\n"
2697 " #privateMethod() {\n"
2698 " this.#privateMethod(); // infinite loop\n"
2700 " static #staticPrivateMethod() {}");
2703 TEST_F(FormatTestJS
, DeclaredFields
) {
2704 verifyFormat("class Example {\n"
2705 " declare pub: string;\n"
2706 " declare private priv: string;\n"
2710 TEST_F(FormatTestJS
, NoBreakAfterAsserts
) {
2712 "interface Assertable<State extends {}> {\n"
2713 " assert<ExportedState extends {}, DependencyState extends State = "
2715 " callback: Callback<ExportedState, DependencyState>):\n"
2716 " asserts this is ExtendedState<DependencyState&ExportedState>;\n"
2718 "interface Assertable<State extends {}> {\n"
2719 " assert<ExportedState extends {}, DependencyState extends State = "
2720 "State>(callback: Callback<ExportedState, DependencyState>): asserts "
2721 "this is ExtendedState<DependencyState&ExportedState>;\n"
2725 TEST_F(FormatTestJS
, NumericSeparators
) {
2726 verifyFormat("x = 1_000_000 + 12;", "x = 1_000_000 + 12;");
2729 TEST_F(FormatTestJS
, AlignConsecutiveDeclarations
) {
2730 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_JavaScript
);
2731 Style
.AlignConsecutiveDeclarations
.Enabled
= true;
2732 verifyFormat("let letVariable = 5;\n"
2733 "double constVariable = 10;",
2736 verifyFormat("let letVariable = 5;\n"
2737 "const constVariable = 10;",
2740 verifyFormat("let letVariable = 5;\n"
2741 "static const constVariable = 10;",
2744 verifyFormat("let letVariable = 5;\n"
2745 "static var constVariable = 10;",
2748 verifyFormat("let letVariable = 5;\n"
2749 "var constVariable = 10;",
2752 verifyFormat("double letVariable = 5;\n"
2753 "var constVariable = 10;",
2756 verifyFormat("const letVariable = 5;\n"
2757 "var constVariable = 10;",
2760 verifyFormat("int letVariable = 5;\n"
2761 "int constVariable = 10;",
2765 TEST_F(FormatTestJS
, AlignConsecutiveAssignments
) {
2766 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_JavaScript
);
2768 Style
.AlignConsecutiveAssignments
.Enabled
= true;
2769 verifyFormat("let letVariable = 5;\n"
2770 "double constVariable = 10;",
2773 verifyFormat("let letVariable = 5;\n"
2774 "const constVariable = 10;",
2777 verifyFormat("let letVariable = 5;\n"
2778 "static const constVariable = 10;",
2781 verifyFormat("let letVariable = 5;\n"
2782 "static var constVariable = 10;",
2785 verifyFormat("let letVariable = 5;\n"
2786 "var constVariable = 10;",
2789 verifyFormat("double letVariable = 5;\n"
2790 "var constVariable = 10;",
2793 verifyFormat("const letVariable = 5;\n"
2794 "var constVariable = 10;",
2797 verifyFormat("int letVariable = 5;\n"
2798 "int constVariable = 10;",
2802 TEST_F(FormatTestJS
, AlignConsecutiveAssignmentsAndDeclarations
) {
2803 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_JavaScript
);
2804 Style
.AlignConsecutiveDeclarations
.Enabled
= true;
2805 Style
.AlignConsecutiveAssignments
.Enabled
= true;
2806 verifyFormat("let letVariable = 5;\n"
2807 "double constVariable = 10;",
2810 verifyFormat("let letVariable = 5;\n"
2811 "const constVariable = 10;",
2814 verifyFormat("let letVariable = 5;\n"
2815 "static const constVariable = 10;",
2818 verifyFormat("let letVariable = 5;\n"
2819 "static var constVariable = 10;",
2822 verifyFormat("let letVariable = 5;\n"
2823 "var constVariable = 10;",
2826 verifyFormat("double letVariable = 5;\n"
2827 "var constVariable = 10;",
2830 verifyFormat("const letVariable = 5;\n"
2831 "var constVariable = 10;",
2834 verifyFormat("int letVariable = 5;\n"
2835 "int constVariable = 10;",
2839 } // namespace format
2840 } // end namespace clang