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