diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -366,20 +366,28 @@ // instead of TheLine->First. if (Style.CompactNamespaces) { - if (auto nsToken = TheLine->First->getNamespaceToken()) { - int i = 0; - unsigned closingLine = TheLine->MatchingClosingBlockLineIndex - 1; - for (; I + 1 + i != E && - nsToken->TokenText == getNamespaceTokenText(I[i + 1]) && - closingLine == I[i + 1]->MatchingClosingBlockLineIndex && - I[i + 1]->Last->TotalLength < Limit; - i++, --closingLine) { - // No extra indent for compacted namespaces. - IndentTracker.skipLine(*I[i + 1]); + if (auto *nsToken = TheLine->First->getNamespaceToken()) { + int j = 1; + unsigned closingLineIndex = TheLine->MatchingClosingBlockLineIndex - 1; - Limit -= I[i + 1]->Last->TotalLength; + for (; I + j != E && + nsToken->TokenText == getNamespaceTokenText(I[j]) && + closingLineIndex == I[j]->MatchingClosingBlockLineIndex && + I[j]->Last->TotalLength < Limit; + j++, --closingLineIndex) { + Limit -= I[j]->Last->TotalLength; + + // Reduce indent level for bodies of namespaces which were compacted, + // but only if their content was indented in the first place + auto *closingLine = AnnotatedLines.begin() + closingLineIndex + 1; + auto dedentBy = I[j]->Level - TheLine->Level; + for (auto *compactedLine = I + j; compactedLine <= closingLine; + compactedLine++) { + if (!(*compactedLine)->InPPDirective) + (*compactedLine)->Level-= dedentBy; + } } - return i; + return j - 1; } if (auto nsToken = getMatchingNamespaceToken(TheLine, AnnotatedLines)) { diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -4431,6 +4431,24 @@ "int k; }} // namespace out::mid", Style)); + verifyFormat("namespace A { namespace B { namespace C {\n" + " int i;\n" + "}}} // namespace A::B::C\n" + "int main() {\n" + " if (true)\n" + " return 0;\n" + "}", + "namespace A { namespace B {\n" + "namespace C {\n" + " int i;\n" + "}} // namespace B::C\n" + "} // namespace A\n" + "int main() {\n" + " if (true)\n" + " return 0;\n" + "}", + Style); + Style.NamespaceIndentation = FormatStyle::NI_Inner; EXPECT_EQ("namespace out { namespace in {\n" " int i;\n"