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 "FormatInternal.h"
20 #include "FormatTokenLexer.h"
21 #include "NamespaceEndCommentsFixer.h"
22 #include "SortJavaScriptImports.h"
23 #include "TokenAnalyzer.h"
24 #include "TokenAnnotator.h"
25 #include "UnwrappedLineFormatter.h"
26 #include "UnwrappedLineParser.h"
27 #include "UsingDeclarationsSorter.h"
28 #include "WhitespaceManager.h"
29 #include "clang/Basic/Diagnostic.h"
30 #include "clang/Basic/DiagnosticOptions.h"
31 #include "clang/Basic/SourceManager.h"
32 #include "clang/Lex/Lexer.h"
33 #include "clang/Tooling/Inclusions/HeaderIncludes.h"
34 #include "llvm/ADT/STLExtras.h"
35 #include "llvm/ADT/StringRef.h"
36 #include "llvm/Support/Allocator.h"
37 #include "llvm/Support/Debug.h"
38 #include "llvm/Support/Path.h"
39 #include "llvm/Support/Regex.h"
40 #include "llvm/Support/VirtualFileSystem.h"
41 #include "llvm/Support/YAMLTraits.h"
42 #include <algorithm>
43 #include <memory>
44 #include <mutex>
45 #include <string>
46 #include <unordered_map>
47 
48 #define DEBUG_TYPE "format-formatter"
49 
50 using clang::format::FormatStyle;
51 
52 LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat)
53 
54 namespace llvm {
55 namespace yaml {
56 template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
57   static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
58     IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
59     IO.enumCase(Value, "Java", FormatStyle::LK_Java);
60     IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
61     IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);
62     IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
63     IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);
64     IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto);
65     IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp);
66   }
67 };
68 
69 template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
70   static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
71     IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03);
72     IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias
73     IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias
74 
75     IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11);
76     IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias
77 
78     IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14);
79     IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17);
80     IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20);
81 
82     IO.enumCase(Value, "Latest", FormatStyle::LS_Latest);
83     IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias
84     IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);
85   }
86 };
87 
88 template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
89   static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {
90     IO.enumCase(Value, "Never", FormatStyle::UT_Never);
91     IO.enumCase(Value, "false", FormatStyle::UT_Never);
92     IO.enumCase(Value, "Always", FormatStyle::UT_Always);
93     IO.enumCase(Value, "true", FormatStyle::UT_Always);
94     IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation);
95     IO.enumCase(Value, "ForContinuationAndIndentation",
96                 FormatStyle::UT_ForContinuationAndIndentation);
97     IO.enumCase(Value, "AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);
98   }
99 };
100 
101 template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {
102   static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) {
103     IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave);
104     IO.enumCase(Value, "Single", FormatStyle::JSQS_Single);
105     IO.enumCase(Value, "Double", FormatStyle::JSQS_Double);
106   }
107 };
108 
109 template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> {
110   static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) {
111     IO.enumCase(Value, "Never", FormatStyle::SBS_Never);
112     IO.enumCase(Value, "false", FormatStyle::SBS_Never);
113     IO.enumCase(Value, "Always", FormatStyle::SBS_Always);
114     IO.enumCase(Value, "true", FormatStyle::SBS_Always);
115     IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty);
116   }
117 };
118 
119 template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
120   static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
121     IO.enumCase(Value, "None", FormatStyle::SFS_None);
122     IO.enumCase(Value, "false", FormatStyle::SFS_None);
123     IO.enumCase(Value, "All", FormatStyle::SFS_All);
124     IO.enumCase(Value, "true", FormatStyle::SFS_All);
125     IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
126     IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly);
127     IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);
128   }
129 };
130 
131 template <> struct ScalarEnumerationTraits<FormatStyle::AlignConsecutiveStyle> {
132   static void enumeration(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
133     IO.enumCase(Value, "None", FormatStyle::ACS_None);
134     IO.enumCase(Value, "Consecutive", FormatStyle::ACS_Consecutive);
135     IO.enumCase(Value, "AcrossEmptyLines", FormatStyle::ACS_AcrossEmptyLines);
136     IO.enumCase(Value, "AcrossComments", FormatStyle::ACS_AcrossComments);
137     IO.enumCase(Value, "AcrossEmptyLinesAndComments",
138                 FormatStyle::ACS_AcrossEmptyLinesAndComments);
139 
140     // For backward compability.
141     IO.enumCase(Value, "true", FormatStyle::ACS_Consecutive);
142     IO.enumCase(Value, "false", FormatStyle::ACS_None);
143   }
144 };
145 
146 template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> {
147   static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) {
148     IO.enumCase(Value, "Never", FormatStyle::SIS_Never);
149     IO.enumCase(Value, "Always", FormatStyle::SIS_Always);
150     IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse);
151 
152     // For backward compatibility.
153     IO.enumCase(Value, "false", FormatStyle::SIS_Never);
154     IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse);
155   }
156 };
157 
158 template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> {
159   static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) {
160     IO.enumCase(Value, "None", FormatStyle::SLS_None);
161     IO.enumCase(Value, "false", FormatStyle::SLS_None);
162     IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty);
163     IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline);
164     IO.enumCase(Value, "All", FormatStyle::SLS_All);
165     IO.enumCase(Value, "true", FormatStyle::SLS_All);
166   }
167 };
168 
169 template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {
170   static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) {
171     IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto);
172     IO.enumCase(Value, "Always", FormatStyle::BPS_Always);
173     IO.enumCase(Value, "Never", FormatStyle::BPS_Never);
174   }
175 };
176 
177 template <> struct ScalarEnumerationTraits<FormatStyle::TrailingCommaStyle> {
178   static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) {
179     IO.enumCase(Value, "None", FormatStyle::TCS_None);
180     IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped);
181   }
182 };
183 
184 template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> {
185   static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {
186     IO.enumCase(Value, "All", FormatStyle::BOS_All);
187     IO.enumCase(Value, "true", FormatStyle::BOS_All);
188     IO.enumCase(Value, "None", FormatStyle::BOS_None);
189     IO.enumCase(Value, "false", FormatStyle::BOS_None);
190     IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment);
191   }
192 };
193 
194 template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
195   static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {
196     IO.enumCase(Value, "Attach", FormatStyle::BS_Attach);
197     IO.enumCase(Value, "Linux", FormatStyle::BS_Linux);
198     IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla);
199     IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);
200     IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
201     IO.enumCase(Value, "Whitesmiths", FormatStyle::BS_Whitesmiths);
202     IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
203     IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit);
204     IO.enumCase(Value, "Custom", FormatStyle::BS_Custom);
205   }
206 };
207 
208 template <>
209 struct ScalarEnumerationTraits<
210     FormatStyle::BraceWrappingAfterControlStatementStyle> {
211   static void
212   enumeration(IO &IO,
213               FormatStyle::BraceWrappingAfterControlStatementStyle &Value) {
214     IO.enumCase(Value, "Never", FormatStyle::BWACS_Never);
215     IO.enumCase(Value, "MultiLine", FormatStyle::BWACS_MultiLine);
216     IO.enumCase(Value, "Always", FormatStyle::BWACS_Always);
217 
218     // For backward compatibility.
219     IO.enumCase(Value, "false", FormatStyle::BWACS_Never);
220     IO.enumCase(Value, "true", FormatStyle::BWACS_Always);
221   }
222 };
223 
224 template <>
225 struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
226   static void
227   enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
228     IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon);
229     IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma);
230     IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon);
231   }
232 };
233 
234 template <>
235 struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {
236   static void enumeration(IO &IO,
237                           FormatStyle::BreakInheritanceListStyle &Value) {
238     IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon);
239     IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma);
240     IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon);
241   }
242 };
243 
244 template <>
245 struct ScalarEnumerationTraits<
246     FormatStyle::EmptyLineBeforeAccessModifierStyle> {
247   static void
248   enumeration(IO &IO, FormatStyle::EmptyLineBeforeAccessModifierStyle &Value) {
249     IO.enumCase(Value, "Never", FormatStyle::ELBAMS_Never);
250     IO.enumCase(Value, "Leave", FormatStyle::ELBAMS_Leave);
251     IO.enumCase(Value, "LogicalBlock", FormatStyle::ELBAMS_LogicalBlock);
252     IO.enumCase(Value, "Always", FormatStyle::ELBAMS_Always);
253   }
254 };
255 
256 template <>
257 struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
258   static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
259     IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
260     IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);
261     IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash);
262   }
263 };
264 
265 template <>
266 struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> {
267   static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value) {
268     IO.enumCase(Value, "AfterExternBlock", FormatStyle::IEBS_AfterExternBlock);
269     IO.enumCase(Value, "Indent", FormatStyle::IEBS_Indent);
270     IO.enumCase(Value, "NoIndent", FormatStyle::IEBS_NoIndent);
271     IO.enumCase(Value, "true", FormatStyle::IEBS_Indent);
272     IO.enumCase(Value, "false", FormatStyle::IEBS_NoIndent);
273   }
274 };
275 
276 template <>
277 struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
278   static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
279     IO.enumCase(Value, "None", FormatStyle::RTBS_None);
280     IO.enumCase(Value, "All", FormatStyle::RTBS_All);
281     IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel);
282     IO.enumCase(Value, "TopLevelDefinitions",
283                 FormatStyle::RTBS_TopLevelDefinitions);
284     IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions);
285   }
286 };
287 
288 template <>
289 struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
290   static void enumeration(IO &IO,
291                           FormatStyle::BreakTemplateDeclarationsStyle &Value) {
292     IO.enumCase(Value, "No", FormatStyle::BTDS_No);
293     IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);
294     IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);
295 
296     // For backward compatibility.
297     IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine);
298     IO.enumCase(Value, "true", FormatStyle::BTDS_Yes);
299   }
300 };
301 
302 template <>
303 struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
304   static void
305   enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
306     IO.enumCase(Value, "None", FormatStyle::DRTBS_None);
307     IO.enumCase(Value, "All", FormatStyle::DRTBS_All);
308     IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel);
309 
310     // For backward compatibility.
311     IO.enumCase(Value, "false", FormatStyle::DRTBS_None);
312     IO.enumCase(Value, "true", FormatStyle::DRTBS_All);
313   }
314 };
315 
316 template <>
317 struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
318   static void enumeration(IO &IO,
319                           FormatStyle::NamespaceIndentationKind &Value) {
320     IO.enumCase(Value, "None", FormatStyle::NI_None);
321     IO.enumCase(Value, "Inner", FormatStyle::NI_Inner);
322     IO.enumCase(Value, "All", FormatStyle::NI_All);
323   }
324 };
325 
326 template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> {
327   static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) {
328     IO.enumCase(Value, "Align", FormatStyle::BAS_Align);
329     IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign);
330     IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak);
331 
332     // For backward compatibility.
333     IO.enumCase(Value, "true", FormatStyle::BAS_Align);
334     IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign);
335   }
336 };
337 
338 template <>
339 struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
340   static void enumeration(IO &IO,
341                           FormatStyle::EscapedNewlineAlignmentStyle &Value) {
342     IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign);
343     IO.enumCase(Value, "Left", FormatStyle::ENAS_Left);
344     IO.enumCase(Value, "Right", FormatStyle::ENAS_Right);
345 
346     // For backward compatibility.
347     IO.enumCase(Value, "true", FormatStyle::ENAS_Left);
348     IO.enumCase(Value, "false", FormatStyle::ENAS_Right);
349   }
350 };
351 
352 template <> struct ScalarEnumerationTraits<FormatStyle::OperandAlignmentStyle> {
353   static void enumeration(IO &IO, FormatStyle::OperandAlignmentStyle &Value) {
354     IO.enumCase(Value, "DontAlign", FormatStyle::OAS_DontAlign);
355     IO.enumCase(Value, "Align", FormatStyle::OAS_Align);
356     IO.enumCase(Value, "AlignAfterOperator",
357                 FormatStyle::OAS_AlignAfterOperator);
358 
359     // For backward compatibility.
360     IO.enumCase(Value, "true", FormatStyle::OAS_Align);
361     IO.enumCase(Value, "false", FormatStyle::OAS_DontAlign);
362   }
363 };
364 
365 template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
366   static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {
367     IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
368     IO.enumCase(Value, "Left", FormatStyle::PAS_Left);
369     IO.enumCase(Value, "Right", FormatStyle::PAS_Right);
370 
371     // For backward compatibility.
372     IO.enumCase(Value, "true", FormatStyle::PAS_Left);
373     IO.enumCase(Value, "false", FormatStyle::PAS_Right);
374   }
375 };
376 
377 template <>
378 struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> {
379   static void
380   enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value) {
381     IO.enumCase(Value, "Default", FormatStyle::SAPQ_Default);
382     IO.enumCase(Value, "Before", FormatStyle::SAPQ_Before);
383     IO.enumCase(Value, "After", FormatStyle::SAPQ_After);
384     IO.enumCase(Value, "Both", FormatStyle::SAPQ_Both);
385   }
386 };
387 
388 template <>
389 struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
390   static void enumeration(IO &IO,
391                           FormatStyle::SpaceBeforeParensOptions &Value) {
392     IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
393     IO.enumCase(Value, "ControlStatements",
394                 FormatStyle::SBPO_ControlStatements);
395     IO.enumCase(Value, "ControlStatementsExceptForEachMacros",
396                 FormatStyle::SBPO_ControlStatementsExceptForEachMacros);
397     IO.enumCase(Value, "NonEmptyParentheses",
398                 FormatStyle::SBPO_NonEmptyParentheses);
399     IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
400 
401     // For backward compatibility.
402     IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
403     IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);
404   }
405 };
406 
407 template <>
408 struct ScalarEnumerationTraits<FormatStyle::BitFieldColonSpacingStyle> {
409   static void enumeration(IO &IO,
410                           FormatStyle::BitFieldColonSpacingStyle &Value) {
411     IO.enumCase(Value, "Both", FormatStyle::BFCS_Both);
412     IO.enumCase(Value, "None", FormatStyle::BFCS_None);
413     IO.enumCase(Value, "Before", FormatStyle::BFCS_Before);
414     IO.enumCase(Value, "After", FormatStyle::BFCS_After);
415   }
416 };
417 
418 template <> struct ScalarEnumerationTraits<FormatStyle::SortIncludesOptions> {
419   static void enumeration(IO &IO, FormatStyle::SortIncludesOptions &Value) {
420     IO.enumCase(Value, "Never", FormatStyle::SI_Never);
421     IO.enumCase(Value, "CaseInsensitive", FormatStyle::SI_CaseInsensitive);
422     IO.enumCase(Value, "CaseSensitive", FormatStyle::SI_CaseSensitive);
423 
424     // For backward compatibility.
425     IO.enumCase(Value, "false", FormatStyle::SI_Never);
426     IO.enumCase(Value, "true", FormatStyle::SI_CaseInsensitive);
427   }
428 };
429 
430 template <>
431 struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> {
432   static void enumeration(IO &IO,
433                           FormatStyle::SortJavaStaticImportOptions &Value) {
434     IO.enumCase(Value, "Before", FormatStyle::SJSIO_Before);
435     IO.enumCase(Value, "After", FormatStyle::SJSIO_After);
436   }
437 };
438 
439 template <> struct MappingTraits<FormatStyle> {
440   static void mapping(IO &IO, FormatStyle &Style) {
441     // When reading, read the language first, we need it for getPredefinedStyle.
442     IO.mapOptional("Language", Style.Language);
443 
444     if (IO.outputting()) {
445       StringRef StylesArray[] = {"LLVM",   "Google", "Chromium", "Mozilla",
446                                  "WebKit", "GNU",    "Microsoft"};
447       ArrayRef<StringRef> Styles(StylesArray);
448       for (size_t i = 0, e = Styles.size(); i < e; ++i) {
449         StringRef StyleName(Styles[i]);
450         FormatStyle PredefinedStyle;
451         if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) &&
452             Style == PredefinedStyle) {
453           IO.mapOptional("# BasedOnStyle", StyleName);
454           break;
455         }
456       }
457     } else {
458       StringRef BasedOnStyle;
459       IO.mapOptional("BasedOnStyle", BasedOnStyle);
460       if (!BasedOnStyle.empty()) {
461         FormatStyle::LanguageKind OldLanguage = Style.Language;
462         FormatStyle::LanguageKind Language =
463             ((FormatStyle *)IO.getContext())->Language;
464         if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
465           IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle));
466           return;
467         }
468         Style.Language = OldLanguage;
469       }
470     }
471 
472     // For backward compatibility.
473     if (!IO.outputting()) {
474       IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines);
475       IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
476       IO.mapOptional("IndentFunctionDeclarationAfterType",
477                      Style.IndentWrappedFunctionNames);
478       IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
479       IO.mapOptional("SpaceAfterControlStatementKeyword",
480                      Style.SpaceBeforeParens);
481     }
482 
483     IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
484     IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
485     IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);
486     IO.mapOptional("AlignConsecutiveAssignments",
487                    Style.AlignConsecutiveAssignments);
488     IO.mapOptional("AlignConsecutiveBitFields",
489                    Style.AlignConsecutiveBitFields);
490     IO.mapOptional("AlignConsecutiveDeclarations",
491                    Style.AlignConsecutiveDeclarations);
492     IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines);
493     IO.mapOptional("AlignOperands", Style.AlignOperands);
494     IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
495     IO.mapOptional("AllowAllArgumentsOnNextLine",
496                    Style.AllowAllArgumentsOnNextLine);
497     IO.mapOptional("AllowAllConstructorInitializersOnNextLine",
498                    Style.AllowAllConstructorInitializersOnNextLine);
499     IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
500                    Style.AllowAllParametersOfDeclarationOnNextLine);
501     IO.mapOptional("AllowShortEnumsOnASingleLine",
502                    Style.AllowShortEnumsOnASingleLine);
503     IO.mapOptional("AllowShortBlocksOnASingleLine",
504                    Style.AllowShortBlocksOnASingleLine);
505     IO.mapOptional("AllowShortCaseLabelsOnASingleLine",
506                    Style.AllowShortCaseLabelsOnASingleLine);
507     IO.mapOptional("AllowShortFunctionsOnASingleLine",
508                    Style.AllowShortFunctionsOnASingleLine);
509     IO.mapOptional("AllowShortLambdasOnASingleLine",
510                    Style.AllowShortLambdasOnASingleLine);
511     IO.mapOptional("AllowShortIfStatementsOnASingleLine",
512                    Style.AllowShortIfStatementsOnASingleLine);
513     IO.mapOptional("AllowShortLoopsOnASingleLine",
514                    Style.AllowShortLoopsOnASingleLine);
515     IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",
516                    Style.AlwaysBreakAfterDefinitionReturnType);
517     IO.mapOptional("AlwaysBreakAfterReturnType",
518                    Style.AlwaysBreakAfterReturnType);
519 
520     // If AlwaysBreakAfterDefinitionReturnType was specified but
521     // AlwaysBreakAfterReturnType was not, initialize the latter from the
522     // former for backwards compatibility.
523     if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&
524         Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) {
525       if (Style.AlwaysBreakAfterDefinitionReturnType == FormatStyle::DRTBS_All)
526         Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
527       else if (Style.AlwaysBreakAfterDefinitionReturnType ==
528                FormatStyle::DRTBS_TopLevel)
529         Style.AlwaysBreakAfterReturnType =
530             FormatStyle::RTBS_TopLevelDefinitions;
531     }
532 
533     IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
534                    Style.AlwaysBreakBeforeMultilineStrings);
535     IO.mapOptional("AlwaysBreakTemplateDeclarations",
536                    Style.AlwaysBreakTemplateDeclarations);
537     IO.mapOptional("AttributeMacros", Style.AttributeMacros);
538     IO.mapOptional("BinPackArguments", Style.BinPackArguments);
539     IO.mapOptional("BinPackParameters", Style.BinPackParameters);
540     IO.mapOptional("BraceWrapping", Style.BraceWrapping);
541     IO.mapOptional("BreakBeforeBinaryOperators",
542                    Style.BreakBeforeBinaryOperators);
543     IO.mapOptional("BreakBeforeConceptDeclarations",
544                    Style.BreakBeforeConceptDeclarations);
545     IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
546 
547     bool BreakBeforeInheritanceComma = false;
548     IO.mapOptional("BreakBeforeInheritanceComma", BreakBeforeInheritanceComma);
549     IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList);
550     // If BreakBeforeInheritanceComma was specified but
551     // BreakInheritance was not, initialize the latter from the
552     // former for backwards compatibility.
553     if (BreakBeforeInheritanceComma &&
554         Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon)
555       Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
556 
557     IO.mapOptional("BreakBeforeTernaryOperators",
558                    Style.BreakBeforeTernaryOperators);
559 
560     bool BreakConstructorInitializersBeforeComma = false;
561     IO.mapOptional("BreakConstructorInitializersBeforeComma",
562                    BreakConstructorInitializersBeforeComma);
563     IO.mapOptional("BreakConstructorInitializers",
564                    Style.BreakConstructorInitializers);
565     // If BreakConstructorInitializersBeforeComma was specified but
566     // BreakConstructorInitializers was not, initialize the latter from the
567     // former for backwards compatibility.
568     if (BreakConstructorInitializersBeforeComma &&
569         Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon)
570       Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
571 
572     IO.mapOptional("BreakAfterJavaFieldAnnotations",
573                    Style.BreakAfterJavaFieldAnnotations);
574     IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
575     IO.mapOptional("ColumnLimit", Style.ColumnLimit);
576     IO.mapOptional("CommentPragmas", Style.CommentPragmas);
577     IO.mapOptional("CompactNamespaces", Style.CompactNamespaces);
578     IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
579                    Style.ConstructorInitializerAllOnOneLineOrOnePerLine);
580     IO.mapOptional("ConstructorInitializerIndentWidth",
581                    Style.ConstructorInitializerIndentWidth);
582     IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
583     IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
584     IO.mapOptional("DeriveLineEnding", Style.DeriveLineEnding);
585     IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
586     IO.mapOptional("DisableFormat", Style.DisableFormat);
587     IO.mapOptional("EmptyLineBeforeAccessModifier",
588                    Style.EmptyLineBeforeAccessModifier);
589     IO.mapOptional("ExperimentalAutoDetectBinPacking",
590                    Style.ExperimentalAutoDetectBinPacking);
591     IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
592     IO.mapOptional("ForEachMacros", Style.ForEachMacros);
593     IO.mapOptional("StatementAttributeLikeMacros",
594                    Style.StatementAttributeLikeMacros);
595     IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
596     IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
597     IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
598     IO.mapOptional("IncludeIsMainSourceRegex",
599                    Style.IncludeStyle.IncludeIsMainSourceRegex);
600     IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
601     IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks);
602     IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels);
603     IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
604     IO.mapOptional("IndentExternBlock", Style.IndentExternBlock);
605     IO.mapOptional("IndentRequires", Style.IndentRequires);
606     IO.mapOptional("IndentWidth", Style.IndentWidth);
607     IO.mapOptional("IndentWrappedFunctionNames",
608                    Style.IndentWrappedFunctionNames);
609     IO.mapOptional("InsertTrailingCommas", Style.InsertTrailingCommas);
610     IO.mapOptional("JavaImportGroups", Style.JavaImportGroups);
611     IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);
612     IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
613     IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
614                    Style.KeepEmptyLinesAtTheStartOfBlocks);
615     IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
616     IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);
617     IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
618     IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
619     IO.mapOptional("NamespaceMacros", Style.NamespaceMacros);
620     IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList);
621     IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);
622     IO.mapOptional("ObjCBreakBeforeNestedBlockParam",
623                    Style.ObjCBreakBeforeNestedBlockParam);
624     IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
625     IO.mapOptional("ObjCSpaceBeforeProtocolList",
626                    Style.ObjCSpaceBeforeProtocolList);
627     IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment);
628     IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",
629                    Style.PenaltyBreakBeforeFirstCallParameter);
630     IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
631     IO.mapOptional("PenaltyBreakFirstLessLess",
632                    Style.PenaltyBreakFirstLessLess);
633     IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
634     IO.mapOptional("PenaltyBreakTemplateDeclaration",
635                    Style.PenaltyBreakTemplateDeclaration);
636     IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
637     IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
638                    Style.PenaltyReturnTypeOnItsOwnLine);
639     IO.mapOptional("PenaltyIndentedWhitespace",
640                    Style.PenaltyIndentedWhitespace);
641     IO.mapOptional("PointerAlignment", Style.PointerAlignment);
642     IO.mapOptional("RawStringFormats", Style.RawStringFormats);
643     IO.mapOptional("ReflowComments", Style.ReflowComments);
644     IO.mapOptional("SortIncludes", Style.SortIncludes);
645     IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport);
646     IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);
647     IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
648     IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot);
649     IO.mapOptional("SpaceAfterTemplateKeyword",
650                    Style.SpaceAfterTemplateKeyword);
651     IO.mapOptional("SpaceBeforeAssignmentOperators",
652                    Style.SpaceBeforeAssignmentOperators);
653     IO.mapOptional("SpaceBeforeCaseColon", Style.SpaceBeforeCaseColon);
654     IO.mapOptional("SpaceBeforeCpp11BracedList",
655                    Style.SpaceBeforeCpp11BracedList);
656     IO.mapOptional("SpaceBeforeCtorInitializerColon",
657                    Style.SpaceBeforeCtorInitializerColon);
658     IO.mapOptional("SpaceBeforeInheritanceColon",
659                    Style.SpaceBeforeInheritanceColon);
660     IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
661     IO.mapOptional("SpaceAroundPointerQualifiers",
662                    Style.SpaceAroundPointerQualifiers);
663     IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
664                    Style.SpaceBeforeRangeBasedForLoopColon);
665     IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock);
666     IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
667     IO.mapOptional("SpacesBeforeTrailingComments",
668                    Style.SpacesBeforeTrailingComments);
669     IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
670     IO.mapOptional("SpacesInConditionalStatement",
671                    Style.SpacesInConditionalStatement);
672     IO.mapOptional("SpacesInContainerLiterals",
673                    Style.SpacesInContainerLiterals);
674     IO.mapOptional("SpacesInCStyleCastParentheses",
675                    Style.SpacesInCStyleCastParentheses);
676     IO.mapOptional("SpacesInLineCommentPrefix",
677                    Style.SpacesInLineCommentPrefix);
678     IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
679     IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
680     IO.mapOptional("SpaceBeforeSquareBrackets",
681                    Style.SpaceBeforeSquareBrackets);
682     IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing);
683     IO.mapOptional("Standard", Style.Standard);
684     IO.mapOptional("StatementMacros", Style.StatementMacros);
685     IO.mapOptional("TabWidth", Style.TabWidth);
686     IO.mapOptional("TypenameMacros", Style.TypenameMacros);
687     IO.mapOptional("UseCRLF", Style.UseCRLF);
688     IO.mapOptional("UseTab", Style.UseTab);
689     IO.mapOptional("WhitespaceSensitiveMacros",
690                    Style.WhitespaceSensitiveMacros);
691   }
692 };
693 
694 template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
695   static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
696     IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel);
697     IO.mapOptional("AfterClass", Wrapping.AfterClass);
698     IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement);
699     IO.mapOptional("AfterEnum", Wrapping.AfterEnum);
700     IO.mapOptional("AfterFunction", Wrapping.AfterFunction);
701     IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace);
702     IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
703     IO.mapOptional("AfterStruct", Wrapping.AfterStruct);
704     IO.mapOptional("AfterUnion", Wrapping.AfterUnion);
705     IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
706     IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
707     IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
708     IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody);
709     IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile);
710     IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
711     IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);
712     IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);
713     IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
714   }
715 };
716 
717 template <> struct MappingTraits<FormatStyle::RawStringFormat> {
718   static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
719     IO.mapOptional("Language", Format.Language);
720     IO.mapOptional("Delimiters", Format.Delimiters);
721     IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);
722     IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter);
723     IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);
724   }
725 };
726 
727 template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {
728   static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
729     // Transform the maximum to signed, to parse "-1" correctly
730     int signedMaximum = static_cast<int>(Space.Maximum);
731     IO.mapOptional("Minimum", Space.Minimum);
732     IO.mapOptional("Maximum", signedMaximum);
733     Space.Maximum = static_cast<unsigned>(signedMaximum);
734 
735     if (Space.Maximum != -1u) {
736       Space.Minimum = std::min(Space.Minimum, Space.Maximum);
737     }
738   }
739 };
740 
741 // Allows to read vector<FormatStyle> while keeping default values.
742 // IO.getContext() should contain a pointer to the FormatStyle structure, that
743 // will be used to get default values for missing keys.
744 // If the first element has no Language specified, it will be treated as the
745 // default one for the following elements.
746 template <> struct DocumentListTraits<std::vector<FormatStyle>> {
747   static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
748     return Seq.size();
749   }
750   static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq,
751                               size_t Index) {
752     if (Index >= Seq.size()) {
753       assert(Index == Seq.size());
754       FormatStyle Template;
755       if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
756         Template = Seq[0];
757       } else {
758         Template = *((const FormatStyle *)IO.getContext());
759         Template.Language = FormatStyle::LK_None;
760       }
761       Seq.resize(Index + 1, Template);
762     }
763     return Seq[Index];
764   }
765 };
766 } // namespace yaml
767 } // namespace llvm
768 
769 namespace clang {
770 namespace format {
771 
772 const std::error_category &getParseCategory() {
773   static const ParseErrorCategory C{};
774   return C;
775 }
776 std::error_code make_error_code(ParseError e) {
777   return std::error_code(static_cast<int>(e), getParseCategory());
778 }
779 
780 inline llvm::Error make_string_error(const llvm::Twine &Message) {
781   return llvm::make_error<llvm::StringError>(Message,
782                                              llvm::inconvertibleErrorCode());
783 }
784 
785 const char *ParseErrorCategory::name() const noexcept {
786   return "clang-format.parse_error";
787 }
788 
789 std::string ParseErrorCategory::message(int EV) const {
790   switch (static_cast<ParseError>(EV)) {
791   case ParseError::Success:
792     return "Success";
793   case ParseError::Error:
794     return "Invalid argument";
795   case ParseError::Unsuitable:
796     return "Unsuitable";
797   case ParseError::BinPackTrailingCommaConflict:
798     return "trailing comma insertion cannot be used with bin packing";
799   }
800   llvm_unreachable("unexpected parse error");
801 }
802 
803 static FormatStyle expandPresets(const FormatStyle &Style) {
804   if (Style.BreakBeforeBraces == FormatStyle::BS_Custom)
805     return Style;
806   FormatStyle Expanded = Style;
807   Expanded.BraceWrapping = {/*AfterCaseLabel=*/false,
808                             /*AfterClass=*/false,
809                             /*AfterControlStatement=*/FormatStyle::BWACS_Never,
810                             /*AfterEnum=*/false,
811                             /*AfterFunction=*/false,
812                             /*AfterNamespace=*/false,
813                             /*AfterObjCDeclaration=*/false,
814                             /*AfterStruct=*/false,
815                             /*AfterUnion=*/false,
816                             /*AfterExternBlock=*/false,
817                             /*BeforeCatch=*/false,
818                             /*BeforeElse=*/false,
819                             /*BeforeLambdaBody=*/false,
820                             /*BeforeWhile=*/false,
821                             /*IndentBraces=*/false,
822                             /*SplitEmptyFunction=*/true,
823                             /*SplitEmptyRecord=*/true,
824                             /*SplitEmptyNamespace=*/true};
825   switch (Style.BreakBeforeBraces) {
826   case FormatStyle::BS_Linux:
827     Expanded.BraceWrapping.AfterClass = true;
828     Expanded.BraceWrapping.AfterFunction = true;
829     Expanded.BraceWrapping.AfterNamespace = true;
830     break;
831   case FormatStyle::BS_Mozilla:
832     Expanded.BraceWrapping.AfterClass = true;
833     Expanded.BraceWrapping.AfterEnum = true;
834     Expanded.BraceWrapping.AfterFunction = true;
835     Expanded.BraceWrapping.AfterStruct = true;
836     Expanded.BraceWrapping.AfterUnion = true;
837     Expanded.BraceWrapping.AfterExternBlock = true;
838     Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
839     Expanded.BraceWrapping.SplitEmptyFunction = true;
840     Expanded.BraceWrapping.SplitEmptyRecord = false;
841     break;
842   case FormatStyle::BS_Stroustrup:
843     Expanded.BraceWrapping.AfterFunction = true;
844     Expanded.BraceWrapping.BeforeCatch = true;
845     Expanded.BraceWrapping.BeforeElse = true;
846     break;
847   case FormatStyle::BS_Allman:
848     Expanded.BraceWrapping.AfterCaseLabel = true;
849     Expanded.BraceWrapping.AfterClass = true;
850     Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
851     Expanded.BraceWrapping.AfterEnum = true;
852     Expanded.BraceWrapping.AfterFunction = true;
853     Expanded.BraceWrapping.AfterNamespace = true;
854     Expanded.BraceWrapping.AfterObjCDeclaration = true;
855     Expanded.BraceWrapping.AfterStruct = true;
856     Expanded.BraceWrapping.AfterUnion = true;
857     Expanded.BraceWrapping.AfterExternBlock = true;
858     Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
859     Expanded.BraceWrapping.BeforeCatch = true;
860     Expanded.BraceWrapping.BeforeElse = true;
861     Expanded.BraceWrapping.BeforeLambdaBody = true;
862     break;
863   case FormatStyle::BS_Whitesmiths:
864     Expanded.BraceWrapping.AfterCaseLabel = true;
865     Expanded.BraceWrapping.AfterClass = true;
866     Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
867     Expanded.BraceWrapping.AfterEnum = true;
868     Expanded.BraceWrapping.AfterFunction = true;
869     Expanded.BraceWrapping.AfterNamespace = true;
870     Expanded.BraceWrapping.AfterObjCDeclaration = true;
871     Expanded.BraceWrapping.AfterStruct = true;
872     Expanded.BraceWrapping.AfterExternBlock = true;
873     Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
874     Expanded.BraceWrapping.BeforeCatch = true;
875     Expanded.BraceWrapping.BeforeElse = true;
876     Expanded.BraceWrapping.BeforeLambdaBody = true;
877     break;
878   case FormatStyle::BS_GNU:
879     Expanded.BraceWrapping = {
880         /*AfterCaseLabel=*/true,
881         /*AfterClass=*/true,
882         /*AfterControlStatement=*/FormatStyle::BWACS_Always,
883         /*AfterEnum=*/true,
884         /*AfterFunction=*/true,
885         /*AfterNamespace=*/true,
886         /*AfterObjCDeclaration=*/true,
887         /*AfterStruct=*/true,
888         /*AfterUnion=*/true,
889         /*AfterExternBlock=*/true,
890         /*BeforeCatch=*/true,
891         /*BeforeElse=*/true,
892         /*BeforeLambdaBody=*/false,
893         /*BeforeWhile=*/true,
894         /*IndentBraces=*/true,
895         /*SplitEmptyFunction=*/true,
896         /*SplitEmptyRecord=*/true,
897         /*SplitEmptyNamespace=*/true};
898     Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
899     break;
900   case FormatStyle::BS_WebKit:
901     Expanded.BraceWrapping.AfterFunction = true;
902     break;
903   default:
904     break;
905   }
906   return Expanded;
907 }
908 
909 FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
910   FormatStyle LLVMStyle;
911   LLVMStyle.InheritsParentConfig = false;
912   LLVMStyle.Language = Language;
913   LLVMStyle.AccessModifierOffset = -2;
914   LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
915   LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
916   LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
917   LLVMStyle.AlignTrailingComments = true;
918   LLVMStyle.AlignConsecutiveAssignments = FormatStyle::ACS_None;
919   LLVMStyle.AlignConsecutiveBitFields = FormatStyle::ACS_None;
920   LLVMStyle.AlignConsecutiveDeclarations = FormatStyle::ACS_None;
921   LLVMStyle.AlignConsecutiveMacros = FormatStyle::ACS_None;
922   LLVMStyle.AllowAllArgumentsOnNextLine = true;
923   LLVMStyle.AllowAllConstructorInitializersOnNextLine = true;
924   LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
925   LLVMStyle.AllowShortEnumsOnASingleLine = true;
926   LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
927   LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
928   LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
929   LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
930   LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
931   LLVMStyle.AllowShortLoopsOnASingleLine = false;
932   LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
933   LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
934   LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
935   LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
936   LLVMStyle.AttributeMacros.push_back("__capability");
937   LLVMStyle.BinPackArguments = true;
938   LLVMStyle.BinPackParameters = true;
939   LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
940   LLVMStyle.BreakBeforeConceptDeclarations = true;
941   LLVMStyle.BreakBeforeTernaryOperators = true;
942   LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
943   LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false,
944                              /*AfterClass=*/false,
945                              /*AfterControlStatement=*/FormatStyle::BWACS_Never,
946                              /*AfterEnum=*/false,
947                              /*AfterFunction=*/false,
948                              /*AfterNamespace=*/false,
949                              /*AfterObjCDeclaration=*/false,
950                              /*AfterStruct=*/false,
951                              /*AfterUnion=*/false,
952                              /*AfterExternBlock=*/false,
953                              /*BeforeCatch=*/false,
954                              /*BeforeElse=*/false,
955                              /*BeforeLambdaBody=*/false,
956                              /*BeforeWhile=*/false,
957                              /*IndentBraces=*/false,
958                              /*SplitEmptyFunction=*/true,
959                              /*SplitEmptyRecord=*/true,
960                              /*SplitEmptyNamespace=*/true};
961   LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
962   LLVMStyle.BreakAfterJavaFieldAnnotations = false;
963   LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
964   LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
965   LLVMStyle.BreakStringLiterals = true;
966   LLVMStyle.ColumnLimit = 80;
967   LLVMStyle.CommentPragmas = "^ IWYU pragma:";
968   LLVMStyle.CompactNamespaces = false;
969   LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false;
970   LLVMStyle.ConstructorInitializerIndentWidth = 4;
971   LLVMStyle.ContinuationIndentWidth = 4;
972   LLVMStyle.Cpp11BracedListStyle = true;
973   LLVMStyle.DeriveLineEnding = true;
974   LLVMStyle.DerivePointerAlignment = false;
975   LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock;
976   LLVMStyle.ExperimentalAutoDetectBinPacking = false;
977   LLVMStyle.FixNamespaceComments = true;
978   LLVMStyle.ForEachMacros.push_back("foreach");
979   LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
980   LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
981   LLVMStyle.IncludeStyle.IncludeCategories = {
982       {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false},
983       {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},
984       {".*", 1, 0, false}};
985   LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
986   LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
987   LLVMStyle.IndentCaseLabels = false;
988   LLVMStyle.IndentCaseBlocks = false;
989   LLVMStyle.IndentGotoLabels = true;
990   LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
991   LLVMStyle.IndentRequires = false;
992   LLVMStyle.IndentWrappedFunctionNames = false;
993   LLVMStyle.IndentWidth = 2;
994   LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
995   LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
996   LLVMStyle.JavaScriptWrapImports = true;
997   LLVMStyle.TabWidth = 8;
998   LLVMStyle.MaxEmptyLinesToKeep = 1;
999   LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
1000   LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
1001   LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto;
1002   LLVMStyle.ObjCBlockIndentWidth = 2;
1003   LLVMStyle.ObjCBreakBeforeNestedBlockParam = true;
1004   LLVMStyle.ObjCSpaceAfterProperty = false;
1005   LLVMStyle.ObjCSpaceBeforeProtocolList = true;
1006   LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
1007   LLVMStyle.SpacesBeforeTrailingComments = 1;
1008   LLVMStyle.Standard = FormatStyle::LS_Latest;
1009   LLVMStyle.UseCRLF = false;
1010   LLVMStyle.UseTab = FormatStyle::UT_Never;
1011   LLVMStyle.ReflowComments = true;
1012   LLVMStyle.SpacesInParentheses = false;
1013   LLVMStyle.SpacesInSquareBrackets = false;
1014   LLVMStyle.SpaceInEmptyBlock = false;
1015   LLVMStyle.SpaceInEmptyParentheses = false;
1016   LLVMStyle.SpacesInContainerLiterals = true;
1017   LLVMStyle.SpacesInCStyleCastParentheses = false;
1018   LLVMStyle.SpacesInLineCommentPrefix = {/*Minimum=*/1, /*Maximum=*/-1u};
1019   LLVMStyle.SpaceAfterCStyleCast = false;
1020   LLVMStyle.SpaceAfterLogicalNot = false;
1021   LLVMStyle.SpaceAfterTemplateKeyword = true;
1022   LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
1023   LLVMStyle.SpaceBeforeCaseColon = false;
1024   LLVMStyle.SpaceBeforeCtorInitializerColon = true;
1025   LLVMStyle.SpaceBeforeInheritanceColon = true;
1026   LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
1027   LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
1028   LLVMStyle.SpaceBeforeAssignmentOperators = true;
1029   LLVMStyle.SpaceBeforeCpp11BracedList = false;
1030   LLVMStyle.SpaceBeforeSquareBrackets = false;
1031   LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;
1032   LLVMStyle.SpacesInAngles = false;
1033   LLVMStyle.SpacesInConditionalStatement = false;
1034 
1035   LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
1036   LLVMStyle.PenaltyBreakComment = 300;
1037   LLVMStyle.PenaltyBreakFirstLessLess = 120;
1038   LLVMStyle.PenaltyBreakString = 1000;
1039   LLVMStyle.PenaltyExcessCharacter = 1000000;
1040   LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
1041   LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
1042   LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;
1043   LLVMStyle.PenaltyIndentedWhitespace = 0;
1044 
1045   LLVMStyle.DisableFormat = false;
1046   LLVMStyle.SortIncludes = FormatStyle::SI_CaseInsensitive;
1047   LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
1048   LLVMStyle.SortUsingDeclarations = true;
1049   LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");
1050   LLVMStyle.StatementMacros.push_back("Q_UNUSED");
1051   LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");
1052   LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE");
1053   LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE");
1054   LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE");
1055   LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME");
1056   LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME");
1057 
1058   // Defaults that differ when not C++.
1059   if (Language == FormatStyle::LK_TableGen) {
1060     LLVMStyle.SpacesInContainerLiterals = false;
1061   }
1062 
1063   return LLVMStyle;
1064 }
1065 
1066 FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
1067   if (Language == FormatStyle::LK_TextProto) {
1068     FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto);
1069     GoogleStyle.Language = FormatStyle::LK_TextProto;
1070 
1071     return GoogleStyle;
1072   }
1073 
1074   FormatStyle GoogleStyle = getLLVMStyle(Language);
1075 
1076   GoogleStyle.AccessModifierOffset = -1;
1077   GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left;
1078   GoogleStyle.AllowShortIfStatementsOnASingleLine =
1079       FormatStyle::SIS_WithoutElse;
1080   GoogleStyle.AllowShortLoopsOnASingleLine = true;
1081   GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
1082   GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
1083   GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
1084   GoogleStyle.DerivePointerAlignment = true;
1085   GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false},
1086                                                 {"^<.*\\.h>", 1, 0, false},
1087                                                 {"^<.*", 2, 0, false},
1088                                                 {".*", 3, 0, false}};
1089   GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
1090   GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
1091   GoogleStyle.IndentCaseLabels = true;
1092   GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
1093   GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never;
1094   GoogleStyle.ObjCSpaceAfterProperty = false;
1095   GoogleStyle.ObjCSpaceBeforeProtocolList = true;
1096   GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;
1097   GoogleStyle.RawStringFormats = {
1098       {
1099           FormatStyle::LK_Cpp,
1100           /*Delimiters=*/
1101           {
1102               "cc",
1103               "CC",
1104               "cpp",
1105               "Cpp",
1106               "CPP",
1107               "c++",
1108               "C++",
1109           },
1110           /*EnclosingFunctionNames=*/
1111           {},
1112           /*CanonicalDelimiter=*/"",
1113           /*BasedOnStyle=*/"google",
1114       },
1115       {
1116           FormatStyle::LK_TextProto,
1117           /*Delimiters=*/
1118           {
1119               "pb",
1120               "PB",
1121               "proto",
1122               "PROTO",
1123           },
1124           /*EnclosingFunctionNames=*/
1125           {
1126               "EqualsProto",
1127               "EquivToProto",
1128               "PARSE_PARTIAL_TEXT_PROTO",
1129               "PARSE_TEST_PROTO",
1130               "PARSE_TEXT_PROTO",
1131               "ParseTextOrDie",
1132               "ParseTextProtoOrDie",
1133               "ParseTestProto",
1134               "ParsePartialTestProto",
1135           },
1136           /*CanonicalDelimiter=*/"",
1137           /*BasedOnStyle=*/"google",
1138       },
1139   };
1140   GoogleStyle.SpacesBeforeTrailingComments = 2;
1141   GoogleStyle.Standard = FormatStyle::LS_Auto;
1142 
1143   GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
1144   GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;
1145 
1146   if (Language == FormatStyle::LK_Java) {
1147     GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
1148     GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
1149     GoogleStyle.AlignTrailingComments = false;
1150     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
1151     GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
1152     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
1153     GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
1154     GoogleStyle.ColumnLimit = 100;
1155     GoogleStyle.SpaceAfterCStyleCast = true;
1156     GoogleStyle.SpacesBeforeTrailingComments = 1;
1157   } else if (Language == FormatStyle::LK_JavaScript) {
1158     GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
1159     GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
1160     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
1161     // TODO: still under discussion whether to switch to SLS_All.
1162     GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
1163     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
1164     GoogleStyle.BreakBeforeTernaryOperators = false;
1165     // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is
1166     // commonly followed by overlong URLs.
1167     GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)";
1168     // TODO: enable once decided, in particular re disabling bin packing.
1169     // https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma
1170     // GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
1171     GoogleStyle.MaxEmptyLinesToKeep = 3;
1172     GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
1173     GoogleStyle.SpacesInContainerLiterals = false;
1174     GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single;
1175     GoogleStyle.JavaScriptWrapImports = false;
1176   } else if (Language == FormatStyle::LK_Proto) {
1177     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
1178     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
1179     GoogleStyle.SpacesInContainerLiterals = false;
1180     GoogleStyle.Cpp11BracedListStyle = false;
1181     // This affects protocol buffer options specifications and text protos.
1182     // Text protos are currently mostly formatted inside C++ raw string literals
1183     // and often the current breaking behavior of string literals is not
1184     // beneficial there. Investigate turning this on once proper string reflow
1185     // has been implemented.
1186     GoogleStyle.BreakStringLiterals = false;
1187   } else if (Language == FormatStyle::LK_ObjC) {
1188     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
1189     GoogleStyle.ColumnLimit = 100;
1190     // "Regroup" doesn't work well for ObjC yet (main header heuristic,
1191     // relationship between ObjC standard library headers and other heades,
1192     // #imports, etc.)
1193     GoogleStyle.IncludeStyle.IncludeBlocks =
1194         tooling::IncludeStyle::IBS_Preserve;
1195   } else if (Language == FormatStyle::LK_CSharp) {
1196     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
1197     GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
1198     GoogleStyle.BreakStringLiterals = false;
1199     GoogleStyle.ColumnLimit = 100;
1200     GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
1201   }
1202 
1203   return GoogleStyle;
1204 }
1205 
1206 FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
1207   FormatStyle ChromiumStyle = getGoogleStyle(Language);
1208 
1209   // Disable include reordering across blocks in Chromium code.
1210   // - clang-format tries to detect that foo.h is the "main" header for
1211   //   foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium
1212   //   uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc,
1213   //   _private.cc, _impl.cc etc) in different permutations
1214   //   (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a
1215   //   better default for Chromium code.
1216   // - The default for .cc and .mm files is different (r357695) for Google style
1217   //   for the same reason. The plan is to unify this again once the main
1218   //   header detection works for Google's ObjC code, but this hasn't happened
1219   //   yet. Since Chromium has some ObjC code, switching Chromium is blocked
1220   //   on that.
1221   // - Finally, "If include reordering is harmful, put things in different
1222   //   blocks to prevent it" has been a recommendation for a long time that
1223   //   people are used to. We'll need a dev education push to change this to
1224   //   "If include reordering is harmful, put things in a different block and
1225   //   _prepend that with a comment_ to prevent it" before changing behavior.
1226   ChromiumStyle.IncludeStyle.IncludeBlocks =
1227       tooling::IncludeStyle::IBS_Preserve;
1228 
1229   if (Language == FormatStyle::LK_Java) {
1230     ChromiumStyle.AllowShortIfStatementsOnASingleLine =
1231         FormatStyle::SIS_WithoutElse;
1232     ChromiumStyle.BreakAfterJavaFieldAnnotations = true;
1233     ChromiumStyle.ContinuationIndentWidth = 8;
1234     ChromiumStyle.IndentWidth = 4;
1235     // See styleguide for import groups:
1236     // https://chromium.googlesource.com/chromium/src/+/master/styleguide/java/java.md#Import-Order
1237     ChromiumStyle.JavaImportGroups = {
1238         "android",
1239         "androidx",
1240         "com",
1241         "dalvik",
1242         "junit",
1243         "org",
1244         "com.google.android.apps.chrome",
1245         "org.chromium",
1246         "java",
1247         "javax",
1248     };
1249     ChromiumStyle.SortIncludes = FormatStyle::SI_CaseInsensitive;
1250   } else if (Language == FormatStyle::LK_JavaScript) {
1251     ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
1252     ChromiumStyle.AllowShortLoopsOnASingleLine = false;
1253   } else {
1254     ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
1255     ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
1256     ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
1257     ChromiumStyle.AllowShortLoopsOnASingleLine = false;
1258     ChromiumStyle.BinPackParameters = false;
1259     ChromiumStyle.DerivePointerAlignment = false;
1260     if (Language == FormatStyle::LK_ObjC)
1261       ChromiumStyle.ColumnLimit = 80;
1262   }
1263   return ChromiumStyle;
1264 }
1265 
1266 FormatStyle getMozillaStyle() {
1267   FormatStyle MozillaStyle = getLLVMStyle();
1268   MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
1269   MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
1270   MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel;
1271   MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
1272       FormatStyle::DRTBS_TopLevel;
1273   MozillaStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
1274   MozillaStyle.BinPackParameters = false;
1275   MozillaStyle.BinPackArguments = false;
1276   MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
1277   MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
1278   MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
1279   MozillaStyle.ConstructorInitializerIndentWidth = 2;
1280   MozillaStyle.ContinuationIndentWidth = 2;
1281   MozillaStyle.Cpp11BracedListStyle = false;
1282   MozillaStyle.FixNamespaceComments = false;
1283   MozillaStyle.IndentCaseLabels = true;
1284   MozillaStyle.ObjCSpaceAfterProperty = true;
1285   MozillaStyle.ObjCSpaceBeforeProtocolList = false;
1286   MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
1287   MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
1288   MozillaStyle.SpaceAfterTemplateKeyword = false;
1289   return MozillaStyle;
1290 }
1291 
1292 FormatStyle getWebKitStyle() {
1293   FormatStyle Style = getLLVMStyle();
1294   Style.AccessModifierOffset = -4;
1295   Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
1296   Style.AlignOperands = FormatStyle::OAS_DontAlign;
1297   Style.AlignTrailingComments = false;
1298   Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;
1299   Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
1300   Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
1301   Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
1302   Style.Cpp11BracedListStyle = false;
1303   Style.ColumnLimit = 0;
1304   Style.FixNamespaceComments = false;
1305   Style.IndentWidth = 4;
1306   Style.NamespaceIndentation = FormatStyle::NI_Inner;
1307   Style.ObjCBlockIndentWidth = 4;
1308   Style.ObjCSpaceAfterProperty = true;
1309   Style.PointerAlignment = FormatStyle::PAS_Left;
1310   Style.SpaceBeforeCpp11BracedList = true;
1311   Style.SpaceInEmptyBlock = true;
1312   return Style;
1313 }
1314 
1315 FormatStyle getGNUStyle() {
1316   FormatStyle Style = getLLVMStyle();
1317   Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
1318   Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
1319   Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
1320   Style.BreakBeforeBraces = FormatStyle::BS_GNU;
1321   Style.BreakBeforeTernaryOperators = true;
1322   Style.Cpp11BracedListStyle = false;
1323   Style.ColumnLimit = 79;
1324   Style.FixNamespaceComments = false;
1325   Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
1326   Style.Standard = FormatStyle::LS_Cpp03;
1327   return Style;
1328 }
1329 
1330 FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) {
1331   FormatStyle Style = getLLVMStyle(Language);
1332   Style.ColumnLimit = 120;
1333   Style.TabWidth = 4;
1334   Style.IndentWidth = 4;
1335   Style.UseTab = FormatStyle::UT_Never;
1336   Style.BreakBeforeBraces = FormatStyle::BS_Custom;
1337   Style.BraceWrapping.AfterClass = true;
1338   Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
1339   Style.BraceWrapping.AfterEnum = true;
1340   Style.BraceWrapping.AfterFunction = true;
1341   Style.BraceWrapping.AfterNamespace = true;
1342   Style.BraceWrapping.AfterObjCDeclaration = true;
1343   Style.BraceWrapping.AfterStruct = true;
1344   Style.BraceWrapping.AfterExternBlock = true;
1345   Style.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
1346   Style.BraceWrapping.BeforeCatch = true;
1347   Style.BraceWrapping.BeforeElse = true;
1348   Style.BraceWrapping.BeforeWhile = false;
1349   Style.PenaltyReturnTypeOnItsOwnLine = 1000;
1350   Style.AllowShortEnumsOnASingleLine = false;
1351   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
1352   Style.AllowShortCaseLabelsOnASingleLine = false;
1353   Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
1354   Style.AllowShortLoopsOnASingleLine = false;
1355   Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
1356   Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
1357   return Style;
1358 }
1359 
1360 FormatStyle getNoStyle() {
1361   FormatStyle NoStyle = getLLVMStyle();
1362   NoStyle.DisableFormat = true;
1363   NoStyle.SortIncludes = FormatStyle::SI_Never;
1364   NoStyle.SortUsingDeclarations = false;
1365   return NoStyle;
1366 }
1367 
1368 bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
1369                         FormatStyle *Style) {
1370   if (Name.equals_lower("llvm")) {
1371     *Style = getLLVMStyle(Language);
1372   } else if (Name.equals_lower("chromium")) {
1373     *Style = getChromiumStyle(Language);
1374   } else if (Name.equals_lower("mozilla")) {
1375     *Style = getMozillaStyle();
1376   } else if (Name.equals_lower("google")) {
1377     *Style = getGoogleStyle(Language);
1378   } else if (Name.equals_lower("webkit")) {
1379     *Style = getWebKitStyle();
1380   } else if (Name.equals_lower("gnu")) {
1381     *Style = getGNUStyle();
1382   } else if (Name.equals_lower("microsoft")) {
1383     *Style = getMicrosoftStyle(Language);
1384   } else if (Name.equals_lower("none")) {
1385     *Style = getNoStyle();
1386   } else if (Name.equals_lower("inheritparentconfig")) {
1387     Style->InheritsParentConfig = true;
1388   } else {
1389     return false;
1390   }
1391 
1392   Style->Language = Language;
1393   return true;
1394 }
1395 
1396 std::error_code parseConfiguration(llvm::MemoryBufferRef Config,
1397                                    FormatStyle *Style,
1398                                    bool AllowUnknownOptions) {
1399   assert(Style);
1400   FormatStyle::LanguageKind Language = Style->Language;
1401   assert(Language != FormatStyle::LK_None);
1402   if (Config.getBuffer().trim().empty())
1403     return make_error_code(ParseError::Error);
1404   Style->StyleSet.Clear();
1405   std::vector<FormatStyle> Styles;
1406   llvm::yaml::Input Input(Config);
1407   // DocumentListTraits<vector<FormatStyle>> uses the context to get default
1408   // values for the fields, keys for which are missing from the configuration.
1409   // Mapping also uses the context to get the language to find the correct
1410   // base style.
1411   Input.setContext(Style);
1412   Input.setAllowUnknownKeys(AllowUnknownOptions);
1413   Input >> Styles;
1414   if (Input.error())
1415     return Input.error();
1416 
1417   for (unsigned i = 0; i < Styles.size(); ++i) {
1418     // Ensures that only the first configuration can skip the Language option.
1419     if (Styles[i].Language == FormatStyle::LK_None && i != 0)
1420       return make_error_code(ParseError::Error);
1421     // Ensure that each language is configured at most once.
1422     for (unsigned j = 0; j < i; ++j) {
1423       if (Styles[i].Language == Styles[j].Language) {
1424         LLVM_DEBUG(llvm::dbgs()
1425                    << "Duplicate languages in the config file on positions "
1426                    << j << " and " << i << "\n");
1427         return make_error_code(ParseError::Error);
1428       }
1429     }
1430   }
1431   // Look for a suitable configuration starting from the end, so we can
1432   // find the configuration for the specific language first, and the default
1433   // configuration (which can only be at slot 0) after it.
1434   FormatStyle::FormatStyleSet StyleSet;
1435   bool LanguageFound = false;
1436   for (int i = Styles.size() - 1; i >= 0; --i) {
1437     if (Styles[i].Language != FormatStyle::LK_None)
1438       StyleSet.Add(Styles[i]);
1439     if (Styles[i].Language == Language)
1440       LanguageFound = true;
1441   }
1442   if (!LanguageFound) {
1443     if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None)
1444       return make_error_code(ParseError::Unsuitable);
1445     FormatStyle DefaultStyle = Styles[0];
1446     DefaultStyle.Language = Language;
1447     StyleSet.Add(std::move(DefaultStyle));
1448   }
1449   *Style = *StyleSet.Get(Language);
1450   if (Style->InsertTrailingCommas != FormatStyle::TCS_None &&
1451       Style->BinPackArguments) {
1452     // See comment on FormatStyle::TSC_Wrapped.
1453     return make_error_code(ParseError::BinPackTrailingCommaConflict);
1454   }
1455   return make_error_code(ParseError::Success);
1456 }
1457 
1458 std::string configurationAsText(const FormatStyle &Style) {
1459   std::string Text;
1460   llvm::raw_string_ostream Stream(Text);
1461   llvm::yaml::Output Output(Stream);
1462   // We use the same mapping method for input and output, so we need a non-const
1463   // reference here.
1464   FormatStyle NonConstStyle = expandPresets(Style);
1465   Output << NonConstStyle;
1466   return Stream.str();
1467 }
1468 
1469 llvm::Optional<FormatStyle>
1470 FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {
1471   if (!Styles)
1472     return None;
1473   auto It = Styles->find(Language);
1474   if (It == Styles->end())
1475     return None;
1476   FormatStyle Style = It->second;
1477   Style.StyleSet = *this;
1478   return Style;
1479 }
1480 
1481 void FormatStyle::FormatStyleSet::Add(FormatStyle Style) {
1482   assert(Style.Language != LK_None &&
1483          "Cannot add a style for LK_None to a StyleSet");
1484   assert(
1485       !Style.StyleSet.Styles &&
1486       "Cannot add a style associated with an existing StyleSet to a StyleSet");
1487   if (!Styles)
1488     Styles = std::make_shared<MapType>();
1489   (*Styles)[Style.Language] = std::move(Style);
1490 }
1491 
1492 void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); }
1493 
1494 llvm::Optional<FormatStyle>
1495 FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {
1496   return StyleSet.Get(Language);
1497 }
1498 
1499 namespace {
1500 
1501 class JavaScriptRequoter : public TokenAnalyzer {
1502 public:
1503   JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)
1504       : TokenAnalyzer(Env, Style) {}
1505 
1506   std::pair<tooling::Replacements, unsigned>
1507   analyze(TokenAnnotator &Annotator,
1508           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1509           FormatTokenLexer &Tokens) override {
1510     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
1511     tooling::Replacements Result;
1512     requoteJSStringLiteral(AnnotatedLines, Result);
1513     return {Result, 0};
1514   }
1515 
1516 private:
1517   // Replaces double/single-quoted string literal as appropriate, re-escaping
1518   // the contents in the process.
1519   void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
1520                               tooling::Replacements &Result) {
1521     for (AnnotatedLine *Line : Lines) {
1522       requoteJSStringLiteral(Line->Children, Result);
1523       if (!Line->Affected)
1524         continue;
1525       for (FormatToken *FormatTok = Line->First; FormatTok;
1526            FormatTok = FormatTok->Next) {
1527         StringRef Input = FormatTok->TokenText;
1528         if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
1529             // NB: testing for not starting with a double quote to avoid
1530             // breaking `template strings`.
1531             (Style.JavaScriptQuotes == FormatStyle::JSQS_Single &&
1532              !Input.startswith("\"")) ||
1533             (Style.JavaScriptQuotes == FormatStyle::JSQS_Double &&
1534              !Input.startswith("\'")))
1535           continue;
1536 
1537         // Change start and end quote.
1538         bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single;
1539         SourceLocation Start = FormatTok->Tok.getLocation();
1540         auto Replace = [&](SourceLocation Start, unsigned Length,
1541                            StringRef ReplacementText) {
1542           auto Err = Result.add(tooling::Replacement(
1543               Env.getSourceManager(), Start, Length, ReplacementText));
1544           // FIXME: handle error. For now, print error message and skip the
1545           // replacement for release version.
1546           if (Err) {
1547             llvm::errs() << llvm::toString(std::move(Err)) << "\n";
1548             assert(false);
1549           }
1550         };
1551         Replace(Start, 1, IsSingle ? "'" : "\"");
1552         Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
1553                 IsSingle ? "'" : "\"");
1554 
1555         // Escape internal quotes.
1556         bool Escaped = false;
1557         for (size_t i = 1; i < Input.size() - 1; i++) {
1558           switch (Input[i]) {
1559           case '\\':
1560             if (!Escaped && i + 1 < Input.size() &&
1561                 ((IsSingle && Input[i + 1] == '"') ||
1562                  (!IsSingle && Input[i + 1] == '\''))) {
1563               // Remove this \, it's escaping a " or ' that no longer needs
1564               // escaping
1565               Replace(Start.getLocWithOffset(i), 1, "");
1566               continue;
1567             }
1568             Escaped = !Escaped;
1569             break;
1570           case '\"':
1571           case '\'':
1572             if (!Escaped && IsSingle == (Input[i] == '\'')) {
1573               // Escape the quote.
1574               Replace(Start.getLocWithOffset(i), 0, "\\");
1575             }
1576             Escaped = false;
1577             break;
1578           default:
1579             Escaped = false;
1580             break;
1581           }
1582         }
1583       }
1584     }
1585   }
1586 };
1587 
1588 class Formatter : public TokenAnalyzer {
1589 public:
1590   Formatter(const Environment &Env, const FormatStyle &Style,
1591             FormattingAttemptStatus *Status)
1592       : TokenAnalyzer(Env, Style), Status(Status) {}
1593 
1594   std::pair<tooling::Replacements, unsigned>
1595   analyze(TokenAnnotator &Annotator,
1596           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1597           FormatTokenLexer &Tokens) override {
1598     tooling::Replacements Result;
1599     deriveLocalStyle(AnnotatedLines);
1600     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
1601     for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
1602       Annotator.calculateFormattingInformation(*AnnotatedLines[i]);
1603     }
1604     Annotator.setCommentLineLevels(AnnotatedLines);
1605 
1606     WhitespaceManager Whitespaces(
1607         Env.getSourceManager(), Style,
1608         Style.DeriveLineEnding
1609             ? inputUsesCRLF(
1610                   Env.getSourceManager().getBufferData(Env.getFileID()),
1611                   Style.UseCRLF)
1612             : Style.UseCRLF);
1613     ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
1614                                   Env.getSourceManager(), Whitespaces, Encoding,
1615                                   BinPackInconclusiveFunctions);
1616     unsigned Penalty =
1617         UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,
1618                                Tokens.getKeywords(), Env.getSourceManager(),
1619                                Status)
1620             .format(AnnotatedLines, /*DryRun=*/false,
1621                     /*AdditionalIndent=*/0,
1622                     /*FixBadIndentation=*/false,
1623                     /*FirstStartColumn=*/Env.getFirstStartColumn(),
1624                     /*NextStartColumn=*/Env.getNextStartColumn(),
1625                     /*LastStartColumn=*/Env.getLastStartColumn());
1626     for (const auto &R : Whitespaces.generateReplacements())
1627       if (Result.add(R))
1628         return std::make_pair(Result, 0);
1629     return std::make_pair(Result, Penalty);
1630   }
1631 
1632 private:
1633   static bool inputUsesCRLF(StringRef Text, bool DefaultToCRLF) {
1634     size_t LF = Text.count('\n');
1635     size_t CR = Text.count('\r') * 2;
1636     return LF == CR ? DefaultToCRLF : CR > LF;
1637   }
1638 
1639   bool
1640   hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) {
1641     for (const AnnotatedLine *Line : Lines) {
1642       if (hasCpp03IncompatibleFormat(Line->Children))
1643         return true;
1644       for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {
1645         if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) {
1646           if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
1647             return true;
1648           if (Tok->is(TT_TemplateCloser) &&
1649               Tok->Previous->is(TT_TemplateCloser))
1650             return true;
1651         }
1652       }
1653     }
1654     return false;
1655   }
1656 
1657   int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) {
1658     int AlignmentDiff = 0;
1659     for (const AnnotatedLine *Line : Lines) {
1660       AlignmentDiff += countVariableAlignments(Line->Children);
1661       for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {
1662         if (!Tok->is(TT_PointerOrReference))
1663           continue;
1664         bool SpaceBefore =
1665             Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd();
1666         bool SpaceAfter = Tok->Next->WhitespaceRange.getBegin() !=
1667                           Tok->Next->WhitespaceRange.getEnd();
1668         if (SpaceBefore && !SpaceAfter)
1669           ++AlignmentDiff;
1670         if (!SpaceBefore && SpaceAfter)
1671           --AlignmentDiff;
1672       }
1673     }
1674     return AlignmentDiff;
1675   }
1676 
1677   void
1678   deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
1679     bool HasBinPackedFunction = false;
1680     bool HasOnePerLineFunction = false;
1681     for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
1682       if (!AnnotatedLines[i]->First->Next)
1683         continue;
1684       FormatToken *Tok = AnnotatedLines[i]->First->Next;
1685       while (Tok->Next) {
1686         if (Tok->is(PPK_BinPacked))
1687           HasBinPackedFunction = true;
1688         if (Tok->is(PPK_OnePerLine))
1689           HasOnePerLineFunction = true;
1690 
1691         Tok = Tok->Next;
1692       }
1693     }
1694     if (Style.DerivePointerAlignment)
1695       Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0
1696                                    ? FormatStyle::PAS_Left
1697                                    : FormatStyle::PAS_Right;
1698     if (Style.Standard == FormatStyle::LS_Auto)
1699       Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
1700                            ? FormatStyle::LS_Latest
1701                            : FormatStyle::LS_Cpp03;
1702     BinPackInconclusiveFunctions =
1703         HasBinPackedFunction || !HasOnePerLineFunction;
1704   }
1705 
1706   bool BinPackInconclusiveFunctions;
1707   FormattingAttemptStatus *Status;
1708 };
1709 
1710 /// TrailingCommaInserter inserts trailing commas into container literals.
1711 /// E.g.:
1712 ///     const x = [
1713 ///       1,
1714 ///     ];
1715 /// TrailingCommaInserter runs after formatting. To avoid causing a required
1716 /// reformatting (and thus reflow), it never inserts a comma that'd exceed the
1717 /// ColumnLimit.
1718 ///
1719 /// Because trailing commas disable binpacking of arrays, TrailingCommaInserter
1720 /// is conceptually incompatible with bin packing.
1721 class TrailingCommaInserter : public TokenAnalyzer {
1722 public:
1723   TrailingCommaInserter(const Environment &Env, const FormatStyle &Style)
1724       : TokenAnalyzer(Env, Style) {}
1725 
1726   std::pair<tooling::Replacements, unsigned>
1727   analyze(TokenAnnotator &Annotator,
1728           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1729           FormatTokenLexer &Tokens) override {
1730     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
1731     tooling::Replacements Result;
1732     insertTrailingCommas(AnnotatedLines, Result);
1733     return {Result, 0};
1734   }
1735 
1736 private:
1737   /// Inserts trailing commas in [] and {} initializers if they wrap over
1738   /// multiple lines.
1739   void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,
1740                             tooling::Replacements &Result) {
1741     for (AnnotatedLine *Line : Lines) {
1742       insertTrailingCommas(Line->Children, Result);
1743       if (!Line->Affected)
1744         continue;
1745       for (FormatToken *FormatTok = Line->First; FormatTok;
1746            FormatTok = FormatTok->Next) {
1747         if (FormatTok->NewlinesBefore == 0)
1748           continue;
1749         FormatToken *Matching = FormatTok->MatchingParen;
1750         if (!Matching || !FormatTok->getPreviousNonComment())
1751           continue;
1752         if (!(FormatTok->is(tok::r_square) &&
1753               Matching->is(TT_ArrayInitializerLSquare)) &&
1754             !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral)))
1755           continue;
1756         FormatToken *Prev = FormatTok->getPreviousNonComment();
1757         if (Prev->is(tok::comma) || Prev->is(tok::semi))
1758           continue;
1759         // getEndLoc is not reliably set during re-lexing, use text length
1760         // instead.
1761         SourceLocation Start =
1762             Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size());
1763         // If inserting a comma would push the code over the column limit, skip
1764         // this location - it'd introduce an unstable formatting due to the
1765         // required reflow.
1766         unsigned ColumnNumber =
1767             Env.getSourceManager().getSpellingColumnNumber(Start);
1768         if (ColumnNumber > Style.ColumnLimit)
1769           continue;
1770         // Comma insertions cannot conflict with each other, and this pass has a
1771         // clean set of Replacements, so the operation below cannot fail.
1772         cantFail(Result.add(
1773             tooling::Replacement(Env.getSourceManager(), Start, 0, ",")));
1774       }
1775     }
1776   }
1777 };
1778 
1779 // This class clean up the erroneous/redundant code around the given ranges in
1780 // file.
1781 class Cleaner : public TokenAnalyzer {
1782 public:
1783   Cleaner(const Environment &Env, const FormatStyle &Style)
1784       : TokenAnalyzer(Env, Style),
1785         DeletedTokens(FormatTokenLess(Env.getSourceManager())) {}
1786 
1787   // FIXME: eliminate unused parameters.
1788   std::pair<tooling::Replacements, unsigned>
1789   analyze(TokenAnnotator &Annotator,
1790           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1791           FormatTokenLexer &Tokens) override {
1792     // FIXME: in the current implementation the granularity of affected range
1793     // is an annotated line. However, this is not sufficient. Furthermore,
1794     // redundant code introduced by replacements does not necessarily
1795     // intercept with ranges of replacements that result in the redundancy.
1796     // To determine if some redundant code is actually introduced by
1797     // replacements(e.g. deletions), we need to come up with a more
1798     // sophisticated way of computing affected ranges.
1799     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
1800 
1801     checkEmptyNamespace(AnnotatedLines);
1802 
1803     for (auto *Line : AnnotatedLines)
1804       cleanupLine(Line);
1805 
1806     return {generateFixes(), 0};
1807   }
1808 
1809 private:
1810   void cleanupLine(AnnotatedLine *Line) {
1811     for (auto *Child : Line->Children) {
1812       cleanupLine(Child);
1813     }
1814 
1815     if (Line->Affected) {
1816       cleanupRight(Line->First, tok::comma, tok::comma);
1817       cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
1818       cleanupRight(Line->First, tok::l_paren, tok::comma);
1819       cleanupLeft(Line->First, tok::comma, tok::r_paren);
1820       cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
1821       cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
1822       cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
1823     }
1824   }
1825 
1826   bool containsOnlyComments(const AnnotatedLine &Line) {
1827     for (FormatToken *Tok = Line.First; Tok != nullptr; Tok = Tok->Next) {
1828       if (Tok->isNot(tok::comment))
1829         return false;
1830     }
1831     return true;
1832   }
1833 
1834   // Iterate through all lines and remove any empty (nested) namespaces.
1835   void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
1836     std::set<unsigned> DeletedLines;
1837     for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
1838       auto &Line = *AnnotatedLines[i];
1839       if (Line.startsWithNamespace()) {
1840         checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
1841       }
1842     }
1843 
1844     for (auto Line : DeletedLines) {
1845       FormatToken *Tok = AnnotatedLines[Line]->First;
1846       while (Tok) {
1847         deleteToken(Tok);
1848         Tok = Tok->Next;
1849       }
1850     }
1851   }
1852 
1853   // The function checks if the namespace, which starts from \p CurrentLine, and
1854   // its nested namespaces are empty and delete them if they are empty. It also
1855   // sets \p NewLine to the last line checked.
1856   // Returns true if the current namespace is empty.
1857   bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1858                            unsigned CurrentLine, unsigned &NewLine,
1859                            std::set<unsigned> &DeletedLines) {
1860     unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
1861     if (Style.BraceWrapping.AfterNamespace) {
1862       // If the left brace is in a new line, we should consume it first so that
1863       // it does not make the namespace non-empty.
1864       // FIXME: error handling if there is no left brace.
1865       if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
1866         NewLine = CurrentLine;
1867         return false;
1868       }
1869     } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
1870       return false;
1871     }
1872     while (++CurrentLine < End) {
1873       if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
1874         break;
1875 
1876       if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
1877         if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
1878                                  DeletedLines))
1879           return false;
1880         CurrentLine = NewLine;
1881         continue;
1882       }
1883 
1884       if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
1885         continue;
1886 
1887       // If there is anything other than comments or nested namespaces in the
1888       // current namespace, the namespace cannot be empty.
1889       NewLine = CurrentLine;
1890       return false;
1891     }
1892 
1893     NewLine = CurrentLine;
1894     if (CurrentLine >= End)
1895       return false;
1896 
1897     // Check if the empty namespace is actually affected by changed ranges.
1898     if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
1899             AnnotatedLines[InitLine]->First->Tok.getLocation(),
1900             AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc())))
1901       return false;
1902 
1903     for (unsigned i = InitLine; i <= CurrentLine; ++i) {
1904       DeletedLines.insert(i);
1905     }
1906 
1907     return true;
1908   }
1909 
1910   // Checks pairs {start, start->next},..., {end->previous, end} and deletes one
1911   // of the token in the pair if the left token has \p LK token kind and the
1912   // right token has \p RK token kind. If \p DeleteLeft is true, the left token
1913   // is deleted on match; otherwise, the right token is deleted.
1914   template <typename LeftKind, typename RightKind>
1915   void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
1916                    bool DeleteLeft) {
1917     auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {
1918       for (auto *Res = Tok.Next; Res; Res = Res->Next)
1919         if (!Res->is(tok::comment) &&
1920             DeletedTokens.find(Res) == DeletedTokens.end())
1921           return Res;
1922       return nullptr;
1923     };
1924     for (auto *Left = Start; Left;) {
1925       auto *Right = NextNotDeleted(*Left);
1926       if (!Right)
1927         break;
1928       if (Left->is(LK) && Right->is(RK)) {
1929         deleteToken(DeleteLeft ? Left : Right);
1930         for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
1931           deleteToken(Tok);
1932         // If the right token is deleted, we should keep the left token
1933         // unchanged and pair it with the new right token.
1934         if (!DeleteLeft)
1935           continue;
1936       }
1937       Left = Right;
1938     }
1939   }
1940 
1941   template <typename LeftKind, typename RightKind>
1942   void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
1943     cleanupPair(Start, LK, RK, /*DeleteLeft=*/true);
1944   }
1945 
1946   template <typename LeftKind, typename RightKind>
1947   void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
1948     cleanupPair(Start, LK, RK, /*DeleteLeft=*/false);
1949   }
1950 
1951   // Delete the given token.
1952   inline void deleteToken(FormatToken *Tok) {
1953     if (Tok)
1954       DeletedTokens.insert(Tok);
1955   }
1956 
1957   tooling::Replacements generateFixes() {
1958     tooling::Replacements Fixes;
1959     std::vector<FormatToken *> Tokens;
1960     std::copy(DeletedTokens.begin(), DeletedTokens.end(),
1961               std::back_inserter(Tokens));
1962 
1963     // Merge multiple continuous token deletions into one big deletion so that
1964     // the number of replacements can be reduced. This makes computing affected
1965     // ranges more efficient when we run reformat on the changed code.
1966     unsigned Idx = 0;
1967     while (Idx < Tokens.size()) {
1968       unsigned St = Idx, End = Idx;
1969       while ((End + 1) < Tokens.size() &&
1970              Tokens[End]->Next == Tokens[End + 1]) {
1971         End++;
1972       }
1973       auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
1974                                               Tokens[End]->Tok.getEndLoc());
1975       auto Err =
1976           Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, ""));
1977       // FIXME: better error handling. for now just print error message and skip
1978       // for the release version.
1979       if (Err) {
1980         llvm::errs() << llvm::toString(std::move(Err)) << "\n";
1981         assert(false && "Fixes must not conflict!");
1982       }
1983       Idx = End + 1;
1984     }
1985 
1986     return Fixes;
1987   }
1988 
1989   // Class for less-than inequality comparason for the set `RedundantTokens`.
1990   // We store tokens in the order they appear in the translation unit so that
1991   // we do not need to sort them in `generateFixes()`.
1992   struct FormatTokenLess {
1993     FormatTokenLess(const SourceManager &SM) : SM(SM) {}
1994 
1995     bool operator()(const FormatToken *LHS, const FormatToken *RHS) const {
1996       return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
1997                                           RHS->Tok.getLocation());
1998     }
1999     const SourceManager &SM;
2000   };
2001 
2002   // Tokens to be deleted.
2003   std::set<FormatToken *, FormatTokenLess> DeletedTokens;
2004 };
2005 
2006 class ObjCHeaderStyleGuesser : public TokenAnalyzer {
2007 public:
2008   ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style)
2009       : TokenAnalyzer(Env, Style), IsObjC(false) {}
2010 
2011   std::pair<tooling::Replacements, unsigned>
2012   analyze(TokenAnnotator &Annotator,
2013           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2014           FormatTokenLexer &Tokens) override {
2015     assert(Style.Language == FormatStyle::LK_Cpp);
2016     IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines,
2017                          Tokens.getKeywords());
2018     tooling::Replacements Result;
2019     return {Result, 0};
2020   }
2021 
2022   bool isObjC() { return IsObjC; }
2023 
2024 private:
2025   static bool
2026   guessIsObjC(const SourceManager &SourceManager,
2027               const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2028               const AdditionalKeywords &Keywords) {
2029     // Keep this array sorted, since we are binary searching over it.
2030     static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
2031         "CGFloat",
2032         "CGPoint",
2033         "CGPointMake",
2034         "CGPointZero",
2035         "CGRect",
2036         "CGRectEdge",
2037         "CGRectInfinite",
2038         "CGRectMake",
2039         "CGRectNull",
2040         "CGRectZero",
2041         "CGSize",
2042         "CGSizeMake",
2043         "CGVector",
2044         "CGVectorMake",
2045         "NSAffineTransform",
2046         "NSArray",
2047         "NSAttributedString",
2048         "NSBlockOperation",
2049         "NSBundle",
2050         "NSCache",
2051         "NSCalendar",
2052         "NSCharacterSet",
2053         "NSCountedSet",
2054         "NSData",
2055         "NSDataDetector",
2056         "NSDecimal",
2057         "NSDecimalNumber",
2058         "NSDictionary",
2059         "NSEdgeInsets",
2060         "NSHashTable",
2061         "NSIndexPath",
2062         "NSIndexSet",
2063         "NSInteger",
2064         "NSInvocationOperation",
2065         "NSLocale",
2066         "NSMapTable",
2067         "NSMutableArray",
2068         "NSMutableAttributedString",
2069         "NSMutableCharacterSet",
2070         "NSMutableData",
2071         "NSMutableDictionary",
2072         "NSMutableIndexSet",
2073         "NSMutableOrderedSet",
2074         "NSMutableSet",
2075         "NSMutableString",
2076         "NSNumber",
2077         "NSNumberFormatter",
2078         "NSObject",
2079         "NSOperation",
2080         "NSOperationQueue",
2081         "NSOperationQueuePriority",
2082         "NSOrderedSet",
2083         "NSPoint",
2084         "NSPointerArray",
2085         "NSQualityOfService",
2086         "NSRange",
2087         "NSRect",
2088         "NSRegularExpression",
2089         "NSSet",
2090         "NSSize",
2091         "NSString",
2092         "NSTimeZone",
2093         "NSUInteger",
2094         "NSURL",
2095         "NSURLComponents",
2096         "NSURLQueryItem",
2097         "NSUUID",
2098         "NSValue",
2099         "UIImage",
2100         "UIView",
2101     };
2102 
2103     for (auto Line : AnnotatedLines) {
2104       if (Line->First && (Line->First->TokenText.startswith("#") ||
2105                           Line->First->TokenText == "__pragma" ||
2106                           Line->First->TokenText == "_Pragma"))
2107         continue;
2108       for (const FormatToken *FormatTok = Line->First; FormatTok;
2109            FormatTok = FormatTok->Next) {
2110         if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
2111              (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
2112               FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
2113                                  tok::l_brace))) ||
2114             (FormatTok->Tok.isAnyIdentifier() &&
2115              std::binary_search(std::begin(FoundationIdentifiers),
2116                                 std::end(FoundationIdentifiers),
2117                                 FormatTok->TokenText)) ||
2118             FormatTok->is(TT_ObjCStringLiteral) ||
2119             FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,
2120                                Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,
2121                                TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,
2122                                TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,
2123                                TT_ObjCProperty)) {
2124           LLVM_DEBUG(llvm::dbgs()
2125                      << "Detected ObjC at location "
2126                      << FormatTok->Tok.getLocation().printToString(
2127                             SourceManager)
2128                      << " token: " << FormatTok->TokenText << " token type: "
2129                      << getTokenTypeName(FormatTok->getType()) << "\n");
2130           return true;
2131         }
2132         if (guessIsObjC(SourceManager, Line->Children, Keywords))
2133           return true;
2134       }
2135     }
2136     return false;
2137   }
2138 
2139   bool IsObjC;
2140 };
2141 
2142 struct IncludeDirective {
2143   StringRef Filename;
2144   StringRef Text;
2145   unsigned Offset;
2146   int Category;
2147   int Priority;
2148 };
2149 
2150 struct JavaImportDirective {
2151   StringRef Identifier;
2152   StringRef Text;
2153   unsigned Offset;
2154   std::vector<StringRef> AssociatedCommentLines;
2155   bool IsStatic;
2156 };
2157 
2158 } // end anonymous namespace
2159 
2160 // Determines whether 'Ranges' intersects with ('Start', 'End').
2161 static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start,
2162                          unsigned End) {
2163   for (auto Range : Ranges) {
2164     if (Range.getOffset() < End &&
2165         Range.getOffset() + Range.getLength() > Start)
2166       return true;
2167   }
2168   return false;
2169 }
2170 
2171 // Returns a pair (Index, OffsetToEOL) describing the position of the cursor
2172 // before sorting/deduplicating. Index is the index of the include under the
2173 // cursor in the original set of includes. If this include has duplicates, it is
2174 // the index of the first of the duplicates as the others are going to be
2175 // removed. OffsetToEOL describes the cursor's position relative to the end of
2176 // its current line.
2177 // If `Cursor` is not on any #include, `Index` will be UINT_MAX.
2178 static std::pair<unsigned, unsigned>
2179 FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes,
2180                 const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) {
2181   unsigned CursorIndex = UINT_MAX;
2182   unsigned OffsetToEOL = 0;
2183   for (int i = 0, e = Includes.size(); i != e; ++i) {
2184     unsigned Start = Includes[Indices[i]].Offset;
2185     unsigned End = Start + Includes[Indices[i]].Text.size();
2186     if (!(Cursor >= Start && Cursor < End))
2187       continue;
2188     CursorIndex = Indices[i];
2189     OffsetToEOL = End - Cursor;
2190     // Put the cursor on the only remaining #include among the duplicate
2191     // #includes.
2192     while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text)
2193       CursorIndex = i;
2194     break;
2195   }
2196   return std::make_pair(CursorIndex, OffsetToEOL);
2197 }
2198 
2199 // Replace all "\r\n" with "\n".
2200 std::string replaceCRLF(const std::string &Code) {
2201   std::string NewCode;
2202   size_t Pos = 0, LastPos = 0;
2203 
2204   do {
2205     Pos = Code.find("\r\n", LastPos);
2206     if (Pos == LastPos) {
2207       LastPos++;
2208       continue;
2209     }
2210     if (Pos == std::string::npos) {
2211       NewCode += Code.substr(LastPos);
2212       break;
2213     }
2214     NewCode += Code.substr(LastPos, Pos - LastPos) + "\n";
2215     LastPos = Pos + 2;
2216   } while (Pos != std::string::npos);
2217 
2218   return NewCode;
2219 }
2220 
2221 // Sorts and deduplicate a block of includes given by 'Includes' alphabetically
2222 // adding the necessary replacement to 'Replaces'. 'Includes' must be in strict
2223 // source order.
2224 // #include directives with the same text will be deduplicated, and only the
2225 // first #include in the duplicate #includes remains. If the `Cursor` is
2226 // provided and put on a deleted #include, it will be moved to the remaining
2227 // #include in the duplicate #includes.
2228 static void sortCppIncludes(const FormatStyle &Style,
2229                             const SmallVectorImpl<IncludeDirective> &Includes,
2230                             ArrayRef<tooling::Range> Ranges, StringRef FileName,
2231                             StringRef Code, tooling::Replacements &Replaces,
2232                             unsigned *Cursor) {
2233   tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
2234   unsigned IncludesBeginOffset = Includes.front().Offset;
2235   unsigned IncludesEndOffset =
2236       Includes.back().Offset + Includes.back().Text.size();
2237   unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
2238   if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
2239     return;
2240   SmallVector<unsigned, 16> Indices;
2241   for (unsigned i = 0, e = Includes.size(); i != e; ++i) {
2242     Indices.push_back(i);
2243   }
2244 
2245   if (Style.SortIncludes == FormatStyle::SI_CaseSensitive) {
2246     llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
2247       const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
2248       const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
2249       return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
2250                       Includes[LHSI].Filename) <
2251              std::tie(Includes[RHSI].Priority, RHSFilenameLower,
2252                       Includes[RHSI].Filename);
2253     });
2254   } else {
2255     llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
2256       return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
2257              std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
2258     });
2259   }
2260 
2261   // The index of the include on which the cursor will be put after
2262   // sorting/deduplicating.
2263   unsigned CursorIndex;
2264   // The offset from cursor to the end of line.
2265   unsigned CursorToEOLOffset;
2266   if (Cursor)
2267     std::tie(CursorIndex, CursorToEOLOffset) =
2268         FindCursorIndex(Includes, Indices, *Cursor);
2269 
2270   // Deduplicate #includes.
2271   Indices.erase(std::unique(Indices.begin(), Indices.end(),
2272                             [&](unsigned LHSI, unsigned RHSI) {
2273                               return Includes[LHSI].Text.trim() ==
2274                                      Includes[RHSI].Text.trim();
2275                             }),
2276                 Indices.end());
2277 
2278   int CurrentCategory = Includes.front().Category;
2279 
2280   // If the #includes are out of order, we generate a single replacement fixing
2281   // the entire block. Otherwise, no replacement is generated.
2282   // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not
2283   // enough as additional newlines might be added or removed across #include
2284   // blocks. This we handle below by generating the updated #imclude blocks and
2285   // comparing it to the original.
2286   if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) &&
2287       Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve)
2288     return;
2289 
2290   std::string result;
2291   for (unsigned Index : Indices) {
2292     if (!result.empty()) {
2293       result += "\n";
2294       if (Style.IncludeStyle.IncludeBlocks ==
2295               tooling::IncludeStyle::IBS_Regroup &&
2296           CurrentCategory != Includes[Index].Category)
2297         result += "\n";
2298     }
2299     result += Includes[Index].Text;
2300     if (Cursor && CursorIndex == Index)
2301       *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
2302     CurrentCategory = Includes[Index].Category;
2303   }
2304 
2305   // If the #includes are out of order, we generate a single replacement fixing
2306   // the entire range of blocks. Otherwise, no replacement is generated.
2307   if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
2308                                  IncludesBeginOffset, IncludesBlockSize))))
2309     return;
2310 
2311   auto Err = Replaces.add(tooling::Replacement(
2312       FileName, Includes.front().Offset, IncludesBlockSize, result));
2313   // FIXME: better error handling. For now, just skip the replacement for the
2314   // release version.
2315   if (Err) {
2316     llvm::errs() << llvm::toString(std::move(Err)) << "\n";
2317     assert(false);
2318   }
2319 }
2320 
2321 namespace {
2322 
2323 const char CppIncludeRegexPattern[] =
2324     R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))";
2325 
2326 } // anonymous namespace
2327 
2328 tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
2329                                       ArrayRef<tooling::Range> Ranges,
2330                                       StringRef FileName,
2331                                       tooling::Replacements &Replaces,
2332                                       unsigned *Cursor) {
2333   unsigned Prev = llvm::StringSwitch<size_t>(Code)
2334                       .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM
2335                       .Default(0);
2336   unsigned SearchFrom = 0;
2337   llvm::Regex IncludeRegex(CppIncludeRegexPattern);
2338   SmallVector<StringRef, 4> Matches;
2339   SmallVector<IncludeDirective, 16> IncludesInBlock;
2340 
2341   // In compiled files, consider the first #include to be the main #include of
2342   // the file if it is not a system #include. This ensures that the header
2343   // doesn't have hidden dependencies
2344   // (http://llvm.org/docs/CodingStandards.html#include-style).
2345   //
2346   // FIXME: Do some sanity checking, e.g. edit distance of the base name, to fix
2347   // cases where the first #include is unlikely to be the main header.
2348   tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
2349   bool FirstIncludeBlock = true;
2350   bool MainIncludeFound = false;
2351   bool FormattingOff = false;
2352 
2353   for (;;) {
2354     auto Pos = Code.find('\n', SearchFrom);
2355     StringRef Line =
2356         Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
2357 
2358     StringRef Trimmed = Line.trim();
2359     if (Trimmed == "// clang-format off" || Trimmed == "/* clang-format off */")
2360       FormattingOff = true;
2361     else if (Trimmed == "// clang-format on" ||
2362              Trimmed == "/* clang-format on */")
2363       FormattingOff = false;
2364 
2365     const bool EmptyLineSkipped =
2366         Trimmed.empty() &&
2367         (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge ||
2368          Style.IncludeStyle.IncludeBlocks ==
2369              tooling::IncludeStyle::IBS_Regroup);
2370 
2371     bool MergeWithNextLine = Trimmed.endswith("\\");
2372     if (!FormattingOff && !MergeWithNextLine) {
2373       if (IncludeRegex.match(Line, &Matches)) {
2374         StringRef IncludeName = Matches[2];
2375         int Category = Categories.getIncludePriority(
2376             IncludeName,
2377             /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock);
2378         int Priority = Categories.getSortIncludePriority(
2379             IncludeName, !MainIncludeFound && FirstIncludeBlock);
2380         if (Category == 0)
2381           MainIncludeFound = true;
2382         IncludesInBlock.push_back(
2383             {IncludeName, Line, Prev, Category, Priority});
2384       } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
2385         sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code,
2386                         Replaces, Cursor);
2387         IncludesInBlock.clear();
2388         if (Trimmed.startswith("#pragma hdrstop")) // Precompiled headers.
2389           FirstIncludeBlock = true;
2390         else
2391           FirstIncludeBlock = false;
2392       }
2393     }
2394     if (Pos == StringRef::npos || Pos + 1 == Code.size())
2395       break;
2396 
2397     if (!MergeWithNextLine)
2398       Prev = Pos + 1;
2399     SearchFrom = Pos + 1;
2400   }
2401   if (!IncludesInBlock.empty()) {
2402     sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces,
2403                     Cursor);
2404   }
2405   return Replaces;
2406 }
2407 
2408 // Returns group number to use as a first order sort on imports. Gives UINT_MAX
2409 // if the import does not match any given groups.
2410 static unsigned findJavaImportGroup(const FormatStyle &Style,
2411                                     StringRef ImportIdentifier) {
2412   unsigned LongestMatchIndex = UINT_MAX;
2413   unsigned LongestMatchLength = 0;
2414   for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) {
2415     std::string GroupPrefix = Style.JavaImportGroups[I];
2416     if (ImportIdentifier.startswith(GroupPrefix) &&
2417         GroupPrefix.length() > LongestMatchLength) {
2418       LongestMatchIndex = I;
2419       LongestMatchLength = GroupPrefix.length();
2420     }
2421   }
2422   return LongestMatchIndex;
2423 }
2424 
2425 // Sorts and deduplicates a block of includes given by 'Imports' based on
2426 // JavaImportGroups, then adding the necessary replacement to 'Replaces'.
2427 // Import declarations with the same text will be deduplicated. Between each
2428 // import group, a newline is inserted, and within each import group, a
2429 // lexicographic sort based on ASCII value is performed.
2430 static void sortJavaImports(const FormatStyle &Style,
2431                             const SmallVectorImpl<JavaImportDirective> &Imports,
2432                             ArrayRef<tooling::Range> Ranges, StringRef FileName,
2433                             StringRef Code, tooling::Replacements &Replaces) {
2434   unsigned ImportsBeginOffset = Imports.front().Offset;
2435   unsigned ImportsEndOffset =
2436       Imports.back().Offset + Imports.back().Text.size();
2437   unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;
2438   if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))
2439     return;
2440   SmallVector<unsigned, 16> Indices;
2441   SmallVector<unsigned, 16> JavaImportGroups;
2442   for (unsigned i = 0, e = Imports.size(); i != e; ++i) {
2443     Indices.push_back(i);
2444     JavaImportGroups.push_back(
2445         findJavaImportGroup(Style, Imports[i].Identifier));
2446   }
2447   bool StaticImportAfterNormalImport =
2448       Style.SortJavaStaticImport == FormatStyle::SJSIO_After;
2449   llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
2450     // Negating IsStatic to push static imports above non-static imports.
2451     return std::make_tuple(!Imports[LHSI].IsStatic ^
2452                                StaticImportAfterNormalImport,
2453                            JavaImportGroups[LHSI], Imports[LHSI].Identifier) <
2454            std::make_tuple(!Imports[RHSI].IsStatic ^
2455                                StaticImportAfterNormalImport,
2456                            JavaImportGroups[RHSI], Imports[RHSI].Identifier);
2457   });
2458 
2459   // Deduplicate imports.
2460   Indices.erase(std::unique(Indices.begin(), Indices.end(),
2461                             [&](unsigned LHSI, unsigned RHSI) {
2462                               return Imports[LHSI].Text == Imports[RHSI].Text;
2463                             }),
2464                 Indices.end());
2465 
2466   bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
2467   unsigned CurrentImportGroup = JavaImportGroups[Indices.front()];
2468 
2469   std::string result;
2470   for (unsigned Index : Indices) {
2471     if (!result.empty()) {
2472       result += "\n";
2473       if (CurrentIsStatic != Imports[Index].IsStatic ||
2474           CurrentImportGroup != JavaImportGroups[Index])
2475         result += "\n";
2476     }
2477     for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) {
2478       result += CommentLine;
2479       result += "\n";
2480     }
2481     result += Imports[Index].Text;
2482     CurrentIsStatic = Imports[Index].IsStatic;
2483     CurrentImportGroup = JavaImportGroups[Index];
2484   }
2485 
2486   // If the imports are out of order, we generate a single replacement fixing
2487   // the entire block. Otherwise, no replacement is generated.
2488   if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
2489                                  Imports.front().Offset, ImportsBlockSize))))
2490     return;
2491 
2492   auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset,
2493                                                ImportsBlockSize, result));
2494   // FIXME: better error handling. For now, just skip the replacement for the
2495   // release version.
2496   if (Err) {
2497     llvm::errs() << llvm::toString(std::move(Err)) << "\n";
2498     assert(false);
2499   }
2500 }
2501 
2502 namespace {
2503 
2504 const char JavaImportRegexPattern[] =
2505     "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;";
2506 
2507 } // anonymous namespace
2508 
2509 tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code,
2510                                       ArrayRef<tooling::Range> Ranges,
2511                                       StringRef FileName,
2512                                       tooling::Replacements &Replaces) {
2513   unsigned Prev = 0;
2514   unsigned SearchFrom = 0;
2515   llvm::Regex ImportRegex(JavaImportRegexPattern);
2516   SmallVector<StringRef, 4> Matches;
2517   SmallVector<JavaImportDirective, 16> ImportsInBlock;
2518   std::vector<StringRef> AssociatedCommentLines;
2519 
2520   bool FormattingOff = false;
2521 
2522   for (;;) {
2523     auto Pos = Code.find('\n', SearchFrom);
2524     StringRef Line =
2525         Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
2526 
2527     StringRef Trimmed = Line.trim();
2528     if (Trimmed == "// clang-format off")
2529       FormattingOff = true;
2530     else if (Trimmed == "// clang-format on")
2531       FormattingOff = false;
2532 
2533     if (ImportRegex.match(Line, &Matches)) {
2534       if (FormattingOff) {
2535         // If at least one import line has formatting turned off, turn off
2536         // formatting entirely.
2537         return Replaces;
2538       }
2539       StringRef Static = Matches[1];
2540       StringRef Identifier = Matches[2];
2541       bool IsStatic = false;
2542       if (Static.contains("static")) {
2543         IsStatic = true;
2544       }
2545       ImportsInBlock.push_back(
2546           {Identifier, Line, Prev, AssociatedCommentLines, IsStatic});
2547       AssociatedCommentLines.clear();
2548     } else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) {
2549       // Associating comments within the imports with the nearest import below
2550       AssociatedCommentLines.push_back(Line);
2551     }
2552     Prev = Pos + 1;
2553     if (Pos == StringRef::npos || Pos + 1 == Code.size())
2554       break;
2555     SearchFrom = Pos + 1;
2556   }
2557   if (!ImportsInBlock.empty())
2558     sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces);
2559   return Replaces;
2560 }
2561 
2562 bool isMpegTS(StringRef Code) {
2563   // MPEG transport streams use the ".ts" file extension. clang-format should
2564   // not attempt to format those. MPEG TS' frame format starts with 0x47 every
2565   // 189 bytes - detect that and return.
2566   return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
2567 }
2568 
2569 bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); }
2570 
2571 tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
2572                                    ArrayRef<tooling::Range> Ranges,
2573                                    StringRef FileName, unsigned *Cursor) {
2574   tooling::Replacements Replaces;
2575   if (!Style.SortIncludes)
2576     return Replaces;
2577   if (isLikelyXml(Code))
2578     return Replaces;
2579   if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript &&
2580       isMpegTS(Code))
2581     return Replaces;
2582   if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript)
2583     return sortJavaScriptImports(Style, Code, Ranges, FileName);
2584   if (Style.Language == FormatStyle::LanguageKind::LK_Java)
2585     return sortJavaImports(Style, Code, Ranges, FileName, Replaces);
2586   sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor);
2587   return Replaces;
2588 }
2589 
2590 template <typename T>
2591 static llvm::Expected<tooling::Replacements>
2592 processReplacements(T ProcessFunc, StringRef Code,
2593                     const tooling::Replacements &Replaces,
2594                     const FormatStyle &Style) {
2595   if (Replaces.empty())
2596     return tooling::Replacements();
2597 
2598   auto NewCode = applyAllReplacements(Code, Replaces);
2599   if (!NewCode)
2600     return NewCode.takeError();
2601   std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();
2602   StringRef FileName = Replaces.begin()->getFilePath();
2603 
2604   tooling::Replacements FormatReplaces =
2605       ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
2606 
2607   return Replaces.merge(FormatReplaces);
2608 }
2609 
2610 llvm::Expected<tooling::Replacements>
2611 formatReplacements(StringRef Code, const tooling::Replacements &Replaces,
2612                    const FormatStyle &Style) {
2613   // We need to use lambda function here since there are two versions of
2614   // `sortIncludes`.
2615   auto SortIncludes = [](const FormatStyle &Style, StringRef Code,
2616                          std::vector<tooling::Range> Ranges,
2617                          StringRef FileName) -> tooling::Replacements {
2618     return sortIncludes(Style, Code, Ranges, FileName);
2619   };
2620   auto SortedReplaces =
2621       processReplacements(SortIncludes, Code, Replaces, Style);
2622   if (!SortedReplaces)
2623     return SortedReplaces.takeError();
2624 
2625   // We need to use lambda function here since there are two versions of
2626   // `reformat`.
2627   auto Reformat = [](const FormatStyle &Style, StringRef Code,
2628                      std::vector<tooling::Range> Ranges,
2629                      StringRef FileName) -> tooling::Replacements {
2630     return reformat(Style, Code, Ranges, FileName);
2631   };
2632   return processReplacements(Reformat, Code, *SortedReplaces, Style);
2633 }
2634 
2635 namespace {
2636 
2637 inline bool isHeaderInsertion(const tooling::Replacement &Replace) {
2638   return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 &&
2639          llvm::Regex(CppIncludeRegexPattern)
2640              .match(Replace.getReplacementText());
2641 }
2642 
2643 inline bool isHeaderDeletion(const tooling::Replacement &Replace) {
2644   return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1;
2645 }
2646 
2647 // FIXME: insert empty lines between newly created blocks.
2648 tooling::Replacements
2649 fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
2650                         const FormatStyle &Style) {
2651   if (!Style.isCpp())
2652     return Replaces;
2653 
2654   tooling::Replacements HeaderInsertions;
2655   std::set<llvm::StringRef> HeadersToDelete;
2656   tooling::Replacements Result;
2657   for (const auto &R : Replaces) {
2658     if (isHeaderInsertion(R)) {
2659       // Replacements from \p Replaces must be conflict-free already, so we can
2660       // simply consume the error.
2661       llvm::consumeError(HeaderInsertions.add(R));
2662     } else if (isHeaderDeletion(R)) {
2663       HeadersToDelete.insert(R.getReplacementText());
2664     } else if (R.getOffset() == UINT_MAX) {
2665       llvm::errs() << "Insertions other than header #include insertion are "
2666                       "not supported! "
2667                    << R.getReplacementText() << "\n";
2668     } else {
2669       llvm::consumeError(Result.add(R));
2670     }
2671   }
2672   if (HeaderInsertions.empty() && HeadersToDelete.empty())
2673     return Replaces;
2674 
2675   StringRef FileName = Replaces.begin()->getFilePath();
2676   tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle);
2677 
2678   for (const auto &Header : HeadersToDelete) {
2679     tooling::Replacements Replaces =
2680         Includes.remove(Header.trim("\"<>"), Header.startswith("<"));
2681     for (const auto &R : Replaces) {
2682       auto Err = Result.add(R);
2683       if (Err) {
2684         // Ignore the deletion on conflict.
2685         llvm::errs() << "Failed to add header deletion replacement for "
2686                      << Header << ": " << llvm::toString(std::move(Err))
2687                      << "\n";
2688       }
2689     }
2690   }
2691 
2692   llvm::Regex IncludeRegex = llvm::Regex(CppIncludeRegexPattern);
2693   llvm::SmallVector<StringRef, 4> Matches;
2694   for (const auto &R : HeaderInsertions) {
2695     auto IncludeDirective = R.getReplacementText();
2696     bool Matched = IncludeRegex.match(IncludeDirective, &Matches);
2697     assert(Matched && "Header insertion replacement must have replacement text "
2698                       "'#include ...'");
2699     (void)Matched;
2700     auto IncludeName = Matches[2];
2701     auto Replace =
2702         Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<"));
2703     if (Replace) {
2704       auto Err = Result.add(*Replace);
2705       if (Err) {
2706         llvm::consumeError(std::move(Err));
2707         unsigned NewOffset =
2708             Result.getShiftedCodePosition(Replace->getOffset());
2709         auto Shifted = tooling::Replacement(FileName, NewOffset, 0,
2710                                             Replace->getReplacementText());
2711         Result = Result.merge(tooling::Replacements(Shifted));
2712       }
2713     }
2714   }
2715   return Result;
2716 }
2717 
2718 } // anonymous namespace
2719 
2720 llvm::Expected<tooling::Replacements>
2721 cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
2722                           const FormatStyle &Style) {
2723   // We need to use lambda function here since there are two versions of
2724   // `cleanup`.
2725   auto Cleanup = [](const FormatStyle &Style, StringRef Code,
2726                     std::vector<tooling::Range> Ranges,
2727                     StringRef FileName) -> tooling::Replacements {
2728     return cleanup(Style, Code, Ranges, FileName);
2729   };
2730   // Make header insertion replacements insert new headers into correct blocks.
2731   tooling::Replacements NewReplaces =
2732       fixCppIncludeInsertions(Code, Replaces, Style);
2733   return processReplacements(Cleanup, Code, NewReplaces, Style);
2734 }
2735 
2736 namespace internal {
2737 std::pair<tooling::Replacements, unsigned>
2738 reformat(const FormatStyle &Style, StringRef Code,
2739          ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,
2740          unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,
2741          FormattingAttemptStatus *Status) {
2742   FormatStyle Expanded = expandPresets(Style);
2743   if (Expanded.DisableFormat)
2744     return {tooling::Replacements(), 0};
2745   if (isLikelyXml(Code))
2746     return {tooling::Replacements(), 0};
2747   if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code))
2748     return {tooling::Replacements(), 0};
2749 
2750   typedef std::function<std::pair<tooling::Replacements, unsigned>(
2751       const Environment &)>
2752       AnalyzerPass;
2753   SmallVector<AnalyzerPass, 4> Passes;
2754 
2755   if (Style.Language == FormatStyle::LK_Cpp) {
2756     if (Style.FixNamespaceComments)
2757       Passes.emplace_back([&](const Environment &Env) {
2758         return NamespaceEndCommentsFixer(Env, Expanded).process();
2759       });
2760 
2761     if (Style.SortUsingDeclarations)
2762       Passes.emplace_back([&](const Environment &Env) {
2763         return UsingDeclarationsSorter(Env, Expanded).process();
2764       });
2765   }
2766 
2767   if (Style.Language == FormatStyle::LK_JavaScript &&
2768       Style.JavaScriptQuotes != FormatStyle::JSQS_Leave)
2769     Passes.emplace_back([&](const Environment &Env) {
2770       return JavaScriptRequoter(Env, Expanded).process();
2771     });
2772 
2773   Passes.emplace_back([&](const Environment &Env) {
2774     return Formatter(Env, Expanded, Status).process();
2775   });
2776 
2777   if (Style.Language == FormatStyle::LK_JavaScript &&
2778       Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped)
2779     Passes.emplace_back([&](const Environment &Env) {
2780       return TrailingCommaInserter(Env, Expanded).process();
2781     });
2782 
2783   auto Env =
2784       std::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn,
2785                                     NextStartColumn, LastStartColumn);
2786   llvm::Optional<std::string> CurrentCode = None;
2787   tooling::Replacements Fixes;
2788   unsigned Penalty = 0;
2789   for (size_t I = 0, E = Passes.size(); I < E; ++I) {
2790     std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
2791     auto NewCode = applyAllReplacements(
2792         CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
2793     if (NewCode) {
2794       Fixes = Fixes.merge(PassFixes.first);
2795       Penalty += PassFixes.second;
2796       if (I + 1 < E) {
2797         CurrentCode = std::move(*NewCode);
2798         Env = std::make_unique<Environment>(
2799             *CurrentCode, FileName,
2800             tooling::calculateRangesAfterReplacements(Fixes, Ranges),
2801             FirstStartColumn, NextStartColumn, LastStartColumn);
2802       }
2803     }
2804   }
2805 
2806   return {Fixes, Penalty};
2807 }
2808 } // namespace internal
2809 
2810 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
2811                                ArrayRef<tooling::Range> Ranges,
2812                                StringRef FileName,
2813                                FormattingAttemptStatus *Status) {
2814   return internal::reformat(Style, Code, Ranges,
2815                             /*FirstStartColumn=*/0,
2816                             /*NextStartColumn=*/0,
2817                             /*LastStartColumn=*/0, FileName, Status)
2818       .first;
2819 }
2820 
2821 tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
2822                               ArrayRef<tooling::Range> Ranges,
2823                               StringRef FileName) {
2824   // cleanups only apply to C++ (they mostly concern ctor commas etc.)
2825   if (Style.Language != FormatStyle::LK_Cpp)
2826     return tooling::Replacements();
2827   return Cleaner(Environment(Code, FileName, Ranges), Style).process().first;
2828 }
2829 
2830 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
2831                                ArrayRef<tooling::Range> Ranges,
2832                                StringRef FileName, bool *IncompleteFormat) {
2833   FormattingAttemptStatus Status;
2834   auto Result = reformat(Style, Code, Ranges, FileName, &Status);
2835   if (!Status.FormatComplete)
2836     *IncompleteFormat = true;
2837   return Result;
2838 }
2839 
2840 tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,
2841                                               StringRef Code,
2842                                               ArrayRef<tooling::Range> Ranges,
2843                                               StringRef FileName) {
2844   return NamespaceEndCommentsFixer(Environment(Code, FileName, Ranges), Style)
2845       .process()
2846       .first;
2847 }
2848 
2849 tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
2850                                             StringRef Code,
2851                                             ArrayRef<tooling::Range> Ranges,
2852                                             StringRef FileName) {
2853   return UsingDeclarationsSorter(Environment(Code, FileName, Ranges), Style)
2854       .process()
2855       .first;
2856 }
2857 
2858 LangOptions getFormattingLangOpts(const FormatStyle &Style) {
2859   LangOptions LangOpts;
2860 
2861   FormatStyle::LanguageStandard LexingStd = Style.Standard;
2862   if (LexingStd == FormatStyle::LS_Auto)
2863     LexingStd = FormatStyle::LS_Latest;
2864   if (LexingStd == FormatStyle::LS_Latest)
2865     LexingStd = FormatStyle::LS_Cpp20;
2866   LangOpts.CPlusPlus = 1;
2867   LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11;
2868   LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14;
2869   LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17;
2870   LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20;
2871   LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20;
2872 
2873   LangOpts.LineComment = 1;
2874   bool AlternativeOperators = Style.isCpp();
2875   LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
2876   LangOpts.Bool = 1;
2877   LangOpts.ObjC = 1;
2878   LangOpts.MicrosoftExt = 1;    // To get kw___try, kw___finally.
2879   LangOpts.DeclSpecKeyword = 1; // To get __declspec.
2880   LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict.
2881   return LangOpts;
2882 }
2883 
2884 const char *StyleOptionHelpDescription =
2885     "Coding style, currently supports:\n"
2886     "  LLVM, GNU, Google, Chromium, Microsoft, Mozilla, WebKit.\n"
2887     "Use -style=file to load style configuration from\n"
2888     ".clang-format file located in one of the parent\n"
2889     "directories of the source file (or current\n"
2890     "directory for stdin).\n"
2891     "Use -style=\"{key: value, ...}\" to set specific\n"
2892     "parameters, e.g.:\n"
2893     "  -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
2894 
2895 static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
2896   if (FileName.endswith(".java"))
2897     return FormatStyle::LK_Java;
2898   if (FileName.endswith_lower(".js") || FileName.endswith_lower(".mjs") ||
2899       FileName.endswith_lower(".ts"))
2900     return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript.
2901   if (FileName.endswith(".m") || FileName.endswith(".mm"))
2902     return FormatStyle::LK_ObjC;
2903   if (FileName.endswith_lower(".proto") ||
2904       FileName.endswith_lower(".protodevel"))
2905     return FormatStyle::LK_Proto;
2906   if (FileName.endswith_lower(".textpb") ||
2907       FileName.endswith_lower(".pb.txt") ||
2908       FileName.endswith_lower(".textproto") ||
2909       FileName.endswith_lower(".asciipb"))
2910     return FormatStyle::LK_TextProto;
2911   if (FileName.endswith_lower(".td"))
2912     return FormatStyle::LK_TableGen;
2913   if (FileName.endswith_lower(".cs"))
2914     return FormatStyle::LK_CSharp;
2915   return FormatStyle::LK_Cpp;
2916 }
2917 
2918 FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {
2919   const auto GuessedLanguage = getLanguageByFileName(FileName);
2920   if (GuessedLanguage == FormatStyle::LK_Cpp) {
2921     auto Extension = llvm::sys::path::extension(FileName);
2922     // If there's no file extension (or it's .h), we need to check the contents
2923     // of the code to see if it contains Objective-C.
2924     if (Extension.empty() || Extension == ".h") {
2925       auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName;
2926       Environment Env(Code, NonEmptyFileName, /*Ranges=*/{});
2927       ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle());
2928       Guesser.process();
2929       if (Guesser.isObjC())
2930         return FormatStyle::LK_ObjC;
2931     }
2932   }
2933   return GuessedLanguage;
2934 }
2935 
2936 const char *DefaultFormatStyle = "file";
2937 
2938 const char *DefaultFallbackStyle = "LLVM";
2939 
2940 llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
2941                                      StringRef FallbackStyleName,
2942                                      StringRef Code, llvm::vfs::FileSystem *FS,
2943                                      bool AllowUnknownOptions) {
2944   if (!FS) {
2945     FS = llvm::vfs::getRealFileSystem().get();
2946   }
2947   FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code));
2948 
2949   FormatStyle FallbackStyle = getNoStyle();
2950   if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))
2951     return make_string_error("Invalid fallback style \"" + FallbackStyleName);
2952 
2953   llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1>
2954       ChildFormatTextToApply;
2955 
2956   if (StyleName.startswith("{")) {
2957     // Parse YAML/JSON style from the command line.
2958     StringRef Source = "<command-line>";
2959     if (std::error_code ec =
2960             parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style,
2961                                AllowUnknownOptions))
2962       return make_string_error("Error parsing -style: " + ec.message());
2963     if (Style.InheritsParentConfig)
2964       ChildFormatTextToApply.emplace_back(
2965           llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false));
2966     else
2967       return Style;
2968   }
2969 
2970   // If the style inherits the parent configuration it is a command line
2971   // configuration, which wants to inherit, so we have to skip the check of the
2972   // StyleName.
2973   if (!Style.InheritsParentConfig && !StyleName.equals_lower("file")) {
2974     if (!getPredefinedStyle(StyleName, Style.Language, &Style))
2975       return make_string_error("Invalid value for -style");
2976     if (!Style.InheritsParentConfig)
2977       return Style;
2978   }
2979 
2980   // Reset possible inheritance
2981   Style.InheritsParentConfig = false;
2982 
2983   // Look for .clang-format/_clang-format file in the file's parent directories.
2984   SmallString<128> UnsuitableConfigFiles;
2985   SmallString<128> Path(FileName);
2986   if (std::error_code EC = FS->makeAbsolute(Path))
2987     return make_string_error(EC.message());
2988 
2989   llvm::SmallVector<std::string, 2> FilesToLookFor;
2990   FilesToLookFor.push_back(".clang-format");
2991   FilesToLookFor.push_back("_clang-format");
2992 
2993   for (StringRef Directory = Path; !Directory.empty();
2994        Directory = llvm::sys::path::parent_path(Directory)) {
2995 
2996     auto Status = FS->status(Directory);
2997     if (!Status ||
2998         Status->getType() != llvm::sys::fs::file_type::directory_file) {
2999       continue;
3000     }
3001 
3002     for (const auto &F : FilesToLookFor) {
3003       SmallString<128> ConfigFile(Directory);
3004 
3005       llvm::sys::path::append(ConfigFile, F);
3006       LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
3007 
3008       Status = FS->status(ConfigFile.str());
3009 
3010       if (Status &&
3011           (Status->getType() == llvm::sys::fs::file_type::regular_file)) {
3012         llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
3013             FS->getBufferForFile(ConfigFile.str());
3014         if (std::error_code EC = Text.getError())
3015           return make_string_error(EC.message());
3016         if (std::error_code ec =
3017                 parseConfiguration(*Text.get(), &Style, AllowUnknownOptions)) {
3018           if (ec == ParseError::Unsuitable) {
3019             if (!UnsuitableConfigFiles.empty())
3020               UnsuitableConfigFiles.append(", ");
3021             UnsuitableConfigFiles.append(ConfigFile);
3022             continue;
3023           }
3024           return make_string_error("Error reading " + ConfigFile + ": " +
3025                                    ec.message());
3026         }
3027         LLVM_DEBUG(llvm::dbgs()
3028                    << "Using configuration file " << ConfigFile << "\n");
3029 
3030         if (!Style.InheritsParentConfig) {
3031           if (ChildFormatTextToApply.empty())
3032             return Style;
3033 
3034           LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n");
3035 
3036           for (const auto& MemBuf : llvm::reverse(ChildFormatTextToApply)){
3037             auto Ec = parseConfiguration(*MemBuf, &Style, AllowUnknownOptions);
3038             // It was already correctly parsed.
3039             assert(!Ec);
3040             static_cast<void>(Ec);
3041           }
3042 
3043           return Style;
3044         }
3045 
3046         LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n");
3047 
3048         // Reset inheritance of style
3049         Style.InheritsParentConfig = false;
3050 
3051         ChildFormatTextToApply.emplace_back(std::move(*Text));
3052 
3053         // Breaking out of the inner loop, since we don't want to parse
3054         // .clang-format AND _clang-format, if both exist. Then we continue the
3055         // inner loop (parent directories) in search for the parent
3056         // configuration.
3057         break;
3058       }
3059     }
3060   }
3061   if (!UnsuitableConfigFiles.empty())
3062     return make_string_error("Configuration file(s) do(es) not support " +
3063                              getLanguageName(Style.Language) + ": " +
3064                              UnsuitableConfigFiles);
3065 
3066   if (!ChildFormatTextToApply.empty()) {
3067     assert(ChildFormatTextToApply.size() == 1);
3068 
3069     LLVM_DEBUG(llvm::dbgs()
3070                << "Applying child configuration on fallback style\n");
3071 
3072     auto Ec = parseConfiguration(*ChildFormatTextToApply.front(),
3073                                  &FallbackStyle, AllowUnknownOptions);
3074     // It was already correctly parsed.
3075     assert(!Ec);
3076     static_cast<void>(Ec);
3077   }
3078 
3079   return FallbackStyle;
3080 }
3081 
3082 } // namespace format
3083 } // namespace clang
3084