Skip to content

Commit 3a25a4a

Browse files
[clang-format] Add xxxMaxDigitsNoSeparator (llvm#164286)
This basically adds a Leave option for a specific range of literals.
1 parent 8706d82 commit 3a25a4a

File tree

7 files changed

+223
-43
lines changed

7 files changed

+223
-43
lines changed

clang/docs/ClangFormatStyleOptions.rst

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4765,9 +4765,21 @@ the configuration (without a prefix: ``Auto``).
47654765
Decimal: 3
47664766
Hex: -1
47674767

4768-
You can also specify a minimum number of digits (``BinaryMinDigits``,
4769-
``DecimalMinDigits``, and ``HexMinDigits``) the integer literal must
4770-
have in order for the separators to be inserted.
4768+
You can also specify a minimum number of digits
4769+
(``BinaryMinDigitsInsert``, ``DecimalMinDigitsInsert``, and
4770+
``HexMinDigitsInsert``) the integer literal must have in order for the
4771+
separators to be inserted, and a maximum number of digits
4772+
(``BinaryMaxDigitsRemove``, ``DecimalMaxDigitsRemove``, and
4773+
``HexMaxDigitsRemove``) until the separators are removed. This divides the
4774+
literals in 3 regions, always without separator (up until including
4775+
``xxxMaxDigitsRemove``), maybe with, or without separators (up until
4776+
excluding ``xxxMinDigitsInsert``), and finally always with separators.
4777+
4778+
.. note::
4779+
4780+
``BinaryMinDigits``, ``DecimalMinDigits``, and ``HexMinDigits`` are
4781+
deprecated and renamed to ``BinaryMinDigitsInsert``,
4782+
``DecimalMinDigitsInsert``, and ``HexMinDigitsInsert``, respectively.
47714783

47724784
* ``int8_t Binary`` Format separators in binary literals.
47734785

@@ -4778,15 +4790,28 @@ the configuration (without a prefix: ``Auto``).
47784790
/* 3: */ b = 0b100'111'101'101;
47794791
/* 4: */ b = 0b1001'1110'1101;
47804792
4781-
* ``int8_t BinaryMinDigits`` Format separators in binary literals with a minimum number of digits.
4793+
* ``int8_t BinaryMinDigitsInsert`` Format separators in binary literals with a minimum number of digits.
47824794

47834795
.. code-block:: text
47844796
47854797
// Binary: 3
4786-
// BinaryMinDigits: 7
4798+
// BinaryMinDigitsInsert: 7
47874799
b1 = 0b101101;
47884800
b2 = 0b1'101'101;
47894801
4802+
* ``int8_t BinaryMaxDigitsRemove`` Remove separators in binary literals with a maximum number of digits.
4803+
4804+
.. code-block:: text
4805+
4806+
// Binary: 3
4807+
// BinaryMinDigitsInsert: 7
4808+
// BinaryMaxDigitsRemove: 4
4809+
b0 = 0b1011; // Always removed.
4810+
b1 = 0b101101; // Not added.
4811+
b2 = 0b1'01'101; // Not removed, not corrected.
4812+
b3 = 0b1'101'101; // Always added.
4813+
b4 = 0b10'1101; // Corrected to 0b101'101.
4814+
47904815
* ``int8_t Decimal`` Format separators in decimal literals.
47914816

47924817
.. code-block:: text
@@ -4795,15 +4820,28 @@ the configuration (without a prefix: ``Auto``).
47954820
/* 0: */ d = 184467'440737'0'95505'92ull;
47964821
/* 3: */ d = 18'446'744'073'709'550'592ull;
47974822
4798-
* ``int8_t DecimalMinDigits`` Format separators in decimal literals with a minimum number of digits.
4823+
* ``int8_t DecimalMinDigitsInsert`` Format separators in decimal literals with a minimum number of digits.
47994824

48004825
.. code-block:: text
48014826
48024827
// Decimal: 3
4803-
// DecimalMinDigits: 5
4828+
// DecimalMinDigitsInsert: 5
48044829
d1 = 2023;
48054830
d2 = 10'000;
48064831
4832+
* ``int8_t DecimalMaxDigitsRemove`` Remove separators in decimal literals with a maximum number of digits.
4833+
4834+
.. code-block:: text
4835+
4836+
// Decimal: 3
4837+
// DecimalMinDigitsInsert: 7
4838+
// DecimalMaxDigitsRemove: 4
4839+
d0 = 2023; // Always removed.
4840+
d1 = 123456; // Not added.
4841+
d2 = 1'23'456; // Not removed, not corrected.
4842+
d3 = 5'000'000; // Always added.
4843+
d4 = 1'23'45; // Corrected to 12'345.
4844+
48074845
* ``int8_t Hex`` Format separators in hexadecimal literals.
48084846

48094847
.. code-block:: text
@@ -4812,16 +4850,30 @@ the configuration (without a prefix: ``Auto``).
48124850
/* 0: */ h = 0xDEAD'BEEF'DE'AD'BEE'Fuz;
48134851
/* 2: */ h = 0xDE'AD'BE'EF'DE'AD'BE'EFuz;
48144852
4815-
* ``int8_t HexMinDigits`` Format separators in hexadecimal literals with a minimum number of
4853+
* ``int8_t HexMinDigitsInsert`` Format separators in hexadecimal literals with a minimum number of
48164854
digits.
48174855

48184856
.. code-block:: text
48194857
48204858
// Hex: 2
4821-
// HexMinDigits: 6
4859+
// HexMinDigitsInsert: 6
48224860
h1 = 0xABCDE;
48234861
h2 = 0xAB'CD'EF;
48244862
4863+
* ``int8_t HexMaxDigitsRemove`` Remove separators in hexadecimal literals with a maximum number of
4864+
digits.
4865+
4866+
.. code-block:: text
4867+
4868+
// Hex: 2
4869+
// HexMinDigitsInsert: 6
4870+
// HexMaxDigitsRemove: 4
4871+
h0 = 0xAFFE; // Always removed.
4872+
h1 = 0xABCDE; // Not added.
4873+
h2 = 0xABC'DE; // Not removed, not corrected.
4874+
h3 = 0xAB'CD'EF; // Always added.
4875+
h4 = 0xABCD'E; // Corrected to 0xA'BC'DE.
4876+
48254877
48264878
.. _JavaImportGroups:
48274879

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,9 @@ clang-format
704704
``AlignAfterOpenBracket`` option, and make ``AlignAfterOpenBracket`` a
705705
``bool`` type.
706706
- Add ``AlignPPAndNotPP`` suboption to ``AlignTrailingComments``.
707+
- Rename ``(Binary|Decimal|Hex)MinDigits`` to ``...MinDigitsInsert`` and add
708+
``(Binary|Decimal|Hex)MaxDigitsSeparator`` suboptions to
709+
``IntegerLiteralSeparator``.
707710

708711
libclang
709712
--------

clang/include/clang/Format/Format.h

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3275,9 +3275,20 @@ struct FormatStyle {
32753275
/// Hex: -1
32763276
/// \endcode
32773277
///
3278-
/// You can also specify a minimum number of digits (``BinaryMinDigits``,
3279-
/// ``DecimalMinDigits``, and ``HexMinDigits``) the integer literal must
3280-
/// have in order for the separators to be inserted.
3278+
/// You can also specify a minimum number of digits
3279+
/// (``BinaryMinDigitsInsert``, ``DecimalMinDigitsInsert``, and
3280+
/// ``HexMinDigitsInsert``) the integer literal must have in order for the
3281+
/// separators to be inserted, and a maximum number of digits
3282+
/// (``BinaryMaxDigitsRemove``, ``DecimalMaxDigitsRemove``, and
3283+
/// ``HexMaxDigitsRemove``) until the separators are removed. This divides the
3284+
/// literals in 3 regions, always without separator (up until including
3285+
/// ``xxxMaxDigitsRemove``), maybe with, or without separators (up until
3286+
/// excluding ``xxxMinDigitsInsert``), and finally always with separators.
3287+
/// \note
3288+
/// ``BinaryMinDigits``, ``DecimalMinDigits``, and ``HexMinDigits`` are
3289+
/// deprecated and renamed to ``BinaryMinDigitsInsert``,
3290+
/// ``DecimalMinDigitsInsert``, and ``HexMinDigitsInsert``, respectively.
3291+
/// \endnote
32813292
struct IntegerLiteralSeparatorStyle {
32823293
/// Format separators in binary literals.
32833294
/// \code{.text}
@@ -3290,11 +3301,23 @@ struct FormatStyle {
32903301
/// Format separators in binary literals with a minimum number of digits.
32913302
/// \code{.text}
32923303
/// // Binary: 3
3293-
/// // BinaryMinDigits: 7
3304+
/// // BinaryMinDigitsInsert: 7
32943305
/// b1 = 0b101101;
32953306
/// b2 = 0b1'101'101;
32963307
/// \endcode
3297-
int8_t BinaryMinDigits;
3308+
int8_t BinaryMinDigitsInsert;
3309+
/// Remove separators in binary literals with a maximum number of digits.
3310+
/// \code{.text}
3311+
/// // Binary: 3
3312+
/// // BinaryMinDigitsInsert: 7
3313+
/// // BinaryMaxDigitsRemove: 4
3314+
/// b0 = 0b1011; // Always removed.
3315+
/// b1 = 0b101101; // Not added.
3316+
/// b2 = 0b1'01'101; // Not removed, not corrected.
3317+
/// b3 = 0b1'101'101; // Always added.
3318+
/// b4 = 0b10'1101; // Corrected to 0b101'101.
3319+
/// \endcode
3320+
int8_t BinaryMaxDigitsRemove;
32983321
/// Format separators in decimal literals.
32993322
/// \code{.text}
33003323
/// /* -1: */ d = 18446744073709550592ull;
@@ -3305,11 +3328,23 @@ struct FormatStyle {
33053328
/// Format separators in decimal literals with a minimum number of digits.
33063329
/// \code{.text}
33073330
/// // Decimal: 3
3308-
/// // DecimalMinDigits: 5
3331+
/// // DecimalMinDigitsInsert: 5
33093332
/// d1 = 2023;
33103333
/// d2 = 10'000;
33113334
/// \endcode
3312-
int8_t DecimalMinDigits;
3335+
int8_t DecimalMinDigitsInsert;
3336+
/// Remove separators in decimal literals with a maximum number of digits.
3337+
/// \code{.text}
3338+
/// // Decimal: 3
3339+
/// // DecimalMinDigitsInsert: 7
3340+
/// // DecimalMaxDigitsRemove: 4
3341+
/// d0 = 2023; // Always removed.
3342+
/// d1 = 123456; // Not added.
3343+
/// d2 = 1'23'456; // Not removed, not corrected.
3344+
/// d3 = 5'000'000; // Always added.
3345+
/// d4 = 1'23'45; // Corrected to 12'345.
3346+
/// \endcode
3347+
int8_t DecimalMaxDigitsRemove;
33133348
/// Format separators in hexadecimal literals.
33143349
/// \code{.text}
33153350
/// /* -1: */ h = 0xDEADBEEFDEADBEEFuz;
@@ -3321,15 +3356,36 @@ struct FormatStyle {
33213356
/// digits.
33223357
/// \code{.text}
33233358
/// // Hex: 2
3324-
/// // HexMinDigits: 6
3359+
/// // HexMinDigitsInsert: 6
33253360
/// h1 = 0xABCDE;
33263361
/// h2 = 0xAB'CD'EF;
33273362
/// \endcode
3328-
int8_t HexMinDigits;
3363+
int8_t HexMinDigitsInsert;
3364+
/// Remove separators in hexadecimal literals with a maximum number of
3365+
/// digits.
3366+
/// \code{.text}
3367+
/// // Hex: 2
3368+
/// // HexMinDigitsInsert: 6
3369+
/// // HexMaxDigitsRemove: 4
3370+
/// h0 = 0xAFFE; // Always removed.
3371+
/// h1 = 0xABCDE; // Not added.
3372+
/// h2 = 0xABC'DE; // Not removed, not corrected.
3373+
/// h3 = 0xAB'CD'EF; // Always added.
3374+
/// h4 = 0xABCD'E; // Corrected to 0xA'BC'DE.
3375+
/// \endcode
3376+
int8_t HexMaxDigitsRemove;
33293377
bool operator==(const IntegerLiteralSeparatorStyle &R) const {
3330-
return Binary == R.Binary && BinaryMinDigits == R.BinaryMinDigits &&
3331-
Decimal == R.Decimal && DecimalMinDigits == R.DecimalMinDigits &&
3332-
Hex == R.Hex && HexMinDigits == R.HexMinDigits;
3378+
return Binary == R.Binary &&
3379+
BinaryMinDigitsInsert == R.BinaryMinDigitsInsert &&
3380+
BinaryMaxDigitsRemove == R.BinaryMaxDigitsRemove &&
3381+
Decimal == R.Decimal &&
3382+
DecimalMinDigitsInsert == R.DecimalMinDigitsInsert &&
3383+
DecimalMaxDigitsRemove == R.DecimalMaxDigitsRemove &&
3384+
Hex == R.Hex && HexMinDigitsInsert == R.HexMinDigitsInsert &&
3385+
HexMaxDigitsRemove == R.HexMaxDigitsRemove;
3386+
}
3387+
bool operator!=(const IntegerLiteralSeparatorStyle &R) const {
3388+
return !operator==(R);
33333389
}
33343390
};
33353391

clang/lib/Format/Format.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -405,11 +405,19 @@ struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> {
405405
template <> struct MappingTraits<FormatStyle::IntegerLiteralSeparatorStyle> {
406406
static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &Base) {
407407
IO.mapOptional("Binary", Base.Binary);
408-
IO.mapOptional("BinaryMinDigits", Base.BinaryMinDigits);
408+
IO.mapOptional("BinaryMinDigitsInsert", Base.BinaryMinDigitsInsert);
409+
IO.mapOptional("BinaryMaxDigitsRemove", Base.BinaryMaxDigitsRemove);
409410
IO.mapOptional("Decimal", Base.Decimal);
410-
IO.mapOptional("DecimalMinDigits", Base.DecimalMinDigits);
411+
IO.mapOptional("DecimalMinDigitsInsert", Base.DecimalMinDigitsInsert);
412+
IO.mapOptional("DecimalMaxDigitsRemove", Base.DecimalMaxDigitsRemove);
411413
IO.mapOptional("Hex", Base.Hex);
412-
IO.mapOptional("HexMinDigits", Base.HexMinDigits);
414+
IO.mapOptional("HexMinDigitsInsert", Base.HexMinDigitsInsert);
415+
IO.mapOptional("HexMaxDigitsRemove", Base.HexMaxDigitsRemove);
416+
417+
// For backward compatibility.
418+
IO.mapOptional("BinaryMinDigits", Base.BinaryMinDigitsInsert);
419+
IO.mapOptional("DecimalMinDigits", Base.DecimalMinDigitsInsert);
420+
IO.mapOptional("HexMinDigits", Base.HexMinDigitsInsert);
413421
}
414422
};
415423

@@ -1758,10 +1766,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
17581766
LLVMStyle.InsertBraces = false;
17591767
LLVMStyle.InsertNewlineAtEOF = false;
17601768
LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
1761-
LLVMStyle.IntegerLiteralSeparator = {
1762-
/*Binary=*/0, /*BinaryMinDigits=*/0,
1763-
/*Decimal=*/0, /*DecimalMinDigits=*/0,
1764-
/*Hex=*/0, /*HexMinDigits=*/0};
1769+
LLVMStyle.IntegerLiteralSeparator = {};
17651770
LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
17661771
LLVMStyle.JavaScriptWrapImports = true;
17671772
LLVMStyle.KeepEmptyLines = {
@@ -2183,7 +2188,7 @@ FormatStyle getClangFormatStyle() {
21832188
Style.InsertBraces = true;
21842189
Style.InsertNewlineAtEOF = true;
21852190
Style.IntegerLiteralSeparator.Decimal = 3;
2186-
Style.IntegerLiteralSeparator.DecimalMinDigits = 5;
2191+
Style.IntegerLiteralSeparator.DecimalMinDigitsInsert = 5;
21872192
Style.LineEnding = FormatStyle::LE_LF;
21882193
Style.RemoveBracesLLVM = true;
21892194
Style.RemoveEmptyLinesInUnwrappedLines = true;

clang/lib/Format/IntegerLiteralSeparatorFixer.cpp

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,22 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env,
7272
if (SkipBinary && SkipDecimal && SkipHex)
7373
return {};
7474

75-
const auto BinaryMinDigits =
76-
std::max((int)Option.BinaryMinDigits, Binary + 1);
77-
const auto DecimalMinDigits =
78-
std::max((int)Option.DecimalMinDigits, Decimal + 1);
79-
const auto HexMinDigits = std::max((int)Option.HexMinDigits, Hex + 1);
75+
auto CalcMinAndMax = [](int DigitsPerGroup, int MinDigitsInsert,
76+
int MaxDigitsRemove) {
77+
MinDigitsInsert = std::max(MinDigitsInsert, DigitsPerGroup + 1);
78+
if (MinDigitsInsert < 1)
79+
MaxDigitsRemove = 0;
80+
else if (MaxDigitsRemove < 1 || MaxDigitsRemove >= MinDigitsInsert)
81+
MaxDigitsRemove = MinDigitsInsert - 1;
82+
return std::pair(MinDigitsInsert, MaxDigitsRemove);
83+
};
84+
85+
const auto [BinaryMinDigitsInsert, BinaryMaxDigitsRemove] = CalcMinAndMax(
86+
Binary, Option.BinaryMinDigitsInsert, Option.BinaryMaxDigitsRemove);
87+
const auto [DecimalMinDigitsInsert, DecimalMaxDigitsRemove] = CalcMinAndMax(
88+
Decimal, Option.DecimalMinDigitsInsert, Option.DecimalMaxDigitsRemove);
89+
const auto [HexMinDigitsInsert, HexMaxDigitsRemove] =
90+
CalcMinAndMax(Hex, Option.HexMinDigitsInsert, Option.HexMaxDigitsRemove);
8091

8192
const auto &SourceMgr = Env.getSourceManager();
8293
AffectedRangeManager AffectedRangeMgr(SourceMgr, Env.getCharRanges());
@@ -138,17 +149,23 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env,
138149
Text = Text.substr(Start, Length);
139150
}
140151
auto DigitsPerGroup = Decimal;
141-
auto MinDigits = DecimalMinDigits;
152+
auto MinDigitsInsert = DecimalMinDigitsInsert;
153+
auto MaxDigitsRemove = DecimalMaxDigitsRemove;
142154
if (IsBase2) {
143155
DigitsPerGroup = Binary;
144-
MinDigits = BinaryMinDigits;
156+
MinDigitsInsert = BinaryMinDigitsInsert;
157+
MaxDigitsRemove = BinaryMaxDigitsRemove;
145158
} else if (IsBase16) {
146159
DigitsPerGroup = Hex;
147-
MinDigits = HexMinDigits;
160+
MinDigitsInsert = HexMinDigitsInsert;
161+
MaxDigitsRemove = HexMaxDigitsRemove;
148162
}
149163
const auto SeparatorCount = Text.count(Separator);
150164
const int DigitCount = Length - SeparatorCount;
151-
const bool RemoveSeparator = DigitsPerGroup < 0 || DigitCount < MinDigits;
165+
if (DigitCount > MaxDigitsRemove && DigitCount < MinDigitsInsert)
166+
continue;
167+
const bool RemoveSeparator =
168+
DigitsPerGroup < 0 || DigitCount <= MaxDigitsRemove;
152169
if (RemoveSeparator && SeparatorCount == 0)
153170
continue;
154171
if (!RemoveSeparator && SeparatorCount > 0 &&

clang/unittests/Format/ConfigParseTest.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,36 @@ TEST(ConfigParseTest, ParsesConfiguration) {
11641164
FormatStyle::BLS_Block);
11651165
CHECK_PARSE("Cpp11BracedListStyle: true", Cpp11BracedListStyle,
11661166
FormatStyle::BLS_AlignFirstComment);
1167+
1168+
constexpr FormatStyle::IntegerLiteralSeparatorStyle
1169+
ExpectedIntegerLiteralSeparatorStyle{/*Binary=*/2,
1170+
/*BinaryMinDigitInsert=*/5,
1171+
/*BinaryMaxDigitRemove=*/2,
1172+
/*Decimal=*/6,
1173+
/*DecimalMinDigitInsert=*/6,
1174+
/*DecimalMaxDigitRemove=*/3,
1175+
/*Hex=*/4,
1176+
/*HexMinDigitInsert=*/2,
1177+
/*HexMaxDigitRemove=*/1};
1178+
CHECK_PARSE("IntegerLiteralSeparator:\n"
1179+
" Binary: 2\n"
1180+
" BinaryMinDigitsInsert: 5\n"
1181+
" BinaryMaxDigitsRemove: 2\n"
1182+
" Decimal: 6\n"
1183+
" DecimalMinDigitsInsert: 6\n"
1184+
" DecimalMaxDigitsRemove: 3\n"
1185+
" Hex: 4\n"
1186+
" HexMinDigitsInsert: 2\n"
1187+
" HexMaxDigitsRemove: 1",
1188+
IntegerLiteralSeparator, ExpectedIntegerLiteralSeparatorStyle);
1189+
1190+
// Backward compatibility:
1191+
CHECK_PARSE_NESTED_VALUE("BinaryMinDigits: 6", IntegerLiteralSeparator,
1192+
BinaryMinDigitsInsert, 6);
1193+
CHECK_PARSE_NESTED_VALUE("DecimalMinDigits: 5", IntegerLiteralSeparator,
1194+
DecimalMinDigitsInsert, 5);
1195+
CHECK_PARSE_NESTED_VALUE("HexMinDigits: 5", IntegerLiteralSeparator,
1196+
HexMinDigitsInsert, 5);
11671197
}
11681198

11691199
TEST(ConfigParseTest, ParsesConfigurationWithLanguages) {

0 commit comments

Comments
 (0)