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