diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1886,14 +1886,16 @@ not use this in config files, etc. Use at your own risk. **FixNamespaceComments** (``bool``) - If ``true``, clang-format adds missing namespace end comments and - fixes invalid existing ones. + If ``true``, clang-format adds missing namespace end comments for + short namespaces and fixes invalid existing ones. Short ones are + controlled by "MaxUnwrappedLinesForShortNamespace". .. code-block:: c++ true: false: namespace a { vs. namespace a { foo(); foo(); + bar(); bar(); } // namespace a } **ForEachMacros** (``std::vector``) @@ -2458,6 +2460,28 @@ return i; } +**MaxUnwrappedLinesForShortNamespace** (``unsigned``) + The maximal number of unwrapped lines that a short namespace spans. + Defaults to 1. + + This determines the maximum length of short namespaces by counting + unwrapped lines (i.e. containing neither opening nor closing + namespace brace) and makes "FixNamespaceComments" omit adding + end comments for those. + + .. code-block:: c++ + + MaxUnwrappedLinesForShortNamespace: 1 vs. MaxUnwrappedLinesForShortNamespace: 0 + namespace a { namespace a { + int foo; int foo; + } } // namespace a + + MaxUnwrappedLinesForShortNamespace: 1 vs. MaxUnwrappedLinesForShortNamespace: 0 + namespace b { namespace b { + int foo; int foo; + int bar; int bar; + } // namespace b } // namespace b + **NamespaceIndentation** (``NamespaceIndentationKind``) The indentation used for namespaces. diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -1653,12 +1653,14 @@ /// not use this in config files, etc. Use at your own risk. bool ExperimentalAutoDetectBinPacking; - /// If ``true``, clang-format adds missing namespace end comments and - /// fixes invalid existing ones. + /// If ``true``, clang-format adds missing namespace end comments for + /// short namespaces and fixes invalid existing ones. Short ones are + /// controlled by "MaxUnwrappedLinesForShortNamespace". /// \code /// true: false: /// namespace a { vs. namespace a { /// foo(); foo(); + /// bar(); bar(); /// } // namespace a } /// \endcode bool FixNamespaceComments; @@ -2094,6 +2096,27 @@ /// \endcode unsigned MaxEmptyLinesToKeep; + /// The maximal number of unwrapped lines that a short namespace spans. + /// Defaults to 1. + /// + /// This determines the maximum length of short namespaces by counting + /// unwrapped lines (i.e. containing neither opening nor closing + /// namespace brace) and makes "FixNamespaceComments" omit adding + /// end comments for those. + /// \code + /// MaxUnwrappedLinesForShortNamespace: 1 vs. MaxUnwrappedLinesForShortNamespace: 0 + /// namespace a { namespace a { + /// int foo; int foo; + /// } } // namespace a + /// + /// MaxUnwrappedLinesForShortNamespace: 1 vs. MaxUnwrappedLinesForShortNamespace: 0 + /// namespace b { namespace b { + /// int foo; int foo; + /// int bar; int bar; + /// } // namespace b } // namespace b + /// \endcode + unsigned MaxUnwrappedLinesForShortNamespace; + /// Different ways to indent namespace contents. enum NamespaceIndentationKind { /// Don't indent in namespaces. @@ -2795,6 +2818,8 @@ MacroBlockBegin == R.MacroBlockBegin && MacroBlockEnd == R.MacroBlockEnd && MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep && + MaxUnwrappedLinesForShortNamespace == + R.MaxUnwrappedLinesForShortNamespace && NamespaceIndentation == R.NamespaceIndentation && NamespaceMacros == R.NamespaceMacros && ObjCBinPackProtocolList == R.ObjCBinPackProtocolList && diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -573,6 +573,8 @@ IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin); IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd); IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep); + IO.mapOptional("MaxUnwrappedLinesForShortNamespace", + Style.MaxUnwrappedLinesForShortNamespace); IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation); IO.mapOptional("NamespaceMacros", Style.NamespaceMacros); IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList); @@ -935,6 +937,7 @@ LLVMStyle.JavaScriptWrapImports = true; LLVMStyle.TabWidth = 8; LLVMStyle.MaxEmptyLinesToKeep = 1; + LLVMStyle.MaxUnwrappedLinesForShortNamespace = 1; LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true; LLVMStyle.NamespaceIndentation = FormatStyle::NI_None; LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto; diff --git a/clang/lib/Format/NamespaceEndCommentsFixer.cpp b/clang/lib/Format/NamespaceEndCommentsFixer.cpp --- a/clang/lib/Format/NamespaceEndCommentsFixer.cpp +++ b/clang/lib/Format/NamespaceEndCommentsFixer.cpp @@ -22,10 +22,6 @@ namespace format { namespace { -// The maximal number of unwrapped lines that a short namespace spans. -// Short namespaces don't need an end comment. -static const int kShortNamespaceMaxLines = 1; - // Computes the name of a namespace given the namespace token. // Returns "" for anonymous namespace. std::string computeName(const FormatToken *NamespaceTok) { @@ -280,7 +276,8 @@ const std::string EndCommentText = computeEndCommentText(NamespaceName, AddNewline, NamespaceTok); if (!hasEndComment(EndCommentPrevTok)) { - bool isShort = I - StartLineIndex <= kShortNamespaceMaxLines + 1; + bool isShort = + I - StartLineIndex <= Style.MaxUnwrappedLinesForShortNamespace + 1; if (!isShort) addEndComment(EndCommentPrevTok, EndCommentText, SourceMgr, &Fixes); } else if (!validEndComment(EndCommentPrevTok, NamespaceName, diff --git a/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp b/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp --- a/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp +++ b/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp @@ -816,7 +816,7 @@ "}\n")); } -TEST_F(NamespaceEndCommentsFixerTest, AddEndCommentForNamespacesAroundMacros) { +TEST_F(NamespaceEndCommentsFixerTest, AddsEndCommentForNamespacesAroundMacros) { // Conditional blocks around are fine EXPECT_EQ("namespace A {\n" "#if 1\n" @@ -1116,6 +1116,92 @@ "}\n" "}\n")); } + +using MaxUnwrappedLinesForShortNamespaceTest = NamespaceEndCommentsFixerTest; + +TEST_F(MaxUnwrappedLinesForShortNamespaceTest, DefaultsToOneUnwrappedLine) { + constexpr auto UnwrappedLines = 1u; + auto const Style = getLLVMStyle(); + + EXPECT_EQ(UnwrappedLines, Style.MaxUnwrappedLinesForShortNamespace); +} + +TEST_F(MaxUnwrappedLinesForShortNamespaceTest, + ZeroUnwrappedLines_DoesNotAddEndCommentForOneLinerNamespace) { + auto Style = getLLVMStyle(); + Style.MaxUnwrappedLinesForShortNamespace = 0; + + EXPECT_EQ("namespace OneLinerNamespace {}\n", + fixNamespaceEndComments("namespace OneLinerNamespace {}\n", Style)); +} + +TEST_F(MaxUnwrappedLinesForShortNamespaceTest, + ZeroUnwrappedLines_DoesNotAddEndCommentForNonOneLinerNamespace) { + auto Style = getLLVMStyle(); + Style.MaxUnwrappedLinesForShortNamespace = 0; + + EXPECT_EQ("namespace NonOneLinerNamespace {\n" + "}\n", + fixNamespaceEndComments("namespace NonOneLinerNamespace {\n" + "}\n", + Style)); +} + +TEST_F(MaxUnwrappedLinesForShortNamespaceTest, + OneUnwrappedLine_DoesNotAddEndCommentForShortNamespace) { + EXPECT_EQ("namespace ShortNamespace {\n" + "int i;\n" + "}\n", + fixNamespaceEndComments("namespace ShortNamespace {\n" + "int i;\n" + "}\n")); +} + +TEST_F(MaxUnwrappedLinesForShortNamespaceTest, + OneUnwrappedLine_AddsEndCommentForLongNamespace) { + EXPECT_EQ("namespace LongNamespace {\n" + "int i;\n" + "int j;\n" + "}// namespace LongNamespace\n", + fixNamespaceEndComments("namespace LongNamespace {\n" + "int i;\n" + "int j;\n" + "}\n")); +} + +TEST_F(MaxUnwrappedLinesForShortNamespaceTest, + MultipleUnwrappedLine_DoesNotAddEndCommentForShortNamespace) { + auto Style = getLLVMStyle(); + Style.MaxUnwrappedLinesForShortNamespace = 2; + + EXPECT_EQ("namespace ShortNamespace {\n" + "int i;\n" + "int j;\n" + "}\n", + fixNamespaceEndComments("namespace ShortNamespace {\n" + "int i;\n" + "int j;\n" + "}\n", + Style)); +} + +TEST_F(MaxUnwrappedLinesForShortNamespaceTest, + MultipleUnwrappedLine_AddsEndCommentForLongNamespace) { + auto Style = getLLVMStyle(); + Style.MaxUnwrappedLinesForShortNamespace = 2; + + EXPECT_EQ("namespace LongNamespace {\n" + "int i;\n" + "int j;\n" + "int k;\n" + "}// namespace LongNamespace\n", + fixNamespaceEndComments("namespace LongNamespace {\n" + "int i;\n" + "int j;\n" + "int k;\n" + "}\n", + Style)); +} } // end namespace } // end namespace format } // end namespace clang