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