2013-12-03 18:50:16 +08:00
|
|
|
//===- unittest/Format/FormatTestJS.cpp - Formatting unit tests for JS ----===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2013-12-03 18:50:16 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "FormatTestUtils.h"
|
|
|
|
#include "clang/Format/Format.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
2014-04-22 11:17:02 +08:00
|
|
|
#define DEBUG_TYPE "format-test"
|
|
|
|
|
2013-12-03 18:50:16 +08:00
|
|
|
namespace clang {
|
|
|
|
namespace format {
|
|
|
|
|
|
|
|
class FormatTestJS : public ::testing::Test {
|
|
|
|
protected:
|
|
|
|
static std::string format(llvm::StringRef Code, unsigned Offset,
|
|
|
|
unsigned Length, const FormatStyle &Style) {
|
2018-05-15 21:30:56 +08:00
|
|
|
LLVM_DEBUG(llvm::errs() << "---\n");
|
|
|
|
LLVM_DEBUG(llvm::errs() << Code << "\n\n");
|
2013-12-03 18:50:16 +08:00
|
|
|
std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
|
2017-04-21 22:35:20 +08:00
|
|
|
FormattingAttemptStatus Status;
|
2015-06-11 21:29:20 +08:00
|
|
|
tooling::Replacements Replaces =
|
2017-04-21 22:35:20 +08:00
|
|
|
reformat(Style, Code, Ranges, "<stdin>", &Status);
|
|
|
|
EXPECT_TRUE(Status.FormatComplete);
|
2016-07-11 21:53:12 +08:00
|
|
|
auto Result = applyAllReplacements(Code, Replaces);
|
|
|
|
EXPECT_TRUE(static_cast<bool>(Result));
|
2018-05-15 21:30:56 +08:00
|
|
|
LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
|
2016-07-11 21:53:12 +08:00
|
|
|
return *Result;
|
2013-12-03 18:50:16 +08:00
|
|
|
}
|
|
|
|
|
2014-05-20 19:14:57 +08:00
|
|
|
static std::string format(
|
|
|
|
llvm::StringRef Code,
|
|
|
|
const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) {
|
2013-12-03 18:50:16 +08:00
|
|
|
return format(Code, 0, Code.size(), Style);
|
|
|
|
}
|
|
|
|
|
2013-12-10 19:28:13 +08:00
|
|
|
static FormatStyle getGoogleJSStyleWithColumns(unsigned ColumnLimit) {
|
2014-02-03 04:50:45 +08:00
|
|
|
FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
|
2013-12-03 18:50:16 +08:00
|
|
|
Style.ColumnLimit = ColumnLimit;
|
|
|
|
return Style;
|
|
|
|
}
|
|
|
|
|
2014-02-03 04:50:45 +08:00
|
|
|
static void verifyFormat(
|
|
|
|
llvm::StringRef Code,
|
|
|
|
const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) {
|
2020-05-02 22:42:20 +08:00
|
|
|
EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable";
|
2016-03-15 03:21:36 +08:00
|
|
|
std::string Result = format(test::messUp(Code), Style);
|
|
|
|
EXPECT_EQ(Code.str(), Result) << "Formatted:\n" << Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void verifyFormat(
|
2020-05-02 22:42:20 +08:00
|
|
|
llvm::StringRef Expected, llvm::StringRef Code,
|
2016-03-15 03:21:36 +08:00
|
|
|
const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) {
|
2018-04-05 05:09:00 +08:00
|
|
|
EXPECT_EQ(Expected.str(), format(Expected, Style))
|
|
|
|
<< "Expected code is not stable";
|
2016-03-15 03:21:36 +08:00
|
|
|
std::string Result = format(Code, Style);
|
|
|
|
EXPECT_EQ(Expected.str(), Result) << "Formatted:\n" << Result;
|
2013-12-03 18:50:16 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-05-30 06:07:22 +08:00
|
|
|
TEST_F(FormatTestJS, BlockComments) {
|
|
|
|
verifyFormat("/* aaaaaaaaaaaaa */ aaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
|
|
|
|
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
|
2017-10-16 17:08:53 +08:00
|
|
|
// Breaks after a single line block comment.
|
|
|
|
EXPECT_EQ("aaaaa = bbbb.ccccccccccccccc(\n"
|
|
|
|
" /** @type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala} */\n"
|
|
|
|
" mediaMessage);",
|
|
|
|
format("aaaaa = bbbb.ccccccccccccccc(\n"
|
|
|
|
" /** "
|
|
|
|
"@type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala} */ "
|
|
|
|
"mediaMessage);",
|
|
|
|
getGoogleJSStyleWithColumns(70)));
|
|
|
|
// Breaks after a multiline block comment.
|
|
|
|
EXPECT_EQ(
|
|
|
|
"aaaaa = bbbb.ccccccccccccccc(\n"
|
|
|
|
" /**\n"
|
|
|
|
" * @type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala}\n"
|
|
|
|
" */\n"
|
|
|
|
" mediaMessage);",
|
|
|
|
format("aaaaa = bbbb.ccccccccccccccc(\n"
|
|
|
|
" /**\n"
|
|
|
|
" * @type_{!cccc.rrrrrrr.MMMMMMMMMMMM.LLLLLLLLLLL.lala}\n"
|
|
|
|
" */ mediaMessage);",
|
|
|
|
getGoogleJSStyleWithColumns(70)));
|
2016-05-30 06:07:22 +08:00
|
|
|
}
|
|
|
|
|
2017-07-21 06:29:39 +08:00
|
|
|
TEST_F(FormatTestJS, JSDocComments) {
|
|
|
|
// Break the first line of a multiline jsdoc comment.
|
|
|
|
EXPECT_EQ("/**\n"
|
|
|
|
" * jsdoc line 1\n"
|
|
|
|
" * jsdoc line 2\n"
|
|
|
|
" */",
|
|
|
|
format("/** jsdoc line 1\n"
|
|
|
|
" * jsdoc line 2\n"
|
|
|
|
" */",
|
|
|
|
getGoogleJSStyleWithColumns(20)));
|
|
|
|
// Both break after '/**' and break the line itself.
|
|
|
|
EXPECT_EQ("/**\n"
|
|
|
|
" * jsdoc line long\n"
|
|
|
|
" * long jsdoc line 2\n"
|
|
|
|
" */",
|
|
|
|
format("/** jsdoc line long long\n"
|
|
|
|
" * jsdoc line 2\n"
|
|
|
|
" */",
|
|
|
|
getGoogleJSStyleWithColumns(20)));
|
|
|
|
// Break a short first line if the ending '*/' is on a newline.
|
|
|
|
EXPECT_EQ("/**\n"
|
|
|
|
" * jsdoc line 1\n"
|
|
|
|
" */",
|
|
|
|
format("/** jsdoc line 1\n"
|
2020-05-02 22:42:20 +08:00
|
|
|
" */",
|
|
|
|
getGoogleJSStyleWithColumns(20)));
|
2017-07-21 06:29:39 +08:00
|
|
|
// Don't break the first line of a short single line jsdoc comment.
|
|
|
|
EXPECT_EQ("/** jsdoc line 1 */",
|
|
|
|
format("/** jsdoc line 1 */", getGoogleJSStyleWithColumns(20)));
|
|
|
|
// Don't break the first line of a single line jsdoc comment if it just fits
|
|
|
|
// the column limit.
|
|
|
|
EXPECT_EQ("/** jsdoc line 12 */",
|
|
|
|
format("/** jsdoc line 12 */", getGoogleJSStyleWithColumns(20)));
|
|
|
|
// Don't break after '/**' and before '*/' if there is no space between
|
|
|
|
// '/**' and the content.
|
|
|
|
EXPECT_EQ(
|
|
|
|
"/*** nonjsdoc long\n"
|
|
|
|
" * line */",
|
|
|
|
format("/*** nonjsdoc long line */", getGoogleJSStyleWithColumns(20)));
|
|
|
|
EXPECT_EQ(
|
|
|
|
"/**strange long long\n"
|
|
|
|
" * line */",
|
|
|
|
format("/**strange long long line */", getGoogleJSStyleWithColumns(20)));
|
|
|
|
// Break the first line of a single line jsdoc comment if it just exceeds the
|
|
|
|
// column limit.
|
|
|
|
EXPECT_EQ("/**\n"
|
|
|
|
" * jsdoc line 123\n"
|
|
|
|
" */",
|
|
|
|
format("/** jsdoc line 123 */", getGoogleJSStyleWithColumns(20)));
|
|
|
|
// Break also if the leading indent of the first line is more than 1 column.
|
|
|
|
EXPECT_EQ("/**\n"
|
|
|
|
" * jsdoc line 123\n"
|
|
|
|
" */",
|
|
|
|
format("/** jsdoc line 123 */", getGoogleJSStyleWithColumns(20)));
|
|
|
|
// Break also if the leading indent of the first line is more than 1 column.
|
|
|
|
EXPECT_EQ("/**\n"
|
|
|
|
" * jsdoc line 123\n"
|
|
|
|
" */",
|
|
|
|
format("/** jsdoc line 123 */", getGoogleJSStyleWithColumns(20)));
|
|
|
|
// Break after the content of the last line.
|
|
|
|
EXPECT_EQ("/**\n"
|
|
|
|
" * line 1\n"
|
|
|
|
" * line 2\n"
|
|
|
|
" */",
|
|
|
|
format("/**\n"
|
|
|
|
" * line 1\n"
|
|
|
|
" * line 2 */",
|
|
|
|
getGoogleJSStyleWithColumns(20)));
|
|
|
|
// Break both the content and after the content of the last line.
|
|
|
|
EXPECT_EQ("/**\n"
|
|
|
|
" * line 1\n"
|
|
|
|
" * line long long\n"
|
|
|
|
" * long\n"
|
|
|
|
" */",
|
|
|
|
format("/**\n"
|
|
|
|
" * line 1\n"
|
|
|
|
" * line long long long */",
|
|
|
|
getGoogleJSStyleWithColumns(20)));
|
|
|
|
|
|
|
|
// The comment block gets indented.
|
|
|
|
EXPECT_EQ("function f() {\n"
|
|
|
|
" /**\n"
|
|
|
|
" * comment about\n"
|
|
|
|
" * x\n"
|
|
|
|
" */\n"
|
|
|
|
" var x = 1;\n"
|
|
|
|
"}",
|
|
|
|
format("function f() {\n"
|
|
|
|
"/** comment about x */\n"
|
|
|
|
"var x = 1;\n"
|
|
|
|
"}",
|
|
|
|
getGoogleJSStyleWithColumns(20)));
|
2017-08-09 17:42:32 +08:00
|
|
|
|
|
|
|
// Don't break the first line of a single line short jsdoc comment pragma.
|
|
|
|
EXPECT_EQ("/** @returns j */",
|
2020-05-02 22:42:20 +08:00
|
|
|
format("/** @returns j */", getGoogleJSStyleWithColumns(20)));
|
2017-08-09 17:42:32 +08:00
|
|
|
|
|
|
|
// Break a single line long jsdoc comment pragma.
|
|
|
|
EXPECT_EQ("/**\n"
|
2018-08-02 19:52:08 +08:00
|
|
|
" * @returns {string}\n"
|
2018-07-30 16:45:45 +08:00
|
|
|
" * jsdoc line 12\n"
|
2017-08-09 17:42:32 +08:00
|
|
|
" */",
|
2018-08-02 19:52:08 +08:00
|
|
|
format("/** @returns {string} jsdoc line 12 */",
|
2017-08-09 17:42:32 +08:00
|
|
|
getGoogleJSStyleWithColumns(20)));
|
|
|
|
|
2018-07-30 16:45:45 +08:00
|
|
|
// FIXME: this overcounts the */ as a continuation of the 12 when breaking.
|
|
|
|
// Related to the FIXME in BreakableBlockComment::getRangeLength.
|
2017-08-09 17:42:32 +08:00
|
|
|
EXPECT_EQ("/**\n"
|
2018-08-02 19:52:08 +08:00
|
|
|
" * @returns {string}\n"
|
|
|
|
" * jsdoc line line\n"
|
2018-07-30 16:45:45 +08:00
|
|
|
" * 12\n"
|
2017-08-09 17:42:32 +08:00
|
|
|
" */",
|
2018-08-02 19:52:08 +08:00
|
|
|
format("/** @returns {string} jsdoc line line 12*/",
|
|
|
|
getGoogleJSStyleWithColumns(25)));
|
2017-08-09 17:42:32 +08:00
|
|
|
|
|
|
|
// Fix a multiline jsdoc comment ending in a comment pragma.
|
|
|
|
EXPECT_EQ("/**\n"
|
|
|
|
" * line 1\n"
|
|
|
|
" * line 2\n"
|
2018-07-30 16:45:45 +08:00
|
|
|
" * @returns {string}\n"
|
|
|
|
" * jsdoc line 12\n"
|
2017-08-09 17:42:32 +08:00
|
|
|
" */",
|
|
|
|
format("/** line 1\n"
|
|
|
|
" * line 2\n"
|
|
|
|
" * @returns {string} jsdoc line 12 */",
|
|
|
|
getGoogleJSStyleWithColumns(20)));
|
|
|
|
|
|
|
|
EXPECT_EQ("/**\n"
|
|
|
|
" * line 1\n"
|
|
|
|
" * line 2\n"
|
|
|
|
" *\n"
|
|
|
|
" * @returns j\n"
|
|
|
|
" */",
|
|
|
|
format("/** line 1\n"
|
|
|
|
" * line 2\n"
|
|
|
|
" *\n"
|
|
|
|
" * @returns j */",
|
|
|
|
getGoogleJSStyleWithColumns(20)));
|
2017-07-21 06:29:39 +08:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:50:16 +08:00
|
|
|
TEST_F(FormatTestJS, UnderstandsJavaScriptOperators) {
|
|
|
|
verifyFormat("a == = b;");
|
|
|
|
verifyFormat("a != = b;");
|
|
|
|
|
|
|
|
verifyFormat("a === b;");
|
2014-11-06 01:22:31 +08:00
|
|
|
verifyFormat("aaaaaaa ===\n b;", getGoogleJSStyleWithColumns(10));
|
2013-12-03 18:50:16 +08:00
|
|
|
verifyFormat("a !== b;");
|
2014-11-06 01:22:31 +08:00
|
|
|
verifyFormat("aaaaaaa !==\n b;", getGoogleJSStyleWithColumns(10));
|
|
|
|
verifyFormat("if (a + b + c +\n"
|
|
|
|
" d !==\n"
|
|
|
|
" e + f + g)\n"
|
2013-12-03 18:50:16 +08:00
|
|
|
" q();",
|
2013-12-10 19:28:13 +08:00
|
|
|
getGoogleJSStyleWithColumns(20));
|
2013-12-03 18:50:16 +08:00
|
|
|
|
|
|
|
verifyFormat("a >> >= b;");
|
|
|
|
|
|
|
|
verifyFormat("a >>> b;");
|
2014-11-06 01:22:31 +08:00
|
|
|
verifyFormat("aaaaaaa >>>\n b;", getGoogleJSStyleWithColumns(10));
|
2013-12-03 18:50:16 +08:00
|
|
|
verifyFormat("a >>>= b;");
|
2014-11-06 01:22:31 +08:00
|
|
|
verifyFormat("aaaaaaa >>>=\n b;", getGoogleJSStyleWithColumns(10));
|
|
|
|
verifyFormat("if (a + b + c +\n"
|
|
|
|
" d >>>\n"
|
|
|
|
" e + f + g)\n"
|
2013-12-03 18:50:16 +08:00
|
|
|
" q();",
|
2013-12-10 19:28:13 +08:00
|
|
|
getGoogleJSStyleWithColumns(20));
|
2014-11-06 01:22:31 +08:00
|
|
|
verifyFormat("var x = aaaaaaaaaa ?\n"
|
2015-12-21 21:52:19 +08:00
|
|
|
" bbbbbb :\n"
|
|
|
|
" ccc;",
|
2013-12-10 19:28:13 +08:00
|
|
|
getGoogleJSStyleWithColumns(20));
|
2014-05-19 15:27:02 +08:00
|
|
|
|
|
|
|
verifyFormat("var b = a.map((x) => x + 1);");
|
2014-09-19 18:48:15 +08:00
|
|
|
verifyFormat("return ('aaa') in bbbb;");
|
2016-02-01 19:20:47 +08:00
|
|
|
verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa() in\n"
|
|
|
|
" aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;");
|
|
|
|
FormatStyle Style = getGoogleJSStyleWithColumns(80);
|
[clang-format] Fix AlignOperands when BreakBeforeBinaryOperators is set
Summary:
Even when BreakBeforeBinaryOperators is set, AlignOperands kept
aligning the beginning of the line, even when it could align the
actual operands (e.g. after an assignment).
With this patch, the operands are actually aligned, and the operator
gets aligned with the equal sign:
int aaaaa = bbbbbb
+ cccccc;
This not happen in tests, to avoid 'breaking' the indentation:
if (aaaaa
&& bbbbb)
return;
Reviewers: krasimir, djasper, klimek, MyDeveloperDay
Reviewed By: MyDeveloperDay
Subscribers: MyDeveloperDay, acoomans, cfe-commits, klimek
Tags: #clang, #clang-format
Differential Revision: https://reviews.llvm.org/D32478
2017-05-22 17:23:08 +08:00
|
|
|
Style.AlignOperands = FormatStyle::OAS_Align;
|
2016-02-01 19:20:47 +08:00
|
|
|
verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa() in\n"
|
|
|
|
" aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
|
|
|
|
Style);
|
|
|
|
Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
|
|
|
|
verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa()\n"
|
|
|
|
" in aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
|
|
|
|
Style);
|
2015-05-26 15:18:56 +08:00
|
|
|
|
|
|
|
// ES6 spread operator.
|
|
|
|
verifyFormat("someFunction(...a);");
|
|
|
|
verifyFormat("var x = [1, ...a, 2];");
|
2013-12-03 18:50:16 +08:00
|
|
|
}
|
|
|
|
|
2014-09-05 16:53:45 +08:00
|
|
|
TEST_F(FormatTestJS, UnderstandsAmpAmp) {
|
|
|
|
verifyFormat("e && e.SomeFunction();");
|
|
|
|
}
|
|
|
|
|
2014-09-05 02:23:42 +08:00
|
|
|
TEST_F(FormatTestJS, LiteralOperatorsCanBeKeywords) {
|
|
|
|
verifyFormat("not.and.or.not_eq = 1;");
|
|
|
|
}
|
|
|
|
|
2015-09-28 22:29:45 +08:00
|
|
|
TEST_F(FormatTestJS, ReservedWords) {
|
|
|
|
// JavaScript reserved words (aka keywords) are only illegal when used as
|
|
|
|
// Identifiers, but are legal as IdentifierNames.
|
|
|
|
verifyFormat("x.class.struct = 1;");
|
|
|
|
verifyFormat("x.case = 1;");
|
|
|
|
verifyFormat("x.interface = 1;");
|
2016-05-20 14:16:01 +08:00
|
|
|
verifyFormat("x.for = 1;");
|
2017-08-15 00:08:16 +08:00
|
|
|
verifyFormat("x.of();");
|
2017-04-05 18:56:07 +08:00
|
|
|
verifyFormat("of(null);");
|
2018-02-19 20:32:13 +08:00
|
|
|
verifyFormat("return of(null);");
|
2017-04-05 18:56:07 +08:00
|
|
|
verifyFormat("import {of} from 'x';");
|
2017-08-15 00:08:16 +08:00
|
|
|
verifyFormat("x.in();");
|
|
|
|
verifyFormat("x.let();");
|
|
|
|
verifyFormat("x.var();");
|
|
|
|
verifyFormat("x.for();");
|
|
|
|
verifyFormat("x.as();");
|
|
|
|
verifyFormat("x.instanceof();");
|
|
|
|
verifyFormat("x.switch();");
|
|
|
|
verifyFormat("x.case();");
|
|
|
|
verifyFormat("x.delete();");
|
|
|
|
verifyFormat("x.throw();");
|
|
|
|
verifyFormat("x.throws();");
|
|
|
|
verifyFormat("x.if();");
|
2015-09-28 22:29:45 +08:00
|
|
|
verifyFormat("x = {\n"
|
|
|
|
" a: 12,\n"
|
|
|
|
" interface: 1,\n"
|
|
|
|
" switch: 1,\n"
|
|
|
|
"};");
|
2015-11-20 23:58:50 +08:00
|
|
|
verifyFormat("var struct = 2;");
|
|
|
|
verifyFormat("var union = 2;");
|
2016-04-20 02:18:59 +08:00
|
|
|
verifyFormat("var interface = 2;");
|
|
|
|
verifyFormat("interface = 2;");
|
|
|
|
verifyFormat("x = interface instanceof y;");
|
2017-08-05 01:07:15 +08:00
|
|
|
verifyFormat("interface Test {\n"
|
|
|
|
" x: string;\n"
|
|
|
|
" switch: string;\n"
|
|
|
|
" case: string;\n"
|
|
|
|
" default: string;\n"
|
|
|
|
"}\n");
|
2017-11-25 17:24:33 +08:00
|
|
|
verifyFormat("const Axis = {\n"
|
|
|
|
" for: 'for',\n"
|
|
|
|
" x: 'x'\n"
|
|
|
|
"};",
|
|
|
|
"const Axis = {for: 'for', x: 'x'};");
|
2015-09-28 22:29:45 +08:00
|
|
|
}
|
|
|
|
|
2016-09-22 15:18:00 +08:00
|
|
|
TEST_F(FormatTestJS, ReservedWordsMethods) {
|
2020-05-02 22:42:20 +08:00
|
|
|
verifyFormat("class X {\n"
|
|
|
|
" delete() {\n"
|
|
|
|
" x();\n"
|
|
|
|
" }\n"
|
|
|
|
" interface() {\n"
|
|
|
|
" x();\n"
|
|
|
|
" }\n"
|
|
|
|
" let() {\n"
|
|
|
|
" x();\n"
|
|
|
|
" }\n"
|
|
|
|
"}\n");
|
2020-01-16 18:49:52 +08:00
|
|
|
verifyFormat("class KeywordNamedMethods {\n"
|
|
|
|
" do() {\n"
|
|
|
|
" }\n"
|
|
|
|
" for() {\n"
|
|
|
|
" }\n"
|
|
|
|
" while() {\n"
|
|
|
|
" }\n"
|
|
|
|
" if() {\n"
|
|
|
|
" }\n"
|
|
|
|
" else() {\n"
|
|
|
|
" }\n"
|
|
|
|
" try() {\n"
|
|
|
|
" }\n"
|
|
|
|
" catch() {\n"
|
|
|
|
" }\n"
|
|
|
|
"}\n");
|
2016-09-22 15:18:00 +08:00
|
|
|
}
|
|
|
|
|
2017-08-02 01:22:15 +08:00
|
|
|
TEST_F(FormatTestJS, ReservedWordsParenthesized) {
|
|
|
|
// All of these are statements using the keyword, not function calls.
|
|
|
|
verifyFormat("throw (x + y);\n"
|
|
|
|
"await (await x).y;\n"
|
2017-08-02 01:42:16 +08:00
|
|
|
"typeof (x) === 'string';\n"
|
2017-08-02 01:22:15 +08:00
|
|
|
"void (0);\n"
|
|
|
|
"delete (x.y);\n"
|
|
|
|
"return (x);\n");
|
|
|
|
}
|
|
|
|
|
2014-05-19 15:37:07 +08:00
|
|
|
TEST_F(FormatTestJS, ES6DestructuringAssignment) {
|
|
|
|
verifyFormat("var [a, b, c] = [1, 2, 3];");
|
2016-05-19 15:18:07 +08:00
|
|
|
verifyFormat("const [a, b, c] = [1, 2, 3];");
|
2015-09-28 22:28:08 +08:00
|
|
|
verifyFormat("let [a, b, c] = [1, 2, 3];");
|
2015-03-15 21:55:54 +08:00
|
|
|
verifyFormat("var {a, b} = {a: 1, b: 2};");
|
2015-09-28 22:28:08 +08:00
|
|
|
verifyFormat("let {a, b} = {a: 1, b: 2};");
|
2014-05-19 15:37:07 +08:00
|
|
|
}
|
|
|
|
|
2014-06-10 22:44:02 +08:00
|
|
|
TEST_F(FormatTestJS, ContainerLiterals) {
|
2016-09-08 07:01:13 +08:00
|
|
|
verifyFormat("var x = {\n"
|
|
|
|
" y: function(a) {\n"
|
|
|
|
" return a;\n"
|
|
|
|
" }\n"
|
|
|
|
"};");
|
2014-06-10 22:44:02 +08:00
|
|
|
verifyFormat("return {\n"
|
|
|
|
" link: function() {\n"
|
|
|
|
" f(); //\n"
|
|
|
|
" }\n"
|
|
|
|
"};");
|
|
|
|
verifyFormat("return {\n"
|
|
|
|
" a: a,\n"
|
|
|
|
" link: function() {\n"
|
|
|
|
" f(); //\n"
|
|
|
|
" }\n"
|
|
|
|
"};");
|
|
|
|
verifyFormat("return {\n"
|
|
|
|
" a: a,\n"
|
2014-09-05 17:27:38 +08:00
|
|
|
" link: function() {\n"
|
|
|
|
" f(); //\n"
|
|
|
|
" },\n"
|
|
|
|
" link: function() {\n"
|
|
|
|
" f(); //\n"
|
|
|
|
" }\n"
|
2014-06-10 22:44:02 +08:00
|
|
|
"};");
|
2014-09-04 22:58:30 +08:00
|
|
|
verifyFormat("var stuff = {\n"
|
|
|
|
" // comment for update\n"
|
|
|
|
" update: false,\n"
|
|
|
|
" // comment for modules\n"
|
|
|
|
" modules: false,\n"
|
|
|
|
" // comment for tasks\n"
|
|
|
|
" tasks: false\n"
|
|
|
|
"};");
|
2014-09-05 16:29:31 +08:00
|
|
|
verifyFormat("return {\n"
|
|
|
|
" 'finish':\n"
|
|
|
|
" //\n"
|
|
|
|
" a\n"
|
|
|
|
"};");
|
2014-11-27 23:24:48 +08:00
|
|
|
verifyFormat("var obj = {\n"
|
|
|
|
" fooooooooo: function(x) {\n"
|
|
|
|
" return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
|
|
|
|
" }\n"
|
|
|
|
"};");
|
2015-03-15 21:55:54 +08:00
|
|
|
// Simple object literal, as opposed to enum style below.
|
|
|
|
verifyFormat("var obj = {a: 123};");
|
|
|
|
// Enum style top level assignment.
|
|
|
|
verifyFormat("X = {\n a: 123\n};");
|
|
|
|
verifyFormat("X.Y = {\n a: 123\n};");
|
2015-06-10 17:21:09 +08:00
|
|
|
// But only on the top level, otherwise its a plain object literal assignment.
|
|
|
|
verifyFormat("function x() {\n"
|
|
|
|
" y = {z: 1};\n"
|
|
|
|
"}");
|
2015-03-15 21:55:54 +08:00
|
|
|
verifyFormat("x = foo && {a: 123};");
|
2015-05-21 20:23:34 +08:00
|
|
|
|
|
|
|
// Arrow functions in object literals.
|
2016-09-08 07:01:13 +08:00
|
|
|
verifyFormat("var x = {\n"
|
|
|
|
" y: (a) => {\n"
|
2020-01-24 18:30:31 +08:00
|
|
|
" x();\n"
|
2016-09-08 07:01:13 +08:00
|
|
|
" return a;\n"
|
2020-01-24 18:30:31 +08:00
|
|
|
" },\n"
|
2016-09-08 07:01:13 +08:00
|
|
|
"};");
|
2015-05-21 20:23:34 +08:00
|
|
|
verifyFormat("var x = {y: (a) => a};");
|
2015-05-29 14:19:49 +08:00
|
|
|
|
2017-02-08 00:33:13 +08:00
|
|
|
// Methods in object literals.
|
|
|
|
verifyFormat("var x = {\n"
|
|
|
|
" y(a: string): number {\n"
|
|
|
|
" return a;\n"
|
|
|
|
" }\n"
|
|
|
|
"};");
|
|
|
|
verifyFormat("var x = {\n"
|
|
|
|
" y(a: string) {\n"
|
|
|
|
" return a;\n"
|
|
|
|
" }\n"
|
|
|
|
"};");
|
|
|
|
|
2015-05-29 14:19:49 +08:00
|
|
|
// Computed keys.
|
2015-05-31 16:40:37 +08:00
|
|
|
verifyFormat("var x = {[a]: 1, b: 2, [c]: 3};");
|
2015-05-29 14:19:49 +08:00
|
|
|
verifyFormat("var x = {\n"
|
|
|
|
" [a]: 1,\n"
|
2015-05-31 16:40:37 +08:00
|
|
|
" b: 2,\n"
|
|
|
|
" [c]: 3,\n"
|
2015-05-29 14:19:49 +08:00
|
|
|
"};");
|
2016-02-08 06:17:13 +08:00
|
|
|
|
|
|
|
// Object literals can leave out labels.
|
|
|
|
verifyFormat("f({a}, () => {\n"
|
2020-01-24 18:30:31 +08:00
|
|
|
" x;\n"
|
|
|
|
" g();\n"
|
2016-02-08 06:17:13 +08:00
|
|
|
"});");
|
2016-03-01 12:19:47 +08:00
|
|
|
|
|
|
|
// Keys can be quoted.
|
|
|
|
verifyFormat("var x = {\n"
|
|
|
|
" a: a,\n"
|
|
|
|
" b: b,\n"
|
|
|
|
" 'c': c,\n"
|
|
|
|
"};");
|
2016-11-29 17:40:36 +08:00
|
|
|
|
|
|
|
// Dict literals can skip the label names.
|
|
|
|
verifyFormat("var x = {\n"
|
|
|
|
" aaa,\n"
|
|
|
|
" aaa,\n"
|
|
|
|
" aaa,\n"
|
|
|
|
"};");
|
2017-03-02 03:47:28 +08:00
|
|
|
verifyFormat("return {\n"
|
|
|
|
" a,\n"
|
|
|
|
" b: 'b',\n"
|
|
|
|
" c,\n"
|
|
|
|
"};");
|
2014-06-10 22:44:02 +08:00
|
|
|
}
|
|
|
|
|
2015-03-31 22:34:15 +08:00
|
|
|
TEST_F(FormatTestJS, MethodsInObjectLiterals) {
|
|
|
|
verifyFormat("var o = {\n"
|
|
|
|
" value: 'test',\n"
|
|
|
|
" get value() { // getter\n"
|
|
|
|
" return this.value;\n"
|
|
|
|
" }\n"
|
|
|
|
"};");
|
|
|
|
verifyFormat("var o = {\n"
|
|
|
|
" value: 'test',\n"
|
|
|
|
" set value(val) { // setter\n"
|
|
|
|
" this.value = val;\n"
|
|
|
|
" }\n"
|
|
|
|
"};");
|
|
|
|
verifyFormat("var o = {\n"
|
|
|
|
" value: 'test',\n"
|
|
|
|
" someMethod(val) { // method\n"
|
|
|
|
" doSomething(this.value + val);\n"
|
|
|
|
" }\n"
|
|
|
|
"};");
|
2015-04-04 15:56:55 +08:00
|
|
|
verifyFormat("var o = {\n"
|
|
|
|
" someMethod(val) { // method\n"
|
|
|
|
" doSomething(this.value + val);\n"
|
|
|
|
" },\n"
|
|
|
|
" someOtherMethod(val) { // method\n"
|
|
|
|
" doSomething(this.value + val);\n"
|
|
|
|
" }\n"
|
|
|
|
"};");
|
2015-03-31 22:34:15 +08:00
|
|
|
}
|
|
|
|
|
2017-04-26 20:34:15 +08:00
|
|
|
TEST_F(FormatTestJS, GettersSettersVisibilityKeywords) {
|
|
|
|
// Don't break after "protected"
|
|
|
|
verifyFormat("class X {\n"
|
|
|
|
" protected get getter():\n"
|
|
|
|
" number {\n"
|
|
|
|
" return 1;\n"
|
|
|
|
" }\n"
|
|
|
|
"}",
|
|
|
|
getGoogleJSStyleWithColumns(12));
|
|
|
|
// Don't break after "get"
|
|
|
|
verifyFormat("class X {\n"
|
|
|
|
" protected get someReallyLongGetterName():\n"
|
|
|
|
" number {\n"
|
|
|
|
" return 1;\n"
|
|
|
|
" }\n"
|
|
|
|
"}",
|
|
|
|
getGoogleJSStyleWithColumns(40));
|
|
|
|
}
|
|
|
|
|
2014-01-15 23:09:08 +08:00
|
|
|
TEST_F(FormatTestJS, SpacesInContainerLiterals) {
|
|
|
|
verifyFormat("var arr = [1, 2, 3];");
|
2014-12-05 00:07:17 +08:00
|
|
|
verifyFormat("f({a: 1, b: 2, c: 3});");
|
2014-02-03 04:50:45 +08:00
|
|
|
|
2014-05-21 21:26:58 +08:00
|
|
|
verifyFormat("var object_literal_with_long_name = {\n"
|
|
|
|
" a: 'aaaaaaaaaaaaaaaaaa',\n"
|
|
|
|
" b: 'bbbbbbbbbbbbbbbbbb'\n"
|
|
|
|
"};");
|
|
|
|
|
2014-12-05 00:07:17 +08:00
|
|
|
verifyFormat("f({a: 1, b: 2, c: 3});",
|
2014-02-03 04:50:45 +08:00
|
|
|
getChromiumStyle(FormatStyle::LK_JavaScript));
|
2014-12-05 00:07:17 +08:00
|
|
|
verifyFormat("f({'a': [{}]});");
|
2014-01-15 23:09:08 +08:00
|
|
|
}
|
|
|
|
|
2016-03-03 06:44:03 +08:00
|
|
|
TEST_F(FormatTestJS, SingleQuotedStrings) {
|
2014-01-31 20:49:42 +08:00
|
|
|
verifyFormat("this.function('', true);");
|
|
|
|
}
|
|
|
|
|
2014-05-06 21:54:10 +08:00
|
|
|
TEST_F(FormatTestJS, GoogScopes) {
|
|
|
|
verifyFormat("goog.scope(function() {\n"
|
|
|
|
"var x = a.b;\n"
|
|
|
|
"var y = c.d;\n"
|
|
|
|
"}); // goog.scope");
|
2015-03-30 17:56:50 +08:00
|
|
|
verifyFormat("goog.scope(function() {\n"
|
|
|
|
"// test\n"
|
|
|
|
"var x = 0;\n"
|
|
|
|
"// test\n"
|
|
|
|
"});");
|
2014-05-06 21:54:10 +08:00
|
|
|
}
|
|
|
|
|
2017-05-10 04:04:09 +08:00
|
|
|
TEST_F(FormatTestJS, IIFEs) {
|
|
|
|
// Internal calling parens; no semi.
|
|
|
|
verifyFormat("(function() {\n"
|
|
|
|
"var a = 1;\n"
|
|
|
|
"}())");
|
|
|
|
// External calling parens; no semi.
|
|
|
|
verifyFormat("(function() {\n"
|
|
|
|
"var b = 2;\n"
|
|
|
|
"})()");
|
|
|
|
// Internal calling parens; with semi.
|
|
|
|
verifyFormat("(function() {\n"
|
|
|
|
"var c = 3;\n"
|
|
|
|
"}());");
|
|
|
|
// External calling parens; with semi.
|
|
|
|
verifyFormat("(function() {\n"
|
|
|
|
"var d = 4;\n"
|
|
|
|
"})();");
|
|
|
|
}
|
|
|
|
|
2014-11-24 00:46:28 +08:00
|
|
|
TEST_F(FormatTestJS, GoogModules) {
|
|
|
|
verifyFormat("goog.module('this.is.really.absurdly.long');",
|
|
|
|
getGoogleJSStyleWithColumns(40));
|
|
|
|
verifyFormat("goog.require('this.is.really.absurdly.long');",
|
|
|
|
getGoogleJSStyleWithColumns(40));
|
|
|
|
verifyFormat("goog.provide('this.is.really.absurdly.long');",
|
|
|
|
getGoogleJSStyleWithColumns(40));
|
|
|
|
verifyFormat("var long = goog.require('this.is.really.absurdly.long');",
|
|
|
|
getGoogleJSStyleWithColumns(40));
|
2019-01-07 21:12:50 +08:00
|
|
|
verifyFormat("const X = goog.requireType('this.is.really.absurdly.long');",
|
|
|
|
getGoogleJSStyleWithColumns(40));
|
2016-02-22 23:06:53 +08:00
|
|
|
verifyFormat("goog.forwardDeclare('this.is.really.absurdly.long');",
|
|
|
|
getGoogleJSStyleWithColumns(40));
|
2014-11-27 22:46:03 +08:00
|
|
|
|
|
|
|
// These should be wrapped normally.
|
|
|
|
verifyFormat(
|
|
|
|
"var MyLongClassName =\n"
|
|
|
|
" goog.module.get('my.long.module.name.followedBy.MyLongClassName');");
|
2017-09-11 23:22:52 +08:00
|
|
|
verifyFormat("function a() {\n"
|
|
|
|
" goog.setTestOnly();\n"
|
|
|
|
"}\n",
|
|
|
|
"function a() {\n"
|
|
|
|
"goog.setTestOnly();\n"
|
|
|
|
"}\n");
|
2014-11-24 00:46:28 +08:00
|
|
|
}
|
|
|
|
|
2016-06-14 00:41:28 +08:00
|
|
|
TEST_F(FormatTestJS, FormatsNamespaces) {
|
|
|
|
verifyFormat("namespace Foo {\n"
|
|
|
|
" export let x = 1;\n"
|
|
|
|
"}\n");
|
|
|
|
verifyFormat("declare namespace Foo {\n"
|
|
|
|
" export let x: number;\n"
|
|
|
|
"}\n");
|
|
|
|
}
|
|
|
|
|
2016-11-11 00:20:58 +08:00
|
|
|
TEST_F(FormatTestJS, NamespacesMayNotWrap) {
|
|
|
|
verifyFormat("declare namespace foobarbaz {\n"
|
2020-05-02 22:42:20 +08:00
|
|
|
"}\n",
|
|
|
|
getGoogleJSStyleWithColumns(18));
|
2016-11-11 00:20:58 +08:00
|
|
|
verifyFormat("declare module foobarbaz {\n"
|
2020-05-02 22:42:20 +08:00
|
|
|
"}\n",
|
|
|
|
getGoogleJSStyleWithColumns(15));
|
2016-11-11 00:20:58 +08:00
|
|
|
verifyFormat("namespace foobarbaz {\n"
|
2020-05-02 22:42:20 +08:00
|
|
|
"}\n",
|
|
|
|
getGoogleJSStyleWithColumns(10));
|
2016-11-11 00:20:58 +08:00
|
|
|
verifyFormat("module foobarbaz {\n"
|
2020-05-02 22:42:20 +08:00
|
|
|
"}\n",
|
|
|
|
getGoogleJSStyleWithColumns(7));
|
2016-11-11 00:20:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(FormatTestJS, AmbientDeclarations) {
|
|
|
|
FormatStyle NineCols = getGoogleJSStyleWithColumns(9);
|
2020-05-02 22:42:20 +08:00
|
|
|
verifyFormat("declare class\n"
|
|
|
|
" X {}",
|
|
|
|
NineCols);
|
|
|
|
verifyFormat("declare function\n"
|
|
|
|
"x();", // TODO(martinprobst): should ideally be indented.
|
|
|
|
NineCols);
|
2017-01-04 21:36:43 +08:00
|
|
|
verifyFormat("declare function foo();\n"
|
|
|
|
"let x = 1;\n");
|
|
|
|
verifyFormat("declare function foo(): string;\n"
|
|
|
|
"let x = 1;\n");
|
|
|
|
verifyFormat("declare function foo(): {x: number};\n"
|
|
|
|
"let x = 1;\n");
|
|
|
|
verifyFormat("declare class X {}\n"
|
|
|
|
"let x = 1;\n");
|
|
|
|
verifyFormat("declare interface Y {}\n"
|
|
|
|
"let x = 1;\n");
|
2020-05-02 22:42:20 +08:00
|
|
|
verifyFormat("declare enum X {\n"
|
|
|
|
"}",
|
|
|
|
NineCols);
|
|
|
|
verifyFormat("declare let\n"
|
|
|
|
" x: number;",
|
|
|
|
NineCols);
|
2016-11-11 00:20:58 +08:00
|
|
|
}
|
|
|
|
|
clang-format: [JS] support free-standing functions again.
This worked initially but was broken by r210887.
Before:
function outer1(a, b) {
function inner1(a, b) { return a; } inner1(a, b);
} function outer2(a, b) { function inner2(a, b) { return a; } inner2(a, b); }
After:
function outer1(a, b) {
function inner1(a, b) { return a; }
inner1(a, b);
}
function outer2(a, b) {
function inner2(a, b) { return a; }
inner2(a, b);
}
Thanks to Adam Strzelecki for working on this.
llvm-svn: 212038
2014-06-30 21:24:54 +08:00
|
|
|
TEST_F(FormatTestJS, FormatsFreestandingFunctions) {
|
|
|
|
verifyFormat("function outer1(a, b) {\n"
|
2016-09-08 07:01:13 +08:00
|
|
|
" function inner1(a, b) {\n"
|
|
|
|
" return a;\n"
|
|
|
|
" }\n"
|
clang-format: [JS] support free-standing functions again.
This worked initially but was broken by r210887.
Before:
function outer1(a, b) {
function inner1(a, b) { return a; } inner1(a, b);
} function outer2(a, b) { function inner2(a, b) { return a; } inner2(a, b); }
After:
function outer1(a, b) {
function inner1(a, b) { return a; }
inner1(a, b);
}
function outer2(a, b) {
function inner2(a, b) { return a; }
inner2(a, b);
}
Thanks to Adam Strzelecki for working on this.
llvm-svn: 212038
2014-06-30 21:24:54 +08:00
|
|
|
" inner1(a, b);\n"
|
|
|
|
"}\n"
|
|
|
|
"function outer2(a, b) {\n"
|
2016-09-08 07:01:13 +08:00
|
|
|
" function inner2(a, b) {\n"
|
|
|
|
" return a;\n"
|
|
|
|
" }\n"
|
clang-format: [JS] support free-standing functions again.
This worked initially but was broken by r210887.
Before:
function outer1(a, b) {
function inner1(a, b) { return a; } inner1(a, b);
} function outer2(a, b) { function inner2(a, b) { return a; } inner2(a, b); }
After:
function outer1(a, b) {
function inner1(a, b) { return a; }
inner1(a, b);
}
function outer2(a, b) {
function inner2(a, b) { return a; }
inner2(a, b);
}
Thanks to Adam Strzelecki for working on this.
llvm-svn: 212038
2014-06-30 21:24:54 +08:00
|
|
|
" inner2(a, b);\n"
|
|
|
|
"}");
|
2015-06-11 21:31:45 +08:00
|
|
|
verifyFormat("function f() {}");
|
2017-05-10 21:53:29 +08:00
|
|
|
verifyFormat("function aFunction() {}\n"
|
|
|
|
"(function f() {\n"
|
|
|
|
" var x = 1;\n"
|
|
|
|
"}());\n");
|
2017-05-31 17:29:40 +08:00
|
|
|
verifyFormat("function aFunction() {}\n"
|
|
|
|
"{\n"
|
2017-05-10 21:53:29 +08:00
|
|
|
" let x = 1;\n"
|
|
|
|
" console.log(x);\n"
|
|
|
|
"}\n");
|
clang-format: [JS] support free-standing functions again.
This worked initially but was broken by r210887.
Before:
function outer1(a, b) {
function inner1(a, b) { return a; } inner1(a, b);
} function outer2(a, b) { function inner2(a, b) { return a; } inner2(a, b); }
After:
function outer1(a, b) {
function inner1(a, b) { return a; }
inner1(a, b);
}
function outer2(a, b) {
function inner2(a, b) { return a; }
inner2(a, b);
}
Thanks to Adam Strzelecki for working on this.
llvm-svn: 212038
2014-06-30 21:24:54 +08:00
|
|
|
}
|
|
|
|
|
2016-04-25 06:05:09 +08:00
|
|
|
TEST_F(FormatTestJS, GeneratorFunctions) {
|
|
|
|
verifyFormat("function* f() {\n"
|
|
|
|
" let x = 1;\n"
|
|
|
|
" yield x;\n"
|
|
|
|
" yield* something();\n"
|
2016-10-31 21:18:25 +08:00
|
|
|
" yield [1, 2];\n"
|
|
|
|
" yield {a: 1};\n"
|
2016-04-25 06:05:09 +08:00
|
|
|
"}");
|
|
|
|
verifyFormat("function*\n"
|
|
|
|
" f() {\n"
|
|
|
|
"}",
|
|
|
|
getGoogleJSStyleWithColumns(8));
|
|
|
|
verifyFormat("export function* f() {\n"
|
|
|
|
" yield 1;\n"
|
|
|
|
"}\n");
|
|
|
|
verifyFormat("class X {\n"
|
2016-09-08 07:01:13 +08:00
|
|
|
" * generatorMethod() {\n"
|
|
|
|
" yield x;\n"
|
|
|
|
" }\n"
|
2016-04-25 06:05:09 +08:00
|
|
|
"}");
|
2016-11-01 14:22:59 +08:00
|
|
|
verifyFormat("var x = {\n"
|
|
|
|
" a: function*() {\n"
|
|
|
|
" //\n"
|
|
|
|
" }\n"
|
|
|
|
"}\n");
|
2016-04-25 06:05:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(FormatTestJS, AsyncFunctions) {
|
|
|
|
verifyFormat("async function f() {\n"
|
|
|
|
" let x = 1;\n"
|
|
|
|
" return fetch(x);\n"
|
|
|
|
"}");
|
2017-04-27 21:07:24 +08:00
|
|
|
verifyFormat("async function f() {\n"
|
|
|
|
" return 1;\n"
|
|
|
|
"}\n"
|
|
|
|
"\n"
|
|
|
|
"function a() {\n"
|
|
|
|
" return 1;\n"
|
|
|
|
"}\n",
|
|
|
|
" async function f() {\n"
|
|
|
|
" return 1;\n"
|
|
|
|
"}\n"
|
|
|
|
"\n"
|
|
|
|
" function a() {\n"
|
|
|
|
" return 1;\n"
|
|
|
|
"} \n");
|
2019-11-18 17:07:32 +08:00
|
|
|
// clang-format must not insert breaks between async and function, otherwise
|
|
|
|
// automatic semicolon insertion may trigger (in particular in a class body).
|
|
|
|
verifyFormat("async function\n"
|
|
|
|
"hello(\n"
|
|
|
|
" myparamnameiswaytooloooong) {\n"
|
|
|
|
"}",
|
|
|
|
"async function hello(myparamnameiswaytooloooong) {}",
|
|
|
|
getGoogleJSStyleWithColumns(10));
|
|
|
|
verifyFormat("class C {\n"
|
|
|
|
" async hello(\n"
|
|
|
|
" myparamnameiswaytooloooong) {\n"
|
|
|
|
" }\n"
|
|
|
|
"}",
|
|
|
|
"class C {\n"
|
|
|
|
" async hello(myparamnameiswaytooloooong) {} }",
|
|
|
|
getGoogleJSStyleWithColumns(10));
|
2016-04-25 06:05:09 +08:00
|
|
|
verifyFormat("async function* f() {\n"
|
|
|
|
" yield fetch(x);\n"
|
|
|
|
"}");
|
|
|
|
verifyFormat("export async function f() {\n"
|
|
|
|
" return fetch(x);\n"
|
|
|
|
"}");
|
2017-02-27 19:15:53 +08:00
|
|
|
verifyFormat("let x = async () => f();");
|
2017-04-27 21:07:24 +08:00
|
|
|
verifyFormat("let x = async function() {\n"
|
|
|
|
" f();\n"
|
|
|
|
"};");
|
2017-02-27 19:15:53 +08:00
|
|
|
verifyFormat("let x = async();");
|
2016-04-25 06:05:09 +08:00
|
|
|
verifyFormat("class X {\n"
|
2016-09-08 07:01:13 +08:00
|
|
|
" async asyncMethod() {\n"
|
|
|
|
" return fetch(1);\n"
|
|
|
|
" }\n"
|
2016-04-25 06:05:09 +08:00
|
|
|
"}");
|
2016-05-29 22:41:07 +08:00
|
|
|
verifyFormat("function initialize() {\n"
|
|
|
|
" // Comment.\n"
|
|
|
|
" return async.then();\n"
|
|
|
|
"}\n");
|
2017-05-19 05:19:29 +08:00
|
|
|
verifyFormat("for await (const x of y) {\n"
|
2017-05-16 03:33:20 +08:00
|
|
|
" console.log(x);\n"
|
|
|
|
"}\n");
|
|
|
|
verifyFormat("function asyncLoop() {\n"
|
2017-05-19 05:19:29 +08:00
|
|
|
" for await (const x of y) {\n"
|
2017-05-16 03:33:20 +08:00
|
|
|
" console.log(x);\n"
|
|
|
|
" }\n"
|
|
|
|
"}\n");
|
2016-04-25 06:05:09 +08:00
|
|
|
}
|
|
|
|
|
2017-05-15 19:15:29 +08:00
|
|
|
TEST_F(FormatTestJS, FunctionParametersTrailingComma) {
|
|
|
|
verifyFormat("function trailingComma(\n"
|
|
|
|
" p1,\n"
|
|
|
|
" p2,\n"
|
|
|
|
" p3,\n"
|
|
|
|
") {\n"
|
|
|
|
" a; //\n"
|
|
|
|
"}\n",
|
|
|
|
"function trailingComma(p1, p2, p3,) {\n"
|
|
|
|
" a; //\n"
|
|
|
|
"}\n");
|
|
|
|
verifyFormat("trailingComma(\n"
|
|
|
|
" p1,\n"
|
|
|
|
" p2,\n"
|
|
|
|
" p3,\n"
|
|
|
|
");\n",
|
|
|
|
"trailingComma(p1, p2, p3,);\n");
|
|
|
|
verifyFormat("trailingComma(\n"
|
|
|
|
" p1 // hello\n"
|
|
|
|
");\n",
|
|
|
|
"trailingComma(p1 // hello\n"
|
|
|
|
");\n");
|
|
|
|
}
|
|
|
|
|
2015-05-28 15:21:50 +08:00
|
|
|
TEST_F(FormatTestJS, ArrayLiterals) {
|
2015-06-17 21:08:06 +08:00
|
|
|
verifyFormat("var aaaaa: List<SomeThing> =\n"
|
|
|
|
" [new SomeThingAAAAAAAAAAAA(), new SomeThingBBBBBBBBB()];");
|
2015-06-03 05:57:51 +08:00
|
|
|
verifyFormat("return [\n"
|
clang-format: [ObjC+JS] Allow bin-packing of array literals.
After reading the style guides again, they don't actually say how to
pack or not pack array literals. Based on some user reports, array
initializers can unnecessarily get quite long if they contain many
small elements. Array literals with trailing commas are still formatted
one per line so that users have a way to opt out of the packing.
Before:
var array = [
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa
];
After:
var array = [
aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa,
aaaaaa, aaaaaa
];
llvm-svn: 257615
2016-01-14 00:41:34 +08:00
|
|
|
" aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
|
2015-06-03 05:57:51 +08:00
|
|
|
" ccccccccccccccccccccccccccc\n"
|
|
|
|
"];");
|
2016-01-08 02:11:54 +08:00
|
|
|
verifyFormat("return [\n"
|
|
|
|
" aaaa().bbbbbbbb('A'),\n"
|
|
|
|
" aaaa().bbbbbbbb('B'),\n"
|
|
|
|
" aaaa().bbbbbbbb('C'),\n"
|
|
|
|
"];");
|
2015-10-27 20:38:37 +08:00
|
|
|
verifyFormat("var someVariable = SomeFunction([\n"
|
clang-format: [ObjC+JS] Allow bin-packing of array literals.
After reading the style guides again, they don't actually say how to
pack or not pack array literals. Based on some user reports, array
initializers can unnecessarily get quite long if they contain many
small elements. Array literals with trailing commas are still formatted
one per line so that users have a way to opt out of the packing.
Before:
var array = [
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa
];
After:
var array = [
aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa,
aaaaaa, aaaaaa
];
llvm-svn: 257615
2016-01-14 00:41:34 +08:00
|
|
|
" aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
|
2015-06-02 21:56:43 +08:00
|
|
|
" ccccccccccccccccccccccccccc\n"
|
2015-06-02 22:20:08 +08:00
|
|
|
"]);");
|
2015-10-27 20:38:37 +08:00
|
|
|
verifyFormat("var someVariable = SomeFunction([\n"
|
2015-06-02 23:04:29 +08:00
|
|
|
" [aaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbb],\n"
|
2015-06-02 23:14:21 +08:00
|
|
|
"]);",
|
|
|
|
getGoogleJSStyleWithColumns(51));
|
2015-10-27 20:38:37 +08:00
|
|
|
verifyFormat("var someVariable = SomeFunction(aaaa, [\n"
|
clang-format: [ObjC+JS] Allow bin-packing of array literals.
After reading the style guides again, they don't actually say how to
pack or not pack array literals. Based on some user reports, array
initializers can unnecessarily get quite long if they contain many
small elements. Array literals with trailing commas are still formatted
one per line so that users have a way to opt out of the packing.
Before:
var array = [
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa
];
After:
var array = [
aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa,
aaaaaa, aaaaaa
];
llvm-svn: 257615
2016-01-14 00:41:34 +08:00
|
|
|
" aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
|
2015-06-02 22:20:08 +08:00
|
|
|
" ccccccccccccccccccccccccccc\n"
|
2015-06-02 21:56:43 +08:00
|
|
|
"]);");
|
2015-10-27 20:38:37 +08:00
|
|
|
verifyFormat("var someVariable = SomeFunction(\n"
|
|
|
|
" aaaa,\n"
|
|
|
|
" [\n"
|
clang-format: [ObjC+JS] Allow bin-packing of array literals.
After reading the style guides again, they don't actually say how to
pack or not pack array literals. Based on some user reports, array
initializers can unnecessarily get quite long if they contain many
small elements. Array literals with trailing commas are still formatted
one per line so that users have a way to opt out of the packing.
Before:
var array = [
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa,
aaaaaa
];
After:
var array = [
aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa, aaaaaa,
aaaaaa, aaaaaa
];
llvm-svn: 257615
2016-01-14 00:41:34 +08:00
|
|
|
" aaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
|
|
|
|
" cccccccccccccccccccccccccc\n"
|
2015-10-27 20:38:37 +08:00
|
|
|
" ],\n"
|
|
|
|
" aaaa);");
|
2016-01-04 21:11:41 +08:00
|
|
|
verifyFormat("var aaaa = aaaaa || // wrap\n"
|
|
|
|
" [];");
|
2015-06-02 23:31:37 +08:00
|
|
|
|
|
|
|
verifyFormat("someFunction([], {a: a});");
|
2017-01-30 15:08:40 +08:00
|
|
|
|
|
|
|
verifyFormat("var string = [\n"
|
|
|
|
" 'aaaaaa',\n"
|
|
|
|
" 'bbbbbb',\n"
|
|
|
|
"].join('+');");
|
2015-05-28 15:21:50 +08:00
|
|
|
}
|
|
|
|
|
2015-12-22 23:48:15 +08:00
|
|
|
TEST_F(FormatTestJS, ColumnLayoutForArrayLiterals) {
|
|
|
|
verifyFormat("var array = [\n"
|
|
|
|
" a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
|
|
|
|
" a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
|
|
|
|
"];");
|
|
|
|
verifyFormat("var array = someFunction([\n"
|
|
|
|
" a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
|
|
|
|
" a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
|
|
|
|
"]);");
|
|
|
|
}
|
|
|
|
|
2020-01-24 23:13:51 +08:00
|
|
|
TEST_F(FormatTestJS, TrailingCommaInsertion) {
|
|
|
|
FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
|
|
|
|
Style.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
|
|
|
|
// Insert comma in wrapped array.
|
|
|
|
verifyFormat("const x = [\n"
|
|
|
|
" 1, //\n"
|
|
|
|
" 2,\n"
|
|
|
|
"];",
|
|
|
|
"const x = [\n"
|
|
|
|
" 1, //\n"
|
|
|
|
" 2];",
|
|
|
|
Style);
|
|
|
|
// Insert comma in newly wrapped array.
|
|
|
|
Style.ColumnLimit = 30;
|
|
|
|
verifyFormat("const x = [\n"
|
|
|
|
" aaaaaaaaaaaaaaaaaaaaaaaaa,\n"
|
|
|
|
"];",
|
|
|
|
"const x = [aaaaaaaaaaaaaaaaaaaaaaaaa];", Style);
|
|
|
|
// Do not insert trailing commas if they'd exceed the colum limit
|
|
|
|
verifyFormat("const x = [\n"
|
|
|
|
" aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
|
|
|
|
"];",
|
|
|
|
"const x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa];", Style);
|
|
|
|
// Object literals.
|
|
|
|
verifyFormat("const x = {\n"
|
|
|
|
" a: aaaaaaaaaaaaaaaaa,\n"
|
|
|
|
"};",
|
|
|
|
"const x = {a: aaaaaaaaaaaaaaaaa};", Style);
|
|
|
|
verifyFormat("const x = {\n"
|
|
|
|
" a: aaaaaaaaaaaaaaaaaaaaaaaaa\n"
|
|
|
|
"};",
|
|
|
|
"const x = {a: aaaaaaaaaaaaaaaaaaaaaaaaa};", Style);
|
|
|
|
// Object literal types.
|
|
|
|
verifyFormat("let x: {\n"
|
|
|
|
" a: aaaaaaaaaaaaaaaaaaaaa,\n"
|
|
|
|
"};",
|
|
|
|
"let x: {a: aaaaaaaaaaaaaaaaaaaaa};", Style);
|
|
|
|
}
|
|
|
|
|
2014-06-13 15:02:04 +08:00
|
|
|
TEST_F(FormatTestJS, FunctionLiterals) {
|
2016-09-08 07:01:13 +08:00
|
|
|
FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
|
|
|
|
Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
|
2014-09-05 16:42:27 +08:00
|
|
|
verifyFormat("doFoo(function() {});");
|
2016-09-08 07:01:13 +08:00
|
|
|
verifyFormat("doFoo(function() { return 1; });", Style);
|
2014-10-01 01:57:06 +08:00
|
|
|
verifyFormat("var func = function() {\n"
|
|
|
|
" return 1;\n"
|
|
|
|
"};");
|
2015-06-18 20:32:59 +08:00
|
|
|
verifyFormat("var func = //\n"
|
|
|
|
" function() {\n"
|
|
|
|
" return 1;\n"
|
|
|
|
"};");
|
2014-05-08 17:25:39 +08:00
|
|
|
verifyFormat("return {\n"
|
|
|
|
" body: {\n"
|
|
|
|
" setAttribute: function(key, val) { this[key] = val; },\n"
|
|
|
|
" getAttribute: function(key) { return this[key]; },\n"
|
|
|
|
" style: {direction: ''}\n"
|
|
|
|
" }\n"
|
2016-09-08 07:01:13 +08:00
|
|
|
"};",
|
|
|
|
Style);
|
2015-10-27 20:38:37 +08:00
|
|
|
verifyFormat("abc = xyz ? function() {\n"
|
|
|
|
" return 1;\n"
|
|
|
|
"} : function() {\n"
|
|
|
|
" return -1;\n"
|
|
|
|
"};");
|
2014-05-21 20:51:23 +08:00
|
|
|
|
|
|
|
verifyFormat("var closure = goog.bind(\n"
|
|
|
|
" function() { // comment\n"
|
|
|
|
" foo();\n"
|
|
|
|
" bar();\n"
|
|
|
|
" },\n"
|
2017-01-06 01:59:44 +08:00
|
|
|
" this, arg1IsReallyLongAndNeedsLineBreaks,\n"
|
|
|
|
" arg3IsReallyLongAndNeedsLineBreaks);");
|
2014-05-21 20:51:23 +08:00
|
|
|
verifyFormat("var closure = goog.bind(function() { // comment\n"
|
|
|
|
" foo();\n"
|
|
|
|
" bar();\n"
|
|
|
|
"}, this);");
|
2014-06-06 21:49:04 +08:00
|
|
|
verifyFormat("return {\n"
|
|
|
|
" a: 'E',\n"
|
|
|
|
" b: function() {\n"
|
|
|
|
" return function() {\n"
|
|
|
|
" f(); //\n"
|
|
|
|
" };\n"
|
|
|
|
" }\n"
|
|
|
|
"};");
|
2014-11-27 23:37:42 +08:00
|
|
|
verifyFormat("{\n"
|
|
|
|
" var someVariable = function(x) {\n"
|
|
|
|
" return x.zIsTooLongForOneLineWithTheDeclarationLine();\n"
|
|
|
|
" };\n"
|
|
|
|
"}");
|
2015-05-08 16:38:52 +08:00
|
|
|
verifyFormat("someLooooooooongFunction(\n"
|
|
|
|
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
|
|
|
|
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
|
|
|
|
" function(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n"
|
|
|
|
" // code\n"
|
|
|
|
" });");
|
2014-05-22 16:36:53 +08:00
|
|
|
|
2014-06-13 15:02:04 +08:00
|
|
|
verifyFormat("return {\n"
|
|
|
|
" a: function SomeFunction() {\n"
|
|
|
|
" // ...\n"
|
|
|
|
" return 1;\n"
|
|
|
|
" }\n"
|
|
|
|
"};");
|
2014-12-12 17:40:58 +08:00
|
|
|
verifyFormat("this.someObject.doSomething(aaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
|
|
|
|
" .then(goog.bind(function(aaaaaaaaaaa) {\n"
|
|
|
|
" someFunction();\n"
|
|
|
|
" someFunction();\n"
|
|
|
|
" }, this), aaaaaaaaaaaaaaaaa);");
|
|
|
|
|
2015-10-27 20:38:37 +08:00
|
|
|
verifyFormat("someFunction(goog.bind(function() {\n"
|
|
|
|
" doSomething();\n"
|
|
|
|
" doSomething();\n"
|
|
|
|
"}, this), goog.bind(function() {\n"
|
|
|
|
" doSomething();\n"
|
|
|
|
" doSomething();\n"
|
|
|
|
"}, this));");
|
2015-06-01 17:56:32 +08:00
|
|
|
|
2017-01-30 15:08:40 +08:00
|
|
|
verifyFormat("SomeFunction(function() {\n"
|
|
|
|
" foo();\n"
|
|
|
|
" bar();\n"
|
|
|
|
"}.bind(this));");
|
|
|
|
|
2017-05-29 15:50:52 +08:00
|
|
|
verifyFormat("SomeFunction((function() {\n"
|
|
|
|
" foo();\n"
|
|
|
|
" bar();\n"
|
|
|
|
" }).bind(this));");
|
|
|
|
|
2015-06-01 17:56:32 +08:00
|
|
|
// FIXME: This is bad, we should be wrapping before "function() {".
|
|
|
|
verifyFormat("someFunction(function() {\n"
|
|
|
|
" doSomething(); // break\n"
|
|
|
|
"})\n"
|
|
|
|
" .doSomethingElse(\n"
|
|
|
|
" // break\n"
|
2017-05-15 19:15:29 +08:00
|
|
|
" );");
|
2016-09-08 07:01:13 +08:00
|
|
|
|
|
|
|
Style.ColumnLimit = 33;
|
|
|
|
verifyFormat("f({a: function() { return 1; }});", Style);
|
|
|
|
Style.ColumnLimit = 32;
|
|
|
|
verifyFormat("f({\n"
|
|
|
|
" a: function() { return 1; }\n"
|
|
|
|
"});",
|
|
|
|
Style);
|
2014-05-07 17:48:30 +08:00
|
|
|
}
|
|
|
|
|
2017-08-02 01:35:57 +08:00
|
|
|
TEST_F(FormatTestJS, DontWrapEmptyLiterals) {
|
|
|
|
verifyFormat("(aaaaaaaaaaaaaaaaaaaaa.getData as jasmine.Spy)\n"
|
|
|
|
" .and.returnValue(Observable.of([]));");
|
|
|
|
verifyFormat("(aaaaaaaaaaaaaaaaaaaaa.getData as jasmine.Spy)\n"
|
|
|
|
" .and.returnValue(Observable.of({}));");
|
|
|
|
verifyFormat("(aaaaaaaaaaaaaaaaaaaaa.getData as jasmine.Spy)\n"
|
|
|
|
" .and.returnValue(Observable.of(()));");
|
|
|
|
}
|
|
|
|
|
2014-10-01 01:57:06 +08:00
|
|
|
TEST_F(FormatTestJS, InliningFunctionLiterals) {
|
|
|
|
FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
|
|
|
|
Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
|
|
|
|
verifyFormat("var func = function() {\n"
|
|
|
|
" return 1;\n"
|
|
|
|
"};",
|
|
|
|
Style);
|
|
|
|
verifyFormat("var func = doSomething(function() { return 1; });", Style);
|
|
|
|
verifyFormat("var outer = function() {\n"
|
|
|
|
" var inner = function() { return 1; }\n"
|
|
|
|
"};",
|
|
|
|
Style);
|
|
|
|
verifyFormat("function outer1(a, b) {\n"
|
|
|
|
" function inner1(a, b) { return a; }\n"
|
|
|
|
"}",
|
|
|
|
Style);
|
|
|
|
|
|
|
|
Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
|
|
|
|
verifyFormat("var func = function() { return 1; };", Style);
|
|
|
|
verifyFormat("var func = doSomething(function() { return 1; });", Style);
|
|
|
|
verifyFormat(
|
|
|
|
"var outer = function() { var inner = function() { return 1; } };",
|
|
|
|
Style);
|
|
|
|
verifyFormat("function outer1(a, b) {\n"
|
|
|
|
" function inner1(a, b) { return a; }\n"
|
|
|
|
"}",
|
|
|
|
Style);
|
|
|
|
|
|
|
|
Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
|
|
|
|
verifyFormat("var func = function() {\n"
|
|
|
|
" return 1;\n"
|
|
|
|
"};",
|
|
|
|
Style);
|
|
|
|
verifyFormat("var func = doSomething(function() {\n"
|
|
|
|
" return 1;\n"
|
|
|
|
"});",
|
|
|
|
Style);
|
|
|
|
verifyFormat("var outer = function() {\n"
|
|
|
|
" var inner = function() {\n"
|
|
|
|
" return 1;\n"
|
|
|
|
" }\n"
|
|
|
|
"};",
|
|
|
|
Style);
|
|
|
|
verifyFormat("function outer1(a, b) {\n"
|
|
|
|
" function inner1(a, b) {\n"
|
|
|
|
" return a;\n"
|
|
|
|
" }\n"
|
|
|
|
"}",
|
|
|
|
Style);
|
2015-11-21 00:44:28 +08:00
|
|
|
|
|
|
|
Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
|
|
|
|
verifyFormat("var func = function() {\n"
|
|
|
|
" return 1;\n"
|
|
|
|
"};",
|
|
|
|
Style);
|
2014-10-01 01:57:06 +08:00
|
|
|
}
|
|
|
|
|
2014-06-03 20:02:45 +08:00
|
|
|
TEST_F(FormatTestJS, MultipleFunctionLiterals) {
|
2016-09-08 07:01:13 +08:00
|
|
|
FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
|
|
|
|
Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
|
2014-06-03 20:02:45 +08:00
|
|
|
verifyFormat("promise.then(\n"
|
|
|
|
" function success() {\n"
|
|
|
|
" doFoo();\n"
|
|
|
|
" doBar();\n"
|
|
|
|
" },\n"
|
|
|
|
" function error() {\n"
|
|
|
|
" doFoo();\n"
|
|
|
|
" doBaz();\n"
|
|
|
|
" },\n"
|
|
|
|
" []);\n");
|
|
|
|
verifyFormat("promise.then(\n"
|
|
|
|
" function success() {\n"
|
|
|
|
" doFoo();\n"
|
|
|
|
" doBar();\n"
|
|
|
|
" },\n"
|
|
|
|
" [],\n"
|
|
|
|
" function error() {\n"
|
|
|
|
" doFoo();\n"
|
|
|
|
" doBaz();\n"
|
|
|
|
" });\n");
|
2015-10-27 20:38:37 +08:00
|
|
|
verifyFormat("promise.then(\n"
|
|
|
|
" [],\n"
|
|
|
|
" function success() {\n"
|
|
|
|
" doFoo();\n"
|
|
|
|
" doBar();\n"
|
|
|
|
" },\n"
|
|
|
|
" function error() {\n"
|
|
|
|
" doFoo();\n"
|
|
|
|
" doBaz();\n"
|
|
|
|
" });\n");
|
2014-09-29 15:54:54 +08:00
|
|
|
|
|
|
|
verifyFormat("getSomeLongPromise()\n"
|
|
|
|
" .then(function(value) { body(); })\n"
|
2014-12-12 17:40:58 +08:00
|
|
|
" .thenCatch(function(error) {\n"
|
|
|
|
" body();\n"
|
|
|
|
" body();\n"
|
2016-09-08 07:01:13 +08:00
|
|
|
" });",
|
|
|
|
Style);
|
2014-09-29 15:54:54 +08:00
|
|
|
verifyFormat("getSomeLongPromise()\n"
|
|
|
|
" .then(function(value) {\n"
|
|
|
|
" body();\n"
|
|
|
|
" body();\n"
|
|
|
|
" })\n"
|
|
|
|
" .thenCatch(function(error) {\n"
|
|
|
|
" body();\n"
|
|
|
|
" body();\n"
|
|
|
|
" });");
|
2014-12-12 17:40:58 +08:00
|
|
|
|
2015-04-07 16:20:35 +08:00
|
|
|
verifyFormat("getSomeLongPromise()\n"
|
|
|
|
" .then(function(value) { body(); })\n"
|
2016-09-08 07:01:13 +08:00
|
|
|
" .thenCatch(function(error) { body(); });",
|
|
|
|
Style);
|
2016-01-11 19:00:58 +08:00
|
|
|
|
|
|
|
verifyFormat("return [aaaaaaaaaaaaaaaaaaaaaa]\n"
|
|
|
|
" .aaaaaaa(function() {\n"
|
|
|
|
" //\n"
|
|
|
|
" })\n"
|
|
|
|
" .bbbbbb();");
|
2014-06-03 20:02:45 +08:00
|
|
|
}
|
|
|
|
|
2015-05-21 20:23:34 +08:00
|
|
|
TEST_F(FormatTestJS, ArrowFunctions) {
|
|
|
|
verifyFormat("var x = (a) => {\n"
|
2020-01-24 18:30:31 +08:00
|
|
|
" x;\n"
|
2015-05-21 20:23:34 +08:00
|
|
|
" return a;\n"
|
2020-01-24 18:30:31 +08:00
|
|
|
"};\n");
|
2015-05-21 20:23:34 +08:00
|
|
|
verifyFormat("var x = (a) => {\n"
|
2016-09-08 07:01:13 +08:00
|
|
|
" function y() {\n"
|
|
|
|
" return 42;\n"
|
|
|
|
" }\n"
|
2015-05-21 20:23:34 +08:00
|
|
|
" return a;\n"
|
|
|
|
"};");
|
|
|
|
verifyFormat("var x = (a: type): {some: type} => {\n"
|
2020-01-24 18:30:31 +08:00
|
|
|
" y;\n"
|
2015-05-21 20:23:34 +08:00
|
|
|
" return a;\n"
|
|
|
|
"};");
|
|
|
|
verifyFormat("var x = (a) => a;");
|
2015-06-03 06:06:07 +08:00
|
|
|
verifyFormat("return () => [];");
|
2015-06-04 01:08:40 +08:00
|
|
|
verifyFormat("var aaaaaaaaaaaaaaaaaaaa = {\n"
|
|
|
|
" aaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n"
|
|
|
|
" (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
|
|
|
|
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) =>\n"
|
2015-06-05 16:25:37 +08:00
|
|
|
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
|
2015-06-04 01:08:40 +08:00
|
|
|
"};");
|
2015-10-27 20:38:37 +08:00
|
|
|
verifyFormat("var a = a.aaaaaaa(\n"
|
|
|
|
" (a: a) => aaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) &&\n"
|
2015-12-21 21:52:19 +08:00
|
|
|
" aaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
|
2015-10-27 20:38:37 +08:00
|
|
|
verifyFormat("var a = a.aaaaaaa(\n"
|
|
|
|
" (a: a) => aaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) ?\n"
|
2015-12-21 21:52:19 +08:00
|
|
|
" aaaaaaaaaaaaaaaaaaaaa(bbbbbbb) :\n"
|
|
|
|
" aaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
|
2015-06-01 17:56:32 +08:00
|
|
|
|
|
|
|
// FIXME: This is bad, we should be wrapping before "() => {".
|
|
|
|
verifyFormat("someFunction(() => {\n"
|
|
|
|
" doSomething(); // break\n"
|
|
|
|
"})\n"
|
|
|
|
" .doSomethingElse(\n"
|
|
|
|
" // break\n"
|
2017-05-15 19:15:29 +08:00
|
|
|
" );");
|
2017-08-02 01:19:32 +08:00
|
|
|
verifyFormat("const f = (x: string|null): string|null => {\n"
|
2020-01-24 18:30:31 +08:00
|
|
|
" y;\n"
|
2017-08-02 01:19:32 +08:00
|
|
|
" return x;\n"
|
|
|
|
"}\n");
|
2015-05-21 20:23:34 +08:00
|
|
|
}
|
|
|
|
|
2020-01-24 18:30:31 +08:00
|
|
|
TEST_F(FormatTestJS, ArrowFunctionStyle) {
|
|
|
|
FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
|
|
|
|
Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
|
|
|
|
verifyFormat("const arr = () => { x; };", Style);
|
|
|
|
verifyFormat("const arrInlineAll = () => {};", Style);
|
|
|
|
Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_None;
|
|
|
|
verifyFormat("const arr = () => {\n"
|
|
|
|
" x;\n"
|
|
|
|
"};",
|
|
|
|
Style);
|
|
|
|
verifyFormat("const arrInlineNone = () => {\n"
|
|
|
|
"};",
|
|
|
|
Style);
|
|
|
|
Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
|
|
|
|
verifyFormat("const arr = () => {\n"
|
|
|
|
" x;\n"
|
|
|
|
"};",
|
|
|
|
Style);
|
2020-05-02 22:42:20 +08:00
|
|
|
verifyFormat("const arrInlineEmpty = () => {};", Style);
|
2020-01-24 18:30:31 +08:00
|
|
|
Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Inline;
|
|
|
|
verifyFormat("const arr = () => {\n"
|
|
|
|
" x;\n"
|
|
|
|
"};",
|
|
|
|
Style);
|
2020-05-02 22:42:20 +08:00
|
|
|
verifyFormat("foo(() => {});", Style);
|
2020-01-24 18:30:31 +08:00
|
|
|
verifyFormat("const arrInlineInline = () => {};", Style);
|
|
|
|
}
|
|
|
|
|
2014-05-06 22:12:21 +08:00
|
|
|
TEST_F(FormatTestJS, ReturnStatements) {
|
2014-10-01 01:57:06 +08:00
|
|
|
verifyFormat("function() {\n"
|
|
|
|
" return [hello, world];\n"
|
|
|
|
"}");
|
2014-05-06 22:12:21 +08:00
|
|
|
}
|
|
|
|
|
2015-11-21 00:18:42 +08:00
|
|
|
TEST_F(FormatTestJS, ForLoops) {
|
|
|
|
verifyFormat("for (var i in [2, 3]) {\n"
|
|
|
|
"}");
|
2016-02-11 21:24:15 +08:00
|
|
|
verifyFormat("for (var i of [2, 3]) {\n"
|
|
|
|
"}");
|
2016-03-06 02:34:26 +08:00
|
|
|
verifyFormat("for (let {a, b} of x) {\n"
|
|
|
|
"}");
|
2017-11-24 18:48:25 +08:00
|
|
|
verifyFormat("for (let {a, b} of [x]) {\n"
|
|
|
|
"}");
|
|
|
|
verifyFormat("for (let [a, b] of [x]) {\n"
|
|
|
|
"}");
|
2016-03-06 02:34:26 +08:00
|
|
|
verifyFormat("for (let {a, b} in x) {\n"
|
|
|
|
"}");
|
2015-11-21 00:18:42 +08:00
|
|
|
}
|
|
|
|
|
2016-03-15 03:21:36 +08:00
|
|
|
TEST_F(FormatTestJS, WrapRespectsAutomaticSemicolonInsertion) {
|
2015-06-12 12:58:27 +08:00
|
|
|
// The following statements must not wrap, as otherwise the program meaning
|
|
|
|
// would change due to automatic semicolon insertion.
|
|
|
|
// See http://www.ecma-international.org/ecma-262/5.1/#sec-7.9.1.
|
|
|
|
verifyFormat("return aaaaa;", getGoogleJSStyleWithColumns(10));
|
2017-11-25 01:05:35 +08:00
|
|
|
verifyFormat("yield aaaaa;", getGoogleJSStyleWithColumns(10));
|
2016-09-07 02:39:30 +08:00
|
|
|
verifyFormat("return /* hello! */ aaaaa;", getGoogleJSStyleWithColumns(10));
|
2015-06-12 12:58:27 +08:00
|
|
|
verifyFormat("continue aaaaa;", getGoogleJSStyleWithColumns(10));
|
2016-09-07 02:39:30 +08:00
|
|
|
verifyFormat("continue /* hello! */ aaaaa;", getGoogleJSStyleWithColumns(10));
|
2015-06-12 12:58:27 +08:00
|
|
|
verifyFormat("break aaaaa;", getGoogleJSStyleWithColumns(10));
|
|
|
|
verifyFormat("throw aaaaa;", getGoogleJSStyleWithColumns(10));
|
|
|
|
verifyFormat("aaaaaaaaa++;", getGoogleJSStyleWithColumns(10));
|
|
|
|
verifyFormat("aaaaaaaaa--;", getGoogleJSStyleWithColumns(10));
|
2016-01-14 13:37:52 +08:00
|
|
|
verifyFormat("return [\n"
|
|
|
|
" aaa\n"
|
|
|
|
"];",
|
|
|
|
getGoogleJSStyleWithColumns(12));
|
2017-07-07 21:17:10 +08:00
|
|
|
verifyFormat("class X {\n"
|
|
|
|
" readonly ratherLongField =\n"
|
|
|
|
" 1;\n"
|
|
|
|
"}",
|
|
|
|
"class X {\n"
|
|
|
|
" readonly ratherLongField = 1;\n"
|
|
|
|
"}",
|
|
|
|
getGoogleJSStyleWithColumns(20));
|
2017-08-09 23:19:16 +08:00
|
|
|
verifyFormat("const x = (5 + 9)\n"
|
|
|
|
"const y = 3\n",
|
|
|
|
"const x = ( 5 + 9)\n"
|
|
|
|
"const y = 3\n");
|
2017-11-30 18:25:17 +08:00
|
|
|
// Ideally the foo() bit should be indented relative to the async function().
|
|
|
|
verifyFormat("async function\n"
|
|
|
|
"foo() {}",
|
|
|
|
getGoogleJSStyleWithColumns(10));
|
|
|
|
verifyFormat("await theReckoning;", getGoogleJSStyleWithColumns(10));
|
2018-01-26 23:07:49 +08:00
|
|
|
verifyFormat("some['a']['b']", getGoogleJSStyleWithColumns(10));
|
|
|
|
verifyFormat("x = (a['a']\n"
|
2018-05-22 18:39:07 +08:00
|
|
|
" ['b']);",
|
|
|
|
getGoogleJSStyleWithColumns(10));
|
|
|
|
verifyFormat("function f() {\n"
|
|
|
|
" return foo.bar(\n"
|
|
|
|
" (param): param is {\n"
|
|
|
|
" a: SomeType\n"
|
|
|
|
" }&ABC => 1)\n"
|
|
|
|
"}",
|
|
|
|
getGoogleJSStyleWithColumns(25));
|
2015-06-12 12:58:27 +08:00
|
|
|
}
|
|
|
|
|
2018-11-20 22:22:43 +08:00
|
|
|
TEST_F(FormatTestJS, AddsIsTheDictKeyOnNewline) {
|
|
|
|
// Do not confuse is, the dict key with is, the type matcher. Put is, the dict
|
|
|
|
// key, on a newline.
|
|
|
|
verifyFormat("Polymer({\n"
|
|
|
|
" is: '', //\n"
|
|
|
|
" rest: 1\n"
|
|
|
|
"});",
|
|
|
|
getGoogleJSStyleWithColumns(20));
|
|
|
|
}
|
|
|
|
|
2016-03-15 03:21:36 +08:00
|
|
|
TEST_F(FormatTestJS, AutomaticSemicolonInsertionHeuristic) {
|
|
|
|
verifyFormat("a\n"
|
|
|
|
"b;",
|
|
|
|
" a \n"
|
|
|
|
" b ;");
|
|
|
|
verifyFormat("a()\n"
|
|
|
|
"b;",
|
|
|
|
" a ()\n"
|
|
|
|
" b ;");
|
|
|
|
verifyFormat("a[b]\n"
|
|
|
|
"c;",
|
|
|
|
"a [b]\n"
|
|
|
|
"c ;");
|
|
|
|
verifyFormat("1\n"
|
|
|
|
"a;",
|
|
|
|
"1 \n"
|
|
|
|
"a ;");
|
|
|
|
verifyFormat("a\n"
|
|
|
|
"1;",
|
|
|
|
"a \n"
|
|
|
|
"1 ;");
|
|
|
|
verifyFormat("a\n"
|
|
|
|
"'x';",
|
|
|
|
"a \n"
|
|
|
|
" 'x';");
|
|
|
|
verifyFormat("a++\n"
|
|
|
|
"b;",
|
|
|
|
"a ++\n"
|
|
|
|
"b ;");
|
|
|
|
verifyFormat("a\n"
|
|
|
|
"!b && c;",
|
|
|
|
"a \n"
|
|
|
|
" ! b && c;");
|
|
|
|
verifyFormat("a\n"
|
|
|
|
"if (1) f();",
|
|
|
|
" a\n"
|
|
|
|
" if (1) f();");
|
|
|
|
verifyFormat("a\n"
|
|
|
|
"class X {}",
|
|
|
|
" a\n"
|
|
|
|
" class X {}");
|
|
|
|
verifyFormat("var a", "var\n"
|
|
|
|
"a");
|
|
|
|
verifyFormat("x instanceof String", "x\n"
|
|
|
|
"instanceof\n"
|
|
|
|
"String");
|
2016-04-11 15:35:57 +08:00
|
|
|
verifyFormat("function f(@Foo bar) {}", "function f(@Foo\n"
|
|
|
|
" bar) {}");
|
2017-11-25 17:19:42 +08:00
|
|
|
verifyFormat("function f(@Foo(Param) bar) {}", "function f(@Foo(Param)\n"
|
|
|
|
" bar) {}");
|
2016-09-19 01:21:52 +08:00
|
|
|
verifyFormat("a = true\n"
|
|
|
|
"return 1",
|
|
|
|
"a = true\n"
|
|
|
|
" return 1");
|
|
|
|
verifyFormat("a = 's'\n"
|
|
|
|
"return 1",
|
|
|
|
"a = 's'\n"
|
|
|
|
" return 1");
|
|
|
|
verifyFormat("a = null\n"
|
|
|
|
"return 1",
|
|
|
|
"a = null\n"
|
|
|
|
" return 1");
|
2017-01-16 17:52:40 +08:00
|
|
|
// Below "class Y {}" should ideally be on its own line.
|
2020-05-02 22:42:20 +08:00
|
|
|
verifyFormat("x = {\n"
|
|
|
|
" a: 1\n"
|
|
|
|
"} class Y {}",
|
|
|
|
" x = {a : 1}\n"
|
|
|
|
" class Y { }");
|
|
|
|
verifyFormat("if (x) {\n"
|
|
|
|
"}\n"
|
|
|
|
"return 1",
|
|
|
|
"if (x) {}\n"
|
|
|
|
" return 1");
|
|
|
|
verifyFormat("if (x) {\n"
|
|
|
|
"}\n"
|
|
|
|
"class X {}",
|
|
|
|
"if (x) {}\n"
|
|
|
|
" class X {}");
|
2017-01-09 16:56:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(FormatTestJS, ImportExportASI) {
|
2020-05-02 22:42:20 +08:00
|
|
|
verifyFormat("import {x} from 'y'\n"
|
|
|
|
"export function z() {}",
|
|
|
|
"import {x} from 'y'\n"
|
|
|
|
" export function z() {}");
|
2017-01-16 17:52:40 +08:00
|
|
|
// Below "class Y {}" should ideally be on its own line.
|
2020-05-02 22:42:20 +08:00
|
|
|
verifyFormat("export {x} class Y {}", " export {x}\n"
|
|
|
|
" class Y {\n}");
|
|
|
|
verifyFormat("if (x) {\n"
|
|
|
|
"}\n"
|
|
|
|
"export class Y {}",
|
|
|
|
"if ( x ) { }\n"
|
|
|
|
" export class Y {}");
|
2016-03-15 03:21:36 +08:00
|
|
|
}
|
|
|
|
|
2015-05-21 20:23:34 +08:00
|
|
|
TEST_F(FormatTestJS, ClosureStyleCasts) {
|
2014-05-06 22:41:29 +08:00
|
|
|
verifyFormat("var x = /** @type {foo} */ (bar);");
|
|
|
|
}
|
|
|
|
|
2014-05-08 19:58:24 +08:00
|
|
|
TEST_F(FormatTestJS, TryCatch) {
|
|
|
|
verifyFormat("try {\n"
|
|
|
|
" f();\n"
|
|
|
|
"} catch (e) {\n"
|
|
|
|
" g();\n"
|
|
|
|
"} finally {\n"
|
|
|
|
" h();\n"
|
|
|
|
"}");
|
2014-09-04 23:03:34 +08:00
|
|
|
|
|
|
|
// But, of course, "catch" is a perfectly fine function name in JavaScript.
|
|
|
|
verifyFormat("someObject.catch();");
|
2014-11-27 22:55:17 +08:00
|
|
|
verifyFormat("someObject.new();");
|
2014-05-08 19:58:24 +08:00
|
|
|
}
|
|
|
|
|
2014-05-22 17:10:04 +08:00
|
|
|
TEST_F(FormatTestJS, StringLiteralConcatenation) {
|
|
|
|
verifyFormat("var literal = 'hello ' +\n"
|
2015-12-21 21:52:19 +08:00
|
|
|
" 'world';");
|
2014-05-22 17:10:04 +08:00
|
|
|
}
|
|
|
|
|
2014-05-08 15:01:45 +08:00
|
|
|
TEST_F(FormatTestJS, RegexLiteralClassification) {
|
|
|
|
// Regex literals.
|
|
|
|
verifyFormat("var regex = /abc/;");
|
|
|
|
verifyFormat("f(/abc/);");
|
|
|
|
verifyFormat("f(abc, /abc/);");
|
|
|
|
verifyFormat("some_map[/abc/];");
|
|
|
|
verifyFormat("var x = a ? /abc/ : /abc/;");
|
|
|
|
verifyFormat("for (var i = 0; /abc/.test(s[i]); i++) {\n}");
|
|
|
|
verifyFormat("var x = !/abc/.test(y);");
|
2017-02-07 22:08:03 +08:00
|
|
|
verifyFormat("var x = foo()! / 10;");
|
2014-05-08 15:01:45 +08:00
|
|
|
verifyFormat("var x = a && /abc/.test(y);");
|
|
|
|
verifyFormat("var x = a || /abc/.test(y);");
|
|
|
|
verifyFormat("var x = a + /abc/.search(y);");
|
2015-07-02 21:20:45 +08:00
|
|
|
verifyFormat("/abc/.search(y);");
|
2014-05-08 15:45:18 +08:00
|
|
|
verifyFormat("var regexs = {/abc/, /abc/};");
|
|
|
|
verifyFormat("return /abc/;");
|
2014-05-08 15:01:45 +08:00
|
|
|
|
|
|
|
// Not regex literals.
|
|
|
|
verifyFormat("var a = a / 2 + b / 3;");
|
2015-10-18 15:02:28 +08:00
|
|
|
verifyFormat("var a = a++ / 2;");
|
|
|
|
// Prefix unary can operate on regex literals, not that it makes sense.
|
|
|
|
verifyFormat("var a = ++/a/;");
|
|
|
|
|
|
|
|
// This is a known issue, regular expressions are incorrectly detected if
|
|
|
|
// directly following a closing parenthesis.
|
|
|
|
verifyFormat("if (foo) / bar /.exec(baz);");
|
2014-05-08 15:01:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(FormatTestJS, RegexLiteralSpecialCharacters) {
|
2015-05-08 15:55:13 +08:00
|
|
|
verifyFormat("var regex = /=/;");
|
2014-05-08 15:01:45 +08:00
|
|
|
verifyFormat("var regex = /a*/;");
|
|
|
|
verifyFormat("var regex = /a+/;");
|
|
|
|
verifyFormat("var regex = /a?/;");
|
|
|
|
verifyFormat("var regex = /.a./;");
|
|
|
|
verifyFormat("var regex = /a\\*/;");
|
|
|
|
verifyFormat("var regex = /^a$/;");
|
|
|
|
verifyFormat("var regex = /\\/a/;");
|
|
|
|
verifyFormat("var regex = /(?:x)/;");
|
|
|
|
verifyFormat("var regex = /x(?=y)/;");
|
|
|
|
verifyFormat("var regex = /x(?!y)/;");
|
|
|
|
verifyFormat("var regex = /x|y/;");
|
|
|
|
verifyFormat("var regex = /a{2}/;");
|
|
|
|
verifyFormat("var regex = /a{1,3}/;");
|
2015-10-12 11:13:48 +08:00
|
|
|
|
2014-05-08 15:01:45 +08:00
|
|
|
verifyFormat("var regex = /[abc]/;");
|
|
|
|
verifyFormat("var regex = /[^abc]/;");
|
|
|
|
verifyFormat("var regex = /[\\b]/;");
|
2015-10-12 11:13:48 +08:00
|
|
|
verifyFormat("var regex = /[/]/;");
|
|
|
|
verifyFormat("var regex = /[\\/]/;");
|
|
|
|
verifyFormat("var regex = /\\[/;");
|
|
|
|
verifyFormat("var regex = /\\\\[/]/;");
|
2015-10-18 15:02:28 +08:00
|
|
|
verifyFormat("var regex = /}[\"]/;");
|
|
|
|
verifyFormat("var regex = /}[/\"]/;");
|
|
|
|
verifyFormat("var regex = /}[\"/]/;");
|
2015-10-12 11:13:48 +08:00
|
|
|
|
2014-05-08 15:01:45 +08:00
|
|
|
verifyFormat("var regex = /\\b/;");
|
|
|
|
verifyFormat("var regex = /\\B/;");
|
|
|
|
verifyFormat("var regex = /\\d/;");
|
|
|
|
verifyFormat("var regex = /\\D/;");
|
|
|
|
verifyFormat("var regex = /\\f/;");
|
|
|
|
verifyFormat("var regex = /\\n/;");
|
|
|
|
verifyFormat("var regex = /\\r/;");
|
|
|
|
verifyFormat("var regex = /\\s/;");
|
|
|
|
verifyFormat("var regex = /\\S/;");
|
|
|
|
verifyFormat("var regex = /\\t/;");
|
|
|
|
verifyFormat("var regex = /\\v/;");
|
|
|
|
verifyFormat("var regex = /\\w/;");
|
|
|
|
verifyFormat("var regex = /\\W/;");
|
|
|
|
verifyFormat("var regex = /a(a)\\1/;");
|
|
|
|
verifyFormat("var regex = /\\0/;");
|
2014-05-12 19:29:50 +08:00
|
|
|
verifyFormat("var regex = /\\\\/g;");
|
|
|
|
verifyFormat("var regex = /\\a\\\\/g;");
|
|
|
|
verifyFormat("var regex = /\a\\//g;");
|
2014-09-09 22:37:39 +08:00
|
|
|
verifyFormat("var regex = /a\\//;\n"
|
|
|
|
"var x = 0;");
|
2016-03-15 03:21:36 +08:00
|
|
|
verifyFormat("var regex = /'/g;", "var regex = /'/g ;");
|
|
|
|
verifyFormat("var regex = /'/g; //'", "var regex = /'/g ; //'");
|
|
|
|
verifyFormat("var regex = /\\/*/;\n"
|
|
|
|
"var x = 0;",
|
|
|
|
"var regex = /\\/*/;\n"
|
|
|
|
"var x=0;");
|
|
|
|
verifyFormat("var x = /a\\//;", "var x = /a\\// \n;");
|
2015-06-25 00:01:02 +08:00
|
|
|
verifyFormat("var regex = /\"/;", getGoogleJSStyleWithColumns(16));
|
|
|
|
verifyFormat("var regex =\n"
|
|
|
|
" /\"/;",
|
|
|
|
getGoogleJSStyleWithColumns(15));
|
2015-07-02 22:14:04 +08:00
|
|
|
verifyFormat("var regex = //\n"
|
|
|
|
" /a/;");
|
2015-07-02 23:00:44 +08:00
|
|
|
verifyFormat("var regexs = [\n"
|
|
|
|
" /d/, //\n"
|
|
|
|
" /aa/, //\n"
|
|
|
|
"];");
|
2014-05-08 15:01:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(FormatTestJS, RegexLiteralModifiers) {
|
|
|
|
verifyFormat("var regex = /abc/g;");
|
|
|
|
verifyFormat("var regex = /abc/i;");
|
|
|
|
verifyFormat("var regex = /abc/m;");
|
|
|
|
verifyFormat("var regex = /abc/y;");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(FormatTestJS, RegexLiteralLength) {
|
|
|
|
verifyFormat("var regex = /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
|
|
|
|
getGoogleJSStyleWithColumns(60));
|
|
|
|
verifyFormat("var regex =\n"
|
|
|
|
" /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
|
|
|
|
getGoogleJSStyleWithColumns(60));
|
2014-12-17 17:11:08 +08:00
|
|
|
verifyFormat("var regex = /\\xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/;",
|
|
|
|
getGoogleJSStyleWithColumns(50));
|
2014-05-08 15:01:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(FormatTestJS, RegexLiteralExamples) {
|
|
|
|
verifyFormat("var regex = search.match(/(?:\?|&)times=([^?&]+)/i);");
|
|
|
|
}
|
|
|
|
|
2017-01-27 17:09:11 +08:00
|
|
|
TEST_F(FormatTestJS, IgnoresMpegTS) {
|
|
|
|
std::string MpegTS(200, ' ');
|
|
|
|
MpegTS.replace(0, strlen("nearlyLooks + like + ts + code; "),
|
|
|
|
"nearlyLooks + like + ts + code; ");
|
|
|
|
MpegTS[0] = 0x47;
|
|
|
|
MpegTS[188] = 0x47;
|
|
|
|
verifyFormat(MpegTS, MpegTS);
|
|
|
|
}
|
|
|
|
|
2015-02-19 01:09:53 +08:00
|
|
|
TEST_F(FormatTestJS, TypeAnnotations) {
|
|
|
|
verifyFormat("var x: string;");
|
2016-01-09 23:56:28 +08:00
|
|
|
verifyFormat("var x: {a: string; b: number;} = {};");
|
2015-02-19 01:09:53 +08:00
|
|
|
verifyFormat("function x(): string {\n return 'x';\n}");
|
2015-05-21 20:23:34 +08:00
|
|
|
verifyFormat("function x(): {x: string} {\n return {x: 'x'};\n}");
|
2015-02-19 01:09:53 +08:00
|
|
|
verifyFormat("function x(y: string): string {\n return 'x';\n}");
|
|
|
|
verifyFormat("for (var y: string in x) {\n x();\n}");
|
2016-02-11 21:24:15 +08:00
|
|
|
verifyFormat("for (var y: string of x) {\n x();\n}");
|
2016-01-09 23:56:28 +08:00
|
|
|
verifyFormat("function x(y: {a?: number;} = {}): number {\n"
|
|
|
|
" return 12;\n"
|
|
|
|
"}");
|
2017-11-25 17:33:47 +08:00
|
|
|
verifyFormat("const x: Array<{a: number; b: string;}> = [];");
|
2015-02-19 01:09:53 +08:00
|
|
|
verifyFormat("((a: string, b: number): string => a + b);");
|
|
|
|
verifyFormat("var x: (y: number) => string;");
|
|
|
|
verifyFormat("var x: P<string, (a: number) => string>;");
|
2016-09-08 07:01:13 +08:00
|
|
|
verifyFormat("var x = {\n"
|
|
|
|
" y: function(): z {\n"
|
|
|
|
" return 1;\n"
|
|
|
|
" }\n"
|
|
|
|
"};");
|
|
|
|
verifyFormat("var x = {\n"
|
|
|
|
" y: function(): {a: number} {\n"
|
|
|
|
" return 1;\n"
|
|
|
|
" }\n"
|
|
|
|
"};");
|
2016-01-08 18:51:24 +08:00
|
|
|
verifyFormat("function someFunc(args: string[]):\n"
|
|
|
|
" {longReturnValue: string[]} {}",
|
|
|
|
getGoogleJSStyleWithColumns(60));
|
2017-02-20 20:43:41 +08:00
|
|
|
verifyFormat(
|
|
|
|
"var someValue = (v as aaaaaaaaaaaaaaaaaaaa<T>[])\n"
|
|
|
|
" .someFunction(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
|
2020-05-02 22:42:20 +08:00
|
|
|
verifyFormat("const xIsALongIdent:\n"
|
|
|
|
" YJustBarelyFitsLinex[];",
|
|
|
|
getGoogleJSStyleWithColumns(20));
|
2019-08-26 23:37:05 +08:00
|
|
|
verifyFormat("const x = {\n"
|
|
|
|
" y: 1\n"
|
|
|
|
"} as const;");
|
2015-02-19 01:09:53 +08:00
|
|
|
}
|
|
|
|
|
2016-03-22 01:57:31 +08:00
|
|
|
TEST_F(FormatTestJS, UnionIntersectionTypes) {
|
|
|
|
verifyFormat("let x: A|B = A | B;");
|
|
|
|
verifyFormat("let x: A&B|C = A & B;");
|
|
|
|
verifyFormat("let x: Foo<A|B> = new Foo<A|B>();");
|
|
|
|
verifyFormat("function(x: A|B): C&D {}");
|
|
|
|
verifyFormat("function(x: A|B = A | B): C&D {}");
|
2016-06-10 06:49:04 +08:00
|
|
|
verifyFormat("function x(path: number|string) {}");
|
|
|
|
verifyFormat("function x(): string|number {}");
|
2016-06-24 03:52:32 +08:00
|
|
|
verifyFormat("type Foo = Bar|Baz;");
|
|
|
|
verifyFormat("type Foo = Bar<X>|Baz;");
|
|
|
|
verifyFormat("type Foo = (Bar<X>|Baz);");
|
|
|
|
verifyFormat("let x: Bar|Baz;");
|
|
|
|
verifyFormat("let x: Bar<X>|Baz;");
|
|
|
|
verifyFormat("let x: (Foo|Bar)[];");
|
2017-06-07 20:53:22 +08:00
|
|
|
verifyFormat("type X = {\n"
|
|
|
|
" a: Foo|Bar;\n"
|
|
|
|
"};");
|
|
|
|
verifyFormat("export type X = {\n"
|
|
|
|
" a: Foo|Bar;\n"
|
|
|
|
"};");
|
2016-03-22 01:57:31 +08:00
|
|
|
}
|
|
|
|
|
2017-08-08 23:00:58 +08:00
|
|
|
TEST_F(FormatTestJS, UnionIntersectionTypesInObjectType) {
|
|
|
|
verifyFormat("let x: {x: number|null} = {x: number | null};");
|
|
|
|
verifyFormat("let nested: {x: {y: number|null}};");
|
|
|
|
verifyFormat("let mixed: {x: [number|null, {w: number}]};");
|
|
|
|
verifyFormat("class X {\n"
|
|
|
|
" contructor(x: {\n"
|
|
|
|
" a: a|null,\n"
|
|
|
|
" b: b|null,\n"
|
|
|
|
" }) {}\n"
|
|
|
|
"}");
|
|
|
|
}
|
|
|
|
|
2015-02-19 01:14:05 +08:00
|
|
|
TEST_F(FormatTestJS, ClassDeclarations) {
|
|
|
|
verifyFormat("class C {\n x: string = 12;\n}");
|
|
|
|
verifyFormat("class C {\n x(): string => 12;\n}");
|
|
|
|
verifyFormat("class C {\n ['x' + 2]: string = 12;\n}");
|
2017-05-31 17:29:40 +08:00
|
|
|
verifyFormat("class C {\n"
|
|
|
|
" foo() {}\n"
|
|
|
|
" [bar]() {}\n"
|
|
|
|
"}\n");
|
2015-02-19 01:14:05 +08:00
|
|
|
verifyFormat("class C {\n private x: string = 12;\n}");
|
|
|
|
verifyFormat("class C {\n private static x: string = 12;\n}");
|
2016-09-08 07:01:13 +08:00
|
|
|
verifyFormat("class C {\n static x(): string {\n return 'asd';\n }\n}");
|
2015-02-19 01:14:05 +08:00
|
|
|
verifyFormat("class C extends P implements I {}");
|
2015-04-13 22:56:54 +08:00
|
|
|
verifyFormat("class C extends p.P implements i.I {}");
|
2020-05-02 22:42:20 +08:00
|
|
|
verifyFormat("x(class {\n"
|
|
|
|
" a(): A {}\n"
|
|
|
|
"});");
|
2015-07-10 21:39:26 +08:00
|
|
|
verifyFormat("class Test {\n"
|
|
|
|
" aaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaaa):\n"
|
|
|
|
" aaaaaaaaaaaaaaaaaaaaaa {}\n"
|
|
|
|
"}");
|
2016-01-08 15:06:07 +08:00
|
|
|
verifyFormat("foo = class Name {\n"
|
|
|
|
" constructor() {}\n"
|
|
|
|
"};");
|
|
|
|
verifyFormat("foo = class {\n"
|
|
|
|
" constructor() {}\n"
|
|
|
|
"};");
|
2016-01-09 23:56:28 +08:00
|
|
|
verifyFormat("class C {\n"
|
|
|
|
" x: {y: Z;} = {};\n"
|
|
|
|
" private y: {y: Z;} = {};\n"
|
|
|
|
"}");
|
2015-06-03 16:43:18 +08:00
|
|
|
|
|
|
|
// ':' is not a type declaration here.
|
|
|
|
verifyFormat("class X {\n"
|
|
|
|
" subs = {\n"
|
|
|
|
" 'b': {\n"
|
|
|
|
" 'c': 1,\n"
|
|
|
|
" },\n"
|
|
|
|
" };\n"
|
|
|
|
"}");
|
2016-06-14 19:28:02 +08:00
|
|
|
verifyFormat("@Component({\n"
|
|
|
|
" moduleId: module.id,\n"
|
|
|
|
"})\n"
|
|
|
|
"class SessionListComponent implements OnDestroy, OnInit {\n"
|
|
|
|
"}");
|
2015-02-19 01:14:05 +08:00
|
|
|
}
|
|
|
|
|
2018-06-12 00:20:13 +08:00
|
|
|
TEST_F(FormatTestJS, StrictPropInitWrap) {
|
|
|
|
const FormatStyle &Style = getGoogleJSStyleWithColumns(22);
|
|
|
|
verifyFormat("class X {\n"
|
|
|
|
" strictPropInitField!:\n"
|
|
|
|
" string;\n"
|
|
|
|
"}",
|
|
|
|
Style);
|
|
|
|
}
|
|
|
|
|
2015-05-05 16:12:50 +08:00
|
|
|
TEST_F(FormatTestJS, InterfaceDeclarations) {
|
|
|
|
verifyFormat("interface I {\n"
|
|
|
|
" x: string;\n"
|
2015-12-29 16:54:23 +08:00
|
|
|
" enum: string[];\n"
|
2016-02-03 13:33:44 +08:00
|
|
|
" enum?: string[];\n"
|
2015-06-12 12:56:34 +08:00
|
|
|
"}\n"
|
|
|
|
"var y;");
|
2015-07-06 22:26:04 +08:00
|
|
|
// Ensure that state is reset after parsing the interface.
|
|
|
|
verifyFormat("interface a {}\n"
|
|
|
|
"export function b() {}\n"
|
|
|
|
"var x;");
|
2015-12-22 23:48:35 +08:00
|
|
|
|
|
|
|
// Arrays of object type literals.
|
|
|
|
verifyFormat("interface I {\n"
|
|
|
|
" o: {}[];\n"
|
|
|
|
"}");
|
2015-05-05 16:12:50 +08:00
|
|
|
}
|
|
|
|
|
2017-08-01 23:46:10 +08:00
|
|
|
TEST_F(FormatTestJS, ObjectTypesInExtendsImplements) {
|
|
|
|
verifyFormat("class C extends {} {}");
|
|
|
|
verifyFormat("class C implements {bar: number} {}");
|
|
|
|
// Somewhat odd, but probably closest to reasonable formatting?
|
|
|
|
verifyFormat("class C implements {\n"
|
|
|
|
" bar: number,\n"
|
|
|
|
" baz: string,\n"
|
|
|
|
"} {}");
|
|
|
|
verifyFormat("class C<P extends {}> {}");
|
|
|
|
}
|
|
|
|
|
2015-06-17 17:44:02 +08:00
|
|
|
TEST_F(FormatTestJS, EnumDeclarations) {
|
2015-06-17 17:44:07 +08:00
|
|
|
verifyFormat("enum Foo {\n"
|
|
|
|
" A = 1,\n"
|
|
|
|
" B\n"
|
|
|
|
"}");
|
|
|
|
verifyFormat("export /* somecomment*/ enum Foo {\n"
|
|
|
|
" A = 1,\n"
|
|
|
|
" B\n"
|
|
|
|
"}");
|
2015-06-17 17:44:02 +08:00
|
|
|
verifyFormat("enum Foo {\n"
|
|
|
|
" A = 1, // comment\n"
|
|
|
|
" B\n"
|
|
|
|
"}\n"
|
|
|
|
"var x = 1;");
|
2017-08-02 01:12:15 +08:00
|
|
|
verifyFormat("const enum Foo {\n"
|
|
|
|
" A = 1,\n"
|
|
|
|
" B\n"
|
|
|
|
"}");
|
|
|
|
verifyFormat("export const enum Foo {\n"
|
|
|
|
" A = 1,\n"
|
|
|
|
" B\n"
|
|
|
|
"}");
|
2015-06-17 17:44:02 +08:00
|
|
|
}
|
|
|
|
|
2017-11-25 17:19:42 +08:00
|
|
|
TEST_F(FormatTestJS, Decorators) {
|
2015-02-19 01:17:15 +08:00
|
|
|
verifyFormat("@A\nclass C {\n}");
|
|
|
|
verifyFormat("@A({arg: 'value'})\nclass C {\n}");
|
|
|
|
verifyFormat("@A\n@B\nclass C {\n}");
|
|
|
|
verifyFormat("class C {\n @A x: string;\n}");
|
|
|
|
verifyFormat("class C {\n"
|
|
|
|
" @A\n"
|
|
|
|
" private x(): string {\n"
|
|
|
|
" return 'y';\n"
|
|
|
|
" }\n"
|
|
|
|
"}");
|
2016-04-11 17:17:57 +08:00
|
|
|
verifyFormat("class C {\n"
|
|
|
|
" private x(@A x: string) {}\n"
|
|
|
|
"}");
|
2015-02-20 00:03:16 +08:00
|
|
|
verifyFormat("class X {}\n"
|
|
|
|
"class Y {}");
|
2017-04-26 20:36:49 +08:00
|
|
|
verifyFormat("class X {\n"
|
|
|
|
" @property() private isReply = false;\n"
|
|
|
|
"}\n");
|
2015-02-19 01:17:15 +08:00
|
|
|
}
|
|
|
|
|
2016-04-19 22:59:16 +08:00
|
|
|
TEST_F(FormatTestJS, TypeAliases) {
|
|
|
|
verifyFormat("type X = number;\n"
|
|
|
|
"class C {}");
|
|
|
|
verifyFormat("type X<Y> = Z<Y>;");
|
|
|
|
verifyFormat("type X = {\n"
|
|
|
|
" y: number\n"
|
|
|
|
"};\n"
|
|
|
|
"class C {}");
|
2017-08-15 00:09:08 +08:00
|
|
|
verifyFormat("export type X = {\n"
|
|
|
|
" a: string,\n"
|
|
|
|
" b?: string,\n"
|
|
|
|
"};\n");
|
2016-04-19 22:59:16 +08:00
|
|
|
}
|
|
|
|
|
2017-03-13 15:10:18 +08:00
|
|
|
TEST_F(FormatTestJS, TypeInterfaceLineWrapping) {
|
|
|
|
const FormatStyle &Style = getGoogleJSStyleWithColumns(20);
|
|
|
|
verifyFormat("type LongTypeIsReallyUnreasonablyLong =\n"
|
|
|
|
" string;\n",
|
2020-05-02 22:42:20 +08:00
|
|
|
"type LongTypeIsReallyUnreasonablyLong = string;\n", Style);
|
|
|
|
verifyFormat("interface AbstractStrategyFactoryProvider {\n"
|
|
|
|
" a: number\n"
|
|
|
|
"}\n",
|
|
|
|
"interface AbstractStrategyFactoryProvider { a: number }\n",
|
2017-03-13 15:10:18 +08:00
|
|
|
Style);
|
|
|
|
}
|
|
|
|
|
2017-11-18 02:06:33 +08:00
|
|
|
TEST_F(FormatTestJS, RemoveEmptyLinesInArrowFunctions) {
|
|
|
|
verifyFormat("x = () => {\n"
|
|
|
|
" foo();\n"
|
2020-01-24 18:30:31 +08:00
|
|
|
" bar();\n"
|
2017-11-18 02:06:33 +08:00
|
|
|
"};\n",
|
|
|
|
"x = () => {\n"
|
|
|
|
"\n"
|
|
|
|
" foo();\n"
|
2020-01-24 18:30:31 +08:00
|
|
|
" bar();\n"
|
2017-11-18 02:06:33 +08:00
|
|
|
"\n"
|
|
|
|
"};\n");
|
|
|
|
}
|
|
|
|
|
2015-02-20 00:07:32 +08:00
|
|
|
TEST_F(FormatTestJS, Modules) {
|
|
|
|
verifyFormat("import SomeThing from 'some/module.js';");
|
|
|
|
verifyFormat("import {X, Y} from 'some/module.js';");
|
2016-01-07 16:53:35 +08:00
|
|
|
verifyFormat("import a, {X, Y} from 'some/module.js';");
|
2016-03-22 22:32:20 +08:00
|
|
|
verifyFormat("import {X, Y,} from 'some/module.js';");
|
2015-02-20 00:07:32 +08:00
|
|
|
verifyFormat("import {X as myLocalX, Y as myLocalY} from 'some/module.js';");
|
2016-06-01 23:22:47 +08:00
|
|
|
// Ensure Automatic Semicolon Insertion does not break on "as\n".
|
|
|
|
verifyFormat("import {X as myX} from 'm';", "import {X as\n"
|
|
|
|
" myX} from 'm';");
|
2015-02-20 00:07:32 +08:00
|
|
|
verifyFormat("import * as lib from 'some/module.js';");
|
2015-03-15 21:55:54 +08:00
|
|
|
verifyFormat("var x = {import: 1};\nx.import = 2;");
|
2015-02-20 00:14:18 +08:00
|
|
|
|
|
|
|
verifyFormat("export function fn() {\n"
|
|
|
|
" return 'fn';\n"
|
|
|
|
"}");
|
2015-06-11 21:31:45 +08:00
|
|
|
verifyFormat("export function A() {}\n"
|
|
|
|
"export default function B() {}\n"
|
|
|
|
"export function C() {}");
|
2016-04-19 22:55:37 +08:00
|
|
|
verifyFormat("export default () => {\n"
|
|
|
|
" let x = 1;\n"
|
|
|
|
" return x;\n"
|
|
|
|
"}");
|
2015-02-20 00:07:32 +08:00
|
|
|
verifyFormat("export const x = 12;");
|
|
|
|
verifyFormat("export default class X {}");
|
2015-02-20 00:14:18 +08:00
|
|
|
verifyFormat("export {X, Y} from 'some/module.js';");
|
2016-03-22 22:32:20 +08:00
|
|
|
verifyFormat("export {X, Y,} from 'some/module.js';");
|
|
|
|
verifyFormat("export {SomeVeryLongExport as X, "
|
|
|
|
"SomeOtherVeryLongExport as Y} from 'some/module.js';");
|
|
|
|
// export without 'from' is wrapped.
|
|
|
|
verifyFormat("export let someRatherLongVariableName =\n"
|
|
|
|
" someSurprisinglyLongVariable + someOtherRatherLongVar;");
|
|
|
|
// ... but not if from is just an identifier.
|
2015-02-20 00:14:18 +08:00
|
|
|
verifyFormat("export {\n"
|
2016-03-22 22:32:20 +08:00
|
|
|
" from as from,\n"
|
2016-06-22 22:35:14 +08:00
|
|
|
" someSurprisinglyLongVariable as\n"
|
|
|
|
" from\n"
|
2016-03-22 22:32:20 +08:00
|
|
|
"};",
|
|
|
|
getGoogleJSStyleWithColumns(20));
|
2015-02-20 00:14:18 +08:00
|
|
|
verifyFormat("export class C {\n"
|
|
|
|
" x: number;\n"
|
|
|
|
" y: string;\n"
|
|
|
|
"}");
|
2017-11-25 17:35:33 +08:00
|
|
|
verifyFormat("export class X {\n"
|
|
|
|
" y: number;\n"
|
|
|
|
"}");
|
|
|
|
verifyFormat("export abstract class X {\n"
|
|
|
|
" y: number;\n"
|
|
|
|
"}");
|
|
|
|
verifyFormat("export default class X {\n"
|
|
|
|
" y: number\n"
|
|
|
|
"}");
|
2015-02-20 00:14:18 +08:00
|
|
|
verifyFormat("export default function() {\n return 1;\n}");
|
|
|
|
verifyFormat("export var x = 12;");
|
2015-06-12 12:52:02 +08:00
|
|
|
verifyFormat("class C {}\n"
|
|
|
|
"export function f() {}\n"
|
|
|
|
"var v;");
|
2015-02-20 00:14:18 +08:00
|
|
|
verifyFormat("export var x: number = 12;");
|
|
|
|
verifyFormat("export const y = {\n"
|
|
|
|
" a: 1,\n"
|
|
|
|
" b: 2\n"
|
|
|
|
"};");
|
2015-06-12 13:08:18 +08:00
|
|
|
verifyFormat("export enum Foo {\n"
|
|
|
|
" BAR,\n"
|
|
|
|
" // adsdasd\n"
|
|
|
|
" BAZ\n"
|
|
|
|
"}");
|
2016-01-04 23:51:56 +08:00
|
|
|
verifyFormat("export default [\n"
|
|
|
|
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
|
|
|
|
" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n"
|
|
|
|
"];");
|
|
|
|
verifyFormat("export default [];");
|
2016-01-05 00:10:36 +08:00
|
|
|
verifyFormat("export default () => {};");
|
2020-01-24 18:30:31 +08:00
|
|
|
verifyFormat("export default () => {\n"
|
|
|
|
" x;\n"
|
|
|
|
" x;\n"
|
|
|
|
"};");
|
2017-11-25 17:35:33 +08:00
|
|
|
verifyFormat("export interface Foo {\n"
|
|
|
|
" foo: number;\n"
|
|
|
|
"}\n"
|
2016-01-12 06:57:40 +08:00
|
|
|
"export class Bar {\n"
|
2016-09-08 07:01:13 +08:00
|
|
|
" blah(): string {\n"
|
|
|
|
" return this.blah;\n"
|
|
|
|
" };\n"
|
2016-01-12 06:57:40 +08:00
|
|
|
"}");
|
2015-02-20 00:07:32 +08:00
|
|
|
}
|
|
|
|
|
2016-06-14 00:39:50 +08:00
|
|
|
TEST_F(FormatTestJS, ImportWrapping) {
|
|
|
|
verifyFormat("import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,"
|
|
|
|
" VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying"
|
|
|
|
"} from 'some/module.js';");
|
|
|
|
FormatStyle Style = getGoogleJSStyleWithColumns(80);
|
|
|
|
Style.JavaScriptWrapImports = true;
|
|
|
|
verifyFormat("import {\n"
|
|
|
|
" VeryLongImportsAreAnnoying,\n"
|
|
|
|
" VeryLongImportsAreAnnoying,\n"
|
|
|
|
" VeryLongImportsAreAnnoying,\n"
|
|
|
|
"} from 'some/module.js';",
|
|
|
|
Style);
|
|
|
|
verifyFormat("import {\n"
|
|
|
|
" A,\n"
|
|
|
|
" A,\n"
|
|
|
|
"} from 'some/module.js';",
|
|
|
|
Style);
|
|
|
|
verifyFormat("export {\n"
|
|
|
|
" A,\n"
|
|
|
|
" A,\n"
|
|
|
|
"} from 'some/module.js';",
|
|
|
|
Style);
|
2017-07-18 22:00:19 +08:00
|
|
|
Style.ColumnLimit = 40;
|
|
|
|
// Using this version of verifyFormat because test::messUp hides the issue.
|
|
|
|
verifyFormat("import {\n"
|
|
|
|
" A,\n"
|
|
|
|
"} from\n"
|
|
|
|
" 'some/path/longer/than/column/limit/module.js';",
|
|
|
|
" import { \n"
|
|
|
|
" A, \n"
|
|
|
|
" } from\n"
|
|
|
|
" 'some/path/longer/than/column/limit/module.js' ; ",
|
|
|
|
Style);
|
2016-06-14 00:39:50 +08:00
|
|
|
}
|
|
|
|
|
2015-02-20 21:47:38 +08:00
|
|
|
TEST_F(FormatTestJS, TemplateStrings) {
|
|
|
|
// Keeps any whitespace/indentation within the template string.
|
2016-03-15 03:21:36 +08:00
|
|
|
verifyFormat("var x = `hello\n"
|
2020-05-02 22:42:20 +08:00
|
|
|
" ${name}\n"
|
|
|
|
" !`;",
|
|
|
|
"var x = `hello\n"
|
|
|
|
" ${ name }\n"
|
|
|
|
" !`;");
|
2015-02-20 21:47:38 +08:00
|
|
|
|
|
|
|
verifyFormat("var x =\n"
|
|
|
|
" `hello ${world}` >= some();",
|
|
|
|
getGoogleJSStyleWithColumns(34)); // Barely doesn't fit.
|
|
|
|
verifyFormat("var x = `hello ${world}` >= some();",
|
2015-07-02 21:08:28 +08:00
|
|
|
getGoogleJSStyleWithColumns(35)); // Barely fits.
|
2016-05-17 14:29:29 +08:00
|
|
|
verifyFormat("var x = `hellö ${wörld}` >= söme();",
|
|
|
|
getGoogleJSStyleWithColumns(35)); // Fits due to UTF-8.
|
2016-03-15 03:21:36 +08:00
|
|
|
verifyFormat("var x = `hello\n"
|
2020-05-02 22:42:20 +08:00
|
|
|
" ${world}` >=\n"
|
|
|
|
" some();",
|
|
|
|
"var x =\n"
|
|
|
|
" `hello\n"
|
|
|
|
" ${world}` >= some();",
|
|
|
|
getGoogleJSStyleWithColumns(21)); // Barely doesn't fit.
|
2016-03-15 03:21:36 +08:00
|
|
|
verifyFormat("var x = `hello\n"
|
2020-05-02 22:42:20 +08:00
|
|
|
" ${world}` >= some();",
|
|
|
|
"var x =\n"
|
|
|
|
" `hello\n"
|
|
|
|
" ${world}` >= some();",
|
|
|
|
getGoogleJSStyleWithColumns(22)); // Barely fits.
|
2015-02-20 21:47:38 +08:00
|
|
|
|
2015-07-02 21:08:28 +08:00
|
|
|
verifyFormat("var x =\n"
|
|
|
|
" `h`;",
|
|
|
|
getGoogleJSStyleWithColumns(11));
|
2016-03-15 03:21:36 +08:00
|
|
|
verifyFormat("var x =\n `multi\n line`;", "var x = `multi\n line`;",
|
|
|
|
getGoogleJSStyleWithColumns(13));
|
2015-07-02 21:08:28 +08:00
|
|
|
verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
|
|
|
|
" `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`);");
|
2016-05-17 14:29:29 +08:00
|
|
|
// Repro for an obscure width-miscounting issue with template strings.
|
|
|
|
verifyFormat(
|
|
|
|
"someLongVariable =\n"
|
|
|
|
" "
|
|
|
|
"`${logPrefix[11]}/${logPrefix[12]}/${logPrefix[13]}${logPrefix[14]}`;",
|
|
|
|
"someLongVariable = "
|
|
|
|
"`${logPrefix[11]}/${logPrefix[12]}/${logPrefix[13]}${logPrefix[14]}`;");
|
2015-02-20 21:47:38 +08:00
|
|
|
|
2015-05-02 16:05:38 +08:00
|
|
|
// Make sure template strings get a proper ColumnWidth assigned, even if they
|
|
|
|
// are first token in line.
|
2020-05-02 22:42:20 +08:00
|
|
|
verifyFormat("var a = aaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n"
|
|
|
|
" `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`;");
|
2015-05-02 16:05:38 +08:00
|
|
|
|
2015-02-20 21:47:38 +08:00
|
|
|
// Two template strings.
|
|
|
|
verifyFormat("var x = `hello` == `hello`;");
|
2015-04-16 16:20:51 +08:00
|
|
|
|
|
|
|
// Comments in template strings.
|
2016-03-15 03:21:36 +08:00
|
|
|
verifyFormat("var x = `//a`;\n"
|
2020-05-02 22:42:20 +08:00
|
|
|
"var y;",
|
|
|
|
"var x =\n `//a`;\n"
|
|
|
|
"var y ;");
|
2016-03-15 03:21:36 +08:00
|
|
|
verifyFormat("var x = `/*a`;\n"
|
|
|
|
"var y;",
|
|
|
|
"var x =\n `/*a`;\n"
|
|
|
|
"var y;");
|
2015-06-14 15:16:57 +08:00
|
|
|
// Unterminated string literals in a template string.
|
|
|
|
verifyFormat("var x = `'`; // comment with matching quote '\n"
|
|
|
|
"var y;");
|
|
|
|
verifyFormat("var x = `\"`; // comment with matching quote \"\n"
|
|
|
|
"var y;");
|
2016-03-15 03:21:36 +08:00
|
|
|
verifyFormat("it(`'aaaaaaaaaaaaaaa `, aaaaaaaaa);",
|
|
|
|
"it(`'aaaaaaaaaaaaaaa `, aaaaaaaaa) ;",
|
|
|
|
getGoogleJSStyleWithColumns(40));
|
2015-04-16 16:20:51 +08:00
|
|
|
// Backticks in a comment - not a template string.
|
2016-03-15 03:21:36 +08:00
|
|
|
verifyFormat("var x = 1 // `/*a`;\n"
|
|
|
|
" ;",
|
|
|
|
"var x =\n 1 // `/*a`;\n"
|
|
|
|
" ;");
|
|
|
|
verifyFormat("/* ` */ var x = 1; /* ` */", "/* ` */ var x\n= 1; /* ` */");
|
2015-04-16 16:20:51 +08:00
|
|
|
// Comment spans multiple template strings.
|
2016-03-15 03:21:36 +08:00
|
|
|
verifyFormat("var x = `/*a`;\n"
|
|
|
|
"var y = ` */ `;",
|
|
|
|
"var x =\n `/*a`;\n"
|
|
|
|
"var y =\n ` */ `;");
|
2015-04-16 16:20:51 +08:00
|
|
|
// Escaped backtick.
|
2016-03-15 03:21:36 +08:00
|
|
|
verifyFormat("var x = ` \\` a`;\n"
|
|
|
|
"var y;",
|
|
|
|
"var x = ` \\` a`;\n"
|
|
|
|
"var y;");
|
2016-08-25 18:13:21 +08:00
|
|
|
// Escaped dollar.
|
|
|
|
verifyFormat("var x = ` \\${foo}`;\n");
|
2017-01-31 20:07:35 +08:00
|
|
|
|
|
|
|
// The token stream can contain two string_literals in sequence, but that
|
|
|
|
// doesn't mean that they are implicitly concatenated in JavaScript.
|
|
|
|
verifyFormat("var f = `aaaa ${a ? 'a' : 'b'}`;");
|
2017-01-31 21:03:07 +08:00
|
|
|
|
|
|
|
// Ensure that scopes are appropriately set around evaluated expressions in
|
|
|
|
// template strings.
|
|
|
|
verifyFormat("var f = `aaaaaaaaaaaaa:${aaaaaaa.aaaaa} aaaaaaaa\n"
|
|
|
|
" aaaaaaaaaaaaa:${aaaaaaa.aaaaa} aaaaaaaa`;",
|
|
|
|
"var f = `aaaaaaaaaaaaa:${aaaaaaa. aaaaa} aaaaaaaa\n"
|
|
|
|
" aaaaaaaaaaaaa:${ aaaaaaa. aaaaa} aaaaaaaa`;");
|
2017-02-03 22:32:38 +08:00
|
|
|
verifyFormat("var x = someFunction(`${})`) //\n"
|
|
|
|
" .oooooooooooooooooon();");
|
2017-02-20 22:51:16 +08:00
|
|
|
verifyFormat("var x = someFunction(`${aaaa}${\n"
|
clang-format: [JS] simplify template string wrapping.
Summary:
Previously, clang-format would try to wrap template string substitutions
by indenting relative to the openening `${`. This helped with
indenting structured strings, such as strings containing HTML, as the
substitutions would be aligned according to the structure of the string.
However it turns out that the overwhelming majority of template string +
substitution usages are for substitutions into non-structured strings,
e.g. URLs or just plain messages. For these situations, clang-format
would often produce very ugly indents, in particular for strings
containing no line breaks:
return `<a href='http://google3/${file}?l=${row}'>${file}</a>(${
row
},${
col
}): `;
This change makes clang-format indent template string substitutions as
if they were string concatenation operations. It wraps +4 on overlong
lines and keeps all operands on the same line:
return `<a href='http://google3/${file}?l=${row}'>${file}</a>(${
row},${col}): `;
While this breaks some lexical continuity between the `${` and `row}`
here, the overall effects are still a huge improvement, and users can
still manually break the string using `+` if desired.
Reviewers: djasper
Subscribers: klimek, cfe-commits
Differential Revision: https://reviews.llvm.org/D37142
llvm-svn: 311988
2017-08-29 16:30:07 +08:00
|
|
|
" aaaaa( //\n"
|
|
|
|
" aaaaa)})`);");
|
2016-08-25 18:13:21 +08:00
|
|
|
}
|
|
|
|
|
2017-01-31 22:39:33 +08:00
|
|
|
TEST_F(FormatTestJS, TemplateStringMultiLineExpression) {
|
2017-02-20 22:51:16 +08:00
|
|
|
verifyFormat("var f = `aaaaaaaaaaaaaaaaaa: ${\n"
|
clang-format: [JS] simplify template string wrapping.
Summary:
Previously, clang-format would try to wrap template string substitutions
by indenting relative to the openening `${`. This helped with
indenting structured strings, such as strings containing HTML, as the
substitutions would be aligned according to the structure of the string.
However it turns out that the overwhelming majority of template string +
substitution usages are for substitutions into non-structured strings,
e.g. URLs or just plain messages. For these situations, clang-format
would often produce very ugly indents, in particular for strings
containing no line breaks:
return `<a href='http://google3/${file}?l=${row}'>${file}</a>(${
row
},${
col
}): `;
This change makes clang-format indent template string substitutions as
if they were string concatenation operations. It wraps +4 on overlong
lines and keeps all operands on the same line:
return `<a href='http://google3/${file}?l=${row}'>${file}</a>(${
row},${col}): `;
While this breaks some lexical continuity between the `${` and `row}`
here, the overall effects are still a huge improvement, and users can
still manually break the string using `+` if desired.
Reviewers: djasper
Subscribers: klimek, cfe-commits
Differential Revision: https://reviews.llvm.org/D37142
llvm-svn: 311988
2017-08-29 16:30:07 +08:00
|
|
|
" aaaaa + //\n"
|
|
|
|
" bbbb}`;",
|
2017-02-20 22:51:16 +08:00
|
|
|
"var f = `aaaaaaaaaaaaaaaaaa: ${aaaaa + //\n"
|
2017-01-31 22:39:33 +08:00
|
|
|
" bbbb}`;");
|
|
|
|
verifyFormat("var f = `\n"
|
2017-02-20 22:51:16 +08:00
|
|
|
" aaaaaaaaaaaaaaaaaa: ${\n"
|
clang-format: [JS] simplify template string wrapping.
Summary:
Previously, clang-format would try to wrap template string substitutions
by indenting relative to the openening `${`. This helped with
indenting structured strings, such as strings containing HTML, as the
substitutions would be aligned according to the structure of the string.
However it turns out that the overwhelming majority of template string +
substitution usages are for substitutions into non-structured strings,
e.g. URLs or just plain messages. For these situations, clang-format
would often produce very ugly indents, in particular for strings
containing no line breaks:
return `<a href='http://google3/${file}?l=${row}'>${file}</a>(${
row
},${
col
}): `;
This change makes clang-format indent template string substitutions as
if they were string concatenation operations. It wraps +4 on overlong
lines and keeps all operands on the same line:
return `<a href='http://google3/${file}?l=${row}'>${file}</a>(${
row},${col}): `;
While this breaks some lexical continuity between the `${` and `row}`
here, the overall effects are still a huge improvement, and users can
still manually break the string using `+` if desired.
Reviewers: djasper
Subscribers: klimek, cfe-commits
Differential Revision: https://reviews.llvm.org/D37142
llvm-svn: 311988
2017-08-29 16:30:07 +08:00
|
|
|
" aaaaa + //\n"
|
|
|
|
" bbbb}`;",
|
2017-01-31 22:39:33 +08:00
|
|
|
"var f = `\n"
|
|
|
|
" aaaaaaaaaaaaaaaaaa: ${ aaaaa + //\n"
|
|
|
|
" bbbb }`;");
|
|
|
|
verifyFormat("var f = `\n"
|
2017-02-20 22:51:16 +08:00
|
|
|
" aaaaaaaaaaaaaaaaaa: ${\n"
|
clang-format: [JS] simplify template string wrapping.
Summary:
Previously, clang-format would try to wrap template string substitutions
by indenting relative to the openening `${`. This helped with
indenting structured strings, such as strings containing HTML, as the
substitutions would be aligned according to the structure of the string.
However it turns out that the overwhelming majority of template string +
substitution usages are for substitutions into non-structured strings,
e.g. URLs or just plain messages. For these situations, clang-format
would often produce very ugly indents, in particular for strings
containing no line breaks:
return `<a href='http://google3/${file}?l=${row}'>${file}</a>(${
row
},${
col
}): `;
This change makes clang-format indent template string substitutions as
if they were string concatenation operations. It wraps +4 on overlong
lines and keeps all operands on the same line:
return `<a href='http://google3/${file}?l=${row}'>${file}</a>(${
row},${col}): `;
While this breaks some lexical continuity between the `${` and `row}`
here, the overall effects are still a huge improvement, and users can
still manually break the string using `+` if desired.
Reviewers: djasper
Subscribers: klimek, cfe-commits
Differential Revision: https://reviews.llvm.org/D37142
llvm-svn: 311988
2017-08-29 16:30:07 +08:00
|
|
|
" someFunction(\n"
|
|
|
|
" aaaaa + //\n"
|
|
|
|
" bbbb)}`;",
|
2017-01-31 22:39:33 +08:00
|
|
|
"var f = `\n"
|
2017-02-20 22:51:16 +08:00
|
|
|
" aaaaaaaaaaaaaaaaaa: ${someFunction (\n"
|
2017-01-31 22:39:33 +08:00
|
|
|
" aaaaa + //\n"
|
|
|
|
" bbbb)}`;");
|
2017-02-20 22:51:16 +08:00
|
|
|
|
|
|
|
// It might be preferable to wrap before "someFunction".
|
2017-01-31 22:39:33 +08:00
|
|
|
verifyFormat("var f = `\n"
|
2017-02-20 22:51:16 +08:00
|
|
|
" aaaaaaaaaaaaaaaaaa: ${someFunction({\n"
|
clang-format: [JS] simplify template string wrapping.
Summary:
Previously, clang-format would try to wrap template string substitutions
by indenting relative to the openening `${`. This helped with
indenting structured strings, such as strings containing HTML, as the
substitutions would be aligned according to the structure of the string.
However it turns out that the overwhelming majority of template string +
substitution usages are for substitutions into non-structured strings,
e.g. URLs or just plain messages. For these situations, clang-format
would often produce very ugly indents, in particular for strings
containing no line breaks:
return `<a href='http://google3/${file}?l=${row}'>${file}</a>(${
row
},${
col
}): `;
This change makes clang-format indent template string substitutions as
if they were string concatenation operations. It wraps +4 on overlong
lines and keeps all operands on the same line:
return `<a href='http://google3/${file}?l=${row}'>${file}</a>(${
row},${col}): `;
While this breaks some lexical continuity between the `${` and `row}`
here, the overall effects are still a huge improvement, and users can
still manually break the string using `+` if desired.
Reviewers: djasper
Subscribers: klimek, cfe-commits
Differential Revision: https://reviews.llvm.org/D37142
llvm-svn: 311988
2017-08-29 16:30:07 +08:00
|
|
|
" aaaa: aaaaa,\n"
|
|
|
|
" bbbb: bbbbb,\n"
|
|
|
|
"})}`;",
|
2017-01-31 22:39:33 +08:00
|
|
|
"var f = `\n"
|
2017-02-20 22:51:16 +08:00
|
|
|
" aaaaaaaaaaaaaaaaaa: ${someFunction ({\n"
|
2017-01-31 22:39:33 +08:00
|
|
|
" aaaa: aaaaa,\n"
|
|
|
|
" bbbb: bbbbb,\n"
|
|
|
|
" })}`;");
|
|
|
|
}
|
|
|
|
|
2016-10-21 13:11:38 +08:00
|
|
|
TEST_F(FormatTestJS, TemplateStringASI) {
|
|
|
|
verifyFormat("var x = `hello${world}`;", "var x = `hello${\n"
|
|
|
|
" world\n"
|
|
|
|
"}`;");
|
|
|
|
}
|
|
|
|
|
2016-08-25 18:13:21 +08:00
|
|
|
TEST_F(FormatTestJS, NestedTemplateStrings) {
|
|
|
|
verifyFormat(
|
|
|
|
"var x = `<ul>${xs.map(x => `<li>${x}</li>`).join('\\n')}</ul>`;");
|
|
|
|
verifyFormat("var x = `he${({text: 'll'}.text)}o`;");
|
2016-09-17 15:20:36 +08:00
|
|
|
|
|
|
|
// Crashed at some point.
|
|
|
|
verifyFormat("}");
|
2016-08-25 18:13:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(FormatTestJS, TaggedTemplateStrings) {
|
|
|
|
verifyFormat("var x = html`<ul>`;");
|
2017-07-04 23:30:21 +08:00
|
|
|
verifyFormat("yield `hello`;");
|
2019-03-19 19:15:52 +08:00
|
|
|
verifyFormat("var f = {\n"
|
|
|
|
" param: longTagName`This is a ${\n"
|
|
|
|
" 'really'} long line`\n"
|
|
|
|
"};",
|
|
|
|
"var f = {param: longTagName`This is a ${'really'} long line`};",
|
|
|
|
getGoogleJSStyleWithColumns(40));
|
2015-02-20 21:47:38 +08:00
|
|
|
}
|
|
|
|
|
2016-04-19 22:59:16 +08:00
|
|
|
TEST_F(FormatTestJS, CastSyntax) {
|
|
|
|
verifyFormat("var x = <type>foo;");
|
|
|
|
verifyFormat("var x = foo as type;");
|
2016-06-22 22:35:14 +08:00
|
|
|
verifyFormat("let x = (a + b) as\n"
|
|
|
|
" LongTypeIsLong;",
|
|
|
|
getGoogleJSStyleWithColumns(20));
|
2016-06-14 21:54:38 +08:00
|
|
|
verifyFormat("foo = <Bar[]>[\n"
|
|
|
|
" 1, //\n"
|
|
|
|
" 2\n"
|
|
|
|
"];");
|
2016-08-19 22:35:01 +08:00
|
|
|
verifyFormat("var x = [{x: 1} as type];");
|
2016-08-22 22:23:30 +08:00
|
|
|
verifyFormat("x = x as [a, b];");
|
|
|
|
verifyFormat("x = x as {a: string};");
|
|
|
|
verifyFormat("x = x as (string);");
|
2016-09-07 02:55:34 +08:00
|
|
|
verifyFormat("x = x! as (string);");
|
2017-11-25 01:04:40 +08:00
|
|
|
verifyFormat("x = y! in z;");
|
2017-03-02 03:26:12 +08:00
|
|
|
verifyFormat("var x = something.someFunction() as\n"
|
|
|
|
" something;",
|
|
|
|
getGoogleJSStyleWithColumns(40));
|
2016-04-19 22:59:16 +08:00
|
|
|
}
|
2015-03-15 21:59:51 +08:00
|
|
|
|
|
|
|
TEST_F(FormatTestJS, TypeArguments) {
|
|
|
|
verifyFormat("class X<Y> {}");
|
|
|
|
verifyFormat("new X<Y>();");
|
|
|
|
verifyFormat("foo<Y>(a);");
|
|
|
|
verifyFormat("var x: X<Y>[];");
|
|
|
|
verifyFormat("class C extends D<E> implements F<G>, H<I> {}");
|
2015-06-11 21:31:45 +08:00
|
|
|
verifyFormat("function f(a: List<any> = null) {}");
|
|
|
|
verifyFormat("function f(): List<any> {}");
|
2015-07-03 18:37:23 +08:00
|
|
|
verifyFormat("function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa():\n"
|
|
|
|
" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {}");
|
2015-10-27 20:38:37 +08:00
|
|
|
verifyFormat("function aaaaaaaaaa(\n"
|
|
|
|
" aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaa,\n"
|
|
|
|
" aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaa):\n"
|
2015-07-06 22:07:51 +08:00
|
|
|
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {}");
|
2015-03-15 21:59:51 +08:00
|
|
|
}
|
|
|
|
|
2015-12-30 16:00:58 +08:00
|
|
|
TEST_F(FormatTestJS, UserDefinedTypeGuards) {
|
|
|
|
verifyFormat(
|
|
|
|
"function foo(check: Object):\n"
|
|
|
|
" check is {foo: string, bar: string, baz: string, foobar: string} {\n"
|
|
|
|
" return 'bar' in check;\n"
|
|
|
|
"}\n");
|
|
|
|
}
|
|
|
|
|
2015-04-13 23:01:40 +08:00
|
|
|
TEST_F(FormatTestJS, OptionalTypes) {
|
2015-06-11 21:31:45 +08:00
|
|
|
verifyFormat("function x(a?: b, c?, d?) {}");
|
2015-04-13 23:01:40 +08:00
|
|
|
verifyFormat("class X {\n"
|
|
|
|
" y?: z;\n"
|
|
|
|
" z?;\n"
|
|
|
|
"}");
|
2015-05-05 16:40:32 +08:00
|
|
|
verifyFormat("interface X {\n"
|
|
|
|
" y?(): z;\n"
|
|
|
|
"}");
|
2015-05-27 13:37:40 +08:00
|
|
|
verifyFormat("constructor({aa}: {\n"
|
|
|
|
" aa?: string,\n"
|
|
|
|
" aaaaaaaa?: string,\n"
|
|
|
|
" aaaaaaaaaaaaaaa?: boolean,\n"
|
|
|
|
" aaaaaa?: List<string>\n"
|
2015-06-11 21:31:45 +08:00
|
|
|
"}) {}");
|
2015-04-13 23:01:40 +08:00
|
|
|
}
|
|
|
|
|
2015-04-13 23:03:30 +08:00
|
|
|
TEST_F(FormatTestJS, IndexSignature) {
|
|
|
|
verifyFormat("var x: {[k: string]: v};");
|
|
|
|
}
|
|
|
|
|
2015-10-27 20:38:37 +08:00
|
|
|
TEST_F(FormatTestJS, WrapAfterParen) {
|
|
|
|
verifyFormat("xxxxxxxxxxx(\n"
|
|
|
|
" aaa, aaa);",
|
|
|
|
getGoogleJSStyleWithColumns(20));
|
|
|
|
verifyFormat("xxxxxxxxxxx(\n"
|
|
|
|
" aaa, aaa, aaa,\n"
|
|
|
|
" aaa, aaa, aaa);",
|
|
|
|
getGoogleJSStyleWithColumns(20));
|
|
|
|
verifyFormat("xxxxxxxxxxx(\n"
|
|
|
|
" aaaaaaaaaaaaaaaaaaaaaaaa,\n"
|
|
|
|
" function(x) {\n"
|
|
|
|
" y(); //\n"
|
|
|
|
" });",
|
|
|
|
getGoogleJSStyleWithColumns(40));
|
|
|
|
verifyFormat("while (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n"
|
|
|
|
" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n}");
|
|
|
|
}
|
|
|
|
|
2016-01-08 16:14:58 +08:00
|
|
|
TEST_F(FormatTestJS, JSDocAnnotations) {
|
2016-03-15 03:21:36 +08:00
|
|
|
verifyFormat("/**\n"
|
2018-08-02 19:52:08 +08:00
|
|
|
" * @exports {this.is.a.long.path.to.a.Type}\n"
|
2016-03-15 03:21:36 +08:00
|
|
|
" */",
|
|
|
|
"/**\n"
|
2018-07-30 16:45:45 +08:00
|
|
|
" * @exports {this.is.a.long.path.to.a.Type}\n"
|
2016-03-15 03:21:36 +08:00
|
|
|
" */",
|
|
|
|
getGoogleJSStyleWithColumns(20));
|
2017-02-28 19:08:24 +08:00
|
|
|
verifyFormat("/**\n"
|
2018-08-02 19:52:08 +08:00
|
|
|
" * @mods {this.is.a.long.path.to.a.Type}\n"
|
|
|
|
" */",
|
|
|
|
"/**\n"
|
|
|
|
" * @mods {this.is.a.long.path.to.a.Type}\n"
|
|
|
|
" */",
|
|
|
|
getGoogleJSStyleWithColumns(20));
|
|
|
|
verifyFormat("/**\n"
|
|
|
|
" * @mods {this.is.a.long.path.to.a.Type}\n"
|
2017-02-28 19:08:24 +08:00
|
|
|
" */",
|
|
|
|
"/**\n"
|
|
|
|
" * @mods {this.is.a.long.path.to.a.Type}\n"
|
|
|
|
" */",
|
|
|
|
getGoogleJSStyleWithColumns(20));
|
|
|
|
verifyFormat("/**\n"
|
2018-08-02 19:52:08 +08:00
|
|
|
" * @param {canWrap\n"
|
|
|
|
" * onSpace}\n"
|
2017-02-28 19:08:24 +08:00
|
|
|
" */",
|
|
|
|
"/**\n"
|
2018-08-02 19:52:08 +08:00
|
|
|
" * @param {canWrap onSpace}\n"
|
2017-02-28 19:08:24 +08:00
|
|
|
" */",
|
|
|
|
getGoogleJSStyleWithColumns(20));
|
2018-08-03 21:58:33 +08:00
|
|
|
// make sure clang-format doesn't break before *any* '{'
|
|
|
|
verifyFormat("/**\n"
|
|
|
|
" * @lala {lala {lalala\n"
|
|
|
|
" */\n",
|
|
|
|
"/**\n"
|
|
|
|
" * @lala {lala {lalala\n"
|
|
|
|
" */\n",
|
|
|
|
getGoogleJSStyleWithColumns(20));
|
2020-11-06 17:33:23 +08:00
|
|
|
// cases where '{' is around the column limit
|
|
|
|
for (int ColumnLimit = 6; ColumnLimit < 13; ++ColumnLimit) {
|
|
|
|
verifyFormat("/**\n"
|
|
|
|
" * @param {type}\n"
|
|
|
|
" */",
|
|
|
|
"/**\n"
|
|
|
|
" * @param {type}\n"
|
|
|
|
" */",
|
|
|
|
getGoogleJSStyleWithColumns(ColumnLimit));
|
|
|
|
}
|
2020-11-11 19:07:30 +08:00
|
|
|
// don't break before @tags
|
|
|
|
verifyFormat("/**\n"
|
|
|
|
" * This\n"
|
|
|
|
" * tag @param\n"
|
|
|
|
" * stays.\n"
|
|
|
|
" */",
|
|
|
|
"/**\n"
|
|
|
|
" * This tag @param stays.\n"
|
|
|
|
" */",
|
|
|
|
getGoogleJSStyleWithColumns(13));
|
2017-03-13 17:39:23 +08:00
|
|
|
verifyFormat("/**\n"
|
|
|
|
" * @see http://very/very/long/url/is/long\n"
|
|
|
|
" */",
|
|
|
|
"/**\n"
|
|
|
|
" * @see http://very/very/long/url/is/long\n"
|
|
|
|
" */",
|
|
|
|
getGoogleJSStyleWithColumns(20));
|
2020-05-02 22:42:20 +08:00
|
|
|
verifyFormat("/**\n"
|
|
|
|
" * @param This is a\n"
|
|
|
|
" * long comment\n"
|
|
|
|
" * but no type\n"
|
|
|
|
" */",
|
|
|
|
"/**\n"
|
|
|
|
" * @param This is a long comment but no type\n"
|
|
|
|
" */",
|
|
|
|
getGoogleJSStyleWithColumns(20));
|
2018-07-30 16:45:45 +08:00
|
|
|
// Break and reindent @param line and reflow unrelated lines.
|
|
|
|
EXPECT_EQ("{\n"
|
|
|
|
" /**\n"
|
|
|
|
" * long long long\n"
|
|
|
|
" * long\n"
|
2018-08-02 19:52:08 +08:00
|
|
|
" * @param {this.is.a.long.path.to.a.Type}\n"
|
2018-07-30 16:45:45 +08:00
|
|
|
" * a\n"
|
|
|
|
" * long long long\n"
|
|
|
|
" * long long\n"
|
|
|
|
" */\n"
|
|
|
|
" function f(a) {}\n"
|
|
|
|
"}",
|
|
|
|
format("{\n"
|
|
|
|
"/**\n"
|
|
|
|
" * long long long long\n"
|
|
|
|
" * @param {this.is.a.long.path.to.a.Type} a\n"
|
|
|
|
" * long long long long\n"
|
|
|
|
" * long\n"
|
|
|
|
" */\n"
|
|
|
|
" function f(a) {}\n"
|
|
|
|
"}",
|
|
|
|
getGoogleJSStyleWithColumns(20)));
|
2016-01-08 16:14:58 +08:00
|
|
|
}
|
|
|
|
|
2020-01-17 17:44:10 +08:00
|
|
|
TEST_F(FormatTestJS, TslintComments) {
|
|
|
|
// tslint uses pragma comments that must be on their own line.
|
|
|
|
verifyFormat("// Comment that needs wrapping. Comment that needs wrapping. "
|
|
|
|
"Comment that needs\n"
|
|
|
|
"// wrapping. Trailing line.\n"
|
|
|
|
"// tslint:disable-next-line:must-be-on-own-line",
|
|
|
|
"// Comment that needs wrapping. Comment that needs wrapping. "
|
|
|
|
"Comment that needs wrapping.\n"
|
|
|
|
"// Trailing line.\n"
|
|
|
|
"// tslint:disable-next-line:must-be-on-own-line");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(FormatTestJS, TscComments) {
|
|
|
|
// As above, @ts-ignore and @ts-check comments must be on their own line.
|
|
|
|
verifyFormat("// Comment that needs wrapping. Comment that needs wrapping. "
|
|
|
|
"Comment that needs\n"
|
|
|
|
"// wrapping. Trailing line.\n"
|
|
|
|
"// @ts-ignore",
|
|
|
|
"// Comment that needs wrapping. Comment that needs wrapping. "
|
|
|
|
"Comment that needs wrapping.\n"
|
|
|
|
"// Trailing line.\n"
|
|
|
|
"// @ts-ignore");
|
|
|
|
verifyFormat("// Comment that needs wrapping. Comment that needs wrapping. "
|
|
|
|
"Comment that needs\n"
|
|
|
|
"// wrapping. Trailing line.\n"
|
|
|
|
"// @ts-check",
|
|
|
|
"// Comment that needs wrapping. Comment that needs wrapping. "
|
|
|
|
"Comment that needs wrapping.\n"
|
|
|
|
"// Trailing line.\n"
|
|
|
|
"// @ts-check");
|
|
|
|
}
|
|
|
|
|
2016-03-03 06:44:03 +08:00
|
|
|
TEST_F(FormatTestJS, RequoteStringsSingle) {
|
2016-03-15 03:21:36 +08:00
|
|
|
verifyFormat("var x = 'foo';", "var x = \"foo\";");
|
|
|
|
verifyFormat("var x = 'fo\\'o\\'';", "var x = \"fo'o'\";");
|
|
|
|
verifyFormat("var x = 'fo\\'o\\'';", "var x = \"fo\\'o'\";");
|
2020-05-02 22:42:20 +08:00
|
|
|
verifyFormat("var x =\n"
|
|
|
|
" 'foo\\'';",
|
|
|
|
// Code below is 15 chars wide, doesn't fit into the line with
|
|
|
|
// the \ escape added.
|
|
|
|
"var x = \"foo'\";", getGoogleJSStyleWithColumns(15));
|
2016-03-03 06:44:03 +08:00
|
|
|
// Removes no-longer needed \ escape from ".
|
2016-03-15 03:21:36 +08:00
|
|
|
verifyFormat("var x = 'fo\"o';", "var x = \"fo\\\"o\";");
|
2016-03-03 06:44:03 +08:00
|
|
|
// Code below fits into 15 chars *after* removing the \ escape.
|
2016-03-15 03:21:36 +08:00
|
|
|
verifyFormat("var x = 'fo\"o';", "var x = \"fo\\\"o\";",
|
|
|
|
getGoogleJSStyleWithColumns(15));
|
2016-05-12 19:20:32 +08:00
|
|
|
verifyFormat("// clang-format off\n"
|
|
|
|
"let x = \"double\";\n"
|
|
|
|
"// clang-format on\n"
|
|
|
|
"let x = 'single';\n",
|
|
|
|
"// clang-format off\n"
|
|
|
|
"let x = \"double\";\n"
|
|
|
|
"// clang-format on\n"
|
|
|
|
"let x = \"single\";\n");
|
2016-03-03 06:44:03 +08:00
|
|
|
}
|
|
|
|
|
2016-09-02 22:29:48 +08:00
|
|
|
TEST_F(FormatTestJS, RequoteAndIndent) {
|
|
|
|
verifyFormat("let x = someVeryLongFunctionThatGoesOnAndOn(\n"
|
|
|
|
" 'double quoted string that needs wrapping');",
|
|
|
|
"let x = someVeryLongFunctionThatGoesOnAndOn("
|
|
|
|
"\"double quoted string that needs wrapping\");");
|
2016-09-08 06:48:53 +08:00
|
|
|
|
|
|
|
verifyFormat("let x =\n"
|
|
|
|
" 'foo\\'oo';\n"
|
|
|
|
"let x =\n"
|
|
|
|
" 'foo\\'oo';",
|
|
|
|
"let x=\"foo'oo\";\n"
|
|
|
|
"let x=\"foo'oo\";",
|
|
|
|
getGoogleJSStyleWithColumns(15));
|
2016-09-02 22:29:48 +08:00
|
|
|
}
|
|
|
|
|
2016-03-03 06:44:03 +08:00
|
|
|
TEST_F(FormatTestJS, RequoteStringsDouble) {
|
|
|
|
FormatStyle DoubleQuotes = getGoogleStyle(FormatStyle::LK_JavaScript);
|
|
|
|
DoubleQuotes.JavaScriptQuotes = FormatStyle::JSQS_Double;
|
|
|
|
verifyFormat("var x = \"foo\";", DoubleQuotes);
|
2016-03-15 03:21:36 +08:00
|
|
|
verifyFormat("var x = \"foo\";", "var x = 'foo';", DoubleQuotes);
|
|
|
|
verifyFormat("var x = \"fo'o\";", "var x = 'fo\\'o';", DoubleQuotes);
|
2016-03-03 06:44:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(FormatTestJS, RequoteStringsLeave) {
|
|
|
|
FormatStyle LeaveQuotes = getGoogleStyle(FormatStyle::LK_JavaScript);
|
|
|
|
LeaveQuotes.JavaScriptQuotes = FormatStyle::JSQS_Leave;
|
|
|
|
verifyFormat("var x = \"foo\";", LeaveQuotes);
|
|
|
|
verifyFormat("var x = 'foo';", LeaveQuotes);
|
|
|
|
}
|
|
|
|
|
2016-05-29 22:41:36 +08:00
|
|
|
TEST_F(FormatTestJS, SupportShebangLines) {
|
|
|
|
verifyFormat("#!/usr/bin/env node\n"
|
|
|
|
"var x = hello();",
|
|
|
|
"#!/usr/bin/env node\n"
|
|
|
|
"var x = hello();");
|
|
|
|
}
|
|
|
|
|
2016-06-13 08:49:54 +08:00
|
|
|
TEST_F(FormatTestJS, NonNullAssertionOperator) {
|
|
|
|
verifyFormat("let x = foo!.bar();\n");
|
|
|
|
verifyFormat("let x = foo ? bar! : baz;\n");
|
|
|
|
verifyFormat("let x = !foo;\n");
|
2018-03-06 21:56:28 +08:00
|
|
|
verifyFormat("if (!+a) {\n}");
|
2016-06-13 08:49:54 +08:00
|
|
|
verifyFormat("let x = foo[0]!;\n");
|
|
|
|
verifyFormat("let x = (foo)!;\n");
|
2017-05-22 22:58:26 +08:00
|
|
|
verifyFormat("let x = x(foo!);\n");
|
2020-05-02 22:42:20 +08:00
|
|
|
verifyFormat("a.aaaaaa(a.a!).then(\n"
|
|
|
|
" x => x(x));\n",
|
|
|
|
getGoogleJSStyleWithColumns(20));
|
2016-11-09 22:12:55 +08:00
|
|
|
verifyFormat("let x = foo! - 1;\n");
|
2016-06-13 08:49:54 +08:00
|
|
|
verifyFormat("let x = {foo: 1}!;\n");
|
2020-05-02 22:42:20 +08:00
|
|
|
verifyFormat("let x = hello.foo()!\n"
|
|
|
|
" .foo()!\n"
|
|
|
|
" .foo()!\n"
|
|
|
|
" .foo()!;\n",
|
|
|
|
getGoogleJSStyleWithColumns(20));
|
2017-05-12 21:00:33 +08:00
|
|
|
verifyFormat("let x = namespace!;\n");
|
2017-05-15 16:15:53 +08:00
|
|
|
verifyFormat("return !!x;\n");
|
2016-06-13 08:49:54 +08:00
|
|
|
}
|
|
|
|
|
2020-04-02 22:53:17 +08:00
|
|
|
TEST_F(FormatTestJS, CppKeywords) {
|
|
|
|
// Make sure we don't mess stuff up because of C++ keywords.
|
|
|
|
verifyFormat("return operator && (aa);");
|
|
|
|
// .. or QT ones.
|
|
|
|
verifyFormat("const slots: Slot[];");
|
|
|
|
// use the "!" assertion operator to validate that clang-format understands
|
|
|
|
// these C++ keywords aren't keywords in JS/TS.
|
|
|
|
verifyFormat("auto!;");
|
|
|
|
verifyFormat("char!;");
|
|
|
|
verifyFormat("concept!;");
|
|
|
|
verifyFormat("double!;");
|
|
|
|
verifyFormat("extern!;");
|
|
|
|
verifyFormat("float!;");
|
|
|
|
verifyFormat("inline!;");
|
|
|
|
verifyFormat("int!;");
|
|
|
|
verifyFormat("long!;");
|
|
|
|
verifyFormat("register!;");
|
|
|
|
verifyFormat("restrict!;");
|
|
|
|
verifyFormat("sizeof!;");
|
|
|
|
verifyFormat("struct!;");
|
|
|
|
verifyFormat("typedef!;");
|
|
|
|
verifyFormat("union!;");
|
|
|
|
verifyFormat("unsigned!;");
|
|
|
|
verifyFormat("volatile!;");
|
|
|
|
verifyFormat("_Alignas!;");
|
|
|
|
verifyFormat("_Alignof!;");
|
|
|
|
verifyFormat("_Atomic!;");
|
|
|
|
verifyFormat("_Bool!;");
|
|
|
|
verifyFormat("_Complex!;");
|
|
|
|
verifyFormat("_Generic!;");
|
|
|
|
verifyFormat("_Imaginary!;");
|
|
|
|
verifyFormat("_Noreturn!;");
|
|
|
|
verifyFormat("_Static_assert!;");
|
|
|
|
verifyFormat("_Thread_local!;");
|
|
|
|
verifyFormat("__func__!;");
|
|
|
|
verifyFormat("__objc_yes!;");
|
|
|
|
verifyFormat("__objc_no!;");
|
|
|
|
verifyFormat("asm!;");
|
|
|
|
verifyFormat("bool!;");
|
|
|
|
verifyFormat("const_cast!;");
|
|
|
|
verifyFormat("dynamic_cast!;");
|
|
|
|
verifyFormat("explicit!;");
|
|
|
|
verifyFormat("friend!;");
|
|
|
|
verifyFormat("mutable!;");
|
|
|
|
verifyFormat("operator!;");
|
|
|
|
verifyFormat("reinterpret_cast!;");
|
|
|
|
verifyFormat("static_cast!;");
|
|
|
|
verifyFormat("template!;");
|
|
|
|
verifyFormat("typename!;");
|
|
|
|
verifyFormat("typeid!;");
|
|
|
|
verifyFormat("using!;");
|
|
|
|
verifyFormat("virtual!;");
|
|
|
|
verifyFormat("wchar_t!;");
|
2020-04-06 21:20:54 +08:00
|
|
|
|
|
|
|
// Positive tests:
|
|
|
|
verifyFormat("x.type!;");
|
|
|
|
verifyFormat("x.get!;");
|
|
|
|
verifyFormat("x.set!;");
|
2020-04-02 22:53:17 +08:00
|
|
|
}
|
|
|
|
|
2019-11-08 06:39:03 +08:00
|
|
|
TEST_F(FormatTestJS, NullPropagatingOperator) {
|
|
|
|
verifyFormat("let x = foo?.bar?.baz();\n");
|
|
|
|
verifyFormat("let x = foo?.(foo);\n");
|
|
|
|
verifyFormat("let x = foo?.['arr'];\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(FormatTestJS, NullishCoalescingOperator) {
|
|
|
|
verifyFormat("const val = something ?? 'some other default';\n");
|
2020-01-20 19:19:47 +08:00
|
|
|
verifyFormat(
|
|
|
|
"const val = something ?? otherDefault ??\n"
|
|
|
|
" evenMore ?? evenMore;\n",
|
|
|
|
"const val = something ?? otherDefault ?? evenMore ?? evenMore;\n",
|
|
|
|
getGoogleJSStyleWithColumns(40));
|
2019-11-08 06:39:03 +08:00
|
|
|
}
|
|
|
|
|
2020-11-10 16:16:49 +08:00
|
|
|
TEST_F(FormatTestJS, AssignmentOperators) {
|
|
|
|
verifyFormat("a &&= b;\n");
|
|
|
|
verifyFormat("a ||= b;\n");
|
|
|
|
// NB: need to split ? ?= to avoid it being interpreted by C++ as a trigraph
|
|
|
|
// for #.
|
|
|
|
verifyFormat("a ?"
|
|
|
|
"?= b;\n");
|
|
|
|
}
|
|
|
|
|
2016-06-24 05:51:49 +08:00
|
|
|
TEST_F(FormatTestJS, Conditional) {
|
|
|
|
verifyFormat("y = x ? 1 : 2;");
|
2016-07-12 23:45:53 +08:00
|
|
|
verifyFormat("x ? 1 : 2;");
|
2016-06-24 05:51:49 +08:00
|
|
|
verifyFormat("class Foo {\n"
|
|
|
|
" field = true ? 1 : 2;\n"
|
|
|
|
" method(a = true ? 1 : 2) {}\n"
|
|
|
|
"}");
|
|
|
|
}
|
|
|
|
|
2016-09-19 01:33:51 +08:00
|
|
|
TEST_F(FormatTestJS, ImportComments) {
|
|
|
|
verifyFormat("import {x} from 'x'; // from some location",
|
|
|
|
getGoogleJSStyleWithColumns(25));
|
|
|
|
verifyFormat("// taze: x from 'location'", getGoogleJSStyleWithColumns(10));
|
2020-05-02 22:42:20 +08:00
|
|
|
verifyFormat("/// <reference path=\"some/location\" />",
|
|
|
|
getGoogleJSStyleWithColumns(10));
|
2016-09-19 01:33:51 +08:00
|
|
|
}
|
2017-05-04 23:04:04 +08:00
|
|
|
|
|
|
|
TEST_F(FormatTestJS, Exponentiation) {
|
|
|
|
verifyFormat("squared = x ** 2;");
|
|
|
|
verifyFormat("squared **= 2;");
|
|
|
|
}
|
|
|
|
|
2017-06-06 20:38:29 +08:00
|
|
|
TEST_F(FormatTestJS, NestedLiterals) {
|
|
|
|
FormatStyle FourSpaces = getGoogleJSStyleWithColumns(15);
|
|
|
|
FourSpaces.IndentWidth = 4;
|
|
|
|
verifyFormat("var l = [\n"
|
|
|
|
" [\n"
|
|
|
|
" 1,\n"
|
|
|
|
" ],\n"
|
2020-05-02 22:42:20 +08:00
|
|
|
"];",
|
|
|
|
FourSpaces);
|
2017-06-06 20:38:29 +08:00
|
|
|
verifyFormat("var l = [\n"
|
|
|
|
" {\n"
|
|
|
|
" 1: 1,\n"
|
|
|
|
" },\n"
|
2020-05-02 22:42:20 +08:00
|
|
|
"];",
|
|
|
|
FourSpaces);
|
2017-06-06 20:38:29 +08:00
|
|
|
verifyFormat("someFunction(\n"
|
|
|
|
" p1,\n"
|
|
|
|
" [\n"
|
|
|
|
" 1,\n"
|
|
|
|
" ],\n"
|
2020-05-02 22:42:20 +08:00
|
|
|
");",
|
|
|
|
FourSpaces);
|
2017-06-06 20:38:29 +08:00
|
|
|
verifyFormat("someFunction(\n"
|
|
|
|
" p1,\n"
|
|
|
|
" {\n"
|
|
|
|
" 1: 1,\n"
|
|
|
|
" },\n"
|
2020-05-02 22:42:20 +08:00
|
|
|
");",
|
|
|
|
FourSpaces);
|
2017-06-06 20:38:29 +08:00
|
|
|
verifyFormat("var o = {\n"
|
|
|
|
" 1: 1,\n"
|
|
|
|
" 2: {\n"
|
|
|
|
" 3: 3,\n"
|
|
|
|
" },\n"
|
2020-05-02 22:42:20 +08:00
|
|
|
"};",
|
|
|
|
FourSpaces);
|
2017-06-06 20:38:29 +08:00
|
|
|
verifyFormat("var o = {\n"
|
|
|
|
" 1: 1,\n"
|
|
|
|
" 2: [\n"
|
|
|
|
" 3,\n"
|
|
|
|
" ],\n"
|
2020-05-02 22:42:20 +08:00
|
|
|
"};",
|
|
|
|
FourSpaces);
|
2017-06-06 20:38:29 +08:00
|
|
|
}
|
|
|
|
|
2017-08-08 22:52:42 +08:00
|
|
|
TEST_F(FormatTestJS, BackslashesInComments) {
|
|
|
|
verifyFormat("// hello \\\n"
|
|
|
|
"if (x) foo();\n",
|
|
|
|
"// hello \\\n"
|
|
|
|
" if ( x) \n"
|
|
|
|
" foo();\n");
|
|
|
|
verifyFormat("/* ignore \\\n"
|
|
|
|
" */\n"
|
|
|
|
"if (x) foo();\n",
|
|
|
|
"/* ignore \\\n"
|
|
|
|
" */\n"
|
|
|
|
" if ( x) foo();\n");
|
|
|
|
verifyFormat("// st \\ art\\\n"
|
|
|
|
"// comment"
|
|
|
|
"// continue \\\n"
|
|
|
|
"formatMe();\n",
|
|
|
|
"// st \\ art\\\n"
|
|
|
|
"// comment"
|
|
|
|
"// continue \\\n"
|
|
|
|
"formatMe( );\n");
|
|
|
|
}
|
|
|
|
|
2018-08-07 18:23:24 +08:00
|
|
|
TEST_F(FormatTestJS, AddsLastLinePenaltyIfEndingIsBroken) {
|
|
|
|
EXPECT_EQ(
|
|
|
|
"a = function() {\n"
|
|
|
|
" b = function() {\n"
|
|
|
|
" this.aaaaaaaaaaaaaaaaaaa[aaaaaaaaaaa] = aaaa.aaaaaa ?\n"
|
|
|
|
" aaaa.aaaaaa : /** @type "
|
|
|
|
"{aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaaaaaaaa} */\n"
|
|
|
|
" (aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaa.aaaaaaaaaaaaaaaaa);\n"
|
|
|
|
" };\n"
|
|
|
|
"};",
|
|
|
|
format("a = function() {\n"
|
|
|
|
" b = function() {\n"
|
|
|
|
" this.aaaaaaaaaaaaaaaaaaa[aaaaaaaaaaa] = aaaa.aaaaaa ? "
|
|
|
|
"aaaa.aaaaaa : /** @type "
|
|
|
|
"{aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaaaaaaaa} */\n"
|
|
|
|
" (aaaa.aaaa.aaaaaaaaa.aaaaaaaaaaaaa.aaaaaaaaaaaaaaaaa);\n"
|
|
|
|
" };\n"
|
|
|
|
"};"));
|
|
|
|
}
|
|
|
|
|
2018-09-26 16:28:33 +08:00
|
|
|
TEST_F(FormatTestJS, ParameterNamingComment) {
|
|
|
|
verifyFormat("callFoo(/*spaceAfterParameterNamingComment=*/ 1);");
|
|
|
|
}
|
|
|
|
|
2018-09-27 14:48:13 +08:00
|
|
|
TEST_F(FormatTestJS, ConditionalTypes) {
|
|
|
|
// Formatting below is not necessarily intentional, this just ensures that
|
|
|
|
// clang-format does not break the code.
|
|
|
|
verifyFormat( // wrap
|
|
|
|
"type UnionToIntersection<U> =\n"
|
|
|
|
" (U extends any ? (k: U) => void :\n"
|
|
|
|
" never) extends((k: infer I) => void) ? I : never;");
|
|
|
|
}
|
|
|
|
|
2019-03-19 20:28:41 +08:00
|
|
|
TEST_F(FormatTestJS, SupportPrivateFieldsAndMethods) {
|
|
|
|
verifyFormat("class Example {\n"
|
|
|
|
" pub = 1;\n"
|
|
|
|
" #priv = 2;\n"
|
|
|
|
" static pub2 = 'foo';\n"
|
|
|
|
" static #priv2 = 'bar';\n"
|
|
|
|
" method() {\n"
|
|
|
|
" this.#priv = 5;\n"
|
|
|
|
" }\n"
|
|
|
|
" static staticMethod() {\n"
|
|
|
|
" switch (this.#priv) {\n"
|
|
|
|
" case '1':\n"
|
|
|
|
" #priv = 3;\n"
|
|
|
|
" break;\n"
|
|
|
|
" }\n"
|
|
|
|
" }\n"
|
|
|
|
" #privateMethod() {\n"
|
|
|
|
" this.#privateMethod(); // infinite loop\n"
|
|
|
|
" }\n"
|
|
|
|
" static #staticPrivateMethod() {}\n");
|
|
|
|
}
|
|
|
|
|
2019-11-08 06:37:06 +08:00
|
|
|
TEST_F(FormatTestJS, DeclaredFields) {
|
|
|
|
verifyFormat("class Example {\n"
|
|
|
|
" declare pub: string;\n"
|
|
|
|
" declare private priv: string;\n"
|
|
|
|
"}\n");
|
|
|
|
}
|
|
|
|
|
2019-03-19 20:28:41 +08:00
|
|
|
} // namespace format
|
2013-12-03 18:50:16 +08:00
|
|
|
} // end namespace clang
|