diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index b07360425ca6e1..7d89f0e63dd225 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -842,10 +842,8 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, CurrentState.ContainsUnwrappedBuilder = true; } - if (Current.is(TT_TrailingReturnArrow) && - Style.Language == FormatStyle::LK_Java) { + if (Current.is(TT_LambdaArrow) && Style.Language == FormatStyle::LK_Java) CurrentState.NoLineBreak = true; - } if (Current.isMemberAccess() && Previous.is(tok::r_paren) && (Previous.MatchingParen && (Previous.TotalLength - Previous.MatchingParen->TotalLength > 10))) { @@ -1000,7 +998,7 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State, // // is common and should be formatted like a free-standing function. The same // goes for wrapping before the lambda return type arrow. - if (Current.isNot(TT_TrailingReturnArrow) && + if (Current.isNot(TT_LambdaArrow) && (!Style.isJavaScript() || Current.NestingLevel != 0 || !PreviousNonComment || PreviousNonComment->isNot(tok::equal) || !Current.isOneOf(Keywords.kw_async, Keywords.kw_function))) { @@ -1257,7 +1255,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { } return CurrentState.Indent; } - if (Current.is(TT_TrailingReturnArrow) && + if (Current.is(TT_LambdaArrow) && Previous.isOneOf(tok::kw_noexcept, tok::kw_mutable, tok::kw_constexpr, tok::kw_consteval, tok::kw_static, TT_AttributeSquare)) { return ContinuationIndent; @@ -1590,7 +1588,7 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, } if (Current.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) && Newline) CurrentState.NestedBlockIndent = State.Column + Current.ColumnWidth + 1; - if (Current.isOneOf(TT_LambdaLSquare, TT_TrailingReturnArrow)) + if (Current.isOneOf(TT_LambdaLSquare, TT_LambdaArrow)) CurrentState.LastSpace = State.Column; if (Current.is(TT_RequiresExpression) && Style.RequiresExpressionIndentation == FormatStyle::REI_Keyword) { diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index cc45d5a8c5c1ec..9bfeb2052164ee 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -102,6 +102,7 @@ namespace format { TYPE(JsTypeColon) \ TYPE(JsTypeOperator) \ TYPE(JsTypeOptionalQuestion) \ + TYPE(LambdaArrow) \ TYPE(LambdaLBrace) \ TYPE(LambdaLSquare) \ TYPE(LeadingJavaAnnotation) \ @@ -725,7 +726,7 @@ struct FormatToken { bool isMemberAccess() const { return isOneOf(tok::arrow, tok::period, tok::arrowstar) && !isOneOf(TT_DesignatedInitializerPeriod, TT_TrailingReturnArrow, - TT_LeadingJavaAnnotation); + TT_LambdaArrow, TT_LeadingJavaAnnotation); } bool isPointerOrReference() const { diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 851f79895ac5ac..07b42e79ba9a61 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -831,7 +831,7 @@ class AnnotatingParser { } // An arrow after an ObjC method expression is not a lambda arrow. if (CurrentToken->is(TT_ObjCMethodExpr) && CurrentToken->Next && - CurrentToken->Next->is(TT_TrailingReturnArrow)) { + CurrentToken->Next->is(TT_LambdaArrow)) { CurrentToken->Next->overwriteFixedType(TT_Unknown); } Left->MatchingParen = CurrentToken; @@ -1769,8 +1769,10 @@ class AnnotatingParser { } break; case tok::arrow: - if (Tok->Previous && Tok->Previous->is(tok::kw_noexcept)) + if (Tok->isNot(TT_LambdaArrow) && Tok->Previous && + Tok->Previous->is(tok::kw_noexcept)) { Tok->setType(TT_TrailingReturnArrow); + } break; case tok::equal: // In TableGen, there must be a value after "="; @@ -2056,11 +2058,11 @@ class AnnotatingParser { TT_LambdaLSquare, TT_LambdaLBrace, TT_AttributeMacro, TT_IfMacro, TT_ForEachMacro, TT_TypenameMacro, TT_FunctionLBrace, TT_ImplicitStringLiteral, TT_InlineASMBrace, TT_FatArrow, - TT_NamespaceMacro, TT_OverloadedOperator, TT_RegexLiteral, - TT_TemplateString, TT_ObjCStringLiteral, TT_UntouchableMacroFunc, - TT_StatementAttributeLikeMacro, TT_FunctionLikeOrFreestandingMacro, - TT_ClassLBrace, TT_EnumLBrace, TT_RecordLBrace, TT_StructLBrace, - TT_UnionLBrace, TT_RequiresClause, + TT_LambdaArrow, TT_NamespaceMacro, TT_OverloadedOperator, + TT_RegexLiteral, TT_TemplateString, TT_ObjCStringLiteral, + TT_UntouchableMacroFunc, TT_StatementAttributeLikeMacro, + TT_FunctionLikeOrFreestandingMacro, TT_ClassLBrace, TT_EnumLBrace, + TT_RecordLBrace, TT_StructLBrace, TT_UnionLBrace, TT_RequiresClause, TT_RequiresClauseInARequiresExpression, TT_RequiresExpression, TT_RequiresExpressionLParen, TT_RequiresExpressionLBrace, TT_BracedListLBrace)) { @@ -2246,7 +2248,7 @@ class AnnotatingParser { Contexts.back().IsExpression = true; } else if (Current.is(TT_TrailingReturnArrow)) { Contexts.back().IsExpression = false; - } else if (Current.is(Keywords.kw_assert)) { + } else if (Current.isOneOf(TT_LambdaArrow, Keywords.kw_assert)) { Contexts.back().IsExpression = Style.Language == FormatStyle::LK_Java; } else if (Current.Previous && Current.Previous->is(TT_CtorInitializerColon)) { @@ -2381,7 +2383,7 @@ class AnnotatingParser { AutoFound = true; } else if (Current.is(tok::arrow) && Style.Language == FormatStyle::LK_Java) { - Current.setType(TT_TrailingReturnArrow); + Current.setType(TT_LambdaArrow); } else if (Current.is(tok::arrow) && Style.isVerilog()) { // The implication operator. Current.setType(TT_BinaryOperator); @@ -3276,7 +3278,7 @@ class ExpressionParser { } if (Current->is(TT_JsComputedPropertyName)) return prec::Assignment; - if (Current->is(TT_TrailingReturnArrow)) + if (Current->is(TT_LambdaArrow)) return prec::Comma; if (Current->is(TT_FatArrow)) return prec::Assignment; @@ -4200,7 +4202,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, } if (Right.is(TT_PointerOrReference)) return 190; - if (Right.is(TT_TrailingReturnArrow)) + if (Right.is(TT_LambdaArrow)) return 110; if (Left.is(tok::equal) && Right.is(tok::l_brace)) return 160; @@ -5278,9 +5280,10 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, return false; } - if (Right.is(TT_TrailingReturnArrow) || Left.is(TT_TrailingReturnArrow)) + if (Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow) || + Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow)) { return true; - + } if (Left.is(tok::comma) && Right.isNot(TT_OverloadedOperatorLParen) && // In an unexpanded macro call we only find the parentheses and commas // in a line; the commas and closing parenthesis do not require a space. @@ -6298,8 +6301,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, return Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace, tok::kw_class, tok::kw_struct, tok::comment) || Right.isMemberAccess() || - Right.isOneOf(TT_TrailingReturnArrow, tok::lessless, tok::colon, - tok::l_square, tok::at) || + Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow, tok::lessless, + tok::colon, tok::l_square, tok::at) || (Left.is(tok::r_paren) && Right.isOneOf(tok::identifier, tok::kw_const)) || (Left.is(tok::l_paren) && Right.isNot(tok::r_paren)) || diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 688c7c5b1e977f..64a84e47512c76 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -2322,7 +2322,7 @@ bool UnwrappedLineParser::tryToParseLambda() { // This might or might not actually be a lambda arrow (this could be an // ObjC method invocation followed by a dereferencing arrow). We might // reset this back to TT_Unknown in TokenAnnotator. - FormatTok->setFinalizedType(TT_TrailingReturnArrow); + FormatTok->setFinalizedType(TT_LambdaArrow); SeenArrow = true; nextToken(); break; diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index c20b50d14b80b1..f82ccaa1ab719e 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -42,6 +42,8 @@ class TokenAnnotatorTest : public testing::Test { EXPECT_EQ((FormatTok)->getPrecedence(), Prec) << *(FormatTok) #define EXPECT_BRACE_KIND(FormatTok, Kind) \ EXPECT_EQ(FormatTok->getBlockKind(), Kind) << *(FormatTok) +#define EXPECT_SPLIT_PENALTY(FormatTok, Penalty) \ + EXPECT_EQ(FormatTok->SplitPenalty, Penalty) << *(FormatTok) #define EXPECT_TOKEN(FormatTok, Kind, Type) \ do { \ EXPECT_TOKEN_KIND(FormatTok, Kind); \ @@ -1695,19 +1697,19 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { Tokens = annotate("[]() -> auto {}"); ASSERT_EQ(Tokens.size(), 9u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); - EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow); + EXPECT_TOKEN(Tokens[4], tok::arrow, TT_LambdaArrow); EXPECT_TOKEN(Tokens[6], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() -> auto & {}"); ASSERT_EQ(Tokens.size(), 10u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); - EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow); + EXPECT_TOKEN(Tokens[4], tok::arrow, TT_LambdaArrow); EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() -> auto * {}"); ASSERT_EQ(Tokens.size(), 10u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); - EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow); + EXPECT_TOKEN(Tokens[4], tok::arrow, TT_LambdaArrow); EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] {}"); @@ -1723,19 +1725,19 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { Tokens = annotate("[] -> auto {}"); ASSERT_EQ(Tokens.size(), 7u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); - EXPECT_TOKEN(Tokens[2], tok::arrow, TT_TrailingReturnArrow); + EXPECT_TOKEN(Tokens[2], tok::arrow, TT_LambdaArrow); EXPECT_TOKEN(Tokens[4], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] -> struct S { return {}; }"); ASSERT_EQ(Tokens.size(), 12u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); - EXPECT_TOKEN(Tokens[2], tok::arrow, TT_TrailingReturnArrow); + EXPECT_TOKEN(Tokens[2], tok::arrow, TT_LambdaArrow); EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("foo([&](u32 bar) __attribute__((attr)) -> void {});"); ASSERT_EQ(Tokens.size(), 22u) << Tokens; EXPECT_TOKEN(Tokens[2], tok::l_square, TT_LambdaLSquare); - EXPECT_TOKEN(Tokens[15], tok::arrow, TT_TrailingReturnArrow); + EXPECT_TOKEN(Tokens[15], tok::arrow, TT_LambdaArrow); EXPECT_TOKEN(Tokens[17], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] () {}"); @@ -1816,7 +1818,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 20u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); - EXPECT_TOKEN(Tokens[10], tok::arrow, TT_TrailingReturnArrow); + EXPECT_TOKEN(Tokens[10], tok::arrow, TT_LambdaArrow); EXPECT_TOKEN(Tokens[12], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[16]->ClosesRequiresClause); EXPECT_TOKEN(Tokens[17], tok::l_brace, TT_LambdaLBrace); @@ -1877,7 +1879,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[6], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[10]->ClosesRequiresClause); - EXPECT_TOKEN(Tokens[11], tok::arrow, TT_TrailingReturnArrow); + EXPECT_TOKEN(Tokens[11], tok::arrow, TT_LambdaArrow); EXPECT_TOKEN(Tokens[13], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] requires Foo (T t) requires Bar {}"); @@ -3304,7 +3306,7 @@ TEST_F(TokenAnnotatorTest, FunctionTryBlock) { EXPECT_TOKEN(Tokens[3], tok::l_paren, TT_FunctionDeclarationLParen); EXPECT_TOKEN(Tokens[11], tok::colon, TT_CtorInitializerColon); EXPECT_TOKEN(Tokens[14], tok::l_square, TT_LambdaLSquare); - EXPECT_TOKEN(Tokens[16], tok::arrow, TT_TrailingReturnArrow); + EXPECT_TOKEN(Tokens[16], tok::arrow, TT_LambdaArrow); EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_LambdaLBrace); EXPECT_TOKEN(Tokens[31], tok::comma, TT_CtorInitializerComma); EXPECT_TOKEN(Tokens[36], tok::l_brace, TT_FunctionLBrace); @@ -3322,6 +3324,20 @@ TEST_F(TokenAnnotatorTest, TypenameMacro) { EXPECT_TOKEN(Tokens[6], tok::l_brace, TT_Unknown); } +TEST_F(TokenAnnotatorTest, SplitPenalty) { + auto Style = getLLVMStyle(); + Style.ColumnLimit = 20; + + auto Tokens = annotate("class foo {\n" + " auto bar()\n" + " -> bool;\n" + "};", + Style); + ASSERT_EQ(Tokens.size(), 13u) << Tokens; + EXPECT_TOKEN(Tokens[7], tok::arrow, TT_TrailingReturnArrow); + EXPECT_SPLIT_PENALTY(Tokens[7], 23u); +} + } // namespace } // namespace format } // namespace clang