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