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(
"AlignCaseColons",
Value.AlignCaseColons);
108struct ScalarEnumerationTraits<
FormatStyle::AttributeBreakingStyle> {
110 IO.enumCase(
Value,
"Always", FormatStyle::ABS_Always);
111 IO.enumCase(
Value,
"Leave", FormatStyle::ABS_Leave);
112 IO.enumCase(
Value,
"Never", FormatStyle::ABS_Never);
117struct ScalarEnumerationTraits<
FormatStyle::ArrayInitializerAlignmentStyle> {
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);
126template <>
struct ScalarEnumerationTraits<
FormatStyle::BinaryOperatorStyle> {
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);
136template <>
struct ScalarEnumerationTraits<
FormatStyle::BinPackStyle> {
138 IO.enumCase(
Value,
"Auto", FormatStyle::BPS_Auto);
139 IO.enumCase(
Value,
"Always", FormatStyle::BPS_Always);
140 IO.enumCase(
Value,
"Never", FormatStyle::BPS_Never);
145struct ScalarEnumerationTraits<
FormatStyle::BitFieldColonSpacingStyle> {
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);
155template <>
struct ScalarEnumerationTraits<
FormatStyle::BraceBreakingStyle> {
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);
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);
192template <>
struct ScalarEnumerationTraits<
FormatStyle::BracketAlignmentStyle> {
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);
200 IO.enumCase(
Value,
"true", FormatStyle::BAS_Align);
201 IO.enumCase(
Value,
"false", FormatStyle::BAS_DontAlign);
206struct ScalarEnumerationTraits<
207 FormatStyle::BraceWrappingAfterControlStatementStyle> {
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);
216 IO.enumCase(
Value,
"false", FormatStyle::BWACS_Never);
217 IO.enumCase(
Value,
"true", FormatStyle::BWACS_Always);
222struct ScalarEnumerationTraits<
223 FormatStyle::BreakBeforeConceptDeclarationsStyle> {
226 IO.enumCase(
Value,
"Never", FormatStyle::BBCDS_Never);
227 IO.enumCase(
Value,
"Allowed", FormatStyle::BBCDS_Allowed);
228 IO.enumCase(
Value,
"Always", FormatStyle::BBCDS_Always);
231 IO.enumCase(
Value,
"true", FormatStyle::BBCDS_Always);
232 IO.enumCase(
Value,
"false", FormatStyle::BBCDS_Allowed);
237struct ScalarEnumerationTraits<
FormatStyle::BreakBeforeInlineASMColonStyle> {
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);
247struct ScalarEnumerationTraits<
FormatStyle::BreakConstructorInitializersStyle> {
250 IO.enumCase(
Value,
"BeforeColon", FormatStyle::BCIS_BeforeColon);
251 IO.enumCase(
Value,
"BeforeComma", FormatStyle::BCIS_BeforeComma);
252 IO.enumCase(
Value,
"AfterColon", FormatStyle::BCIS_AfterColon);
257struct ScalarEnumerationTraits<
FormatStyle::BreakInheritanceListStyle> {
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);
268struct ScalarEnumerationTraits<
FormatStyle::BreakTemplateDeclarationsStyle> {
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);
277 IO.enumCase(
Value,
"false", FormatStyle::BTDS_MultiLine);
278 IO.enumCase(
Value,
"true", FormatStyle::BTDS_Yes);
283struct ScalarEnumerationTraits<
FormatStyle::DefinitionReturnTypeBreakingStyle> {
286 IO.enumCase(
Value,
"None", FormatStyle::DRTBS_None);
287 IO.enumCase(
Value,
"All", FormatStyle::DRTBS_All);
288 IO.enumCase(
Value,
"TopLevel", FormatStyle::DRTBS_TopLevel);
291 IO.enumCase(
Value,
"false", FormatStyle::DRTBS_None);
292 IO.enumCase(
Value,
"true", FormatStyle::DRTBS_All);
297struct ScalarEnumerationTraits<
FormatStyle::EscapedNewlineAlignmentStyle> {
299 FormatStyle::EscapedNewlineAlignmentStyle &
Value) {
300 IO.enumCase(
Value,
"DontAlign", FormatStyle::ENAS_DontAlign);
301 IO.enumCase(
Value,
"Left", FormatStyle::ENAS_Left);
302 IO.enumCase(
Value,
"Right", FormatStyle::ENAS_Right);
305 IO.enumCase(
Value,
"true", FormatStyle::ENAS_Left);
306 IO.enumCase(
Value,
"false", FormatStyle::ENAS_Right);
311struct ScalarEnumerationTraits<
FormatStyle::EmptyLineAfterAccessModifierStyle> {
314 IO.enumCase(
Value,
"Never", FormatStyle::ELAAMS_Never);
315 IO.enumCase(
Value,
"Leave", FormatStyle::ELAAMS_Leave);
316 IO.enumCase(
Value,
"Always", FormatStyle::ELAAMS_Always);
321struct ScalarEnumerationTraits<
325 IO.enumCase(
Value,
"Never", FormatStyle::ELBAMS_Never);
326 IO.enumCase(
Value,
"Leave", FormatStyle::ELBAMS_Leave);
327 IO.enumCase(
Value,
"LogicalBlock", FormatStyle::ELBAMS_LogicalBlock);
328 IO.enumCase(
Value,
"Always", FormatStyle::ELBAMS_Always);
333struct ScalarEnumerationTraits<
FormatStyle::IndentExternBlockStyle> {
335 IO.enumCase(
Value,
"AfterExternBlock", FormatStyle::IEBS_AfterExternBlock);
336 IO.enumCase(
Value,
"Indent", FormatStyle::IEBS_Indent);
337 IO.enumCase(
Value,
"NoIndent", FormatStyle::IEBS_NoIndent);
338 IO.enumCase(
Value,
"true", FormatStyle::IEBS_Indent);
339 IO.enumCase(
Value,
"false", FormatStyle::IEBS_NoIndent);
343template <>
struct MappingTraits<
FormatStyle::IntegerLiteralSeparatorStyle> {
344 static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &
Base) {
345 IO.mapOptional(
"Binary",
Base.Binary);
346 IO.mapOptional(
"BinaryMinDigits",
Base.BinaryMinDigits);
347 IO.mapOptional(
"Decimal",
Base.Decimal);
348 IO.mapOptional(
"DecimalMinDigits",
Base.DecimalMinDigits);
349 IO.mapOptional(
"Hex",
Base.Hex);
350 IO.mapOptional(
"HexMinDigits",
Base.HexMinDigits);
354template <>
struct ScalarEnumerationTraits<
FormatStyle::JavaScriptQuoteStyle> {
356 IO.enumCase(
Value,
"Leave", FormatStyle::JSQS_Leave);
357 IO.enumCase(
Value,
"Single", FormatStyle::JSQS_Single);
358 IO.enumCase(
Value,
"Double", FormatStyle::JSQS_Double);
362template <>
struct ScalarEnumerationTraits<
FormatStyle::LanguageKind> {
364 IO.enumCase(
Value,
"Cpp", FormatStyle::LK_Cpp);
365 IO.enumCase(
Value,
"Java", FormatStyle::LK_Java);
366 IO.enumCase(
Value,
"JavaScript", FormatStyle::LK_JavaScript);
367 IO.enumCase(
Value,
"ObjC", FormatStyle::LK_ObjC);
368 IO.enumCase(
Value,
"Proto", FormatStyle::LK_Proto);
369 IO.enumCase(
Value,
"TableGen", FormatStyle::LK_TableGen);
370 IO.enumCase(
Value,
"TextProto", FormatStyle::LK_TextProto);
371 IO.enumCase(
Value,
"CSharp", FormatStyle::LK_CSharp);
372 IO.enumCase(
Value,
"Json", FormatStyle::LK_Json);
373 IO.enumCase(
Value,
"Verilog", FormatStyle::LK_Verilog);
377template <>
struct ScalarEnumerationTraits<
FormatStyle::LanguageStandard> {
379 IO.enumCase(
Value,
"c++03", FormatStyle::LS_Cpp03);
380 IO.enumCase(
Value,
"C++03", FormatStyle::LS_Cpp03);
381 IO.enumCase(
Value,
"Cpp03", FormatStyle::LS_Cpp03);
383 IO.enumCase(
Value,
"c++11", FormatStyle::LS_Cpp11);
384 IO.enumCase(
Value,
"C++11", FormatStyle::LS_Cpp11);
386 IO.enumCase(
Value,
"c++14", FormatStyle::LS_Cpp14);
387 IO.enumCase(
Value,
"c++17", FormatStyle::LS_Cpp17);
388 IO.enumCase(
Value,
"c++20", FormatStyle::LS_Cpp20);
390 IO.enumCase(
Value,
"Latest", FormatStyle::LS_Latest);
391 IO.enumCase(
Value,
"Cpp11", FormatStyle::LS_Latest);
392 IO.enumCase(
Value,
"Auto", FormatStyle::LS_Auto);
397struct ScalarEnumerationTraits<
FormatStyle::LambdaBodyIndentationKind> {
399 FormatStyle::LambdaBodyIndentationKind &
Value) {
400 IO.enumCase(
Value,
"Signature", FormatStyle::LBI_Signature);
401 IO.enumCase(
Value,
"OuterScope", FormatStyle::LBI_OuterScope);
405template <>
struct ScalarEnumerationTraits<
FormatStyle::LineEndingStyle> {
407 IO.enumCase(
Value,
"LF", FormatStyle::LE_LF);
408 IO.enumCase(
Value,
"CRLF", FormatStyle::LE_CRLF);
409 IO.enumCase(
Value,
"DeriveLF", FormatStyle::LE_DeriveLF);
410 IO.enumCase(
Value,
"DeriveCRLF", FormatStyle::LE_DeriveCRLF);
415struct ScalarEnumerationTraits<
FormatStyle::NamespaceIndentationKind> {
417 FormatStyle::NamespaceIndentationKind &
Value) {
418 IO.enumCase(
Value,
"None", FormatStyle::NI_None);
419 IO.enumCase(
Value,
"Inner", FormatStyle::NI_Inner);
420 IO.enumCase(
Value,
"All", FormatStyle::NI_All);
424template <>
struct ScalarEnumerationTraits<
FormatStyle::OperandAlignmentStyle> {
426 IO.enumCase(
Value,
"DontAlign", FormatStyle::OAS_DontAlign);
427 IO.enumCase(
Value,
"Align", FormatStyle::OAS_Align);
428 IO.enumCase(
Value,
"AlignAfterOperator",
429 FormatStyle::OAS_AlignAfterOperator);
432 IO.enumCase(
Value,
"true", FormatStyle::OAS_Align);
433 IO.enumCase(
Value,
"false", FormatStyle::OAS_DontAlign);
438struct ScalarEnumerationTraits<
FormatStyle::PackConstructorInitializersStyle> {
441 IO.enumCase(
Value,
"Never", FormatStyle::PCIS_Never);
442 IO.enumCase(
Value,
"BinPack", FormatStyle::PCIS_BinPack);
443 IO.enumCase(
Value,
"CurrentLine", FormatStyle::PCIS_CurrentLine);
444 IO.enumCase(
Value,
"NextLine", FormatStyle::PCIS_NextLine);
445 IO.enumCase(
Value,
"NextLineOnly", FormatStyle::PCIS_NextLineOnly);
449template <>
struct ScalarEnumerationTraits<
FormatStyle::PointerAlignmentStyle> {
451 IO.enumCase(
Value,
"Middle", FormatStyle::PAS_Middle);
452 IO.enumCase(
Value,
"Left", FormatStyle::PAS_Left);
453 IO.enumCase(
Value,
"Right", FormatStyle::PAS_Right);
456 IO.enumCase(
Value,
"true", FormatStyle::PAS_Left);
457 IO.enumCase(
Value,
"false", FormatStyle::PAS_Right);
462struct ScalarEnumerationTraits<
FormatStyle::PPDirectiveIndentStyle> {
464 IO.enumCase(
Value,
"None", FormatStyle::PPDIS_None);
465 IO.enumCase(
Value,
"AfterHash", FormatStyle::PPDIS_AfterHash);
466 IO.enumCase(
Value,
"BeforeHash", FormatStyle::PPDIS_BeforeHash);
471struct ScalarEnumerationTraits<
FormatStyle::QualifierAlignmentStyle> {
473 IO.enumCase(
Value,
"Leave", FormatStyle::QAS_Leave);
474 IO.enumCase(
Value,
"Left", FormatStyle::QAS_Left);
475 IO.enumCase(
Value,
"Right", FormatStyle::QAS_Right);
476 IO.enumCase(
Value,
"Custom", FormatStyle::QAS_Custom);
481 static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
482 IO.mapOptional(
"Language", Format.Language);
483 IO.mapOptional(
"Delimiters", Format.Delimiters);
484 IO.mapOptional(
"EnclosingFunctions", Format.EnclosingFunctions);
485 IO.mapOptional(
"CanonicalDelimiter", Format.CanonicalDelimiter);
486 IO.mapOptional(
"BasedOnStyle", Format.BasedOnStyle);
491struct ScalarEnumerationTraits<
FormatStyle::ReferenceAlignmentStyle> {
493 IO.enumCase(
Value,
"Pointer", FormatStyle::RAS_Pointer);
494 IO.enumCase(
Value,
"Middle", FormatStyle::RAS_Middle);
495 IO.enumCase(
Value,
"Left", FormatStyle::RAS_Left);
496 IO.enumCase(
Value,
"Right", FormatStyle::RAS_Right);
501struct ScalarEnumerationTraits<
FormatStyle::RemoveParenthesesStyle> {
503 IO.enumCase(
Value,
"Leave", FormatStyle::RPS_Leave);
504 IO.enumCase(
Value,
"MultipleParentheses",
505 FormatStyle::RPS_MultipleParentheses);
506 IO.enumCase(
Value,
"ReturnStatement", FormatStyle::RPS_ReturnStatement);
511struct ScalarEnumerationTraits<
FormatStyle::RequiresClausePositionStyle> {
513 FormatStyle::RequiresClausePositionStyle &
Value) {
514 IO.enumCase(
Value,
"OwnLine", FormatStyle::RCPS_OwnLine);
515 IO.enumCase(
Value,
"WithPreceding", FormatStyle::RCPS_WithPreceding);
516 IO.enumCase(
Value,
"WithFollowing", FormatStyle::RCPS_WithFollowing);
517 IO.enumCase(
Value,
"SingleLine", FormatStyle::RCPS_SingleLine);
522struct ScalarEnumerationTraits<
FormatStyle::RequiresExpressionIndentationKind> {
525 IO.enumCase(
Value,
"Keyword", FormatStyle::REI_Keyword);
526 IO.enumCase(
Value,
"OuterScope", FormatStyle::REI_OuterScope);
531struct ScalarEnumerationTraits<
FormatStyle::ReturnTypeBreakingStyle> {
533 IO.enumCase(
Value,
"None", FormatStyle::RTBS_None);
534 IO.enumCase(
Value,
"Automatic", FormatStyle::RTBS_Automatic);
535 IO.enumCase(
Value,
"ExceptShortType", FormatStyle::RTBS_ExceptShortType);
536 IO.enumCase(
Value,
"All", FormatStyle::RTBS_All);
537 IO.enumCase(
Value,
"TopLevel", FormatStyle::RTBS_TopLevel);
538 IO.enumCase(
Value,
"TopLevelDefinitions",
539 FormatStyle::RTBS_TopLevelDefinitions);
540 IO.enumCase(
Value,
"AllDefinitions", FormatStyle::RTBS_AllDefinitions);
545struct ScalarEnumerationTraits<
FormatStyle::SeparateDefinitionStyle> {
547 IO.enumCase(
Value,
"Leave", FormatStyle::SDS_Leave);
548 IO.enumCase(
Value,
"Always", FormatStyle::SDS_Always);
549 IO.enumCase(
Value,
"Never", FormatStyle::SDS_Never);
553template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortBlockStyle> {
555 IO.enumCase(
Value,
"Never", FormatStyle::SBS_Never);
556 IO.enumCase(
Value,
"false", FormatStyle::SBS_Never);
557 IO.enumCase(
Value,
"Always", FormatStyle::SBS_Always);
558 IO.enumCase(
Value,
"true", FormatStyle::SBS_Always);
559 IO.enumCase(
Value,
"Empty", FormatStyle::SBS_Empty);
563template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortFunctionStyle> {
565 IO.enumCase(
Value,
"None", FormatStyle::SFS_None);
566 IO.enumCase(
Value,
"false", FormatStyle::SFS_None);
567 IO.enumCase(
Value,
"All", FormatStyle::SFS_All);
568 IO.enumCase(
Value,
"true", FormatStyle::SFS_All);
569 IO.enumCase(
Value,
"Inline", FormatStyle::SFS_Inline);
570 IO.enumCase(
Value,
"InlineOnly", FormatStyle::SFS_InlineOnly);
571 IO.enumCase(
Value,
"Empty", FormatStyle::SFS_Empty);
575template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortIfStyle> {
577 IO.enumCase(
Value,
"Never", FormatStyle::SIS_Never);
578 IO.enumCase(
Value,
"WithoutElse", FormatStyle::SIS_WithoutElse);
579 IO.enumCase(
Value,
"OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf);
580 IO.enumCase(
Value,
"AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse);
583 IO.enumCase(
Value,
"Always", FormatStyle::SIS_OnlyFirstIf);
584 IO.enumCase(
Value,
"false", FormatStyle::SIS_Never);
585 IO.enumCase(
Value,
"true", FormatStyle::SIS_WithoutElse);
589template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortLambdaStyle> {
591 IO.enumCase(
Value,
"None", FormatStyle::SLS_None);
592 IO.enumCase(
Value,
"false", FormatStyle::SLS_None);
593 IO.enumCase(
Value,
"Empty", FormatStyle::SLS_Empty);
594 IO.enumCase(
Value,
"Inline", FormatStyle::SLS_Inline);
595 IO.enumCase(
Value,
"All", FormatStyle::SLS_All);
596 IO.enumCase(
Value,
"true", FormatStyle::SLS_All);
600template <>
struct ScalarEnumerationTraits<
FormatStyle::SortIncludesOptions> {
602 IO.enumCase(
Value,
"Never", FormatStyle::SI_Never);
603 IO.enumCase(
Value,
"CaseInsensitive", FormatStyle::SI_CaseInsensitive);
604 IO.enumCase(
Value,
"CaseSensitive", FormatStyle::SI_CaseSensitive);
607 IO.enumCase(
Value,
"false", FormatStyle::SI_Never);
608 IO.enumCase(
Value,
"true", FormatStyle::SI_CaseSensitive);
613struct ScalarEnumerationTraits<
FormatStyle::SortJavaStaticImportOptions> {
615 FormatStyle::SortJavaStaticImportOptions &
Value) {
616 IO.enumCase(
Value,
"Before", FormatStyle::SJSIO_Before);
617 IO.enumCase(
Value,
"After", FormatStyle::SJSIO_After);
622struct ScalarEnumerationTraits<
FormatStyle::SortUsingDeclarationsOptions> {
624 FormatStyle::SortUsingDeclarationsOptions &
Value) {
625 IO.enumCase(
Value,
"Never", FormatStyle::SUD_Never);
626 IO.enumCase(
Value,
"Lexicographic", FormatStyle::SUD_Lexicographic);
627 IO.enumCase(
Value,
"LexicographicNumeric",
628 FormatStyle::SUD_LexicographicNumeric);
631 IO.enumCase(
Value,
"false", FormatStyle::SUD_Never);
632 IO.enumCase(
Value,
"true", FormatStyle::SUD_LexicographicNumeric);
637struct ScalarEnumerationTraits<
FormatStyle::SpaceAroundPointerQualifiersStyle> {
640 IO.enumCase(
Value,
"Default", FormatStyle::SAPQ_Default);
641 IO.enumCase(
Value,
"Before", FormatStyle::SAPQ_Before);
642 IO.enumCase(
Value,
"After", FormatStyle::SAPQ_After);
643 IO.enumCase(
Value,
"Both", FormatStyle::SAPQ_Both);
647template <>
struct MappingTraits<
FormatStyle::SpaceBeforeParensCustom> {
648 static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) {
649 IO.mapOptional(
"AfterControlStatements", Spacing.AfterControlStatements);
650 IO.mapOptional(
"AfterForeachMacros", Spacing.AfterForeachMacros);
651 IO.mapOptional(
"AfterFunctionDefinitionName",
652 Spacing.AfterFunctionDefinitionName);
653 IO.mapOptional(
"AfterFunctionDeclarationName",
654 Spacing.AfterFunctionDeclarationName);
655 IO.mapOptional(
"AfterIfMacros", Spacing.AfterIfMacros);
656 IO.mapOptional(
"AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
657 IO.mapOptional(
"AfterPlacementOperator", Spacing.AfterPlacementOperator);
658 IO.mapOptional(
"AfterRequiresInClause", Spacing.AfterRequiresInClause);
659 IO.mapOptional(
"AfterRequiresInExpression",
660 Spacing.AfterRequiresInExpression);
661 IO.mapOptional(
"BeforeNonEmptyParentheses",
662 Spacing.BeforeNonEmptyParentheses);
667struct ScalarEnumerationTraits<
FormatStyle::SpaceBeforeParensStyle> {
669 IO.enumCase(
Value,
"Never", FormatStyle::SBPO_Never);
670 IO.enumCase(
Value,
"ControlStatements",
671 FormatStyle::SBPO_ControlStatements);
672 IO.enumCase(
Value,
"ControlStatementsExceptControlMacros",
673 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
674 IO.enumCase(
Value,
"NonEmptyParentheses",
675 FormatStyle::SBPO_NonEmptyParentheses);
676 IO.enumCase(
Value,
"Always", FormatStyle::SBPO_Always);
677 IO.enumCase(
Value,
"Custom", FormatStyle::SBPO_Custom);
680 IO.enumCase(
Value,
"false", FormatStyle::SBPO_Never);
681 IO.enumCase(
Value,
"true", FormatStyle::SBPO_ControlStatements);
682 IO.enumCase(
Value,
"ControlStatementsExceptForEachMacros",
683 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
687template <>
struct ScalarEnumerationTraits<
FormatStyle::SpacesInAnglesStyle> {
689 IO.enumCase(
Value,
"Never", FormatStyle::SIAS_Never);
690 IO.enumCase(
Value,
"Always", FormatStyle::SIAS_Always);
691 IO.enumCase(
Value,
"Leave", FormatStyle::SIAS_Leave);
694 IO.enumCase(
Value,
"false", FormatStyle::SIAS_Never);
695 IO.enumCase(
Value,
"true", FormatStyle::SIAS_Always);
699template <>
struct MappingTraits<
FormatStyle::SpacesInLineComment> {
700 static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
702 int signedMaximum =
static_cast<int>(Space.Maximum);
703 IO.mapOptional(
"Minimum", Space.Minimum);
704 IO.mapOptional(
"Maximum", signedMaximum);
705 Space.Maximum =
static_cast<unsigned>(signedMaximum);
707 if (Space.Maximum != -1u)
708 Space.Minimum = std::min(Space.Minimum, Space.Maximum);
712template <>
struct MappingTraits<
FormatStyle::SpacesInParensCustom> {
713 static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) {
714 IO.mapOptional(
"InCStyleCasts", Spaces.InCStyleCasts);
715 IO.mapOptional(
"InConditionalStatements", Spaces.InConditionalStatements);
716 IO.mapOptional(
"InEmptyParentheses", Spaces.InEmptyParentheses);
717 IO.mapOptional(
"Other", Spaces.Other);
721template <>
struct ScalarEnumerationTraits<
FormatStyle::SpacesInParensStyle> {
723 IO.enumCase(
Value,
"Never", FormatStyle::SIPO_Never);
724 IO.enumCase(
Value,
"Custom", FormatStyle::SIPO_Custom);
728template <>
struct ScalarEnumerationTraits<
FormatStyle::TrailingCommaStyle> {
730 IO.enumCase(
Value,
"None", FormatStyle::TCS_None);
731 IO.enumCase(
Value,
"Wrapped", FormatStyle::TCS_Wrapped);
736struct ScalarEnumerationTraits<
FormatStyle::TrailingCommentsAlignmentKinds> {
738 FormatStyle::TrailingCommentsAlignmentKinds &
Value) {
739 IO.enumCase(
Value,
"Leave", FormatStyle::TCAS_Leave);
740 IO.enumCase(
Value,
"Always", FormatStyle::TCAS_Always);
741 IO.enumCase(
Value,
"Never", FormatStyle::TCAS_Never);
745template <>
struct MappingTraits<
FormatStyle::TrailingCommentsAlignmentStyle> {
747 FormatStyle::TrailingCommentsAlignmentStyle &
Value) {
748 IO.enumCase(
Value,
"Leave",
749 FormatStyle::TrailingCommentsAlignmentStyle(
750 {FormatStyle::TCAS_Leave, 0}));
752 IO.enumCase(
Value,
"Always",
753 FormatStyle::TrailingCommentsAlignmentStyle(
754 {FormatStyle::TCAS_Always, 0}));
756 IO.enumCase(
Value,
"Never",
757 FormatStyle::TrailingCommentsAlignmentStyle(
758 {FormatStyle::TCAS_Never, 0}));
761 IO.enumCase(
Value,
"true",
762 FormatStyle::TrailingCommentsAlignmentStyle(
763 {FormatStyle::TCAS_Always, 0}));
764 IO.enumCase(
Value,
"false",
765 FormatStyle::TrailingCommentsAlignmentStyle(
766 {FormatStyle::TCAS_Never, 0}));
770 FormatStyle::TrailingCommentsAlignmentStyle &
Value) {
771 IO.mapOptional(
"Kind",
Value.Kind);
772 IO.mapOptional(
"OverEmptyLines",
Value.OverEmptyLines);
776template <>
struct ScalarEnumerationTraits<
FormatStyle::UseTabStyle> {
778 IO.enumCase(
Value,
"Never", FormatStyle::UT_Never);
779 IO.enumCase(
Value,
"false", FormatStyle::UT_Never);
780 IO.enumCase(
Value,
"Always", FormatStyle::UT_Always);
781 IO.enumCase(
Value,
"true", FormatStyle::UT_Always);
782 IO.enumCase(
Value,
"ForIndentation", FormatStyle::UT_ForIndentation);
783 IO.enumCase(
Value,
"ForContinuationAndIndentation",
784 FormatStyle::UT_ForContinuationAndIndentation);
785 IO.enumCase(
Value,
"AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);
792 IO.mapOptional(
"Language", Style.
Language);
794 StringRef BasedOnStyle;
795 if (IO.outputting()) {
796 StringRef Styles[] = {
"LLVM",
"Google",
"Chromium",
"Mozilla",
797 "WebKit",
"GNU",
"Microsoft",
"clang-format"};
798 for (StringRef StyleName : Styles) {
800 if (getPredefinedStyle(StyleName, Style.
Language, &PredefinedStyle) &&
801 Style == PredefinedStyle) {
802 IO.mapOptional(
"# BasedOnStyle", StyleName);
803 BasedOnStyle = StyleName;
808 IO.mapOptional(
"BasedOnStyle", BasedOnStyle);
809 if (!BasedOnStyle.empty()) {
810 FormatStyle::LanguageKind OldLanguage = Style.
Language;
811 FormatStyle::LanguageKind Language =
813 if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
814 IO.setError(Twine(
"Unknown value for BasedOnStyle: ", BasedOnStyle));
832 const bool IsGoogleOrChromium = BasedOnStyle.equals_insensitive(
"google") ||
833 BasedOnStyle.equals_insensitive(
"chromium");
834 bool OnCurrentLine = IsGoogleOrChromium;
835 bool OnNextLine =
true;
837 bool BreakBeforeInheritanceComma =
false;
838 bool BreakConstructorInitializersBeforeComma =
false;
840 bool DeriveLineEnding =
true;
841 bool UseCRLF =
false;
843 bool SpaceInEmptyParentheses =
false;
844 bool SpacesInConditionalStatement =
false;
845 bool SpacesInCStyleCastParentheses =
false;
846 bool SpacesInParentheses =
false;
849 if (!IO.outputting()) {
851 IO.mapOptional(
"AllowAllConstructorInitializersOnNextLine", OnNextLine);
853 IO.mapOptional(
"AlwaysBreakTemplateDeclarations",
855 IO.mapOptional(
"BreakBeforeInheritanceComma",
856 BreakBeforeInheritanceComma);
857 IO.mapOptional(
"BreakConstructorInitializersBeforeComma",
858 BreakConstructorInitializersBeforeComma);
859 IO.mapOptional(
"ConstructorInitializerAllOnOneLineOrOnePerLine",
861 IO.mapOptional(
"DeriveLineEnding", DeriveLineEnding);
863 IO.mapOptional(
"IndentFunctionDeclarationAfterType",
867 IO.mapOptional(
"SpaceAfterControlStatementKeyword",
869 IO.mapOptional(
"SpaceInEmptyParentheses", SpaceInEmptyParentheses);
870 IO.mapOptional(
"SpacesInConditionalStatement",
871 SpacesInConditionalStatement);
872 IO.mapOptional(
"SpacesInCStyleCastParentheses",
873 SpacesInCStyleCastParentheses);
874 IO.mapOptional(
"SpacesInParentheses", SpacesInParentheses);
875 IO.mapOptional(
"UseCRLF", UseCRLF);
881 IO.mapOptional(
"AlignConsecutiveAssignments",
883 IO.mapOptional(
"AlignConsecutiveBitFields",
885 IO.mapOptional(
"AlignConsecutiveDeclarations",
888 IO.mapOptional(
"AlignConsecutiveShortCaseStatements",
890 IO.mapOptional(
"AlignConsecutiveTableGenCondOperatorColons",
892 IO.mapOptional(
"AlignConsecutiveTableGenDefinitionColons",
897 IO.mapOptional(
"AllowAllArgumentsOnNextLine",
899 IO.mapOptional(
"AllowAllParametersOfDeclarationOnNextLine",
901 IO.mapOptional(
"AllowBreakBeforeNoexceptSpecifier",
903 IO.mapOptional(
"AllowShortBlocksOnASingleLine",
905 IO.mapOptional(
"AllowShortCaseLabelsOnASingleLine",
907 IO.mapOptional(
"AllowShortCompoundRequirementOnASingleLine",
909 IO.mapOptional(
"AllowShortEnumsOnASingleLine",
911 IO.mapOptional(
"AllowShortFunctionsOnASingleLine",
913 IO.mapOptional(
"AllowShortIfStatementsOnASingleLine",
915 IO.mapOptional(
"AllowShortLambdasOnASingleLine",
917 IO.mapOptional(
"AllowShortLoopsOnASingleLine",
919 IO.mapOptional(
"AlwaysBreakAfterDefinitionReturnType",
921 IO.mapOptional(
"AlwaysBreakBeforeMultilineStrings",
927 IO.mapOptional(
"BracedInitializerIndentWidth",
930 IO.mapOptional(
"BreakAdjacentStringLiterals",
933 IO.mapOptional(
"BreakAfterJavaFieldAnnotations",
937 IO.mapOptional(
"BreakBeforeBinaryOperators",
939 IO.mapOptional(
"BreakBeforeConceptDeclarations",
942 IO.mapOptional(
"BreakBeforeInlineASMColon",
944 IO.mapOptional(
"BreakBeforeTernaryOperators",
946 IO.mapOptional(
"BreakConstructorInitializers",
950 IO.mapOptional(
"BreakTemplateDeclarations",
955 IO.mapOptional(
"ConstructorInitializerIndentWidth",
961 IO.mapOptional(
"EmptyLineAfterAccessModifier",
963 IO.mapOptional(
"EmptyLineBeforeAccessModifier",
965 IO.mapOptional(
"ExperimentalAutoDetectBinPacking",
969 IO.mapOptional(
"IfMacros", Style.
IfMacros);
973 IO.mapOptional(
"IncludeIsMainSourceRegex",
983 IO.mapOptional(
"IndentWrappedFunctionNames",
992 IO.mapOptional(
"KeepEmptyLinesAtTheStartOfBlocks",
996 IO.mapOptional(
"LineEnding", Style.
LineEnding);
999 IO.mapOptional(
"Macros", Style.
Macros);
1006 IO.mapOptional(
"ObjCBreakBeforeNestedBlockParam",
1008 IO.mapOptional(
"ObjCPropertyAttributeOrder",
1011 IO.mapOptional(
"ObjCSpaceBeforeProtocolList",
1013 IO.mapOptional(
"PackConstructorInitializers",
1016 IO.mapOptional(
"PenaltyBreakBeforeFirstCallParameter",
1019 IO.mapOptional(
"PenaltyBreakFirstLessLess",
1021 IO.mapOptional(
"PenaltyBreakOpenParenthesis",
1023 IO.mapOptional(
"PenaltyBreakScopeResolution",
1026 IO.mapOptional(
"PenaltyBreakTemplateDeclaration",
1029 IO.mapOptional(
"PenaltyIndentedWhitespace",
1031 IO.mapOptional(
"PenaltyReturnTypeOnItsOwnLine",
1050 IO.mapOptional(
"RequiresExpressionIndentation",
1060 IO.mapOptional(
"SpaceAfterTemplateKeyword",
1062 IO.mapOptional(
"SpaceAroundPointerQualifiers",
1064 IO.mapOptional(
"SpaceBeforeAssignmentOperators",
1067 IO.mapOptional(
"SpaceBeforeCpp11BracedList",
1069 IO.mapOptional(
"SpaceBeforeCtorInitializerColon",
1071 IO.mapOptional(
"SpaceBeforeInheritanceColon",
1076 IO.mapOptional(
"SpaceBeforeRangeBasedForLoopColon",
1078 IO.mapOptional(
"SpaceBeforeSquareBrackets",
1081 IO.mapOptional(
"SpacesBeforeTrailingComments",
1084 IO.mapOptional(
"SpacesInContainerLiterals",
1086 IO.mapOptional(
"SpacesInLineCommentPrefix",
1091 IO.mapOptional(
"Standard", Style.
Standard);
1092 IO.mapOptional(
"StatementAttributeLikeMacros",
1095 IO.mapOptional(
"TabWidth", Style.
TabWidth);
1096 IO.mapOptional(
"TypeNames", Style.
TypeNames);
1098 IO.mapOptional(
"UseTab", Style.
UseTab);
1099 IO.mapOptional(
"VerilogBreakBetweenInstancePorts",
1101 IO.mapOptional(
"WhitespaceSensitiveMacros",
1110 FormatStyle::DRTBS_All) {
1113 FormatStyle::DRTBS_TopLevel) {
1120 if (BreakBeforeInheritanceComma &&
1128 if (BreakConstructorInitializersBeforeComma &&
1133 if (!IsGoogleOrChromium) {
1137 ? FormatStyle::PCIS_NextLine
1138 : FormatStyle::PCIS_CurrentLine;
1141 FormatStyle::PCIS_NextLine) {
1144 else if (!OnNextLine)
1148 if (Style.
LineEnding == FormatStyle::LE_DeriveLF) {
1149 if (!DeriveLineEnding)
1150 Style.
LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF;
1152 Style.
LineEnding = FormatStyle::LE_DeriveCRLF;
1156 (SpacesInParentheses || SpaceInEmptyParentheses ||
1157 SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) {
1158 if (SpacesInParentheses) {
1163 SpacesInCStyleCastParentheses;
1165 SpaceInEmptyParentheses;
1170 SpacesInConditionalStatement;
1172 SpacesInCStyleCastParentheses;
1174 SpaceInEmptyParentheses;
1186template <>
struct DocumentListTraits<
std::vector<FormatStyle>> {
1187 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
1192 if (Index >= Seq.size()) {
1193 assert(Index == Seq.size());
1195 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
1198 Template = *((
const FormatStyle *)IO.getContext());
1199 Template.
Language = FormatStyle::LK_None;
1201 Seq.resize(Index + 1, Template);
1221 return llvm::make_error<llvm::StringError>(Message,
1222 llvm::inconvertibleErrorCode());
1226 return "clang-format.parse_error";
1234 return "Invalid argument";
1236 return "Unsuitable";
1238 return "trailing comma insertion cannot be used with bin packing";
1240 return "Invalid qualifier specified in QualifierOrder";
1242 return "Duplicate qualifier specified in QualifierOrder";
1244 return "Missing type in QualifierOrder";
1246 return "Missing QualifierOrder";
1248 llvm_unreachable(
"unexpected parse error");
1471 LLVMStyle.
IfMacros.push_back(
"KJ_IF_MAYBE");
1474 {
"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0,
false},
1475 {
"^(<|\"(gtest|gmock|isl|json)/)", 3, 0,
false},
1476 {
".*", 1, 0,
false}};
1615 {
"^<.*\\.h>", 1, 0,
false},
1616 {
"^<.*", 2, 0,
false},
1617 {
".*", 3, 0,
false}};
1657 "PARSE_PARTIAL_TEXT_PROTO",
1661 "ParseTextProtoOrDie",
1663 "ParsePartialTestProto",
1775 "com.google.android.apps.chrome",
1794 return ChromiumStyle;
1820 return MozillaStyle;
1914 if (Name.equals_insensitive(
"llvm"))
1916 else if (Name.equals_insensitive(
"chromium"))
1918 else if (Name.equals_insensitive(
"mozilla"))
1920 else if (Name.equals_insensitive(
"google"))
1922 else if (Name.equals_insensitive(
"webkit"))
1924 else if (Name.equals_insensitive(
"gnu"))
1926 else if (Name.equals_insensitive(
"microsoft"))
1928 else if (Name.equals_insensitive(
"clang-format"))
1930 else if (Name.equals_insensitive(
"none"))
1932 else if (Name.equals_insensitive(
"inheritparentconfig"))
1948 if (Qualifier ==
"type")
1952 if (token == tok::identifier)
1957 std::set<std::string> UniqueQualifiers(Style->
QualifierOrder.begin(),
1960 LLVM_DEBUG(llvm::dbgs()
1962 <<
" vs " << UniqueQualifiers.size() <<
"\n");
1975 llvm::SourceMgr::DiagHandlerTy DiagHandler,
1976 void *DiagHandlerCtxt) {
1980 if (Config.getBuffer().trim().empty())
1982 Style->StyleSet.
Clear();
1983 std::vector<FormatStyle> Styles;
1984 llvm::yaml::Input Input(Config,
nullptr, DiagHandler,
1990 Input.setContext(Style);
1991 Input.setAllowUnknownKeys(AllowUnknownOptions);
1994 return Input.error();
1996 for (
unsigned i = 0; i < Styles.size(); ++i) {
2001 for (
unsigned j = 0; j < i; ++j) {
2003 LLVM_DEBUG(llvm::dbgs()
2004 <<
"Duplicate languages in the config file on positions "
2005 << j <<
" and " << i <<
"\n");
2014 bool LanguageFound =
false;
2015 for (
const FormatStyle &Style : llvm::reverse(Styles)) {
2017 StyleSet.
Add(Style);
2019 LanguageFound =
true;
2021 if (!LanguageFound) {
2026 StyleSet.
Add(std::move(DefaultStyle));
2041 llvm::raw_string_ostream Stream(
Text);
2042 llvm::yaml::Output Output(Stream);
2049 Output << NonConstStyle;
2051 return Stream.str();
2054std::optional<FormatStyle>
2057 return std::nullopt;
2059 if (It == Styles->end())
2060 return std::nullopt;
2062 Style.StyleSet = *
this;
2068 "Cannot add a style for LK_None to a StyleSet");
2070 !Style.StyleSet.Styles &&
2071 "Cannot add a style associated with an existing StyleSet to a StyleSet");
2073 Styles = std::make_shared<MapType>();
2074 (*Styles)[Style.
Language] = std::move(Style);
2079std::optional<FormatStyle>
2091 std::pair<tooling::Replacements, unsigned>
2092 analyze(TokenAnnotator &Annotator,
2094 FormatTokenLexer &Tokens)
override {
2095 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2097 removeParens(AnnotatedLines, Result);
2102 void removeParens(SmallVectorImpl<AnnotatedLine *> &Lines,
2103 tooling::Replacements &Result) {
2104 const auto &SourceMgr =
Env.getSourceManager();
2105 for (
auto *Line : Lines) {
2106 removeParens(Line->Children, Result);
2107 if (!Line->Affected)
2109 for (
const auto *Token = Line->First; Token && !Token->Finalized;
2110 Token = Token->Next) {
2111 if (!Token->Optional || !Token->isOneOf(tok::l_paren, tok::r_paren))
2113 auto *Next = Token->Next;
2114 assert(Next && Next->isNot(tok::eof));
2115 SourceLocation Start;
2116 if (Next->NewlinesBefore == 0) {
2117 Start = Token->Tok.getLocation();
2118 Next->WhitespaceRange = Token->WhitespaceRange;
2120 Start = Token->WhitespaceRange.getBegin();
2123 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2124 cantFail(Result.add(tooling::Replacement(SourceMgr, Range,
" ")));
2130class BracesInserter :
public TokenAnalyzer {
2133 : TokenAnalyzer(
Env, Style) {}
2135 std::pair<tooling::Replacements, unsigned>
2136 analyze(TokenAnnotator &Annotator,
2137 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2138 FormatTokenLexer &Tokens)
override {
2139 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2140 tooling::Replacements Result;
2141 insertBraces(AnnotatedLines, Result);
2146 void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2147 tooling::Replacements &Result) {
2148 const auto &SourceMgr =
Env.getSourceManager();
2149 int OpeningBraceSurplus = 0;
2150 for (AnnotatedLine *Line : Lines) {
2151 insertBraces(Line->Children, Result);
2152 if (!Line->Affected && OpeningBraceSurplus == 0)
2154 for (FormatToken *Token = Line->First; Token && !Token->Finalized;
2155 Token = Token->Next) {
2156 int BraceCount = Token->BraceCount;
2157 if (BraceCount == 0)
2160 if (BraceCount < 0) {
2161 assert(BraceCount == -1);
2162 if (!Line->Affected)
2164 Brace = Token->is(tok::comment) ?
"\n{" :
"{";
2165 ++OpeningBraceSurplus;
2167 if (OpeningBraceSurplus == 0)
2169 if (OpeningBraceSurplus < BraceCount)
2170 BraceCount = OpeningBraceSurplus;
2171 Brace =
'\n' + std::string(BraceCount,
'}');
2172 OpeningBraceSurplus -= BraceCount;
2174 Token->BraceCount = 0;
2175 const auto Start = Token->Tok.getEndLoc();
2176 cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0,
Brace)));
2179 assert(OpeningBraceSurplus == 0);
2183class BracesRemover :
public TokenAnalyzer {
2186 : TokenAnalyzer(
Env, Style) {}
2188 std::pair<tooling::Replacements, unsigned>
2189 analyze(TokenAnnotator &Annotator,
2190 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2191 FormatTokenLexer &Tokens)
override {
2192 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2193 tooling::Replacements Result;
2194 removeBraces(AnnotatedLines, Result);
2199 void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2200 tooling::Replacements &Result) {
2201 const auto &SourceMgr =
Env.getSourceManager();
2202 const auto End = Lines.end();
2203 for (
auto I = Lines.begin(); I != End; ++I) {
2204 const auto Line = *I;
2205 removeBraces(Line->Children, Result);
2206 if (!Line->Affected)
2208 const auto NextLine = I + 1 == End ? nullptr : I[1];
2209 for (
auto Token = Line->First; Token && !Token->Finalized;
2210 Token = Token->Next) {
2211 if (!Token->Optional)
2213 if (!Token->isOneOf(tok::l_brace, tok::r_brace))
2215 auto Next = Token->Next;
2216 assert(Next || Token == Line->Last);
2217 if (!Next && NextLine)
2218 Next = NextLine->First;
2219 SourceLocation Start;
2220 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2221 Start = Token->Tok.getLocation();
2222 Next->WhitespaceRange = Token->WhitespaceRange;
2224 Start = Token->WhitespaceRange.getBegin();
2227 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2228 cantFail(Result.add(tooling::Replacement(SourceMgr, Range,
"")));
2234class SemiRemover :
public TokenAnalyzer {
2237 : TokenAnalyzer(
Env, Style) {}
2239 std::pair<tooling::Replacements, unsigned>
2240 analyze(TokenAnnotator &Annotator,
2241 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2242 FormatTokenLexer &Tokens)
override {
2243 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2244 tooling::Replacements Result;
2245 removeSemi(Annotator, AnnotatedLines, Result);
2250 void removeSemi(TokenAnnotator &Annotator,
2251 SmallVectorImpl<AnnotatedLine *> &Lines,
2252 tooling::Replacements &Result) {
2253 auto PrecededByFunctionRBrace = [](
const FormatToken &Tok) {
2254 const auto *Prev = Tok.Previous;
2255 if (!Prev || Prev->isNot(tok::r_brace))
2257 const auto *LBrace = Prev->MatchingParen;
2258 return LBrace && LBrace->is(TT_FunctionLBrace);
2260 const auto &SourceMgr =
Env.getSourceManager();
2261 const auto End = Lines.end();
2262 for (
auto I = Lines.begin(); I != End; ++I) {
2263 const auto Line = *I;
2264 removeSemi(Annotator, Line->Children, Result);
2265 if (!Line->Affected)
2267 Annotator.calculateFormattingInformation(*Line);
2268 const auto NextLine = I + 1 == End ? nullptr : I[1];
2269 for (
auto Token = Line->First; Token && !Token->Finalized;
2270 Token = Token->Next) {
2271 if (Token->isNot(tok::semi) ||
2272 (!Token->Optional && !PrecededByFunctionRBrace(*Token))) {
2275 auto Next = Token->Next;
2276 assert(Next || Token == Line->Last);
2277 if (!Next && NextLine)
2278 Next = NextLine->First;
2279 SourceLocation Start;
2280 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2281 Start = Token->Tok.getLocation();
2282 Next->WhitespaceRange = Token->WhitespaceRange;
2284 Start = Token->WhitespaceRange.getBegin();
2287 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2288 cantFail(Result.add(tooling::Replacement(SourceMgr, Range,
"")));
2294class JavaScriptRequoter :
public TokenAnalyzer {
2296 JavaScriptRequoter(
const Environment &
Env,
const FormatStyle &Style)
2297 : TokenAnalyzer(
Env, Style) {}
2299 std::pair<tooling::Replacements, unsigned>
2300 analyze(TokenAnnotator &Annotator,
2301 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2302 FormatTokenLexer &Tokens)
override {
2303 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2304 tooling::Replacements Result;
2305 requoteJSStringLiteral(AnnotatedLines, Result);
2312 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
2313 tooling::Replacements &Result) {
2314 for (AnnotatedLine *Line : Lines) {
2315 requoteJSStringLiteral(Line->Children, Result);
2316 if (!Line->Affected)
2318 for (FormatToken *FormatTok = Line->First; FormatTok;
2319 FormatTok = FormatTok->Next) {
2320 StringRef Input = FormatTok->TokenText;
2321 if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
2325 !Input.starts_with(
"\"")) ||
2327 !Input.starts_with(
"\'"))) {
2333 SourceLocation Start = FormatTok->Tok.getLocation();
2334 auto Replace = [&](SourceLocation Start,
unsigned Length,
2335 StringRef ReplacementText) {
2336 auto Err = Result.add(tooling::Replacement(
2337 Env.getSourceManager(), Start, Length, ReplacementText));
2341 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
2345 Replace(Start, 1, IsSingle ?
"'" :
"\"");
2346 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
2347 IsSingle ?
"'" :
"\"");
2350 bool Escaped =
false;
2351 for (
size_t i = 1; i < Input.size() - 1; i++) {
2354 if (!Escaped && i + 1 < Input.size() &&
2355 ((IsSingle && Input[i + 1] ==
'"') ||
2356 (!IsSingle && Input[i + 1] ==
'\''))) {
2359 Replace(Start.getLocWithOffset(i), 1,
"");
2366 if (!Escaped && IsSingle == (Input[i] ==
'\'')) {
2368 Replace(Start.getLocWithOffset(i), 0,
"\\");
2382class Formatter :
public TokenAnalyzer {
2385 FormattingAttemptStatus *Status)
2386 : TokenAnalyzer(
Env, Style), Status(Status) {}
2388 std::pair<tooling::Replacements, unsigned>
2389 analyze(TokenAnnotator &Annotator,
2390 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2391 FormatTokenLexer &Tokens)
override {
2392 tooling::Replacements Result;
2393 deriveLocalStyle(AnnotatedLines);
2394 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2395 for (AnnotatedLine *Line : AnnotatedLines)
2396 Annotator.calculateFormattingInformation(*Line);
2397 Annotator.setCommentLineLevels(AnnotatedLines);
2399 WhitespaceManager Whitespaces(
2400 Env.getSourceManager(), Style,
2402 ? WhitespaceManager::inputUsesCRLF(
2403 Env.getSourceManager().getBufferData(
Env.getFileID()),
2404 Style.
LineEnding == FormatStyle::LE_DeriveCRLF)
2406 ContinuationIndenter
Indenter(Style, Tokens.getKeywords(),
2407 Env.getSourceManager(), Whitespaces, Encoding,
2408 BinPackInconclusiveFunctions);
2410 UnwrappedLineFormatter(&
Indenter, &Whitespaces, Style,
2411 Tokens.getKeywords(),
Env.getSourceManager(),
2413 .format(AnnotatedLines,
false,
2416 Env.getFirstStartColumn(),
2417 Env.getNextStartColumn(),
2418 Env.getLastStartColumn());
2419 for (
const auto &R : Whitespaces.generateReplacements())
2421 return std::make_pair(Result, 0);
2422 return std::make_pair(Result, Penalty);
2427 hasCpp03IncompatibleFormat(
const SmallVectorImpl<AnnotatedLine *> &Lines) {
2428 for (
const AnnotatedLine *Line : Lines) {
2429 if (hasCpp03IncompatibleFormat(Line->Children))
2431 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {
2432 if (!Tok->hasWhitespaceBefore()) {
2433 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
2435 if (Tok->is(TT_TemplateCloser) &&
2436 Tok->Previous->is(TT_TemplateCloser)) {
2445 int countVariableAlignments(
const SmallVectorImpl<AnnotatedLine *> &Lines) {
2446 int AlignmentDiff = 0;
2447 for (
const AnnotatedLine *Line : Lines) {
2448 AlignmentDiff += countVariableAlignments(Line->Children);
2449 for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {
2450 if (Tok->isNot(TT_PointerOrReference))
2453 if (
const auto *Prev = Tok->getPreviousNonComment()) {
2454 if (Prev->is(tok::r_paren) && Prev->MatchingParen) {
2455 if (
const auto *Func =
2456 Prev->MatchingParen->getPreviousNonComment()) {
2457 if (
Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName,
2458 TT_OverloadedOperator)) {
2464 bool SpaceBefore = Tok->hasWhitespaceBefore();
2465 bool SpaceAfter = Tok->Next->hasWhitespaceBefore();
2466 if (SpaceBefore && !SpaceAfter)
2468 if (!SpaceBefore && SpaceAfter)
2472 return AlignmentDiff;
2476 deriveLocalStyle(
const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2477 bool HasBinPackedFunction =
false;
2478 bool HasOnePerLineFunction =
false;
2479 for (AnnotatedLine *Line : AnnotatedLines) {
2480 if (!Line->First->Next)
2482 FormatToken *Tok = Line->First->Next;
2484 if (Tok->is(PPK_BinPacked))
2485 HasBinPackedFunction =
true;
2486 if (Tok->is(PPK_OnePerLine))
2487 HasOnePerLineFunction =
true;
2493 const auto NetRightCount = countVariableAlignments(AnnotatedLines);
2494 if (NetRightCount > 0)
2496 else if (NetRightCount < 0)
2500 if (Style.
Standard == FormatStyle::LS_Auto) {
2501 Style.
Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
2502 ? FormatStyle::LS_Latest
2503 : FormatStyle::LS_Cpp03;
2505 BinPackInconclusiveFunctions =
2506 HasBinPackedFunction || !HasOnePerLineFunction;
2509 bool BinPackInconclusiveFunctions;
2510 FormattingAttemptStatus *Status;
2524class TrailingCommaInserter :
public TokenAnalyzer {
2526 TrailingCommaInserter(
const Environment &
Env,
const FormatStyle &Style)
2527 : TokenAnalyzer(
Env, Style) {}
2529 std::pair<tooling::Replacements, unsigned>
2530 analyze(TokenAnnotator &Annotator,
2531 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2532 FormatTokenLexer &Tokens)
override {
2533 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2534 tooling::Replacements Result;
2535 insertTrailingCommas(AnnotatedLines, Result);
2542 void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,
2543 tooling::Replacements &Result) {
2544 for (AnnotatedLine *Line : Lines) {
2545 insertTrailingCommas(Line->Children, Result);
2546 if (!Line->Affected)
2548 for (FormatToken *FormatTok = Line->First; FormatTok;
2549 FormatTok = FormatTok->Next) {
2550 if (FormatTok->NewlinesBefore == 0)
2552 FormatToken *Matching = FormatTok->MatchingParen;
2553 if (!Matching || !FormatTok->getPreviousNonComment())
2555 if (!(FormatTok->is(tok::r_square) &&
2556 Matching->is(TT_ArrayInitializerLSquare)) &&
2557 !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) {
2560 FormatToken *Prev = FormatTok->getPreviousNonComment();
2561 if (Prev->is(tok::comma) || Prev->is(tok::semi))
2565 SourceLocation Start =
2566 Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size());
2570 unsigned ColumnNumber =
2571 Env.getSourceManager().getSpellingColumnNumber(Start);
2576 cantFail(Result.add(
2577 tooling::Replacement(
Env.getSourceManager(), Start, 0,
",")));
2585class Cleaner :
public TokenAnalyzer {
2588 : TokenAnalyzer(
Env, Style),
2589 DeletedTokens(FormatTokenLess(
Env.getSourceManager())) {}
2592 std::pair<tooling::Replacements, unsigned>
2593 analyze(TokenAnnotator &Annotator,
2594 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2595 FormatTokenLexer &Tokens)
override {
2603 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2605 checkEmptyNamespace(AnnotatedLines);
2607 for (
auto *Line : AnnotatedLines)
2610 return {generateFixes(), 0};
2614 void cleanupLine(AnnotatedLine *Line) {
2615 for (
auto *Child : Line->Children)
2618 if (Line->Affected) {
2619 cleanupRight(Line->First, tok::comma, tok::comma);
2620 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
2621 cleanupRight(Line->First, tok::l_paren, tok::comma);
2622 cleanupLeft(Line->First, tok::comma, tok::r_paren);
2623 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
2624 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
2625 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
2629 bool containsOnlyComments(
const AnnotatedLine &Line) {
2630 for (FormatToken *Tok = Line.First; Tok; Tok = Tok->Next)
2631 if (Tok->isNot(tok::comment))
2637 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2638 std::set<unsigned> DeletedLines;
2639 for (
unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
2640 auto &Line = *AnnotatedLines[i];
2641 if (Line.startsWithNamespace())
2642 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
2645 for (
auto Line : DeletedLines) {
2646 FormatToken *Tok = AnnotatedLines[Line]->First;
2658 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2659 unsigned CurrentLine,
unsigned &
NewLine,
2660 std::set<unsigned> &DeletedLines) {
2661 unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
2666 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
2670 }
else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
2673 while (++CurrentLine < End) {
2674 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
2677 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
2678 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine,
NewLine,
2686 if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
2696 if (CurrentLine >= End)
2700 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
2701 AnnotatedLines[InitLine]->First->Tok.getLocation(),
2702 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) {
2706 for (
unsigned i = InitLine; i <= CurrentLine; ++i)
2707 DeletedLines.insert(i);
2716 template <
typename LeftKind,
typename RightKind>
2717 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
2719 auto NextNotDeleted = [
this](
const FormatToken &Tok) -> FormatToken * {
2720 for (
auto *Res = Tok.Next; Res; Res = Res->Next) {
2721 if (Res->isNot(tok::comment) &&
2722 DeletedTokens.find(Res) == DeletedTokens.end()) {
2728 for (
auto *Left = Start; Left;) {
2729 auto *Right = NextNotDeleted(*Left);
2732 if (Left->is(LK) && Right->is(RK)) {
2733 deleteToken(DeleteLeft ? Left : Right);
2734 for (
auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
2745 template <
typename LeftKind,
typename RightKind>
2746 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
2747 cleanupPair(Start, LK, RK,
true);
2750 template <
typename LeftKind,
typename RightKind>
2751 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
2752 cleanupPair(Start, LK, RK,
false);
2756 inline void deleteToken(FormatToken *Tok) {
2758 DeletedTokens.insert(Tok);
2761 tooling::Replacements generateFixes() {
2762 tooling::Replacements Fixes;
2763 SmallVector<FormatToken *> Tokens;
2764 std::copy(DeletedTokens.begin(), DeletedTokens.end(),
2765 std::back_inserter(Tokens));
2771 while (Idx < Tokens.size()) {
2772 unsigned St = Idx, End = Idx;
2773 while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1])
2775 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
2776 Tokens[End]->Tok.getEndLoc());
2778 Fixes.add(tooling::Replacement(
Env.getSourceManager(), SR,
""));
2782 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
2783 assert(
false &&
"Fixes must not conflict!");
2794 struct FormatTokenLess {
2795 FormatTokenLess(
const SourceManager &
SM) :
SM(
SM) {}
2797 bool operator()(
const FormatToken *LHS,
const FormatToken *RHS)
const {
2798 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
2799 RHS->Tok.getLocation());
2805 std::set<FormatToken *, FormatTokenLess> DeletedTokens;
2808class ObjCHeaderStyleGuesser :
public TokenAnalyzer {
2810 ObjCHeaderStyleGuesser(
const Environment &
Env,
const FormatStyle &Style)
2811 : TokenAnalyzer(
Env, Style), IsObjC(
false) {}
2813 std::pair<tooling::Replacements, unsigned>
2814 analyze(TokenAnnotator &Annotator,
2815 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2816 FormatTokenLexer &Tokens)
override {
2817 assert(Style.
Language == FormatStyle::LK_Cpp);
2818 IsObjC = guessIsObjC(
Env.getSourceManager(), AnnotatedLines,
2819 Tokens.getKeywords());
2820 tooling::Replacements Result;
2824 bool isObjC() {
return IsObjC; }
2828 guessIsObjC(
const SourceManager &SourceManager,
2829 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2830 const AdditionalKeywords &Keywords) {
2832 static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
2847 "FOUNDATION_EXPORT",
2848 "FOUNDATION_EXTERN",
2849 "NSAffineTransform",
2851 "NSAttributedString",
2870 "NSInvocationOperation",
2874 "NSMutableAttributedString",
2875 "NSMutableCharacterSet",
2877 "NSMutableDictionary",
2878 "NSMutableIndexSet",
2879 "NSMutableOrderedSet",
2883 "NSNumberFormatter",
2887 "NSOperationQueuePriority",
2891 "NSQualityOfService",
2894 "NSRegularExpression",
2905 "NS_ASSUME_NONNULL_BEGIN",
2910 for (
auto *Line : AnnotatedLines) {
2911 if (Line->First && (Line->First->TokenText.starts_with(
"#") ||
2912 Line->First->TokenText ==
"__pragma" ||
2913 Line->First->TokenText ==
"_Pragma")) {
2916 for (
const FormatToken *FormatTok = Line->First; FormatTok;
2917 FormatTok = FormatTok->Next) {
2918 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
2919 (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
2920 FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
2922 (FormatTok->Tok.isAnyIdentifier() &&
2923 std::binary_search(std::begin(FoundationIdentifiers),
2924 std::end(FoundationIdentifiers),
2925 FormatTok->TokenText)) ||
2926 FormatTok->is(TT_ObjCStringLiteral) ||
2927 FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,
2928 Keywords.kw_NS_ERROR_ENUM,
2929 Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,
2930 TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,
2931 TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,
2933 LLVM_DEBUG(llvm::dbgs()
2934 <<
"Detected ObjC at location "
2935 << FormatTok->Tok.getLocation().printToString(
2937 <<
" token: " << FormatTok->TokenText <<
" token type: "
2942 if (guessIsObjC(SourceManager, Line->Children, Keywords))
2959struct JavaImportDirective {
2972 for (
const auto &Range : Ranges) {
2973 if (Range.getOffset() < End &&
2974 Range.getOffset() + Range.getLength() > Start) {
2988static std::pair<unsigned, unsigned>
2992 unsigned OffsetToEOL = 0;
2993 for (
int i = 0, e = Includes.size(); i != e; ++i) {
2994 unsigned Start = Includes[Indices[i]].Offset;
2995 unsigned End = Start + Includes[Indices[i]].Text.size();
2996 if (!(Cursor >= Start && Cursor < End))
2998 CursorIndex = Indices[i];
2999 OffsetToEOL = End - Cursor;
3002 while (--i >= 0 && Includes[CursorIndex].
Text == Includes[Indices[i]].
Text)
3006 return std::make_pair(CursorIndex, OffsetToEOL);
3011 std::string NewCode;
3012 size_t Pos = 0, LastPos = 0;
3015 Pos = Code.find(
"\r\n", LastPos);
3016 if (Pos == LastPos) {
3020 if (Pos == std::string::npos) {
3021 NewCode += Code.substr(LastPos);
3024 NewCode += Code.substr(LastPos, Pos - LastPos) +
"\n";
3026 }
while (Pos != std::string::npos);
3044 const unsigned IncludesBeginOffset = Includes.front().Offset;
3045 const unsigned IncludesEndOffset =
3046 Includes.back().Offset + Includes.back().Text.size();
3047 const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
3048 if (!
affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
3051 llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size()));
3054 llvm::stable_sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
3055 const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
3056 const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
3057 return std::tie(Includes[LHSI].
Priority, LHSFilenameLower,
3059 std::tie(Includes[RHSI].
Priority, RHSFilenameLower,
3063 llvm::stable_sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
3071 unsigned CursorIndex;
3073 unsigned CursorToEOLOffset;
3075 std::tie(CursorIndex, CursorToEOLOffset) =
3080 Indices.erase(std::unique(Indices.begin(), Indices.end(),
3081 [&](
unsigned LHSI,
unsigned RHSI) {
3082 return Includes[LHSI].Text.trim() ==
3083 Includes[RHSI].Text.trim();
3087 int CurrentCategory = Includes.front().Category;
3095 if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) &&
3101 for (
unsigned Index : Indices) {
3102 if (!result.empty()) {
3106 CurrentCategory != Includes[Index].Category) {
3110 result += Includes[Index].Text;
3111 if (Cursor && CursorIndex == Index)
3112 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
3113 CurrentCategory = Includes[Index].Category;
3116 if (Cursor && *Cursor >= IncludesEndOffset)
3117 *Cursor += result.size() - IncludesBlockSize;
3122 IncludesBeginOffset, IncludesBlockSize)))) {
3127 FileName, Includes.front().Offset, IncludesBlockSize, result));
3131 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
3141 unsigned Prev = llvm::StringSwitch<size_t>(Code)
3142 .StartsWith(
"\xEF\xBB\xBF", 3)
3144 unsigned SearchFrom = 0;
3156 bool FirstIncludeBlock =
true;
3157 bool MainIncludeFound =
false;
3158 bool FormattingOff =
false;
3161 llvm::Regex RawStringRegex(
3162 "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\(");
3164 std::string RawStringTermination =
")\"";
3167 auto Pos = Code.find(
'\n', SearchFrom);
3169 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3171 StringRef Trimmed =
Line.trim();
3176 if (RawStringRegex.match(Trimmed, &RawStringMatches)) {
3177 std::string CharSequence = RawStringMatches[1].str();
3178 RawStringTermination =
")" + CharSequence +
"\"";
3179 FormattingOff =
true;
3182 if (Trimmed.contains(RawStringTermination))
3183 FormattingOff =
false;
3186 FormattingOff =
true;
3188 FormattingOff =
false;
3190 const bool EmptyLineSkipped =
3196 bool MergeWithNextLine = Trimmed.ends_with(
"\\");
3197 if (!FormattingOff && !MergeWithNextLine) {
3199 StringRef IncludeName = Matches[2];
3200 if (
Line.contains(
"/*") && !
Line.contains(
"*/")) {
3205 Pos = Code.find(
"*/", SearchFrom);
3207 Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev);
3211 !MainIncludeFound && FirstIncludeBlock);
3213 IncludeName, !MainIncludeFound && FirstIncludeBlock);
3215 MainIncludeFound =
true;
3216 IncludesInBlock.push_back(
3218 }
else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
3221 IncludesInBlock.clear();
3222 if (Trimmed.starts_with(
"#pragma hdrstop"))
3223 FirstIncludeBlock =
true;
3225 FirstIncludeBlock =
false;
3228 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3231 if (!MergeWithNextLine)
3233 SearchFrom = Pos + 1;
3235 if (!IncludesInBlock.empty()) {
3245 StringRef ImportIdentifier) {
3246 unsigned LongestMatchIndex =
UINT_MAX;
3247 unsigned LongestMatchLength = 0;
3250 if (ImportIdentifier.starts_with(GroupPrefix) &&
3251 GroupPrefix.length() > LongestMatchLength) {
3252 LongestMatchIndex = I;
3253 LongestMatchLength = GroupPrefix.length();
3256 return LongestMatchIndex;
3268 unsigned ImportsBeginOffset = Imports.front().Offset;
3269 unsigned ImportsEndOffset =
3270 Imports.back().Offset + Imports.back().Text.size();
3271 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;
3272 if (!
affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))
3276 llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size()));
3279 for (
const JavaImportDirective &Import : Imports)
3282 bool StaticImportAfterNormalImport =
3284 llvm::sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
3286 return std::make_tuple(!Imports[LHSI].
IsStatic ^
3287 StaticImportAfterNormalImport,
3289 std::make_tuple(!Imports[RHSI].
IsStatic ^
3290 StaticImportAfterNormalImport,
3295 Indices.erase(std::unique(Indices.begin(), Indices.end(),
3296 [&](
unsigned LHSI,
unsigned RHSI) {
3297 return Imports[LHSI].Text == Imports[RHSI].Text;
3301 bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
3305 for (
unsigned Index : Indices) {
3306 if (!result.empty()) {
3308 if (CurrentIsStatic != Imports[Index].
IsStatic ||
3314 result += CommentLine;
3317 result += Imports[Index].Text;
3318 CurrentIsStatic = Imports[Index].IsStatic;
3325 Imports.front().Offset, ImportsBlockSize)))) {
3330 ImportsBlockSize, result));
3334 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
3341const char JavaImportRegexPattern[] =
3342 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;";
3351 unsigned SearchFrom = 0;
3352 llvm::Regex ImportRegex(JavaImportRegexPattern);
3357 bool FormattingOff =
false;
3360 auto Pos = Code.find(
'\n', SearchFrom);
3362 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3364 StringRef Trimmed =
Line.trim();
3366 FormattingOff =
true;
3368 FormattingOff =
false;
3370 if (ImportRegex.match(
Line, &Matches)) {
3371 if (FormattingOff) {
3376 StringRef
Static = Matches[1];
3379 if (
Static.contains(
"static"))
3381 ImportsInBlock.push_back(
3384 }
else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) {
3389 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3391 SearchFrom = Pos + 1;
3393 if (!ImportsInBlock.empty())
3402 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
3405bool isLikelyXml(StringRef Code) {
return Code.ltrim().starts_with(
"<"); }
3409 StringRef
FileName,
unsigned *Cursor) {
3427template <
typename T>
3432 if (Replaces.
empty())
3435 auto NewCode = applyAllReplacements(Code, Replaces);
3437 return NewCode.takeError();
3442 ProcessFunc(Style, *NewCode, ChangedRanges,
FileName);
3444 return Replaces.
merge(FormatReplaces);
3453 std::vector<tooling::Range> Ranges,
3457 auto SortedReplaces =
3459 if (!SortedReplaces)
3460 return SortedReplaces.takeError();
3464 auto Reformat = [](
const FormatStyle &Style, StringRef Code,
3465 std::vector<tooling::Range> Ranges,
3480inline bool isHeaderDeletion(
const tooling::Replacement &Replace) {
3481 return Replace.getOffset() ==
UINT_MAX && Replace.getLength() == 1;
3485tooling::Replacements
3486fixCppIncludeInsertions(StringRef Code,
const tooling::Replacements &Replaces,
3491 tooling::Replacements HeaderInsertions;
3492 std::set<llvm::StringRef> HeadersToDelete;
3493 tooling::Replacements
Result;
3494 for (
const auto &R : Replaces) {
3495 if (isHeaderInsertion(R)) {
3498 llvm::consumeError(HeaderInsertions.add(R));
3499 }
else if (isHeaderDeletion(R)) {
3500 HeadersToDelete.insert(R.getReplacementText());
3501 }
else if (R.getOffset() ==
UINT_MAX) {
3502 llvm::errs() <<
"Insertions other than header #include insertion are "
3504 << R.getReplacementText() <<
"\n";
3506 llvm::consumeError(
Result.add(R));
3509 if (HeaderInsertions.empty() && HeadersToDelete.empty())
3512 StringRef
FileName = Replaces.begin()->getFilePath();
3515 for (
const auto &Header : HeadersToDelete) {
3516 tooling::Replacements Replaces =
3517 Includes.remove(Header.trim(
"\"<>"), Header.starts_with(
"<"));
3518 for (
const auto &R : Replaces) {
3519 auto Err =
Result.add(R);
3522 llvm::errs() <<
"Failed to add header deletion replacement for "
3523 << Header <<
": " << llvm::toString(std::move(Err))
3530 for (
const auto &R : HeaderInsertions) {
3534 assert(Matched &&
"Header insertion replacement must have replacement text "
3537 auto IncludeName = Matches[2];
3539 Includes.insert(IncludeName.trim(
"\"<>"), IncludeName.starts_with(
"<"),
3542 auto Err =
Result.add(*Replace);
3544 llvm::consumeError(std::move(Err));
3545 unsigned NewOffset =
3546 Result.getShiftedCodePosition(Replace->getOffset());
3547 auto Shifted = tooling::Replacement(
FileName, NewOffset, 0,
3548 Replace->getReplacementText());
3563 auto Cleanup = [](
const FormatStyle &Style, StringRef Code,
3564 std::vector<tooling::Range> Ranges,
3570 fixCppIncludeInsertions(Code, Replaces, Style);
3575std::pair<tooling::Replacements, unsigned>
3578 unsigned NextStartColumn,
unsigned LastStartColumn, StringRef FileName,
3589 case FormatStyle::RCPS_SingleLine:
3590 case FormatStyle::RCPS_WithPreceding:
3606 std::vector<tooling::Range> Ranges(1,
tooling::Range(0, Code.size()));
3607 auto Env = Environment::make(Code,
FileName, Ranges, FirstStartColumn,
3608 NextStartColumn, LastStartColumn);
3613 Formatter(*
Env, Style, Status).process().first;
3615 Replaces = Replaces.
merge(
3618 if (applyAllReplacements(Code, Replaces))
3619 return {Replaces, 0};
3623 auto Env = Environment::make(Code,
FileName, Ranges, FirstStartColumn,
3624 NextStartColumn, LastStartColumn);
3628 typedef std::function<std::pair<tooling::Replacements, unsigned>(
3638 if (Style.
isCpp()) {
3645 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3646 return ParensRemover(
Env, S).process(
true);
3652 S.InsertBraces =
true;
3653 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3654 return BracesInserter(
Env, S).process(
true);
3660 S.RemoveBracesLLVM =
true;
3661 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3662 return BracesRemover(
Env, S).process(
true);
3668 S.RemoveSemicolon =
true;
3669 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3670 return SemiRemover(
Env, S).process();
3693 if (Style.
Language == FormatStyle::LK_ObjC &&
3703 return JavaScriptRequoter(
Env, Expanded).process(
true);
3708 return Formatter(
Env, Expanded, Status).process();
3714 return TrailingCommaInserter(
Env, Expanded).process();
3718 std::optional<std::string> CurrentCode;
3720 unsigned Penalty = 0;
3721 for (
size_t I = 0, E = Passes.size(); I < E; ++I) {
3722 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
3723 auto NewCode = applyAllReplacements(
3724 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
3726 Fixes = Fixes.
merge(PassFixes.first);
3727 Penalty += PassFixes.second;
3729 CurrentCode = std::move(*NewCode);
3730 Env = Environment::make(
3732 tooling::calculateRangesAfterReplacements(Fixes, Ranges),
3733 FirstStartColumn, NextStartColumn, LastStartColumn);
3746 StringRef OriginalCode = Code.substr(Fix.getOffset(), Fix.getLength());
3747 if (!OriginalCode.equals(Fix.getReplacementText())) {
3748 auto Err = NonNoOpFixes.
add(Fix);
3750 llvm::errs() <<
"Error adding replacements : "
3751 << llvm::toString(std::move(Err)) <<
"\n";
3755 Fixes = std::move(NonNoOpFixes);
3758 return {Fixes, Penalty};
3782 return Cleaner(*
Env, Style).process().first;
3787 StringRef
FileName,
bool *IncompleteFormat) {
3790 if (!Status.FormatComplete)
3791 *IncompleteFormat =
true;
3825 LangOpts.CPlusPlus = 1;
3835 LangOpts.LineComment = 1;
3836 LangOpts.CXXOperatorNames =
IsCpp;
3839 LangOpts.MicrosoftExt = 1;
3840 LangOpts.DeclSpecKeyword = 1;
3846 "Set coding style. <string> can be:\n"
3847 "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"
3848 " Mozilla, WebKit.\n"
3849 "2. 'file' to load style configuration from a\n"
3850 " .clang-format file in one of the parent directories\n"
3851 " of the source file (for stdin, see --assume-filename).\n"
3852 " If no .clang-format file is found, falls back to\n"
3853 " --fallback-style.\n"
3854 " --style=file is the default.\n"
3855 "3. 'file:<format_file_path>' to explicitly specify\n"
3856 " the configuration file.\n"
3857 "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n"
3858 " --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
3863 if (
FileName.ends_with_insensitive(
".js") ||
3864 FileName.ends_with_insensitive(
".mjs") ||
3865 FileName.ends_with_insensitive(
".ts")) {
3870 if (
FileName.ends_with_insensitive(
".proto") ||
3871 FileName.ends_with_insensitive(
".protodevel")) {
3874 if (
FileName.ends_with_insensitive(
".textpb") ||
3875 FileName.ends_with_insensitive(
".pb.txt") ||
3876 FileName.ends_with_insensitive(
".textproto") ||
3877 FileName.ends_with_insensitive(
".asciipb")) {
3880 if (
FileName.ends_with_insensitive(
".td"))
3882 if (
FileName.ends_with_insensitive(
".cs"))
3884 if (
FileName.ends_with_insensitive(
".json"))
3886 if (
FileName.ends_with_insensitive(
".sv") ||
3887 FileName.ends_with_insensitive(
".svh") ||
3888 FileName.ends_with_insensitive(
".v") ||
3889 FileName.ends_with_insensitive(
".vh")) {
3898 auto Extension = llvm::sys::path::extension(
FileName);
3901 if (!Code.empty() && (Extension.empty() || Extension ==
".h")) {
3906 if (Guesser.isObjC())
3910 return GuessedLanguage;
3918llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
3921 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
3922 FS->getBufferForFile(ConfigFile.str());
3923 if (
auto EC =
Text.getError())
3931 StringRef FallbackStyleName,
3932 StringRef Code, llvm::vfs::FileSystem *FS,
3933 bool AllowUnknownOptions) {
3940 ChildFormatTextToApply;
3942 if (StyleName.starts_with(
"{")) {
3944 StringRef Source =
"<command-line>";
3945 if (std::error_code ec =
3947 AllowUnknownOptions)) {
3954 ChildFormatTextToApply.emplace_back(
3955 llvm::MemoryBuffer::getMemBuffer(StyleName, Source,
false));
3959 FS = llvm::vfs::getRealFileSystem().get();
3964 StyleName.starts_with_insensitive(
"file:")) {
3965 auto ConfigFile = StyleName.substr(5);
3966 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
3968 if (
auto EC =
Text.getError()) {
3973 LLVM_DEBUG(llvm::dbgs()
3974 <<
"Using configuration file " << ConfigFile <<
"\n");
3982 ChildFormatTextToApply.emplace_back(std::move(*
Text));
3996 if (std::error_code EC = FS->makeAbsolute(Path))
4002 auto dropDiagnosticHandler = [](
const llvm::SMDiagnostic &,
void *) {};
4004 auto applyChildFormatTexts = [&](
FormatStyle *Style) {
4005 for (
const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) {
4007 dropDiagnosticHandler);
4010 static_cast<void>(EC);
4016 FilesToLookFor.push_back(
".clang-format");
4017 FilesToLookFor.push_back(
"_clang-format");
4020 for (StringRef Directory = Path; !Directory.empty();
4021 Directory = llvm::sys::path::parent_path(Directory)) {
4022 auto Status = FS->status(Directory);
4024 Status->getType() != llvm::sys::fs::file_type::directory_file) {
4028 for (
const auto &F : FilesToLookFor) {
4031 llvm::sys::path::append(ConfigFile, F);
4032 LLVM_DEBUG(llvm::dbgs() <<
"Trying " << ConfigFile <<
"...\n");
4034 Status = FS->status(ConfigFile);
4036 Status->getType() != llvm::sys::fs::file_type::regular_file) {
4040 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
4042 if (
auto EC =
Text.getError()) {
4047 if (!UnsuitableConfigFiles.empty())
4048 UnsuitableConfigFiles.append(
", ");
4049 UnsuitableConfigFiles.append(ConfigFile);
4053 LLVM_DEBUG(llvm::dbgs()
4054 <<
"Using configuration file " << ConfigFile <<
"\n");
4057 if (!ChildFormatTextToApply.empty()) {
4058 LLVM_DEBUG(llvm::dbgs() <<
"Applying child configurations\n");
4059 applyChildFormatTexts(&Style);
4064 LLVM_DEBUG(llvm::dbgs() <<
"Inherits parent configuration\n");
4069 ChildFormatTextToApply.emplace_back(std::move(*
Text));
4079 if (!UnsuitableConfigFiles.empty()) {
4082 UnsuitableConfigFiles);
4085 if (!ChildFormatTextToApply.empty()) {
4086 LLVM_DEBUG(llvm::dbgs()
4087 <<
"Applying child configurations on fallback style\n");
4088 applyChildFormatTexts(&FallbackStyle);
4091 return FallbackStyle;
4095 if (Comment == (On ?
"/* clang-format on */" :
"/* clang-format off */"))
4098 static const char ClangFormatOn[] =
"// clang-format on";
4099 static const char ClangFormatOff[] =
"// clang-format off";
4100 const unsigned Size = (On ?
sizeof ClangFormatOn :
sizeof ClangFormatOff) - 1;
4102 return Comment.starts_with(On ? ClangFormatOn : ClangFormatOff) &&
4103 (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.
YAML serialization mapping.
static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value)
static void enumeration(IO &IO, FormatStyle::LambdaBodyIndentationKind &Value)