1 //===- unittest/Format/FormatTestJS.cpp - Formatting unit tests for JS ----===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "FormatTestUtils.h"
11 #include "clang/Format/Format.h"
12 #include "llvm/Support/Debug.h"
13 #include "gtest/gtest.h"
15 #define DEBUG_TYPE "format-test"
20 class FormatTestJS : public ::testing::Test {
22 static std::string format(llvm::StringRef Code, unsigned Offset,
23 unsigned Length, const FormatStyle &Style) {
24 LLVM_DEBUG(llvm::errs() << "---\n");
25 LLVM_DEBUG(llvm::errs() << Code << "\n\n");
26 std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
27 FormattingAttemptStatus Status;
28 tooling::Replacements Replaces =
29 reformat(Style, Code, Ranges, "<stdin>", &Status);
30 EXPECT_TRUE(Status.FormatComplete);
31 auto Result = applyAllReplacements(Code, Replaces);
32 EXPECT_TRUE(static_cast<bool>(Result));
33 LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
37 static std::string format(
39 const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) {
40 return format(Code, 0, Code.size(), Style);
43 static FormatStyle getGoogleJSStyleWithColumns(unsigned ColumnLimit) {
44 FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
45 Style.ColumnLimit = ColumnLimit;
49 static void verifyFormat(
51 const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) {
52 EXPECT_EQ(Code.str(), format(Code, Style))
53 << "Expected code is not stable";
54 std::string Result = format(test::messUp(Code), Style);
55 EXPECT_EQ(Code.str(), Result) << "Formatted:\n" << Result;
58 static void verifyFormat(
59 llvm::StringRef Expected,
61 const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) {
62 EXPECT_EQ(Expected.str(), format(Expected, Style))
63 << "Expected code is not stable";
64 std::string Result = format(Code, Style);
65 EXPECT_EQ(Expected.str(), Result) << "Formatted:\n" << Result;
69 TEST_F(FormatTestJS, BlockComments) {
70 verifyFormat("/* aaaaaaaaaaaaa */ aaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
71 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
72 // Breaks after a single line block comment.
73 EXPECT_EQ("aaaaa = bbbb.ccccccccccccccc(\n"
74 " /** @type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala} */\n"
76 format("aaaaa = bbbb.ccccccccccccccc(\n"
78 "@type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala} */ "
80 getGoogleJSStyleWithColumns(70)));
81 // Breaks after a multiline block comment.
83 "aaaaa = bbbb.ccccccccccccccc(\n"
85 " * @type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala}\n"
88 format("aaaaa = bbbb.ccccccccccccccc(\n"
90 " * @type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala}\n"
92 getGoogleJSStyleWithColumns(70)));
95 TEST_F(FormatTestJS, JSDocComments) {
96 // Break the first line of a multiline jsdoc comment.
101 format("/** jsdoc line 1\n"
104 getGoogleJSStyleWithColumns(20)));
105 // Both break after '/**' and break the line itself.
107 " * jsdoc line long\n"
108 " * long jsdoc line 2\n"
110 format("/** jsdoc line long long\n"
113 getGoogleJSStyleWithColumns(20)));
114 // Break a short first line if the ending '*/' is on a newline.
118 format("/** jsdoc line 1\n"
119 " */", getGoogleJSStyleWithColumns(20)));
120 // Don't break the first line of a short single line jsdoc comment.
121 EXPECT_EQ("/** jsdoc line 1 */",
122 format("/** jsdoc line 1 */", getGoogleJSStyleWithColumns(20)));
123 // Don't break the first line of a single line jsdoc comment if it just fits
125 EXPECT_EQ("/** jsdoc line 12 */",
126 format("/** jsdoc line 12 */", getGoogleJSStyleWithColumns(20)));
127 // Don't break after '/**' and before '*/' if there is no space between
128 // '/**' and the content.
130 "/*** nonjsdoc long\n"
132 format("/*** nonjsdoc long line */", getGoogleJSStyleWithColumns(20)));
134 "/**strange long long\n"
136 format("/**strange long long line */", getGoogleJSStyleWithColumns(20)));
137 // Break the first line of a single line jsdoc comment if it just exceeds the
140 " * jsdoc line 123\n"
142 format("/** jsdoc line 123 */", getGoogleJSStyleWithColumns(20)));
143 // Break also if the leading indent of the first line is more than 1 column.
145 " * jsdoc line 123\n"
147 format("/** jsdoc line 123 */", getGoogleJSStyleWithColumns(20)));
148 // Break also if the leading indent of the first line is more than 1 column.
150 " * jsdoc line 123\n"
152 format("/** jsdoc line 123 */", getGoogleJSStyleWithColumns(20)));
153 // Break after the content of the last line.
161 getGoogleJSStyleWithColumns(20)));
162 // Break both the content and after the content of the last line.
165 " * line long long\n"
170 " * line long long long */",
171 getGoogleJSStyleWithColumns(20)));
173 // The comment block gets indented.
174 EXPECT_EQ("function f() {\n"
181 format("function f() {\n"
182 "/** comment about x */\n"
185 getGoogleJSStyleWithColumns(20)));
187 // Don't break the first line of a single line short jsdoc comment pragma.
188 EXPECT_EQ("/** @returns j */",
189 format("/** @returns j */",
190 getGoogleJSStyleWithColumns(20)));
192 // Break a single line long jsdoc comment pragma.
194 " * @returns {string} jsdoc line 12\n"
196 format("/** @returns {string} jsdoc line 12 */",
197 getGoogleJSStyleWithColumns(20)));
200 " * @returns {string} jsdoc line 12\n"
202 format("/** @returns {string} jsdoc line 12 */",
203 getGoogleJSStyleWithColumns(20)));
206 " * @returns {string} jsdoc line 12\n"
208 format("/** @returns {string} jsdoc line 12*/",
209 getGoogleJSStyleWithColumns(20)));
211 // Fix a multiline jsdoc comment ending in a comment pragma.
215 " * @returns {string} jsdoc line 12\n"
217 format("/** line 1\n"
219 " * @returns {string} jsdoc line 12 */",
220 getGoogleJSStyleWithColumns(20)));
228 format("/** line 1\n"
232 getGoogleJSStyleWithColumns(20)));
235 TEST_F(FormatTestJS, UnderstandsJavaScriptOperators) {
236 verifyFormat("a == = b;");
237 verifyFormat("a != = b;");
239 verifyFormat("a === b;");
240 verifyFormat("aaaaaaa ===\n b;", getGoogleJSStyleWithColumns(10));
241 verifyFormat("a !== b;");
242 verifyFormat("aaaaaaa !==\n b;", getGoogleJSStyleWithColumns(10));
243 verifyFormat("if (a + b + c +\n"
247 getGoogleJSStyleWithColumns(20));
249 verifyFormat("a >> >= b;");
251 verifyFormat("a >>> b;");
252 verifyFormat("aaaaaaa >>>\n b;", getGoogleJSStyleWithColumns(10));
253 verifyFormat("a >>>= b;");
254 verifyFormat("aaaaaaa >>>=\n b;", getGoogleJSStyleWithColumns(10));
255 verifyFormat("if (a + b + c +\n"
259 getGoogleJSStyleWithColumns(20));
260 verifyFormat("var x = aaaaaaaaaa ?\n"
263 getGoogleJSStyleWithColumns(20));
265 verifyFormat("var b = a.map((x) => x + 1);");
266 verifyFormat("return ('aaa') in bbbb;");
267 verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa() in\n"
268 " aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;");
269 FormatStyle Style = getGoogleJSStyleWithColumns(80);
270 Style.AlignOperands = true;
271 verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa() in\n"
272 " aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
274 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
275 verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa()\n"
276 " in aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
279 // ES6 spread operator.
280 verifyFormat("someFunction(...a);");
281 verifyFormat("var x = [1, ...a, 2];");
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("interface = 2;");
324 verifyFormat("x = interface instanceof y;");
325 verifyFormat("interface Test {\n"
329 " default: string;\n"
331 verifyFormat("const Axis = {\n"
335 "const Axis = {for: 'for', x: 'x'};");
338 TEST_F(FormatTestJS, ReservedWordsMethods) {
353 TEST_F(FormatTestJS, ReservedWordsParenthesized) {
354 // All of these are statements using the keyword, not function calls.
355 verifyFormat("throw (x + y);\n"
356 "await (await x).y;\n"
357 "typeof (x) === 'string';\n"
363 TEST_F(FormatTestJS, CppKeywords) {
364 // Make sure we don't mess stuff up because of C++ keywords.
365 verifyFormat("return operator && (aa);");
367 verifyFormat("slots: Slot[];");
370 TEST_F(FormatTestJS, ES6DestructuringAssignment) {
371 verifyFormat("var [a, b, c] = [1, 2, 3];");
372 verifyFormat("const [a, b, c] = [1, 2, 3];");
373 verifyFormat("let [a, b, c] = [1, 2, 3];");
374 verifyFormat("var {a, b} = {a: 1, b: 2};");
375 verifyFormat("let {a, b} = {a: 1, b: 2};");
378 TEST_F(FormatTestJS, ContainerLiterals) {
379 verifyFormat("var x = {\n"
380 " y: function(a) {\n"
384 verifyFormat("return {\n"
385 " link: function() {\n"
389 verifyFormat("return {\n"
391 " link: function() {\n"
395 verifyFormat("return {\n"
397 " link: function() {\n"
400 " link: function() {\n"
404 verifyFormat("var stuff = {\n"
405 " // comment for update\n"
407 " // comment for modules\n"
409 " // comment for tasks\n"
412 verifyFormat("return {\n"
417 verifyFormat("var obj = {\n"
418 " fooooooooo: function(x) {\n"
419 " return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
422 // Simple object literal, as opposed to enum style below.
423 verifyFormat("var obj = {a: 123};");
424 // Enum style top level assignment.
425 verifyFormat("X = {\n a: 123\n};");
426 verifyFormat("X.Y = {\n a: 123\n};");
427 // But only on the top level, otherwise its a plain object literal assignment.
428 verifyFormat("function x() {\n"
431 verifyFormat("x = foo && {a: 123};");
433 // Arrow functions in object literals.
434 verifyFormat("var x = {\n"
439 verifyFormat("var x = {y: (a) => a};");
441 // Methods in object literals.
442 verifyFormat("var x = {\n"
443 " y(a: string): number {\n"
447 verifyFormat("var x = {\n"
454 verifyFormat("var x = {[a]: 1, b: 2, [c]: 3};");
455 verifyFormat("var x = {\n"
461 // Object literals can leave out labels.
462 verifyFormat("f({a}, () => {\n"
466 // Keys can be quoted.
467 verifyFormat("var x = {\n"
473 // Dict literals can skip the label names.
474 verifyFormat("var x = {\n"
479 verifyFormat("return {\n"
486 TEST_F(FormatTestJS, MethodsInObjectLiterals) {
487 verifyFormat("var o = {\n"
489 " get value() { // getter\n"
490 " return this.value;\n"
493 verifyFormat("var o = {\n"
495 " set value(val) { // setter\n"
496 " this.value = val;\n"
499 verifyFormat("var o = {\n"
501 " someMethod(val) { // method\n"
502 " doSomething(this.value + val);\n"
505 verifyFormat("var o = {\n"
506 " someMethod(val) { // method\n"
507 " doSomething(this.value + val);\n"
509 " someOtherMethod(val) { // method\n"
510 " doSomething(this.value + val);\n"
515 TEST_F(FormatTestJS, GettersSettersVisibilityKeywords) {
516 // Don't break after "protected"
517 verifyFormat("class X {\n"
518 " protected get getter():\n"
523 getGoogleJSStyleWithColumns(12));
524 // Don't break after "get"
525 verifyFormat("class X {\n"
526 " protected get someReallyLongGetterName():\n"
531 getGoogleJSStyleWithColumns(40));
534 TEST_F(FormatTestJS, SpacesInContainerLiterals) {
535 verifyFormat("var arr = [1, 2, 3];");
536 verifyFormat("f({a: 1, b: 2, c: 3});");
538 verifyFormat("var object_literal_with_long_name = {\n"
539 " a: 'aaaaaaaaaaaaaaaaaa',\n"
540 " b: 'bbbbbbbbbbbbbbbbbb'\n"
543 verifyFormat("f({a: 1, b: 2, c: 3});",
544 getChromiumStyle(FormatStyle::LK_JavaScript));
545 verifyFormat("f({'a': [{}]});");
548 TEST_F(FormatTestJS, SingleQuotedStrings) {
549 verifyFormat("this.function('', true);");
552 TEST_F(FormatTestJS, GoogScopes) {
553 verifyFormat("goog.scope(function() {\n"
556 "}); // goog.scope");
557 verifyFormat("goog.scope(function() {\n"
564 TEST_F(FormatTestJS, IIFEs) {
565 // Internal calling parens; no semi.
566 verifyFormat("(function() {\n"
569 // External calling parens; no semi.
570 verifyFormat("(function() {\n"
573 // Internal calling parens; with semi.
574 verifyFormat("(function() {\n"
577 // External calling parens; with semi.
578 verifyFormat("(function() {\n"
583 TEST_F(FormatTestJS, GoogModules) {
584 verifyFormat("goog.module('this.is.really.absurdly.long');",
585 getGoogleJSStyleWithColumns(40));
586 verifyFormat("goog.require('this.is.really.absurdly.long');",
587 getGoogleJSStyleWithColumns(40));
588 verifyFormat("goog.provide('this.is.really.absurdly.long');",
589 getGoogleJSStyleWithColumns(40));
590 verifyFormat("var long = goog.require('this.is.really.absurdly.long');",
591 getGoogleJSStyleWithColumns(40));
592 verifyFormat("goog.forwardDeclare('this.is.really.absurdly.long');",
593 getGoogleJSStyleWithColumns(40));
595 // These should be wrapped normally.
597 "var MyLongClassName =\n"
598 " goog.module.get('my.long.module.name.followedBy.MyLongClassName');");
599 verifyFormat("function a() {\n"
600 " goog.setTestOnly();\n"
603 "goog.setTestOnly();\n"
607 TEST_F(FormatTestJS, FormatsNamespaces) {
608 verifyFormat("namespace Foo {\n"
609 " export let x = 1;\n"
611 verifyFormat("declare namespace Foo {\n"
612 " export let x: number;\n"
616 TEST_F(FormatTestJS, NamespacesMayNotWrap) {
617 verifyFormat("declare namespace foobarbaz {\n"
618 "}\n", getGoogleJSStyleWithColumns(18));
619 verifyFormat("declare module foobarbaz {\n"
620 "}\n", getGoogleJSStyleWithColumns(15));
621 verifyFormat("namespace foobarbaz {\n"
622 "}\n", getGoogleJSStyleWithColumns(10));
623 verifyFormat("module foobarbaz {\n"
624 "}\n", getGoogleJSStyleWithColumns(7));
627 TEST_F(FormatTestJS, AmbientDeclarations) {
628 FormatStyle NineCols = getGoogleJSStyleWithColumns(9);
635 "x();", // TODO(martinprobst): should ideally be indented.
637 verifyFormat("declare function foo();\n"
639 verifyFormat("declare function foo(): string;\n"
641 verifyFormat("declare function foo(): {x: number};\n"
643 verifyFormat("declare class X {}\n"
645 verifyFormat("declare interface Y {}\n"
657 TEST_F(FormatTestJS, FormatsFreestandingFunctions) {
658 verifyFormat("function outer1(a, b) {\n"
659 " function inner1(a, b) {\n"
664 "function outer2(a, b) {\n"
665 " function inner2(a, b) {\n"
670 verifyFormat("function f() {}");
671 verifyFormat("function aFunction() {}\n"
675 verifyFormat("function aFunction() {}\n"
682 TEST_F(FormatTestJS, GeneratorFunctions) {
683 verifyFormat("function* f() {\n"
686 " yield* something();\n"
690 verifyFormat("function*\n"
693 getGoogleJSStyleWithColumns(8));
694 verifyFormat("export function* f() {\n"
697 verifyFormat("class X {\n"
698 " * generatorMethod() {\n"
702 verifyFormat("var x = {\n"
703 " a: function*() {\n"
709 TEST_F(FormatTestJS, AsyncFunctions) {
710 verifyFormat("async function f() {\n"
712 " return fetch(x);\n"
714 verifyFormat("async function f() {\n"
721 " async function f() {\n"
728 verifyFormat("async function* f() {\n"
731 verifyFormat("export async function f() {\n"
732 " return fetch(x);\n"
734 verifyFormat("let x = async () => f();");
735 verifyFormat("let x = async function() {\n"
738 verifyFormat("let x = async();");
739 verifyFormat("class X {\n"
740 " async asyncMethod() {\n"
741 " return fetch(1);\n"
744 verifyFormat("function initialize() {\n"
746 " return async.then();\n"
748 verifyFormat("for await (const x of y) {\n"
751 verifyFormat("function asyncLoop() {\n"
752 " for await (const x of y) {\n"
758 TEST_F(FormatTestJS, FunctionParametersTrailingComma) {
759 verifyFormat("function trailingComma(\n"
766 "function trailingComma(p1, p2, p3,) {\n"
769 verifyFormat("trailingComma(\n"
774 "trailingComma(p1, p2, p3,);\n");
775 verifyFormat("trailingComma(\n"
778 "trailingComma(p1 // hello\n"
782 TEST_F(FormatTestJS, ArrayLiterals) {
783 verifyFormat("var aaaaa: List<SomeThing> =\n"
784 " [new SomeThingAAAAAAAAAAAA(), new SomeThingBBBBBBBBB()];");
785 verifyFormat("return [\n"
786 " aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
787 " ccccccccccccccccccccccccccc\n"
789 verifyFormat("return [\n"
790 " aaaa().bbbbbbbb('A'),\n"
791 " aaaa().bbbbbbbb('B'),\n"
792 " aaaa().bbbbbbbb('C'),\n"
794 verifyFormat("var someVariable = SomeFunction([\n"
795 " aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
796 " ccccccccccccccccccccccccccc\n"
798 verifyFormat("var someVariable = SomeFunction([\n"
799 " [aaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbb],\n"
801 getGoogleJSStyleWithColumns(51));
802 verifyFormat("var someVariable = SomeFunction(aaaa, [\n"
803 " aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
804 " ccccccccccccccccccccccccccc\n"
806 verifyFormat("var someVariable = SomeFunction(\n"
809 " aaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
810 " cccccccccccccccccccccccccc\n"
813 verifyFormat("var aaaa = aaaaa || // wrap\n"
816 verifyFormat("someFunction([], {a: a});");
818 verifyFormat("var string = [\n"
824 TEST_F(FormatTestJS, ColumnLayoutForArrayLiterals) {
825 verifyFormat("var array = [\n"
826 " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
827 " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
829 verifyFormat("var array = someFunction([\n"
830 " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
831 " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
835 TEST_F(FormatTestJS, FunctionLiterals) {
836 FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
837 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
838 verifyFormat("doFoo(function() {});");
839 verifyFormat("doFoo(function() { return 1; });", Style);
840 verifyFormat("var func = function() {\n"
843 verifyFormat("var func = //\n"
847 verifyFormat("return {\n"
849 " setAttribute: function(key, val) { this[key] = val; },\n"
850 " getAttribute: function(key) { return this[key]; },\n"
851 " style: {direction: ''}\n"
855 verifyFormat("abc = xyz ? function() {\n"
861 verifyFormat("var closure = goog.bind(\n"
862 " function() { // comment\n"
866 " this, arg1IsReallyLongAndNeedsLineBreaks,\n"
867 " arg3IsReallyLongAndNeedsLineBreaks);");
868 verifyFormat("var closure = goog.bind(function() { // comment\n"
872 verifyFormat("return {\n"
875 " return function() {\n"
881 " var someVariable = function(x) {\n"
882 " return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
885 verifyFormat("someLooooooooongFunction(\n"
886 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
887 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
888 " function(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n"
892 verifyFormat("return {\n"
893 " a: function SomeFunction() {\n"
898 verifyFormat("this.someObject.doSomething(aaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
899 " .then(goog.bind(function(aaaaaaaaaaa) {\n"
902 " }, this), aaaaaaaaaaaaaaaaa);");
904 verifyFormat("someFunction(goog.bind(function() {\n"
907 "}, this), goog.bind(function() {\n"
912 verifyFormat("SomeFunction(function() {\n"
917 verifyFormat("SomeFunction((function() {\n"
922 // FIXME: This is bad, we should be wrapping before "function() {".
923 verifyFormat("someFunction(function() {\n"
924 " doSomething(); // break\n"
926 " .doSomethingElse(\n"
930 Style.ColumnLimit = 33;
931 verifyFormat("f({a: function() { return 1; }});", Style);
932 Style.ColumnLimit = 32;
934 " a: function() { return 1; }\n"
940 TEST_F(FormatTestJS, DontWrapEmptyLiterals) {
941 verifyFormat("(aaaaaaaaaaaaaaaaaaaaa.getData as jasmine.Spy)\n"
942 " .and.returnValue(Observable.of([]));");
943 verifyFormat("(aaaaaaaaaaaaaaaaaaaaa.getData as jasmine.Spy)\n"
944 " .and.returnValue(Observable.of({}));");
945 verifyFormat("(aaaaaaaaaaaaaaaaaaaaa.getData as jasmine.Spy)\n"
946 " .and.returnValue(Observable.of(()));");
949 TEST_F(FormatTestJS, InliningFunctionLiterals) {
950 FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
951 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
952 verifyFormat("var func = function() {\n"
956 verifyFormat("var func = doSomething(function() { return 1; });", Style);
957 verifyFormat("var outer = function() {\n"
958 " var inner = function() { return 1; }\n"
961 verifyFormat("function outer1(a, b) {\n"
962 " function inner1(a, b) { return a; }\n"
966 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
967 verifyFormat("var func = function() { return 1; };", Style);
968 verifyFormat("var func = doSomething(function() { return 1; });", Style);
970 "var outer = function() { var inner = function() { return 1; } };",
972 verifyFormat("function outer1(a, b) {\n"
973 " function inner1(a, b) { return a; }\n"
977 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
978 verifyFormat("var func = function() {\n"
982 verifyFormat("var func = doSomething(function() {\n"
986 verifyFormat("var outer = function() {\n"
987 " var inner = function() {\n"
992 verifyFormat("function outer1(a, b) {\n"
993 " function inner1(a, b) {\n"
999 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
1000 verifyFormat("var func = function() {\n"
1006 TEST_F(FormatTestJS, MultipleFunctionLiterals) {
1007 FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
1008 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
1009 verifyFormat("promise.then(\n"
1010 " function success() {\n"
1014 " function error() {\n"
1019 verifyFormat("promise.then(\n"
1020 " function success() {\n"
1025 " function error() {\n"
1029 verifyFormat("promise.then(\n"
1031 " function success() {\n"
1035 " function error() {\n"
1040 verifyFormat("getSomeLongPromise()\n"
1041 " .then(function(value) { body(); })\n"
1042 " .thenCatch(function(error) {\n"
1047 verifyFormat("getSomeLongPromise()\n"
1048 " .then(function(value) {\n"
1052 " .thenCatch(function(error) {\n"
1057 verifyFormat("getSomeLongPromise()\n"
1058 " .then(function(value) { body(); })\n"
1059 " .thenCatch(function(error) { body(); });",
1062 verifyFormat("return [aaaaaaaaaaaaaaaaaaaaaa]\n"
1063 " .aaaaaaa(function() {\n"
1069 TEST_F(FormatTestJS, ArrowFunctions) {
1070 verifyFormat("var x = (a) => {\n"
1073 verifyFormat("var x = (a) => {\n"
1079 verifyFormat("var x = (a: type): {some: type} => {\n"
1082 verifyFormat("var x = (a) => a;");
1083 verifyFormat("return () => [];");
1084 verifyFormat("var aaaaaaaaaaaaaaaaaaaa = {\n"
1085 " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n"
1086 " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
1087 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) =>\n"
1088 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
1090 verifyFormat("var a = a.aaaaaaa(\n"
1091 " (a: a) => aaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) &&\n"
1092 " aaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
1093 verifyFormat("var a = a.aaaaaaa(\n"
1094 " (a: a) => aaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) ?\n"
1095 " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb) :\n"
1096 " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
1098 // FIXME: This is bad, we should be wrapping before "() => {".
1099 verifyFormat("someFunction(() => {\n"
1100 " doSomething(); // break\n"
1102 " .doSomethingElse(\n"
1105 verifyFormat("const f = (x: string|null): string|null => {\n"
1110 TEST_F(FormatTestJS, ReturnStatements) {
1111 verifyFormat("function() {\n"
1112 " return [hello, world];\n"
1116 TEST_F(FormatTestJS, ForLoops) {
1117 verifyFormat("for (var i in [2, 3]) {\n"
1119 verifyFormat("for (var i of [2, 3]) {\n"
1121 verifyFormat("for (let {a, b} of x) {\n"
1123 verifyFormat("for (let {a, b} of [x]) {\n"
1125 verifyFormat("for (let [a, b] of [x]) {\n"
1127 verifyFormat("for (let {a, b} in x) {\n"
1131 TEST_F(FormatTestJS, WrapRespectsAutomaticSemicolonInsertion) {
1132 // The following statements must not wrap, as otherwise the program meaning
1133 // would change due to automatic semicolon insertion.
1134 // See http://www.ecma-international.org/ecma-262/5.1/#sec-7.9.1.
1135 verifyFormat("return aaaaa;", getGoogleJSStyleWithColumns(10));
1136 verifyFormat("yield aaaaa;", getGoogleJSStyleWithColumns(10));
1137 verifyFormat("return /* hello! */ aaaaa;", getGoogleJSStyleWithColumns(10));
1138 verifyFormat("continue aaaaa;", getGoogleJSStyleWithColumns(10));
1139 verifyFormat("continue /* hello! */ aaaaa;", getGoogleJSStyleWithColumns(10));
1140 verifyFormat("break aaaaa;", getGoogleJSStyleWithColumns(10));
1141 verifyFormat("throw aaaaa;", getGoogleJSStyleWithColumns(10));
1142 verifyFormat("aaaaaaaaa++;", getGoogleJSStyleWithColumns(10));
1143 verifyFormat("aaaaaaaaa--;", getGoogleJSStyleWithColumns(10));
1144 verifyFormat("return [\n"
1147 getGoogleJSStyleWithColumns(12));
1148 verifyFormat("class X {\n"
1149 " readonly ratherLongField =\n"
1153 " readonly ratherLongField = 1;\n"
1155 getGoogleJSStyleWithColumns(20));
1156 verifyFormat("const x = (5 + 9)\n"
1158 "const x = ( 5 + 9)\n"
1160 // Ideally the foo() bit should be indented relative to the async function().
1161 verifyFormat("async function\n"
1163 getGoogleJSStyleWithColumns(10));
1164 verifyFormat("await theReckoning;", getGoogleJSStyleWithColumns(10));
1165 verifyFormat("some['a']['b']", getGoogleJSStyleWithColumns(10));
1166 verifyFormat("x = (a['a']\n"
1168 getGoogleJSStyleWithColumns(10));
1169 verifyFormat("function f() {\n"
1170 " return foo.bar(\n"
1171 " (param): param is {\n"
1175 getGoogleJSStyleWithColumns(25));
1178 TEST_F(FormatTestJS, AutomaticSemicolonInsertionHeuristic) {
1183 verifyFormat("a()\n"
1187 verifyFormat("a[b]\n"
1203 verifyFormat("a++\n"
1219 verifyFormat("var a", "var\n"
1221 verifyFormat("x instanceof String", "x\n"
1224 verifyFormat("function f(@Foo bar) {}", "function f(@Foo\n"
1226 verifyFormat("function f(@Foo(Param) bar) {}", "function f(@Foo(Param)\n"
1228 verifyFormat("a = true\n"
1232 verifyFormat("a = 's'\n"
1236 verifyFormat("a = null\n"
1240 // Below "class Y {}" should ideally be on its own line.
1261 TEST_F(FormatTestJS, ImportExportASI) {
1263 "import {x} from 'y'\n"
1264 "export function z() {}",
1265 "import {x} from 'y'\n"
1266 " export function z() {}");
1267 // Below "class Y {}" should ideally be on its own line.
1269 "export {x} class Y {}",
1275 "export class Y {}",
1277 " export class Y {}");
1280 TEST_F(FormatTestJS, ClosureStyleCasts) {
1281 verifyFormat("var x = /** @type {foo} */ (bar);");
1284 TEST_F(FormatTestJS, TryCatch) {
1285 verifyFormat("try {\n"
1293 // But, of course, "catch" is a perfectly fine function name in JavaScript.
1294 verifyFormat("someObject.catch();");
1295 verifyFormat("someObject.new();");
1298 TEST_F(FormatTestJS, StringLiteralConcatenation) {
1299 verifyFormat("var literal = 'hello ' +\n"
1303 TEST_F(FormatTestJS, RegexLiteralClassification) {
1305 verifyFormat("var regex = /abc/;");
1306 verifyFormat("f(/abc/);");
1307 verifyFormat("f(abc, /abc/);");
1308 verifyFormat("some_map[/abc/];");
1309 verifyFormat("var x = a ? /abc/ : /abc/;");
1310 verifyFormat("for (var i = 0; /abc/.test(s[i]); i++) {\n}");
1311 verifyFormat("var x = !/abc/.test(y);");
1312 verifyFormat("var x = foo()! / 10;");
1313 verifyFormat("var x = a && /abc/.test(y);");
1314 verifyFormat("var x = a || /abc/.test(y);");
1315 verifyFormat("var x = a + /abc/.search(y);");
1316 verifyFormat("/abc/.search(y);");
1317 verifyFormat("var regexs = {/abc/, /abc/};");
1318 verifyFormat("return /abc/;");
1320 // Not regex literals.
1321 verifyFormat("var a = a / 2 + b / 3;");
1322 verifyFormat("var a = a++ / 2;");
1323 // Prefix unary can operate on regex literals, not that it makes sense.
1324 verifyFormat("var a = ++/a/;");
1326 // This is a known issue, regular expressions are incorrectly detected if
1327 // directly following a closing parenthesis.
1328 verifyFormat("if (foo) / bar /.exec(baz);");
1331 TEST_F(FormatTestJS, RegexLiteralSpecialCharacters) {
1332 verifyFormat("var regex = /=/;");
1333 verifyFormat("var regex = /a*/;");
1334 verifyFormat("var regex = /a+/;");
1335 verifyFormat("var regex = /a?/;");
1336 verifyFormat("var regex = /.a./;");
1337 verifyFormat("var regex = /a\\*/;");
1338 verifyFormat("var regex = /^a$/;");
1339 verifyFormat("var regex = /\\/a/;");
1340 verifyFormat("var regex = /(?:x)/;");
1341 verifyFormat("var regex = /x(?=y)/;");
1342 verifyFormat("var regex = /x(?!y)/;");
1343 verifyFormat("var regex = /x|y/;");
1344 verifyFormat("var regex = /a{2}/;");
1345 verifyFormat("var regex = /a{1,3}/;");
1347 verifyFormat("var regex = /[abc]/;");
1348 verifyFormat("var regex = /[^abc]/;");
1349 verifyFormat("var regex = /[\\b]/;");
1350 verifyFormat("var regex = /[/]/;");
1351 verifyFormat("var regex = /[\\/]/;");
1352 verifyFormat("var regex = /\\[/;");
1353 verifyFormat("var regex = /\\\\[/]/;");
1354 verifyFormat("var regex = /}[\"]/;");
1355 verifyFormat("var regex = /}[/\"]/;");
1356 verifyFormat("var regex = /}[\"/]/;");
1358 verifyFormat("var regex = /\\b/;");
1359 verifyFormat("var regex = /\\B/;");
1360 verifyFormat("var regex = /\\d/;");
1361 verifyFormat("var regex = /\\D/;");
1362 verifyFormat("var regex = /\\f/;");
1363 verifyFormat("var regex = /\\n/;");
1364 verifyFormat("var regex = /\\r/;");
1365 verifyFormat("var regex = /\\s/;");
1366 verifyFormat("var regex = /\\S/;");
1367 verifyFormat("var regex = /\\t/;");
1368 verifyFormat("var regex = /\\v/;");
1369 verifyFormat("var regex = /\\w/;");
1370 verifyFormat("var regex = /\\W/;");
1371 verifyFormat("var regex = /a(a)\\1/;");
1372 verifyFormat("var regex = /\\0/;");
1373 verifyFormat("var regex = /\\\\/g;");
1374 verifyFormat("var regex = /\\a\\\\/g;");
1375 verifyFormat("var regex = /\a\\//g;");
1376 verifyFormat("var regex = /a\\//;\n"
1378 verifyFormat("var regex = /'/g;", "var regex = /'/g ;");
1379 verifyFormat("var regex = /'/g; //'", "var regex = /'/g ; //'");
1380 verifyFormat("var regex = /\\/*/;\n"
1382 "var regex = /\\/*/;\n"
1384 verifyFormat("var x = /a\\//;", "var x = /a\\// \n;");
1385 verifyFormat("var regex = /\"/;", getGoogleJSStyleWithColumns(16));
1386 verifyFormat("var regex =\n"
1388 getGoogleJSStyleWithColumns(15));
1389 verifyFormat("var regex = //\n"
1391 verifyFormat("var regexs = [\n"
1397 TEST_F(FormatTestJS, RegexLiteralModifiers) {
1398 verifyFormat("var regex = /abc/g;");
1399 verifyFormat("var regex = /abc/i;");
1400 verifyFormat("var regex = /abc/m;");
1401 verifyFormat("var regex = /abc/y;");
1404 TEST_F(FormatTestJS, RegexLiteralLength) {
1405 verifyFormat("var regex = /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
1406 getGoogleJSStyleWithColumns(60));
1407 verifyFormat("var regex =\n"
1408 " /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
1409 getGoogleJSStyleWithColumns(60));
1410 verifyFormat("var regex = /\\xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
1411 getGoogleJSStyleWithColumns(50));
1414 TEST_F(FormatTestJS, RegexLiteralExamples) {
1415 verifyFormat("var regex = search.match(/(?:\?|&)times=([^?&]+)/i);");
1418 TEST_F(FormatTestJS, IgnoresMpegTS) {
1419 std::string MpegTS(200, ' ');
1420 MpegTS.replace(0, strlen("nearlyLooks + like + ts + code; "),
1421 "nearlyLooks + like + ts + code; ");
1424 verifyFormat(MpegTS, MpegTS);
1427 TEST_F(FormatTestJS, TypeAnnotations) {
1428 verifyFormat("var x: string;");
1429 verifyFormat("var x: {a: string; b: number;} = {};");
1430 verifyFormat("function x(): string {\n return 'x';\n}");
1431 verifyFormat("function x(): {x: string} {\n return {x: 'x'};\n}");
1432 verifyFormat("function x(y: string): string {\n return 'x';\n}");
1433 verifyFormat("for (var y: string in x) {\n x();\n}");
1434 verifyFormat("for (var y: string of x) {\n x();\n}");
1435 verifyFormat("function x(y: {a?: number;} = {}): number {\n"
1438 verifyFormat("const x: Array<{a: number; b: string;}> = [];");
1439 verifyFormat("((a: string, b: number): string => a + b);");
1440 verifyFormat("var x: (y: number) => string;");
1441 verifyFormat("var x: P<string, (a: number) => string>;");
1442 verifyFormat("var x = {\n"
1443 " y: function(): z {\n"
1447 verifyFormat("var x = {\n"
1448 " y: function(): {a: number} {\n"
1452 verifyFormat("function someFunc(args: string[]):\n"
1453 " {longReturnValue: string[]} {}",
1454 getGoogleJSStyleWithColumns(60));
1456 "var someValue = (v as aaaaaaaaaaaaaaaaaaaa<T>[])\n"
1457 " .someFunction(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
1458 verifyFormat("const xIsALongIdent:\n"" YJustBarelyFitsLinex[];",
1459 getGoogleJSStyleWithColumns(20));
1462 TEST_F(FormatTestJS, UnionIntersectionTypes) {
1463 verifyFormat("let x: A|B = A | B;");
1464 verifyFormat("let x: A&B|C = A & B;");
1465 verifyFormat("let x: Foo<A|B> = new Foo<A|B>();");
1466 verifyFormat("function(x: A|B): C&D {}");
1467 verifyFormat("function(x: A|B = A | B): C&D {}");
1468 verifyFormat("function x(path: number|string) {}");
1469 verifyFormat("function x(): string|number {}");
1470 verifyFormat("type Foo = Bar|Baz;");
1471 verifyFormat("type Foo = Bar<X>|Baz;");
1472 verifyFormat("type Foo = (Bar<X>|Baz);");
1473 verifyFormat("let x: Bar|Baz;");
1474 verifyFormat("let x: Bar<X>|Baz;");
1475 verifyFormat("let x: (Foo|Bar)[];");
1476 verifyFormat("type X = {\n"
1479 verifyFormat("export type X = {\n"
1484 TEST_F(FormatTestJS, UnionIntersectionTypesInObjectType) {
1485 verifyFormat("let x: {x: number|null} = {x: number | null};");
1486 verifyFormat("let nested: {x: {y: number|null}};");
1487 verifyFormat("let mixed: {x: [number|null, {w: number}]};");
1488 verifyFormat("class X {\n"
1489 " contructor(x: {\n"
1496 TEST_F(FormatTestJS, ClassDeclarations) {
1497 verifyFormat("class C {\n x: string = 12;\n}");
1498 verifyFormat("class C {\n x(): string => 12;\n}");
1499 verifyFormat("class C {\n ['x' + 2]: string = 12;\n}");
1500 verifyFormat("class C {\n"
1504 verifyFormat("class C {\n private x: string = 12;\n}");
1505 verifyFormat("class C {\n private static x: string = 12;\n}");
1506 verifyFormat("class C {\n static x(): string {\n return 'asd';\n }\n}");
1507 verifyFormat("class C extends P implements I {}");
1508 verifyFormat("class C extends p.P implements i.I {}");
1513 verifyFormat("class Test {\n"
1514 " aaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaaa):\n"
1515 " aaaaaaaaaaaaaaaaaaaaaa {}\n"
1517 verifyFormat("foo = class Name {\n"
1518 " constructor() {}\n"
1520 verifyFormat("foo = class {\n"
1521 " constructor() {}\n"
1523 verifyFormat("class C {\n"
1524 " x: {y: Z;} = {};\n"
1525 " private y: {y: Z;} = {};\n"
1528 // ':' is not a type declaration here.
1529 verifyFormat("class X {\n"
1536 verifyFormat("@Component({\n"
1537 " moduleId: module.id,\n"
1539 "class SessionListComponent implements OnDestroy, OnInit {\n"
1543 TEST_F(FormatTestJS, StrictPropInitWrap) {
1544 const FormatStyle &Style = getGoogleJSStyleWithColumns(22);
1545 verifyFormat("class X {\n"
1546 " strictPropInitField!:\n"
1552 TEST_F(FormatTestJS, InterfaceDeclarations) {
1553 verifyFormat("interface I {\n"
1555 " enum: string[];\n"
1556 " enum?: string[];\n"
1559 // Ensure that state is reset after parsing the interface.
1560 verifyFormat("interface a {}\n"
1561 "export function b() {}\n"
1564 // Arrays of object type literals.
1565 verifyFormat("interface I {\n"
1570 TEST_F(FormatTestJS, ObjectTypesInExtendsImplements) {
1571 verifyFormat("class C extends {} {}");
1572 verifyFormat("class C implements {bar: number} {}");
1573 // Somewhat odd, but probably closest to reasonable formatting?
1574 verifyFormat("class C implements {\n"
1578 verifyFormat("class C<P extends {}> {}");
1581 TEST_F(FormatTestJS, EnumDeclarations) {
1582 verifyFormat("enum Foo {\n"
1586 verifyFormat("export /* somecomment*/ enum Foo {\n"
1590 verifyFormat("enum Foo {\n"
1591 " A = 1, // comment\n"
1595 verifyFormat("const enum Foo {\n"
1599 verifyFormat("export const enum Foo {\n"
1605 TEST_F(FormatTestJS, Decorators) {
1606 verifyFormat("@A\nclass C {\n}");
1607 verifyFormat("@A({arg: 'value'})\nclass C {\n}");
1608 verifyFormat("@A\n@B\nclass C {\n}");
1609 verifyFormat("class C {\n @A x: string;\n}");
1610 verifyFormat("class C {\n"
1612 " private x(): string {\n"
1616 verifyFormat("class C {\n"
1617 " private x(@A x: string) {}\n"
1619 verifyFormat("class X {}\n"
1621 verifyFormat("class X {\n"
1622 " @property() private isReply = false;\n"
1626 TEST_F(FormatTestJS, TypeAliases) {
1627 verifyFormat("type X = number;\n"
1629 verifyFormat("type X<Y> = Z<Y>;");
1630 verifyFormat("type X = {\n"
1634 verifyFormat("export type X = {\n"
1640 TEST_F(FormatTestJS, TypeInterfaceLineWrapping) {
1641 const FormatStyle &Style = getGoogleJSStyleWithColumns(20);
1642 verifyFormat("type LongTypeIsReallyUnreasonablyLong =\n"
1644 "type LongTypeIsReallyUnreasonablyLong = string;\n",
1647 "interface AbstractStrategyFactoryProvider {\n"
1650 "interface AbstractStrategyFactoryProvider { a: number }\n",
1654 TEST_F(FormatTestJS, RemoveEmptyLinesInArrowFunctions) {
1655 verifyFormat("x = () => {\n"
1665 TEST_F(FormatTestJS, Modules) {
1666 verifyFormat("import SomeThing from 'some/module.js';");
1667 verifyFormat("import {X, Y} from 'some/module.js';");
1668 verifyFormat("import a, {X, Y} from 'some/module.js';");
1669 verifyFormat("import {X, Y,} from 'some/module.js';");
1670 verifyFormat("import {X as myLocalX, Y as myLocalY} from 'some/module.js';");
1671 // Ensure Automatic Semicolon Insertion does not break on "as\n".
1672 verifyFormat("import {X as myX} from 'm';", "import {X as\n"
1674 verifyFormat("import * as lib from 'some/module.js';");
1675 verifyFormat("var x = {import: 1};\nx.import = 2;");
1677 verifyFormat("export function fn() {\n"
1680 verifyFormat("export function A() {}\n"
1681 "export default function B() {}\n"
1682 "export function C() {}");
1683 verifyFormat("export default () => {\n"
1687 verifyFormat("export const x = 12;");
1688 verifyFormat("export default class X {}");
1689 verifyFormat("export {X, Y} from 'some/module.js';");
1690 verifyFormat("export {X, Y,} from 'some/module.js';");
1691 verifyFormat("export {SomeVeryLongExport as X, "
1692 "SomeOtherVeryLongExport as Y} from 'some/module.js';");
1693 // export without 'from' is wrapped.
1694 verifyFormat("export let someRatherLongVariableName =\n"
1695 " someSurprisinglyLongVariable + someOtherRatherLongVar;");
1696 // ... but not if from is just an identifier.
1697 verifyFormat("export {\n"
1699 " someSurprisinglyLongVariable as\n"
1702 getGoogleJSStyleWithColumns(20));
1703 verifyFormat("export class C {\n"
1707 verifyFormat("export class X {\n"
1710 verifyFormat("export abstract class X {\n"
1713 verifyFormat("export default class X {\n"
1716 verifyFormat("export default function() {\n return 1;\n}");
1717 verifyFormat("export var x = 12;");
1718 verifyFormat("class C {}\n"
1719 "export function f() {}\n"
1721 verifyFormat("export var x: number = 12;");
1722 verifyFormat("export const y = {\n"
1726 verifyFormat("export enum Foo {\n"
1731 verifyFormat("export default [\n"
1732 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
1733 " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"
1735 verifyFormat("export default [];");
1736 verifyFormat("export default () => {};");
1737 verifyFormat("export interface Foo {\n"
1740 "export class Bar {\n"
1741 " blah(): string {\n"
1742 " return this.blah;\n"
1747 TEST_F(FormatTestJS, ImportWrapping) {
1748 verifyFormat("import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,"
1749 " VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying"
1750 "} from 'some/module.js';");
1751 FormatStyle Style = getGoogleJSStyleWithColumns(80);
1752 Style.JavaScriptWrapImports = true;
1753 verifyFormat("import {\n"
1754 " VeryLongImportsAreAnnoying,\n"
1755 " VeryLongImportsAreAnnoying,\n"
1756 " VeryLongImportsAreAnnoying,\n"
1757 "} from 'some/module.js';",
1759 verifyFormat("import {\n"
1762 "} from 'some/module.js';",
1764 verifyFormat("export {\n"
1767 "} from 'some/module.js';",
1769 Style.ColumnLimit = 40;
1770 // Using this version of verifyFormat because test::messUp hides the issue.
1771 verifyFormat("import {\n"
1774 " 'some/path/longer/than/column/limit/module.js';",
1778 " 'some/path/longer/than/column/limit/module.js' ; ",
1782 TEST_F(FormatTestJS, TemplateStrings) {
1783 // Keeps any whitespace/indentation within the template string.
1784 verifyFormat("var x = `hello\n"
1791 verifyFormat("var x =\n"
1792 " `hello ${world}` >= some();",
1793 getGoogleJSStyleWithColumns(34)); // Barely doesn't fit.
1794 verifyFormat("var x = `hello ${world}` >= some();",
1795 getGoogleJSStyleWithColumns(35)); // Barely fits.
1796 verifyFormat("var x = `hellö ${wörld}` >= söme();",
1797 getGoogleJSStyleWithColumns(35)); // Fits due to UTF-8.
1798 verifyFormat("var x = `hello\n"
1803 " ${world}` >= some();",
1804 getGoogleJSStyleWithColumns(21)); // Barely doesn't fit.
1805 verifyFormat("var x = `hello\n"
1806 " ${world}` >= some();",
1809 " ${world}` >= some();",
1810 getGoogleJSStyleWithColumns(22)); // Barely fits.
1812 verifyFormat("var x =\n"
1814 getGoogleJSStyleWithColumns(11));
1815 verifyFormat("var x =\n `multi\n line`;", "var x = `multi\n line`;",
1816 getGoogleJSStyleWithColumns(13));
1817 verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
1818 " `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`);");
1819 // Repro for an obscure width-miscounting issue with template strings.
1821 "someLongVariable =\n"
1823 "`${logPrefix[11]}/${logPrefix[12]}/${logPrefix[13]}${logPrefix[14]}`;",
1824 "someLongVariable = "
1825 "`${logPrefix[11]}/${logPrefix[12]}/${logPrefix[13]}${logPrefix[14]}`;");
1827 // Make sure template strings get a proper ColumnWidth assigned, even if they
1828 // are first token in line.
1830 "var a = aaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n"
1831 " `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`;");
1833 // Two template strings.
1834 verifyFormat("var x = `hello` == `hello`;");
1836 // Comments in template strings.
1837 verifyFormat("var x = `//a`;\n"
1839 "var x =\n `//a`;\n"
1841 verifyFormat("var x = `/*a`;\n"
1843 "var x =\n `/*a`;\n"
1845 // Unterminated string literals in a template string.
1846 verifyFormat("var x = `'`; // comment with matching quote '\n"
1848 verifyFormat("var x = `\"`; // comment with matching quote \"\n"
1850 verifyFormat("it(`'aaaaaaaaaaaaaaa `, aaaaaaaaa);",
1851 "it(`'aaaaaaaaaaaaaaa `, aaaaaaaaa) ;",
1852 getGoogleJSStyleWithColumns(40));
1853 // Backticks in a comment - not a template string.
1854 verifyFormat("var x = 1 // `/*a`;\n"
1856 "var x =\n 1 // `/*a`;\n"
1858 verifyFormat("/* ` */ var x = 1; /* ` */", "/* ` */ var x\n= 1; /* ` */");
1859 // Comment spans multiple template strings.
1860 verifyFormat("var x = `/*a`;\n"
1862 "var x =\n `/*a`;\n"
1863 "var y =\n ` */ `;");
1864 // Escaped backtick.
1865 verifyFormat("var x = ` \\` a`;\n"
1867 "var x = ` \\` a`;\n"
1870 verifyFormat("var x = ` \\${foo}`;\n");
1872 // The token stream can contain two string_literals in sequence, but that
1873 // doesn't mean that they are implicitly concatenated in JavaScript.
1874 verifyFormat("var f = `aaaa ${a ? 'a' : 'b'}`;");
1876 // Ensure that scopes are appropriately set around evaluated expressions in
1877 // template strings.
1878 verifyFormat("var f = `aaaaaaaaaaaaa:${aaaaaaa.aaaaa} aaaaaaaa\n"
1879 " aaaaaaaaaaaaa:${aaaaaaa.aaaaa} aaaaaaaa`;",
1880 "var f = `aaaaaaaaaaaaa:${aaaaaaa. aaaaa} aaaaaaaa\n"
1881 " aaaaaaaaaaaaa:${ aaaaaaa. aaaaa} aaaaaaaa`;");
1882 verifyFormat("var x = someFunction(`${})`) //\n"
1883 " .oooooooooooooooooon();");
1884 verifyFormat("var x = someFunction(`${aaaa}${\n"
1889 TEST_F(FormatTestJS, TemplateStringMultiLineExpression) {
1890 verifyFormat("var f = `aaaaaaaaaaaaaaaaaa: ${\n"
1893 "var f = `aaaaaaaaaaaaaaaaaa: ${aaaaa + //\n"
1895 verifyFormat("var f = `\n"
1896 " aaaaaaaaaaaaaaaaaa: ${\n"
1900 " aaaaaaaaaaaaaaaaaa: ${ aaaaa + //\n"
1902 verifyFormat("var f = `\n"
1903 " aaaaaaaaaaaaaaaaaa: ${\n"
1908 " aaaaaaaaaaaaaaaaaa: ${someFunction (\n"
1912 // It might be preferable to wrap before "someFunction".
1913 verifyFormat("var f = `\n"
1914 " aaaaaaaaaaaaaaaaaa: ${someFunction({\n"
1919 " aaaaaaaaaaaaaaaaaa: ${someFunction ({\n"
1925 TEST_F(FormatTestJS, TemplateStringASI) {
1926 verifyFormat("var x = `hello${world}`;", "var x = `hello${\n"
1931 TEST_F(FormatTestJS, NestedTemplateStrings) {
1933 "var x = `<ul>${xs.map(x => `<li>${x}</li>`).join('\\n')}</ul>`;");
1934 verifyFormat("var x = `he${({text: 'll'}.text)}o`;");
1936 // Crashed at some point.
1940 TEST_F(FormatTestJS, TaggedTemplateStrings) {
1941 verifyFormat("var x = html`<ul>`;");
1942 verifyFormat("yield `hello`;");
1945 TEST_F(FormatTestJS, CastSyntax) {
1946 verifyFormat("var x = <type>foo;");
1947 verifyFormat("var x = foo as type;");
1948 verifyFormat("let x = (a + b) as\n"
1950 getGoogleJSStyleWithColumns(20));
1951 verifyFormat("foo = <Bar[]>[\n"
1955 verifyFormat("var x = [{x: 1} as type];");
1956 verifyFormat("x = x as [a, b];");
1957 verifyFormat("x = x as {a: string};");
1958 verifyFormat("x = x as (string);");
1959 verifyFormat("x = x! as (string);");
1960 verifyFormat("x = y! in z;");
1961 verifyFormat("var x = something.someFunction() as\n"
1963 getGoogleJSStyleWithColumns(40));
1966 TEST_F(FormatTestJS, TypeArguments) {
1967 verifyFormat("class X<Y> {}");
1968 verifyFormat("new X<Y>();");
1969 verifyFormat("foo<Y>(a);");
1970 verifyFormat("var x: X<Y>[];");
1971 verifyFormat("class C extends D<E> implements F<G>, H<I> {}");
1972 verifyFormat("function f(a: List<any> = null) {}");
1973 verifyFormat("function f(): List<any> {}");
1974 verifyFormat("function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa():\n"
1975 " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {}");
1976 verifyFormat("function aaaaaaaaaa(\n"
1977 " aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaa,\n"
1978 " aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaa):\n"
1979 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {}");
1982 TEST_F(FormatTestJS, UserDefinedTypeGuards) {
1984 "function foo(check: Object):\n"
1985 " check is {foo: string, bar: string, baz: string, foobar: string} {\n"
1986 " return 'bar' in check;\n"
1990 TEST_F(FormatTestJS, OptionalTypes) {
1991 verifyFormat("function x(a?: b, c?, d?) {}");
1992 verifyFormat("class X {\n"
1996 verifyFormat("interface X {\n"
1999 verifyFormat("constructor({aa}: {\n"
2001 " aaaaaaaa?: string,\n"
2002 " aaaaaaaaaaaaaaa?: boolean,\n"
2003 " aaaaaa?: List<string>\n"
2007 TEST_F(FormatTestJS, IndexSignature) {
2008 verifyFormat("var x: {[k: string]: v};");
2011 TEST_F(FormatTestJS, WrapAfterParen) {
2012 verifyFormat("xxxxxxxxxxx(\n"
2014 getGoogleJSStyleWithColumns(20));
2015 verifyFormat("xxxxxxxxxxx(\n"
2018 getGoogleJSStyleWithColumns(20));
2019 verifyFormat("xxxxxxxxxxx(\n"
2020 " aaaaaaaaaaaaaaaaaaaaaaaa,\n"
2024 getGoogleJSStyleWithColumns(40));
2025 verifyFormat("while (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n"
2026 " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n}");
2029 TEST_F(FormatTestJS, JSDocAnnotations) {
2030 verifyFormat("/**\n"
2031 " * @export {this.is.a.long.path.to.a.Type}\n"
2034 " * @export {this.is.a.long.path.to.a.Type}\n"
2036 getGoogleJSStyleWithColumns(20));
2037 verifyFormat("/**\n"
2038 " * @mods {this.is.a.long.path.to.a.Type}\n"
2041 " * @mods {this.is.a.long.path.to.a.Type}\n"
2043 getGoogleJSStyleWithColumns(20));
2044 verifyFormat("/**\n"
2045 " * @param {this.is.a.long.path.to.a.Type}\n"
2048 " * @param {this.is.a.long.path.to.a.Type}\n"
2050 getGoogleJSStyleWithColumns(20));
2051 verifyFormat("/**\n"
2052 " * @see http://very/very/long/url/is/long\n"
2055 " * @see http://very/very/long/url/is/long\n"
2057 getGoogleJSStyleWithColumns(20));
2060 " * @param This is a\n"
2061 " * long comment but\n"
2065 " * @param This is a long comment but no type\n"
2067 getGoogleJSStyleWithColumns(20));
2068 // Don't break @param line, but reindent it and reflow unrelated lines.
2071 " * long long long\n"
2073 " * @param {this.is.a.long.path.to.a.Type} a\n"
2074 " * long long long\n"
2077 " function f(a) {}\n"
2081 " * long long long long\n"
2082 " * @param {this.is.a.long.path.to.a.Type} a\n"
2083 " * long long long long\n"
2086 " function f(a) {}\n"
2088 getGoogleJSStyleWithColumns(20));
2091 TEST_F(FormatTestJS, RequoteStringsSingle) {
2092 verifyFormat("var x = 'foo';", "var x = \"foo\";");
2093 verifyFormat("var x = 'fo\\'o\\'';", "var x = \"fo'o'\";");
2094 verifyFormat("var x = 'fo\\'o\\'';", "var x = \"fo\\'o'\";");
2098 // Code below is 15 chars wide, doesn't fit into the line with the
2100 "var x = \"foo'\";", getGoogleJSStyleWithColumns(15));
2101 // Removes no-longer needed \ escape from ".
2102 verifyFormat("var x = 'fo\"o';", "var x = \"fo\\\"o\";");
2103 // Code below fits into 15 chars *after* removing the \ escape.
2104 verifyFormat("var x = 'fo\"o';", "var x = \"fo\\\"o\";",
2105 getGoogleJSStyleWithColumns(15));
2106 verifyFormat("// clang-format off\n"
2107 "let x = \"double\";\n"
2108 "// clang-format on\n"
2109 "let x = 'single';\n",
2110 "// clang-format off\n"
2111 "let x = \"double\";\n"
2112 "// clang-format on\n"
2113 "let x = \"single\";\n");
2116 TEST_F(FormatTestJS, RequoteAndIndent) {
2117 verifyFormat("let x = someVeryLongFunctionThatGoesOnAndOn(\n"
2118 " 'double quoted string that needs wrapping');",
2119 "let x = someVeryLongFunctionThatGoesOnAndOn("
2120 "\"double quoted string that needs wrapping\");");
2122 verifyFormat("let x =\n"
2126 "let x=\"foo'oo\";\n"
2127 "let x=\"foo'oo\";",
2128 getGoogleJSStyleWithColumns(15));
2131 TEST_F(FormatTestJS, RequoteStringsDouble) {
2132 FormatStyle DoubleQuotes = getGoogleStyle(FormatStyle::LK_JavaScript);
2133 DoubleQuotes.JavaScriptQuotes = FormatStyle::JSQS_Double;
2134 verifyFormat("var x = \"foo\";", DoubleQuotes);
2135 verifyFormat("var x = \"foo\";", "var x = 'foo';", DoubleQuotes);
2136 verifyFormat("var x = \"fo'o\";", "var x = 'fo\\'o';", DoubleQuotes);
2139 TEST_F(FormatTestJS, RequoteStringsLeave) {
2140 FormatStyle LeaveQuotes = getGoogleStyle(FormatStyle::LK_JavaScript);
2141 LeaveQuotes.JavaScriptQuotes = FormatStyle::JSQS_Leave;
2142 verifyFormat("var x = \"foo\";", LeaveQuotes);
2143 verifyFormat("var x = 'foo';", LeaveQuotes);
2146 TEST_F(FormatTestJS, SupportShebangLines) {
2147 verifyFormat("#!/usr/bin/env node\n"
2149 "#!/usr/bin/env node\n"
2150 "var x = hello();");
2153 TEST_F(FormatTestJS, NonNullAssertionOperator) {
2154 verifyFormat("let x = foo!.bar();\n");
2155 verifyFormat("let x = foo ? bar! : baz;\n");
2156 verifyFormat("let x = !foo;\n");
2157 verifyFormat("if (!+a) {\n}");
2158 verifyFormat("let x = foo[0]!;\n");
2159 verifyFormat("let x = (foo)!;\n");
2160 verifyFormat("let x = x(foo!);\n");
2162 "a.aaaaaa(a.a!).then(\n"
2164 getGoogleJSStyleWithColumns(20));
2165 verifyFormat("let x = foo! - 1;\n");
2166 verifyFormat("let x = {foo: 1}!;\n");
2168 "let x = hello.foo()!\n"
2172 getGoogleJSStyleWithColumns(20));
2173 verifyFormat("let x = namespace!;\n");
2174 verifyFormat("return !!x;\n");
2177 TEST_F(FormatTestJS, Conditional) {
2178 verifyFormat("y = x ? 1 : 2;");
2179 verifyFormat("x ? 1 : 2;");
2180 verifyFormat("class Foo {\n"
2181 " field = true ? 1 : 2;\n"
2182 " method(a = true ? 1 : 2) {}\n"
2186 TEST_F(FormatTestJS, ImportComments) {
2187 verifyFormat("import {x} from 'x'; // from some location",
2188 getGoogleJSStyleWithColumns(25));
2189 verifyFormat("// taze: x from 'location'", getGoogleJSStyleWithColumns(10));
2190 verifyFormat("/// <reference path=\"some/location\" />", getGoogleJSStyleWithColumns(10));
2193 TEST_F(FormatTestJS, Exponentiation) {
2194 verifyFormat("squared = x ** 2;");
2195 verifyFormat("squared **= 2;");
2198 TEST_F(FormatTestJS, NestedLiterals) {
2199 FormatStyle FourSpaces = getGoogleJSStyleWithColumns(15);
2200 FourSpaces.IndentWidth = 4;
2201 verifyFormat("var l = [\n"
2206 verifyFormat("var l = [\n"
2211 verifyFormat("someFunction(\n"
2217 verifyFormat("someFunction(\n"
2223 verifyFormat("var o = {\n"
2229 verifyFormat("var o = {\n"
2237 TEST_F(FormatTestJS, BackslashesInComments) {
2238 verifyFormat("// hello \\\n"
2243 verifyFormat("/* ignore \\\n"
2248 " if ( x) foo();\n");
2249 verifyFormat("// st \\ art\\\n"
2259 } // end namespace tooling
2260 } // end namespace clang