Author: Martin Probst Date: 2020-01-27T16:27:25+01:00 New Revision: 02656f29abda4eedd22e3b2b30bf2f422983514e
URL: https://github.com/llvm/llvm-project/commit/02656f29abda4eedd22e3b2b30bf2f422983514e DIFF: https://github.com/llvm/llvm-project/commit/02656f29abda4eedd22e3b2b30bf2f422983514e.diff LOG: clang-format: [JS] options for arrow functions. Summary: clang-format currently always wraps the body of non-empty arrow functions: const x = () => { z(); }; This change implements support for the `AllowShortLambdasOnASingleLine` style options, controlling the indent style for arrow function bodies that have one or fewer statements. SLS_All puts all on a single line, SLS_Inline only arrow functions used in an inline position. const x = () => { z(); }; Multi-statement arrow functions continue to be wrapped. Function expressions (`a = function() {}`) and function/method declarations are unaffected as well. Reviewers: krasimir Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D73335 Added: Modified: clang/lib/Format/Format.cpp clang/lib/Format/TokenAnnotator.cpp clang/unittests/Format/FormatTestJS.cpp Removed: ################################################################################ diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index a962e32f66b0..bc9551756bee 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -939,6 +939,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { 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 index 723dc5c7ba88..8f9a29ab2f29 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -3144,6 +3144,26 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, // 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 index ef3c6361355a..3c104b7aadbe 100644 --- a/clang/unittests/Format/FormatTestJS.cpp +++ b/clang/unittests/Format/FormatTestJS.cpp @@ -459,8 +459,9 @@ TEST_F(FormatTestJS, ContainerLiterals) { // 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 @@ TEST_F(FormatTestJS, ContainerLiterals) { // 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, MultipleFunctionLiterals) { 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 @@ TEST_F(FormatTestJS, ArrowFunctions) { " 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 @@ TEST_F(FormatTestJS, ArrowFunctions) { " // 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, TypeInterfaceLineWrapping) { 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 @@ TEST_F(FormatTestJS, Modules) { "];"); verifyFormat("export default [];"); verifyFormat("export default () => {};"); + verifyFormat("export default () => {\n" + " x;\n" + " x;\n" + "};"); verifyFormat("export interface Foo {\n" " foo: number;\n" "}\n" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits