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