diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -939,6 +939,8 @@ GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; GoogleStyle.AlignOperands = false; GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; + // TODO: still under discussion whether to switch to SLS_All. + GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty; GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; GoogleStyle.BreakBeforeTernaryOperators = false; // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -3144,6 +3144,26 @@ // JavaScript top-level enum key/value pairs are put on separate lines // instead of bin-packing. return true; + if (Right.is(tok::r_brace) && Left.is(tok::l_brace) && Left.Previous && + Left.Previous->is(TT_JsFatArrow)) { + // JS arrow function (=> {...}). + switch (Style.AllowShortLambdasOnASingleLine) { + case FormatStyle::SLS_All: + return false; + case FormatStyle::SLS_None: + return true; + case FormatStyle::SLS_Empty: + return !Left.Children.empty(); + case FormatStyle::SLS_Inline: + // allow one-lining inline (e.g. in function call args) and empty arrow + // functions. + return (Left.NestingLevel == 0 && Line.Level == 0) && + !Left.Children.empty(); + default: + break; + } + } + if (Right.is(tok::r_brace) && Left.is(tok::l_brace) && !Left.Children.empty()) // Support AllowShortFunctionsOnASingleLine for JavaScript. diff --git a/clang/unittests/Format/FormatTestJS.cpp b/clang/unittests/Format/FormatTestJS.cpp --- a/clang/unittests/Format/FormatTestJS.cpp +++ b/clang/unittests/Format/FormatTestJS.cpp @@ -459,8 +459,9 @@ // Arrow functions in object literals. verifyFormat("var x = {\n" " y: (a) => {\n" + " x();\n" " return a;\n" - " }\n" + " },\n" "};"); verifyFormat("var x = {y: (a) => a};"); @@ -486,7 +487,8 @@ // Object literals can leave out labels. verifyFormat("f({a}, () => {\n" - " g(); //\n" + " x;\n" + " g();\n" "});"); // Keys can be quoted. @@ -1112,8 +1114,9 @@ TEST_F(FormatTestJS, ArrowFunctions) { verifyFormat("var x = (a) => {\n" + " x;\n" " return a;\n" - "};"); + "};\n"); verifyFormat("var x = (a) => {\n" " function y() {\n" " return 42;\n" @@ -1121,6 +1124,7 @@ " return a;\n" "};"); verifyFormat("var x = (a: type): {some: type} => {\n" + " y;\n" " return a;\n" "};"); verifyFormat("var x = (a) => a;"); @@ -1147,10 +1151,41 @@ " // break\n" " );"); verifyFormat("const f = (x: string|null): string|null => {\n" + " y;\n" " return x;\n" "}\n"); } +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); + verifyFormat("const arrInlineEmpty = () => {};", + Style); + Style.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Inline; + verifyFormat("const arr = () => {\n" + " x;\n" + "};", + Style); + verifyFormat("foo(() => {});", + Style); + verifyFormat("const arrInlineInline = () => {};", Style); +} + TEST_F(FormatTestJS, ReturnStatements) { verifyFormat("function() {\n" " return [hello, world];\n" @@ -1711,10 +1746,12 @@ TEST_F(FormatTestJS, RemoveEmptyLinesInArrowFunctions) { verifyFormat("x = () => {\n" " foo();\n" + " bar();\n" "};\n", "x = () => {\n" "\n" " foo();\n" + " bar();\n" "\n" "};\n"); } @@ -1791,6 +1828,10 @@ "];"); verifyFormat("export default [];"); verifyFormat("export default () => {};"); + verifyFormat("export default () => {\n" + " x;\n" + " x;\n" + "};"); verifyFormat("export interface Foo {\n" " foo: number;\n" "}\n"