diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:44:14 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:44:14 +0000 |
commit | 2b6b257f4e5503a7a2675bdb8735693db769f75c (patch) | |
tree | e85e046ae7003fe3bcc8b5454cd0fa3f7407b470 /unittests/Format/FormatTestJS.cpp | |
parent | b4348ed0b7e90c0831b925fbee00b5f179a99796 (diff) |
Notes
Diffstat (limited to 'unittests/Format/FormatTestJS.cpp')
-rw-r--r-- | unittests/Format/FormatTestJS.cpp | 453 |
1 files changed, 375 insertions, 78 deletions
diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp index 0e0f64a31ac6..2819383a3585 100644 --- a/unittests/Format/FormatTestJS.cpp +++ b/unittests/Format/FormatTestJS.cpp @@ -28,10 +28,10 @@ protected: tooling::Replacements Replaces = reformat(Style, Code, Ranges, "<stdin>", &IncompleteFormat); EXPECT_FALSE(IncompleteFormat); - std::string Result = applyAllReplacements(Code, Replaces); - EXPECT_NE("", Result); - DEBUG(llvm::errs() << "\n" << Result << "\n\n"); - return Result; + auto Result = applyAllReplacements(Code, Replaces); + EXPECT_TRUE(static_cast<bool>(Result)); + DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); + return *Result; } static std::string format( @@ -49,11 +49,24 @@ protected: static void verifyFormat( llvm::StringRef Code, const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) { - std::string result = format(test::messUp(Code), Style); - EXPECT_EQ(Code.str(), result) << "Formatted:\n" << result; + std::string Result = format(test::messUp(Code), Style); + EXPECT_EQ(Code.str(), Result) << "Formatted:\n" << Result; + } + + static void verifyFormat( + llvm::StringRef Expected, + llvm::StringRef Code, + const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) { + std::string Result = format(Code, Style); + EXPECT_EQ(Expected.str(), Result) << "Formatted:\n" << Result; } }; +TEST_F(FormatTestJS, BlockComments) { + verifyFormat("/* aaaaaaaaaaaaa */ aaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);"); +} + TEST_F(FormatTestJS, UnderstandsJavaScriptOperators) { verifyFormat("a == = b;"); verifyFormat("a != = b;"); @@ -86,6 +99,17 @@ TEST_F(FormatTestJS, UnderstandsJavaScriptOperators) { verifyFormat("var b = a.map((x) => x + 1);"); verifyFormat("return ('aaa') in bbbb;"); + verifyFormat("var x = aaaaaaaaaaaaaaaaaaaaaaaaa() in\n" + " aaaa.aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;"); + FormatStyle Style = getGoogleJSStyleWithColumns(80); + Style.AlignOperands = true; + 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); // ES6 spread operator. verifyFormat("someFunction(...a);"); @@ -106,6 +130,11 @@ TEST_F(FormatTestJS, ReservedWords) { verifyFormat("x.class.struct = 1;"); verifyFormat("x.case = 1;"); verifyFormat("x.interface = 1;"); + verifyFormat("x.for = 1;"); + verifyFormat("x.of() = 1;"); + verifyFormat("x.in() = 1;"); + verifyFormat("x.let() = 1;"); + verifyFormat("x.var() = 1;"); verifyFormat("x = {\n" " a: 12,\n" " interface: 1,\n" @@ -113,6 +142,9 @@ TEST_F(FormatTestJS, ReservedWords) { "};"); verifyFormat("var struct = 2;"); verifyFormat("var union = 2;"); + verifyFormat("var interface = 2;"); + verifyFormat("interface = 2;"); + verifyFormat("x = interface instanceof y;"); } TEST_F(FormatTestJS, CppKeywords) { @@ -122,6 +154,7 @@ TEST_F(FormatTestJS, CppKeywords) { TEST_F(FormatTestJS, ES6DestructuringAssignment) { verifyFormat("var [a, b, c] = [1, 2, 3];"); + verifyFormat("const [a, b, c] = [1, 2, 3];"); verifyFormat("let [a, b, c] = [1, 2, 3];"); verifyFormat("var {a, b} = {a: 1, b: 2};"); verifyFormat("let {a, b} = {a: 1, b: 2};"); @@ -189,6 +222,18 @@ TEST_F(FormatTestJS, ContainerLiterals) { " b: 2,\n" " [c]: 3,\n" "};"); + + // Object literals can leave out labels. + verifyFormat("f({a}, () => {\n" + " g(); //\n" + "});"); + + // Keys can be quoted. + verifyFormat("var x = {\n" + " a: a,\n" + " b: b,\n" + " 'c': c,\n" + "};"); } TEST_F(FormatTestJS, MethodsInObjectLiterals) { @@ -234,7 +279,7 @@ TEST_F(FormatTestJS, SpacesInContainerLiterals) { verifyFormat("f({'a': [{}]});"); } -TEST_F(FormatTestJS, SingleQuoteStrings) { +TEST_F(FormatTestJS, SingleQuotedStrings) { verifyFormat("this.function('', true);"); } @@ -261,6 +306,8 @@ TEST_F(FormatTestJS, GoogModules) { getGoogleJSStyleWithColumns(40)); verifyFormat("goog.setTestOnly('this.is.really.absurdly.long');", getGoogleJSStyleWithColumns(40)); + verifyFormat("goog.forwardDeclare('this.is.really.absurdly.long');", + getGoogleJSStyleWithColumns(40)); // These should be wrapped normally. verifyFormat( @@ -268,6 +315,15 @@ TEST_F(FormatTestJS, GoogModules) { " goog.module.get('my.long.module.name.followedBy.MyLongClassName');"); } +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"); +} + TEST_F(FormatTestJS, FormatsFreestandingFunctions) { verifyFormat("function outer1(a, b) {\n" " function inner1(a, b) { return a; }\n" @@ -280,6 +336,44 @@ TEST_F(FormatTestJS, FormatsFreestandingFunctions) { verifyFormat("function f() {}"); } +TEST_F(FormatTestJS, GeneratorFunctions) { + verifyFormat("function* f() {\n" + " let x = 1;\n" + " yield x;\n" + " yield* something();\n" + "}"); + verifyFormat("function*\n" + " f() {\n" + "}", + getGoogleJSStyleWithColumns(8)); + verifyFormat("export function* f() {\n" + " yield 1;\n" + "}\n"); + verifyFormat("class X {\n" + " * generatorMethod() { yield x; }\n" + "}"); +} + +TEST_F(FormatTestJS, AsyncFunctions) { + verifyFormat("async function f() {\n" + " let x = 1;\n" + " return fetch(x);\n" + "}"); + verifyFormat("async function* f() {\n" + " yield fetch(x);\n" + "}"); + verifyFormat("export async function f() {\n" + " return fetch(x);\n" + "}"); + verifyFormat("class X {\n" + " async asyncMethod() { return fetch(1); }\n" + "}"); + verifyFormat("function initialize() {\n" + " // Comment.\n" + " return async.then();\n" + "}\n"); +} + TEST_F(FormatTestJS, ArrayLiterals) { verifyFormat("var aaaaa: List<SomeThing> =\n" " [new SomeThingAAAAAAAAAAAA(), new SomeThingBBBBBBBBB()];"); @@ -579,9 +673,15 @@ TEST_F(FormatTestJS, ReturnStatements) { TEST_F(FormatTestJS, ForLoops) { verifyFormat("for (var i in [2, 3]) {\n" "}"); + verifyFormat("for (var i of [2, 3]) {\n" + "}"); + verifyFormat("for (let {a, b} of x) {\n" + "}"); + verifyFormat("for (let {a, b} in x) {\n" + "}"); } -TEST_F(FormatTestJS, AutomaticSemicolonInsertion) { +TEST_F(FormatTestJS, WrapRespectsAutomaticSemicolonInsertion) { // 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. @@ -591,6 +691,60 @@ TEST_F(FormatTestJS, AutomaticSemicolonInsertion) { verifyFormat("throw aaaaa;", getGoogleJSStyleWithColumns(10)); verifyFormat("aaaaaaaaa++;", getGoogleJSStyleWithColumns(10)); verifyFormat("aaaaaaaaa--;", getGoogleJSStyleWithColumns(10)); + verifyFormat("return [\n" + " aaa\n" + "];", + getGoogleJSStyleWithColumns(12)); +} + +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"); + verifyFormat("function f(@Foo bar) {}", "function f(@Foo\n" + " bar) {}"); } TEST_F(FormatTestJS, ClosureStyleCasts) { @@ -691,13 +845,13 @@ TEST_F(FormatTestJS, RegexLiteralSpecialCharacters) { verifyFormat("var regex = /\a\\//g;"); verifyFormat("var regex = /a\\//;\n" "var x = 0;"); - EXPECT_EQ("var regex = /'/g;", format("var regex = /'/g ;")); - EXPECT_EQ("var regex = /'/g; //'", format("var regex = /'/g ; //'")); - EXPECT_EQ("var regex = /\\/*/;\n" - "var x = 0;", - format("var regex = /\\/*/;\n" - "var x=0;")); - EXPECT_EQ("var x = /a\\//;", format("var x = /a\\// \n;")); + 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;"); verifyFormat("var regex = /\"/;", getGoogleJSStyleWithColumns(16)); verifyFormat("var regex =\n" " /\"/;", @@ -738,6 +892,7 @@ TEST_F(FormatTestJS, TypeAnnotations) { verifyFormat("function x(): {x: string} {\n return {x: 'x'};\n}"); verifyFormat("function x(y: string): string {\n return 'x';\n}"); verifyFormat("for (var y: string in x) {\n x();\n}"); + verifyFormat("for (var y: string of x) {\n x();\n}"); verifyFormat("function x(y: {a?: number;} = {}): number {\n" " return 12;\n" "}"); @@ -751,6 +906,22 @@ TEST_F(FormatTestJS, TypeAnnotations) { getGoogleJSStyleWithColumns(60)); } +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 {}"); + verifyFormat("function x(path: number|string) {}"); + verifyFormat("function x(): string|number {}"); + 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)[];"); +} + TEST_F(FormatTestJS, ClassDeclarations) { verifyFormat("class C {\n x: string = 12;\n}"); verifyFormat("class C {\n x(): string => 12;\n}"); @@ -783,12 +954,18 @@ TEST_F(FormatTestJS, ClassDeclarations) { " },\n" " };\n" "}"); + verifyFormat("@Component({\n" + " moduleId: module.id,\n" + "})\n" + "class SessionListComponent implements OnDestroy, OnInit {\n" + "}"); } TEST_F(FormatTestJS, InterfaceDeclarations) { verifyFormat("interface I {\n" " x: string;\n" " enum: string[];\n" + " enum?: string[];\n" "}\n" "var y;"); // Ensure that state is reset after parsing the interface. @@ -829,30 +1006,32 @@ TEST_F(FormatTestJS, MetadataAnnotations) { " return 'y';\n" " }\n" "}"); + verifyFormat("class C {\n" + " private x(@A x: string) {}\n" + "}"); verifyFormat("class X {}\n" "class Y {}"); } +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 {}"); +} + TEST_F(FormatTestJS, Modules) { verifyFormat("import SomeThing from 'some/module.js';"); verifyFormat("import {X, Y} from 'some/module.js';"); verifyFormat("import a, {X, Y} from 'some/module.js';"); - verifyFormat("import {\n" - " VeryLongImportsAreAnnoying,\n" - " VeryLongImportsAreAnnoying,\n" - " VeryLongImportsAreAnnoying,\n" - " VeryLongImportsAreAnnoying\n" - "} from 'some/module.js';"); - verifyFormat("import {\n" - " X,\n" - " Y,\n" - "} from 'some/module.js';"); - verifyFormat("import {\n" - " X,\n" - " Y,\n" - "} from 'some/long/module.js';", - getGoogleJSStyleWithColumns(20)); + verifyFormat("import {X, Y,} from 'some/module.js';"); verifyFormat("import {X as myLocalX, Y as myLocalY} from 'some/module.js';"); + // Ensure Automatic Semicolon Insertion does not break on "as\n". + verifyFormat("import {X as myX} from 'm';", "import {X as\n" + " myX} from 'm';"); verifyFormat("import * as lib from 'some/module.js';"); verifyFormat("var x = {import: 1};\nx.import = 2;"); @@ -862,13 +1041,26 @@ TEST_F(FormatTestJS, Modules) { verifyFormat("export function A() {}\n" "export default function B() {}\n" "export function C() {}"); + verifyFormat("export default () => {\n" + " let x = 1;\n" + " return x;\n" + "}"); verifyFormat("export const x = 12;"); verifyFormat("export default class X {}"); verifyFormat("export {X, Y} from 'some/module.js';"); + 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. verifyFormat("export {\n" - " X,\n" - " Y,\n" - "} from 'some/module.js';"); + " from as from,\n" + " someSurprisinglyLongVariable as\n" + " from\n" + "};", + getGoogleJSStyleWithColumns(20)); verifyFormat("export class C {\n" " x: number;\n" " y: string;\n" @@ -903,42 +1095,74 @@ TEST_F(FormatTestJS, Modules) { "}"); } +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); +} + TEST_F(FormatTestJS, TemplateStrings) { // Keeps any whitespace/indentation within the template string. - EXPECT_EQ("var x = `hello\n" + verifyFormat("var x = `hello\n" " ${ name }\n" " !`;", - format("var x = `hello\n" + "var x = `hello\n" " ${ name }\n" - " !`;")); + " !`;"); verifyFormat("var x =\n" " `hello ${world}` >= some();", getGoogleJSStyleWithColumns(34)); // Barely doesn't fit. verifyFormat("var x = `hello ${world}` >= some();", getGoogleJSStyleWithColumns(35)); // Barely fits. - EXPECT_EQ("var x = `hello\n" + verifyFormat("var x = `hellö ${wörld}` >= söme();", + getGoogleJSStyleWithColumns(35)); // Fits due to UTF-8. + verifyFormat("var x = `hello\n" " ${world}` >=\n" " some();", - format("var x =\n" + "var x =\n" " `hello\n" " ${world}` >= some();", - getGoogleJSStyleWithColumns(21))); // Barely doesn't fit. - EXPECT_EQ("var x = `hello\n" + getGoogleJSStyleWithColumns(21)); // Barely doesn't fit. + verifyFormat("var x = `hello\n" " ${world}` >= some();", - format("var x =\n" + "var x =\n" " `hello\n" " ${world}` >= some();", - getGoogleJSStyleWithColumns(22))); // Barely fits. + getGoogleJSStyleWithColumns(22)); // Barely fits. verifyFormat("var x =\n" " `h`;", getGoogleJSStyleWithColumns(11)); - EXPECT_EQ( - "var x =\n `multi\n line`;", - format("var x = `multi\n line`;", getGoogleJSStyleWithColumns(13))); + verifyFormat("var x =\n `multi\n line`;", "var x = `multi\n line`;", + getGoogleJSStyleWithColumns(13)); verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" " `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`);"); + // 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]}`;"); // Make sure template strings get a proper ColumnWidth assigned, even if they // are first token in line. @@ -950,42 +1174,51 @@ TEST_F(FormatTestJS, TemplateStrings) { verifyFormat("var x = `hello` == `hello`;"); // Comments in template strings. - EXPECT_EQ("var x = `//a`;\n" - "var y;", - format("var x =\n `//a`;\n" - "var y ;")); - EXPECT_EQ("var x = `/*a`;\n" + verifyFormat("var x = `//a`;\n" "var y;", - format("var x =\n `/*a`;\n" - "var y;")); + "var x =\n `//a`;\n" + "var y ;"); + verifyFormat("var x = `/*a`;\n" + "var y;", + "var x =\n `/*a`;\n" + "var y;"); // 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;"); - EXPECT_EQ("it(`'aaaaaaaaaaaaaaa `, aaaaaaaaa);", - format("it(`'aaaaaaaaaaaaaaa `, aaaaaaaaa) ;", - getGoogleJSStyleWithColumns(40))); + verifyFormat("it(`'aaaaaaaaaaaaaaa `, aaaaaaaaa);", + "it(`'aaaaaaaaaaaaaaa `, aaaaaaaaa) ;", + getGoogleJSStyleWithColumns(40)); // Backticks in a comment - not a template string. - EXPECT_EQ("var x = 1 // `/*a`;\n" - " ;", - format("var x =\n 1 // `/*a`;\n" - " ;")); - EXPECT_EQ("/* ` */ var x = 1; /* ` */", - format("/* ` */ var x\n= 1; /* ` */")); + verifyFormat("var x = 1 // `/*a`;\n" + " ;", + "var x =\n 1 // `/*a`;\n" + " ;"); + verifyFormat("/* ` */ var x = 1; /* ` */", "/* ` */ var x\n= 1; /* ` */"); // Comment spans multiple template strings. - EXPECT_EQ("var x = `/*a`;\n" - "var y = ` */ `;", - format("var x =\n `/*a`;\n" - "var y =\n ` */ `;")); + verifyFormat("var x = `/*a`;\n" + "var y = ` */ `;", + "var x =\n `/*a`;\n" + "var y =\n ` */ `;"); // Escaped backtick. - EXPECT_EQ("var x = ` \\` a`;\n" - "var y;", - format("var x = ` \\` a`;\n" - "var y;")); + verifyFormat("var x = ` \\` a`;\n" + "var y;", + "var x = ` \\` a`;\n" + "var y;"); } -TEST_F(FormatTestJS, CastSyntax) { verifyFormat("var x = <type>foo;"); } +TEST_F(FormatTestJS, CastSyntax) { + verifyFormat("var x = <type>foo;"); + verifyFormat("var x = foo as type;"); + verifyFormat("let x = (a + b) as\n" + " LongTypeIsLong;", + getGoogleJSStyleWithColumns(20)); + verifyFormat("foo = <Bar[]>[\n" + " 1, //\n" + " 2\n" + "];"); +} TEST_F(FormatTestJS, TypeArguments) { verifyFormat("class X<Y> {}"); @@ -1020,7 +1253,6 @@ TEST_F(FormatTestJS, OptionalTypes) { verifyFormat("interface X {\n" " y?(): z;\n" "}"); - verifyFormat("x ? 1 : 2;"); verifyFormat("constructor({aa}: {\n" " aa?: string,\n" " aaaaaaaa?: string,\n" @@ -1052,13 +1284,78 @@ TEST_F(FormatTestJS, WrapAfterParen) { } TEST_F(FormatTestJS, JSDocAnnotations) { - EXPECT_EQ("/**\n" - " * @export {this.is.a.long.path.to.a.Type}\n" - " */", - format("/**\n" - " * @export {this.is.a.long.path.to.a.Type}\n" - " */", - getGoogleJSStyleWithColumns(20))); + verifyFormat("/**\n" + " * @export {this.is.a.long.path.to.a.Type}\n" + " */", + "/**\n" + " * @export {this.is.a.long.path.to.a.Type}\n" + " */", + getGoogleJSStyleWithColumns(20)); +} + +TEST_F(FormatTestJS, RequoteStringsSingle) { + 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'\";"); + 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)); + // Removes no-longer needed \ escape from ". + verifyFormat("var x = 'fo\"o';", "var x = \"fo\\\"o\";"); + // Code below fits into 15 chars *after* removing the \ escape. + verifyFormat("var x = 'fo\"o';", "var x = \"fo\\\"o\";", + getGoogleJSStyleWithColumns(15)); + 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"); +} + +TEST_F(FormatTestJS, RequoteStringsDouble) { + FormatStyle DoubleQuotes = getGoogleStyle(FormatStyle::LK_JavaScript); + DoubleQuotes.JavaScriptQuotes = FormatStyle::JSQS_Double; + verifyFormat("var x = \"foo\";", DoubleQuotes); + verifyFormat("var x = \"foo\";", "var x = 'foo';", DoubleQuotes); + verifyFormat("var x = \"fo'o\";", "var x = 'fo\\'o';", DoubleQuotes); +} + +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); +} + +TEST_F(FormatTestJS, SupportShebangLines) { + verifyFormat("#!/usr/bin/env node\n" + "var x = hello();", + "#!/usr/bin/env node\n" + "var x = hello();"); +} + +TEST_F(FormatTestJS, NonNullAssertionOperator) { + verifyFormat("let x = foo!.bar();\n"); + verifyFormat("let x = foo ? bar! : baz;\n"); + verifyFormat("let x = !foo;\n"); + verifyFormat("let x = foo[0]!;\n"); + verifyFormat("let x = (foo)!;\n"); + verifyFormat("let x = {foo: 1}!;\n"); +} + +TEST_F(FormatTestJS, Conditional) { + verifyFormat("y = x ? 1 : 2;"); + verifyFormat("x ? 1 : 2;"); + verifyFormat("class Foo {\n" + " field = true ? 1 : 2;\n" + " method(a = true ? 1 : 2) {}\n" + "}"); } } // end namespace tooling |