1a48a12cfSAlexander Kornienko //===- unittest/Format/FormatTestJS.cpp - Formatting unit tests for JS ----===//
2a48a12cfSAlexander Kornienko //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a48a12cfSAlexander Kornienko //
7a48a12cfSAlexander Kornienko //===----------------------------------------------------------------------===//
8a48a12cfSAlexander Kornienko 
9a48a12cfSAlexander Kornienko #include "FormatTestUtils.h"
10a48a12cfSAlexander Kornienko #include "clang/Format/Format.h"
11a48a12cfSAlexander Kornienko #include "llvm/Support/Debug.h"
12a48a12cfSAlexander Kornienko #include "gtest/gtest.h"
13a48a12cfSAlexander Kornienko 
1410346667SChandler Carruth #define DEBUG_TYPE "format-test"
1510346667SChandler Carruth 
16a48a12cfSAlexander Kornienko namespace clang {
17a48a12cfSAlexander Kornienko namespace format {
18a48a12cfSAlexander Kornienko 
19a48a12cfSAlexander Kornienko class FormatTestJS : public ::testing::Test {
20a48a12cfSAlexander Kornienko protected:
format(llvm::StringRef Code,unsigned Offset,unsigned Length,const FormatStyle & Style)21a48a12cfSAlexander Kornienko   static std::string format(llvm::StringRef Code, unsigned Offset,
22a48a12cfSAlexander Kornienko                             unsigned Length, const FormatStyle &Style) {
233538b39eSNicola Zaghen     LLVM_DEBUG(llvm::errs() << "---\n");
243538b39eSNicola Zaghen     LLVM_DEBUG(llvm::errs() << Code << "\n\n");
25a48a12cfSAlexander Kornienko     std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
26bcda54b6SKrasimir Georgiev     FormattingAttemptStatus Status;
2756691b8cSDaniel Jasper     tooling::Replacements Replaces =
28bcda54b6SKrasimir Georgiev         reformat(Style, Code, Ranges, "<stdin>", &Status);
29bcda54b6SKrasimir Georgiev     EXPECT_TRUE(Status.FormatComplete);
304f8d9943SEric Liu     auto Result = applyAllReplacements(Code, Replaces);
314f8d9943SEric Liu     EXPECT_TRUE(static_cast<bool>(Result));
323538b39eSNicola Zaghen     LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
334f8d9943SEric Liu     return *Result;
34a48a12cfSAlexander Kornienko   }
35a48a12cfSAlexander Kornienko 
format(llvm::StringRef Code,const FormatStyle & Style=getGoogleStyle (FormatStyle::LK_JavaScript))36069e5f48SDaniel Jasper   static std::string format(
37069e5f48SDaniel Jasper       llvm::StringRef Code,
38069e5f48SDaniel Jasper       const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) {
39a48a12cfSAlexander Kornienko     return format(Code, 0, Code.size(), Style);
40a48a12cfSAlexander Kornienko   }
41a48a12cfSAlexander Kornienko 
getGoogleJSStyleWithColumns(unsigned ColumnLimit)42c1637f16SAlexander Kornienko   static FormatStyle getGoogleJSStyleWithColumns(unsigned ColumnLimit) {
43514ecc8cSNico Weber     FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
44a48a12cfSAlexander Kornienko     Style.ColumnLimit = ColumnLimit;
45a48a12cfSAlexander Kornienko     return Style;
46a48a12cfSAlexander Kornienko   }
47a48a12cfSAlexander Kornienko 
verifyFormat(llvm::StringRef Code,const FormatStyle & Style=getGoogleStyle (FormatStyle::LK_JavaScript))48514ecc8cSNico Weber   static void verifyFormat(
49514ecc8cSNico Weber       llvm::StringRef Code,
50514ecc8cSNico Weber       const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) {
51ece7e95fSmydeveloperday     EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable";
521dcbbcfcSDaniel Jasper     std::string Result = format(test::messUp(Code), Style);
531dcbbcfcSDaniel Jasper     EXPECT_EQ(Code.str(), Result) << "Formatted:\n" << Result;
541dcbbcfcSDaniel Jasper   }
551dcbbcfcSDaniel Jasper 
verifyFormat(llvm::StringRef Expected,llvm::StringRef Code,const FormatStyle & Style=getGoogleStyle (FormatStyle::LK_JavaScript))561dcbbcfcSDaniel Jasper   static void verifyFormat(
57ece7e95fSmydeveloperday       llvm::StringRef Expected, llvm::StringRef Code,
581dcbbcfcSDaniel Jasper       const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) {
59c9a918c5SMark Zeren     EXPECT_EQ(Expected.str(), format(Expected, Style))
60c9a918c5SMark Zeren         << "Expected code is not stable";
611dcbbcfcSDaniel Jasper     std::string Result = format(Code, Style);
621dcbbcfcSDaniel Jasper     EXPECT_EQ(Expected.str(), Result) << "Formatted:\n" << Result;
63a48a12cfSAlexander Kornienko   }
64a48a12cfSAlexander Kornienko };
65a48a12cfSAlexander Kornienko 
TEST_F(FormatTestJS,BlockComments)66e77f19c0SDaniel Jasper TEST_F(FormatTestJS, BlockComments) {
67e77f19c0SDaniel Jasper   verifyFormat("/* aaaaaaaaaaaaa */ aaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
68e77f19c0SDaniel Jasper                "    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
6935599fdfSKrasimir Georgiev   // Breaks after a single line block comment.
7035599fdfSKrasimir Georgiev   EXPECT_EQ("aaaaa = bbbb.ccccccccccccccc(\n"
7135599fdfSKrasimir Georgiev             "    /** @type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala} */\n"
7235599fdfSKrasimir Georgiev             "    mediaMessage);",
7335599fdfSKrasimir Georgiev             format("aaaaa = bbbb.ccccccccccccccc(\n"
7435599fdfSKrasimir Georgiev                    "    /** "
7535599fdfSKrasimir Georgiev                    "@type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala} */ "
7635599fdfSKrasimir Georgiev                    "mediaMessage);",
7735599fdfSKrasimir Georgiev                    getGoogleJSStyleWithColumns(70)));
7835599fdfSKrasimir Georgiev   // Breaks after a multiline block comment.
7935599fdfSKrasimir Georgiev   EXPECT_EQ(
8035599fdfSKrasimir Georgiev       "aaaaa = bbbb.ccccccccccccccc(\n"
8135599fdfSKrasimir Georgiev       "    /**\n"
8235599fdfSKrasimir Georgiev       "     * @type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala}\n"
8335599fdfSKrasimir Georgiev       "     */\n"
8435599fdfSKrasimir Georgiev       "    mediaMessage);",
8535599fdfSKrasimir Georgiev       format("aaaaa = bbbb.ccccccccccccccc(\n"
8635599fdfSKrasimir Georgiev              "    /**\n"
8735599fdfSKrasimir Georgiev              "     * @type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala}\n"
8835599fdfSKrasimir Georgiev              "     */ mediaMessage);",
8935599fdfSKrasimir Georgiev              getGoogleJSStyleWithColumns(70)));
90e77f19c0SDaniel Jasper }
91e77f19c0SDaniel Jasper 
TEST_F(FormatTestJS,JSDocComments)9222d7e6b0SKrasimir Georgiev TEST_F(FormatTestJS, JSDocComments) {
9322d7e6b0SKrasimir Georgiev   // Break the first line of a multiline jsdoc comment.
9422d7e6b0SKrasimir Georgiev   EXPECT_EQ("/**\n"
9522d7e6b0SKrasimir Georgiev             " * jsdoc line 1\n"
9622d7e6b0SKrasimir Georgiev             " * jsdoc line 2\n"
9722d7e6b0SKrasimir Georgiev             " */",
9822d7e6b0SKrasimir Georgiev             format("/** jsdoc line 1\n"
9922d7e6b0SKrasimir Georgiev                    " * jsdoc line 2\n"
10022d7e6b0SKrasimir Georgiev                    " */",
10122d7e6b0SKrasimir Georgiev                    getGoogleJSStyleWithColumns(20)));
10222d7e6b0SKrasimir Georgiev   // Both break after '/**' and break the line itself.
10322d7e6b0SKrasimir Georgiev   EXPECT_EQ("/**\n"
10422d7e6b0SKrasimir Georgiev             " * jsdoc line long\n"
10522d7e6b0SKrasimir Georgiev             " * long jsdoc line 2\n"
10622d7e6b0SKrasimir Georgiev             " */",
10722d7e6b0SKrasimir Georgiev             format("/** jsdoc line long long\n"
10822d7e6b0SKrasimir Georgiev                    " * jsdoc line 2\n"
10922d7e6b0SKrasimir Georgiev                    " */",
11022d7e6b0SKrasimir Georgiev                    getGoogleJSStyleWithColumns(20)));
11122d7e6b0SKrasimir Georgiev   // Break a short first line if the ending '*/' is on a newline.
11222d7e6b0SKrasimir Georgiev   EXPECT_EQ("/**\n"
11322d7e6b0SKrasimir Georgiev             " * jsdoc line 1\n"
11422d7e6b0SKrasimir Georgiev             " */",
11522d7e6b0SKrasimir Georgiev             format("/** jsdoc line 1\n"
116ece7e95fSmydeveloperday                    " */",
117ece7e95fSmydeveloperday                    getGoogleJSStyleWithColumns(20)));
11822d7e6b0SKrasimir Georgiev   // Don't break the first line of a short single line jsdoc comment.
11922d7e6b0SKrasimir Georgiev   EXPECT_EQ("/** jsdoc line 1 */",
12022d7e6b0SKrasimir Georgiev             format("/** jsdoc line 1 */", getGoogleJSStyleWithColumns(20)));
12122d7e6b0SKrasimir Georgiev   // Don't break the first line of a single line jsdoc comment if it just fits
12222d7e6b0SKrasimir Georgiev   // the column limit.
12322d7e6b0SKrasimir Georgiev   EXPECT_EQ("/** jsdoc line 12 */",
12422d7e6b0SKrasimir Georgiev             format("/** jsdoc line 12 */", getGoogleJSStyleWithColumns(20)));
12522d7e6b0SKrasimir Georgiev   // Don't break after '/**' and before '*/' if there is no space between
12622d7e6b0SKrasimir Georgiev   // '/**' and the content.
12722d7e6b0SKrasimir Georgiev   EXPECT_EQ(
12822d7e6b0SKrasimir Georgiev       "/*** nonjsdoc long\n"
12922d7e6b0SKrasimir Georgiev       " * line */",
13022d7e6b0SKrasimir Georgiev       format("/*** nonjsdoc long line */", getGoogleJSStyleWithColumns(20)));
13122d7e6b0SKrasimir Georgiev   EXPECT_EQ(
13222d7e6b0SKrasimir Georgiev       "/**strange long long\n"
13322d7e6b0SKrasimir Georgiev       " * line */",
13422d7e6b0SKrasimir Georgiev       format("/**strange long long line */", getGoogleJSStyleWithColumns(20)));
13522d7e6b0SKrasimir Georgiev   // Break the first line of a single line jsdoc comment if it just exceeds the
13622d7e6b0SKrasimir Georgiev   // column limit.
13722d7e6b0SKrasimir Georgiev   EXPECT_EQ("/**\n"
13822d7e6b0SKrasimir Georgiev             " * jsdoc line 123\n"
13922d7e6b0SKrasimir Georgiev             " */",
14022d7e6b0SKrasimir Georgiev             format("/** jsdoc line 123 */", getGoogleJSStyleWithColumns(20)));
14122d7e6b0SKrasimir Georgiev   // Break also if the leading indent of the first line is more than 1 column.
14222d7e6b0SKrasimir Georgiev   EXPECT_EQ("/**\n"
14322d7e6b0SKrasimir Georgiev             " * jsdoc line 123\n"
14422d7e6b0SKrasimir Georgiev             " */",
14522d7e6b0SKrasimir Georgiev             format("/**  jsdoc line 123 */", getGoogleJSStyleWithColumns(20)));
14622d7e6b0SKrasimir Georgiev   // Break also if the leading indent of the first line is more than 1 column.
14722d7e6b0SKrasimir Georgiev   EXPECT_EQ("/**\n"
14822d7e6b0SKrasimir Georgiev             " * jsdoc line 123\n"
14922d7e6b0SKrasimir Georgiev             " */",
15022d7e6b0SKrasimir Georgiev             format("/**   jsdoc line 123 */", getGoogleJSStyleWithColumns(20)));
15122d7e6b0SKrasimir Georgiev   // Break after the content of the last line.
15222d7e6b0SKrasimir Georgiev   EXPECT_EQ("/**\n"
15322d7e6b0SKrasimir Georgiev             " * line 1\n"
15422d7e6b0SKrasimir Georgiev             " * line 2\n"
15522d7e6b0SKrasimir Georgiev             " */",
15622d7e6b0SKrasimir Georgiev             format("/**\n"
15722d7e6b0SKrasimir Georgiev                    " * line 1\n"
15822d7e6b0SKrasimir Georgiev                    " * line 2 */",
15922d7e6b0SKrasimir Georgiev                    getGoogleJSStyleWithColumns(20)));
16022d7e6b0SKrasimir Georgiev   // Break both the content and after the content of the last line.
16122d7e6b0SKrasimir Georgiev   EXPECT_EQ("/**\n"
16222d7e6b0SKrasimir Georgiev             " * line 1\n"
16322d7e6b0SKrasimir Georgiev             " * line long long\n"
16422d7e6b0SKrasimir Georgiev             " * long\n"
16522d7e6b0SKrasimir Georgiev             " */",
16622d7e6b0SKrasimir Georgiev             format("/**\n"
16722d7e6b0SKrasimir Georgiev                    " * line 1\n"
16822d7e6b0SKrasimir Georgiev                    " * line long long long */",
16922d7e6b0SKrasimir Georgiev                    getGoogleJSStyleWithColumns(20)));
17022d7e6b0SKrasimir Georgiev 
17122d7e6b0SKrasimir Georgiev   // The comment block gets indented.
17222d7e6b0SKrasimir Georgiev   EXPECT_EQ("function f() {\n"
17322d7e6b0SKrasimir Georgiev             "  /**\n"
17422d7e6b0SKrasimir Georgiev             "   * comment about\n"
17522d7e6b0SKrasimir Georgiev             "   * x\n"
17622d7e6b0SKrasimir Georgiev             "   */\n"
17722d7e6b0SKrasimir Georgiev             "  var x = 1;\n"
17822d7e6b0SKrasimir Georgiev             "}",
17922d7e6b0SKrasimir Georgiev             format("function f() {\n"
18022d7e6b0SKrasimir Georgiev                    "/** comment about x */\n"
18122d7e6b0SKrasimir Georgiev                    "var x = 1;\n"
18222d7e6b0SKrasimir Georgiev                    "}",
18322d7e6b0SKrasimir Georgiev                    getGoogleJSStyleWithColumns(20)));
1843b86534aSKrasimir Georgiev 
1853b86534aSKrasimir Georgiev   // Don't break the first line of a single line short jsdoc comment pragma.
1863b86534aSKrasimir Georgiev   EXPECT_EQ("/** @returns j */",
187ece7e95fSmydeveloperday             format("/** @returns j */", getGoogleJSStyleWithColumns(20)));
1883b86534aSKrasimir Georgiev 
1893b86534aSKrasimir Georgiev   // Break a single line long jsdoc comment pragma.
1903b86534aSKrasimir Georgiev   EXPECT_EQ("/**\n"
1919d717813SMartin Probst             " * @returns {string}\n"
1929d717813SMartin Probst             " *     jsdoc line 12\n"
1939d717813SMartin Probst             " */",
1949d717813SMartin Probst             format("/** @returns {string} jsdoc line 12 */",
1953b86534aSKrasimir Georgiev                    getGoogleJSStyleWithColumns(20)));
1963b86534aSKrasimir Georgiev 
1976a5c95bdSKrasimir Georgiev   // FIXME: this overcounts the */ as a continuation of the 12 when breaking.
198f4d5195dSMarek Kurdej   // Cf. BreakableBlockComment::getRemainingLength.
1993b86534aSKrasimir Georgiev   EXPECT_EQ("/**\n"
2009d717813SMartin Probst             " * @returns {string}\n"
2019d717813SMartin Probst             " *     jsdoc line line\n"
2026a5c95bdSKrasimir Georgiev             " *     12\n"
2033b86534aSKrasimir Georgiev             " */",
2049d717813SMartin Probst             format("/** @returns {string} jsdoc line line 12*/",
2059d717813SMartin Probst                    getGoogleJSStyleWithColumns(25)));
2063b86534aSKrasimir Georgiev 
2073b86534aSKrasimir Georgiev   // Fix a multiline jsdoc comment ending in a comment pragma.
2083b86534aSKrasimir Georgiev   EXPECT_EQ("/**\n"
2093b86534aSKrasimir Georgiev             " * line 1\n"
2103b86534aSKrasimir Georgiev             " * line 2\n"
2116a5c95bdSKrasimir Georgiev             " * @returns {string}\n"
2126a5c95bdSKrasimir Georgiev             " *     jsdoc line 12\n"
2133b86534aSKrasimir Georgiev             " */",
2143b86534aSKrasimir Georgiev             format("/** line 1\n"
2153b86534aSKrasimir Georgiev                    " * line 2\n"
2163b86534aSKrasimir Georgiev                    " * @returns {string} jsdoc line 12 */",
2173b86534aSKrasimir Georgiev                    getGoogleJSStyleWithColumns(20)));
2183b86534aSKrasimir Georgiev 
2193b86534aSKrasimir Georgiev   EXPECT_EQ("/**\n"
2203b86534aSKrasimir Georgiev             " * line 1\n"
2213b86534aSKrasimir Georgiev             " * line 2\n"
2223b86534aSKrasimir Georgiev             " *\n"
2233b86534aSKrasimir Georgiev             " * @returns j\n"
2243b86534aSKrasimir Georgiev             " */",
2253b86534aSKrasimir Georgiev             format("/** line 1\n"
2263b86534aSKrasimir Georgiev                    " * line 2\n"
2273b86534aSKrasimir Georgiev                    " *\n"
2283b86534aSKrasimir Georgiev                    " * @returns j */",
2293b86534aSKrasimir Georgiev                    getGoogleJSStyleWithColumns(20)));
23022d7e6b0SKrasimir Georgiev }
23122d7e6b0SKrasimir Georgiev 
TEST_F(FormatTestJS,UnderstandsJavaScriptOperators)232a48a12cfSAlexander Kornienko TEST_F(FormatTestJS, UnderstandsJavaScriptOperators) {
233a48a12cfSAlexander Kornienko   verifyFormat("a == = b;");
234a48a12cfSAlexander Kornienko   verifyFormat("a != = b;");
235a48a12cfSAlexander Kornienko 
236a48a12cfSAlexander Kornienko   verifyFormat("a === b;");
237e551bb70SDaniel Jasper   verifyFormat("aaaaaaa ===\n    b;", getGoogleJSStyleWithColumns(10));
238a48a12cfSAlexander Kornienko   verifyFormat("a !== b;");
239e551bb70SDaniel Jasper   verifyFormat("aaaaaaa !==\n    b;", getGoogleJSStyleWithColumns(10));
240e551bb70SDaniel Jasper   verifyFormat("if (a + b + c +\n"
241e551bb70SDaniel Jasper                "        d !==\n"
242e551bb70SDaniel Jasper                "    e + f + g)\n"
243a48a12cfSAlexander Kornienko                "  q();",
244c1637f16SAlexander Kornienko                getGoogleJSStyleWithColumns(20));
245a48a12cfSAlexander Kornienko 
246a48a12cfSAlexander Kornienko   verifyFormat("a >> >= b;");
247a48a12cfSAlexander Kornienko 
248a48a12cfSAlexander Kornienko   verifyFormat("a >>> b;");
249e551bb70SDaniel Jasper   verifyFormat("aaaaaaa >>>\n    b;", getGoogleJSStyleWithColumns(10));
250a48a12cfSAlexander Kornienko   verifyFormat("a >>>= b;");
251e551bb70SDaniel Jasper   verifyFormat("aaaaaaa >>>=\n    b;", getGoogleJSStyleWithColumns(10));
252e551bb70SDaniel Jasper   verifyFormat("if (a + b + c +\n"
253e551bb70SDaniel Jasper                "        d >>>\n"
254e551bb70SDaniel Jasper                "    e + f + g)\n"
255a48a12cfSAlexander Kornienko                "  q();",
256c1637f16SAlexander Kornienko                getGoogleJSStyleWithColumns(20));
257e551bb70SDaniel Jasper   verifyFormat("var x = aaaaaaaaaa ?\n"
258e551bb70SDaniel Jasper                "    bbbbbb :\n"
259e551bb70SDaniel Jasper                "    ccc;",
260c1637f16SAlexander Kornienko                getGoogleJSStyleWithColumns(20));
26178214397SDaniel Jasper 
26278214397SDaniel Jasper   verifyFormat("var b = a.map((x) => x + 1);");
2633549ea1aSDaniel Jasper   verifyFormat("return ('aaa') in bbbb;");
2641ce41112SDaniel Jasper   verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa() in\n"
2651ce41112SDaniel Jasper                "    aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;");
2661ce41112SDaniel Jasper   FormatStyle Style = getGoogleJSStyleWithColumns(80);
2670ee04e6eSFrancois Ferrand   Style.AlignOperands = FormatStyle::OAS_Align;
2681ce41112SDaniel Jasper   verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa() in\n"
2691ce41112SDaniel Jasper                "        aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
2701ce41112SDaniel Jasper                Style);
2711ce41112SDaniel Jasper   Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
2721ce41112SDaniel Jasper   verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa()\n"
2731ce41112SDaniel Jasper                "            in aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
2741ce41112SDaniel Jasper                Style);
27508051991SDaniel Jasper 
27608051991SDaniel Jasper   // ES6 spread operator.
27708051991SDaniel Jasper   verifyFormat("someFunction(...a);");
27808051991SDaniel Jasper   verifyFormat("var x = [1, ...a, 2];");
2792b30bd2bSMartin Probst 
2802b30bd2bSMartin Probst   // "- -1" is legal JS syntax, but must not collapse into "--".
2812b30bd2bSMartin Probst   verifyFormat("- -1;", " - -1;");
2822b30bd2bSMartin Probst   verifyFormat("-- -1;", " -- -1;");
2832b30bd2bSMartin Probst   verifyFormat("+ +1;", " + +1;");
2842b30bd2bSMartin Probst   verifyFormat("++ +1;", " ++ +1;");
285a48a12cfSAlexander Kornienko }
286a48a12cfSAlexander Kornienko 
TEST_F(FormatTestJS,UnderstandsAmpAmp)2873a038de3SDaniel Jasper TEST_F(FormatTestJS, UnderstandsAmpAmp) {
2883a038de3SDaniel Jasper   verifyFormat("e && e.SomeFunction();");
2893a038de3SDaniel Jasper }
2903a038de3SDaniel Jasper 
TEST_F(FormatTestJS,LiteralOperatorsCanBeKeywords)2914db69bd5SDaniel Jasper TEST_F(FormatTestJS, LiteralOperatorsCanBeKeywords) {
2924db69bd5SDaniel Jasper   verifyFormat("not.and.or.not_eq = 1;");
2934db69bd5SDaniel Jasper }
2944db69bd5SDaniel Jasper 
TEST_F(FormatTestJS,ReservedWords)295ba52fcb7SDaniel Jasper TEST_F(FormatTestJS, ReservedWords) {
296ba52fcb7SDaniel Jasper   // JavaScript reserved words (aka keywords) are only illegal when used as
297ba52fcb7SDaniel Jasper   // Identifiers, but are legal as IdentifierNames.
298ba52fcb7SDaniel Jasper   verifyFormat("x.class.struct = 1;");
299ba52fcb7SDaniel Jasper   verifyFormat("x.case = 1;");
300ba52fcb7SDaniel Jasper   verifyFormat("x.interface = 1;");
301997cf2feSDaniel Jasper   verifyFormat("x.for = 1;");
30283e0220bSMartin Probst   verifyFormat("x.of();");
303c4a3d081SMartin Probst   verifyFormat("of(null);");
304110ecc70SMartin Probst   verifyFormat("return of(null);");
305c4a3d081SMartin Probst   verifyFormat("import {of} from 'x';");
30683e0220bSMartin Probst   verifyFormat("x.in();");
30783e0220bSMartin Probst   verifyFormat("x.let();");
30883e0220bSMartin Probst   verifyFormat("x.var();");
30983e0220bSMartin Probst   verifyFormat("x.for();");
31083e0220bSMartin Probst   verifyFormat("x.as();");
31183e0220bSMartin Probst   verifyFormat("x.instanceof();");
31283e0220bSMartin Probst   verifyFormat("x.switch();");
31383e0220bSMartin Probst   verifyFormat("x.case();");
31483e0220bSMartin Probst   verifyFormat("x.delete();");
31583e0220bSMartin Probst   verifyFormat("x.throw();");
31683e0220bSMartin Probst   verifyFormat("x.throws();");
31783e0220bSMartin Probst   verifyFormat("x.if();");
318ba52fcb7SDaniel Jasper   verifyFormat("x = {\n"
319ba52fcb7SDaniel Jasper                "  a: 12,\n"
320ba52fcb7SDaniel Jasper                "  interface: 1,\n"
321ba52fcb7SDaniel Jasper                "  switch: 1,\n"
322ba52fcb7SDaniel Jasper                "};");
32309840efdSDaniel Jasper   verifyFormat("var struct = 2;");
32409840efdSDaniel Jasper   verifyFormat("var union = 2;");
3251e8261eaSMartin Probst   verifyFormat("var interface = 2;");
326071f870eSMarek Kurdej   verifyFormat("var requires = {};");
3271e8261eaSMartin Probst   verifyFormat("interface = 2;");
3281e8261eaSMartin Probst   verifyFormat("x = interface instanceof y;");
329f785fd94SMartin Probst   verifyFormat("interface Test {\n"
330f785fd94SMartin Probst                "  x: string;\n"
331f785fd94SMartin Probst                "  switch: string;\n"
332f785fd94SMartin Probst                "  case: string;\n"
333f785fd94SMartin Probst                "  default: string;\n"
334f785fd94SMartin Probst                "}\n");
3356c38ef90SMartin Probst   verifyFormat("const Axis = {\n"
3366c38ef90SMartin Probst                "  for: 'for',\n"
3376c38ef90SMartin Probst                "  x: 'x'\n"
3386c38ef90SMartin Probst                "};",
3396c38ef90SMartin Probst                "const Axis = {for: 'for', x:   'x'};");
3404e88cb68SMarek Kurdej   verifyFormat("export class Foo extends Bar {\n"
3414e88cb68SMarek Kurdej                "  get case(): Case {\n"
3424e88cb68SMarek Kurdej                "    return (\n"
3434e88cb68SMarek Kurdej                "        (this.Bar$has('case')) ? (this.Bar$get('case')) :\n"
3444e88cb68SMarek Kurdej                "                                 (this.case = new Case()));\n"
3454e88cb68SMarek Kurdej                "  }\n"
3464e88cb68SMarek Kurdej                "}");
347ba52fcb7SDaniel Jasper }
348ba52fcb7SDaniel Jasper 
TEST_F(FormatTestJS,ReservedWordsMethods)3494210d2fdSMartin Probst TEST_F(FormatTestJS, ReservedWordsMethods) {
350ece7e95fSmydeveloperday   verifyFormat("class X {\n"
3514210d2fdSMartin Probst                "  delete() {\n"
3524210d2fdSMartin Probst                "    x();\n"
3534210d2fdSMartin Probst                "  }\n"
3544210d2fdSMartin Probst                "  interface() {\n"
3554210d2fdSMartin Probst                "    x();\n"
3564210d2fdSMartin Probst                "  }\n"
3574210d2fdSMartin Probst                "  let() {\n"
3584210d2fdSMartin Probst                "    x();\n"
3594210d2fdSMartin Probst                "  }\n"
3604210d2fdSMartin Probst                "}\n");
3610734fb21SMartin Probst   verifyFormat("class KeywordNamedMethods {\n"
3620734fb21SMartin Probst                "  do() {\n"
3630734fb21SMartin Probst                "  }\n"
3640734fb21SMartin Probst                "  for() {\n"
3650734fb21SMartin Probst                "  }\n"
3660734fb21SMartin Probst                "  while() {\n"
3670734fb21SMartin Probst                "  }\n"
3680734fb21SMartin Probst                "  if() {\n"
3690734fb21SMartin Probst                "  }\n"
3700734fb21SMartin Probst                "  else() {\n"
3710734fb21SMartin Probst                "  }\n"
3720734fb21SMartin Probst                "  try() {\n"
3730734fb21SMartin Probst                "  }\n"
3740734fb21SMartin Probst                "  catch() {\n"
3750734fb21SMartin Probst                "  }\n"
3760734fb21SMartin Probst                "}\n");
3774210d2fdSMartin Probst }
3784210d2fdSMartin Probst 
TEST_F(FormatTestJS,ReservedWordsParenthesized)37922e00f09SMartin Probst TEST_F(FormatTestJS, ReservedWordsParenthesized) {
38022e00f09SMartin Probst   // All of these are statements using the keyword, not function calls.
38122e00f09SMartin Probst   verifyFormat("throw (x + y);\n"
38222e00f09SMartin Probst                "await (await x).y;\n"
3839926abb9SMartin Probst                "typeof (x) === 'string';\n"
38422e00f09SMartin Probst                "void (0);\n"
38522e00f09SMartin Probst                "delete (x.y);\n"
38622e00f09SMartin Probst                "return (x);\n");
38722e00f09SMartin Probst }
38822e00f09SMartin Probst 
TEST_F(FormatTestJS,ES6DestructuringAssignment)3890dd5291eSDaniel Jasper TEST_F(FormatTestJS, ES6DestructuringAssignment) {
3900dd5291eSDaniel Jasper   verifyFormat("var [a, b, c] = [1, 2, 3];");
3915dbcd3bdSDaniel Jasper   verifyFormat("const [a, b, c] = [1, 2, 3];");
3929f642f7dSDaniel Jasper   verifyFormat("let [a, b, c] = [1, 2, 3];");
39360948b12SDaniel Jasper   verifyFormat("var {a, b} = {a: 1, b: 2};");
3949f642f7dSDaniel Jasper   verifyFormat("let {a, b} = {a: 1, b: 2};");
3950dd5291eSDaniel Jasper }
3960dd5291eSDaniel Jasper 
TEST_F(FormatTestJS,ContainerLiterals)39717062ff5SDaniel Jasper TEST_F(FormatTestJS, ContainerLiterals) {
39828d8a5abSDaniel Jasper   verifyFormat("var x = {\n"
39928d8a5abSDaniel Jasper                "  y: function(a) {\n"
40028d8a5abSDaniel Jasper                "    return a;\n"
40128d8a5abSDaniel Jasper                "  }\n"
40228d8a5abSDaniel Jasper                "};");
40317062ff5SDaniel Jasper   verifyFormat("return {\n"
40417062ff5SDaniel Jasper                "  link: function() {\n"
40517062ff5SDaniel Jasper                "    f();  //\n"
40617062ff5SDaniel Jasper                "  }\n"
40717062ff5SDaniel Jasper                "};");
40817062ff5SDaniel Jasper   verifyFormat("return {\n"
40917062ff5SDaniel Jasper                "  a: a,\n"
41017062ff5SDaniel Jasper                "  link: function() {\n"
41117062ff5SDaniel Jasper                "    f();  //\n"
41217062ff5SDaniel Jasper                "  }\n"
41317062ff5SDaniel Jasper                "};");
41417062ff5SDaniel Jasper   verifyFormat("return {\n"
41517062ff5SDaniel Jasper                "  a: a,\n"
41690ebc98eSDaniel Jasper                "  link: function() {\n"
41717062ff5SDaniel Jasper                "    f();  //\n"
41817062ff5SDaniel Jasper                "  },\n"
41990ebc98eSDaniel Jasper                "  link: function() {\n"
42017062ff5SDaniel Jasper                "    f();  //\n"
42117062ff5SDaniel Jasper                "  }\n"
42217062ff5SDaniel Jasper                "};");
42394e11d02SDaniel Jasper   verifyFormat("var stuff = {\n"
42494e11d02SDaniel Jasper                "  // comment for update\n"
42594e11d02SDaniel Jasper                "  update: false,\n"
42694e11d02SDaniel Jasper                "  // comment for modules\n"
42794e11d02SDaniel Jasper                "  modules: false,\n"
42894e11d02SDaniel Jasper                "  // comment for tasks\n"
42994e11d02SDaniel Jasper                "  tasks: false\n"
43094e11d02SDaniel Jasper                "};");
43197bfb7b1SDaniel Jasper   verifyFormat("return {\n"
43297bfb7b1SDaniel Jasper                "  'finish':\n"
43397bfb7b1SDaniel Jasper                "      //\n"
43497bfb7b1SDaniel Jasper                "      a\n"
43597bfb7b1SDaniel Jasper                "};");
4364087432fSDaniel Jasper   verifyFormat("var obj = {\n"
4374087432fSDaniel Jasper                "  fooooooooo: function(x) {\n"
4384087432fSDaniel Jasper                "    return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
4394087432fSDaniel Jasper                "  }\n"
4404087432fSDaniel Jasper                "};");
44160948b12SDaniel Jasper   // Simple object literal, as opposed to enum style below.
44260948b12SDaniel Jasper   verifyFormat("var obj = {a: 123};");
44360948b12SDaniel Jasper   // Enum style top level assignment.
44460948b12SDaniel Jasper   verifyFormat("X = {\n  a: 123\n};");
44560948b12SDaniel Jasper   verifyFormat("X.Y = {\n  a: 123\n};");
44611ca2639SDaniel Jasper   // But only on the top level, otherwise its a plain object literal assignment.
44711ca2639SDaniel Jasper   verifyFormat("function x() {\n"
44811ca2639SDaniel Jasper                "  y = {z: 1};\n"
44911ca2639SDaniel Jasper                "}");
45060948b12SDaniel Jasper   verifyFormat("x = foo && {a: 123};");
45179e06081SManuel Klimek 
45279e06081SManuel Klimek   // Arrow functions in object literals.
45328d8a5abSDaniel Jasper   verifyFormat("var x = {\n"
45428d8a5abSDaniel Jasper                "  y: (a) => {\n"
45502656f29SMartin Probst                "    x();\n"
45628d8a5abSDaniel Jasper                "    return a;\n"
45702656f29SMartin Probst                "  },\n"
45828d8a5abSDaniel Jasper                "};");
45979e06081SManuel Klimek   verifyFormat("var x = {y: (a) => a};");
4608c42d445SDaniel Jasper 
4618e3eba03SMartin Probst   // Methods in object literals.
4628e3eba03SMartin Probst   verifyFormat("var x = {\n"
4638e3eba03SMartin Probst                "  y(a: string): number {\n"
4648e3eba03SMartin Probst                "    return a;\n"
4658e3eba03SMartin Probst                "  }\n"
4668e3eba03SMartin Probst                "};");
4678e3eba03SMartin Probst   verifyFormat("var x = {\n"
4688e3eba03SMartin Probst                "  y(a: string) {\n"
4698e3eba03SMartin Probst                "    return a;\n"
4708e3eba03SMartin Probst                "  }\n"
4718e3eba03SMartin Probst                "};");
4728e3eba03SMartin Probst 
4738c42d445SDaniel Jasper   // Computed keys.
474cd8d4ff9SDaniel Jasper   verifyFormat("var x = {[a]: 1, b: 2, [c]: 3};");
4758c42d445SDaniel Jasper   verifyFormat("var x = {\n"
4768c42d445SDaniel Jasper                "  [a]: 1,\n"
477cd8d4ff9SDaniel Jasper                "  b: 2,\n"
478cd8d4ff9SDaniel Jasper                "  [c]: 3,\n"
4798c42d445SDaniel Jasper                "};");
4809f4c9d41SDaniel Jasper 
4819f4c9d41SDaniel Jasper   // Object literals can leave out labels.
4829f4c9d41SDaniel Jasper   verifyFormat("f({a}, () => {\n"
48302656f29SMartin Probst                "  x;\n"
48402656f29SMartin Probst                "  g();\n"
4859f4c9d41SDaniel Jasper                "});");
486b18425bfSDaniel Jasper 
487b18425bfSDaniel Jasper   // Keys can be quoted.
488b18425bfSDaniel Jasper   verifyFormat("var x = {\n"
489b18425bfSDaniel Jasper                "  a: a,\n"
490b18425bfSDaniel Jasper                "  b: b,\n"
491b18425bfSDaniel Jasper                "  'c': c,\n"
492b18425bfSDaniel Jasper                "};");
493e98e5811SDaniel Jasper 
494e98e5811SDaniel Jasper   // Dict literals can skip the label names.
495e98e5811SDaniel Jasper   verifyFormat("var x = {\n"
496e98e5811SDaniel Jasper                "  aaa,\n"
497e98e5811SDaniel Jasper                "  aaa,\n"
498e98e5811SDaniel Jasper                "  aaa,\n"
499e98e5811SDaniel Jasper                "};");
500893b8adcSDaniel Jasper   verifyFormat("return {\n"
501893b8adcSDaniel Jasper                "  a,\n"
502893b8adcSDaniel Jasper                "  b: 'b',\n"
503893b8adcSDaniel Jasper                "  c,\n"
504893b8adcSDaniel Jasper                "};");
50517062ff5SDaniel Jasper }
50617062ff5SDaniel Jasper 
TEST_F(FormatTestJS,MethodsInObjectLiterals)507f46dec86SDaniel Jasper TEST_F(FormatTestJS, MethodsInObjectLiterals) {
508f46dec86SDaniel Jasper   verifyFormat("var o = {\n"
509f46dec86SDaniel Jasper                "  value: 'test',\n"
510f46dec86SDaniel Jasper                "  get value() {  // getter\n"
511f46dec86SDaniel Jasper                "    return this.value;\n"
512f46dec86SDaniel Jasper                "  }\n"
513f46dec86SDaniel Jasper                "};");
514f46dec86SDaniel Jasper   verifyFormat("var o = {\n"
515f46dec86SDaniel Jasper                "  value: 'test',\n"
516f46dec86SDaniel Jasper                "  set value(val) {  // setter\n"
517f46dec86SDaniel Jasper                "    this.value = val;\n"
518f46dec86SDaniel Jasper                "  }\n"
519f46dec86SDaniel Jasper                "};");
520f46dec86SDaniel Jasper   verifyFormat("var o = {\n"
521f46dec86SDaniel Jasper                "  value: 'test',\n"
522f46dec86SDaniel Jasper                "  someMethod(val) {  // method\n"
523f46dec86SDaniel Jasper                "    doSomething(this.value + val);\n"
524f46dec86SDaniel Jasper                "  }\n"
525f46dec86SDaniel Jasper                "};");
526739ec534SDaniel Jasper   verifyFormat("var o = {\n"
527739ec534SDaniel Jasper                "  someMethod(val) {  // method\n"
528739ec534SDaniel Jasper                "    doSomething(this.value + val);\n"
529739ec534SDaniel Jasper                "  },\n"
530739ec534SDaniel Jasper                "  someOtherMethod(val) {  // method\n"
531739ec534SDaniel Jasper                "    doSomething(this.value + val);\n"
532739ec534SDaniel Jasper                "  }\n"
533739ec534SDaniel Jasper                "};");
534f46dec86SDaniel Jasper }
535f46dec86SDaniel Jasper 
TEST_F(FormatTestJS,GettersSettersVisibilityKeywords)53619c7de0aSMartin Probst TEST_F(FormatTestJS, GettersSettersVisibilityKeywords) {
53719c7de0aSMartin Probst   // Don't break after "protected"
53819c7de0aSMartin Probst   verifyFormat("class X {\n"
53919c7de0aSMartin Probst                "  protected get getter():\n"
54019c7de0aSMartin Probst                "      number {\n"
54119c7de0aSMartin Probst                "    return 1;\n"
54219c7de0aSMartin Probst                "  }\n"
54319c7de0aSMartin Probst                "}",
54419c7de0aSMartin Probst                getGoogleJSStyleWithColumns(12));
54519c7de0aSMartin Probst   // Don't break after "get"
54619c7de0aSMartin Probst   verifyFormat("class X {\n"
54719c7de0aSMartin Probst                "  protected get someReallyLongGetterName():\n"
54819c7de0aSMartin Probst                "      number {\n"
54919c7de0aSMartin Probst                "    return 1;\n"
55019c7de0aSMartin Probst                "  }\n"
55119c7de0aSMartin Probst                "}",
55219c7de0aSMartin Probst                getGoogleJSStyleWithColumns(40));
55319c7de0aSMartin Probst }
55419c7de0aSMartin Probst 
TEST_F(FormatTestJS,SpacesInContainerLiterals)555b2e10a54SDaniel Jasper TEST_F(FormatTestJS, SpacesInContainerLiterals) {
556b2e10a54SDaniel Jasper   verifyFormat("var arr = [1, 2, 3];");
557a4e55f4dSDaniel Jasper   verifyFormat("f({a: 1, b: 2, c: 3});");
558514ecc8cSNico Weber 
5592a958321SDaniel Jasper   verifyFormat("var object_literal_with_long_name = {\n"
5602a958321SDaniel Jasper                "  a: 'aaaaaaaaaaaaaaaaaa',\n"
5612a958321SDaniel Jasper                "  b: 'bbbbbbbbbbbbbbbbbb'\n"
5622a958321SDaniel Jasper                "};");
5632a958321SDaniel Jasper 
564a4e55f4dSDaniel Jasper   verifyFormat("f({a: 1, b: 2, c: 3});",
565514ecc8cSNico Weber                getChromiumStyle(FormatStyle::LK_JavaScript));
566a4e55f4dSDaniel Jasper   verifyFormat("f({'a': [{}]});");
567b2e10a54SDaniel Jasper }
568b2e10a54SDaniel Jasper 
TEST_F(FormatTestJS,SingleQuotedStrings)569abd1f574SDaniel Jasper TEST_F(FormatTestJS, SingleQuotedStrings) {
57086fee2faSDaniel Jasper   verifyFormat("this.function('', true);");
57186fee2faSDaniel Jasper }
57286fee2faSDaniel Jasper 
TEST_F(FormatTestJS,GoogScopes)5734a39c84cSDaniel Jasper TEST_F(FormatTestJS, GoogScopes) {
5744a39c84cSDaniel Jasper   verifyFormat("goog.scope(function() {\n"
5754a39c84cSDaniel Jasper                "var x = a.b;\n"
5764a39c84cSDaniel Jasper                "var y = c.d;\n"
5774a39c84cSDaniel Jasper                "});  // goog.scope");
57802c7bca5SDaniel Jasper   verifyFormat("goog.scope(function() {\n"
57902c7bca5SDaniel Jasper                "// test\n"
58002c7bca5SDaniel Jasper                "var x = 0;\n"
58102c7bca5SDaniel Jasper                "// test\n"
58202c7bca5SDaniel Jasper                "});");
5834a39c84cSDaniel Jasper }
5844a39c84cSDaniel Jasper 
TEST_F(FormatTestJS,IIFEs)585101ec894SMartin Probst TEST_F(FormatTestJS, IIFEs) {
586101ec894SMartin Probst   // Internal calling parens; no semi.
587101ec894SMartin Probst   verifyFormat("(function() {\n"
588101ec894SMartin Probst                "var a = 1;\n"
589101ec894SMartin Probst                "}())");
590101ec894SMartin Probst   // External calling parens; no semi.
591101ec894SMartin Probst   verifyFormat("(function() {\n"
592101ec894SMartin Probst                "var b = 2;\n"
593101ec894SMartin Probst                "})()");
594101ec894SMartin Probst   // Internal calling parens; with semi.
595101ec894SMartin Probst   verifyFormat("(function() {\n"
596101ec894SMartin Probst                "var c = 3;\n"
597101ec894SMartin Probst                "}());");
598101ec894SMartin Probst   // External calling parens; with semi.
599101ec894SMartin Probst   verifyFormat("(function() {\n"
600101ec894SMartin Probst                "var d = 4;\n"
601101ec894SMartin Probst                "})();");
602101ec894SMartin Probst }
603101ec894SMartin Probst 
TEST_F(FormatTestJS,GoogModules)604616de864SDaniel Jasper TEST_F(FormatTestJS, GoogModules) {
605616de864SDaniel Jasper   verifyFormat("goog.module('this.is.really.absurdly.long');",
606616de864SDaniel Jasper                getGoogleJSStyleWithColumns(40));
607616de864SDaniel Jasper   verifyFormat("goog.require('this.is.really.absurdly.long');",
608616de864SDaniel Jasper                getGoogleJSStyleWithColumns(40));
609616de864SDaniel Jasper   verifyFormat("goog.provide('this.is.really.absurdly.long');",
610616de864SDaniel Jasper                getGoogleJSStyleWithColumns(40));
611616de864SDaniel Jasper   verifyFormat("var long = goog.require('this.is.really.absurdly.long');",
612616de864SDaniel Jasper                getGoogleJSStyleWithColumns(40));
61355b6d4b9SMartin Probst   verifyFormat("const X = goog.requireType('this.is.really.absurdly.long');",
61455b6d4b9SMartin Probst                getGoogleJSStyleWithColumns(40));
61502cbeb22SDaniel Jasper   verifyFormat("goog.forwardDeclare('this.is.really.absurdly.long');",
61602cbeb22SDaniel Jasper                getGoogleJSStyleWithColumns(40));
61753c38f4eSDaniel Jasper 
61853c38f4eSDaniel Jasper   // These should be wrapped normally.
61953c38f4eSDaniel Jasper   verifyFormat(
62053c38f4eSDaniel Jasper       "var MyLongClassName =\n"
62153c38f4eSDaniel Jasper       "    goog.module.get('my.long.module.name.followedBy.MyLongClassName');");
622103a7b5bSMartin Probst   verifyFormat("function a() {\n"
623103a7b5bSMartin Probst                "  goog.setTestOnly();\n"
624103a7b5bSMartin Probst                "}\n",
625103a7b5bSMartin Probst                "function a() {\n"
626103a7b5bSMartin Probst                "goog.setTestOnly();\n"
627103a7b5bSMartin Probst                "}\n");
628616de864SDaniel Jasper }
629616de864SDaniel Jasper 
TEST_F(FormatTestJS,FormatsNamespaces)630ece8c0c6SMartin Probst TEST_F(FormatTestJS, FormatsNamespaces) {
631ece8c0c6SMartin Probst   verifyFormat("namespace Foo {\n"
632ece8c0c6SMartin Probst                "  export let x = 1;\n"
633ece8c0c6SMartin Probst                "}\n");
634ece8c0c6SMartin Probst   verifyFormat("declare namespace Foo {\n"
635ece8c0c6SMartin Probst                "  export let x: number;\n"
636ece8c0c6SMartin Probst                "}\n");
637ece8c0c6SMartin Probst }
638ece8c0c6SMartin Probst 
TEST_F(FormatTestJS,NamespacesMayNotWrap)63972fd75a0SMartin Probst TEST_F(FormatTestJS, NamespacesMayNotWrap) {
64072fd75a0SMartin Probst   verifyFormat("declare namespace foobarbaz {\n"
641ece7e95fSmydeveloperday                "}\n",
642ece7e95fSmydeveloperday                getGoogleJSStyleWithColumns(18));
64372fd75a0SMartin Probst   verifyFormat("declare module foobarbaz {\n"
644ece7e95fSmydeveloperday                "}\n",
645ece7e95fSmydeveloperday                getGoogleJSStyleWithColumns(15));
64672fd75a0SMartin Probst   verifyFormat("namespace foobarbaz {\n"
647ece7e95fSmydeveloperday                "}\n",
648ece7e95fSmydeveloperday                getGoogleJSStyleWithColumns(10));
64972fd75a0SMartin Probst   verifyFormat("module foobarbaz {\n"
650ece7e95fSmydeveloperday                "}\n",
651ece7e95fSmydeveloperday                getGoogleJSStyleWithColumns(7));
65272fd75a0SMartin Probst }
65372fd75a0SMartin Probst 
TEST_F(FormatTestJS,AmbientDeclarations)65472fd75a0SMartin Probst TEST_F(FormatTestJS, AmbientDeclarations) {
65572fd75a0SMartin Probst   FormatStyle NineCols = getGoogleJSStyleWithColumns(9);
656ece7e95fSmydeveloperday   verifyFormat("declare class\n"
65772fd75a0SMartin Probst                "    X {}",
65872fd75a0SMartin Probst                NineCols);
659ece7e95fSmydeveloperday   verifyFormat("declare function\n"
66072fd75a0SMartin Probst                "x();", // TODO(martinprobst): should ideally be indented.
66172fd75a0SMartin Probst                NineCols);
662af16c506SMartin Probst   verifyFormat("declare function foo();\n"
663af16c506SMartin Probst                "let x = 1;\n");
664af16c506SMartin Probst   verifyFormat("declare function foo(): string;\n"
665af16c506SMartin Probst                "let x = 1;\n");
666af16c506SMartin Probst   verifyFormat("declare function foo(): {x: number};\n"
667af16c506SMartin Probst                "let x = 1;\n");
668af16c506SMartin Probst   verifyFormat("declare class X {}\n"
669af16c506SMartin Probst                "let x = 1;\n");
670af16c506SMartin Probst   verifyFormat("declare interface Y {}\n"
671af16c506SMartin Probst                "let x = 1;\n");
672ece7e95fSmydeveloperday   verifyFormat("declare enum X {\n"
67372fd75a0SMartin Probst                "}",
67472fd75a0SMartin Probst                NineCols);
675ece7e95fSmydeveloperday   verifyFormat("declare let\n"
67672fd75a0SMartin Probst                "    x: number;",
67772fd75a0SMartin Probst                NineCols);
67872fd75a0SMartin Probst }
67972fd75a0SMartin Probst 
TEST_F(FormatTestJS,FormatsFreestandingFunctions)680ad9eb0d7SDaniel Jasper TEST_F(FormatTestJS, FormatsFreestandingFunctions) {
681ad9eb0d7SDaniel Jasper   verifyFormat("function outer1(a, b) {\n"
68228d8a5abSDaniel Jasper                "  function inner1(a, b) {\n"
68328d8a5abSDaniel Jasper                "    return a;\n"
68428d8a5abSDaniel Jasper                "  }\n"
685ad9eb0d7SDaniel Jasper                "  inner1(a, b);\n"
686ad9eb0d7SDaniel Jasper                "}\n"
687ad9eb0d7SDaniel Jasper                "function outer2(a, b) {\n"
68828d8a5abSDaniel Jasper                "  function inner2(a, b) {\n"
68928d8a5abSDaniel Jasper                "    return a;\n"
69028d8a5abSDaniel Jasper                "  }\n"
691ad9eb0d7SDaniel Jasper                "  inner2(a, b);\n"
692ad9eb0d7SDaniel Jasper                "}");
69320580fd5SDaniel Jasper   verifyFormat("function f() {}");
694b7fb267eSMartin Probst   verifyFormat("function aFunction() {}\n"
695b7fb267eSMartin Probst                "(function f() {\n"
696b7fb267eSMartin Probst                "  var x = 1;\n"
697b7fb267eSMartin Probst                "}());\n");
69895ed8e79SMartin Probst   verifyFormat("function aFunction() {}\n"
69995ed8e79SMartin Probst                "{\n"
700b7fb267eSMartin Probst                "  let x = 1;\n"
701b7fb267eSMartin Probst                "  console.log(x);\n"
702b7fb267eSMartin Probst                "}\n");
7034f4f2783SKrasimir Georgiev   EXPECT_EQ("a = function(x) {}\n"
7044f4f2783SKrasimir Georgiev             "\n"
7054f4f2783SKrasimir Georgiev             "function f(x) {}",
7064f4f2783SKrasimir Georgiev             format("a = function(x) {}\n"
7074f4f2783SKrasimir Georgiev                    "\n"
7084f4f2783SKrasimir Georgiev                    "function f(x) {}",
7094f4f2783SKrasimir Georgiev                    getGoogleJSStyleWithColumns(20)));
710ad9eb0d7SDaniel Jasper }
711ad9eb0d7SDaniel Jasper 
TEST_F(FormatTestJS,FormatsDecorators)712befb9dc3SKrasimir Georgiev TEST_F(FormatTestJS, FormatsDecorators) {
713befb9dc3SKrasimir Georgiev   // No line break after argument decorators.
714befb9dc3SKrasimir Georgiev   verifyFormat("class A {\n"
715befb9dc3SKrasimir Georgiev                "  constructor(@arg(DECOR) private arg: Type) {}\n"
716befb9dc3SKrasimir Georgiev                "}");
717befb9dc3SKrasimir Georgiev   // Ensure that there is a break before functions, getters and setters.
718f3671a68SKrasimir Georgiev   EXPECT_EQ("class A {\n"
719f3671a68SKrasimir Georgiev             "  private p = () => {}\n"
720f3671a68SKrasimir Georgiev             "\n"
721f3671a68SKrasimir Georgiev             "  @decorated('a')\n"
722f3671a68SKrasimir Georgiev             "  get f() {\n"
723f3671a68SKrasimir Georgiev             "    return result;\n"
724f3671a68SKrasimir Georgiev             "  }\n"
725befb9dc3SKrasimir Georgiev             "}\n"
726befb9dc3SKrasimir Georgiev             "\n"
727befb9dc3SKrasimir Georgiev             "class B {\n"
728befb9dc3SKrasimir Georgiev             "  private p = () => {}\n"
729befb9dc3SKrasimir Georgiev             "\n"
730befb9dc3SKrasimir Georgiev             "  @decorated('a')\n"
731befb9dc3SKrasimir Georgiev             "  set f() {\n"
732befb9dc3SKrasimir Georgiev             "    return result;\n"
733befb9dc3SKrasimir Georgiev             "  }\n"
734befb9dc3SKrasimir Georgiev             "}\n"
735befb9dc3SKrasimir Georgiev             "\n"
736befb9dc3SKrasimir Georgiev             "class C {\n"
737befb9dc3SKrasimir Georgiev             "  private p = () => {}\n"
738befb9dc3SKrasimir Georgiev             "\n"
739befb9dc3SKrasimir Georgiev             "  @decorated('a')\n"
740befb9dc3SKrasimir Georgiev             "  function f() {\n"
741befb9dc3SKrasimir Georgiev             "    return result;\n"
742befb9dc3SKrasimir Georgiev             "  }\n"
743f3671a68SKrasimir Georgiev             "}",
744f3671a68SKrasimir Georgiev             format("class A {\n"
745f3671a68SKrasimir Georgiev                    "  private p = () => {}\n"
746f3671a68SKrasimir Georgiev                    "\n"
747f3671a68SKrasimir Georgiev                    "  @decorated('a')\n"
748f3671a68SKrasimir Georgiev                    "  get f() {\n"
749f3671a68SKrasimir Georgiev                    "    return result;\n"
750f3671a68SKrasimir Georgiev                    "  }\n"
751befb9dc3SKrasimir Georgiev                    "}\n"
752befb9dc3SKrasimir Georgiev                    "\n"
753befb9dc3SKrasimir Georgiev                    "class B {\n"
754befb9dc3SKrasimir Georgiev                    "  private p = () => {}\n"
755befb9dc3SKrasimir Georgiev                    "\n"
756befb9dc3SKrasimir Georgiev                    "  @decorated('a')\n"
757befb9dc3SKrasimir Georgiev                    "  set f() {\n"
758befb9dc3SKrasimir Georgiev                    "    return result;\n"
759befb9dc3SKrasimir Georgiev                    "  }\n"
760befb9dc3SKrasimir Georgiev                    "}\n"
761befb9dc3SKrasimir Georgiev                    "\n"
762befb9dc3SKrasimir Georgiev                    "class C {\n"
763befb9dc3SKrasimir Georgiev                    "  private p = () => {}\n"
764befb9dc3SKrasimir Georgiev                    "\n"
765befb9dc3SKrasimir Georgiev                    "  @decorated('a')\n"
766befb9dc3SKrasimir Georgiev                    "  function f() {\n"
767befb9dc3SKrasimir Georgiev                    "    return result;\n"
768befb9dc3SKrasimir Georgiev                    "  }\n"
769f3671a68SKrasimir Georgiev                    "}",
770f3671a68SKrasimir Georgiev                    getGoogleJSStyleWithColumns(50)));
771f3671a68SKrasimir Georgiev }
772f3671a68SKrasimir Georgiev 
TEST_F(FormatTestJS,GeneratorFunctions)7735f8445b3SMartin Probst TEST_F(FormatTestJS, GeneratorFunctions) {
7745f8445b3SMartin Probst   verifyFormat("function* f() {\n"
7755f8445b3SMartin Probst                "  let x = 1;\n"
7765f8445b3SMartin Probst                "  yield x;\n"
7775f8445b3SMartin Probst                "  yield* something();\n"
778eb886635SDaniel Jasper                "  yield [1, 2];\n"
779eb886635SDaniel Jasper                "  yield {a: 1};\n"
7805f8445b3SMartin Probst                "}");
7815f8445b3SMartin Probst   verifyFormat("function*\n"
7825f8445b3SMartin Probst                "    f() {\n"
7835f8445b3SMartin Probst                "}",
7845f8445b3SMartin Probst                getGoogleJSStyleWithColumns(8));
7855f8445b3SMartin Probst   verifyFormat("export function* f() {\n"
7865f8445b3SMartin Probst                "  yield 1;\n"
7875f8445b3SMartin Probst                "}\n");
7885f8445b3SMartin Probst   verifyFormat("class X {\n"
78928d8a5abSDaniel Jasper                "  * generatorMethod() {\n"
79028d8a5abSDaniel Jasper                "    yield x;\n"
79128d8a5abSDaniel Jasper                "  }\n"
7925f8445b3SMartin Probst                "}");
79371e50af6SDaniel Jasper   verifyFormat("var x = {\n"
79471e50af6SDaniel Jasper                "  a: function*() {\n"
79571e50af6SDaniel Jasper                "    //\n"
79671e50af6SDaniel Jasper                "  }\n"
79771e50af6SDaniel Jasper                "}\n");
7985f8445b3SMartin Probst }
7995f8445b3SMartin Probst 
TEST_F(FormatTestJS,AsyncFunctions)8005f8445b3SMartin Probst TEST_F(FormatTestJS, AsyncFunctions) {
8015f8445b3SMartin Probst   verifyFormat("async function f() {\n"
8025f8445b3SMartin Probst                "  let x = 1;\n"
8035f8445b3SMartin Probst                "  return fetch(x);\n"
8045f8445b3SMartin Probst                "}");
805973ff79eSMartin Probst   verifyFormat("async function f() {\n"
806973ff79eSMartin Probst                "  return 1;\n"
807973ff79eSMartin Probst                "}\n"
808973ff79eSMartin Probst                "\n"
809973ff79eSMartin Probst                "function a() {\n"
810973ff79eSMartin Probst                "  return 1;\n"
811973ff79eSMartin Probst                "}\n",
812973ff79eSMartin Probst                "  async   function f() {\n"
813973ff79eSMartin Probst                "   return 1;\n"
814973ff79eSMartin Probst                "}\n"
815973ff79eSMartin Probst                "\n"
816973ff79eSMartin Probst                "   function a() {\n"
817973ff79eSMartin Probst                "  return   1;\n"
818973ff79eSMartin Probst                "}  \n");
819736a3802SMartin Probst   // clang-format must not insert breaks between async and function, otherwise
820736a3802SMartin Probst   // automatic semicolon insertion may trigger (in particular in a class body).
821736a3802SMartin Probst   verifyFormat("async function\n"
822736a3802SMartin Probst                "hello(\n"
823736a3802SMartin Probst                "    myparamnameiswaytooloooong) {\n"
824736a3802SMartin Probst                "}",
825736a3802SMartin Probst                "async function hello(myparamnameiswaytooloooong) {}",
826736a3802SMartin Probst                getGoogleJSStyleWithColumns(10));
827736a3802SMartin Probst   verifyFormat("class C {\n"
828736a3802SMartin Probst                "  async hello(\n"
829736a3802SMartin Probst                "      myparamnameiswaytooloooong) {\n"
830736a3802SMartin Probst                "  }\n"
831736a3802SMartin Probst                "}",
832736a3802SMartin Probst                "class C {\n"
833736a3802SMartin Probst                "  async hello(myparamnameiswaytooloooong) {} }",
834736a3802SMartin Probst                getGoogleJSStyleWithColumns(10));
8355f8445b3SMartin Probst   verifyFormat("async function* f() {\n"
8365f8445b3SMartin Probst                "  yield fetch(x);\n"
8375f8445b3SMartin Probst                "}");
8385f8445b3SMartin Probst   verifyFormat("export async function f() {\n"
8395f8445b3SMartin Probst                "  return fetch(x);\n"
8405f8445b3SMartin Probst                "}");
84120371c30SMartin Probst   verifyFormat("let x = async () => f();");
842973ff79eSMartin Probst   verifyFormat("let x = async function() {\n"
843973ff79eSMartin Probst                "  f();\n"
844973ff79eSMartin Probst                "};");
84520371c30SMartin Probst   verifyFormat("let x = async();");
8465f8445b3SMartin Probst   verifyFormat("class X {\n"
84728d8a5abSDaniel Jasper                "  async asyncMethod() {\n"
84828d8a5abSDaniel Jasper                "    return fetch(1);\n"
84928d8a5abSDaniel Jasper                "  }\n"
8505f8445b3SMartin Probst                "}");
851409697ecSMartin Probst   verifyFormat("function initialize() {\n"
852409697ecSMartin Probst                "  // Comment.\n"
853409697ecSMartin Probst                "  return async.then();\n"
854409697ecSMartin Probst                "}\n");
855a050f41cSMartin Probst   verifyFormat("for await (const x of y) {\n"
856bd49e321SMartin Probst                "  console.log(x);\n"
857bd49e321SMartin Probst                "}\n");
858bd49e321SMartin Probst   verifyFormat("function asyncLoop() {\n"
859a050f41cSMartin Probst                "  for await (const x of y) {\n"
860bd49e321SMartin Probst                "    console.log(x);\n"
861bd49e321SMartin Probst                "  }\n"
862bd49e321SMartin Probst                "}\n");
8635f8445b3SMartin Probst }
8645f8445b3SMartin Probst 
TEST_F(FormatTestJS,OverriddenMembers)865e708808fSJan Kuehle TEST_F(FormatTestJS, OverriddenMembers) {
866e708808fSJan Kuehle   verifyFormat(
867e708808fSJan Kuehle       "class C extends P {\n"
868e708808fSJan Kuehle       "  protected override "
869e708808fSJan Kuehle       "anOverlyLongPropertyNameSoLongItHasToGoInASeparateLineWhenOverriden:\n"
870e708808fSJan Kuehle       "      undefined;\n"
871e708808fSJan Kuehle       "}\n");
872e708808fSJan Kuehle   verifyFormat(
873e708808fSJan Kuehle       "class C extends P {\n"
874e708808fSJan Kuehle       "  protected override "
875e708808fSJan Kuehle       "anOverlyLongMethodNameSoLongItHasToGoInASeparateLineWhenOverriden() {\n"
876e708808fSJan Kuehle       "  }\n"
877e708808fSJan Kuehle       "}\n");
878e708808fSJan Kuehle   verifyFormat("class C extends P {\n"
879e708808fSJan Kuehle                "  protected override aMethodName<ATypeParam extends {},\n"
880e708808fSJan Kuehle                "                                                    BTypeParam "
881e708808fSJan Kuehle                "extends {}>() {}\n"
882e708808fSJan Kuehle                "}\n");
883e708808fSJan Kuehle }
884e708808fSJan Kuehle 
TEST_F(FormatTestJS,FunctionParametersTrailingComma)8852c1cdae2SMartin Probst TEST_F(FormatTestJS, FunctionParametersTrailingComma) {
8862c1cdae2SMartin Probst   verifyFormat("function trailingComma(\n"
8872c1cdae2SMartin Probst                "    p1,\n"
8882c1cdae2SMartin Probst                "    p2,\n"
8892c1cdae2SMartin Probst                "    p3,\n"
8902c1cdae2SMartin Probst                ") {\n"
8912c1cdae2SMartin Probst                "  a;  //\n"
8922c1cdae2SMartin Probst                "}\n",
8932c1cdae2SMartin Probst                "function trailingComma(p1, p2, p3,) {\n"
8942c1cdae2SMartin Probst                "  a;  //\n"
8952c1cdae2SMartin Probst                "}\n");
8962c1cdae2SMartin Probst   verifyFormat("trailingComma(\n"
8972c1cdae2SMartin Probst                "    p1,\n"
8982c1cdae2SMartin Probst                "    p2,\n"
8992c1cdae2SMartin Probst                "    p3,\n"
9002c1cdae2SMartin Probst                ");\n",
9012c1cdae2SMartin Probst                "trailingComma(p1, p2, p3,);\n");
9022c1cdae2SMartin Probst   verifyFormat("trailingComma(\n"
9032c1cdae2SMartin Probst                "    p1  // hello\n"
9042c1cdae2SMartin Probst                ");\n",
9052c1cdae2SMartin Probst                "trailingComma(p1 // hello\n"
9062c1cdae2SMartin Probst                ");\n");
9072c1cdae2SMartin Probst }
9082c1cdae2SMartin Probst 
TEST_F(FormatTestJS,ArrayLiterals)909f841d3a6SDaniel Jasper TEST_F(FormatTestJS, ArrayLiterals) {
910e6fcf7d3SDaniel Jasper   verifyFormat("var aaaaa: List<SomeThing> =\n"
9119970df1fSDaniel Jasper                "    [new SomeThingAAAAAAAAAAAA(), new SomeThingBBBBBBBBB()];");
912d492b5ecSDaniel Jasper   verifyFormat("return [\n"
91350780ce1SDaniel Jasper                "  aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
914d492b5ecSDaniel Jasper                "  ccccccccccccccccccccccccccc\n"
915d492b5ecSDaniel Jasper                "];");
9167bec87c9SDaniel Jasper   verifyFormat("return [\n"
9177bec87c9SDaniel Jasper                "  aaaa().bbbbbbbb('A'),\n"
9187bec87c9SDaniel Jasper                "  aaaa().bbbbbbbb('B'),\n"
9197bec87c9SDaniel Jasper                "  aaaa().bbbbbbbb('C'),\n"
9207bec87c9SDaniel Jasper                "];");
9216501f7e8SDaniel Jasper   verifyFormat("var someVariable = SomeFunction([\n"
92250780ce1SDaniel Jasper                "  aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
9235ce80de4SDaniel Jasper                "  ccccccccccccccccccccccccccc\n"
9245ce80de4SDaniel Jasper                "]);");
9256501f7e8SDaniel Jasper   verifyFormat("var someVariable = SomeFunction([\n"
92640432ceeSDaniel Jasper                "  [aaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbb],\n"
927199d0c9eSDaniel Jasper                "]);",
928199d0c9eSDaniel Jasper                getGoogleJSStyleWithColumns(51));
9296501f7e8SDaniel Jasper   verifyFormat("var someVariable = SomeFunction(aaaa, [\n"
93050780ce1SDaniel Jasper                "  aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
9314284e362SDaniel Jasper                "  ccccccccccccccccccccccccccc\n"
9324284e362SDaniel Jasper                "]);");
9336501f7e8SDaniel Jasper   verifyFormat("var someVariable = SomeFunction(\n"
9346501f7e8SDaniel Jasper                "    aaaa,\n"
935b2ad4d4cSDaniel Jasper                "    [\n"
93650780ce1SDaniel Jasper                "      aaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
93750780ce1SDaniel Jasper                "      cccccccccccccccccccccccccc\n"
938b2ad4d4cSDaniel Jasper                "    ],\n"
939b2ad4d4cSDaniel Jasper                "    aaaa);");
940ebcb71fbSDaniel Jasper   verifyFormat("var aaaa = aaaaa ||  // wrap\n"
941ebcb71fbSDaniel Jasper                "    [];");
9421feab0f9SDaniel Jasper 
9431feab0f9SDaniel Jasper   verifyFormat("someFunction([], {a: a});");
94451c868e9SDaniel Jasper 
94551c868e9SDaniel Jasper   verifyFormat("var string = [\n"
94651c868e9SDaniel Jasper                "  'aaaaaa',\n"
94751c868e9SDaniel Jasper                "  'bbbbbb',\n"
94851c868e9SDaniel Jasper                "].join('+');");
949f841d3a6SDaniel Jasper }
950f841d3a6SDaniel Jasper 
TEST_F(FormatTestJS,ColumnLayoutForArrayLiterals)951e2deb59fSDaniel Jasper TEST_F(FormatTestJS, ColumnLayoutForArrayLiterals) {
952e2deb59fSDaniel Jasper   verifyFormat("var array = [\n"
953e2deb59fSDaniel Jasper                "  a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
954e2deb59fSDaniel Jasper                "  a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
955e2deb59fSDaniel Jasper                "];");
956e2deb59fSDaniel Jasper   verifyFormat("var array = someFunction([\n"
957e2deb59fSDaniel Jasper                "  a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
958e2deb59fSDaniel Jasper                "  a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
959e2deb59fSDaniel Jasper                "]);");
960e2deb59fSDaniel Jasper }
961e2deb59fSDaniel Jasper 
TEST_F(FormatTestJS,TrailingCommaInsertion)962a324fcf1SMartin Probst TEST_F(FormatTestJS, TrailingCommaInsertion) {
963a324fcf1SMartin Probst   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
964a324fcf1SMartin Probst   Style.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
965a324fcf1SMartin Probst   // Insert comma in wrapped array.
966a324fcf1SMartin Probst   verifyFormat("const x = [\n"
967a324fcf1SMartin Probst                "  1,  //\n"
968a324fcf1SMartin Probst                "  2,\n"
969a324fcf1SMartin Probst                "];",
970a324fcf1SMartin Probst                "const x = [\n"
971a324fcf1SMartin Probst                "  1,  //\n"
972a324fcf1SMartin Probst                "  2];",
973a324fcf1SMartin Probst                Style);
974a324fcf1SMartin Probst   // Insert comma in newly wrapped array.
975a324fcf1SMartin Probst   Style.ColumnLimit = 30;
976a324fcf1SMartin Probst   verifyFormat("const x = [\n"
977a324fcf1SMartin Probst                "  aaaaaaaaaaaaaaaaaaaaaaaaa,\n"
978a324fcf1SMartin Probst                "];",
979a324fcf1SMartin Probst                "const x = [aaaaaaaaaaaaaaaaaaaaaaaaa];", Style);
980a324fcf1SMartin Probst   // Do not insert trailing commas if they'd exceed the colum limit
981a324fcf1SMartin Probst   verifyFormat("const x = [\n"
982a324fcf1SMartin Probst                "  aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
983a324fcf1SMartin Probst                "];",
984a324fcf1SMartin Probst                "const x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa];", Style);
985a324fcf1SMartin Probst   // Object literals.
986a324fcf1SMartin Probst   verifyFormat("const x = {\n"
987a324fcf1SMartin Probst                "  a: aaaaaaaaaaaaaaaaa,\n"
988a324fcf1SMartin Probst                "};",
989a324fcf1SMartin Probst                "const x = {a: aaaaaaaaaaaaaaaaa};", Style);
990a324fcf1SMartin Probst   verifyFormat("const x = {\n"
991a324fcf1SMartin Probst                "  a: aaaaaaaaaaaaaaaaaaaaaaaaa\n"
992a324fcf1SMartin Probst                "};",
993a324fcf1SMartin Probst                "const x = {a: aaaaaaaaaaaaaaaaaaaaaaaaa};", Style);
994a324fcf1SMartin Probst   // Object literal types.
995a324fcf1SMartin Probst   verifyFormat("let x: {\n"
996a324fcf1SMartin Probst                "  a: aaaaaaaaaaaaaaaaaaaaa,\n"
997a324fcf1SMartin Probst                "};",
998a324fcf1SMartin Probst                "let x: {a: aaaaaaaaaaaaaaaaaaaaa};", Style);
999a324fcf1SMartin Probst }
1000a324fcf1SMartin Probst 
TEST_F(FormatTestJS,FunctionLiterals)10015217a8b8SDaniel Jasper TEST_F(FormatTestJS, FunctionLiterals) {
100228d8a5abSDaniel Jasper   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
100328d8a5abSDaniel Jasper   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
10043f69ba10SDaniel Jasper   verifyFormat("doFoo(function() {});");
100528d8a5abSDaniel Jasper   verifyFormat("doFoo(function() { return 1; });", Style);
100667f8ad25SDaniel Jasper   verifyFormat("var func = function() {\n"
100767f8ad25SDaniel Jasper                "  return 1;\n"
100867f8ad25SDaniel Jasper                "};");
1009ed3f3957SDaniel Jasper   verifyFormat("var func =  //\n"
1010ed3f3957SDaniel Jasper                "    function() {\n"
1011ed3f3957SDaniel Jasper                "  return 1;\n"
1012ed3f3957SDaniel Jasper                "};");
1013c03e16a7SDaniel Jasper   verifyFormat("return {\n"
1014c03e16a7SDaniel Jasper                "  body: {\n"
1015c03e16a7SDaniel Jasper                "    setAttribute: function(key, val) { this[key] = val; },\n"
1016c03e16a7SDaniel Jasper                "    getAttribute: function(key) { return this[key]; },\n"
1017c03e16a7SDaniel Jasper                "    style: {direction: ''}\n"
1018c03e16a7SDaniel Jasper                "  }\n"
101928d8a5abSDaniel Jasper                "};",
102028d8a5abSDaniel Jasper                Style);
10216501f7e8SDaniel Jasper   verifyFormat("abc = xyz ? function() {\n"
102267f8ad25SDaniel Jasper                "  return 1;\n"
10236501f7e8SDaniel Jasper                "} : function() {\n"
102467f8ad25SDaniel Jasper                "  return -1;\n"
10256501f7e8SDaniel Jasper                "};");
1026b16b969dSDaniel Jasper 
1027b16b969dSDaniel Jasper   verifyFormat("var closure = goog.bind(\n"
1028b16b969dSDaniel Jasper                "    function() {  // comment\n"
1029b16b969dSDaniel Jasper                "      foo();\n"
1030b16b969dSDaniel Jasper                "      bar();\n"
1031b16b969dSDaniel Jasper                "    },\n"
1032e9987a1dSJoerg Sonnenberger                "    this, arg1IsReallyLongAndNeedsLineBreaks,\n"
1033e9987a1dSJoerg Sonnenberger                "    arg3IsReallyLongAndNeedsLineBreaks);");
1034b16b969dSDaniel Jasper   verifyFormat("var closure = goog.bind(function() {  // comment\n"
1035b16b969dSDaniel Jasper                "  foo();\n"
1036b16b969dSDaniel Jasper                "  bar();\n"
1037b16b969dSDaniel Jasper                "}, this);");
103858cb2eddSDaniel Jasper   verifyFormat("return {\n"
103958cb2eddSDaniel Jasper                "  a: 'E',\n"
104058cb2eddSDaniel Jasper                "  b: function() {\n"
104158cb2eddSDaniel Jasper                "    return function() {\n"
104258cb2eddSDaniel Jasper                "      f();  //\n"
104358cb2eddSDaniel Jasper                "    };\n"
104458cb2eddSDaniel Jasper                "  }\n"
104558cb2eddSDaniel Jasper                "};");
104641368e9eSDaniel Jasper   verifyFormat("{\n"
104741368e9eSDaniel Jasper                "  var someVariable = function(x) {\n"
104841368e9eSDaniel Jasper                "    return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
104941368e9eSDaniel Jasper                "  };\n"
105041368e9eSDaniel Jasper                "}");
10517325aee1SDaniel Jasper   verifyFormat("someLooooooooongFunction(\n"
10527325aee1SDaniel Jasper                "    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
10537325aee1SDaniel Jasper                "    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
10547325aee1SDaniel Jasper                "    function(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n"
10557325aee1SDaniel Jasper                "      // code\n"
10567325aee1SDaniel Jasper                "    });");
10575f3ea477SDaniel Jasper 
10585217a8b8SDaniel Jasper   verifyFormat("return {\n"
10595217a8b8SDaniel Jasper                "  a: function SomeFunction() {\n"
10605217a8b8SDaniel Jasper                "    // ...\n"
10615217a8b8SDaniel Jasper                "    return 1;\n"
10625217a8b8SDaniel Jasper                "  }\n"
10635217a8b8SDaniel Jasper                "};");
106411a0ac66SDaniel Jasper   verifyFormat("this.someObject.doSomething(aaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
106511a0ac66SDaniel Jasper                "    .then(goog.bind(function(aaaaaaaaaaa) {\n"
106611a0ac66SDaniel Jasper                "      someFunction();\n"
106711a0ac66SDaniel Jasper                "      someFunction();\n"
106811a0ac66SDaniel Jasper                "    }, this), aaaaaaaaaaaaaaaaa);");
106911a0ac66SDaniel Jasper 
10706501f7e8SDaniel Jasper   verifyFormat("someFunction(goog.bind(function() {\n"
107111a0ac66SDaniel Jasper                "  doSomething();\n"
107211a0ac66SDaniel Jasper                "  doSomething();\n"
10736501f7e8SDaniel Jasper                "}, this), goog.bind(function() {\n"
107411a0ac66SDaniel Jasper                "  doSomething();\n"
107511a0ac66SDaniel Jasper                "  doSomething();\n"
107611a0ac66SDaniel Jasper                "}, this));");
10771699eca1SDaniel Jasper 
107851c868e9SDaniel Jasper   verifyFormat("SomeFunction(function() {\n"
107951c868e9SDaniel Jasper                "  foo();\n"
108051c868e9SDaniel Jasper                "  bar();\n"
108151c868e9SDaniel Jasper                "}.bind(this));");
108251c868e9SDaniel Jasper 
1083b2f06eaeSMartin Probst   verifyFormat("SomeFunction((function() {\n"
1084b2f06eaeSMartin Probst                "               foo();\n"
1085b2f06eaeSMartin Probst                "               bar();\n"
1086b2f06eaeSMartin Probst                "             }).bind(this));");
1087b2f06eaeSMartin Probst 
10881699eca1SDaniel Jasper   // FIXME: This is bad, we should be wrapping before "function() {".
10891699eca1SDaniel Jasper   verifyFormat("someFunction(function() {\n"
10901699eca1SDaniel Jasper                "  doSomething();  // break\n"
10911699eca1SDaniel Jasper                "})\n"
10921699eca1SDaniel Jasper                "    .doSomethingElse(\n"
10931699eca1SDaniel Jasper                "        // break\n"
10941699eca1SDaniel Jasper                "    );");
109528d8a5abSDaniel Jasper 
109628d8a5abSDaniel Jasper   Style.ColumnLimit = 33;
109728d8a5abSDaniel Jasper   verifyFormat("f({a: function() { return 1; }});", Style);
109828d8a5abSDaniel Jasper   Style.ColumnLimit = 32;
109928d8a5abSDaniel Jasper   verifyFormat("f({\n"
110028d8a5abSDaniel Jasper                "  a: function() { return 1; }\n"
110128d8a5abSDaniel Jasper                "});",
110228d8a5abSDaniel Jasper                Style);
110379dffb41SDaniel Jasper }
110479dffb41SDaniel Jasper 
TEST_F(FormatTestJS,DontWrapEmptyLiterals)1105cde9815dSMartin Probst TEST_F(FormatTestJS, DontWrapEmptyLiterals) {
1106cde9815dSMartin Probst   verifyFormat("(aaaaaaaaaaaaaaaaaaaaa.getData as jasmine.Spy)\n"
1107cde9815dSMartin Probst                "    .and.returnValue(Observable.of([]));");
1108cde9815dSMartin Probst   verifyFormat("(aaaaaaaaaaaaaaaaaaaaa.getData as jasmine.Spy)\n"
1109cde9815dSMartin Probst                "    .and.returnValue(Observable.of({}));");
1110cde9815dSMartin Probst   verifyFormat("(aaaaaaaaaaaaaaaaaaaaa.getData as jasmine.Spy)\n"
1111cde9815dSMartin Probst                "    .and.returnValue(Observable.of(()));");
1112cde9815dSMartin Probst }
1113cde9815dSMartin Probst 
TEST_F(FormatTestJS,InliningFunctionLiterals)111467f8ad25SDaniel Jasper TEST_F(FormatTestJS, InliningFunctionLiterals) {
111567f8ad25SDaniel Jasper   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
111667f8ad25SDaniel Jasper   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
111767f8ad25SDaniel Jasper   verifyFormat("var func = function() {\n"
111867f8ad25SDaniel Jasper                "  return 1;\n"
111967f8ad25SDaniel Jasper                "};",
112067f8ad25SDaniel Jasper                Style);
112167f8ad25SDaniel Jasper   verifyFormat("var func = doSomething(function() { return 1; });", Style);
112267f8ad25SDaniel Jasper   verifyFormat("var outer = function() {\n"
112367f8ad25SDaniel Jasper                "  var inner = function() { return 1; }\n"
112467f8ad25SDaniel Jasper                "};",
112567f8ad25SDaniel Jasper                Style);
112667f8ad25SDaniel Jasper   verifyFormat("function outer1(a, b) {\n"
112767f8ad25SDaniel Jasper                "  function inner1(a, b) { return a; }\n"
112867f8ad25SDaniel Jasper                "}",
112967f8ad25SDaniel Jasper                Style);
113067f8ad25SDaniel Jasper 
113167f8ad25SDaniel Jasper   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
113267f8ad25SDaniel Jasper   verifyFormat("var func = function() { return 1; };", Style);
113367f8ad25SDaniel Jasper   verifyFormat("var func = doSomething(function() { return 1; });", Style);
113467f8ad25SDaniel Jasper   verifyFormat(
113567f8ad25SDaniel Jasper       "var outer = function() { var inner = function() { return 1; } };",
113667f8ad25SDaniel Jasper       Style);
113767f8ad25SDaniel Jasper   verifyFormat("function outer1(a, b) {\n"
113867f8ad25SDaniel Jasper                "  function inner1(a, b) { return a; }\n"
113967f8ad25SDaniel Jasper                "}",
114067f8ad25SDaniel Jasper                Style);
114167f8ad25SDaniel Jasper 
114267f8ad25SDaniel Jasper   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
114367f8ad25SDaniel Jasper   verifyFormat("var func = function() {\n"
114467f8ad25SDaniel Jasper                "  return 1;\n"
114567f8ad25SDaniel Jasper                "};",
114667f8ad25SDaniel Jasper                Style);
114767f8ad25SDaniel Jasper   verifyFormat("var func = doSomething(function() {\n"
114867f8ad25SDaniel Jasper                "  return 1;\n"
114967f8ad25SDaniel Jasper                "});",
115067f8ad25SDaniel Jasper                Style);
115167f8ad25SDaniel Jasper   verifyFormat("var outer = function() {\n"
115267f8ad25SDaniel Jasper                "  var inner = function() {\n"
115367f8ad25SDaniel Jasper                "    return 1;\n"
115467f8ad25SDaniel Jasper                "  }\n"
115567f8ad25SDaniel Jasper                "};",
115667f8ad25SDaniel Jasper                Style);
115767f8ad25SDaniel Jasper   verifyFormat("function outer1(a, b) {\n"
115867f8ad25SDaniel Jasper                "  function inner1(a, b) {\n"
115967f8ad25SDaniel Jasper                "    return a;\n"
116067f8ad25SDaniel Jasper                "  }\n"
116167f8ad25SDaniel Jasper                "}",
116267f8ad25SDaniel Jasper                Style);
116371e57454SDaniel Jasper 
116471e57454SDaniel Jasper   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
116571e57454SDaniel Jasper   verifyFormat("var func = function() {\n"
116671e57454SDaniel Jasper                "  return 1;\n"
116771e57454SDaniel Jasper                "};",
116871e57454SDaniel Jasper                Style);
116967f8ad25SDaniel Jasper }
117067f8ad25SDaniel Jasper 
TEST_F(FormatTestJS,MultipleFunctionLiterals)1171114a2bc9SDaniel Jasper TEST_F(FormatTestJS, MultipleFunctionLiterals) {
117228d8a5abSDaniel Jasper   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
117328d8a5abSDaniel Jasper   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
1174114a2bc9SDaniel Jasper   verifyFormat("promise.then(\n"
1175114a2bc9SDaniel Jasper                "    function success() {\n"
1176114a2bc9SDaniel Jasper                "      doFoo();\n"
1177114a2bc9SDaniel Jasper                "      doBar();\n"
1178114a2bc9SDaniel Jasper                "    },\n"
1179114a2bc9SDaniel Jasper                "    function error() {\n"
1180114a2bc9SDaniel Jasper                "      doFoo();\n"
1181114a2bc9SDaniel Jasper                "      doBaz();\n"
1182114a2bc9SDaniel Jasper                "    },\n"
1183114a2bc9SDaniel Jasper                "    []);\n");
1184114a2bc9SDaniel Jasper   verifyFormat("promise.then(\n"
1185114a2bc9SDaniel Jasper                "    function success() {\n"
1186114a2bc9SDaniel Jasper                "      doFoo();\n"
1187114a2bc9SDaniel Jasper                "      doBar();\n"
1188114a2bc9SDaniel Jasper                "    },\n"
1189114a2bc9SDaniel Jasper                "    [],\n"
1190114a2bc9SDaniel Jasper                "    function error() {\n"
1191114a2bc9SDaniel Jasper                "      doFoo();\n"
1192114a2bc9SDaniel Jasper                "      doBaz();\n"
1193114a2bc9SDaniel Jasper                "    });\n");
11946501f7e8SDaniel Jasper   verifyFormat("promise.then(\n"
11956501f7e8SDaniel Jasper                "    [],\n"
1196114a2bc9SDaniel Jasper                "    function success() {\n"
1197114a2bc9SDaniel Jasper                "      doFoo();\n"
1198114a2bc9SDaniel Jasper                "      doBar();\n"
1199114a2bc9SDaniel Jasper                "    },\n"
1200114a2bc9SDaniel Jasper                "    function error() {\n"
1201114a2bc9SDaniel Jasper                "      doFoo();\n"
1202114a2bc9SDaniel Jasper                "      doBaz();\n"
1203114a2bc9SDaniel Jasper                "    });\n");
12041779d438SDaniel Jasper 
12051779d438SDaniel Jasper   verifyFormat("getSomeLongPromise()\n"
12061779d438SDaniel Jasper                "    .then(function(value) { body(); })\n"
120711a0ac66SDaniel Jasper                "    .thenCatch(function(error) {\n"
120811a0ac66SDaniel Jasper                "      body();\n"
120911a0ac66SDaniel Jasper                "      body();\n"
121028d8a5abSDaniel Jasper                "    });",
121128d8a5abSDaniel Jasper                Style);
12121779d438SDaniel Jasper   verifyFormat("getSomeLongPromise()\n"
12131779d438SDaniel Jasper                "    .then(function(value) {\n"
12141779d438SDaniel Jasper                "      body();\n"
12151779d438SDaniel Jasper                "      body();\n"
12161779d438SDaniel Jasper                "    })\n"
12171779d438SDaniel Jasper                "    .thenCatch(function(error) {\n"
12181779d438SDaniel Jasper                "      body();\n"
12191779d438SDaniel Jasper                "      body();\n"
12201779d438SDaniel Jasper                "    });");
122111a0ac66SDaniel Jasper 
1222acf67e3eSDaniel Jasper   verifyFormat("getSomeLongPromise()\n"
1223acf67e3eSDaniel Jasper                "    .then(function(value) { body(); })\n"
122428d8a5abSDaniel Jasper                "    .thenCatch(function(error) { body(); });",
122528d8a5abSDaniel Jasper                Style);
122628024560SDaniel Jasper 
122728024560SDaniel Jasper   verifyFormat("return [aaaaaaaaaaaaaaaaaaaaaa]\n"
122828024560SDaniel Jasper                "    .aaaaaaa(function() {\n"
122928024560SDaniel Jasper                "      //\n"
123028024560SDaniel Jasper                "    })\n"
123128024560SDaniel Jasper                "    .bbbbbb();");
1232114a2bc9SDaniel Jasper }
1233114a2bc9SDaniel Jasper 
TEST_F(FormatTestJS,ArrowFunctions)123479e06081SManuel Klimek TEST_F(FormatTestJS, ArrowFunctions) {
123579e06081SManuel Klimek   verifyFormat("var x = (a) => {\n"
123602656f29SMartin Probst                "  x;\n"
123779e06081SManuel Klimek                "  return a;\n"
123802656f29SMartin Probst                "};\n");
123979e06081SManuel Klimek   verifyFormat("var x = (a) => {\n"
124028d8a5abSDaniel Jasper                "  function y() {\n"
124128d8a5abSDaniel Jasper                "    return 42;\n"
124228d8a5abSDaniel Jasper                "  }\n"
124379e06081SManuel Klimek                "  return a;\n"
124479e06081SManuel Klimek                "};");
124579e06081SManuel Klimek   verifyFormat("var x = (a: type): {some: type} => {\n"
124602656f29SMartin Probst                "  y;\n"
124779e06081SManuel Klimek                "  return a;\n"
124879e06081SManuel Klimek                "};");
124979e06081SManuel Klimek   verifyFormat("var x = (a) => a;");
1250e497beddSDaniel Jasper   verifyFormat("return () => [];");
12513c306e89SDaniel Jasper   verifyFormat("var aaaaaaaaaaaaaaaaaaaa = {\n"
12523c306e89SDaniel Jasper                "  aaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n"
12533c306e89SDaniel Jasper                "      (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
12543c306e89SDaniel Jasper                "       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) =>\n"
12553b0f3045SDaniel Jasper                "          aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
12563c306e89SDaniel Jasper                "};");
12576501f7e8SDaniel Jasper   verifyFormat("var a = a.aaaaaaa(\n"
12586501f7e8SDaniel Jasper                "    (a: a) => aaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) &&\n"
12596501f7e8SDaniel Jasper                "        aaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
12606501f7e8SDaniel Jasper   verifyFormat("var a = a.aaaaaaa(\n"
12616501f7e8SDaniel Jasper                "    (a: a) => aaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) ?\n"
12623b0f3045SDaniel Jasper                "        aaaaaaaaaaaaaaaaaaaaa(bbbbbbb) :\n"
12633b0f3045SDaniel Jasper                "        aaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
12641699eca1SDaniel Jasper 
12651699eca1SDaniel Jasper   // FIXME: This is bad, we should be wrapping before "() => {".
12661699eca1SDaniel Jasper   verifyFormat("someFunction(() => {\n"
12671699eca1SDaniel Jasper                "  doSomething();  // break\n"
12681699eca1SDaniel Jasper                "})\n"
12691699eca1SDaniel Jasper                "    .doSomethingElse(\n"
12701699eca1SDaniel Jasper                "        // break\n"
12711699eca1SDaniel Jasper                "    );");
1272ec36326dSMartin Probst   verifyFormat("const f = (x: string|null): string|null => {\n"
127302656f29SMartin Probst                "  y;\n"
1274ec36326dSMartin Probst                "  return x;\n"
1275ec36326dSMartin Probst                "}\n");
127679e06081SManuel Klimek }
127779e06081SManuel Klimek 
TEST_F(FormatTestJS,ArrowFunctionStyle)127802656f29SMartin Probst TEST_F(FormatTestJS, ArrowFunctionStyle) {
127902656f29SMartin Probst   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
128002656f29SMartin Probst   Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
128102656f29SMartin Probst   verifyFormat("const arr = () => { x; };", Style);
128202656f29SMartin Probst   verifyFormat("const arrInlineAll = () => {};", Style);
128302656f29SMartin Probst   Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_None;
128402656f29SMartin Probst   verifyFormat("const arr = () => {\n"
128502656f29SMartin Probst                "  x;\n"
128602656f29SMartin Probst                "};",
128702656f29SMartin Probst                Style);
128802656f29SMartin Probst   verifyFormat("const arrInlineNone = () => {\n"
128902656f29SMartin Probst                "};",
129002656f29SMartin Probst                Style);
129102656f29SMartin Probst   Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
129202656f29SMartin Probst   verifyFormat("const arr = () => {\n"
129302656f29SMartin Probst                "  x;\n"
129402656f29SMartin Probst                "};",
129502656f29SMartin Probst                Style);
1296ece7e95fSmydeveloperday   verifyFormat("const arrInlineEmpty = () => {};", Style);
129702656f29SMartin Probst   Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Inline;
129802656f29SMartin Probst   verifyFormat("const arr = () => {\n"
129902656f29SMartin Probst                "  x;\n"
130002656f29SMartin Probst                "};",
130102656f29SMartin Probst                Style);
1302ece7e95fSmydeveloperday   verifyFormat("foo(() => {});", Style);
130302656f29SMartin Probst   verifyFormat("const arrInlineInline = () => {};", Style);
130402656f29SMartin Probst }
130502656f29SMartin Probst 
TEST_F(FormatTestJS,ReturnStatements)1306166c19bdSDaniel Jasper TEST_F(FormatTestJS, ReturnStatements) {
130767f8ad25SDaniel Jasper   verifyFormat("function() {\n"
130867f8ad25SDaniel Jasper                "  return [hello, world];\n"
130967f8ad25SDaniel Jasper                "}");
1310166c19bdSDaniel Jasper }
1311166c19bdSDaniel Jasper 
TEST_F(FormatTestJS,ForLoops)1312f95b1f45SDaniel Jasper TEST_F(FormatTestJS, ForLoops) {
1313f95b1f45SDaniel Jasper   verifyFormat("for (var i in [2, 3]) {\n"
1314f95b1f45SDaniel Jasper                "}");
1315b7fda115SDaniel Jasper   verifyFormat("for (var i of [2, 3]) {\n"
1316b7fda115SDaniel Jasper                "}");
1317acffeb8bSDaniel Jasper   verifyFormat("for (let {a, b} of x) {\n"
1318acffeb8bSDaniel Jasper                "}");
131970cec59eSMartin Probst   verifyFormat("for (let {a, b} of [x]) {\n"
132070cec59eSMartin Probst                "}");
132170cec59eSMartin Probst   verifyFormat("for (let [a, b] of [x]) {\n"
132270cec59eSMartin Probst                "}");
1323acffeb8bSDaniel Jasper   verifyFormat("for (let {a, b} in x) {\n"
1324acffeb8bSDaniel Jasper                "}");
1325f95b1f45SDaniel Jasper }
1326f95b1f45SDaniel Jasper 
TEST_F(FormatTestJS,WrapRespectsAutomaticSemicolonInsertion)13271dcbbcfcSDaniel Jasper TEST_F(FormatTestJS, WrapRespectsAutomaticSemicolonInsertion) {
13284c0bf703SDaniel Jasper   // The following statements must not wrap, as otherwise the program meaning
13294c0bf703SDaniel Jasper   // would change due to automatic semicolon insertion.
13304c0bf703SDaniel Jasper   // See http://www.ecma-international.org/ecma-262/5.1/#sec-7.9.1.
13314c0bf703SDaniel Jasper   verifyFormat("return aaaaa;", getGoogleJSStyleWithColumns(10));
1332a5968aadSMartin Probst   verifyFormat("yield aaaaa;", getGoogleJSStyleWithColumns(10));
133356ff7aaaSMartin Probst   verifyFormat("return /* hello! */ aaaaa;", getGoogleJSStyleWithColumns(10));
13344c0bf703SDaniel Jasper   verifyFormat("continue aaaaa;", getGoogleJSStyleWithColumns(10));
133556ff7aaaSMartin Probst   verifyFormat("continue /* hello! */ aaaaa;", getGoogleJSStyleWithColumns(10));
13364c0bf703SDaniel Jasper   verifyFormat("break aaaaa;", getGoogleJSStyleWithColumns(10));
13374c0bf703SDaniel Jasper   verifyFormat("throw aaaaa;", getGoogleJSStyleWithColumns(10));
13384c0bf703SDaniel Jasper   verifyFormat("aaaaaaaaa++;", getGoogleJSStyleWithColumns(10));
13394c0bf703SDaniel Jasper   verifyFormat("aaaaaaaaa--;", getGoogleJSStyleWithColumns(10));
134011a87653SDaniel Jasper   verifyFormat("return [\n"
134111a87653SDaniel Jasper                "  aaa\n"
134211a87653SDaniel Jasper                "];",
134311a87653SDaniel Jasper                getGoogleJSStyleWithColumns(12));
1344a81dd0b6SMartin Probst   verifyFormat("class X {\n"
1345a81dd0b6SMartin Probst                "  readonly ratherLongField =\n"
1346a81dd0b6SMartin Probst                "      1;\n"
1347a81dd0b6SMartin Probst                "}",
1348a81dd0b6SMartin Probst                "class X {\n"
1349a81dd0b6SMartin Probst                "  readonly ratherLongField = 1;\n"
1350a81dd0b6SMartin Probst                "}",
1351a81dd0b6SMartin Probst                getGoogleJSStyleWithColumns(20));
13520a19d433SMartin Probst   verifyFormat("const x = (5 + 9)\n"
13530a19d433SMartin Probst                "const y = 3\n",
13540a19d433SMartin Probst                "const x = (   5 +    9)\n"
13550a19d433SMartin Probst                "const y = 3\n");
135627b6603fSMartin Probst   // Ideally the foo() bit should be indented relative to the async function().
135727b6603fSMartin Probst   verifyFormat("async function\n"
135827b6603fSMartin Probst                "foo() {}",
135927b6603fSMartin Probst                getGoogleJSStyleWithColumns(10));
136027b6603fSMartin Probst   verifyFormat("await theReckoning;", getGoogleJSStyleWithColumns(10));
1361f8e1f5c7SMartin Probst   verifyFormat("some['a']['b']", getGoogleJSStyleWithColumns(10));
1362f8e1f5c7SMartin Probst   verifyFormat("x = (a['a']\n"
13637ebad4eaSMartin Probst                "      ['b']);",
13647ebad4eaSMartin Probst                getGoogleJSStyleWithColumns(10));
13657ebad4eaSMartin Probst   verifyFormat("function f() {\n"
13667ebad4eaSMartin Probst                "  return foo.bar(\n"
13677ebad4eaSMartin Probst                "      (param): param is {\n"
13687ebad4eaSMartin Probst                "        a: SomeType\n"
13697ebad4eaSMartin Probst                "      }&ABC => 1)\n"
13707ebad4eaSMartin Probst                "}",
13717ebad4eaSMartin Probst                getGoogleJSStyleWithColumns(25));
13724c0bf703SDaniel Jasper }
13734c0bf703SDaniel Jasper 
TEST_F(FormatTestJS,AddsIsTheDictKeyOnNewline)1374c1631019SKrasimir Georgiev TEST_F(FormatTestJS, AddsIsTheDictKeyOnNewline) {
1375c1631019SKrasimir Georgiev   // Do not confuse is, the dict key with is, the type matcher. Put is, the dict
1376c1631019SKrasimir Georgiev   // key, on a newline.
1377c1631019SKrasimir Georgiev   verifyFormat("Polymer({\n"
1378c1631019SKrasimir Georgiev                "  is: '',  //\n"
1379c1631019SKrasimir Georgiev                "  rest: 1\n"
1380c1631019SKrasimir Georgiev                "});",
1381c1631019SKrasimir Georgiev                getGoogleJSStyleWithColumns(20));
1382c1631019SKrasimir Georgiev }
1383c1631019SKrasimir Georgiev 
TEST_F(FormatTestJS,AutomaticSemicolonInsertionHeuristic)13841dcbbcfcSDaniel Jasper TEST_F(FormatTestJS, AutomaticSemicolonInsertionHeuristic) {
13851dcbbcfcSDaniel Jasper   verifyFormat("a\n"
13861dcbbcfcSDaniel Jasper                "b;",
13871dcbbcfcSDaniel Jasper                " a \n"
13881dcbbcfcSDaniel Jasper                " b ;");
13891dcbbcfcSDaniel Jasper   verifyFormat("a()\n"
13901dcbbcfcSDaniel Jasper                "b;",
13911dcbbcfcSDaniel Jasper                " a ()\n"
13921dcbbcfcSDaniel Jasper                " b ;");
13931dcbbcfcSDaniel Jasper   verifyFormat("a[b]\n"
13941dcbbcfcSDaniel Jasper                "c;",
13951dcbbcfcSDaniel Jasper                "a [b]\n"
13961dcbbcfcSDaniel Jasper                "c ;");
13971dcbbcfcSDaniel Jasper   verifyFormat("1\n"
13981dcbbcfcSDaniel Jasper                "a;",
13991dcbbcfcSDaniel Jasper                "1 \n"
14001dcbbcfcSDaniel Jasper                "a ;");
14011dcbbcfcSDaniel Jasper   verifyFormat("a\n"
14021dcbbcfcSDaniel Jasper                "1;",
14031dcbbcfcSDaniel Jasper                "a \n"
14041dcbbcfcSDaniel Jasper                "1 ;");
14051dcbbcfcSDaniel Jasper   verifyFormat("a\n"
14061dcbbcfcSDaniel Jasper                "'x';",
14071dcbbcfcSDaniel Jasper                "a \n"
14081dcbbcfcSDaniel Jasper                " 'x';");
14091dcbbcfcSDaniel Jasper   verifyFormat("a++\n"
14101dcbbcfcSDaniel Jasper                "b;",
14111dcbbcfcSDaniel Jasper                "a ++\n"
14121dcbbcfcSDaniel Jasper                "b ;");
14131dcbbcfcSDaniel Jasper   verifyFormat("a\n"
14141dcbbcfcSDaniel Jasper                "!b && c;",
14151dcbbcfcSDaniel Jasper                "a \n"
14161dcbbcfcSDaniel Jasper                " ! b && c;");
14171dcbbcfcSDaniel Jasper   verifyFormat("a\n"
14181dcbbcfcSDaniel Jasper                "if (1) f();",
14191dcbbcfcSDaniel Jasper                " a\n"
14201dcbbcfcSDaniel Jasper                " if (1) f();");
14211dcbbcfcSDaniel Jasper   verifyFormat("a\n"
14221dcbbcfcSDaniel Jasper                "class X {}",
14231dcbbcfcSDaniel Jasper                " a\n"
14241dcbbcfcSDaniel Jasper                " class X {}");
14251dcbbcfcSDaniel Jasper   verifyFormat("var a", "var\n"
14261dcbbcfcSDaniel Jasper                         "a");
14271dcbbcfcSDaniel Jasper   verifyFormat("x instanceof String", "x\n"
14281dcbbcfcSDaniel Jasper                                       "instanceof\n"
14291dcbbcfcSDaniel Jasper                                       "String");
1430bbffeac5SMartin Probst   verifyFormat("function f(@Foo bar) {}", "function f(@Foo\n"
1431bbffeac5SMartin Probst                                           "  bar) {}");
14327e0f25b2SMartin Probst   verifyFormat("function f(@Foo(Param) bar) {}", "function f(@Foo(Param)\n"
14337e0f25b2SMartin Probst                                                  "  bar) {}");
1434b9316ff8SMartin Probst   verifyFormat("a = true\n"
1435b9316ff8SMartin Probst                "return 1",
1436b9316ff8SMartin Probst                "a = true\n"
1437b9316ff8SMartin Probst                "  return   1");
1438b9316ff8SMartin Probst   verifyFormat("a = 's'\n"
1439b9316ff8SMartin Probst                "return 1",
1440b9316ff8SMartin Probst                "a = 's'\n"
1441b9316ff8SMartin Probst                "  return   1");
1442b9316ff8SMartin Probst   verifyFormat("a = null\n"
1443b9316ff8SMartin Probst                "return 1",
1444b9316ff8SMartin Probst                "a = null\n"
1445b9316ff8SMartin Probst                "  return   1");
1446e6b5b34fSMartin Probst   // Below "class Y {}" should ideally be on its own line.
1447ece7e95fSmydeveloperday   verifyFormat("x = {\n"
1448fd18ec58SMartin Probst                "  a: 1\n"
1449e6b5b34fSMartin Probst                "} class Y {}",
1450d40bca43SMartin Probst                "  x  =  {a  : 1}\n"
1451d40bca43SMartin Probst                "   class  Y {  }");
1452ece7e95fSmydeveloperday   verifyFormat("if (x) {\n"
1453e6b5b34fSMartin Probst                "}\n"
1454e6b5b34fSMartin Probst                "return 1",
1455e6b5b34fSMartin Probst                "if (x) {}\n"
1456e6b5b34fSMartin Probst                " return   1");
1457ece7e95fSmydeveloperday   verifyFormat("if (x) {\n"
1458e6b5b34fSMartin Probst                "}\n"
1459e6b5b34fSMartin Probst                "class X {}",
1460e6b5b34fSMartin Probst                "if (x) {}\n"
1461e6b5b34fSMartin Probst                " class X {}");
1462d40bca43SMartin Probst }
1463d40bca43SMartin Probst 
TEST_F(FormatTestJS,ImportExportASI)1464d40bca43SMartin Probst TEST_F(FormatTestJS, ImportExportASI) {
1465ece7e95fSmydeveloperday   verifyFormat("import {x} from 'y'\n"
1466d40bca43SMartin Probst                "export function z() {}",
1467d40bca43SMartin Probst                "import   {x} from 'y'\n"
1468d40bca43SMartin Probst                "  export function z() {}");
1469e6b5b34fSMartin Probst   // Below "class Y {}" should ideally be on its own line.
1470ece7e95fSmydeveloperday   verifyFormat("export {x} class Y {}", "  export {x}\n"
1471d40bca43SMartin Probst                                         "  class  Y {\n}");
1472ece7e95fSmydeveloperday   verifyFormat("if (x) {\n"
1473e6b5b34fSMartin Probst                "}\n"
1474e6b5b34fSMartin Probst                "export class Y {}",
1475e6b5b34fSMartin Probst                "if ( x ) { }\n"
1476e6b5b34fSMartin Probst                " export class Y {}");
14771dcbbcfcSDaniel Jasper }
14781dcbbcfcSDaniel Jasper 
TEST_F(FormatTestJS,ClosureStyleCasts)147979e06081SManuel Klimek TEST_F(FormatTestJS, ClosureStyleCasts) {
1480484033b1SDaniel Jasper   verifyFormat("var x = /** @type {foo} */ (bar);");
1481484033b1SDaniel Jasper }
1482484033b1SDaniel Jasper 
TEST_F(FormatTestJS,TryCatch)148304a71a45SDaniel Jasper TEST_F(FormatTestJS, TryCatch) {
148404a71a45SDaniel Jasper   verifyFormat("try {\n"
148504a71a45SDaniel Jasper                "  f();\n"
148604a71a45SDaniel Jasper                "} catch (e) {\n"
148704a71a45SDaniel Jasper                "  g();\n"
148804a71a45SDaniel Jasper                "} finally {\n"
148904a71a45SDaniel Jasper                "  h();\n"
149004a71a45SDaniel Jasper                "}");
14918f2e94c8SDaniel Jasper 
14928f2e94c8SDaniel Jasper   // But, of course, "catch" is a perfectly fine function name in JavaScript.
14938f2e94c8SDaniel Jasper   verifyFormat("someObject.catch();");
149479121238SDaniel Jasper   verifyFormat("someObject.new();");
149504a71a45SDaniel Jasper }
149604a71a45SDaniel Jasper 
TEST_F(FormatTestJS,StringLiteralConcatenation)149749802ef9SDaniel Jasper TEST_F(FormatTestJS, StringLiteralConcatenation) {
149849802ef9SDaniel Jasper   verifyFormat("var literal = 'hello ' +\n"
149949802ef9SDaniel Jasper                "    'world';");
150049802ef9SDaniel Jasper }
150149802ef9SDaniel Jasper 
TEST_F(FormatTestJS,RegexLiteralClassification)1502f9ae312fSDaniel Jasper TEST_F(FormatTestJS, RegexLiteralClassification) {
1503f9ae312fSDaniel Jasper   // Regex literals.
1504f9ae312fSDaniel Jasper   verifyFormat("var regex = /abc/;");
1505f9ae312fSDaniel Jasper   verifyFormat("f(/abc/);");
1506f9ae312fSDaniel Jasper   verifyFormat("f(abc, /abc/);");
1507f9ae312fSDaniel Jasper   verifyFormat("some_map[/abc/];");
1508f9ae312fSDaniel Jasper   verifyFormat("var x = a ? /abc/ : /abc/;");
1509f9ae312fSDaniel Jasper   verifyFormat("for (var i = 0; /abc/.test(s[i]); i++) {\n}");
1510f9ae312fSDaniel Jasper   verifyFormat("var x = !/abc/.test(y);");
151116282993SMartin Probst   verifyFormat("var x = foo()! / 10;");
1512f9ae312fSDaniel Jasper   verifyFormat("var x = a && /abc/.test(y);");
1513f9ae312fSDaniel Jasper   verifyFormat("var x = a || /abc/.test(y);");
1514f9ae312fSDaniel Jasper   verifyFormat("var x = a + /abc/.search(y);");
1515c553ae13SDaniel Jasper   verifyFormat("/abc/.search(y);");
1516f7405c12SDaniel Jasper   verifyFormat("var regexs = {/abc/, /abc/};");
1517f7405c12SDaniel Jasper   verifyFormat("return /abc/;");
1518f9ae312fSDaniel Jasper 
1519f9ae312fSDaniel Jasper   // Not regex literals.
1520f9ae312fSDaniel Jasper   verifyFormat("var a = a / 2 + b / 3;");
1521265309e3SDaniel Jasper   verifyFormat("var a = a++ / 2;");
1522265309e3SDaniel Jasper   // Prefix unary can operate on regex literals, not that it makes sense.
1523265309e3SDaniel Jasper   verifyFormat("var a = ++/a/;");
1524265309e3SDaniel Jasper 
1525265309e3SDaniel Jasper   // This is a known issue, regular expressions are incorrectly detected if
1526265309e3SDaniel Jasper   // directly following a closing parenthesis.
1527265309e3SDaniel Jasper   verifyFormat("if (foo) / bar /.exec(baz);");
1528f9ae312fSDaniel Jasper }
1529f9ae312fSDaniel Jasper 
TEST_F(FormatTestJS,RegexLiteralSpecialCharacters)1530f9ae312fSDaniel Jasper TEST_F(FormatTestJS, RegexLiteralSpecialCharacters) {
153169694b06SDaniel Jasper   verifyFormat("var regex = /=/;");
1532f9ae312fSDaniel Jasper   verifyFormat("var regex = /a*/;");
1533f9ae312fSDaniel Jasper   verifyFormat("var regex = /a+/;");
1534f9ae312fSDaniel Jasper   verifyFormat("var regex = /a?/;");
1535f9ae312fSDaniel Jasper   verifyFormat("var regex = /.a./;");
1536f9ae312fSDaniel Jasper   verifyFormat("var regex = /a\\*/;");
1537f9ae312fSDaniel Jasper   verifyFormat("var regex = /^a$/;");
1538f9ae312fSDaniel Jasper   verifyFormat("var regex = /\\/a/;");
1539f9ae312fSDaniel Jasper   verifyFormat("var regex = /(?:x)/;");
1540f9ae312fSDaniel Jasper   verifyFormat("var regex = /x(?=y)/;");
1541f9ae312fSDaniel Jasper   verifyFormat("var regex = /x(?!y)/;");
1542f9ae312fSDaniel Jasper   verifyFormat("var regex = /x|y/;");
1543f9ae312fSDaniel Jasper   verifyFormat("var regex = /a{2}/;");
1544f9ae312fSDaniel Jasper   verifyFormat("var regex = /a{1,3}/;");
15458d0e2234SDaniel Jasper 
1546f9ae312fSDaniel Jasper   verifyFormat("var regex = /[abc]/;");
1547f9ae312fSDaniel Jasper   verifyFormat("var regex = /[^abc]/;");
1548f9ae312fSDaniel Jasper   verifyFormat("var regex = /[\\b]/;");
15498d0e2234SDaniel Jasper   verifyFormat("var regex = /[/]/;");
15508d0e2234SDaniel Jasper   verifyFormat("var regex = /[\\/]/;");
15518d0e2234SDaniel Jasper   verifyFormat("var regex = /\\[/;");
15528d0e2234SDaniel Jasper   verifyFormat("var regex = /\\\\[/]/;");
1553265309e3SDaniel Jasper   verifyFormat("var regex = /}[\"]/;");
1554265309e3SDaniel Jasper   verifyFormat("var regex = /}[/\"]/;");
1555265309e3SDaniel Jasper   verifyFormat("var regex = /}[\"/]/;");
15568d0e2234SDaniel Jasper 
1557f9ae312fSDaniel Jasper   verifyFormat("var regex = /\\b/;");
1558f9ae312fSDaniel Jasper   verifyFormat("var regex = /\\B/;");
1559f9ae312fSDaniel Jasper   verifyFormat("var regex = /\\d/;");
1560f9ae312fSDaniel Jasper   verifyFormat("var regex = /\\D/;");
1561f9ae312fSDaniel Jasper   verifyFormat("var regex = /\\f/;");
1562f9ae312fSDaniel Jasper   verifyFormat("var regex = /\\n/;");
1563f9ae312fSDaniel Jasper   verifyFormat("var regex = /\\r/;");
1564f9ae312fSDaniel Jasper   verifyFormat("var regex = /\\s/;");
1565f9ae312fSDaniel Jasper   verifyFormat("var regex = /\\S/;");
1566f9ae312fSDaniel Jasper   verifyFormat("var regex = /\\t/;");
1567f9ae312fSDaniel Jasper   verifyFormat("var regex = /\\v/;");
1568f9ae312fSDaniel Jasper   verifyFormat("var regex = /\\w/;");
1569f9ae312fSDaniel Jasper   verifyFormat("var regex = /\\W/;");
1570f9ae312fSDaniel Jasper   verifyFormat("var regex = /a(a)\\1/;");
1571f9ae312fSDaniel Jasper   verifyFormat("var regex = /\\0/;");
1572fb4333b0SDaniel Jasper   verifyFormat("var regex = /\\\\/g;");
1573fb4333b0SDaniel Jasper   verifyFormat("var regex = /\\a\\\\/g;");
1574fb4333b0SDaniel Jasper   verifyFormat("var regex = /\a\\//g;");
157523376259SDaniel Jasper   verifyFormat("var regex = /a\\//;\n"
157623376259SDaniel Jasper                "var x = 0;");
15771dcbbcfcSDaniel Jasper   verifyFormat("var regex = /'/g;", "var regex = /'/g ;");
15781dcbbcfcSDaniel Jasper   verifyFormat("var regex = /'/g;  //'", "var regex = /'/g ; //'");
15791dcbbcfcSDaniel Jasper   verifyFormat("var regex = /\\/*/;\n"
158049a9a283SDaniel Jasper                "var x = 0;",
15811dcbbcfcSDaniel Jasper                "var regex = /\\/*/;\n"
15821dcbbcfcSDaniel Jasper                "var x=0;");
15831dcbbcfcSDaniel Jasper   verifyFormat("var x = /a\\//;", "var x = /a\\//  \n;");
15846b8d26c2SDaniel Jasper   verifyFormat("var regex = /\"/;", getGoogleJSStyleWithColumns(16));
15856b8d26c2SDaniel Jasper   verifyFormat("var regex =\n"
15866b8d26c2SDaniel Jasper                "    /\"/;",
15876b8d26c2SDaniel Jasper                getGoogleJSStyleWithColumns(15));
1588f7372152SDaniel Jasper   verifyFormat("var regex =  //\n"
1589f7372152SDaniel Jasper                "    /a/;");
1590f144620cSDaniel Jasper   verifyFormat("var regexs = [\n"
1591f144620cSDaniel Jasper                "  /d/,   //\n"
1592f144620cSDaniel Jasper                "  /aa/,  //\n"
1593f144620cSDaniel Jasper                "];");
1594f9ae312fSDaniel Jasper }
1595f9ae312fSDaniel Jasper 
TEST_F(FormatTestJS,RegexLiteralModifiers)1596f9ae312fSDaniel Jasper TEST_F(FormatTestJS, RegexLiteralModifiers) {
1597f9ae312fSDaniel Jasper   verifyFormat("var regex = /abc/g;");
1598f9ae312fSDaniel Jasper   verifyFormat("var regex = /abc/i;");
1599f9ae312fSDaniel Jasper   verifyFormat("var regex = /abc/m;");
1600f9ae312fSDaniel Jasper   verifyFormat("var regex = /abc/y;");
1601f9ae312fSDaniel Jasper }
1602f9ae312fSDaniel Jasper 
TEST_F(FormatTestJS,RegexLiteralLength)1603f9ae312fSDaniel Jasper TEST_F(FormatTestJS, RegexLiteralLength) {
1604f9ae312fSDaniel Jasper   verifyFormat("var regex = /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
1605f9ae312fSDaniel Jasper                getGoogleJSStyleWithColumns(60));
1606f9ae312fSDaniel Jasper   verifyFormat("var regex =\n"
1607f9ae312fSDaniel Jasper                "    /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
1608f9ae312fSDaniel Jasper                getGoogleJSStyleWithColumns(60));
16090580ff0eSDaniel Jasper   verifyFormat("var regex = /\\xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
16100580ff0eSDaniel Jasper                getGoogleJSStyleWithColumns(50));
1611f9ae312fSDaniel Jasper }
1612f9ae312fSDaniel Jasper 
TEST_F(FormatTestJS,RegexLiteralExamples)1613f9ae312fSDaniel Jasper TEST_F(FormatTestJS, RegexLiteralExamples) {
1614f9ae312fSDaniel Jasper   verifyFormat("var regex = search.match(/(?:\?|&)times=([^?&]+)/i);");
1615f9ae312fSDaniel Jasper }
1616f9ae312fSDaniel Jasper 
TEST_F(FormatTestJS,IgnoresMpegTS)1617fa37b18fSMartin Probst TEST_F(FormatTestJS, IgnoresMpegTS) {
1618fa37b18fSMartin Probst   std::string MpegTS(200, ' ');
1619fa37b18fSMartin Probst   MpegTS.replace(0, strlen("nearlyLooks  +   like +   ts + code;  "),
1620fa37b18fSMartin Probst                  "nearlyLooks  +   like +   ts + code;  ");
1621fa37b18fSMartin Probst   MpegTS[0] = 0x47;
1622fa37b18fSMartin Probst   MpegTS[188] = 0x47;
1623fa37b18fSMartin Probst   verifyFormat(MpegTS, MpegTS);
1624fa37b18fSMartin Probst }
1625fa37b18fSMartin Probst 
TEST_F(FormatTestJS,TypeAnnotations)1626b10bdff3SDaniel Jasper TEST_F(FormatTestJS, TypeAnnotations) {
1627b10bdff3SDaniel Jasper   verifyFormat("var x: string;");
1628b9a4990aSDaniel Jasper   verifyFormat("var x: {a: string; b: number;} = {};");
1629b10bdff3SDaniel Jasper   verifyFormat("function x(): string {\n  return 'x';\n}");
163079e06081SManuel Klimek   verifyFormat("function x(): {x: string} {\n  return {x: 'x'};\n}");
1631b10bdff3SDaniel Jasper   verifyFormat("function x(y: string): string {\n  return 'x';\n}");
1632b10bdff3SDaniel Jasper   verifyFormat("for (var y: string in x) {\n  x();\n}");
1633b7fda115SDaniel Jasper   verifyFormat("for (var y: string of x) {\n  x();\n}");
1634b9a4990aSDaniel Jasper   verifyFormat("function x(y: {a?: number;} = {}): number {\n"
1635b9a4990aSDaniel Jasper                "  return 12;\n"
1636b9a4990aSDaniel Jasper                "}");
1637e8e27ca8SMartin Probst   verifyFormat("const x: Array<{a: number; b: string;}> = [];");
1638b10bdff3SDaniel Jasper   verifyFormat("((a: string, b: number): string => a + b);");
1639b10bdff3SDaniel Jasper   verifyFormat("var x: (y: number) => string;");
1640b10bdff3SDaniel Jasper   verifyFormat("var x: P<string, (a: number) => string>;");
164128d8a5abSDaniel Jasper   verifyFormat("var x = {\n"
164228d8a5abSDaniel Jasper                "  y: function(): z {\n"
164328d8a5abSDaniel Jasper                "    return 1;\n"
164428d8a5abSDaniel Jasper                "  }\n"
164528d8a5abSDaniel Jasper                "};");
164628d8a5abSDaniel Jasper   verifyFormat("var x = {\n"
164728d8a5abSDaniel Jasper                "  y: function(): {a: number} {\n"
164828d8a5abSDaniel Jasper                "    return 1;\n"
164928d8a5abSDaniel Jasper                "  }\n"
165028d8a5abSDaniel Jasper                "};");
1651f412e26dSDaniel Jasper   verifyFormat("function someFunc(args: string[]):\n"
1652f412e26dSDaniel Jasper                "    {longReturnValue: string[]} {}",
1653f412e26dSDaniel Jasper                getGoogleJSStyleWithColumns(60));
16543d934d36SDaniel Jasper   verifyFormat(
16553d934d36SDaniel Jasper       "var someValue = (v as aaaaaaaaaaaaaaaaaaaa<T>[])\n"
16563d934d36SDaniel Jasper       "                    .someFunction(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
1657ece7e95fSmydeveloperday   verifyFormat("const xIsALongIdent:\n"
1658ece7e95fSmydeveloperday                "    YJustBarelyFitsLinex[];",
1659ce2bd4dfSMartin Probst                getGoogleJSStyleWithColumns(20));
16605836472aSMartin Probst   verifyFormat("const x = {\n"
16615836472aSMartin Probst                "  y: 1\n"
16625836472aSMartin Probst                "} as const;");
1663b10bdff3SDaniel Jasper }
1664b10bdff3SDaniel Jasper 
TEST_F(FormatTestJS,UnionIntersectionTypes)166591b1d1abSDaniel Jasper TEST_F(FormatTestJS, UnionIntersectionTypes) {
166691b1d1abSDaniel Jasper   verifyFormat("let x: A|B = A | B;");
166791b1d1abSDaniel Jasper   verifyFormat("let x: A&B|C = A & B;");
166891b1d1abSDaniel Jasper   verifyFormat("let x: Foo<A|B> = new Foo<A|B>();");
166991b1d1abSDaniel Jasper   verifyFormat("function(x: A|B): C&D {}");
167091b1d1abSDaniel Jasper   verifyFormat("function(x: A|B = A | B): C&D {}");
16712ec2324fSMartin Probst   verifyFormat("function x(path: number|string) {}");
16722ec2324fSMartin Probst   verifyFormat("function x(): string|number {}");
16731b7f9804SMartin Probst   verifyFormat("type Foo = Bar|Baz;");
16741b7f9804SMartin Probst   verifyFormat("type Foo = Bar<X>|Baz;");
16751b7f9804SMartin Probst   verifyFormat("type Foo = (Bar<X>|Baz);");
16761b7f9804SMartin Probst   verifyFormat("let x: Bar|Baz;");
16771b7f9804SMartin Probst   verifyFormat("let x: Bar<X>|Baz;");
16781b7f9804SMartin Probst   verifyFormat("let x: (Foo|Bar)[];");
1679d96a052cSMartin Probst   verifyFormat("type X = {\n"
1680d96a052cSMartin Probst                "  a: Foo|Bar;\n"
1681d96a052cSMartin Probst                "};");
1682d96a052cSMartin Probst   verifyFormat("export type X = {\n"
1683d96a052cSMartin Probst                "  a: Foo|Bar;\n"
1684d96a052cSMartin Probst                "};");
168591b1d1abSDaniel Jasper }
168691b1d1abSDaniel Jasper 
TEST_F(FormatTestJS,UnionIntersectionTypesInObjectType)16870fb46bb2SMartin Probst TEST_F(FormatTestJS, UnionIntersectionTypesInObjectType) {
16880fb46bb2SMartin Probst   verifyFormat("let x: {x: number|null} = {x: number | null};");
16890fb46bb2SMartin Probst   verifyFormat("let nested: {x: {y: number|null}};");
16900fb46bb2SMartin Probst   verifyFormat("let mixed: {x: [number|null, {w: number}]};");
16910fb46bb2SMartin Probst   verifyFormat("class X {\n"
16920fb46bb2SMartin Probst                "  contructor(x: {\n"
16930fb46bb2SMartin Probst                "    a: a|null,\n"
16940fb46bb2SMartin Probst                "    b: b|null,\n"
16950fb46bb2SMartin Probst                "  }) {}\n"
16960fb46bb2SMartin Probst                "}");
16970fb46bb2SMartin Probst }
16980fb46bb2SMartin Probst 
TEST_F(FormatTestJS,ClassDeclarations)169983709086SDaniel Jasper TEST_F(FormatTestJS, ClassDeclarations) {
170083709086SDaniel Jasper   verifyFormat("class C {\n  x: string = 12;\n}");
170183709086SDaniel Jasper   verifyFormat("class C {\n  x(): string => 12;\n}");
170283709086SDaniel Jasper   verifyFormat("class C {\n  ['x' + 2]: string = 12;\n}");
170395ed8e79SMartin Probst   verifyFormat("class C {\n"
170495ed8e79SMartin Probst                "  foo() {}\n"
170595ed8e79SMartin Probst                "  [bar]() {}\n"
170695ed8e79SMartin Probst                "}\n");
170783709086SDaniel Jasper   verifyFormat("class C {\n  private x: string = 12;\n}");
170883709086SDaniel Jasper   verifyFormat("class C {\n  private static x: string = 12;\n}");
170928d8a5abSDaniel Jasper   verifyFormat("class C {\n  static x(): string {\n    return 'asd';\n  }\n}");
171083709086SDaniel Jasper   verifyFormat("class C extends P implements I {}");
17116a5d38d2SDaniel Jasper   verifyFormat("class C extends p.P implements i.I {}");
1712ece7e95fSmydeveloperday   verifyFormat("x(class {\n"
17131027fb8aSMartin Probst                "  a(): A {}\n"
17141027fb8aSMartin Probst                "});");
1715b9a52814SDaniel Jasper   verifyFormat("class Test {\n"
1716b9a52814SDaniel Jasper                "  aaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaaa):\n"
1717b9a52814SDaniel Jasper                "      aaaaaaaaaaaaaaaaaaaaaa {}\n"
1718b9a52814SDaniel Jasper                "}");
1719d5ec65baSDaniel Jasper   verifyFormat("foo = class Name {\n"
1720d5ec65baSDaniel Jasper                "  constructor() {}\n"
1721d5ec65baSDaniel Jasper                "};");
1722d5ec65baSDaniel Jasper   verifyFormat("foo = class {\n"
1723d5ec65baSDaniel Jasper                "  constructor() {}\n"
1724d5ec65baSDaniel Jasper                "};");
1725b9a4990aSDaniel Jasper   verifyFormat("class C {\n"
1726b9a4990aSDaniel Jasper                "  x: {y: Z;} = {};\n"
1727b9a4990aSDaniel Jasper                "  private y: {y: Z;} = {};\n"
1728b9a4990aSDaniel Jasper                "}");
172981dbb564SDaniel Jasper 
173081dbb564SDaniel Jasper   // ':' is not a type declaration here.
173181dbb564SDaniel Jasper   verifyFormat("class X {\n"
173281dbb564SDaniel Jasper                "  subs = {\n"
173381dbb564SDaniel Jasper                "    'b': {\n"
173481dbb564SDaniel Jasper                "      'c': 1,\n"
173581dbb564SDaniel Jasper                "    },\n"
173681dbb564SDaniel Jasper                "  };\n"
173781dbb564SDaniel Jasper                "}");
17386465008eSDaniel Jasper   verifyFormat("@Component({\n"
17396465008eSDaniel Jasper                "  moduleId: module.id,\n"
17406465008eSDaniel Jasper                "})\n"
17416465008eSDaniel Jasper                "class SessionListComponent implements OnDestroy, OnInit {\n"
17426465008eSDaniel Jasper                "}");
174383709086SDaniel Jasper }
174483709086SDaniel Jasper 
TEST_F(FormatTestJS,StrictPropInitWrap)1745c8b7a41aSMartin Probst TEST_F(FormatTestJS, StrictPropInitWrap) {
1746c8b7a41aSMartin Probst   const FormatStyle &Style = getGoogleJSStyleWithColumns(22);
1747c8b7a41aSMartin Probst   verifyFormat("class X {\n"
1748c8b7a41aSMartin Probst                "  strictPropInitField!:\n"
1749c8b7a41aSMartin Probst                "      string;\n"
1750c8b7a41aSMartin Probst                "}",
1751c8b7a41aSMartin Probst                Style);
1752c8b7a41aSMartin Probst }
1753c8b7a41aSMartin Probst 
TEST_F(FormatTestJS,InterfaceDeclarations)17542964749cSDaniel Jasper TEST_F(FormatTestJS, InterfaceDeclarations) {
17552964749cSDaniel Jasper   verifyFormat("interface I {\n"
17562964749cSDaniel Jasper                "  x: string;\n"
17576f5a1933SDaniel Jasper                "  enum: string[];\n"
17588737930cSDaniel Jasper                "  enum?: string[];\n"
1759259188b1SDaniel Jasper                "}\n"
1760259188b1SDaniel Jasper                "var y;");
17615c235c09SDaniel Jasper   // Ensure that state is reset after parsing the interface.
17625c235c09SDaniel Jasper   verifyFormat("interface a {}\n"
17635c235c09SDaniel Jasper                "export function b() {}\n"
17645c235c09SDaniel Jasper                "var x;");
1765b542f9f1SDaniel Jasper 
1766b542f9f1SDaniel Jasper   // Arrays of object type literals.
1767b542f9f1SDaniel Jasper   verifyFormat("interface I {\n"
1768b542f9f1SDaniel Jasper                "  o: {}[];\n"
1769b542f9f1SDaniel Jasper                "}");
17702964749cSDaniel Jasper }
17712964749cSDaniel Jasper 
TEST_F(FormatTestJS,ObjectTypesInExtendsImplements)1772cb870c57SMartin Probst TEST_F(FormatTestJS, ObjectTypesInExtendsImplements) {
1773cb870c57SMartin Probst   verifyFormat("class C extends {} {}");
1774cb870c57SMartin Probst   verifyFormat("class C implements {bar: number} {}");
1775cb870c57SMartin Probst   // Somewhat odd, but probably closest to reasonable formatting?
1776cb870c57SMartin Probst   verifyFormat("class C implements {\n"
1777cb870c57SMartin Probst                "  bar: number,\n"
1778cb870c57SMartin Probst                "  baz: string,\n"
1779cb870c57SMartin Probst                "} {}");
1780cb870c57SMartin Probst   verifyFormat("class C<P extends {}> {}");
1781cb870c57SMartin Probst }
1782cb870c57SMartin Probst 
TEST_F(FormatTestJS,EnumDeclarations)178390cf380eSDaniel Jasper TEST_F(FormatTestJS, EnumDeclarations) {
178490cf380eSDaniel Jasper   verifyFormat("enum Foo {\n"
17859f4ec152SDaniel Jasper                "  A = 1,\n"
17869f4ec152SDaniel Jasper                "  B\n"
17879f4ec152SDaniel Jasper                "}");
17889f4ec152SDaniel Jasper   verifyFormat("export /* somecomment*/ enum Foo {\n"
17899f4ec152SDaniel Jasper                "  A = 1,\n"
17909f4ec152SDaniel Jasper                "  B\n"
17919f4ec152SDaniel Jasper                "}");
17929f4ec152SDaniel Jasper   verifyFormat("enum Foo {\n"
179390cf380eSDaniel Jasper                "  A = 1,  // comment\n"
179490cf380eSDaniel Jasper                "  B\n"
179590cf380eSDaniel Jasper                "}\n"
179690cf380eSDaniel Jasper                "var x = 1;");
1797db51cc57SMartin Probst   verifyFormat("const enum Foo {\n"
1798db51cc57SMartin Probst                "  A = 1,\n"
1799db51cc57SMartin Probst                "  B\n"
1800db51cc57SMartin Probst                "}");
1801db51cc57SMartin Probst   verifyFormat("export const enum Foo {\n"
1802db51cc57SMartin Probst                "  A = 1,\n"
1803db51cc57SMartin Probst                "  B\n"
1804db51cc57SMartin Probst                "}");
180590cf380eSDaniel Jasper }
180690cf380eSDaniel Jasper 
TEST_F(FormatTestJS,Decorators)18077e0f25b2SMartin Probst TEST_F(FormatTestJS, Decorators) {
18083c42dba2SDaniel Jasper   verifyFormat("@A\nclass C {\n}");
18093c42dba2SDaniel Jasper   verifyFormat("@A({arg: 'value'})\nclass C {\n}");
18103c42dba2SDaniel Jasper   verifyFormat("@A\n@B\nclass C {\n}");
18113c42dba2SDaniel Jasper   verifyFormat("class C {\n  @A x: string;\n}");
18123c42dba2SDaniel Jasper   verifyFormat("class C {\n"
18133c42dba2SDaniel Jasper                "  @A\n"
18143c42dba2SDaniel Jasper                "  private x(): string {\n"
18153c42dba2SDaniel Jasper                "    return 'y';\n"
18163c42dba2SDaniel Jasper                "  }\n"
18173c42dba2SDaniel Jasper                "}");
1818716a533aSMartin Probst   verifyFormat("class C {\n"
1819716a533aSMartin Probst                "  private x(@A x: string) {}\n"
1820716a533aSMartin Probst                "}");
18216fa9ec78SDaniel Jasper   verifyFormat("class X {}\n"
18226fa9ec78SDaniel Jasper                "class Y {}");
1823ad06391cSMartin Probst   verifyFormat("class X {\n"
1824ad06391cSMartin Probst                "  @property() private isReply = false;\n"
1825ad06391cSMartin Probst                "}\n");
18263c42dba2SDaniel Jasper }
18273c42dba2SDaniel Jasper 
TEST_F(FormatTestJS,TypeAliases)1828805c6167SMartin Probst TEST_F(FormatTestJS, TypeAliases) {
1829805c6167SMartin Probst   verifyFormat("type X = number;\n"
1830805c6167SMartin Probst                "class C {}");
1831805c6167SMartin Probst   verifyFormat("type X<Y> = Z<Y>;");
1832805c6167SMartin Probst   verifyFormat("type X = {\n"
1833805c6167SMartin Probst                "  y: number\n"
1834805c6167SMartin Probst                "};\n"
1835805c6167SMartin Probst                "class C {}");
1836325ff7c5SMartin Probst   verifyFormat("export type X = {\n"
1837325ff7c5SMartin Probst                "  a: string,\n"
1838325ff7c5SMartin Probst                "  b?: string,\n"
1839325ff7c5SMartin Probst                "};\n");
1840805c6167SMartin Probst }
1841805c6167SMartin Probst 
TEST_F(FormatTestJS,TypeInterfaceLineWrapping)1842b98ab89eSMartin Probst TEST_F(FormatTestJS, TypeInterfaceLineWrapping) {
1843b98ab89eSMartin Probst   const FormatStyle &Style = getGoogleJSStyleWithColumns(20);
1844b98ab89eSMartin Probst   verifyFormat("type LongTypeIsReallyUnreasonablyLong =\n"
1845b98ab89eSMartin Probst                "    string;\n",
1846ece7e95fSmydeveloperday                "type LongTypeIsReallyUnreasonablyLong = string;\n", Style);
1847ece7e95fSmydeveloperday   verifyFormat("interface AbstractStrategyFactoryProvider {\n"
1848b98ab89eSMartin Probst                "  a: number\n"
1849b98ab89eSMartin Probst                "}\n",
1850b98ab89eSMartin Probst                "interface AbstractStrategyFactoryProvider { a: number }\n",
1851b98ab89eSMartin Probst                Style);
1852b98ab89eSMartin Probst }
1853b98ab89eSMartin Probst 
TEST_F(FormatTestJS,RemoveEmptyLinesInArrowFunctions)1854a004b3f5SMartin Probst TEST_F(FormatTestJS, RemoveEmptyLinesInArrowFunctions) {
1855a004b3f5SMartin Probst   verifyFormat("x = () => {\n"
1856a004b3f5SMartin Probst                "  foo();\n"
185702656f29SMartin Probst                "  bar();\n"
1858a004b3f5SMartin Probst                "};\n",
1859a004b3f5SMartin Probst                "x = () => {\n"
1860a004b3f5SMartin Probst                "\n"
1861a004b3f5SMartin Probst                "  foo();\n"
186202656f29SMartin Probst                "  bar();\n"
1863a004b3f5SMartin Probst                "\n"
1864a004b3f5SMartin Probst                "};\n");
1865a004b3f5SMartin Probst }
1866a004b3f5SMartin Probst 
TEST_F(FormatTestJS,Modules)1867354aa515SDaniel Jasper TEST_F(FormatTestJS, Modules) {
1868354aa515SDaniel Jasper   verifyFormat("import SomeThing from 'some/module.js';");
1869354aa515SDaniel Jasper   verifyFormat("import {X, Y} from 'some/module.js';");
1870efc1a83aSDaniel Jasper   verifyFormat("import a, {X, Y} from 'some/module.js';");
18718fc7a1e9SDaniel Jasper   verifyFormat("import {X, Y,} from 'some/module.js';");
1872354aa515SDaniel Jasper   verifyFormat("import {X as myLocalX, Y as myLocalY} from 'some/module.js';");
187348622090SMartin Probst   // Ensure Automatic Semicolon Insertion does not break on "as\n".
187448622090SMartin Probst   verifyFormat("import {X as myX} from 'm';", "import {X as\n"
187548622090SMartin Probst                                               " myX} from 'm';");
1876354aa515SDaniel Jasper   verifyFormat("import * as lib from 'some/module.js';");
187760948b12SDaniel Jasper   verifyFormat("var x = {import: 1};\nx.import = 2;");
1878*f6740fe4Ssstwcw   // Ensure an import statement inside a block is at the correct level.
1879*f6740fe4Ssstwcw   verifyFormat("function() {\n"
1880*f6740fe4Ssstwcw                "  var x;\n"
1881*f6740fe4Ssstwcw                "  import 'some/module.js';\n"
1882*f6740fe4Ssstwcw                "}");
1883fca735cdSDaniel Jasper 
1884fca735cdSDaniel Jasper   verifyFormat("export function fn() {\n"
1885fca735cdSDaniel Jasper                "  return 'fn';\n"
1886fca735cdSDaniel Jasper                "}");
188720580fd5SDaniel Jasper   verifyFormat("export function A() {}\n"
188820580fd5SDaniel Jasper                "export default function B() {}\n"
188920580fd5SDaniel Jasper                "export function C() {}");
1890053f1aa6SMartin Probst   verifyFormat("export default () => {\n"
1891053f1aa6SMartin Probst                "  let x = 1;\n"
1892053f1aa6SMartin Probst                "  return x;\n"
1893053f1aa6SMartin Probst                "}");
1894354aa515SDaniel Jasper   verifyFormat("export const x = 12;");
1895354aa515SDaniel Jasper   verifyFormat("export default class X {}");
1896fca735cdSDaniel Jasper   verifyFormat("export {X, Y} from 'some/module.js';");
18978fc7a1e9SDaniel Jasper   verifyFormat("export {X, Y,} from 'some/module.js';");
18988fc7a1e9SDaniel Jasper   verifyFormat("export {SomeVeryLongExport as X, "
18998fc7a1e9SDaniel Jasper                "SomeOtherVeryLongExport as Y} from 'some/module.js';");
19008fc7a1e9SDaniel Jasper   // export without 'from' is wrapped.
19018fc7a1e9SDaniel Jasper   verifyFormat("export let someRatherLongVariableName =\n"
19028fc7a1e9SDaniel Jasper                "    someSurprisinglyLongVariable + someOtherRatherLongVar;");
19038fc7a1e9SDaniel Jasper   // ... but not if from is just an identifier.
1904fca735cdSDaniel Jasper   verifyFormat("export {\n"
19058fc7a1e9SDaniel Jasper                "  from as from,\n"
1906dce8e417SMartin Probst                "  someSurprisinglyLongVariable as\n"
1907dce8e417SMartin Probst                "      from\n"
19088fc7a1e9SDaniel Jasper                "};",
19098fc7a1e9SDaniel Jasper                getGoogleJSStyleWithColumns(20));
1910fca735cdSDaniel Jasper   verifyFormat("export class C {\n"
1911fca735cdSDaniel Jasper                "  x: number;\n"
1912fca735cdSDaniel Jasper                "  y: string;\n"
1913fca735cdSDaniel Jasper                "}");
1914c160cfafSMartin Probst   verifyFormat("export class X {\n"
1915c160cfafSMartin Probst                "  y: number;\n"
1916c160cfafSMartin Probst                "}");
1917c160cfafSMartin Probst   verifyFormat("export abstract class X {\n"
1918c160cfafSMartin Probst                "  y: number;\n"
1919c160cfafSMartin Probst                "}");
1920c160cfafSMartin Probst   verifyFormat("export default class X {\n"
1921c160cfafSMartin Probst                "  y: number\n"
1922c160cfafSMartin Probst                "}");
1923fca735cdSDaniel Jasper   verifyFormat("export default function() {\n  return 1;\n}");
1924fca735cdSDaniel Jasper   verifyFormat("export var x = 12;");
1925910807d4SDaniel Jasper   verifyFormat("class C {}\n"
1926910807d4SDaniel Jasper                "export function f() {}\n"
1927910807d4SDaniel Jasper                "var v;");
1928fca735cdSDaniel Jasper   verifyFormat("export var x: number = 12;");
1929fca735cdSDaniel Jasper   verifyFormat("export const y = {\n"
1930fca735cdSDaniel Jasper                "  a: 1,\n"
1931fca735cdSDaniel Jasper                "  b: 2\n"
1932fca735cdSDaniel Jasper                "};");
1933216c9cdbSDaniel Jasper   verifyFormat("export enum Foo {\n"
1934216c9cdbSDaniel Jasper                "  BAR,\n"
1935216c9cdbSDaniel Jasper                "  // adsdasd\n"
1936216c9cdbSDaniel Jasper                "  BAZ\n"
1937216c9cdbSDaniel Jasper                "}");
1938b14f6675SDaniel Jasper   verifyFormat("export default [\n"
1939b14f6675SDaniel Jasper                "  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
1940b14f6675SDaniel Jasper                "  bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"
1941b14f6675SDaniel Jasper                "];");
1942b14f6675SDaniel Jasper   verifyFormat("export default [];");
19435e27146dSDaniel Jasper   verifyFormat("export default () => {};");
194402656f29SMartin Probst   verifyFormat("export default () => {\n"
194502656f29SMartin Probst                "  x;\n"
194602656f29SMartin Probst                "  x;\n"
194702656f29SMartin Probst                "};");
1948c160cfafSMartin Probst   verifyFormat("export interface Foo {\n"
1949c160cfafSMartin Probst                "  foo: number;\n"
1950c160cfafSMartin Probst                "}\n"
1951f55e4182SDaniel Jasper                "export class Bar {\n"
195228d8a5abSDaniel Jasper                "  blah(): string {\n"
195328d8a5abSDaniel Jasper                "    return this.blah;\n"
195428d8a5abSDaniel Jasper                "  };\n"
1955f55e4182SDaniel Jasper                "}");
1956354aa515SDaniel Jasper }
1957354aa515SDaniel Jasper 
TEST_F(FormatTestJS,ImportWrapping)19580cd74ee8SMartin Probst TEST_F(FormatTestJS, ImportWrapping) {
19590cd74ee8SMartin Probst   verifyFormat("import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,"
19600cd74ee8SMartin Probst                " VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying"
19610cd74ee8SMartin Probst                "} from 'some/module.js';");
19620cd74ee8SMartin Probst   FormatStyle Style = getGoogleJSStyleWithColumns(80);
19630cd74ee8SMartin Probst   Style.JavaScriptWrapImports = true;
19640cd74ee8SMartin Probst   verifyFormat("import {\n"
19650cd74ee8SMartin Probst                "  VeryLongImportsAreAnnoying,\n"
19660cd74ee8SMartin Probst                "  VeryLongImportsAreAnnoying,\n"
19670cd74ee8SMartin Probst                "  VeryLongImportsAreAnnoying,\n"
19680cd74ee8SMartin Probst                "} from 'some/module.js';",
19690cd74ee8SMartin Probst                Style);
19700cd74ee8SMartin Probst   verifyFormat("import {\n"
19710cd74ee8SMartin Probst                "  A,\n"
19720cd74ee8SMartin Probst                "  A,\n"
19730cd74ee8SMartin Probst                "} from 'some/module.js';",
19740cd74ee8SMartin Probst                Style);
19750cd74ee8SMartin Probst   verifyFormat("export {\n"
19760cd74ee8SMartin Probst                "  A,\n"
19770cd74ee8SMartin Probst                "  A,\n"
19780cd74ee8SMartin Probst                "} from 'some/module.js';",
19790cd74ee8SMartin Probst                Style);
198093008f01SMartin Probst   Style.ColumnLimit = 40;
198193008f01SMartin Probst   // Using this version of verifyFormat because test::messUp hides the issue.
198293008f01SMartin Probst   verifyFormat("import {\n"
198393008f01SMartin Probst                "  A,\n"
198493008f01SMartin Probst                "} from\n"
198593008f01SMartin Probst                "    'some/path/longer/than/column/limit/module.js';",
198693008f01SMartin Probst                " import  {  \n"
198793008f01SMartin Probst                "    A,  \n"
198893008f01SMartin Probst                "  }    from\n"
198993008f01SMartin Probst                "      'some/path/longer/than/column/limit/module.js'  ; ",
199093008f01SMartin Probst                Style);
19910cd74ee8SMartin Probst }
19920cd74ee8SMartin Probst 
TEST_F(FormatTestJS,TemplateStrings)1993a0ef4f36SDaniel Jasper TEST_F(FormatTestJS, TemplateStrings) {
1994a0ef4f36SDaniel Jasper   // Keeps any whitespace/indentation within the template string.
19951dcbbcfcSDaniel Jasper   verifyFormat("var x = `hello\n"
1996a0ef4f36SDaniel Jasper                "     ${name}\n"
1997a0ef4f36SDaniel Jasper                "  !`;",
19981dcbbcfcSDaniel Jasper                "var x    =    `hello\n"
1999a0ef4f36SDaniel Jasper                "     ${  name    }\n"
20001dcbbcfcSDaniel Jasper                "  !`;");
2001a0ef4f36SDaniel Jasper 
2002a0ef4f36SDaniel Jasper   verifyFormat("var x =\n"
2003a0ef4f36SDaniel Jasper                "    `hello ${world}` >= some();",
2004a0ef4f36SDaniel Jasper                getGoogleJSStyleWithColumns(34)); // Barely doesn't fit.
2005a0ef4f36SDaniel Jasper   verifyFormat("var x = `hello ${world}` >= some();",
2006553a5b00SDaniel Jasper                getGoogleJSStyleWithColumns(35)); // Barely fits.
2007e71b4cbdSMartin Probst   verifyFormat("var x = `hellö ${wörld}` >= söme();",
2008e71b4cbdSMartin Probst                getGoogleJSStyleWithColumns(35)); // Fits due to UTF-8.
20091dcbbcfcSDaniel Jasper   verifyFormat("var x = `hello\n"
2010a0ef4f36SDaniel Jasper                "  ${world}` >=\n"
2011a0ef4f36SDaniel Jasper                "    some();",
20121dcbbcfcSDaniel Jasper                "var x =\n"
2013a0ef4f36SDaniel Jasper                "    `hello\n"
2014a0ef4f36SDaniel Jasper                "  ${world}` >= some();",
20151dcbbcfcSDaniel Jasper                getGoogleJSStyleWithColumns(21)); // Barely doesn't fit.
20161dcbbcfcSDaniel Jasper   verifyFormat("var x = `hello\n"
2017a0ef4f36SDaniel Jasper                "  ${world}` >= some();",
20181dcbbcfcSDaniel Jasper                "var x =\n"
2019a0ef4f36SDaniel Jasper                "    `hello\n"
2020a0ef4f36SDaniel Jasper                "  ${world}` >= some();",
20211dcbbcfcSDaniel Jasper                getGoogleJSStyleWithColumns(22)); // Barely fits.
2022a0ef4f36SDaniel Jasper 
2023553a5b00SDaniel Jasper   verifyFormat("var x =\n"
2024553a5b00SDaniel Jasper                "    `h`;",
2025553a5b00SDaniel Jasper                getGoogleJSStyleWithColumns(11));
20261dcbbcfcSDaniel Jasper   verifyFormat("var x =\n    `multi\n  line`;", "var x = `multi\n  line`;",
20271dcbbcfcSDaniel Jasper                getGoogleJSStyleWithColumns(13));
2028553a5b00SDaniel Jasper   verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
2029553a5b00SDaniel Jasper                "    `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`);");
2030e71b4cbdSMartin Probst   // Repro for an obscure width-miscounting issue with template strings.
2031e71b4cbdSMartin Probst   verifyFormat(
2032e71b4cbdSMartin Probst       "someLongVariable =\n"
2033e71b4cbdSMartin Probst       "    "
2034e71b4cbdSMartin Probst       "`${logPrefix[11]}/${logPrefix[12]}/${logPrefix[13]}${logPrefix[14]}`;",
2035e71b4cbdSMartin Probst       "someLongVariable = "
2036e71b4cbdSMartin Probst       "`${logPrefix[11]}/${logPrefix[12]}/${logPrefix[13]}${logPrefix[14]}`;");
2037a0ef4f36SDaniel Jasper 
2038f69b922eSDaniel Jasper   // Make sure template strings get a proper ColumnWidth assigned, even if they
2039f69b922eSDaniel Jasper   // are first token in line.
2040ece7e95fSmydeveloperday   verifyFormat("var a = aaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n"
2041f69b922eSDaniel Jasper                "    `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`;");
2042f69b922eSDaniel Jasper 
2043a0ef4f36SDaniel Jasper   // Two template strings.
2044a0ef4f36SDaniel Jasper   verifyFormat("var x = `hello` == `hello`;");
20450d6ac27bSDaniel Jasper 
20460d6ac27bSDaniel Jasper   // Comments in template strings.
20471dcbbcfcSDaniel Jasper   verifyFormat("var x = `//a`;\n"
20480d6ac27bSDaniel Jasper                "var y;",
20491dcbbcfcSDaniel Jasper                "var x =\n `//a`;\n"
20501dcbbcfcSDaniel Jasper                "var y  ;");
20511dcbbcfcSDaniel Jasper   verifyFormat("var x = `/*a`;\n"
20520d6ac27bSDaniel Jasper                "var y;",
20531dcbbcfcSDaniel Jasper                "var x =\n `/*a`;\n"
20541dcbbcfcSDaniel Jasper                "var y;");
20552ebb0c57SDaniel Jasper   // Unterminated string literals in a template string.
20562ebb0c57SDaniel Jasper   verifyFormat("var x = `'`;  // comment with matching quote '\n"
20572ebb0c57SDaniel Jasper                "var y;");
20582ebb0c57SDaniel Jasper   verifyFormat("var x = `\"`;  // comment with matching quote \"\n"
20592ebb0c57SDaniel Jasper                "var y;");
20601dcbbcfcSDaniel Jasper   verifyFormat("it(`'aaaaaaaaaaaaaaa   `, aaaaaaaaa);",
20611dcbbcfcSDaniel Jasper                "it(`'aaaaaaaaaaaaaaa   `,   aaaaaaaaa) ;",
20621dcbbcfcSDaniel Jasper                getGoogleJSStyleWithColumns(40));
20630d6ac27bSDaniel Jasper   // Backticks in a comment - not a template string.
20641dcbbcfcSDaniel Jasper   verifyFormat("var x = 1  // `/*a`;\n"
20650d6ac27bSDaniel Jasper                "    ;",
20661dcbbcfcSDaniel Jasper                "var x =\n 1  // `/*a`;\n"
20671dcbbcfcSDaniel Jasper                "    ;");
20681dcbbcfcSDaniel Jasper   verifyFormat("/* ` */ var x = 1; /* ` */", "/* ` */ var x\n= 1; /* ` */");
20690d6ac27bSDaniel Jasper   // Comment spans multiple template strings.
20701dcbbcfcSDaniel Jasper   verifyFormat("var x = `/*a`;\n"
20710d6ac27bSDaniel Jasper                "var y = ` */ `;",
20721dcbbcfcSDaniel Jasper                "var x =\n `/*a`;\n"
20731dcbbcfcSDaniel Jasper                "var y =\n ` */ `;");
20740d6ac27bSDaniel Jasper   // Escaped backtick.
20751dcbbcfcSDaniel Jasper   verifyFormat("var x = ` \\` a`;\n"
20760d6ac27bSDaniel Jasper                "var y;",
20771dcbbcfcSDaniel Jasper                "var x = ` \\` a`;\n"
20781dcbbcfcSDaniel Jasper                "var y;");
20796181da47SMartin Probst   // Escaped dollar.
20806181da47SMartin Probst   verifyFormat("var x = ` \\${foo}`;\n");
2081f2019290SDaniel Jasper 
2082f2019290SDaniel Jasper   // The token stream can contain two string_literals in sequence, but that
2083f2019290SDaniel Jasper   // doesn't mean that they are implicitly concatenated in JavaScript.
2084f2019290SDaniel Jasper   verifyFormat("var f = `aaaa ${a ? 'a' : 'b'}`;");
208524de6fbfSDaniel Jasper 
208624de6fbfSDaniel Jasper   // Ensure that scopes are appropriately set around evaluated expressions in
208724de6fbfSDaniel Jasper   // template strings.
208824de6fbfSDaniel Jasper   verifyFormat("var f = `aaaaaaaaaaaaa:${aaaaaaa.aaaaa} aaaaaaaa\n"
208924de6fbfSDaniel Jasper                "         aaaaaaaaaaaaa:${aaaaaaa.aaaaa} aaaaaaaa`;",
209024de6fbfSDaniel Jasper                "var f = `aaaaaaaaaaaaa:${aaaaaaa.  aaaaa} aaaaaaaa\n"
209124de6fbfSDaniel Jasper                "         aaaaaaaaaaaaa:${  aaaaaaa. aaaaa} aaaaaaaa`;");
2092c06f6da3SDaniel Jasper   verifyFormat("var x = someFunction(`${})`)  //\n"
2093c06f6da3SDaniel Jasper                "            .oooooooooooooooooon();");
209498e0b12dSDaniel Jasper   verifyFormat("var x = someFunction(`${aaaa}${\n"
209598e0b12dSDaniel Jasper                "    aaaaa(  //\n"
2096c10d97f9SMartin Probst                "        aaaaa)})`);");
20976181da47SMartin Probst }
20986181da47SMartin Probst 
TEST_F(FormatTestJS,TemplateStringMultiLineExpression)20993f11941dSDaniel Jasper TEST_F(FormatTestJS, TemplateStringMultiLineExpression) {
210098e0b12dSDaniel Jasper   verifyFormat("var f = `aaaaaaaaaaaaaaaaaa: ${\n"
210198e0b12dSDaniel Jasper                "    aaaaa +  //\n"
2102c10d97f9SMartin Probst                "    bbbb}`;",
21033f11941dSDaniel Jasper                "var f = `aaaaaaaaaaaaaaaaaa: ${aaaaa +  //\n"
21043f11941dSDaniel Jasper                "                               bbbb}`;");
21053f11941dSDaniel Jasper   verifyFormat("var f = `\n"
210698e0b12dSDaniel Jasper                "  aaaaaaaaaaaaaaaaaa: ${\n"
210798e0b12dSDaniel Jasper                "    aaaaa +  //\n"
2108c10d97f9SMartin Probst                "    bbbb}`;",
21093f11941dSDaniel Jasper                "var f  =  `\n"
21103f11941dSDaniel Jasper                "  aaaaaaaaaaaaaaaaaa: ${   aaaaa  +  //\n"
21113f11941dSDaniel Jasper                "                        bbbb }`;");
21123f11941dSDaniel Jasper   verifyFormat("var f = `\n"
211398e0b12dSDaniel Jasper                "  aaaaaaaaaaaaaaaaaa: ${\n"
211498e0b12dSDaniel Jasper                "    someFunction(\n"
21153f11941dSDaniel Jasper                "        aaaaa +  //\n"
2116c10d97f9SMartin Probst                "        bbbb)}`;",
21173f11941dSDaniel Jasper                "var f  =  `\n"
21183f11941dSDaniel Jasper                "  aaaaaaaaaaaaaaaaaa: ${someFunction (\n"
21193f11941dSDaniel Jasper                "                            aaaaa  +   //\n"
21203f11941dSDaniel Jasper                "                            bbbb)}`;");
212198e0b12dSDaniel Jasper 
212298e0b12dSDaniel Jasper   // It might be preferable to wrap before "someFunction".
21233f11941dSDaniel Jasper   verifyFormat("var f = `\n"
212498e0b12dSDaniel Jasper                "  aaaaaaaaaaaaaaaaaa: ${someFunction({\n"
21253f11941dSDaniel Jasper                "  aaaa: aaaaa,\n"
21263f11941dSDaniel Jasper                "  bbbb: bbbbb,\n"
21273f11941dSDaniel Jasper                "})}`;",
21283f11941dSDaniel Jasper                "var f  =  `\n"
212998e0b12dSDaniel Jasper                "  aaaaaaaaaaaaaaaaaa: ${someFunction ({\n"
21303f11941dSDaniel Jasper                "                          aaaa:  aaaaa,\n"
21313f11941dSDaniel Jasper                "                          bbbb:  bbbbb,\n"
21323f11941dSDaniel Jasper                "                        })}`;");
21333f11941dSDaniel Jasper }
21343f11941dSDaniel Jasper 
TEST_F(FormatTestJS,TemplateStringASI)2135717f6dcdSMartin Probst TEST_F(FormatTestJS, TemplateStringASI) {
2136717f6dcdSMartin Probst   verifyFormat("var x = `hello${world}`;", "var x = `hello${\n"
2137717f6dcdSMartin Probst                                            "    world\n"
2138717f6dcdSMartin Probst                                            "}`;");
2139717f6dcdSMartin Probst }
2140717f6dcdSMartin Probst 
TEST_F(FormatTestJS,NestedTemplateStrings)21416181da47SMartin Probst TEST_F(FormatTestJS, NestedTemplateStrings) {
21426181da47SMartin Probst   verifyFormat(
21436181da47SMartin Probst       "var x = `<ul>${xs.map(x => `<li>${x}</li>`).join('\\n')}</ul>`;");
21446181da47SMartin Probst   verifyFormat("var x = `he${({text: 'll'}.text)}o`;");
214558209dd9SDaniel Jasper 
214658209dd9SDaniel Jasper   // Crashed at some point.
214758209dd9SDaniel Jasper   verifyFormat("}");
21486181da47SMartin Probst }
21496181da47SMartin Probst 
TEST_F(FormatTestJS,TaggedTemplateStrings)21506181da47SMartin Probst TEST_F(FormatTestJS, TaggedTemplateStrings) {
21516181da47SMartin Probst   verifyFormat("var x = html`<ul>`;");
215237a7f910SMartin Probst   verifyFormat("yield `hello`;");
2153b274d3d7SMartin Probst   verifyFormat("var f = {\n"
2154b274d3d7SMartin Probst                "  param: longTagName`This is a ${\n"
2155b274d3d7SMartin Probst                "                    'really'} long line`\n"
2156b274d3d7SMartin Probst                "};",
2157b274d3d7SMartin Probst                "var f = {param: longTagName`This is a ${'really'} long line`};",
2158b274d3d7SMartin Probst                getGoogleJSStyleWithColumns(40));
2159a0ef4f36SDaniel Jasper }
2160a0ef4f36SDaniel Jasper 
TEST_F(FormatTestJS,CastSyntax)2161805c6167SMartin Probst TEST_F(FormatTestJS, CastSyntax) {
2162805c6167SMartin Probst   verifyFormat("var x = <type>foo;");
2163805c6167SMartin Probst   verifyFormat("var x = foo as type;");
2164dce8e417SMartin Probst   verifyFormat("let x = (a + b) as\n"
2165dce8e417SMartin Probst                "    LongTypeIsLong;",
2166dce8e417SMartin Probst                getGoogleJSStyleWithColumns(20));
2167887a3994SDaniel Jasper   verifyFormat("foo = <Bar[]>[\n"
2168887a3994SDaniel Jasper                "  1,  //\n"
2169887a3994SDaniel Jasper                "  2\n"
2170887a3994SDaniel Jasper                "];");
2171e1e12a73SMartin Probst   verifyFormat("var x = [{x: 1} as type];");
2172ed87d788SMartin Probst   verifyFormat("x = x as [a, b];");
2173ed87d788SMartin Probst   verifyFormat("x = x as {a: string};");
2174ed87d788SMartin Probst   verifyFormat("x = x as (string);");
217534ecf42bSMartin Probst   verifyFormat("x = x! as (string);");
2176a2555114SMartin Probst   verifyFormat("x = y! in z;");
217701b8783aSDaniel Jasper   verifyFormat("var x = something.someFunction() as\n"
217801b8783aSDaniel Jasper                "    something;",
217901b8783aSDaniel Jasper                getGoogleJSStyleWithColumns(40));
2180805c6167SMartin Probst }
2181bc46b939SDaniel Jasper 
TEST_F(FormatTestJS,TypeArguments)2182bc46b939SDaniel Jasper TEST_F(FormatTestJS, TypeArguments) {
2183bc46b939SDaniel Jasper   verifyFormat("class X<Y> {}");
2184bc46b939SDaniel Jasper   verifyFormat("new X<Y>();");
2185bc46b939SDaniel Jasper   verifyFormat("foo<Y>(a);");
2186bc46b939SDaniel Jasper   verifyFormat("var x: X<Y>[];");
2187bc46b939SDaniel Jasper   verifyFormat("class C extends D<E> implements F<G>, H<I> {}");
218820580fd5SDaniel Jasper   verifyFormat("function f(a: List<any> = null) {}");
218920580fd5SDaniel Jasper   verifyFormat("function f(): List<any> {}");
21905a3de1d0SDaniel Jasper   verifyFormat("function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa():\n"
21915a3de1d0SDaniel Jasper                "    bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {}");
21926501f7e8SDaniel Jasper   verifyFormat("function aaaaaaaaaa(\n"
21936501f7e8SDaniel Jasper                "    aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaa,\n"
21946501f7e8SDaniel Jasper                "    aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaa):\n"
2195b2328b1eSDaniel Jasper                "    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {}");
2196bc46b939SDaniel Jasper }
2197bc46b939SDaniel Jasper 
TEST_F(FormatTestJS,UserDefinedTypeGuards)2198779c66f3SDaniel Jasper TEST_F(FormatTestJS, UserDefinedTypeGuards) {
2199779c66f3SDaniel Jasper   verifyFormat(
2200779c66f3SDaniel Jasper       "function foo(check: Object):\n"
2201779c66f3SDaniel Jasper       "    check is {foo: string, bar: string, baz: string, foobar: string} {\n"
2202779c66f3SDaniel Jasper       "  return 'bar' in check;\n"
2203779c66f3SDaniel Jasper       "}\n");
2204779c66f3SDaniel Jasper }
2205779c66f3SDaniel Jasper 
TEST_F(FormatTestJS,OptionalTypes)2206a74f5072SDaniel Jasper TEST_F(FormatTestJS, OptionalTypes) {
220720580fd5SDaniel Jasper   verifyFormat("function x(a?: b, c?, d?) {}");
2208a74f5072SDaniel Jasper   verifyFormat("class X {\n"
2209a74f5072SDaniel Jasper                "  y?: z;\n"
2210a74f5072SDaniel Jasper                "  z?;\n"
2211a74f5072SDaniel Jasper                "}");
22129326f919SDaniel Jasper   verifyFormat("interface X {\n"
22139326f919SDaniel Jasper                "  y?(): z;\n"
22149326f919SDaniel Jasper                "}");
22153e0dcc27SDaniel Jasper   verifyFormat("constructor({aa}: {\n"
22163e0dcc27SDaniel Jasper                "  aa?: string,\n"
22173e0dcc27SDaniel Jasper                "  aaaaaaaa?: string,\n"
22183e0dcc27SDaniel Jasper                "  aaaaaaaaaaaaaaa?: boolean,\n"
22193e0dcc27SDaniel Jasper                "  aaaaaa?: List<string>\n"
222020580fd5SDaniel Jasper                "}) {}");
2221a74f5072SDaniel Jasper }
2222a74f5072SDaniel Jasper 
TEST_F(FormatTestJS,IndexSignature)2223d9309774SDaniel Jasper TEST_F(FormatTestJS, IndexSignature) {
2224d9309774SDaniel Jasper   verifyFormat("var x: {[k: string]: v};");
2225d9309774SDaniel Jasper }
2226d9309774SDaniel Jasper 
TEST_F(FormatTestJS,WrapAfterParen)22276501f7e8SDaniel Jasper TEST_F(FormatTestJS, WrapAfterParen) {
22286501f7e8SDaniel Jasper   verifyFormat("xxxxxxxxxxx(\n"
22296501f7e8SDaniel Jasper                "    aaa, aaa);",
22306501f7e8SDaniel Jasper                getGoogleJSStyleWithColumns(20));
22316501f7e8SDaniel Jasper   verifyFormat("xxxxxxxxxxx(\n"
22326501f7e8SDaniel Jasper                "    aaa, aaa, aaa,\n"
22336501f7e8SDaniel Jasper                "    aaa, aaa, aaa);",
22346501f7e8SDaniel Jasper                getGoogleJSStyleWithColumns(20));
22356501f7e8SDaniel Jasper   verifyFormat("xxxxxxxxxxx(\n"
22366501f7e8SDaniel Jasper                "    aaaaaaaaaaaaaaaaaaaaaaaa,\n"
22376501f7e8SDaniel Jasper                "    function(x) {\n"
22386501f7e8SDaniel Jasper                "      y();  //\n"
22396501f7e8SDaniel Jasper                "    });",
22406501f7e8SDaniel Jasper                getGoogleJSStyleWithColumns(40));
22416501f7e8SDaniel Jasper   verifyFormat("while (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n"
22426501f7e8SDaniel Jasper                "       bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n}");
22436501f7e8SDaniel Jasper }
22446501f7e8SDaniel Jasper 
TEST_F(FormatTestJS,JSDocAnnotations)2245d196abbbSDaniel Jasper TEST_F(FormatTestJS, JSDocAnnotations) {
22461dcbbcfcSDaniel Jasper   verifyFormat("/**\n"
22479d717813SMartin Probst                " * @exports {this.is.a.long.path.to.a.Type}\n"
2248d196abbbSDaniel Jasper                " */",
22491dcbbcfcSDaniel Jasper                "/**\n"
22506a5c95bdSKrasimir Georgiev                " * @exports {this.is.a.long.path.to.a.Type}\n"
2251d196abbbSDaniel Jasper                " */",
22521dcbbcfcSDaniel Jasper                getGoogleJSStyleWithColumns(20));
2253bb46a7ddSMartin Probst   verifyFormat("/**\n"
22549d717813SMartin Probst                " * @mods {this.is.a.long.path.to.a.Type}\n"
2255bb46a7ddSMartin Probst                " */",
2256bb46a7ddSMartin Probst                "/**\n"
2257bb46a7ddSMartin Probst                " * @mods {this.is.a.long.path.to.a.Type}\n"
2258bb46a7ddSMartin Probst                " */",
2259bb46a7ddSMartin Probst                getGoogleJSStyleWithColumns(20));
2260bb46a7ddSMartin Probst   verifyFormat("/**\n"
22619d717813SMartin Probst                " * @mods {this.is.a.long.path.to.a.Type}\n"
2262bb46a7ddSMartin Probst                " */",
2263bb46a7ddSMartin Probst                "/**\n"
22649d717813SMartin Probst                " * @mods {this.is.a.long.path.to.a.Type}\n"
22659d717813SMartin Probst                " */",
22669d717813SMartin Probst                getGoogleJSStyleWithColumns(20));
22679d717813SMartin Probst   verifyFormat("/**\n"
22689d717813SMartin Probst                " * @param {canWrap\n"
22699d717813SMartin Probst                " *     onSpace}\n"
22709d717813SMartin Probst                " */",
22719d717813SMartin Probst                "/**\n"
22729d717813SMartin Probst                " * @param {canWrap onSpace}\n"
2273bb46a7ddSMartin Probst                " */",
2274bb46a7ddSMartin Probst                getGoogleJSStyleWithColumns(20));
2275f326b6b9SMartin Probst   // make sure clang-format doesn't break before *any* '{'
2276f326b6b9SMartin Probst   verifyFormat("/**\n"
2277f326b6b9SMartin Probst                " * @lala {lala {lalala\n"
2278f326b6b9SMartin Probst                " */\n",
2279f326b6b9SMartin Probst                "/**\n"
2280f326b6b9SMartin Probst                " * @lala {lala {lalala\n"
2281f326b6b9SMartin Probst                " */\n",
2282f326b6b9SMartin Probst                getGoogleJSStyleWithColumns(20));
22832dbcbd35SKrasimir Georgiev   // cases where '{' is around the column limit
22842dbcbd35SKrasimir Georgiev   for (int ColumnLimit = 6; ColumnLimit < 13; ++ColumnLimit) {
22852dbcbd35SKrasimir Georgiev     verifyFormat("/**\n"
22862dbcbd35SKrasimir Georgiev                  " * @param {type}\n"
22872dbcbd35SKrasimir Georgiev                  " */",
22882dbcbd35SKrasimir Georgiev                  "/**\n"
22892dbcbd35SKrasimir Georgiev                  " * @param {type}\n"
22902dbcbd35SKrasimir Georgiev                  " */",
22912dbcbd35SKrasimir Georgiev                  getGoogleJSStyleWithColumns(ColumnLimit));
22922dbcbd35SKrasimir Georgiev   }
229377b48411SKrasimir Georgiev   // don't break before @tags
229477b48411SKrasimir Georgiev   verifyFormat("/**\n"
229577b48411SKrasimir Georgiev                " * This\n"
229677b48411SKrasimir Georgiev                " * tag @param\n"
229777b48411SKrasimir Georgiev                " * stays.\n"
229877b48411SKrasimir Georgiev                " */",
229977b48411SKrasimir Georgiev                "/**\n"
230077b48411SKrasimir Georgiev                " * This tag @param stays.\n"
230177b48411SKrasimir Georgiev                " */",
230277b48411SKrasimir Georgiev                getGoogleJSStyleWithColumns(13));
2303b4cdb65eSMartin Probst   verifyFormat("/**\n"
2304b4cdb65eSMartin Probst                " * @see http://very/very/long/url/is/long\n"
2305b4cdb65eSMartin Probst                " */",
2306b4cdb65eSMartin Probst                "/**\n"
2307b4cdb65eSMartin Probst                " * @see http://very/very/long/url/is/long\n"
2308b4cdb65eSMartin Probst                " */",
2309b4cdb65eSMartin Probst                getGoogleJSStyleWithColumns(20));
2310ece7e95fSmydeveloperday   verifyFormat("/**\n"
2311bb46a7ddSMartin Probst                " * @param This is a\n"
23126a5c95bdSKrasimir Georgiev                " *     long comment\n"
23136a5c95bdSKrasimir Georgiev                " *     but no type\n"
2314bb46a7ddSMartin Probst                " */",
2315bb46a7ddSMartin Probst                "/**\n"
2316bb46a7ddSMartin Probst                " * @param This is a long comment but no type\n"
2317bb46a7ddSMartin Probst                " */",
2318bb46a7ddSMartin Probst                getGoogleJSStyleWithColumns(20));
23196a5c95bdSKrasimir Georgiev   // Break and reindent @param line and reflow unrelated lines.
23206a5c95bdSKrasimir Georgiev   EXPECT_EQ("{\n"
232117725d83SKrasimir Georgiev             "  /**\n"
232217725d83SKrasimir Georgiev             "   * long long long\n"
232317725d83SKrasimir Georgiev             "   * long\n"
23249d717813SMartin Probst             "   * @param {this.is.a.long.path.to.a.Type}\n"
23256a5c95bdSKrasimir Georgiev             "   *     a\n"
232617725d83SKrasimir Georgiev             "   * long long long\n"
232717725d83SKrasimir Georgiev             "   * long long\n"
232817725d83SKrasimir Georgiev             "   */\n"
232917725d83SKrasimir Georgiev             "  function f(a) {}\n"
233017725d83SKrasimir Georgiev             "}",
23316a5c95bdSKrasimir Georgiev             format("{\n"
233217725d83SKrasimir Georgiev                    "/**\n"
233317725d83SKrasimir Georgiev                    " * long long long long\n"
233417725d83SKrasimir Georgiev                    " * @param {this.is.a.long.path.to.a.Type} a\n"
233517725d83SKrasimir Georgiev                    " * long long long long\n"
233617725d83SKrasimir Georgiev                    " * long\n"
233717725d83SKrasimir Georgiev                    " */\n"
233817725d83SKrasimir Georgiev                    "  function f(a) {}\n"
233917725d83SKrasimir Georgiev                    "}",
23406a5c95bdSKrasimir Georgiev                    getGoogleJSStyleWithColumns(20)));
2341d196abbbSDaniel Jasper }
2342d196abbbSDaniel Jasper 
TEST_F(FormatTestJS,TslintComments)23439835cf15SMartin Probst TEST_F(FormatTestJS, TslintComments) {
23449835cf15SMartin Probst   // tslint uses pragma comments that must be on their own line.
23459835cf15SMartin Probst   verifyFormat("// Comment that needs wrapping. Comment that needs wrapping. "
23469835cf15SMartin Probst                "Comment that needs\n"
23479835cf15SMartin Probst                "// wrapping. Trailing line.\n"
23489835cf15SMartin Probst                "// tslint:disable-next-line:must-be-on-own-line",
23499835cf15SMartin Probst                "// Comment that needs wrapping. Comment that needs wrapping. "
23509835cf15SMartin Probst                "Comment that needs wrapping.\n"
23519835cf15SMartin Probst                "// Trailing line.\n"
23529835cf15SMartin Probst                "// tslint:disable-next-line:must-be-on-own-line");
23539835cf15SMartin Probst }
23549835cf15SMartin Probst 
TEST_F(FormatTestJS,TscComments)23559835cf15SMartin Probst TEST_F(FormatTestJS, TscComments) {
23569835cf15SMartin Probst   // As above, @ts-ignore and @ts-check comments must be on their own line.
23579835cf15SMartin Probst   verifyFormat("// Comment that needs wrapping. Comment that needs wrapping. "
23589835cf15SMartin Probst                "Comment that needs\n"
23599835cf15SMartin Probst                "// wrapping. Trailing line.\n"
23609835cf15SMartin Probst                "// @ts-ignore",
23619835cf15SMartin Probst                "// Comment that needs wrapping. Comment that needs wrapping. "
23629835cf15SMartin Probst                "Comment that needs wrapping.\n"
23639835cf15SMartin Probst                "// Trailing line.\n"
23649835cf15SMartin Probst                "// @ts-ignore");
23659835cf15SMartin Probst   verifyFormat("// Comment that needs wrapping. Comment that needs wrapping. "
23669835cf15SMartin Probst                "Comment that needs\n"
23679835cf15SMartin Probst                "// wrapping. Trailing line.\n"
23689835cf15SMartin Probst                "// @ts-check",
23699835cf15SMartin Probst                "// Comment that needs wrapping. Comment that needs wrapping. "
23709835cf15SMartin Probst                "Comment that needs wrapping.\n"
23719835cf15SMartin Probst                "// Trailing line.\n"
23729835cf15SMartin Probst                "// @ts-check");
23739835cf15SMartin Probst }
23749835cf15SMartin Probst 
TEST_F(FormatTestJS,RequoteStringsSingle)2375abd1f574SDaniel Jasper TEST_F(FormatTestJS, RequoteStringsSingle) {
23761dcbbcfcSDaniel Jasper   verifyFormat("var x = 'foo';", "var x = \"foo\";");
23771dcbbcfcSDaniel Jasper   verifyFormat("var x = 'fo\\'o\\'';", "var x = \"fo'o'\";");
23781dcbbcfcSDaniel Jasper   verifyFormat("var x = 'fo\\'o\\'';", "var x = \"fo\\'o'\";");
2379ece7e95fSmydeveloperday   verifyFormat("var x =\n"
2380abd1f574SDaniel Jasper                "    'foo\\'';",
2381ece7e95fSmydeveloperday                // Code below is 15 chars wide, doesn't fit into the line with
2382ece7e95fSmydeveloperday                // the \ escape added.
23831dcbbcfcSDaniel Jasper                "var x = \"foo'\";", getGoogleJSStyleWithColumns(15));
2384abd1f574SDaniel Jasper   // Removes no-longer needed \ escape from ".
23851dcbbcfcSDaniel Jasper   verifyFormat("var x = 'fo\"o';", "var x = \"fo\\\"o\";");
2386abd1f574SDaniel Jasper   // Code below fits into 15 chars *after* removing the \ escape.
23871dcbbcfcSDaniel Jasper   verifyFormat("var x = 'fo\"o';", "var x = \"fo\\\"o\";",
23881dcbbcfcSDaniel Jasper                getGoogleJSStyleWithColumns(15));
2389a166979eSMartin Probst   verifyFormat("// clang-format off\n"
2390a166979eSMartin Probst                "let x = \"double\";\n"
2391a166979eSMartin Probst                "// clang-format on\n"
2392a166979eSMartin Probst                "let x = 'single';\n",
2393a166979eSMartin Probst                "// clang-format off\n"
2394a166979eSMartin Probst                "let x = \"double\";\n"
2395a166979eSMartin Probst                "// clang-format on\n"
2396a166979eSMartin Probst                "let x = \"single\";\n");
2397abd1f574SDaniel Jasper }
2398abd1f574SDaniel Jasper 
TEST_F(FormatTestJS,RequoteAndIndent)2399a9855afeSMartin Probst TEST_F(FormatTestJS, RequoteAndIndent) {
2400a9855afeSMartin Probst   verifyFormat("let x = someVeryLongFunctionThatGoesOnAndOn(\n"
2401a9855afeSMartin Probst                "    'double quoted string that needs wrapping');",
2402a9855afeSMartin Probst                "let x = someVeryLongFunctionThatGoesOnAndOn("
2403a9855afeSMartin Probst                "\"double quoted string that needs wrapping\");");
2404496c1999SDaniel Jasper 
2405496c1999SDaniel Jasper   verifyFormat("let x =\n"
2406496c1999SDaniel Jasper                "    'foo\\'oo';\n"
2407496c1999SDaniel Jasper                "let x =\n"
2408496c1999SDaniel Jasper                "    'foo\\'oo';",
2409496c1999SDaniel Jasper                "let x=\"foo'oo\";\n"
2410496c1999SDaniel Jasper                "let x=\"foo'oo\";",
2411496c1999SDaniel Jasper                getGoogleJSStyleWithColumns(15));
2412a9855afeSMartin Probst }
2413a9855afeSMartin Probst 
TEST_F(FormatTestJS,RequoteStringsDouble)2414abd1f574SDaniel Jasper TEST_F(FormatTestJS, RequoteStringsDouble) {
2415abd1f574SDaniel Jasper   FormatStyle DoubleQuotes = getGoogleStyle(FormatStyle::LK_JavaScript);
2416abd1f574SDaniel Jasper   DoubleQuotes.JavaScriptQuotes = FormatStyle::JSQS_Double;
2417abd1f574SDaniel Jasper   verifyFormat("var x = \"foo\";", DoubleQuotes);
24181dcbbcfcSDaniel Jasper   verifyFormat("var x = \"foo\";", "var x = 'foo';", DoubleQuotes);
24191dcbbcfcSDaniel Jasper   verifyFormat("var x = \"fo'o\";", "var x = 'fo\\'o';", DoubleQuotes);
2420abd1f574SDaniel Jasper }
2421abd1f574SDaniel Jasper 
TEST_F(FormatTestJS,RequoteStringsLeave)2422abd1f574SDaniel Jasper TEST_F(FormatTestJS, RequoteStringsLeave) {
2423abd1f574SDaniel Jasper   FormatStyle LeaveQuotes = getGoogleStyle(FormatStyle::LK_JavaScript);
2424abd1f574SDaniel Jasper   LeaveQuotes.JavaScriptQuotes = FormatStyle::JSQS_Leave;
2425abd1f574SDaniel Jasper   verifyFormat("var x = \"foo\";", LeaveQuotes);
2426abd1f574SDaniel Jasper   verifyFormat("var x = 'foo';", LeaveQuotes);
2427abd1f574SDaniel Jasper }
2428abd1f574SDaniel Jasper 
TEST_F(FormatTestJS,SupportShebangLines)24297ea9b6d7SMartin Probst TEST_F(FormatTestJS, SupportShebangLines) {
24307ea9b6d7SMartin Probst   verifyFormat("#!/usr/bin/env node\n"
24317ea9b6d7SMartin Probst                "var x = hello();",
24327ea9b6d7SMartin Probst                "#!/usr/bin/env node\n"
24337ea9b6d7SMartin Probst                "var x   =  hello();");
24347ea9b6d7SMartin Probst }
24357ea9b6d7SMartin Probst 
TEST_F(FormatTestJS,NonNullAssertionOperator)24360eb40cfaSMartin Probst TEST_F(FormatTestJS, NonNullAssertionOperator) {
24370eb40cfaSMartin Probst   verifyFormat("let x = foo!.bar();\n");
24380eb40cfaSMartin Probst   verifyFormat("let x = foo ? bar! : baz;\n");
24390eb40cfaSMartin Probst   verifyFormat("let x = !foo;\n");
2440446d6ec9SKrasimir Georgiev   verifyFormat("if (!+a) {\n}");
24410eb40cfaSMartin Probst   verifyFormat("let x = foo[0]!;\n");
24420eb40cfaSMartin Probst   verifyFormat("let x = (foo)!;\n");
2443ab60acb6SMartin Probst   verifyFormat("let x = x(foo!);\n");
2444ece7e95fSmydeveloperday   verifyFormat("a.aaaaaa(a.a!).then(\n"
2445ab60acb6SMartin Probst                "    x => x(x));\n",
2446ab60acb6SMartin Probst                getGoogleJSStyleWithColumns(20));
24478315ea16SDaniel Jasper   verifyFormat("let x = foo! - 1;\n");
24480eb40cfaSMartin Probst   verifyFormat("let x = {foo: 1}!;\n");
2449ece7e95fSmydeveloperday   verifyFormat("let x = hello.foo()!\n"
245022b8d269SMartin Probst                "            .foo()!\n"
245122b8d269SMartin Probst                "            .foo()!\n"
245222b8d269SMartin Probst                "            .foo()!;\n",
245322b8d269SMartin Probst                getGoogleJSStyleWithColumns(20));
245479f9c5feSMartin Probst   verifyFormat("let x = namespace!;\n");
245582b3d906SMartin Probst   verifyFormat("return !!x;\n");
24560eb40cfaSMartin Probst }
24570eb40cfaSMartin Probst 
TEST_F(FormatTestJS,CppKeywords)2458146d685cSMartin Probst TEST_F(FormatTestJS, CppKeywords) {
2459146d685cSMartin Probst   // Make sure we don't mess stuff up because of C++ keywords.
2460146d685cSMartin Probst   verifyFormat("return operator && (aa);");
2461146d685cSMartin Probst   // .. or QT ones.
2462146d685cSMartin Probst   verifyFormat("const slots: Slot[];");
2463146d685cSMartin Probst   // use the "!" assertion operator to validate that clang-format understands
2464146d685cSMartin Probst   // these C++ keywords aren't keywords in JS/TS.
2465146d685cSMartin Probst   verifyFormat("auto!;");
2466146d685cSMartin Probst   verifyFormat("char!;");
2467146d685cSMartin Probst   verifyFormat("concept!;");
2468146d685cSMartin Probst   verifyFormat("double!;");
2469146d685cSMartin Probst   verifyFormat("extern!;");
2470146d685cSMartin Probst   verifyFormat("float!;");
2471146d685cSMartin Probst   verifyFormat("inline!;");
2472146d685cSMartin Probst   verifyFormat("int!;");
2473146d685cSMartin Probst   verifyFormat("long!;");
2474146d685cSMartin Probst   verifyFormat("register!;");
2475146d685cSMartin Probst   verifyFormat("restrict!;");
2476146d685cSMartin Probst   verifyFormat("sizeof!;");
2477146d685cSMartin Probst   verifyFormat("struct!;");
2478146d685cSMartin Probst   verifyFormat("typedef!;");
2479146d685cSMartin Probst   verifyFormat("union!;");
2480146d685cSMartin Probst   verifyFormat("unsigned!;");
2481146d685cSMartin Probst   verifyFormat("volatile!;");
2482146d685cSMartin Probst   verifyFormat("_Alignas!;");
2483146d685cSMartin Probst   verifyFormat("_Alignof!;");
2484146d685cSMartin Probst   verifyFormat("_Atomic!;");
2485146d685cSMartin Probst   verifyFormat("_Bool!;");
2486146d685cSMartin Probst   verifyFormat("_Complex!;");
2487146d685cSMartin Probst   verifyFormat("_Generic!;");
2488146d685cSMartin Probst   verifyFormat("_Imaginary!;");
2489146d685cSMartin Probst   verifyFormat("_Noreturn!;");
2490146d685cSMartin Probst   verifyFormat("_Static_assert!;");
2491146d685cSMartin Probst   verifyFormat("_Thread_local!;");
2492146d685cSMartin Probst   verifyFormat("__func__!;");
2493146d685cSMartin Probst   verifyFormat("__objc_yes!;");
2494146d685cSMartin Probst   verifyFormat("__objc_no!;");
2495146d685cSMartin Probst   verifyFormat("asm!;");
2496146d685cSMartin Probst   verifyFormat("bool!;");
2497146d685cSMartin Probst   verifyFormat("const_cast!;");
2498146d685cSMartin Probst   verifyFormat("dynamic_cast!;");
2499146d685cSMartin Probst   verifyFormat("explicit!;");
2500146d685cSMartin Probst   verifyFormat("friend!;");
2501146d685cSMartin Probst   verifyFormat("mutable!;");
2502146d685cSMartin Probst   verifyFormat("operator!;");
2503146d685cSMartin Probst   verifyFormat("reinterpret_cast!;");
2504146d685cSMartin Probst   verifyFormat("static_cast!;");
2505146d685cSMartin Probst   verifyFormat("template!;");
2506146d685cSMartin Probst   verifyFormat("typename!;");
2507146d685cSMartin Probst   verifyFormat("typeid!;");
2508146d685cSMartin Probst   verifyFormat("using!;");
2509146d685cSMartin Probst   verifyFormat("virtual!;");
2510146d685cSMartin Probst   verifyFormat("wchar_t!;");
251192201505SMartin Probst 
251292201505SMartin Probst   // Positive tests:
251392201505SMartin Probst   verifyFormat("x.type!;");
251492201505SMartin Probst   verifyFormat("x.get!;");
251592201505SMartin Probst   verifyFormat("x.set!;");
2516146d685cSMartin Probst }
2517146d685cSMartin Probst 
TEST_F(FormatTestJS,NullPropagatingOperator)2518a7638d38SMartin Probst TEST_F(FormatTestJS, NullPropagatingOperator) {
2519a7638d38SMartin Probst   verifyFormat("let x = foo?.bar?.baz();\n");
2520a7638d38SMartin Probst   verifyFormat("let x = foo?.(foo);\n");
2521a7638d38SMartin Probst   verifyFormat("let x = foo?.['arr'];\n");
2522a7638d38SMartin Probst }
2523a7638d38SMartin Probst 
TEST_F(FormatTestJS,NullishCoalescingOperator)2524a7638d38SMartin Probst TEST_F(FormatTestJS, NullishCoalescingOperator) {
2525a7638d38SMartin Probst   verifyFormat("const val = something ?? 'some other default';\n");
25264c9d6914SMartin Probst   verifyFormat(
25274c9d6914SMartin Probst       "const val = something ?? otherDefault ??\n"
25284c9d6914SMartin Probst       "    evenMore ?? evenMore;\n",
25294c9d6914SMartin Probst       "const val = something ?? otherDefault ?? evenMore ?? evenMore;\n",
25304c9d6914SMartin Probst       getGoogleJSStyleWithColumns(40));
2531a7638d38SMartin Probst }
2532a7638d38SMartin Probst 
TEST_F(FormatTestJS,AssignmentOperators)253316212b8bSMartin Probst TEST_F(FormatTestJS, AssignmentOperators) {
253416212b8bSMartin Probst   verifyFormat("a &&= b;\n");
253516212b8bSMartin Probst   verifyFormat("a ||= b;\n");
253616212b8bSMartin Probst   // NB: need to split ? ?= to avoid it being interpreted by C++ as a trigraph
253716212b8bSMartin Probst   // for #.
253816212b8bSMartin Probst   verifyFormat("a ?"
253916212b8bSMartin Probst                "?= b;\n");
254016212b8bSMartin Probst }
254116212b8bSMartin Probst 
TEST_F(FormatTestJS,Conditional)254231d6da7cSMartin Probst TEST_F(FormatTestJS, Conditional) {
254331d6da7cSMartin Probst   verifyFormat("y = x ? 1 : 2;");
2544d9d8da28SDaniel Jasper   verifyFormat("x ? 1 : 2;");
254531d6da7cSMartin Probst   verifyFormat("class Foo {\n"
254631d6da7cSMartin Probst                "  field = true ? 1 : 2;\n"
254731d6da7cSMartin Probst                "  method(a = true ? 1 : 2) {}\n"
254831d6da7cSMartin Probst                "}");
254931d6da7cSMartin Probst }
255031d6da7cSMartin Probst 
TEST_F(FormatTestJS,ImportComments)2551fbbe75b1SMartin Probst TEST_F(FormatTestJS, ImportComments) {
2552fbbe75b1SMartin Probst   verifyFormat("import {x} from 'x';  // from some location",
2553fbbe75b1SMartin Probst                getGoogleJSStyleWithColumns(25));
2554fbbe75b1SMartin Probst   verifyFormat("// taze: x from 'location'", getGoogleJSStyleWithColumns(10));
2555ece7e95fSmydeveloperday   verifyFormat("/// <reference path=\"some/location\" />",
2556ece7e95fSmydeveloperday                getGoogleJSStyleWithColumns(10));
2557fbbe75b1SMartin Probst }
25584ef0370eSMartin Probst 
TEST_F(FormatTestJS,Exponentiation)25594ef0370eSMartin Probst TEST_F(FormatTestJS, Exponentiation) {
25604ef0370eSMartin Probst   verifyFormat("squared = x ** 2;");
25614ef0370eSMartin Probst   verifyFormat("squared **= 2;");
25624ef0370eSMartin Probst }
25634ef0370eSMartin Probst 
TEST_F(FormatTestJS,NestedLiterals)256438423276SMartin Probst TEST_F(FormatTestJS, NestedLiterals) {
256538423276SMartin Probst   FormatStyle FourSpaces = getGoogleJSStyleWithColumns(15);
256638423276SMartin Probst   FourSpaces.IndentWidth = 4;
256738423276SMartin Probst   verifyFormat("var l = [\n"
256838423276SMartin Probst                "    [\n"
256938423276SMartin Probst                "        1,\n"
257038423276SMartin Probst                "    ],\n"
2571ece7e95fSmydeveloperday                "];",
2572ece7e95fSmydeveloperday                FourSpaces);
257338423276SMartin Probst   verifyFormat("var l = [\n"
257438423276SMartin Probst                "    {\n"
257538423276SMartin Probst                "        1: 1,\n"
257638423276SMartin Probst                "    },\n"
2577ece7e95fSmydeveloperday                "];",
2578ece7e95fSmydeveloperday                FourSpaces);
257938423276SMartin Probst   verifyFormat("someFunction(\n"
258038423276SMartin Probst                "    p1,\n"
258138423276SMartin Probst                "    [\n"
258238423276SMartin Probst                "        1,\n"
258338423276SMartin Probst                "    ],\n"
2584ece7e95fSmydeveloperday                ");",
2585ece7e95fSmydeveloperday                FourSpaces);
258638423276SMartin Probst   verifyFormat("someFunction(\n"
258738423276SMartin Probst                "    p1,\n"
258838423276SMartin Probst                "    {\n"
258938423276SMartin Probst                "        1: 1,\n"
259038423276SMartin Probst                "    },\n"
2591ece7e95fSmydeveloperday                ");",
2592ece7e95fSmydeveloperday                FourSpaces);
259338423276SMartin Probst   verifyFormat("var o = {\n"
259438423276SMartin Probst                "    1: 1,\n"
259538423276SMartin Probst                "    2: {\n"
259638423276SMartin Probst                "        3: 3,\n"
259738423276SMartin Probst                "    },\n"
2598ece7e95fSmydeveloperday                "};",
2599ece7e95fSmydeveloperday                FourSpaces);
260038423276SMartin Probst   verifyFormat("var o = {\n"
260138423276SMartin Probst                "    1: 1,\n"
260238423276SMartin Probst                "    2: [\n"
260338423276SMartin Probst                "        3,\n"
260438423276SMartin Probst                "    ],\n"
2605ece7e95fSmydeveloperday                "};",
2606ece7e95fSmydeveloperday                FourSpaces);
260738423276SMartin Probst }
260838423276SMartin Probst 
TEST_F(FormatTestJS,BackslashesInComments)260964d31edeSMartin Probst TEST_F(FormatTestJS, BackslashesInComments) {
261064d31edeSMartin Probst   verifyFormat("// hello \\\n"
261164d31edeSMartin Probst                "if (x) foo();\n",
261264d31edeSMartin Probst                "// hello \\\n"
261364d31edeSMartin Probst                "     if ( x) \n"
261464d31edeSMartin Probst                "   foo();\n");
261564d31edeSMartin Probst   verifyFormat("/* ignore \\\n"
261664d31edeSMartin Probst                " */\n"
261764d31edeSMartin Probst                "if (x) foo();\n",
261864d31edeSMartin Probst                "/* ignore \\\n"
261964d31edeSMartin Probst                " */\n"
262064d31edeSMartin Probst                " if (  x) foo();\n");
262164d31edeSMartin Probst   verifyFormat("// st \\ art\\\n"
262264d31edeSMartin Probst                "// comment"
262364d31edeSMartin Probst                "// continue \\\n"
262464d31edeSMartin Probst                "formatMe();\n",
262564d31edeSMartin Probst                "// st \\ art\\\n"
262664d31edeSMartin Probst                "// comment"
262764d31edeSMartin Probst                "// continue \\\n"
262864d31edeSMartin Probst                "formatMe( );\n");
262964d31edeSMartin Probst }
263064d31edeSMartin Probst 
TEST_F(FormatTestJS,AddsLastLinePenaltyIfEndingIsBroken)2631123ca80bSKrasimir Georgiev TEST_F(FormatTestJS, AddsLastLinePenaltyIfEndingIsBroken) {
2632123ca80bSKrasimir Georgiev   EXPECT_EQ(
2633123ca80bSKrasimir Georgiev       "a = function() {\n"
2634123ca80bSKrasimir Georgiev       "  b = function() {\n"
2635123ca80bSKrasimir Georgiev       "    this.aaaaaaaaaaaaaaaaaaa[aaaaaaaaaaa] = aaaa.aaaaaa ?\n"
2636123ca80bSKrasimir Georgiev       "        aaaa.aaaaaa : /** @type "
2637123ca80bSKrasimir Georgiev       "{aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaaaaaaaa} */\n"
2638123ca80bSKrasimir Georgiev       "        (aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaa.aaaaaaaaaaaaaaaaa);\n"
2639123ca80bSKrasimir Georgiev       "  };\n"
2640123ca80bSKrasimir Georgiev       "};",
2641123ca80bSKrasimir Georgiev       format("a = function() {\n"
2642123ca80bSKrasimir Georgiev              "  b = function() {\n"
2643123ca80bSKrasimir Georgiev              "    this.aaaaaaaaaaaaaaaaaaa[aaaaaaaaaaa] = aaaa.aaaaaa ? "
2644123ca80bSKrasimir Georgiev              "aaaa.aaaaaa : /** @type "
2645123ca80bSKrasimir Georgiev              "{aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaaaaaaaa} */\n"
2646123ca80bSKrasimir Georgiev              "        (aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaa.aaaaaaaaaaaaaaaaa);\n"
2647123ca80bSKrasimir Georgiev              "  };\n"
2648123ca80bSKrasimir Georgiev              "};"));
2649123ca80bSKrasimir Georgiev }
2650123ca80bSKrasimir Georgiev 
TEST_F(FormatTestJS,ParameterNamingComment)2651cc525e7bSMartin Probst TEST_F(FormatTestJS, ParameterNamingComment) {
2652cc525e7bSMartin Probst   verifyFormat("callFoo(/*spaceAfterParameterNamingComment=*/ 1);");
2653cc525e7bSMartin Probst }
2654cc525e7bSMartin Probst 
TEST_F(FormatTestJS,ConditionalTypes)26553315aed4SMartin Probst TEST_F(FormatTestJS, ConditionalTypes) {
26563315aed4SMartin Probst   // Formatting below is not necessarily intentional, this just ensures that
26573315aed4SMartin Probst   // clang-format does not break the code.
26583315aed4SMartin Probst   verifyFormat( // wrap
26593315aed4SMartin Probst       "type UnionToIntersection<U> =\n"
26603315aed4SMartin Probst       "    (U extends any ? (k: U) => void :\n"
26613315aed4SMartin Probst       "                     never) extends((k: infer I) => void) ? I : never;");
26623315aed4SMartin Probst }
26633315aed4SMartin Probst 
TEST_F(FormatTestJS,SupportPrivateFieldsAndMethods)266426a484f4SMartin Probst TEST_F(FormatTestJS, SupportPrivateFieldsAndMethods) {
266526a484f4SMartin Probst   verifyFormat("class Example {\n"
266626a484f4SMartin Probst                "  pub = 1;\n"
266726a484f4SMartin Probst                "  #priv = 2;\n"
266826a484f4SMartin Probst                "  static pub2 = 'foo';\n"
266926a484f4SMartin Probst                "  static #priv2 = 'bar';\n"
267026a484f4SMartin Probst                "  method() {\n"
267126a484f4SMartin Probst                "    this.#priv = 5;\n"
267226a484f4SMartin Probst                "  }\n"
267326a484f4SMartin Probst                "  static staticMethod() {\n"
267426a484f4SMartin Probst                "    switch (this.#priv) {\n"
267526a484f4SMartin Probst                "      case '1':\n"
267626a484f4SMartin Probst                "        #priv = 3;\n"
267726a484f4SMartin Probst                "        break;\n"
267826a484f4SMartin Probst                "    }\n"
267926a484f4SMartin Probst                "  }\n"
268026a484f4SMartin Probst                "  #privateMethod() {\n"
268126a484f4SMartin Probst                "    this.#privateMethod();  // infinite loop\n"
268226a484f4SMartin Probst                "  }\n"
268326a484f4SMartin Probst                "  static #staticPrivateMethod() {}\n");
268426a484f4SMartin Probst }
268526a484f4SMartin Probst 
TEST_F(FormatTestJS,DeclaredFields)26866bcd8d4aSMartin Probst TEST_F(FormatTestJS, DeclaredFields) {
26876bcd8d4aSMartin Probst   verifyFormat("class Example {\n"
26886bcd8d4aSMartin Probst                "  declare pub: string;\n"
26896bcd8d4aSMartin Probst                "  declare private priv: string;\n"
26906bcd8d4aSMartin Probst                "}\n");
26916bcd8d4aSMartin Probst }
26926bcd8d4aSMartin Probst 
TEST_F(FormatTestJS,NoBreakAfterAsserts)269370ae843dSMartin Probst TEST_F(FormatTestJS, NoBreakAfterAsserts) {
269470ae843dSMartin Probst   verifyFormat(
269570ae843dSMartin Probst       "interface Assertable<State extends {}> {\n"
269670ae843dSMartin Probst       "  assert<ExportedState extends {}, DependencyState extends State = "
269770ae843dSMartin Probst       "State>(\n"
269870ae843dSMartin Probst       "      callback: Callback<ExportedState, DependencyState>):\n"
269970ae843dSMartin Probst       "      asserts this is ExtendedState<DependencyState&ExportedState>;\n"
270070ae843dSMartin Probst       "}\n",
270170ae843dSMartin Probst       "interface Assertable<State extends {}> {\n"
270270ae843dSMartin Probst       "  assert<ExportedState extends {}, DependencyState extends State = "
270370ae843dSMartin Probst       "State>(callback: Callback<ExportedState, DependencyState>): asserts "
270470ae843dSMartin Probst       "this is ExtendedState<DependencyState&ExportedState>;\n"
270570ae843dSMartin Probst       "}\n");
270670ae843dSMartin Probst }
270770ae843dSMartin Probst 
TEST_F(FormatTestJS,NumericSeparators)2708327d9663SMartin Probst TEST_F(FormatTestJS, NumericSeparators) {
2709327d9663SMartin Probst   verifyFormat("x = 1_000_000 + 12;", "x = 1_000_000   + 12;");
2710327d9663SMartin Probst }
2711327d9663SMartin Probst 
TEST_F(FormatTestJS,AlignConsecutiveDeclarations)27126e28b86cSmydeveloperday TEST_F(FormatTestJS, AlignConsecutiveDeclarations) {
27136e28b86cSmydeveloperday   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
2714c24b3db4Ssstwcw   Style.AlignConsecutiveDeclarations.Enabled = true;
27156e28b86cSmydeveloperday   verifyFormat("let    letVariable = 5;\n"
27166e28b86cSmydeveloperday                "double constVariable = 10;",
27176e28b86cSmydeveloperday                Style);
27186e28b86cSmydeveloperday 
27196e28b86cSmydeveloperday   verifyFormat("let   letVariable = 5;\n"
27206e28b86cSmydeveloperday                "const constVariable = 10;",
27216e28b86cSmydeveloperday                Style);
27226e28b86cSmydeveloperday 
27236e28b86cSmydeveloperday   verifyFormat("let          letVariable = 5;\n"
27246e28b86cSmydeveloperday                "static const constVariable = 10;",
27256e28b86cSmydeveloperday                Style);
27266e28b86cSmydeveloperday 
27276e28b86cSmydeveloperday   verifyFormat("let        letVariable = 5;\n"
27286e28b86cSmydeveloperday                "static var constVariable = 10;",
27296e28b86cSmydeveloperday                Style);
27306e28b86cSmydeveloperday 
27316e28b86cSmydeveloperday   verifyFormat("let letVariable = 5;\n"
27326e28b86cSmydeveloperday                "var constVariable = 10;",
27336e28b86cSmydeveloperday                Style);
27346e28b86cSmydeveloperday 
27356e28b86cSmydeveloperday   verifyFormat("double letVariable = 5;\n"
27366e28b86cSmydeveloperday                "var    constVariable = 10;",
27376e28b86cSmydeveloperday                Style);
27386e28b86cSmydeveloperday 
27396e28b86cSmydeveloperday   verifyFormat("const letVariable = 5;\n"
27406e28b86cSmydeveloperday                "var   constVariable = 10;",
27416e28b86cSmydeveloperday                Style);
27426e28b86cSmydeveloperday 
27436e28b86cSmydeveloperday   verifyFormat("int letVariable = 5;\n"
27446e28b86cSmydeveloperday                "int constVariable = 10;",
27456e28b86cSmydeveloperday                Style);
27466e28b86cSmydeveloperday }
27476e28b86cSmydeveloperday 
TEST_F(FormatTestJS,AlignConsecutiveAssignments)27486e28b86cSmydeveloperday TEST_F(FormatTestJS, AlignConsecutiveAssignments) {
27496e28b86cSmydeveloperday   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
27506e28b86cSmydeveloperday 
2751c24b3db4Ssstwcw   Style.AlignConsecutiveAssignments.Enabled = true;
27526e28b86cSmydeveloperday   verifyFormat("let letVariable      = 5;\n"
27536e28b86cSmydeveloperday                "double constVariable = 10;",
27546e28b86cSmydeveloperday                Style);
27556e28b86cSmydeveloperday 
27566e28b86cSmydeveloperday   verifyFormat("let letVariable     = 5;\n"
27576e28b86cSmydeveloperday                "const constVariable = 10;",
27586e28b86cSmydeveloperday                Style);
27596e28b86cSmydeveloperday 
27606e28b86cSmydeveloperday   verifyFormat("let letVariable            = 5;\n"
27616e28b86cSmydeveloperday                "static const constVariable = 10;",
27626e28b86cSmydeveloperday                Style);
27636e28b86cSmydeveloperday 
27646e28b86cSmydeveloperday   verifyFormat("let letVariable          = 5;\n"
27656e28b86cSmydeveloperday                "static var constVariable = 10;",
27666e28b86cSmydeveloperday                Style);
27676e28b86cSmydeveloperday 
27686e28b86cSmydeveloperday   verifyFormat("let letVariable   = 5;\n"
27696e28b86cSmydeveloperday                "var constVariable = 10;",
27706e28b86cSmydeveloperday                Style);
27716e28b86cSmydeveloperday 
27726e28b86cSmydeveloperday   verifyFormat("double letVariable = 5;\n"
27736e28b86cSmydeveloperday                "var constVariable  = 10;",
27746e28b86cSmydeveloperday                Style);
27756e28b86cSmydeveloperday 
27766e28b86cSmydeveloperday   verifyFormat("const letVariable = 5;\n"
27776e28b86cSmydeveloperday                "var constVariable = 10;",
27786e28b86cSmydeveloperday                Style);
27796e28b86cSmydeveloperday 
27806e28b86cSmydeveloperday   verifyFormat("int letVariable   = 5;\n"
27816e28b86cSmydeveloperday                "int constVariable = 10;",
27826e28b86cSmydeveloperday                Style);
27836e28b86cSmydeveloperday }
27846e28b86cSmydeveloperday 
TEST_F(FormatTestJS,AlignConsecutiveAssignmentsAndDeclarations)27856e28b86cSmydeveloperday TEST_F(FormatTestJS, AlignConsecutiveAssignmentsAndDeclarations) {
27866e28b86cSmydeveloperday   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
2787c24b3db4Ssstwcw   Style.AlignConsecutiveDeclarations.Enabled = true;
2788c24b3db4Ssstwcw   Style.AlignConsecutiveAssignments.Enabled = true;
27896e28b86cSmydeveloperday   verifyFormat("let    letVariable   = 5;\n"
27906e28b86cSmydeveloperday                "double constVariable = 10;",
27916e28b86cSmydeveloperday                Style);
27926e28b86cSmydeveloperday 
27936e28b86cSmydeveloperday   verifyFormat("let   letVariable   = 5;\n"
27946e28b86cSmydeveloperday                "const constVariable = 10;",
27956e28b86cSmydeveloperday                Style);
27966e28b86cSmydeveloperday 
27976e28b86cSmydeveloperday   verifyFormat("let          letVariable   = 5;\n"
27986e28b86cSmydeveloperday                "static const constVariable = 10;",
27996e28b86cSmydeveloperday                Style);
28006e28b86cSmydeveloperday 
28016e28b86cSmydeveloperday   verifyFormat("let        letVariable   = 5;\n"
28026e28b86cSmydeveloperday                "static var constVariable = 10;",
28036e28b86cSmydeveloperday                Style);
28046e28b86cSmydeveloperday 
28056e28b86cSmydeveloperday   verifyFormat("let letVariable   = 5;\n"
28066e28b86cSmydeveloperday                "var constVariable = 10;",
28076e28b86cSmydeveloperday                Style);
28086e28b86cSmydeveloperday 
28096e28b86cSmydeveloperday   verifyFormat("double letVariable   = 5;\n"
28106e28b86cSmydeveloperday                "var    constVariable = 10;",
28116e28b86cSmydeveloperday                Style);
28126e28b86cSmydeveloperday 
28136e28b86cSmydeveloperday   verifyFormat("const letVariable   = 5;\n"
28146e28b86cSmydeveloperday                "var   constVariable = 10;",
28156e28b86cSmydeveloperday                Style);
28166e28b86cSmydeveloperday 
28176e28b86cSmydeveloperday   verifyFormat("int letVariable   = 5;\n"
28186e28b86cSmydeveloperday                "int constVariable = 10;",
28196e28b86cSmydeveloperday                Style);
28206e28b86cSmydeveloperday }
28216e28b86cSmydeveloperday 
282226a484f4SMartin Probst } // namespace format
2823a48a12cfSAlexander Kornienko } // end namespace clang
2824