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