mprobst created this revision. Herald added a subscriber: klimek. clang-format already removes lines trailing at the end of blocks:
function x() { foo(); // next line will be removed. } However because JS arrow functions are parsed as expressions, the existing logic to remove empty lines in UnwrappedLineFormatter doesn't handle them. This code special cases arrow functions in ContinuationIndenter to remove any trailing spaces: x = () => { foo(); // next line will (now) be removed. }; https://reviews.llvm.org/D40178 Files: lib/Format/ContinuationIndenter.cpp unittests/Format/FormatTestJS.cpp Index: unittests/Format/FormatTestJS.cpp =================================================================== --- unittests/Format/FormatTestJS.cpp +++ unittests/Format/FormatTestJS.cpp @@ -1606,6 +1606,16 @@ Style); } +TEST_F(FormatTestJS, RemoveEmptyLinesTrailingArrowFunctions) { + verifyFormat("x = () => {\n" + " foo();\n" + "};\n", + "x = () => {\n" + " foo();\n" + "\n" + "};\n"); +} + TEST_F(FormatTestJS, Modules) { verifyFormat("import SomeThing from 'some/module.js';"); verifyFormat("import {X, Y} from 'some/module.js';"); Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -701,8 +701,18 @@ State.Stack.back().BreakBeforeParameter = false; if (!DryRun) { + unsigned MaxEmptyLinesToKeep = Style.MaxEmptyLinesToKeep + 1; + if (Style.Language == FormatStyle::LK_JavaScript && + Current.is(tok::r_brace) && Current.MatchingParen && + Current.MatchingParen->Previous && + Current.MatchingParen->Previous->is(TT_JsFatArrow)) { + // JavaScript arrow functions are experssions, thus their r_brace is not + // on its own line, and thus not covered by UnwrappedLineFormatter's logic + // about removing empty lines on closing blocks. Special case it here. + MaxEmptyLinesToKeep = 0; + } unsigned Newlines = std::max( - 1u, std::min(Current.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1)); + 1u, std::min(Current.NewlinesBefore, MaxEmptyLinesToKeep)); bool ContinuePPDirective = State.Line->InPPDirective && State.Line->Type != LT_ImportStatement; Whitespaces.replaceWhitespace(Current, Newlines, State.Column, State.Column,
Index: unittests/Format/FormatTestJS.cpp =================================================================== --- unittests/Format/FormatTestJS.cpp +++ unittests/Format/FormatTestJS.cpp @@ -1606,6 +1606,16 @@ Style); } +TEST_F(FormatTestJS, RemoveEmptyLinesTrailingArrowFunctions) { + verifyFormat("x = () => {\n" + " foo();\n" + "};\n", + "x = () => {\n" + " foo();\n" + "\n" + "};\n"); +} + TEST_F(FormatTestJS, Modules) { verifyFormat("import SomeThing from 'some/module.js';"); verifyFormat("import {X, Y} from 'some/module.js';"); Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -701,8 +701,18 @@ State.Stack.back().BreakBeforeParameter = false; if (!DryRun) { + unsigned MaxEmptyLinesToKeep = Style.MaxEmptyLinesToKeep + 1; + if (Style.Language == FormatStyle::LK_JavaScript && + Current.is(tok::r_brace) && Current.MatchingParen && + Current.MatchingParen->Previous && + Current.MatchingParen->Previous->is(TT_JsFatArrow)) { + // JavaScript arrow functions are experssions, thus their r_brace is not + // on its own line, and thus not covered by UnwrappedLineFormatter's logic + // about removing empty lines on closing blocks. Special case it here. + MaxEmptyLinesToKeep = 0; + } unsigned Newlines = std::max( - 1u, std::min(Current.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1)); + 1u, std::min(Current.NewlinesBefore, MaxEmptyLinesToKeep)); bool ContinuePPDirective = State.Line->InPPDirective && State.Line->Type != LT_ImportStatement; Whitespaces.replaceWhitespace(Current, Newlines, State.Column, State.Column,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits