Skip to content

[clang-format] revert to string << string handling to previous default #88490

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3359,6 +3359,50 @@ the configuration (without a prefix: ``Auto``).



.. _BreakStreamOperator:

**BreakStreamOperator** (``BreakStreamOperatorStyle``) :versionbadge:`clang-format 19` :ref:`¶ <BreakStreamOperator>`
Break Between Stream Operators.

Possible values:

* ``BCOS_Normal`` (in configuration: ``Normal``)
Break using ColumnLimit rules.

.. code-block:: c++

os << "aaaaa" << "bbbbb" << "\n";

* ``BCOS_BetweenStrings`` (in configuration: ``BetweenStrings``)
Break between adjacent strings.

.. code-block:: c++

os << "aaaaa"
<< "bbbbb"
<< "\n";

* ``BCOS_BetweenNewlineStrings`` (in configuration: ``BetweenNewlineStrings``)
Break between adjacent strings that end with \n.

.. code-block:: c++

os << "aaaaa\n"
<< "bbbbb" << "ccccc\n"
<< "\n";

* ``BCOS_Always`` (in configuration: ``Always``)
Break between adjacent stream operations.

.. code-block:: c++

os << "aaaaa\n"
<< "bbbbb"
<< "ccccc\n"
<< "\n";



.. _BreakStringLiterals:

**BreakStringLiterals** (``Boolean``) :versionbadge:`clang-format 3.9` :ref:`¶ <BreakStringLiterals>`
Expand Down
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,8 @@ clang-format
``BreakTemplateDeclarations``.
- ``AlwaysBreakAfterReturnType`` is deprecated and renamed to
``BreakAfterReturnType``.
- ``BreakStreamOperator`` Style is added and the previous default
of breaking between strings is reverted.

