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