From be94ccb27bc5cc8de428c67d1199ef992de982a1 Mon Sep 17 00:00:00 2001 From: Martin Probst Date: Tue, 7 Feb 2017 16:33:13 +0000 Subject: [PATCH] clang-format: [JS] correcly format object literal methods. Summary: In JavaScript, object literals can contain methods: var x = { a() { return 1; }, }; Previously, clang-format always parsed nested {} inside a braced list as further braced lists. Special case this logic for JavaScript to try parsing as a braced list, but fall back to parsing as a child block. Reviewers: djasper Subscribers: klimek, cfe-commits Differential Revision: https://reviews.llvm.org/D29656 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@294315 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/TokenAnnotator.cpp | 1 + lib/Format/UnwrappedLineParser.cpp | 25 +++++++++++++++++-------- unittests/Format/FormatTestJS.cpp | 12 ++++++++++++ 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index bfb74f0b96..940b5cc57e 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -2648,6 +2648,7 @@ void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) { << " T=" << getTokenTypeName(Tok->Type) << " S=" << Tok->SpacesRequiredBefore << " B=" << Tok->BlockParameterCount + << " BK=" << Tok->BlockKind << " P=" << Tok->SplitPenalty << " Name=" << Tok->Tok.getName() << " L=" << Tok->TotalLength << " PPK=" << Tok->PackingKind << " FakeLParens="; diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index 5ffada8ae7..5b6d0b73e4 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -335,8 +335,11 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) { case tok::l_brace: if (Style.Language == FormatStyle::LK_JavaScript && PrevTok && PrevTok->is(tok::colon)) - // In TypeScript's TypeMemberLists, there can be semicolons between the - // individual members. + // A colon indicates this code is in a type, or a braced list following + // a label in an object literal ({a: {b: 1}}). + // The code below could be confused by semicolons between the individual + // members in a type member list, which would normally trigger BK_Block. + // In both cases, this must be parsed as an inline braced init. Tok->BlockKind = BK_BracedInit; else Tok->BlockKind = BK_Unknown; @@ -1298,6 +1301,12 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) { continue; } } + if (FormatTok->is(tok::l_brace)) { + // Could be a method inside of a braced list `{a() { return 1; }}`. + if (tryToParseBracedList()) + continue; + parseChildBlock(); + } } switch (FormatTok->Tok.getKind()) { case tok::caret: @@ -1309,12 +1318,6 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) { case tok::l_square: tryToParseLambda(); break; - case tok::l_brace: - // Assume there are no blocks inside a braced init list apart - // from the ones we explicitly parse out (like lambdas). - FormatTok->BlockKind = BK_BracedInit; - parseBracedList(); - break; case tok::l_paren: parseParens(); // JavaScript can just have free standing methods and getters/setters in @@ -1325,6 +1328,12 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) { break; } break; + case tok::l_brace: + // Assume there are no blocks inside a braced init list apart + // from the ones we explicitly parse out (like lambdas). + FormatTok->BlockKind = BK_BracedInit; + parseBracedList(); + break; case tok::r_brace: nextToken(); return !HasError; diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp index 61acce3a97..4038e51259 100644 --- a/unittests/Format/FormatTestJS.cpp +++ b/unittests/Format/FormatTestJS.cpp @@ -240,6 +240,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" -- 2.40.0