libclang
--------
Expand Down
36 changes: 36 additions & 0 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -2348,6 +2348,41 @@ struct FormatStyle {
/// \version 7
BreakInheritanceListStyle BreakInheritanceList;

/// Different ways to Break Between Stream Operators.
enum BreakStreamOperatorStyle : int8_t {
/// Break using ColumnLimit rules.
/// \code
/// os << "aaaaa" << "bbbbb" << "\n";
/// \endcode
BCOS_Normal,
/// Break between adjacent strings.
/// \code
/// os << "aaaaa"
/// << "bbbbb"
/// << "\n";
/// \endcode
BCOS_BetweenStrings,
/// Break between adjacent strings that end with \n.
/// \code
/// os << "aaaaa\n"
/// << "bbbbb" << "ccccc\n"
/// << "\n";
/// \endcode
BCOS_BetweenNewlineStrings,
/// Break between adjacent stream operations.
/// \code
/// os << "aaaaa\n"
/// << "bbbbb"
/// << "ccccc\n"
/// << "\n";
/// \endcode
BCOS_Always
};

/// Break Between Stream Operators.
/// \version 19
BreakStreamOperatorStyle BreakStreamOperator;

/// The template declaration breaking style to use.
/// \version 19
BreakTemplateDeclarationsStyle BreakTemplateDeclarations;
Expand Down Expand Up @@ -4951,6 +4986,7 @@ struct FormatStyle {
BreakBeforeConceptDeclarations == R.BreakBeforeConceptDeclarations &&
BreakBeforeInlineASMColon == R.BreakBeforeInlineASMColon &&
BreakBeforeTernaryOperators == R.BreakBeforeTernaryOperators &&
BreakStreamOperator == R.BreakStreamOperator &&
BreakConstructorInitializers == R.BreakConstructorInitializers &&
BreakFunctionDefinitionParameters ==
R.BreakFunctionDefinitionParameters &&
Expand Down
14 changes: 14 additions & 0 deletions clang/lib/Format/Format.cpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,18 @@ struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {
}
};

template <>
struct ScalarEnumerationTraits<FormatStyle::BreakStreamOperatorStyle> {
static void enumeration(IO &IO,
FormatStyle::BreakStreamOperatorStyle &Value) {
IO.enumCase(Value, "Normal", FormatStyle::BCOS_Normal);
IO.enumCase(Value, "BetweenStrings", FormatStyle::BCOS_BetweenStrings);
IO.enumCase(Value, "BetweenNewlineStrings",
FormatStyle::BCOS_BetweenNewlineStrings);
IO.enumCase(Value, "Always", FormatStyle::BCOS_Always);
}
};

template <>
struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
static void enumeration(IO &IO,
Expand Down Expand Up @@ -953,6 +965,7 @@ template <> struct MappingTraits<FormatStyle> {
Style.BreakBeforeInlineASMColon);
IO.mapOptional("BreakBeforeTernaryOperators",
Style.BreakBeforeTernaryOperators);
IO.mapOptional("BreakStreamOperator", Style.BreakStreamOperator);
IO.mapOptional("BreakConstructorInitializers",
Style.BreakConstructorInitializers);
IO.mapOptional("BreakFunctionDefinitionParameters",
Expand Down Expand Up @@ -1469,6 +1482,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
LLVMStyle.BreakFunctionDefinitionParameters = false;
LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
LLVMStyle.BreakStreamOperator = FormatStyle::BCOS_BetweenStrings;
LLVMStyle.BreakStringLiterals = true;
LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
LLVMStyle.ColumnLimit = 80;
Expand Down
42 changes: 38 additions & 4 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5598,11 +5598,45 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
// FIXME: Breaking after newlines seems useful in general. Turn this into an
// option and recognize more cases like endl etc, and break independent of
// what comes after operator lessless.
if (Right.is(tok::lessless) && Right.Next &&
Right.Next->is(tok::string_literal) && Left.is(tok::string_literal) &&
Left.TokenText.ends_with("\\n\"")) {
return true;
switch (Style.BreakStreamOperator) {
case FormatStyle::BCOS_BetweenStrings: {
if (Right.is(tok::lessless) && Right.Next && Left.is(tok::string_literal) &&
Right.Next->is(tok::string_literal)) {
return true;
}
break;
}
case FormatStyle::BCOS_BetweenNewlineStrings: {
if (Right.is(tok::lessless) && Right.Next &&
Right.Next->is(tok::string_literal) && Left.is(tok::string_literal) &&
Left.TokenText.ends_with("\\n\"")) {
return true;
}
break;
}
case FormatStyle::BCOS_Always: {
// Don't break after the very first << or >>
// but the Left token can be os or std::os so
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still don't understand the part of os or std::os.

// scan back
auto *FirstStream = Right.Previous;
while (FirstStream) {
if (FirstStream->isOneOf(tok::lessless, tok::greater))
break;
FirstStream = FirstStream->Previous;
}

if (Right.is(tok::lessless) && FirstStream)
return true;
if (Right.is(tok::greater) && Right.Next && Right.Next->is(tok::greater) &&
FirstStream) {
return true;
}
break;
}
case FormatStyle::BCOS_Normal:
break;
}

if (Right.is(TT_RequiresClause)) {
switch (Style.RequiresClausePosition) {
case FormatStyle::RCPS_OwnLine:
Expand Down
10 changes: 10 additions & 0 deletions clang/unittests/Format/ConfigParseTest.cpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,16 @@ TEST(ConfigParseTest, ParsesConfiguration) {
CHECK_PARSE("BreakBeforeInheritanceComma: true", BreakInheritanceList,
FormatStyle::BILS_BeforeComma);

Style.BreakStreamOperator = FormatStyle::BCOS_BetweenStrings;
CHECK_PARSE("BreakStreamOperator: BetweenNewlineStrings", BreakStreamOperator,
FormatStyle::BCOS_BetweenNewlineStrings);
CHECK_PARSE("BreakStreamOperator: Normal", BreakStreamOperator,
FormatStyle::BCOS_Normal);
CHECK_PARSE("BreakStreamOperator: BetweenStrings", BreakStreamOperator,
FormatStyle::BCOS_BetweenStrings);
CHECK_PARSE("BreakStreamOperator: Always", BreakStreamOperator,
FormatStyle::BCOS_Always);

Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
CHECK_PARSE("PackConstructorInitializers: Never", PackConstructorInitializers,
FormatStyle::PCIS_Never);
Expand Down
102 changes: 99 additions & 3 deletions clang/unittests/Format/FormatTest.cpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -27340,9 +27340,105 @@ TEST_F(FormatTest, PPDirectivesAndCommentsInBracedInit) {
}

TEST_F(FormatTest, StreamOutputOperator) {
verifyFormat("std::cout << \"foo\" << \"bar\" << baz;");
verifyFormat("std::cout << \"foo\\n\"\n"
" << \"bar\";");
auto Style = getLLVMStyle();

// This should be the default as it was the original style, thats
// been in place since the beginning.
verifyFormat("std::cout << \"aaaa\"\n"
" << \"bbbbb\";",
Style);
verifyFormat("std::cout << \"aaaa\"\n"
" << \"bbbbb\"\n"
" << \"ccc\";",
Style);
verifyFormat("std::cout << \"aaaa\"\n"
" << \"bbbbb\"\n"
" << \"cccc\"\n"
" << \"ddd\";",
Style);
verifyFormat("std::cout << \"aaaa\"\n"
" << \"bbbbb\" << baz << \"cccc\"\n"
" << \"ddd\";",
Style);

Style.BreakStreamOperator = FormatStyle::BCOS_Normal;
verifyFormat("std::cout << \"aaaa\" << \"bbb\" << baz;", Style);
verifyFormat("std::cout << \"ccc\\n\" << \"dddd\";", Style);

Style.BreakStreamOperator = FormatStyle::BCOS_BetweenStrings;
verifyFormat("std::cout << \"eee\"\n"
" << \"ffff\";",
Style);
verifyFormat("std::cout << \"aa\\n\"\n"
" << \"bbbb\";",
Style);

Style.BreakStreamOperator = FormatStyle::BCOS_BetweenNewlineStrings;
verifyFormat("std::cout << \"aaaa\" << \"bbb\" << baz;", Style);
verifyFormat("std::cout << \"ggg\\n\"\n"
" << \"dddd\";",
Style);

Style.BreakStreamOperator = FormatStyle::BCOS_Always;
verifyFormat("std::cout << \"aaaa\"\n"
" << \"bbb\"\n"
" << baz;",
Style);
verifyFormat("std::cout << \"ggg\\n\"\n"
" << \"dddd\";",
Style);
verifyFormat("std::cout << \"aaaa\"\n"
" << \"bbbbb\"\n"
" << \"cccc\"\n"
" << \"ddd\";",
Style);
verifyFormat("std::cout << \"aaaa\"\n"
" << \"bbbbb\"\n"
" << baz\n"
" << \"cccc\"\n"
" << \"ddd\";",
Style);
verifyFormat("cout << \"aaaa\"\n"
" << \"bbbbb\"\n"
" << baz\n"
" << \"cccc\"\n"
" << \"ddd\";",
Style);
}

TEST_F(FormatTest, StreamInputOperator) {
auto Style = getLLVMStyle();

Style.BreakStreamOperator = FormatStyle::BCOS_Normal;
verifyFormat("std::in >> aaaa >> bbb >> baz;", Style);
verifyFormat("std::in >> ccc >> dddd;", Style);

Style.BreakStreamOperator = FormatStyle::BCOS_Always;
verifyFormat("std::in >> ccc;", Style);
verifyFormat("std::in >> aaaa\n"
" >> bbb\n"
" >> baz;",
Style);
verifyFormat("std::in >> ggg\n"
" >> dddd;",
Style);
verifyFormat("std::in >> aaaa\n"
" >> bbbbb\n"
" >> cccc\n"
" >> ddd;",
Style);
verifyFormat("std::in >> aaaa\n"
" >> bbbbb\n"
" >> baz\n"
" >> cccc\n"
" >> ddd;",
Style);
verifyFormat("in >> aaaa\n"
" >> bbbbb\n"
" >> baz\n"
" >> cccc\n"
" >> ddd;",
Style);
}

TEST_F(FormatTest, BreakAdjacentStringLiterals) {
Expand Down