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