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