From: Daniel Jasper Date: Wed, 5 Dec 2012 14:57:28 +0000 (+0000) Subject: Indentation fixes for clang-format. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=33182dd0f7d5b5e913b1957c2cb6dc04942efd46;p=clang Indentation fixes for clang-format. - Fix behavior of memoization together with optimization - Correctly attribute the PenaltyIndentLevel (breaking directly after "(" did not count towards the inner level) - Recognize more tokens as assignments Review: http://llvm-reviews.chandlerc.com/D172 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@169384 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 78450469f5..030e35e38d 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -28,10 +28,18 @@ namespace format { // FIXME: Move somewhere sane. struct TokenAnnotation { - enum TokenType { TT_Unknown, TT_TemplateOpener, TT_TemplateCloser, - TT_BinaryOperator, TT_UnaryOperator, TT_OverloadedOperator, - TT_PointerOrReference, TT_ConditionalExpr, TT_LineComment, - TT_BlockComment }; + enum TokenType { + TT_Unknown, + TT_TemplateOpener, + TT_TemplateCloser, + TT_BinaryOperator, + TT_UnaryOperator, + TT_OverloadedOperator, + TT_PointerOrReference, + TT_ConditionalExpr, + TT_LineComment, + TT_BlockComment + }; TokenType Type; @@ -85,7 +93,6 @@ public: void format() { unsigned Indent = formatFirstToken(); - count = 0; IndentState State; State.Column = Indent + Line.Tokens[0].Tok.getLength(); State.CtorInitializerOnNewLine = false; @@ -230,9 +237,6 @@ private: ++State.ConsumedTokens; } - typedef std::map StateMap; - StateMap Memory; - unsigned splitPenalty(const FormatToken &Token) { if (Token.Tok.is(tok::semi)) return 0; @@ -272,36 +276,41 @@ private: if (NewLine && State.InCtorInitializer && !State.CtorInitializerOnNewLine) return UINT_MAX; - addTokenToState(NewLine, true, State); - - // Exceeding column limit is bad. - if (State.Column > Style.ColumnLimit) - return UINT_MAX; - unsigned CurrentPenalty = 0; if (NewLine) { CurrentPenalty += Parameters.PenaltyIndentLevel * State.Indent.size() + Parameters.PenaltyExtraLine + - splitPenalty(Line.Tokens[State.ConsumedTokens - 2]); + splitPenalty(Line.Tokens[State.ConsumedTokens - 1]); } + addTokenToState(NewLine, true, State); + + // Exceeding column limit is bad. + if (State.Column > Style.ColumnLimit) + return UINT_MAX; + if (StopAt <= CurrentPenalty) return UINT_MAX; StopAt -= CurrentPenalty; - // Has this state already been examined? StateMap::iterator I = Memory.find(State); - if (I != Memory.end()) - return I->second; - ++count; + if (I != Memory.end()) { + // If this state has already been examined, we can safely return the + // previous result if we + // - have not hit the optimatization (and thus returned UINT_MAX) OR + // - are now computing for a smaller or equal StopAt. + unsigned SavedResult = I->second.first; + unsigned SavedStopAt = I->second.second; + if (SavedResult != UINT_MAX || StopAt <= SavedStopAt) + return SavedResult; + } unsigned NoBreak = calcPenalty(State, false, StopAt); unsigned WithBreak = calcPenalty(State, true, std::min(StopAt, NoBreak)); unsigned Result = std::min(NoBreak, WithBreak); if (Result != UINT_MAX) Result += CurrentPenalty; - Memory[State] = Result; - assert(Memory.find(State) != Memory.end()); + Memory[State] = std::pair(Result, StopAt); return Result; } @@ -340,9 +349,12 @@ private: const UnwrappedLine &Line; const std::vector &Annotations; tooling::Replacements &Replaces; - unsigned int count; bool StructuralError; + // A map from an indent state to a pair (Result, Used-StopAt). + typedef std::map > StateMap; + StateMap Memory; + OptimizationParameters Parameters; }; @@ -548,16 +560,18 @@ public: private: void determineTokenTypes() { - bool EqualEncountered = false; + bool AssignmentEncountered = false; for (int i = 0, e = Line.Tokens.size(); i != e; ++i) { TokenAnnotation &Annotation = Annotations[i]; const FormatToken &Tok = Line.Tokens[i]; - if (Tok.Tok.is(tok::equal)) - EqualEncountered = true; + if (Tok.Tok.is(tok::equal) || Tok.Tok.is(tok::plusequal) || + Tok.Tok.is(tok::minusequal) || Tok.Tok.is(tok::starequal) || + Tok.Tok.is(tok::slashequal)) + AssignmentEncountered = true; if (Tok.Tok.is(tok::star) || Tok.Tok.is(tok::amp)) - Annotation.Type = determineStarAmpUsage(i, EqualEncountered); + Annotation.Type = determineStarAmpUsage(i, AssignmentEncountered); else if (isUnaryOperator(i)) Annotation.Type = TokenAnnotation::TT_UnaryOperator; else if (isBinaryOperator(Line.Tokens[i])) @@ -605,7 +619,7 @@ private: } TokenAnnotation::TokenType determineStarAmpUsage(unsigned Index, - bool EqualEncountered) { + bool AssignmentEncountered) { if (Index == Annotations.size()) return TokenAnnotation::TT_Unknown; @@ -620,7 +634,7 @@ private: // It is very unlikely that we are going to find a pointer or reference type // definition on the RHS of an assignment. - if (EqualEncountered) + if (AssignmentEncountered) return TokenAnnotation::TT_BinaryOperator; return TokenAnnotation::TT_PointerOrReference; @@ -676,8 +690,9 @@ private: return false; if (isBinaryOperator(Left)) return true; - return Right.Tok.is(tok::colon) || Left.Tok.is(tok::comma) || Left.Tok.is( - tok::semi) || Left.Tok.is(tok::equal) || Left.Tok.is(tok::ampamp) || + return Right.Tok.is(tok::colon) || Left.Tok.is(tok::comma) || + Left.Tok.is(tok::semi) || Left.Tok.is(tok::equal) || + Left.Tok.is(tok::ampamp) || Left.Tok.is(tok::pipepipe) || (Left.Tok.is(tok::l_paren) && !Right.Tok.is(tok::r_paren)); } diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index bdea42a2eb..c2cb5b8027 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -106,6 +106,12 @@ void UnwrappedLineParser::parseComment() { } void UnwrappedLineParser::parseStatement() { + // Consume leading line comments, e.g. for branches without compounds. + while (FormatTok.Tok.is(tok::comment)) { + nextToken(); + addUnwrappedLine(); + } + switch (FormatTok.Tok.getKind()) { case tok::kw_public: case tok::kw_protected: diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index be4363353e..c9860d595c 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -110,6 +110,7 @@ TEST_F(FormatTest, FormatIfWithoutCompountStatement) { verifyFormat("if (true)\n f();\ng();"); verifyFormat("if (a)\n if (b)\n if (c)\n g();\nh();"); verifyFormat("if (a)\n if (b) {\n f();\n }\ng();"); + EXPECT_EQ("if (a)\n // comment\n f();", format("if(a)\n// comment\nf();")); } TEST_F(FormatTest, ParseIfThenElse) { @@ -277,6 +278,17 @@ TEST_F(FormatTest, BreaksDesireably) { " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)),\n" " aaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)));"); + + verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n" + " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);"); + + // This test case breaks on an incorrect memoization, i.e. an optimization not + // taking into account the StopAt value. + verifyFormat( + "return aaaaaaaaaaaaaaaaaaaaaaaa || aaaaaaaaaaaaaaaaaaaaaaa ||\n" + " aaaaaaaaaaa(aaaaaaaaa) || aaaaaaaaaaaaaaaaaaaaaaa ||\n" + " aaaaaaaaaaaaaaaaaaaaaaaaa || aaaaaaaaaaaaaaaaaaaaaaa ||\n" + " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);"); } TEST_F(FormatTest, AlignsStringLiterals) { @@ -350,6 +362,10 @@ TEST_F(FormatTest, UnderstandsUsesOfStar) { verifyFormat("int a = b * 10;"); verifyFormat("int a = 10 * b;"); verifyFormat("int a = b * c;"); + verifyFormat("int a += b * c;"); + verifyFormat("int a -= b * c;"); + verifyFormat("int a *= b * c;"); + verifyFormat("int a /= b * c;"); verifyFormat("int a = *b;"); verifyFormat("int a = *b * c;"); verifyFormat("int a = b * *c;");