Skip to content

Commit 6ca5281

Browse files
kuzkryHazardyKnusperkeks
authored andcommitted
[clang-format][PR47290] Add ShortNamespaceLines format option
clang-format documentation states that having enabled FixNamespaceComments one may expect below code: c++ namespace a { foo(); } to be turned into: c++ namespace a { foo(); } // namespace a In reality, no "// namespace a" was added. The problem was too high value of kShortNamespaceMaxLines, which is used while deciding whether a namespace is long enough to be formatted. As with 9163fe2, clang-format idempotence is preserved. Differential Revision: https://reviews.llvm.org/D87587
1 parent 418b4a7 commit 6ca5281

File tree

6 files changed

+155
-30
lines changed

6 files changed

+155
-30
lines changed

clang/docs/ClangFormatStyleOptions.rst

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2210,14 +2210,16 @@ the configuration (without a prefix: ``Auto``).
22102210
not use this in config files, etc. Use at your own risk.
22112211

22122212
**FixNamespaceComments** (``bool``)
2213-
If ``true``, clang-format adds missing namespace end comments and
2214-
fixes invalid existing ones.
2213+
If ``true``, clang-format adds missing namespace end comments for
2214+
short namespaces and fixes invalid existing ones. Short ones are
2215+
controlled by "ShortNamespaceLines".
22152216

22162217
.. code-block:: c++
22172218

