clang 23.0.0git
Format.cpp
Go to the documentation of this file.
1//===--- Format.cpp - Format C++ code -------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file implements functions declared in Format.h. This will be
11/// split into separate files as we go.
12///
13//===----------------------------------------------------------------------===//
14
15#include "clang/Format/Format.h"
26#include "llvm/ADT/Sequence.h"
27#include "llvm/ADT/StringSet.h"
28#include <limits>
29
30#define DEBUG_TYPE "format-formatter"
31
32using clang::format::FormatStyle;
33
34LLVM_YAML_IS_SEQUENCE_VECTOR(FormatStyle::RawStringFormat)
35LLVM_YAML_IS_SEQUENCE_VECTOR(FormatStyle::BinaryOperationBreakRule)
36LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tok::TokenKind)
37
44
45namespace llvm {
46namespace yaml {
47template <>
48struct ScalarEnumerationTraits<FormatStyle::BreakBeforeNoexceptSpecifierStyle> {
49 static void
50 enumeration(IO &IO, FormatStyle::BreakBeforeNoexceptSpecifierStyle &Value) {
51 IO.enumCase(Value, "Never", FormatStyle::BBNSS_Never);
52 IO.enumCase(Value, "OnlyWithParen", FormatStyle::BBNSS_OnlyWithParen);
53 IO.enumCase(Value, "Always", FormatStyle::BBNSS_Always);
54 }
55};
56
57template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {
58 static void enumInput(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
59 IO.enumCase(Value, "None", FormatStyle::AlignConsecutiveStyle({}));
60 IO.enumCase(Value, "Consecutive",
61 FormatStyle::AlignConsecutiveStyle(
62 {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
63 /*AcrossComments=*/false, /*AlignCompound=*/false,
64 /*AlignFunctionDeclarations=*/true,
65 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
66 IO.enumCase(Value, "AcrossEmptyLines",
67 FormatStyle::AlignConsecutiveStyle(
68 {/*Enabled=*/true, /*AcrossEmptyLines=*/true,
69 /*AcrossComments=*/false, /*AlignCompound=*/false,
70 /*AlignFunctionDeclarations=*/true,
71 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
72 IO.enumCase(Value, "AcrossComments",
73 FormatStyle::AlignConsecutiveStyle(
74 {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
75 /*AcrossComments=*/true, /*AlignCompound=*/false,
76 /*AlignFunctionDeclarations=*/true,
77 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
78 IO.enumCase(Value, "AcrossEmptyLinesAndComments",
79 FormatStyle::AlignConsecutiveStyle(
80 {/*Enabled=*/true, /*AcrossEmptyLines=*/true,
81 /*AcrossComments=*/true, /*AlignCompound=*/false,
82 /*AlignFunctionDeclarations=*/true,
83 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
84
85 // For backward compatibility.
86 IO.enumCase(Value, "true",
87 FormatStyle::AlignConsecutiveStyle(
88 {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
89 /*AcrossComments=*/false, /*AlignCompound=*/false,
90 /*AlignFunctionDeclarations=*/true,
91 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
92 IO.enumCase(Value, "false", FormatStyle::AlignConsecutiveStyle({}));
93 }
94
95 static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
96 IO.mapOptional("Enabled", Value.Enabled);
97 IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);
98 IO.mapOptional("AcrossComments", Value.AcrossComments);
99 IO.mapOptional("AlignCompound", Value.AlignCompound);
100 IO.mapOptional("AlignFunctionDeclarations",
101 Value.AlignFunctionDeclarations);
102 IO.mapOptional("AlignFunctionPointers", Value.AlignFunctionPointers);
103 IO.mapOptional("PadOperators", Value.PadOperators);
104 }
105};
106
107template <>
108struct MappingTraits<FormatStyle::ShortCaseStatementsAlignmentStyle> {
109 static void mapping(IO &IO,
110 FormatStyle::ShortCaseStatementsAlignmentStyle &Value) {
111 IO.mapOptional("Enabled", Value.Enabled);
112 IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);
113 IO.mapOptional("AcrossComments", Value.AcrossComments);
114 IO.mapOptional("AlignCaseArrows", Value.AlignCaseArrows);
115 IO.mapOptional("AlignCaseColons", Value.AlignCaseColons);
116 }
117};
118
119template <>
120struct ScalarEnumerationTraits<FormatStyle::AttributeBreakingStyle> {
121 static void enumeration(IO &IO, FormatStyle::AttributeBreakingStyle &Value) {
122 IO.enumCase(Value, "Always", FormatStyle::ABS_Always);
123 IO.enumCase(Value, "Leave", FormatStyle::ABS_Leave);
124 IO.enumCase(Value, "Never", FormatStyle::ABS_Never);
125 }
126};
127
128template <>
129struct ScalarEnumerationTraits<FormatStyle::ArrayInitializerAlignmentStyle> {
130 static void enumeration(IO &IO,
131 FormatStyle::ArrayInitializerAlignmentStyle &Value) {
132 IO.enumCase(Value, "None", FormatStyle::AIAS_None);
133 IO.enumCase(Value, "Left", FormatStyle::AIAS_Left);
134 IO.enumCase(Value, "Right", FormatStyle::AIAS_Right);
135 }
136};
137
138template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> {
139 static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {
140 IO.enumCase(Value, "All", FormatStyle::BOS_All);
141 IO.enumCase(Value, "true", FormatStyle::BOS_All);
142 IO.enumCase(Value, "None", FormatStyle::BOS_None);
143 IO.enumCase(Value, "false", FormatStyle::BOS_None);
144 IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment);
145 }
146};
147
148template <>
149struct ScalarEnumerationTraits<FormatStyle::BinPackParametersStyle> {
150 static void enumeration(IO &IO, FormatStyle::BinPackParametersStyle &Value) {
151 IO.enumCase(Value, "BinPack", FormatStyle::BPPS_BinPack);
152 IO.enumCase(Value, "OnePerLine", FormatStyle::BPPS_OnePerLine);
153 IO.enumCase(Value, "AlwaysOnePerLine", FormatStyle::BPPS_AlwaysOnePerLine);
154
155 // For backward compatibility.
156 IO.enumCase(Value, "true", FormatStyle::BPPS_BinPack);
157 IO.enumCase(Value, "false", FormatStyle::BPPS_OnePerLine);
158 }
159};
160
161template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {
162 static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) {
163 IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto);
164 IO.enumCase(Value, "Always", FormatStyle::BPS_Always);
165 IO.enumCase(Value, "Never", FormatStyle::BPS_Never);
166 }
167};
168
169template <>
170struct ScalarEnumerationTraits<FormatStyle::BitFieldColonSpacingStyle> {
171 static void enumeration(IO &IO,
172 FormatStyle::BitFieldColonSpacingStyle &Value) {
173 IO.enumCase(Value, "Both", FormatStyle::BFCS_Both);
174 IO.enumCase(Value, "None", FormatStyle::BFCS_None);
175 IO.enumCase(Value, "Before", FormatStyle::BFCS_Before);
176 IO.enumCase(Value, "After", FormatStyle::BFCS_After);
177 }
178};
179
180template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
181 static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {
182 IO.enumCase(Value, "Attach", FormatStyle::BS_Attach);
183 IO.enumCase(Value, "Linux", FormatStyle::BS_Linux);
184 IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla);
185 IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);
186 IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
187 IO.enumCase(Value, "Whitesmiths", FormatStyle::BS_Whitesmiths);
188 IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
189 IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit);
190 IO.enumCase(Value, "Custom", FormatStyle::BS_Custom);
191 }
192};
193
194template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
195 static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
196 IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel);
197 IO.mapOptional("AfterClass", Wrapping.AfterClass);
198 IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement);
199 IO.mapOptional("AfterEnum", Wrapping.AfterEnum);
200 IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
201 IO.mapOptional("AfterFunction", Wrapping.AfterFunction);
202 IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace);
203 IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
204 IO.mapOptional("AfterStruct", Wrapping.AfterStruct);
205 IO.mapOptional("AfterUnion", Wrapping.AfterUnion);
206 IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
207 IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
208 IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody);
209 IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile);
210 IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
211 IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);
212 IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);
213 IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
214 }
215};
216
217template <> struct ScalarEnumerationTraits<BracketAlignmentStyle> {
219 IO.enumCase(Value, "Align", BAS_Align);
220 IO.enumCase(Value, "DontAlign", BAS_DontAlign);
221
222 // For backward compatibility.
223 IO.enumCase(Value, "true", BAS_Align);
224 IO.enumCase(Value, "false", BAS_DontAlign);
225 IO.enumCase(Value, "AlwaysBreak", BAS_AlwaysBreak);
226 IO.enumCase(Value, "BlockIndent", BAS_BlockIndent);
227 }
228};
229
230template <>
231struct ScalarEnumerationTraits<
232 FormatStyle::BraceWrappingAfterControlStatementStyle> {
233 static void
235 FormatStyle::BraceWrappingAfterControlStatementStyle &Value) {
236 IO.enumCase(Value, "Never", FormatStyle::BWACS_Never);
237 IO.enumCase(Value, "MultiLine", FormatStyle::BWACS_MultiLine);
238 IO.enumCase(Value, "Always", FormatStyle::BWACS_Always);
239
240 // For backward compatibility.
241 IO.enumCase(Value, "false", FormatStyle::BWACS_Never);
242 IO.enumCase(Value, "true", FormatStyle::BWACS_Always);
243 }
244};
245
246template <>
247struct ScalarEnumerationTraits<
248 FormatStyle::BreakBeforeConceptDeclarationsStyle> {
249 static void
250 enumeration(IO &IO, FormatStyle::BreakBeforeConceptDeclarationsStyle &Value) {
251 IO.enumCase(Value, "Never", FormatStyle::BBCDS_Never);
252 IO.enumCase(Value, "Allowed", FormatStyle::BBCDS_Allowed);
253 IO.enumCase(Value, "Always", FormatStyle::BBCDS_Always);
254
255 // For backward compatibility.
256 IO.enumCase(Value, "true", FormatStyle::BBCDS_Always);
257 IO.enumCase(Value, "false", FormatStyle::BBCDS_Allowed);
258 }
259};
260
261template <>
262struct ScalarEnumerationTraits<FormatStyle::BreakBeforeInlineASMColonStyle> {
263 static void enumeration(IO &IO,
264 FormatStyle::BreakBeforeInlineASMColonStyle &Value) {
265 IO.enumCase(Value, "Never", FormatStyle::BBIAS_Never);
266 IO.enumCase(Value, "OnlyMultiline", FormatStyle::BBIAS_OnlyMultiline);
267 IO.enumCase(Value, "Always", FormatStyle::BBIAS_Always);
268 }
269};
270
271template <>
272struct ScalarEnumerationTraits<FormatStyle::BreakBinaryOperationsStyle> {
273 static void enumeration(IO &IO,
274 FormatStyle::BreakBinaryOperationsStyle &Value) {
275 IO.enumCase(Value, "Never", FormatStyle::BBO_Never);
276 IO.enumCase(Value, "OnePerLine", FormatStyle::BBO_OnePerLine);
277 IO.enumCase(Value, "RespectPrecedence", FormatStyle::BBO_RespectPrecedence);
278 }
279};
280
281template <> struct ScalarTraits<clang::tok::TokenKind> {
282 static void output(const clang::tok::TokenKind &Value, void *,
283 llvm::raw_ostream &Out) {
284 if (const char *Spelling = clang::tok::getPunctuatorSpelling(Value))
285 Out << Spelling;
286 else
288 }
289
290 static StringRef input(StringRef Scalar, void *,
292 // Map operator spelling strings to tok::TokenKind.
293#define PUNCTUATOR(Name, Spelling) \
294 if (Scalar == Spelling) { \
295 Value = clang::tok::Name; \
296 return {}; \
297 }
298#include "clang/Basic/TokenKinds.def"
299 return "unknown operator";
300 }
301
302 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
303};
304
305template <> struct MappingTraits<FormatStyle::BinaryOperationBreakRule> {
306 static void mapping(IO &IO, FormatStyle::BinaryOperationBreakRule &Value) {
307 IO.mapOptional("Operators", Value.Operators);
308 // Default to OnePerLine since a per-operator rule with Never is a no-op.
309 if (!IO.outputting())
310 Value.Style = FormatStyle::BBO_OnePerLine;
311 IO.mapOptional("Style", Value.Style);
312 IO.mapOptional("MinChainLength", Value.MinChainLength);
313 }
314};
315
316template <> struct MappingTraits<FormatStyle::BreakBinaryOperationsOptions> {
317 static void enumInput(IO &IO,
318 FormatStyle::BreakBinaryOperationsOptions &Value) {
319 IO.enumCase(Value, "Never",
320 FormatStyle::BreakBinaryOperationsOptions(
321 {FormatStyle::BBO_Never, {}}));
322 IO.enumCase(Value, "OnePerLine",
323 FormatStyle::BreakBinaryOperationsOptions(
324 {FormatStyle::BBO_OnePerLine, {}}));
325 IO.enumCase(Value, "RespectPrecedence",
326 FormatStyle::BreakBinaryOperationsOptions(
327 {FormatStyle::BBO_RespectPrecedence, {}}));
328 }
329
330 static void mapping(IO &IO,
331 FormatStyle::BreakBinaryOperationsOptions &Value) {
332 IO.mapOptional("Default", Value.Default);
333 IO.mapOptional("PerOperator", Value.PerOperator);
334 }
335};
336
337template <>
338struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
339 static void
340 enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
341 IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon);
342 IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma);
343 IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon);
344 IO.enumCase(Value, "AfterComma", FormatStyle::BCIS_AfterComma);
345 }
346};
347
348template <>
349struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {
350 static void enumeration(IO &IO,
351 FormatStyle::BreakInheritanceListStyle &Value) {
352 IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon);
353 IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma);
354 IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon);
355 IO.enumCase(Value, "AfterComma", FormatStyle::BILS_AfterComma);
356 }
357};
358
359template <>
360struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
361 static void enumeration(IO &IO,
362 FormatStyle::BreakTemplateDeclarationsStyle &Value) {
363 IO.enumCase(Value, "Leave", FormatStyle::BTDS_Leave);
364 IO.enumCase(Value, "No", FormatStyle::BTDS_No);
365 IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);
366 IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);
367
368 // For backward compatibility.
369 IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine);
370 IO.enumCase(Value, "true", FormatStyle::BTDS_Yes);
371 }
372};
373
374template <> struct ScalarEnumerationTraits<FormatStyle::BracedListStyle> {
375 static void enumeration(IO &IO, FormatStyle::BracedListStyle &Value) {
376 IO.enumCase(Value, "Block", FormatStyle::BLS_Block);
377 IO.enumCase(Value, "FunctionCall", FormatStyle::BLS_FunctionCall);
378 IO.enumCase(Value, "AlignFirstComment", FormatStyle::BLS_AlignFirstComment);
379
380 // For backward compatibility.
381 IO.enumCase(Value, "false", FormatStyle::BLS_Block);
382 IO.enumCase(Value, "true", FormatStyle::BLS_AlignFirstComment);
383 }
384};
385
386template <> struct ScalarEnumerationTraits<FormatStyle::DAGArgStyle> {
387 static void enumeration(IO &IO, FormatStyle::DAGArgStyle &Value) {
388 IO.enumCase(Value, "DontBreak", FormatStyle::DAS_DontBreak);
389 IO.enumCase(Value, "BreakElements", FormatStyle::DAS_BreakElements);
390 IO.enumCase(Value, "BreakAll", FormatStyle::DAS_BreakAll);
391 }
392};
393
394template <>
395struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
396 static void
397 enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
398 IO.enumCase(Value, "None", FormatStyle::DRTBS_None);
399 IO.enumCase(Value, "All", FormatStyle::DRTBS_All);
400 IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel);
401
402 // For backward compatibility.
403 IO.enumCase(Value, "false", FormatStyle::DRTBS_None);
404 IO.enumCase(Value, "true", FormatStyle::DRTBS_All);
405 }
406};
407
408template <>
409struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
410 static void enumeration(IO &IO,
411 FormatStyle::EscapedNewlineAlignmentStyle &Value) {
412 IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign);
413 IO.enumCase(Value, "Left", FormatStyle::ENAS_Left);
414 IO.enumCase(Value, "LeftWithLastLine", FormatStyle::ENAS_LeftWithLastLine);
415 IO.enumCase(Value, "Right", FormatStyle::ENAS_Right);
416
417 // For backward compatibility.
418 IO.enumCase(Value, "true", FormatStyle::ENAS_Left);
419 IO.enumCase(Value, "false", FormatStyle::ENAS_Right);
420 }
421};
422
423template <>
424struct ScalarEnumerationTraits<FormatStyle::EmptyLineAfterAccessModifierStyle> {
425 static void
426 enumeration(IO &IO, FormatStyle::EmptyLineAfterAccessModifierStyle &Value) {
427 IO.enumCase(Value, "Never", FormatStyle::ELAAMS_Never);
428 IO.enumCase(Value, "Leave", FormatStyle::ELAAMS_Leave);
429 IO.enumCase(Value, "Always", FormatStyle::ELAAMS_Always);
430 }
431};
432
433template <>
434struct ScalarEnumerationTraits<
435 FormatStyle::EmptyLineBeforeAccessModifierStyle> {
436 static void
437 enumeration(IO &IO, FormatStyle::EmptyLineBeforeAccessModifierStyle &Value) {
438 IO.enumCase(Value, "Never", FormatStyle::ELBAMS_Never);
439 IO.enumCase(Value, "Leave", FormatStyle::ELBAMS_Leave);
440 IO.enumCase(Value, "LogicalBlock", FormatStyle::ELBAMS_LogicalBlock);
441 IO.enumCase(Value, "Always", FormatStyle::ELBAMS_Always);
442 }
443};
444
445template <>
446struct ScalarEnumerationTraits<FormatStyle::EnumTrailingCommaStyle> {
447 static void enumeration(IO &IO, FormatStyle::EnumTrailingCommaStyle &Value) {
448 IO.enumCase(Value, "Leave", FormatStyle::ETC_Leave);
449 IO.enumCase(Value, "Insert", FormatStyle::ETC_Insert);
450 IO.enumCase(Value, "Remove", FormatStyle::ETC_Remove);
451 }
452};
453
454template <>
455struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> {
456 static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value) {
457 IO.enumCase(Value, "AfterExternBlock", FormatStyle::IEBS_AfterExternBlock);
458 IO.enumCase(Value, "Indent", FormatStyle::IEBS_Indent);
459 IO.enumCase(Value, "NoIndent", FormatStyle::IEBS_NoIndent);
460 IO.enumCase(Value, "true", FormatStyle::IEBS_Indent);
461 IO.enumCase(Value, "false", FormatStyle::IEBS_NoIndent);
462 }
463};
464
465template <> struct MappingTraits<FormatStyle::IntegerLiteralSeparatorStyle> {
466 static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &Base) {
467 IO.mapOptional("Binary", Base.Binary);
468 IO.mapOptional("BinaryMinDigitsInsert", Base.BinaryMinDigitsInsert);
469 IO.mapOptional("BinaryMaxDigitsRemove", Base.BinaryMaxDigitsRemove);
470 IO.mapOptional("Decimal", Base.Decimal);
471 IO.mapOptional("DecimalMinDigitsInsert", Base.DecimalMinDigitsInsert);
472 IO.mapOptional("DecimalMaxDigitsRemove", Base.DecimalMaxDigitsRemove);
473 IO.mapOptional("Hex", Base.Hex);
474 IO.mapOptional("HexMinDigitsInsert", Base.HexMinDigitsInsert);
475 IO.mapOptional("HexMaxDigitsRemove", Base.HexMaxDigitsRemove);
476
477 // For backward compatibility.
478 IO.mapOptional("BinaryMinDigits", Base.BinaryMinDigitsInsert);
479 IO.mapOptional("DecimalMinDigits", Base.DecimalMinDigitsInsert);
480 IO.mapOptional("HexMinDigits", Base.HexMinDigitsInsert);
481 }
482};
483
484template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {
485 static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) {
486 IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave);
487 IO.enumCase(Value, "Single", FormatStyle::JSQS_Single);
488 IO.enumCase(Value, "Double", FormatStyle::JSQS_Double);
489 }
490};
491
492template <> struct MappingTraits<FormatStyle::KeepEmptyLinesStyle> {
493 static void mapping(IO &IO, FormatStyle::KeepEmptyLinesStyle &Value) {
494 IO.mapOptional("AtEndOfFile", Value.AtEndOfFile);
495 IO.mapOptional("AtStartOfBlock", Value.AtStartOfBlock);
496 IO.mapOptional("AtStartOfFile", Value.AtStartOfFile);
497 }
498};
499
500template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
501 static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
502 IO.enumCase(Value, "C", FormatStyle::LK_C);
503 IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
504 IO.enumCase(Value, "Java", FormatStyle::LK_Java);
505 IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
506 IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);
507 IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
508 IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);
509 IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto);
510 IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp);
511 IO.enumCase(Value, "Json", FormatStyle::LK_Json);
512 IO.enumCase(Value, "Verilog", FormatStyle::LK_Verilog);
513 }
514};
515
516template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
517 static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
518 IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03);
519 IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias
520 IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias
521
522 IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11);
523 IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias
524
525 IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14);
526 IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17);
527 IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20);
528
529 IO.enumCase(Value, "Latest", FormatStyle::LS_Latest);
530 IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias
531 IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);
532 }
533};
534
535template <>
536struct ScalarEnumerationTraits<FormatStyle::LambdaBodyIndentationKind> {
537 static void enumeration(IO &IO,
538 FormatStyle::LambdaBodyIndentationKind &Value) {
539 IO.enumCase(Value, "Signature", FormatStyle::LBI_Signature);
540 IO.enumCase(Value, "OuterScope", FormatStyle::LBI_OuterScope);
541 }
542};
543
544template <> struct ScalarEnumerationTraits<FormatStyle::LineEndingStyle> {
545 static void enumeration(IO &IO, FormatStyle::LineEndingStyle &Value) {
546 IO.enumCase(Value, "LF", FormatStyle::LE_LF);
547 IO.enumCase(Value, "CRLF", FormatStyle::LE_CRLF);
548 IO.enumCase(Value, "DeriveLF", FormatStyle::LE_DeriveLF);
549 IO.enumCase(Value, "DeriveCRLF", FormatStyle::LE_DeriveCRLF);
550 }
551};
552
553template <>
554struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
555 static void enumeration(IO &IO,
556 FormatStyle::NamespaceIndentationKind &Value) {
557 IO.enumCase(Value, "None", FormatStyle::NI_None);
558 IO.enumCase(Value, "Inner", FormatStyle::NI_Inner);
559 IO.enumCase(Value, "All", FormatStyle::NI_All);
560 }
561};
562
563template <>
564struct ScalarEnumerationTraits<FormatStyle::NumericLiteralComponentStyle> {
565 static void enumeration(IO &IO,
566 FormatStyle::NumericLiteralComponentStyle &Value) {
567 IO.enumCase(Value, "Leave", FormatStyle::NLCS_Leave);
568 IO.enumCase(Value, "Upper", FormatStyle::NLCS_Upper);
569 IO.enumCase(Value, "Lower", FormatStyle::NLCS_Lower);
570 }
571};
572
573template <> struct MappingTraits<FormatStyle::NumericLiteralCaseStyle> {
574 static void mapping(IO &IO, FormatStyle::NumericLiteralCaseStyle &Value) {
575 IO.mapOptional("ExponentLetter", Value.ExponentLetter);
576 IO.mapOptional("HexDigit", Value.HexDigit);
577 IO.mapOptional("Prefix", Value.Prefix);
578 IO.mapOptional("Suffix", Value.Suffix);
579 }
580};
581
582template <> struct ScalarEnumerationTraits<FormatStyle::OperandAlignmentStyle> {
583 static void enumeration(IO &IO, FormatStyle::OperandAlignmentStyle &Value) {
584 IO.enumCase(Value, "DontAlign", FormatStyle::OAS_DontAlign);
585 IO.enumCase(Value, "Align", FormatStyle::OAS_Align);
586 IO.enumCase(Value, "AlignAfterOperator",
587 FormatStyle::OAS_AlignAfterOperator);
588
589 // For backward compatibility.
590 IO.enumCase(Value, "true", FormatStyle::OAS_Align);
591 IO.enumCase(Value, "false", FormatStyle::OAS_DontAlign);
592 }
593};
594
595template <>
596struct ScalarEnumerationTraits<FormatStyle::PackConstructorInitializersStyle> {
597 static void
598 enumeration(IO &IO, FormatStyle::PackConstructorInitializersStyle &Value) {
599 IO.enumCase(Value, "Never", FormatStyle::PCIS_Never);
600 IO.enumCase(Value, "BinPack", FormatStyle::PCIS_BinPack);
601 IO.enumCase(Value, "CurrentLine", FormatStyle::PCIS_CurrentLine);
602 IO.enumCase(Value, "NextLine", FormatStyle::PCIS_NextLine);
603 IO.enumCase(Value, "NextLineOnly", FormatStyle::PCIS_NextLineOnly);
604 }
605};
606
607template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
608 static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {
609 IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
610 IO.enumCase(Value, "Left", FormatStyle::PAS_Left);
611 IO.enumCase(Value, "Right", FormatStyle::PAS_Right);
612
613 // For backward compatibility.
614 IO.enumCase(Value, "true", FormatStyle::PAS_Left);
615 IO.enumCase(Value, "false", FormatStyle::PAS_Right);
616 }
617};
618
619template <>
620struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
621 static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
622 IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
623 IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);
624 IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash);
625 IO.enumCase(Value, "Leave", FormatStyle::PPDIS_Leave);
626 }
627};
628
629template <>
630struct ScalarEnumerationTraits<FormatStyle::QualifierAlignmentStyle> {
631 static void enumeration(IO &IO, FormatStyle::QualifierAlignmentStyle &Value) {
632 IO.enumCase(Value, "Leave", FormatStyle::QAS_Leave);
633 IO.enumCase(Value, "Left", FormatStyle::QAS_Left);
634 IO.enumCase(Value, "Right", FormatStyle::QAS_Right);
635 IO.enumCase(Value, "Custom", FormatStyle::QAS_Custom);
636 }
637};
638
639template <> struct MappingTraits<FormatStyle::RawStringFormat> {
640 static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
641 IO.mapOptional("Language", Format.Language);
642 IO.mapOptional("Delimiters", Format.Delimiters);
643 IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);
644 IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter);
645 IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);
646 }
647};
648
649template <> struct ScalarEnumerationTraits<FormatStyle::ReflowCommentsStyle> {
650 static void enumeration(IO &IO, FormatStyle::ReflowCommentsStyle &Value) {
651 IO.enumCase(Value, "Never", FormatStyle::RCS_Never);
652 IO.enumCase(Value, "IndentOnly", FormatStyle::RCS_IndentOnly);
653 IO.enumCase(Value, "Always", FormatStyle::RCS_Always);
654 // For backward compatibility:
655 IO.enumCase(Value, "false", FormatStyle::RCS_Never);
656 IO.enumCase(Value, "true", FormatStyle::RCS_Always);
657 }
658};
659
660template <>
661struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> {
662 static void enumeration(IO &IO, FormatStyle::ReferenceAlignmentStyle &Value) {
663 IO.enumCase(Value, "Pointer", FormatStyle::RAS_Pointer);
664 IO.enumCase(Value, "Middle", FormatStyle::RAS_Middle);
665 IO.enumCase(Value, "Left", FormatStyle::RAS_Left);
666 IO.enumCase(Value, "Right", FormatStyle::RAS_Right);
667 }
668};
669
670template <>
671struct ScalarEnumerationTraits<FormatStyle::RemoveParenthesesStyle> {
672 static void enumeration(IO &IO, FormatStyle::RemoveParenthesesStyle &Value) {
673 IO.enumCase(Value, "Leave", FormatStyle::RPS_Leave);
674 IO.enumCase(Value, "MultipleParentheses",
675 FormatStyle::RPS_MultipleParentheses);
676 IO.enumCase(Value, "ReturnStatement", FormatStyle::RPS_ReturnStatement);
677 }
678};
679
680template <>
681struct ScalarEnumerationTraits<FormatStyle::RequiresClausePositionStyle> {
682 static void enumeration(IO &IO,
683 FormatStyle::RequiresClausePositionStyle &Value) {
684 IO.enumCase(Value, "OwnLine", FormatStyle::RCPS_OwnLine);
685 IO.enumCase(Value, "OwnLineWithBrace", FormatStyle::RCPS_OwnLineWithBrace);
686 IO.enumCase(Value, "WithPreceding", FormatStyle::RCPS_WithPreceding);
687 IO.enumCase(Value, "WithFollowing", FormatStyle::RCPS_WithFollowing);
688 IO.enumCase(Value, "SingleLine", FormatStyle::RCPS_SingleLine);
689 }
690};
691
692template <>
693struct ScalarEnumerationTraits<FormatStyle::RequiresExpressionIndentationKind> {
694 static void
695 enumeration(IO &IO, FormatStyle::RequiresExpressionIndentationKind &Value) {
696 IO.enumCase(Value, "Keyword", FormatStyle::REI_Keyword);
697 IO.enumCase(Value, "OuterScope", FormatStyle::REI_OuterScope);
698 }
699};
700
701template <>
702struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
703 static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
704 IO.enumCase(Value, "None", FormatStyle::RTBS_None);
705 IO.enumCase(Value, "Automatic", FormatStyle::RTBS_Automatic);
706 IO.enumCase(Value, "ExceptShortType", FormatStyle::RTBS_ExceptShortType);
707 IO.enumCase(Value, "All", FormatStyle::RTBS_All);
708 IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel);
709 IO.enumCase(Value, "TopLevelDefinitions",
710 FormatStyle::RTBS_TopLevelDefinitions);
711 IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions);
712 }
713};
714
715template <>
716struct ScalarEnumerationTraits<FormatStyle::SeparateDefinitionStyle> {
717 static void enumeration(IO &IO, FormatStyle::SeparateDefinitionStyle &Value) {
718 IO.enumCase(Value, "Leave", FormatStyle::SDS_Leave);
719 IO.enumCase(Value, "Always", FormatStyle::SDS_Always);
720 IO.enumCase(Value, "Never", FormatStyle::SDS_Never);
721 }
722};
723
724template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> {
725 static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) {
726 IO.enumCase(Value, "Never", FormatStyle::SBS_Never);
727 IO.enumCase(Value, "false", FormatStyle::SBS_Never);
728 IO.enumCase(Value, "Always", FormatStyle::SBS_Always);
729 IO.enumCase(Value, "true", FormatStyle::SBS_Always);
730 IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty);
731 }
732};
733
734template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
735 static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
736 IO.enumCase(Value, "None", FormatStyle::SFS_None);
737 IO.enumCase(Value, "false", FormatStyle::SFS_None);
738 IO.enumCase(Value, "All", FormatStyle::SFS_All);
739 IO.enumCase(Value, "true", FormatStyle::SFS_All);
740 IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
741 IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly);
742 IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);
743 }
744};
745
746template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> {
747 static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) {
748 IO.enumCase(Value, "Never", FormatStyle::SIS_Never);
749 IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse);
750 IO.enumCase(Value, "OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf);
751 IO.enumCase(Value, "AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse);
752
753 // For backward compatibility.
754 IO.enumCase(Value, "Always", FormatStyle::SIS_OnlyFirstIf);
755 IO.enumCase(Value, "false", FormatStyle::SIS_Never);
756 IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse);
757 }
758};
759
760template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> {
761 static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) {
762 IO.enumCase(Value, "None", FormatStyle::SLS_None);
763 IO.enumCase(Value, "false", FormatStyle::SLS_None);
764 IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty);
765 IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline);
766 IO.enumCase(Value, "All", FormatStyle::SLS_All);
767 IO.enumCase(Value, "true", FormatStyle::SLS_All);
768 }
769};
770
771template <> struct MappingTraits<FormatStyle::SortIncludesOptions> {
772 static void enumInput(IO &IO, FormatStyle::SortIncludesOptions &Value) {
773 IO.enumCase(Value, "Never", FormatStyle::SortIncludesOptions({}));
774 IO.enumCase(Value, "CaseInsensitive",
775 FormatStyle::SortIncludesOptions({/*Enabled=*/true,
776 /*IgnoreCase=*/true,
777 /*IgnoreExtension=*/false}));
778 IO.enumCase(Value, "CaseSensitive",
779 FormatStyle::SortIncludesOptions({/*Enabled=*/true,
780 /*IgnoreCase=*/false,
781 /*IgnoreExtension=*/false}));
782
783 // For backward compatibility.
784 IO.enumCase(Value, "false", FormatStyle::SortIncludesOptions({}));
785 IO.enumCase(Value, "true",
786 FormatStyle::SortIncludesOptions({/*Enabled=*/true,
787 /*IgnoreCase=*/false,
788 /*IgnoreExtension=*/false}));
789 }
790
791 static void mapping(IO &IO, FormatStyle::SortIncludesOptions &Value) {
792 IO.mapOptional("Enabled", Value.Enabled);
793 IO.mapOptional("IgnoreCase", Value.IgnoreCase);
794 IO.mapOptional("IgnoreExtension", Value.IgnoreExtension);
795 }
796};
797
798template <>
799struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> {
800 static void enumeration(IO &IO,
801 FormatStyle::SortJavaStaticImportOptions &Value) {
802 IO.enumCase(Value, "Before", FormatStyle::SJSIO_Before);
803 IO.enumCase(Value, "After", FormatStyle::SJSIO_After);
804 }
805};
806
807template <>
808struct ScalarEnumerationTraits<FormatStyle::SortUsingDeclarationsOptions> {
809 static void enumeration(IO &IO,
810 FormatStyle::SortUsingDeclarationsOptions &Value) {
811 IO.enumCase(Value, "Never", FormatStyle::SUD_Never);
812 IO.enumCase(Value, "Lexicographic", FormatStyle::SUD_Lexicographic);
813 IO.enumCase(Value, "LexicographicNumeric",
814 FormatStyle::SUD_LexicographicNumeric);
815
816 // For backward compatibility.
817 IO.enumCase(Value, "false", FormatStyle::SUD_Never);
818 IO.enumCase(Value, "true", FormatStyle::SUD_LexicographicNumeric);
819 }
820};
821
822template <>
823struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> {
824 static void
825 enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value) {
826 IO.enumCase(Value, "Default", FormatStyle::SAPQ_Default);
827 IO.enumCase(Value, "Before", FormatStyle::SAPQ_Before);
828 IO.enumCase(Value, "After", FormatStyle::SAPQ_After);
829 IO.enumCase(Value, "Both", FormatStyle::SAPQ_Both);
830 }
831};
832
833template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> {
834 static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) {
835 IO.mapOptional("AfterControlStatements", Spacing.AfterControlStatements);
836 IO.mapOptional("AfterForeachMacros", Spacing.AfterForeachMacros);
837 IO.mapOptional("AfterFunctionDefinitionName",
838 Spacing.AfterFunctionDefinitionName);
839 IO.mapOptional("AfterFunctionDeclarationName",
840 Spacing.AfterFunctionDeclarationName);
841 IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros);
842 IO.mapOptional("AfterNot", Spacing.AfterNot);
843 IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
844 IO.mapOptional("AfterPlacementOperator", Spacing.AfterPlacementOperator);
845 IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause);
846 IO.mapOptional("AfterRequiresInExpression",
847 Spacing.AfterRequiresInExpression);
848 IO.mapOptional("BeforeNonEmptyParentheses",
849 Spacing.BeforeNonEmptyParentheses);
850 }
851};
852
853template <>
854struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> {
855 static void enumeration(IO &IO, FormatStyle::SpaceBeforeParensStyle &Value) {
856 IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
857 IO.enumCase(Value, "ControlStatements",
858 FormatStyle::SBPO_ControlStatements);
859 IO.enumCase(Value, "ControlStatementsExceptControlMacros",
860 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
861 IO.enumCase(Value, "NonEmptyParentheses",
862 FormatStyle::SBPO_NonEmptyParentheses);
863 IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
864 IO.enumCase(Value, "Custom", FormatStyle::SBPO_Custom);
865
866 // For backward compatibility.
867 IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
868 IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);
869 IO.enumCase(Value, "ControlStatementsExceptForEachMacros",
870 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
871 }
872};
873
874template <>
875struct ScalarEnumerationTraits<FormatStyle::SpaceInEmptyBracesStyle> {
876 static void enumeration(IO &IO, FormatStyle::SpaceInEmptyBracesStyle &Value) {
877 IO.enumCase(Value, "Always", FormatStyle::SIEB_Always);
878 IO.enumCase(Value, "Block", FormatStyle::SIEB_Block);
879 IO.enumCase(Value, "Never", FormatStyle::SIEB_Never);
880 }
881};
882
883template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> {
884 static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value) {
885 IO.enumCase(Value, "Never", FormatStyle::SIAS_Never);
886 IO.enumCase(Value, "Always", FormatStyle::SIAS_Always);
887 IO.enumCase(Value, "Leave", FormatStyle::SIAS_Leave);
888
889 // For backward compatibility.
890 IO.enumCase(Value, "false", FormatStyle::SIAS_Never);
891 IO.enumCase(Value, "true", FormatStyle::SIAS_Always);
892 }
893};
894
895template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {
896 static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
897 // Transform the maximum to signed, to parse "-1" correctly
898 int signedMaximum = static_cast<int>(Space.Maximum);
899 IO.mapOptional("Minimum", Space.Minimum);
900 IO.mapOptional("Maximum", signedMaximum);
901 Space.Maximum = static_cast<unsigned>(signedMaximum);
902
903 if (Space.Maximum < std::numeric_limits<unsigned>::max())
904 Space.Minimum = std::min(Space.Minimum, Space.Maximum);
905 }
906};
907
908template <> struct MappingTraits<FormatStyle::SpacesInParensCustom> {
909 static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) {
910 IO.mapOptional("ExceptDoubleParentheses", Spaces.ExceptDoubleParentheses);
911 IO.mapOptional("InCStyleCasts", Spaces.InCStyleCasts);
912 IO.mapOptional("InConditionalStatements", Spaces.InConditionalStatements);
913 IO.mapOptional("InEmptyParentheses", Spaces.InEmptyParentheses);
914 IO.mapOptional("Other", Spaces.Other);
915 }
916};
917
918template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInParensStyle> {
919 static void enumeration(IO &IO, FormatStyle::SpacesInParensStyle &Value) {
920 IO.enumCase(Value, "Never", FormatStyle::SIPO_Never);
921 IO.enumCase(Value, "Custom", FormatStyle::SIPO_Custom);
922 }
923};
924
925template <> struct ScalarEnumerationTraits<FormatStyle::TrailingCommaStyle> {
926 static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) {
927 IO.enumCase(Value, "None", FormatStyle::TCS_None);
928 IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped);
929 }
930};
931
932template <>
933struct ScalarEnumerationTraits<FormatStyle::TrailingCommentsAlignmentKinds> {
934 static void enumeration(IO &IO,
935 FormatStyle::TrailingCommentsAlignmentKinds &Value) {
936 IO.enumCase(Value, "Leave", FormatStyle::TCAS_Leave);
937 IO.enumCase(Value, "Always", FormatStyle::TCAS_Always);
938 IO.enumCase(Value, "Never", FormatStyle::TCAS_Never);
939 }
940};
941
942template <> struct MappingTraits<FormatStyle::TrailingCommentsAlignmentStyle> {
943 static void enumInput(IO &IO,
944 FormatStyle::TrailingCommentsAlignmentStyle &Value) {
945 IO.enumCase(Value, "Leave",
946 FormatStyle::TrailingCommentsAlignmentStyle(
947 {FormatStyle::TCAS_Leave, 0, true}));
948
949 IO.enumCase(Value, "Always",
950 FormatStyle::TrailingCommentsAlignmentStyle(
951 {FormatStyle::TCAS_Always, 0, true}));
952
953 IO.enumCase(Value, "Never",
954 FormatStyle::TrailingCommentsAlignmentStyle(
955 {FormatStyle::TCAS_Never, 0, true}));
956
957 // For backwards compatibility
958 IO.enumCase(Value, "true",
959 FormatStyle::TrailingCommentsAlignmentStyle(
960 {FormatStyle::TCAS_Always, 0, true}));
961 IO.enumCase(Value, "false",
962 FormatStyle::TrailingCommentsAlignmentStyle(
963 {FormatStyle::TCAS_Never, 0, true}));
964 }
965
966 static void mapping(IO &IO,
967 FormatStyle::TrailingCommentsAlignmentStyle &Value) {
968 IO.mapOptional("AlignPPAndNotPP", Value.AlignPPAndNotPP);
969 IO.mapOptional("Kind", Value.Kind);
970 IO.mapOptional("OverEmptyLines", Value.OverEmptyLines);
971 }
972};
973
974template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
975 static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {
976 IO.enumCase(Value, "Never", FormatStyle::UT_Never);
977 IO.enumCase(Value, "false", FormatStyle::UT_Never);
978 IO.enumCase(Value, "Always", FormatStyle::UT_Always);
979 IO.enumCase(Value, "true", FormatStyle::UT_Always);
980 IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation);
981 IO.enumCase(Value, "ForContinuationAndIndentation",
982 FormatStyle::UT_ForContinuationAndIndentation);
983 IO.enumCase(Value, "AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);
984 }
985};
986
987template <>
988struct ScalarEnumerationTraits<
989 FormatStyle::WrapNamespaceBodyWithEmptyLinesStyle> {
990 static void
992 FormatStyle::WrapNamespaceBodyWithEmptyLinesStyle &Value) {
993 IO.enumCase(Value, "Never", FormatStyle::WNBWELS_Never);
994 IO.enumCase(Value, "Always", FormatStyle::WNBWELS_Always);
995 IO.enumCase(Value, "Leave", FormatStyle::WNBWELS_Leave);
996 }
997};
998
999template <> struct MappingTraits<FormatStyle> {
1000 static void mapping(IO &IO, FormatStyle &Style) {
1001 // When reading, read the language first, we need it for getPredefinedStyle.
1002 IO.mapOptional("Language", Style.Language);
1003
1004 StringRef BasedOnStyle;
1005 if (IO.outputting()) {
1006 StringRef Styles[] = {"LLVM", "Google", "Chromium", "Mozilla",
1007 "WebKit", "GNU", "Microsoft", "clang-format"};
1008 for (StringRef StyleName : Styles) {
1009 FormatStyle PredefinedStyle;
1010 if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) &&
1011 Style == PredefinedStyle) {
1012 BasedOnStyle = StyleName;
1013 break;
1014 }
1015 }
1016 } else {
1017 IO.mapOptional("BasedOnStyle", BasedOnStyle);
1018 if (!BasedOnStyle.empty()) {
1019 FormatStyle::LanguageKind OldLanguage = Style.Language;
1020 FormatStyle::LanguageKind Language =
1021 ((FormatStyle *)IO.getContext())->Language;
1022 if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
1023 IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle));
1024 return;
1025 }
1026 Style.Language = OldLanguage;
1027 }
1028 }
1029
1030 // Initialize some variables used in the parsing. The using logic is at the
1031 // end.
1032
1033 // For backward compatibility:
1034 // The default value of ConstructorInitializerAllOnOneLineOrOnePerLine was
1035 // false unless BasedOnStyle was Google or Chromium whereas that of
1036 // AllowAllConstructorInitializersOnNextLine was always true, so the
1037 // equivalent default value of PackConstructorInitializers is PCIS_NextLine
1038 // for Google/Chromium or PCIS_BinPack otherwise. If the deprecated options
1039 // had a non-default value while PackConstructorInitializers has a default
1040 // value, set the latter to an equivalent non-default value if needed.
1041 const bool IsGoogleOrChromium = BasedOnStyle.equals_insensitive("google") ||
1042 BasedOnStyle.equals_insensitive("chromium");
1043 bool OnCurrentLine = IsGoogleOrChromium;
1044 bool OnNextLine = true;
1045
1046 bool BreakBeforeInheritanceComma = false;
1047 bool BreakConstructorInitializersBeforeComma = false;
1048
1049 bool DeriveLineEnding = true;
1050 bool UseCRLF = false;
1051
1052 bool SpaceInEmptyBlock = false;
1053 bool SpaceInEmptyParentheses = false;
1054 bool SpacesInConditionalStatement = false;
1055 bool SpacesInCStyleCastParentheses = false;
1056 bool SpacesInParentheses = false;
1057
1058 if (IO.outputting()) {
1059 IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
1060 } else {
1061 // For backward compatibility.
1063 if (IsGoogleOrChromium) {
1064 FormatStyle::LanguageKind Language = Style.Language;
1065 if (Language == FormatStyle::LK_None)
1066 Language = ((FormatStyle *)IO.getContext())->Language;
1067 if (Language == FormatStyle::LK_JavaScript)
1068 LocalBAS = BAS_AlwaysBreak;
1069 else if (Language == FormatStyle::LK_Java)
1070 LocalBAS = BAS_DontAlign;
1071 } else if (BasedOnStyle.equals_insensitive("webkit")) {
1072 LocalBAS = BAS_DontAlign;
1073 }
1074 IO.mapOptional("AlignAfterOpenBracket", LocalBAS);
1075 Style.BreakAfterOpenBracketBracedList = false;
1076 Style.BreakAfterOpenBracketFunction = false;
1077 Style.BreakAfterOpenBracketIf = false;
1078 Style.BreakAfterOpenBracketLoop = false;
1079 Style.BreakAfterOpenBracketSwitch = false;
1080 Style.BreakBeforeCloseBracketBracedList = false;
1081 Style.BreakBeforeCloseBracketFunction = false;
1082 Style.BreakBeforeCloseBracketIf = false;
1083 Style.BreakBeforeCloseBracketLoop = false;
1084 Style.BreakBeforeCloseBracketSwitch = false;
1085
1086 switch (LocalBAS) {
1087 case BAS_DontAlign:
1088 Style.AlignAfterOpenBracket = false;
1089 break;
1090 case BAS_BlockIndent:
1091 Style.BreakBeforeCloseBracketBracedList = true;
1092 Style.BreakBeforeCloseBracketFunction = true;
1093 Style.BreakBeforeCloseBracketIf = true;
1094 [[fallthrough]];
1095 case BAS_AlwaysBreak:
1096 Style.BreakAfterOpenBracketBracedList = true;
1097 Style.BreakAfterOpenBracketFunction = true;
1098 Style.BreakAfterOpenBracketIf = true;
1099 [[fallthrough]];
1100 case BAS_Align:
1101 Style.AlignAfterOpenBracket = true;
1102 break;
1103 }
1104 }
1105
1106 // For backward compatibility.
1107 if (!IO.outputting()) {
1108 IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines);
1109 IO.mapOptional("AllowAllConstructorInitializersOnNextLine", OnNextLine);
1110 IO.mapOptional("AlwaysBreakAfterReturnType", Style.BreakAfterReturnType);
1111 IO.mapOptional("AlwaysBreakTemplateDeclarations",
1112 Style.BreakTemplateDeclarations);
1113 IO.mapOptional("BreakBeforeInheritanceComma",
1114 BreakBeforeInheritanceComma);
1115 IO.mapOptional("BreakConstructorInitializersBeforeComma",
1116 BreakConstructorInitializersBeforeComma);
1117 IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
1118 OnCurrentLine);
1119 IO.mapOptional("DeriveLineEnding", DeriveLineEnding);
1120 IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
1121 IO.mapOptional("KeepEmptyLinesAtEOF", Style.KeepEmptyLines.AtEndOfFile);
1122 IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
1123 Style.KeepEmptyLines.AtStartOfBlock);
1124 IO.mapOptional("IndentFunctionDeclarationAfterType",
1125 Style.IndentWrappedFunctionNames);
1126 IO.mapOptional("IndentRequires", Style.IndentRequiresClause);
1127 IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
1128 IO.mapOptional("SpaceAfterControlStatementKeyword",
1129 Style.SpaceBeforeParens);
1130 IO.mapOptional("SpaceInEmptyBlock", SpaceInEmptyBlock);
1131 IO.mapOptional("SpaceInEmptyParentheses", SpaceInEmptyParentheses);
1132 IO.mapOptional("SpacesInConditionalStatement",
1133 SpacesInConditionalStatement);
1134 IO.mapOptional("SpacesInCStyleCastParentheses",
1135 SpacesInCStyleCastParentheses);
1136 IO.mapOptional("SpacesInParentheses", SpacesInParentheses);
1137 IO.mapOptional("UseCRLF", UseCRLF);
1138 }
1139
1140 IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
1141 IO.mapOptional("AlignArrayOfStructures", Style.AlignArrayOfStructures);
1142 IO.mapOptional("AlignConsecutiveAssignments",
1143 Style.AlignConsecutiveAssignments);
1144 IO.mapOptional("AlignConsecutiveBitFields",
1145 Style.AlignConsecutiveBitFields);
1146 IO.mapOptional("AlignConsecutiveDeclarations",
1147 Style.AlignConsecutiveDeclarations);
1148 IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);
1149 IO.mapOptional("AlignConsecutiveShortCaseStatements",
1150 Style.AlignConsecutiveShortCaseStatements);
1151 IO.mapOptional("AlignConsecutiveTableGenBreakingDAGArgColons",
1152 Style.AlignConsecutiveTableGenBreakingDAGArgColons);
1153 IO.mapOptional("AlignConsecutiveTableGenCondOperatorColons",
1154 Style.AlignConsecutiveTableGenCondOperatorColons);
1155 IO.mapOptional("AlignConsecutiveTableGenDefinitionColons",
1156 Style.AlignConsecutiveTableGenDefinitionColons);
1157 IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines);
1158 IO.mapOptional("AlignOperands", Style.AlignOperands);
1159 IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
1160 IO.mapOptional("AllowAllArgumentsOnNextLine",
1161 Style.AllowAllArgumentsOnNextLine);
1162 IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
1163 Style.AllowAllParametersOfDeclarationOnNextLine);
1164 IO.mapOptional("AllowBreakBeforeNoexceptSpecifier",
1165 Style.AllowBreakBeforeNoexceptSpecifier);
1166 IO.mapOptional("AllowBreakBeforeQtProperty",
1167 Style.AllowBreakBeforeQtProperty);
1168 IO.mapOptional("AllowShortBlocksOnASingleLine",
1169 Style.AllowShortBlocksOnASingleLine);
1170 IO.mapOptional("AllowShortCaseExpressionOnASingleLine",
1171 Style.AllowShortCaseExpressionOnASingleLine);
1172 IO.mapOptional("AllowShortCaseLabelsOnASingleLine",
1173 Style.AllowShortCaseLabelsOnASingleLine);
1174 IO.mapOptional("AllowShortCompoundRequirementOnASingleLine",
1175 Style.AllowShortCompoundRequirementOnASingleLine);
1176 IO.mapOptional("AllowShortEnumsOnASingleLine",
1177 Style.AllowShortEnumsOnASingleLine);
1178 IO.mapOptional("AllowShortFunctionsOnASingleLine",
1179 Style.AllowShortFunctionsOnASingleLine);
1180 IO.mapOptional("AllowShortIfStatementsOnASingleLine",
1181 Style.AllowShortIfStatementsOnASingleLine);
1182 IO.mapOptional("AllowShortLambdasOnASingleLine",
1183 Style.AllowShortLambdasOnASingleLine);
1184 IO.mapOptional("AllowShortLoopsOnASingleLine",
1185 Style.AllowShortLoopsOnASingleLine);
1186 IO.mapOptional("AllowShortNamespacesOnASingleLine",
1187 Style.AllowShortNamespacesOnASingleLine);
1188 IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",
1189 Style.AlwaysBreakAfterDefinitionReturnType);
1190 IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
1191 Style.AlwaysBreakBeforeMultilineStrings);
1192 IO.mapOptional("AttributeMacros", Style.AttributeMacros);
1193 IO.mapOptional("BinPackArguments", Style.BinPackArguments);
1194 IO.mapOptional("BinPackLongBracedList", Style.BinPackLongBracedList);
1195 IO.mapOptional("BinPackParameters", Style.BinPackParameters);
1196 IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing);
1197 IO.mapOptional("BracedInitializerIndentWidth",
1198 Style.BracedInitializerIndentWidth);
1199 IO.mapOptional("BraceWrapping", Style.BraceWrapping);
1200 IO.mapOptional("BreakAdjacentStringLiterals",
1201 Style.BreakAdjacentStringLiterals);
1202 IO.mapOptional("BreakAfterAttributes", Style.BreakAfterAttributes);
1203 IO.mapOptional("BreakAfterJavaFieldAnnotations",
1204 Style.BreakAfterJavaFieldAnnotations);
1205 IO.mapOptional("BreakAfterOpenBracketBracedList",
1206 Style.BreakAfterOpenBracketBracedList);
1207 IO.mapOptional("BreakAfterOpenBracketFunction",
1208 Style.BreakAfterOpenBracketFunction);
1209 IO.mapOptional("BreakAfterOpenBracketIf", Style.BreakAfterOpenBracketIf);
1210 IO.mapOptional("BreakAfterOpenBracketLoop",
1211 Style.BreakAfterOpenBracketLoop);
1212 IO.mapOptional("BreakAfterOpenBracketSwitch",
1213 Style.BreakAfterOpenBracketSwitch);
1214 IO.mapOptional("BreakAfterReturnType", Style.BreakAfterReturnType);
1215 IO.mapOptional("BreakArrays", Style.BreakArrays);
1216 IO.mapOptional("BreakBeforeBinaryOperators",
1217 Style.BreakBeforeBinaryOperators);
1218 IO.mapOptional("BreakBeforeCloseBracketBracedList",
1219 Style.BreakBeforeCloseBracketBracedList);
1220 IO.mapOptional("BreakBeforeCloseBracketFunction",
1221 Style.BreakBeforeCloseBracketFunction);
1222 IO.mapOptional("BreakBeforeCloseBracketIf",
1223 Style.BreakBeforeCloseBracketIf);
1224 IO.mapOptional("BreakBeforeCloseBracketLoop",
1225 Style.BreakBeforeCloseBracketLoop);
1226 IO.mapOptional("BreakBeforeCloseBracketSwitch",
1227 Style.BreakBeforeCloseBracketSwitch);
1228 IO.mapOptional("BreakBeforeConceptDeclarations",
1229 Style.BreakBeforeConceptDeclarations);
1230 IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
1231 IO.mapOptional("BreakBeforeInlineASMColon",
1232 Style.BreakBeforeInlineASMColon);
1233 IO.mapOptional("BreakBeforeTemplateCloser",
1234 Style.BreakBeforeTemplateCloser);
1235 IO.mapOptional("BreakBeforeTernaryOperators",
1236 Style.BreakBeforeTernaryOperators);
1237 IO.mapOptional("BreakBinaryOperations", Style.BreakBinaryOperations);
1238 IO.mapOptional("BreakConstructorInitializers",
1239 Style.BreakConstructorInitializers);
1240 IO.mapOptional("BreakFunctionDefinitionParameters",
1241 Style.BreakFunctionDefinitionParameters);
1242 IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList);
1243 IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
1244 IO.mapOptional("BreakTemplateDeclarations",
1245 Style.BreakTemplateDeclarations);
1246 IO.mapOptional("ColumnLimit", Style.ColumnLimit);
1247 IO.mapOptional("CommentPragmas", Style.CommentPragmas);
1248 IO.mapOptional("CompactNamespaces", Style.CompactNamespaces);
1249 IO.mapOptional("ConstructorInitializerIndentWidth",
1250 Style.ConstructorInitializerIndentWidth);
1251 IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
1252 IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
1253 IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
1254 IO.mapOptional("DisableFormat", Style.DisableFormat);
1255 IO.mapOptional("EmptyLineAfterAccessModifier",
1256 Style.EmptyLineAfterAccessModifier);
1257 IO.mapOptional("EmptyLineBeforeAccessModifier",
1258 Style.EmptyLineBeforeAccessModifier);
1259 IO.mapOptional("EnumTrailingComma", Style.EnumTrailingComma);
1260 IO.mapOptional("ExperimentalAutoDetectBinPacking",
1261 Style.ExperimentalAutoDetectBinPacking);
1262 IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
1263 IO.mapOptional("ForEachMacros", Style.ForEachMacros);
1264 IO.mapOptional("IfMacros", Style.IfMacros);
1265 IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
1266 IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
1267 IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
1268 IO.mapOptional("IncludeIsMainSourceRegex",
1269 Style.IncludeStyle.IncludeIsMainSourceRegex);
1270 IO.mapOptional("IndentAccessModifiers", Style.IndentAccessModifiers);
1271 IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks);
1272 IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
1273 IO.mapOptional("IndentExportBlock", Style.IndentExportBlock);
1274 IO.mapOptional("IndentExternBlock", Style.IndentExternBlock);
1275 IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels);
1276 IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
1277 IO.mapOptional("IndentRequiresClause", Style.IndentRequiresClause);
1278 IO.mapOptional("IndentWidth", Style.IndentWidth);
1279 IO.mapOptional("IndentWrappedFunctionNames",
1280 Style.IndentWrappedFunctionNames);
1281 IO.mapOptional("InsertBraces", Style.InsertBraces);
1282 IO.mapOptional("InsertNewlineAtEOF", Style.InsertNewlineAtEOF);
1283 IO.mapOptional("InsertTrailingCommas", Style.InsertTrailingCommas);
1284 IO.mapOptional("IntegerLiteralSeparator", Style.IntegerLiteralSeparator);
1285 IO.mapOptional("JavaImportGroups", Style.JavaImportGroups);
1286 IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);
1287 IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
1288 IO.mapOptional("KeepEmptyLines", Style.KeepEmptyLines);
1289 IO.mapOptional("KeepFormFeed", Style.KeepFormFeed);
1290 IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation);
1291 IO.mapOptional("LineEnding", Style.LineEnding);
1292 IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
1293 IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);
1294 IO.mapOptional("Macros", Style.Macros);
1295 IO.mapOptional("MacrosSkippedByRemoveParentheses",
1296 Style.MacrosSkippedByRemoveParentheses);
1297 IO.mapOptional("MainIncludeChar", Style.IncludeStyle.MainIncludeChar);
1298 IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
1299 IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
1300 IO.mapOptional("NamespaceMacros", Style.NamespaceMacros);
1301 IO.mapOptional("NumericLiteralCase", Style.NumericLiteralCase);
1302 IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList);
1303 IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);
1304 IO.mapOptional("ObjCBreakBeforeNestedBlockParam",
1305 Style.ObjCBreakBeforeNestedBlockParam);
1306 IO.mapOptional("ObjCPropertyAttributeOrder",
1307 Style.ObjCPropertyAttributeOrder);
1308 IO.mapOptional("ObjCSpaceAfterMethodDeclarationPrefix",
1309 Style.ObjCSpaceAfterMethodDeclarationPrefix);
1310 IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
1311 IO.mapOptional("ObjCSpaceBeforeProtocolList",
1312 Style.ObjCSpaceBeforeProtocolList);
1313 IO.mapOptional("OneLineFormatOffRegex", Style.OneLineFormatOffRegex);
1314 IO.mapOptional("PackConstructorInitializers",
1315 Style.PackConstructorInitializers);
1316 IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment);
1317 IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",
1318 Style.PenaltyBreakBeforeFirstCallParameter);
1319 IO.mapOptional("PenaltyBreakBeforeMemberAccess",
1320 Style.PenaltyBreakBeforeMemberAccess);
1321 IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
1322 IO.mapOptional("PenaltyBreakFirstLessLess",
1323 Style.PenaltyBreakFirstLessLess);
1324 IO.mapOptional("PenaltyBreakOpenParenthesis",
1325 Style.PenaltyBreakOpenParenthesis);
1326 IO.mapOptional("PenaltyBreakScopeResolution",
1327 Style.PenaltyBreakScopeResolution);
1328 IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
1329 IO.mapOptional("PenaltyBreakTemplateDeclaration",
1330 Style.PenaltyBreakTemplateDeclaration);
1331 IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
1332 IO.mapOptional("PenaltyIndentedWhitespace",
1333 Style.PenaltyIndentedWhitespace);
1334 IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
1335 Style.PenaltyReturnTypeOnItsOwnLine);
1336 IO.mapOptional("PointerAlignment", Style.PointerAlignment);
1337 IO.mapOptional("PPIndentWidth", Style.PPIndentWidth);
1338 IO.mapOptional("QualifierAlignment", Style.QualifierAlignment);
1339 // Default Order for Left/Right based Qualifier alignment.
1340 if (Style.QualifierAlignment == FormatStyle::QAS_Right)
1341 Style.QualifierOrder = {"type", "const", "volatile"};
1342 else if (Style.QualifierAlignment == FormatStyle::QAS_Left)
1343 Style.QualifierOrder = {"const", "volatile", "type"};
1344 else if (Style.QualifierAlignment == FormatStyle::QAS_Custom)
1345 IO.mapOptional("QualifierOrder", Style.QualifierOrder);
1346 IO.mapOptional("RawStringFormats", Style.RawStringFormats);
1347 IO.mapOptional("ReferenceAlignment", Style.ReferenceAlignment);
1348 IO.mapOptional("ReflowComments", Style.ReflowComments);
1349 IO.mapOptional("RemoveBracesLLVM", Style.RemoveBracesLLVM);
1350 IO.mapOptional("RemoveEmptyLinesInUnwrappedLines",
1351 Style.RemoveEmptyLinesInUnwrappedLines);
1352 IO.mapOptional("RemoveParentheses", Style.RemoveParentheses);
1353 IO.mapOptional("RemoveSemicolon", Style.RemoveSemicolon);
1354 IO.mapOptional("RequiresClausePosition", Style.RequiresClausePosition);
1355 IO.mapOptional("RequiresExpressionIndentation",
1356 Style.RequiresExpressionIndentation);
1357 IO.mapOptional("SeparateDefinitionBlocks", Style.SeparateDefinitionBlocks);
1358 IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines);
1359 IO.mapOptional("SkipMacroDefinitionBody", Style.SkipMacroDefinitionBody);
1360 IO.mapOptional("SortIncludes", Style.SortIncludes);
1361 IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport);
1362 IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);
1363 IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
1364 IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot);
1365 IO.mapOptional("SpaceAfterOperatorKeyword",
1366 Style.SpaceAfterOperatorKeyword);
1367 IO.mapOptional("SpaceAfterTemplateKeyword",
1368 Style.SpaceAfterTemplateKeyword);
1369 IO.mapOptional("SpaceAroundPointerQualifiers",
1370 Style.SpaceAroundPointerQualifiers);
1371 IO.mapOptional("SpaceBeforeAssignmentOperators",
1372 Style.SpaceBeforeAssignmentOperators);
1373 IO.mapOptional("SpaceBeforeCaseColon", Style.SpaceBeforeCaseColon);
1374 IO.mapOptional("SpaceBeforeCpp11BracedList",
1375 Style.SpaceBeforeCpp11BracedList);
1376 IO.mapOptional("SpaceBeforeCtorInitializerColon",
1377 Style.SpaceBeforeCtorInitializerColon);
1378 IO.mapOptional("SpaceBeforeInheritanceColon",
1379 Style.SpaceBeforeInheritanceColon);
1380 IO.mapOptional("SpaceBeforeJsonColon", Style.SpaceBeforeJsonColon);
1381 IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
1382 IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions);
1383 IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
1384 Style.SpaceBeforeRangeBasedForLoopColon);
1385 IO.mapOptional("SpaceBeforeSquareBrackets",
1386 Style.SpaceBeforeSquareBrackets);
1387 IO.mapOptional("SpaceInEmptyBraces", Style.SpaceInEmptyBraces);
1388 IO.mapOptional("SpacesBeforeTrailingComments",
1389 Style.SpacesBeforeTrailingComments);
1390 IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
1391 IO.mapOptional("SpacesInContainerLiterals",
1392 Style.SpacesInContainerLiterals);
1393 IO.mapOptional("SpacesInLineCommentPrefix",
1394 Style.SpacesInLineCommentPrefix);
1395 IO.mapOptional("SpacesInParens", Style.SpacesInParens);
1396 IO.mapOptional("SpacesInParensOptions", Style.SpacesInParensOptions);
1397 IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
1398 IO.mapOptional("Standard", Style.Standard);
1399 IO.mapOptional("StatementAttributeLikeMacros",
1400 Style.StatementAttributeLikeMacros);
1401 IO.mapOptional("StatementMacros", Style.StatementMacros);
1402 IO.mapOptional("TableGenBreakingDAGArgOperators",
1403 Style.TableGenBreakingDAGArgOperators);
1404 IO.mapOptional("TableGenBreakInsideDAGArg",
1405 Style.TableGenBreakInsideDAGArg);
1406 IO.mapOptional("TabWidth", Style.TabWidth);
1407 IO.mapOptional("TemplateNames", Style.TemplateNames);
1408 IO.mapOptional("TypeNames", Style.TypeNames);
1409 IO.mapOptional("TypenameMacros", Style.TypenameMacros);
1410 IO.mapOptional("UseTab", Style.UseTab);
1411 IO.mapOptional("VariableTemplates", Style.VariableTemplates);
1412 IO.mapOptional("VerilogBreakBetweenInstancePorts",
1413 Style.VerilogBreakBetweenInstancePorts);
1414 IO.mapOptional("WhitespaceSensitiveMacros",
1415 Style.WhitespaceSensitiveMacros);
1416 IO.mapOptional("WrapNamespaceBodyWithEmptyLines",
1417 Style.WrapNamespaceBodyWithEmptyLines);
1418
1419 // If AlwaysBreakAfterDefinitionReturnType was specified but
1420 // BreakAfterReturnType was not, initialize the latter from the former for
1421 // backwards compatibility.
1422 if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&
1423 Style.BreakAfterReturnType == FormatStyle::RTBS_None) {
1424 if (Style.AlwaysBreakAfterDefinitionReturnType ==
1425 FormatStyle::DRTBS_All) {
1426 Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
1427 } else if (Style.AlwaysBreakAfterDefinitionReturnType ==
1428 FormatStyle::DRTBS_TopLevel) {
1429 Style.BreakAfterReturnType = FormatStyle::RTBS_TopLevelDefinitions;
1430 }
1431 }
1432
1433 // If BreakBeforeInheritanceComma was specified but BreakInheritance was
1434 // not, initialize the latter from the former for backwards compatibility.
1435 if (BreakBeforeInheritanceComma &&
1436 Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) {
1437 Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
1438 }
1439
1440 // If BreakConstructorInitializersBeforeComma was specified but
1441 // BreakConstructorInitializers was not, initialize the latter from the
1442 // former for backwards compatibility.
1443 if (BreakConstructorInitializersBeforeComma &&
1444 Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon) {
1445 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
1446 }
1447
1448 if (!IsGoogleOrChromium) {
1449 if (Style.PackConstructorInitializers == FormatStyle::PCIS_BinPack &&
1450 OnCurrentLine) {
1451 Style.PackConstructorInitializers = OnNextLine
1452 ? FormatStyle::PCIS_NextLine
1453 : FormatStyle::PCIS_CurrentLine;
1454 }
1455 } else if (Style.PackConstructorInitializers ==
1456 FormatStyle::PCIS_NextLine) {
1457 if (!OnCurrentLine)
1458 Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
1459 else if (!OnNextLine)
1460 Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine;
1461 }
1462
1463 if (Style.LineEnding == FormatStyle::LE_DeriveLF) {
1464 if (!DeriveLineEnding)
1465 Style.LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF;
1466 else if (UseCRLF)
1467 Style.LineEnding = FormatStyle::LE_DeriveCRLF;
1468 }
1469
1470 // If SpaceInEmptyBlock was specified but SpaceInEmptyBraces was not,
1471 // initialize the latter from the former for backward compatibility.
1472 if (SpaceInEmptyBlock &&
1473 Style.SpaceInEmptyBraces == FormatStyle::SIEB_Never) {
1474 Style.SpaceInEmptyBraces = FormatStyle::SIEB_Block;
1475 }
1476
1477 if (Style.SpacesInParens != FormatStyle::SIPO_Custom &&
1478 (SpacesInParentheses || SpaceInEmptyParentheses ||
1479 SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) {
1480 if (SpacesInParentheses) {
1481 // For backward compatibility.
1482 Style.SpacesInParensOptions.ExceptDoubleParentheses = false;
1483 Style.SpacesInParensOptions.InConditionalStatements = true;
1484 Style.SpacesInParensOptions.InCStyleCasts =
1485 SpacesInCStyleCastParentheses;
1486 Style.SpacesInParensOptions.InEmptyParentheses =
1487 SpaceInEmptyParentheses;
1488 Style.SpacesInParensOptions.Other = true;
1489 } else {
1490 Style.SpacesInParensOptions = {};
1491 Style.SpacesInParensOptions.InConditionalStatements =
1492 SpacesInConditionalStatement;
1493 Style.SpacesInParensOptions.InCStyleCasts =
1494 SpacesInCStyleCastParentheses;
1495 Style.SpacesInParensOptions.InEmptyParentheses =
1496 SpaceInEmptyParentheses;
1497 }
1498 Style.SpacesInParens = FormatStyle::SIPO_Custom;
1499 }
1500 }
1501};
1502
1503// Allows to read vector<FormatStyle> while keeping default values.
1504// IO.getContext() should contain a pointer to the FormatStyle structure, that
1505// will be used to get default values for missing keys.
1506// If the first element has no Language specified, it will be treated as the
1507// default one for the following elements.
1508template <> struct DocumentListTraits<std::vector<FormatStyle>> {
1509 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
1510 return Seq.size();
1511 }
1512 static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq,
1513 size_t Index) {
1514 if (Index >= Seq.size()) {
1515 assert(Index == Seq.size());
1516 FormatStyle Template;
1517 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
1518 Template = Seq[0];
1519 } else {
1520 Template = *((const FormatStyle *)IO.getContext());
1521 Template.Language = FormatStyle::LK_None;
1522 }
1523 Seq.resize(Index + 1, Template);
1524 }
1525 return Seq[Index];
1526 }
1527};
1528
1529template <> struct ScalarEnumerationTraits<FormatStyle::IndentGotoLabelStyle> {
1530 static void enumeration(IO &IO, FormatStyle::IndentGotoLabelStyle &Value) {
1531 IO.enumCase(Value, "NoIndent", FormatStyle::IGLS_NoIndent);
1532 IO.enumCase(Value, "OuterIndent", FormatStyle::IGLS_OuterIndent);
1533 IO.enumCase(Value, "InnerIndent", FormatStyle::IGLS_InnerIndent);
1534 IO.enumCase(Value, "HalfIndent", FormatStyle::IGLS_HalfIndent);
1535
1536 // For backward compatibility.
1537 IO.enumCase(Value, "false", FormatStyle::IGLS_NoIndent);
1538 IO.enumCase(Value, "true", FormatStyle::IGLS_OuterIndent);
1539 }
1540};
1541
1542} // namespace yaml
1543} // namespace llvm
1544
1545namespace clang {
1546namespace format {
1547
1548const std::error_category &getParseCategory() {
1549 static const ParseErrorCategory C{};
1550 return C;
1551}
1552std::error_code make_error_code(ParseError e) {
1553 return std::error_code(static_cast<int>(e), getParseCategory());
1554}
1555
1556inline llvm::Error make_string_error(const Twine &Message) {
1557 return llvm::make_error<llvm::StringError>(Message,
1558 llvm::inconvertibleErrorCode());
1559}
1560
1561const char *ParseErrorCategory::name() const noexcept {
1562 return "clang-format.parse_error";
1563}
1564
1565std::string ParseErrorCategory::message(int EV) const {
1566 switch (static_cast<ParseError>(EV)) {
1568 return "Success";
1569 case ParseError::Error:
1570 return "Invalid argument";
1572 return "Unsuitable";
1574 return "trailing comma insertion cannot be used with bin packing";
1576 return "Invalid qualifier specified in QualifierOrder";
1578 return "Duplicate qualifier specified in QualifierOrder";
1580 return "Missing type in QualifierOrder";
1582 return "Missing QualifierOrder";
1583 }
1584 llvm_unreachable("unexpected parse error");
1585}
1586
1587static void expandPresetsBraceWrapping(FormatStyle &Expanded) {
1588 if (Expanded.BreakBeforeBraces == FormatStyle::BS_Custom)
1589 return;
1590 Expanded.BraceWrapping = {/*AfterCaseLabel=*/false,
1591 /*AfterClass=*/false,
1592 /*AfterControlStatement=*/FormatStyle::BWACS_Never,
1593 /*AfterEnum=*/false,
1594 /*AfterFunction=*/false,
1595 /*AfterNamespace=*/false,
1596 /*AfterObjCDeclaration=*/false,
1597 /*AfterStruct=*/false,
1598 /*AfterUnion=*/false,
1599 /*AfterExternBlock=*/false,
1600 /*BeforeCatch=*/false,
1601 /*BeforeElse=*/false,
1602 /*BeforeLambdaBody=*/false,
1603 /*BeforeWhile=*/false,
1604 /*IndentBraces=*/false,
1605 /*SplitEmptyFunction=*/true,
1606 /*SplitEmptyRecord=*/true,
1607 /*SplitEmptyNamespace=*/true};
1608 switch (Expanded.BreakBeforeBraces) {
1609 case FormatStyle::BS_Linux:
1610 Expanded.BraceWrapping.AfterClass = true;
1611 Expanded.BraceWrapping.AfterFunction = true;
1612 Expanded.BraceWrapping.AfterNamespace = true;
1613 break;
1614 case FormatStyle::BS_Mozilla:
1615 Expanded.BraceWrapping.AfterClass = true;
1616 Expanded.BraceWrapping.AfterEnum = true;
1617 Expanded.BraceWrapping.AfterFunction = true;
1618 Expanded.BraceWrapping.AfterStruct = true;
1619 Expanded.BraceWrapping.AfterUnion = true;
1620 Expanded.BraceWrapping.AfterExternBlock = true;
1621 Expanded.BraceWrapping.SplitEmptyFunction = true;
1622 Expanded.BraceWrapping.SplitEmptyRecord = false;
1623 break;
1624 case FormatStyle::BS_Stroustrup:
1625 Expanded.BraceWrapping.AfterFunction = true;
1626 Expanded.BraceWrapping.BeforeCatch = true;
1627 Expanded.BraceWrapping.BeforeElse = true;
1628 break;
1629 case FormatStyle::BS_Allman:
1630 Expanded.BraceWrapping.AfterCaseLabel = true;
1631 Expanded.BraceWrapping.AfterClass = true;
1632 Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
1633 Expanded.BraceWrapping.AfterEnum = true;
1634 Expanded.BraceWrapping.AfterFunction = true;
1635 Expanded.BraceWrapping.AfterNamespace = true;
1636 Expanded.BraceWrapping.AfterObjCDeclaration = true;
1637 Expanded.BraceWrapping.AfterStruct = true;
1638 Expanded.BraceWrapping.AfterUnion = true;
1639 Expanded.BraceWrapping.AfterExternBlock = true;
1640 Expanded.BraceWrapping.BeforeCatch = true;
1641 Expanded.BraceWrapping.BeforeElse = true;
1642 Expanded.BraceWrapping.BeforeLambdaBody = true;
1643 break;
1644 case FormatStyle::BS_Whitesmiths:
1645 Expanded.BraceWrapping.AfterCaseLabel = true;
1646 Expanded.BraceWrapping.AfterClass = true;
1647 Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
1648 Expanded.BraceWrapping.AfterEnum = true;
1649 Expanded.BraceWrapping.AfterFunction = true;
1650 Expanded.BraceWrapping.AfterNamespace = true;
1651 Expanded.BraceWrapping.AfterObjCDeclaration = true;
1652 Expanded.BraceWrapping.AfterStruct = true;
1653 Expanded.BraceWrapping.AfterExternBlock = true;
1654 Expanded.BraceWrapping.BeforeCatch = true;
1655 Expanded.BraceWrapping.BeforeElse = true;
1656 Expanded.BraceWrapping.BeforeLambdaBody = true;
1657 break;
1658 case FormatStyle::BS_GNU:
1659 Expanded.BraceWrapping = {
1660 /*AfterCaseLabel=*/true,
1661 /*AfterClass=*/true,
1662 /*AfterControlStatement=*/FormatStyle::BWACS_Always,
1663 /*AfterEnum=*/true,
1664 /*AfterFunction=*/true,
1665 /*AfterNamespace=*/true,
1666 /*AfterObjCDeclaration=*/true,
1667 /*AfterStruct=*/true,
1668 /*AfterUnion=*/true,
1669 /*AfterExternBlock=*/true,
1670 /*BeforeCatch=*/true,
1671 /*BeforeElse=*/true,
1672 /*BeforeLambdaBody=*/true,
1673 /*BeforeWhile=*/true,
1674 /*IndentBraces=*/true,
1675 /*SplitEmptyFunction=*/true,
1676 /*SplitEmptyRecord=*/true,
1677 /*SplitEmptyNamespace=*/true};
1678 break;
1679 case FormatStyle::BS_WebKit:
1680 Expanded.BraceWrapping.AfterFunction = true;
1681 break;
1682 default:
1683 break;
1684 }
1685}
1686
1687static void expandPresetsSpaceBeforeParens(FormatStyle &Expanded) {
1688 if (Expanded.SpaceBeforeParens == FormatStyle::SBPO_Custom)
1689 return;
1690 // Reset all flags
1691 Expanded.SpaceBeforeParensOptions = {};
1692 Expanded.SpaceBeforeParensOptions.AfterPlacementOperator = true;
1693
1694 switch (Expanded.SpaceBeforeParens) {
1695 case FormatStyle::SBPO_ControlStatements:
1696 Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;
1697 Expanded.SpaceBeforeParensOptions.AfterForeachMacros = true;
1698 Expanded.SpaceBeforeParensOptions.AfterIfMacros = true;
1699 break;
1700 case FormatStyle::SBPO_ControlStatementsExceptControlMacros:
1701 Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;
1702 break;
1703 case FormatStyle::SBPO_NonEmptyParentheses:
1704 Expanded.SpaceBeforeParensOptions.BeforeNonEmptyParentheses = true;
1705 break;
1706 default:
1707 break;
1708 }
1709}
1710
1711static void expandPresetsSpacesInParens(FormatStyle &Expanded) {
1712 if (Expanded.SpacesInParens == FormatStyle::SIPO_Custom)
1713 return;
1714 assert(Expanded.SpacesInParens == FormatStyle::SIPO_Never);
1715 // Reset all flags
1716 Expanded.SpacesInParensOptions = {};
1717}
1718
1719FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
1720 FormatStyle LLVMStyle;
1721 LLVMStyle.AccessModifierOffset = -2;
1722 LLVMStyle.AlignAfterOpenBracket = true;
1723 LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;
1724 LLVMStyle.AlignConsecutiveAssignments = {};
1725 LLVMStyle.AlignConsecutiveAssignments.PadOperators = true;
1726 LLVMStyle.AlignConsecutiveBitFields = {};
1727 LLVMStyle.AlignConsecutiveDeclarations = {};
1728 LLVMStyle.AlignConsecutiveDeclarations.AlignFunctionDeclarations = true;
1729 LLVMStyle.AlignConsecutiveMacros = {};
1730 LLVMStyle.AlignConsecutiveShortCaseStatements = {};
1731 LLVMStyle.AlignConsecutiveTableGenBreakingDAGArgColons = {};
1732 LLVMStyle.AlignConsecutiveTableGenCondOperatorColons = {};
1733 LLVMStyle.AlignConsecutiveTableGenDefinitionColons = {};
1734 LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
1735 LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
1736 LLVMStyle.AlignTrailingComments = {};
1737 LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always;
1738 LLVMStyle.AlignTrailingComments.OverEmptyLines = 0;
1739 LLVMStyle.AlignTrailingComments.AlignPPAndNotPP = true;
1740 LLVMStyle.AllowAllArgumentsOnNextLine = true;
1741 LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
1742 LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;
1743 LLVMStyle.AllowBreakBeforeQtProperty = false;
1744 LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
1745 LLVMStyle.AllowShortCaseExpressionOnASingleLine = true;
1746 LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
1747 LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true;
1748 LLVMStyle.AllowShortEnumsOnASingleLine = true;
1749 LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
1750 LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
1751 LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
1752 LLVMStyle.AllowShortLoopsOnASingleLine = false;
1753 LLVMStyle.AllowShortNamespacesOnASingleLine = false;
1754 LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
1755 LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
1756 LLVMStyle.AttributeMacros.push_back("__capability");
1757 LLVMStyle.BinPackArguments = true;
1758 LLVMStyle.BinPackLongBracedList = true;
1759 LLVMStyle.BinPackParameters = FormatStyle::BPPS_BinPack;
1760 LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;
1761 LLVMStyle.BracedInitializerIndentWidth = -1;
1762 LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false,
1763 /*AfterClass=*/false,
1764 /*AfterControlStatement=*/FormatStyle::BWACS_Never,
1765 /*AfterEnum=*/false,
1766 /*AfterFunction=*/false,
1767 /*AfterNamespace=*/false,
1768 /*AfterObjCDeclaration=*/false,
1769 /*AfterStruct=*/false,
1770 /*AfterUnion=*/false,
1771 /*AfterExternBlock=*/false,
1772 /*BeforeCatch=*/false,
1773 /*BeforeElse=*/false,
1774 /*BeforeLambdaBody=*/false,
1775 /*BeforeWhile=*/false,
1776 /*IndentBraces=*/false,
1777 /*SplitEmptyFunction=*/true,
1778 /*SplitEmptyRecord=*/true,
1779 /*SplitEmptyNamespace=*/true};
1780 LLVMStyle.BreakAdjacentStringLiterals = true;
1781 LLVMStyle.BreakAfterAttributes = FormatStyle::ABS_Leave;
1782 LLVMStyle.BreakAfterJavaFieldAnnotations = false;
1783 LLVMStyle.BreakAfterOpenBracketBracedList = false;
1784 LLVMStyle.BreakAfterOpenBracketFunction = false;
1785 LLVMStyle.BreakAfterOpenBracketIf = false;
1786 LLVMStyle.BreakAfterOpenBracketLoop = false;
1787 LLVMStyle.BreakAfterOpenBracketSwitch = false;
1788 LLVMStyle.BreakAfterReturnType = FormatStyle::RTBS_None;
1789 LLVMStyle.BreakArrays = true;
1790 LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
1791 LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
1792 LLVMStyle.BreakBeforeCloseBracketBracedList = false;
1793 LLVMStyle.BreakBeforeCloseBracketFunction = false;
1794 LLVMStyle.BreakBeforeCloseBracketIf = false;
1795 LLVMStyle.BreakBeforeCloseBracketLoop = false;
1796 LLVMStyle.BreakBeforeCloseBracketSwitch = false;
1797 LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always;
1798 LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline;
1799 LLVMStyle.BreakBeforeTemplateCloser = false;
1800 LLVMStyle.BreakBeforeTernaryOperators = true;
1801 LLVMStyle.BreakBinaryOperations = {FormatStyle::BBO_Never, {}};
1802 LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
1803 LLVMStyle.BreakFunctionDefinitionParameters = false;
1804 LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
1805 LLVMStyle.BreakStringLiterals = true;
1806 LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
1807 LLVMStyle.ColumnLimit = 80;
1808 LLVMStyle.CommentPragmas = "^ IWYU pragma:";
1809 LLVMStyle.CompactNamespaces = false;
1810 LLVMStyle.ConstructorInitializerIndentWidth = 4;
1811 LLVMStyle.ContinuationIndentWidth = 4;
1812 LLVMStyle.Cpp11BracedListStyle = FormatStyle::BLS_AlignFirstComment;
1813 LLVMStyle.DerivePointerAlignment = false;
1814 LLVMStyle.DisableFormat = false;
1815 LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never;
1816 LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock;
1817 LLVMStyle.EnumTrailingComma = FormatStyle::ETC_Leave;
1818 LLVMStyle.ExperimentalAutoDetectBinPacking = false;
1819 LLVMStyle.FixNamespaceComments = true;
1820 LLVMStyle.ForEachMacros.push_back("foreach");
1821 LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
1822 LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
1823 LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE");
1824 LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
1825 LLVMStyle.IncludeStyle.IncludeCategories = {
1826 {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false},
1827 {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},
1828 {".*", 1, 0, false}};
1829 LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
1830 LLVMStyle.IncludeStyle.MainIncludeChar = tooling::IncludeStyle::MICD_Quote;
1831 LLVMStyle.IndentAccessModifiers = false;
1832 LLVMStyle.IndentCaseBlocks = false;
1833 LLVMStyle.IndentCaseLabels = false;
1834 LLVMStyle.IndentExportBlock = true;
1835 LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
1836 LLVMStyle.IndentGotoLabels = FormatStyle::IGLS_OuterIndent;
1837 LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
1838 LLVMStyle.IndentRequiresClause = true;
1839 LLVMStyle.IndentWidth = 2;
1840 LLVMStyle.IndentWrappedFunctionNames = false;
1841 LLVMStyle.InsertBraces = false;
1842 LLVMStyle.InsertNewlineAtEOF = false;
1843 LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
1844 LLVMStyle.IntegerLiteralSeparator = {};
1845 LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
1846 LLVMStyle.JavaScriptWrapImports = true;
1847 LLVMStyle.KeepEmptyLines = {
1848 /*AtEndOfFile=*/false,
1849 /*AtStartOfBlock=*/true,
1850 /*AtStartOfFile=*/true,
1851 };
1852 LLVMStyle.KeepFormFeed = false;
1853 LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature;
1854 LLVMStyle.Language = Language;
1855 LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF;
1856 LLVMStyle.MaxEmptyLinesToKeep = 1;
1857 LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
1858 LLVMStyle.NumericLiteralCase = {/*ExponentLetter=*/FormatStyle::NLCS_Leave,
1859 /*HexDigit=*/FormatStyle::NLCS_Leave,
1860 /*Prefix=*/FormatStyle::NLCS_Leave,
1861 /*Suffix=*/FormatStyle::NLCS_Leave};
1862 LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto;
1863 LLVMStyle.ObjCBlockIndentWidth = 2;
1864 LLVMStyle.ObjCBreakBeforeNestedBlockParam = true;
1865 LLVMStyle.ObjCSpaceAfterMethodDeclarationPrefix = true;
1866 LLVMStyle.ObjCSpaceAfterProperty = false;
1867 LLVMStyle.ObjCSpaceBeforeProtocolList = true;
1868 LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
1869 LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
1870 LLVMStyle.PPIndentWidth = -1;
1871 LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
1872 LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer;
1873 LLVMStyle.ReflowComments = FormatStyle::RCS_Always;
1874 LLVMStyle.RemoveBracesLLVM = false;
1875 LLVMStyle.RemoveEmptyLinesInUnwrappedLines = false;
1876 LLVMStyle.RemoveParentheses = FormatStyle::RPS_Leave;
1877 LLVMStyle.RemoveSemicolon = false;
1878 LLVMStyle.RequiresClausePosition = FormatStyle::RCPS_OwnLine;
1879 LLVMStyle.RequiresExpressionIndentation = FormatStyle::REI_OuterScope;
1880 LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
1881 LLVMStyle.ShortNamespaceLines = 1;
1882 LLVMStyle.SkipMacroDefinitionBody = false;
1883 LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false,
1884 /*IgnoreExtension=*/false};
1885 LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
1886 LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;
1887 LLVMStyle.SpaceAfterCStyleCast = false;
1888 LLVMStyle.SpaceAfterLogicalNot = false;
1889 LLVMStyle.SpaceAfterOperatorKeyword = false;
1890 LLVMStyle.SpaceAfterTemplateKeyword = true;
1891 LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
1892 LLVMStyle.SpaceBeforeAssignmentOperators = true;
1893 LLVMStyle.SpaceBeforeCaseColon = false;
1894 LLVMStyle.SpaceBeforeCpp11BracedList = false;
1895 LLVMStyle.SpaceBeforeCtorInitializerColon = true;
1896 LLVMStyle.SpaceBeforeInheritanceColon = true;
1897 LLVMStyle.SpaceBeforeJsonColon = false;
1898 LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
1899 LLVMStyle.SpaceBeforeParensOptions = {};
1900 LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true;
1901 LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true;
1902 LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true;
1903 LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
1904 LLVMStyle.SpaceBeforeSquareBrackets = false;
1905 LLVMStyle.SpaceInEmptyBraces = FormatStyle::SIEB_Never;
1906 LLVMStyle.SpacesBeforeTrailingComments = 1;
1907 LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never;
1908 LLVMStyle.SpacesInContainerLiterals = true;
1909 LLVMStyle.SpacesInLineCommentPrefix = {
1910 /*Minimum=*/1, /*Maximum=*/std::numeric_limits<unsigned>::max()};
1911 LLVMStyle.SpacesInParens = FormatStyle::SIPO_Never;
1912 LLVMStyle.SpacesInSquareBrackets = false;
1913 LLVMStyle.Standard = FormatStyle::LS_Latest;
1914 LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");
1915 LLVMStyle.StatementMacros.push_back("Q_UNUSED");
1916 LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");
1917 LLVMStyle.TableGenBreakingDAGArgOperators = {};
1918 LLVMStyle.TableGenBreakInsideDAGArg = FormatStyle::DAS_DontBreak;
1919 LLVMStyle.TabWidth = 8;
1920 LLVMStyle.UseTab = FormatStyle::UT_Never;
1921 LLVMStyle.VerilogBreakBetweenInstancePorts = true;
1922 LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE");
1923 LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME");
1924 LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME");
1925 LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE");
1926 LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE");
1927 LLVMStyle.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Leave;
1928
1929 LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
1930 LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
1931 LLVMStyle.PenaltyBreakBeforeMemberAccess = 150;
1932 LLVMStyle.PenaltyBreakComment = 300;
1933 LLVMStyle.PenaltyBreakFirstLessLess = 120;
1934 LLVMStyle.PenaltyBreakOpenParenthesis = 0;
1935 LLVMStyle.PenaltyBreakScopeResolution = 500;
1936 LLVMStyle.PenaltyBreakString = 1000;
1937 LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;
1938 LLVMStyle.PenaltyExcessCharacter = 1'000'000;
1939 LLVMStyle.PenaltyIndentedWhitespace = 0;
1940 LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
1941
1942 // Defaults that differ when not C++.
1943 switch (Language) {
1944 case FormatStyle::LK_TableGen:
1945 LLVMStyle.SpacesInContainerLiterals = false;
1946 break;
1947 case FormatStyle::LK_Json:
1948 LLVMStyle.ColumnLimit = 0;
1949 break;
1950 case FormatStyle::LK_Verilog:
1951 LLVMStyle.IndentCaseLabels = true;
1952 LLVMStyle.SpacesInContainerLiterals = false;
1953 break;
1954 default:
1955 break;
1956 }
1957
1958 return LLVMStyle;
1959}
1960
1961FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
1962 if (Language == FormatStyle::LK_TextProto) {
1963 FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto);
1964 GoogleStyle.Language = FormatStyle::LK_TextProto;
1965
1966 return GoogleStyle;
1967 }
1968
1969 FormatStyle GoogleStyle = getLLVMStyle(Language);
1970
1971 GoogleStyle.AccessModifierOffset = -1;
1972 GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left;
1973 GoogleStyle.AllowShortIfStatementsOnASingleLine =
1974 FormatStyle::SIS_WithoutElse;
1975 GoogleStyle.AllowShortLoopsOnASingleLine = true;
1976 GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
1977 // Abseil aliases to clang's `_Nonnull`, `_Nullable` and `_Null_unspecified`.
1978 GoogleStyle.AttributeMacros.push_back("absl_nonnull");
1979 GoogleStyle.AttributeMacros.push_back("absl_nullable");
1980 GoogleStyle.AttributeMacros.push_back("absl_nullability_unknown");
1981 GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
1982 GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
1983 GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false},
1984 {"^<.*\\.h>", 1, 0, false},
1985 {"^<.*", 2, 0, false},
1986 {".*", 3, 0, false}};
1987 GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
1988 GoogleStyle.IndentCaseLabels = true;
1989 GoogleStyle.KeepEmptyLines.AtStartOfBlock = false;
1990
1991 GoogleStyle.Macros.push_back("ASSIGN_OR_RETURN(a, b)=a = (b)");
1992 GoogleStyle.Macros.push_back(
1993 "ASSIGN_OR_RETURN(a, b, c)=a = (b); if (x) return c");
1994
1995 GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never;
1996 GoogleStyle.ObjCSpaceAfterProperty = false;
1997 GoogleStyle.ObjCSpaceBeforeProtocolList = true;
1998 GoogleStyle.PackConstructorInitializers = FormatStyle::PCIS_NextLine;
1999 GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;
2000 GoogleStyle.RawStringFormats = {
2001 {
2002 FormatStyle::LK_Cpp,
2003 /*Delimiters=*/
2004 {
2005 "cc",
2006 "CC",
2007 "cpp",
2008 "Cpp",
2009 "CPP",
2010 "c++",
2011 "C++",
2012 },
2013 /*EnclosingFunctionNames=*/
2014 {},
2015 /*CanonicalDelimiter=*/"",
2016 /*BasedOnStyle=*/"google",
2017 },
2018 {
2019 FormatStyle::LK_TextProto,
2020 /*Delimiters=*/
2021 {
2022 "pb",
2023 "PB",
2024 "proto",
2025 "PROTO",
2026 },
2027 /*EnclosingFunctionNames=*/
2028 {
2029 "EqualsProto",
2030 "EquivToProto",
2031 "PARSE_PARTIAL_TEXT_PROTO",
2032 "PARSE_TEST_PROTO",
2033 "PARSE_TEXT_PROTO",
2034 "ParseTextOrDie",
2035 "ParseTextProtoOrDie",
2036 "ParseTestProto",
2037 "ParsePartialTestProto",
2038 },
2039 /*CanonicalDelimiter=*/"pb",
2040 /*BasedOnStyle=*/"google",
2041 },
2042 };
2043
2044 GoogleStyle.SpacesBeforeTrailingComments = 2;
2045 GoogleStyle.Standard = FormatStyle::LS_Auto;
2046
2047 GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;
2048 GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
2049
2050 if (Language == FormatStyle::LK_Java) {
2051 GoogleStyle.AlignAfterOpenBracket = false;
2052 GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
2053 GoogleStyle.AlignTrailingComments = {};
2054 GoogleStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;
2055 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
2056 GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
2057 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
2058 GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
2059 GoogleStyle.ColumnLimit = 100;
2060 GoogleStyle.SpaceAfterCStyleCast = true;
2061 GoogleStyle.SpacesBeforeTrailingComments = 1;
2062 } else if (Language == FormatStyle::LK_JavaScript) {
2063 GoogleStyle.BreakAfterOpenBracketBracedList = true;
2064 GoogleStyle.BreakAfterOpenBracketFunction = true;
2065 GoogleStyle.BreakAfterOpenBracketIf = true;
2066 GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
2067 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
2068 // TODO: still under discussion whether to switch to SLS_All.
2069 GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
2070 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
2071 GoogleStyle.BreakBeforeTernaryOperators = false;
2072 // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is
2073 // commonly followed by overlong URLs.
2074 GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)";
2075 // TODO: enable once decided, in particular re disabling bin packing.
2076 // https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma
2077 // GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
2078 GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single;
2079 GoogleStyle.JavaScriptWrapImports = false;
2080 GoogleStyle.MaxEmptyLinesToKeep = 3;
2081 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
2082 GoogleStyle.SpacesInContainerLiterals = false;
2083 } else if (Language == FormatStyle::LK_Proto) {
2084 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
2085 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
2086 // This affects protocol buffer options specifications and text protos.
2087 // Text protos are currently mostly formatted inside C++ raw string literals
2088 // and often the current breaking behavior of string literals is not
2089 // beneficial there. Investigate turning this on once proper string reflow
2090 // has been implemented.
2091 GoogleStyle.BreakStringLiterals = false;
2092 GoogleStyle.Cpp11BracedListStyle = FormatStyle::BLS_Block;
2093 GoogleStyle.SpacesInContainerLiterals = false;
2094 } else if (Language == FormatStyle::LK_ObjC) {
2095 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
2096 GoogleStyle.ColumnLimit = 100;
2097 GoogleStyle.DerivePointerAlignment = true;
2098 // "Regroup" doesn't work well for ObjC yet (main header heuristic,
2099 // relationship between ObjC standard library headers and other heades,
2100 // #imports, etc.)
2101 GoogleStyle.IncludeStyle.IncludeBlocks =
2103 } else if (Language == FormatStyle::LK_CSharp) {
2104 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
2105 GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
2106 GoogleStyle.BreakStringLiterals = false;
2107 GoogleStyle.ColumnLimit = 100;
2108 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
2109 }
2110
2111 return GoogleStyle;
2112}
2113
2114FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
2115 FormatStyle ChromiumStyle = getGoogleStyle(Language);
2116
2117 // Disable include reordering across blocks in Chromium code.
2118 // - clang-format tries to detect that foo.h is the "main" header for
2119 // foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium
2120 // uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc,
2121 // _private.cc, _impl.cc etc) in different permutations
2122 // (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a
2123 // better default for Chromium code.
2124 // - The default for .cc and .mm files is different (r357695) for Google style
2125 // for the same reason. The plan is to unify this again once the main
2126 // header detection works for Google's ObjC code, but this hasn't happened
2127 // yet. Since Chromium has some ObjC code, switching Chromium is blocked
2128 // on that.
2129 // - Finally, "If include reordering is harmful, put things in different
2130 // blocks to prevent it" has been a recommendation for a long time that
2131 // people are used to. We'll need a dev education push to change this to
2132 // "If include reordering is harmful, put things in a different block and
2133 // _prepend that with a comment_ to prevent it" before changing behavior.
2134 ChromiumStyle.IncludeStyle.IncludeBlocks =
2136
2137 if (Language == FormatStyle::LK_Java) {
2138 ChromiumStyle.AllowShortIfStatementsOnASingleLine =
2139 FormatStyle::SIS_WithoutElse;
2140 ChromiumStyle.BreakAfterJavaFieldAnnotations = true;
2141 ChromiumStyle.ContinuationIndentWidth = 8;
2142 ChromiumStyle.IndentWidth = 4;
2143 // See styleguide for import groups:
2144 // https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/java/java.md#Import-Order
2145 ChromiumStyle.JavaImportGroups = {
2146 "android",
2147 "androidx",
2148 "com",
2149 "dalvik",
2150 "junit",
2151 "org",
2152 "com.google.android.apps.chrome",
2153 "org.chromium",
2154 "java",
2155 "javax",
2156 };
2157 } else if (Language == FormatStyle::LK_JavaScript) {
2158 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
2159 ChromiumStyle.AllowShortLoopsOnASingleLine = false;
2160 } else {
2161 ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
2162 ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
2163 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
2164 ChromiumStyle.AllowShortLoopsOnASingleLine = false;
2165 ChromiumStyle.BinPackParameters = FormatStyle::BPPS_OnePerLine;
2166 ChromiumStyle.DerivePointerAlignment = false;
2167 if (Language == FormatStyle::LK_ObjC)
2168 ChromiumStyle.ColumnLimit = 80;
2169 }
2170 return ChromiumStyle;
2171}
2172
2173FormatStyle getMozillaStyle() {
2174 FormatStyle MozillaStyle = getLLVMStyle();
2175 MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
2176 MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
2177 MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
2178 FormatStyle::DRTBS_TopLevel;
2179 MozillaStyle.BinPackArguments = false;
2180 MozillaStyle.BinPackParameters = FormatStyle::BPPS_OnePerLine;
2181 MozillaStyle.BreakAfterReturnType = FormatStyle::RTBS_TopLevel;
2182 MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
2183 MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
2184 MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
2185 MozillaStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
2186 MozillaStyle.ConstructorInitializerIndentWidth = 2;
2187 MozillaStyle.ContinuationIndentWidth = 2;
2188 MozillaStyle.Cpp11BracedListStyle = FormatStyle::BLS_Block;
2189 MozillaStyle.FixNamespaceComments = false;
2190 MozillaStyle.IndentCaseLabels = true;
2191 MozillaStyle.ObjCSpaceAfterProperty = true;
2192 MozillaStyle.ObjCSpaceBeforeProtocolList = false;
2193 MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
2194 MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
2195 MozillaStyle.SpaceAfterTemplateKeyword = false;
2196 return MozillaStyle;
2197}
2198
2199FormatStyle getWebKitStyle() {
2200 FormatStyle Style = getLLVMStyle();
2201 Style.AccessModifierOffset = -4;
2202 Style.AlignAfterOpenBracket = false;
2203 Style.AlignOperands = FormatStyle::OAS_DontAlign;
2204 Style.AlignTrailingComments = {};
2205 Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;
2206 Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;
2207 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
2208 Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
2209 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
2210 Style.ColumnLimit = 0;
2211 Style.Cpp11BracedListStyle = FormatStyle::BLS_Block;
2212 Style.FixNamespaceComments = false;
2213 Style.IndentWidth = 4;
2214 Style.NamespaceIndentation = FormatStyle::NI_Inner;
2215 Style.ObjCBlockIndentWidth = 4;
2216 Style.ObjCSpaceAfterProperty = true;
2217 Style.PointerAlignment = FormatStyle::PAS_Left;
2218 Style.SpaceBeforeCpp11BracedList = true;
2219 Style.SpaceInEmptyBraces = FormatStyle::SIEB_Always;
2220 return Style;
2221}
2222
2223FormatStyle getGNUStyle() {
2224 FormatStyle Style = getLLVMStyle();
2225 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
2226 Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
2227 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
2228 Style.BreakBeforeBraces = FormatStyle::BS_GNU;
2229 Style.BreakBeforeTernaryOperators = true;
2230 Style.ColumnLimit = 79;
2231 Style.Cpp11BracedListStyle = FormatStyle::BLS_Block;
2232 Style.FixNamespaceComments = false;
2233 Style.KeepFormFeed = true;
2234 Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
2235 return Style;
2236}
2237
2238FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) {
2239 FormatStyle Style = getLLVMStyle(Language);
2240 Style.ColumnLimit = 120;
2241 Style.TabWidth = 4;
2242 Style.IndentWidth = 4;
2243 Style.UseTab = FormatStyle::UT_Never;
2244 Style.BreakBeforeBraces = FormatStyle::BS_Custom;
2245 Style.BraceWrapping.AfterClass = true;
2246 Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
2247 Style.BraceWrapping.AfterEnum = true;
2248 Style.BraceWrapping.AfterFunction = true;
2249 Style.BraceWrapping.AfterNamespace = true;
2250 Style.BraceWrapping.AfterObjCDeclaration = true;
2251 Style.BraceWrapping.AfterStruct = true;
2252 Style.BraceWrapping.AfterExternBlock = true;
2253 Style.BraceWrapping.BeforeCatch = true;
2254 Style.BraceWrapping.BeforeElse = true;
2255 Style.BraceWrapping.BeforeWhile = false;
2256 Style.PenaltyReturnTypeOnItsOwnLine = 1000;
2257 Style.AllowShortEnumsOnASingleLine = false;
2258 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
2259 Style.AllowShortCaseLabelsOnASingleLine = false;
2260 Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
2261 Style.AllowShortLoopsOnASingleLine = false;
2262 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
2263 Style.BreakAfterReturnType = FormatStyle::RTBS_None;
2264 return Style;
2265}
2266
2267FormatStyle getClangFormatStyle() {
2268 FormatStyle Style = getLLVMStyle();
2269 Style.InsertBraces = true;
2270 Style.InsertNewlineAtEOF = true;
2271 Style.IntegerLiteralSeparator.Decimal = 3;
2272 Style.IntegerLiteralSeparator.DecimalMinDigitsInsert = 5;
2273 Style.LineEnding = FormatStyle::LE_LF;
2274 Style.RemoveBracesLLVM = true;
2275 Style.RemoveEmptyLinesInUnwrappedLines = true;
2276 Style.RemoveParentheses = FormatStyle::RPS_ReturnStatement;
2277 Style.RemoveSemicolon = true;
2278 return Style;
2279}
2280
2281FormatStyle getNoStyle() {
2282 FormatStyle NoStyle = getLLVMStyle();
2283 NoStyle.DisableFormat = true;
2284 NoStyle.SortIncludes = {};
2285 NoStyle.SortUsingDeclarations = FormatStyle::SUD_Never;
2286 return NoStyle;
2287}
2288
2289bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
2290 FormatStyle *Style) {
2291 constexpr StringRef Prefix("inheritparentconfig=");
2292
2293 if (Name.equals_insensitive("llvm"))
2294 *Style = getLLVMStyle(Language);
2295 else if (Name.equals_insensitive("chromium"))
2296 *Style = getChromiumStyle(Language);
2297 else if (Name.equals_insensitive("mozilla"))
2298 *Style = getMozillaStyle();
2299 else if (Name.equals_insensitive("google"))
2300 *Style = getGoogleStyle(Language);
2301 else if (Name.equals_insensitive("webkit"))
2302 *Style = getWebKitStyle();
2303 else if (Name.equals_insensitive("gnu"))
2304 *Style = getGNUStyle();
2305 else if (Name.equals_insensitive("microsoft"))
2306 *Style = getMicrosoftStyle(Language);
2307 else if (Name.equals_insensitive("clang-format"))
2308 *Style = getClangFormatStyle();
2309 else if (Name.equals_insensitive("none"))
2310 *Style = getNoStyle();
2311 else if (Name.equals_insensitive(Prefix.drop_back()))
2312 Style->InheritConfig = "..";
2313 else if (Name.size() > Prefix.size() && Name.starts_with_insensitive(Prefix))
2314 Style->InheritConfig = Name.substr(Prefix.size());
2315 else
2316 return false;
2317
2318 Style->Language = Language;
2319 return true;
2320}
2321
2323 // If its empty then it means don't do anything.
2324 if (Style->QualifierOrder.empty())
2326
2327 // Ensure the list contains only currently valid qualifiers.
2328 for (const auto &Qualifier : Style->QualifierOrder) {
2329 if (Qualifier == "type")
2330 continue;
2331 auto token =
2333 if (token == tok::identifier)
2335 }
2336
2337 // Ensure the list is unique (no duplicates).
2338 std::set<std::string> UniqueQualifiers(Style->QualifierOrder.begin(),
2339 Style->QualifierOrder.end());
2340 if (Style->QualifierOrder.size() != UniqueQualifiers.size()) {
2341 LLVM_DEBUG(llvm::dbgs()
2342 << "Duplicate Qualifiers " << Style->QualifierOrder.size()
2343 << " vs " << UniqueQualifiers.size() << "\n");
2345 }
2346
2347 // Ensure the list has 'type' in it.
2348 if (!llvm::is_contained(Style->QualifierOrder, "type"))
2350
2351 return ParseError::Success;
2352}
2353
2354std::error_code parseConfiguration(llvm::MemoryBufferRef Config,
2355 FormatStyle *Style, bool AllowUnknownOptions,
2356 llvm::SourceMgr::DiagHandlerTy DiagHandler,
2357 void *DiagHandlerCtxt, bool IsDotHFile) {
2358 assert(Style);
2359 FormatStyle::LanguageKind Language = Style->Language;
2360 assert(Language != FormatStyle::LK_None);
2361 if (Config.getBuffer().trim().empty())
2363 Style->StyleSet.Clear();
2364 std::vector<FormatStyle> Styles;
2365 llvm::yaml::Input Input(Config, /*Ctxt=*/nullptr, DiagHandler,
2366 DiagHandlerCtxt);
2367 // DocumentListTraits<vector<FormatStyle>> uses the context to get default
2368 // values for the fields, keys for which are missing from the configuration.
2369 // Mapping also uses the context to get the language to find the correct
2370 // base style.
2371 Input.setContext(Style);
2372 Input.setAllowUnknownKeys(AllowUnknownOptions);
2373 Input >> Styles;
2374 if (Input.error())
2375 return Input.error();
2376 if (Styles.empty())
2378
2379 const auto StyleCount = Styles.size();
2380
2381 // Start from the second style as (only) the first one may be the default.
2382 for (unsigned I = 1; I < StyleCount; ++I) {
2383 const auto Lang = Styles[I].Language;
2384 if (Lang == FormatStyle::LK_None)
2386 // Ensure that each language is configured at most once.
2387 for (unsigned J = 0; J < I; ++J) {
2388 if (Lang == Styles[J].Language) {
2389 LLVM_DEBUG(llvm::dbgs()
2390 << "Duplicate languages in the config file on positions "
2391 << J << " and " << I << '\n');
2393 }
2394 }
2395 }
2396
2397 int LanguagePos = -1; // Position of the style for Language.
2398 int CppPos = -1; // Position of the style for C++.
2399 int CPos = -1; // Position of the style for C.
2400
2401 // Search Styles for Language and store the positions of C++ and C styles in
2402 // case Language is not found.
2403 for (unsigned I = 0; I < StyleCount; ++I) {
2404 const auto Lang = Styles[I].Language;
2405 if (Lang == Language) {
2406 LanguagePos = I;
2407 break;
2408 }
2409 if (Lang == FormatStyle::LK_Cpp)
2410 CppPos = I;
2411 else if (Lang == FormatStyle::LK_C)
2412 CPos = I;
2413 }
2414
2415 // If Language is not found, use the default style if there is one. Otherwise,
2416 // use the C style for C++ .h files and for backward compatibility, the C++
2417 // style for .c files.
2418 if (LanguagePos < 0) {
2419 if (Styles[0].Language == FormatStyle::LK_None) // Default style.
2420 LanguagePos = 0;
2421 else if (IsDotHFile && Language == FormatStyle::LK_Cpp)
2422 LanguagePos = CPos;
2423 else if (!IsDotHFile && Language == FormatStyle::LK_C)
2424 LanguagePos = CppPos;
2425 if (LanguagePos < 0)
2427 }
2428
2429 for (const auto &S : llvm::reverse(llvm::drop_begin(Styles)))
2430 Style->StyleSet.Add(S);
2431
2432 *Style = Styles[LanguagePos];
2433
2434 if (LanguagePos == 0) {
2435 if (Style->Language == FormatStyle::LK_None) // Default style.
2436 Style->Language = Language;
2437 Style->StyleSet.Add(*Style);
2438 }
2439
2440 if (Style->InsertTrailingCommas != FormatStyle::TCS_None &&
2441 Style->BinPackArguments) {
2442 // See comment on FormatStyle::TSC_Wrapped.
2444 }
2445 if (Style->QualifierAlignment != FormatStyle::QAS_Leave)
2448}
2449
2450std::string configurationAsText(const FormatStyle &Style) {
2451 std::string Text;
2452 llvm::raw_string_ostream Stream(Text);
2453 llvm::yaml::Output Output(Stream);
2454 // We use the same mapping method for input and output, so we need a non-const
2455 // reference here.
2456 FormatStyle NonConstStyle = Style;
2457 expandPresetsBraceWrapping(NonConstStyle);
2458 expandPresetsSpaceBeforeParens(NonConstStyle);
2459 expandPresetsSpacesInParens(NonConstStyle);
2460 Output << NonConstStyle;
2461
2462 return Stream.str();
2463}
2464
2465std::optional<FormatStyle>
2466FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {
2467 if (!Styles)
2468 return std::nullopt;
2469 auto It = Styles->find(Language);
2470 if (It == Styles->end())
2471 return std::nullopt;
2472 FormatStyle Style = It->second;
2473 Style.StyleSet = *this;
2474 return Style;
2475}
2476
2477void FormatStyle::FormatStyleSet::Add(FormatStyle Style) {
2478 assert(Style.Language != LK_None &&
2479 "Cannot add a style for LK_None to a StyleSet");
2480 assert(
2481 !Style.StyleSet.Styles &&
2482 "Cannot add a style associated with an existing StyleSet to a StyleSet");
2483 if (!Styles)
2484 Styles = std::make_shared<MapType>();
2485 (*Styles)[Style.Language] = std::move(Style);
2486}
2487
2488void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); }
2489
2490std::optional<FormatStyle>
2491FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {
2492 return StyleSet.Get(Language);
2493}
2494
2495namespace {
2496
2497void replaceToken(const FormatToken &Token, FormatToken *Next,
2498 const SourceManager &SourceMgr, tooling::Replacements &Result,
2499 StringRef Text = "") {
2500 const auto &Tok = Token.Tok;
2501 SourceLocation Start;
2502 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2503 Start = Tok.getLocation();
2504 Next->WhitespaceRange = Token.WhitespaceRange;
2505 } else {
2506 Start = Token.WhitespaceRange.getBegin();
2507 }
2508 const auto &Range = CharSourceRange::getCharRange(Start, Tok.getEndLoc());
2509 cantFail(Result.add(tooling::Replacement(SourceMgr, Range, Text)));
2510}
2511
2512class ParensRemover : public TokenAnalyzer {
2513public:
2514 ParensRemover(const Environment &Env, const FormatStyle &Style)
2515 : TokenAnalyzer(Env, Style) {}
2516
2517 std::pair<tooling::Replacements, unsigned>
2518 analyze(TokenAnnotator &Annotator,
2519 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2520 FormatTokenLexer &Tokens) override {
2521 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2522 tooling::Replacements Result;
2523 removeParens(AnnotatedLines, Result);
2524 return {Result, 0};
2525 }
2526
2527private:
2528 void removeParens(SmallVectorImpl<AnnotatedLine *> &Lines,
2529 tooling::Replacements &Result) {
2530 const auto &SourceMgr = Env.getSourceManager();
2531 for (auto *Line : Lines) {
2532 if (!Line->Children.empty())
2533 removeParens(Line->Children, Result);
2534 if (!Line->Affected)
2535 continue;
2536 for (const auto *Token = Line->First; Token && !Token->Finalized;
2537 Token = Token->Next) {
2538 if (Token->Optional && Token->isOneOf(tok::l_paren, tok::r_paren))
2539 replaceToken(*Token, Token->Next, SourceMgr, Result, " ");
2540 }
2541 }
2542 }
2543};
2544
2545class BracesInserter : public TokenAnalyzer {
2546public:
2547 BracesInserter(const Environment &Env, const FormatStyle &Style)
2548 : TokenAnalyzer(Env, Style) {}
2549
2550 std::pair<tooling::Replacements, unsigned>
2551 analyze(TokenAnnotator &Annotator,
2552 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2553 FormatTokenLexer &Tokens) override {
2554 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2555 tooling::Replacements Result;
2556 insertBraces(AnnotatedLines, Result);
2557 return {Result, 0};
2558 }
2559
2560private:
2561 void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2562 tooling::Replacements &Result) {
2563 const auto &SourceMgr = Env.getSourceManager();
2564 int OpeningBraceSurplus = 0;
2565 for (AnnotatedLine *Line : Lines) {
2566 if (!Line->Children.empty())
2567 insertBraces(Line->Children, Result);
2568 if (!Line->Affected && OpeningBraceSurplus == 0)
2569 continue;
2570 for (FormatToken *Token = Line->First; Token && !Token->Finalized;
2571 Token = Token->Next) {
2572 int BraceCount = Token->BraceCount;
2573 if (BraceCount == 0)
2574 continue;
2575 std::string Brace;
2576 if (BraceCount < 0) {
2577 assert(BraceCount == -1);
2578 if (!Line->Affected)
2579 break;
2580 Brace = Token->is(tok::comment) ? "\n{" : "{";
2581 ++OpeningBraceSurplus;
2582 } else {
2583 if (OpeningBraceSurplus == 0)
2584 break;
2585 if (OpeningBraceSurplus < BraceCount)
2586 BraceCount = OpeningBraceSurplus;
2587 Brace = '\n' + std::string(BraceCount, '}');
2588 OpeningBraceSurplus -= BraceCount;
2589 }
2590 Token->BraceCount = 0;
2591 const auto Start = Token->Tok.getEndLoc();
2592 cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0, Brace)));
2593 }
2594 }
2595 assert(OpeningBraceSurplus == 0);
2596 }
2597};
2598
2599class BracesRemover : public TokenAnalyzer {
2600public:
2601 BracesRemover(const Environment &Env, const FormatStyle &Style)
2602 : TokenAnalyzer(Env, Style) {}
2603
2604 std::pair<tooling::Replacements, unsigned>
2605 analyze(TokenAnnotator &Annotator,
2606 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2607 FormatTokenLexer &Tokens) override {
2608 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2609 tooling::Replacements Result;
2610 removeBraces(AnnotatedLines, Result);
2611 return {Result, 0};
2612 }
2613
2614private:
2615 void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2616 tooling::Replacements &Result) {
2617 const auto &SourceMgr = Env.getSourceManager();
2618 const auto *End = Lines.end();
2619 for (const auto *I = Lines.begin(); I != End; ++I) {
2620 const auto &Line = *I;
2621 if (!Line->Children.empty())
2622 removeBraces(Line->Children, Result);
2623 if (!Line->Affected)
2624 continue;
2625 const auto *NextLine = I + 1 == End ? nullptr : I[1];
2626 for (const auto *Token = Line->First; Token && !Token->Finalized;
2627 Token = Token->Next) {
2628 if (!Token->Optional || Token->isNoneOf(tok::l_brace, tok::r_brace))
2629 continue;
2630 auto *Next = Token->Next;
2631 assert(Next || Token == Line->Last);
2632 if (!Next && NextLine)
2633 Next = NextLine->First;
2634 replaceToken(*Token, Next, SourceMgr, Result);
2635 }
2636 }
2637 }
2638};
2639
2640class SemiRemover : public TokenAnalyzer {
2641public:
2642 SemiRemover(const Environment &Env, const FormatStyle &Style)
2643 : TokenAnalyzer(Env, Style) {}
2644
2645 std::pair<tooling::Replacements, unsigned>
2646 analyze(TokenAnnotator &Annotator,
2647 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2648 FormatTokenLexer &Tokens) override {
2649 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2650 tooling::Replacements Result;
2651 removeSemi(Annotator, AnnotatedLines, Result);
2652 return {Result, 0};
2653 }
2654
2655private:
2656 void removeSemi(TokenAnnotator &Annotator,
2657 SmallVectorImpl<AnnotatedLine *> &Lines,
2658 tooling::Replacements &Result) {
2659 auto PrecededByFunctionRBrace = [](const FormatToken &Tok) {
2660 const auto *Prev = Tok.Previous;
2661 if (!Prev || Prev->isNot(tok::r_brace))
2662 return false;
2663 const auto *LBrace = Prev->MatchingParen;
2664 return LBrace && LBrace->is(TT_FunctionLBrace);
2665 };
2666 const auto &SourceMgr = Env.getSourceManager();
2667 const auto *End = Lines.end();
2668 for (const auto *I = Lines.begin(); I != End; ++I) {
2669 const auto &Line = *I;
2670 if (!Line->Children.empty())
2671 removeSemi(Annotator, Line->Children, Result);
2672 if (!Line->Affected)
2673 continue;
2674 Annotator.calculateFormattingInformation(*Line);
2675 const auto *NextLine = I + 1 == End ? nullptr : I[1];
2676 for (const auto *Token = Line->First; Token && !Token->Finalized;
2677 Token = Token->Next) {
2678 if (Token->isNot(tok::semi) ||
2679 (!Token->Optional && !PrecededByFunctionRBrace(*Token))) {
2680 continue;
2681 }
2682 auto *Next = Token->Next;
2683 assert(Next || Token == Line->Last);
2684 if (!Next && NextLine)
2685 Next = NextLine->First;
2686 replaceToken(*Token, Next, SourceMgr, Result);
2687 }
2688 }
2689 }
2690};
2691
2692class EnumTrailingCommaEditor : public TokenAnalyzer {
2693public:
2694 EnumTrailingCommaEditor(const Environment &Env, const FormatStyle &Style)
2695 : TokenAnalyzer(Env, Style) {}
2696
2697 std::pair<tooling::Replacements, unsigned>
2698 analyze(TokenAnnotator &Annotator,
2699 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2700 FormatTokenLexer &Tokens) override {
2701 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2702 tooling::Replacements Result;
2703 editEnumTrailingComma(AnnotatedLines, Result);
2704 return {Result, 0};
2705 }
2706
2707private:
2708 void editEnumTrailingComma(SmallVectorImpl<AnnotatedLine *> &Lines,
2709 tooling::Replacements &Result) {
2710 bool InEnumBraces = false;
2711 const FormatToken *BeforeRBrace = nullptr;
2712 const auto &SourceMgr = Env.getSourceManager();
2713 for (auto *Line : Lines) {
2714 if (!Line->Children.empty())
2715 editEnumTrailingComma(Line->Children, Result);
2716 for (const auto *Token = Line->First; Token && !Token->Finalized;
2717 Token = Token->Next) {
2718 if (Token->isNot(TT_EnumRBrace)) {
2719 if (Token->is(TT_EnumLBrace))
2720 InEnumBraces = true;
2721 else if (InEnumBraces && Token->isNot(tok::comment))
2722 BeforeRBrace = Line->Affected ? Token : nullptr;
2723 continue;
2724 }
2725 InEnumBraces = false;
2726 if (!BeforeRBrace) // Empty braces or Line not affected.
2727 continue;
2728 if (BeforeRBrace->is(tok::comma)) {
2729 if (Style.EnumTrailingComma == FormatStyle::ETC_Remove)
2730 replaceToken(*BeforeRBrace, BeforeRBrace->Next, SourceMgr, Result);
2731 } else if (Style.EnumTrailingComma == FormatStyle::ETC_Insert) {
2732 cantFail(Result.add(tooling::Replacement(
2733 SourceMgr, BeforeRBrace->Tok.getEndLoc(), 0, ",")));
2734 }
2735 BeforeRBrace = nullptr;
2736 }
2737 }
2738 }
2739};
2740
2741class JavaScriptRequoter : public TokenAnalyzer {
2742public:
2743 JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)
2744 : TokenAnalyzer(Env, Style) {}
2745
2746 std::pair<tooling::Replacements, unsigned>
2747 analyze(TokenAnnotator &Annotator,
2748 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2749 FormatTokenLexer &Tokens) override {
2750 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2751 tooling::Replacements Result;
2752 requoteJSStringLiteral(AnnotatedLines, Result);
2753 return {Result, 0};
2754 }
2755
2756private:
2757 // Replaces double/single-quoted string literal as appropriate, re-escaping
2758 // the contents in the process.
2759 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
2760 tooling::Replacements &Result) {
2761 for (AnnotatedLine *Line : Lines) {
2762 requoteJSStringLiteral(Line->Children, Result);
2763 if (!Line->Affected)
2764 continue;
2765 for (FormatToken *FormatTok = Line->First; FormatTok;
2766 FormatTok = FormatTok->Next) {
2767 StringRef Input = FormatTok->TokenText;
2768 if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
2769 // NB: testing for not starting with a double quote to avoid
2770 // breaking `template strings`.
2771 (Style.JavaScriptQuotes == FormatStyle::JSQS_Single &&
2772 !Input.starts_with("\"")) ||
2773 (Style.JavaScriptQuotes == FormatStyle::JSQS_Double &&
2774 !Input.starts_with("\'"))) {
2775 continue;
2776 }
2777
2778 // Change start and end quote.
2779 bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single;
2780 SourceLocation Start = FormatTok->Tok.getLocation();
2781 auto Replace = [&](SourceLocation Start, unsigned Length,
2782 StringRef ReplacementText) {
2783 auto Err = Result.add(tooling::Replacement(
2784 Env.getSourceManager(), Start, Length, ReplacementText));
2785 // FIXME: handle error. For now, print error message and skip the
2786 // replacement for release version.
2787 if (Err) {
2788 llvm::errs() << toString(std::move(Err)) << "\n";
2789 assert(false);
2790 }
2791 };
2792 Replace(Start, 1, IsSingle ? "'" : "\"");
2793 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
2794 IsSingle ? "'" : "\"");
2795
2796 // Escape internal quotes.
2797 bool Escaped = false;
2798 for (size_t i = 1; i < Input.size() - 1; i++) {
2799 switch (Input[i]) {
2800 case '\\':
2801 if (!Escaped && i + 1 < Input.size() &&
2802 ((IsSingle && Input[i + 1] == '"') ||
2803 (!IsSingle && Input[i + 1] == '\''))) {
2804 // Remove this \, it's escaping a " or ' that no longer needs
2805 // escaping
2806 Replace(Start.getLocWithOffset(i), 1, "");
2807 continue;
2808 }
2809 Escaped = !Escaped;
2810 break;
2811 case '\"':
2812 case '\'':
2813 if (!Escaped && IsSingle == (Input[i] == '\'')) {
2814 // Escape the quote.
2815 Replace(Start.getLocWithOffset(i), 0, "\\");
2816 }
2817 Escaped = false;
2818 break;
2819 default:
2820 Escaped = false;
2821 break;
2822 }
2823 }
2824 }
2825 }
2826 }
2827};
2828
2829class Formatter : public TokenAnalyzer {
2830public:
2831 Formatter(const Environment &Env, const FormatStyle &Style,
2832 FormattingAttemptStatus *Status)
2833 : TokenAnalyzer(Env, Style), Status(Status) {}
2834
2835 std::pair<tooling::Replacements, unsigned>
2836 analyze(TokenAnnotator &Annotator,
2837 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2838 FormatTokenLexer &Tokens) override {
2839 tooling::Replacements Result;
2840 deriveLocalStyle(AnnotatedLines);
2841 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2842 for (AnnotatedLine *Line : AnnotatedLines)
2843 Annotator.calculateFormattingInformation(*Line);
2844 Annotator.setCommentLineLevels(AnnotatedLines);
2845
2846 WhitespaceManager Whitespaces(
2847 Env.getSourceManager(), Style,
2848 Style.LineEnding > FormatStyle::LE_CRLF
2850 Env.getSourceManager().getBufferData(Env.getFileID()),
2851 Style.LineEnding == FormatStyle::LE_DeriveCRLF)
2852 : Style.LineEnding == FormatStyle::LE_CRLF);
2853 ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
2854 Env.getSourceManager(), Whitespaces, Encoding,
2855 BinPackInconclusiveFunctions);
2856 unsigned Penalty =
2857 UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,
2858 Tokens.getKeywords(), Env.getSourceManager(),
2859 Status)
2860 .format(AnnotatedLines, /*DryRun=*/false,
2861 /*AdditionalIndent=*/0,
2862 /*FixBadIndentation=*/false,
2863 /*FirstStartColumn=*/Env.getFirstStartColumn(),
2864 /*NextStartColumn=*/Env.getNextStartColumn(),
2865 /*LastStartColumn=*/Env.getLastStartColumn());
2866 for (const auto &R : Whitespaces.generateReplacements())
2867 if (Result.add(R))
2868 return std::make_pair(Result, 0);
2869 return std::make_pair(Result, Penalty);
2870 }
2871
2872private:
2873 bool
2874 hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) {
2875 for (const AnnotatedLine *Line : Lines) {
2876 if (hasCpp03IncompatibleFormat(Line->Children))
2877 return true;
2878 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {
2879 if (!Tok->hasWhitespaceBefore()) {
2880 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
2881 return true;
2882 if (Tok->is(TT_TemplateCloser) &&
2883 Tok->Previous->is(TT_TemplateCloser)) {
2884 return true;
2885 }
2886 }
2887 }
2888 }
2889 return false;
2890 }
2891
2892 int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) {
2893 int AlignmentDiff = 0;
2894
2895 for (const AnnotatedLine *Line : Lines) {
2896 AlignmentDiff += countVariableAlignments(Line->Children);
2897
2898 for (const auto *Tok = Line->getFirstNonComment(); Tok; Tok = Tok->Next) {
2899 if (Tok->isNot(TT_PointerOrReference))
2900 continue;
2901
2902 const auto *Prev = Tok->Previous;
2903 const bool PrecededByName = Prev && Prev->Tok.getIdentifierInfo();
2904 const bool SpaceBefore = Tok->hasWhitespaceBefore();
2905
2906 // e.g. `int **`, `int*&`, etc.
2907 while (Tok->Next && Tok->Next->is(TT_PointerOrReference))
2908 Tok = Tok->Next;
2909
2910 const auto *Next = Tok->Next;
2911 const bool FollowedByName = Next && Next->Tok.getIdentifierInfo();
2912 const bool SpaceAfter = Next && Next->hasWhitespaceBefore();
2913
2914 if ((!PrecededByName && !FollowedByName) ||
2915 // e.g. `int * i` or `int*i`
2916 (PrecededByName && FollowedByName && SpaceBefore == SpaceAfter)) {
2917 continue;
2918 }
2919
2920 if ((PrecededByName && SpaceBefore) ||
2921 (FollowedByName && !SpaceAfter)) {
2922 // Right alignment.
2923 ++AlignmentDiff;
2924 } else if ((PrecededByName && !SpaceBefore) ||
2925 (FollowedByName && SpaceAfter)) {
2926 // Left alignment.
2927 --AlignmentDiff;
2928 }
2929 }
2930 }
2931
2932 return AlignmentDiff;
2933 }
2934
2935 void
2936 deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2937 bool HasBinPackedFunction = false;
2938 bool HasOnePerLineFunction = false;
2939 for (AnnotatedLine *Line : AnnotatedLines) {
2940 if (!Line->First->Next)
2941 continue;
2942 FormatToken *Tok = Line->First->Next;
2943 while (Tok->Next) {
2944 if (Tok->is(PPK_BinPacked))
2945 HasBinPackedFunction = true;
2946 if (Tok->is(PPK_OnePerLine))
2947 HasOnePerLineFunction = true;
2948
2949 Tok = Tok->Next;
2950 }
2951 }
2952 if (Style.DerivePointerAlignment) {
2953 const auto NetRightCount = countVariableAlignments(AnnotatedLines);
2954 if (NetRightCount > 0)
2955 Style.PointerAlignment = FormatStyle::PAS_Right;
2956 else if (NetRightCount < 0)
2957 Style.PointerAlignment = FormatStyle::PAS_Left;
2958 Style.ReferenceAlignment = FormatStyle::RAS_Pointer;
2959 }
2960 if (Style.Standard == FormatStyle::LS_Auto) {
2961 Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
2962 ? FormatStyle::LS_Latest
2963 : FormatStyle::LS_Cpp03;
2964 }
2965 BinPackInconclusiveFunctions =
2966 HasBinPackedFunction || !HasOnePerLineFunction;
2967 }
2968
2969 bool BinPackInconclusiveFunctions;
2970 FormattingAttemptStatus *Status;
2971};
2972
2973/// TrailingCommaInserter inserts trailing commas into container literals.
2974/// E.g.:
2975/// const x = [
2976/// 1,
2977/// ];
2978/// TrailingCommaInserter runs after formatting. To avoid causing a required
2979/// reformatting (and thus reflow), it never inserts a comma that'd exceed the
2980/// ColumnLimit.
2981///
2982/// Because trailing commas disable binpacking of arrays, TrailingCommaInserter
2983/// is conceptually incompatible with bin packing.
2984class TrailingCommaInserter : public TokenAnalyzer {
2985public:
2986 TrailingCommaInserter(const Environment &Env, const FormatStyle &Style)
2987 : TokenAnalyzer(Env, Style) {}
2988
2989 std::pair<tooling::Replacements, unsigned>
2990 analyze(TokenAnnotator &Annotator,
2991 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2992 FormatTokenLexer &Tokens) override {
2993 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2994 tooling::Replacements Result;
2995 insertTrailingCommas(AnnotatedLines, Result);
2996 return {Result, 0};
2997 }
2998
2999private:
3000 /// Inserts trailing commas in [] and {} initializers if they wrap over
3001 /// multiple lines.
3002 void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,
3003 tooling::Replacements &Result) {
3004 for (AnnotatedLine *Line : Lines) {
3005 insertTrailingCommas(Line->Children, Result);
3006 if (!Line->Affected)
3007 continue;
3008 for (FormatToken *FormatTok = Line->First; FormatTok;
3009 FormatTok = FormatTok->Next) {
3010 if (FormatTok->NewlinesBefore == 0)
3011 continue;
3012 FormatToken *Matching = FormatTok->MatchingParen;
3013 if (!Matching || !FormatTok->getPreviousNonComment())
3014 continue;
3015 if (!(FormatTok->is(tok::r_square) &&
3016 Matching->is(TT_ArrayInitializerLSquare)) &&
3017 !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) {
3018 continue;
3019 }
3020 FormatToken *Prev = FormatTok->getPreviousNonComment();
3021 if (Prev->is(tok::comma) || Prev->is(tok::semi))
3022 continue;
3023 // getEndLoc is not reliably set during re-lexing, use text length
3024 // instead.
3025 SourceLocation Start =
3026 Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size());
3027 // If inserting a comma would push the code over the column limit, skip
3028 // this location - it'd introduce an unstable formatting due to the
3029 // required reflow.
3030 unsigned ColumnNumber =
3031 Env.getSourceManager().getSpellingColumnNumber(Start);
3032 if (ColumnNumber > Style.ColumnLimit)
3033 continue;
3034 // Comma insertions cannot conflict with each other, and this pass has a
3035 // clean set of Replacements, so the operation below cannot fail.
3036 cantFail(Result.add(
3037 tooling::Replacement(Env.getSourceManager(), Start, 0, ",")));
3038 }
3039 }
3040 }
3041};
3042
3043// This class clean up the erroneous/redundant code around the given ranges in
3044// file.
3045class Cleaner : public TokenAnalyzer {
3046public:
3047 Cleaner(const Environment &Env, const FormatStyle &Style)
3048 : TokenAnalyzer(Env, Style),
3049 DeletedTokens(FormatTokenLess(Env.getSourceManager())) {}
3050
3051 // FIXME: eliminate unused parameters.
3052 std::pair<tooling::Replacements, unsigned>
3053 analyze(TokenAnnotator &Annotator,
3054 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
3055 FormatTokenLexer &Tokens) override {
3056 // FIXME: in the current implementation the granularity of affected range
3057 // is an annotated line. However, this is not sufficient. Furthermore,
3058 // redundant code introduced by replacements does not necessarily
3059 // intercept with ranges of replacements that result in the redundancy.
3060 // To determine if some redundant code is actually introduced by
3061 // replacements(e.g. deletions), we need to come up with a more
3062 // sophisticated way of computing affected ranges.
3063 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
3064
3065 checkEmptyNamespace(AnnotatedLines);
3066
3067 for (auto *Line : AnnotatedLines)
3068 cleanupLine(Line);
3069
3070 return {generateFixes(), 0};
3071 }
3072
3073private:
3074 void cleanupLine(AnnotatedLine *Line) {
3075 for (auto *Child : Line->Children)
3076 cleanupLine(Child);
3077
3078 if (Line->Affected) {
3079 cleanupRight(Line->First, tok::comma, tok::comma);
3080 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
3081 cleanupRight(Line->First, tok::l_paren, tok::comma);
3082 cleanupLeft(Line->First, tok::comma, tok::r_paren);
3083 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
3084 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
3085 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
3086 }
3087 }
3088
3089 bool containsOnlyComments(const AnnotatedLine &Line) {
3090 for (FormatToken *Tok = Line.First; Tok; Tok = Tok->Next)
3091 if (Tok->isNot(tok::comment))
3092 return false;
3093 return true;
3094 }
3095
3096 // Iterate through all lines and remove any empty (nested) namespaces.
3097 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
3098 std::set<unsigned> DeletedLines;
3099 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
3100 auto &Line = *AnnotatedLines[i];
3101 if (Line.startsWithNamespace())
3102 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
3103 }
3104
3105 for (auto Line : DeletedLines) {
3106 FormatToken *Tok = AnnotatedLines[Line]->First;
3107 while (Tok) {
3108 deleteToken(Tok);
3109 Tok = Tok->Next;
3110 }
3111 }
3112 }
3113
3114 // The function checks if the namespace, which starts from \p CurrentLine, and
3115 // its nested namespaces are empty and delete them if they are empty. It also
3116 // sets \p NewLine to the last line checked.
3117 // Returns true if the current namespace is empty.
3118 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
3119 unsigned CurrentLine, unsigned &NewLine,
3120 std::set<unsigned> &DeletedLines) {
3121 unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
3122 if (Style.BraceWrapping.AfterNamespace) {
3123 // If the left brace is in a new line, we should consume it first so that
3124 // it does not make the namespace non-empty.
3125 // FIXME: error handling if there is no left brace.
3126 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
3127 NewLine = CurrentLine;
3128 return false;
3129 }
3130 } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
3131 return false;
3132 }
3133 while (++CurrentLine < End) {
3134 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
3135 break;
3136
3137 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
3138 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
3139 DeletedLines)) {
3140 return false;
3141 }
3142 CurrentLine = NewLine;
3143 continue;
3144 }
3145
3146 if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
3147 continue;
3148
3149 // If there is anything other than comments or nested namespaces in the
3150 // current namespace, the namespace cannot be empty.
3151 NewLine = CurrentLine;
3152 return false;
3153 }
3154
3155 NewLine = CurrentLine;
3156 if (CurrentLine >= End)
3157 return false;
3158
3159 // Check if the empty namespace is actually affected by changed ranges.
3160 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
3161 AnnotatedLines[InitLine]->First->Tok.getLocation(),
3162 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) {
3163 return false;
3164 }
3165
3166 for (unsigned i = InitLine; i <= CurrentLine; ++i)
3167 DeletedLines.insert(i);
3168
3169 return true;
3170 }
3171
3172 // Checks pairs {start, start->next},..., {end->previous, end} and deletes one
3173 // of the token in the pair if the left token has \p LK token kind and the
3174 // right token has \p RK token kind. If \p DeleteLeft is true, the left token
3175 // is deleted on match; otherwise, the right token is deleted.
3176 template <typename LeftKind, typename RightKind>
3177 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
3178 bool DeleteLeft) {
3179 auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {
3180 for (auto *Res = Tok.Next; Res; Res = Res->Next) {
3181 if (Res->isNot(tok::comment) &&
3182 DeletedTokens.find(Res) == DeletedTokens.end()) {
3183 return Res;
3184 }
3185 }
3186 return nullptr;
3187 };
3188 for (auto *Left = Start; Left;) {
3189 auto *Right = NextNotDeleted(*Left);
3190 if (!Right)
3191 break;
3192 if (Left->is(LK) && Right->is(RK)) {
3193 deleteToken(DeleteLeft ? Left : Right);
3194 for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
3195 deleteToken(Tok);
3196 // If the right token is deleted, we should keep the left token
3197 // unchanged and pair it with the new right token.
3198 if (!DeleteLeft)
3199 continue;
3200 }
3201 Left = Right;
3202 }
3203 }
3204
3205 template <typename LeftKind, typename RightKind>
3206 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
3207 cleanupPair(Start, LK, RK, /*DeleteLeft=*/true);
3208 }
3209
3210 template <typename LeftKind, typename RightKind>
3211 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
3212 cleanupPair(Start, LK, RK, /*DeleteLeft=*/false);
3213 }
3214
3215 // Delete the given token.
3216 inline void deleteToken(FormatToken *Tok) {
3217 if (Tok)
3218 DeletedTokens.insert(Tok);
3219 }
3220
3221 tooling::Replacements generateFixes() {
3222 tooling::Replacements Fixes;
3223 SmallVector<FormatToken *> Tokens;
3224 std::copy(DeletedTokens.begin(), DeletedTokens.end(),
3225 std::back_inserter(Tokens));
3226
3227 // Merge multiple continuous token deletions into one big deletion so that
3228 // the number of replacements can be reduced. This makes computing affected
3229 // ranges more efficient when we run reformat on the changed code.
3230 unsigned Idx = 0;
3231 while (Idx < Tokens.size()) {
3232 unsigned St = Idx, End = Idx;
3233 while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1])
3234 ++End;
3235 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
3236 Tokens[End]->Tok.getEndLoc());
3237 auto Err =
3238 Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, ""));
3239 // FIXME: better error handling. for now just print error message and skip
3240 // for the release version.
3241 if (Err) {
3242 llvm::errs() << toString(std::move(Err)) << "\n";
3243 assert(false && "Fixes must not conflict!");
3244 }
3245 Idx = End + 1;
3246 }
3247
3248 return Fixes;
3249 }
3250
3251 // Class for less-than inequality comparason for the set `RedundantTokens`.
3252 // We store tokens in the order they appear in the translation unit so that
3253 // we do not need to sort them in `generateFixes()`.
3254 struct FormatTokenLess {
3255 FormatTokenLess(const SourceManager &SM) : SM(SM) {}
3256
3257 bool operator()(const FormatToken *LHS, const FormatToken *RHS) const {
3258 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
3259 RHS->Tok.getLocation());
3260 }
3261 const SourceManager &SM;
3262 };
3263
3264 // Tokens to be deleted.
3265 std::set<FormatToken *, FormatTokenLess> DeletedTokens;
3266};
3267
3268class ObjCHeaderStyleGuesser : public TokenAnalyzer {
3269public:
3270 ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style)
3271 : TokenAnalyzer(Env, Style), IsObjC(false) {}
3272
3273 std::pair<tooling::Replacements, unsigned>
3274 analyze(TokenAnnotator &Annotator,
3275 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
3276 FormatTokenLexer &Tokens) override {
3277 assert(Style.Language == FormatStyle::LK_Cpp);
3278 IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines,
3279 Tokens.getKeywords());
3280 tooling::Replacements Result;
3281 return {Result, 0};
3282 }
3283
3284 bool isObjC() { return IsObjC; }
3285
3286private:
3287 static bool
3288 guessIsObjC(const SourceManager &SourceManager,
3289 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
3290 const AdditionalKeywords &Keywords) {
3291 // Keep this array sorted, since we are binary searching over it.
3292 static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
3293 "CGFloat",
3294 "CGPoint",
3295 "CGPointMake",
3296 "CGPointZero",
3297 "CGRect",
3298 "CGRectEdge",
3299 "CGRectInfinite",
3300 "CGRectMake",
3301 "CGRectNull",
3302 "CGRectZero",
3303 "CGSize",
3304 "CGSizeMake",
3305 "CGVector",
3306 "CGVectorMake",
3307 "FOUNDATION_EXPORT", // This is an alias for FOUNDATION_EXTERN.
3308 "FOUNDATION_EXTERN",
3309 "NSAffineTransform",
3310 "NSArray",
3311 "NSAttributedString",
3312 "NSBlockOperation",
3313 "NSBundle",
3314 "NSCache",
3315 "NSCalendar",
3316 "NSCharacterSet",
3317 "NSCountedSet",
3318 "NSData",
3319 "NSDataDetector",
3320 "NSDecimal",
3321 "NSDecimalNumber",
3322 "NSDictionary",
3323 "NSEdgeInsets",
3324 "NSError",
3325 "NSErrorDomain",
3326 "NSHashTable",
3327 "NSIndexPath",
3328 "NSIndexSet",
3329 "NSInteger",
3330 "NSInvocationOperation",
3331 "NSLocale",
3332 "NSMapTable",
3333 "NSMutableArray",
3334 "NSMutableAttributedString",
3335 "NSMutableCharacterSet",
3336 "NSMutableData",
3337 "NSMutableDictionary",
3338 "NSMutableIndexSet",
3339 "NSMutableOrderedSet",
3340 "NSMutableSet",
3341 "NSMutableString",
3342 "NSNumber",
3343 "NSNumberFormatter",
3344 "NSObject",
3345 "NSOperation",
3346 "NSOperationQueue",
3347 "NSOperationQueuePriority",
3348 "NSOrderedSet",
3349 "NSPoint",
3350 "NSPointerArray",
3351 "NSQualityOfService",
3352 "NSRange",
3353 "NSRect",
3354 "NSRegularExpression",
3355 "NSSet",
3356 "NSSize",
3357 "NSString",
3358 "NSTimeZone",
3359 "NSUInteger",
3360 "NSURL",
3361 "NSURLComponents",
3362 "NSURLQueryItem",
3363 "NSUUID",
3364 "NSValue",
3365 "NS_ASSUME_NONNULL_BEGIN",
3366 "UIImage",
3367 "UIView",
3368 };
3369 assert(llvm::is_sorted(FoundationIdentifiers));
3370
3371 for (auto *Line : AnnotatedLines) {
3372 if (Line->First && (Line->First->TokenText.starts_with("#") ||
3373 Line->First->TokenText == "__pragma" ||
3374 Line->First->TokenText == "_Pragma")) {
3375 continue;
3376 }
3377 for (const FormatToken *FormatTok = Line->First; FormatTok;
3378 FormatTok = FormatTok->Next) {
3379 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
3380 (FormatTok->isNot(tok::objc_not_keyword) ||
3381 FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
3382 tok::l_brace))) ||
3383 (FormatTok->Tok.isAnyIdentifier() &&
3384 llvm::binary_search(FoundationIdentifiers,
3385 FormatTok->TokenText)) ||
3386 FormatTok->is(TT_ObjCStringLiteral) ||
3387 FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,
3388 Keywords.kw_NS_ERROR_ENUM,
3389 Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,
3390 TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,
3391 TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,
3392 TT_ObjCProperty, TT_ObjCSelector)) {
3393 LLVM_DEBUG(llvm::dbgs()
3394 << "Detected ObjC at location "
3395 << FormatTok->Tok.getLocation().printToString(
3396 SourceManager)
3397 << " token: " << FormatTok->TokenText << " token type: "
3398 << getTokenTypeName(FormatTok->getType()) << "\n");
3399 return true;
3400 }
3401 }
3402 if (guessIsObjC(SourceManager, Line->Children, Keywords))
3403 return true;
3404 }
3405 return false;
3406 }
3407
3408 bool IsObjC;
3409};
3410
3411struct IncludeDirective {
3412 StringRef Filename;
3413 StringRef Text;
3414 unsigned Offset;
3415 int Category;
3416 int Priority;
3417};
3418
3419struct JavaImportDirective {
3420 StringRef Identifier;
3421 StringRef Text;
3422 unsigned Offset;
3423 SmallVector<StringRef> AssociatedCommentLines;
3424 bool IsStatic;
3425};
3426
3427} // end anonymous namespace
3428
3429// Determines whether 'Ranges' intersects with ('Start', 'End').
3430static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start,
3431 unsigned End) {
3432 for (const auto &Range : Ranges) {
3433 if (Range.getOffset() < End &&
3434 Range.getOffset() + Range.getLength() > Start) {
3435 return true;
3436 }
3437 }
3438 return false;
3439}
3440
3441// Returns a pair (Index, OffsetToEOL) describing the position of the cursor
3442// before sorting/deduplicating. Index is the index of the include under the
3443// cursor in the original set of includes. If this include has duplicates, it is
3444// the index of the first of the duplicates as the others are going to be
3445// removed. OffsetToEOL describes the cursor's position relative to the end of
3446// its current line.
3447// If `Cursor` is not on any #include, `Index` will be
3448// std::numeric_limits<unsigned>::max().
3449static std::pair<unsigned, unsigned>
3451 const ArrayRef<unsigned> &Indices, unsigned Cursor) {
3452 unsigned CursorIndex = std::numeric_limits<unsigned>::max();
3453 unsigned OffsetToEOL = 0;
3454 for (int i = 0, e = Includes.size(); i != e; ++i) {
3455 unsigned Start = Includes[Indices[i]].Offset;
3456 unsigned End = Start + Includes[Indices[i]].Text.size();
3457 if (!(Cursor >= Start && Cursor < End))
3458 continue;
3459 CursorIndex = Indices[i];
3460 OffsetToEOL = End - Cursor;
3461 // Put the cursor on the only remaining #include among the duplicate
3462 // #includes.
3463 while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text)
3464 CursorIndex = i;
3465 break;
3466 }
3467 return std::make_pair(CursorIndex, OffsetToEOL);
3468}
3469
3470// Replace all "\r\n" with "\n".
3471std::string replaceCRLF(const std::string &Code) {
3472 std::string NewCode;
3473 size_t Pos = 0, LastPos = 0;
3474
3475 do {
3476 Pos = Code.find("\r\n", LastPos);
3477 if (Pos == LastPos) {
3478 ++LastPos;
3479 continue;
3480 }
3481 if (Pos == std::string::npos) {
3482 NewCode += Code.substr(LastPos);
3483 break;
3484 }
3485 NewCode += Code.substr(LastPos, Pos - LastPos) + "\n";
3486 LastPos = Pos + 2;
3487 } while (Pos != std::string::npos);
3488
3489 return NewCode;
3490}
3491
3492// Sorts and deduplicate a block of includes given by 'Includes' alphabetically
3493// adding the necessary replacement to 'Replaces'. 'Includes' must be in strict
3494// source order.
3495// #include directives with the same text will be deduplicated, and only the
3496// first #include in the duplicate #includes remains. If the `Cursor` is
3497// provided and put on a deleted #include, it will be moved to the remaining
3498// #include in the duplicate #includes.
3499static void sortCppIncludes(const FormatStyle &Style,
3500 const ArrayRef<IncludeDirective> &Includes,
3501 ArrayRef<tooling::Range> Ranges, StringRef FileName,
3502 StringRef Code, tooling::Replacements &Replaces,
3503 unsigned *Cursor) {
3504 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
3505 const unsigned IncludesBeginOffset = Includes.front().Offset;
3506 const unsigned IncludesEndOffset =
3507 Includes.back().Offset + Includes.back().Text.size();
3508 const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
3509 if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
3510 return;
3512 llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size()));
3513
3514 if (Style.SortIncludes.Enabled) {
3515 stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
3516 SmallString<128> LHSStem, RHSStem;
3517 if (Style.SortIncludes.IgnoreExtension) {
3518 LHSStem = Includes[LHSI].Filename;
3519 RHSStem = Includes[RHSI].Filename;
3520 llvm::sys::path::replace_extension(LHSStem, "");
3521 llvm::sys::path::replace_extension(RHSStem, "");
3522 }
3523 std::string LHSStemLower, RHSStemLower;
3524 std::string LHSFilenameLower, RHSFilenameLower;
3525 if (Style.SortIncludes.IgnoreCase) {
3526 LHSStemLower = LHSStem.str().lower();
3527 RHSStemLower = RHSStem.str().lower();
3528 LHSFilenameLower = Includes[LHSI].Filename.lower();
3529 RHSFilenameLower = Includes[RHSI].Filename.lower();
3530 }
3531 return std::tie(Includes[LHSI].Priority, LHSStemLower, LHSStem,
3532 LHSFilenameLower, Includes[LHSI].Filename) <
3533 std::tie(Includes[RHSI].Priority, RHSStemLower, RHSStem,
3534 RHSFilenameLower, Includes[RHSI].Filename);
3535 });
3536 }
3537
3538 // The index of the include on which the cursor will be put after
3539 // sorting/deduplicating.
3540 unsigned CursorIndex;
3541 // The offset from cursor to the end of line.
3542 unsigned CursorToEOLOffset;
3543 if (Cursor) {
3544 std::tie(CursorIndex, CursorToEOLOffset) =
3545 FindCursorIndex(Includes, Indices, *Cursor);
3546 }
3547
3548 // Deduplicate #includes.
3549 Indices.erase(llvm::unique(Indices,
3550 [&](unsigned LHSI, unsigned RHSI) {
3551 return Includes[LHSI].Text.trim() ==
3552 Includes[RHSI].Text.trim();
3553 }),
3554 Indices.end());
3555
3556 int CurrentCategory = Includes.front().Category;
3557
3558 // If the #includes are out of order, we generate a single replacement fixing
3559 // the entire block. Otherwise, no replacement is generated.
3560 // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not
3561 // enough as additional newlines might be added or removed across #include
3562 // blocks. This we handle below by generating the updated #include blocks and
3563 // comparing it to the original.
3564 if (Indices.size() == Includes.size() && is_sorted(Indices) &&
3565 Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) {
3566 return;
3567 }
3568
3569 const auto OldCursor = Cursor ? *Cursor : 0;
3570 std::string result;
3571 for (unsigned Index : Indices) {
3572 if (!result.empty()) {
3573 result += "\n";
3574 if (Style.IncludeStyle.IncludeBlocks ==
3576 CurrentCategory != Includes[Index].Category) {
3577 result += "\n";
3578 }
3579 }
3580 result += Includes[Index].Text;
3581 if (Cursor && CursorIndex == Index)
3582 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
3583 CurrentCategory = Includes[Index].Category;
3584 }
3585
3586 if (Cursor && *Cursor >= IncludesEndOffset)
3587 *Cursor += result.size() - IncludesBlockSize;
3588
3589 // If the #includes are out of order, we generate a single replacement fixing
3590 // the entire range of blocks. Otherwise, no replacement is generated.
3591 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
3592 IncludesBeginOffset, IncludesBlockSize)))) {
3593 if (Cursor)
3594 *Cursor = OldCursor;
3595 return;
3596 }
3597
3598 auto Err = Replaces.add(tooling::Replacement(
3599 FileName, Includes.front().Offset, IncludesBlockSize, result));
3600 // FIXME: better error handling. For now, just skip the replacement for the
3601 // release version.
3602 if (Err) {
3603 llvm::errs() << toString(std::move(Err)) << "\n";
3604 assert(false);
3605 }
3606}
3607
3608tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
3610 StringRef FileName,
3611 tooling::Replacements &Replaces,
3612 unsigned *Cursor) {
3613 unsigned Prev = llvm::StringSwitch<size_t>(Code)
3614 .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM
3615 .Default(0);
3616 unsigned SearchFrom = 0;
3618 SmallVector<IncludeDirective, 16> IncludesInBlock;
3619
3620 // In compiled files, consider the first #include to be the main #include of
3621 // the file if it is not a system #include. This ensures that the header
3622 // doesn't have hidden dependencies
3623 // (http://llvm.org/docs/CodingStandards.html#include-style).
3624 //
3625 // FIXME: Do some validation, e.g. edit distance of the base name, to fix
3626 // cases where the first #include is unlikely to be the main header.
3627 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
3628 bool FirstIncludeBlock = true;
3629 bool MainIncludeFound = false;
3630 bool FormattingOff = false;
3631
3632 // '[' must be the first and '-' the last character inside [...].
3633 llvm::Regex RawStringRegex(
3634 "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\(");
3635 SmallVector<StringRef, 2> RawStringMatches;
3636 std::string RawStringTermination = ")\"";
3637
3638 for (const auto Size = Code.size(); SearchFrom < Size;) {
3639 size_t Pos = SearchFrom;
3640 if (Code[SearchFrom] != '\n') {
3641 do { // Search for the first newline while skipping line splices.
3642 ++Pos;
3643 Pos = Code.find('\n', Pos);
3644 } while (Pos != StringRef::npos && Code[Pos - 1] == '\\');
3645 }
3646
3647 StringRef Line =
3648 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3649
3650 StringRef Trimmed = Line.trim();
3651
3652 // #includes inside raw string literals need to be ignored.
3653 // or we will sort the contents of the string.
3654 // Skip past until we think we are at the rawstring literal close.
3655 if (RawStringRegex.match(Trimmed, &RawStringMatches)) {
3656 std::string CharSequence = RawStringMatches[1].str();
3657 RawStringTermination = ")" + CharSequence + "\"";
3658 FormattingOff = true;
3659 }
3660
3661 if (Trimmed.contains(RawStringTermination))
3662 FormattingOff = false;
3663
3664 bool IsBlockComment = false;
3665
3666 if (isClangFormatOff(Trimmed)) {
3667 FormattingOff = true;
3668 } else if (isClangFormatOn(Trimmed)) {
3669 FormattingOff = false;
3670 } else if (Trimmed.starts_with("/*")) {
3671 IsBlockComment = true;
3672 Pos = Code.find("*/", SearchFrom + 2);
3673 }
3674
3675 const bool EmptyLineSkipped =
3676 Trimmed.empty() &&
3677 (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge ||
3678 Style.IncludeStyle.IncludeBlocks ==
3680
3681 bool MergeWithNextLine = Trimmed.ends_with("\\");
3682 if (!FormattingOff && !MergeWithNextLine) {
3683 if (!IsBlockComment &&
3684 tooling::HeaderIncludes::IncludeRegex.match(Trimmed, &Matches)) {
3685 StringRef IncludeName = Matches[2];
3686 if (Trimmed.contains("/*") && !Trimmed.contains("*/")) {
3687 // #include with a start of a block comment, but without the end.
3688 // Need to keep all the lines until the end of the comment together.
3689 // FIXME: This is somehow simplified check that probably does not work
3690 // correctly if there are multiple comments on a line.
3691 Pos = Code.find("*/", SearchFrom);
3692 Line = Code.substr(
3693 Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev);
3694 }
3695 int Category = Categories.getIncludePriority(
3696 IncludeName,
3697 /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock);
3698 int Priority = Categories.getSortIncludePriority(
3699 IncludeName, !MainIncludeFound && FirstIncludeBlock);
3700 if (Category == 0)
3701 MainIncludeFound = true;
3702 IncludesInBlock.push_back(
3703 {IncludeName, Line, Prev, Category, Priority});
3704 } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
3705 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code,
3706 Replaces, Cursor);
3707 IncludesInBlock.clear();
3708 if (Trimmed.starts_with("#pragma hdrstop")) // Precompiled headers.
3709 FirstIncludeBlock = true;
3710 else
3711 FirstIncludeBlock = false;
3712 }
3713 }
3714 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3715 break;
3716
3717 if (!MergeWithNextLine)
3718 Prev = Pos + 1;
3719 SearchFrom = Pos + 1;
3720 }
3721 if (!IncludesInBlock.empty()) {
3722 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces,
3723 Cursor);
3724 }
3725 return Replaces;
3726}
3727
3728// Returns group number to use as a first order sort on imports. Gives
3729// std::numeric_limits<unsigned>::max() if the import does not match any given
3730// groups.
3731static unsigned findJavaImportGroup(const FormatStyle &Style,
3732 StringRef ImportIdentifier) {
3733 unsigned LongestMatchIndex = std::numeric_limits<unsigned>::max();
3734 unsigned LongestMatchLength = 0;
3735 for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) {
3736 const std::string &GroupPrefix = Style.JavaImportGroups[I];
3737 if (ImportIdentifier.starts_with(GroupPrefix) &&
3738 GroupPrefix.length() > LongestMatchLength) {
3739 LongestMatchIndex = I;
3740 LongestMatchLength = GroupPrefix.length();
3741 }
3742 }
3743 return LongestMatchIndex;
3744}
3745
3746// Sorts and deduplicates a block of includes given by 'Imports' based on
3747// JavaImportGroups, then adding the necessary replacement to 'Replaces'.
3748// Import declarations with the same text will be deduplicated. Between each
3749// import group, a newline is inserted, and within each import group, a
3750// lexicographic sort based on ASCII value is performed.
3751static void sortJavaImports(const FormatStyle &Style,
3752 const ArrayRef<JavaImportDirective> &Imports,
3753 ArrayRef<tooling::Range> Ranges, StringRef FileName,
3754 StringRef Code, tooling::Replacements &Replaces) {
3755 unsigned ImportsBeginOffset = Imports.front().Offset;
3756 unsigned ImportsEndOffset =
3757 Imports.back().Offset + Imports.back().Text.size();
3758 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;
3759 if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))
3760 return;
3761
3763 llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size()));
3765 JavaImportGroups.reserve(Imports.size());
3766 for (const JavaImportDirective &Import : Imports)
3767 JavaImportGroups.push_back(findJavaImportGroup(Style, Import.Identifier));
3768
3769 bool StaticImportAfterNormalImport =
3770 Style.SortJavaStaticImport == FormatStyle::SJSIO_After;
3771 sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
3772 // Negating IsStatic to push static imports above non-static imports.
3773 return std::make_tuple(!Imports[LHSI].IsStatic ^
3774 StaticImportAfterNormalImport,
3775 JavaImportGroups[LHSI], Imports[LHSI].Identifier) <
3776 std::make_tuple(!Imports[RHSI].IsStatic ^
3777 StaticImportAfterNormalImport,
3778 JavaImportGroups[RHSI], Imports[RHSI].Identifier);
3779 });
3780
3781 // Deduplicate imports.
3782 Indices.erase(llvm::unique(Indices,
3783 [&](unsigned LHSI, unsigned RHSI) {
3784 return Imports[LHSI].Text == Imports[RHSI].Text;
3785 }),
3786 Indices.end());
3787
3788 bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
3789 unsigned CurrentImportGroup = JavaImportGroups[Indices.front()];
3790
3791 std::string result;
3792 for (unsigned Index : Indices) {
3793 if (!result.empty()) {
3794 result += "\n";
3795 if (CurrentIsStatic != Imports[Index].IsStatic ||
3796 CurrentImportGroup != JavaImportGroups[Index]) {
3797 result += "\n";
3798 }
3799 }
3800 for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) {
3801 result += CommentLine;
3802 result += "\n";
3803 }
3804 result += Imports[Index].Text;
3805 CurrentIsStatic = Imports[Index].IsStatic;
3806 CurrentImportGroup = JavaImportGroups[Index];
3807 }
3808
3809 // If the imports are out of order, we generate a single replacement fixing
3810 // the entire block. Otherwise, no replacement is generated.
3811 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
3812 Imports.front().Offset, ImportsBlockSize)))) {
3813 return;
3814 }
3815
3816 auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset,
3817 ImportsBlockSize, result));
3818 // FIXME: better error handling. For now, just skip the replacement for the
3819 // release version.
3820 if (Err) {
3821 llvm::errs() << toString(std::move(Err)) << "\n";
3822 assert(false);
3823 }
3824}
3825
3826namespace {
3827
3828const char JavaImportRegexPattern[] =
3829 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;";
3830
3831} // anonymous namespace
3832
3833tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code,
3835 StringRef FileName,
3836 tooling::Replacements &Replaces) {
3837 unsigned Prev = 0;
3838 unsigned SearchFrom = 0;
3839 llvm::Regex ImportRegex(JavaImportRegexPattern);
3842 SmallVector<StringRef> AssociatedCommentLines;
3843
3844 bool FormattingOff = false;
3845
3846 for (;;) {
3847 auto Pos = Code.find('\n', SearchFrom);
3848 StringRef Line =
3849 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3850
3851 StringRef Trimmed = Line.trim();
3852 if (isClangFormatOff(Trimmed))
3853 FormattingOff = true;
3854 else if (isClangFormatOn(Trimmed))
3855 FormattingOff = false;
3856
3857 if (ImportRegex.match(Line, &Matches)) {
3858 if (FormattingOff) {
3859 // If at least one import line has formatting turned off, turn off
3860 // formatting entirely.
3861 return Replaces;
3862 }
3863 StringRef Static = Matches[1];
3864 StringRef Identifier = Matches[2];
3865 bool IsStatic = false;
3866 if (Static.contains("static"))
3867 IsStatic = true;
3868 ImportsInBlock.push_back(
3869 {Identifier, Line, Prev, AssociatedCommentLines, IsStatic});
3870 AssociatedCommentLines.clear();
3871 } else if (!Trimmed.empty() && !ImportsInBlock.empty()) {
3872 // Associating comments within the imports with the nearest import below
3873 AssociatedCommentLines.push_back(Line);
3874 }
3875 Prev = Pos + 1;
3876 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3877 break;
3878 SearchFrom = Pos + 1;
3879 }
3880 if (!ImportsInBlock.empty())
3881 sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces);
3882 return Replaces;
3883}
3884
3885bool isMpegTS(StringRef Code) {
3886 // MPEG transport streams use the ".ts" file extension. clang-format should
3887 // not attempt to format those. MPEG TS' frame format starts with 0x47 every
3888 // 189 bytes - detect that and return.
3889 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
3890}
3891
3892bool isLikelyXml(StringRef Code) { return Code.ltrim().starts_with("<"); }
3893
3894tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
3896 StringRef FileName, unsigned *Cursor) {
3897 tooling::Replacements Replaces;
3898 if (!Style.SortIncludes.Enabled || Style.DisableFormat)
3899 return Replaces;
3900 if (isLikelyXml(Code))
3901 return Replaces;
3902 if (Style.isJavaScript()) {
3903 if (isMpegTS(Code))
3904 return Replaces;
3905 return sortJavaScriptImports(Style, Code, Ranges, FileName);
3906 }
3907 if (Style.isJava())
3908 return sortJavaImports(Style, Code, Ranges, FileName, Replaces);
3909 if (Style.isCpp())
3910 sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor);
3911 return Replaces;
3912}
3913
3914template <typename T>
3916processReplacements(T ProcessFunc, StringRef Code,
3917 const tooling::Replacements &Replaces,
3918 const FormatStyle &Style) {
3919 if (Replaces.empty())
3920 return tooling::Replacements();
3921
3922 auto NewCode = applyAllReplacements(Code, Replaces);
3923 if (!NewCode)
3924 return NewCode.takeError();
3925 std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();
3926 StringRef FileName = Replaces.begin()->getFilePath();
3927
3928 tooling::Replacements FormatReplaces =
3929 ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
3930
3931 return Replaces.merge(FormatReplaces);
3932}
3933
3935formatReplacements(StringRef Code, const tooling::Replacements &Replaces,
3936 const FormatStyle &Style) {
3937 // We need to use lambda function here since there are two versions of
3938 // `sortIncludes`.
3939 auto SortIncludes = [](const FormatStyle &Style, StringRef Code,
3940 std::vector<tooling::Range> Ranges,
3941 StringRef FileName) -> tooling::Replacements {
3942 return sortIncludes(Style, Code, Ranges, FileName);
3943 };
3944 auto SortedReplaces =
3945 processReplacements(SortIncludes, Code, Replaces, Style);
3946 if (!SortedReplaces)
3947 return SortedReplaces.takeError();
3948
3949 // We need to use lambda function here since there are two versions of
3950 // `reformat`.
3951 auto Reformat = [](const FormatStyle &Style, StringRef Code,
3952 std::vector<tooling::Range> Ranges,
3953 StringRef FileName) -> tooling::Replacements {
3954 return reformat(Style, Code, Ranges, FileName);
3955 };
3956 return processReplacements(Reformat, Code, *SortedReplaces, Style);
3957}
3958
3959namespace {
3960
3961inline bool isHeaderInsertion(const tooling::Replacement &Replace) {
3962 return Replace.getOffset() == std::numeric_limits<unsigned>::max() &&
3963 Replace.getLength() == 0 &&
3965 Replace.getReplacementText());
3966}
3967
3968inline bool isHeaderDeletion(const tooling::Replacement &Replace) {
3969 return Replace.getOffset() == std::numeric_limits<unsigned>::max() &&
3970 Replace.getLength() == 1;
3971}
3972
3973// FIXME: insert empty lines between newly created blocks.
3974tooling::Replacements
3975fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
3976 const FormatStyle &Style) {
3977 if (!Style.isCpp())
3978 return Replaces;
3979
3980 tooling::Replacements HeaderInsertions;
3981 std::set<StringRef> HeadersToDelete;
3982 tooling::Replacements Result;
3983 for (const auto &R : Replaces) {
3984 if (isHeaderInsertion(R)) {
3985 // Replacements from \p Replaces must be conflict-free already, so we can
3986 // simply consume the error.
3987 consumeError(HeaderInsertions.add(R));
3988 } else if (isHeaderDeletion(R)) {
3989 HeadersToDelete.insert(R.getReplacementText());
3990 } else if (R.getOffset() == std::numeric_limits<unsigned>::max()) {
3991 llvm::errs() << "Insertions other than header #include insertion are "
3992 "not supported! "
3993 << R.getReplacementText() << "\n";
3994 } else {
3995 consumeError(Result.add(R));
3996 }
3997 }
3998 if (HeaderInsertions.empty() && HeadersToDelete.empty())
3999 return Replaces;
4000
4001 StringRef FileName = Replaces.begin()->getFilePath();
4002 tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle);
4003
4004 for (const auto &Header : HeadersToDelete) {
4005 tooling::Replacements Replaces =
4006 Includes.remove(Header.trim("\"<>"), Header.starts_with("<"));
4007 for (const auto &R : Replaces) {
4008 auto Err = Result.add(R);
4009 if (Err) {
4010 // Ignore the deletion on conflict.
4011 llvm::errs() << "Failed to add header deletion replacement for "
4012 << Header << ": " << toString(std::move(Err)) << "\n";
4013 }
4014 }
4015 }
4016
4018 for (const auto &R : HeaderInsertions) {
4019 auto IncludeDirective = R.getReplacementText();
4020 bool Matched =
4021 tooling::HeaderIncludes::IncludeRegex.match(IncludeDirective, &Matches);
4022 assert(Matched && "Header insertion replacement must have replacement text "
4023 "'#include ...'");
4024 (void)Matched;
4025 auto IncludeName = Matches[2];
4026 auto Replace =
4027 Includes.insert(IncludeName.trim("\"<>"), IncludeName.starts_with("<"),
4029 if (Replace) {
4030 auto Err = Result.add(*Replace);
4031 if (Err) {
4032 consumeError(std::move(Err));
4033 unsigned NewOffset =
4034 Result.getShiftedCodePosition(Replace->getOffset());
4035 auto Shifted = tooling::Replacement(FileName, NewOffset, 0,
4036 Replace->getReplacementText());
4037 Result = Result.merge(tooling::Replacements(Shifted));
4038 }
4039 }
4040 }
4041 return Result;
4042}
4043
4044} // anonymous namespace
4045
4047cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
4048 const FormatStyle &Style) {
4049 // We need to use lambda function here since there are two versions of
4050 // `cleanup`.
4051 auto Cleanup = [](const FormatStyle &Style, StringRef Code,
4053 StringRef FileName) -> tooling::Replacements {
4054 return cleanup(Style, Code, Ranges, FileName);
4055 };
4056 // Make header insertion replacements insert new headers into correct blocks.
4057 tooling::Replacements NewReplaces =
4058 fixCppIncludeInsertions(Code, Replaces, Style);
4059 return cantFail(processReplacements(Cleanup, Code, NewReplaces, Style));
4060}
4061
4062namespace internal {
4063std::pair<tooling::Replacements, unsigned>
4064reformat(const FormatStyle &Style, StringRef Code,
4065 ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,
4066 unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,
4067 FormattingAttemptStatus *Status) {
4068 FormatStyle Expanded = Style;
4072 Expanded.InsertBraces = false;
4073 Expanded.RemoveBracesLLVM = false;
4074 Expanded.RemoveParentheses = FormatStyle::RPS_Leave;
4075 Expanded.RemoveSemicolon = false;
4076 switch (Expanded.RequiresClausePosition) {
4077 case FormatStyle::RCPS_SingleLine:
4078 case FormatStyle::RCPS_WithPreceding:
4079 Expanded.IndentRequiresClause = false;
4080 break;
4081 default:
4082 break;
4083 }
4084
4085 if (Expanded.DisableFormat)
4086 return {tooling::Replacements(), 0};
4087 if (isLikelyXml(Code))
4088 return {tooling::Replacements(), 0};
4089 if (Expanded.isJavaScript() && isMpegTS(Code))
4090 return {tooling::Replacements(), 0};
4091
4092 // JSON only needs the formatting passing.
4093 if (Style.isJson()) {
4094 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
4095 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
4096 NextStartColumn, LastStartColumn);
4097 if (!Env)
4098 return {};
4099 // Perform the actual formatting pass.
4100 tooling::Replacements Replaces =
4101 Formatter(*Env, Style, Status).process().first;
4102 // add a replacement to remove the "x = " from the result.
4103 if (Code.starts_with("x = ")) {
4104 Replaces = Replaces.merge(
4106 }
4107 // apply the reformatting changes and the removal of "x = ".
4108 if (applyAllReplacements(Code, Replaces))
4109 return {Replaces, 0};
4110 return {tooling::Replacements(), 0};
4111 }
4112
4113 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
4114 NextStartColumn, LastStartColumn);
4115 if (!Env)
4116 return {};
4117
4119 const Environment &)>
4121
4123
4124 Passes.emplace_back([&](const Environment &Env) {
4125 return IntegerLiteralSeparatorFixer().process(Env, Expanded);
4126 });
4127
4128 Passes.emplace_back([&](const Environment &Env) {
4129 return NumericLiteralCaseFixer().process(Env, Expanded);
4130 });
4131
4132 if (Style.isCpp()) {
4133 if (Style.QualifierAlignment != FormatStyle::QAS_Leave)
4134 addQualifierAlignmentFixerPasses(Expanded, Passes);
4135
4136 if (Style.RemoveParentheses != FormatStyle::RPS_Leave) {
4137 FormatStyle S = Expanded;
4138 S.RemoveParentheses = Style.RemoveParentheses;
4139 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
4140 return ParensRemover(Env, S).process(/*SkipAnnotation=*/true);
4141 });
4142 }
4143
4144 if (Style.InsertBraces) {
4145 FormatStyle S = Expanded;
4146 S.InsertBraces = true;
4147 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
4148 return BracesInserter(Env, S).process(/*SkipAnnotation=*/true);
4149 });
4150 }
4151
4152 if (Style.RemoveBracesLLVM) {
4153 FormatStyle S = Expanded;
4154 S.RemoveBracesLLVM = true;
4155 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
4156 return BracesRemover(Env, S).process(/*SkipAnnotation=*/true);
4157 });
4158 }
4159
4160 if (Style.RemoveSemicolon) {
4161 FormatStyle S = Expanded;
4162 S.RemoveSemicolon = true;
4163 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
4164 return SemiRemover(Env, S).process();
4165 });
4166 }
4167
4168 if (Style.EnumTrailingComma != FormatStyle::ETC_Leave) {
4169 Passes.emplace_back([&](const Environment &Env) {
4170 return EnumTrailingCommaEditor(Env, Expanded)
4171 .process(/*SkipAnnotation=*/true);
4172 });
4173 }
4174
4175 if (Style.FixNamespaceComments) {
4176 Passes.emplace_back([&](const Environment &Env) {
4177 return NamespaceEndCommentsFixer(Env, Expanded).process();
4178 });
4179 }
4180
4181 if (Style.SortUsingDeclarations != FormatStyle::SUD_Never) {
4182 Passes.emplace_back([&](const Environment &Env) {
4183 return UsingDeclarationsSorter(Env, Expanded).process();
4184 });
4185 }
4186 }
4187
4188 if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) {
4189 Passes.emplace_back([&](const Environment &Env) {
4190 return DefinitionBlockSeparator(Env, Expanded).process();
4191 });
4192 }
4193
4194 if (Style.Language == FormatStyle::LK_ObjC &&
4195 !Style.ObjCPropertyAttributeOrder.empty()) {
4196 Passes.emplace_back([&](const Environment &Env) {
4197 return ObjCPropertyAttributeOrderFixer(Env, Expanded).process();
4198 });
4199 }
4200
4201 if (Style.isJavaScript() &&
4202 Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) {
4203 Passes.emplace_back([&](const Environment &Env) {
4204 return JavaScriptRequoter(Env, Expanded).process(/*SkipAnnotation=*/true);
4205 });
4206 }
4207
4208 Passes.emplace_back([&](const Environment &Env) {
4209 return Formatter(Env, Expanded, Status).process();
4210 });
4211
4212 if (Style.isJavaScript() &&
4213 Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) {
4214 Passes.emplace_back([&](const Environment &Env) {
4215 return TrailingCommaInserter(Env, Expanded).process();
4216 });
4217 }
4218
4219 std::optional<std::string> CurrentCode;
4221 unsigned Penalty = 0;
4222 for (size_t I = 0, E = Passes.size(); I < E; ++I) {
4223 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
4224 auto NewCode = applyAllReplacements(
4225 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
4226 if (NewCode) {
4227 Fixes = Fixes.merge(PassFixes.first);
4228 Penalty += PassFixes.second;
4229 if (I + 1 < E) {
4230 CurrentCode = std::move(*NewCode);
4231 Env = Environment::make(
4232 *CurrentCode, FileName,
4234 FirstStartColumn, NextStartColumn, LastStartColumn);
4235 if (!Env)
4236 return {};
4237 }
4238 }
4239 }
4240
4241 if (Style.QualifierAlignment != FormatStyle::QAS_Leave) {
4242 // Don't make replacements that replace nothing. QualifierAlignment can
4243 // produce them if one of its early passes changes e.g. `const volatile` to
4244 // `volatile const` and then a later pass changes it back again.
4245 tooling::Replacements NonNoOpFixes;
4246 for (const tooling::Replacement &Fix : Fixes) {
4247 StringRef OriginalCode = Code.substr(Fix.getOffset(), Fix.getLength());
4248 if (OriginalCode != Fix.getReplacementText()) {
4249 auto Err = NonNoOpFixes.add(Fix);
4250 if (Err) {
4251 llvm::errs() << "Error adding replacements : "
4252 << toString(std::move(Err)) << "\n";
4253 }
4254 }
4255 }
4256 Fixes = std::move(NonNoOpFixes);
4257 }
4258
4259 return {Fixes, Penalty};
4260}
4261} // namespace internal
4262
4263tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
4265 StringRef FileName,
4266 FormattingAttemptStatus *Status) {
4267 return internal::reformat(Style, Code, Ranges,
4268 /*FirstStartColumn=*/0,
4269 /*NextStartColumn=*/0,
4270 /*LastStartColumn=*/0, FileName, Status)
4271 .first;
4272}
4273
4274tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
4276 StringRef FileName) {
4277 // cleanups only apply to C++ (they mostly concern ctor commas etc.)
4278 if (Style.Language != FormatStyle::LK_Cpp)
4279 return tooling::Replacements();
4280 auto Env = Environment::make(Code, FileName, Ranges);
4281 if (!Env)
4282 return {};
4283 return Cleaner(*Env, Style).process().first;
4284}
4285
4286tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
4288 StringRef FileName, bool *IncompleteFormat) {
4290 auto Result = reformat(Style, Code, Ranges, FileName, &Status);
4291 if (!Status.FormatComplete)
4292 *IncompleteFormat = true;
4293 return Result;
4294}
4295
4297 StringRef Code,
4299 StringRef FileName) {
4300 auto Env = Environment::make(Code, FileName, Ranges);
4301 if (!Env)
4302 return {};
4303 return NamespaceEndCommentsFixer(*Env, Style).process().first;
4304}
4305
4307 StringRef Code,
4309 StringRef FileName) {
4310 auto Env = Environment::make(Code, FileName, Ranges);
4311 if (!Env)
4312 return {};
4313 return UsingDeclarationsSorter(*Env, Style).process().first;
4314}
4315
4316LangOptions getFormattingLangOpts(const FormatStyle &Style) {
4317 LangOptions LangOpts;
4318
4319 auto LexingStd = Style.Standard;
4320 if (LexingStd == FormatStyle::LS_Auto || LexingStd == FormatStyle::LS_Latest)
4321 LexingStd = FormatStyle::LS_Cpp20;
4322
4323 const bool SinceCpp11 = LexingStd >= FormatStyle::LS_Cpp11;
4324 const bool SinceCpp20 = LexingStd >= FormatStyle::LS_Cpp20;
4325
4326 switch (Style.Language) {
4327 case FormatStyle::LK_C:
4328 LangOpts.C11 = 1;
4329 LangOpts.C23 = 1;
4330 break;
4331 case FormatStyle::LK_Cpp:
4332 case FormatStyle::LK_ObjC:
4333 LangOpts.CXXOperatorNames = 1;
4334 LangOpts.CPlusPlus11 = SinceCpp11;
4335 LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14;
4336 LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17;
4337 LangOpts.CPlusPlus20 = SinceCpp20;
4338 [[fallthrough]];
4339 default:
4340 LangOpts.CPlusPlus = 1;
4341 }
4342
4343 LangOpts.Char8 = SinceCpp20;
4344 LangOpts.AllowLiteralDigitSeparator = LangOpts.CPlusPlus14 || LangOpts.C23;
4345 // Turning on digraphs in standards before C++0x is error-prone, because e.g.
4346 // the sequence "<::" will be unconditionally treated as "[:".
4347 // Cf. Lexer::LexTokenInternal.
4348 LangOpts.Digraphs = SinceCpp11;
4349
4350 LangOpts.LineComment = 1;
4351 LangOpts.Bool = 1;
4352 LangOpts.ObjC = 1;
4353 LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally.
4354 LangOpts.DeclSpecKeyword = 1; // To get __declspec.
4355 LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict.
4356
4357 return LangOpts;
4358}
4359
4361 "Set coding style. <string> can be:\n"
4362 "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"
4363 " Mozilla, WebKit.\n"
4364 "2. 'file' to load style configuration from a\n"
4365 " .clang-format file in one of the parent directories\n"
4366 " of the source file (for stdin, see --assume-filename).\n"
4367 " If no .clang-format file is found, falls back to\n"
4368 " --fallback-style.\n"
4369 " --style=file is the default.\n"
4370 "3. 'file:<format_file_path>' to explicitly specify\n"
4371 " the configuration file.\n"
4372 "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n"
4373 " --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
4374
4375static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
4376 if (FileName.ends_with(".c"))
4377 return FormatStyle::LK_C;
4378 if (FileName.ends_with(".java"))
4379 return FormatStyle::LK_Java;
4380 if (FileName.ends_with_insensitive(".js") ||
4381 FileName.ends_with_insensitive(".mjs") ||
4382 FileName.ends_with_insensitive(".cjs") ||
4383 FileName.ends_with_insensitive(".ts")) {
4384 return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript.
4385 }
4386 if (FileName.ends_with(".m") || FileName.ends_with(".mm"))
4387 return FormatStyle::LK_ObjC;
4388 if (FileName.ends_with_insensitive(".proto") ||
4389 FileName.ends_with_insensitive(".protodevel")) {
4390 return FormatStyle::LK_Proto;
4391 }
4392 // txtpb is the canonical extension, and textproto is the legacy canonical
4393 // extension
4394 // https://protobuf.dev/reference/protobuf/textformat-spec/#text-format-files
4395 if (FileName.ends_with_insensitive(".txtpb") ||
4396 FileName.ends_with_insensitive(".textpb") ||
4397 FileName.ends_with_insensitive(".pb.txt") ||
4398 FileName.ends_with_insensitive(".textproto") ||
4399 FileName.ends_with_insensitive(".asciipb")) {
4400 return FormatStyle::LK_TextProto;
4401 }
4402 if (FileName.ends_with_insensitive(".td"))
4403 return FormatStyle::LK_TableGen;
4404 if (FileName.ends_with_insensitive(".cs"))
4405 return FormatStyle::LK_CSharp;
4406 if (FileName.ends_with_insensitive(".json") ||
4407 FileName.ends_with_insensitive(".ipynb")) {
4408 return FormatStyle::LK_Json;
4409 }
4410 if (FileName.ends_with_insensitive(".sv") ||
4411 FileName.ends_with_insensitive(".svh") ||
4412 FileName.ends_with_insensitive(".v") ||
4413 FileName.ends_with_insensitive(".vh")) {
4414 return FormatStyle::LK_Verilog;
4415 }
4416 return FormatStyle::LK_Cpp;
4417}
4418
4419static FormatStyle::LanguageKind getLanguageByComment(const Environment &Env) {
4420 const auto ID = Env.getFileID();
4421 const auto &SourceMgr = Env.getSourceManager();
4422
4423 LangOptions LangOpts;
4424 LangOpts.CPlusPlus = 1;
4425 LangOpts.LineComment = 1;
4426
4427 Lexer Lex(ID, SourceMgr.getBufferOrFake(ID), SourceMgr, LangOpts);
4428 Lex.SetCommentRetentionState(true);
4429
4430 for (Token Tok; !Lex.LexFromRawLexer(Tok) && Tok.is(tok::comment);) {
4431 auto Text = StringRef(SourceMgr.getCharacterData(Tok.getLocation()),
4432 Tok.getLength());
4433 if (!Text.consume_front("// clang-format Language:"))
4434 continue;
4435
4436 Text = Text.trim();
4437 if (Text == "C")
4438 return FormatStyle::LK_C;
4439 if (Text == "Cpp")
4440 return FormatStyle::LK_Cpp;
4441 if (Text == "ObjC")
4442 return FormatStyle::LK_ObjC;
4443 }
4444
4445 return FormatStyle::LK_None;
4446}
4447
4448FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {
4449 const auto GuessedLanguage = getLanguageByFileName(FileName);
4450 if (GuessedLanguage == FormatStyle::LK_Cpp) {
4451 auto Extension = llvm::sys::path::extension(FileName);
4452 // If there's no file extension (or it's .h), we need to check the contents
4453 // of the code to see if it contains Objective-C.
4454 if (!Code.empty() && (Extension.empty() || Extension == ".h")) {
4455 auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName;
4456 Environment Env(Code, NonEmptyFileName, /*Ranges=*/{});
4457 if (const auto Language = getLanguageByComment(Env);
4458 Language != FormatStyle::LK_None) {
4459 return Language;
4460 }
4461 ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle());
4462 Guesser.process();
4463 if (Guesser.isObjC())
4464 return FormatStyle::LK_ObjC;
4465 }
4466 }
4467 return GuessedLanguage;
4468}
4469
4470// Update StyleOptionHelpDescription above when changing this.
4471const char *DefaultFormatStyle = "file";
4472
4473const char *DefaultFallbackStyle = "LLVM";
4474
4475llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
4476loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS,
4477 FormatStyle *Style, bool AllowUnknownOptions,
4478 llvm::SourceMgr::DiagHandlerTy DiagHandler,
4479 bool IsDotHFile) {
4480 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
4481 FS->getBufferForFile(ConfigFile.str());
4482 if (auto EC = Text.getError())
4483 return EC;
4484 if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions,
4485 DiagHandler, /*DiagHandlerCtx=*/nullptr,
4486 IsDotHFile)) {
4487 return EC;
4488 }
4489 return Text;
4490}
4491
4492Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
4493 StringRef FallbackStyleName, StringRef Code,
4494 llvm::vfs::FileSystem *FS,
4495 bool AllowUnknownOptions,
4496 llvm::SourceMgr::DiagHandlerTy DiagHandler) {
4497 FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code));
4498 FormatStyle FallbackStyle = getNoStyle();
4499 if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))
4500 return make_string_error("Invalid fallback style: " + FallbackStyleName);
4501
4502 SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1> ChildFormatTextToApply;
4503
4504 if (StyleName.starts_with("{")) {
4505 // Parse YAML/JSON style from the command line.
4506 StringRef Source = "<command-line>";
4507 if (std::error_code ec =
4508 parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style,
4509 AllowUnknownOptions, DiagHandler)) {
4510 return make_string_error("Error parsing -style: " + ec.message());
4511 }
4512
4513 if (Style.InheritConfig.empty())
4514 return Style;
4515
4516 ChildFormatTextToApply.emplace_back(
4517 llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false));
4518 }
4519
4520 if (!FS)
4521 FS = llvm::vfs::getRealFileSystem().get();
4522 assert(FS);
4523
4524 const bool IsDotHFile = FileName.ends_with(".h");
4525
4526 // User provided clang-format file using -style=file:path/to/format/file.
4527 if (Style.InheritConfig.empty() &&
4528 StyleName.starts_with_insensitive("file:")) {
4529 auto ConfigFile = StyleName.substr(5);
4530 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
4531 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions,
4532 DiagHandler, IsDotHFile);
4533 if (auto EC = Text.getError()) {
4534 return make_string_error("Error reading " + ConfigFile + ": " +
4535 EC.message());
4536 }
4537
4538 LLVM_DEBUG(llvm::dbgs()
4539 << "Using configuration file " << ConfigFile << "\n");
4540
4541 if (Style.InheritConfig.empty())
4542 return Style;
4543
4544 // Search for parent configs starting from the parent directory of
4545 // ConfigFile.
4546 FileName = ConfigFile;
4547 ChildFormatTextToApply.emplace_back(std::move(*Text));
4548 }
4549
4550 // If the style inherits the parent configuration it is a command line
4551 // configuration, which wants to inherit, so we have to skip the check of the
4552 // StyleName.
4553 if (Style.InheritConfig.empty() && !StyleName.equals_insensitive("file")) {
4554 if (!getPredefinedStyle(StyleName, Style.Language, &Style))
4555 return make_string_error("Invalid value for -style");
4556 if (Style.InheritConfig.empty())
4557 return Style;
4558 }
4559
4560 using namespace llvm::sys::path;
4561 using String = SmallString<128>;
4562
4563 String Path(FileName);
4564 if (std::error_code EC = FS->makeAbsolute(Path))
4565 return make_string_error(EC.message());
4566
4567 auto Normalize = [](String &Path) {
4568 Path = convert_to_slash(Path);
4569 remove_dots(Path, /*remove_dot_dot=*/true, Style::posix);
4570 };
4571
4572 Normalize(Path);
4573
4574 // Reset possible inheritance
4575 Style.InheritConfig.clear();
4576
4577 auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {};
4578
4579 auto applyChildFormatTexts = [&](FormatStyle *Style) {
4580 for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) {
4581 auto EC =
4582 parseConfiguration(*MemBuf, Style, AllowUnknownOptions,
4583 DiagHandler ? DiagHandler : dropDiagnosticHandler);
4584 // It was already correctly parsed.
4585 assert(!EC);
4586 static_cast<void>(EC);
4587 }
4588 };
4589
4590 // Look for .clang-format/_clang-format file in the file's parent directories.
4591 SmallVector<std::string, 2> FilesToLookFor;
4592 FilesToLookFor.push_back(".clang-format");
4593 FilesToLookFor.push_back("_clang-format");
4594
4595 llvm::StringSet<> Directories; // Inherited directories.
4596 bool Redirected = false;
4597 String Dir, UnsuitableConfigFiles;
4598 for (StringRef Directory = Path; !Directory.empty();
4599 Directory = Redirected ? Dir.str() : parent_path(Directory)) {
4600 auto Status = FS->status(Directory);
4601 if (!Status ||
4602 Status->getType() != llvm::sys::fs::file_type::directory_file) {
4603 if (!Redirected)
4604 continue;
4605 return make_string_error("Failed to inherit configuration directory " +
4606 Directory);
4607 }
4608
4609 for (const auto &F : FilesToLookFor) {
4610 String ConfigFile(Directory);
4611
4612 append(ConfigFile, F);
4613 LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
4614
4615 Status = FS->status(ConfigFile);
4616 if (!Status ||
4617 Status->getType() != llvm::sys::fs::file_type::regular_file) {
4618 continue;
4619 }
4620
4621 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
4622 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions,
4623 DiagHandler, IsDotHFile);
4624 if (auto EC = Text.getError()) {
4625 if (EC != ParseError::Unsuitable) {
4626 return make_string_error("Error reading " + ConfigFile + ": " +
4627 EC.message());
4628 }
4629 if (!UnsuitableConfigFiles.empty())
4630 UnsuitableConfigFiles.append(", ");
4631 UnsuitableConfigFiles.append(ConfigFile);
4632 continue;
4633 }
4634
4635 LLVM_DEBUG(llvm::dbgs()
4636 << "Using configuration file " << ConfigFile << "\n");
4637
4638 if (Style.InheritConfig.empty()) {
4639 if (!ChildFormatTextToApply.empty()) {
4640 LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n");
4641 applyChildFormatTexts(&Style);
4642 }
4643 return Style;
4644 }
4645
4646 if (!Directories.insert(Directory).second) {
4647 return make_string_error(
4648 "Loop detected when inheriting configuration file in " + Directory);
4649 }
4650
4651 LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n");
4652
4653 if (Style.InheritConfig == "..") {
4654 Redirected = false;
4655 } else {
4656 Redirected = true;
4657 String ExpandedDir;
4658 llvm::sys::fs::expand_tilde(Style.InheritConfig, ExpandedDir);
4659 Normalize(ExpandedDir);
4660 if (is_absolute(ExpandedDir, Style::posix)) {
4661 Dir = ExpandedDir;
4662 } else {
4663 Dir = Directory.str();
4664 append(Dir, Style::posix, ExpandedDir);
4665 }
4666 }
4667
4668 // Reset inheritance of style
4669 Style.InheritConfig.clear();
4670
4671 ChildFormatTextToApply.emplace_back(std::move(*Text));
4672
4673 // Breaking out of the inner loop, since we don't want to parse
4674 // .clang-format AND _clang-format, if both exist. Then we continue the
4675 // outer loop (parent directories) in search for the parent
4676 // configuration.
4677 break;
4678 }
4679 }
4680
4681 if (!UnsuitableConfigFiles.empty()) {
4682 return make_string_error("Configuration file(s) do(es) not support " +
4683 getLanguageName(Style.Language) + ": " +
4684 UnsuitableConfigFiles);
4685 }
4686
4687 if (!ChildFormatTextToApply.empty()) {
4688 LLVM_DEBUG(llvm::dbgs()
4689 << "Applying child configurations on fallback style\n");
4690 applyChildFormatTexts(&FallbackStyle);
4691 }
4692
4693 return FallbackStyle;
4694}
4695
4696static bool isClangFormatOnOff(StringRef Comment, bool On) {
4697 if (Comment == (On ? "/* clang-format on */" : "/* clang-format off */"))
4698 return true;
4699
4700 static const char ClangFormatOn[] = "// clang-format on";
4701 static const char ClangFormatOff[] = "// clang-format off";
4702 const unsigned Size = (On ? sizeof ClangFormatOn : sizeof ClangFormatOff) - 1;
4703
4704 return Comment.starts_with(On ? ClangFormatOn : ClangFormatOff) &&
4705 (Comment.size() == Size || Comment[Size] == ':');
4706}
4707
4708bool isClangFormatOn(StringRef Comment) {
4709 return isClangFormatOnOff(Comment, /*On=*/true);
4710}
4711
4712bool isClangFormatOff(StringRef Comment) {
4713 return isClangFormatOnOff(Comment, /*On=*/false);
4714}
4715
4716} // namespace format
4717} // namespace clang
This file declares DefinitionBlockSeparator, a TokenAnalyzer that inserts or removes empty lines sepa...
int8_t BraceCount
Number of optional braces to be inserted after this token: -1: a single left brace 0: no braces >0: n...
FormatToken()
Token Tok
The Token.
FormatToken * Next
The next token in the unwrapped line.
BracketAlignmentStyle
Definition Format.cpp:38
@ BAS_DontAlign
Definition Format.cpp:40
@ BAS_BlockIndent
Definition Format.cpp:42
@ BAS_Align
Definition Format.cpp:39
@ BAS_AlwaysBreak
Definition Format.cpp:41
Various functions to configurably format source code.
StringRef getLanguageName(FormatStyle::LanguageKind Language)
Definition Format.h:6268
bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language, FormatStyle *Style)
Gets a predefined style for the specified language by name.
This file declares IntegerLiteralSeparatorFixer that fixes C++ integer literal separators.
This file declares NamespaceEndCommentsFixer, a TokenAnalyzer that fixes namespace end comments.
This file declares NumericLiteralCaseFixer that standardizes character case within numeric literals.
This file declares ObjCPropertyAttributeOrderFixer, a TokenAnalyzer that adjusts the order of attribu...
This file declares QualifierAlignmentFixer, a TokenAnalyzer that enforces either east or west const d...
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
This file implements a sorter for JavaScript ES6 imports.
Implements a combinatorial exploration of all the different linebreaks unwrapped lines can be formatt...
This file declares UsingDeclarationsSorter, a TokenAnalyzer that sorts consecutive using declarations...
static CharSourceRange getCharRange(SourceRange R)
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens.
Definition Lexer.h:78
bool LexFromRawLexer(Token &Result)
LexFromRawLexer - Lex a token from a designated raw lexer (one with no associated preprocessor object...
Definition Lexer.h:236
void SetCommentRetentionState(bool Mode)
SetCommentRetentionMode - Change the comment retention mode of the lexer to the specified mode.
Definition Lexer.h:269
Token - This structure provides full information about a lexed token.
Definition Token.h:36
SourceManager & getSourceManager() const
static std::unique_ptr< Environment > make(StringRef Code, StringRef FileName, ArrayRef< tooling::Range > Ranges, unsigned FirstStartColumn=0, unsigned NextStartColumn=0, unsigned LastStartColumn=0)
std::pair< tooling::Replacements, unsigned > process(const Environment &Env, const FormatStyle &Style)
static tok::TokenKind getTokenFromQualifier(const std::string &Qualifier)
std::pair< tooling::Replacements, unsigned > process(const Environment &Env, const FormatStyle &Style)
const char * name() const noexcept override
Definition Format.cpp:1561
std::string message(int EV) const override
Definition Format.cpp:1565
std::pair< tooling::Replacements, unsigned > process(bool SkipAnnotation=false)
static bool inputUsesCRLF(StringRef Text, bool DefaultToCRLF)
Infers whether the input is using CRLF.
static const llvm::Regex IncludeRegex
This class manages priorities of C++ include categories and calculates priorities for headers.
int getIncludePriority(StringRef IncludeName, bool CheckMainHeader) const
Returns the priority of the category which IncludeName belongs to.
int getSortIncludePriority(StringRef IncludeName, bool CheckMainHeader) const
A source range independent of the SourceManager.
Definition Replacement.h:44
A text replacement.
Definition Replacement.h:83
unsigned getLength() const
StringRef getReplacementText() const
unsigned getOffset() const
Maintains a set of replacements that are conflict-free.
std::vector< Range > getAffectedRanges() const
const_iterator begin() const
llvm::Error add(const Replacement &R)
Adds a new replacement R to the current set of replacements.
Replacements merge(const Replacements &Replaces) const
Merges Replaces into the current replacements.
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
bool isObjC(ID Id)
isObjC - Is this an "ObjC" input (Obj-C and Obj-C++ sources and headers).
Definition Types.cpp:216
std::pair< tooling::Replacements, unsigned > reformat(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, unsigned FirstStartColumn, unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName, FormattingAttemptStatus *Status)
Reformats the given Ranges in the code fragment Code.
Definition Format.cpp:4064
void addQualifierAlignmentFixerPasses(const FormatStyle &Style, SmallVectorImpl< AnalyzerPass > &Passes)
static void expandPresetsSpaceBeforeParens(FormatStyle &Expanded)
Definition Format.cpp:1687
static bool affectsRange(ArrayRef< tooling::Range > Ranges, unsigned Start, unsigned End)
Definition Format.cpp:3430
const char * getTokenTypeName(TokenType Type)
Determines the name of a token type.
FormatStyle getWebKitStyle()
Definition Format.cpp:2199
bool isLikelyXml(StringRef Code)
Definition Format.cpp:3892
static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName)
Definition Format.cpp:4375
tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName, FormattingAttemptStatus *Status)
Definition Format.cpp:4263
const char * StyleOptionHelpDescription
Definition Format.cpp:4360
tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName)
Definition Format.cpp:4306
static unsigned findJavaImportGroup(const FormatStyle &Style, StringRef ImportIdentifier)
Definition Format.cpp:3731
std::string replaceCRLF(const std::string &Code)
Definition Format.cpp:3471
std::error_code make_error_code(ParseError e)
Definition Format.cpp:1552
const char * DefaultFallbackStyle
Definition Format.cpp:4473
FormatStyle getClangFormatStyle()
Definition Format.cpp:2267
std::function< std::pair< tooling::Replacements, unsigned >(const Environment &)> AnalyzerPass
const char * DefaultFormatStyle
Definition Format.cpp:4471
static void replaceToken(const SourceManager &SourceMgr, tooling::Replacements &Fixes, const CharSourceRange &Range, std::string NewText)
FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language)
Definition Format.cpp:1961
std::string configurationAsText(const FormatStyle &Style)
Definition Format.cpp:2450
FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language)
Definition Format.cpp:2238
const std::error_category & getParseCategory()
Definition Format.cpp:1548
FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code)
Definition Format.cpp:4448
bool isMpegTS(StringRef Code)
Definition Format.cpp:3885
tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName)
Definition Format.cpp:4296
static std::pair< unsigned, unsigned > FindCursorIndex(const ArrayRef< IncludeDirective > &Includes, const ArrayRef< unsigned > &Indices, unsigned Cursor)
Definition Format.cpp:3450
tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName)
Definition Format.cpp:4274
static FormatStyle::LanguageKind getLanguageByComment(const Environment &Env)
Definition Format.cpp:4419
FormatStyle getGNUStyle()
Definition Format.cpp:2223
bool isClangFormatOff(StringRef Comment)
Definition Format.cpp:4712
static bool isClangFormatOnOff(StringRef Comment, bool On)
Definition Format.cpp:4696
tooling::Replacements sortJavaScriptImports(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName)
static void sortJavaImports(const FormatStyle &Style, const ArrayRef< JavaImportDirective > &Imports, ArrayRef< tooling::Range > Ranges, StringRef FileName, StringRef Code, tooling::Replacements &Replaces)
Definition Format.cpp:3751
FormatStyle getMozillaStyle()
Definition Format.cpp:2173
bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language, FormatStyle *Style)
Definition Format.cpp:2289
Expected< tooling::Replacements > cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, const FormatStyle &Style)
Definition Format.cpp:4047
static void expandPresetsBraceWrapping(FormatStyle &Expanded)
Definition Format.cpp:1587
tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName, unsigned *Cursor)
Definition Format.cpp:3894
static void sortCppIncludes(const FormatStyle &Style, const ArrayRef< IncludeDirective > &Includes, ArrayRef< tooling::Range > Ranges, StringRef FileName, StringRef Code, tooling::Replacements &Replaces, unsigned *Cursor)
Definition Format.cpp:3499
bool isClangFormatOn(StringRef Comment)
Definition Format.cpp:4708
FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language)
Definition Format.cpp:1719
Expected< FormatStyle > getStyle(StringRef StyleName, StringRef FileName, StringRef FallbackStyleName, StringRef Code, llvm::vfs::FileSystem *FS, bool AllowUnknownOptions, llvm::SourceMgr::DiagHandlerTy DiagHandler)
Definition Format.cpp:4492
llvm::Error make_string_error(const Twine &Message)
Definition Format.cpp:1556
ParseError validateQualifierOrder(FormatStyle *Style)
Definition Format.cpp:2322
FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language)
Definition Format.cpp:2114
static void expandPresetsSpacesInParens(FormatStyle &Expanded)
Definition Format.cpp:1711
std::error_code parseConfiguration(llvm::MemoryBufferRef Config, FormatStyle *Style, bool AllowUnknownOptions, llvm::SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt, bool IsDotHFile)
Definition Format.cpp:2354
Expected< tooling::Replacements > formatReplacements(StringRef Code, const tooling::Replacements &Replaces, const FormatStyle &Style)
Definition Format.cpp:3935
FormatStyle getNoStyle()
Definition Format.cpp:2281
LangOptions getFormattingLangOpts(const FormatStyle &Style)
Definition Format.cpp:4316
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS, FormatStyle *Style, bool AllowUnknownOptions, llvm::SourceMgr::DiagHandlerTy DiagHandler, bool IsDotHFile)
Definition Format.cpp:4476
static Expected< tooling::Replacements > processReplacements(T ProcessFunc, StringRef Code, const tooling::Replacements &Replaces, const FormatStyle &Style)
Definition Format.cpp:3916
const char * getTokenName(TokenKind Kind) LLVM_READNONE
Determines the name of a token as used within the front end.
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
Definition TokenKinds.h:25
const char * getPunctuatorSpelling(TokenKind Kind) LLVM_READNONE
Determines the spelling of simple punctuation tokens like '!
std::vector< Range > calculateRangesAfterReplacements(const Replacements &Replaces, const std::vector< Range > &Ranges)
Calculates the new ranges after Replaces are applied.
The JSON file list parser is used to communicate input to InstallAPI.
std::vector< std::string > JavaImportGroups
A vector of prefixes ordered by the desired groups for Java imports.
Definition Format.h:3552
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
Language
The language for the input, used to select and validate the language standard and possible actions.
@ Result
The result type of a method or function.
Definition TypeBase.h:905
SortIncludesOptions SortIncludes
Controls if and how clang-format will sort #includes.
Definition Format.h:4824
@ LK_None
Do not use.
Definition Format.h:3692
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
int const char * function
Definition c++config.h:31
#define false
Definition stdbool.h:26
Represents the status of a formatting attempt.
Definition Format.h:6138
std::optional< FormatStyle > Get(LanguageKind Language) const
A wrapper around a Token storing information about the whitespace characters preceding it.
bool isNot(T Kind) const
unsigned NewlinesBefore
The number of newlines immediately before the Token.
SourceRange WhitespaceRange
The range of the whitespace immediately preceding the Token.
@ IBS_Preserve
Sort each #include block separately.
@ IBS_Regroup
Merge multiple #include blocks together and sort as one. Then split into groups based on category pri...
@ IBS_Merge
Merge multiple #include blocks together and sort as one.
static FormatStyle & element(IO &IO, std::vector< FormatStyle > &Seq, size_t Index)
Definition Format.cpp:1512
static size_t size(IO &IO, std::vector< FormatStyle > &Seq)
Definition Format.cpp:1509
static void mapping(IO &IO, FormatStyle &Style)
Definition Format.cpp:1000
static void enumInput(IO &IO, FormatStyle::AlignConsecutiveStyle &Value)
Definition Format.cpp:58
static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &Value)
Definition Format.cpp:95
static void mapping(IO &IO, FormatStyle::BinaryOperationBreakRule &Value)
Definition Format.cpp:306
static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping)
Definition Format.cpp:195
static void mapping(IO &IO, FormatStyle::BreakBinaryOperationsOptions &Value)
Definition Format.cpp:330
static void enumInput(IO &IO, FormatStyle::BreakBinaryOperationsOptions &Value)
Definition Format.cpp:317
static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &Base)
Definition Format.cpp:466
static void mapping(IO &IO, FormatStyle::KeepEmptyLinesStyle &Value)
Definition Format.cpp:493
static void mapping(IO &IO, FormatStyle::NumericLiteralCaseStyle &Value)
Definition Format.cpp:574
static void mapping(IO &IO, FormatStyle::RawStringFormat &Format)
Definition Format.cpp:640
static void mapping(IO &IO, FormatStyle::ShortCaseStatementsAlignmentStyle &Value)
Definition Format.cpp:109
static void mapping(IO &IO, FormatStyle::SortIncludesOptions &Value)
Definition Format.cpp:791
static void enumInput(IO &IO, FormatStyle::SortIncludesOptions &Value)
Definition Format.cpp:772
static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing)
Definition Format.cpp:834
static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space)
Definition Format.cpp:896
static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces)
Definition Format.cpp:909
static void mapping(IO &IO, FormatStyle::TrailingCommentsAlignmentStyle &Value)
Definition Format.cpp:966
static void enumInput(IO &IO, FormatStyle::TrailingCommentsAlignmentStyle &Value)
Definition Format.cpp:943
static void enumeration(IO &IO, BracketAlignmentStyle &Value)
Definition Format.cpp:218
static void enumeration(IO &IO, FormatStyle::ArrayInitializerAlignmentStyle &Value)
Definition Format.cpp:130
static void enumeration(IO &IO, FormatStyle::AttributeBreakingStyle &Value)
Definition Format.cpp:121
static void enumeration(IO &IO, FormatStyle::BinPackParametersStyle &Value)
Definition Format.cpp:150
static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value)
Definition Format.cpp:162
static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value)
Definition Format.cpp:139
static void enumeration(IO &IO, FormatStyle::BitFieldColonSpacingStyle &Value)
Definition Format.cpp:171
static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value)
Definition Format.cpp:181
static void enumeration(IO &IO, FormatStyle::BraceWrappingAfterControlStatementStyle &Value)
Definition Format.cpp:234
static void enumeration(IO &IO, FormatStyle::BracedListStyle &Value)
Definition Format.cpp:375
static void enumeration(IO &IO, FormatStyle::BreakBeforeConceptDeclarationsStyle &Value)
Definition Format.cpp:250
static void enumeration(IO &IO, FormatStyle::BreakBeforeInlineASMColonStyle &Value)
Definition Format.cpp:263
static void enumeration(IO &IO, FormatStyle::BreakBeforeNoexceptSpecifierStyle &Value)
Definition Format.cpp:50
static void enumeration(IO &IO, FormatStyle::BreakBinaryOperationsStyle &Value)
Definition Format.cpp:273
static void enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value)
Definition Format.cpp:340
static void enumeration(IO &IO, FormatStyle::BreakInheritanceListStyle &Value)
Definition Format.cpp:350
static void enumeration(IO &IO, FormatStyle::BreakTemplateDeclarationsStyle &Value)
Definition Format.cpp:361
static void enumeration(IO &IO, FormatStyle::DAGArgStyle &Value)
Definition Format.cpp:387
static void enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value)
Definition Format.cpp:397
static void enumeration(IO &IO, FormatStyle::EmptyLineAfterAccessModifierStyle &Value)
Definition Format.cpp:426
static void enumeration(IO &IO, FormatStyle::EmptyLineBeforeAccessModifierStyle &Value)
Definition Format.cpp:437
static void enumeration(IO &IO, FormatStyle::EnumTrailingCommaStyle &Value)
Definition Format.cpp:447
static void enumeration(IO &IO, FormatStyle::EscapedNewlineAlignmentStyle &Value)
Definition Format.cpp:410
static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value)
Definition Format.cpp:456
static void enumeration(IO &IO, FormatStyle::IndentGotoLabelStyle &Value)
Definition Format.cpp:1530
static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value)
Definition Format.cpp:485
static void enumeration(IO &IO, FormatStyle::LambdaBodyIndentationKind &Value)
Definition Format.cpp:537
static void enumeration(IO &IO, FormatStyle::LanguageKind &Value)
Definition Format.cpp:501
static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value)
Definition Format.cpp:517
static void enumeration(IO &IO, FormatStyle::LineEndingStyle &Value)
Definition Format.cpp:545
static void enumeration(IO &IO, FormatStyle::NamespaceIndentationKind &Value)
Definition Format.cpp:555
static void enumeration(IO &IO, FormatStyle::NumericLiteralComponentStyle &Value)
Definition Format.cpp:565
static void enumeration(IO &IO, FormatStyle::OperandAlignmentStyle &Value)
Definition Format.cpp:583
static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value)
Definition Format.cpp:621
static void enumeration(IO &IO, FormatStyle::PackConstructorInitializersStyle &Value)
Definition Format.cpp:598
static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value)
Definition Format.cpp:608
static void enumeration(IO &IO, FormatStyle::QualifierAlignmentStyle &Value)
Definition Format.cpp:631
static void enumeration(IO &IO, FormatStyle::ReferenceAlignmentStyle &Value)
Definition Format.cpp:662
static void enumeration(IO &IO, FormatStyle::ReflowCommentsStyle &Value)
Definition Format.cpp:650
static void enumeration(IO &IO, FormatStyle::RemoveParenthesesStyle &Value)
Definition Format.cpp:672
static void enumeration(IO &IO, FormatStyle::RequiresClausePositionStyle &Value)
Definition Format.cpp:682
static void enumeration(IO &IO, FormatStyle::RequiresExpressionIndentationKind &Value)
Definition Format.cpp:695
static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value)
Definition Format.cpp:703
static void enumeration(IO &IO, FormatStyle::SeparateDefinitionStyle &Value)
Definition Format.cpp:717
static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value)
Definition Format.cpp:725
static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value)
Definition Format.cpp:735
static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value)
Definition Format.cpp:747
static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value)
Definition Format.cpp:761
static void enumeration(IO &IO, FormatStyle::SortJavaStaticImportOptions &Value)
Definition Format.cpp:800
static void enumeration(IO &IO, FormatStyle::SortUsingDeclarationsOptions &Value)
Definition Format.cpp:809
static void enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value)
Definition Format.cpp:825
static void enumeration(IO &IO, FormatStyle::SpaceBeforeParensStyle &Value)
Definition Format.cpp:855
static void enumeration(IO &IO, FormatStyle::SpaceInEmptyBracesStyle &Value)
Definition Format.cpp:876
static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value)
Definition Format.cpp:884
static void enumeration(IO &IO, FormatStyle::SpacesInParensStyle &Value)
Definition Format.cpp:919
static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value)
Definition Format.cpp:926
static void enumeration(IO &IO, FormatStyle::TrailingCommentsAlignmentKinds &Value)
Definition Format.cpp:934
static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value)
Definition Format.cpp:975
static void enumeration(IO &IO, FormatStyle::WrapNamespaceBodyWithEmptyLinesStyle &Value)
Definition Format.cpp:991
static StringRef input(StringRef Scalar, void *, clang::tok::TokenKind &Value)
Definition Format.cpp:290
static QuotingType mustQuote(StringRef)
Definition Format.cpp:302
static void output(const clang::tok::TokenKind &Value, void *, llvm::raw_ostream &Out)
Definition Format.cpp:282