HazardyKnusperkeks created this revision.
HazardyKnusperkeks added reviewers: MyDeveloperDay, curdeius, nikola.
HazardyKnusperkeks added a project: clang-format.
HazardyKnusperkeks requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Breaking a string literal or a function calls arguments with
AlignConsecutiveDeclarations or AlignConsecutiveAssignments did misalign
the contiued line. E.g.:
void foo() {
int myVar = 5;
double x = 3.14;
auto str = "Hello"
"World";
}
or
void foo() {
int myVar = 5;
double x = 3.14;
auto str = "Hello"
"World";
}
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D98214
Files:
clang/lib/Format/WhitespaceManager.cpp
clang/unittests/Format/FormatTest.cpp
Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -14297,6 +14297,94 @@
Alignment);
}
+TEST_F(FormatTest, AlignWithLineBreaks) {
+ auto Style = getLLVMStyleWithColumns(120);
+
+ EXPECT_EQ(Style.AlignConsecutiveAssignments, FormatStyle::ACS_None);
+ EXPECT_EQ(Style.AlignConsecutiveDeclarations, FormatStyle::ACS_None);
+ verifyFormat("void foo() {\n"
+ " int myVar = 5;\n"
+ " double x = 3.14;\n"
+ " auto str = \"Hello \"\n"
+ " \"World\";\n"
+ "}",
+ Style);
+
+ // clang-format off
+ verifyFormat("void foo() {\n"
+ " const int capacityBefore = Entries.capacity();\n"
+ " const auto newEntry = Entries.emplaceHint(std::piecewise_construct, std::forward_as_tuple(uniqueId),\n"
+ " std::forward_as_tuple(id, uniqueId, name, threadCreation));\n"
+ " const X newEntry2 = Entries.emplaceHint(std::piecewise_construct, std::forward_as_tuple(uniqueId),\n"
+ " std::forward_as_tuple(id, uniqueId, name, threadCreation));\n"
+ "}",
+ Style);
+ // clang-format on
+
+ Style.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
+ verifyFormat("void foo() {\n"
+ " int myVar = 5;\n"
+ " double x = 3.14;\n"
+ " auto str = \"Hello \"\n"
+ " \"World\";\n"
+ "}",
+ Style);
+
+ // clang-format off
+ verifyFormat("void foo() {\n"
+ " const int capacityBefore = Entries.capacity();\n"
+ " const auto newEntry = Entries.emplaceHint(std::piecewise_construct, std::forward_as_tuple(uniqueId),\n"
+ " std::forward_as_tuple(id, uniqueId, name, threadCreation));\n"
+ " const X newEntry2 = Entries.emplaceHint(std::piecewise_construct, std::forward_as_tuple(uniqueId),\n"
+ " std::forward_as_tuple(id, uniqueId, name, threadCreation));\n"
+ "}",
+ Style);
+ // clang-format on
+
+ Style.AlignConsecutiveAssignments = FormatStyle::ACS_None;
+ Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+ verifyFormat("void foo() {\n"
+ " int myVar = 5;\n"
+ " double x = 3.14;\n"
+ " auto str = \"Hello \"\n"
+ " \"World\";\n"
+ "}",
+ Style);
+
+ // clang-format off
+ verifyFormat("void foo() {\n"
+ " const int capacityBefore = Entries.capacity();\n"
+ " const auto newEntry = Entries.emplaceHint(std::piecewise_construct, std::forward_as_tuple(uniqueId),\n"
+ " std::forward_as_tuple(id, uniqueId, name, threadCreation));\n"
+ " const X newEntry2 = Entries.emplaceHint(std::piecewise_construct, std::forward_as_tuple(uniqueId),\n"
+ " std::forward_as_tuple(id, uniqueId, name, threadCreation));\n"
+ "}",
+ Style);
+ // clang-format on
+
+ Style.AlignConsecutiveAssignments = FormatStyle::ACS_Consecutive;
+ Style.AlignConsecutiveDeclarations = FormatStyle::ACS_Consecutive;
+
+ verifyFormat("void foo() {\n"
+ " int myVar = 5;\n"
+ " double x = 3.14;\n"
+ " auto str = \"Hello \"\n"
+ " \"World\";\n"
+ "}",
+ Style);
+
+ // clang-format off
+ verifyFormat("void foo() {\n"
+ " const int capacityBefore = Entries.capacity();\n"
+ " const auto newEntry = Entries.emplaceHint(std::piecewise_construct, std::forward_as_tuple(uniqueId),\n"
+ " std::forward_as_tuple(id, uniqueId, name, threadCreation));\n"
+ " const X newEntry2 = Entries.emplaceHint(std::piecewise_construct, std::forward_as_tuple(uniqueId),\n"
+ " std::forward_as_tuple(id, uniqueId, name, threadCreation));\n"
+ "}",
+ Style);
+ // clang-format on
+}
+
TEST_F(FormatTest, LinuxBraceBreaking) {
FormatStyle LinuxBraceStyle = getLLVMStyle();
LinuxBraceStyle.BreakBeforeBraces = FormatStyle::BS_Linux;
Index: clang/lib/Format/WhitespaceManager.cpp
===================================================================
--- clang/lib/Format/WhitespaceManager.cpp
+++ clang/lib/Format/WhitespaceManager.cpp
@@ -277,7 +277,15 @@
// int b(int y,
// double z);
// In the above example, we need to take special care to ensure that
- // 'double z' is indented along with it's owning function 'b'.
+ // 'double z' is indented along with it's owning function 'b'. The same holds
+ // for calling a function:
+ // double a = foo(x);
+ // int b = bar(foo(y),
+ // foor(z));
+ // Similar for broken string literals:
+ // double x = 3.14;
+ // auto s = "Hello"
+ // "World";
// Special handling is required for 'nested' ternary operators.
SmallVector<unsigned, 16> ScopeStack;
@@ -298,8 +306,12 @@
ScopeStack.push_back(i);
bool InsideNestedScope = ScopeStack.size() != 0;
+ bool ContinuedStringLiteral = i > Start &&
+ Changes[i].Tok->is(tok::string_literal) &&
+ Changes[i - 1].Tok->is(tok::string_literal);
+ bool SkipMatchCheck = InsideNestedScope || ContinuedStringLiteral;
- if (Changes[i].NewlinesBefore > 0 && !InsideNestedScope) {
+ if (Changes[i].NewlinesBefore > 0 && !SkipMatchCheck) {
Shift = 0;
FoundMatchOnLine = false;
}
@@ -307,7 +319,7 @@
// If this is the first matching token to be aligned, remember by how many
// spaces it has to be shifted, so the rest of the changes on the line are
// shifted by the same amount
- if (!FoundMatchOnLine && !InsideNestedScope && Matches(Changes[i])) {
+ if (!FoundMatchOnLine && !SkipMatchCheck && Matches(Changes[i])) {
FoundMatchOnLine = true;
Shift = Column - Changes[i].StartOfTokenColumn;
Changes[i].Spaces += Shift;
@@ -320,12 +332,18 @@
if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName) ||
(ScopeStart > Start + 1 &&
Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName)) ||
+ (ScopeStart > Start + 1 &&
+ Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
+ Changes[ScopeStart - 1].Tok->is(tok::l_paren)) ||
Changes[i].Tok->is(TT_ConditionalExpr) ||
(Changes[i].Tok->Previous &&
Changes[i].Tok->Previous->is(TT_ConditionalExpr)))
Changes[i].Spaces += Shift;
}
+ if (ContinuedStringLiteral)
+ Changes[i].Spaces += Shift;
+
assert(Shift >= 0);
Changes[i].StartOfTokenColumn += Shift;
if (i + 1 != Changes.size())
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits