Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -1077,12 +1077,20 @@ checkEmptyNamespace(AnnotatedLines); + // Trailing or duplicated commas have semantic meaning in JS, e.g. + // x = [a,,b]; + // creates an array with three elements, one of them undefined. + bool CleanUpCommas = Style.Language != FormatStyle::LK_JavaScript; + for (auto &Line : AnnotatedLines) { if (Line->Affected) { - cleanupRight(Line->First, tok::comma, tok::comma); + if (CleanUpCommas) + cleanupRight(Line->First, tok::comma, tok::comma); cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma); - cleanupRight(Line->First, tok::l_paren, tok::comma); - cleanupLeft(Line->First, tok::comma, tok::r_paren); + if (CleanUpCommas) { + cleanupRight(Line->First, tok::l_paren, tok::comma); + cleanupLeft(Line->First, tok::comma, tok::r_paren); + } cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace); cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace); cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal); Index: unittests/Format/CleanupTest.cpp =================================================================== --- unittests/Format/CleanupTest.cpp +++ unittests/Format/CleanupTest.cpp @@ -36,11 +36,12 @@ // Returns code after cleanup around \p Offsets. std::string cleanupAroundOffsets(llvm::ArrayRef Offsets, - llvm::StringRef Code) { + llvm::StringRef Code, + const FormatStyle &Style = getLLVMStyle()) { std::vector Ranges; for (auto Offset : Offsets) Ranges.push_back(tooling::Range(Offset, 0)); - return cleanup(Code, Ranges); + return cleanup(Code, Ranges, Style); } }; @@ -171,6 +172,14 @@ EXPECT_EQ(Expected, cleanupAroundOffsets({17, 22}, Code)); } +TEST_F(CleanupTest, ListRedundantCommaJavaScript) { + std::string Code = "function f() { var x = [a, b, , c]; }"; + std::string Expected = "function f() { var x = [a, b, , c]; }"; + const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript); + + EXPECT_EQ(Expected, cleanupAroundOffsets({30}, Code, Style)); +} + TEST_F(CleanupTest, TrailingCommaInParens) { std::string Code = "int main() { f(,1,,2,3,f(1,2,),4,,);}"; std::string Expected = "int main() { f(1,2,3,f(1,2),4);}";