clang 19.0.0git
Format.cpp
Go to the documentation of this file.
1//===--- Format.cpp - Format C++ code -------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file implements functions declared in Format.h. This will be
11/// split into separate files as we go.
12///
13//===----------------------------------------------------------------------===//
14
15#include "clang/Format/Format.h"
25#include "llvm/ADT/Sequence.h"
26
27#define DEBUG_TYPE "format-formatter"
28
30
31LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat)
32
33namespace llvm {
34namespace yaml {
35template <>
36struct 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);
42 }
43};
44
45template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {
46 static void enumInput(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
47 IO.enumCase(Value, "None",
48 FormatStyle::AlignConsecutiveStyle(
49 {/*Enabled=*/false, /*AcrossEmptyLines=*/false,
50 /*AcrossComments=*/false, /*AlignCompound=*/false,
51 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
52 IO.enumCase(Value, "Consecutive",
53 FormatStyle::AlignConsecutiveStyle(
54 {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
55 /*AcrossComments=*/false, /*AlignCompound=*/false,
56 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
57 IO.enumCase(Value, "AcrossEmptyLines",
58 FormatStyle::AlignConsecutiveStyle(
59 {/*Enabled=*/true, /*AcrossEmptyLines=*/true,
60 /*AcrossComments=*/false, /*AlignCompound=*/false,
61 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
62 IO.enumCase(Value, "AcrossComments",
63 FormatStyle::AlignConsecutiveStyle(
64 {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
65 /*AcrossComments=*/true, /*AlignCompound=*/false,
66 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
67 IO.enumCase(Value, "AcrossEmptyLinesAndComments",
68 FormatStyle::AlignConsecutiveStyle(
69 {/*Enabled=*/true, /*AcrossEmptyLines=*/true,
70 /*AcrossComments=*/true, /*AlignCompound=*/false,
71 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
72
73 // For backward compatibility.
74 IO.enumCase(Value, "true",
75 FormatStyle::AlignConsecutiveStyle(
76 {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
77 /*AcrossComments=*/false, /*AlignCompound=*/false,
78 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
79 IO.enumCase(Value, "false",
80 FormatStyle::AlignConsecutiveStyle(
81 {/*Enabled=*/false, /*AcrossEmptyLines=*/false,
82 /*AcrossComments=*/false, /*AlignCompound=*/false,
83 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
84 }
85
86 static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
87 IO.mapOptional("Enabled", Value.Enabled);
88 IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);
89 IO.mapOptional("AcrossComments", Value.AcrossComments);
90 IO.mapOptional("AlignCompound", Value.AlignCompound);
91 IO.mapOptional("AlignFunctionPointers", Value.AlignFunctionPointers);
92 IO.mapOptional("PadOperators", Value.PadOperators);
93 }
94};
95
96template <>
97struct MappingTraits<FormatStyle::ShortCaseStatementsAlignmentStyle> {
98 static void mapping(IO &IO,
99 FormatStyle::ShortCaseStatementsAlignmentStyle &Value) {
100 IO.mapOptional("Enabled", Value.Enabled);
101 IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);
102 IO.mapOptional("AcrossComments", Value.AcrossComments);
103 IO.mapOptional("AlignCaseColons", Value.AlignCaseColons);
104 }
105};
106
107template <>
108struct 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);
113 }
114};
115
116template <>
117struct 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);
123 }
124};
125
126template <> 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);
133 }
134};
135
136template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {
137 static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) {
138 IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto);
139 IO.enumCase(Value, "Always", FormatStyle::BPS_Always);
140 IO.enumCase(Value, "Never", FormatStyle::BPS_Never);
141 }
142};
143
144template <>
145struct ScalarEnumerationTraits<FormatStyle::BitFieldColonSpacingStyle> {
146 static void enumeration(IO &IO,
147 FormatStyle::BitFieldColonSpacingStyle &Value) {
148 IO.enumCase(Value, "Both", FormatStyle::BFCS_Both);
149 IO.enumCase(Value, "None", FormatStyle::BFCS_None);
150 IO.enumCase(Value, "Before", FormatStyle::BFCS_Before);
151 IO.enumCase(Value, "After", FormatStyle::BFCS_After);
152 }
153};
154
155template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
156 static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {
157 IO.enumCase(Value, "Attach", FormatStyle::BS_Attach);
158 IO.enumCase(Value, "Linux", FormatStyle::BS_Linux);
159 IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla);
160 IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);
161 IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
162 IO.enumCase(Value, "Whitesmiths", FormatStyle::BS_Whitesmiths);
163 IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
164 IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit);
165 IO.enumCase(Value, "Custom", FormatStyle::BS_Custom);
166 }
167};
168
169template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
170 static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
171 IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel);
172 IO.mapOptional("AfterClass", Wrapping.AfterClass);
173 IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement);
174 IO.mapOptional("AfterEnum", Wrapping.AfterEnum);
175 IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
176 IO.mapOptional("AfterFunction", Wrapping.AfterFunction);
177 IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace);
178 IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
179 IO.mapOptional("AfterStruct", Wrapping.AfterStruct);
180 IO.mapOptional("AfterUnion", Wrapping.AfterUnion);
181 IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
182 IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
183 IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody);
184 IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile);
185 IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
186 IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);
187 IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);
188 IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
189 }
190};
191
192template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> {
193 static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) {
194 IO.enumCase(Value, "Align", FormatStyle::BAS_Align);
195 IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign);
196 IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak);
197 IO.enumCase(Value, "BlockIndent", FormatStyle::BAS_BlockIndent);
198
199 // For backward compatibility.
200 IO.enumCase(Value, "true", FormatStyle::BAS_Align);
201 IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign);
202 }
203};
204
205template <>
206struct ScalarEnumerationTraits<
207 FormatStyle::BraceWrappingAfterControlStatementStyle> {
208 static void
210 FormatStyle::BraceWrappingAfterControlStatementStyle &Value) {
211 IO.enumCase(Value, "Never", FormatStyle::BWACS_Never);
212 IO.enumCase(Value, "MultiLine", FormatStyle::BWACS_MultiLine);
213 IO.enumCase(Value, "Always", FormatStyle::BWACS_Always);
214
215 // For backward compatibility.
216 IO.enumCase(Value, "false", FormatStyle::BWACS_Never);
217 IO.enumCase(Value, "true", FormatStyle::BWACS_Always);
218 }
219};
220
221template <>
222struct ScalarEnumerationTraits<
223 FormatStyle::BreakBeforeConceptDeclarationsStyle> {
224 static void
225 enumeration(IO &IO, FormatStyle::BreakBeforeConceptDeclarationsStyle &Value) {
226 IO.enumCase(Value, "Never", FormatStyle::BBCDS_Never);
227 IO.enumCase(Value, "Allowed", FormatStyle::BBCDS_Allowed);
228 IO.enumCase(Value, "Always", FormatStyle::BBCDS_Always);
229
230 // For backward compatibility.
231 IO.enumCase(Value, "true", FormatStyle::BBCDS_Always);
232 IO.enumCase(Value, "false", FormatStyle::BBCDS_Allowed);
233 }
234};
235
236template <>
237struct ScalarEnumerationTraits<FormatStyle::BreakBeforeInlineASMColonStyle> {
238 static void enumeration(IO &IO,
239 FormatStyle::BreakBeforeInlineASMColonStyle &Value) {
240 IO.enumCase(Value, "Never", FormatStyle::BBIAS_Never);
241 IO.enumCase(Value, "OnlyMultiline", FormatStyle::BBIAS_OnlyMultiline);
242 IO.enumCase(Value, "Always", FormatStyle::BBIAS_Always);
243 }
244};
245
246template <>
247struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
248 static void
249 enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
250 IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon);
251 IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma);
252 IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon);
253 }
254};
255
256template <>
257struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {
258 static void enumeration(IO &IO,
259 FormatStyle::BreakInheritanceListStyle &Value) {
260 IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon);
261 IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma);
262 IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon);
263 IO.enumCase(Value, "AfterComma", FormatStyle::BILS_AfterComma);
264 }
265};
266
267template <>
268struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
269 static void enumeration(IO &IO,
270 FormatStyle::BreakTemplateDeclarationsStyle &Value) {
271 IO.enumCase(Value, "Leave", FormatStyle::BTDS_Leave);
272 IO.enumCase(Value, "No", FormatStyle::BTDS_No);
273 IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);
274 IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);
275
276 // For backward compatibility.
277 IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine);
278 IO.enumCase(Value, "true", FormatStyle::BTDS_Yes);
279 }
280};
281
282template <> struct ScalarEnumerationTraits<FormatStyle::DAGArgStyle> {
283 static void enumeration(IO &IO, FormatStyle::DAGArgStyle &Value) {
284 IO.enumCase(Value, "DontBreak", FormatStyle::DAS_DontBreak);
285 IO.enumCase(Value, "BreakElements", FormatStyle::DAS_BreakElements);
286 IO.enumCase(Value, "BreakAll", FormatStyle::DAS_BreakAll);
287 }
288};
289
290template <>
291struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
292 static void
293 enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
294 IO.enumCase(Value, "None", FormatStyle::DRTBS_None);
295 IO.enumCase(Value, "All", FormatStyle::DRTBS_All);
296 IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel);
297
298 // For backward compatibility.
299 IO.enumCase(Value, "false", FormatStyle::DRTBS_None);
300 IO.enumCase(Value, "true", FormatStyle::DRTBS_All);
301 }
302};
303
304template <>
305struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
306 static void enumeration(IO &IO,
307 FormatStyle::EscapedNewlineAlignmentStyle &Value) {
308 IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign);
309 IO.enumCase(Value, "Left", FormatStyle::ENAS_Left);
310 IO.enumCase(Value, "Right", FormatStyle::ENAS_Right);
311
312 // For backward compatibility.
313 IO.enumCase(Value, "true", FormatStyle::ENAS_Left);
314 IO.enumCase(Value, "false", FormatStyle::ENAS_Right);
315 }
316};
317
318template <>
319struct ScalarEnumerationTraits<FormatStyle::EmptyLineAfterAccessModifierStyle> {
320 static void
321 enumeration(IO &IO, FormatStyle::EmptyLineAfterAccessModifierStyle &Value) {
322 IO.enumCase(Value, "Never", FormatStyle::ELAAMS_Never);
323 IO.enumCase(Value, "Leave", FormatStyle::ELAAMS_Leave);
324 IO.enumCase(Value, "Always", FormatStyle::ELAAMS_Always);
325 }
326};
327
328template <>
329struct ScalarEnumerationTraits<
330 FormatStyle::EmptyLineBeforeAccessModifierStyle> {
331 static void
332 enumeration(IO &IO, FormatStyle::EmptyLineBeforeAccessModifierStyle &Value) {
333 IO.enumCase(Value, "Never", FormatStyle::ELBAMS_Never);
334 IO.enumCase(Value, "Leave", FormatStyle::ELBAMS_Leave);
335 IO.enumCase(Value, "LogicalBlock", FormatStyle::ELBAMS_LogicalBlock);
336 IO.enumCase(Value, "Always", FormatStyle::ELBAMS_Always);
337 }
338};
339
340template <>
341struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> {
342 static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value) {
343 IO.enumCase(Value, "AfterExternBlock", FormatStyle::IEBS_AfterExternBlock);
344 IO.enumCase(Value, "Indent", FormatStyle::IEBS_Indent);
345 IO.enumCase(Value, "NoIndent", FormatStyle::IEBS_NoIndent);
346 IO.enumCase(Value, "true", FormatStyle::IEBS_Indent);
347 IO.enumCase(Value, "false", FormatStyle::IEBS_NoIndent);
348 }
349};
350
351template <> struct MappingTraits<FormatStyle::IntegerLiteralSeparatorStyle> {
352 static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &Base) {
353 IO.mapOptional("Binary", Base.Binary);
354 IO.mapOptional("BinaryMinDigits", Base.BinaryMinDigits);
355 IO.mapOptional("Decimal", Base.Decimal);
356 IO.mapOptional("DecimalMinDigits", Base.DecimalMinDigits);
357 IO.mapOptional("Hex", Base.Hex);
358 IO.mapOptional("HexMinDigits", Base.HexMinDigits);
359 }
360};
361
362template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {
363 static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) {
364 IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave);
365 IO.enumCase(Value, "Single", FormatStyle::JSQS_Single);
366 IO.enumCase(Value, "Double", FormatStyle::JSQS_Double);
367 }
368};
369
370template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
371 static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
372 IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
373 IO.enumCase(Value, "Java", FormatStyle::LK_Java);
374 IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
375 IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);
376 IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
377 IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);
378 IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto);
379 IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp);
380 IO.enumCase(Value, "Json", FormatStyle::LK_Json);
381 IO.enumCase(Value, "Verilog", FormatStyle::LK_Verilog);
382 }
383};
384
385template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
386 static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
387 IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03);
388 IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias
389 IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias
390
391 IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11);
392 IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias
393
394 IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14);
395 IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17);
396 IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20);
397
398 IO.enumCase(Value, "Latest", FormatStyle::LS_Latest);
399 IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias
400 IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);
401 }
402};
403
404template <>
405struct ScalarEnumerationTraits<FormatStyle::LambdaBodyIndentationKind> {
406 static void enumeration(IO &IO,
407 FormatStyle::LambdaBodyIndentationKind &Value) {
408 IO.enumCase(Value, "Signature", FormatStyle::LBI_Signature);
409 IO.enumCase(Value, "OuterScope", FormatStyle::LBI_OuterScope);
410 }
411};
412
413template <> struct ScalarEnumerationTraits<FormatStyle::LineEndingStyle> {
414 static void enumeration(IO &IO, FormatStyle::LineEndingStyle &Value) {
415 IO.enumCase(Value, "LF", FormatStyle::LE_LF);
416 IO.enumCase(Value, "CRLF", FormatStyle::LE_CRLF);
417 IO.enumCase(Value, "DeriveLF", FormatStyle::LE_DeriveLF);
418 IO.enumCase(Value, "DeriveCRLF", FormatStyle::LE_DeriveCRLF);
419 }
420};
421
422template <>
423struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
424 static void enumeration(IO &IO,
425 FormatStyle::NamespaceIndentationKind &Value) {
426 IO.enumCase(Value, "None", FormatStyle::NI_None);
427 IO.enumCase(Value, "Inner", FormatStyle::NI_Inner);
428 IO.enumCase(Value, "All", FormatStyle::NI_All);
429 }
430};
431
432template <> struct ScalarEnumerationTraits<FormatStyle::OperandAlignmentStyle> {
433 static void enumeration(IO &IO, FormatStyle::OperandAlignmentStyle &Value) {
434 IO.enumCase(Value, "DontAlign", FormatStyle::OAS_DontAlign);
435 IO.enumCase(Value, "Align", FormatStyle::OAS_Align);
436 IO.enumCase(Value, "AlignAfterOperator",
437 FormatStyle::OAS_AlignAfterOperator);
438
439 // For backward compatibility.
440 IO.enumCase(Value, "true", FormatStyle::OAS_Align);
441 IO.enumCase(Value, "false", FormatStyle::OAS_DontAlign);
442 }
443};
444
445template <>
446struct ScalarEnumerationTraits<FormatStyle::PackConstructorInitializersStyle> {
447 static void
448 enumeration(IO &IO, FormatStyle::PackConstructorInitializersStyle &Value) {
449 IO.enumCase(Value, "Never", FormatStyle::PCIS_Never);
450 IO.enumCase(Value, "BinPack", FormatStyle::PCIS_BinPack);
451 IO.enumCase(Value, "CurrentLine", FormatStyle::PCIS_CurrentLine);
452 IO.enumCase(Value, "NextLine", FormatStyle::PCIS_NextLine);
453 IO.enumCase(Value, "NextLineOnly", FormatStyle::PCIS_NextLineOnly);
454 }
455};
456
457template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
458 static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {
459 IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
460 IO.enumCase(Value, "Left", FormatStyle::PAS_Left);
461 IO.enumCase(Value, "Right", FormatStyle::PAS_Right);
462
463 // For backward compatibility.
464 IO.enumCase(Value, "true", FormatStyle::PAS_Left);
465 IO.enumCase(Value, "false", FormatStyle::PAS_Right);
466 }
467};
468
469template <>
470struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
471 static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
472 IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
473 IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);
474 IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash);
475 }
476};
477
478template <>
479struct ScalarEnumerationTraits<FormatStyle::QualifierAlignmentStyle> {
480 static void enumeration(IO &IO, FormatStyle::QualifierAlignmentStyle &Value) {
481 IO.enumCase(Value, "Leave", FormatStyle::QAS_Leave);
482 IO.enumCase(Value, "Left", FormatStyle::QAS_Left);
483 IO.enumCase(Value, "Right", FormatStyle::QAS_Right);
484 IO.enumCase(Value, "Custom", FormatStyle::QAS_Custom);
485 }
486};
487
488template <> struct MappingTraits<FormatStyle::RawStringFormat> {
489 static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
490 IO.mapOptional("Language", Format.Language);
491 IO.mapOptional("Delimiters", Format.Delimiters);
492 IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);
493 IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter);
494 IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);
495 }
496};
497
498template <>
499struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> {
500 static void enumeration(IO &IO, FormatStyle::ReferenceAlignmentStyle &Value) {
501 IO.enumCase(Value, "Pointer", FormatStyle::RAS_Pointer);
502 IO.enumCase(Value, "Middle", FormatStyle::RAS_Middle);
503 IO.enumCase(Value, "Left", FormatStyle::RAS_Left);
504 IO.enumCase(Value, "Right", FormatStyle::RAS_Right);
505 }
506};
507
508template <>
509struct ScalarEnumerationTraits<FormatStyle::RemoveParenthesesStyle> {
510 static void enumeration(IO &IO, FormatStyle::RemoveParenthesesStyle &Value) {
511 IO.enumCase(Value, "Leave", FormatStyle::RPS_Leave);
512 IO.enumCase(Value, "MultipleParentheses",
513 FormatStyle::RPS_MultipleParentheses);
514 IO.enumCase(Value, "ReturnStatement", FormatStyle::RPS_ReturnStatement);
515 }
516};
517
518template <>
519struct ScalarEnumerationTraits<FormatStyle::RequiresClausePositionStyle> {
520 static void enumeration(IO &IO,
521 FormatStyle::RequiresClausePositionStyle &Value) {
522 IO.enumCase(Value, "OwnLine", FormatStyle::RCPS_OwnLine);
523 IO.enumCase(Value, "WithPreceding", FormatStyle::RCPS_WithPreceding);
524 IO.enumCase(Value, "WithFollowing", FormatStyle::RCPS_WithFollowing);
525 IO.enumCase(Value, "SingleLine", FormatStyle::RCPS_SingleLine);
526 }
527};
528
529template <>
530struct ScalarEnumerationTraits<FormatStyle::RequiresExpressionIndentationKind> {
531 static void
532 enumeration(IO &IO, FormatStyle::RequiresExpressionIndentationKind &Value) {
533 IO.enumCase(Value, "Keyword", FormatStyle::REI_Keyword);
534 IO.enumCase(Value, "OuterScope", FormatStyle::REI_OuterScope);
535 }
536};
537
538template <>
539struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
540 static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
541 IO.enumCase(Value, "None", FormatStyle::RTBS_None);
542 IO.enumCase(Value, "Automatic", FormatStyle::RTBS_Automatic);
543 IO.enumCase(Value, "ExceptShortType", FormatStyle::RTBS_ExceptShortType);
544 IO.enumCase(Value, "All", FormatStyle::RTBS_All);
545 IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel);
546 IO.enumCase(Value, "TopLevelDefinitions",
547 FormatStyle::RTBS_TopLevelDefinitions);
548 IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions);
549 }
550};
551
552template <>
553struct ScalarEnumerationTraits<FormatStyle::SeparateDefinitionStyle> {
554 static void enumeration(IO &IO, FormatStyle::SeparateDefinitionStyle &Value) {
555 IO.enumCase(Value, "Leave", FormatStyle::SDS_Leave);
556 IO.enumCase(Value, "Always", FormatStyle::SDS_Always);
557 IO.enumCase(Value, "Never", FormatStyle::SDS_Never);
558 }
559};
560
561template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> {
562 static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) {
563 IO.enumCase(Value, "Never", FormatStyle::SBS_Never);
564 IO.enumCase(Value, "false", FormatStyle::SBS_Never);
565 IO.enumCase(Value, "Always", FormatStyle::SBS_Always);
566 IO.enumCase(Value, "true", FormatStyle::SBS_Always);
567 IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty);
568 }
569};
570
571template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
572 static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
573 IO.enumCase(Value, "None", FormatStyle::SFS_None);
574 IO.enumCase(Value, "false", FormatStyle::SFS_None);
575 IO.enumCase(Value, "All", FormatStyle::SFS_All);
576 IO.enumCase(Value, "true", FormatStyle::SFS_All);
577 IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
578 IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly);
579 IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);
580 }
581};
582
583template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> {
584 static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) {
585 IO.enumCase(Value, "Never", FormatStyle::SIS_Never);
586 IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse);
587 IO.enumCase(Value, "OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf);
588 IO.enumCase(Value, "AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse);
589
590 // For backward compatibility.
591 IO.enumCase(Value, "Always", FormatStyle::SIS_OnlyFirstIf);
592 IO.enumCase(Value, "false", FormatStyle::SIS_Never);
593 IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse);
594 }
595};
596
597template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> {
598 static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) {
599 IO.enumCase(Value, "None", FormatStyle::SLS_None);
600 IO.enumCase(Value, "false", FormatStyle::SLS_None);
601 IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty);
602 IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline);
603 IO.enumCase(Value, "All", FormatStyle::SLS_All);
604 IO.enumCase(Value, "true", FormatStyle::SLS_All);
605 }
606};
607
608template <> struct ScalarEnumerationTraits<FormatStyle::SortIncludesOptions> {
609 static void enumeration(IO &IO, FormatStyle::SortIncludesOptions &Value) {
610 IO.enumCase(Value, "Never", FormatStyle::SI_Never);
611 IO.enumCase(Value, "CaseInsensitive", FormatStyle::SI_CaseInsensitive);
612 IO.enumCase(Value, "CaseSensitive", FormatStyle::SI_CaseSensitive);
613
614 // For backward compatibility.
615 IO.enumCase(Value, "false", FormatStyle::SI_Never);
616 IO.enumCase(Value, "true", FormatStyle::SI_CaseSensitive);
617 }
618};
619
620template <>
621struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> {
622 static void enumeration(IO &IO,
623 FormatStyle::SortJavaStaticImportOptions &Value) {
624 IO.enumCase(Value, "Before", FormatStyle::SJSIO_Before);
625 IO.enumCase(Value, "After", FormatStyle::SJSIO_After);
626 }
627};
628
629template <>
630struct ScalarEnumerationTraits<FormatStyle::SortUsingDeclarationsOptions> {
631 static void enumeration(IO &IO,
632 FormatStyle::SortUsingDeclarationsOptions &Value) {
633 IO.enumCase(Value, "Never", FormatStyle::SUD_Never);
634 IO.enumCase(Value, "Lexicographic", FormatStyle::SUD_Lexicographic);
635 IO.enumCase(Value, "LexicographicNumeric",
636 FormatStyle::SUD_LexicographicNumeric);
637
638 // For backward compatibility.
639 IO.enumCase(Value, "false", FormatStyle::SUD_Never);
640 IO.enumCase(Value, "true", FormatStyle::SUD_LexicographicNumeric);
641 }
642};
643
644template <>
645struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> {
646 static void
647 enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value) {
648 IO.enumCase(Value, "Default", FormatStyle::SAPQ_Default);
649 IO.enumCase(Value, "Before", FormatStyle::SAPQ_Before);
650 IO.enumCase(Value, "After", FormatStyle::SAPQ_After);
651 IO.enumCase(Value, "Both", FormatStyle::SAPQ_Both);
652 }
653};
654
655template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> {
656 static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) {
657 IO.mapOptional("AfterControlStatements", Spacing.AfterControlStatements);
658 IO.mapOptional("AfterForeachMacros", Spacing.AfterForeachMacros);
659 IO.mapOptional("AfterFunctionDefinitionName",
660 Spacing.AfterFunctionDefinitionName);
661 IO.mapOptional("AfterFunctionDeclarationName",
662 Spacing.AfterFunctionDeclarationName);
663 IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros);
664 IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
665 IO.mapOptional("AfterPlacementOperator", Spacing.AfterPlacementOperator);
666 IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause);
667 IO.mapOptional("AfterRequiresInExpression",
668 Spacing.AfterRequiresInExpression);
669 IO.mapOptional("BeforeNonEmptyParentheses",
670 Spacing.BeforeNonEmptyParentheses);
671 }
672};
673
674template <>
675struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> {
676 static void enumeration(IO &IO, FormatStyle::SpaceBeforeParensStyle &Value) {
677 IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
678 IO.enumCase(Value, "ControlStatements",
679 FormatStyle::SBPO_ControlStatements);
680 IO.enumCase(Value, "ControlStatementsExceptControlMacros",
681 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
682 IO.enumCase(Value, "NonEmptyParentheses",
683 FormatStyle::SBPO_NonEmptyParentheses);
684 IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
685 IO.enumCase(Value, "Custom", FormatStyle::SBPO_Custom);
686
687 // For backward compatibility.
688 IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
689 IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);
690 IO.enumCase(Value, "ControlStatementsExceptForEachMacros",
691 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
692 }
693};
694
695template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> {
696 static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value) {
697 IO.enumCase(Value, "Never", FormatStyle::SIAS_Never);
698 IO.enumCase(Value, "Always", FormatStyle::SIAS_Always);
699 IO.enumCase(Value, "Leave", FormatStyle::SIAS_Leave);
700
701 // For backward compatibility.
702 IO.enumCase(Value, "false", FormatStyle::SIAS_Never);
703 IO.enumCase(Value, "true", FormatStyle::SIAS_Always);
704 }
705};
706
707template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {
708 static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
709 // Transform the maximum to signed, to parse "-1" correctly
710 int signedMaximum = static_cast<int>(Space.Maximum);
711 IO.mapOptional("Minimum", Space.Minimum);
712 IO.mapOptional("Maximum", signedMaximum);
713 Space.Maximum = static_cast<unsigned>(signedMaximum);
714
715 if (Space.Maximum != -1u)
716 Space.Minimum = std::min(Space.Minimum, Space.Maximum);
717 }
718};
719
720template <> struct MappingTraits<FormatStyle::SpacesInParensCustom> {
721 static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) {
722 IO.mapOptional("InCStyleCasts", Spaces.InCStyleCasts);
723 IO.mapOptional("InConditionalStatements", Spaces.InConditionalStatements);
724 IO.mapOptional("InEmptyParentheses", Spaces.InEmptyParentheses);
725 IO.mapOptional("Other", Spaces.Other);
726 }
727};
728
729template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInParensStyle> {
730 static void enumeration(IO &IO, FormatStyle::SpacesInParensStyle &Value) {
731 IO.enumCase(Value, "Never", FormatStyle::SIPO_Never);
732 IO.enumCase(Value, "Custom", FormatStyle::SIPO_Custom);
733 }
734};
735
736template <> struct ScalarEnumerationTraits<FormatStyle::TrailingCommaStyle> {
737 static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) {
738 IO.enumCase(Value, "None", FormatStyle::TCS_None);
739 IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped);
740 }
741};
742
743template <>
744struct ScalarEnumerationTraits<FormatStyle::TrailingCommentsAlignmentKinds> {
745 static void enumeration(IO &IO,
746 FormatStyle::TrailingCommentsAlignmentKinds &Value) {
747 IO.enumCase(Value, "Leave", FormatStyle::TCAS_Leave);
748 IO.enumCase(Value, "Always", FormatStyle::TCAS_Always);
749 IO.enumCase(Value, "Never", FormatStyle::TCAS_Never);
750 }
751};
752
753template <> struct MappingTraits<FormatStyle::TrailingCommentsAlignmentStyle> {
754 static void enumInput(IO &IO,
755 FormatStyle::TrailingCommentsAlignmentStyle &Value) {
756 IO.enumCase(Value, "Leave",
757 FormatStyle::TrailingCommentsAlignmentStyle(
758 {FormatStyle::TCAS_Leave, 0}));
759
760 IO.enumCase(Value, "Always",
761 FormatStyle::TrailingCommentsAlignmentStyle(
762 {FormatStyle::TCAS_Always, 0}));
763
764 IO.enumCase(Value, "Never",
765 FormatStyle::TrailingCommentsAlignmentStyle(
766 {FormatStyle::TCAS_Never, 0}));
767
768 // For backwards compatibility
769 IO.enumCase(Value, "true",
770 FormatStyle::TrailingCommentsAlignmentStyle(
771 {FormatStyle::TCAS_Always, 0}));
772 IO.enumCase(Value, "false",
773 FormatStyle::TrailingCommentsAlignmentStyle(
774 {FormatStyle::TCAS_Never, 0}));
775 }
776
777 static void mapping(IO &IO,
778 FormatStyle::TrailingCommentsAlignmentStyle &Value) {
779 IO.mapOptional("Kind", Value.Kind);
780 IO.mapOptional("OverEmptyLines", Value.OverEmptyLines);
781 }
782};
783
784template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
785 static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {
786 IO.enumCase(Value, "Never", FormatStyle::UT_Never);
787 IO.enumCase(Value, "false", FormatStyle::UT_Never);
788 IO.enumCase(Value, "Always", FormatStyle::UT_Always);
789 IO.enumCase(Value, "true", FormatStyle::UT_Always);
790 IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation);
791 IO.enumCase(Value, "ForContinuationAndIndentation",
792 FormatStyle::UT_ForContinuationAndIndentation);
793 IO.enumCase(Value, "AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);
794 }
795};
796
797template <> struct MappingTraits<FormatStyle> {
798 static void mapping(IO &IO, FormatStyle &Style) {
799 // When reading, read the language first, we need it for getPredefinedStyle.
800 IO.mapOptional("Language", Style.Language);
801
802 StringRef BasedOnStyle;
803 if (IO.outputting()) {
804 StringRef Styles[] = {"LLVM", "Google", "Chromium", "Mozilla",
805 "WebKit", "GNU", "Microsoft", "clang-format"};
806 for (StringRef StyleName : Styles) {
807 FormatStyle PredefinedStyle;
808 if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) &&
809 Style == PredefinedStyle) {
810 IO.mapOptional("# BasedOnStyle", StyleName);
811 BasedOnStyle = StyleName;
812 break;
813 }
814 }
815 } else {
816 IO.mapOptional("BasedOnStyle", BasedOnStyle);
817 if (!BasedOnStyle.empty()) {
818 FormatStyle::LanguageKind OldLanguage = Style.Language;
819 FormatStyle::LanguageKind Language =
820 ((FormatStyle *)IO.getContext())->Language;
821 if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
822 IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle));
823 return;
824 }
825 Style.Language = OldLanguage;
826 }
827 }
828
829 // Initialize some variables used in the parsing. The using logic is at the
830 // end.
831
832 // For backward compatibility:
833 // The default value of ConstructorInitializerAllOnOneLineOrOnePerLine was
834 // false unless BasedOnStyle was Google or Chromium whereas that of
835 // AllowAllConstructorInitializersOnNextLine was always true, so the
836 // equivalent default value of PackConstructorInitializers is PCIS_NextLine
837 // for Google/Chromium or PCIS_BinPack otherwise. If the deprecated options
838 // had a non-default value while PackConstructorInitializers has a default
839 // value, set the latter to an equivalent non-default value if needed.
840 const bool IsGoogleOrChromium = BasedOnStyle.equals_insensitive("google") ||
841 BasedOnStyle.equals_insensitive("chromium");
842 bool OnCurrentLine = IsGoogleOrChromium;
843 bool OnNextLine = true;
844
845 bool BreakBeforeInheritanceComma = false;
846 bool BreakConstructorInitializersBeforeComma = false;
847
848 bool DeriveLineEnding = true;
849 bool UseCRLF = false;
850
851 bool SpaceInEmptyParentheses = false;
852 bool SpacesInConditionalStatement = false;
853 bool SpacesInCStyleCastParentheses = false;
854 bool SpacesInParentheses = false;
855
856 // For backward compatibility.
857 if (!IO.outputting()) {
858 IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines);
859 IO.mapOptional("AllowAllConstructorInitializersOnNextLine", OnNextLine);
860 IO.mapOptional("AlwaysBreakAfterReturnType", Style.BreakAfterReturnType);
861 IO.mapOptional("AlwaysBreakTemplateDeclarations",
863 IO.mapOptional("BreakBeforeInheritanceComma",
864 BreakBeforeInheritanceComma);
865 IO.mapOptional("BreakConstructorInitializersBeforeComma",
866 BreakConstructorInitializersBeforeComma);
867 IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
868 OnCurrentLine);
869 IO.mapOptional("DeriveLineEnding", DeriveLineEnding);
870 IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
871 IO.mapOptional("IndentFunctionDeclarationAfterType",
873 IO.mapOptional("IndentRequires", Style.IndentRequiresClause);
874 IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
875 IO.mapOptional("SpaceAfterControlStatementKeyword",
876 Style.SpaceBeforeParens);
877 IO.mapOptional("SpaceInEmptyParentheses", SpaceInEmptyParentheses);
878 IO.mapOptional("SpacesInConditionalStatement",
879 SpacesInConditionalStatement);
880 IO.mapOptional("SpacesInCStyleCastParentheses",
881 SpacesInCStyleCastParentheses);
882 IO.mapOptional("SpacesInParentheses", SpacesInParentheses);
883 IO.mapOptional("UseCRLF", UseCRLF);
884 }
885
886 IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
887 IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
888 IO.mapOptional("AlignArrayOfStructures", Style.AlignArrayOfStructures);
889 IO.mapOptional("AlignConsecutiveAssignments",
891 IO.mapOptional("AlignConsecutiveBitFields",
893 IO.mapOptional("AlignConsecutiveDeclarations",
895 IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);
896 IO.mapOptional("AlignConsecutiveShortCaseStatements",
898 IO.mapOptional("AlignConsecutiveTableGenBreakingDAGArgColons",
900 IO.mapOptional("AlignConsecutiveTableGenCondOperatorColons",
902 IO.mapOptional("AlignConsecutiveTableGenDefinitionColons",
904 IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines);
905 IO.mapOptional("AlignOperands", Style.AlignOperands);
906 IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
907 IO.mapOptional("AllowAllArgumentsOnNextLine",
909 IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
911 IO.mapOptional("AllowBreakBeforeNoexceptSpecifier",
913 IO.mapOptional("AllowShortBlocksOnASingleLine",
915 IO.mapOptional("AllowShortCaseLabelsOnASingleLine",
917 IO.mapOptional("AllowShortCompoundRequirementOnASingleLine",
919 IO.mapOptional("AllowShortEnumsOnASingleLine",
921 IO.mapOptional("AllowShortFunctionsOnASingleLine",
923 IO.mapOptional("AllowShortIfStatementsOnASingleLine",
925 IO.mapOptional("AllowShortLambdasOnASingleLine",
927 IO.mapOptional("AllowShortLoopsOnASingleLine",
929 IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",
931 IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
933 IO.mapOptional("AttributeMacros", Style.AttributeMacros);
934 IO.mapOptional("BinPackArguments", Style.BinPackArguments);
935 IO.mapOptional("BinPackParameters", Style.BinPackParameters);
936 IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing);
937 IO.mapOptional("BracedInitializerIndentWidth",
939 IO.mapOptional("BraceWrapping", Style.BraceWrapping);
940 IO.mapOptional("BreakAdjacentStringLiterals",
942 IO.mapOptional("BreakAfterAttributes", Style.BreakAfterAttributes);
943 IO.mapOptional("BreakAfterJavaFieldAnnotations",
945 IO.mapOptional("BreakAfterReturnType", Style.BreakAfterReturnType);
946 IO.mapOptional("BreakArrays", Style.BreakArrays);
947 IO.mapOptional("BreakBeforeBinaryOperators",
949 IO.mapOptional("BreakBeforeConceptDeclarations",
951 IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
952 IO.mapOptional("BreakBeforeInlineASMColon",
954 IO.mapOptional("BreakBeforeTernaryOperators",
956 IO.mapOptional("BreakConstructorInitializers",
958 IO.mapOptional("BreakFunctionDefinitionParameters",
960 IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList);
961 IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
962 IO.mapOptional("BreakTemplateDeclarations",
964 IO.mapOptional("ColumnLimit", Style.ColumnLimit);
965 IO.mapOptional("CommentPragmas", Style.CommentPragmas);
966 IO.mapOptional("CompactNamespaces", Style.CompactNamespaces);
967 IO.mapOptional("ConstructorInitializerIndentWidth",
969 IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
970 IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
971 IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
972 IO.mapOptional("DisableFormat", Style.DisableFormat);
973 IO.mapOptional("EmptyLineAfterAccessModifier",
975 IO.mapOptional("EmptyLineBeforeAccessModifier",
977 IO.mapOptional("ExperimentalAutoDetectBinPacking",
979 IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
980 IO.mapOptional("ForEachMacros", Style.ForEachMacros);
981 IO.mapOptional("IfMacros", Style.IfMacros);
982 IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
983 IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
984 IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
985 IO.mapOptional("IncludeIsMainSourceRegex",
987 IO.mapOptional("IndentAccessModifiers", Style.IndentAccessModifiers);
988 IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks);
989 IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
990 IO.mapOptional("IndentExternBlock", Style.IndentExternBlock);
991 IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels);
992 IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
993 IO.mapOptional("IndentRequiresClause", Style.IndentRequiresClause);
994 IO.mapOptional("IndentWidth", Style.IndentWidth);
995 IO.mapOptional("IndentWrappedFunctionNames",
997 IO.mapOptional("InsertBraces", Style.InsertBraces);
998 IO.mapOptional("InsertNewlineAtEOF", Style.InsertNewlineAtEOF);
999 IO.mapOptional("InsertTrailingCommas", Style.InsertTrailingCommas);
1000 IO.mapOptional("IntegerLiteralSeparator", Style.IntegerLiteralSeparator);
1001 IO.mapOptional("JavaImportGroups", Style.JavaImportGroups);
1002 IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);
1003 IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
1004 IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
1006 IO.mapOptional("KeepEmptyLinesAtEOF", Style.KeepEmptyLinesAtEOF);
1007 IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation);
1008 IO.mapOptional("LineEnding", Style.LineEnding);
1009 IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
1010 IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);
1011 IO.mapOptional("Macros", Style.Macros);
1012 IO.mapOptional("MainIncludeChar", Style.IncludeStyle.MainIncludeChar);
1013 IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
1014 IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
1015 IO.mapOptional("NamespaceMacros", Style.NamespaceMacros);
1016 IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList);
1017 IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);
1018 IO.mapOptional("ObjCBreakBeforeNestedBlockParam",
1020 IO.mapOptional("ObjCPropertyAttributeOrder",
1022 IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
1023 IO.mapOptional("ObjCSpaceBeforeProtocolList",
1025 IO.mapOptional("PackConstructorInitializers",
1027 IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment);
1028 IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",
1030 IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
1031 IO.mapOptional("PenaltyBreakFirstLessLess",
1033 IO.mapOptional("PenaltyBreakOpenParenthesis",
1035 IO.mapOptional("PenaltyBreakScopeResolution",
1037 IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
1038 IO.mapOptional("PenaltyBreakTemplateDeclaration",
1040 IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
1041 IO.mapOptional("PenaltyIndentedWhitespace",
1043 IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
1045 IO.mapOptional("PointerAlignment", Style.PointerAlignment);
1046 IO.mapOptional("PPIndentWidth", Style.PPIndentWidth);
1047 IO.mapOptional("QualifierAlignment", Style.QualifierAlignment);
1048 // Default Order for Left/Right based Qualifier alignment.
1049 if (Style.QualifierAlignment == FormatStyle::QAS_Right)
1050 Style.QualifierOrder = {"type", "const", "volatile"};
1051 else if (Style.QualifierAlignment == FormatStyle::QAS_Left)
1052 Style.QualifierOrder = {"const", "volatile", "type"};
1053 else if (Style.QualifierAlignment == FormatStyle::QAS_Custom)
1054 IO.mapOptional("QualifierOrder", Style.QualifierOrder);
1055 IO.mapOptional("RawStringFormats", Style.RawStringFormats);
1056 IO.mapOptional("ReferenceAlignment", Style.ReferenceAlignment);
1057 IO.mapOptional("ReflowComments", Style.ReflowComments);
1058 IO.mapOptional("RemoveBracesLLVM", Style.RemoveBracesLLVM);
1059 IO.mapOptional("RemoveParentheses", Style.RemoveParentheses);
1060 IO.mapOptional("RemoveSemicolon", Style.RemoveSemicolon);
1061 IO.mapOptional("RequiresClausePosition", Style.RequiresClausePosition);
1062 IO.mapOptional("RequiresExpressionIndentation",
1064 IO.mapOptional("SeparateDefinitionBlocks", Style.SeparateDefinitionBlocks);
1065 IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines);
1066 IO.mapOptional("SkipMacroDefinitionBody", Style.SkipMacroDefinitionBody);
1067 IO.mapOptional("SortIncludes", Style.SortIncludes);
1068 IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport);
1069 IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);
1070 IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
1071 IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot);
1072 IO.mapOptional("SpaceAfterTemplateKeyword",
1074 IO.mapOptional("SpaceAroundPointerQualifiers",
1076 IO.mapOptional("SpaceBeforeAssignmentOperators",
1078 IO.mapOptional("SpaceBeforeCaseColon", Style.SpaceBeforeCaseColon);
1079 IO.mapOptional("SpaceBeforeCpp11BracedList",
1081 IO.mapOptional("SpaceBeforeCtorInitializerColon",
1083 IO.mapOptional("SpaceBeforeInheritanceColon",
1085 IO.mapOptional("SpaceBeforeJsonColon", Style.SpaceBeforeJsonColon);
1086 IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
1087 IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions);
1088 IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
1090 IO.mapOptional("SpaceBeforeSquareBrackets",
1092 IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock);
1093 IO.mapOptional("SpacesBeforeTrailingComments",
1095 IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
1096 IO.mapOptional("SpacesInContainerLiterals",
1098 IO.mapOptional("SpacesInLineCommentPrefix",
1100 IO.mapOptional("SpacesInParens", Style.SpacesInParens);
1101 IO.mapOptional("SpacesInParensOptions", Style.SpacesInParensOptions);
1102 IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
1103 IO.mapOptional("Standard", Style.Standard);
1104 IO.mapOptional("StatementAttributeLikeMacros",
1106 IO.mapOptional("StatementMacros", Style.StatementMacros);
1107 IO.mapOptional("TableGenBreakingDAGArgOperators",
1109 IO.mapOptional("TableGenBreakInsideDAGArg",
1111 IO.mapOptional("TabWidth", Style.TabWidth);
1112 IO.mapOptional("TypeNames", Style.TypeNames);
1113 IO.mapOptional("TypenameMacros", Style.TypenameMacros);
1114 IO.mapOptional("UseTab", Style.UseTab);
1115 IO.mapOptional("VerilogBreakBetweenInstancePorts",
1117 IO.mapOptional("WhitespaceSensitiveMacros",
1119
1120 // If AlwaysBreakAfterDefinitionReturnType was specified but
1121 // BreakAfterReturnType was not, initialize the latter from the former for
1122 // backwards compatibility.
1123 if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&
1124 Style.BreakAfterReturnType == FormatStyle::RTBS_None) {
1126 FormatStyle::DRTBS_All) {
1127 Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
1128 } else if (Style.AlwaysBreakAfterDefinitionReturnType ==
1129 FormatStyle::DRTBS_TopLevel) {
1130 Style.BreakAfterReturnType = FormatStyle::RTBS_TopLevelDefinitions;
1131 }
1132 }
1133
1134 // If BreakBeforeInheritanceComma was specified but BreakInheritance was
1135 // not, initialize the latter from the former for backwards compatibility.
1136 if (BreakBeforeInheritanceComma &&
1137 Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) {
1138 Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
1139 }
1140
1141 // If BreakConstructorInitializersBeforeComma was specified but
1142 // BreakConstructorInitializers was not, initialize the latter from the
1143 // former for backwards compatibility.
1144 if (BreakConstructorInitializersBeforeComma &&
1145 Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon) {
1146 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
1147 }
1148
1149 if (!IsGoogleOrChromium) {
1150 if (Style.PackConstructorInitializers == FormatStyle::PCIS_BinPack &&
1151 OnCurrentLine) {
1152 Style.PackConstructorInitializers = OnNextLine
1153 ? FormatStyle::PCIS_NextLine
1154 : FormatStyle::PCIS_CurrentLine;
1155 }
1156 } else if (Style.PackConstructorInitializers ==
1157 FormatStyle::PCIS_NextLine) {
1158 if (!OnCurrentLine)
1159 Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
1160 else if (!OnNextLine)
1161 Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine;
1162 }
1163
1164 if (Style.LineEnding == FormatStyle::LE_DeriveLF) {
1165 if (!DeriveLineEnding)
1166 Style.LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF;
1167 else if (UseCRLF)
1168 Style.LineEnding = FormatStyle::LE_DeriveCRLF;
1169 }
1170
1171 if (Style.SpacesInParens != FormatStyle::SIPO_Custom &&
1172 (SpacesInParentheses || SpaceInEmptyParentheses ||
1173 SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) {
1174 if (SpacesInParentheses) {
1175 // set all options except InCStyleCasts and InEmptyParentheses
1176 // to true for backward compatibility.
1179 SpacesInCStyleCastParentheses;
1181 SpaceInEmptyParentheses;
1182 Style.SpacesInParensOptions.Other = true;
1183 } else {
1184 Style.SpacesInParensOptions = {};
1186 SpacesInConditionalStatement;
1188 SpacesInCStyleCastParentheses;
1190 SpaceInEmptyParentheses;
1191 }
1192 Style.SpacesInParens = FormatStyle::SIPO_Custom;
1193 }
1194 }
1195};
1196
1197// Allows to read vector<FormatStyle> while keeping default values.
1198// IO.getContext() should contain a pointer to the FormatStyle structure, that
1199// will be used to get default values for missing keys.
1200// If the first element has no Language specified, it will be treated as the
1201// default one for the following elements.
1202template <> struct DocumentListTraits<std::vector<FormatStyle>> {
1203 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
1204 return Seq.size();
1205 }
1206 static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq,
1207 size_t Index) {
1208 if (Index >= Seq.size()) {
1209 assert(Index == Seq.size());
1210 FormatStyle Template;
1211 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
1212 Template = Seq[0];
1213 } else {
1214 Template = *((const FormatStyle *)IO.getContext());
1215 Template.Language = FormatStyle::LK_None;
1216 }
1217 Seq.resize(Index + 1, Template);
1218 }
1219 return Seq[Index];
1220 }
1221};
1222} // namespace yaml
1223} // namespace llvm
1224
1225namespace clang {
1226namespace format {
1227
1228const std::error_category &getParseCategory() {
1229 static const ParseErrorCategory C{};
1230 return C;
1231}
1232std::error_code make_error_code(ParseError e) {
1233 return std::error_code(static_cast<int>(e), getParseCategory());
1234}
1235
1236inline llvm::Error make_string_error(const llvm::Twine &Message) {
1237 return llvm::make_error<llvm::StringError>(Message,
1238 llvm::inconvertibleErrorCode());
1239}
1240
1241const char *ParseErrorCategory::name() const noexcept {
1242 return "clang-format.parse_error";
1243}
1244
1245std::string ParseErrorCategory::message(int EV) const {
1246 switch (static_cast<ParseError>(EV)) {
1248 return "Success";
1249 case ParseError::Error:
1250 return "Invalid argument";
1252 return "Unsuitable";
1254 return "trailing comma insertion cannot be used with bin packing";
1256 return "Invalid qualifier specified in QualifierOrder";
1258 return "Duplicate qualifier specified in QualifierOrder";
1260 return "Missing type in QualifierOrder";
1262 return "Missing QualifierOrder";
1263 }
1264 llvm_unreachable("unexpected parse error");
1265}
1266
1269 return;
1270 Expanded.BraceWrapping = {/*AfterCaseLabel=*/false,
1271 /*AfterClass=*/false,
1272 /*AfterControlStatement=*/FormatStyle::BWACS_Never,
1273 /*AfterEnum=*/false,
1274 /*AfterFunction=*/false,
1275 /*AfterNamespace=*/false,
1276 /*AfterObjCDeclaration=*/false,
1277 /*AfterStruct=*/false,
1278 /*AfterUnion=*/false,
1279 /*AfterExternBlock=*/false,
1280 /*BeforeCatch=*/false,
1281 /*BeforeElse=*/false,
1282 /*BeforeLambdaBody=*/false,
1283 /*BeforeWhile=*/false,
1284 /*IndentBraces=*/false,
1285 /*SplitEmptyFunction=*/true,
1286 /*SplitEmptyRecord=*/true,
1287 /*SplitEmptyNamespace=*/true};
1288 switch (Expanded.BreakBeforeBraces) {
1290 Expanded.BraceWrapping.AfterClass = true;
1291 Expanded.BraceWrapping.AfterFunction = true;
1292 Expanded.BraceWrapping.AfterNamespace = true;
1293 break;
1295 Expanded.BraceWrapping.AfterClass = true;
1296 Expanded.BraceWrapping.AfterEnum = true;
1297 Expanded.BraceWrapping.AfterFunction = true;
1298 Expanded.BraceWrapping.AfterStruct = true;
1299 Expanded.BraceWrapping.AfterUnion = true;
1300 Expanded.BraceWrapping.AfterExternBlock = true;
1301 Expanded.BraceWrapping.SplitEmptyFunction = true;
1302 Expanded.BraceWrapping.SplitEmptyRecord = false;
1303 break;
1305 Expanded.BraceWrapping.AfterFunction = true;
1306 Expanded.BraceWrapping.BeforeCatch = true;
1307 Expanded.BraceWrapping.BeforeElse = true;
1308 break;
1310 Expanded.BraceWrapping.AfterCaseLabel = true;
1311 Expanded.BraceWrapping.AfterClass = true;
1313 Expanded.BraceWrapping.AfterEnum = true;
1314 Expanded.BraceWrapping.AfterFunction = true;
1315 Expanded.BraceWrapping.AfterNamespace = true;
1316 Expanded.BraceWrapping.AfterObjCDeclaration = true;
1317 Expanded.BraceWrapping.AfterStruct = true;
1318 Expanded.BraceWrapping.AfterUnion = true;
1319 Expanded.BraceWrapping.AfterExternBlock = true;
1320 Expanded.BraceWrapping.BeforeCatch = true;
1321 Expanded.BraceWrapping.BeforeElse = true;
1322 Expanded.BraceWrapping.BeforeLambdaBody = true;
1323 break;
1325 Expanded.BraceWrapping.AfterCaseLabel = true;
1326 Expanded.BraceWrapping.AfterClass = true;
1328 Expanded.BraceWrapping.AfterEnum = true;
1329 Expanded.BraceWrapping.AfterFunction = true;
1330 Expanded.BraceWrapping.AfterNamespace = true;
1331 Expanded.BraceWrapping.AfterObjCDeclaration = true;
1332 Expanded.BraceWrapping.AfterStruct = true;
1333 Expanded.BraceWrapping.AfterExternBlock = true;
1334 Expanded.BraceWrapping.BeforeCatch = true;
1335 Expanded.BraceWrapping.BeforeElse = true;
1336 Expanded.BraceWrapping.BeforeLambdaBody = true;
1337 break;
1339 Expanded.BraceWrapping = {
1340 /*AfterCaseLabel=*/true,
1341 /*AfterClass=*/true,
1342 /*AfterControlStatement=*/FormatStyle::BWACS_Always,
1343 /*AfterEnum=*/true,
1344 /*AfterFunction=*/true,
1345 /*AfterNamespace=*/true,
1346 /*AfterObjCDeclaration=*/true,
1347 /*AfterStruct=*/true,
1348 /*AfterUnion=*/true,
1349 /*AfterExternBlock=*/true,
1350 /*BeforeCatch=*/true,
1351 /*BeforeElse=*/true,
1352 /*BeforeLambdaBody=*/false,
1353 /*BeforeWhile=*/true,
1354 /*IndentBraces=*/true,
1355 /*SplitEmptyFunction=*/true,
1356 /*SplitEmptyRecord=*/true,
1357 /*SplitEmptyNamespace=*/true};
1358 break;
1360 Expanded.BraceWrapping.AfterFunction = true;
1361 break;
1362 default:
1363 break;
1364 }
1365}
1366
1369 return;
1370 // Reset all flags
1371 Expanded.SpaceBeforeParensOptions = {};
1373
1374 switch (Expanded.SpaceBeforeParens) {
1379 break;
1382 break;
1385 break;
1386 default:
1387 break;
1388 }
1389}
1390
1393 return;
1394 assert(Expanded.SpacesInParens == FormatStyle::SIPO_Never);
1395 // Reset all flags
1396 Expanded.SpacesInParensOptions = {};
1397}
1398
1400 FormatStyle LLVMStyle;
1401 LLVMStyle.AccessModifierOffset = -2;
1404 LLVMStyle.AlignConsecutiveAssignments = {};
1409 LLVMStyle.AlignConsecutiveAssignments.Enabled = false;
1411 LLVMStyle.AlignConsecutiveBitFields = {};
1412 LLVMStyle.AlignConsecutiveDeclarations = {};
1413 LLVMStyle.AlignConsecutiveMacros = {};
1420 LLVMStyle.AlignTrailingComments = {};
1423 LLVMStyle.AllowAllArgumentsOnNextLine = true;
1427 LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
1429 LLVMStyle.AllowShortEnumsOnASingleLine = true;
1433 LLVMStyle.AllowShortLoopsOnASingleLine = false;
1435 LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
1436 LLVMStyle.AttributeMacros.push_back("__capability");
1437 LLVMStyle.BinPackArguments = true;
1438 LLVMStyle.BinPackParameters = true;
1440 LLVMStyle.BracedInitializerIndentWidth = std::nullopt;
1441 LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false,
1442 /*AfterClass=*/false,
1443 /*AfterControlStatement=*/FormatStyle::BWACS_Never,
1444 /*AfterEnum=*/false,
1445 /*AfterFunction=*/false,
1446 /*AfterNamespace=*/false,
1447 /*AfterObjCDeclaration=*/false,
1448 /*AfterStruct=*/false,
1449 /*AfterUnion=*/false,
1450 /*AfterExternBlock=*/false,
1451 /*BeforeCatch=*/false,
1452 /*BeforeElse=*/false,
1453 /*BeforeLambdaBody=*/false,
1454 /*BeforeWhile=*/false,
1455 /*IndentBraces=*/false,
1456 /*SplitEmptyFunction=*/true,
1457 /*SplitEmptyRecord=*/true,
1458 /*SplitEmptyNamespace=*/true};
1459 LLVMStyle.BreakAdjacentStringLiterals = true;
1461 LLVMStyle.BreakAfterJavaFieldAnnotations = false;
1463 LLVMStyle.BreakArrays = true;
1468 LLVMStyle.BreakBeforeTernaryOperators = true;
1470 LLVMStyle.BreakFunctionDefinitionParameters = false;
1472 LLVMStyle.BreakStringLiterals = true;
1474 LLVMStyle.ColumnLimit = 80;
1475 LLVMStyle.CommentPragmas = "^ IWYU pragma:";
1476 LLVMStyle.CompactNamespaces = false;
1478 LLVMStyle.ContinuationIndentWidth = 4;
1479 LLVMStyle.Cpp11BracedListStyle = true;
1480 LLVMStyle.DerivePointerAlignment = false;
1481 LLVMStyle.DisableFormat = false;
1484 LLVMStyle.ExperimentalAutoDetectBinPacking = false;
1485 LLVMStyle.FixNamespaceComments = true;
1486 LLVMStyle.ForEachMacros.push_back("foreach");
1487 LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
1488 LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
1489 LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE");
1491 LLVMStyle.IncludeStyle.IncludeCategories = {
1492 {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false},
1493 {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},
1494 {".*", 1, 0, false}};
1495 LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
1497 LLVMStyle.IndentAccessModifiers = false;
1498 LLVMStyle.IndentCaseBlocks = false;
1499 LLVMStyle.IndentCaseLabels = false;
1501 LLVMStyle.IndentGotoLabels = true;
1503 LLVMStyle.IndentRequiresClause = true;
1504 LLVMStyle.IndentWidth = 2;
1505 LLVMStyle.IndentWrappedFunctionNames = false;
1506 LLVMStyle.InheritsParentConfig = false;
1507 LLVMStyle.InsertBraces = false;
1508 LLVMStyle.InsertNewlineAtEOF = false;
1510 LLVMStyle.IntegerLiteralSeparator = {
1511 /*Binary=*/0, /*BinaryMinDigits=*/0,
1512 /*Decimal=*/0, /*DecimalMinDigits=*/0,
1513 /*Hex=*/0, /*HexMinDigits=*/0};
1515 LLVMStyle.JavaScriptWrapImports = true;
1516 LLVMStyle.KeepEmptyLinesAtEOF = false;
1517 LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
1519 LLVMStyle.Language = Language;
1521 LLVMStyle.MaxEmptyLinesToKeep = 1;
1524 LLVMStyle.ObjCBlockIndentWidth = 2;
1525 LLVMStyle.ObjCBreakBeforeNestedBlockParam = true;
1526 LLVMStyle.ObjCSpaceAfterProperty = false;
1527 LLVMStyle.ObjCSpaceBeforeProtocolList = true;
1530 LLVMStyle.PPIndentWidth = -1;
1533 LLVMStyle.ReflowComments = true;
1534 LLVMStyle.RemoveBracesLLVM = false;
1536 LLVMStyle.RemoveSemicolon = false;
1540 LLVMStyle.ShortNamespaceLines = 1;
1541 LLVMStyle.SkipMacroDefinitionBody = false;
1545 LLVMStyle.SpaceAfterCStyleCast = false;
1546 LLVMStyle.SpaceAfterLogicalNot = false;
1547 LLVMStyle.SpaceAfterTemplateKeyword = true;
1549 LLVMStyle.SpaceBeforeAssignmentOperators = true;
1550 LLVMStyle.SpaceBeforeCaseColon = false;
1551 LLVMStyle.SpaceBeforeCpp11BracedList = false;
1552 LLVMStyle.SpaceBeforeCtorInitializerColon = true;
1553 LLVMStyle.SpaceBeforeInheritanceColon = true;
1554 LLVMStyle.SpaceBeforeJsonColon = false;
1556 LLVMStyle.SpaceBeforeParensOptions = {};
1559 LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true;
1560 LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
1561 LLVMStyle.SpaceBeforeSquareBrackets = false;
1562 LLVMStyle.SpaceInEmptyBlock = false;
1563 LLVMStyle.SpacesBeforeTrailingComments = 1;
1565 LLVMStyle.SpacesInContainerLiterals = true;
1566 LLVMStyle.SpacesInLineCommentPrefix = {/*Minimum=*/1, /*Maximum=*/-1u};
1568 LLVMStyle.SpacesInSquareBrackets = false;
1569 LLVMStyle.Standard = FormatStyle::LS_Latest;
1570 LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");
1571 LLVMStyle.StatementMacros.push_back("Q_UNUSED");
1572 LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");
1573 LLVMStyle.TableGenBreakingDAGArgOperators = {};
1575 LLVMStyle.TabWidth = 8;
1576 LLVMStyle.UseTab = FormatStyle::UT_Never;
1577 LLVMStyle.VerilogBreakBetweenInstancePorts = true;
1578 LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE");
1579 LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME");
1580 LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME");
1581 LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE");
1582 LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE");
1583
1586 LLVMStyle.PenaltyBreakComment = 300;
1587 LLVMStyle.PenaltyBreakFirstLessLess = 120;
1588 LLVMStyle.PenaltyBreakOpenParenthesis = 0;
1589 LLVMStyle.PenaltyBreakScopeResolution = 500;
1590 LLVMStyle.PenaltyBreakString = 1000;
1592 LLVMStyle.PenaltyExcessCharacter = 1'000'000;
1593 LLVMStyle.PenaltyIndentedWhitespace = 0;
1594 LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
1595
1596 // Defaults that differ when not C++.
1597 switch (Language) {
1599 LLVMStyle.SpacesInContainerLiterals = false;
1600 break;
1602 LLVMStyle.ColumnLimit = 0;
1603 break;
1605 LLVMStyle.IndentCaseLabels = true;
1606 LLVMStyle.SpacesInContainerLiterals = false;
1607 break;
1608 default:
1609 break;
1610 }
1611
1612 return LLVMStyle;
1613}
1614
1618 GoogleStyle.Language = FormatStyle::LK_TextProto;
1619
1620 return GoogleStyle;
1621 }
1622
1623 FormatStyle GoogleStyle = getLLVMStyle(Language);
1624
1625 GoogleStyle.AccessModifierOffset = -1;
1629 GoogleStyle.AllowShortLoopsOnASingleLine = true;
1630 GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
1632 GoogleStyle.DerivePointerAlignment = true;
1634 GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false},
1635 {"^<.*\\.h>", 1, 0, false},
1636 {"^<.*", 2, 0, false},
1637 {".*", 3, 0, false}};
1638 GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
1639 GoogleStyle.IndentCaseLabels = true;
1640 GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
1642 GoogleStyle.ObjCSpaceAfterProperty = false;
1643 GoogleStyle.ObjCSpaceBeforeProtocolList = true;
1646 GoogleStyle.RawStringFormats = {
1647 {
1649 /*Delimiters=*/
1650 {
1651 "cc",
1652 "CC",
1653 "cpp",
1654 "Cpp",
1655 "CPP",
1656 "c++",
1657 "C++",
1658 },
1659 /*EnclosingFunctionNames=*/
1660 {},
1661 /*CanonicalDelimiter=*/"",
1662 /*BasedOnStyle=*/"google",
1663 },
1664 {
1666 /*Delimiters=*/
1667 {
1668 "pb",
1669 "PB",
1670 "proto",
1671 "PROTO",
1672 },
1673 /*EnclosingFunctionNames=*/
1674 {
1675 "EqualsProto",
1676 "EquivToProto",
1677 "PARSE_PARTIAL_TEXT_PROTO",
1678 "PARSE_TEST_PROTO",
1679 "PARSE_TEXT_PROTO",
1680 "ParseTextOrDie",
1681 "ParseTextProtoOrDie",
1682 "ParseTestProto",
1683 "ParsePartialTestProto",
1684 },
1685 /*CanonicalDelimiter=*/"pb",
1686 /*BasedOnStyle=*/"google",
1687 },
1688 };
1689
1690 GoogleStyle.SpacesBeforeTrailingComments = 2;
1691 GoogleStyle.Standard = FormatStyle::LS_Auto;
1692
1694 GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
1695
1699 GoogleStyle.AlignTrailingComments = {};
1703 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
1705 GoogleStyle.ColumnLimit = 100;
1706 GoogleStyle.SpaceAfterCStyleCast = true;
1707 GoogleStyle.SpacesBeforeTrailingComments = 1;
1708 } else if (Language == FormatStyle::LK_JavaScript) {
1712 // TODO: still under discussion whether to switch to SLS_All.
1714 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
1715 GoogleStyle.BreakBeforeTernaryOperators = false;
1716 // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is
1717 // commonly followed by overlong URLs.
1718 GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)";
1719 // TODO: enable once decided, in particular re disabling bin packing.
1720 // https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma
1721 // GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
1723 GoogleStyle.JavaScriptWrapImports = false;
1724 GoogleStyle.MaxEmptyLinesToKeep = 3;
1726 GoogleStyle.SpacesInContainerLiterals = false;
1727 } else if (Language == FormatStyle::LK_Proto) {
1729 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
1730 // This affects protocol buffer options specifications and text protos.
1731 // Text protos are currently mostly formatted inside C++ raw string literals
1732 // and often the current breaking behavior of string literals is not
1733 // beneficial there. Investigate turning this on once proper string reflow
1734 // has been implemented.
1735 GoogleStyle.BreakStringLiterals = false;
1736 GoogleStyle.Cpp11BracedListStyle = false;
1737 GoogleStyle.SpacesInContainerLiterals = false;
1738 } else if (Language == FormatStyle::LK_ObjC) {
1739 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
1740 GoogleStyle.ColumnLimit = 100;
1741 // "Regroup" doesn't work well for ObjC yet (main header heuristic,
1742 // relationship between ObjC standard library headers and other heades,
1743 // #imports, etc.)
1744 GoogleStyle.IncludeStyle.IncludeBlocks =
1746 } else if (Language == FormatStyle::LK_CSharp) {
1749 GoogleStyle.BreakStringLiterals = false;
1750 GoogleStyle.ColumnLimit = 100;
1752 }
1753
1754 return GoogleStyle;
1755}
1756
1758 FormatStyle ChromiumStyle = getGoogleStyle(Language);
1759
1760 // Disable include reordering across blocks in Chromium code.
1761 // - clang-format tries to detect that foo.h is the "main" header for
1762 // foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium
1763 // uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc,
1764 // _private.cc, _impl.cc etc) in different permutations
1765 // (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a
1766 // better default for Chromium code.
1767 // - The default for .cc and .mm files is different (r357695) for Google style
1768 // for the same reason. The plan is to unify this again once the main
1769 // header detection works for Google's ObjC code, but this hasn't happened
1770 // yet. Since Chromium has some ObjC code, switching Chromium is blocked
1771 // on that.
1772 // - Finally, "If include reordering is harmful, put things in different
1773 // blocks to prevent it" has been a recommendation for a long time that
1774 // people are used to. We'll need a dev education push to change this to
1775 // "If include reordering is harmful, put things in a different block and
1776 // _prepend that with a comment_ to prevent it" before changing behavior.
1777 ChromiumStyle.IncludeStyle.IncludeBlocks =
1779
1783 ChromiumStyle.BreakAfterJavaFieldAnnotations = true;
1784 ChromiumStyle.ContinuationIndentWidth = 8;
1785 ChromiumStyle.IndentWidth = 4;
1786 // See styleguide for import groups:
1787 // https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/java/java.md#Import-Order
1788 ChromiumStyle.JavaImportGroups = {
1789 "android",
1790 "androidx",
1791 "com",
1792 "dalvik",
1793 "junit",
1794 "org",
1795 "com.google.android.apps.chrome",
1796 "org.chromium",
1797 "java",
1798 "javax",
1799 };
1801 } else if (Language == FormatStyle::LK_JavaScript) {
1803 ChromiumStyle.AllowShortLoopsOnASingleLine = false;
1804 } else {
1805 ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
1808 ChromiumStyle.AllowShortLoopsOnASingleLine = false;
1809 ChromiumStyle.BinPackParameters = false;
1810 ChromiumStyle.DerivePointerAlignment = false;
1812 ChromiumStyle.ColumnLimit = 80;
1813 }
1814 return ChromiumStyle;
1815}
1816
1818 FormatStyle MozillaStyle = getLLVMStyle();
1819 MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
1823 MozillaStyle.BinPackArguments = false;
1824 MozillaStyle.BinPackParameters = false;
1830 MozillaStyle.ConstructorInitializerIndentWidth = 2;
1831 MozillaStyle.ContinuationIndentWidth = 2;
1832 MozillaStyle.Cpp11BracedListStyle = false;
1833 MozillaStyle.FixNamespaceComments = false;
1834 MozillaStyle.IndentCaseLabels = true;
1835 MozillaStyle.ObjCSpaceAfterProperty = true;
1836 MozillaStyle.ObjCSpaceBeforeProtocolList = false;
1837 MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
1839 MozillaStyle.SpaceAfterTemplateKeyword = false;
1840 return MozillaStyle;
1841}
1842
1844 FormatStyle Style = getLLVMStyle();
1845 Style.AccessModifierOffset = -4;
1848 Style.AlignTrailingComments = {};
1854 Style.ColumnLimit = 0;
1855 Style.Cpp11BracedListStyle = false;
1856 Style.FixNamespaceComments = false;
1857 Style.IndentWidth = 4;
1859 Style.ObjCBlockIndentWidth = 4;
1860 Style.ObjCSpaceAfterProperty = true;
1862 Style.SpaceBeforeCpp11BracedList = true;
1863 Style.SpaceInEmptyBlock = true;
1864 return Style;
1865}
1866
1868 FormatStyle Style = getLLVMStyle();
1873 Style.BreakBeforeTernaryOperators = true;
1874 Style.ColumnLimit = 79;
1875 Style.Cpp11BracedListStyle = false;
1876 Style.FixNamespaceComments = false;
1879 return Style;
1880}
1881
1884 Style.ColumnLimit = 120;
1885 Style.TabWidth = 4;
1886 Style.IndentWidth = 4;
1889 Style.BraceWrapping.AfterClass = true;
1891 Style.BraceWrapping.AfterEnum = true;
1892 Style.BraceWrapping.AfterFunction = true;
1893 Style.BraceWrapping.AfterNamespace = true;
1895 Style.BraceWrapping.AfterStruct = true;
1896 Style.BraceWrapping.AfterExternBlock = true;
1897 Style.BraceWrapping.BeforeCatch = true;
1898 Style.BraceWrapping.BeforeElse = true;
1899 Style.BraceWrapping.BeforeWhile = false;
1900 Style.PenaltyReturnTypeOnItsOwnLine = 1000;
1901 Style.AllowShortEnumsOnASingleLine = false;
1905 Style.AllowShortLoopsOnASingleLine = false;
1908 return Style;
1909}
1910
1912 FormatStyle Style = getLLVMStyle();
1913 Style.InsertBraces = true;
1914 Style.InsertNewlineAtEOF = true;
1918 Style.RemoveBracesLLVM = true;
1920 Style.RemoveSemicolon = true;
1921 return Style;
1922}
1923
1925 FormatStyle NoStyle = getLLVMStyle();
1926 NoStyle.DisableFormat = true;
1929 return NoStyle;
1930}
1931
1933 FormatStyle *Style) {
1934 if (Name.equals_insensitive("llvm"))
1935 *Style = getLLVMStyle(Language);
1936 else if (Name.equals_insensitive("chromium"))
1937 *Style = getChromiumStyle(Language);
1938 else if (Name.equals_insensitive("mozilla"))
1939 *Style = getMozillaStyle();
1940 else if (Name.equals_insensitive("google"))
1941 *Style = getGoogleStyle(Language);
1942 else if (Name.equals_insensitive("webkit"))
1943 *Style = getWebKitStyle();
1944 else if (Name.equals_insensitive("gnu"))
1945 *Style = getGNUStyle();
1946 else if (Name.equals_insensitive("microsoft"))
1947 *Style = getMicrosoftStyle(Language);
1948 else if (Name.equals_insensitive("clang-format"))
1949 *Style = getClangFormatStyle();
1950 else if (Name.equals_insensitive("none"))
1951 *Style = getNoStyle();
1952 else if (Name.equals_insensitive("inheritparentconfig"))
1953 Style->InheritsParentConfig = true;
1954 else
1955 return false;
1956
1957 Style->Language = Language;
1958 return true;
1959}
1960
1962 // If its empty then it means don't do anything.
1963 if (Style->QualifierOrder.empty())
1965
1966 // Ensure the list contains only currently valid qualifiers.
1967 for (const auto &Qualifier : Style->QualifierOrder) {
1968 if (Qualifier == "type")
1969 continue;
1970 auto token =
1972 if (token == tok::identifier)
1974 }
1975
1976 // Ensure the list is unique (no duplicates).
1977 std::set<std::string> UniqueQualifiers(Style->QualifierOrder.begin(),
1978 Style->QualifierOrder.end());
1979 if (Style->QualifierOrder.size() != UniqueQualifiers.size()) {
1980 LLVM_DEBUG(llvm::dbgs()
1981 << "Duplicate Qualifiers " << Style->QualifierOrder.size()
1982 << " vs " << UniqueQualifiers.size() << "\n");
1984 }
1985
1986 // Ensure the list has 'type' in it.
1987 if (!llvm::is_contained(Style->QualifierOrder, "type"))
1989
1990 return ParseError::Success;
1991}
1992
1993std::error_code parseConfiguration(llvm::MemoryBufferRef Config,
1994 FormatStyle *Style, bool AllowUnknownOptions,
1995 llvm::SourceMgr::DiagHandlerTy DiagHandler,
1996 void *DiagHandlerCtxt) {
1997 assert(Style);
1999 assert(Language != FormatStyle::LK_None);
2000 if (Config.getBuffer().trim().empty())
2002 Style->StyleSet.Clear();
2003 std::vector<FormatStyle> Styles;
2004 llvm::yaml::Input Input(Config, /*Ctxt=*/nullptr, DiagHandler,
2005 DiagHandlerCtxt);
2006 // DocumentListTraits<vector<FormatStyle>> uses the context to get default
2007 // values for the fields, keys for which are missing from the configuration.
2008 // Mapping also uses the context to get the language to find the correct
2009 // base style.
2010 Input.setContext(Style);
2011 Input.setAllowUnknownKeys(AllowUnknownOptions);
2012 Input >> Styles;
2013 if (Input.error())
2014 return Input.error();
2015
2016 for (unsigned i = 0; i < Styles.size(); ++i) {
2017 // Ensures that only the first configuration can skip the Language option.
2018 if (Styles[i].Language == FormatStyle::LK_None && i != 0)
2020 // Ensure that each language is configured at most once.
2021 for (unsigned j = 0; j < i; ++j) {
2022 if (Styles[i].Language == Styles[j].Language) {
2023 LLVM_DEBUG(llvm::dbgs()
2024 << "Duplicate languages in the config file on positions "
2025 << j << " and " << i << "\n");
2027 }
2028 }
2029 }
2030 // Look for a suitable configuration starting from the end, so we can
2031 // find the configuration for the specific language first, and the default
2032 // configuration (which can only be at slot 0) after it.
2034 bool LanguageFound = false;
2035 for (const FormatStyle &Style : llvm::reverse(Styles)) {
2036 if (Style.Language != FormatStyle::LK_None)
2037 StyleSet.Add(Style);
2038 if (Style.Language == Language)
2039 LanguageFound = true;
2040 }
2041 if (!LanguageFound) {
2042 if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None)
2044 FormatStyle DefaultStyle = Styles[0];
2045 DefaultStyle.Language = Language;
2046 StyleSet.Add(std::move(DefaultStyle));
2047 }
2048 *Style = *StyleSet.Get(Language);
2050 Style->BinPackArguments) {
2051 // See comment on FormatStyle::TSC_Wrapped.
2053 }
2057}
2058
2059std::string configurationAsText(const FormatStyle &Style) {
2060 std::string Text;
2061 llvm::raw_string_ostream Stream(Text);
2062 llvm::yaml::Output Output(Stream);
2063 // We use the same mapping method for input and output, so we need a non-const
2064 // reference here.
2065 FormatStyle NonConstStyle = Style;
2066 expandPresetsBraceWrapping(NonConstStyle);
2067 expandPresetsSpaceBeforeParens(NonConstStyle);
2068 expandPresetsSpacesInParens(NonConstStyle);
2069 Output << NonConstStyle;
2070
2071 return Stream.str();
2072}
2073
2074std::optional<FormatStyle>
2076 if (!Styles)
2077 return std::nullopt;
2078 auto It = Styles->find(Language);
2079 if (It == Styles->end())
2080 return std::nullopt;
2081 FormatStyle Style = It->second;
2082 Style.StyleSet = *this;
2083 return Style;
2084}
2085
2087 assert(Style.Language != LK_None &&
2088 "Cannot add a style for LK_None to a StyleSet");
2089 assert(
2090 !Style.StyleSet.Styles &&
2091 "Cannot add a style associated with an existing StyleSet to a StyleSet");
2092 if (!Styles)
2093 Styles = std::make_shared<MapType>();
2094 (*Styles)[Style.Language] = std::move(Style);
2095}
2096
2097void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); }
2098
2099std::optional<FormatStyle>
2101 return StyleSet.Get(Language);
2102}
2103
2104namespace {
2105
2106class ParensRemover : public TokenAnalyzer {
2107public:
2108 ParensRemover(const Environment &Env, const FormatStyle &Style)
2109 : TokenAnalyzer(Env, Style) {}
2110
2111 std::pair<tooling::Replacements, unsigned>
2112 analyze(TokenAnnotator &Annotator,
2113 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2114 FormatTokenLexer &Tokens) override {
2115 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2116 tooling::Replacements Result;
2117 removeParens(AnnotatedLines, Result);
2118 return {Result, 0};
2119 }
2120
2121private:
2122 void removeParens(SmallVectorImpl<AnnotatedLine *> &Lines,
2123 tooling::Replacements &Result) {
2124 const auto &SourceMgr = Env.getSourceManager();
2125 for (auto *Line : Lines) {
2126 removeParens(Line->Children, Result);
2127 if (!Line->Affected)
2128 continue;
2129 for (const auto *Token = Line->First; Token && !Token->Finalized;
2130 Token = Token->Next) {
2131 if (!Token->Optional || !Token->isOneOf(tok::l_paren, tok::r_paren))
2132 continue;
2133 auto *Next = Token->Next;
2134 assert(Next && Next->isNot(tok::eof));
2135 SourceLocation Start;
2136 if (Next->NewlinesBefore == 0) {
2137 Start = Token->Tok.getLocation();
2138 Next->WhitespaceRange = Token->WhitespaceRange;
2139 } else {
2140 Start = Token->WhitespaceRange.getBegin();
2141 }
2142 const auto &Range =
2143 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2144 cantFail(Result.add(tooling::Replacement(SourceMgr, Range, " ")));
2145 }
2146 }
2147 }
2148};
2149
2150class BracesInserter : public TokenAnalyzer {
2151public:
2152 BracesInserter(const Environment &Env, const FormatStyle &Style)
2153 : TokenAnalyzer(Env, Style) {}
2154
2155 std::pair<tooling::Replacements, unsigned>
2156 analyze(TokenAnnotator &Annotator,
2157 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2158 FormatTokenLexer &Tokens) override {
2159 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2160 tooling::Replacements Result;
2161 insertBraces(AnnotatedLines, Result);
2162 return {Result, 0};
2163 }
2164
2165private:
2166 void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2167 tooling::Replacements &Result) {
2168 const auto &SourceMgr = Env.getSourceManager();
2169 int OpeningBraceSurplus = 0;
2170 for (AnnotatedLine *Line : Lines) {
2171 insertBraces(Line->Children, Result);
2172 if (!Line->Affected && OpeningBraceSurplus == 0)
2173 continue;
2174 for (FormatToken *Token = Line->First; Token && !Token->Finalized;
2175 Token = Token->Next) {
2176 int BraceCount = Token->BraceCount;
2177 if (BraceCount == 0)
2178 continue;
2179 std::string Brace;
2180 if (BraceCount < 0) {
2181 assert(BraceCount == -1);
2182 if (!Line->Affected)
2183 break;
2184 Brace = Token->is(tok::comment) ? "\n{" : "{";
2185 ++OpeningBraceSurplus;
2186 } else {
2187 if (OpeningBraceSurplus == 0)
2188 break;
2189 if (OpeningBraceSurplus < BraceCount)
2190 BraceCount = OpeningBraceSurplus;
2191 Brace = '\n' + std::string(BraceCount, '}');
2192 OpeningBraceSurplus -= BraceCount;
2193 }
2194 Token->BraceCount = 0;
2195 const auto Start = Token->Tok.getEndLoc();
2196 cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0, Brace)));
2197 }
2198 }
2199 assert(OpeningBraceSurplus == 0);
2200 }
2201};
2202
2203class BracesRemover : public TokenAnalyzer {
2204public:
2205 BracesRemover(const Environment &Env, const FormatStyle &Style)
2206 : TokenAnalyzer(Env, Style) {}
2207
2208 std::pair<tooling::Replacements, unsigned>
2209 analyze(TokenAnnotator &Annotator,
2210 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2211 FormatTokenLexer &Tokens) override {
2212 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2213 tooling::Replacements Result;
2214 removeBraces(AnnotatedLines, Result);
2215 return {Result, 0};
2216 }
2217
2218private:
2219 void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2220 tooling::Replacements &Result) {
2221 const auto &SourceMgr = Env.getSourceManager();
2222 const auto End = Lines.end();
2223 for (auto I = Lines.begin(); I != End; ++I) {
2224 const auto Line = *I;
2225 removeBraces(Line->Children, Result);
2226 if (!Line->Affected)
2227 continue;
2228 const auto NextLine = I + 1 == End ? nullptr : I[1];
2229 for (auto Token = Line->First; Token && !Token->Finalized;
2230 Token = Token->Next) {
2231 if (!Token->Optional)
2232 continue;
2233 if (!Token->isOneOf(tok::l_brace, tok::r_brace))
2234 continue;
2235 auto Next = Token->Next;
2236 assert(Next || Token == Line->Last);
2237 if (!Next && NextLine)
2238 Next = NextLine->First;
2239 SourceLocation Start;
2240 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2241 Start = Token->Tok.getLocation();
2242 Next->WhitespaceRange = Token->WhitespaceRange;
2243 } else {
2244 Start = Token->WhitespaceRange.getBegin();
2245 }
2246 const auto Range =
2247 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2248 cantFail(Result.add(tooling::Replacement(SourceMgr, Range, "")));
2249 }
2250 }
2251 }
2252};
2253
2254class SemiRemover : public TokenAnalyzer {
2255public:
2256 SemiRemover(const Environment &Env, const FormatStyle &Style)
2257 : TokenAnalyzer(Env, Style) {}
2258
2259 std::pair<tooling::Replacements, unsigned>
2260 analyze(TokenAnnotator &Annotator,
2261 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2262 FormatTokenLexer &Tokens) override {
2263 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2264 tooling::Replacements Result;
2265 removeSemi(Annotator, AnnotatedLines, Result);
2266 return {Result, 0};
2267 }
2268
2269private:
2270 void removeSemi(TokenAnnotator &Annotator,
2271 SmallVectorImpl<AnnotatedLine *> &Lines,
2272 tooling::Replacements &Result) {
2273 auto PrecededByFunctionRBrace = [](const FormatToken &Tok) {
2274 const auto *Prev = Tok.Previous;
2275 if (!Prev || Prev->isNot(tok::r_brace))
2276 return false;
2277 const auto *LBrace = Prev->MatchingParen;
2278 return LBrace && LBrace->is(TT_FunctionLBrace);
2279 };
2280 const auto &SourceMgr = Env.getSourceManager();
2281 const auto End = Lines.end();
2282 for (auto I = Lines.begin(); I != End; ++I) {
2283 const auto Line = *I;
2284 removeSemi(Annotator, Line->Children, Result);
2285 if (!Line->Affected)
2286 continue;
2287 Annotator.calculateFormattingInformation(*Line);
2288 const auto NextLine = I + 1 == End ? nullptr : I[1];
2289 for (auto Token = Line->First; Token && !Token->Finalized;
2290 Token = Token->Next) {
2291 if (Token->isNot(tok::semi) ||
2292 (!Token->Optional && !PrecededByFunctionRBrace(*Token))) {
2293 continue;
2294 }
2295 auto Next = Token->Next;
2296 assert(Next || Token == Line->Last);
2297 if (!Next && NextLine)
2298 Next = NextLine->First;
2299 SourceLocation Start;
2300 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2301 Start = Token->Tok.getLocation();
2302 Next->WhitespaceRange = Token->WhitespaceRange;
2303 } else {
2304 Start = Token->WhitespaceRange.getBegin();
2305 }
2306 const auto Range =
2307 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2308 cantFail(Result.add(tooling::Replacement(SourceMgr, Range, "")));
2309 }
2310 }
2311 }
2312};
2313
2314class JavaScriptRequoter : public TokenAnalyzer {
2315public:
2316 JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)
2317 : TokenAnalyzer(Env, Style) {}
2318
2319 std::pair<tooling::Replacements, unsigned>
2320 analyze(TokenAnnotator &Annotator,
2321 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2322 FormatTokenLexer &Tokens) override {
2323 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2324 tooling::Replacements Result;
2325 requoteJSStringLiteral(AnnotatedLines, Result);
2326 return {Result, 0};
2327 }
2328
2329private:
2330 // Replaces double/single-quoted string literal as appropriate, re-escaping
2331 // the contents in the process.
2332 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
2333 tooling::Replacements &Result) {
2334 for (AnnotatedLine *Line : Lines) {
2335 requoteJSStringLiteral(Line->Children, Result);
2336 if (!Line->Affected)
2337 continue;
2338 for (FormatToken *FormatTok = Line->First; FormatTok;
2339 FormatTok = FormatTok->Next) {
2340 StringRef Input = FormatTok->TokenText;
2341 if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
2342 // NB: testing for not starting with a double quote to avoid
2343 // breaking `template strings`.
2344 (Style.JavaScriptQuotes == FormatStyle::JSQS_Single &&
2345 !Input.starts_with("\"")) ||
2346 (Style.JavaScriptQuotes == FormatStyle::JSQS_Double &&
2347 !Input.starts_with("\'"))) {
2348 continue;
2349 }
2350
2351 // Change start and end quote.
2352 bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single;
2353 SourceLocation Start = FormatTok->Tok.getLocation();
2354 auto Replace = [&](SourceLocation Start, unsigned Length,
2355 StringRef ReplacementText) {
2356 auto Err = Result.add(tooling::Replacement(
2357 Env.getSourceManager(), Start, Length, ReplacementText));
2358 // FIXME: handle error. For now, print error message and skip the
2359 // replacement for release version.
2360 if (Err) {
2361 llvm::errs() << llvm::toString(std::move(Err)) << "\n";
2362 assert(false);
2363 }
2364 };
2365 Replace(Start, 1, IsSingle ? "'" : "\"");
2366 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
2367 IsSingle ? "'" : "\"");
2368
2369 // Escape internal quotes.
2370 bool Escaped = false;
2371 for (size_t i = 1; i < Input.size() - 1; i++) {
2372 switch (Input[i]) {
2373 case '\\':
2374 if (!Escaped && i + 1 < Input.size() &&
2375 ((IsSingle && Input[i + 1] == '"') ||
2376 (!IsSingle && Input[i + 1] == '\''))) {
2377 // Remove this \, it's escaping a " or ' that no longer needs
2378 // escaping
2379 Replace(Start.getLocWithOffset(i), 1, "");
2380 continue;
2381 }
2382 Escaped = !Escaped;
2383 break;
2384 case '\"':
2385 case '\'':
2386 if (!Escaped && IsSingle == (Input[i] == '\'')) {
2387 // Escape the quote.
2388 Replace(Start.getLocWithOffset(i), 0, "\\");
2389 }
2390 Escaped = false;
2391 break;
2392 default:
2393 Escaped = false;
2394 break;
2395 }
2396 }
2397 }
2398 }
2399 }
2400};
2401
2402class Formatter : public TokenAnalyzer {
2403public:
2404 Formatter(const Environment &Env, const FormatStyle &Style,
2405 FormattingAttemptStatus *Status)
2406 : TokenAnalyzer(Env, Style), Status(Status) {}
2407
2408 std::pair<tooling::Replacements, unsigned>
2409 analyze(TokenAnnotator &Annotator,
2410 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2411 FormatTokenLexer &Tokens) override {
2412 tooling::Replacements Result;
2413 deriveLocalStyle(AnnotatedLines);
2414 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2415 for (AnnotatedLine *Line : AnnotatedLines)
2416 Annotator.calculateFormattingInformation(*Line);
2417 Annotator.setCommentLineLevels(AnnotatedLines);
2418
2419 WhitespaceManager Whitespaces(
2420 Env.getSourceManager(), Style,
2421 Style.LineEnding > FormatStyle::LE_CRLF
2422 ? WhitespaceManager::inputUsesCRLF(
2423 Env.getSourceManager().getBufferData(Env.getFileID()),
2424 Style.LineEnding == FormatStyle::LE_DeriveCRLF)
2425 : Style.LineEnding == FormatStyle::LE_CRLF);
2426 ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
2427 Env.getSourceManager(), Whitespaces, Encoding,
2428 BinPackInconclusiveFunctions);
2429 unsigned Penalty =
2430 UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,
2431 Tokens.getKeywords(), Env.getSourceManager(),
2432 Status)
2433 .format(AnnotatedLines, /*DryRun=*/false,
2434 /*AdditionalIndent=*/0,
2435 /*FixBadIndentation=*/false,
2436 /*FirstStartColumn=*/Env.getFirstStartColumn(),
2437 /*NextStartColumn=*/Env.getNextStartColumn(),
2438 /*LastStartColumn=*/Env.getLastStartColumn());
2439 for (const auto &R : Whitespaces.generateReplacements())
2440 if (Result.add(R))
2441 return std::make_pair(Result, 0);
2442 return std::make_pair(Result, Penalty);
2443 }
2444
2445private:
2446 bool
2447 hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) {
2448 for (const AnnotatedLine *Line : Lines) {
2449 if (hasCpp03IncompatibleFormat(Line->Children))
2450 return true;
2451 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {
2452 if (!Tok->hasWhitespaceBefore()) {
2453 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
2454 return true;
2455 if (Tok->is(TT_TemplateCloser) &&
2456 Tok->Previous->is(TT_TemplateCloser)) {
2457 return true;
2458 }
2459 }
2460 }
2461 }
2462 return false;
2463 }
2464
2465 int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) {
2466 int AlignmentDiff = 0;
2467 for (const AnnotatedLine *Line : Lines) {
2468 AlignmentDiff += countVariableAlignments(Line->Children);
2469 for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {
2470 if (Tok->isNot(TT_PointerOrReference))
2471 continue;
2472 // Don't treat space in `void foo() &&` as evidence.
2473 if (const auto *Prev = Tok->getPreviousNonComment()) {
2474 if (Prev->is(tok::r_paren) && Prev->MatchingParen) {
2475 if (const auto *Func =
2476 Prev->MatchingParen->getPreviousNonComment()) {
2477 if (Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName,
2478 TT_OverloadedOperator)) {
2479 continue;
2480 }
2481 }
2482 }
2483 }
2484 bool SpaceBefore = Tok->hasWhitespaceBefore();
2485 bool SpaceAfter = Tok->Next->hasWhitespaceBefore();
2486 if (SpaceBefore && !SpaceAfter)
2487 ++AlignmentDiff;
2488 if (!SpaceBefore && SpaceAfter)
2489 --AlignmentDiff;
2490 }
2491 }
2492 return AlignmentDiff;
2493 }
2494
2495 void
2496 deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2497 bool HasBinPackedFunction = false;
2498 bool HasOnePerLineFunction = false;
2499 for (AnnotatedLine *Line : AnnotatedLines) {
2500 if (!Line->First->Next)
2501 continue;
2502 FormatToken *Tok = Line->First->Next;
2503 while (Tok->Next) {
2504 if (Tok->is(PPK_BinPacked))
2505 HasBinPackedFunction = true;
2506 if (Tok->is(PPK_OnePerLine))
2507 HasOnePerLineFunction = true;
2508
2509 Tok = Tok->Next;
2510 }
2511 }
2512 if (Style.DerivePointerAlignment) {
2513 const auto NetRightCount = countVariableAlignments(AnnotatedLines);
2514 if (NetRightCount > 0)
2515 Style.PointerAlignment = FormatStyle::PAS_Right;
2516 else if (NetRightCount < 0)
2517 Style.PointerAlignment = FormatStyle::PAS_Left;
2518 Style.ReferenceAlignment = FormatStyle::RAS_Pointer;
2519 }
2520 if (Style.Standard == FormatStyle::LS_Auto) {
2521 Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
2522 ? FormatStyle::LS_Latest
2523 : FormatStyle::LS_Cpp03;
2524 }
2525 BinPackInconclusiveFunctions =
2526 HasBinPackedFunction || !HasOnePerLineFunction;
2527 }
2528
2529 bool BinPackInconclusiveFunctions;
2530 FormattingAttemptStatus *Status;
2531};
2532
2533/// TrailingCommaInserter inserts trailing commas into container literals.
2534/// E.g.:
2535/// const x = [
2536/// 1,
2537/// ];
2538/// TrailingCommaInserter runs after formatting. To avoid causing a required
2539/// reformatting (and thus reflow), it never inserts a comma that'd exceed the
2540/// ColumnLimit.
2541///
2542/// Because trailing commas disable binpacking of arrays, TrailingCommaInserter
2543/// is conceptually incompatible with bin packing.
2544class TrailingCommaInserter : public TokenAnalyzer {
2545public:
2546 TrailingCommaInserter(const Environment &Env, const FormatStyle &Style)
2547 : TokenAnalyzer(Env, Style) {}
2548
2549 std::pair<tooling::Replacements, unsigned>
2550 analyze(TokenAnnotator &Annotator,
2551 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2552 FormatTokenLexer &Tokens) override {
2553 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2554 tooling::Replacements Result;
2555 insertTrailingCommas(AnnotatedLines, Result);
2556 return {Result, 0};
2557 }
2558
2559private:
2560 /// Inserts trailing commas in [] and {} initializers if they wrap over
2561 /// multiple lines.
2562 void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,
2563 tooling::Replacements &Result) {
2564 for (AnnotatedLine *Line : Lines) {
2565 insertTrailingCommas(Line->Children, Result);
2566 if (!Line->Affected)
2567 continue;
2568 for (FormatToken *FormatTok = Line->First; FormatTok;
2569 FormatTok = FormatTok->Next) {
2570 if (FormatTok->NewlinesBefore == 0)
2571 continue;
2572 FormatToken *Matching = FormatTok->MatchingParen;
2573 if (!Matching || !FormatTok->getPreviousNonComment())
2574 continue;
2575 if (!(FormatTok->is(tok::r_square) &&
2576 Matching->is(TT_ArrayInitializerLSquare)) &&
2577 !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) {
2578 continue;
2579 }
2580 FormatToken *Prev = FormatTok->getPreviousNonComment();
2581 if (Prev->is(tok::comma) || Prev->is(tok::semi))
2582 continue;
2583 // getEndLoc is not reliably set during re-lexing, use text length
2584 // instead.
2585 SourceLocation Start =
2586 Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size());
2587 // If inserting a comma would push the code over the column limit, skip
2588 // this location - it'd introduce an unstable formatting due to the
2589 // required reflow.
2590 unsigned ColumnNumber =
2591 Env.getSourceManager().getSpellingColumnNumber(Start);
2592 if (ColumnNumber > Style.ColumnLimit)
2593 continue;
2594 // Comma insertions cannot conflict with each other, and this pass has a
2595 // clean set of Replacements, so the operation below cannot fail.
2596 cantFail(Result.add(
2597 tooling::Replacement(Env.getSourceManager(), Start, 0, ",")));
2598 }
2599 }
2600 }
2601};
2602
2603// This class clean up the erroneous/redundant code around the given ranges in
2604// file.
2605class Cleaner : public TokenAnalyzer {
2606public:
2607 Cleaner(const Environment &Env, const FormatStyle &Style)
2608 : TokenAnalyzer(Env, Style),
2609 DeletedTokens(FormatTokenLess(Env.getSourceManager())) {}
2610
2611 // FIXME: eliminate unused parameters.
2612 std::pair<tooling::Replacements, unsigned>
2613 analyze(TokenAnnotator &Annotator,
2614 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2615 FormatTokenLexer &Tokens) override {
2616 // FIXME: in the current implementation the granularity of affected range
2617 // is an annotated line. However, this is not sufficient. Furthermore,
2618 // redundant code introduced by replacements does not necessarily
2619 // intercept with ranges of replacements that result in the redundancy.
2620 // To determine if some redundant code is actually introduced by
2621 // replacements(e.g. deletions), we need to come up with a more
2622 // sophisticated way of computing affected ranges.
2623 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2624
2625 checkEmptyNamespace(AnnotatedLines);
2626
2627 for (auto *Line : AnnotatedLines)
2628 cleanupLine(Line);
2629
2630 return {generateFixes(), 0};
2631 }
2632
2633private:
2634 void cleanupLine(AnnotatedLine *Line) {
2635 for (auto *Child : Line->Children)
2636 cleanupLine(Child);
2637
2638 if (Line->Affected) {
2639 cleanupRight(Line->First, tok::comma, tok::comma);
2640 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
2641 cleanupRight(Line->First, tok::l_paren, tok::comma);
2642 cleanupLeft(Line->First, tok::comma, tok::r_paren);
2643 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
2644 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
2645 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
2646 }
2647 }
2648
2649 bool containsOnlyComments(const AnnotatedLine &Line) {
2650 for (FormatToken *Tok = Line.First; Tok; Tok = Tok->Next)
2651 if (Tok->isNot(tok::comment))
2652 return false;
2653 return true;
2654 }
2655
2656 // Iterate through all lines and remove any empty (nested) namespaces.
2657 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2658 std::set<unsigned> DeletedLines;
2659 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
2660 auto &Line = *AnnotatedLines[i];
2661 if (Line.startsWithNamespace())
2662 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
2663 }
2664
2665 for (auto Line : DeletedLines) {
2666 FormatToken *Tok = AnnotatedLines[Line]->First;
2667 while (Tok) {
2668 deleteToken(Tok);
2669 Tok = Tok->Next;
2670 }
2671 }
2672 }
2673
2674 // The function checks if the namespace, which starts from \p CurrentLine, and
2675 // its nested namespaces are empty and delete them if they are empty. It also
2676 // sets \p NewLine to the last line checked.
2677 // Returns true if the current namespace is empty.
2678 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2679 unsigned CurrentLine, unsigned &NewLine,
2680 std::set<unsigned> &DeletedLines) {
2681 unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
2682 if (Style.BraceWrapping.AfterNamespace) {
2683 // If the left brace is in a new line, we should consume it first so that
2684 // it does not make the namespace non-empty.
2685 // FIXME: error handling if there is no left brace.
2686 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
2687 NewLine = CurrentLine;
2688 return false;
2689 }
2690 } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
2691 return false;
2692 }
2693 while (++CurrentLine < End) {
2694 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
2695 break;
2696
2697 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
2698 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
2699 DeletedLines)) {
2700 return false;
2701 }
2702 CurrentLine = NewLine;
2703 continue;
2704 }
2705
2706 if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
2707 continue;
2708
2709 // If there is anything other than comments or nested namespaces in the
2710 // current namespace, the namespace cannot be empty.
2711 NewLine = CurrentLine;
2712 return false;
2713 }
2714
2715 NewLine = CurrentLine;
2716 if (CurrentLine >= End)
2717 return false;
2718
2719 // Check if the empty namespace is actually affected by changed ranges.
2720 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
2721 AnnotatedLines[InitLine]->First->Tok.getLocation(),
2722 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) {
2723 return false;
2724 }
2725
2726 for (unsigned i = InitLine; i <= CurrentLine; ++i)
2727 DeletedLines.insert(i);
2728
2729 return true;
2730 }
2731
2732 // Checks pairs {start, start->next},..., {end->previous, end} and deletes one
2733 // of the token in the pair if the left token has \p LK token kind and the
2734 // right token has \p RK token kind. If \p DeleteLeft is true, the left token
2735 // is deleted on match; otherwise, the right token is deleted.
2736 template <typename LeftKind, typename RightKind>
2737 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
2738 bool DeleteLeft) {
2739 auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {
2740 for (auto *Res = Tok.Next; Res; Res = Res->Next) {
2741 if (Res->isNot(tok::comment) &&
2742 DeletedTokens.find(Res) == DeletedTokens.end()) {
2743 return Res;
2744 }
2745 }
2746 return nullptr;
2747 };
2748 for (auto *Left = Start; Left;) {
2749 auto *Right = NextNotDeleted(*Left);
2750 if (!Right)
2751 break;
2752 if (Left->is(LK) && Right->is(RK)) {
2753 deleteToken(DeleteLeft ? Left : Right);
2754 for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
2755 deleteToken(Tok);
2756 // If the right token is deleted, we should keep the left token
2757 // unchanged and pair it with the new right token.
2758 if (!DeleteLeft)
2759 continue;
2760 }
2761 Left = Right;
2762 }
2763 }
2764
2765 template <typename LeftKind, typename RightKind>
2766 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
2767 cleanupPair(Start, LK, RK, /*DeleteLeft=*/true);
2768 }
2769
2770 template <typename LeftKind, typename RightKind>
2771 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
2772 cleanupPair(Start, LK, RK, /*DeleteLeft=*/false);
2773 }
2774
2775 // Delete the given token.
2776 inline void deleteToken(FormatToken *Tok) {
2777 if (Tok)
2778 DeletedTokens.insert(Tok);
2779 }
2780
2781 tooling::Replacements generateFixes() {
2782 tooling::Replacements Fixes;
2783 SmallVector<FormatToken *> Tokens;
2784 std::copy(DeletedTokens.begin(), DeletedTokens.end(),
2785 std::back_inserter(Tokens));
2786
2787 // Merge multiple continuous token deletions into one big deletion so that
2788 // the number of replacements can be reduced. This makes computing affected
2789 // ranges more efficient when we run reformat on the changed code.
2790 unsigned Idx = 0;
2791 while (Idx < Tokens.size()) {
2792 unsigned St = Idx, End = Idx;
2793 while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1])
2794 ++End;
2795 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
2796 Tokens[End]->Tok.getEndLoc());
2797 auto Err =
2798 Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, ""));
2799 // FIXME: better error handling. for now just print error message and skip
2800 // for the release version.
2801 if (Err) {
2802 llvm::errs() << llvm::toString(std::move(Err)) << "\n";
2803 assert(false && "Fixes must not conflict!");
2804 }
2805 Idx = End + 1;
2806 }
2807
2808 return Fixes;
2809 }
2810
2811 // Class for less-than inequality comparason for the set `RedundantTokens`.
2812 // We store tokens in the order they appear in the translation unit so that
2813 // we do not need to sort them in `generateFixes()`.
2814 struct FormatTokenLess {
2815 FormatTokenLess(const SourceManager &SM) : SM(SM) {}
2816
2817 bool operator()(const FormatToken *LHS, const FormatToken *RHS) const {
2818 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
2819 RHS->Tok.getLocation());
2820 }
2821 const SourceManager &SM;
2822 };
2823
2824 // Tokens to be deleted.
2825 std::set<FormatToken *, FormatTokenLess> DeletedTokens;
2826};
2827
2828class ObjCHeaderStyleGuesser : public TokenAnalyzer {
2829public:
2830 ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style)
2831 : TokenAnalyzer(Env, Style), IsObjC(false) {}
2832
2833 std::pair<tooling::Replacements, unsigned>
2834 analyze(TokenAnnotator &Annotator,
2835 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2836 FormatTokenLexer &Tokens) override {
2837 assert(Style.Language == FormatStyle::LK_Cpp);
2838 IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines,
2839 Tokens.getKeywords());
2840 tooling::Replacements Result;
2841 return {Result, 0};
2842 }
2843
2844 bool isObjC() { return IsObjC; }
2845
2846private:
2847 static bool
2848 guessIsObjC(const SourceManager &SourceManager,
2849 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2850 const AdditionalKeywords &Keywords) {
2851 // Keep this array sorted, since we are binary searching over it.
2852 static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
2853 "CGFloat",
2854 "CGPoint",
2855 "CGPointMake",
2856 "CGPointZero",
2857 "CGRect",
2858 "CGRectEdge",
2859 "CGRectInfinite",
2860 "CGRectMake",
2861 "CGRectNull",
2862 "CGRectZero",
2863 "CGSize",
2864 "CGSizeMake",
2865 "CGVector",
2866 "CGVectorMake",
2867 "FOUNDATION_EXPORT", // This is an alias for FOUNDATION_EXTERN.
2868 "FOUNDATION_EXTERN",
2869 "NSAffineTransform",
2870 "NSArray",
2871 "NSAttributedString",
2872 "NSBlockOperation",
2873 "NSBundle",
2874 "NSCache",
2875 "NSCalendar",
2876 "NSCharacterSet",
2877 "NSCountedSet",
2878 "NSData",
2879 "NSDataDetector",
2880 "NSDecimal",
2881 "NSDecimalNumber",
2882 "NSDictionary",
2883 "NSEdgeInsets",
2884 "NSError",
2885 "NSErrorDomain",
2886 "NSHashTable",
2887 "NSIndexPath",
2888 "NSIndexSet",
2889 "NSInteger",
2890 "NSInvocationOperation",
2891 "NSLocale",
2892 "NSMapTable",
2893 "NSMutableArray",
2894 "NSMutableAttributedString",
2895 "NSMutableCharacterSet",
2896 "NSMutableData",
2897 "NSMutableDictionary",
2898 "NSMutableIndexSet",
2899 "NSMutableOrderedSet",
2900 "NSMutableSet",
2901 "NSMutableString",
2902 "NSNumber",
2903 "NSNumberFormatter",
2904 "NSObject",
2905 "NSOperation",
2906 "NSOperationQueue",
2907 "NSOperationQueuePriority",
2908 "NSOrderedSet",
2909 "NSPoint",
2910 "NSPointerArray",
2911 "NSQualityOfService",
2912 "NSRange",
2913 "NSRect",
2914 "NSRegularExpression",
2915 "NSSet",
2916 "NSSize",
2917 "NSString",
2918 "NSTimeZone",
2919 "NSUInteger",
2920 "NSURL",
2921 "NSURLComponents",
2922 "NSURLQueryItem",
2923 "NSUUID",
2924 "NSValue",
2925 "NS_ASSUME_NONNULL_BEGIN",
2926 "UIImage",
2927 "UIView",
2928 };
2929
2930 for (auto *Line : AnnotatedLines) {
2931 if (Line->First && (Line->First->TokenText.starts_with("#") ||
2932 Line->First->TokenText == "__pragma" ||
2933 Line->First->TokenText == "_Pragma")) {
2934 continue;
2935 }
2936 for (const FormatToken *FormatTok = Line->First; FormatTok;
2937 FormatTok = FormatTok->Next) {
2938 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
2939 (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
2940 FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
2941 tok::l_brace))) ||
2942 (FormatTok->Tok.isAnyIdentifier() &&
2943 std::binary_search(std::begin(FoundationIdentifiers),
2944 std::end(FoundationIdentifiers),
2945 FormatTok->TokenText)) ||
2946 FormatTok->is(TT_ObjCStringLiteral) ||
2947 FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,
2948 Keywords.kw_NS_ERROR_ENUM,
2949 Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,
2950 TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,
2951 TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,
2952 TT_ObjCProperty)) {
2953 LLVM_DEBUG(llvm::dbgs()
2954 << "Detected ObjC at location "
2955 << FormatTok->Tok.getLocation().printToString(
2956 SourceManager)
2957 << " token: " << FormatTok->TokenText << " token type: "
2958 << getTokenTypeName(FormatTok->getType()) << "\n");
2959 return true;
2960 }
2961 }
2962 if (guessIsObjC(SourceManager, Line->Children, Keywords))
2963 return true;
2964 }
2965 return false;
2966 }
2967
2968 bool IsObjC;
2969};
2970
2971struct IncludeDirective {
2972 StringRef Filename;
2973 StringRef Text;
2974 unsigned Offset;
2977};
2978
2979struct JavaImportDirective {
2980 StringRef Identifier;
2981 StringRef Text;
2982 unsigned Offset;
2983 SmallVector<StringRef> AssociatedCommentLines;
2985};
2986
2987} // end anonymous namespace
2988
2989// Determines whether 'Ranges' intersects with ('Start', 'End').
2990static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start,
2991 unsigned End) {
2992 for (const auto &Range : Ranges) {
2993 if (Range.getOffset() < End &&
2994 Range.getOffset() + Range.getLength() > Start) {
2995 return true;
2996 }
2997 }
2998 return false;
2999}
3000
3001// Returns a pair (Index, OffsetToEOL) describing the position of the cursor
3002// before sorting/deduplicating. Index is the index of the include under the
3003// cursor in the original set of includes. If this include has duplicates, it is
3004// the index of the first of the duplicates as the others are going to be
3005// removed. OffsetToEOL describes the cursor's position relative to the end of
3006// its current line.
3007// If `Cursor` is not on any #include, `Index` will be UINT_MAX.
3008static std::pair<unsigned, unsigned>
3010 const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) {
3011 unsigned CursorIndex = UINT_MAX;
3012 unsigned OffsetToEOL = 0;
3013 for (int i = 0, e = Includes.size(); i != e; ++i) {
3014 unsigned Start = Includes[Indices[i]].Offset;
3015 unsigned End = Start + Includes[Indices[i]].Text.size();
3016 if (!(Cursor >= Start && Cursor < End))
3017 continue;
3018 CursorIndex = Indices[i];
3019 OffsetToEOL = End - Cursor;
3020 // Put the cursor on the only remaining #include among the duplicate
3021 // #includes.
3022 while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text)
3023 CursorIndex = i;
3024 break;
3025 }
3026 return std::make_pair(CursorIndex, OffsetToEOL);
3027}
3028
3029// Replace all "\r\n" with "\n".
3030std::string replaceCRLF(const std::string &Code) {
3031 std::string NewCode;
3032 size_t Pos = 0, LastPos = 0;
3033
3034 do {
3035 Pos = Code.find("\r\n", LastPos);
3036 if (Pos == LastPos) {
3037 ++LastPos;
3038 continue;
3039 }
3040 if (Pos == std::string::npos) {
3041 NewCode += Code.substr(LastPos);
3042 break;
3043 }
3044 NewCode += Code.substr(LastPos, Pos - LastPos) + "\n";
3045 LastPos = Pos + 2;
3046 } while (Pos != std::string::npos);
3047
3048 return NewCode;
3049}
3050
3051// Sorts and deduplicate a block of includes given by 'Includes' alphabetically
3052// adding the necessary replacement to 'Replaces'. 'Includes' must be in strict
3053// source order.
3054// #include directives with the same text will be deduplicated, and only the
3055// first #include in the duplicate #includes remains. If the `Cursor` is
3056// provided and put on a deleted #include, it will be moved to the remaining
3057// #include in the duplicate #includes.
3058static void sortCppIncludes(const FormatStyle &Style,
3059 const SmallVectorImpl<IncludeDirective> &Includes,
3060 ArrayRef<tooling::Range> Ranges, StringRef FileName,
3061 StringRef Code, tooling::Replacements &Replaces,
3062 unsigned *Cursor) {
3064 const unsigned IncludesBeginOffset = Includes.front().Offset;
3065 const unsigned IncludesEndOffset =
3066 Includes.back().Offset + Includes.back().Text.size();
3067 const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
3068 if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
3069 return;
3071 llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size()));
3072
3074 llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
3075 const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
3076 const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
3077 return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
3078 Includes[LHSI].Filename) <
3079 std::tie(Includes[RHSI].Priority, RHSFilenameLower,
3080 Includes[RHSI].Filename);
3081 });
3082 } else {
3083 llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
3084 return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
3085 std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
3086 });
3087 }
3088
3089 // The index of the include on which the cursor will be put after
3090 // sorting/deduplicating.
3091 unsigned CursorIndex;
3092 // The offset from cursor to the end of line.
3093 unsigned CursorToEOLOffset;
3094 if (Cursor) {
3095 std::tie(CursorIndex, CursorToEOLOffset) =
3096 FindCursorIndex(Includes, Indices, *Cursor);
3097 }
3098
3099 // Deduplicate #includes.
3100 Indices.erase(std::unique(Indices.begin(), Indices.end(),
3101 [&](unsigned LHSI, unsigned RHSI) {
3102 return Includes[LHSI].Text.trim() ==
3103 Includes[RHSI].Text.trim();
3104 }),
3105 Indices.end());
3106
3107 int CurrentCategory = Includes.front().Category;
3108
3109 // If the #includes are out of order, we generate a single replacement fixing
3110 // the entire block. Otherwise, no replacement is generated.
3111 // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not
3112 // enough as additional newlines might be added or removed across #include
3113 // blocks. This we handle below by generating the updated #include blocks and
3114 // comparing it to the original.
3115 if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) &&
3117 return;
3118 }
3119
3120 std::string result;
3121 for (unsigned Index : Indices) {
3122 if (!result.empty()) {
3123 result += "\n";
3124 if (Style.IncludeStyle.IncludeBlocks ==
3126 CurrentCategory != Includes[Index].Category) {
3127 result += "\n";
3128 }
3129 }
3130 result += Includes[Index].Text;
3131 if (Cursor && CursorIndex == Index)
3132 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
3133 CurrentCategory = Includes[Index].Category;
3134 }
3135
3136 if (Cursor && *Cursor >= IncludesEndOffset)
3137 *Cursor += result.size() - IncludesBlockSize;
3138
3139 // If the #includes are out of order, we generate a single replacement fixing
3140 // the entire range of blocks. Otherwise, no replacement is generated.
3141 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
3142 IncludesBeginOffset, IncludesBlockSize)))) {
3143 return;
3144 }
3145
3146 auto Err = Replaces.add(tooling::Replacement(
3147 FileName, Includes.front().Offset, IncludesBlockSize, result));
3148 // FIXME: better error handling. For now, just skip the replacement for the
3149 // release version.
3150 if (Err) {
3151 llvm::errs() << llvm::toString(std::move(Err)) << "\n";
3152 assert(false);
3153 }
3154}
3155
3158 StringRef FileName,
3159 tooling::Replacements &Replaces,
3160 unsigned *Cursor) {
3161 unsigned Prev = llvm::StringSwitch<size_t>(Code)
3162 .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM
3163 .Default(0);
3164 unsigned SearchFrom = 0;
3166 SmallVector<IncludeDirective, 16> IncludesInBlock;
3167
3168 // In compiled files, consider the first #include to be the main #include of
3169 // the file if it is not a system #include. This ensures that the header
3170 // doesn't have hidden dependencies
3171 // (http://llvm.org/docs/CodingStandards.html#include-style).
3172 //
3173 // FIXME: Do some validation, e.g. edit distance of the base name, to fix
3174 // cases where the first #include is unlikely to be the main header.
3176 bool FirstIncludeBlock = true;
3177 bool MainIncludeFound = false;
3178 bool FormattingOff = false;
3179
3180 // '[' must be the first and '-' the last character inside [...].
3181 llvm::Regex RawStringRegex(
3182 "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\(");
3183 SmallVector<StringRef, 2> RawStringMatches;
3184 std::string RawStringTermination = ")\"";
3185
3186 for (;;) {
3187 auto Pos = Code.find('\n', SearchFrom);
3188 StringRef Line =
3189 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3190
3191 StringRef Trimmed = Line.trim();
3192
3193 // #includes inside raw string literals need to be ignored.
3194 // or we will sort the contents of the string.
3195 // Skip past until we think we are at the rawstring literal close.
3196 if (RawStringRegex.match(Trimmed, &RawStringMatches)) {
3197 std::string CharSequence = RawStringMatches[1].str();
3198 RawStringTermination = ")" + CharSequence + "\"";
3199 FormattingOff = true;
3200 }
3201
3202 if (Trimmed.contains(RawStringTermination))
3203 FormattingOff = false;
3204
3205 if (isClangFormatOff(Trimmed))
3206 FormattingOff = true;
3207 else if (isClangFormatOn(Trimmed))
3208 FormattingOff = false;
3209
3210 const bool EmptyLineSkipped =
3211 Trimmed.empty() &&
3215
3216 bool MergeWithNextLine = Trimmed.ends_with("\\");
3217 if (!FormattingOff && !MergeWithNextLine) {
3219 StringRef IncludeName = Matches[2];
3220 if (Line.contains("/*") && !Line.contains("*/")) {
3221 // #include with a start of a block comment, but without the end.
3222 // Need to keep all the lines until the end of the comment together.
3223 // FIXME: This is somehow simplified check that probably does not work
3224 // correctly if there are multiple comments on a line.
3225 Pos = Code.find("*/", SearchFrom);
3226 Line = Code.substr(
3227 Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev);
3228 }
3229 int Category = Categories.getIncludePriority(
3230 IncludeName,
3231 /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock);
3232 int Priority = Categories.getSortIncludePriority(
3233 IncludeName, !MainIncludeFound && FirstIncludeBlock);
3234 if (Category == 0)
3235 MainIncludeFound = true;
3236 IncludesInBlock.push_back(
3237 {IncludeName, Line, Prev, Category, Priority});
3238 } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
3239 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code,
3240 Replaces, Cursor);
3241 IncludesInBlock.clear();
3242 if (Trimmed.starts_with("#pragma hdrstop")) // Precompiled headers.
3243 FirstIncludeBlock = true;
3244 else
3245 FirstIncludeBlock = false;
3246 }
3247 }
3248 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3249 break;
3250
3251 if (!MergeWithNextLine)
3252 Prev = Pos + 1;
3253 SearchFrom = Pos + 1;
3254 }
3255 if (!IncludesInBlock.empty()) {
3256 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces,
3257 Cursor);
3258 }
3259 return Replaces;
3260}
3261
3262// Returns group number to use as a first order sort on imports. Gives UINT_MAX
3263// if the import does not match any given groups.
3264static unsigned findJavaImportGroup(const FormatStyle &Style,
3265 StringRef ImportIdentifier) {
3266 unsigned LongestMatchIndex = UINT_MAX;
3267 unsigned LongestMatchLength = 0;
3268 for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) {
3269 const std::string &GroupPrefix = Style.JavaImportGroups[I];
3270 if (ImportIdentifier.starts_with(GroupPrefix) &&
3271 GroupPrefix.length() > LongestMatchLength) {
3272 LongestMatchIndex = I;
3273 LongestMatchLength = GroupPrefix.length();
3274 }
3275 }
3276 return LongestMatchIndex;
3277}
3278
3279// Sorts and deduplicates a block of includes given by 'Imports' based on
3280// JavaImportGroups, then adding the necessary replacement to 'Replaces'.
3281// Import declarations with the same text will be deduplicated. Between each
3282// import group, a newline is inserted, and within each import group, a
3283// lexicographic sort based on ASCII value is performed.
3284static void sortJavaImports(const FormatStyle &Style,
3286 ArrayRef<tooling::Range> Ranges, StringRef FileName,
3287 StringRef Code, tooling::Replacements &Replaces) {
3288 unsigned ImportsBeginOffset = Imports.front().Offset;
3289 unsigned ImportsEndOffset =
3290 Imports.back().Offset + Imports.back().Text.size();
3291 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;
3292 if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))
3293 return;
3294
3296 llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size()));
3298 JavaImportGroups.reserve(Imports.size());
3299 for (const JavaImportDirective &Import : Imports)
3300 JavaImportGroups.push_back(findJavaImportGroup(Style, Import.Identifier));
3301
3302 bool StaticImportAfterNormalImport =
3304 llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
3305 // Negating IsStatic to push static imports above non-static imports.
3306 return std::make_tuple(!Imports[LHSI].IsStatic ^
3307 StaticImportAfterNormalImport,
3308 JavaImportGroups[LHSI], Imports[LHSI].Identifier) <
3309 std::make_tuple(!Imports[RHSI].IsStatic ^
3310 StaticImportAfterNormalImport,
3311 JavaImportGroups[RHSI], Imports[RHSI].Identifier);
3312 });
3313
3314 // Deduplicate imports.
3315 Indices.erase(std::unique(Indices.begin(), Indices.end(),
3316 [&](unsigned LHSI, unsigned RHSI) {
3317 return Imports[LHSI].Text == Imports[RHSI].Text;
3318 }),
3319 Indices.end());
3320
3321 bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
3322 unsigned CurrentImportGroup = JavaImportGroups[Indices.front()];
3323
3324 std::string result;
3325 for (unsigned Index : Indices) {
3326 if (!result.empty()) {
3327 result += "\n";
3328 if (CurrentIsStatic != Imports[Index].IsStatic ||
3329 CurrentImportGroup != JavaImportGroups[Index]) {
3330 result += "\n";
3331 }
3332 }
3333 for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) {
3334 result += CommentLine;
3335 result += "\n";
3336 }
3337 result += Imports[Index].Text;
3338 CurrentIsStatic = Imports[Index].IsStatic;
3339 CurrentImportGroup = JavaImportGroups[Index];
3340 }
3341
3342 // If the imports are out of order, we generate a single replacement fixing
3343 // the entire block. Otherwise, no replacement is generated.
3344 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
3345 Imports.front().Offset, ImportsBlockSize)))) {
3346 return;
3347 }
3348
3349 auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset,
3350 ImportsBlockSize, result));
3351 // FIXME: better error handling. For now, just skip the replacement for the
3352 // release version.
3353 if (Err) {
3354 llvm::errs() << llvm::toString(std::move(Err)) << "\n";
3355 assert(false);
3356 }
3357}
3358
3359namespace {
3360
3361const char JavaImportRegexPattern[] =
3362 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;";
3363
3364} // anonymous namespace
3365
3368 StringRef FileName,
3369 tooling::Replacements &Replaces) {
3370 unsigned Prev = 0;
3371 unsigned SearchFrom = 0;
3372 llvm::Regex ImportRegex(JavaImportRegexPattern);
3376
3377 bool FormattingOff = false;
3378
3379 for (;;) {
3380 auto Pos = Code.find('\n', SearchFrom);
3381 StringRef Line =
3382 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3383
3384 StringRef Trimmed = Line.trim();
3385 if (isClangFormatOff(Trimmed))
3386 FormattingOff = true;
3387 else if (isClangFormatOn(Trimmed))
3388 FormattingOff = false;
3389
3390 if (ImportRegex.match(Line, &Matches)) {
3391 if (FormattingOff) {
3392 // If at least one import line has formatting turned off, turn off
3393 // formatting entirely.
3394 return Replaces;
3395 }
3396 StringRef Static = Matches[1];
3397 StringRef Identifier = Matches[2];
3398 bool IsStatic = false;
3399 if (Static.contains("static"))
3400 IsStatic = true;
3401 ImportsInBlock.push_back(
3403 AssociatedCommentLines.clear();
3404 } else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) {
3405 // Associating comments within the imports with the nearest import below
3406 AssociatedCommentLines.push_back(Line);
3407 }
3408 Prev = Pos + 1;
3409 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3410 break;
3411 SearchFrom = Pos + 1;
3412 }
3413 if (!ImportsInBlock.empty())
3414 sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces);
3415 return Replaces;
3416}
3417
3418bool isMpegTS(StringRef Code) {
3419 // MPEG transport streams use the ".ts" file extension. clang-format should
3420 // not attempt to format those. MPEG TS' frame format starts with 0x47 every
3421 // 189 bytes - detect that and return.
3422 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
3423}
3424
3425bool isLikelyXml(StringRef Code) { return Code.ltrim().starts_with("<"); }
3426
3429 StringRef FileName, unsigned *Cursor) {
3430 tooling::Replacements Replaces;
3431 if (!Style.SortIncludes || Style.DisableFormat)
3432 return Replaces;
3433 if (isLikelyXml(Code))
3434 return Replaces;
3436 isMpegTS(Code)) {
3437 return Replaces;
3438 }
3440 return sortJavaScriptImports(Style, Code, Ranges, FileName);
3442 return sortJavaImports(Style, Code, Ranges, FileName, Replaces);
3443 sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor);
3444 return Replaces;
3445}
3446
3447template <typename T>
3449processReplacements(T ProcessFunc, StringRef Code,
3450 const tooling::Replacements &Replaces,
3451 const FormatStyle &Style) {
3452 if (Replaces.empty())
3453 return tooling::Replacements();
3454
3455 auto NewCode = applyAllReplacements(Code, Replaces);
3456 if (!NewCode)
3457 return NewCode.takeError();
3458 std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();
3459 StringRef FileName = Replaces.begin()->getFilePath();
3460
3461 tooling::Replacements FormatReplaces =
3462 ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
3463
3464 return Replaces.merge(FormatReplaces);
3465}
3466
3468formatReplacements(StringRef Code, const tooling::Replacements &Replaces,
3469 const FormatStyle &Style) {
3470 // We need to use lambda function here since there are two versions of
3471 // `sortIncludes`.
3472 auto SortIncludes = [](const FormatStyle &Style, StringRef Code,
3473 std::vector<tooling::Range> Ranges,
3474 StringRef FileName) -> tooling::Replacements {
3475 return sortIncludes(Style, Code, Ranges, FileName);
3476 };
3477 auto SortedReplaces =
3478 processReplacements(SortIncludes, Code, Replaces, Style);
3479 if (!SortedReplaces)
3480 return SortedReplaces.takeError();
3481
3482 // We need to use lambda function here since there are two versions of
3483 // `reformat`.
3484 auto Reformat = [](const FormatStyle &Style, StringRef Code,
3485 std::vector<tooling::Range> Ranges,
3486 StringRef FileName) -> tooling::Replacements {
3487 return reformat(Style, Code, Ranges, FileName);
3488 };
3489 return processReplacements(Reformat, Code, *SortedReplaces, Style);
3490}
3491
3492namespace {
3493
3494inline bool isHeaderInsertion(const tooling::Replacement &Replace) {
3495 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 &&
3497 Replace.getReplacementText());
3498}
3499
3500inline bool isHeaderDeletion(const tooling::Replacement &Replace) {
3501 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1;
3502}
3503
3504// FIXME: insert empty lines between newly created blocks.
3505tooling::Replacements
3506fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
3507 const FormatStyle &Style) {
3508 if (!Style.isCpp())
3509 return Replaces;
3510
3511 tooling::Replacements HeaderInsertions;
3512 std::set<llvm::StringRef> HeadersToDelete;
3513 tooling::Replacements Result;
3514 for (const auto &R : Replaces) {
3515 if (isHeaderInsertion(R)) {
3516 // Replacements from \p Replaces must be conflict-free already, so we can
3517 // simply consume the error.
3518 llvm::consumeError(HeaderInsertions.add(R));
3519 } else if (isHeaderDeletion(R)) {
3520 HeadersToDelete.insert(R.getReplacementText());
3521 } else if (R.getOffset() == UINT_MAX) {
3522 llvm::errs() << "Insertions other than header #include insertion are "
3523 "not supported! "
3524 << R.getReplacementText() << "\n";
3525 } else {
3526 llvm::consumeError(Result.add(R));
3527 }
3528 }
3529 if (HeaderInsertions.empty() && HeadersToDelete.empty())
3530 return Replaces;
3531
3532 StringRef FileName = Replaces.begin()->getFilePath();
3533 tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle);
3534
3535 for (const auto &Header : HeadersToDelete) {
3536 tooling::Replacements Replaces =
3537 Includes.remove(Header.trim("\"<>"), Header.starts_with("<"));
3538 for (const auto &R : Replaces) {
3539 auto Err = Result.add(R);
3540 if (Err) {
3541 // Ignore the deletion on conflict.
3542 llvm::errs() << "Failed to add header deletion replacement for "
3543 << Header << ": " << llvm::toString(std::move(Err))
3544 << "\n";
3545 }
3546 }
3547 }
3548
3550 for (const auto &R : HeaderInsertions) {
3551 auto IncludeDirective = R.getReplacementText();
3552 bool Matched =
3553 tooling::HeaderIncludes::IncludeRegex.match(IncludeDirective, &Matches);
3554 assert(Matched && "Header insertion replacement must have replacement text "
3555 "'#include ...'");
3556 (void)Matched;
3557 auto IncludeName = Matches[2];
3558 auto Replace =
3559 Includes.insert(IncludeName.trim("\"<>"), IncludeName.starts_with("<"),
3561 if (Replace) {
3562 auto Err = Result.add(*Replace);
3563 if (Err) {
3564 llvm::consumeError(std::move(Err));
3565 unsigned NewOffset =
3566 Result.getShiftedCodePosition(Replace->getOffset());
3567 auto Shifted = tooling::Replacement(FileName, NewOffset, 0,
3568 Replace->getReplacementText());
3569 Result = Result.merge(tooling::Replacements(Shifted));
3570 }
3571 }
3572 }
3573 return Result;
3574}
3575
3576} // anonymous namespace
3577
3579cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
3580 const FormatStyle &Style) {
3581 // We need to use lambda function here since there are two versions of
3582 // `cleanup`.
3583 auto Cleanup = [](const FormatStyle &Style, StringRef Code,
3585 StringRef FileName) -> tooling::Replacements {
3586 return cleanup(Style, Code, Ranges, FileName);
3587 };
3588 // Make header insertion replacements insert new headers into correct blocks.
3589 tooling::Replacements NewReplaces =
3590 fixCppIncludeInsertions(Code, Replaces, Style);
3591 return cantFail(processReplacements(Cleanup, Code, NewReplaces, Style));
3592}
3593
3594namespace internal {
3595std::pair<tooling::Replacements, unsigned>
3596reformat(const FormatStyle &Style, StringRef Code,
3597 ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,
3598 unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,
3599 FormattingAttemptStatus *Status) {
3600 FormatStyle Expanded = Style;
3604 Expanded.InsertBraces = false;
3605 Expanded.RemoveBracesLLVM = false;
3606 Expanded.RemoveParentheses = FormatStyle::RPS_Leave;
3607 Expanded.RemoveSemicolon = false;
3608 switch (Expanded.RequiresClausePosition) {
3609 case FormatStyle::RCPS_SingleLine:
3610 case FormatStyle::RCPS_WithPreceding:
3611 Expanded.IndentRequiresClause = false;
3612 break;
3613 default:
3614 break;
3615 }
3616
3617 if (Expanded.DisableFormat)
3618 return {tooling::Replacements(), 0};
3619 if (isLikelyXml(Code))
3620 return {tooling::Replacements(), 0};
3621 if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code))
3622 return {tooling::Replacements(), 0};
3623
3624 // JSON only needs the formatting passing.
3625 if (Style.isJson()) {
3626 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
3627 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
3628 NextStartColumn, LastStartColumn);
3629 if (!Env)
3630 return {};
3631 // Perform the actual formatting pass.
3632 tooling::Replacements Replaces =
3633 Formatter(*Env, Style, Status).process().first;
3634 // add a replacement to remove the "x = " from the result.
3635 Replaces = Replaces.merge(
3637 // apply the reformatting changes and the removal of "x = ".
3638 if (applyAllReplacements(Code, Replaces))
3639 return {Replaces, 0};
3640 return {tooling::Replacements(), 0};
3641 }
3642
3643 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
3644 NextStartColumn, LastStartColumn);
3645 if (!Env)
3646 return {};
3647
3648 typedef std::function<std::pair<tooling::Replacements, unsigned>(
3649 const Environment &)>
3651
3653
3654 Passes.emplace_back([&](const Environment &Env) {
3655 return IntegerLiteralSeparatorFixer().process(Env, Expanded);
3656 });
3657
3658 if (Style.isCpp()) {
3659 if (Style.QualifierAlignment != FormatStyle::QAS_Leave)
3660 addQualifierAlignmentFixerPasses(Expanded, Passes);
3661
3662 if (Style.RemoveParentheses != FormatStyle::RPS_Leave) {
3663 FormatStyle S = Expanded;
3664 S.RemoveParentheses = Style.RemoveParentheses;
3665 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
3666 return ParensRemover(Env, S).process(/*SkipAnnotation=*/true);
3667 });
3668 }
3669
3670 if (Style.InsertBraces) {
3671 FormatStyle S = Expanded;
3672 S.InsertBraces = true;
3673 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
3674 return BracesInserter(Env, S).process(/*SkipAnnotation=*/true);
3675 });
3676 }
3677
3678 if (Style.RemoveBracesLLVM) {
3679 FormatStyle S = Expanded;
3680 S.RemoveBracesLLVM = true;
3681 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
3682 return BracesRemover(Env, S).process(/*SkipAnnotation=*/true);
3683 });
3684 }
3685
3686 if (Style.RemoveSemicolon) {
3687 FormatStyle S = Expanded;
3688 S.RemoveSemicolon = true;
3689 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
3690 return SemiRemover(Env, S).process();
3691 });
3692 }
3693
3694 if (Style.FixNamespaceComments) {
3695 Passes.emplace_back([&](const Environment &Env) {
3696 return NamespaceEndCommentsFixer(Env, Expanded).process();
3697 });
3698 }
3699
3700 if (Style.SortUsingDeclarations != FormatStyle::SUD_Never) {
3701 Passes.emplace_back([&](const Environment &Env) {
3702 return UsingDeclarationsSorter(Env, Expanded).process();
3703 });
3704 }
3705 }
3706
3707 if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) {
3708 Passes.emplace_back([&](const Environment &Env) {
3709 return DefinitionBlockSeparator(Env, Expanded).process();
3710 });
3711 }
3712
3713 if (Style.Language == FormatStyle::LK_ObjC &&
3714 !Style.ObjCPropertyAttributeOrder.empty()) {
3715 Passes.emplace_back([&](const Environment &Env) {
3716 return ObjCPropertyAttributeOrderFixer(Env, Expanded).process();
3717 });
3718 }
3719
3720 if (Style.isJavaScript() &&
3721 Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) {
3722 Passes.emplace_back([&](const Environment &Env) {
3723 return JavaScriptRequoter(Env, Expanded).process(/*SkipAnnotation=*/true);
3724 });
3725 }
3726
3727 Passes.emplace_back([&](const Environment &Env) {
3728 return Formatter(Env, Expanded, Status).process();
3729 });
3730
3731 if (Style.isJavaScript() &&
3732 Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) {
3733 Passes.emplace_back([&](const Environment &Env) {
3734 return TrailingCommaInserter(Env, Expanded).process();
3735 });
3736 }
3737
3738 std::optional<std::string> CurrentCode;
3740 unsigned Penalty = 0;
3741 for (size_t I = 0, E = Passes.size(); I < E; ++I) {
3742 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
3743 auto NewCode = applyAllReplacements(
3744 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
3745 if (NewCode) {
3746 Fixes = Fixes.merge(PassFixes.first);
3747 Penalty += PassFixes.second;
3748 if (I + 1 < E) {
3749 CurrentCode = std::move(*NewCode);
3750 Env = Environment::make(
3751 *CurrentCode, FileName,
3752 tooling::calculateRangesAfterReplacements(Fixes, Ranges),
3753 FirstStartColumn, NextStartColumn, LastStartColumn);
3754 if (!Env)
3755 return {};
3756 }
3757 }
3758 }
3759
3760 if (Style.QualifierAlignment != FormatStyle::QAS_Leave) {
3761 // Don't make replacements that replace nothing. QualifierAlignment can
3762 // produce them if one of its early passes changes e.g. `const volatile` to
3763 // `volatile const` and then a later pass changes it back again.
3764 tooling::Replacements NonNoOpFixes;
3765 for (const tooling::Replacement &Fix : Fixes) {
3766 StringRef OriginalCode = Code.substr(Fix.getOffset(), Fix.getLength());
3767 if (!OriginalCode.equals(Fix.getReplacementText())) {
3768 auto Err = NonNoOpFixes.add(Fix);
3769 if (Err) {
3770 llvm::errs() << "Error adding replacements : "
3771 << llvm::toString(std::move(Err)) << "\n";
3772 }
3773 }
3774 }
3775 Fixes = std::move(NonNoOpFixes);
3776 }
3777
3778 return {Fixes, Penalty};
3779}
3780} // namespace internal
3781
3782tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
3784 StringRef FileName,
3785 FormattingAttemptStatus *Status) {
3786 return internal::reformat(Style, Code, Ranges,
3787 /*FirstStartColumn=*/0,
3788 /*NextStartColumn=*/0,
3789 /*LastStartColumn=*/0, FileName, Status)
3790 .first;
3791}
3792
3793tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
3795 StringRef FileName) {
3796 // cleanups only apply to C++ (they mostly concern ctor commas etc.)
3797 if (Style.Language != FormatStyle::LK_Cpp)
3798 return tooling::Replacements();
3799 auto Env = Environment::make(Code, FileName, Ranges);
3800 if (!Env)
3801 return {};
3802 return Cleaner(*Env, Style).process().first;
3803}
3804
3805tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
3807 StringRef FileName, bool *IncompleteFormat) {
3809 auto Result = reformat(Style, Code, Ranges, FileName, &Status);
3810 if (!Status.FormatComplete)
3811 *IncompleteFormat = true;
3812 return Result;
3813}
3814
3816 StringRef Code,
3818 StringRef FileName) {
3819 auto Env = Environment::make(Code, FileName, Ranges);
3820 if (!Env)
3821 return {};
3822 return NamespaceEndCommentsFixer(*Env, Style).process().first;
3823}
3824
3826 StringRef Code,
3828 StringRef FileName) {
3829 auto Env = Environment::make(Code, FileName, Ranges);
3830 if (!Env)
3831 return {};
3832 return UsingDeclarationsSorter(*Env, Style).process().first;
3833}
3834
3836 LangOptions LangOpts;
3837
3838 FormatStyle::LanguageStandard LexingStd = Style.Standard;
3839 if (LexingStd == FormatStyle::LS_Auto)
3840 LexingStd = FormatStyle::LS_Latest;
3841 if (LexingStd == FormatStyle::LS_Latest)
3842 LexingStd = FormatStyle::LS_Cpp20;
3843 LangOpts.CPlusPlus = 1;
3844 LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11;
3845 LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14;
3846 LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17;
3847 LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20;
3848 LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20;
3849 // Turning on digraphs in standards before C++0x is error-prone, because e.g.
3850 // the sequence "<::" will be unconditionally treated as "[:".
3851 // Cf. Lexer::LexTokenInternal.
3852 LangOpts.Digraphs = LexingStd >= FormatStyle::LS_Cpp11;
3853
3854 LangOpts.LineComment = 1;
3855 bool AlternativeOperators = Style.isCpp();
3856 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
3857 LangOpts.Bool = 1;
3858 LangOpts.ObjC = 1;
3859 LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally.
3860 LangOpts.DeclSpecKeyword = 1; // To get __declspec.
3861 LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict.
3862 return LangOpts;
3863}
3864
3866 "Set coding style. <string> can be:\n"
3867 "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"
3868 " Mozilla, WebKit.\n"
3869 "2. 'file' to load style configuration from a\n"
3870 " .clang-format file in one of the parent directories\n"
3871 " of the source file (for stdin, see --assume-filename).\n"
3872 " If no .clang-format file is found, falls back to\n"
3873 " --fallback-style.\n"
3874 " --style=file is the default.\n"
3875 "3. 'file:<format_file_path>' to explicitly specify\n"
3876 " the configuration file.\n"
3877 "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n"
3878 " --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
3879
3881 if (FileName.ends_with(".java"))
3882 return FormatStyle::LK_Java;
3883 if (FileName.ends_with_insensitive(".js") ||
3884 FileName.ends_with_insensitive(".mjs") ||
3885 FileName.ends_with_insensitive(".ts")) {
3886 return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript.
3887 }
3888 if (FileName.ends_with(".m") || FileName.ends_with(".mm"))
3889 return FormatStyle::LK_ObjC;
3890 if (FileName.ends_with_insensitive(".proto") ||
3891 FileName.ends_with_insensitive(".protodevel")) {
3892 return FormatStyle::LK_Proto;
3893 }
3894 // txtpb is the canonical extension, and textproto is the legacy canonical
3895 // extension
3896 // https://protobuf.dev/reference/protobuf/textformat-spec/#text-format-files
3897 if (FileName.ends_with_insensitive(".txtpb") ||
3898 FileName.ends_with_insensitive(".textpb") ||
3899 FileName.ends_with_insensitive(".pb.txt") ||
3900 FileName.ends_with_insensitive(".textproto") ||
3901 FileName.ends_with_insensitive(".asciipb")) {
3903 }
3904 if (FileName.ends_with_insensitive(".td"))
3906 if (FileName.ends_with_insensitive(".cs"))
3908 if (FileName.ends_with_insensitive(".json"))
3909 return FormatStyle::LK_Json;
3910 if (FileName.ends_with_insensitive(".sv") ||
3911 FileName.ends_with_insensitive(".svh") ||
3912 FileName.ends_with_insensitive(".v") ||
3913 FileName.ends_with_insensitive(".vh")) {
3915 }
3916 return FormatStyle::LK_Cpp;
3917}
3918
3920 const auto GuessedLanguage = getLanguageByFileName(FileName);
3921 if (GuessedLanguage == FormatStyle::LK_Cpp) {
3922 auto Extension = llvm::sys::path::extension(FileName);
3923 // If there's no file extension (or it's .h), we need to check the contents
3924 // of the code to see if it contains Objective-C.
3925 if (!Code.empty() && (Extension.empty() || Extension == ".h")) {
3926 auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName;
3927 Environment Env(Code, NonEmptyFileName, /*Ranges=*/{});
3928 ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle());
3929 Guesser.process();
3930 if (Guesser.isObjC())
3931 return FormatStyle::LK_ObjC;
3932 }
3933 }
3934 return GuessedLanguage;
3935}
3936
3937// Update StyleOptionHelpDescription above when changing this.
3938const char *DefaultFormatStyle = "file";
3939
3940const char *DefaultFallbackStyle = "LLVM";
3941
3942llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
3943loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS,
3944 FormatStyle *Style, bool AllowUnknownOptions) {
3945 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
3946 FS->getBufferForFile(ConfigFile.str());
3947 if (auto EC = Text.getError())
3948 return EC;
3949 if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions))
3950 return EC;
3951 return Text;
3952}
3953
3954llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
3955 StringRef FallbackStyleName,
3956 StringRef Code, llvm::vfs::FileSystem *FS,
3957 bool AllowUnknownOptions) {
3959 FormatStyle FallbackStyle = getNoStyle();
3960 if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))
3961 return make_string_error("Invalid fallback style: " + FallbackStyleName);
3962
3964 ChildFormatTextToApply;
3965
3966 if (StyleName.starts_with("{")) {
3967 // Parse YAML/JSON style from the command line.
3968 StringRef Source = "<command-line>";
3969 if (std::error_code ec =
3970 parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style,
3971 AllowUnknownOptions)) {
3972 return make_string_error("Error parsing -style: " + ec.message());
3973 }
3974
3975 if (!Style.InheritsParentConfig)
3976 return Style;
3977
3978 ChildFormatTextToApply.emplace_back(
3979 llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false));
3980 }
3981
3982 if (!FS)
3983 FS = llvm::vfs::getRealFileSystem().get();
3984 assert(FS);
3985
3986 // User provided clang-format file using -style=file:path/to/format/file.
3987 if (!Style.InheritsParentConfig &&
3988 StyleName.starts_with_insensitive("file:")) {
3989 auto ConfigFile = StyleName.substr(5);
3990 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
3991 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions);
3992 if (auto EC = Text.getError()) {
3993 return make_string_error("Error reading " + ConfigFile + ": " +
3994 EC.message());
3995 }
3996
3997 LLVM_DEBUG(llvm::dbgs()
3998 << "Using configuration file " << ConfigFile << "\n");
3999
4000 if (!Style.InheritsParentConfig)
4001 return Style;
4002
4003 // Search for parent configs starting from the parent directory of
4004 // ConfigFile.
4005 FileName = ConfigFile;
4006 ChildFormatTextToApply.emplace_back(std::move(*Text));
4007 }
4008
4009 // If the style inherits the parent configuration it is a command line
4010 // configuration, which wants to inherit, so we have to skip the check of the
4011 // StyleName.
4012 if (!Style.InheritsParentConfig && !StyleName.equals_insensitive("file")) {
4013 if (!getPredefinedStyle(StyleName, Style.Language, &Style))
4014 return make_string_error("Invalid value for -style");
4015 if (!Style.InheritsParentConfig)
4016 return Style;
4017 }
4018
4020 if (std::error_code EC = FS->makeAbsolute(Path))
4021 return make_string_error(EC.message());
4022
4023 // Reset possible inheritance
4024 Style.InheritsParentConfig = false;
4025
4026 auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {};
4027
4028 auto applyChildFormatTexts = [&](FormatStyle *Style) {
4029 for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) {
4030 auto EC = parseConfiguration(*MemBuf, Style, AllowUnknownOptions,
4031 dropDiagnosticHandler);
4032 // It was already correctly parsed.
4033 assert(!EC);
4034 static_cast<void>(EC);
4035 }
4036 };
4037
4038 // Look for .clang-format/_clang-format file in the file's parent directories.
4039 llvm::SmallVector<std::string, 2> FilesToLookFor;
4040 FilesToLookFor.push_back(".clang-format");
4041 FilesToLookFor.push_back("_clang-format");
4042
4043 SmallString<128> UnsuitableConfigFiles;
4044 for (StringRef Directory = Path; !Directory.empty();
4045 Directory = llvm::sys::path::parent_path(Directory)) {
4046 auto Status = FS->status(Directory);
4047 if (!Status ||
4048 Status->getType() != llvm::sys::fs::file_type::directory_file) {
4049 continue;
4050 }
4051
4052 for (const auto &F : FilesToLookFor) {
4053 SmallString<128> ConfigFile(Directory);
4054
4055 llvm::sys::path::append(ConfigFile, F);
4056 LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
4057
4058 Status = FS->status(ConfigFile);
4059 if (!Status ||
4060 Status->getType() != llvm::sys::fs::file_type::regular_file) {
4061 continue;
4062 }
4063
4064 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
4065 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions);
4066 if (auto EC = Text.getError()) {
4067 if (EC != ParseError::Unsuitable) {
4068 return make_string_error("Error reading " + ConfigFile + ": " +
4069 EC.message());
4070 }
4071 if (!UnsuitableConfigFiles.empty())
4072 UnsuitableConfigFiles.append(", ");
4073 UnsuitableConfigFiles.append(ConfigFile);
4074 continue;
4075 }
4076
4077 LLVM_DEBUG(llvm::dbgs()
4078 << "Using configuration file " << ConfigFile << "\n");
4079
4080 if (!Style.InheritsParentConfig) {
4081 if (!ChildFormatTextToApply.empty()) {
4082 LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n");
4083 applyChildFormatTexts(&Style);
4084 }
4085 return Style;
4086 }
4087
4088 LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n");
4089
4090 // Reset inheritance of style
4091 Style.InheritsParentConfig = false;
4092
4093 ChildFormatTextToApply.emplace_back(std::move(*Text));
4094
4095 // Breaking out of the inner loop, since we don't want to parse
4096 // .clang-format AND _clang-format, if both exist. Then we continue the
4097 // outer loop (parent directories) in search for the parent
4098 // configuration.
4099 break;
4100 }
4101 }
4102
4103 if (!UnsuitableConfigFiles.empty()) {
4104 return make_string_error("Configuration file(s) do(es) not support " +
4105 getLanguageName(Style.Language) + ": " +
4106 UnsuitableConfigFiles);
4107 }
4108
4109 if (!ChildFormatTextToApply.empty()) {
4110 LLVM_DEBUG(llvm::dbgs()
4111 << "Applying child configurations on fallback style\n");
4112 applyChildFormatTexts(&FallbackStyle);
4113 }
4114
4115 return FallbackStyle;
4116}
4117
4118static bool isClangFormatOnOff(StringRef Comment, bool On) {
4119 if (Comment == (On ? "/* clang-format on */" : "/* clang-format off */"))
4120 return true;
4121
4122 static const char ClangFormatOn[] = "// clang-format on";
4123 static const char ClangFormatOff[] = "// clang-format off";
4124 const unsigned Size = (On ? sizeof ClangFormatOn : sizeof ClangFormatOff) - 1;
4125
4126 return Comment.starts_with(On ? ClangFormatOn : ClangFormatOff) &&
4127 (Comment.size() == Size || Comment[Size] == ':');
4128}
4129
4130bool isClangFormatOn(StringRef Comment) {
4131 return isClangFormatOnOff(Comment, /*On=*/true);
4132}
4133
4134bool isClangFormatOff(StringRef Comment) {
4135 return isClangFormatOnOff(Comment, /*On=*/false);
4136}
4137
4138} // namespace format
4139} // namespace clang
#define SM(sm)
Definition: Cuda.cpp:82
This file declares DefinitionBlockSeparator, a TokenAnalyzer that inserts or removes empty lines sepa...
StringRef Text
Definition: Format.cpp:2973
int Priority
Definition: Format.cpp:2976
SmallVector< StringRef > AssociatedCommentLines
Definition: Format.cpp:2983
int Category
Definition: Format.cpp:2975
bool IsStatic
Definition: Format.cpp:2984
StringRef Filename
Definition: Format.cpp:2972
StringRef Identifier
Definition: Format.cpp:2980
Various functions to configurably format source code.
const Environment & Env
Definition: HTMLLogger.cpp:148
This file declares IntegerLiteralSeparatorFixer that fixes C++ integer literal separators.
This file declares NamespaceEndCommentsFixer, a TokenAnalyzer that fixes namespace end comments.
This file declares ObjCPropertyAttributeOrderFixer, a TokenAnalyzer that adjusts the order of attribu...
This file declares QualifierAlignmentFixer, a TokenAnalyzer that enforces either east or west const d...
This file implements a sorter for JavaScript ES6 imports.
ContinuationIndenter * Indenter
Implements a combinatorial exploration of all the different linebreaks unwrapped lines can be formatt...
This file declares UsingDeclarationsSorter, a TokenAnalyzer that sorts consecutive using declarations...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:449
static std::unique_ptr< Environment > make(StringRef Code, StringRef FileName, ArrayRef< tooling::Range > Ranges, unsigned FirstStartColumn=0, unsigned NextStartColumn=0, unsigned LastStartColumn=0)
std::pair< tooling::Replacements, unsigned > process(const Environment &Env, const FormatStyle &Style)
static tok::TokenKind getTokenFromQualifier(const std::string &Qualifier)
const char * name() const noexcept override
Definition: Format.cpp:1241
std::string message(int EV) const override
Definition: Format.cpp:1245
std::pair< tooling::Replacements, unsigned > process(bool SkipAnnotation=false)
static const llvm::Regex IncludeRegex
This class manages priorities of C++ #include categories and calculates priorities for headers.
int getIncludePriority(StringRef IncludeName, bool CheckMainHeader) const
Returns the priority of the category which IncludeName belongs to.
int getSortIncludePriority(StringRef IncludeName, bool CheckMainHeader) const
A source range independent of the SourceManager.
Definition: Replacement.h:44
A text replacement.
Definition: Replacement.h:83
unsigned getLength() const
Definition: Replacement.h:122
StringRef getReplacementText() const
Definition: Replacement.h:123
unsigned getOffset() const
Definition: Replacement.h:121
Maintains a set of replacements that are conflict-free.
Definition: Replacement.h:212
std::vector< Range > getAffectedRanges() const
const_iterator begin() const
Definition: Replacement.h:281
llvm::Error add(const Replacement &R)
Adds a new replacement R to the current set of replacements.
Replacements merge(const Replacements &Replaces) const
Merges Replaces into the current replacements.
#define UINT_MAX
Definition: limits.h:60
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
bool isObjC(ID Id)
isObjC - Is this an "ObjC" input (Obj-C and Obj-C++ sources and headers).
Definition: Types.cpp:217
std::pair< tooling::Replacements, unsigned > reformat(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, unsigned FirstStartColumn, unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName, FormattingAttemptStatus *Status)
Reformats the given Ranges in the code fragment Code.
Definition: Format.cpp:3596
const char * StyleOptionHelpDescription
Description to be used for help text for a llvm::cl option for specifying format style.
Definition: Format.cpp:3865
void addQualifierAlignmentFixerPasses(const FormatStyle &Style, SmallVectorImpl< AnalyzerPass > &Passes)
static void expandPresetsSpaceBeforeParens(FormatStyle &Expanded)
Definition: Format.cpp:1367
const char * DefaultFallbackStyle
The suggested predefined style to use as the fallback style in getStyle.
Definition: Format.cpp:3940
static bool affectsRange(ArrayRef< tooling::Range > Ranges, unsigned Start, unsigned End)
Definition: Format.cpp:2990
const char * getTokenTypeName(TokenType Type)
Determines the name of a token type.
Definition: FormatToken.cpp:24
FormatStyle getWebKitStyle()
Returns a format style complying with Webkit's style guide: http://www.webkit.org/coding/coding-style...
Definition: Format.cpp:1843
bool isLikelyXml(StringRef Code)
Definition: Format.cpp:3425
static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName)
Definition: Format.cpp:3880
llvm::Error make_string_error(const llvm::Twine &Message)
Definition: Format.cpp:1236
static unsigned findJavaImportGroup(const FormatStyle &Style, StringRef ImportIdentifier)
Definition: Format.cpp:3264
llvm::Expected< tooling::Replacements > cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, const FormatStyle &Style)
Returns the replacements corresponding to applying Replaces and cleaning up the code after that on su...
Definition: Format.cpp:3579
std::string replaceCRLF(const std::string &Code)
Definition: Format.cpp:3030
static std::pair< unsigned, unsigned > FindCursorIndex(const SmallVectorImpl< IncludeDirective > &Includes, const SmallVectorImpl< unsigned > &Indices, unsigned Cursor)
Definition: Format.cpp:3009
std::error_code make_error_code(ParseError e)
Definition: Format.cpp:1232
FormatStyle getClangFormatStyle()
Definition: Format.cpp:1911
std::function< std::pair< tooling::Replacements, unsigned >(const Environment &)> AnalyzerPass
FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language=FormatStyle::LanguageKind::LK_Cpp)
Returns a format style complying with the LLVM coding standards: http://llvm.org/docs/CodingStandards...
Definition: Format.cpp:1399
static llvm::Expected< tooling::Replacements > processReplacements(T ProcessFunc, StringRef Code, const tooling::Replacements &Replaces, const FormatStyle &Style)
Definition: Format.cpp:3449
FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language)
Returns a format style complying with one of Google's style guides: http://google-styleguide....
Definition: Format.cpp:1615
std::string configurationAsText(const FormatStyle &Style)
Gets configuration in a YAML string.
Definition: Format.cpp:2059
FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language)
Returns a format style complying with Microsoft style guide: https://docs.microsoft....
Definition: Format.cpp:1882
std::error_code parseConfiguration(llvm::MemoryBufferRef Config, FormatStyle *Style, bool AllowUnknownOptions=false, llvm::SourceMgr::DiagHandlerTy DiagHandler=nullptr, void *DiagHandlerCtx=nullptr)
Parse configuration from YAML-formatted text.
Definition: Format.cpp:1993
const std::error_category & getParseCategory()
Definition: Format.cpp:1228
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS, FormatStyle *Style, bool AllowUnknownOptions)
Definition: Format.cpp:3943
tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName="<stdin>")
Fix namespace end comments in the given Ranges in Code.
Definition: Format.cpp:3815
FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code)
Definition: Format.cpp:3919
bool isMpegTS(StringRef Code)
Definition: Format.cpp:3418
const char * DefaultFormatStyle
The suggested format style to use by default.
Definition: Format.cpp:3938
llvm::Expected< FormatStyle > getStyle(StringRef StyleName, StringRef FileName, StringRef FallbackStyle, StringRef Code="", llvm::vfs::FileSystem *FS=nullptr, bool AllowUnknownOptions=false)
Construct a FormatStyle based on StyleName.
Definition: Format.cpp:3954
FormatStyle getGNUStyle()
Returns a format style complying with GNU Coding Standards: http://www.gnu.org/prep/standards/standar...
Definition: Format.cpp:1867
bool isClangFormatOff(StringRef Comment)
Definition: Format.cpp:4134
LangOptions getFormattingLangOpts(const FormatStyle &Style=getLLVMStyle())
Returns the LangOpts that the formatter expects you to set.
Definition: Format.cpp:3835
static bool isClangFormatOnOff(StringRef Comment, bool On)
Definition: Format.cpp:4118
tooling::Replacements sortJavaScriptImports(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName)
FormatStyle getMozillaStyle()
Returns a format style complying with Mozilla's style guide: https://firefox-source-docs....
Definition: Format.cpp:1817
bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language, FormatStyle *Style)
Gets a predefined style for the specified language by name.
Definition: Format.cpp:1932
static void expandPresetsBraceWrapping(FormatStyle &Expanded)
Definition: Format.cpp:1267
static void sortJavaImports(const FormatStyle &Style, const SmallVectorImpl< JavaImportDirective > &Imports, ArrayRef< tooling::Range > Ranges, StringRef FileName, StringRef Code, tooling::Replacements &Replaces)
Definition: Format.cpp:3284
tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName="<stdin>", FormattingAttemptStatus *Status=nullptr)
Reformats the given Ranges in Code.
Definition: Format.cpp:3782
bool isClangFormatOn(StringRef Comment)
Definition: Format.cpp:4130
tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName="<stdin>")
Sort consecutive using declarations in the given Ranges in Code.
Definition: Format.cpp:3825
ParseError validateQualifierOrder(FormatStyle *Style)
Definition: Format.cpp:1961
FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language)
Returns a format style complying with Chromium's style guide: http://www.chromium....
Definition: Format.cpp:1757
static void expandPresetsSpacesInParens(FormatStyle &Expanded)
Definition: Format.cpp:1391
tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName="<stdin>")
Clean up any erroneous/redundant code in the given Ranges in Code.
Definition: Format.cpp:3793
FormatStyle getNoStyle()
Returns style indicating formatting should be not applied at all.
Definition: Format.cpp:1924
tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, ArrayRef< tooling::Range > Ranges, StringRef FileName, unsigned *Cursor=nullptr)
Returns the replacements necessary to sort all #include blocks that are affected by Ranges.
Definition: Format.cpp:3427
static void sortCppIncludes(const FormatStyle &Style, const SmallVectorImpl< IncludeDirective > &Includes, ArrayRef< tooling::Range > Ranges, StringRef FileName, StringRef Code, tooling::Replacements &Replaces, unsigned *Cursor)
Definition: Format.cpp:3058
llvm::Expected< tooling::Replacements > formatReplacements(StringRef Code, const tooling::Replacements &Replaces, const FormatStyle &Style)
Returns the replacements corresponding to applying and formatting Replaces on success; otheriwse,...
Definition: Format.cpp:3468
StringRef getLanguageName(FormatStyle::LanguageKind Language)
Definition: Format.h:5361
The JSON file list parser is used to communicate input to InstallAPI.
Language
The language for the input, used to select and validate the language standard and possible actions.
Definition: LangStandard.h:23
@ Result
The result type of a method or function.
const FunctionProtoType * T
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
Definition: Format.h:5394
bool AcrossEmptyLines
Whether to align across empty lines.
Definition: Format.h:202
bool PadOperators
Only for AlignConsecutiveAssignments.
Definition: Format.h:262
bool AlignFunctionPointers
Only for AlignConsecutiveDeclarations.
Definition: Format.h:243
bool Enabled
Whether aligning is enabled.
Definition: Format.h:185
bool AlignCompound
Only for AlignConsecutiveAssignments.
Definition: Format.h:227
bool AcrossComments
Whether to align across comments.
Definition: Format.h:215
bool SplitEmptyRecord
If false, empty record (e.g.
Definition: Format.h:1485
bool AfterClass
Wrap class definitions.
Definition: Format.h:1301
bool AfterStruct
Wrap struct definitions.
Definition: Format.h:1368
bool AfterUnion
Wrap union definitions.
Definition: Format.h:1382
bool AfterEnum
Wrap enum definitions.
Definition: Format.h:1316
bool AfterObjCDeclaration
Wrap ObjC definitions (interfaces, implementations...).
Definition: Format.h:1354
bool AfterNamespace
Wrap namespace definitions.
Definition: Format.h:1348
BraceWrappingAfterControlStatementStyle AfterControlStatement
Wrap control statements (if/for/while/switch/..).
Definition: Format.h:1304
bool AfterFunction
Wrap function definitions.
Definition: Format.h:1332
bool SplitEmptyFunction
If false, empty function body can be put on a single line.
Definition: Format.h:1473
bool AfterExternBlock
Wrap extern blocks.
Definition: Format.h:1396
std::optional< FormatStyle > Get(FormatStyle::LanguageKind Language) const
Definition: Format.cpp:2075
int8_t DecimalMinDigits
Format separators in decimal literals with a minimum number of digits.
Definition: Format.h:2953
int8_t Decimal
Format separators in decimal literals.
Definition: Format.h:2945
See documentation of RawStringFormats.
Definition: Format.h:3629
bool AfterControlStatements
If true, put space between control statement keywords (for/if/while...) and opening parentheses.
Definition: Format.h:4327
bool AfterForeachMacros
If true, put space between foreach macros and opening parentheses.
Definition: Format.h:4334
bool BeforeNonEmptyParentheses
If true, put a space before opening parentheses only if the parentheses are not empty.
Definition: Format.h:4398
bool AfterIfMacros
If true, put space between if macros and opening parentheses.
Definition: Format.h:4355
bool AfterPlacementOperator
If true, put a space between operator new/delete and opening parenthesis.
Definition: Format.h:4371
bool Other
Put a space in parentheses not covered by preceding options.
Definition: Format.h:4649
bool InEmptyParentheses
Put a space in parentheses only if the parentheses are empty i.e.
Definition: Format.h:4643
bool InCStyleCasts
Put a space in C style casts.
Definition: Format.h:4632
bool InConditionalStatements
Put a space in parentheses only inside conditional statements (for/if/while/switch....
Definition: Format.h:4626
TrailingCommentsAlignmentKinds Kind
Specifies the way to align trailing comments.
Definition: Format.h:560
unsigned OverEmptyLines
How many empty lines to apply alignment.
Definition: Format.h:583
The FormatStyle is used to configure the formatting to follow specific guidelines.
Definition: Format.h:55
@ UT_Never
Never use tab.
Definition: Format.h:4852
bool SpaceBeforeInheritanceColon
If false, spaces will be removed before inheritance colon.
Definition: Format.h:4238
unsigned ContinuationIndentWidth
Indent width for line continuations.
Definition: Format.h:2398
bool AlwaysBreakBeforeMultilineStrings
This option is renamed to BreakAfterReturnType.
Definition: Format.h:1066
LanguageStandard Standard
Parse and format C++ constructs compatible with this standard.
Definition: Format.h:4730
bool BreakAdjacentStringLiterals
Break between adjacent string literals.
Definition: Format.h:1526
ReturnTypeBreakingStyle BreakAfterReturnType
The function declaration return type breaking style to use.
Definition: Format.h:1617
LanguageKind
Supported languages.
Definition: Format.h:3114
@ LK_CSharp
Should be used for C#.
Definition: Format.h:3120
@ LK_None
Do not use.
Definition: Format.h:3116
@ LK_Java
Should be used for Java.
Definition: Format.h:3122
@ LK_Cpp
Should be used for C, C++.
Definition: Format.h:3118
@ LK_JavaScript
Should be used for JavaScript.
Definition: Format.h:3124
@ LK_ObjC
Should be used for Objective-C, Objective-C++.
Definition: Format.h:3128
@ LK_Verilog
Should be used for Verilog and SystemVerilog.
Definition: Format.h:3140
@ LK_TableGen
Should be used for TableGen code.
Definition: Format.h:3133
@ LK_Proto
Should be used for Protocol Buffers (https://developers.google.com/protocol-buffers/).
Definition: Format.h:3131
@ LK_Json
Should be used for JSON.
Definition: Format.h:3126
@ LK_TextProto
Should be used for Protocol Buffer messages in text format (https://developers.google....
Definition: Format.h:3136
bool Cpp11BracedListStyle
If true, format braced lists as best suited for C++11 braced lists.
Definition: Format.h:2421
SortIncludesOptions SortIncludes
Controls if and how clang-format will sort #includes.
Definition: Format.h:4065
BreakInheritanceListStyle BreakInheritanceList
The inheritance list style to use.
Definition: Format.h:2349
unsigned IndentWidth
The number of columns to use for indentation.
Definition: Format.h:2821
std::vector< std::string > AttributeMacros
This option is renamed to BreakTemplateDeclarations.
Definition: Format.h:1136
@ SLS_All
Merge all lambdas fitting on a single line.
Definition: Format.h:924
@ SLS_Empty
Only merge empty lambdas.
Definition: Format.h:910
@ SDS_Leave
Leave definition blocks as they are.
Definition: Format.h:3951
bool IndentRequiresClause
Indent the requires clause in a template.
Definition: Format.h:2807
SpacesInAnglesStyle SpacesInAngles
The SpacesInAnglesStyle to use for template argument lists.
Definition: Format.h:4513
bool IndentCaseLabels
Indent case labels one level from the switch statement.
Definition: Format.h:2693
std::vector< RawStringFormat > RawStringFormats
Defines hints for detecting supported languages code blocks in raw strings.
Definition: Format.h:3686
@ SJSIO_Before
Static imports are placed before non-static imports.
Definition: Format.h:4075
@ SJSIO_After
Static imports are placed after non-static imports.
Definition: Format.h:4082
PPDirectiveIndentStyle IndentPPDirectives
The preprocessor directive indenting style to use.
Definition: Format.h:2785
bool RemoveSemicolon
Remove semicolons after the closing braces of functions and constructors/destructors.
Definition: Format.h:3839
std::vector< std::string > Macros
A list of macros of the form <definition>=<expansion> .
Definition: Format.h:3243
bool SpaceBeforeJsonColon
If true, a space will be added before a JSON colon.
Definition: Format.h:4249
@ TCS_None
Do not insert trailing commas.
Definition: Format.h:2876
unsigned PenaltyBreakBeforeFirstCallParameter
The penalty for breaking a function call after call(.
Definition: Format.h:3479
bool SpaceBeforeCtorInitializerColon
If false, spaces will be removed before constructor initializer colon.
Definition: Format.h:4230
BinaryOperatorStyle BreakBeforeBinaryOperators
The way to wrap binary operators.
Definition: Format.h:1691
@ SI_Never
Includes are never sorted.
Definition: Format.h:4042
@ SI_CaseSensitive
Includes are sorted in an ASCIIbetical or case sensitive fashion.
Definition: Format.h:4051
@ SI_CaseInsensitive
Includes are sorted in an alphabetical or case insensitive fashion.
Definition: Format.h:4060
@ BPS_Never
Never bin-pack parameters.
Definition: Format.h:1646
@ BPS_Auto
Automatically determine parameter bin-packing behavior.
Definition: Format.h:1642
BitFieldColonSpacingStyle BitFieldColonSpacing
The BitFieldColonSpacingStyle to use for bitfields.
Definition: Format.h:1199
@ ELBAMS_LogicalBlock
Add empty line only when access modifier starts a new logical block.
Definition: Format.h:2527
unsigned SpacesBeforeTrailingComments
If true, spaces may be inserted into ().
Definition: Format.h:4490
@ BCIS_BeforeColon
Break constructor initializers before the colon and after the commas.
Definition: Format.h:2204
@ BCIS_BeforeComma
Break constructor initializers before the colon and commas, and align the commas with the colon.
Definition: Format.h:2212
@ IEBS_AfterExternBlock
Backwards compatible with AfterExternBlock's indenting.
Definition: Format.h:2731
bool IndentCaseBlocks
Indent case label blocks one level from the case label.
Definition: Format.h:2674
bool InsertBraces
Insert braces after control statements (if, else, for, do, and while) in C++ unless the control state...
Definition: Format.h:2867
BreakBeforeConceptDeclarationsStyle BreakBeforeConceptDeclarations
The concept declaration style to use.
Definition: Format.h:2150
BreakTemplateDeclarationsStyle BreakTemplateDeclarations
The template declaration breaking style to use.
Definition: Format.h:2353
bool DerivePointerAlignment
This option is deprecated.
Definition: Format.h:2434
@ BOS_All
Break before operators.
Definition: Format.h:1686
@ BOS_None
Break after operators.
Definition: Format.h:1662
@ BOS_NonAssignment
Break before operators that aren't assignments.
Definition: Format.h:1674
@ LE_DeriveLF
Use \n unless the input has more lines ending in \r\n.
Definition: Format.h:3163
bool SpacesInSquareBrackets
If true, spaces will be inserted after [ and before ].
Definition: Format.h:4695
bool IndentWrappedFunctionNames
Indent if a function definition or declaration is wrapped after the type.
Definition: Format.h:2835
AlignConsecutiveStyle AlignConsecutiveTableGenBreakingDAGArgColons
Style of aligning consecutive TableGen DAGArg operator colons.
Definition: Format.h:430
bool FixNamespaceComments
If true, clang-format adds missing namespace end comments for namespaces and fixes invalid existing o...
Definition: Format.h:2583
bool ObjCSpaceBeforeProtocolList
Add a space in front of an Objective-C protocol list, i.e.
Definition: Format.h:3409
@ TCAS_Never
Don't align trailing comments but other formatter applies.
Definition: Format.h:554
@ TCAS_Always
Align trailing comments.
Definition: Format.h:545
RemoveParenthesesStyle RemoveParentheses
Remove redundant parentheses.
Definition: Format.h:3821
std::string MacroBlockBegin
A regular expression matching macros that start a block.
Definition: Format.h:3199
bool SpaceInEmptyBlock
If true, spaces will be inserted into {}.
Definition: Format.h:4464
LanguageKind Language
Language, this format style is targeted at.
Definition: Format.h:3154
@ SIPO_Custom
Configure each individual space in parentheses in SpacesInParensOptions.
Definition: Format.h:4594
@ SIPO_Never
Never put a space in parentheses.
Definition: Format.h:4591
bool RemoveBracesLLVM
Remove optional braces of control statements (if, else, for, and while) in C++ according to the LLVM ...
Definition: Format.h:3785
@ BAS_DontAlign
Don't align, instead use ContinuationIndentWidth, e.g.:
Definition: Format.h:78
@ BAS_AlwaysBreak
Always break after an open bracket, if the parameters don't fit on a single line, e....
Definition: Format.h:85
@ BAS_Align
Align parameters on the open bracket, e.g.:
Definition: Format.h:72
@ BBIAS_OnlyMultiline
Break before inline ASM colon if the line length is longer than column limit.
Definition: Format.h:2167
bool VerilogBreakBetweenInstancePorts
For Verilog, put each port on its own line in module instantiations.
Definition: Format.h:4882
unsigned TabWidth
The number of columns used for tab stops.
Definition: Format.h:4816
@ PPDIS_None
Does not indent any directives.
Definition: Format.h:2762
@ LBI_Signature
Align lambda body relative to the lambda signature.
Definition: Format.h:3084
std::vector< std::string > JavaImportGroups
A vector of prefixes ordered by the desired groups for Java imports.
Definition: Format.h:3014
bool AllowShortCaseLabelsOnASingleLine
If true, short case labels will be contracted to a single line.
Definition: Format.h:739
unsigned PenaltyBreakFirstLessLess
The penalty for breaking before the first <<.
Definition: Format.h:3487
std::vector< std::string > StatementAttributeLikeMacros
Macros which are ignored in front of a statement, as if they were an attribute.
Definition: Format.h:4747
unsigned ObjCBlockIndentWidth
The number of characters to use for indentation of ObjC blocks.
Definition: Format.h:3352
bool AllowShortLoopsOnASingleLine
If true, while (true) continue; can be put on a single line.
Definition: Format.h:935
int AccessModifierOffset
The extra indent or outdent of access modifiers, e.g.
Definition: Format.h:63
std::vector< std::string > QualifierOrder
The order in which the qualifiers appear.
Definition: Format.h:3626
bool AllowShortEnumsOnASingleLine
Allow short enums on a single line.
Definition: Format.h:772
@ SBS_Empty
Only merge empty blocks.
Definition: Format.h:713