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 DEBUG(llvm::errs() << "---\n");
25 DEBUG(llvm::errs() << Code << "\n\n");
26 std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
27 bool IncompleteFormat = false;
28 tooling::Replacements Replaces =
29 reformat(Style, Code, Ranges, "<stdin>", &IncompleteFormat);
30 EXPECT_FALSE(IncompleteFormat);
31 std::string Result = applyAllReplacements(Code, Replaces);
32 EXPECT_NE("", Result);
33 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 std::string result = format(test::messUp(Code), Style);
53 EXPECT_EQ(Code.str(), result) << "Formatted:\n" << result;
57 TEST_F(FormatTestJS, UnderstandsJavaScriptOperators) {
58 verifyFormat("a == = b;");
59 verifyFormat("a != = b;");
61 verifyFormat("a === b;");
62 verifyFormat("aaaaaaa ===\n b;", getGoogleJSStyleWithColumns(10));
63 verifyFormat("a !== b;");
64 verifyFormat("aaaaaaa !==\n b;", getGoogleJSStyleWithColumns(10));
65 verifyFormat("if (a + b + c +\n"
69 getGoogleJSStyleWithColumns(20));
71 verifyFormat("a >> >= b;");
73 verifyFormat("a >>> b;");
74 verifyFormat("aaaaaaa >>>\n b;", getGoogleJSStyleWithColumns(10));
75 verifyFormat("a >>>= b;");
76 verifyFormat("aaaaaaa >>>=\n b;", getGoogleJSStyleWithColumns(10));
77 verifyFormat("if (a + b + c +\n"
81 getGoogleJSStyleWithColumns(20));
82 verifyFormat("var x = aaaaaaaaaa ?\n"
85 getGoogleJSStyleWithColumns(20));
87 verifyFormat("var b = a.map((x) => x + 1);");
88 verifyFormat("return ('aaa') in bbbb;");
90 // ES6 spread operator.
91 verifyFormat("someFunction(...a);");
92 verifyFormat("var x = [1, ...a, 2];");
95 TEST_F(FormatTestJS, UnderstandsAmpAmp) {
96 verifyFormat("e && e.SomeFunction();");
99 TEST_F(FormatTestJS, LiteralOperatorsCanBeKeywords) {
100 verifyFormat("not.and.or.not_eq = 1;");
103 TEST_F(FormatTestJS, ReservedWords) {
104 // JavaScript reserved words (aka keywords) are only illegal when used as
105 // Identifiers, but are legal as IdentifierNames.
106 verifyFormat("x.class.struct = 1;");
107 verifyFormat("x.case = 1;");
108 verifyFormat("x.interface = 1;");
109 verifyFormat("x = {\n"
114 verifyFormat("var struct = 2;");
115 verifyFormat("var union = 2;");
118 TEST_F(FormatTestJS, CppKeywords) {
119 // Make sure we don't mess stuff up because of C++ keywords.
120 verifyFormat("return operator && (aa);");
123 TEST_F(FormatTestJS, ES6DestructuringAssignment) {
124 verifyFormat("var [a, b, c] = [1, 2, 3];");
125 verifyFormat("let [a, b, c] = [1, 2, 3];");
126 verifyFormat("var {a, b} = {a: 1, b: 2};");
127 verifyFormat("let {a, b} = {a: 1, b: 2};");
130 TEST_F(FormatTestJS, ContainerLiterals) {
131 verifyFormat("var x = {y: function(a) { return a; }};");
132 verifyFormat("return {\n"
133 " link: function() {\n"
137 verifyFormat("return {\n"
139 " link: function() {\n"
143 verifyFormat("return {\n"
145 " link: function() {\n"
148 " link: function() {\n"
152 verifyFormat("var stuff = {\n"
153 " // comment for update\n"
155 " // comment for modules\n"
157 " // comment for tasks\n"
160 verifyFormat("return {\n"
165 verifyFormat("var obj = {\n"
166 " fooooooooo: function(x) {\n"
167 " return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
170 // Simple object literal, as opposed to enum style below.
171 verifyFormat("var obj = {a: 123};");
172 // Enum style top level assignment.
173 verifyFormat("X = {\n a: 123\n};");
174 verifyFormat("X.Y = {\n a: 123\n};");
175 // But only on the top level, otherwise its a plain object literal assignment.
176 verifyFormat("function x() {\n"
179 verifyFormat("x = foo && {a: 123};");
181 // Arrow functions in object literals.
182 verifyFormat("var x = {y: (a) => { return a; }};");
183 verifyFormat("var x = {y: (a) => a};");
186 verifyFormat("var x = {[a]: 1, b: 2, [c]: 3};");
187 verifyFormat("var x = {\n"
194 TEST_F(FormatTestJS, MethodsInObjectLiterals) {
195 verifyFormat("var o = {\n"
197 " get value() { // getter\n"
198 " return this.value;\n"
201 verifyFormat("var o = {\n"
203 " set value(val) { // setter\n"
204 " this.value = val;\n"
207 verifyFormat("var o = {\n"
209 " someMethod(val) { // method\n"
210 " doSomething(this.value + val);\n"
213 verifyFormat("var o = {\n"
214 " someMethod(val) { // method\n"
215 " doSomething(this.value + val);\n"
217 " someOtherMethod(val) { // method\n"
218 " doSomething(this.value + val);\n"
223 TEST_F(FormatTestJS, SpacesInContainerLiterals) {
224 verifyFormat("var arr = [1, 2, 3];");
225 verifyFormat("f({a: 1, b: 2, c: 3});");
227 verifyFormat("var object_literal_with_long_name = {\n"
228 " a: 'aaaaaaaaaaaaaaaaaa',\n"
229 " b: 'bbbbbbbbbbbbbbbbbb'\n"
232 verifyFormat("f({a: 1, b: 2, c: 3});",
233 getChromiumStyle(FormatStyle::LK_JavaScript));
234 verifyFormat("f({'a': [{}]});");
237 TEST_F(FormatTestJS, SingleQuoteStrings) {
238 verifyFormat("this.function('', true);");
241 TEST_F(FormatTestJS, GoogScopes) {
242 verifyFormat("goog.scope(function() {\n"
245 "}); // goog.scope");
246 verifyFormat("goog.scope(function() {\n"
253 TEST_F(FormatTestJS, GoogModules) {
254 verifyFormat("goog.module('this.is.really.absurdly.long');",
255 getGoogleJSStyleWithColumns(40));
256 verifyFormat("goog.require('this.is.really.absurdly.long');",
257 getGoogleJSStyleWithColumns(40));
258 verifyFormat("goog.provide('this.is.really.absurdly.long');",
259 getGoogleJSStyleWithColumns(40));
260 verifyFormat("var long = goog.require('this.is.really.absurdly.long');",
261 getGoogleJSStyleWithColumns(40));
262 verifyFormat("goog.setTestOnly('this.is.really.absurdly.long');",
263 getGoogleJSStyleWithColumns(40));
265 // These should be wrapped normally.
267 "var MyLongClassName =\n"
268 " goog.module.get('my.long.module.name.followedBy.MyLongClassName');");
271 TEST_F(FormatTestJS, FormatsFreestandingFunctions) {
272 verifyFormat("function outer1(a, b) {\n"
273 " function inner1(a, b) { return a; }\n"
276 "function outer2(a, b) {\n"
277 " function inner2(a, b) { return a; }\n"
280 verifyFormat("function f() {}");
283 TEST_F(FormatTestJS, ArrayLiterals) {
284 verifyFormat("var aaaaa: List<SomeThing> =\n"
285 " [new SomeThingAAAAAAAAAAAA(), new SomeThingBBBBBBBBB()];");
286 verifyFormat("return [\n"
287 " aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
288 " bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
289 " ccccccccccccccccccccccccccc\n"
291 verifyFormat("var someVariable = SomeFunction([\n"
292 " aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
293 " bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
294 " ccccccccccccccccccccccccccc\n"
296 verifyFormat("var someVariable = SomeFunction([\n"
297 " [aaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbb],\n"
299 getGoogleJSStyleWithColumns(51));
300 verifyFormat("var someVariable = SomeFunction(aaaa, [\n"
301 " aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
302 " bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
303 " ccccccccccccccccccccccccccc\n"
305 verifyFormat("var someVariable = SomeFunction(\n"
308 " aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
309 " bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
310 " ccccccccccccccccccccccccccc\n"
314 verifyFormat("someFunction([], {a: a});");
317 TEST_F(FormatTestJS, ColumnLayoutForArrayLiterals) {
318 verifyFormat("var array = [\n"
319 " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
320 " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
322 verifyFormat("var array = someFunction([\n"
323 " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
324 " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
328 TEST_F(FormatTestJS, FunctionLiterals) {
329 verifyFormat("doFoo(function() {});");
330 verifyFormat("doFoo(function() { return 1; });");
331 verifyFormat("var func = function() {\n"
334 verifyFormat("var func = //\n"
338 verifyFormat("return {\n"
340 " setAttribute: function(key, val) { this[key] = val; },\n"
341 " getAttribute: function(key) { return this[key]; },\n"
342 " style: {direction: ''}\n"
345 verifyFormat("abc = xyz ? function() {\n"
351 verifyFormat("var closure = goog.bind(\n"
352 " function() { // comment\n"
356 " this, arg1IsReallyLongAndNeeedsLineBreaks,\n"
357 " arg3IsReallyLongAndNeeedsLineBreaks);");
358 verifyFormat("var closure = goog.bind(function() { // comment\n"
362 verifyFormat("return {\n"
365 " return function() {\n"
371 " var someVariable = function(x) {\n"
372 " return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
375 verifyFormat("someLooooooooongFunction(\n"
376 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
377 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
378 " function(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n"
382 verifyFormat("f({a: function() { return 1; }});",
383 getGoogleJSStyleWithColumns(33));
385 " a: function() { return 1; }\n"
387 getGoogleJSStyleWithColumns(32));
389 verifyFormat("return {\n"
390 " a: function SomeFunction() {\n"
395 verifyFormat("this.someObject.doSomething(aaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
396 " .then(goog.bind(function(aaaaaaaaaaa) {\n"
399 " }, this), aaaaaaaaaaaaaaaaa);");
401 verifyFormat("someFunction(goog.bind(function() {\n"
404 "}, this), goog.bind(function() {\n"
409 // FIXME: This is bad, we should be wrapping before "function() {".
410 verifyFormat("someFunction(function() {\n"
411 " doSomething(); // break\n"
413 " .doSomethingElse(\n"
418 TEST_F(FormatTestJS, InliningFunctionLiterals) {
419 FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
420 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
421 verifyFormat("var func = function() {\n"
425 verifyFormat("var func = doSomething(function() { return 1; });", Style);
426 verifyFormat("var outer = function() {\n"
427 " var inner = function() { return 1; }\n"
430 verifyFormat("function outer1(a, b) {\n"
431 " function inner1(a, b) { return a; }\n"
435 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
436 verifyFormat("var func = function() { return 1; };", Style);
437 verifyFormat("var func = doSomething(function() { return 1; });", Style);
439 "var outer = function() { var inner = function() { return 1; } };",
441 verifyFormat("function outer1(a, b) {\n"
442 " function inner1(a, b) { return a; }\n"
446 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
447 verifyFormat("var func = function() {\n"
451 verifyFormat("var func = doSomething(function() {\n"
455 verifyFormat("var outer = function() {\n"
456 " var inner = function() {\n"
461 verifyFormat("function outer1(a, b) {\n"
462 " function inner1(a, b) {\n"
468 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
469 verifyFormat("var func = function() {\n"
475 TEST_F(FormatTestJS, MultipleFunctionLiterals) {
476 verifyFormat("promise.then(\n"
477 " function success() {\n"
481 " function error() {\n"
486 verifyFormat("promise.then(\n"
487 " function success() {\n"
492 " function error() {\n"
496 verifyFormat("promise.then(\n"
498 " function success() {\n"
502 " function error() {\n"
507 verifyFormat("getSomeLongPromise()\n"
508 " .then(function(value) { body(); })\n"
509 " .thenCatch(function(error) {\n"
513 verifyFormat("getSomeLongPromise()\n"
514 " .then(function(value) {\n"
518 " .thenCatch(function(error) {\n"
523 verifyFormat("getSomeLongPromise()\n"
524 " .then(function(value) { body(); })\n"
525 " .thenCatch(function(error) { body(); });");
528 TEST_F(FormatTestJS, ArrowFunctions) {
529 verifyFormat("var x = (a) => {\n"
532 verifyFormat("var x = (a) => {\n"
533 " function y() { return 42; }\n"
536 verifyFormat("var x = (a: type): {some: type} => {\n"
539 verifyFormat("var x = (a) => a;");
540 verifyFormat("return () => [];");
541 verifyFormat("var aaaaaaaaaaaaaaaaaaaa = {\n"
542 " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n"
543 " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
544 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) =>\n"
545 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
547 verifyFormat("var a = a.aaaaaaa(\n"
548 " (a: a) => aaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) &&\n"
549 " aaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
550 verifyFormat("var a = a.aaaaaaa(\n"
551 " (a: a) => aaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) ?\n"
552 " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb) :\n"
553 " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
555 // FIXME: This is bad, we should be wrapping before "() => {".
556 verifyFormat("someFunction(() => {\n"
557 " doSomething(); // break\n"
559 " .doSomethingElse(\n"
564 TEST_F(FormatTestJS, ReturnStatements) {
565 verifyFormat("function() {\n"
566 " return [hello, world];\n"
570 TEST_F(FormatTestJS, ForLoops) {
571 verifyFormat("for (var i in [2, 3]) {\n"
575 TEST_F(FormatTestJS, AutomaticSemicolonInsertion) {
576 // The following statements must not wrap, as otherwise the program meaning
577 // would change due to automatic semicolon insertion.
578 // See http://www.ecma-international.org/ecma-262/5.1/#sec-7.9.1.
579 verifyFormat("return aaaaa;", getGoogleJSStyleWithColumns(10));
580 verifyFormat("continue aaaaa;", getGoogleJSStyleWithColumns(10));
581 verifyFormat("break aaaaa;", getGoogleJSStyleWithColumns(10));
582 verifyFormat("throw aaaaa;", getGoogleJSStyleWithColumns(10));
583 verifyFormat("aaaaaaaaa++;", getGoogleJSStyleWithColumns(10));
584 verifyFormat("aaaaaaaaa--;", getGoogleJSStyleWithColumns(10));
587 TEST_F(FormatTestJS, ClosureStyleCasts) {
588 verifyFormat("var x = /** @type {foo} */ (bar);");
591 TEST_F(FormatTestJS, TryCatch) {
592 verifyFormat("try {\n"
600 // But, of course, "catch" is a perfectly fine function name in JavaScript.
601 verifyFormat("someObject.catch();");
602 verifyFormat("someObject.new();");
603 verifyFormat("someObject.delete();");
606 TEST_F(FormatTestJS, StringLiteralConcatenation) {
607 verifyFormat("var literal = 'hello ' +\n"
611 TEST_F(FormatTestJS, RegexLiteralClassification) {
613 verifyFormat("var regex = /abc/;");
614 verifyFormat("f(/abc/);");
615 verifyFormat("f(abc, /abc/);");
616 verifyFormat("some_map[/abc/];");
617 verifyFormat("var x = a ? /abc/ : /abc/;");
618 verifyFormat("for (var i = 0; /abc/.test(s[i]); i++) {\n}");
619 verifyFormat("var x = !/abc/.test(y);");
620 verifyFormat("var x = a && /abc/.test(y);");
621 verifyFormat("var x = a || /abc/.test(y);");
622 verifyFormat("var x = a + /abc/.search(y);");
623 verifyFormat("/abc/.search(y);");
624 verifyFormat("var regexs = {/abc/, /abc/};");
625 verifyFormat("return /abc/;");
627 // Not regex literals.
628 verifyFormat("var a = a / 2 + b / 3;");
629 verifyFormat("var a = a++ / 2;");
630 // Prefix unary can operate on regex literals, not that it makes sense.
631 verifyFormat("var a = ++/a/;");
633 // This is a known issue, regular expressions are incorrectly detected if
634 // directly following a closing parenthesis.
635 verifyFormat("if (foo) / bar /.exec(baz);");
638 TEST_F(FormatTestJS, RegexLiteralSpecialCharacters) {
639 verifyFormat("var regex = /=/;");
640 verifyFormat("var regex = /a*/;");
641 verifyFormat("var regex = /a+/;");
642 verifyFormat("var regex = /a?/;");
643 verifyFormat("var regex = /.a./;");
644 verifyFormat("var regex = /a\\*/;");
645 verifyFormat("var regex = /^a$/;");
646 verifyFormat("var regex = /\\/a/;");
647 verifyFormat("var regex = /(?:x)/;");
648 verifyFormat("var regex = /x(?=y)/;");
649 verifyFormat("var regex = /x(?!y)/;");
650 verifyFormat("var regex = /x|y/;");
651 verifyFormat("var regex = /a{2}/;");
652 verifyFormat("var regex = /a{1,3}/;");
654 verifyFormat("var regex = /[abc]/;");
655 verifyFormat("var regex = /[^abc]/;");
656 verifyFormat("var regex = /[\\b]/;");
657 verifyFormat("var regex = /[/]/;");
658 verifyFormat("var regex = /[\\/]/;");
659 verifyFormat("var regex = /\\[/;");
660 verifyFormat("var regex = /\\\\[/]/;");
661 verifyFormat("var regex = /}[\"]/;");
662 verifyFormat("var regex = /}[/\"]/;");
663 verifyFormat("var regex = /}[\"/]/;");
665 verifyFormat("var regex = /\\b/;");
666 verifyFormat("var regex = /\\B/;");
667 verifyFormat("var regex = /\\d/;");
668 verifyFormat("var regex = /\\D/;");
669 verifyFormat("var regex = /\\f/;");
670 verifyFormat("var regex = /\\n/;");
671 verifyFormat("var regex = /\\r/;");
672 verifyFormat("var regex = /\\s/;");
673 verifyFormat("var regex = /\\S/;");
674 verifyFormat("var regex = /\\t/;");
675 verifyFormat("var regex = /\\v/;");
676 verifyFormat("var regex = /\\w/;");
677 verifyFormat("var regex = /\\W/;");
678 verifyFormat("var regex = /a(a)\\1/;");
679 verifyFormat("var regex = /\\0/;");
680 verifyFormat("var regex = /\\\\/g;");
681 verifyFormat("var regex = /\\a\\\\/g;");
682 verifyFormat("var regex = /\a\\//g;");
683 verifyFormat("var regex = /a\\//;\n"
685 EXPECT_EQ("var regex = /'/g;", format("var regex = /'/g ;"));
686 EXPECT_EQ("var regex = /'/g; //'", format("var regex = /'/g ; //'"));
687 EXPECT_EQ("var regex = /\\/*/;\n"
689 format("var regex = /\\/*/;\n"
691 EXPECT_EQ("var x = /a\\//;", format("var x = /a\\// \n;"));
692 verifyFormat("var regex = /\"/;", getGoogleJSStyleWithColumns(16));
693 verifyFormat("var regex =\n"
695 getGoogleJSStyleWithColumns(15));
696 verifyFormat("var regex = //\n"
698 verifyFormat("var regexs = [\n"
704 TEST_F(FormatTestJS, RegexLiteralModifiers) {
705 verifyFormat("var regex = /abc/g;");
706 verifyFormat("var regex = /abc/i;");
707 verifyFormat("var regex = /abc/m;");
708 verifyFormat("var regex = /abc/y;");
711 TEST_F(FormatTestJS, RegexLiteralLength) {
712 verifyFormat("var regex = /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
713 getGoogleJSStyleWithColumns(60));
714 verifyFormat("var regex =\n"
715 " /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
716 getGoogleJSStyleWithColumns(60));
717 verifyFormat("var regex = /\\xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
718 getGoogleJSStyleWithColumns(50));
721 TEST_F(FormatTestJS, RegexLiteralExamples) {
722 verifyFormat("var regex = search.match(/(?:\?|&)times=([^?&]+)/i);");
725 TEST_F(FormatTestJS, TypeAnnotations) {
726 verifyFormat("var x: string;");
727 verifyFormat("function x(): string {\n return 'x';\n}");
728 verifyFormat("function x(): {x: string} {\n return {x: 'x'};\n}");
729 verifyFormat("function x(y: string): string {\n return 'x';\n}");
730 verifyFormat("for (var y: string in x) {\n x();\n}");
731 verifyFormat("((a: string, b: number): string => a + b);");
732 verifyFormat("var x: (y: number) => string;");
733 verifyFormat("var x: P<string, (a: number) => string>;");
734 verifyFormat("var x = {y: function(): z { return 1; }};");
735 verifyFormat("var x = {y: function(): {a: number} { return 1; }};");
738 TEST_F(FormatTestJS, ClassDeclarations) {
739 verifyFormat("class C {\n x: string = 12;\n}");
740 verifyFormat("class C {\n x(): string => 12;\n}");
741 verifyFormat("class C {\n ['x' + 2]: string = 12;\n}");
742 verifyFormat("class C {\n private x: string = 12;\n}");
743 verifyFormat("class C {\n private static x: string = 12;\n}");
744 verifyFormat("class C {\n static x(): string { return 'asd'; }\n}");
745 verifyFormat("class C extends P implements I {}");
746 verifyFormat("class C extends p.P implements i.I {}");
747 verifyFormat("class Test {\n"
748 " aaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaaa):\n"
749 " aaaaaaaaaaaaaaaaaaaaaa {}\n"
752 // ':' is not a type declaration here.
753 verifyFormat("class X {\n"
762 TEST_F(FormatTestJS, InterfaceDeclarations) {
763 verifyFormat("interface I {\n"
768 // Ensure that state is reset after parsing the interface.
769 verifyFormat("interface a {}\n"
770 "export function b() {}\n"
773 // Arrays of object type literals.
774 verifyFormat("interface I {\n"
779 TEST_F(FormatTestJS, EnumDeclarations) {
780 verifyFormat("enum Foo {\n"
784 verifyFormat("export /* somecomment*/ enum Foo {\n"
788 verifyFormat("enum Foo {\n"
789 " A = 1, // comment\n"
795 TEST_F(FormatTestJS, MetadataAnnotations) {
796 verifyFormat("@A\nclass C {\n}");
797 verifyFormat("@A({arg: 'value'})\nclass C {\n}");
798 verifyFormat("@A\n@B\nclass C {\n}");
799 verifyFormat("class C {\n @A x: string;\n}");
800 verifyFormat("class C {\n"
802 " private x(): string {\n"
806 verifyFormat("class X {}\n"
810 TEST_F(FormatTestJS, Modules) {
811 verifyFormat("import SomeThing from 'some/module.js';");
812 verifyFormat("import {X, Y} from 'some/module.js';");
813 verifyFormat("import {\n"
814 " VeryLongImportsAreAnnoying,\n"
815 " VeryLongImportsAreAnnoying,\n"
816 " VeryLongImportsAreAnnoying,\n"
817 " VeryLongImportsAreAnnoying\n"
818 "} from 'some/module.js';");
819 verifyFormat("import {\n"
822 "} from 'some/module.js';");
823 verifyFormat("import {\n"
826 "} from 'some/long/module.js';",
827 getGoogleJSStyleWithColumns(20));
828 verifyFormat("import {X as myLocalX, Y as myLocalY} from 'some/module.js';");
829 verifyFormat("import * as lib from 'some/module.js';");
830 verifyFormat("var x = {import: 1};\nx.import = 2;");
832 verifyFormat("export function fn() {\n"
835 verifyFormat("export function A() {}\n"
836 "export default function B() {}\n"
837 "export function C() {}");
838 verifyFormat("export const x = 12;");
839 verifyFormat("export default class X {}");
840 verifyFormat("export {X, Y} from 'some/module.js';");
841 verifyFormat("export {\n"
844 "} from 'some/module.js';");
845 verifyFormat("export class C {\n"
849 verifyFormat("export class X { y: number; }");
850 verifyFormat("export default class X { y: number }");
851 verifyFormat("export default function() {\n return 1;\n}");
852 verifyFormat("export var x = 12;");
853 verifyFormat("class C {}\n"
854 "export function f() {}\n"
856 verifyFormat("export var x: number = 12;");
857 verifyFormat("export const y = {\n"
861 verifyFormat("export enum Foo {\n"
868 TEST_F(FormatTestJS, TemplateStrings) {
869 // Keeps any whitespace/indentation within the template string.
870 EXPECT_EQ("var x = `hello\n"
873 format("var x = `hello\n"
877 verifyFormat("var x =\n"
878 " `hello ${world}` >= some();",
879 getGoogleJSStyleWithColumns(34)); // Barely doesn't fit.
880 verifyFormat("var x = `hello ${world}` >= some();",
881 getGoogleJSStyleWithColumns(35)); // Barely fits.
882 EXPECT_EQ("var x = `hello\n"
887 " ${world}` >= some();",
888 getGoogleJSStyleWithColumns(21))); // Barely doesn't fit.
889 EXPECT_EQ("var x = `hello\n"
890 " ${world}` >= some();",
893 " ${world}` >= some();",
894 getGoogleJSStyleWithColumns(22))); // Barely fits.
896 verifyFormat("var x =\n"
898 getGoogleJSStyleWithColumns(11));
900 "var x =\n `multi\n line`;",
901 format("var x = `multi\n line`;", getGoogleJSStyleWithColumns(13)));
902 verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
903 " `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`);");
905 // Make sure template strings get a proper ColumnWidth assigned, even if they
906 // are first token in line.
908 "var a = aaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n"
909 " `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`;");
911 // Two template strings.
912 verifyFormat("var x = `hello` == `hello`;");
914 // Comments in template strings.
915 EXPECT_EQ("var x = `//a`;\n"
917 format("var x =\n `//a`;\n"
919 EXPECT_EQ("var x = `/*a`;\n"
921 format("var x =\n `/*a`;\n"
923 // Unterminated string literals in a template string.
924 verifyFormat("var x = `'`; // comment with matching quote '\n"
926 verifyFormat("var x = `\"`; // comment with matching quote \"\n"
928 // Backticks in a comment - not a template string.
929 EXPECT_EQ("var x = 1 // `/*a`;\n"
931 format("var x =\n 1 // `/*a`;\n"
933 EXPECT_EQ("/* ` */ var x = 1; /* ` */",
934 format("/* ` */ var x\n= 1; /* ` */"));
935 // Comment spans multiple template strings.
936 EXPECT_EQ("var x = `/*a`;\n"
938 format("var x =\n `/*a`;\n"
939 "var y =\n ` */ `;"));
941 EXPECT_EQ("var x = ` \\` a`;\n"
943 format("var x = ` \\` a`;\n"
947 TEST_F(FormatTestJS, CastSyntax) { verifyFormat("var x = <type>foo;"); }
949 TEST_F(FormatTestJS, TypeArguments) {
950 verifyFormat("class X<Y> {}");
951 verifyFormat("new X<Y>();");
952 verifyFormat("foo<Y>(a);");
953 verifyFormat("var x: X<Y>[];");
954 verifyFormat("class C extends D<E> implements F<G>, H<I> {}");
955 verifyFormat("function f(a: List<any> = null) {}");
956 verifyFormat("function f(): List<any> {}");
957 verifyFormat("function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa():\n"
958 " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {}");
959 verifyFormat("function aaaaaaaaaa(\n"
960 " aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaa,\n"
961 " aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaa):\n"
962 " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {}");
965 TEST_F(FormatTestJS, UserDefinedTypeGuards) {
967 "function foo(check: Object):\n"
968 " check is {foo: string, bar: string, baz: string, foobar: string} {\n"
969 " return 'bar' in check;\n"
973 TEST_F(FormatTestJS, OptionalTypes) {
974 verifyFormat("function x(a?: b, c?, d?) {}");
975 verifyFormat("class X {\n"
979 verifyFormat("interface X {\n"
982 verifyFormat("x ? 1 : 2;");
983 verifyFormat("constructor({aa}: {\n"
985 " aaaaaaaa?: string,\n"
986 " aaaaaaaaaaaaaaa?: boolean,\n"
987 " aaaaaa?: List<string>\n"
991 TEST_F(FormatTestJS, IndexSignature) {
992 verifyFormat("var x: {[k: string]: v};");
995 TEST_F(FormatTestJS, WrapAfterParen) {
996 verifyFormat("xxxxxxxxxxx(\n"
998 getGoogleJSStyleWithColumns(20));
999 verifyFormat("xxxxxxxxxxx(\n"
1002 getGoogleJSStyleWithColumns(20));
1003 verifyFormat("xxxxxxxxxxx(\n"
1004 " aaaaaaaaaaaaaaaaaaaaaaaa,\n"
1008 getGoogleJSStyleWithColumns(40));
1009 verifyFormat("while (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n"
1010 " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n}");
1013 } // end namespace tooling
1014 } // end namespace clang