diff options
Diffstat (limited to 'unittests/Format/FormatTestJS.cpp')
-rw-r--r-- | unittests/Format/FormatTestJS.cpp | 208 |
1 files changed, 203 insertions, 5 deletions
diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp index 230717fe47cc..d8fa8e4b942c 100644 --- a/unittests/Format/FormatTestJS.cpp +++ b/unittests/Format/FormatTestJS.cpp @@ -132,6 +132,8 @@ TEST_F(FormatTestJS, ReservedWords) { verifyFormat("x.interface = 1;"); verifyFormat("x.for = 1;"); verifyFormat("x.of() = 1;"); + verifyFormat("of(null);"); + verifyFormat("import {of} from 'x';"); verifyFormat("x.in() = 1;"); verifyFormat("x.let() = 1;"); verifyFormat("x.var() = 1;"); @@ -167,6 +169,8 @@ TEST_F(FormatTestJS, ReservedWordsMethods) { TEST_F(FormatTestJS, CppKeywords) { // Make sure we don't mess stuff up because of C++ keywords. verifyFormat("return operator && (aa);"); + // .. or QT ones. + verifyFormat("slots: Slot[];"); } TEST_F(FormatTestJS, ES6DestructuringAssignment) { @@ -240,6 +244,18 @@ TEST_F(FormatTestJS, ContainerLiterals) { "};"); verifyFormat("var x = {y: (a) => a};"); + // 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" + "};"); + // Computed keys. verifyFormat("var x = {[a]: 1, b: 2, [c]: 3};"); verifyFormat("var x = {\n" @@ -266,6 +282,11 @@ TEST_F(FormatTestJS, ContainerLiterals) { " aaa,\n" " aaa,\n" "};"); + verifyFormat("return {\n" + " a,\n" + " b: 'b',\n" + " c,\n" + "};"); } TEST_F(FormatTestJS, MethodsInObjectLiterals) { @@ -451,6 +472,8 @@ TEST_F(FormatTestJS, AsyncFunctions) { verifyFormat("export async function f() {\n" " return fetch(x);\n" "}"); + verifyFormat("let x = async () => f();"); + verifyFormat("let x = async();"); verifyFormat("class X {\n" " async asyncMethod() {\n" " return fetch(1);\n" @@ -497,6 +520,11 @@ TEST_F(FormatTestJS, ArrayLiterals) { " [];"); verifyFormat("someFunction([], {a: a});"); + + verifyFormat("var string = [\n" + " 'aaaaaa',\n" + " 'bbbbbb',\n" + "].join('+');"); } TEST_F(FormatTestJS, ColumnLayoutForArrayLiterals) { @@ -587,6 +615,11 @@ TEST_F(FormatTestJS, FunctionLiterals) { " doSomething();\n" "}, this));"); + verifyFormat("SomeFunction(function() {\n" + " foo();\n" + " bar();\n" + "}.bind(this));"); + // FIXME: This is bad, we should be wrapping before "function() {". verifyFormat("someFunction(function() {\n" " doSomething(); // break\n" @@ -858,13 +891,25 @@ TEST_F(FormatTestJS, AutomaticSemicolonInsertionHeuristic) { "return 1", "a = null\n" " return 1"); + // Below "class Y {}" should ideally be on its own line. verifyFormat( "x = {\n" " a: 1\n" - "}\n" - "class Y {}", + "} 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 {}"); } TEST_F(FormatTestJS, ImportExportASI) { @@ -873,11 +918,17 @@ TEST_F(FormatTestJS, ImportExportASI) { "export function z() {}", "import {x} from 'y'\n" " export function z() {}"); + // Below "class Y {}" should ideally be on its own line. verifyFormat( - "export {x}\n" - "class Y {}", + "export {x} class Y {}", " export {x}\n" " class Y {\n}"); + verifyFormat( + "if (x) {\n" + "}\n" + "export class Y {}", + "if ( x ) { }\n" + " export class Y {}"); } TEST_F(FormatTestJS, ClosureStyleCasts) { @@ -913,6 +964,7 @@ TEST_F(FormatTestJS, RegexLiteralClassification) { verifyFormat("var x = a ? /abc/ : /abc/;"); verifyFormat("for (var i = 0; /abc/.test(s[i]); i++) {\n}"); verifyFormat("var x = !/abc/.test(y);"); + verifyFormat("var x = foo()! / 10;"); verifyFormat("var x = a && /abc/.test(y);"); verifyFormat("var x = a || /abc/.test(y);"); verifyFormat("var x = a + /abc/.search(y);"); @@ -1018,6 +1070,15 @@ TEST_F(FormatTestJS, RegexLiteralExamples) { verifyFormat("var regex = search.match(/(?:\?|&)times=([^?&]+)/i);"); } +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); +} + TEST_F(FormatTestJS, TypeAnnotations) { verifyFormat("var x: string;"); verifyFormat("var x: {a: string; b: number;} = {};"); @@ -1045,6 +1106,9 @@ TEST_F(FormatTestJS, TypeAnnotations) { verifyFormat("function someFunc(args: string[]):\n" " {longReturnValue: string[]} {}", getGoogleJSStyleWithColumns(60)); + verifyFormat( + "var someValue = (v as aaaaaaaaaaaaaaaaaaaa<T>[])\n" + " .someFunction(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);"); } TEST_F(FormatTestJS, UnionIntersectionTypes) { @@ -1072,6 +1136,10 @@ TEST_F(FormatTestJS, ClassDeclarations) { verifyFormat("class C {\n static x(): string {\n return 'asd';\n }\n}"); verifyFormat("class C extends P implements I {}"); verifyFormat("class C extends p.P implements i.I {}"); + verifyFormat( + "x(class {\n" + " a(): A {}\n" + "});"); verifyFormat("class Test {\n" " aaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaaa):\n" " aaaaaaaaaaaaaaaaaaaaaa {}\n" @@ -1164,6 +1232,20 @@ TEST_F(FormatTestJS, TypeAliases) { "class C {}"); } +TEST_F(FormatTestJS, TypeInterfaceLineWrapping) { + const FormatStyle &Style = getGoogleJSStyleWithColumns(20); + verifyFormat("type LongTypeIsReallyUnreasonablyLong =\n" + " string;\n", + "type LongTypeIsReallyUnreasonablyLong = string;\n", + Style); + verifyFormat( + "interface AbstractStrategyFactoryProvider {\n" + " a: number\n" + "}\n", + "interface AbstractStrategyFactoryProvider { a: number }\n", + Style); +} + TEST_F(FormatTestJS, Modules) { verifyFormat("import SomeThing from 'some/module.js';"); verifyFormat("import {X, Y} from 'some/module.js';"); @@ -1351,6 +1433,62 @@ TEST_F(FormatTestJS, TemplateStrings) { "var y;"); // Escaped dollar. verifyFormat("var x = ` \\${foo}`;\n"); + + // 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'}`;"); + + // 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`;"); + verifyFormat("var x = someFunction(`${})`) //\n" + " .oooooooooooooooooon();"); + verifyFormat("var x = someFunction(`${aaaa}${\n" + " aaaaa( //\n" + " aaaaa)\n" + " })`);"); +} + +TEST_F(FormatTestJS, TemplateStringMultiLineExpression) { + verifyFormat("var f = `aaaaaaaaaaaaaaaaaa: ${\n" + " aaaaa + //\n" + " bbbb\n" + " }`;", + "var f = `aaaaaaaaaaaaaaaaaa: ${aaaaa + //\n" + " bbbb}`;"); + verifyFormat("var f = `\n" + " aaaaaaaaaaaaaaaaaa: ${\n" + " aaaaa + //\n" + " bbbb\n" + " }`;", + "var f = `\n" + " aaaaaaaaaaaaaaaaaa: ${ aaaaa + //\n" + " bbbb }`;"); + verifyFormat("var f = `\n" + " aaaaaaaaaaaaaaaaaa: ${\n" + " someFunction(\n" + " aaaaa + //\n" + " bbbb)\n" + " }`;", + "var f = `\n" + " aaaaaaaaaaaaaaaaaa: ${someFunction (\n" + " aaaaa + //\n" + " bbbb)}`;"); + + // It might be preferable to wrap before "someFunction". + verifyFormat("var f = `\n" + " aaaaaaaaaaaaaaaaaa: ${someFunction({\n" + " aaaa: aaaaa,\n" + " bbbb: bbbbb,\n" + " })}`;", + "var f = `\n" + " aaaaaaaaaaaaaaaaaa: ${someFunction ({\n" + " aaaa: aaaaa,\n" + " bbbb: bbbbb,\n" + " })}`;"); } TEST_F(FormatTestJS, TemplateStringASI) { @@ -1387,6 +1525,9 @@ TEST_F(FormatTestJS, CastSyntax) { verifyFormat("x = x as {a: string};"); verifyFormat("x = x as (string);"); verifyFormat("x = x! as (string);"); + verifyFormat("var x = something.someFunction() as\n" + " something;", + getGoogleJSStyleWithColumns(40)); } TEST_F(FormatTestJS, TypeArguments) { @@ -1460,6 +1601,58 @@ TEST_F(FormatTestJS, JSDocAnnotations) { " * @export {this.is.a.long.path.to.a.Type}\n" " */", getGoogleJSStyleWithColumns(20)); + verifyFormat("/**\n" + " * @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" + " * @param {this.is.a.long.path.to.a.Type}\n" + " */", + "/**\n" + " * @param {this.is.a.long.path.to.a.Type}\n" + " */", + getGoogleJSStyleWithColumns(20)); + verifyFormat("/**\n" + " * @see http://very/very/long/url/is/long\n" + " */", + "/**\n" + " * @see http://very/very/long/url/is/long\n" + " */", + getGoogleJSStyleWithColumns(20)); + verifyFormat( + "/**\n" + " * @param This is a\n" + " * long comment but\n" + " * no type\n" + " */", + "/**\n" + " * @param This is a long comment but no type\n" + " */", + getGoogleJSStyleWithColumns(20)); + // Don't break @param line, but reindent it and reflow unrelated lines. + verifyFormat("{\n" + " /**\n" + " * long long long\n" + " * long\n" + " * @param {this.is.a.long.path.to.a.Type} a\n" + " * long long long\n" + " * long long\n" + " */\n" + " function f(a) {}\n" + "}", + "{\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)); } TEST_F(FormatTestJS, RequoteStringsSingle) { @@ -1532,6 +1725,12 @@ TEST_F(FormatTestJS, NonNullAssertionOperator) { verifyFormat("let x = (foo)!;\n"); verifyFormat("let x = foo! - 1;\n"); verifyFormat("let x = {foo: 1}!;\n"); + verifyFormat( + "let x = hello.foo()!\n" + " .foo()!\n" + " .foo()!\n" + " .foo()!;\n", + getGoogleJSStyleWithColumns(20)); } TEST_F(FormatTestJS, Conditional) { @@ -1548,6 +1747,5 @@ TEST_F(FormatTestJS, ImportComments) { getGoogleJSStyleWithColumns(25)); verifyFormat("// taze: x from 'location'", getGoogleJSStyleWithColumns(10)); } - } // end namespace tooling } // end namespace clang |