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