diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index b07360425ca6e..df86a774ba0f4 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -803,6 +803,37 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, return !Tok.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while, tok::kw_switch); }; + auto IsFunctionCallParen = [](const FormatToken &Tok) { + return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous && + Tok.Previous->is(tok::identifier); + }; + const auto IsInTemplateString = [this](const FormatToken &Tok) { + if (!Style.isJavaScript()) + return false; + for (const auto *Prev = &Tok; Prev; Prev = Prev->Previous) { + if (Prev->is(TT_TemplateString) && Prev->opensScope()) + return true; + if (Prev->is(TT_TemplateString) && Prev->closesScope()) + break; + } + return false; + }; + // Identifies simple (no expression) one-argument function calls. + const auto IsSimpleFunction = [&](const FormatToken &Tok) { + if (!Tok.FakeLParens.empty() && Tok.FakeLParens.back() > prec::Unknown) + return false; + const auto *Previous = Tok.Previous; + if (!Previous || (!Previous->isOneOf(TT_FunctionDeclarationLParen, + TT_LambdaDefinitionLParen) && + !IsFunctionCallParen(*Previous))) { + return true; + } + if (IsOpeningBracket(Tok) || IsInTemplateString(Tok)) + return true; + const auto *Next = Tok.Next; + return !Next || Next->isMemberAccess() || + Next->is(TT_FunctionDeclarationLParen) || IsFunctionCallParen(*Next); + }; if ((Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak || Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent) && IsOpeningBracket(Previous) && State.Column > getNewLineColumn(State) && @@ -813,10 +844,10 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, // caaaaaaaaaaaall( // caaaaaaaaaaaall( // caaaaaaaaaaaaaaaaaaaaaaall(aaaaaaaaaaaaaa, aaaaaaaaa)))); - Current.FakeLParens.size() > 0 && - Current.FakeLParens.back() > prec::Unknown) { + !IsSimpleFunction(Current)) { CurrentState.NoLineBreak = true; } + if (Previous.is(TT_TemplateString) && Previous.opensScope()) CurrentState.NoLineBreak = true; @@ -831,7 +862,8 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, Previous.isNot(TT_TableGenDAGArgOpenerToBreak) && !(Current.MacroParent && Previous.MacroParent) && (Current.isNot(TT_LineComment) || - Previous.isOneOf(BK_BracedInit, TT_VerilogMultiLineListLParen))) { + Previous.isOneOf(BK_BracedInit, TT_VerilogMultiLineListLParen)) && + !IsInTemplateString(Current)) { CurrentState.Indent = State.Column + Spaces; CurrentState.IsAligned = true; } diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index cc45d5a8c5c1e..abcedb66b57cc 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(LambdaDefinitionLParen) \ TYPE(LambdaLBrace) \ TYPE(LambdaLSquare) \ TYPE(LeadingJavaAnnotation) \ diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 21924a8fe17d1..6cdd339fdeb89 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -62,6 +62,7 @@ static bool canBeObjCSelectorComponent(const FormatToken &Tok) { /// With `Left` being '(', check if we're at either `[...](` or /// `[...]<...>(`, where the [ opens a lambda capture list. +// FIXME: this doesn't cover attributes/constraints before the l_paren. static bool isLambdaParameterList(const FormatToken *Left) { // Skip <...> if present. if (Left->Previous && Left->Previous->is(tok::greater) && @@ -365,6 +366,7 @@ class AnnotatingParser { Contexts.back().IsExpression = false; } else if (isLambdaParameterList(&OpeningParen)) { // This is a parameter list of a lambda expression. + OpeningParen.setType(TT_LambdaDefinitionLParen); Contexts.back().IsExpression = false; } else if (OpeningParen.is(TT_RequiresExpressionLParen)) { Contexts.back().IsExpression = false; @@ -6205,6 +6207,12 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, return !(Previous && (Previous->is(tok::kw_for) || Previous->isIf())); } + if (Left.isOneOf(tok::r_paren, TT_TrailingAnnotation) && + Right.is(TT_TrailingAnnotation) && + Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent) { + return false; + } + // Allow breaking after a trailing annotation, e.g. after a method // declaration. if (Left.is(TT_TrailingAnnotation)) { diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 39fcbab3447a7..d7f81813835fa 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -9338,6 +9338,31 @@ TEST_F(FormatTest, AlignsAfterOpenBracket) { " aaaaaaaaaaaaaaaa\n" ");", Style); + verifyFormat("bool aaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" + " const bool &aaaaaaaaa, const void *aaaaaaaaaa\n" + ") const {\n" + " return true;\n" + "}", + Style); + verifyFormat("bool aaaaaaaaaaaaaaaaaaaaaaaa(\n" + " const bool &aaaaaaaaaa, const void *aaaaaaaaaa\n" + ") const;", + Style); + verifyFormat("void aaaaaaaaa(\n" + " int aaaaaa, int bbbbbb, int cccccc, int dddddddddd\n" + ") const noexcept -> std::vector;", + Style); + verifyFormat( + "x = aaaaaaaaaaaaaaa(\n" + " \"a aaaaaaa aaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaa aaaaaaaaaaaaa\"\n" + ");", + Style); + Style.ColumnLimit = 60; + verifyFormat("auto lambda =\n" + " [&b](\n" + " auto aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " ) {};", + Style); } TEST_F(FormatTest, ParenthesesAndOperandAlignment) { diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index b01ca322505b1..1778cdc296d5b 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1665,38 +1665,45 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { auto Tokens = annotate("[]() constexpr {}"); ASSERT_EQ(Tokens.size(), 8u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() consteval {}"); ASSERT_EQ(Tokens.size(), 8u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() mutable {}"); ASSERT_EQ(Tokens.size(), 8u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() static {}"); ASSERT_EQ(Tokens.size(), 8u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() -> auto {}"); ASSERT_EQ(Tokens.size(), 9u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow); 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[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow); 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[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow); EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_LambdaLBrace); @@ -1725,6 +1732,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { 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[5], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[15], tok::arrow, TT_TrailingReturnArrow); EXPECT_TOKEN(Tokens[17], tok::l_brace, TT_LambdaLBrace); @@ -1732,6 +1740,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 11u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[8], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] {}"); @@ -1744,6 +1753,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 12u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[9], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] {}"); @@ -1756,6 +1766,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 12u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[9], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] {}"); @@ -1768,6 +1779,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 12u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[9], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] {}"); @@ -1781,6 +1793,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 18u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[10], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[14]->ClosesRequiresClause); EXPECT_TOKEN(Tokens[15], tok::l_brace, TT_LambdaLBrace); @@ -1789,6 +1802,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 19u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[8], tok::ampamp, TT_PointerOrReference); EXPECT_TOKEN(Tokens[11], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[15]->ClosesRequiresClause); @@ -1798,6 +1812,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 23u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[10], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[19]->ClosesRequiresClause); EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_LambdaLBrace); @@ -1806,6 +1821,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[6], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[10], tok::arrow, TT_TrailingReturnArrow); EXPECT_TOKEN(Tokens[12], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[16]->ClosesRequiresClause); @@ -1817,6 +1833,8 @@ 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); + // FIXME: + // EXPECT_TOKEN(Tokens[11], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[15], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] requires Bar (T &&t) {}"); @@ -1825,6 +1843,8 @@ 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); + // FIXME: + // EXPECT_TOKEN(Tokens[11], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[13], tok::ampamp, TT_PointerOrReference); EXPECT_TOKEN(Tokens[16], tok::l_brace, TT_LambdaLBrace); @@ -1834,6 +1854,8 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[6], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[15]->ClosesRequiresClause); + // FIXME: + // EXPECT_TOKEN(Tokens[16], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] requires true (T&& t) {}"); @@ -1842,6 +1864,8 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[6], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[7]->ClosesRequiresClause); + // FIXME: + // EXPECT_TOKEN(Tokens[8], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[10], tok::ampamp, TT_PointerOrReference); EXPECT_TOKEN(Tokens[13], tok::l_brace, TT_LambdaLBrace); @@ -1876,6 +1900,8 @@ 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); + // FIXME: + // EXPECT_TOKEN(Tokens[11], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[15], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[19]->ClosesRequiresClause); EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_LambdaLBrace); @@ -1885,6 +1911,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[8], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] (T t) {}"); @@ -1892,6 +1919,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[8], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] (T t) {}"); @@ -1899,6 +1927,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[8], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] (T&& t) {}"); @@ -1907,6 +1936,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[7], tok::ampamp, TT_BinaryOperator); EXPECT_TOKEN(Tokens[9], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[10], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[12], tok::ampamp, TT_PointerOrReference); EXPECT_TOKEN(Tokens[15], tok::l_brace, TT_LambdaLBrace); @@ -1916,6 +1946,8 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser); EXPECT_TOKEN(Tokens[8], tok::kw_requires, TT_RequiresClause); + // FIXME: + // EXPECT_TOKEN(Tokens[13], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[17], tok::l_brace, TT_LambdaLBrace); }