22182219
true: false:
22192220
namespace a { vs. namespace a {
22202221
foo(); foo();
2222+
bar(); bar();
22212223
} // namespace a }
22222224

22232225
**ForEachMacros** (``std::vector<std::string>``)
@@ -2367,7 +2369,7 @@ the configuration (without a prefix: ``Auto``).
23672369
the record members, respecting the ``AccessModifierOffset``. Record
23682370
members are indented one level below the record.
23692371
When ``true``, access modifiers get their own indentation level. As a
2370-
consequence, record members are indented 2 levels below the record,
2372+
consequence, record members are always indented 2 levels below the record,
23712373
regardless of the access modifier presence. Value of the
23722374
``AccessModifierOffset`` is ignored.
23732375

@@ -3040,43 +3042,72 @@ the configuration (without a prefix: ``Auto``).
30403042
/* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
30413043
* information */
30423044
3045+
**ShortNamespaceLines** (``unsigned``)
3046+
The maximal number of unwrapped lines that a short namespace spans.
3047+
Defaults to 1.
3048+
3049+
This determines the maximum length of short namespaces by counting
3050+
unwrapped lines (i.e. containing neither opening nor closing
3051+
namespace brace) and makes "FixNamespaceComments" omit adding
3052+
end comments for those.
3053+
3054+
.. code-block:: c++
3055+
3056+
ShortNamespaceLines: 1 vs. ShortNamespaceLines: 0
3057+
namespace a { namespace a {
3058+
int foo; int foo;
3059+
} } // namespace a
3060+
3061+
ShortNamespaceLines: 1 vs. ShortNamespaceLines: 0
3062+
namespace b { namespace b {
3063+
int foo; int foo;
3064+
int bar; int bar;
3065+
} // namespace b } // namespace b
3066+
30433067
**SortIncludes** (``SortIncludesOptions``)
30443068
Controls if and how clang-format will sort ``#includes``.
3069+
If ``Never``, includes are never sorted.
3070+
If ``CaseInsensitive``, includes are sorted in an ASCIIbetical or case
3071+
insensitive fashion.
3072+
If ``CaseSensitive``, includes are sorted in an alphabetical or case
3073+
sensitive fashion.
30453074

3046-
Possible Values:
3075+
Possible values:
30473076

3048-
* ``SI_Never`` (in configuration ``Never``)
3077+
* ``SI_Never`` (in configuration: ``Never``)
30493078
Includes are never sorted.
30503079

30513080
.. code-block:: c++
30523081

3053-
#include "B/A.h"
3054-
#include "A/B.h"
3055-
#include "a/b.h"
3056-
#include "A/b.h"
3057-
#include "B/a.h"
3082+
#include "B/A.h"
3083+
#include "A/B.h"
3084+
#include "a/b.h"
3085+
#include "A/b.h"
3086+
#include "B/a.h"
30583087

3059-
* ``SI_CaseInsensitive`` (in configuration ``CaseInsensitive``)
3088+
* ``SI_CaseInsensitive`` (in configuration: ``CaseInsensitive``)
30603089
Includes are sorted in an ASCIIbetical or case insensitive fashion.
30613090

30623091
.. code-block:: c++
30633092

3064-
#include "A/B.h"
3065-
#include "A/b.h"
3066-
#include "B/A.h"
3067-
#include "B/a.h"
3068-
#include "a/b.h"
3093+
#include "A/B.h"
3094+
#include "A/b.h"
3095+
#include "B/A.h"
3096+
#include "B/a.h"
3097+
#include "a/b.h"
30693098

3070-
* ``SI_CaseSensitive`` (in configuration ``CaseSensitive``)
3099+
* ``SI_CaseSensitive`` (in configuration: ``CaseSensitive``)
30713100
Includes are sorted in an alphabetical or case sensitive fashion.
30723101

30733102
.. code-block:: c++
30743103

3075-
#include "A/B.h"
3076-
#include "A/b.h"
3077-
#include "a/b.h"
3078-
#include "B/A.h"
3079-
#include "B/a.h"
3104+
#include "A/B.h"
3105+
#include "A/b.h"
3106+
#include "a/b.h"
3107+
#include "B/A.h"
3108+
#include "B/a.h"
3109+
3110+
30803111

30813112
**SortJavaStaticImport** (``SortJavaStaticImportOptions``)
30823113
When sorting Java imports, by default static imports are placed before

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ clang-format
203203
- Option ``IndentAccessModifiers`` has been added to be able to give access
204204
modifiers their own indentation level inside records.
205205

206+
- Option ``ShortNamespaceLines`` has been added to give better control
207+
over ``FixNamespaceComments`` when determining a namespace length.
208+
206209
libclang
207210
--------
208211

clang/include/clang/Format/Format.h

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1964,12 +1964,14 @@ struct FormatStyle {
19641964
/// not use this in config files, etc. Use at your own risk.
19651965
bool ExperimentalAutoDetectBinPacking;
19661966

1967-
/// If ``true``, clang-format adds missing namespace end comments and
1968-
/// fixes invalid existing ones.
1967+
/// If ``true``, clang-format adds missing namespace end comments for
1968+
/// short namespaces and fixes invalid existing ones. Short ones are
1969+
/// controlled by "ShortNamespaceLines".
19691970
/// \code
19701971
/// true: false:
19711972
/// namespace a { vs. namespace a {
19721973
/// foo(); foo();
1974+
/// bar(); bar();
19731975
/// } // namespace a }
19741976
/// \endcode
19751977
bool FixNamespaceComments;
@@ -2644,6 +2646,27 @@ struct FormatStyle {
26442646
bool ReflowComments;
26452647
// clang-format on
26462648

2649+
/// The maximal number of unwrapped lines that a short namespace spans.
2650+
/// Defaults to 1.
2651+
///
2652+
/// This determines the maximum length of short namespaces by counting
2653+
/// unwrapped lines (i.e. containing neither opening nor closing
2654+
/// namespace brace) and makes "FixNamespaceComments" omit adding
2655+
/// end comments for those.
2656+
/// \code
2657+
/// ShortNamespaceLines: 1 vs. ShortNamespaceLines: 0
2658+
/// namespace a { namespace a {
2659+
/// int foo; int foo;
2660+
/// } } // namespace a
2661+
///
2662+
/// ShortNamespaceLines: 1 vs. ShortNamespaceLines: 0
2663+
/// namespace b { namespace b {
2664+
/// int foo; int foo;
2665+
/// int bar; int bar;
2666+
/// } // namespace b } // namespace b
2667+
/// \endcode
2668+
unsigned ShortNamespaceLines;
2669+
26472670
/// Include sorting options.
26482671
enum SortIncludesOptions : unsigned char {
26492672
/// Includes are never sorted.
@@ -3224,6 +3247,7 @@ struct FormatStyle {
32243247
R.PenaltyBreakTemplateDeclaration &&
32253248
PointerAlignment == R.PointerAlignment &&
32263249
RawStringFormats == R.RawStringFormats &&
3250+
ShortNamespaceLines == R.ShortNamespaceLines &&
32273251
SortIncludes == R.SortIncludes &&
32283252
SortJavaStaticImport == R.SortJavaStaticImport &&
32293253
SpaceAfterCStyleCast == R.SpaceAfterCStyleCast &&

clang/lib/Format/Format.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,7 @@ template <> struct MappingTraits<FormatStyle> {
642642
IO.mapOptional("PointerAlignment", Style.PointerAlignment);
643643
IO.mapOptional("RawStringFormats", Style.RawStringFormats);
644644
IO.mapOptional("ReflowComments", Style.ReflowComments);
645+
IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines);
645646
IO.mapOptional("SortIncludes", Style.SortIncludes);
646647
IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport);
647648
IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);
@@ -1006,6 +1007,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
10061007
LLVMStyle.ObjCSpaceAfterProperty = false;
10071008
LLVMStyle.ObjCSpaceBeforeProtocolList = true;
10081009
LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
1010+
LLVMStyle.ShortNamespaceLines = 1;
10091011
LLVMStyle.SpacesBeforeTrailingComments = 1;
10101012
LLVMStyle.Standard = FormatStyle::LS_Latest;
10111013
LLVMStyle.UseCRLF = false;

clang/lib/Format/NamespaceEndCommentsFixer.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ namespace clang {
2222
namespace format {
2323

2424
namespace {
25-
// The maximal number of unwrapped lines that a short namespace spans.
26-
// Short namespaces don't need an end comment.
27-
static const int kShortNamespaceMaxLines = 1;
28-
2925
// Computes the name of a namespace given the namespace token.
3026
// Returns "" for anonymous namespace.
3127
std::string computeName(const FormatToken *NamespaceTok) {
@@ -283,7 +279,7 @@ std::pair<tooling::Replacements, unsigned> NamespaceEndCommentsFixer::analyze(
283279
computeEndCommentText(NamespaceName, AddNewline, NamespaceTok,
284280
Style.SpacesInLineCommentPrefix.Minimum);
285281
if (!hasEndComment(EndCommentPrevTok)) {
286-
bool isShort = I - StartLineIndex <= kShortNamespaceMaxLines + 1;
282+
bool isShort = I - StartLineIndex <= Style.ShortNamespaceLines + 1;
287283
if (!isShort)
288284
addEndComment(EndCommentPrevTok, EndCommentText, SourceMgr, &Fixes);
289285
} else if (!validEndComment(EndCommentPrevTok, NamespaceName,

clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,7 @@ TEST_F(NamespaceEndCommentsFixerTest,
816816
"}\n"));
817817
}
818818

819-
TEST_F(NamespaceEndCommentsFixerTest, AddEndCommentForNamespacesAroundMacros) {
819+
TEST_F(NamespaceEndCommentsFixerTest, AddsEndCommentForNamespacesAroundMacros) {
820820
// Conditional blocks around are fine
821821
EXPECT_EQ("namespace A {\n"
822822
"#if 1\n"
@@ -1116,6 +1116,75 @@ TEST_F(NamespaceEndCommentsFixerTest, IgnoreUnbalanced) {
11161116
"}\n"
11171117
"}\n"));
11181118
}
1119+
1120+
using ShortNamespaceLinesTest = NamespaceEndCommentsFixerTest;
1121+
1122+
TEST_F(ShortNamespaceLinesTest, ZeroUnwrappedLines) {
1123+
auto Style = getLLVMStyle();
1124+
Style.ShortNamespaceLines = 0u;
1125+
1126+
EXPECT_EQ("namespace OneLinerNamespace {}\n",
1127+
fixNamespaceEndComments("namespace OneLinerNamespace {}\n", Style));
1128+
EXPECT_EQ("namespace ShortNamespace {\n"
1129+
"}\n",
1130+
fixNamespaceEndComments("namespace ShortNamespace {\n"
1131+
"}\n",
1132+
Style));
1133+
EXPECT_EQ("namespace LongNamespace {\n"
1134+
"int i;\n"
1135+
"}// namespace LongNamespace\n",
1136+
fixNamespaceEndComments("namespace LongNamespace {\n"
1137+
"int i;\n"
1138+
"}\n",
1139+
Style));
1140+
}
1141+
1142+
TEST_F(ShortNamespaceLinesTest, OneUnwrappedLine) {
1143+
constexpr auto DefaultUnwrappedLines = 1u;
1144+
auto const Style = getLLVMStyle();
1145+
1146+
EXPECT_EQ(DefaultUnwrappedLines, Style.ShortNamespaceLines);
1147+
EXPECT_EQ("namespace ShortNamespace {\n"
1148+
"int i;\n"
1149+
"}\n",
1150+
fixNamespaceEndComments("namespace ShortNamespace {\n"
1151+
"int i;\n"
1152+
"}\n"));
1153+
EXPECT_EQ("namespace LongNamespace {\n"
1154+
"int i;\n"
1155+
"int j;\n"
1156+
"}// namespace LongNamespace\n",
1157+
fixNamespaceEndComments("namespace LongNamespace {\n"
1158+
"int i;\n"
1159+
"int j;\n"
1160+
"}\n"));
1161+
}
1162+
1163+
TEST_F(ShortNamespaceLinesTest, MultipleUnwrappedLine) {
1164+
auto Style = getLLVMStyle();
1165+
Style.ShortNamespaceLines = 2u;
1166+
1167+
EXPECT_EQ("namespace ShortNamespace {\n"
1168+
"int i;\n"
1169+
"int j;\n"
1170+
"}\n",
1171+
fixNamespaceEndComments("namespace ShortNamespace {\n"
1172+
"int i;\n"
1173+
"int j;\n"
1174+
"}\n",
1175+
Style));
1176+
EXPECT_EQ("namespace LongNamespace {\n"
1177+
"int i;\n"
1178+
"int j;\n"
1179+
"int k;\n"
1180+
"}// namespace LongNamespace\n",
1181+
fixNamespaceEndComments("namespace LongNamespace {\n"
1182+
"int i;\n"
1183+
"int j;\n"
1184+
"int k;\n"
1185+
"}\n",
1186+
Style));
1187+
}
11191188
} // end namespace
11201189
} // end namespace format
11211190
} // end namespace clang

0 commit comments

Comments
 (0)