25#include "llvm/ADT/Sequence.h"
27#define DEBUG_TYPE "format-formatter"
36struct ScalarEnumerationTraits<
FormatStyle::BreakBeforeNoexceptSpecifierStyle> {
39 IO.enumCase(
Value,
"Never", FormatStyle::BBNSS_Never);
40 IO.enumCase(
Value,
"OnlyWithParen", FormatStyle::BBNSS_OnlyWithParen);
41 IO.enumCase(
Value,
"Always", FormatStyle::BBNSS_Always);
45template <>
struct MappingTraits<
FormatStyle::AlignConsecutiveStyle> {
47 IO.enumCase(
Value,
"None",
48 FormatStyle::AlignConsecutiveStyle(
52 IO.enumCase(
Value,
"Consecutive",
53 FormatStyle::AlignConsecutiveStyle(
57 IO.enumCase(
Value,
"AcrossEmptyLines",
58 FormatStyle::AlignConsecutiveStyle(
62 IO.enumCase(
Value,
"AcrossComments",
63 FormatStyle::AlignConsecutiveStyle(
67 IO.enumCase(
Value,
"AcrossEmptyLinesAndComments",
68 FormatStyle::AlignConsecutiveStyle(
74 IO.enumCase(
Value,
"true",
75 FormatStyle::AlignConsecutiveStyle(
79 IO.enumCase(
Value,
"false",
80 FormatStyle::AlignConsecutiveStyle(
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);
97struct MappingTraits<
FormatStyle::ShortCaseStatementsAlignmentStyle> {
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(
"AlignCaseArrows",
Value.AlignCaseArrows);
104 IO.mapOptional(
"AlignCaseColons",
Value.AlignCaseColons);
109struct ScalarEnumerationTraits<
FormatStyle::AttributeBreakingStyle> {
111 IO.enumCase(
Value,
"Always", FormatStyle::ABS_Always);
112 IO.enumCase(
Value,
"Leave", FormatStyle::ABS_Leave);
113 IO.enumCase(
Value,
"Never", FormatStyle::ABS_Never);
118struct ScalarEnumerationTraits<
FormatStyle::ArrayInitializerAlignmentStyle> {
120 FormatStyle::ArrayInitializerAlignmentStyle &
Value) {
121 IO.enumCase(
Value,
"None", FormatStyle::AIAS_None);
122 IO.enumCase(
Value,
"Left", FormatStyle::AIAS_Left);
123 IO.enumCase(
Value,
"Right", FormatStyle::AIAS_Right);
127template <>
struct ScalarEnumerationTraits<
FormatStyle::BinaryOperatorStyle> {
129 IO.enumCase(
Value,
"All", FormatStyle::BOS_All);
130 IO.enumCase(
Value,
"true", FormatStyle::BOS_All);
131 IO.enumCase(
Value,
"None", FormatStyle::BOS_None);
132 IO.enumCase(
Value,
"false", FormatStyle::BOS_None);
133 IO.enumCase(
Value,
"NonAssignment", FormatStyle::BOS_NonAssignment);
137template <>
struct ScalarEnumerationTraits<
FormatStyle::BinPackStyle> {
139 IO.enumCase(
Value,
"Auto", FormatStyle::BPS_Auto);
140 IO.enumCase(
Value,
"Always", FormatStyle::BPS_Always);
141 IO.enumCase(
Value,
"Never", FormatStyle::BPS_Never);
146struct ScalarEnumerationTraits<
FormatStyle::BitFieldColonSpacingStyle> {
148 FormatStyle::BitFieldColonSpacingStyle &
Value) {
149 IO.enumCase(
Value,
"Both", FormatStyle::BFCS_Both);
150 IO.enumCase(
Value,
"None", FormatStyle::BFCS_None);
151 IO.enumCase(
Value,
"Before", FormatStyle::BFCS_Before);
152 IO.enumCase(
Value,
"After", FormatStyle::BFCS_After);
156template <>
struct ScalarEnumerationTraits<
FormatStyle::BraceBreakingStyle> {
158 IO.enumCase(
Value,
"Attach", FormatStyle::BS_Attach);
159 IO.enumCase(
Value,
"Linux", FormatStyle::BS_Linux);
160 IO.enumCase(
Value,
"Mozilla", FormatStyle::BS_Mozilla);
161 IO.enumCase(
Value,
"Stroustrup", FormatStyle::BS_Stroustrup);
162 IO.enumCase(
Value,
"Allman", FormatStyle::BS_Allman);
163 IO.enumCase(
Value,
"Whitesmiths", FormatStyle::BS_Whitesmiths);
164 IO.enumCase(
Value,
"GNU", FormatStyle::BS_GNU);
165 IO.enumCase(
Value,
"WebKit", FormatStyle::BS_WebKit);
166 IO.enumCase(
Value,
"Custom", FormatStyle::BS_Custom);
170template <>
struct MappingTraits<
FormatStyle::BraceWrappingFlags> {
171 static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
172 IO.mapOptional(
"AfterCaseLabel", Wrapping.AfterCaseLabel);
173 IO.mapOptional(
"AfterClass", Wrapping.AfterClass);
174 IO.mapOptional(
"AfterControlStatement", Wrapping.AfterControlStatement);
175 IO.mapOptional(
"AfterEnum", Wrapping.AfterEnum);
176 IO.mapOptional(
"AfterExternBlock", Wrapping.AfterExternBlock);
177 IO.mapOptional(
"AfterFunction", Wrapping.AfterFunction);
178 IO.mapOptional(
"AfterNamespace", Wrapping.AfterNamespace);
179 IO.mapOptional(
"AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
180 IO.mapOptional(
"AfterStruct", Wrapping.AfterStruct);
181 IO.mapOptional(
"AfterUnion", Wrapping.AfterUnion);
182 IO.mapOptional(
"BeforeCatch", Wrapping.BeforeCatch);
183 IO.mapOptional(
"BeforeElse", Wrapping.BeforeElse);
184 IO.mapOptional(
"BeforeLambdaBody", Wrapping.BeforeLambdaBody);
185 IO.mapOptional(
"BeforeWhile", Wrapping.BeforeWhile);
186 IO.mapOptional(
"IndentBraces", Wrapping.IndentBraces);
187 IO.mapOptional(
"SplitEmptyFunction", Wrapping.SplitEmptyFunction);
188 IO.mapOptional(
"SplitEmptyRecord", Wrapping.SplitEmptyRecord);
189 IO.mapOptional(
"SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
193template <>
struct ScalarEnumerationTraits<
FormatStyle::BracketAlignmentStyle> {
195 IO.enumCase(
Value,
"Align", FormatStyle::BAS_Align);
196 IO.enumCase(
Value,
"DontAlign", FormatStyle::BAS_DontAlign);
197 IO.enumCase(
Value,
"AlwaysBreak", FormatStyle::BAS_AlwaysBreak);
198 IO.enumCase(
Value,
"BlockIndent", FormatStyle::BAS_BlockIndent);
201 IO.enumCase(
Value,
"true", FormatStyle::BAS_Align);
202 IO.enumCase(
Value,
"false", FormatStyle::BAS_DontAlign);
207struct ScalarEnumerationTraits<
208 FormatStyle::BraceWrappingAfterControlStatementStyle> {
211 FormatStyle::BraceWrappingAfterControlStatementStyle &
Value) {
212 IO.enumCase(
Value,
"Never", FormatStyle::BWACS_Never);
213 IO.enumCase(
Value,
"MultiLine", FormatStyle::BWACS_MultiLine);
214 IO.enumCase(
Value,
"Always", FormatStyle::BWACS_Always);
217 IO.enumCase(
Value,
"false", FormatStyle::BWACS_Never);
218 IO.enumCase(
Value,
"true", FormatStyle::BWACS_Always);
223struct ScalarEnumerationTraits<
224 FormatStyle::BreakBeforeConceptDeclarationsStyle> {
227 IO.enumCase(
Value,
"Never", FormatStyle::BBCDS_Never);
228 IO.enumCase(
Value,
"Allowed", FormatStyle::BBCDS_Allowed);
229 IO.enumCase(
Value,
"Always", FormatStyle::BBCDS_Always);
232 IO.enumCase(
Value,
"true", FormatStyle::BBCDS_Always);
233 IO.enumCase(
Value,
"false", FormatStyle::BBCDS_Allowed);
238struct ScalarEnumerationTraits<
FormatStyle::BreakBeforeInlineASMColonStyle> {
240 FormatStyle::BreakBeforeInlineASMColonStyle &
Value) {
241 IO.enumCase(
Value,
"Never", FormatStyle::BBIAS_Never);
242 IO.enumCase(
Value,
"OnlyMultiline", FormatStyle::BBIAS_OnlyMultiline);
243 IO.enumCase(
Value,
"Always", FormatStyle::BBIAS_Always);
248struct ScalarEnumerationTraits<
FormatStyle::BreakConstructorInitializersStyle> {
251 IO.enumCase(
Value,
"BeforeColon", FormatStyle::BCIS_BeforeColon);
252 IO.enumCase(
Value,
"BeforeComma", FormatStyle::BCIS_BeforeComma);
253 IO.enumCase(
Value,
"AfterColon", FormatStyle::BCIS_AfterColon);
258struct ScalarEnumerationTraits<
FormatStyle::BreakInheritanceListStyle> {
260 FormatStyle::BreakInheritanceListStyle &
Value) {
261 IO.enumCase(
Value,
"BeforeColon", FormatStyle::BILS_BeforeColon);
262 IO.enumCase(
Value,
"BeforeComma", FormatStyle::BILS_BeforeComma);
263 IO.enumCase(
Value,
"AfterColon", FormatStyle::BILS_AfterColon);
264 IO.enumCase(
Value,
"AfterComma", FormatStyle::BILS_AfterComma);
269struct ScalarEnumerationTraits<
FormatStyle::BreakTemplateDeclarationsStyle> {
271 FormatStyle::BreakTemplateDeclarationsStyle &
Value) {
272 IO.enumCase(
Value,
"Leave", FormatStyle::BTDS_Leave);
273 IO.enumCase(
Value,
"No", FormatStyle::BTDS_No);
274 IO.enumCase(
Value,
"MultiLine", FormatStyle::BTDS_MultiLine);
275 IO.enumCase(
Value,
"Yes", FormatStyle::BTDS_Yes);
278 IO.enumCase(
Value,
"false", FormatStyle::BTDS_MultiLine);
279 IO.enumCase(
Value,
"true", FormatStyle::BTDS_Yes);
283template <>
struct ScalarEnumerationTraits<
FormatStyle::DAGArgStyle> {
285 IO.enumCase(
Value,
"DontBreak", FormatStyle::DAS_DontBreak);
286 IO.enumCase(
Value,
"BreakElements", FormatStyle::DAS_BreakElements);
287 IO.enumCase(
Value,
"BreakAll", FormatStyle::DAS_BreakAll);
292struct ScalarEnumerationTraits<
FormatStyle::DefinitionReturnTypeBreakingStyle> {
295 IO.enumCase(
Value,
"None", FormatStyle::DRTBS_None);
296 IO.enumCase(
Value,
"All", FormatStyle::DRTBS_All);
297 IO.enumCase(
Value,
"TopLevel", FormatStyle::DRTBS_TopLevel);
300 IO.enumCase(
Value,
"false", FormatStyle::DRTBS_None);
301 IO.enumCase(
Value,
"true", FormatStyle::DRTBS_All);
306struct ScalarEnumerationTraits<
FormatStyle::EscapedNewlineAlignmentStyle> {
308 FormatStyle::EscapedNewlineAlignmentStyle &
Value) {
309 IO.enumCase(
Value,
"DontAlign", FormatStyle::ENAS_DontAlign);
310 IO.enumCase(
Value,
"Left", FormatStyle::ENAS_Left);
311 IO.enumCase(
Value,
"Right", FormatStyle::ENAS_Right);
314 IO.enumCase(
Value,
"true", FormatStyle::ENAS_Left);
315 IO.enumCase(
Value,
"false", FormatStyle::ENAS_Right);
320struct ScalarEnumerationTraits<
FormatStyle::EmptyLineAfterAccessModifierStyle> {
323 IO.enumCase(
Value,
"Never", FormatStyle::ELAAMS_Never);
324 IO.enumCase(
Value,
"Leave", FormatStyle::ELAAMS_Leave);
325 IO.enumCase(
Value,
"Always", FormatStyle::ELAAMS_Always);
330struct ScalarEnumerationTraits<
334 IO.enumCase(
Value,
"Never", FormatStyle::ELBAMS_Never);
335 IO.enumCase(
Value,
"Leave", FormatStyle::ELBAMS_Leave);
336 IO.enumCase(
Value,
"LogicalBlock", FormatStyle::ELBAMS_LogicalBlock);
337 IO.enumCase(
Value,
"Always", FormatStyle::ELBAMS_Always);
342struct ScalarEnumerationTraits<
FormatStyle::IndentExternBlockStyle> {
344 IO.enumCase(
Value,
"AfterExternBlock", FormatStyle::IEBS_AfterExternBlock);
345 IO.enumCase(
Value,
"Indent", FormatStyle::IEBS_Indent);
346 IO.enumCase(
Value,
"NoIndent", FormatStyle::IEBS_NoIndent);
347 IO.enumCase(
Value,
"true", FormatStyle::IEBS_Indent);
348 IO.enumCase(
Value,
"false", FormatStyle::IEBS_NoIndent);
352template <>
struct MappingTraits<
FormatStyle::IntegerLiteralSeparatorStyle> {
353 static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &
Base) {
354 IO.mapOptional(
"Binary",
Base.Binary);
355 IO.mapOptional(
"BinaryMinDigits",
Base.BinaryMinDigits);
356 IO.mapOptional(
"Decimal",
Base.Decimal);
357 IO.mapOptional(
"DecimalMinDigits",
Base.DecimalMinDigits);
358 IO.mapOptional(
"Hex",
Base.Hex);
359 IO.mapOptional(
"HexMinDigits",
Base.HexMinDigits);
363template <>
struct ScalarEnumerationTraits<
FormatStyle::JavaScriptQuoteStyle> {
365 IO.enumCase(
Value,
"Leave", FormatStyle::JSQS_Leave);
366 IO.enumCase(
Value,
"Single", FormatStyle::JSQS_Single);
367 IO.enumCase(
Value,
"Double", FormatStyle::JSQS_Double);
371template <>
struct ScalarEnumerationTraits<
FormatStyle::LanguageKind> {
373 IO.enumCase(
Value,
"Cpp", FormatStyle::LK_Cpp);
374 IO.enumCase(
Value,
"Java", FormatStyle::LK_Java);
375 IO.enumCase(
Value,
"JavaScript", FormatStyle::LK_JavaScript);
376 IO.enumCase(
Value,
"ObjC", FormatStyle::LK_ObjC);
377 IO.enumCase(
Value,
"Proto", FormatStyle::LK_Proto);
378 IO.enumCase(
Value,
"TableGen", FormatStyle::LK_TableGen);
379 IO.enumCase(
Value,
"TextProto", FormatStyle::LK_TextProto);
380 IO.enumCase(
Value,
"CSharp", FormatStyle::LK_CSharp);
381 IO.enumCase(
Value,
"Json", FormatStyle::LK_Json);
382 IO.enumCase(
Value,
"Verilog", FormatStyle::LK_Verilog);
386template <>
struct ScalarEnumerationTraits<
FormatStyle::LanguageStandard> {
388 IO.enumCase(
Value,
"c++03", FormatStyle::LS_Cpp03);
389 IO.enumCase(
Value,
"C++03", FormatStyle::LS_Cpp03);
390 IO.enumCase(
Value,
"Cpp03", FormatStyle::LS_Cpp03);
392 IO.enumCase(
Value,
"c++11", FormatStyle::LS_Cpp11);
393 IO.enumCase(
Value,
"C++11", FormatStyle::LS_Cpp11);
395 IO.enumCase(
Value,
"c++14", FormatStyle::LS_Cpp14);
396 IO.enumCase(
Value,
"c++17", FormatStyle::LS_Cpp17);
397 IO.enumCase(
Value,
"c++20", FormatStyle::LS_Cpp20);
399 IO.enumCase(
Value,
"Latest", FormatStyle::LS_Latest);
400 IO.enumCase(
Value,
"Cpp11", FormatStyle::LS_Latest);
401 IO.enumCase(
Value,
"Auto", FormatStyle::LS_Auto);
406struct ScalarEnumerationTraits<
FormatStyle::LambdaBodyIndentationKind> {
408 FormatStyle::LambdaBodyIndentationKind &
Value) {
409 IO.enumCase(
Value,
"Signature", FormatStyle::LBI_Signature);
410 IO.enumCase(
Value,
"OuterScope", FormatStyle::LBI_OuterScope);
414template <>
struct ScalarEnumerationTraits<
FormatStyle::LineEndingStyle> {
416 IO.enumCase(
Value,
"LF", FormatStyle::LE_LF);
417 IO.enumCase(
Value,
"CRLF", FormatStyle::LE_CRLF);
418 IO.enumCase(
Value,
"DeriveLF", FormatStyle::LE_DeriveLF);
419 IO.enumCase(
Value,
"DeriveCRLF", FormatStyle::LE_DeriveCRLF);
424struct ScalarEnumerationTraits<
FormatStyle::NamespaceIndentationKind> {
426 FormatStyle::NamespaceIndentationKind &
Value) {
427 IO.enumCase(
Value,
"None", FormatStyle::NI_None);
428 IO.enumCase(
Value,
"Inner", FormatStyle::NI_Inner);
429 IO.enumCase(
Value,
"All", FormatStyle::NI_All);
433template <>
struct ScalarEnumerationTraits<
FormatStyle::OperandAlignmentStyle> {
435 IO.enumCase(
Value,
"DontAlign", FormatStyle::OAS_DontAlign);
436 IO.enumCase(
Value,
"Align", FormatStyle::OAS_Align);
437 IO.enumCase(
Value,
"AlignAfterOperator",
438 FormatStyle::OAS_AlignAfterOperator);
441 IO.enumCase(
Value,
"true", FormatStyle::OAS_Align);
442 IO.enumCase(
Value,
"false", FormatStyle::OAS_DontAlign);
447struct ScalarEnumerationTraits<
FormatStyle::PackConstructorInitializersStyle> {
450 IO.enumCase(
Value,
"Never", FormatStyle::PCIS_Never);
451 IO.enumCase(
Value,
"BinPack", FormatStyle::PCIS_BinPack);
452 IO.enumCase(
Value,
"CurrentLine", FormatStyle::PCIS_CurrentLine);
453 IO.enumCase(
Value,
"NextLine", FormatStyle::PCIS_NextLine);
454 IO.enumCase(
Value,
"NextLineOnly", FormatStyle::PCIS_NextLineOnly);
458template <>
struct ScalarEnumerationTraits<
FormatStyle::PointerAlignmentStyle> {
460 IO.enumCase(
Value,
"Middle", FormatStyle::PAS_Middle);
461 IO.enumCase(
Value,
"Left", FormatStyle::PAS_Left);
462 IO.enumCase(
Value,
"Right", FormatStyle::PAS_Right);
465 IO.enumCase(
Value,
"true", FormatStyle::PAS_Left);
466 IO.enumCase(
Value,
"false", FormatStyle::PAS_Right);
471struct ScalarEnumerationTraits<
FormatStyle::PPDirectiveIndentStyle> {
473 IO.enumCase(
Value,
"None", FormatStyle::PPDIS_None);
474 IO.enumCase(
Value,
"AfterHash", FormatStyle::PPDIS_AfterHash);
475 IO.enumCase(
Value,
"BeforeHash", FormatStyle::PPDIS_BeforeHash);
480struct ScalarEnumerationTraits<
FormatStyle::QualifierAlignmentStyle> {
482 IO.enumCase(
Value,
"Leave", FormatStyle::QAS_Leave);
483 IO.enumCase(
Value,
"Left", FormatStyle::QAS_Left);
484 IO.enumCase(
Value,
"Right", FormatStyle::QAS_Right);
485 IO.enumCase(
Value,
"Custom", FormatStyle::QAS_Custom);
490 static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
491 IO.mapOptional(
"Language", Format.Language);
492 IO.mapOptional(
"Delimiters", Format.Delimiters);
493 IO.mapOptional(
"EnclosingFunctions", Format.EnclosingFunctions);
494 IO.mapOptional(
"CanonicalDelimiter", Format.CanonicalDelimiter);
495 IO.mapOptional(
"BasedOnStyle", Format.BasedOnStyle);
500struct ScalarEnumerationTraits<
FormatStyle::ReferenceAlignmentStyle> {
502 IO.enumCase(
Value,
"Pointer", FormatStyle::RAS_Pointer);
503 IO.enumCase(
Value,
"Middle", FormatStyle::RAS_Middle);
504 IO.enumCase(
Value,
"Left", FormatStyle::RAS_Left);
505 IO.enumCase(
Value,
"Right", FormatStyle::RAS_Right);
510struct ScalarEnumerationTraits<
FormatStyle::RemoveParenthesesStyle> {
512 IO.enumCase(
Value,
"Leave", FormatStyle::RPS_Leave);
513 IO.enumCase(
Value,
"MultipleParentheses",
514 FormatStyle::RPS_MultipleParentheses);
515 IO.enumCase(
Value,
"ReturnStatement", FormatStyle::RPS_ReturnStatement);
520struct ScalarEnumerationTraits<
FormatStyle::RequiresClausePositionStyle> {
522 FormatStyle::RequiresClausePositionStyle &
Value) {
523 IO.enumCase(
Value,
"OwnLine", FormatStyle::RCPS_OwnLine);
524 IO.enumCase(
Value,
"WithPreceding", FormatStyle::RCPS_WithPreceding);
525 IO.enumCase(
Value,
"WithFollowing", FormatStyle::RCPS_WithFollowing);
526 IO.enumCase(
Value,
"SingleLine", FormatStyle::RCPS_SingleLine);
531struct ScalarEnumerationTraits<
FormatStyle::RequiresExpressionIndentationKind> {
534 IO.enumCase(
Value,
"Keyword", FormatStyle::REI_Keyword);
535 IO.enumCase(
Value,
"OuterScope", FormatStyle::REI_OuterScope);
540struct ScalarEnumerationTraits<
FormatStyle::ReturnTypeBreakingStyle> {
542 IO.enumCase(
Value,
"None", FormatStyle::RTBS_None);
543 IO.enumCase(
Value,
"Automatic", FormatStyle::RTBS_Automatic);
544 IO.enumCase(
Value,
"ExceptShortType", FormatStyle::RTBS_ExceptShortType);
545 IO.enumCase(
Value,
"All", FormatStyle::RTBS_All);
546 IO.enumCase(
Value,
"TopLevel", FormatStyle::RTBS_TopLevel);
547 IO.enumCase(
Value,
"TopLevelDefinitions",
548 FormatStyle::RTBS_TopLevelDefinitions);
549 IO.enumCase(
Value,
"AllDefinitions", FormatStyle::RTBS_AllDefinitions);
554struct ScalarEnumerationTraits<
FormatStyle::SeparateDefinitionStyle> {
556 IO.enumCase(
Value,
"Leave", FormatStyle::SDS_Leave);
557 IO.enumCase(
Value,
"Always", FormatStyle::SDS_Always);
558 IO.enumCase(
Value,
"Never", FormatStyle::SDS_Never);
562template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortBlockStyle> {
564 IO.enumCase(
Value,
"Never", FormatStyle::SBS_Never);
565 IO.enumCase(
Value,
"false", FormatStyle::SBS_Never);
566 IO.enumCase(
Value,
"Always", FormatStyle::SBS_Always);
567 IO.enumCase(
Value,
"true", FormatStyle::SBS_Always);
568 IO.enumCase(
Value,
"Empty", FormatStyle::SBS_Empty);
572template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortFunctionStyle> {
574 IO.enumCase(
Value,
"None", FormatStyle::SFS_None);
575 IO.enumCase(
Value,
"false", FormatStyle::SFS_None);
576 IO.enumCase(
Value,
"All", FormatStyle::SFS_All);
577 IO.enumCase(
Value,
"true", FormatStyle::SFS_All);
578 IO.enumCase(
Value,
"Inline", FormatStyle::SFS_Inline);
579 IO.enumCase(
Value,
"InlineOnly", FormatStyle::SFS_InlineOnly);
580 IO.enumCase(
Value,
"Empty", FormatStyle::SFS_Empty);
584template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortIfStyle> {
586 IO.enumCase(
Value,
"Never", FormatStyle::SIS_Never);
587 IO.enumCase(
Value,
"WithoutElse", FormatStyle::SIS_WithoutElse);
588 IO.enumCase(
Value,
"OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf);
589 IO.enumCase(
Value,
"AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse);
592 IO.enumCase(
Value,
"Always", FormatStyle::SIS_OnlyFirstIf);
593 IO.enumCase(
Value,
"false", FormatStyle::SIS_Never);
594 IO.enumCase(
Value,
"true", FormatStyle::SIS_WithoutElse);
598template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortLambdaStyle> {
600 IO.enumCase(
Value,
"None", FormatStyle::SLS_None);
601 IO.enumCase(
Value,
"false", FormatStyle::SLS_None);
602 IO.enumCase(
Value,
"Empty", FormatStyle::SLS_Empty);
603 IO.enumCase(
Value,
"Inline", FormatStyle::SLS_Inline);
604 IO.enumCase(
Value,
"All", FormatStyle::SLS_All);
605 IO.enumCase(
Value,
"true", FormatStyle::SLS_All);
609template <>
struct ScalarEnumerationTraits<
FormatStyle::SortIncludesOptions> {
611 IO.enumCase(
Value,
"Never", FormatStyle::SI_Never);
612 IO.enumCase(
Value,
"CaseInsensitive", FormatStyle::SI_CaseInsensitive);
613 IO.enumCase(
Value,
"CaseSensitive", FormatStyle::SI_CaseSensitive);
616 IO.enumCase(
Value,
"false", FormatStyle::SI_Never);
617 IO.enumCase(
Value,
"true", FormatStyle::SI_CaseSensitive);
622struct ScalarEnumerationTraits<
FormatStyle::SortJavaStaticImportOptions> {
624 FormatStyle::SortJavaStaticImportOptions &
Value) {
625 IO.enumCase(
Value,
"Before", FormatStyle::SJSIO_Before);
626 IO.enumCase(
Value,
"After", FormatStyle::SJSIO_After);
631struct ScalarEnumerationTraits<
FormatStyle::SortUsingDeclarationsOptions> {
633 FormatStyle::SortUsingDeclarationsOptions &
Value) {
634 IO.enumCase(
Value,
"Never", FormatStyle::SUD_Never);
635 IO.enumCase(
Value,
"Lexicographic", FormatStyle::SUD_Lexicographic);
636 IO.enumCase(
Value,
"LexicographicNumeric",
637 FormatStyle::SUD_LexicographicNumeric);
640 IO.enumCase(
Value,
"false", FormatStyle::SUD_Never);
641 IO.enumCase(
Value,
"true", FormatStyle::SUD_LexicographicNumeric);
646struct ScalarEnumerationTraits<
FormatStyle::SpaceAroundPointerQualifiersStyle> {
649 IO.enumCase(
Value,
"Default", FormatStyle::SAPQ_Default);
650 IO.enumCase(
Value,
"Before", FormatStyle::SAPQ_Before);
651 IO.enumCase(
Value,
"After", FormatStyle::SAPQ_After);
652 IO.enumCase(
Value,
"Both", FormatStyle::SAPQ_Both);
656template <>
struct MappingTraits<
FormatStyle::SpaceBeforeParensCustom> {
657 static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) {
658 IO.mapOptional(
"AfterControlStatements", Spacing.AfterControlStatements);
659 IO.mapOptional(
"AfterForeachMacros", Spacing.AfterForeachMacros);
660 IO.mapOptional(
"AfterFunctionDefinitionName",
661 Spacing.AfterFunctionDefinitionName);
662 IO.mapOptional(
"AfterFunctionDeclarationName",
663 Spacing.AfterFunctionDeclarationName);
664 IO.mapOptional(
"AfterIfMacros", Spacing.AfterIfMacros);
665 IO.mapOptional(
"AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
666 IO.mapOptional(
"AfterPlacementOperator", Spacing.AfterPlacementOperator);
667 IO.mapOptional(
"AfterRequiresInClause", Spacing.AfterRequiresInClause);
668 IO.mapOptional(
"AfterRequiresInExpression",
669 Spacing.AfterRequiresInExpression);
670 IO.mapOptional(
"BeforeNonEmptyParentheses",
671 Spacing.BeforeNonEmptyParentheses);
676struct ScalarEnumerationTraits<
FormatStyle::SpaceBeforeParensStyle> {
678 IO.enumCase(
Value,
"Never", FormatStyle::SBPO_Never);
679 IO.enumCase(
Value,
"ControlStatements",
680 FormatStyle::SBPO_ControlStatements);
681 IO.enumCase(
Value,
"ControlStatementsExceptControlMacros",
682 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
683 IO.enumCase(
Value,
"NonEmptyParentheses",
684 FormatStyle::SBPO_NonEmptyParentheses);
685 IO.enumCase(
Value,
"Always", FormatStyle::SBPO_Always);
686 IO.enumCase(
Value,
"Custom", FormatStyle::SBPO_Custom);
689 IO.enumCase(
Value,
"false", FormatStyle::SBPO_Never);
690 IO.enumCase(
Value,
"true", FormatStyle::SBPO_ControlStatements);
691 IO.enumCase(
Value,
"ControlStatementsExceptForEachMacros",
692 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
696template <>
struct ScalarEnumerationTraits<
FormatStyle::SpacesInAnglesStyle> {
698 IO.enumCase(
Value,
"Never", FormatStyle::SIAS_Never);
699 IO.enumCase(
Value,
"Always", FormatStyle::SIAS_Always);
700 IO.enumCase(
Value,
"Leave", FormatStyle::SIAS_Leave);
703 IO.enumCase(
Value,
"false", FormatStyle::SIAS_Never);
704 IO.enumCase(
Value,
"true", FormatStyle::SIAS_Always);
708template <>
struct MappingTraits<
FormatStyle::SpacesInLineComment> {
709 static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
711 int signedMaximum =
static_cast<int>(Space.Maximum);
712 IO.mapOptional(
"Minimum", Space.Minimum);
713 IO.mapOptional(
"Maximum", signedMaximum);
714 Space.Maximum =
static_cast<unsigned>(signedMaximum);
716 if (Space.Maximum != -1u)
717 Space.Minimum = std::min(Space.Minimum, Space.Maximum);
721template <>
struct MappingTraits<
FormatStyle::SpacesInParensCustom> {
722 static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) {
723 IO.mapOptional(
"InCStyleCasts", Spaces.InCStyleCasts);
724 IO.mapOptional(
"InConditionalStatements", Spaces.InConditionalStatements);
725 IO.mapOptional(
"InEmptyParentheses", Spaces.InEmptyParentheses);
726 IO.mapOptional(
"Other", Spaces.Other);
730template <>
struct ScalarEnumerationTraits<
FormatStyle::SpacesInParensStyle> {
732 IO.enumCase(
Value,
"Never", FormatStyle::SIPO_Never);
733 IO.enumCase(
Value,
"Custom", FormatStyle::SIPO_Custom);
737template <>
struct ScalarEnumerationTraits<
FormatStyle::TrailingCommaStyle> {
739 IO.enumCase(
Value,
"None", FormatStyle::TCS_None);
740 IO.enumCase(
Value,
"Wrapped", FormatStyle::TCS_Wrapped);
745struct ScalarEnumerationTraits<
FormatStyle::TrailingCommentsAlignmentKinds> {
747 FormatStyle::TrailingCommentsAlignmentKinds &
Value) {
748 IO.enumCase(
Value,
"Leave", FormatStyle::TCAS_Leave);
749 IO.enumCase(
Value,
"Always", FormatStyle::TCAS_Always);
750 IO.enumCase(
Value,
"Never", FormatStyle::TCAS_Never);
754template <>
struct MappingTraits<
FormatStyle::TrailingCommentsAlignmentStyle> {
756 FormatStyle::TrailingCommentsAlignmentStyle &
Value) {
757 IO.enumCase(
Value,
"Leave",
758 FormatStyle::TrailingCommentsAlignmentStyle(
759 {FormatStyle::TCAS_Leave, 0}));
761 IO.enumCase(
Value,
"Always",
762 FormatStyle::TrailingCommentsAlignmentStyle(
763 {FormatStyle::TCAS_Always, 0}));
765 IO.enumCase(
Value,
"Never",
766 FormatStyle::TrailingCommentsAlignmentStyle(
767 {FormatStyle::TCAS_Never, 0}));
770 IO.enumCase(
Value,
"true",
771 FormatStyle::TrailingCommentsAlignmentStyle(
772 {FormatStyle::TCAS_Always, 0}));
773 IO.enumCase(
Value,
"false",
774 FormatStyle::TrailingCommentsAlignmentStyle(
775 {FormatStyle::TCAS_Never, 0}));
779 FormatStyle::TrailingCommentsAlignmentStyle &
Value) {
780 IO.mapOptional(
"Kind",
Value.Kind);
781 IO.mapOptional(
"OverEmptyLines",
Value.OverEmptyLines);
785template <>
struct ScalarEnumerationTraits<
FormatStyle::UseTabStyle> {
787 IO.enumCase(
Value,
"Never", FormatStyle::UT_Never);
788 IO.enumCase(
Value,
"false", FormatStyle::UT_Never);
789 IO.enumCase(
Value,
"Always", FormatStyle::UT_Always);
790 IO.enumCase(
Value,
"true", FormatStyle::UT_Always);
791 IO.enumCase(
Value,
"ForIndentation", FormatStyle::UT_ForIndentation);
792 IO.enumCase(
Value,
"ForContinuationAndIndentation",
793 FormatStyle::UT_ForContinuationAndIndentation);
794 IO.enumCase(
Value,
"AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);
801 IO.mapOptional(
"Language", Style.
Language);
803 StringRef BasedOnStyle;
804 if (IO.outputting()) {
805 StringRef Styles[] = {
"LLVM",
"Google",
"Chromium",
"Mozilla",
806 "WebKit",
"GNU",
"Microsoft",
"clang-format"};
807 for (StringRef StyleName : Styles) {
809 if (getPredefinedStyle(StyleName, Style.
Language, &PredefinedStyle) &&
810 Style == PredefinedStyle) {
811 BasedOnStyle = StyleName;
816 IO.mapOptional(
"BasedOnStyle", BasedOnStyle);
817 if (!BasedOnStyle.empty()) {
818 FormatStyle::LanguageKind OldLanguage = Style.
Language;
819 FormatStyle::LanguageKind Language =
821 if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
822 IO.setError(Twine(
"Unknown value for BasedOnStyle: ", BasedOnStyle));
840 const bool IsGoogleOrChromium = BasedOnStyle.equals_insensitive(
"google") ||
841 BasedOnStyle.equals_insensitive(
"chromium");
842 bool OnCurrentLine = IsGoogleOrChromium;
843 bool OnNextLine =
true;
845 bool BreakBeforeInheritanceComma =
false;
846 bool BreakConstructorInitializersBeforeComma =
false;
848 bool DeriveLineEnding =
true;
849 bool UseCRLF =
false;
851 bool SpaceInEmptyParentheses =
false;
852 bool SpacesInConditionalStatement =
false;
853 bool SpacesInCStyleCastParentheses =
false;
854 bool SpacesInParentheses =
false;
857 if (!IO.outputting()) {
859 IO.mapOptional(
"AllowAllConstructorInitializersOnNextLine", OnNextLine);
861 IO.mapOptional(
"AlwaysBreakTemplateDeclarations",
863 IO.mapOptional(
"BreakBeforeInheritanceComma",
864 BreakBeforeInheritanceComma);
865 IO.mapOptional(
"BreakConstructorInitializersBeforeComma",
866 BreakConstructorInitializersBeforeComma);
867 IO.mapOptional(
"ConstructorInitializerAllOnOneLineOrOnePerLine",
869 IO.mapOptional(
"DeriveLineEnding", DeriveLineEnding);
871 IO.mapOptional(
"IndentFunctionDeclarationAfterType",
875 IO.mapOptional(
"SpaceAfterControlStatementKeyword",
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);
889 IO.mapOptional(
"AlignConsecutiveAssignments",
891 IO.mapOptional(
"AlignConsecutiveBitFields",
893 IO.mapOptional(
"AlignConsecutiveDeclarations",
896 IO.mapOptional(
"AlignConsecutiveShortCaseStatements",
898 IO.mapOptional(
"AlignConsecutiveTableGenBreakingDAGArgColons",
900 IO.mapOptional(
"AlignConsecutiveTableGenCondOperatorColons",
902 IO.mapOptional(
"AlignConsecutiveTableGenDefinitionColons",
907 IO.mapOptional(
"AllowAllArgumentsOnNextLine",
909 IO.mapOptional(
"AllowAllParametersOfDeclarationOnNextLine",
911 IO.mapOptional(
"AllowBreakBeforeNoexceptSpecifier",
913 IO.mapOptional(
"AllowShortBlocksOnASingleLine",
915 IO.mapOptional(
"AllowShortCaseExpressionOnASingleLine",
917 IO.mapOptional(
"AllowShortCaseLabelsOnASingleLine",
919 IO.mapOptional(
"AllowShortCompoundRequirementOnASingleLine",
921 IO.mapOptional(
"AllowShortEnumsOnASingleLine",
923 IO.mapOptional(
"AllowShortFunctionsOnASingleLine",
925 IO.mapOptional(
"AllowShortIfStatementsOnASingleLine",
927 IO.mapOptional(
"AllowShortLambdasOnASingleLine",
929 IO.mapOptional(
"AllowShortLoopsOnASingleLine",
931 IO.mapOptional(
"AlwaysBreakAfterDefinitionReturnType",
933 IO.mapOptional(
"AlwaysBreakBeforeMultilineStrings",
939 IO.mapOptional(
"BracedInitializerIndentWidth",
942 IO.mapOptional(
"BreakAdjacentStringLiterals",
945 IO.mapOptional(
"BreakAfterJavaFieldAnnotations",
949 IO.mapOptional(
"BreakBeforeBinaryOperators",
951 IO.mapOptional(
"BreakBeforeConceptDeclarations",
954 IO.mapOptional(
"BreakBeforeInlineASMColon",
956 IO.mapOptional(
"BreakBeforeTernaryOperators",
958 IO.mapOptional(
"BreakConstructorInitializers",
960 IO.mapOptional(
"BreakFunctionDefinitionParameters",
964 IO.mapOptional(
"BreakTemplateDeclarations",
969 IO.mapOptional(
"ConstructorInitializerIndentWidth",
975 IO.mapOptional(
"EmptyLineAfterAccessModifier",
977 IO.mapOptional(
"EmptyLineBeforeAccessModifier",
979 IO.mapOptional(
"ExperimentalAutoDetectBinPacking",
983 IO.mapOptional(
"IfMacros", Style.
IfMacros);
987 IO.mapOptional(
"IncludeIsMainSourceRegex",
997 IO.mapOptional(
"IndentWrappedFunctionNames",
1006 IO.mapOptional(
"KeepEmptyLinesAtTheStartOfBlocks",
1010 IO.mapOptional(
"LineEnding", Style.
LineEnding);
1013 IO.mapOptional(
"Macros", Style.
Macros);
1020 IO.mapOptional(
"ObjCBreakBeforeNestedBlockParam",
1022 IO.mapOptional(
"ObjCPropertyAttributeOrder",
1025 IO.mapOptional(
"ObjCSpaceBeforeProtocolList",
1027 IO.mapOptional(
"PackConstructorInitializers",
1030 IO.mapOptional(
"PenaltyBreakBeforeFirstCallParameter",
1033 IO.mapOptional(
"PenaltyBreakFirstLessLess",
1035 IO.mapOptional(
"PenaltyBreakOpenParenthesis",
1037 IO.mapOptional(
"PenaltyBreakScopeResolution",
1040 IO.mapOptional(
"PenaltyBreakTemplateDeclaration",
1043 IO.mapOptional(
"PenaltyIndentedWhitespace",
1045 IO.mapOptional(
"PenaltyReturnTypeOnItsOwnLine",
1064 IO.mapOptional(
"RequiresExpressionIndentation",
1074 IO.mapOptional(
"SpaceAfterTemplateKeyword",
1076 IO.mapOptional(
"SpaceAroundPointerQualifiers",
1078 IO.mapOptional(
"SpaceBeforeAssignmentOperators",
1081 IO.mapOptional(
"SpaceBeforeCpp11BracedList",
1083 IO.mapOptional(
"SpaceBeforeCtorInitializerColon",
1085 IO.mapOptional(
"SpaceBeforeInheritanceColon",
1090 IO.mapOptional(
"SpaceBeforeRangeBasedForLoopColon",
1092 IO.mapOptional(
"SpaceBeforeSquareBrackets",
1095 IO.mapOptional(
"SpacesBeforeTrailingComments",
1098 IO.mapOptional(
"SpacesInContainerLiterals",
1100 IO.mapOptional(
"SpacesInLineCommentPrefix",
1105 IO.mapOptional(
"Standard", Style.
Standard);
1106 IO.mapOptional(
"StatementAttributeLikeMacros",
1109 IO.mapOptional(
"TableGenBreakingDAGArgOperators",
1111 IO.mapOptional(
"TableGenBreakInsideDAGArg",
1113 IO.mapOptional(
"TabWidth", Style.
TabWidth);
1114 IO.mapOptional(
"TypeNames", Style.
TypeNames);
1116 IO.mapOptional(
"UseTab", Style.
UseTab);
1117 IO.mapOptional(
"VerilogBreakBetweenInstancePorts",
1119 IO.mapOptional(
"WhitespaceSensitiveMacros",
1128 FormatStyle::DRTBS_All) {
1131 FormatStyle::DRTBS_TopLevel) {
1138 if (BreakBeforeInheritanceComma &&
1146 if (BreakConstructorInitializersBeforeComma &&
1151 if (!IsGoogleOrChromium) {
1155 ? FormatStyle::PCIS_NextLine
1156 : FormatStyle::PCIS_CurrentLine;
1159 FormatStyle::PCIS_NextLine) {
1162 else if (!OnNextLine)
1166 if (Style.
LineEnding == FormatStyle::LE_DeriveLF) {
1167 if (!DeriveLineEnding)
1168 Style.
LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF;
1170 Style.
LineEnding = FormatStyle::LE_DeriveCRLF;
1174 (SpacesInParentheses || SpaceInEmptyParentheses ||
1175 SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) {
1176 if (SpacesInParentheses) {
1181 SpacesInCStyleCastParentheses;
1183 SpaceInEmptyParentheses;
1188 SpacesInConditionalStatement;
1190 SpacesInCStyleCastParentheses;
1192 SpaceInEmptyParentheses;
1204template <>
struct DocumentListTraits<
std::vector<FormatStyle>> {
1205 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
1210 if (Index >= Seq.size()) {
1211 assert(Index == Seq.size());
1213 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
1216 Template = *((
const FormatStyle *)IO.getContext());
1217 Template.
Language = FormatStyle::LK_None;
1219 Seq.resize(Index + 1, Template);
1239 return llvm::make_error<llvm::StringError>(Message,
1240 llvm::inconvertibleErrorCode());
1244 return "clang-format.parse_error";
1252 return "Invalid argument";
1254 return "Unsuitable";
1256 return "trailing comma insertion cannot be used with bin packing";
1258 return "Invalid qualifier specified in QualifierOrder";
1260 return "Duplicate qualifier specified in QualifierOrder";
1262 return "Missing type in QualifierOrder";
1264 return "Missing QualifierOrder";
1266 llvm_unreachable(
"unexpected parse error");
1492 LLVMStyle.
IfMacros.push_back(
"KJ_IF_MAYBE");
1495 {
"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0,
false},
1496 {
"^(<|\"(gtest|gmock|isl|json)/)", 3, 0,
false},
1497 {
".*", 1, 0,
false}};
1638 {
"^<.*\\.h>", 1, 0,
false},
1639 {
"^<.*", 2, 0,
false},
1640 {
".*", 3, 0,
false}};
1680 "PARSE_PARTIAL_TEXT_PROTO",
1684 "ParseTextProtoOrDie",
1686 "ParsePartialTestProto",
1798 "com.google.android.apps.chrome",
1817 return ChromiumStyle;
1843 return MozillaStyle;
1937 if (Name.equals_insensitive(
"llvm"))
1939 else if (Name.equals_insensitive(
"chromium"))
1941 else if (Name.equals_insensitive(
"mozilla"))
1943 else if (Name.equals_insensitive(
"google"))
1945 else if (Name.equals_insensitive(
"webkit"))
1947 else if (Name.equals_insensitive(
"gnu"))
1949 else if (Name.equals_insensitive(
"microsoft"))
1951 else if (Name.equals_insensitive(
"clang-format"))
1953 else if (Name.equals_insensitive(
"none"))
1955 else if (Name.equals_insensitive(
"inheritparentconfig"))
1971 if (Qualifier ==
"type")
1975 if (token == tok::identifier)
1980 std::set<std::string> UniqueQualifiers(Style->
QualifierOrder.begin(),
1983 LLVM_DEBUG(llvm::dbgs()
1985 <<
" vs " << UniqueQualifiers.size() <<
"\n");
1998 llvm::SourceMgr::DiagHandlerTy DiagHandler,
1999 void *DiagHandlerCtxt) {
2003 if (Config.getBuffer().trim().empty())
2005 Style->StyleSet.
Clear();
2006 std::vector<FormatStyle> Styles;
2007 llvm::yaml::Input Input(Config,
nullptr, DiagHandler,
2013 Input.setContext(Style);
2014 Input.setAllowUnknownKeys(AllowUnknownOptions);
2017 return Input.error();
2019 for (
unsigned i = 0; i < Styles.size(); ++i) {
2024 for (
unsigned j = 0; j < i; ++j) {
2026 LLVM_DEBUG(llvm::dbgs()
2027 <<
"Duplicate languages in the config file on positions "
2028 << j <<
" and " << i <<
"\n");
2037 bool LanguageFound =
false;
2038 for (
const FormatStyle &Style : llvm::reverse(Styles)) {
2040 StyleSet.
Add(Style);
2042 LanguageFound =
true;
2044 if (!LanguageFound) {
2049 StyleSet.
Add(std::move(DefaultStyle));
2064 llvm::raw_string_ostream Stream(
Text);
2065 llvm::yaml::Output Output(Stream);
2072 Output << NonConstStyle;
2074 return Stream.str();
2077std::optional<FormatStyle>
2080 return std::nullopt;
2082 if (It == Styles->end())
2083 return std::nullopt;
2085 Style.StyleSet = *
this;
2091 "Cannot add a style for LK_None to a StyleSet");
2093 !Style.StyleSet.Styles &&
2094 "Cannot add a style associated with an existing StyleSet to a StyleSet");
2096 Styles = std::make_shared<MapType>();
2097 (*Styles)[Style.
Language] = std::move(Style);
2102std::optional<FormatStyle>
2114 std::pair<tooling::Replacements, unsigned>
2115 analyze(TokenAnnotator &Annotator,
2117 FormatTokenLexer &Tokens)
override {
2118 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2120 removeParens(AnnotatedLines, Result);
2125 void removeParens(SmallVectorImpl<AnnotatedLine *> &Lines,
2126 tooling::Replacements &Result) {
2127 const auto &SourceMgr =
Env.getSourceManager();
2128 for (
auto *Line : Lines) {
2129 removeParens(Line->Children, Result);
2130 if (!Line->Affected)
2132 for (
const auto *Token = Line->First; Token && !Token->Finalized;
2133 Token = Token->Next) {
2134 if (!Token->Optional || !Token->isOneOf(tok::l_paren, tok::r_paren))
2136 auto *Next = Token->Next;
2137 assert(Next && Next->isNot(tok::eof));
2138 SourceLocation Start;
2139 if (Next->NewlinesBefore == 0) {
2140 Start = Token->Tok.getLocation();
2141 Next->WhitespaceRange = Token->WhitespaceRange;
2143 Start = Token->WhitespaceRange.getBegin();
2146 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2147 cantFail(Result.add(tooling::Replacement(SourceMgr,
Range,
" ")));
2153class BracesInserter :
public TokenAnalyzer {
2156 : TokenAnalyzer(
Env, Style) {}
2158 std::pair<tooling::Replacements, unsigned>
2159 analyze(TokenAnnotator &Annotator,
2160 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2161 FormatTokenLexer &Tokens)
override {
2162 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2163 tooling::Replacements Result;
2164 insertBraces(AnnotatedLines, Result);
2169 void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2170 tooling::Replacements &Result) {
2171 const auto &SourceMgr =
Env.getSourceManager();
2172 int OpeningBraceSurplus = 0;
2173 for (AnnotatedLine *Line : Lines) {
2174 insertBraces(Line->Children, Result);
2175 if (!Line->Affected && OpeningBraceSurplus == 0)
2177 for (FormatToken *Token = Line->First; Token && !Token->Finalized;
2178 Token = Token->Next) {
2179 int BraceCount = Token->BraceCount;
2180 if (BraceCount == 0)
2183 if (BraceCount < 0) {
2184 assert(BraceCount == -1);
2185 if (!Line->Affected)
2187 Brace = Token->is(tok::comment) ?
"\n{" :
"{";
2188 ++OpeningBraceSurplus;
2190 if (OpeningBraceSurplus == 0)
2192 if (OpeningBraceSurplus < BraceCount)
2193 BraceCount = OpeningBraceSurplus;
2194 Brace =
'\n' + std::string(BraceCount,
'}');
2195 OpeningBraceSurplus -= BraceCount;
2197 Token->BraceCount = 0;
2198 const auto Start = Token->Tok.getEndLoc();
2199 cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0,
Brace)));
2202 assert(OpeningBraceSurplus == 0);
2206class BracesRemover :
public TokenAnalyzer {
2209 : TokenAnalyzer(
Env, Style) {}
2211 std::pair<tooling::Replacements, unsigned>
2212 analyze(TokenAnnotator &Annotator,
2213 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2214 FormatTokenLexer &Tokens)
override {
2215 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2216 tooling::Replacements Result;
2217 removeBraces(AnnotatedLines, Result);
2222 void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2223 tooling::Replacements &Result) {
2224 const auto &SourceMgr =
Env.getSourceManager();
2225 const auto End = Lines.end();
2226 for (
auto I = Lines.begin(); I != End; ++I) {
2227 const auto Line = *I;
2228 removeBraces(Line->Children, Result);
2229 if (!Line->Affected)
2231 const auto NextLine = I + 1 == End ? nullptr : I[1];
2232 for (
auto Token = Line->First; Token && !Token->Finalized;
2233 Token = Token->Next) {
2234 if (!Token->Optional)
2236 if (!Token->isOneOf(tok::l_brace, tok::r_brace))
2238 auto Next = Token->Next;
2239 assert(Next || Token == Line->Last);
2240 if (!Next && NextLine)
2241 Next = NextLine->First;
2242 SourceLocation Start;
2243 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2244 Start = Token->Tok.getLocation();
2245 Next->WhitespaceRange = Token->WhitespaceRange;
2247 Start = Token->WhitespaceRange.getBegin();
2250 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2251 cantFail(Result.add(tooling::Replacement(SourceMgr,
Range,
"")));
2257class SemiRemover :
public TokenAnalyzer {
2260 : TokenAnalyzer(
Env, Style) {}
2262 std::pair<tooling::Replacements, unsigned>
2263 analyze(TokenAnnotator &Annotator,
2264 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2265 FormatTokenLexer &Tokens)
override {
2266 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2267 tooling::Replacements Result;
2268 removeSemi(Annotator, AnnotatedLines, Result);
2273 void removeSemi(TokenAnnotator &Annotator,
2274 SmallVectorImpl<AnnotatedLine *> &Lines,
2275 tooling::Replacements &Result) {
2276 auto PrecededByFunctionRBrace = [](
const FormatToken &Tok) {
2277 const auto *Prev = Tok.Previous;
2278 if (!Prev || Prev->isNot(tok::r_brace))
2280 const auto *LBrace = Prev->MatchingParen;
2281 return LBrace && LBrace->is(TT_FunctionLBrace);
2283 const auto &SourceMgr =
Env.getSourceManager();
2284 const auto End = Lines.end();
2285 for (
auto I = Lines.begin(); I != End; ++I) {
2286 const auto Line = *I;
2287 removeSemi(Annotator, Line->Children, Result);
2288 if (!Line->Affected)
2290 Annotator.calculateFormattingInformation(*Line);
2291 const auto NextLine = I + 1 == End ? nullptr : I[1];
2292 for (
auto Token = Line->First; Token && !Token->Finalized;
2293 Token = Token->Next) {
2294 if (Token->isNot(tok::semi) ||
2295 (!Token->Optional && !PrecededByFunctionRBrace(*Token))) {
2298 auto Next = Token->Next;
2299 assert(Next || Token == Line->Last);
2300 if (!Next && NextLine)
2301 Next = NextLine->First;
2302 SourceLocation Start;
2303 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2304 Start = Token->Tok.getLocation();
2305 Next->WhitespaceRange = Token->WhitespaceRange;
2307 Start = Token->WhitespaceRange.getBegin();
2310 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2311 cantFail(Result.add(tooling::Replacement(SourceMgr,
Range,
"")));
2317class JavaScriptRequoter :
public TokenAnalyzer {
2319 JavaScriptRequoter(
const Environment &
Env,
const FormatStyle &Style)
2320 : TokenAnalyzer(
Env, Style) {}
2322 std::pair<tooling::Replacements, unsigned>
2323 analyze(TokenAnnotator &Annotator,
2324 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2325 FormatTokenLexer &Tokens)
override {
2326 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2327 tooling::Replacements Result;
2328 requoteJSStringLiteral(AnnotatedLines, Result);
2335 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
2336 tooling::Replacements &Result) {
2337 for (AnnotatedLine *Line : Lines) {
2338 requoteJSStringLiteral(Line->Children, Result);
2339 if (!Line->Affected)
2341 for (FormatToken *FormatTok = Line->First; FormatTok;
2342 FormatTok = FormatTok->Next) {
2343 StringRef Input = FormatTok->TokenText;
2344 if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
2348 !Input.starts_with(
"\"")) ||
2350 !Input.starts_with(
"\'"))) {
2356 SourceLocation Start = FormatTok->Tok.getLocation();
2357 auto Replace = [&](SourceLocation Start,
unsigned Length,
2358 StringRef ReplacementText) {
2359 auto Err = Result.add(tooling::Replacement(
2360 Env.getSourceManager(), Start, Length, ReplacementText));
2364 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
2368 Replace(Start, 1, IsSingle ?
"'" :
"\"");
2369 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
2370 IsSingle ?
"'" :
"\"");
2373 bool Escaped =
false;
2374 for (
size_t i = 1; i < Input.size() - 1; i++) {
2377 if (!Escaped && i + 1 < Input.size() &&
2378 ((IsSingle && Input[i + 1] ==
'"') ||
2379 (!IsSingle && Input[i + 1] ==
'\''))) {
2382 Replace(Start.getLocWithOffset(i), 1,
"");
2389 if (!Escaped && IsSingle == (Input[i] ==
'\'')) {
2391 Replace(Start.getLocWithOffset(i), 0,
"\\");
2405class Formatter :
public TokenAnalyzer {
2408 FormattingAttemptStatus *Status)
2409 : TokenAnalyzer(
Env, Style), Status(Status) {}
2411 std::pair<tooling::Replacements, unsigned>
2412 analyze(TokenAnnotator &Annotator,
2413 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2414 FormatTokenLexer &Tokens)
override {
2415 tooling::Replacements Result;
2416 deriveLocalStyle(AnnotatedLines);
2417 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2418 for (AnnotatedLine *Line : AnnotatedLines)
2419 Annotator.calculateFormattingInformation(*Line);
2420 Annotator.setCommentLineLevels(AnnotatedLines);
2422 WhitespaceManager Whitespaces(
2423 Env.getSourceManager(), Style,
2425 ? WhitespaceManager::inputUsesCRLF(
2426 Env.getSourceManager().getBufferData(
Env.getFileID()),
2427 Style.
LineEnding == FormatStyle::LE_DeriveCRLF)
2429 ContinuationIndenter
Indenter(Style, Tokens.getKeywords(),
2430 Env.getSourceManager(), Whitespaces, Encoding,
2431 BinPackInconclusiveFunctions);
2433 UnwrappedLineFormatter(&
Indenter, &Whitespaces, Style,
2434 Tokens.getKeywords(),
Env.getSourceManager(),
2436 .format(AnnotatedLines,
false,
2439 Env.getFirstStartColumn(),
2440 Env.getNextStartColumn(),
2441 Env.getLastStartColumn());
2442 for (
const auto &R : Whitespaces.generateReplacements())
2444 return std::make_pair(Result, 0);
2445 return std::make_pair(Result, Penalty);
2450 hasCpp03IncompatibleFormat(
const SmallVectorImpl<AnnotatedLine *> &Lines) {
2451 for (
const AnnotatedLine *Line : Lines) {
2452 if (hasCpp03IncompatibleFormat(Line->Children))
2454 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {
2455 if (!Tok->hasWhitespaceBefore()) {
2456 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
2458 if (Tok->is(TT_TemplateCloser) &&
2459 Tok->Previous->is(TT_TemplateCloser)) {
2468 int countVariableAlignments(
const SmallVectorImpl<AnnotatedLine *> &Lines) {
2469 int AlignmentDiff = 0;
2470 for (
const AnnotatedLine *Line : Lines) {
2471 AlignmentDiff += countVariableAlignments(Line->Children);
2472 for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {
2473 if (Tok->isNot(TT_PointerOrReference))
2476 if (
const auto *Prev = Tok->getPreviousNonComment()) {
2477 if (Prev->is(tok::r_paren) && Prev->MatchingParen) {
2478 if (
const auto *Func =
2479 Prev->MatchingParen->getPreviousNonComment()) {
2480 if (
Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName,
2481 TT_OverloadedOperator)) {
2487 bool SpaceBefore = Tok->hasWhitespaceBefore();
2488 bool SpaceAfter = Tok->Next->hasWhitespaceBefore();
2489 if (SpaceBefore && !SpaceAfter)
2491 if (!SpaceBefore && SpaceAfter)
2495 return AlignmentDiff;
2499 deriveLocalStyle(
const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2500 bool HasBinPackedFunction =
false;
2501 bool HasOnePerLineFunction =
false;
2502 for (AnnotatedLine *Line : AnnotatedLines) {
2503 if (!Line->First->Next)
2505 FormatToken *Tok = Line->First->Next;
2507 if (Tok->is(PPK_BinPacked))
2508 HasBinPackedFunction =
true;
2509 if (Tok->is(PPK_OnePerLine))
2510 HasOnePerLineFunction =
true;
2516 const auto NetRightCount = countVariableAlignments(AnnotatedLines);
2517 if (NetRightCount > 0)
2519 else if (NetRightCount < 0)
2523 if (Style.
Standard == FormatStyle::LS_Auto) {
2524 Style.
Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
2525 ? FormatStyle::LS_Latest
2526 : FormatStyle::LS_Cpp03;
2528 BinPackInconclusiveFunctions =
2529 HasBinPackedFunction || !HasOnePerLineFunction;
2532 bool BinPackInconclusiveFunctions;
2533 FormattingAttemptStatus *Status;
2547class TrailingCommaInserter :
public TokenAnalyzer {
2549 TrailingCommaInserter(
const Environment &
Env,
const FormatStyle &Style)
2550 : TokenAnalyzer(
Env, Style) {}
2552 std::pair<tooling::Replacements, unsigned>
2553 analyze(TokenAnnotator &Annotator,
2554 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2555 FormatTokenLexer &Tokens)
override {
2556 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2557 tooling::Replacements Result;
2558 insertTrailingCommas(AnnotatedLines, Result);
2565 void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,
2566 tooling::Replacements &Result) {
2567 for (AnnotatedLine *Line : Lines) {
2568 insertTrailingCommas(Line->Children, Result);
2569 if (!Line->Affected)
2571 for (FormatToken *FormatTok = Line->First; FormatTok;
2572 FormatTok = FormatTok->Next) {
2573 if (FormatTok->NewlinesBefore == 0)
2575 FormatToken *Matching = FormatTok->MatchingParen;
2576 if (!Matching || !FormatTok->getPreviousNonComment())
2578 if (!(FormatTok->is(tok::r_square) &&
2579 Matching->is(TT_ArrayInitializerLSquare)) &&
2580 !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) {
2583 FormatToken *Prev = FormatTok->getPreviousNonComment();
2584 if (Prev->is(tok::comma) || Prev->is(tok::semi))
2588 SourceLocation Start =
2589 Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size());
2593 unsigned ColumnNumber =
2594 Env.getSourceManager().getSpellingColumnNumber(Start);
2599 cantFail(Result.add(
2600 tooling::Replacement(
Env.getSourceManager(), Start, 0,
",")));
2608class Cleaner :
public TokenAnalyzer {
2611 : TokenAnalyzer(
Env, Style),
2612 DeletedTokens(FormatTokenLess(
Env.getSourceManager())) {}
2615 std::pair<tooling::Replacements, unsigned>
2616 analyze(TokenAnnotator &Annotator,
2617 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2618 FormatTokenLexer &Tokens)
override {
2626 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2628 checkEmptyNamespace(AnnotatedLines);
2630 for (
auto *Line : AnnotatedLines)
2633 return {generateFixes(), 0};
2637 void cleanupLine(AnnotatedLine *Line) {
2638 for (
auto *Child : Line->Children)
2641 if (Line->Affected) {
2642 cleanupRight(Line->First, tok::comma, tok::comma);
2643 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
2644 cleanupRight(Line->First, tok::l_paren, tok::comma);
2645 cleanupLeft(Line->First, tok::comma, tok::r_paren);
2646 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
2647 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
2648 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
2652 bool containsOnlyComments(
const AnnotatedLine &Line) {
2653 for (FormatToken *Tok = Line.First; Tok; Tok = Tok->Next)
2654 if (Tok->isNot(tok::comment))
2660 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2661 std::set<unsigned> DeletedLines;
2662 for (
unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
2663 auto &Line = *AnnotatedLines[i];
2664 if (Line.startsWithNamespace())
2665 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
2668 for (
auto Line : DeletedLines) {
2669 FormatToken *Tok = AnnotatedLines[Line]->First;
2681 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2682 unsigned CurrentLine,
unsigned &
NewLine,
2683 std::set<unsigned> &DeletedLines) {
2684 unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
2689 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
2693 }
else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
2696 while (++CurrentLine < End) {
2697 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
2700 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
2701 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine,
NewLine,
2709 if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
2719 if (CurrentLine >= End)
2723 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
2724 AnnotatedLines[InitLine]->First->Tok.getLocation(),
2725 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) {
2729 for (
unsigned i = InitLine; i <= CurrentLine; ++i)
2730 DeletedLines.insert(i);
2739 template <
typename LeftKind,
typename RightKind>
2740 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
2742 auto NextNotDeleted = [
this](
const FormatToken &Tok) -> FormatToken * {
2743 for (
auto *Res = Tok.Next; Res; Res = Res->Next) {
2744 if (Res->isNot(tok::comment) &&
2745 DeletedTokens.find(Res) == DeletedTokens.end()) {
2751 for (
auto *Left = Start; Left;) {
2752 auto *Right = NextNotDeleted(*Left);
2755 if (Left->is(LK) && Right->is(RK)) {
2756 deleteToken(DeleteLeft ? Left : Right);
2757 for (
auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
2768 template <
typename LeftKind,
typename RightKind>
2769 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
2770 cleanupPair(Start, LK, RK,
true);
2773 template <
typename LeftKind,
typename RightKind>
2774 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
2775 cleanupPair(Start, LK, RK,
false);
2779 inline void deleteToken(FormatToken *Tok) {
2781 DeletedTokens.insert(Tok);
2784 tooling::Replacements generateFixes() {
2785 tooling::Replacements Fixes;
2786 SmallVector<FormatToken *> Tokens;
2787 std::copy(DeletedTokens.begin(), DeletedTokens.end(),
2788 std::back_inserter(Tokens));
2794 while (Idx < Tokens.size()) {
2795 unsigned St = Idx, End = Idx;
2796 while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1])
2798 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
2799 Tokens[End]->Tok.getEndLoc());
2801 Fixes.add(tooling::Replacement(
Env.getSourceManager(), SR,
""));
2805 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
2806 assert(
false &&
"Fixes must not conflict!");
2817 struct FormatTokenLess {
2818 FormatTokenLess(
const SourceManager &
SM) :
SM(
SM) {}
2820 bool operator()(
const FormatToken *LHS,
const FormatToken *RHS)
const {
2821 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
2822 RHS->Tok.getLocation());
2828 std::set<FormatToken *, FormatTokenLess> DeletedTokens;
2831class ObjCHeaderStyleGuesser :
public TokenAnalyzer {
2833 ObjCHeaderStyleGuesser(
const Environment &
Env,
const FormatStyle &Style)
2834 : TokenAnalyzer(
Env, Style), IsObjC(
false) {}
2836 std::pair<tooling::Replacements, unsigned>
2837 analyze(TokenAnnotator &Annotator,
2838 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2839 FormatTokenLexer &Tokens)
override {
2840 assert(Style.
Language == FormatStyle::LK_Cpp);
2841 IsObjC = guessIsObjC(
Env.getSourceManager(), AnnotatedLines,
2842 Tokens.getKeywords());
2843 tooling::Replacements Result;
2847 bool isObjC() {
return IsObjC; }
2851 guessIsObjC(
const SourceManager &SourceManager,
2852 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2853 const AdditionalKeywords &Keywords) {
2855 static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
2870 "FOUNDATION_EXPORT",
2871 "FOUNDATION_EXTERN",
2872 "NSAffineTransform",
2874 "NSAttributedString",
2893 "NSInvocationOperation",
2897 "NSMutableAttributedString",
2898 "NSMutableCharacterSet",
2900 "NSMutableDictionary",
2901 "NSMutableIndexSet",
2902 "NSMutableOrderedSet",
2906 "NSNumberFormatter",
2910 "NSOperationQueuePriority",
2914 "NSQualityOfService",
2917 "NSRegularExpression",
2928 "NS_ASSUME_NONNULL_BEGIN",
2933 for (
auto *Line : AnnotatedLines) {
2934 if (Line->First && (Line->First->TokenText.starts_with(
"#") ||
2935 Line->First->TokenText ==
"__pragma" ||
2936 Line->First->TokenText ==
"_Pragma")) {
2939 for (
const FormatToken *FormatTok = Line->First; FormatTok;
2940 FormatTok = FormatTok->Next) {
2941 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
2942 (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
2943 FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
2945 (FormatTok->Tok.isAnyIdentifier() &&
2946 std::binary_search(std::begin(FoundationIdentifiers),
2947 std::end(FoundationIdentifiers),
2948 FormatTok->TokenText)) ||
2949 FormatTok->is(TT_ObjCStringLiteral) ||
2950 FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,
2951 Keywords.kw_NS_ERROR_ENUM,
2952 Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,
2953 TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,
2954 TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,
2956 LLVM_DEBUG(llvm::dbgs()
2957 <<
"Detected ObjC at location "
2958 << FormatTok->Tok.getLocation().printToString(
2960 <<
" token: " << FormatTok->TokenText <<
" token type: "
2965 if (guessIsObjC(SourceManager, Line->Children, Keywords))
2982struct JavaImportDirective {
2995 for (
const auto &
Range : Ranges) {
2996 if (
Range.getOffset() < End &&
2997 Range.getOffset() +
Range.getLength() > Start) {
3011static std::pair<unsigned, unsigned>
3015 unsigned OffsetToEOL = 0;
3016 for (
int i = 0, e = Includes.size(); i != e; ++i) {
3017 unsigned Start = Includes[Indices[i]].Offset;
3018 unsigned End = Start + Includes[Indices[i]].Text.size();
3019 if (!(Cursor >= Start && Cursor < End))
3021 CursorIndex = Indices[i];
3022 OffsetToEOL = End - Cursor;
3025 while (--i >= 0 && Includes[CursorIndex].
Text == Includes[Indices[i]].
Text)
3029 return std::make_pair(CursorIndex, OffsetToEOL);
3034 std::string NewCode;
3035 size_t Pos = 0, LastPos = 0;
3038 Pos = Code.find(
"\r\n", LastPos);
3039 if (Pos == LastPos) {
3043 if (Pos == std::string::npos) {
3044 NewCode += Code.substr(LastPos);
3047 NewCode += Code.substr(LastPos, Pos - LastPos) +
"\n";
3049 }
while (Pos != std::string::npos);
3067 const unsigned IncludesBeginOffset = Includes.front().Offset;
3068 const unsigned IncludesEndOffset =
3069 Includes.back().Offset + Includes.back().Text.size();
3070 const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
3071 if (!
affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
3074 llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size()));
3077 llvm::stable_sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
3078 const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
3079 const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
3080 return std::tie(Includes[LHSI].
Priority, LHSFilenameLower,
3082 std::tie(Includes[RHSI].
Priority, RHSFilenameLower,
3086 llvm::stable_sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
3094 unsigned CursorIndex;
3096 unsigned CursorToEOLOffset;
3098 std::tie(CursorIndex, CursorToEOLOffset) =
3103 Indices.erase(std::unique(Indices.begin(), Indices.end(),
3104 [&](
unsigned LHSI,
unsigned RHSI) {
3105 return Includes[LHSI].Text.trim() ==
3106 Includes[RHSI].Text.trim();
3110 int CurrentCategory = Includes.front().Category;
3118 if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) &&
3123 const auto OldCursor = Cursor ? *Cursor : 0;
3125 for (
unsigned Index : Indices) {
3126 if (!result.empty()) {
3130 CurrentCategory != Includes[Index].Category) {
3134 result += Includes[Index].Text;
3135 if (Cursor && CursorIndex == Index)
3136 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
3137 CurrentCategory = Includes[Index].Category;
3140 if (Cursor && *Cursor >= IncludesEndOffset)
3141 *Cursor += result.size() - IncludesBlockSize;
3146 IncludesBeginOffset, IncludesBlockSize)))) {
3148 *Cursor = OldCursor;
3153 FileName, Includes.front().Offset, IncludesBlockSize, result));
3157 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
3167 unsigned Prev = llvm::StringSwitch<size_t>(Code)
3168 .StartsWith(
"\xEF\xBB\xBF", 3)
3170 unsigned SearchFrom = 0;
3182 bool FirstIncludeBlock =
true;
3183 bool MainIncludeFound =
false;
3184 bool FormattingOff =
false;
3187 llvm::Regex RawStringRegex(
3188 "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\(");
3190 std::string RawStringTermination =
")\"";
3193 auto Pos = Code.find(
'\n', SearchFrom);
3195 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3197 StringRef Trimmed =
Line.trim();
3202 if (RawStringRegex.match(Trimmed, &RawStringMatches)) {
3203 std::string CharSequence = RawStringMatches[1].str();
3204 RawStringTermination =
")" + CharSequence +
"\"";
3205 FormattingOff =
true;
3208 if (Trimmed.contains(RawStringTermination))
3209 FormattingOff =
false;
3212 FormattingOff =
true;
3214 FormattingOff =
false;
3216 const bool EmptyLineSkipped =
3222 bool MergeWithNextLine = Trimmed.ends_with(
"\\");
3223 if (!FormattingOff && !MergeWithNextLine) {
3225 StringRef IncludeName = Matches[2];
3226 if (
Line.contains(
"/*") && !
Line.contains(
"*/")) {
3231 Pos = Code.find(
"*/", SearchFrom);
3233 Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev);
3237 !MainIncludeFound && FirstIncludeBlock);
3239 IncludeName, !MainIncludeFound && FirstIncludeBlock);
3241 MainIncludeFound =
true;
3242 IncludesInBlock.push_back(
3244 }
else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
3247 IncludesInBlock.clear();
3248 if (Trimmed.starts_with(
"#pragma hdrstop"))
3249 FirstIncludeBlock =
true;
3251 FirstIncludeBlock =
false;
3254 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3257 if (!MergeWithNextLine)
3259 SearchFrom = Pos + 1;
3261 if (!IncludesInBlock.empty()) {
3271 StringRef ImportIdentifier) {
3272 unsigned LongestMatchIndex =
UINT_MAX;
3273 unsigned LongestMatchLength = 0;
3276 if (ImportIdentifier.starts_with(GroupPrefix) &&
3277 GroupPrefix.length() > LongestMatchLength) {
3278 LongestMatchIndex = I;
3279 LongestMatchLength = GroupPrefix.length();
3282 return LongestMatchIndex;
3294 unsigned ImportsBeginOffset = Imports.front().Offset;
3295 unsigned ImportsEndOffset =
3296 Imports.back().Offset + Imports.back().Text.size();
3297 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;
3298 if (!
affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))
3302 llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size()));
3305 for (
const JavaImportDirective &Import : Imports)
3308 bool StaticImportAfterNormalImport =
3310 llvm::sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
3312 return std::make_tuple(!Imports[LHSI].
IsStatic ^
3313 StaticImportAfterNormalImport,
3315 std::make_tuple(!Imports[RHSI].
IsStatic ^
3316 StaticImportAfterNormalImport,
3321 Indices.erase(std::unique(Indices.begin(), Indices.end(),
3322 [&](
unsigned LHSI,
unsigned RHSI) {
3323 return Imports[LHSI].Text == Imports[RHSI].Text;
3327 bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
3331 for (
unsigned Index : Indices) {
3332 if (!result.empty()) {
3334 if (CurrentIsStatic != Imports[Index].
IsStatic ||
3340 result += CommentLine;
3343 result += Imports[Index].Text;
3344 CurrentIsStatic = Imports[Index].IsStatic;
3351 Imports.front().Offset, ImportsBlockSize)))) {
3356 ImportsBlockSize, result));
3360 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
3367const char JavaImportRegexPattern[] =
3368 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;";
3377 unsigned SearchFrom = 0;
3378 llvm::Regex ImportRegex(JavaImportRegexPattern);
3383 bool FormattingOff =
false;
3386 auto Pos = Code.find(
'\n', SearchFrom);
3388 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3390 StringRef Trimmed =
Line.trim();
3392 FormattingOff =
true;
3394 FormattingOff =
false;
3396 if (ImportRegex.match(
Line, &Matches)) {
3397 if (FormattingOff) {
3402 StringRef
Static = Matches[1];
3405 if (
Static.contains(
"static"))
3407 ImportsInBlock.push_back(
3410 }
else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) {
3415 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3417 SearchFrom = Pos + 1;
3419 if (!ImportsInBlock.empty())
3428 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
3431bool isLikelyXml(StringRef Code) {
return Code.ltrim().starts_with(
"<"); }
3435 StringRef
FileName,
unsigned *Cursor) {
3453template <
typename T>
3458 if (Replaces.
empty())
3461 auto NewCode = applyAllReplacements(Code, Replaces);
3463 return NewCode.takeError();
3468 ProcessFunc(Style, *NewCode, ChangedRanges,
FileName);
3470 return Replaces.
merge(FormatReplaces);
3479 std::vector<tooling::Range> Ranges,
3483 auto SortedReplaces =
3485 if (!SortedReplaces)
3486 return SortedReplaces.takeError();
3490 auto Reformat = [](
const FormatStyle &Style, StringRef Code,
3491 std::vector<tooling::Range> Ranges,
3506inline bool isHeaderDeletion(
const tooling::Replacement &Replace) {
3507 return Replace.getOffset() ==
UINT_MAX && Replace.getLength() == 1;
3511tooling::Replacements
3512fixCppIncludeInsertions(StringRef Code,
const tooling::Replacements &Replaces,
3517 tooling::Replacements HeaderInsertions;
3518 std::set<llvm::StringRef> HeadersToDelete;
3519 tooling::Replacements
Result;
3520 for (
const auto &R : Replaces) {
3521 if (isHeaderInsertion(R)) {
3524 llvm::consumeError(HeaderInsertions.add(R));
3525 }
else if (isHeaderDeletion(R)) {
3526 HeadersToDelete.insert(R.getReplacementText());
3527 }
else if (R.getOffset() ==
UINT_MAX) {
3528 llvm::errs() <<
"Insertions other than header #include insertion are "
3530 << R.getReplacementText() <<
"\n";
3532 llvm::consumeError(
Result.add(R));
3535 if (HeaderInsertions.empty() && HeadersToDelete.empty())
3538 StringRef
FileName = Replaces.begin()->getFilePath();
3541 for (
const auto &Header : HeadersToDelete) {
3542 tooling::Replacements Replaces =
3543 Includes.remove(Header.trim(
"\"<>"), Header.starts_with(
"<"));
3544 for (
const auto &R : Replaces) {
3545 auto Err =
Result.add(R);
3548 llvm::errs() <<
"Failed to add header deletion replacement for "
3549 << Header <<
": " << llvm::toString(std::move(Err))
3556 for (
const auto &R : HeaderInsertions) {
3560 assert(Matched &&
"Header insertion replacement must have replacement text "
3563 auto IncludeName = Matches[2];
3565 Includes.insert(IncludeName.trim(
"\"<>"), IncludeName.starts_with(
"<"),
3568 auto Err =
Result.add(*Replace);
3570 llvm::consumeError(std::move(Err));
3571 unsigned NewOffset =
3572 Result.getShiftedCodePosition(Replace->getOffset());
3573 auto Shifted = tooling::Replacement(
FileName, NewOffset, 0,
3574 Replace->getReplacementText());
3589 auto Cleanup = [](
const FormatStyle &Style, StringRef Code,
3596 fixCppIncludeInsertions(Code, Replaces, Style);
3601std::pair<tooling::Replacements, unsigned>
3604 unsigned NextStartColumn,
unsigned LastStartColumn, StringRef FileName,
3615 case FormatStyle::RCPS_SingleLine:
3616 case FormatStyle::RCPS_WithPreceding:
3632 std::vector<tooling::Range> Ranges(1,
tooling::Range(0, Code.size()));
3633 auto Env = Environment::make(Code,
FileName, Ranges, FirstStartColumn,
3634 NextStartColumn, LastStartColumn);
3639 Formatter(*
Env, Style, Status).process().first;
3641 Replaces = Replaces.
merge(
3644 if (applyAllReplacements(Code, Replaces))
3645 return {Replaces, 0};
3649 auto Env = Environment::make(Code,
FileName, Ranges, FirstStartColumn,
3650 NextStartColumn, LastStartColumn);
3654 typedef std::function<std::pair<tooling::Replacements, unsigned>(
3664 if (Style.
isCpp()) {
3671 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3672 return ParensRemover(
Env, S).process(
true);
3678 S.InsertBraces =
true;
3679 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3680 return BracesInserter(
Env, S).process(
true);
3686 S.RemoveBracesLLVM =
true;
3687 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3688 return BracesRemover(
Env, S).process(
true);
3694 S.RemoveSemicolon =
true;
3695 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3696 return SemiRemover(
Env, S).process();
3719 if (Style.
Language == FormatStyle::LK_ObjC &&
3729 return JavaScriptRequoter(
Env, Expanded).process(
true);
3734 return Formatter(
Env, Expanded, Status).process();
3740 return TrailingCommaInserter(
Env, Expanded).process();
3744 std::optional<std::string> CurrentCode;
3746 unsigned Penalty = 0;
3747 for (
size_t I = 0, E = Passes.size(); I < E; ++I) {
3748 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
3749 auto NewCode = applyAllReplacements(
3750 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
3752 Fixes = Fixes.
merge(PassFixes.first);
3753 Penalty += PassFixes.second;
3755 CurrentCode = std::move(*NewCode);
3756 Env = Environment::make(
3758 tooling::calculateRangesAfterReplacements(Fixes, Ranges),
3759 FirstStartColumn, NextStartColumn, LastStartColumn);
3772 StringRef OriginalCode = Code.substr(Fix.getOffset(), Fix.getLength());
3773 if (OriginalCode != Fix.getReplacementText()) {
3774 auto Err = NonNoOpFixes.
add(Fix);
3776 llvm::errs() <<
"Error adding replacements : "
3777 << llvm::toString(std::move(Err)) <<
"\n";
3781 Fixes = std::move(NonNoOpFixes);
3784 return {Fixes, Penalty};
3808 return Cleaner(*
Env, Style).process().first;
3813 StringRef
FileName,
bool *IncompleteFormat) {
3816 if (!Status.FormatComplete)
3817 *IncompleteFormat =
true;
3849 LangOpts.CPlusPlus = 1;
3860 LangOpts.LineComment = 1;
3861 LangOpts.CXXOperatorNames = Style.
isCpp();
3864 LangOpts.MicrosoftExt = 1;
3865 LangOpts.DeclSpecKeyword = 1;
3871 "Set coding style. <string> can be:\n"
3872 "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"
3873 " Mozilla, WebKit.\n"
3874 "2. 'file' to load style configuration from a\n"
3875 " .clang-format file in one of the parent directories\n"
3876 " of the source file (for stdin, see --assume-filename).\n"
3877 " If no .clang-format file is found, falls back to\n"
3878 " --fallback-style.\n"
3879 " --style=file is the default.\n"
3880 "3. 'file:<format_file_path>' to explicitly specify\n"
3881 " the configuration file.\n"
3882 "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n"
3883 " --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
3888 if (
FileName.ends_with_insensitive(
".js") ||
3889 FileName.ends_with_insensitive(
".mjs") ||
3890 FileName.ends_with_insensitive(
".ts")) {
3895 if (
FileName.ends_with_insensitive(
".proto") ||
3896 FileName.ends_with_insensitive(
".protodevel")) {
3902 if (
FileName.ends_with_insensitive(
".txtpb") ||
3903 FileName.ends_with_insensitive(
".textpb") ||
3904 FileName.ends_with_insensitive(
".pb.txt") ||
3905 FileName.ends_with_insensitive(
".textproto") ||
3906 FileName.ends_with_insensitive(
".asciipb")) {
3909 if (
FileName.ends_with_insensitive(
".td"))
3911 if (
FileName.ends_with_insensitive(
".cs"))
3913 if (
FileName.ends_with_insensitive(
".json"))
3915 if (
FileName.ends_with_insensitive(
".sv") ||
3916 FileName.ends_with_insensitive(
".svh") ||
3917 FileName.ends_with_insensitive(
".v") ||
3918 FileName.ends_with_insensitive(
".vh")) {
3927 auto Extension = llvm::sys::path::extension(
FileName);
3930 if (!Code.empty() && (Extension.empty() || Extension ==
".h")) {
3935 if (Guesser.isObjC())
3939 return GuessedLanguage;
3947llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
3950 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
3951 FS->getBufferForFile(ConfigFile.str());
3952 if (
auto EC =
Text.getError())
3960 StringRef FallbackStyleName,
3961 StringRef Code, llvm::vfs::FileSystem *FS,
3962 bool AllowUnknownOptions) {
3969 ChildFormatTextToApply;
3971 if (StyleName.starts_with(
"{")) {
3973 StringRef Source =
"<command-line>";
3974 if (std::error_code ec =
3976 AllowUnknownOptions)) {
3983 ChildFormatTextToApply.emplace_back(
3984 llvm::MemoryBuffer::getMemBuffer(StyleName, Source,
false));
3988 FS = llvm::vfs::getRealFileSystem().get();
3993 StyleName.starts_with_insensitive(
"file:")) {
3994 auto ConfigFile = StyleName.substr(5);
3995 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
3997 if (
auto EC =
Text.getError()) {
4002 LLVM_DEBUG(llvm::dbgs()
4003 <<
"Using configuration file " << ConfigFile <<
"\n");
4011 ChildFormatTextToApply.emplace_back(std::move(*
Text));
4025 if (std::error_code EC = FS->makeAbsolute(Path))
4031 auto dropDiagnosticHandler = [](
const llvm::SMDiagnostic &,
void *) {};
4033 auto applyChildFormatTexts = [&](
FormatStyle *Style) {
4034 for (
const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) {
4036 dropDiagnosticHandler);
4039 static_cast<void>(EC);
4045 FilesToLookFor.push_back(
".clang-format");
4046 FilesToLookFor.push_back(
"_clang-format");
4049 for (StringRef Directory = Path; !Directory.empty();
4050 Directory = llvm::sys::path::parent_path(Directory)) {
4051 auto Status = FS->status(Directory);
4053 Status->getType() != llvm::sys::fs::file_type::directory_file) {
4057 for (
const auto &F : FilesToLookFor) {
4060 llvm::sys::path::append(ConfigFile, F);
4061 LLVM_DEBUG(llvm::dbgs() <<
"Trying " << ConfigFile <<
"...\n");
4063 Status = FS->status(ConfigFile);
4065 Status->getType() != llvm::sys::fs::file_type::regular_file) {
4069 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
4071 if (
auto EC =
Text.getError()) {
4076 if (!UnsuitableConfigFiles.empty())
4077 UnsuitableConfigFiles.append(
", ");
4078 UnsuitableConfigFiles.append(ConfigFile);
4082 LLVM_DEBUG(llvm::dbgs()
4083 <<
"Using configuration file " << ConfigFile <<
"\n");
4086 if (!ChildFormatTextToApply.empty()) {
4087 LLVM_DEBUG(llvm::dbgs() <<
"Applying child configurations\n");
4088 applyChildFormatTexts(&Style);
4093 LLVM_DEBUG(llvm::dbgs() <<
"Inherits parent configuration\n");
4098 ChildFormatTextToApply.emplace_back(std::move(*
Text));
4108 if (!UnsuitableConfigFiles.empty()) {
4111 UnsuitableConfigFiles);
4114 if (!ChildFormatTextToApply.empty()) {
4115 LLVM_DEBUG(llvm::dbgs()
4116 <<
"Applying child configurations on fallback style\n");
4117 applyChildFormatTexts(&FallbackStyle);
4120 return FallbackStyle;
4124 if (Comment == (On ?
"/* clang-format on */" :
"/* clang-format off */"))
4127 static const char ClangFormatOn[] =
"// clang-format on";
4128 static const char ClangFormatOff[] =
"// clang-format off";
4129 const unsigned Size = (On ?
sizeof ClangFormatOn :
sizeof ClangFormatOff) - 1;
4131 return Comment.starts_with(On ? ClangFormatOn : ClangFormatOff) &&
4132 (Comment.size() == Size || Comment[Size] ==
':');
This file declares DefinitionBlockSeparator, a TokenAnalyzer that inserts or removes empty lines sepa...
This file declares IntegerLiteralSeparatorFixer that fixes C++ integer literal separators.
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.
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...
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).
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.
@ Result
The result type of a method or function.
const FunctionProtoType * T
Diagnostic wrappers for TextAPI types for error reporting.
static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value)
static void enumeration(IO &IO, FormatStyle::LambdaBodyIndentationKind &Value)