clang: lib/Format/IntegerLiteralSeparatorFixer.cpp Source File (original) (raw)
24
28 }
29
31
33 case 'b':
34 case 'B':
36 case 'x':
37 case 'X':
39 default:
41 }
42}
46 const FormatStyle &Style) {
47 switch (Style.Language) {
48 case FormatStyle::LK_CSharp:
49 case FormatStyle::LK_Java:
50 case FormatStyle::LK_JavaScript:
51 Separator = '_';
52 break;
53 case FormatStyle::LK_Cpp:
54 case FormatStyle::LK_ObjC:
55 if (Style.Standard >= FormatStyle::LS_Cpp14) {
56 Separator = '\'';
57 break;
58 }
59 [[fallthrough]];
60 default:
61 return {};
62 }
63
64 const auto &Option = Style.IntegerLiteralSeparator;
65 const auto Binary = Option.Binary;
66 const auto Decimal = Option.Decimal;
67 const auto Hex = Option.Hex;
68 const bool SkipBinary = Binary == 0;
69 const bool SkipDecimal = Decimal == 0;
70 const bool SkipHex = Hex == 0;
71
72 if (SkipBinary && SkipDecimal && SkipHex)
73 return {};
74
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);
91
94
97 Lexer Lex(ID, SourceMgr.getBufferOrFake(ID), SourceMgr, LangOpts);
99
102
104 auto Length = Tok.getLength();
105 if (Length < 2)
106 continue;
107 auto Location = Tok.getLocation();
108 auto Text = StringRef(SourceMgr.getCharacterData(Location), Length);
109 if (Tok.is(tok::comment)) {
113 Skip = false;
114 continue;
115 }
116 if (Skip || Tok.isNot(tok::numeric_constant) || Text[0] == '.' ||
119 continue;
120 }
124 const bool IsBase16 = B == Base::Hex;
125 if ((IsBase2 && SkipBinary) || (IsBase10 && SkipDecimal) ||
126 (IsBase16 && SkipHex) || B == Base::Other) {
127 continue;
128 }
129 if (Style.isCpp()) {
130
131 static constexpr StringRef Suffixes("_himnsuyd");
132 if (const auto Pos =
134 Pos != StringRef::npos) {
136 Length = Pos;
137 }
138 }
139 if ((IsBase10 && Text.find_last_of(".eEfFdDmM") != StringRef::npos) ||
140 (IsBase16 && Text.find_last_of(".pP") != StringRef::npos)) {
141 continue;
142 }
143 const auto Start = Text[0] == '0' ? 2 : 0;
144 auto End = Text.find_first_of("uUlLzZn", Start);
145 if (End == StringRef::npos)
146 End = Length;
147 if (Start > 0 || End < Length) {
148 Length = End - Start;
149 Text = Text.substr(Start, Length);
150 }
151 auto DigitsPerGroup = Decimal;
152 auto MinDigitsInsert = DecimalMinDigitsInsert;
153 auto MaxDigitsRemove = DecimalMaxDigitsRemove;
154 if (IsBase2) {
155 DigitsPerGroup = Binary;
156 MinDigitsInsert = BinaryMinDigitsInsert;
157 MaxDigitsRemove = BinaryMaxDigitsRemove;
158 } else if (IsBase16) {
159 DigitsPerGroup = Hex;
160 MinDigitsInsert = HexMinDigitsInsert;
161 MaxDigitsRemove = HexMaxDigitsRemove;
162 }
163 const auto SeparatorCount = Text.count(Separator);
164 const int DigitCount = Length - SeparatorCount;
165 if (DigitCount > MaxDigitsRemove && DigitCount < MinDigitsInsert)
166 continue;
167 const bool RemoveSeparator =
168 DigitsPerGroup < 0 || DigitCount <= MaxDigitsRemove;
169 if (RemoveSeparator && SeparatorCount == 0)
170 continue;
171 if (!RemoveSeparator && SeparatorCount > 0 &&
172 checkSeparator(Text, DigitsPerGroup)) {
173 continue;
174 }
175 const auto &Formatted =
176 format(Text, DigitsPerGroup, DigitCount, RemoveSeparator);
177 assert(Formatted != Text);
178 if (Start > 0)
179 Location = Location.getLocWithOffset(Start);
182 }
183
185}