diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index dd7e991342715..ea3bbe368d5b0 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -396,6 +396,21 @@ struct FormatToken { } } + /// \brief Returns \c true if this is a string literal that's like a label, + /// e.g. ends with "=" or ":". + bool isLabelString() const { + if (!is(tok::string_literal)) + return false; + StringRef Content = TokenText; + if (Content.startswith("\"") || Content.startswith("'")) + Content = Content.drop_front(1); + if (Content.endswith("\"") || Content.endswith("'")) + Content = Content.drop_back(1); + Content = Content.trim(); + return Content.size() > 1 && + (Content.back() == ':' || Content.back() == '='); + } + /// \brief Returns actual token start location without leading escaped /// newlines and whitespace. /// diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 4db0e937afc03..77b6a5d4d26bb 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1882,8 +1882,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, return 100; } - if (Left.is(tok::comma) || (Right.is(tok::identifier) && Right.Next && - Right.Next->is(TT_DictLiteral))) + if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral)) return 1; if (Right.is(tok::l_square)) { if (Style.Language == FormatStyle::LK_Proto) @@ -1999,21 +1998,17 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, if (Left.is(TT_JavaAnnotation)) return 50; - if (Right.is(tok::lessless)) { - if (Left.is(tok::string_literal) && - (Right.NextOperator || Right.OperatorIndex != 1)) { - StringRef Content = Left.TokenText; - if (Content.startswith("\"")) - Content = Content.drop_front(1); - if (Content.endswith("\"")) - Content = Content.drop_back(1); - Content = Content.trim(); - if (Content.size() > 1 && - (Content.back() == ':' || Content.back() == '=')) - return 25; - } + if (Left.isOneOf(tok::plus, tok::comma) && Left.Previous && + Left.Previous->isLabelString() && + (Left.NextOperator || Left.OperatorIndex != 1)) + return 100; + if (Left.is(tok::comma)) + return 1; + if (Right.isOneOf(tok::lessless, tok::plus) && Left.isLabelString() && + (Right.NextOperator || Right.OperatorIndex != 1)) + return 25; + if (Right.is(tok::lessless)) return 1; // Breaking at a << is really cheap. - } if (Left.is(TT_ConditionalExpr)) return prec::Conditional; prec::Level Level = Left.getPrecedence(); @@ -2631,7 +2626,8 @@ void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) { << " FakeLParens="; for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i) llvm::errs() << Tok->FakeLParens[i] << "/"; - llvm::errs() << " FakeRParens=" << Tok->FakeRParens << "\n"; + llvm::errs() << " FakeRParens=" << Tok->FakeRParens; + llvm::errs() << " Text='" << Tok->TokenText << "'\n"; if (!Tok->Next) assert(Tok == Line.Last); Tok = Tok->Next; diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 5bed7a81de190..adf529cfedacd 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -5109,29 +5109,6 @@ TEST_F(FormatTest, AlignsPipes) { "llvm::errs() << aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaa);"); - verifyFormat("return out << \"somepacket = {\\n\"\n" - " << \" aaaaaa = \" << pkt.aaaaaa << \"\\n\"\n" - " << \" bbbb = \" << pkt.bbbb << \"\\n\"\n" - " << \" cccccc = \" << pkt.cccccc << \"\\n\"\n" - " << \" ddd = [\" << pkt.ddd << \"]\\n\"\n" - " << \"}\";"); - - verifyFormat("llvm::outs() << \"aaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaa\n" - " << \"aaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaa\n" - " << \"aaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaa;"); - verifyFormat( - "llvm::outs() << \"aaaaaaaaaaaaaaaaa = \" << aaaaaaaaaaaaaaaaa\n" - " << \"bbbbbbbbbbbbbbbbb = \" << bbbbbbbbbbbbbbbbb\n" - " << \"ccccccccccccccccc = \" << ccccccccccccccccc\n" - " << \"ddddddddddddddddd = \" << ddddddddddddddddd\n" - " << \"eeeeeeeeeeeeeeeee = \" << eeeeeeeeeeeeeeeee;"); - verifyFormat("llvm::outs() << aaaaaaaaaaaaaaaaaaaaaaaa << \"=\"\n" - " << bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb;"); - verifyFormat( - "void f() {\n" - " llvm::outs() << \"aaaaaaaaaaaaaaaaaaaa: \"\n" - " << aaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaa);\n" - "}"); verifyFormat("llvm::outs() << \"aaaaaaaaaaaaaaaa: \"\n" " << aaaaaaaa.aaaaaaaaaaaa(aaa)->aaaaaaaaaaaaaa();"); verifyFormat("llvm::errs() << aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" @@ -5142,22 +5119,6 @@ TEST_F(FormatTest, AlignsPipes) { " bbb)\n" " << a << b;"); - // Breaking before the first "<<" is generally not desirable. - verifyFormat( - "llvm::errs()\n" - " << \"aaaaaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" - " << \"aaaaaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" - " << \"aaaaaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" - " << \"aaaaaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaaaaaaaaaaaaaa;", - getLLVMStyleWithColumns(70)); - verifyFormat("llvm::errs() << \"aaaaaaaaaaaaaaaaaaa: \"\n" - " << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" - " << \"aaaaaaaaaaaaaaaaaaa: \"\n" - " << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" - " << \"aaaaaaaaaaaaaaaaaaa: \"\n" - " << aaaaaaaaaaaaaaaaaaaaaaaaaaaa;", - getLLVMStyleWithColumns(70)); - // But sometimes, breaking before the first "<<" is desirable. verifyFormat("Diag(aaaaaaaaaaaaaaaaaaaa, aaaaaaaa)\n" " << aaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaa);"); @@ -5203,6 +5164,55 @@ TEST_F(FormatTest, AlignsPipes) { verifyFormat("llvm::errs() << \"\\n\" << bbbbbbbbbbbbbbbbbbbbbb << \"\\n\";"); } +TEST_F(FormatTest, KeepStringLabelValuePairsOnALine) { + verifyFormat("return out << \"somepacket = {\\n\"\n" + " << \" aaaaaa = \" << pkt.aaaaaa << \"\\n\"\n" + " << \" bbbb = \" << pkt.bbbb << \"\\n\"\n" + " << \" cccccc = \" << pkt.cccccc << \"\\n\"\n" + " << \" ddd = [\" << pkt.ddd << \"]\\n\"\n" + " << \"}\";"); + + verifyFormat("llvm::outs() << \"aaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaa\n" + " << \"aaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaa\n" + " << \"aaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaa;"); + verifyFormat( + "llvm::outs() << \"aaaaaaaaaaaaaaaaa = \" << aaaaaaaaaaaaaaaaa\n" + " << \"bbbbbbbbbbbbbbbbb = \" << bbbbbbbbbbbbbbbbb\n" + " << \"ccccccccccccccccc = \" << ccccccccccccccccc\n" + " << \"ddddddddddddddddd = \" << ddddddddddddddddd\n" + " << \"eeeeeeeeeeeeeeeee = \" << eeeeeeeeeeeeeeeee;"); + verifyFormat("llvm::outs() << aaaaaaaaaaaaaaaaaaaaaaaa << \"=\"\n" + " << bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb;"); + verifyFormat( + "void f() {\n" + " llvm::outs() << \"aaaaaaaaaaaaaaaaaaaa: \"\n" + " << aaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaa);\n" + "}"); + + // Breaking before the first "<<" is generally not desirable. + verifyFormat( + "llvm::errs()\n" + " << \"aaaaaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " << \"aaaaaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " << \"aaaaaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " << \"aaaaaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaaaaaaaaaaaaaa;", + getLLVMStyleWithColumns(70)); + verifyFormat("llvm::errs() << \"aaaaaaaaaaaaaaaaaaa: \"\n" + " << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " << \"aaaaaaaaaaaaaaaaaaa: \"\n" + " << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " << \"aaaaaaaaaaaaaaaaaaa: \"\n" + " << aaaaaaaaaaaaaaaaaaaaaaaaaaaa;", + getLLVMStyleWithColumns(70)); + + verifyFormat("string v = \"aaaaaaaaaaaaaaaa: \" + aaaaaaaaaaaaaaaa +\n" + " \"aaaaaaaaaaaaaaaa: \" + aaaaaaaaaaaaaaaa +\n" + " \"aaaaaaaaaaaaaaaa: \" + aaaaaaaaaaaaaaaa;"); + verifyFormat("string v = StrCat(\"aaaaaaaaaaaaaaaa: \", aaaaaaaaaaaaaaaa,\n" + " \"aaaaaaaaaaaaaaaa: \", aaaaaaaaaaaaaaaa,\n" + " \"aaaaaaaaaaaaaaaa: \", aaaaaaaaaaaaaaaa);"); +} + TEST_F(FormatTest, UnderstandsEquals) { verifyFormat( "aaaaaaaaaaaaaaaaa =\n"