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("SpaceBeforeInheritanceColon",
1402 Style.SpaceBeforeInheritanceColon);
1403 IO.mapOptional("SpaceBeforeJsonColon", Style.SpaceBeforeJsonColon);
1404 IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
1405 IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions);
1406 IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
1407 Style.SpaceBeforeRangeBasedForLoopColon);
1408 IO.mapOptional("SpaceBeforeSquareBrackets",
1409 Style.SpaceBeforeSquareBrackets);
1410 IO.mapOptional("SpaceInEmptyBraces", Style.SpaceInEmptyBraces);
1411 IO.mapOptional("SpacesBeforeTrailingComments",
1412 Style.SpacesBeforeTrailingComments);
1413 IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
1414 IO.mapOptional("SpacesInContainerLiterals",
1415 Style.SpacesInContainerLiterals);
1416 IO.mapOptional("SpacesInLineCommentPrefix",
1417 Style.SpacesInLineCommentPrefix);
1418 IO.mapOptional("SpacesInParens", Style.SpacesInParens);
1419 IO.mapOptional("SpacesInParensOptions", Style.SpacesInParensOptions);
1420 IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
1421 IO.mapOptional("Standard", Style.Standard);
1422 IO.mapOptional("StatementAttributeLikeMacros",
1423 Style.StatementAttributeLikeMacros);
1424 IO.mapOptional("StatementMacros", Style.StatementMacros);
1425 IO.mapOptional("TableGenBreakingDAGArgOperators",
1426 Style.TableGenBreakingDAGArgOperators);
1427 IO.mapOptional("TableGenBreakInsideDAGArg",
1428 Style.TableGenBreakInsideDAGArg);
1429 IO.mapOptional("TabWidth", Style.TabWidth);
1430 IO.mapOptional("TemplateNames", Style.TemplateNames);
1431 IO.mapOptional("TypeNames", Style.TypeNames);
1432 IO.mapOptional("TypenameMacros", Style.TypenameMacros);
1433 IO.mapOptional("UseTab", Style.UseTab);
1434 IO.mapOptional("VariableTemplates", Style.VariableTemplates);
1435 IO.mapOptional("VerilogBreakBetweenInstancePorts",
1436 Style.VerilogBreakBetweenInstancePorts);
1437 IO.mapOptional("WhitespaceSensitiveMacros",
1438 Style.WhitespaceSensitiveMacros);
1439 IO.mapOptional("WrapNamespaceBodyWithEmptyLines",
1440 Style.WrapNamespaceBodyWithEmptyLines);
1441
1442 // If AlwaysBreakAfterDefinitionReturnType was specified but
1443 // BreakAfterReturnType was not, initialize the latter from the former for
1444 // backwards compatibility.
1445 if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&
1446 Style.BreakAfterReturnType == FormatStyle::RTBS_None) {
1447 if (Style.AlwaysBreakAfterDefinitionReturnType ==
1448 FormatStyle::DRTBS_All) {
1449 Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
1450 } else if (Style.AlwaysBreakAfterDefinitionReturnType ==
1451 FormatStyle::DRTBS_TopLevel) {
1452 Style.BreakAfterReturnType = FormatStyle::RTBS_TopLevelDefinitions;
1453 }
1454 }
1455
1456 // If BreakBeforeInheritanceComma was specified but BreakInheritance was
1457 // not, initialize the latter from the former for backwards compatibility.
1458 if (BreakBeforeInheritanceComma &&
1459 Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) {
1460 Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
1461 }
1462
1463 // If BreakConstructorInitializersBeforeComma was specified but
1464 // BreakConstructorInitializers was not, initialize the latter from the
1465 // former for backwards compatibility.
1466 if (BreakConstructorInitializersBeforeComma &&
1467 Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon) {
1468 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
1469 }
1470
1471 if (!IsGoogleOrChromium) {
1472 if (Style.PackConstructorInitializers == FormatStyle::PCIS_BinPack &&
1473 OnCurrentLine) {
1474 Style.PackConstructorInitializers = OnNextLine
1475 ? FormatStyle::PCIS_NextLine
1476 : FormatStyle::PCIS_CurrentLine;
1477 }
1478 } else if (Style.PackConstructorInitializers ==
1479 FormatStyle::PCIS_NextLine) {
1480 if (!OnCurrentLine)
1481 Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
1482 else if (!OnNextLine)
1483 Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine;
1484 }
1485
1486 if (Style.LineEnding == FormatStyle::LE_DeriveLF) {
1487 if (!DeriveLineEnding)
1488 Style.LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF;
1489 else if (UseCRLF)
1490 Style.LineEnding = FormatStyle::LE_DeriveCRLF;
1491 }
1492
1493 // If SpaceInEmptyBlock was specified but SpaceInEmptyBraces was not,
1494 // initialize the latter from the former for backward compatibility.
1495 if (SpaceInEmptyBlock &&
1496 Style.SpaceInEmptyBraces == FormatStyle::SIEB_Never) {
1497 Style.SpaceInEmptyBraces = FormatStyle::SIEB_Block;
1498 }
1499
1500 if (Style.SpacesInParens != FormatStyle::SIPO_Custom &&
1501 (SpacesInParentheses || SpaceInEmptyParentheses ||
1502 SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) {
1503 if (SpacesInParentheses) {
1504 // For backward compatibility.
1505 Style.SpacesInParensOptions.ExceptDoubleParentheses = false;
1506 Style.SpacesInParensOptions.InConditionalStatements = true;
1507 Style.SpacesInParensOptions.InCStyleCasts =
1508 SpacesInCStyleCastParentheses;
1509 Style.SpacesInParensOptions.InEmptyParentheses =
1510 SpaceInEmptyParentheses;
1511 Style.SpacesInParensOptions.Other = true;
1512 } else {
1513 Style.SpacesInParensOptions = {};
1514 Style.SpacesInParensOptions.InConditionalStatements =
1515 SpacesInConditionalStatement;
1516 Style.SpacesInParensOptions.InCStyleCasts =
1517 SpacesInCStyleCastParentheses;
1518 Style.SpacesInParensOptions.InEmptyParentheses =
1519 SpaceInEmptyParentheses;
1520 }
1521 Style.SpacesInParens = FormatStyle::SIPO_Custom;
1522 }
1523 }
1524};
1525
1526// Allows to read vector<FormatStyle> while keeping default values.
1527// IO.getContext() should contain a pointer to the FormatStyle structure, that
1528// will be used to get default values for missing keys.
1529// If the first element has no Language specified, it will be treated as the
1530// default one for the following elements.
1531template <> struct DocumentListTraits<std::vector<FormatStyle>> {
1532 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
1533 return Seq.size();
1534 }
1535 static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq,
1536 size_t Index) {
1537 if (Index >= Seq.size()) {
1538 assert(Index == Seq.size());
1539 FormatStyle Template;
1540 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
1541 Template = Seq[0];
1542 } else {
1543 Template = *((const FormatStyle *)IO.getContext());
1544 Template.Language = FormatStyle::LK_None;
1545 }
1546 Seq.resize(Index + 1, Template);
1547 }
1548 return Seq[Index];
1549 }
1550};
1551
1552template <> struct ScalarEnumerationTraits<FormatStyle::IndentGotoLabelStyle> {
1553 static void enumeration(IO &IO, FormatStyle::IndentGotoLabelStyle &Value) {
1554 IO.enumCase(Value, "NoIndent", FormatStyle::IGLS_NoIndent);
1555 IO.enumCase(Value, "OuterIndent", FormatStyle::IGLS_OuterIndent);
1556 IO.enumCase(Value, "InnerIndent", FormatStyle::IGLS_InnerIndent);
1557 IO.enumCase(Value, "HalfIndent", FormatStyle::IGLS_HalfIndent);
1558
1559 // For backward compatibility.
1560 IO.enumCase(Value, "false", FormatStyle::IGLS_NoIndent);
1561 IO.enumCase(Value, "true", FormatStyle::IGLS_OuterIndent);
1562 }
1563};
1564
1565} // namespace yaml
1566} // namespace llvm
1567
1568namespace clang {
1569namespace format {
1570
1571const std::error_category &getParseCategory() {
1572 static const ParseErrorCategory C{};
1573 return C;
1574}
1575std::error_code make_error_code(ParseError e) {
1576 return std::error_code(static_cast<int>(e), getParseCategory());
1577}
1578
1579inline llvm::Error make_string_error(const Twine &Message) {
1580 return llvm::make_error<llvm::StringError>(Message,
1581 llvm::inconvertibleErrorCode());
1582}
1583
1584const char *ParseErrorCategory::name() const noexcept {
1585 return "clang-format.parse_error";
1586}
1587
1588std::string ParseErrorCategory::message(int EV) const {
1589 switch (static_cast<ParseError>(EV)) {
1591 return "Success";
1592 case ParseError::Error:
1593 return "Invalid argument";
1595 return "Unsuitable";
1597 return "trailing comma insertion cannot be used with bin packing";
1599 return "Invalid qualifier specified in QualifierOrder";
1601 return "Duplicate qualifier specified in QualifierOrder";
1603 return "Missing type in QualifierOrder";
1605 return "Missing QualifierOrder";
1606 }
1607 llvm_unreachable("unexpected parse error");
1608}
1609
1610static void expandPresetsBraceWrapping(FormatStyle &Expanded) {
1611 if (Expanded.BreakBeforeBraces == FormatStyle::BS_Custom)
1612 return;
1613 Expanded.BraceWrapping = {/*AfterCaseLabel=*/false,
1614 /*AfterClass=*/false,
1615 /*AfterControlStatement=*/FormatStyle::BWACS_Never,
1616 /*AfterEnum=*/false,
1617 /*AfterFunction=*/false,
1618 /*AfterNamespace=*/false,
1619 /*AfterObjCDeclaration=*/false,
1620 /*AfterStruct=*/false,
1621 /*AfterUnion=*/false,
1622 /*AfterExternBlock=*/false,
1623 /*BeforeCatch=*/false,
1624 /*BeforeElse=*/false,
1625 /*BeforeLambdaBody=*/false,
1626 /*BeforeWhile=*/false,
1627 /*IndentBraces=*/false,
1628 /*SplitEmptyFunction=*/true,
1629 /*SplitEmptyRecord=*/true,
1630 /*SplitEmptyNamespace=*/true};
1631 switch (Expanded.BreakBeforeBraces) {
1632 case FormatStyle::BS_Linux:
1633 Expanded.BraceWrapping.AfterClass = true;
1634 Expanded.BraceWrapping.AfterFunction = true;
1635 Expanded.BraceWrapping.AfterNamespace = true;
1636 break;
1637 case FormatStyle::BS_Mozilla:
1638 Expanded.BraceWrapping.AfterClass = true;
1639 Expanded.BraceWrapping.AfterEnum = true;
1640 Expanded.BraceWrapping.AfterFunction = true;
1641 Expanded.BraceWrapping.AfterStruct = true;
1642 Expanded.BraceWrapping.AfterUnion = true;
1643 Expanded.BraceWrapping.AfterExternBlock = true;
1644 Expanded.BraceWrapping.SplitEmptyFunction = true;
1645 Expanded.BraceWrapping.SplitEmptyRecord = false;
1646 break;
1647 case FormatStyle::BS_Stroustrup:
1648 Expanded.BraceWrapping.AfterFunction = true;
1649 Expanded.BraceWrapping.BeforeCatch = true;
1650 Expanded.BraceWrapping.BeforeElse = true;
1651 break;
1652 case FormatStyle::BS_Allman:
1653 Expanded.BraceWrapping.AfterCaseLabel = true;
1654 Expanded.BraceWrapping.AfterClass = true;
1655 Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
1656 Expanded.BraceWrapping.AfterEnum = true;
1657 Expanded.BraceWrapping.AfterFunction = true;
1658 Expanded.BraceWrapping.AfterNamespace = true;
1659 Expanded.BraceWrapping.AfterObjCDeclaration = true;
1660 Expanded.BraceWrapping.AfterStruct = true;
1661 Expanded.BraceWrapping.AfterUnion = true;
1662 Expanded.BraceWrapping.AfterExternBlock = true;
1663 Expanded.BraceWrapping.BeforeCatch = true;
1664 Expanded.BraceWrapping.BeforeElse = true;
1665 Expanded.BraceWrapping.BeforeLambdaBody = true;
1666 break;
1667 case FormatStyle::BS_Whitesmiths:
1668 Expanded.BraceWrapping.AfterCaseLabel = true;
1669 Expanded.BraceWrapping.AfterClass = true;
1670 Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
1671 Expanded.BraceWrapping.AfterEnum = true;
1672 Expanded.BraceWrapping.AfterFunction = true;
1673 Expanded.BraceWrapping.AfterNamespace = true;
1674 Expanded.BraceWrapping.AfterObjCDeclaration = true;
1675 Expanded.BraceWrapping.AfterStruct = true;
1676 Expanded.BraceWrapping.AfterExternBlock = true;
1677 Expanded.BraceWrapping.BeforeCatch = true;
1678 Expanded.BraceWrapping.BeforeElse = true;
1679 Expanded.BraceWrapping.BeforeLambdaBody = true;
1680 break;
1681 case FormatStyle::BS_GNU:
1682 Expanded.BraceWrapping = {
1683 /*AfterCaseLabel=*/true,
1684 /*AfterClass=*/true,
1685 /*AfterControlStatement=*/FormatStyle::BWACS_Always,
1686 /*AfterEnum=*/true,
1687 /*AfterFunction=*/true,
1688 /*AfterNamespace=*/true,
1689 /*AfterObjCDeclaration=*/true,
1690 /*AfterStruct=*/true,
1691 /*AfterUnion=*/true,
1692 /*AfterExternBlock=*/true,
1693 /*BeforeCatch=*/true,
1694 /*BeforeElse=*/true,
1695 /*BeforeLambdaBody=*/true,
1696 /*BeforeWhile=*/true,
1697 /*IndentBraces=*/true,
1698 /*SplitEmptyFunction=*/true,
1699 /*SplitEmptyRecord=*/true,
1700 /*SplitEmptyNamespace=*/true};
1701 break;
1702 case FormatStyle::BS_WebKit:
1703 Expanded.BraceWrapping.AfterFunction = true;
1704 break;
1705 default:
1706 break;
1707 }
1708}
1709
1710static void expandPresetsSpaceBeforeParens(FormatStyle &Expanded) {
1711 if (Expanded.SpaceBeforeParens == FormatStyle::SBPO_Custom)
1712 return;
1713 // Reset all flags
1714 Expanded.SpaceBeforeParensOptions = {};
1715 Expanded.SpaceBeforeParensOptions.AfterPlacementOperator = true;
1716
1717 switch (Expanded.SpaceBeforeParens) {
1718 case FormatStyle::SBPO_ControlStatements:
1719 Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;
1720 Expanded.SpaceBeforeParensOptions.AfterForeachMacros = true;
1721 Expanded.SpaceBeforeParensOptions.AfterIfMacros = true;
1722 break;
1723 case FormatStyle::SBPO_ControlStatementsExceptControlMacros:
1724 Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;
1725 break;
1726 case FormatStyle::SBPO_NonEmptyParentheses:
1727 Expanded.SpaceBeforeParensOptions.BeforeNonEmptyParentheses = true;
1728 break;
1729 default:
1730 break;
1731 }
1732}
1733
1734static void expandPresetsSpacesInParens(FormatStyle &Expanded) {
1735 if (Expanded.SpacesInParens == FormatStyle::SIPO_Custom)
1736 return;
1737 assert(Expanded.SpacesInParens == FormatStyle::SIPO_Never);
1738 // Reset all flags
1739 Expanded.SpacesInParensOptions = {};
1740}
1741
1742FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
1743 FormatStyle LLVMStyle;
1744 LLVMStyle.AccessModifierOffset = -2;
1745 LLVMStyle.AlignAfterOpenBracket = true;
1746 LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;
1747 LLVMStyle.AlignConsecutiveAssignments = {};
1748 LLVMStyle.AlignConsecutiveAssignments.PadOperators = true;
1749 LLVMStyle.AlignConsecutiveBitFields = {};
1750 LLVMStyle.AlignConsecutiveDeclarations = {};
1751 LLVMStyle.AlignConsecutiveDeclarations.AlignFunctionDeclarations = true;
1752 LLVMStyle.AlignConsecutiveMacros = {};
1753 LLVMStyle.AlignConsecutiveShortCaseStatements = {};
1754 LLVMStyle.AlignConsecutiveTableGenBreakingDAGArgColons = {};
1755 LLVMStyle.AlignConsecutiveTableGenCondOperatorColons = {};
1756 LLVMStyle.AlignConsecutiveTableGenDefinitionColons = {};
1757 LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
1758 LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
1759 LLVMStyle.AlignTrailingComments = {};
1760 LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always;
1761 LLVMStyle.AlignTrailingComments.OverEmptyLines = 0;
1762 LLVMStyle.AlignTrailingComments.AlignPPAndNotPP = true;
1763 LLVMStyle.AllowAllArgumentsOnNextLine = true;
1764 LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
1765 LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;
1766 LLVMStyle.AllowBreakBeforeQtProperty = false;
1767 LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
1768 LLVMStyle.AllowShortCaseExpressionOnASingleLine = true;
1769 LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
1770 LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true;
1771 LLVMStyle.AllowShortEnumsOnASingleLine = true;
1772 LLVMStyle.AllowShortFunctionsOnASingleLine =
1773 FormatStyle::ShortFunctionStyle::setAll();
1774 LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
1775 LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
1776 LLVMStyle.AllowShortLoopsOnASingleLine = false;
1777 LLVMStyle.AllowShortNamespacesOnASingleLine = false;
1778 LLVMStyle.AllowShortRecordOnASingleLine = FormatStyle::SRS_EmptyAndAttached;
1779 LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
1780 LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
1781 LLVMStyle.AttributeMacros.push_back("__capability");
1782 LLVMStyle.BinPackArguments = true;
1783 LLVMStyle.BinPackLongBracedList = true;
1784 LLVMStyle.BinPackParameters = FormatStyle::BPPS_BinPack;
1785 LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;
1786 LLVMStyle.BracedInitializerIndentWidth = -1;
1787 LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false,
1788 /*AfterClass=*/false,
1789 /*AfterControlStatement=*/FormatStyle::BWACS_Never,
1790 /*AfterEnum=*/false,
1791 /*AfterFunction=*/false,
1792 /*AfterNamespace=*/false,
1793 /*AfterObjCDeclaration=*/false,
1794 /*AfterStruct=*/false,
1795 /*AfterUnion=*/false,
1796 /*AfterExternBlock=*/false,
1797 /*BeforeCatch=*/false,
1798 /*BeforeElse=*/false,
1799 /*BeforeLambdaBody=*/false,
1800 /*BeforeWhile=*/false,
1801 /*IndentBraces=*/false,
1802 /*SplitEmptyFunction=*/true,
1803 /*SplitEmptyRecord=*/true,
1804 /*SplitEmptyNamespace=*/true};
1805 LLVMStyle.BreakAdjacentStringLiterals = true;
1806 LLVMStyle.BreakAfterAttributes = FormatStyle::ABS_Leave;
1807 LLVMStyle.BreakAfterJavaFieldAnnotations = false;
1808 LLVMStyle.BreakAfterOpenBracketBracedList = false;
1809 LLVMStyle.BreakAfterOpenBracketFunction = false;
1810 LLVMStyle.BreakAfterOpenBracketIf = false;
1811 LLVMStyle.BreakAfterOpenBracketLoop = false;
1812 LLVMStyle.BreakAfterOpenBracketSwitch = false;
1813 LLVMStyle.BreakAfterReturnType = FormatStyle::RTBS_None;
1814 LLVMStyle.BreakArrays = true;
1815 LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
1816 LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
1817 LLVMStyle.BreakBeforeCloseBracketBracedList = false;
1818 LLVMStyle.BreakBeforeCloseBracketFunction = false;
1819 LLVMStyle.BreakBeforeCloseBracketIf = false;
1820 LLVMStyle.BreakBeforeCloseBracketLoop = false;
1821 LLVMStyle.BreakBeforeCloseBracketSwitch = false;
1822 LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always;
1823 LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline;
1824 LLVMStyle.BreakBeforeTemplateCloser = false;
1825 LLVMStyle.BreakBeforeTernaryOperators = true;
1826 LLVMStyle.BreakBinaryOperations = {FormatStyle::BBO_Never, {}};
1827 LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
1828 LLVMStyle.BreakFunctionDefinitionParameters = false;
1829 LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
1830 LLVMStyle.BreakStringLiterals = true;
1831 LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
1832 LLVMStyle.ColumnLimit = 80;
1833 LLVMStyle.CommentPragmas = "^ IWYU pragma:";
1834 LLVMStyle.CompactNamespaces = false;
1835 LLVMStyle.ConstructorInitializerIndentWidth = 4;
1836 LLVMStyle.ContinuationIndentWidth = 4;
1837 LLVMStyle.Cpp11BracedListStyle = FormatStyle::BLS_AlignFirstComment;
1838 LLVMStyle.DerivePointerAlignment = false;
1839 LLVMStyle.DisableFormat = false;
1840 LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never;
1841 LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock;
1842 LLVMStyle.EnumTrailingComma = FormatStyle::ETC_Leave;
1843 LLVMStyle.ExperimentalAutoDetectBinPacking = false;
1844 LLVMStyle.FixNamespaceComments = true;
1845 LLVMStyle.ForEachMacros.push_back("foreach");
1846 LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
1847 LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
1848 LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE");
1849 LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
1850 LLVMStyle.IncludeStyle.IncludeCategories = {
1851 {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false},
1852 {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},
1853 {".*", 1, 0, false}};
1854 LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
1855 LLVMStyle.IncludeStyle.MainIncludeChar = tooling::IncludeStyle::MICD_Quote;
1856 LLVMStyle.IndentAccessModifiers = false;
1857 LLVMStyle.IndentCaseBlocks = false;
1858 LLVMStyle.IndentCaseLabels = false;
1859 LLVMStyle.IndentExportBlock = true;
1860 LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
1861 LLVMStyle.IndentGotoLabels = FormatStyle::IGLS_OuterIndent;
1862 LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
1863 LLVMStyle.IndentRequiresClause = true;
1864 LLVMStyle.IndentWidth = 2;
1865 LLVMStyle.IndentWrappedFunctionNames = false;
1866 LLVMStyle.InsertBraces = false;
1867 LLVMStyle.InsertNewlineAtEOF = false;
1868 LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
1869 LLVMStyle.IntegerLiteralSeparator = {};
1870 LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
1871 LLVMStyle.JavaScriptWrapImports = true;
1872 LLVMStyle.KeepEmptyLines = {
1873 /*AtEndOfFile=*/false,
1874 /*AtStartOfBlock=*/true,
1875 /*AtStartOfFile=*/true,
1876 };
1877 LLVMStyle.KeepFormFeed = false;
1878 LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature;
1879 LLVMStyle.Language = Language;
1880 LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF;
1881 LLVMStyle.MaxEmptyLinesToKeep = 1;
1882 LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
1883 LLVMStyle.NumericLiteralCase = {/*ExponentLetter=*/FormatStyle::NLCS_Leave,
1884 /*HexDigit=*/FormatStyle::NLCS_Leave,
1885 /*Prefix=*/FormatStyle::NLCS_Leave,
1886 /*Suffix=*/FormatStyle::NLCS_Leave};
1887 LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto;
1888 LLVMStyle.ObjCBlockIndentWidth = 2;
1889 LLVMStyle.ObjCBreakBeforeNestedBlockParam = true;
1890 LLVMStyle.ObjCSpaceAfterMethodDeclarationPrefix = true;
1891 LLVMStyle.ObjCSpaceAfterProperty = false;
1892 LLVMStyle.ObjCSpaceBeforeProtocolList = true;
1893 LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
1894 LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
1895 LLVMStyle.PPIndentWidth = -1;
1896 LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
1897 LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer;
1898 LLVMStyle.ReflowComments = FormatStyle::RCS_Always;
1899 LLVMStyle.RemoveBracesLLVM = false;
1900 LLVMStyle.RemoveEmptyLinesInUnwrappedLines = false;
1901 LLVMStyle.RemoveParentheses = FormatStyle::RPS_Leave;
1902 LLVMStyle.RemoveSemicolon = false;
1903 LLVMStyle.RequiresClausePosition = FormatStyle::RCPS_OwnLine;
1904 LLVMStyle.RequiresExpressionIndentation = FormatStyle::REI_OuterScope;
1905 LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
1906 LLVMStyle.ShortNamespaceLines = 1;
1907 LLVMStyle.SkipMacroDefinitionBody = false;
1908 LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false,
1909 /*IgnoreExtension=*/false};
1910 LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
1911 LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;
1912 LLVMStyle.SpaceAfterCStyleCast = false;
1913 LLVMStyle.SpaceAfterLogicalNot = false;
1914 LLVMStyle.SpaceAfterOperatorKeyword = false;
1915 LLVMStyle.SpaceAfterTemplateKeyword = true;
1916 LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
1917 LLVMStyle.SpaceBeforeAssignmentOperators = true;
1918 LLVMStyle.SpaceBeforeCaseColon = false;
1919 LLVMStyle.SpaceBeforeCpp11BracedList = false;
1920 LLVMStyle.SpaceBeforeCtorInitializerColon = true;
1921 LLVMStyle.SpaceBeforeInheritanceColon = true;
1922 LLVMStyle.SpaceBeforeJsonColon = false;
1923 LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
1924 LLVMStyle.SpaceBeforeParensOptions = {};
1925 LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true;
1926 LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true;
1927 LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true;
1928 LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
1929 LLVMStyle.SpaceBeforeSquareBrackets = false;
1930 LLVMStyle.SpaceInEmptyBraces = FormatStyle::SIEB_Never;
1931 LLVMStyle.SpacesBeforeTrailingComments = 1;
1932 LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never;
1933 LLVMStyle.SpacesInContainerLiterals = true;
1934 LLVMStyle.SpacesInLineCommentPrefix = {
1935 /*Minimum=*/1, /*Maximum=*/std::numeric_limits<unsigned>::max()};
1936 LLVMStyle.SpacesInParens = FormatStyle::SIPO_Never;
1937 LLVMStyle.SpacesInSquareBrackets = false;
1938 LLVMStyle.Standard = FormatStyle::LS_Latest;
1939 LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");
1940 LLVMStyle.StatementMacros.push_back("Q_UNUSED");
1941 LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");
1942 LLVMStyle.TableGenBreakingDAGArgOperators = {};
1943 LLVMStyle.TableGenBreakInsideDAGArg = FormatStyle::DAS_DontBreak;
1944 LLVMStyle.TabWidth = 8;
1945 LLVMStyle.UseTab = FormatStyle::UT_Never;
1946 LLVMStyle.VerilogBreakBetweenInstancePorts = true;
1947 LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE");
1948 LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME");
1949 LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME");
1950 LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE");
1951 LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE");
1952 LLVMStyle.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Leave;
1953
1954 LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
1955 LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
1956 LLVMStyle.PenaltyBreakBeforeMemberAccess = 150;
1957 LLVMStyle.PenaltyBreakComment = 300;
1958 LLVMStyle.PenaltyBreakFirstLessLess = 120;
1959 LLVMStyle.PenaltyBreakOpenParenthesis = 0;
1960 LLVMStyle.PenaltyBreakScopeResolution = 500;
1961 LLVMStyle.PenaltyBreakString = 1000;
1962 LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;
1963 LLVMStyle.PenaltyExcessCharacter = 1'000'000;
1964 LLVMStyle.PenaltyIndentedWhitespace = 0;
1965 LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
1966
1967 // Defaults that differ when not C++.
1968 switch (Language) {
1969 case FormatStyle::LK_TableGen:
1970 LLVMStyle.SpacesInContainerLiterals = false;
1971 break;
1972 case FormatStyle::LK_Json:
1973 LLVMStyle.ColumnLimit = 0;
1974 break;
1975 case FormatStyle::LK_Verilog:
1976 LLVMStyle.IndentCaseLabels = true;
1977 LLVMStyle.SpacesInContainerLiterals = false;
1978 break;
1979 default:
1980 break;
1981 }
1982
1983 return LLVMStyle;
1984}
1985
1986FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
1987 if (Language == FormatStyle::LK_TextProto) {
1988 FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto);
1989 GoogleStyle.Language = FormatStyle::LK_TextProto;
1990
1991 return GoogleStyle;
1992 }
1993
1994 FormatStyle GoogleStyle = getLLVMStyle(Language);
1995
1996 GoogleStyle.AccessModifierOffset = -1;
1997 GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left;
1998 GoogleStyle.AllowShortIfStatementsOnASingleLine =
1999 FormatStyle::SIS_WithoutElse;
2000 GoogleStyle.AllowShortLoopsOnASingleLine = true;
2001 GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
2002 // Abseil aliases to clang's `_Nonnull`, `_Nullable` and `_Null_unspecified`.
2003 GoogleStyle.AttributeMacros.push_back("absl_nonnull");
2004 GoogleStyle.AttributeMacros.push_back("absl_nullable");
2005 GoogleStyle.AttributeMacros.push_back("absl_nullability_unknown");
2006 GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
2007 GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
2008 GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false},
2009 {"^<.*\\.h>", 1, 0, false},
2010 {"^<.*", 2, 0, false},
2011 {".*", 3, 0, false}};
2012 GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
2013 GoogleStyle.IndentCaseLabels = true;
2014 GoogleStyle.KeepEmptyLines.AtStartOfBlock = false;
2015 GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never;
2016 GoogleStyle.ObjCSpaceAfterProperty = false;
2017 GoogleStyle.ObjCSpaceBeforeProtocolList = true;
2018 GoogleStyle.PackConstructorInitializers = FormatStyle::PCIS_NextLine;
2019 GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;
2020 GoogleStyle.RawStringFormats = {
2021 {
2022 FormatStyle::LK_Cpp,
2023 /*Delimiters=*/
2024 {
2025 "cc",
2026 "CC",
2027 "cpp",
2028 "Cpp",
2029 "CPP",
2030 "c++",
2031 "C++",
2032 },
2033 /*EnclosingFunctionNames=*/
2034 {},
2035 /*CanonicalDelimiter=*/"",
2036 /*BasedOnStyle=*/"google",
2037 },
2038 {
2039 FormatStyle::LK_TextProto,
2040 /*Delimiters=*/
2041 {
2042 "pb",
2043 "PB",
2044 "proto",
2045 "PROTO",
2046 },
2047 /*EnclosingFunctionNames=*/
2048 {
2049 "EqualsProto",
2050 "EquivToProto",
2051 "PARSE_PARTIAL_TEXT_PROTO",
2052 "PARSE_TEST_PROTO",
2053 "PARSE_TEXT_PROTO",
2054 "ParseTextOrDie",
2055 "ParseTextProtoOrDie",
2056 "ParseTestProto",
2057 "ParsePartialTestProto",
2058 },
2059 /*CanonicalDelimiter=*/"pb",
2060 /*BasedOnStyle=*/"google",
2061 },
2062 };
2063
2064 GoogleStyle.SpacesBeforeTrailingComments = 2;
2065 GoogleStyle.Standard = FormatStyle::LS_Auto;
2066
2067 GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;
2068 GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
2069
2070 if (Language == FormatStyle::LK_Java) {
2071 GoogleStyle.AlignAfterOpenBracket = false;
2072 GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
2073 GoogleStyle.AlignTrailingComments = {};
2074 GoogleStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;
2075 GoogleStyle.AllowShortFunctionsOnASingleLine =
2076 FormatStyle::ShortFunctionStyle::setEmptyOnly();
2077 GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
2078 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
2079 GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
2080 GoogleStyle.ColumnLimit = 100;
2081 GoogleStyle.SpaceAfterCStyleCast = true;
2082 GoogleStyle.SpacesBeforeTrailingComments = 1;
2083 } else if (Language == FormatStyle::LK_JavaScript) {
2084 GoogleStyle.BreakAfterOpenBracketBracedList = true;
2085 GoogleStyle.BreakAfterOpenBracketFunction = true;
2086 GoogleStyle.BreakAfterOpenBracketIf = true;
2087 GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
2088 GoogleStyle.AllowShortFunctionsOnASingleLine =
2089 FormatStyle::ShortFunctionStyle::setEmptyOnly();
2090 // TODO: still under discussion whether to switch to SLS_All.
2091 GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
2092 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
2093 GoogleStyle.BreakBeforeTernaryOperators = false;
2094 // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is
2095 // commonly followed by overlong URLs.
2096 GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)";
2097 // TODO: enable once decided, in particular re disabling bin packing.
2098 // https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma
2099 // GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
2100 GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single;
2101 GoogleStyle.JavaScriptWrapImports = false;
2102 GoogleStyle.MaxEmptyLinesToKeep = 3;
2103 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
2104 GoogleStyle.SpacesInContainerLiterals = false;
2105 } else if (Language == FormatStyle::LK_Proto) {
2106 GoogleStyle.AllowShortFunctionsOnASingleLine =
2107 FormatStyle::ShortFunctionStyle::setEmptyOnly();
2108 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
2109 // This affects protocol buffer options specifications and text protos.
2110 // Text protos are currently mostly formatted inside C++ raw string literals
2111 // and often the current breaking behavior of string literals is not
2112 // beneficial there. Investigate turning this on once proper string reflow
2113 // has been implemented.
2114 GoogleStyle.BreakStringLiterals = false;
2115 GoogleStyle.Cpp11BracedListStyle = FormatStyle::BLS_Block;
2116 GoogleStyle.SpacesInContainerLiterals = false;
2117 } else if (Language == FormatStyle::LK_ObjC) {
2118 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
2119 GoogleStyle.ColumnLimit = 100;
2120 GoogleStyle.DerivePointerAlignment = true;
2121 // "Regroup" doesn't work well for ObjC yet (main header heuristic,
2122 // relationship between ObjC standard library headers and other heades,
2123 // #imports, etc.)
2124 GoogleStyle.IncludeStyle.IncludeBlocks =
2126 } else if (Language == FormatStyle::LK_CSharp) {
2127 GoogleStyle.AllowShortFunctionsOnASingleLine =
2128 FormatStyle::ShortFunctionStyle::setEmptyOnly();
2129 GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
2130 GoogleStyle.BreakStringLiterals = false;
2131 GoogleStyle.ColumnLimit = 100;
2132 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
2133 }
2134
2135 return GoogleStyle;
2136}
2137
2138FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
2139 FormatStyle ChromiumStyle = getGoogleStyle(Language);
2140
2141 // Disable include reordering across blocks in Chromium code.
2142 // - clang-format tries to detect that foo.h is the "main" header for
2143 // foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium
2144 // uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc,
2145 // _private.cc, _impl.cc etc) in different permutations
2146 // (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a
2147 // better default for Chromium code.
2148 // - The default for .cc and .mm files is different (r357695) for Google style
2149 // for the same reason. The plan is to unify this again once the main
2150 // header detection works for Google's ObjC code, but this hasn't happened
2151 // yet. Since Chromium has some ObjC code, switching Chromium is blocked
2152 // on that.
2153 // - Finally, "If include reordering is harmful, put things in different
2154 // blocks to prevent it" has been a recommendation for a long time that
2155 // people are used to. We'll need a dev education push to change this to
2156 // "If include reordering is harmful, put things in a different block and
2157 // _prepend that with a comment_ to prevent it" before changing behavior.
2158 ChromiumStyle.IncludeStyle.IncludeBlocks =
2160
2161 if (Language == FormatStyle::LK_Java) {
2162 ChromiumStyle.AllowShortIfStatementsOnASingleLine =
2163 FormatStyle::SIS_WithoutElse;
2164 ChromiumStyle.BreakAfterJavaFieldAnnotations = true;
2165 ChromiumStyle.ContinuationIndentWidth = 8;
2166 ChromiumStyle.IndentWidth = 4;
2167 // See styleguide for import groups:
2168 // https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/java/java.md#Import-Order
2169 ChromiumStyle.JavaImportGroups = {
2170 "android",
2171 "androidx",
2172 "com",
2173 "dalvik",
2174 "junit",
2175 "org",
2176 "com.google.android.apps.chrome",
2177 "org.chromium",
2178 "java",
2179 "javax",
2180 };
2181 } else if (Language == FormatStyle::LK_JavaScript) {
2182 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
2183 ChromiumStyle.AllowShortLoopsOnASingleLine = false;
2184 } else {
2185 ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
2186 ChromiumStyle.AllowShortFunctionsOnASingleLine =
2187 FormatStyle::ShortFunctionStyle::setEmptyAndInline();
2188 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
2189 ChromiumStyle.AllowShortLoopsOnASingleLine = false;
2190 ChromiumStyle.BinPackParameters = FormatStyle::BPPS_OnePerLine;
2191 ChromiumStyle.DerivePointerAlignment = false;
2192 if (Language == FormatStyle::LK_ObjC)
2193 ChromiumStyle.ColumnLimit = 80;
2194 }
2195 return ChromiumStyle;
2196}
2197
2198FormatStyle getMozillaStyle() {
2199 FormatStyle MozillaStyle = getLLVMStyle();
2200 MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
2201 MozillaStyle.AllowShortFunctionsOnASingleLine =
2202 FormatStyle::ShortFunctionStyle::setEmptyAndInline();
2203 MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
2204 FormatStyle::DRTBS_TopLevel;
2205 MozillaStyle.BinPackArguments = false;
2206 MozillaStyle.BinPackParameters = FormatStyle::BPPS_OnePerLine;
2207 MozillaStyle.BreakAfterReturnType = FormatStyle::RTBS_TopLevel;
2208 MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
2209 MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
2210 MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
2211 MozillaStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
2212 MozillaStyle.ConstructorInitializerIndentWidth = 2;
2213 MozillaStyle.ContinuationIndentWidth = 2;
2214 MozillaStyle.Cpp11BracedListStyle = FormatStyle::BLS_Block;
2215 MozillaStyle.FixNamespaceComments = false;
2216 MozillaStyle.IndentCaseLabels = true;
2217 MozillaStyle.ObjCSpaceAfterProperty = true;
2218 MozillaStyle.ObjCSpaceBeforeProtocolList = false;
2219 MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
2220 MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
2221 MozillaStyle.SpaceAfterTemplateKeyword = false;
2222 return MozillaStyle;
2223}
2224
2225FormatStyle getWebKitStyle() {
2226 FormatStyle Style = getLLVMStyle();
2227 Style.AccessModifierOffset = -4;
2228 Style.AlignAfterOpenBracket = false;
2229 Style.AlignOperands = FormatStyle::OAS_DontAlign;
2230 Style.AlignTrailingComments = {};
2231 Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;
2232 Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;
2233 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
2234 Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
2235 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
2236 Style.ColumnLimit = 0;
2237 Style.Cpp11BracedListStyle = FormatStyle::BLS_Block;
2238 Style.FixNamespaceComments = false;
2239 Style.IndentWidth = 4;
2240 Style.NamespaceIndentation = FormatStyle::NI_Inner;
2241 Style.ObjCBlockIndentWidth = 4;
2242 Style.ObjCSpaceAfterProperty = true;
2243 Style.PointerAlignment = FormatStyle::PAS_Left;
2244 Style.SpaceBeforeCpp11BracedList = true;
2245 Style.SpaceInEmptyBraces = FormatStyle::SIEB_Always;
2246 return Style;
2247}
2248
2249FormatStyle getGNUStyle() {
2250 FormatStyle Style = getLLVMStyle();
2251 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
2252 Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
2253 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
2254 Style.BreakBeforeBraces = FormatStyle::BS_GNU;
2255 Style.BreakBeforeTernaryOperators = true;
2256 Style.ColumnLimit = 79;
2257 Style.Cpp11BracedListStyle = FormatStyle::BLS_Block;
2258 Style.FixNamespaceComments = false;
2259 Style.KeepFormFeed = true;
2260 Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
2261 return Style;
2262}
2263
2264FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) {
2265 FormatStyle Style = getLLVMStyle(Language);
2266 Style.ColumnLimit = 120;
2267 Style.TabWidth = 4;
2268 Style.IndentWidth = 4;
2269 Style.UseTab = FormatStyle::UT_Never;
2270 Style.BreakBeforeBraces = FormatStyle::BS_Custom;
2271 Style.BraceWrapping.AfterClass = true;
2272 Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
2273 Style.BraceWrapping.AfterEnum = true;
2274 Style.BraceWrapping.AfterFunction = true;
2275 Style.BraceWrapping.AfterNamespace = true;
2276 Style.BraceWrapping.AfterObjCDeclaration = true;
2277 Style.BraceWrapping.AfterStruct = true;
2278 Style.BraceWrapping.AfterExternBlock = true;
2279 Style.BraceWrapping.BeforeCatch = true;
2280 Style.BraceWrapping.BeforeElse = true;
2281 Style.BraceWrapping.BeforeWhile = false;
2282 Style.PenaltyReturnTypeOnItsOwnLine = 1000;
2283 Style.AllowShortEnumsOnASingleLine = false;
2284 Style.AllowShortFunctionsOnASingleLine = FormatStyle::ShortFunctionStyle();
2285 Style.AllowShortCaseLabelsOnASingleLine = false;
2286 Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
2287 Style.AllowShortLoopsOnASingleLine = false;
2288 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
2289 Style.BreakAfterReturnType = FormatStyle::RTBS_None;
2290 return Style;
2291}
2292
2293FormatStyle getClangFormatStyle() {
2294 FormatStyle Style = getLLVMStyle();
2295 Style.InsertBraces = true;
2296 Style.InsertNewlineAtEOF = true;
2297 Style.IntegerLiteralSeparator.Decimal = 3;
2298 Style.IntegerLiteralSeparator.DecimalMinDigitsInsert = 5;
2299 Style.LineEnding = FormatStyle::LE_LF;
2300 Style.RemoveBracesLLVM = true;
2301 Style.RemoveEmptyLinesInUnwrappedLines = true;
2302 Style.RemoveParentheses = FormatStyle::RPS_ReturnStatement;
2303 Style.RemoveSemicolon = true;
2304 return Style;
2305}
2306
2307FormatStyle getNoStyle() {
2308 FormatStyle NoStyle = getLLVMStyle();
2309 NoStyle.DisableFormat = true;
2310 NoStyle.SortIncludes = {};
2311 NoStyle.SortUsingDeclarations = FormatStyle::SUD_Never;
2312 return NoStyle;
2313}
2314
2315bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
2316 FormatStyle *Style) {
2317 constexpr StringRef Prefix("inheritparentconfig=");
2318
2319 if (Name.equals_insensitive("llvm"))
2320 *Style = getLLVMStyle(Language);
2321 else if (Name.equals_insensitive("chromium"))
2322 *Style = getChromiumStyle(Language);
2323 else if (Name.equals_insensitive("mozilla"))
2324 *Style = getMozillaStyle();
2325 else if (Name.equals_insensitive("google"))
2326 *Style = getGoogleStyle(Language);
2327 else if (Name.equals_insensitive("webkit"))
2328 *Style = getWebKitStyle();
2329 else if (Name.equals_insensitive("gnu"))
2330 *Style = getGNUStyle();
2331 else if (Name.equals_insensitive("microsoft"))
2332 *Style = getMicrosoftStyle(Language);
2333 else if (Name.equals_insensitive("clang-format"))
2334 *Style = getClangFormatStyle();
2335 else if (Name.equals_insensitive("none"))
2336 *Style = getNoStyle();
2337 else if (Name.equals_insensitive(Prefix.drop_back()))
2338 Style->InheritConfig = "..";
2339 else if (Name.size() > Prefix.size() && Name.starts_with_insensitive(Prefix))
2340 Style->InheritConfig = Name.substr(Prefix.size());
2341 else
2342 return false;
2343
2344 Style->Language = Language;
2345 return true;
2346}
2347
2349 // If its empty then it means don't do anything.
2350 if (Style->QualifierOrder.empty())
2352
2353 // Ensure the list contains only currently valid qualifiers.
2354 for (const auto &Qualifier : Style->QualifierOrder) {
2355 if (Qualifier == "type")
2356 continue;
2357 auto token =
2359 if (token == tok::identifier)
2361 }
2362
2363 // Ensure the list is unique (no duplicates).
2364 std::set<std::string> UniqueQualifiers(Style->QualifierOrder.begin(),
2365 Style->QualifierOrder.end());
2366 if (Style->QualifierOrder.size() != UniqueQualifiers.size()) {
2367 LLVM_DEBUG(llvm::dbgs()
2368 << "Duplicate Qualifiers " << Style->QualifierOrder.size()
2369 << " vs " << UniqueQualifiers.size() << "\n");
2371 }
2372
2373 // Ensure the list has 'type' in it.
2374 if (!llvm::is_contained(Style->QualifierOrder, "type"))
2376
2377 return ParseError::Success;
2378}
2379
2380std::error_code parseConfiguration(llvm::MemoryBufferRef Config,
2381 FormatStyle *Style, bool AllowUnknownOptions,
2382 llvm::SourceMgr::DiagHandlerTy DiagHandler,
2383 void *DiagHandlerCtxt, bool IsDotHFile) {
2384 assert(Style);
2385 FormatStyle::LanguageKind Language = Style->Language;
2386 assert(Language != FormatStyle::LK_None);
2387 if (Config.getBuffer().trim().empty())
2389 Style->StyleSet.Clear();
2390 std::vector<FormatStyle> Styles;
2391 llvm::yaml::Input Input(Config, /*Ctxt=*/nullptr, DiagHandler,
2392 DiagHandlerCtxt);
2393 // DocumentListTraits<vector<FormatStyle>> uses the context to get default
2394 // values for the fields, keys for which are missing from the configuration.
2395 // Mapping also uses the context to get the language to find the correct
2396 // base style.
2397 Input.setContext(Style);
2398 Input.setAllowUnknownKeys(AllowUnknownOptions);
2399 Input >> Styles;
2400 if (Input.error())
2401 return Input.error();
2402 if (Styles.empty())
2404
2405 const auto StyleCount = Styles.size();
2406
2407 // Start from the second style as (only) the first one may be the default.
2408 for (unsigned I = 1; I < StyleCount; ++I) {
2409 const auto Lang = Styles[I].Language;
2410 if (Lang == FormatStyle::LK_None)
2412 // Ensure that each language is configured at most once.
2413 for (unsigned J = 0; J < I; ++J) {
2414 if (Lang == Styles[J].Language) {
2415 LLVM_DEBUG(llvm::dbgs()
2416 << "Duplicate languages in the config file on positions "
2417 << J << " and " << I << '\n');
2419 }
2420 }
2421 }
2422
2423 int LanguagePos = -1; // Position of the style for Language.
2424 int CppPos = -1; // Position of the style for C++.
2425 int CPos = -1; // Position of the style for C.
2426
2427 // Search Styles for Language and store the positions of C++ and C styles in
2428 // case Language is not found.
2429 for (unsigned I = 0; I < StyleCount; ++I) {
2430 const auto Lang = Styles[I].Language;
2431 if (Lang == Language) {
2432 LanguagePos = I;
2433 break;
2434 }
2435 if (Lang == FormatStyle::LK_Cpp)
2436 CppPos = I;
2437 else if (Lang == FormatStyle::LK_C)
2438 CPos = I;
2439 }
2440
2441 // If Language is not found, use the default style if there is one. Otherwise,
2442 // use the C style for C++ .h files and for backward compatibility, the C++
2443 // style for .c files.
2444 if (LanguagePos < 0) {
2445 if (Styles[0].Language == FormatStyle::LK_None) // Default style.
2446 LanguagePos = 0;
2447 else if (IsDotHFile && Language == FormatStyle::LK_Cpp)
2448 LanguagePos = CPos;
2449 else if (!IsDotHFile && Language == FormatStyle::LK_C)
2450 LanguagePos = CppPos;
2451 if (LanguagePos < 0)
2453 }
2454
2455 for (const auto &S : llvm::reverse(llvm::drop_begin(Styles)))
2456 Style->StyleSet.Add(S);
2457
2458 *Style = Styles[LanguagePos];
2459
2460 if (LanguagePos == 0) {
2461 if (Style->Language == FormatStyle::LK_None) // Default style.
2462 Style->Language = Language;
2463 Style->StyleSet.Add(*Style);
2464 }
2465
2466 if (Style->InsertTrailingCommas != FormatStyle::TCS_None &&
2467 Style->BinPackArguments) {
2468 // See comment on FormatStyle::TSC_Wrapped.
2470 }
2471 if (Style->QualifierAlignment != FormatStyle::QAS_Leave)
2474}
2475
2476std::string configurationAsText(const FormatStyle &Style) {
2477 std::string Text;
2478 llvm::raw_string_ostream Stream(Text);
2479 llvm::yaml::Output Output(Stream);
2480 // We use the same mapping method for input and output, so we need a non-const
2481 // reference here.
2482 FormatStyle NonConstStyle = Style;
2483 expandPresetsBraceWrapping(NonConstStyle);
2484 expandPresetsSpaceBeforeParens(NonConstStyle);
2485 expandPresetsSpacesInParens(NonConstStyle);
2486 Output << NonConstStyle;
2487
2488 return Stream.str();
2489}
2490
2491std::optional<FormatStyle>
2492FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {
2493 if (!Styles)
2494 return std::nullopt;
2495 auto It = Styles->find(Language);
2496 if (It == Styles->end())
2497 return std::nullopt;
2498 FormatStyle Style = It->second;
2499 Style.StyleSet = *this;
2500 return Style;
2501}
2502
2503void FormatStyle::FormatStyleSet::Add(FormatStyle Style) {
2504 assert(Style.Language != LK_None &&
2505 "Cannot add a style for LK_None to a StyleSet");
2506 assert(
2507 !Style.StyleSet.Styles &&
2508 "Cannot add a style associated with an existing StyleSet to a StyleSet");
2509 if (!Styles)
2510 Styles = std::make_shared<MapType>();
2511 (*Styles)[Style.Language] = std::move(Style);
2512}
2513
2514void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); }
2515
2516std::optional<FormatStyle>
2517FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {
2518 return StyleSet.Get(Language);
2519}
2520
2521namespace {
2522
2523void replaceToken(const FormatToken &Token, FormatToken *Next,
2524 const SourceManager &SourceMgr, tooling::Replacements &Result,
2525 StringRef Text = "") {
2526 const auto &Tok = Token.Tok;
2527 SourceLocation Start;
2528 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2529 Start = Tok.getLocation();
2530 Next->WhitespaceRange = Token.WhitespaceRange;
2531 } else {
2532 Start = Token.WhitespaceRange.getBegin();
2533 }
2534 const auto &Range = CharSourceRange::getCharRange(Start, Tok.getEndLoc());
2535 cantFail(Result.add(tooling::Replacement(SourceMgr, Range, Text)));
2536}
2537
2538class ParensRemover : public TokenAnalyzer {
2539public:
2540 ParensRemover(const Environment &Env, const FormatStyle &Style)
2541 : TokenAnalyzer(Env, Style) {}
2542
2543 std::pair<tooling::Replacements, unsigned>
2544 analyze(TokenAnnotator &Annotator,
2545 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2546 FormatTokenLexer &Tokens) override {
2547 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2548 tooling::Replacements Result;
2549 removeParens(AnnotatedLines, Result);
2550 return {Result, 0};
2551 }
2552
2553private:
2554 void removeParens(SmallVectorImpl<AnnotatedLine *> &Lines,
2555 tooling::Replacements &Result) {
2556 const auto &SourceMgr = Env.getSourceManager();
2557 for (auto *Line : Lines) {
2558 if (!Line->Children.empty())
2559 removeParens(Line->Children, Result);
2560 if (!Line->Affected)
2561 continue;
2562 for (const auto *Token = Line->First; Token && !Token->Finalized;
2563 Token = Token->Next) {
2564 if (Token->Optional && Token->isOneOf(tok::l_paren, tok::r_paren))
2565 replaceToken(*Token, Token->Next, SourceMgr, Result, " ");
2566 }
2567 }
2568 }
2569};
2570
2571class BracesInserter : public TokenAnalyzer {
2572public:
2573 BracesInserter(const Environment &Env, const FormatStyle &Style)
2574 : TokenAnalyzer(Env, Style) {}
2575
2576 std::pair<tooling::Replacements, unsigned>
2577 analyze(TokenAnnotator &Annotator,
2578 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2579 FormatTokenLexer &Tokens) override {
2580 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2581 tooling::Replacements Result;
2582 insertBraces(AnnotatedLines, Result);
2583 return {Result, 0};
2584 }
2585
2586private:
2587 void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2588 tooling::Replacements &Result) {
2589 const auto &SourceMgr = Env.getSourceManager();
2590 int OpeningBraceSurplus = 0;
2591 for (AnnotatedLine *Line : Lines) {
2592 if (!Line->Children.empty())
2593 insertBraces(Line->Children, Result);
2594 if (!Line->Affected && OpeningBraceSurplus == 0)
2595 continue;
2596 for (FormatToken *Token = Line->First; Token && !Token->Finalized;
2597 Token = Token->Next) {
2598 int BraceCount = Token->BraceCount;
2599 if (BraceCount == 0)
2600 continue;
2601 std::string Brace;
2602 if (BraceCount < 0) {
2603 assert(BraceCount == -1);
2604 if (!Line->Affected)
2605 break;
2606 Brace = Token->is(tok::comment) ? "\n{" : "{";
2607 ++OpeningBraceSurplus;
2608 } else {
2609 if (OpeningBraceSurplus == 0)
2610 break;
2611 if (OpeningBraceSurplus < BraceCount)
2612 BraceCount = OpeningBraceSurplus;
2613 Brace = '\n' + std::string(BraceCount, '}');
2614 OpeningBraceSurplus -= BraceCount;
2615 }
2616 Token->BraceCount = 0;
2617 const auto Start = Token->Tok.getEndLoc();
2618 cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0, Brace)));
2619 }
2620 }
2621 assert(OpeningBraceSurplus == 0);
2622 }
2623};
2624
2625class BracesRemover : public TokenAnalyzer {
2626public:
2627 BracesRemover(const Environment &Env, const FormatStyle &Style)
2628 : TokenAnalyzer(Env, Style) {}
2629
2630 std::pair<tooling::Replacements, unsigned>
2631 analyze(TokenAnnotator &Annotator,
2632 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2633 FormatTokenLexer &Tokens) override {
2634 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2635 tooling::Replacements Result;
2636 removeBraces(AnnotatedLines, Result);
2637 return {Result, 0};
2638 }
2639
2640private:
2641 void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2642 tooling::Replacements &Result) {
2643 const auto &SourceMgr = Env.getSourceManager();
2644 const auto *End = Lines.end();
2645 for (const auto *I = Lines.begin(); I != End; ++I) {
2646 const auto &Line = *I;
2647 if (!Line->Children.empty())
2648 removeBraces(Line->Children, Result);
2649 if (!Line->Affected)
2650 continue;
2651 const auto *NextLine = I + 1 == End ? nullptr : I[1];
2652 for (const auto *Token = Line->First; Token && !Token->Finalized;
2653 Token = Token->Next) {
2654 if (!Token->Optional || Token->isNoneOf(tok::l_brace, tok::r_brace))
2655 continue;
2656 auto *Next = Token->Next;
2657 assert(Next || Token == Line->Last);
2658 if (!Next && NextLine)
2659 Next = NextLine->First;
2660 replaceToken(*Token, Next, SourceMgr, Result);
2661 }
2662 }
2663 }
2664};
2665
2666class SemiRemover : public TokenAnalyzer {
2667public:
2668 SemiRemover(const Environment &Env, const FormatStyle &Style)
2669 : TokenAnalyzer(Env, Style) {}
2670
2671 std::pair<tooling::Replacements, unsigned>
2672 analyze(TokenAnnotator &Annotator,
2673 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2674 FormatTokenLexer &Tokens) override {
2675 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2676 tooling::Replacements Result;
2677 removeSemi(Annotator, AnnotatedLines, Result);
2678 return {Result, 0};
2679 }
2680
2681private:
2682 void removeSemi(TokenAnnotator &Annotator,
2683 SmallVectorImpl<AnnotatedLine *> &Lines,
2684 tooling::Replacements &Result) {
2685 auto PrecededByFunctionRBrace = [](const FormatToken &Tok) {
2686 const auto *Prev = Tok.Previous;
2687 if (!Prev || Prev->isNot(tok::r_brace))
2688 return false;
2689 const auto *LBrace = Prev->MatchingParen;
2690 return LBrace && LBrace->is(TT_FunctionLBrace);
2691 };
2692 const auto &SourceMgr = Env.getSourceManager();
2693 const auto *End = Lines.end();
2694 for (const auto *I = Lines.begin(); I != End; ++I) {
2695 const auto &Line = *I;
2696 if (!Line->Children.empty())
2697 removeSemi(Annotator, Line->Children, Result);
2698 if (!Line->Affected)
2699 continue;
2700 Annotator.calculateFormattingInformation(*Line);
2701 const auto *NextLine = I + 1 == End ? nullptr : I[1];
2702 for (const auto *Token = Line->First; Token && !Token->Finalized;
2703 Token = Token->Next) {
2704 if (Token->isNot(tok::semi) ||
2705 (!Token->Optional && !PrecededByFunctionRBrace(*Token))) {
2706 continue;
2707 }
2708 auto *Next = Token->Next;
2709 assert(Next || Token == Line->Last);
2710 if (!Next && NextLine)
2711 Next = NextLine->First;
2712 replaceToken(*Token, Next, SourceMgr, Result);
2713 }
2714 }
2715 }
2716};
2717
2718class EnumTrailingCommaEditor : public TokenAnalyzer {
2719public:
2720 EnumTrailingCommaEditor(const Environment &Env, const FormatStyle &Style)
2721 : TokenAnalyzer(Env, Style) {}
2722
2723 std::pair<tooling::Replacements, unsigned>
2724 analyze(TokenAnnotator &Annotator,
2725 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2726 FormatTokenLexer &Tokens) override {
2727 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2728 tooling::Replacements Result;
2729 editEnumTrailingComma(AnnotatedLines, Result);
2730 return {Result, 0};
2731 }
2732
2733private:
2734 void editEnumTrailingComma(SmallVectorImpl<AnnotatedLine *> &Lines,
2735 tooling::Replacements &Result) {
2736 bool InEnumBraces = false;
2737 const FormatToken *BeforeRBrace = nullptr;
2738 const auto &SourceMgr = Env.getSourceManager();
2739 for (auto *Line : Lines) {
2740 if (!Line->Children.empty())
2741 editEnumTrailingComma(Line->Children, Result);
2742 for (const auto *Token = Line->First; Token && !Token->Finalized;
2743 Token = Token->Next) {
2744 if (Token->isNot(TT_EnumRBrace)) {
2745 if (Token->is(TT_EnumLBrace))
2746 InEnumBraces = true;
2747 else if (InEnumBraces && Token->isNot(tok::comment))
2748 BeforeRBrace = Line->Affected ? Token : nullptr;
2749 continue;
2750 }
2751 InEnumBraces = false;
2752 if (!BeforeRBrace) // Empty braces or Line not affected.
2753 continue;
2754 if (BeforeRBrace->is(tok::comma)) {
2755 if (Style.EnumTrailingComma == FormatStyle::ETC_Remove)
2756 replaceToken(*BeforeRBrace, BeforeRBrace->Next, SourceMgr, Result);
2757 } else if (Style.EnumTrailingComma == FormatStyle::ETC_Insert) {
2758 cantFail(Result.add(tooling::Replacement(
2759 SourceMgr, BeforeRBrace->Tok.getEndLoc(), 0, ",")));
2760 }
2761 BeforeRBrace = nullptr;
2762 }
2763 }
2764 }
2765};
2766
2767class JavaScriptRequoter : public TokenAnalyzer {
2768public:
2769 JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)
2770 : TokenAnalyzer(Env, Style) {}
2771
2772 std::pair<tooling::Replacements, unsigned>
2773 analyze(TokenAnnotator &Annotator,
2774 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2775 FormatTokenLexer &Tokens) override {
2776 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2777 tooling::Replacements Result;
2778 requoteJSStringLiteral(AnnotatedLines, Result);
2779 return {Result, 0};
2780 }
2781
2782private:
2783 // Replaces double/single-quoted string literal as appropriate, re-escaping
2784 // the contents in the process.
2785 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
2786 tooling::Replacements &Result) {
2787 for (AnnotatedLine *Line : Lines) {
2788 requoteJSStringLiteral(Line->Children, Result);
2789 if (!Line->Affected)
2790 continue;
2791 for (FormatToken *FormatTok = Line->First; FormatTok;
2792 FormatTok = FormatTok->Next) {
2793 StringRef Input = FormatTok->TokenText;
2794 if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
2795 // NB: testing for not starting with a double quote to avoid
2796 // breaking `template strings`.
2797 (Style.JavaScriptQuotes == FormatStyle::JSQS_Single &&
2798 !Input.starts_with("\"")) ||
2799 (Style.JavaScriptQuotes == FormatStyle::JSQS_Double &&
2800 !Input.starts_with("\'"))) {
2801 continue;
2802 }
2803
2804 // Change start and end quote.
2805 bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single;
2806 SourceLocation Start = FormatTok->Tok.getLocation();
2807 auto Replace = [&](SourceLocation Start, unsigned Length,
2808 StringRef ReplacementText) {
2809 auto Err = Result.add(tooling::Replacement(
2810 Env.getSourceManager(), Start, Length, ReplacementText));
2811 // FIXME: handle error. For now, print error message and skip the
2812 // replacement for release version.
2813 if (Err) {
2814 llvm::errs() << toString(std::move(Err)) << "\n";
2815 assert(false);
2816 }
2817 };
2818 Replace(Start, 1, IsSingle ? "'" : "\"");
2819 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
2820 IsSingle ? "'" : "\"");
2821
2822 // Escape internal quotes.
2823 bool Escaped = false;
2824 for (size_t i = 1; i < Input.size() - 1; i++) {
2825 switch (Input[i]) {
2826 case '\\':
2827 if (!Escaped && i + 1 < Input.size() &&
2828 ((IsSingle && Input[i + 1] == '"') ||
2829 (!IsSingle && Input[i + 1] == '\''))) {
2830 // Remove this \, it's escaping a " or ' that no longer needs
2831 // escaping
2832 Replace(Start.getLocWithOffset(i), 1, "");
2833 continue;
2834 }
2835 Escaped = !Escaped;
2836 break;
2837 case '\"':
2838 case '\'':
2839 if (!Escaped && IsSingle == (Input[i] == '\'')) {
2840 // Escape the quote.
2841 Replace(Start.getLocWithOffset(i), 0, "\\");
2842 }
2843 Escaped = false;
2844 break;
2845 default:
2846 Escaped = false;
2847 break;
2848 }
2849 }
2850 }
2851 }
2852 }
2853};
2854
2855class Formatter : public TokenAnalyzer {
2856public:
2857 Formatter(const Environment &Env, const FormatStyle &Style,
2858 FormattingAttemptStatus *Status)
2859 : TokenAnalyzer(Env, Style), Status(Status) {}
2860
2861 std::pair<tooling::Replacements, unsigned>
2862 analyze(TokenAnnotator &Annotator,
2863 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2864 FormatTokenLexer &Tokens) override {
2865 tooling::Replacements Result;
2866 deriveLocalStyle(AnnotatedLines);
2867 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2868 for (AnnotatedLine *Line : AnnotatedLines)
2869 Annotator.calculateFormattingInformation(*Line);
2870 Annotator.setCommentLineLevels(AnnotatedLines);
2871
2872 WhitespaceManager Whitespaces(
2873 Env.getSourceManager(), Style,
2874 Style.LineEnding > FormatStyle::LE_CRLF
2876 Env.getSourceManager().getBufferData(Env.getFileID()),
2877 Style.LineEnding == FormatStyle::LE_DeriveCRLF)
2878 : Style.LineEnding == FormatStyle::LE_CRLF);
2879 ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
2880 Env.getSourceManager(), Whitespaces, Encoding,
2881 BinPackInconclusiveFunctions);
2882 unsigned Penalty =
2883 UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,
2884 Tokens.getKeywords(), Env.getSourceManager(),
2885 Status)
2886 .format(AnnotatedLines, /*DryRun=*/false,
2887 /*AdditionalIndent=*/0,
2888 /*FixBadIndentation=*/false,
2889 /*FirstStartColumn=*/Env.getFirstStartColumn(),
2890 /*NextStartColumn=*/Env.getNextStartColumn(),
2891 /*LastStartColumn=*/Env.getLastStartColumn());
2892 for (const auto &R : Whitespaces.generateReplacements())
2893 if (Result.add(R))
2894 return std::make_pair(Result, 0);
2895 return std::make_pair(Result, Penalty);
2896 }
2897
2898private:
2899 bool
2900 hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) {
2901 for (const AnnotatedLine *Line : Lines) {
2902 if (hasCpp03IncompatibleFormat(Line->Children))
2903 return true;
2904 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {
2905 if (!Tok->hasWhitespaceBefore()) {
2906 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
2907 return true;
2908 if (Tok->is(TT_TemplateCloser) &&
2909 Tok->Previous->is(TT_TemplateCloser)) {
2910 return true;
2911 }
2912 }
2913 }
2914 }
2915 return false;
2916 }
2917
2918 int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) {
2919 int AlignmentDiff = 0;
2920
2921 for (const AnnotatedLine *Line : Lines) {
2922 AlignmentDiff += countVariableAlignments(Line->Children);
2923
2924 for (const auto *Tok = Line->getFirstNonComment(); Tok; Tok = Tok->Next) {
2925 if (Tok->isNot(TT_PointerOrReference))
2926 continue;
2927
2928 const auto *Prev = Tok->Previous;
2929 const bool PrecededByName = Prev && Prev->Tok.getIdentifierInfo();
2930 const bool SpaceBefore = Tok->hasWhitespaceBefore();
2931
2932 // e.g. `int **`, `int*&`, etc.
2933 while (Tok->Next && Tok->Next->is(TT_PointerOrReference))
2934 Tok = Tok->Next;
2935
2936 const auto *Next = Tok->Next;
2937 const bool FollowedByName = Next && Next->Tok.getIdentifierInfo();
2938 const bool SpaceAfter = Next && Next->hasWhitespaceBefore();
2939
2940 if ((!PrecededByName && !FollowedByName) ||
2941 // e.g. `int * i` or `int*i`
2942 (PrecededByName && FollowedByName && SpaceBefore == SpaceAfter)) {
2943 continue;
2944 }
2945
2946 if ((PrecededByName && SpaceBefore) ||
2947 (FollowedByName && !SpaceAfter)) {
2948 // Right alignment.
2949 ++AlignmentDiff;
2950 } else if ((PrecededByName && !SpaceBefore) ||
2951 (FollowedByName && SpaceAfter)) {
2952 // Left alignment.
2953 --AlignmentDiff;
2954 }
2955 }
2956 }
2957
2958 return AlignmentDiff;
2959 }
2960
2961 void
2962 deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2963 bool HasBinPackedFunction = false;
2964 bool HasOnePerLineFunction = false;
2965 for (AnnotatedLine *Line : AnnotatedLines) {
2966 if (!Line->First->Next)
2967 continue;
2968 FormatToken *Tok = Line->First->Next;
2969 while (Tok->Next) {
2970 if (Tok->is(PPK_BinPacked))
2971 HasBinPackedFunction = true;
2972 if (Tok->is(PPK_OnePerLine))
2973 HasOnePerLineFunction = true;
2974
2975 Tok = Tok->Next;
2976 }
2977 }
2978 if (Style.DerivePointerAlignment) {
2979 const auto NetRightCount = countVariableAlignments(AnnotatedLines);
2980 if (NetRightCount > 0)
2981 Style.PointerAlignment = FormatStyle::PAS_Right;
2982 else if (NetRightCount < 0)
2983 Style.PointerAlignment = FormatStyle::PAS_Left;
2984 Style.ReferenceAlignment = FormatStyle::RAS_Pointer;
2985 }
2986 if (Style.Standard == FormatStyle::LS_Auto) {
2987 Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
2988 ? FormatStyle::LS_Latest
2989 : FormatStyle::LS_Cpp03;
2990 }
2991 BinPackInconclusiveFunctions =
2992 HasBinPackedFunction || !HasOnePerLineFunction;
2993 }
2994
2995 bool BinPackInconclusiveFunctions;
2996 FormattingAttemptStatus *Status;
2997};
2998
2999/// TrailingCommaInserter inserts trailing commas into container literals.
3000/// E.g.:
3001/// const x = [
3002/// 1,
3003/// ];
3004/// TrailingCommaInserter runs after formatting. To avoid causing a required
3005/// reformatting (and thus reflow), it never inserts a comma that'd exceed the
3006/// ColumnLimit.
3007///
3008/// Because trailing commas disable binpacking of arrays, TrailingCommaInserter
3009/// is conceptually incompatible with bin packing.
3010class TrailingCommaInserter : public TokenAnalyzer {
3011public:
3012 TrailingCommaInserter(const Environment &Env, const FormatStyle &Style)
3013 : TokenAnalyzer(Env, Style) {}
3014
3015 std::pair<tooling::Replacements, unsigned>
3016 analyze(TokenAnnotator &Annotator,
3017 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
3018 FormatTokenLexer &Tokens) override {
3019 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
3020 tooling::Replacements Result;
3021 insertTrailingCommas(AnnotatedLines, Result);
3022 return {Result, 0};
3023 }
3024
3025private:
3026 /// Inserts trailing commas in [] and {} initializers if they wrap over
3027 /// multiple lines.
3028 void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,
3029 tooling::Replacements &Result) {
3030 for (AnnotatedLine *Line : Lines) {
3031 insertTrailingCommas(Line->Children, Result);
3032 if (!Line->Affected)
3033 continue;
3034 for (FormatToken *FormatTok = Line->First; FormatTok;
3035 FormatTok = FormatTok->Next) {
3036 if (FormatTok->NewlinesBefore == 0)
3037 continue;
3038 FormatToken *Matching = FormatTok->MatchingParen;
3039 if (!Matching || !FormatTok->getPreviousNonComment())
3040 continue;
3041 if (!(FormatTok->is(tok::r_square) &&
3042 Matching->is(TT_ArrayInitializerLSquare)) &&
3043 !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) {
3044 continue;
3045 }
3046 FormatToken *Prev = FormatTok->getPreviousNonComment();
3047 if (Prev->is(tok::comma) || Prev->is(tok::semi))
3048 continue;
3049 // getEndLoc is not reliably set during re-lexing, use text length
3050 // instead.
3051 SourceLocation Start =
3052 Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size());
3053 // If inserting a comma would push the code over the column limit, skip
3054 // this location - it'd introduce an unstable formatting due to the
3055 // required reflow.
3056 unsigned ColumnNumber =
3057 Env.getSourceManager().getSpellingColumnNumber(Start);
3058 if (ColumnNumber > Style.ColumnLimit)
3059 continue;
3060 // Comma insertions cannot conflict with each other, and this pass has a
3061 // clean set of Replacements, so the operation below cannot fail.
3062 cantFail(Result.add(
3063 tooling::Replacement(Env.getSourceManager(), Start, 0, ",")));
3064 }
3065 }
3066 }
3067};
3068
3069// This class clean up the erroneous/redundant code around the given ranges in
3070// file.
3071class Cleaner : public TokenAnalyzer {
3072public:
3073 Cleaner(const Environment &Env, const FormatStyle &Style)
3074 : TokenAnalyzer(Env, Style),
3075 DeletedTokens(FormatTokenLess(Env.getSourceManager())) {}
3076
3077 // FIXME: eliminate unused parameters.
3078 std::pair<tooling::Replacements, unsigned>
3079 analyze(TokenAnnotator &Annotator,
3080 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
3081 FormatTokenLexer &Tokens) override {
3082 // FIXME: in the current implementation the granularity of affected range
3083 // is an annotated line. However, this is not sufficient. Furthermore,
3084 // redundant code introduced by replacements does not necessarily
3085 // intercept with ranges of replacements that result in the redundancy.
3086 // To determine if some redundant code is actually introduced by
3087 // replacements(e.g. deletions), we need to come up with a more
3088 // sophisticated way of computing affected ranges.
3089 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
3090
3091 checkEmptyNamespace(AnnotatedLines);
3092
3093 for (auto *Line : AnnotatedLines)
3094 cleanupLine(Line);
3095
3096 return {generateFixes(), 0};
3097 }
3098
3099private:
3100 void cleanupLine(AnnotatedLine *Line) {
3101 for (auto *Child : Line->Children)
3102 cleanupLine(Child);
3103
3104 if (Line->Affected) {
3105 cleanupRight(Line->First, tok::comma, tok::comma);
3106 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
3107 cleanupRight(Line->First, tok::l_paren, tok::comma);
3108 cleanupLeft(Line->First, tok::comma, tok::r_paren);
3109 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
3110 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
3111 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
3112 }
3113 }
3114
3115 bool containsOnlyComments(const AnnotatedLine &Line) {
3116 for (FormatToken *Tok = Line.First; Tok; Tok = Tok->Next)
3117 if (Tok->isNot(tok::comment))
3118 return false;
3119 return true;
3120 }
3121
3122 // Iterate through all lines and remove any empty (nested) namespaces.
3123 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
3124 std::set<unsigned> DeletedLines;
3125 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
3126 auto &Line = *AnnotatedLines[i];
3127 if (Line.startsWithNamespace())
3128 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
3129 }
3130
3131 for (auto Line : DeletedLines) {
3132 FormatToken *Tok = AnnotatedLines[Line]->First;
3133 while (Tok) {
3134 deleteToken(Tok);
3135 Tok = Tok->Next;
3136 }
3137 }
3138 }
3139
3140 // The function checks if the namespace, which starts from \p CurrentLine, and
3141 // its nested namespaces are empty and delete them if they are empty. It also
3142 // sets \p NewLine to the last line checked.
3143 // Returns true if the current namespace is empty.
3144 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
3145 unsigned CurrentLine, unsigned &NewLine,
3146 std::set<unsigned> &DeletedLines) {
3147 unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
3148 if (Style.BraceWrapping.AfterNamespace) {
3149 // If the left brace is in a new line, we should consume it first so that
3150 // it does not make the namespace non-empty.
3151 // FIXME: error handling if there is no left brace.
3152 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
3153 NewLine = CurrentLine;
3154 return false;
3155 }
3156 } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
3157 return false;
3158 }
3159 while (++CurrentLine < End) {
3160 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
3161 break;
3162
3163 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
3164 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
3165 DeletedLines)) {
3166 return false;
3167 }
3168 CurrentLine = NewLine;
3169 continue;
3170 }
3171
3172 if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
3173 continue;
3174
3175 // If there is anything other than comments or nested namespaces in the
3176 // current namespace, the namespace cannot be empty.
3177 NewLine = CurrentLine;
3178 return false;
3179 }
3180
3181 NewLine = CurrentLine;
3182 if (CurrentLine >= End)
3183 return false;
3184
3185 // Check if the empty namespace is actually affected by changed ranges.
3186 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
3187 AnnotatedLines[InitLine]->First->Tok.getLocation(),
3188 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) {
3189 return false;
3190 }
3191
3192 for (unsigned i = InitLine; i <= CurrentLine; ++i)
3193 DeletedLines.insert(i);
3194
3195 return true;
3196 }
3197
3198 // Checks pairs {start, start->next},..., {end->previous, end} and deletes one
3199 // of the token in the pair if the left token has \p LK token kind and the
3200 // right token has \p RK token kind. If \p DeleteLeft is true, the left token
3201 // is deleted on match; otherwise, the right token is deleted.
3202 template <typename LeftKind, typename RightKind>
3203 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
3204 bool DeleteLeft) {
3205 auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {
3206 for (auto *Res = Tok.Next; Res; Res = Res->Next) {
3207 if (Res->isNot(tok::comment) &&
3208 DeletedTokens.find(Res) == DeletedTokens.end()) {
3209 return Res;
3210 }
3211 }
3212 return nullptr;
3213 };
3214 for (auto *Left = Start; Left;) {
3215 auto *Right = NextNotDeleted(*Left);
3216 if (!Right)
3217 break;
3218 if (Left->is(LK) && Right->is(RK)) {
3219 deleteToken(DeleteLeft ? Left : Right);
3220 for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
3221 deleteToken(Tok);
3222 // If the right token is deleted, we should keep the left token
3223 // unchanged and pair it with the new right token.
3224 if (!DeleteLeft)
3225 continue;
3226 }
3227 Left = Right;
3228 }
3229 }
3230
3231 template <typename LeftKind, typename RightKind>
3232 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
3233 cleanupPair(Start, LK, RK, /*DeleteLeft=*/true);
3234 }
3235
3236 template <typename LeftKind, typename RightKind>
3237 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
3238 cleanupPair(Start, LK, RK, /*DeleteLeft=*/false);
3239 }
3240
3241 // Delete the given token.
3242 inline void deleteToken(FormatToken *Tok) {
3243 if (Tok)
3244 DeletedTokens.insert(Tok);
3245 }
3246
3247 tooling::Replacements generateFixes() {
3248 tooling::Replacements Fixes;
3249 SmallVector<FormatToken *> Tokens;
3250 std::copy(DeletedTokens.begin(), DeletedTokens.end(),
3251 std::back_inserter(Tokens));
3252
3253 // Merge multiple continuous token deletions into one big deletion so that
3254 // the number of replacements can be reduced. This makes computing affected
3255 // ranges more efficient when we run reformat on the changed code.
3256 unsigned Idx = 0;
3257 while (Idx < Tokens.size()) {
3258 unsigned St = Idx, End = Idx;
3259 while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1])
3260 ++End;
3261 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
3262 Tokens[End]->Tok.getEndLoc());
3263 auto Err =
3264 Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, ""));
3265 // FIXME: better error handling. for now just print error message and skip
3266 // for the release version.
3267 if (Err) {
3268 llvm::errs() << toString(std::move(Err)) << "\n";
3269 assert(false && "Fixes must not conflict!");
3270 }
3271 Idx = End + 1;
3272 }
3273
3274 return Fixes;
3275 }
3276
3277 // Class for less-than inequality comparason for the set `RedundantTokens`.
3278 // We store tokens in the order they appear in the translation unit so that
3279 // we do not need to sort them in `generateFixes()`.
3280 struct FormatTokenLess {
3281 FormatTokenLess(const SourceManager &SM) : SM(SM) {}
3282
3283 bool operator()(const FormatToken *LHS, const FormatToken *RHS) const {
3284 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
3285 RHS->Tok.getLocation());
3286 }
3287 const SourceManager &SM;
3288 };
3289
3290 // Tokens to be deleted.
3291 std::set<FormatToken *, FormatTokenLess> DeletedTokens;
3292};
3293
3294class ObjCHeaderStyleGuesser : public TokenAnalyzer {
3295public:
3296 ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style)
3297 : TokenAnalyzer(Env, Style), IsObjC(false) {}
3298
3299 std::pair<tooling::Replacements, unsigned>
3300 analyze(TokenAnnotator &Annotator,
3301 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
3302 FormatTokenLexer &Tokens) override {
3303 assert(Style.Language == FormatStyle::LK_Cpp);
3304 IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines,
3305 Tokens.getKeywords());
3306 tooling::Replacements Result;
3307 return {Result, 0};
3308 }
3309
3310 bool isObjC() { return IsObjC; }
3311
3312private:
3313 static bool
3314 guessIsObjC(const SourceManager &SourceManager,
3315 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
3316 const AdditionalKeywords &Keywords) {
3317 // Keep this array sorted, since we are binary searching over it.
3318 static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
3319 "CGFloat",
3320 "CGPoint",
3321 "CGPointMake",
3322 "CGPointZero",
3323 "CGRect",
3324 "CGRectEdge",
3325 "CGRectInfinite",
3326 "CGRectMake",
3327 "CGRectNull",
3328 "CGRectZero",
3329 "CGSize",
3330 "CGSizeMake",
3331 "CGVector",
3332 "CGVectorMake",
3333 "FOUNDATION_EXPORT", // This is an alias for FOUNDATION_EXTERN.
3334 "FOUNDATION_EXTERN",
3335 "NSAffineTransform",
3336 "NSArray",
3337 "NSAttributedString",
3338 "NSBlockOperation",
3339 "NSBundle",
3340 "NSCache",
3341 "NSCalendar",
3342 "NSCharacterSet",
3343 "NSCountedSet",
3344 "NSData",
3345 "NSDataDetector",
3346 "NSDecimal",
3347 "NSDecimalNumber",
3348 "NSDictionary",
3349 "NSEdgeInsets",
3350 "NSError",
3351 "NSErrorDomain",
3352 "NSHashTable",
3353 "NSIndexPath",
3354 "NSIndexSet",
3355 "NSInteger",
3356 "NSInvocationOperation",
3357 "NSLocale",
3358 "NSMapTable",
3359 "NSMutableArray",
3360 "NSMutableAttributedString",
3361 "NSMutableCharacterSet",
3362 "NSMutableData",
3363 "NSMutableDictionary",
3364 "NSMutableIndexSet",
3365 "NSMutableOrderedSet",
3366 "NSMutableSet",
3367 "NSMutableString",
3368 "NSNumber",
3369 "NSNumberFormatter",
3370 "NSObject",
3371 "NSOperation",
3372 "NSOperationQueue",
3373 "NSOperationQueuePriority",
3374 "NSOrderedSet",
3375 "NSPoint",
3376 "NSPointerArray",
3377 "NSQualityOfService",
3378 "NSRange",
3379 "NSRect",
3380 "NSRegularExpression",
3381 "NSSet",
3382 "NSSize",
3383 "NSString",
3384 "NSTimeZone",
3385 "NSUInteger",
3386 "NSURL",
3387 "NSURLComponents",
3388 "NSURLQueryItem",
3389 "NSUUID",
3390 "NSValue",
3391 "NS_ASSUME_NONNULL_BEGIN",
3392 "UIImage",
3393 "UIView",
3394 };
3395 assert(llvm::is_sorted(FoundationIdentifiers));
3396
3397 for (auto *Line : AnnotatedLines) {
3398 if (Line->First && (Line->First->TokenText.starts_with("#") ||
3399 Line->First->TokenText == "__pragma" ||
3400 Line->First->TokenText == "_Pragma")) {
3401 continue;
3402 }
3403 for (const FormatToken *FormatTok = Line->First; FormatTok;
3404 FormatTok = FormatTok->Next) {
3405 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
3406 (FormatTok->isNot(tok::objc_not_keyword) ||
3407 FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
3408 tok::l_brace))) ||
3409 (FormatTok->Tok.isAnyIdentifier() &&
3410 llvm::binary_search(FoundationIdentifiers,
3411 FormatTok->TokenText)) ||
3412 FormatTok->is(TT_ObjCStringLiteral) ||
3413 FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,
3414 Keywords.kw_NS_ERROR_ENUM,
3415 Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,
3416 TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,
3417 TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,
3418 TT_ObjCProperty, TT_ObjCSelector)) {
3419 LLVM_DEBUG(llvm::dbgs()
3420 << "Detected ObjC at location "
3421 << FormatTok->Tok.getLocation().printToString(
3422 SourceManager)
3423 << " token: " << FormatTok->TokenText << " token type: "
3424 << getTokenTypeName(FormatTok->getType()) << "\n");
3425 return true;
3426 }
3427 }
3428 if (guessIsObjC(SourceManager, Line->Children, Keywords))
3429 return true;
3430 }
3431 return false;
3432 }
3433
3434 bool IsObjC;
3435};
3436
3437struct IncludeDirective {
3438 StringRef Filename;
3439 StringRef Text;
3440 unsigned Offset;
3441 int Category;
3442 int Priority;
3443};
3444
3445struct JavaImportDirective {
3446 StringRef Identifier;
3447 StringRef Text;
3448 unsigned Offset;
3449 SmallVector<StringRef> AssociatedCommentLines;
3450 bool IsStatic;
3451};
3452
3453} // end anonymous namespace
3454
3455// Determines whether 'Ranges' intersects with ('Start', 'End').
3456static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start,
3457 unsigned End) {
3458 for (const auto &Range : Ranges) {
3459 if (Range.getOffset() < End &&
3460 Range.getOffset() + Range.getLength() > Start) {
3461 return true;
3462 }
3463 }
3464 return false;
3465}
3466
3467// Returns a pair (Index, OffsetToEOL) describing the position of the cursor
3468// before sorting/deduplicating. Index is the index of the include under the
3469// cursor in the original set of includes. If this include has duplicates, it is
3470// the index of the first of the duplicates as the others are going to be
3471// removed. OffsetToEOL describes the cursor's position relative to the end of
3472// its current line.
3473// If `Cursor` is not on any #include, `Index` will be
3474// std::numeric_limits<unsigned>::max().
3475static std::pair<unsigned, unsigned>
3477 const ArrayRef<unsigned> &Indices, unsigned Cursor) {
3478 unsigned CursorIndex = std::numeric_limits<unsigned>::max();
3479 unsigned OffsetToEOL = 0;
3480 for (int i = 0, e = Includes.size(); i != e; ++i) {
3481 unsigned Start = Includes[Indices[i]].Offset;
3482 unsigned End = Start + Includes[Indices[i]].Text.size();
3483 if (!(Cursor >= Start && Cursor < End))
3484 continue;
3485 CursorIndex = Indices[i];
3486 OffsetToEOL = End - Cursor;
3487 // Put the cursor on the only remaining #include among the duplicate
3488 // #includes.
3489 while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text)
3490 CursorIndex = i;
3491 break;
3492 }
3493 return std::make_pair(CursorIndex, OffsetToEOL);
3494}
3495
3496// Replace all "\r\n" with "\n".
3497std::string replaceCRLF(const std::string &Code) {
3498 std::string NewCode;
3499 size_t Pos = 0, LastPos = 0;
3500
3501 do {
3502 Pos = Code.find("\r\n", LastPos);
3503 if (Pos == LastPos) {
3504 ++LastPos;
3505 continue;
3506 }
3507 if (Pos == std::string::npos) {
3508 NewCode += Code.substr(LastPos);
3509 break;
3510 }
3511 NewCode += Code.substr(LastPos, Pos - LastPos) + "\n";
3512 LastPos = Pos + 2;
3513 } while (Pos != std::string::npos);
3514
3515 return NewCode;
3516}
3517
3518// Sorts and deduplicate a block of includes given by 'Includes' alphabetically
3519// adding the necessary replacement to 'Replaces'. 'Includes' must be in strict
3520// source order.
3521// #include directives with the same text will be deduplicated, and only the
3522// first #include in the duplicate #includes remains. If the `Cursor` is
3523// provided and put on a deleted #include, it will be moved to the remaining
3524// #include in the duplicate #includes.
3525static void sortCppIncludes(const FormatStyle &Style,
3526 const ArrayRef<IncludeDirective> &Includes,
3527 ArrayRef<tooling::Range> Ranges, StringRef FileName,
3528 StringRef Code, tooling::Replacements &Replaces,
3529 unsigned *Cursor) {
3530 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
3531 const unsigned IncludesBeginOffset = Includes.front().Offset;
3532 const unsigned IncludesEndOffset =
3533 Includes.back().Offset + Includes.back().Text.size();
3534 const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
3535 if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
3536 return;
3538 llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size()));
3539
3540 if (Style.SortIncludes.Enabled) {
3541 stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
3542 SmallString<128> LHSStem, RHSStem;
3543 if (Style.SortIncludes.IgnoreExtension) {
3544 LHSStem = Includes[LHSI].Filename;
3545 RHSStem = Includes[RHSI].Filename;
3546 llvm::sys::path::replace_extension(LHSStem, "");
3547 llvm::sys::path::replace_extension(RHSStem, "");
3548 }
3549 std::string LHSStemLower, RHSStemLower;
3550 std::string LHSFilenameLower, RHSFilenameLower;
3551 if (Style.SortIncludes.IgnoreCase) {
3552 LHSStemLower = LHSStem.str().lower();
3553 RHSStemLower = RHSStem.str().lower();
3554 LHSFilenameLower = Includes[LHSI].Filename.lower();
3555 RHSFilenameLower = Includes[RHSI].Filename.lower();
3556 }
3557 return std::tie(Includes[LHSI].Priority, LHSStemLower, LHSStem,
3558 LHSFilenameLower, Includes[LHSI].Filename) <
3559 std::tie(Includes[RHSI].Priority, RHSStemLower, RHSStem,
3560 RHSFilenameLower, Includes[RHSI].Filename);
3561 });
3562 }
3563
3564 // The index of the include on which the cursor will be put after
3565 // sorting/deduplicating.
3566 unsigned CursorIndex;
3567 // The offset from cursor to the end of line.
3568 unsigned CursorToEOLOffset;
3569 if (Cursor) {
3570 std::tie(CursorIndex, CursorToEOLOffset) =
3571 FindCursorIndex(Includes, Indices, *Cursor);
3572 }
3573
3574 // Deduplicate #includes.
3575 Indices.erase(llvm::unique(Indices,
3576 [&](unsigned LHSI, unsigned RHSI) {
3577 return Includes[LHSI].Text.trim() ==
3578 Includes[RHSI].Text.trim();
3579 }),
3580 Indices.end());
3581
3582 int CurrentCategory = Includes.front().Category;
3583
3584 // If the #includes are out of order, we generate a single replacement fixing
3585 // the entire block. Otherwise, no replacement is generated.
3586 // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not
3587 // enough as additional newlines might be added or removed across #include
3588 // blocks. This we handle below by generating the updated #include blocks and
3589 // comparing it to the original.
3590 if (Indices.size() == Includes.size() && is_sorted(Indices) &&
3591 Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) {
3592 return;
3593 }
3594
3595 const auto OldCursor = Cursor ? *Cursor : 0;
3596 std::string result;
3597 for (unsigned Index : Indices) {
3598 if (!result.empty()) {
3599 result += "\n";
3600 if (Style.IncludeStyle.IncludeBlocks ==
3602 CurrentCategory != Includes[Index].Category) {
3603 result += "\n";
3604 }
3605 }
3606 result += Includes[Index].Text;
3607 if (Cursor && CursorIndex == Index)
3608 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
3609 CurrentCategory = Includes[Index].Category;
3610 }
3611
3612 if (Cursor && *Cursor >= IncludesEndOffset)
3613 *Cursor += result.size() - IncludesBlockSize;
3614
3615 // If the #includes are out of order, we generate a single replacement fixing
3616 // the entire range of blocks. Otherwise, no replacement is generated.
3617 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
3618 IncludesBeginOffset, IncludesBlockSize)))) {
3619 if (Cursor)
3620 *Cursor = OldCursor;
3621 return;
3622 }
3623
3624 auto Err = Replaces.add(tooling::Replacement(
3625 FileName, Includes.front().Offset, IncludesBlockSize, result));
3626 // FIXME: better error handling. For now, just skip the replacement for the
3627 // release version.
3628 if (Err) {
3629 llvm::errs() << toString(std::move(Err)) << "\n";
3630 assert(false);
3631 }
3632}
3633
3634tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
3636 StringRef FileName,
3637 tooling::Replacements &Replaces,
3638 unsigned *Cursor) {
3639 unsigned Prev = llvm::StringSwitch<size_t>(Code)
3640 .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM
3641 .Default(0);
3642 unsigned SearchFrom = 0;
3644 SmallVector<IncludeDirective, 16> IncludesInBlock;
3645
3646 // In compiled files, consider the first #include to be the main #include of
3647 // the file if it is not a system #include. This ensures that the header
3648 // doesn't have hidden dependencies
3649 // (http://llvm.org/docs/CodingStandards.html#include-style).
3650 //
3651 // FIXME: Do some validation, e.g. edit distance of the base name, to fix
3652 // cases where the first #include is unlikely to be the main header.
3653 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
3654 bool FirstIncludeBlock = true;
3655 bool MainIncludeFound = false;
3656 bool FormattingOff = false;
3657
3658 // '[' must be the first and '-' the last character inside [...].
3659 llvm::Regex RawStringRegex(
3660 "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\(");
3661 SmallVector<StringRef, 2> RawStringMatches;
3662 std::string RawStringTermination = ")\"";
3663
3664 for (const auto Size = Code.size(); SearchFrom < Size;) {
3665 size_t Pos = SearchFrom;
3666 if (Code[SearchFrom] != '\n') {
3667 do { // Search for the first newline while skipping line splices.
3668 ++Pos;
3669 Pos = Code.find('\n', Pos);
3670 } while (Pos != StringRef::npos && Code[Pos - 1] == '\\');
3671 }
3672
3673 StringRef Line =
3674 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3675
3676 StringRef Trimmed = Line.trim();
3677
3678 // #includes inside raw string literals need to be ignored.
3679 // or we will sort the contents of the string.
3680 // Skip past until we think we are at the rawstring literal close.
3681 if (RawStringRegex.match(Trimmed, &RawStringMatches)) {
3682 std::string CharSequence = RawStringMatches[1].str();
3683 RawStringTermination = ")" + CharSequence + "\"";
3684 FormattingOff = true;
3685 }
3686
3687 if (Trimmed.contains(RawStringTermination))
3688 FormattingOff = false;
3689
3690 bool IsBlockComment = false;
3691
3692 if (isClangFormatOff(Trimmed)) {
3693 FormattingOff = true;
3694 } else if (isClangFormatOn(Trimmed)) {
3695 FormattingOff = false;
3696 } else if (Trimmed.starts_with("/*")) {
3697 IsBlockComment = true;
3698 Pos = Code.find("*/", SearchFrom + 2);
3699 }
3700
3701 const bool EmptyLineSkipped =
3702 Trimmed.empty() &&
3703 (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge ||
3704 Style.IncludeStyle.IncludeBlocks ==
3706
3707 bool MergeWithNextLine = Trimmed.ends_with("\\");
3708 if (!FormattingOff && !MergeWithNextLine) {
3709 if (!IsBlockComment &&
3710 tooling::HeaderIncludes::IncludeRegex.match(Trimmed, &Matches)) {
3711 StringRef IncludeName = Matches[2];
3712 if (Trimmed.contains("/*") && !Trimmed.contains("*/")) {
3713 // #include with a start of a block comment, but without the end.
3714 // Need to keep all the lines until the end of the comment together.
3715 // FIXME: This is somehow simplified check that probably does not work
3716 // correctly if there are multiple comments on a line.
3717 Pos = Code.find("*/", SearchFrom);
3718 Line = Code.substr(
3719 Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev);
3720 }
3721 int Category = Categories.getIncludePriority(
3722 IncludeName,
3723 /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock);
3724 int Priority = Categories.getSortIncludePriority(
3725 IncludeName, !MainIncludeFound && FirstIncludeBlock);
3726 if (Category == 0)
3727 MainIncludeFound = true;
3728 IncludesInBlock.push_back(
3729 {IncludeName, Line, Prev, Category, Priority});
3730 } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
3731 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code,
3732 Replaces, Cursor);
3733 IncludesInBlock.clear();
3734 if (Trimmed.starts_with("#pragma hdrstop")) // Precompiled headers.
3735 FirstIncludeBlock = true;
3736 else
3737 FirstIncludeBlock = false;
3738 }
3739 }
3740 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3741 break;
3742
3743 if (!MergeWithNextLine)
3744 Prev = Pos + 1;
3745 SearchFrom = Pos + 1;
3746 }
3747 if (!IncludesInBlock.empty()) {
3748 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces,
3749 Cursor);
3750 }
3751 return Replaces;
3752}
3753
3754// Returns group number to use as a first order sort on imports. Gives
3755// std::numeric_limits<unsigned>::max() if the import does not match any given
3756// groups.
3757static unsigned findJavaImportGroup(const FormatStyle &Style,
3758 StringRef ImportIdentifier) {
3759 unsigned LongestMatchIndex = std::numeric_limits<unsigned>::max();
3760 unsigned LongestMatchLength = 0;
3761 for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) {
3762 const std::string &GroupPrefix = Style.JavaImportGroups[I];
3763 if (ImportIdentifier.starts_with(GroupPrefix) &&
3764 GroupPrefix.length() > LongestMatchLength) {
3765 LongestMatchIndex = I;
3766 LongestMatchLength = GroupPrefix.length();
3767 }
3768 }
3769 return LongestMatchIndex;
3770}
3771
3772// Sorts and deduplicates a block of includes given by 'Imports' based on
3773// JavaImportGroups, then adding the necessary replacement to 'Replaces'.
3774// Import declarations with the same text will be deduplicated. Between each
3775// import group, a newline is inserted, and within each import group, a
3776// lexicographic sort based on ASCII value is performed.
3777static void sortJavaImports(const FormatStyle &Style,
3778 const ArrayRef<JavaImportDirective> &Imports,
3779 ArrayRef<tooling::Range> Ranges, StringRef FileName,
3780 StringRef Code, tooling::Replacements &Replaces) {
3781 unsigned ImportsBeginOffset = Imports.front().Offset;
3782 unsigned ImportsEndOffset =
3783 Imports.back().Offset + Imports.back().Text.size();
3784 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;
3785 if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))
3786 return;
3787
3789 llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size()));
3791 JavaImportGroups.reserve(Imports.size());
3792 for (const JavaImportDirective &Import : Imports)
3793 JavaImportGroups.push_back(findJavaImportGroup(Style, Import.Identifier));
3794
3795 bool StaticImportAfterNormalImport =
3796 Style.SortJavaStaticImport == FormatStyle::SJSIO_After;
3797 sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
3798 // Negating IsStatic to push static imports above non-static imports.
3799 return std::make_tuple(!Imports[LHSI].IsStatic ^
3800 StaticImportAfterNormalImport,
3801 JavaImportGroups[LHSI], Imports[LHSI].Identifier) <
3802 std::make_tuple(!Imports[RHSI].IsStatic ^
3803 StaticImportAfterNormalImport,
3804 JavaImportGroups[RHSI], Imports[RHSI].Identifier);
3805 });
3806
3807 // Deduplicate imports.
3808 Indices.erase(llvm::unique(Indices,
3809 [&](unsigned LHSI, unsigned RHSI) {
3810 return Imports[LHSI].Text == Imports[RHSI].Text;
3811 }),
3812 Indices.end());
3813
3814 bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
3815 unsigned CurrentImportGroup = JavaImportGroups[Indices.front()];
3816
3817 std::string result;
3818 for (unsigned Index : Indices) {
3819 if (!result.empty()) {
3820 result += "\n";
3821 if (CurrentIsStatic != Imports[Index].IsStatic ||
3822 CurrentImportGroup != JavaImportGroups[Index]) {
3823 result += "\n";
3824 }
3825 }
3826 for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) {
3827 result += CommentLine;
3828 result += "\n";
3829 }
3830 result += Imports[Index].Text;
3831 CurrentIsStatic = Imports[Index].IsStatic;
3832 CurrentImportGroup = JavaImportGroups[Index];
3833 }
3834
3835 // If the imports are out of order, we generate a single replacement fixing
3836 // the entire block. Otherwise, no replacement is generated.
3837 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
3838 Imports.front().Offset, ImportsBlockSize)))) {
3839 return;
3840 }
3841
3842 auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset,
3843 ImportsBlockSize, result));
3844 // FIXME: better error handling. For now, just skip the replacement for the
3845 // release version.
3846 if (Err) {
3847 llvm::errs() << toString(std::move(Err)) << "\n";
3848 assert(false);
3849 }
3850}
3851
3852namespace {
3853
3854constexpr StringRef
3855 JavaImportRegexPattern("^import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;");
3856
3857constexpr StringRef JavaPackageRegexPattern("^package[\t ]");
3858
3859} // anonymous namespace
3860
3861tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code,
3863 StringRef FileName,
3864 tooling::Replacements &Replaces) {
3865 unsigned Prev = 0;
3866 bool HasImport = false;
3867 llvm::Regex ImportRegex(JavaImportRegexPattern);
3868 llvm::Regex PackageRegex(JavaPackageRegexPattern);
3871 SmallVector<StringRef> AssociatedCommentLines;
3872
3873 for (bool FormattingOff = false;;) {
3874 auto Pos = Code.find('\n', Prev);
3875 auto GetLine = [&] {
3876 return Code.substr(Prev,
3877 (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3878 };
3879 StringRef Line = GetLine();
3880
3881 StringRef Trimmed = Line.trim();
3882 if (Trimmed.empty() || PackageRegex.match(Trimmed)) {
3883 // Skip empty line and package statement.
3884 } else if (isClangFormatOff(Trimmed)) {
3885 FormattingOff = true;
3886 } else if (isClangFormatOn(Trimmed)) {
3887 FormattingOff = false;
3888 } else if (Trimmed.starts_with("//")) {
3889 // Associating comments within the imports with the nearest import below.
3890 if (HasImport)
3891 AssociatedCommentLines.push_back(Line);
3892 } else if (Trimmed.starts_with("/*")) {
3893 Pos = Code.find("*/", Pos + 2);
3894 if (Pos != StringRef::npos)
3895 Pos = Code.find('\n', Pos + 2);
3896 if (HasImport) {
3897 // Extend `Line` for a multiline comment to include all lines the
3898 // comment spans.
3899 Line = GetLine();
3900 AssociatedCommentLines.push_back(Line);
3901 }
3902 } else if (ImportRegex.match(Trimmed, &Matches)) {
3903 if (FormattingOff) {
3904 // If at least one import line has formatting turned off, turn off
3905 // formatting entirely.
3906 return Replaces;
3907 }
3908 StringRef Static = Matches[1];
3909 StringRef Identifier = Matches[2];
3910 bool IsStatic = false;
3911 if (Static.contains("static"))
3912 IsStatic = true;
3913 ImportsInBlock.push_back(
3914 {Identifier, Line, Prev, AssociatedCommentLines, IsStatic});
3915 HasImport = true;
3916 AssociatedCommentLines.clear();
3917 } else {
3918 // `Trimmed` is neither empty, nor a comment or a package/import
3919 // statement.
3920 break;
3921 }
3922 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3923 break;
3924 Prev = Pos + 1;
3925 }
3926 if (HasImport)
3927 sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces);
3928 return Replaces;
3929}
3930
3931bool isMpegTS(StringRef Code) {
3932 // MPEG transport streams use the ".ts" file extension. clang-format should
3933 // not attempt to format those. MPEG TS' frame format starts with 0x47 every
3934 // 189 bytes - detect that and return.
3935 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
3936}
3937
3938bool isLikelyXml(StringRef Code) { return Code.ltrim().starts_with("<"); }
3939
3940tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
3942 StringRef FileName, unsigned *Cursor) {
3943 tooling::Replacements Replaces;
3944 if (!Style.SortIncludes.Enabled || Style.DisableFormat)
3945 return Replaces;
3946 if (isLikelyXml(Code))
3947 return Replaces;
3948 if (Style.isJavaScript()) {
3949 if (isMpegTS(Code))
3950 return Replaces;
3951 return sortJavaScriptImports(Style, Code, Ranges, FileName);
3952 }
3953 if (Style.isJava())
3954 return sortJavaImports(Style, Code, Ranges, FileName, Replaces);
3955 if (Style.isCpp())
3956 sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor);
3957 return Replaces;
3958}
3959
3960template <typename T>
3962processReplacements(T ProcessFunc, StringRef Code,
3963 const tooling::Replacements &Replaces,
3964 const FormatStyle &Style) {
3965 if (Replaces.empty())
3966 return tooling::Replacements();
3967
3968 auto NewCode = applyAllReplacements(Code, Replaces);
3969 if (!NewCode)
3970 return NewCode.takeError();
3971 std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();
3972 StringRef FileName = Replaces.begin()->getFilePath();
3973
3974 tooling::Replacements FormatReplaces =
3975 ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
3976
3977 return Replaces.merge(FormatReplaces);
3978}
3979
3981formatReplacements(StringRef Code, const tooling::Replacements &Replaces,
3982 const FormatStyle &Style) {
3983 // We need to use lambda function here since there are two versions of
3984 // `sortIncludes`.
3985 auto SortIncludes = [](const FormatStyle &Style, StringRef Code,
3986 std::vector<tooling::Range> Ranges,
3987 StringRef FileName) -> tooling::Replacements {
3988 return sortIncludes(Style, Code, Ranges, FileName);
3989 };
3990 auto SortedReplaces =
3991 processReplacements(SortIncludes, Code, Replaces, Style);
3992 if (!SortedReplaces)
3993 return SortedReplaces.takeError();
3994
3995 // We need to use lambda function here since there are two versions of
3996 // `reformat`.
3997 auto Reformat = [](const FormatStyle &Style, StringRef Code,
3998 std::vector<tooling::Range> Ranges,
3999 StringRef FileName) -> tooling::Replacements {
4000 return reformat(Style, Code, Ranges, FileName);
4001 };
4002 return processReplacements(Reformat, Code, *SortedReplaces, Style);
4003}
4004
4005namespace {
4006
4007inline bool isHeaderInsertion(const tooling::Replacement &Replace) {
4008 return Replace.getOffset() == std::numeric_limits<unsigned>::max() &&
4009 Replace.getLength() == 0 &&
4011 Replace.getReplacementText());
4012}
4013
4014inline bool isHeaderDeletion(const tooling::Replacement &Replace) {
4015 return Replace.getOffset() == std::numeric_limits<unsigned>::max() &&
4016 Replace.getLength() == 1;
4017}
4018
4019// FIXME: insert empty lines between newly created blocks.
4020tooling::Replacements
4021fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
4022 const FormatStyle &Style) {
4023 if (!Style.isCpp())
4024 return Replaces;
4025
4026 tooling::Replacements HeaderInsertions;
4027 std::set<StringRef> HeadersToDelete;
4028 tooling::Replacements Result;
4029 for (const auto &R : Replaces) {
4030 if (isHeaderInsertion(R)) {
4031 // Replacements from \p Replaces must be conflict-free already, so we can
4032 // simply consume the error.
4033 consumeError(HeaderInsertions.add(R));
4034 } else if (isHeaderDeletion(R)) {
4035 HeadersToDelete.insert(R.getReplacementText());
4036 } else if (R.getOffset() == std::numeric_limits<unsigned>::max()) {
4037 llvm::errs() << "Insertions other than header #include insertion are "
4038 "not supported! "
4039 << R.getReplacementText() << "\n";
4040 } else {
4041 consumeError(Result.add(R));
4042 }
4043 }
4044 if (HeaderInsertions.empty() && HeadersToDelete.empty())
4045 return Replaces;
4046
4047 StringRef FileName = Replaces.begin()->getFilePath();
4048 tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle);
4049
4050 for (const auto &Header : HeadersToDelete) {
4051 tooling::Replacements Replaces =
4052 Includes.remove(Header.trim("\"<>"), Header.starts_with("<"));
4053 for (const auto &R : Replaces) {
4054 auto Err = Result.add(R);
4055 if (Err) {
4056 // Ignore the deletion on conflict.
4057 llvm::errs() << "Failed to add header deletion replacement for "
4058 << Header << ": " << toString(std::move(Err)) << "\n";
4059 }
4060 }
4061 }
4062
4064 for (const auto &R : HeaderInsertions) {
4065 auto IncludeDirective = R.getReplacementText();
4066 bool Matched =
4067 tooling::HeaderIncludes::IncludeRegex.match(IncludeDirective, &Matches);
4068 assert(Matched && "Header insertion replacement must have replacement text "
4069 "'#include ...'");
4070 (void)Matched;
4071 auto IncludeName = Matches[2];
4072 auto Replace =
4073 Includes.insert(IncludeName.trim("\"<>"), IncludeName.starts_with("<"),
4075 if (Replace) {
4076 auto Err = Result.add(*Replace);
4077 if (Err) {
4078 consumeError(std::move(Err));
4079 unsigned NewOffset =
4080 Result.getShiftedCodePosition(Replace->getOffset());
4081 auto Shifted = tooling::Replacement(FileName, NewOffset, 0,
4082 Replace->getReplacementText());
4083 Result = Result.merge(tooling::Replacements(Shifted));
4084 }
4085 }
4086 }
4087 return Result;
4088}
4089
4090} // anonymous namespace
4091
4093cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
4094 const FormatStyle &Style) {
4095 // We need to use lambda function here since there are two versions of
4096 // `cleanup`.
4097 auto Cleanup = [](const FormatStyle &Style, StringRef Code,
4099 StringRef FileName) -> tooling::Replacements {
4100 return cleanup(Style, Code, Ranges, FileName);
4101 };
4102 // Make header insertion replacements insert new headers into correct blocks.
4103 tooling::Replacements NewReplaces =
4104 fixCppIncludeInsertions(Code, Replaces, Style);
4105 return cantFail(processReplacements(Cleanup, Code, NewReplaces, Style));
4106}
4107
4108namespace internal {
4109std::pair<tooling::Replacements, unsigned>
4110reformat(const FormatStyle &Style, StringRef Code,
4111 ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,
4112 unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,
4113 FormattingAttemptStatus *Status) {
4114 FormatStyle Expanded = Style;
4118
4119 // These are handled by separate passes.
4120 Expanded.InsertBraces = false;
4121 Expanded.RemoveBracesLLVM = false;
4122 Expanded.RemoveParentheses = FormatStyle::RPS_Leave;
4123 Expanded.RemoveSemicolon = false;
4124
4125 // Make some sanity adjustments.
4126 switch (Expanded.RequiresClausePosition) {
4127 case FormatStyle::RCPS_SingleLine:
4128 case FormatStyle::RCPS_WithPreceding:
4129 Expanded.IndentRequiresClause = false;
4130 break;
4131 default:
4132 break;
4133 }
4134 if (Expanded.BraceWrapping.AfterEnum)
4135 Expanded.AllowShortEnumsOnASingleLine = false;
4136
4137 if (Expanded.DisableFormat)
4138 return {tooling::Replacements(), 0};
4139 if (isLikelyXml(Code))
4140 return {tooling::Replacements(), 0};
4141 if (Expanded.isJavaScript() && isMpegTS(Code))
4142 return {tooling::Replacements(), 0};
4143
4144 // JSON only needs the formatting passing.
4145 if (Style.isJson()) {
4146 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
4147 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
4148 NextStartColumn, LastStartColumn);
4149 if (!Env)
4150 return {};
4151 // Perform the actual formatting pass.
4152 tooling::Replacements Replaces =
4153 Formatter(*Env, Style, Status).process().first;
4154 // add a replacement to remove the "x = " from the result.
4155 if (Code.starts_with("x = ")) {
4156 Replaces = Replaces.merge(
4158 }
4159 // apply the reformatting changes and the removal of "x = ".
4160 if (applyAllReplacements(Code, Replaces))
4161 return {Replaces, 0};
4162 return {tooling::Replacements(), 0};
4163 }
4164
4165 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
4166 NextStartColumn, LastStartColumn);
4167 if (!Env)
4168 return {};
4169
4171 const Environment &)>
4173
4175
4176 Passes.emplace_back([&](const Environment &Env) {
4177 return IntegerLiteralSeparatorFixer().process(Env, Expanded);
4178 });
4179
4180 Passes.emplace_back([&](const Environment &Env) {
4181 return NumericLiteralCaseFixer().process(Env, Expanded);
4182 });
4183
4184 if (Style.isCpp()) {
4185 if (Style.QualifierAlignment != FormatStyle::QAS_Leave)
4186 addQualifierAlignmentFixerPasses(Expanded, Passes);
4187
4188 if (Style.RemoveParentheses != FormatStyle::RPS_Leave) {
4189 FormatStyle S = Expanded;
4190 S.RemoveParentheses = Style.RemoveParentheses;
4191 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
4192 return ParensRemover(Env, S).process(/*SkipAnnotation=*/true);
4193 });
4194 }
4195
4196 if (Style.InsertBraces) {
4197 FormatStyle S = Expanded;
4198 S.InsertBraces = true;
4199 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
4200 return BracesInserter(Env, S).process(/*SkipAnnotation=*/true);
4201 });
4202 }
4203
4204 if (Style.RemoveBracesLLVM) {
4205 FormatStyle S = Expanded;
4206 S.RemoveBracesLLVM = true;
4207 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
4208 return BracesRemover(Env, S).process(/*SkipAnnotation=*/true);
4209 });
4210 }
4211
4212 if (Style.RemoveSemicolon) {
4213 FormatStyle S = Expanded;
4214 S.RemoveSemicolon = true;
4215 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
4216 return SemiRemover(Env, S).process();
4217 });
4218 }
4219
4220 if (Style.EnumTrailingComma != FormatStyle::ETC_Leave) {
4221 Passes.emplace_back([&](const Environment &Env) {
4222 return EnumTrailingCommaEditor(Env, Expanded)
4223 .process(/*SkipAnnotation=*/true);
4224 });
4225 }
4226
4227 if (Style.FixNamespaceComments) {
4228 Passes.emplace_back([&](const Environment &Env) {
4229 return NamespaceEndCommentsFixer(Env, Expanded).process();
4230 });
4231 }
4232
4233 if (Style.SortUsingDeclarations != FormatStyle::SUD_Never) {
4234 Passes.emplace_back([&](const Environment &Env) {
4235 return UsingDeclarationsSorter(Env, Expanded).process();
4236 });
4237 }
4238 }
4239
4240 if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) {
4241 Passes.emplace_back([&](const Environment &Env) {
4242 return DefinitionBlockSeparator(Env, Expanded).process();
4243 });
4244 }
4245
4246 if (Style.Language == FormatStyle::LK_ObjC &&
4247 !Style.ObjCPropertyAttributeOrder.empty()) {
4248 Passes.emplace_back([&](const Environment &Env) {
4249 return ObjCPropertyAttributeOrderFixer(Env, Expanded).process();
4250 });
4251 }
4252
4253 if (Style.isJavaScript() &&
4254 Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) {
4255 Passes.emplace_back([&](const Environment &Env) {
4256 return JavaScriptRequoter(Env, Expanded).process(/*SkipAnnotation=*/true);
4257 });
4258 }
4259
4260 Passes.emplace_back([&](const Environment &Env) {
4261 return Formatter(Env, Expanded, Status).process();
4262 });
4263
4264 if (Style.isJavaScript() &&
4265 Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) {
4266 Passes.emplace_back([&](const Environment &Env) {
4267 return TrailingCommaInserter(Env, Expanded).process();
4268 });
4269 }
4270
4271 std::optional<std::string> CurrentCode;
4273 unsigned Penalty = 0;
4274 for (size_t I = 0, E = Passes.size(); I < E; ++I) {
4275 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
4276 auto NewCode = applyAllReplacements(
4277 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
4278 if (NewCode) {
4279 Fixes = Fixes.merge(PassFixes.first);
4280 Penalty += PassFixes.second;
4281 if (I + 1 < E) {
4282 CurrentCode = std::move(*NewCode);
4283 Env = Environment::make(
4284 *CurrentCode, FileName,
4286 FirstStartColumn, NextStartColumn, LastStartColumn);
4287 if (!Env)
4288 return {};
4289 }
4290 }
4291 }
4292
4293 if (Style.QualifierAlignment != FormatStyle::QAS_Leave) {
4294 // Don't make replacements that replace nothing. QualifierAlignment can
4295 // produce them if one of its early passes changes e.g. `const volatile` to
4296 // `volatile const` and then a later pass changes it back again.
4297 tooling::Replacements NonNoOpFixes;
4298 for (const tooling::Replacement &Fix : Fixes) {
4299 StringRef OriginalCode = Code.substr(Fix.getOffset(), Fix.getLength());
4300 if (OriginalCode != Fix.getReplacementText()) {
4301 auto Err = NonNoOpFixes.add(Fix);
4302 if (Err) {
4303 llvm::errs() << "Error adding replacements : "
4304 << toString(std::move(Err)) << "\n";
4305 }
4306 }
4307 }
4308 Fixes = std::move(NonNoOpFixes);
4309 }
4310
4311 return {Fixes, Penalty};
4312}
4313} // namespace internal
4314
4315tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
4317 StringRef FileName,
4318 FormattingAttemptStatus *Status) {
4319 return internal::reformat(Style, Code, Ranges,
4320 /*FirstStartColumn=*/0,
4321 /*NextStartColumn=*/0,
4322 /*LastStartColumn=*/0, FileName, Status)
4323 .first;
4324}
4325
4326tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
4328 StringRef FileName) {
4329 // cleanups only apply to C++ (they mostly concern ctor commas etc.)
4330 if (Style.Language != FormatStyle::LK_Cpp)
4331 return tooling::Replacements();
4332 auto Env = Environment::make(Code, FileName, Ranges);
4333 if (!Env)
4334 return {};
4335 return Cleaner(*Env, Style).process().first;
4336}
4337
4338tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
4340 StringRef FileName, bool *IncompleteFormat) {
4342 auto Result = reformat(Style, Code, Ranges, FileName, &Status);
4343 if (!Status.FormatComplete)
4344 *IncompleteFormat = true;
4345 return Result;
4346}
4347
4349 StringRef Code,
4351 StringRef FileName) {
4352 auto Env = Environment::make(Code, FileName, Ranges);
4353 if (!Env)
4354 return {};
4355 return NamespaceEndCommentsFixer(*Env, Style).process().first;
4356}
4357
4359 StringRef Code,
4361 StringRef FileName) {
4362 auto Env = Environment::make(Code, FileName, Ranges);
4363 if (!Env)
4364 return {};
4365 return UsingDeclarationsSorter(*Env, Style).process().first;
4366}
4367
4368LangOptions getFormattingLangOpts(const FormatStyle &Style) {
4369 LangOptions LangOpts;
4370
4371 auto LexingStd = Style.Standard;
4372 if (LexingStd == FormatStyle::LS_Auto || LexingStd == FormatStyle::LS_Latest)
4373 LexingStd = FormatStyle::LS_Cpp20;
4374
4375 const bool SinceCpp11 = LexingStd >= FormatStyle::LS_Cpp11;
4376 const bool SinceCpp20 = LexingStd >= FormatStyle::LS_Cpp20;
4377
4378 switch (Style.Language) {
4379 case FormatStyle::LK_C:
4380 LangOpts.C11 = 1;
4381 LangOpts.C23 = 1;
4382 break;
4383 case FormatStyle::LK_Cpp:
4384 case FormatStyle::LK_ObjC:
4385 LangOpts.CXXOperatorNames = 1;
4386 LangOpts.CPlusPlus11 = SinceCpp11;
4387 LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14;
4388 LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17;
4389 LangOpts.CPlusPlus20 = SinceCpp20;
4390 [[fallthrough]];
4391 default:
4392 LangOpts.CPlusPlus = 1;
4393 }
4394
4395 LangOpts.Char8 = SinceCpp20;
4396 LangOpts.AllowLiteralDigitSeparator = LangOpts.CPlusPlus14 || LangOpts.C23;
4397 // Turning on digraphs in standards before C++0x is error-prone, because e.g.
4398 // the sequence "<::" will be unconditionally treated as "[:".
4399 // Cf. Lexer::LexTokenInternal.
4400 LangOpts.Digraphs = SinceCpp11;
4401
4402 LangOpts.LineComment = 1;
4403 LangOpts.Bool = 1;
4404 LangOpts.ObjC = 1;
4405 LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally.
4406 LangOpts.DeclSpecKeyword = 1; // To get __declspec.
4407 LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict.
4408
4409 return LangOpts;
4410}
4411
4413 "Set coding style. <string> can be:\n"
4414 "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"
4415 " Mozilla, WebKit.\n"
4416 "2. 'file' to load style configuration from a\n"
4417 " .clang-format file in one of the parent directories\n"
4418 " of the source file (for stdin, see --assume-filename).\n"
4419 " If no .clang-format file is found, falls back to\n"
4420 " --fallback-style.\n"
4421 " --style=file is the default.\n"
4422 "3. 'file:<format_file_path>' to explicitly specify\n"
4423 " the configuration file.\n"
4424 "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n"
4425 " --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
4426
4427static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
4428 if (FileName.ends_with(".c"))
4429 return FormatStyle::LK_C;
4430 if (FileName.ends_with(".java"))
4431 return FormatStyle::LK_Java;
4432 if (FileName.ends_with_insensitive(".js") ||
4433 FileName.ends_with_insensitive(".mjs") ||
4434 FileName.ends_with_insensitive(".cjs") ||
4435 FileName.ends_with_insensitive(".ts")) {
4436 return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript.
4437 }
4438 if (FileName.ends_with(".m") || FileName.ends_with(".mm"))
4439 return FormatStyle::LK_ObjC;
4440 if (FileName.ends_with_insensitive(".proto") ||
4441 FileName.ends_with_insensitive(".protodevel")) {
4442 return FormatStyle::LK_Proto;
4443 }
4444 // txtpb is the canonical extension, and textproto is the legacy canonical
4445 // extension
4446 // https://protobuf.dev/reference/protobuf/textformat-spec/#text-format-files
4447 if (FileName.ends_with_insensitive(".txtpb") ||
4448 FileName.ends_with_insensitive(".textpb") ||
4449 FileName.ends_with_insensitive(".pb.txt") ||
4450 FileName.ends_with_insensitive(".textproto") ||
4451 FileName.ends_with_insensitive(".asciipb")) {
4452 return FormatStyle::LK_TextProto;
4453 }
4454 if (FileName.ends_with_insensitive(".td"))
4455 return FormatStyle::LK_TableGen;
4456 if (FileName.ends_with_insensitive(".cs"))
4457 return FormatStyle::LK_CSharp;
4458 if (FileName.ends_with_insensitive(".json") ||
4459 FileName.ends_with_insensitive(".ipynb")) {
4460 return FormatStyle::LK_Json;
4461 }
4462 if (FileName.ends_with_insensitive(".sv") ||
4463 FileName.ends_with_insensitive(".svh") ||
4464 FileName.ends_with_insensitive(".v") ||
4465 FileName.ends_with_insensitive(".vh")) {
4466 return FormatStyle::LK_Verilog;
4467 }
4468 return FormatStyle::LK_Cpp;
4469}
4470
4471static FormatStyle::LanguageKind getLanguageByComment(const Environment &Env) {
4472 const auto ID = Env.getFileID();
4473 const auto &SourceMgr = Env.getSourceManager();
4474
4475 LangOptions LangOpts;
4476 LangOpts.CPlusPlus = 1;
4477 LangOpts.LineComment = 1;
4478
4479 Lexer Lex(ID, SourceMgr.getBufferOrFake(ID), SourceMgr, LangOpts);
4480 Lex.SetCommentRetentionState(true);
4481
4482 for (Token Tok; !Lex.LexFromRawLexer(Tok) && Tok.is(tok::comment);) {
4483 auto Text = StringRef(SourceMgr.getCharacterData(Tok.getLocation()),
4484 Tok.getLength());
4485 if (!Text.consume_front("// clang-format Language:"))
4486 continue;
4487
4488 Text = Text.trim();
4489 if (Text == "C")
4490 return FormatStyle::LK_C;
4491 if (Text == "Cpp")
4492 return FormatStyle::LK_Cpp;
4493 if (Text == "ObjC")
4494 return FormatStyle::LK_ObjC;
4495 }
4496
4497 return FormatStyle::LK_None;
4498}
4499
4500FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {
4501 const auto GuessedLanguage = getLanguageByFileName(FileName);
4502 if (GuessedLanguage == FormatStyle::LK_Cpp) {
4503 auto Extension = llvm::sys::path::extension(FileName);
4504 // If there's no file extension (or it's .h), we need to check the contents
4505 // of the code to see if it contains Objective-C.
4506 if (!Code.empty() && (Extension.empty() || Extension == ".h")) {
4507 auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName;
4508 Environment Env(Code, NonEmptyFileName, /*Ranges=*/{});
4509 if (const auto Language = getLanguageByComment(Env);
4510 Language != FormatStyle::LK_None) {
4511 return Language;
4512 }
4513 ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle());
4514 Guesser.process();
4515 if (Guesser.isObjC())
4516 return FormatStyle::LK_ObjC;
4517 }
4518 }
4519 return GuessedLanguage;
4520}
4521
4522// Update StyleOptionHelpDescription above when changing this.
4523const char *DefaultFormatStyle = "file";
4524
4525const char *DefaultFallbackStyle = "LLVM";
4526
4527llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
4528loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS,
4529 FormatStyle *Style, bool AllowUnknownOptions,
4530 llvm::SourceMgr::DiagHandlerTy DiagHandler,
4531 bool IsDotHFile) {
4532 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
4533 FS->getBufferForFile(ConfigFile.str());
4534 if (auto EC = Text.getError())
4535 return EC;
4536 if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions,
4537 DiagHandler, /*DiagHandlerCtx=*/nullptr,
4538 IsDotHFile)) {
4539 return EC;
4540 }
4541 return Text;
4542}
4543
4544Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
4545 StringRef FallbackStyleName, StringRef Code,
4546 llvm::vfs::FileSystem *FS,
4547 bool AllowUnknownOptions,
4548 llvm::SourceMgr::DiagHandlerTy DiagHandler) {
4549 FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code));
4550 FormatStyle FallbackStyle = getNoStyle();
4551 if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))
4552 return make_string_error("Invalid fallback style: " + FallbackStyleName);
4553
4554 SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1> ChildFormatTextToApply;
4555
4556 if (StyleName.starts_with("{")) {
4557 // Parse YAML/JSON style from the command line.
4558 StringRef Source = "<command-line>";
4559 if (std::error_code ec =
4560 parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style,
4561 AllowUnknownOptions, DiagHandler)) {
4562 return make_string_error("Error parsing -style: " + ec.message());
4563 }
4564
4565 if (Style.InheritConfig.empty())
4566 return Style;
4567
4568 ChildFormatTextToApply.emplace_back(
4569 llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false));
4570 }
4571
4572 if (!FS)
4573 FS = llvm::vfs::getRealFileSystem().get();
4574 assert(FS);
4575
4576 const bool IsDotHFile = FileName.ends_with(".h");
4577
4578 // User provided clang-format file using -style=file:path/to/format/file.
4579 if (Style.InheritConfig.empty() &&
4580 StyleName.starts_with_insensitive("file:")) {
4581 auto ConfigFile = StyleName.substr(5);
4582 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
4583 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions,
4584 DiagHandler, IsDotHFile);
4585 if (auto EC = Text.getError()) {
4586 return make_string_error("Error reading " + ConfigFile + ": " +
4587 EC.message());
4588 }
4589
4590 LLVM_DEBUG(llvm::dbgs()
4591 << "Using configuration file " << ConfigFile << "\n");
4592
4593 if (Style.InheritConfig.empty())
4594 return Style;
4595
4596 // Search for parent configs starting from the parent directory of
4597 // ConfigFile.
4598 FileName = ConfigFile;
4599 ChildFormatTextToApply.emplace_back(std::move(*Text));
4600 }
4601
4602 // If the style inherits the parent configuration it is a command line
4603 // configuration, which wants to inherit, so we have to skip the check of the
4604 // StyleName.
4605 if (Style.InheritConfig.empty() && !StyleName.equals_insensitive("file")) {
4606 if (!getPredefinedStyle(StyleName, Style.Language, &Style))
4607 return make_string_error("Invalid value for -style");
4608 if (Style.InheritConfig.empty())
4609 return Style;
4610 }
4611
4612 using namespace llvm::sys::path;
4613 using String = SmallString<128>;
4614
4615 String Path(FileName);
4616 if (std::error_code EC = FS->makeAbsolute(Path))
4617 return make_string_error(EC.message());
4618
4619 auto Normalize = [](String &Path) {
4620 Path = convert_to_slash(Path);
4621 remove_dots(Path, /*remove_dot_dot=*/true, Style::posix);
4622 };
4623
4624 Normalize(Path);
4625
4626 // Reset possible inheritance
4627 Style.InheritConfig.clear();
4628
4629 auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {};
4630
4631 auto applyChildFormatTexts = [&](FormatStyle *Style) {
4632 for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) {
4633 auto EC =
4634 parseConfiguration(*MemBuf, Style, AllowUnknownOptions,
4635 DiagHandler ? DiagHandler : dropDiagnosticHandler);
4636 // It was already correctly parsed.
4637 assert(!EC);
4638 static_cast<void>(EC);
4639 }
4640 };
4641
4642 // Look for .clang-format/_clang-format file in the file's parent directories.
4643 SmallVector<std::string, 2> FilesToLookFor;
4644 FilesToLookFor.push_back(".clang-format");
4645 FilesToLookFor.push_back("_clang-format");
4646
4647 llvm::StringSet<> Directories; // Inherited directories.
4648 bool Redirected = false;
4649 String Dir, UnsuitableConfigFiles;
4650 for (StringRef Directory = Path; !Directory.empty();
4651 Directory = Redirected ? Dir.str() : parent_path(Directory)) {
4652 auto Status = FS->status(Directory);
4653 if (!Status ||
4654 Status->getType() != llvm::sys::fs::file_type::directory_file) {
4655 if (!Redirected)
4656 continue;
4657 return make_string_error("Failed to inherit configuration directory " +
4658 Directory);
4659 }
4660
4661 for (const auto &F : FilesToLookFor) {
4662 String ConfigFile(Directory);
4663
4664 append(ConfigFile, F);
4665 LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
4666
4667 Status = FS->status(ConfigFile);
4668 if (!Status ||
4669 Status->getType() != llvm::sys::fs::file_type::regular_file) {
4670 continue;
4671 }
4672
4673 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
4674 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions,
4675 DiagHandler, IsDotHFile);
4676 if (auto EC = Text.getError()) {
4677 if (EC != ParseError::Unsuitable) {
4678 return make_string_error("Error reading " + ConfigFile + ": " +
4679 EC.message());
4680 }
4681 if (!UnsuitableConfigFiles.empty())
4682 UnsuitableConfigFiles.append(", ");
4683 UnsuitableConfigFiles.append(ConfigFile);
4684 continue;
4685 }
4686
4687 LLVM_DEBUG(llvm::dbgs()
4688 << "Using configuration file " << ConfigFile << "\n");
4689
4690 if (Style.InheritConfig.empty()) {
4691 if (!ChildFormatTextToApply.empty()) {
4692 LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n");
4693 applyChildFormatTexts(&Style);
4694 }
4695 return Style;
4696 }
4697
4698 if (!Directories.insert(Directory).second) {
4699 return make_string_error(
4700 "Loop detected when inheriting configuration file in " + Directory);
4701 }
4702
4703 LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n");
4704
4705 if (Style.InheritConfig == "..") {
4706 Redirected = false;
4707 } else {
4708 Redirected = true;
4709 String ExpandedDir;
4710 llvm::sys::fs::expand_tilde(Style.InheritConfig, ExpandedDir);
4711 Normalize(ExpandedDir);
4712 if (is_absolute(ExpandedDir, Style::posix)) {
4713 Dir = ExpandedDir;
4714 } else {
4715 Dir = Directory.str();
4716 append(Dir, Style::posix, ExpandedDir);
4717 }
4718 }
4719
4720 // Reset inheritance of style
4721 Style.InheritConfig.clear();
4722
4723 ChildFormatTextToApply.emplace_back(std::move(*Text));
4724
4725 // Breaking out of the inner loop, since we don't want to parse
4726 // .clang-format AND _clang-format, if both exist. Then we continue the
4727 // outer loop (parent directories) in search for the parent
4728 // configuration.
4729 break;
4730 }
4731 }
4732
4733 if (!UnsuitableConfigFiles.empty()) {
4734 return make_string_error("Configuration file(s) do(es) not support " +
4735 getLanguageName(Style.Language) + ": " +
4736 UnsuitableConfigFiles);
4737 }
4738
4739 if (!ChildFormatTextToApply.empty()) {
4740 LLVM_DEBUG(llvm::dbgs()
4741 << "Applying child configurations on fallback style\n");
4742 applyChildFormatTexts(&FallbackStyle);
4743 }
4744
4745 return FallbackStyle;
4746}
4747
4748static bool isClangFormatOnOff(StringRef Comment, bool On) {
4749 if (Comment == (On ? "/* clang-format on */" : "/* clang-format off */"))
4750 return true;
4751
4752 static const char ClangFormatOn[] = "// clang-format on";
4753 static const char ClangFormatOff[] = "// clang-format off";
4754 const unsigned Size = (On ? sizeof ClangFormatOn : sizeof ClangFormatOff) - 1;
4755
4756 return Comment.starts_with(On ? ClangFormatOn : ClangFormatOff) &&
4757 (Comment.size() == Size || Comment[Size] == ':');
4758}
4759
4760bool isClangFormatOn(StringRef Comment) {
4761 return isClangFormatOnOff(Comment, /*On=*/true);
4762}
4763
4764bool isClangFormatOff(StringRef Comment) {
4765 return isClangFormatOnOff(Comment, /*On=*/false);
4766}
4767
4768} // namespace format
4769} // 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:6394
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:1584
std::string message(int EV) const override
Definition Format.cpp:1588
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:4110
void addQualifierAlignmentFixerPasses(const FormatStyle &Style, SmallVectorImpl< AnalyzerPass > &Passes)
static void expandPresetsSpaceBeforeParens(FormatStyle &Expanded)
Definition Format.cpp:1710
static bool affectsRange(ArrayRef< tooling::Range > Ranges, unsigned Start, unsigned End)
Definition Format.cpp:3456
const char * getTokenTypeName(TokenType Type)
Determines the name of a token type.
FormatStyle getWebKitStyle()
Definition Format.cpp:2225
bool isLikelyXml(StringRef Code)
Definition Format.cpp:3938
static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName)
Definition Format.cpp:4427
tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName, FormattingAttemptStatus *Status)
Definition Format.cpp:4315
const char * StyleOptionHelpDescription
Definition Format.cpp:4412
tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName)
Definition Format.cpp:4358
static unsigned findJavaImportGroup(const FormatStyle &Style, StringRef ImportIdentifier)
Definition Format.cpp:3757
std::string replaceCRLF(const std::string &Code)
Definition Format.cpp:3497
std::error_code make_error_code(ParseError e)
Definition Format.cpp:1575
const char * DefaultFallbackStyle
Definition Format.cpp:4525
FormatStyle getClangFormatStyle()
Definition Format.cpp:2293
std::function< std::pair< tooling::Replacements, unsigned >(const Environment &)> AnalyzerPass
const char * DefaultFormatStyle
Definition Format.cpp:4523
static void replaceToken(const SourceManager &SourceMgr, tooling::Replacements &Fixes, const CharSourceRange &Range, std::string NewText)
FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language)
Definition Format.cpp:1986
std::string configurationAsText(const FormatStyle &Style)
Definition Format.cpp:2476
FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language)
Definition Format.cpp:2264
const std::error_category & getParseCategory()
Definition Format.cpp:1571
FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code)
Definition Format.cpp:4500
bool isMpegTS(StringRef Code)
Definition Format.cpp:3931
tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName)
Definition Format.cpp:4348
static std::pair< unsigned, unsigned > FindCursorIndex(const ArrayRef< IncludeDirective > &Includes, const ArrayRef< unsigned > &Indices, unsigned Cursor)
Definition Format.cpp:3476
tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName)
Definition Format.cpp:4326
static FormatStyle::LanguageKind getLanguageByComment(const Environment &Env)
Definition Format.cpp:4471
FormatStyle getGNUStyle()
Definition Format.cpp:2249
bool isClangFormatOff(StringRef Comment)
Definition Format.cpp:4764
static bool isClangFormatOnOff(StringRef Comment, bool On)
Definition Format.cpp:4748
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:3777
FormatStyle getMozillaStyle()
Definition Format.cpp:2198
bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language, FormatStyle *Style)
Definition Format.cpp:2315
Expected< tooling::Replacements > cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, const FormatStyle &Style)
Definition Format.cpp:4093
static void expandPresetsBraceWrapping(FormatStyle &Expanded)
Definition Format.cpp:1610
tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName, unsigned *Cursor)
Definition Format.cpp:3940
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:3525
bool isClangFormatOn(StringRef Comment)
Definition Format.cpp:4760
FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language)
Definition Format.cpp:1742
Expected< FormatStyle > getStyle(StringRef StyleName, StringRef FileName, StringRef FallbackStyleName, StringRef Code, llvm::vfs::FileSystem *FS, bool AllowUnknownOptions, llvm::SourceMgr::DiagHandlerTy DiagHandler)
Definition Format.cpp:4544
llvm::Error make_string_error(const Twine &Message)
Definition Format.cpp:1579
ParseError validateQualifierOrder(FormatStyle *Style)
Definition Format.cpp:2348
FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language)
Definition Format.cpp:2138
static void expandPresetsSpacesInParens(FormatStyle &Expanded)
Definition Format.cpp:1734
std::error_code parseConfiguration(llvm::MemoryBufferRef Config, FormatStyle *Style, bool AllowUnknownOptions, llvm::SourceMgr::DiagHandlerTy DiagHandler, void *DiagHandlerCtxt, bool IsDotHFile)
Definition Format.cpp:2380
Expected< tooling::Replacements > formatReplacements(StringRef Code, const tooling::Replacements &Replaces, const FormatStyle &Style)
Definition Format.cpp:3981
FormatStyle getNoStyle()
Definition Format.cpp:2307
LangOptions getFormattingLangOpts(const FormatStyle &Style)
Definition Format.cpp:4368
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:4528
static Expected< tooling::Replacements > processReplacements(T ProcessFunc, StringRef Code, const tooling::Replacements &Replaces, const FormatStyle &Style)
Definition Format.cpp:3962
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:6264
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:1535
static size_t size(IO &IO, std::vector< FormatStyle > &Seq)
Definition Format.cpp:1532
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:1553
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