mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 06:46:07 +00:00
[clang-format] Add option WrapNamespaceBodyWithNewlines (#106145)
It wraps the body of namespace with additional newlines, turning this code: ``` namespace N { int function(); } ``` into the following: ``` namespace N { int function(); } ``` --------- Co-authored-by: Owen Pan <owenpiano@gmail.com>
This commit is contained in:
parent
b6c06d1a8d
commit
1c997feff1
@ -6843,6 +6843,45 @@ the configuration (without a prefix: ``Auto``).
|
||||
|
||||
For example: BOOST_PP_STRINGIZE
|
||||
|
||||
.. _WrapNamespaceBodyWithEmptyLines:
|
||||
|
||||
**WrapNamespaceBodyWithEmptyLines** (``WrapNamespaceBodyWithEmptyLinesStyle``) :versionbadge:`clang-format 20` :ref:`¶ <WrapNamespaceBodyWithEmptyLines>`
|
||||
Wrap namespace body with empty lines.
|
||||
|
||||
Possible values:
|
||||
|
||||
* ``WNBWELS_Never`` (in configuration: ``Never``)
|
||||
Remove all empty lines at the beginning and the end of namespace body.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
namespace N1 {
|
||||
namespace N2
|
||||
function();
|
||||
}
|
||||
}
|
||||
|
||||
* ``WNBWELS_Always`` (in configuration: ``Always``)
|
||||
Always have at least one empty line at the beginning and the end of
|
||||
namespace body except that the number of empty lines between consecutive
|
||||
nested namespace definitions is not increased.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
namespace N1 {
|
||||
namespace N2 {
|
||||
|
||||
function();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
* ``WNBWELS_Leave`` (in configuration: ``Leave``)
|
||||
Keep existing newlines at the beginning and the end of namespace body.
|
||||
``MaxEmptyLinesToKeep`` still applies.
|
||||
|
||||
|
||||
|
||||
.. END_FORMAT_STYLE_OPTIONS
|
||||
|
||||
Adding additional style options
|
||||
|
@ -1127,6 +1127,7 @@ clang-format
|
||||
- Adds ``AllowShortNamespacesOnASingleLine`` option.
|
||||
- Adds ``VariableTemplates`` option.
|
||||
- Adds support for bash globstar in ``.clang-format-ignore``.
|
||||
- Adds ``WrapNamespaceBodyWithEmptyLines`` option.
|
||||
|
||||
libclang
|
||||
--------
|
||||
|
@ -5143,6 +5143,39 @@ struct FormatStyle {
|
||||
/// \version 11
|
||||
std::vector<std::string> WhitespaceSensitiveMacros;
|
||||
|
||||
/// Different styles for wrapping namespace body with empty lines.
|
||||
enum WrapNamespaceBodyWithEmptyLinesStyle : int8_t {
|
||||
/// Remove all empty lines at the beginning and the end of namespace body.
|
||||
/// \code
|
||||
/// namespace N1 {
|
||||
/// namespace N2
|
||||
/// function();
|
||||
/// }
|
||||
/// }
|
||||
/// \endcode
|
||||
WNBWELS_Never,
|
||||
/// Always have at least one empty line at the beginning and the end of
|
||||
/// namespace body except that the number of empty lines between consecutive
|
||||
/// nested namespace definitions is not increased.
|
||||
/// \code
|
||||
/// namespace N1 {
|
||||
/// namespace N2 {
|
||||
///
|
||||
/// function();
|
||||
///
|
||||
/// }
|
||||
/// }
|
||||
/// \endcode
|
||||
WNBWELS_Always,
|
||||
/// Keep existing newlines at the beginning and the end of namespace body.
|
||||
/// ``MaxEmptyLinesToKeep`` still applies.
|
||||
WNBWELS_Leave
|
||||
};
|
||||
|
||||
/// Wrap namespace body with empty lines.
|
||||
/// \version 20
|
||||
WrapNamespaceBodyWithEmptyLinesStyle WrapNamespaceBodyWithEmptyLines;
|
||||
|
||||
bool operator==(const FormatStyle &R) const {
|
||||
return AccessModifierOffset == R.AccessModifierOffset &&
|
||||
AlignAfterOpenBracket == R.AlignAfterOpenBracket &&
|
||||
@ -5326,7 +5359,8 @@ struct FormatStyle {
|
||||
UseTab == R.UseTab && VariableTemplates == R.VariableTemplates &&
|
||||
VerilogBreakBetweenInstancePorts ==
|
||||
R.VerilogBreakBetweenInstancePorts &&
|
||||
WhitespaceSensitiveMacros == R.WhitespaceSensitiveMacros;
|
||||
WhitespaceSensitiveMacros == R.WhitespaceSensitiveMacros &&
|
||||
WrapNamespaceBodyWithEmptyLines == R.WrapNamespaceBodyWithEmptyLines;
|
||||
}
|
||||
|
||||
std::optional<FormatStyle> GetLanguageStyle(LanguageKind Language) const;
|
||||
|
@ -839,6 +839,18 @@ template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ScalarEnumerationTraits<
|
||||
FormatStyle::WrapNamespaceBodyWithEmptyLinesStyle> {
|
||||
static void
|
||||
enumeration(IO &IO,
|
||||
FormatStyle::WrapNamespaceBodyWithEmptyLinesStyle &Value) {
|
||||
IO.enumCase(Value, "Never", FormatStyle::WNBWELS_Never);
|
||||
IO.enumCase(Value, "Always", FormatStyle::WNBWELS_Always);
|
||||
IO.enumCase(Value, "Leave", FormatStyle::WNBWELS_Leave);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<FormatStyle> {
|
||||
static void mapping(IO &IO, FormatStyle &Style) {
|
||||
// When reading, read the language first, we need it for getPredefinedStyle.
|
||||
@ -1171,6 +1183,8 @@ template <> struct MappingTraits<FormatStyle> {
|
||||
Style.VerilogBreakBetweenInstancePorts);
|
||||
IO.mapOptional("WhitespaceSensitiveMacros",
|
||||
Style.WhitespaceSensitiveMacros);
|
||||
IO.mapOptional("WrapNamespaceBodyWithEmptyLines",
|
||||
Style.WrapNamespaceBodyWithEmptyLines);
|
||||
|
||||
// If AlwaysBreakAfterDefinitionReturnType was specified but
|
||||
// BreakAfterReturnType was not, initialize the latter from the former for
|
||||
@ -1639,6 +1653,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
|
||||
LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME");
|
||||
LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE");
|
||||
LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE");
|
||||
LLVMStyle.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Leave;
|
||||
|
||||
LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
|
||||
LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
|
||||
|
@ -1584,6 +1584,23 @@ static auto computeNewlines(const AnnotatedLine &Line,
|
||||
Newlines = 1;
|
||||
}
|
||||
|
||||
if (Style.WrapNamespaceBodyWithEmptyLines != FormatStyle::WNBWELS_Leave) {
|
||||
// Modify empty lines after TT_NamespaceLBrace.
|
||||
if (PreviousLine && PreviousLine->endsWith(TT_NamespaceLBrace)) {
|
||||
if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
|
||||
Newlines = 1;
|
||||
else if (!Line.startsWithNamespace())
|
||||
Newlines = std::max(Newlines, 2u);
|
||||
}
|
||||
// Modify empty lines before TT_NamespaceRBrace.
|
||||
if (Line.startsWith(TT_NamespaceRBrace)) {
|
||||
if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
|
||||
Newlines = 1;
|
||||
else if (!PreviousLine->startsWith(TT_NamespaceRBrace))
|
||||
Newlines = std::max(Newlines, 2u);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert or remove empty line before access specifiers.
|
||||
if (PreviousLine && RootToken.isAccessSpecifier()) {
|
||||
switch (Style.EmptyLineBeforeAccessModifier) {
|
||||
|
@ -865,6 +865,13 @@ TEST(ConfigParseTest, ParsesConfiguration) {
|
||||
CHECK_PARSE("SortUsingDeclarations: true", SortUsingDeclarations,
|
||||
FormatStyle::SUD_LexicographicNumeric);
|
||||
|
||||
CHECK_PARSE("WrapNamespaceBodyWithEmptyLines: Never",
|
||||
WrapNamespaceBodyWithEmptyLines, FormatStyle::WNBWELS_Never);
|
||||
CHECK_PARSE("WrapNamespaceBodyWithEmptyLines: Always",
|
||||
WrapNamespaceBodyWithEmptyLines, FormatStyle::WNBWELS_Always);
|
||||
CHECK_PARSE("WrapNamespaceBodyWithEmptyLines: Leave",
|
||||
WrapNamespaceBodyWithEmptyLines, FormatStyle::WNBWELS_Leave);
|
||||
|
||||
// FIXME: This is required because parsing a configuration simply overwrites
|
||||
// the first N elements of the list instead of resetting it.
|
||||
Style.ForEachMacros.clear();
|
||||
|
@ -28427,6 +28427,136 @@ TEST_F(FormatTest, ShortNamespacesOption) {
|
||||
Style);
|
||||
}
|
||||
|
||||
TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesNever) {
|
||||
auto Style = getLLVMStyle();
|
||||
Style.FixNamespaceComments = false;
|
||||
Style.MaxEmptyLinesToKeep = 2;
|
||||
Style.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Never;
|
||||
|
||||
// Empty namespace.
|
||||
verifyFormat("namespace N {}", Style);
|
||||
|
||||
// Single namespace.
|
||||
verifyFormat("namespace N {\n"
|
||||
"int f1(int a) { return 2 * a; }\n"
|
||||
"}",
|
||||
"namespace N {\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"int f1(int a) { return 2 * a; }\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"}",
|
||||
Style);
|
||||
|
||||
// Nested namespace.
|
||||
verifyFormat("namespace N1 {\n"
|
||||
"namespace N2 {\n"
|
||||
"int a = 1;\n"
|
||||
"}\n"
|
||||
"}",
|
||||
"namespace N1 {\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"namespace N2 {\n"
|
||||
"\n"
|
||||
"int a = 1;\n"
|
||||
"\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"}",
|
||||
Style);
|
||||
|
||||
Style.CompactNamespaces = true;
|
||||
|
||||
verifyFormat("namespace N1 { namespace N2 {\n"
|
||||
"int a = 1;\n"
|
||||
"}}",
|
||||
"namespace N1 { namespace N2 {\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"int a = 1;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"}}",
|
||||
Style);
|
||||
}
|
||||
|
||||
TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesAlways) {
|
||||
auto Style = getLLVMStyle();
|
||||
Style.FixNamespaceComments = false;
|
||||
Style.MaxEmptyLinesToKeep = 2;
|
||||
Style.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Always;
|
||||
|
||||
// Empty namespace.
|
||||
verifyFormat("namespace N {}", Style);
|
||||
|
||||
// Single namespace.
|
||||
verifyFormat("namespace N {\n"
|
||||
"\n"
|
||||
"int f1(int a) { return 2 * a; }\n"
|
||||
"\n"
|
||||
"}",
|
||||
"namespace N {\n"
|
||||
"int f1(int a) { return 2 * a; }\n"
|
||||
"}",
|
||||
Style);
|
||||
|
||||
// Nested namespace.
|
||||
verifyFormat("namespace N1 {\n"
|
||||
"namespace N2 {\n"
|
||||
"\n"
|
||||
"int a = 1;\n"
|
||||
"\n"
|
||||
"}\n"
|
||||
"}",
|
||||
"namespace N1 {\n"
|
||||
"namespace N2 {\n"
|
||||
"int a = 1;\n"
|
||||
"}\n"
|
||||
"}",
|
||||
Style);
|
||||
|
||||
verifyFormat("namespace N1 {\n"
|
||||
"\n"
|
||||
"namespace N2 {\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"int a = 1;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"}",
|
||||
"namespace N1 {\n"
|
||||
"\n"
|
||||
"namespace N2 {\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"int a = 1;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"}",
|
||||
Style);
|
||||
|
||||
Style.CompactNamespaces = true;
|
||||
|
||||
verifyFormat("namespace N1 { namespace N2 {\n"
|
||||
"\n"
|
||||
"int a = 1;\n"
|
||||
"\n"
|
||||
"}}",
|
||||
"namespace N1 { namespace N2 {\n"
|
||||
"int a = 1;\n"
|
||||
"}}",
|
||||
Style);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace test
|
||||
} // namespace format
|
||||
|
Loading…
x
Reference in New Issue
Block a user