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);
282template <>
struct ScalarEnumerationTraits<
FormatStyle::DAGArgStyle> {
284 IO.enumCase(
Value,
"DontBreak", FormatStyle::DAS_DontBreak);
285 IO.enumCase(
Value,
"BreakElements", FormatStyle::DAS_BreakElements);
286 IO.enumCase(
Value,
"BreakAll", FormatStyle::DAS_BreakAll);
291struct ScalarEnumerationTraits<
FormatStyle::DefinitionReturnTypeBreakingStyle> {
294 IO.enumCase(
Value,
"None", FormatStyle::DRTBS_None);
295 IO.enumCase(
Value,
"All", FormatStyle::DRTBS_All);
296 IO.enumCase(
Value,
"TopLevel", FormatStyle::DRTBS_TopLevel);
299 IO.enumCase(
Value,
"false", FormatStyle::DRTBS_None);
300 IO.enumCase(
Value,
"true", FormatStyle::DRTBS_All);
305struct ScalarEnumerationTraits<
FormatStyle::EscapedNewlineAlignmentStyle> {
307 FormatStyle::EscapedNewlineAlignmentStyle &
Value) {
308 IO.enumCase(
Value,
"DontAlign", FormatStyle::ENAS_DontAlign);
309 IO.enumCase(
Value,
"Left", FormatStyle::ENAS_Left);
310 IO.enumCase(
Value,
"Right", FormatStyle::ENAS_Right);
313 IO.enumCase(
Value,
"true", FormatStyle::ENAS_Left);
314 IO.enumCase(
Value,
"false", FormatStyle::ENAS_Right);
319struct ScalarEnumerationTraits<
FormatStyle::EmptyLineAfterAccessModifierStyle> {
322 IO.enumCase(
Value,
"Never", FormatStyle::ELAAMS_Never);
323 IO.enumCase(
Value,
"Leave", FormatStyle::ELAAMS_Leave);
324 IO.enumCase(
Value,
"Always", FormatStyle::ELAAMS_Always);
329struct ScalarEnumerationTraits<
333 IO.enumCase(
Value,
"Never", FormatStyle::ELBAMS_Never);
334 IO.enumCase(
Value,
"Leave", FormatStyle::ELBAMS_Leave);
335 IO.enumCase(
Value,
"LogicalBlock", FormatStyle::ELBAMS_LogicalBlock);
336 IO.enumCase(
Value,
"Always", FormatStyle::ELBAMS_Always);
341struct ScalarEnumerationTraits<
FormatStyle::IndentExternBlockStyle> {
343 IO.enumCase(
Value,
"AfterExternBlock", FormatStyle::IEBS_AfterExternBlock);
344 IO.enumCase(
Value,
"Indent", FormatStyle::IEBS_Indent);
345 IO.enumCase(
Value,
"NoIndent", FormatStyle::IEBS_NoIndent);
346 IO.enumCase(
Value,
"true", FormatStyle::IEBS_Indent);
347 IO.enumCase(
Value,
"false", FormatStyle::IEBS_NoIndent);
351template <>
struct MappingTraits<
FormatStyle::IntegerLiteralSeparatorStyle> {
352 static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &
Base) {
353 IO.mapOptional(
"Binary",
Base.Binary);
354 IO.mapOptional(
"BinaryMinDigits",
Base.BinaryMinDigits);
355 IO.mapOptional(
"Decimal",
Base.Decimal);
356 IO.mapOptional(
"DecimalMinDigits",
Base.DecimalMinDigits);
357 IO.mapOptional(
"Hex",
Base.Hex);
358 IO.mapOptional(
"HexMinDigits",
Base.HexMinDigits);
362template <>
struct ScalarEnumerationTraits<
FormatStyle::JavaScriptQuoteStyle> {
364 IO.enumCase(
Value,
"Leave", FormatStyle::JSQS_Leave);
365 IO.enumCase(
Value,
"Single", FormatStyle::JSQS_Single);
366 IO.enumCase(
Value,
"Double", FormatStyle::JSQS_Double);
370template <>
struct ScalarEnumerationTraits<
FormatStyle::LanguageKind> {
372 IO.enumCase(
Value,
"Cpp", FormatStyle::LK_Cpp);
373 IO.enumCase(
Value,
"Java", FormatStyle::LK_Java);
374 IO.enumCase(
Value,
"JavaScript", FormatStyle::LK_JavaScript);
375 IO.enumCase(
Value,
"ObjC", FormatStyle::LK_ObjC);
376 IO.enumCase(
Value,
"Proto", FormatStyle::LK_Proto);
377 IO.enumCase(
Value,
"TableGen", FormatStyle::LK_TableGen);
378 IO.enumCase(
Value,
"TextProto", FormatStyle::LK_TextProto);
379 IO.enumCase(
Value,
"CSharp", FormatStyle::LK_CSharp);
380 IO.enumCase(
Value,
"Json", FormatStyle::LK_Json);
381 IO.enumCase(
Value,
"Verilog", FormatStyle::LK_Verilog);
385template <>
struct ScalarEnumerationTraits<
FormatStyle::LanguageStandard> {
387 IO.enumCase(
Value,
"c++03", FormatStyle::LS_Cpp03);
388 IO.enumCase(
Value,
"C++03", FormatStyle::LS_Cpp03);
389 IO.enumCase(
Value,
"Cpp03", FormatStyle::LS_Cpp03);
391 IO.enumCase(
Value,
"c++11", FormatStyle::LS_Cpp11);
392 IO.enumCase(
Value,
"C++11", FormatStyle::LS_Cpp11);
394 IO.enumCase(
Value,
"c++14", FormatStyle::LS_Cpp14);
395 IO.enumCase(
Value,
"c++17", FormatStyle::LS_Cpp17);
396 IO.enumCase(
Value,
"c++20", FormatStyle::LS_Cpp20);
398 IO.enumCase(
Value,
"Latest", FormatStyle::LS_Latest);
399 IO.enumCase(
Value,
"Cpp11", FormatStyle::LS_Latest);
400 IO.enumCase(
Value,
"Auto", FormatStyle::LS_Auto);
405struct ScalarEnumerationTraits<
FormatStyle::LambdaBodyIndentationKind> {
407 FormatStyle::LambdaBodyIndentationKind &
Value) {
408 IO.enumCase(
Value,
"Signature", FormatStyle::LBI_Signature);
409 IO.enumCase(
Value,
"OuterScope", FormatStyle::LBI_OuterScope);
413template <>
struct ScalarEnumerationTraits<
FormatStyle::LineEndingStyle> {
415 IO.enumCase(
Value,
"LF", FormatStyle::LE_LF);
416 IO.enumCase(
Value,
"CRLF", FormatStyle::LE_CRLF);
417 IO.enumCase(
Value,
"DeriveLF", FormatStyle::LE_DeriveLF);
418 IO.enumCase(
Value,
"DeriveCRLF", FormatStyle::LE_DeriveCRLF);
423struct ScalarEnumerationTraits<
FormatStyle::NamespaceIndentationKind> {
425 FormatStyle::NamespaceIndentationKind &
Value) {
426 IO.enumCase(
Value,
"None", FormatStyle::NI_None);
427 IO.enumCase(
Value,
"Inner", FormatStyle::NI_Inner);
428 IO.enumCase(
Value,
"All", FormatStyle::NI_All);
432template <>
struct ScalarEnumerationTraits<
FormatStyle::OperandAlignmentStyle> {
434 IO.enumCase(
Value,
"DontAlign", FormatStyle::OAS_DontAlign);
435 IO.enumCase(
Value,
"Align", FormatStyle::OAS_Align);
436 IO.enumCase(
Value,
"AlignAfterOperator",
437 FormatStyle::OAS_AlignAfterOperator);
440 IO.enumCase(
Value,
"true", FormatStyle::OAS_Align);
441 IO.enumCase(
Value,
"false", FormatStyle::OAS_DontAlign);
446struct ScalarEnumerationTraits<
FormatStyle::PackConstructorInitializersStyle> {
449 IO.enumCase(
Value,
"Never", FormatStyle::PCIS_Never);
450 IO.enumCase(
Value,
"BinPack", FormatStyle::PCIS_BinPack);
451 IO.enumCase(
Value,
"CurrentLine", FormatStyle::PCIS_CurrentLine);
452 IO.enumCase(
Value,
"NextLine", FormatStyle::PCIS_NextLine);
453 IO.enumCase(
Value,
"NextLineOnly", FormatStyle::PCIS_NextLineOnly);
457template <>
struct ScalarEnumerationTraits<
FormatStyle::PointerAlignmentStyle> {
459 IO.enumCase(
Value,
"Middle", FormatStyle::PAS_Middle);
460 IO.enumCase(
Value,
"Left", FormatStyle::PAS_Left);
461 IO.enumCase(
Value,
"Right", FormatStyle::PAS_Right);
464 IO.enumCase(
Value,
"true", FormatStyle::PAS_Left);
465 IO.enumCase(
Value,
"false", FormatStyle::PAS_Right);
470struct ScalarEnumerationTraits<
FormatStyle::PPDirectiveIndentStyle> {
472 IO.enumCase(
Value,
"None", FormatStyle::PPDIS_None);
473 IO.enumCase(
Value,
"AfterHash", FormatStyle::PPDIS_AfterHash);
474 IO.enumCase(
Value,
"BeforeHash", FormatStyle::PPDIS_BeforeHash);
479struct ScalarEnumerationTraits<
FormatStyle::QualifierAlignmentStyle> {
481 IO.enumCase(
Value,
"Leave", FormatStyle::QAS_Leave);
482 IO.enumCase(
Value,
"Left", FormatStyle::QAS_Left);
483 IO.enumCase(
Value,
"Right", FormatStyle::QAS_Right);
484 IO.enumCase(
Value,
"Custom", FormatStyle::QAS_Custom);
489 static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
490 IO.mapOptional(
"Language", Format.Language);
491 IO.mapOptional(
"Delimiters", Format.Delimiters);
492 IO.mapOptional(
"EnclosingFunctions", Format.EnclosingFunctions);
493 IO.mapOptional(
"CanonicalDelimiter", Format.CanonicalDelimiter);
494 IO.mapOptional(
"BasedOnStyle", Format.BasedOnStyle);
499struct ScalarEnumerationTraits<
FormatStyle::ReferenceAlignmentStyle> {
501 IO.enumCase(
Value,
"Pointer", FormatStyle::RAS_Pointer);
502 IO.enumCase(
Value,
"Middle", FormatStyle::RAS_Middle);
503 IO.enumCase(
Value,
"Left", FormatStyle::RAS_Left);
504 IO.enumCase(
Value,
"Right", FormatStyle::RAS_Right);
509struct ScalarEnumerationTraits<
FormatStyle::RemoveParenthesesStyle> {
511 IO.enumCase(
Value,
"Leave", FormatStyle::RPS_Leave);
512 IO.enumCase(
Value,
"MultipleParentheses",
513 FormatStyle::RPS_MultipleParentheses);
514 IO.enumCase(
Value,
"ReturnStatement", FormatStyle::RPS_ReturnStatement);
519struct ScalarEnumerationTraits<
FormatStyle::RequiresClausePositionStyle> {
521 FormatStyle::RequiresClausePositionStyle &
Value) {
522 IO.enumCase(
Value,
"OwnLine", FormatStyle::RCPS_OwnLine);
523 IO.enumCase(
Value,
"WithPreceding", FormatStyle::RCPS_WithPreceding);
524 IO.enumCase(
Value,
"WithFollowing", FormatStyle::RCPS_WithFollowing);
525 IO.enumCase(
Value,
"SingleLine", FormatStyle::RCPS_SingleLine);
530struct ScalarEnumerationTraits<
FormatStyle::RequiresExpressionIndentationKind> {
533 IO.enumCase(
Value,
"Keyword", FormatStyle::REI_Keyword);
534 IO.enumCase(
Value,
"OuterScope", FormatStyle::REI_OuterScope);
539struct ScalarEnumerationTraits<
FormatStyle::ReturnTypeBreakingStyle> {
541 IO.enumCase(
Value,
"None", FormatStyle::RTBS_None);
542 IO.enumCase(
Value,
"Automatic", FormatStyle::RTBS_Automatic);
543 IO.enumCase(
Value,
"ExceptShortType", FormatStyle::RTBS_ExceptShortType);
544 IO.enumCase(
Value,
"All", FormatStyle::RTBS_All);
545 IO.enumCase(
Value,
"TopLevel", FormatStyle::RTBS_TopLevel);
546 IO.enumCase(
Value,
"TopLevelDefinitions",
547 FormatStyle::RTBS_TopLevelDefinitions);
548 IO.enumCase(
Value,
"AllDefinitions", FormatStyle::RTBS_AllDefinitions);
553struct ScalarEnumerationTraits<
FormatStyle::SeparateDefinitionStyle> {
555 IO.enumCase(
Value,
"Leave", FormatStyle::SDS_Leave);
556 IO.enumCase(
Value,
"Always", FormatStyle::SDS_Always);
557 IO.enumCase(
Value,
"Never", FormatStyle::SDS_Never);
561template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortBlockStyle> {
563 IO.enumCase(
Value,
"Never", FormatStyle::SBS_Never);
564 IO.enumCase(
Value,
"false", FormatStyle::SBS_Never);
565 IO.enumCase(
Value,
"Always", FormatStyle::SBS_Always);
566 IO.enumCase(
Value,
"true", FormatStyle::SBS_Always);
567 IO.enumCase(
Value,
"Empty", FormatStyle::SBS_Empty);
571template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortFunctionStyle> {
573 IO.enumCase(
Value,
"None", FormatStyle::SFS_None);
574 IO.enumCase(
Value,
"false", FormatStyle::SFS_None);
575 IO.enumCase(
Value,
"All", FormatStyle::SFS_All);
576 IO.enumCase(
Value,
"true", FormatStyle::SFS_All);
577 IO.enumCase(
Value,
"Inline", FormatStyle::SFS_Inline);
578 IO.enumCase(
Value,
"InlineOnly", FormatStyle::SFS_InlineOnly);
579 IO.enumCase(
Value,
"Empty", FormatStyle::SFS_Empty);
583template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortIfStyle> {
585 IO.enumCase(
Value,
"Never", FormatStyle::SIS_Never);
586 IO.enumCase(
Value,
"WithoutElse", FormatStyle::SIS_WithoutElse);
587 IO.enumCase(
Value,
"OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf);
588 IO.enumCase(
Value,
"AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse);
591 IO.enumCase(
Value,
"Always", FormatStyle::SIS_OnlyFirstIf);
592 IO.enumCase(
Value,
"false", FormatStyle::SIS_Never);
593 IO.enumCase(
Value,
"true", FormatStyle::SIS_WithoutElse);
597template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortLambdaStyle> {
599 IO.enumCase(
Value,
"None", FormatStyle::SLS_None);
600 IO.enumCase(
Value,
"false", FormatStyle::SLS_None);
601 IO.enumCase(
Value,
"Empty", FormatStyle::SLS_Empty);
602 IO.enumCase(
Value,
"Inline", FormatStyle::SLS_Inline);
603 IO.enumCase(
Value,
"All", FormatStyle::SLS_All);
604 IO.enumCase(
Value,
"true", FormatStyle::SLS_All);
608template <>
struct ScalarEnumerationTraits<
FormatStyle::SortIncludesOptions> {
610 IO.enumCase(
Value,
"Never", FormatStyle::SI_Never);
611 IO.enumCase(
Value,
"CaseInsensitive", FormatStyle::SI_CaseInsensitive);
612 IO.enumCase(
Value,
"CaseSensitive", FormatStyle::SI_CaseSensitive);
615 IO.enumCase(
Value,
"false", FormatStyle::SI_Never);
616 IO.enumCase(
Value,
"true", FormatStyle::SI_CaseSensitive);
621struct ScalarEnumerationTraits<
FormatStyle::SortJavaStaticImportOptions> {
623 FormatStyle::SortJavaStaticImportOptions &
Value) {
624 IO.enumCase(
Value,
"Before", FormatStyle::SJSIO_Before);
625 IO.enumCase(
Value,
"After", FormatStyle::SJSIO_After);
630struct ScalarEnumerationTraits<
FormatStyle::SortUsingDeclarationsOptions> {
632 FormatStyle::SortUsingDeclarationsOptions &
Value) {
633 IO.enumCase(
Value,
"Never", FormatStyle::SUD_Never);
634 IO.enumCase(
Value,
"Lexicographic", FormatStyle::SUD_Lexicographic);
635 IO.enumCase(
Value,
"LexicographicNumeric",
636 FormatStyle::SUD_LexicographicNumeric);
639 IO.enumCase(
Value,
"false", FormatStyle::SUD_Never);
640 IO.enumCase(
Value,
"true", FormatStyle::SUD_LexicographicNumeric);
645struct ScalarEnumerationTraits<
FormatStyle::SpaceAroundPointerQualifiersStyle> {
648 IO.enumCase(
Value,
"Default", FormatStyle::SAPQ_Default);
649 IO.enumCase(
Value,
"Before", FormatStyle::SAPQ_Before);
650 IO.enumCase(
Value,
"After", FormatStyle::SAPQ_After);
651 IO.enumCase(
Value,
"Both", FormatStyle::SAPQ_Both);
655template <>
struct MappingTraits<
FormatStyle::SpaceBeforeParensCustom> {
656 static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) {
657 IO.mapOptional(
"AfterControlStatements", Spacing.AfterControlStatements);
658 IO.mapOptional(
"AfterForeachMacros", Spacing.AfterForeachMacros);
659 IO.mapOptional(
"AfterFunctionDefinitionName",
660 Spacing.AfterFunctionDefinitionName);
661 IO.mapOptional(
"AfterFunctionDeclarationName",
662 Spacing.AfterFunctionDeclarationName);
663 IO.mapOptional(
"AfterIfMacros", Spacing.AfterIfMacros);
664 IO.mapOptional(
"AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
665 IO.mapOptional(
"AfterPlacementOperator", Spacing.AfterPlacementOperator);
666 IO.mapOptional(
"AfterRequiresInClause", Spacing.AfterRequiresInClause);
667 IO.mapOptional(
"AfterRequiresInExpression",
668 Spacing.AfterRequiresInExpression);
669 IO.mapOptional(
"BeforeNonEmptyParentheses",
670 Spacing.BeforeNonEmptyParentheses);
675struct ScalarEnumerationTraits<
FormatStyle::SpaceBeforeParensStyle> {
677 IO.enumCase(
Value,
"Never", FormatStyle::SBPO_Never);
678 IO.enumCase(
Value,
"ControlStatements",
679 FormatStyle::SBPO_ControlStatements);
680 IO.enumCase(
Value,
"ControlStatementsExceptControlMacros",
681 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
682 IO.enumCase(
Value,
"NonEmptyParentheses",
683 FormatStyle::SBPO_NonEmptyParentheses);
684 IO.enumCase(
Value,
"Always", FormatStyle::SBPO_Always);
685 IO.enumCase(
Value,
"Custom", FormatStyle::SBPO_Custom);
688 IO.enumCase(
Value,
"false", FormatStyle::SBPO_Never);
689 IO.enumCase(
Value,
"true", FormatStyle::SBPO_ControlStatements);
690 IO.enumCase(
Value,
"ControlStatementsExceptForEachMacros",
691 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
695template <>
struct ScalarEnumerationTraits<
FormatStyle::SpacesInAnglesStyle> {
697 IO.enumCase(
Value,
"Never", FormatStyle::SIAS_Never);
698 IO.enumCase(
Value,
"Always", FormatStyle::SIAS_Always);
699 IO.enumCase(
Value,
"Leave", FormatStyle::SIAS_Leave);
702 IO.enumCase(
Value,
"false", FormatStyle::SIAS_Never);
703 IO.enumCase(
Value,
"true", FormatStyle::SIAS_Always);
707template <>
struct MappingTraits<
FormatStyle::SpacesInLineComment> {
708 static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
710 int signedMaximum =
static_cast<int>(Space.Maximum);
711 IO.mapOptional(
"Minimum", Space.Minimum);
712 IO.mapOptional(
"Maximum", signedMaximum);
713 Space.Maximum =
static_cast<unsigned>(signedMaximum);
715 if (Space.Maximum != -1u)
716 Space.Minimum = std::min(Space.Minimum, Space.Maximum);
720template <>
struct MappingTraits<
FormatStyle::SpacesInParensCustom> {
721 static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) {
722 IO.mapOptional(
"InCStyleCasts", Spaces.InCStyleCasts);
723 IO.mapOptional(
"InConditionalStatements", Spaces.InConditionalStatements);
724 IO.mapOptional(
"InEmptyParentheses", Spaces.InEmptyParentheses);
725 IO.mapOptional(
"Other", Spaces.Other);
729template <>
struct ScalarEnumerationTraits<
FormatStyle::SpacesInParensStyle> {
731 IO.enumCase(
Value,
"Never", FormatStyle::SIPO_Never);
732 IO.enumCase(
Value,
"Custom", FormatStyle::SIPO_Custom);
736template <>
struct ScalarEnumerationTraits<
FormatStyle::TrailingCommaStyle> {
738 IO.enumCase(
Value,
"None", FormatStyle::TCS_None);
739 IO.enumCase(
Value,
"Wrapped", FormatStyle::TCS_Wrapped);
744struct ScalarEnumerationTraits<
FormatStyle::TrailingCommentsAlignmentKinds> {
746 FormatStyle::TrailingCommentsAlignmentKinds &
Value) {
747 IO.enumCase(
Value,
"Leave", FormatStyle::TCAS_Leave);
748 IO.enumCase(
Value,
"Always", FormatStyle::TCAS_Always);
749 IO.enumCase(
Value,
"Never", FormatStyle::TCAS_Never);
753template <>
struct MappingTraits<
FormatStyle::TrailingCommentsAlignmentStyle> {
755 FormatStyle::TrailingCommentsAlignmentStyle &
Value) {
756 IO.enumCase(
Value,
"Leave",
757 FormatStyle::TrailingCommentsAlignmentStyle(
758 {FormatStyle::TCAS_Leave, 0}));
760 IO.enumCase(
Value,
"Always",
761 FormatStyle::TrailingCommentsAlignmentStyle(
762 {FormatStyle::TCAS_Always, 0}));
764 IO.enumCase(
Value,
"Never",
765 FormatStyle::TrailingCommentsAlignmentStyle(
766 {FormatStyle::TCAS_Never, 0}));
769 IO.enumCase(
Value,
"true",
770 FormatStyle::TrailingCommentsAlignmentStyle(
771 {FormatStyle::TCAS_Always, 0}));
772 IO.enumCase(
Value,
"false",
773 FormatStyle::TrailingCommentsAlignmentStyle(
774 {FormatStyle::TCAS_Never, 0}));
778 FormatStyle::TrailingCommentsAlignmentStyle &
Value) {
779 IO.mapOptional(
"Kind",
Value.Kind);
780 IO.mapOptional(
"OverEmptyLines",
Value.OverEmptyLines);
784template <>
struct ScalarEnumerationTraits<
FormatStyle::UseTabStyle> {
786 IO.enumCase(
Value,
"Never", FormatStyle::UT_Never);
787 IO.enumCase(
Value,
"false", FormatStyle::UT_Never);
788 IO.enumCase(
Value,
"Always", FormatStyle::UT_Always);
789 IO.enumCase(
Value,
"true", FormatStyle::UT_Always);
790 IO.enumCase(
Value,
"ForIndentation", FormatStyle::UT_ForIndentation);
791 IO.enumCase(
Value,
"ForContinuationAndIndentation",
792 FormatStyle::UT_ForContinuationAndIndentation);
793 IO.enumCase(
Value,
"AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);
800 IO.mapOptional(
"Language", Style.
Language);
802 StringRef BasedOnStyle;
803 if (IO.outputting()) {
804 StringRef Styles[] = {
"LLVM",
"Google",
"Chromium",
"Mozilla",
805 "WebKit",
"GNU",
"Microsoft",
"clang-format"};
806 for (StringRef StyleName : Styles) {
808 if (getPredefinedStyle(StyleName, Style.
Language, &PredefinedStyle) &&
809 Style == PredefinedStyle) {
810 BasedOnStyle = StyleName;
815 IO.mapOptional(
"BasedOnStyle", BasedOnStyle);
816 if (!BasedOnStyle.empty()) {
817 FormatStyle::LanguageKind OldLanguage = Style.
Language;
818 FormatStyle::LanguageKind Language =
820 if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
821 IO.setError(Twine(
"Unknown value for BasedOnStyle: ", BasedOnStyle));
839 const bool IsGoogleOrChromium = BasedOnStyle.equals_insensitive(
"google") ||
840 BasedOnStyle.equals_insensitive(
"chromium");
841 bool OnCurrentLine = IsGoogleOrChromium;
842 bool OnNextLine =
true;
844 bool BreakBeforeInheritanceComma =
false;
845 bool BreakConstructorInitializersBeforeComma =
false;
847 bool DeriveLineEnding =
true;
848 bool UseCRLF =
false;
850 bool SpaceInEmptyParentheses =
false;
851 bool SpacesInConditionalStatement =
false;
852 bool SpacesInCStyleCastParentheses =
false;
853 bool SpacesInParentheses =
false;
856 if (!IO.outputting()) {
858 IO.mapOptional(
"AllowAllConstructorInitializersOnNextLine", OnNextLine);
860 IO.mapOptional(
"AlwaysBreakTemplateDeclarations",
862 IO.mapOptional(
"BreakBeforeInheritanceComma",
863 BreakBeforeInheritanceComma);
864 IO.mapOptional(
"BreakConstructorInitializersBeforeComma",
865 BreakConstructorInitializersBeforeComma);
866 IO.mapOptional(
"ConstructorInitializerAllOnOneLineOrOnePerLine",
868 IO.mapOptional(
"DeriveLineEnding", DeriveLineEnding);
870 IO.mapOptional(
"IndentFunctionDeclarationAfterType",
874 IO.mapOptional(
"SpaceAfterControlStatementKeyword",
876 IO.mapOptional(
"SpaceInEmptyParentheses", SpaceInEmptyParentheses);
877 IO.mapOptional(
"SpacesInConditionalStatement",
878 SpacesInConditionalStatement);
879 IO.mapOptional(
"SpacesInCStyleCastParentheses",
880 SpacesInCStyleCastParentheses);
881 IO.mapOptional(
"SpacesInParentheses", SpacesInParentheses);
882 IO.mapOptional(
"UseCRLF", UseCRLF);
888 IO.mapOptional(
"AlignConsecutiveAssignments",
890 IO.mapOptional(
"AlignConsecutiveBitFields",
892 IO.mapOptional(
"AlignConsecutiveDeclarations",
895 IO.mapOptional(
"AlignConsecutiveShortCaseStatements",
897 IO.mapOptional(
"AlignConsecutiveTableGenBreakingDAGArgColons",
899 IO.mapOptional(
"AlignConsecutiveTableGenCondOperatorColons",
901 IO.mapOptional(
"AlignConsecutiveTableGenDefinitionColons",
906 IO.mapOptional(
"AllowAllArgumentsOnNextLine",
908 IO.mapOptional(
"AllowAllParametersOfDeclarationOnNextLine",
910 IO.mapOptional(
"AllowBreakBeforeNoexceptSpecifier",
912 IO.mapOptional(
"AllowShortBlocksOnASingleLine",
914 IO.mapOptional(
"AllowShortCaseLabelsOnASingleLine",
916 IO.mapOptional(
"AllowShortCompoundRequirementOnASingleLine",
918 IO.mapOptional(
"AllowShortEnumsOnASingleLine",
920 IO.mapOptional(
"AllowShortFunctionsOnASingleLine",
922 IO.mapOptional(
"AllowShortIfStatementsOnASingleLine",
924 IO.mapOptional(
"AllowShortLambdasOnASingleLine",
926 IO.mapOptional(
"AllowShortLoopsOnASingleLine",
928 IO.mapOptional(
"AlwaysBreakAfterDefinitionReturnType",
930 IO.mapOptional(
"AlwaysBreakBeforeMultilineStrings",
936 IO.mapOptional(
"BracedInitializerIndentWidth",
939 IO.mapOptional(
"BreakAdjacentStringLiterals",
942 IO.mapOptional(
"BreakAfterJavaFieldAnnotations",
946 IO.mapOptional(
"BreakBeforeBinaryOperators",
948 IO.mapOptional(
"BreakBeforeConceptDeclarations",
951 IO.mapOptional(
"BreakBeforeInlineASMColon",
953 IO.mapOptional(
"BreakBeforeTernaryOperators",
955 IO.mapOptional(
"BreakConstructorInitializers",
957 IO.mapOptional(
"BreakFunctionDefinitionParameters",
961 IO.mapOptional(
"BreakTemplateDeclarations",
966 IO.mapOptional(
"ConstructorInitializerIndentWidth",
972 IO.mapOptional(
"EmptyLineAfterAccessModifier",
974 IO.mapOptional(
"EmptyLineBeforeAccessModifier",
976 IO.mapOptional(
"ExperimentalAutoDetectBinPacking",
980 IO.mapOptional(
"IfMacros", Style.
IfMacros);
984 IO.mapOptional(
"IncludeIsMainSourceRegex",
994 IO.mapOptional(
"IndentWrappedFunctionNames",
1003 IO.mapOptional(
"KeepEmptyLinesAtTheStartOfBlocks",
1007 IO.mapOptional(
"LineEnding", Style.
LineEnding);
1010 IO.mapOptional(
"Macros", Style.
Macros);
1017 IO.mapOptional(
"ObjCBreakBeforeNestedBlockParam",
1019 IO.mapOptional(
"ObjCPropertyAttributeOrder",
1022 IO.mapOptional(
"ObjCSpaceBeforeProtocolList",
1024 IO.mapOptional(
"PackConstructorInitializers",
1027 IO.mapOptional(
"PenaltyBreakBeforeFirstCallParameter",
1030 IO.mapOptional(
"PenaltyBreakFirstLessLess",
1032 IO.mapOptional(
"PenaltyBreakOpenParenthesis",
1034 IO.mapOptional(
"PenaltyBreakScopeResolution",
1037 IO.mapOptional(
"PenaltyBreakTemplateDeclaration",
1040 IO.mapOptional(
"PenaltyIndentedWhitespace",
1042 IO.mapOptional(
"PenaltyReturnTypeOnItsOwnLine",
1061 IO.mapOptional(
"RequiresExpressionIndentation",
1071 IO.mapOptional(
"SpaceAfterTemplateKeyword",
1073 IO.mapOptional(
"SpaceAroundPointerQualifiers",
1075 IO.mapOptional(
"SpaceBeforeAssignmentOperators",
1078 IO.mapOptional(
"SpaceBeforeCpp11BracedList",
1080 IO.mapOptional(
"SpaceBeforeCtorInitializerColon",
1082 IO.mapOptional(
"SpaceBeforeInheritanceColon",
1087 IO.mapOptional(
"SpaceBeforeRangeBasedForLoopColon",
1089 IO.mapOptional(
"SpaceBeforeSquareBrackets",
1092 IO.mapOptional(
"SpacesBeforeTrailingComments",
1095 IO.mapOptional(
"SpacesInContainerLiterals",
1097 IO.mapOptional(
"SpacesInLineCommentPrefix",
1102 IO.mapOptional(
"Standard", Style.
Standard);
1103 IO.mapOptional(
"StatementAttributeLikeMacros",
1106 IO.mapOptional(
"TableGenBreakingDAGArgOperators",
1108 IO.mapOptional(
"TableGenBreakInsideDAGArg",
1110 IO.mapOptional(
"TabWidth", Style.
TabWidth);
1111 IO.mapOptional(
"TypeNames", Style.
TypeNames);
1113 IO.mapOptional(
"UseTab", Style.
UseTab);
1114 IO.mapOptional(
"VerilogBreakBetweenInstancePorts",
1116 IO.mapOptional(
"WhitespaceSensitiveMacros",
1125 FormatStyle::DRTBS_All) {
1128 FormatStyle::DRTBS_TopLevel) {
1135 if (BreakBeforeInheritanceComma &&
1143 if (BreakConstructorInitializersBeforeComma &&
1148 if (!IsGoogleOrChromium) {
1152 ? FormatStyle::PCIS_NextLine
1153 : FormatStyle::PCIS_CurrentLine;
1156 FormatStyle::PCIS_NextLine) {
1159 else if (!OnNextLine)
1163 if (Style.
LineEnding == FormatStyle::LE_DeriveLF) {
1164 if (!DeriveLineEnding)
1165 Style.
LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF;
1167 Style.
LineEnding = FormatStyle::LE_DeriveCRLF;
1171 (SpacesInParentheses || SpaceInEmptyParentheses ||
1172 SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) {
1173 if (SpacesInParentheses) {
1178 SpacesInCStyleCastParentheses;
1180 SpaceInEmptyParentheses;
1185 SpacesInConditionalStatement;
1187 SpacesInCStyleCastParentheses;
1189 SpaceInEmptyParentheses;
1201template <>
struct DocumentListTraits<
std::vector<FormatStyle>> {
1202 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
1207 if (Index >= Seq.size()) {
1208 assert(Index == Seq.size());
1210 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
1213 Template = *((
const FormatStyle *)IO.getContext());
1214 Template.
Language = FormatStyle::LK_None;
1216 Seq.resize(Index + 1, Template);
1236 return llvm::make_error<llvm::StringError>(Message,
1237 llvm::inconvertibleErrorCode());
1241 return "clang-format.parse_error";
1249 return "Invalid argument";
1251 return "Unsuitable";
1253 return "trailing comma insertion cannot be used with bin packing";
1255 return "Invalid qualifier specified in QualifierOrder";
1257 return "Duplicate qualifier specified in QualifierOrder";
1259 return "Missing type in QualifierOrder";
1261 return "Missing QualifierOrder";
1263 llvm_unreachable(
"unexpected parse error");
1488 LLVMStyle.
IfMacros.push_back(
"KJ_IF_MAYBE");
1491 {
"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0,
false},
1492 {
"^(<|\"(gtest|gmock|isl|json)/)", 3, 0,
false},
1493 {
".*", 1, 0,
false}};
1634 {
"^<.*\\.h>", 1, 0,
false},
1635 {
"^<.*", 2, 0,
false},
1636 {
".*", 3, 0,
false}};
1676 "PARSE_PARTIAL_TEXT_PROTO",
1680 "ParseTextProtoOrDie",
1682 "ParsePartialTestProto",
1794 "com.google.android.apps.chrome",
1813 return ChromiumStyle;
1839 return MozillaStyle;
1933 if (Name.equals_insensitive(
"llvm"))
1935 else if (Name.equals_insensitive(
"chromium"))
1937 else if (Name.equals_insensitive(
"mozilla"))
1939 else if (Name.equals_insensitive(
"google"))
1941 else if (Name.equals_insensitive(
"webkit"))
1943 else if (Name.equals_insensitive(
"gnu"))
1945 else if (Name.equals_insensitive(
"microsoft"))
1947 else if (Name.equals_insensitive(
"clang-format"))
1949 else if (Name.equals_insensitive(
"none"))
1951 else if (Name.equals_insensitive(
"inheritparentconfig"))
1967 if (Qualifier ==
"type")
1971 if (token == tok::identifier)
1976 std::set<std::string> UniqueQualifiers(Style->
QualifierOrder.begin(),
1979 LLVM_DEBUG(llvm::dbgs()
1981 <<
" vs " << UniqueQualifiers.size() <<
"\n");
1994 llvm::SourceMgr::DiagHandlerTy DiagHandler,
1995 void *DiagHandlerCtxt) {
1999 if (Config.getBuffer().trim().empty())
2001 Style->StyleSet.
Clear();
2002 std::vector<FormatStyle> Styles;
2003 llvm::yaml::Input Input(Config,
nullptr, DiagHandler,
2009 Input.setContext(Style);
2010 Input.setAllowUnknownKeys(AllowUnknownOptions);
2013 return Input.error();
2015 for (
unsigned i = 0; i < Styles.size(); ++i) {
2020 for (
unsigned j = 0; j < i; ++j) {
2022 LLVM_DEBUG(llvm::dbgs()
2023 <<
"Duplicate languages in the config file on positions "
2024 << j <<
" and " << i <<
"\n");
2033 bool LanguageFound =
false;
2034 for (
const FormatStyle &Style : llvm::reverse(Styles)) {
2036 StyleSet.
Add(Style);
2038 LanguageFound =
true;
2040 if (!LanguageFound) {
2045 StyleSet.
Add(std::move(DefaultStyle));
2060 llvm::raw_string_ostream Stream(
Text);
2061 llvm::yaml::Output Output(Stream);
2068 Output << NonConstStyle;
2070 return Stream.str();
2073std::optional<FormatStyle>
2076 return std::nullopt;
2078 if (It == Styles->end())
2079 return std::nullopt;
2081 Style.StyleSet = *
this;
2087 "Cannot add a style for LK_None to a StyleSet");
2089 !Style.StyleSet.Styles &&
2090 "Cannot add a style associated with an existing StyleSet to a StyleSet");
2092 Styles = std::make_shared<MapType>();
2093 (*Styles)[Style.
Language] = std::move(Style);
2098std::optional<FormatStyle>
2110 std::pair<tooling::Replacements, unsigned>
2111 analyze(TokenAnnotator &Annotator,
2113 FormatTokenLexer &Tokens)
override {
2114 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2116 removeParens(AnnotatedLines, Result);
2121 void removeParens(SmallVectorImpl<AnnotatedLine *> &Lines,
2122 tooling::Replacements &Result) {
2123 const auto &SourceMgr =
Env.getSourceManager();
2124 for (
auto *Line : Lines) {
2125 removeParens(Line->Children, Result);
2126 if (!Line->Affected)
2128 for (
const auto *Token = Line->First; Token && !Token->Finalized;
2129 Token = Token->Next) {
2130 if (!Token->Optional || !Token->isOneOf(tok::l_paren, tok::r_paren))
2132 auto *Next = Token->Next;
2133 assert(Next && Next->isNot(tok::eof));
2134 SourceLocation Start;
2135 if (Next->NewlinesBefore == 0) {
2136 Start = Token->Tok.getLocation();
2137 Next->WhitespaceRange = Token->WhitespaceRange;
2139 Start = Token->WhitespaceRange.getBegin();
2142 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2143 cantFail(Result.add(tooling::Replacement(SourceMgr, Range,
" ")));
2149class BracesInserter :
public TokenAnalyzer {
2152 : TokenAnalyzer(
Env, Style) {}
2154 std::pair<tooling::Replacements, unsigned>
2155 analyze(TokenAnnotator &Annotator,
2156 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2157 FormatTokenLexer &Tokens)
override {
2158 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2159 tooling::Replacements Result;
2160 insertBraces(AnnotatedLines, Result);
2165 void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2166 tooling::Replacements &Result) {
2167 const auto &SourceMgr =
Env.getSourceManager();
2168 int OpeningBraceSurplus = 0;
2169 for (AnnotatedLine *Line : Lines) {
2170 insertBraces(Line->Children, Result);
2171 if (!Line->Affected && OpeningBraceSurplus == 0)
2173 for (FormatToken *Token = Line->First; Token && !Token->Finalized;
2174 Token = Token->Next) {
2175 int BraceCount = Token->BraceCount;
2176 if (BraceCount == 0)
2179 if (BraceCount < 0) {
2180 assert(BraceCount == -1);
2181 if (!Line->Affected)
2183 Brace = Token->is(tok::comment) ?
"\n{" :
"{";
2184 ++OpeningBraceSurplus;
2186 if (OpeningBraceSurplus == 0)
2188 if (OpeningBraceSurplus < BraceCount)
2189 BraceCount = OpeningBraceSurplus;
2190 Brace =
'\n' + std::string(BraceCount,
'}');
2191 OpeningBraceSurplus -= BraceCount;
2193 Token->BraceCount = 0;
2194 const auto Start = Token->Tok.getEndLoc();
2195 cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0,
Brace)));
2198 assert(OpeningBraceSurplus == 0);
2202class BracesRemover :
public TokenAnalyzer {
2205 : TokenAnalyzer(
Env, Style) {}
2207 std::pair<tooling::Replacements, unsigned>
2208 analyze(TokenAnnotator &Annotator,
2209 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2210 FormatTokenLexer &Tokens)
override {
2211 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2212 tooling::Replacements Result;
2213 removeBraces(AnnotatedLines, Result);
2218 void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2219 tooling::Replacements &Result) {
2220 const auto &SourceMgr =
Env.getSourceManager();
2221 const auto End = Lines.end();
2222 for (
auto I = Lines.begin(); I != End; ++I) {
2223 const auto Line = *I;
2224 removeBraces(Line->Children, Result);
2225 if (!Line->Affected)
2227 const auto NextLine = I + 1 == End ? nullptr : I[1];
2228 for (
auto Token = Line->First; Token && !Token->Finalized;
2229 Token = Token->Next) {
2230 if (!Token->Optional)
2232 if (!Token->isOneOf(tok::l_brace, tok::r_brace))
2234 auto Next = Token->Next;
2235 assert(Next || Token == Line->Last);
2236 if (!Next && NextLine)
2237 Next = NextLine->First;
2238 SourceLocation Start;
2239 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2240 Start = Token->Tok.getLocation();
2241 Next->WhitespaceRange = Token->WhitespaceRange;
2243 Start = Token->WhitespaceRange.getBegin();
2246 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2247 cantFail(Result.add(tooling::Replacement(SourceMgr, Range,
"")));
2253class SemiRemover :
public TokenAnalyzer {
2256 : TokenAnalyzer(
Env, Style) {}
2258 std::pair<tooling::Replacements, unsigned>
2259 analyze(TokenAnnotator &Annotator,
2260 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2261 FormatTokenLexer &Tokens)
override {
2262 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2263 tooling::Replacements Result;
2264 removeSemi(Annotator, AnnotatedLines, Result);
2269 void removeSemi(TokenAnnotator &Annotator,
2270 SmallVectorImpl<AnnotatedLine *> &Lines,
2271 tooling::Replacements &Result) {
2272 auto PrecededByFunctionRBrace = [](
const FormatToken &Tok) {
2273 const auto *Prev = Tok.Previous;
2274 if (!Prev || Prev->isNot(tok::r_brace))
2276 const auto *LBrace = Prev->MatchingParen;
2277 return LBrace && LBrace->is(TT_FunctionLBrace);
2279 const auto &SourceMgr =
Env.getSourceManager();
2280 const auto End = Lines.end();
2281 for (
auto I = Lines.begin(); I != End; ++I) {
2282 const auto Line = *I;
2283 removeSemi(Annotator, Line->Children, Result);
2284 if (!Line->Affected)
2286 Annotator.calculateFormattingInformation(*Line);
2287 const auto NextLine = I + 1 == End ? nullptr : I[1];
2288 for (
auto Token = Line->First; Token && !Token->Finalized;
2289 Token = Token->Next) {
2290 if (Token->isNot(tok::semi) ||
2291 (!Token->Optional && !PrecededByFunctionRBrace(*Token))) {
2294 auto Next = Token->Next;
2295 assert(Next || Token == Line->Last);
2296 if (!Next && NextLine)
2297 Next = NextLine->First;
2298 SourceLocation Start;
2299 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2300 Start = Token->Tok.getLocation();
2301 Next->WhitespaceRange = Token->WhitespaceRange;
2303 Start = Token->WhitespaceRange.getBegin();
2306 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2307 cantFail(Result.add(tooling::Replacement(SourceMgr, Range,
"")));
2313class JavaScriptRequoter :
public TokenAnalyzer {
2315 JavaScriptRequoter(
const Environment &
Env,
const FormatStyle &Style)
2316 : TokenAnalyzer(
Env, Style) {}
2318 std::pair<tooling::Replacements, unsigned>
2319 analyze(TokenAnnotator &Annotator,
2320 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2321 FormatTokenLexer &Tokens)
override {
2322 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2323 tooling::Replacements Result;
2324 requoteJSStringLiteral(AnnotatedLines, Result);
2331 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
2332 tooling::Replacements &Result) {
2333 for (AnnotatedLine *Line : Lines) {
2334 requoteJSStringLiteral(Line->Children, Result);
2335 if (!Line->Affected)
2337 for (FormatToken *FormatTok = Line->First; FormatTok;
2338 FormatTok = FormatTok->Next) {
2339 StringRef Input = FormatTok->TokenText;
2340 if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
2344 !Input.starts_with(
"\"")) ||
2346 !Input.starts_with(
"\'"))) {
2352 SourceLocation Start = FormatTok->Tok.getLocation();
2353 auto Replace = [&](SourceLocation Start,
unsigned Length,
2354 StringRef ReplacementText) {
2355 auto Err = Result.add(tooling::Replacement(
2356 Env.getSourceManager(), Start, Length, ReplacementText));
2360 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
2364 Replace(Start, 1, IsSingle ?
"'" :
"\"");
2365 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
2366 IsSingle ?
"'" :
"\"");
2369 bool Escaped =
false;
2370 for (
size_t i = 1; i < Input.size() - 1; i++) {
2373 if (!Escaped && i + 1 < Input.size() &&
2374 ((IsSingle && Input[i + 1] ==
'"') ||
2375 (!IsSingle && Input[i + 1] ==
'\''))) {
2378 Replace(Start.getLocWithOffset(i), 1,
"");
2385 if (!Escaped && IsSingle == (Input[i] ==
'\'')) {
2387 Replace(Start.getLocWithOffset(i), 0,
"\\");
2401class Formatter :
public TokenAnalyzer {
2404 FormattingAttemptStatus *Status)
2405 : TokenAnalyzer(
Env, Style), Status(Status) {}
2407 std::pair<tooling::Replacements, unsigned>
2408 analyze(TokenAnnotator &Annotator,
2409 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2410 FormatTokenLexer &Tokens)
override {
2411 tooling::Replacements Result;
2412 deriveLocalStyle(AnnotatedLines);
2413 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2414 for (AnnotatedLine *Line : AnnotatedLines)
2415 Annotator.calculateFormattingInformation(*Line);
2416 Annotator.setCommentLineLevels(AnnotatedLines);
2418 WhitespaceManager Whitespaces(
2419 Env.getSourceManager(), Style,
2421 ? WhitespaceManager::inputUsesCRLF(
2422 Env.getSourceManager().getBufferData(
Env.getFileID()),
2423 Style.
LineEnding == FormatStyle::LE_DeriveCRLF)
2425 ContinuationIndenter
Indenter(Style, Tokens.getKeywords(),
2426 Env.getSourceManager(), Whitespaces, Encoding,
2427 BinPackInconclusiveFunctions);
2429 UnwrappedLineFormatter(&
Indenter, &Whitespaces, Style,
2430 Tokens.getKeywords(),
Env.getSourceManager(),
2432 .format(AnnotatedLines,
false,
2435 Env.getFirstStartColumn(),
2436 Env.getNextStartColumn(),
2437 Env.getLastStartColumn());
2438 for (
const auto &R : Whitespaces.generateReplacements())
2440 return std::make_pair(Result, 0);
2441 return std::make_pair(Result, Penalty);
2446 hasCpp03IncompatibleFormat(
const SmallVectorImpl<AnnotatedLine *> &Lines) {
2447 for (
const AnnotatedLine *Line : Lines) {
2448 if (hasCpp03IncompatibleFormat(Line->Children))
2450 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {
2451 if (!Tok->hasWhitespaceBefore()) {
2452 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
2454 if (Tok->is(TT_TemplateCloser) &&
2455 Tok->Previous->is(TT_TemplateCloser)) {
2464 int countVariableAlignments(
const SmallVectorImpl<AnnotatedLine *> &Lines) {
2465 int AlignmentDiff = 0;
2466 for (
const AnnotatedLine *Line : Lines) {
2467 AlignmentDiff += countVariableAlignments(Line->Children);
2468 for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {
2469 if (Tok->isNot(TT_PointerOrReference))
2472 if (
const auto *Prev = Tok->getPreviousNonComment()) {
2473 if (Prev->is(tok::r_paren) && Prev->MatchingParen) {
2474 if (
const auto *Func =
2475 Prev->MatchingParen->getPreviousNonComment()) {
2476 if (
Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName,
2477 TT_OverloadedOperator)) {
2483 bool SpaceBefore = Tok->hasWhitespaceBefore();
2484 bool SpaceAfter = Tok->Next->hasWhitespaceBefore();
2485 if (SpaceBefore && !SpaceAfter)
2487 if (!SpaceBefore && SpaceAfter)
2491 return AlignmentDiff;
2495 deriveLocalStyle(
const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2496 bool HasBinPackedFunction =
false;
2497 bool HasOnePerLineFunction =
false;
2498 for (AnnotatedLine *Line : AnnotatedLines) {
2499 if (!Line->First->Next)
2501 FormatToken *Tok = Line->First->Next;
2503 if (Tok->is(PPK_BinPacked))
2504 HasBinPackedFunction =
true;
2505 if (Tok->is(PPK_OnePerLine))
2506 HasOnePerLineFunction =
true;
2512 const auto NetRightCount = countVariableAlignments(AnnotatedLines);
2513 if (NetRightCount > 0)
2515 else if (NetRightCount < 0)
2519 if (Style.
Standard == FormatStyle::LS_Auto) {
2520 Style.
Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
2521 ? FormatStyle::LS_Latest
2522 : FormatStyle::LS_Cpp03;
2524 BinPackInconclusiveFunctions =
2525 HasBinPackedFunction || !HasOnePerLineFunction;
2528 bool BinPackInconclusiveFunctions;
2529 FormattingAttemptStatus *Status;
2543class TrailingCommaInserter :
public TokenAnalyzer {
2545 TrailingCommaInserter(
const Environment &
Env,
const FormatStyle &Style)
2546 : TokenAnalyzer(
Env, Style) {}
2548 std::pair<tooling::Replacements, unsigned>
2549 analyze(TokenAnnotator &Annotator,
2550 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2551 FormatTokenLexer &Tokens)
override {
2552 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2553 tooling::Replacements Result;
2554 insertTrailingCommas(AnnotatedLines, Result);
2561 void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,
2562 tooling::Replacements &Result) {
2563 for (AnnotatedLine *Line : Lines) {
2564 insertTrailingCommas(Line->Children, Result);
2565 if (!Line->Affected)
2567 for (FormatToken *FormatTok = Line->First; FormatTok;
2568 FormatTok = FormatTok->Next) {
2569 if (FormatTok->NewlinesBefore == 0)
2571 FormatToken *Matching = FormatTok->MatchingParen;
2572 if (!Matching || !FormatTok->getPreviousNonComment())
2574 if (!(FormatTok->is(tok::r_square) &&
2575 Matching->is(TT_ArrayInitializerLSquare)) &&
2576 !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) {
2579 FormatToken *Prev = FormatTok->getPreviousNonComment();
2580 if (Prev->is(tok::comma) || Prev->is(tok::semi))
2584 SourceLocation Start =
2585 Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size());
2589 unsigned ColumnNumber =
2590 Env.getSourceManager().getSpellingColumnNumber(Start);
2595 cantFail(Result.add(
2596 tooling::Replacement(
Env.getSourceManager(), Start, 0,
",")));
2604class Cleaner :
public TokenAnalyzer {
2607 : TokenAnalyzer(
Env, Style),
2608 DeletedTokens(FormatTokenLess(
Env.getSourceManager())) {}
2611 std::pair<tooling::Replacements, unsigned>
2612 analyze(TokenAnnotator &Annotator,
2613 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2614 FormatTokenLexer &Tokens)
override {
2622 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2624 checkEmptyNamespace(AnnotatedLines);
2626 for (
auto *Line : AnnotatedLines)
2629 return {generateFixes(), 0};
2633 void cleanupLine(AnnotatedLine *Line) {
2634 for (
auto *Child : Line->Children)
2637 if (Line->Affected) {
2638 cleanupRight(Line->First, tok::comma, tok::comma);
2639 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
2640 cleanupRight(Line->First, tok::l_paren, tok::comma);
2641 cleanupLeft(Line->First, tok::comma, tok::r_paren);
2642 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
2643 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
2644 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
2648 bool containsOnlyComments(
const AnnotatedLine &Line) {
2649 for (FormatToken *Tok = Line.First; Tok; Tok = Tok->Next)
2650 if (Tok->isNot(tok::comment))
2656 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2657 std::set<unsigned> DeletedLines;
2658 for (
unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
2659 auto &Line = *AnnotatedLines[i];
2660 if (Line.startsWithNamespace())
2661 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
2664 for (
auto Line : DeletedLines) {
2665 FormatToken *Tok = AnnotatedLines[Line]->First;
2677 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2678 unsigned CurrentLine,
unsigned &
NewLine,
2679 std::set<unsigned> &DeletedLines) {
2680 unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
2685 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
2689 }
else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
2692 while (++CurrentLine < End) {
2693 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
2696 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
2697 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine,
NewLine,
2705 if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
2715 if (CurrentLine >= End)
2719 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
2720 AnnotatedLines[InitLine]->First->Tok.getLocation(),
2721 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) {
2725 for (
unsigned i = InitLine; i <= CurrentLine; ++i)
2726 DeletedLines.insert(i);
2735 template <
typename LeftKind,
typename RightKind>
2736 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
2738 auto NextNotDeleted = [
this](
const FormatToken &Tok) -> FormatToken * {
2739 for (
auto *Res = Tok.Next; Res; Res = Res->Next) {
2740 if (Res->isNot(tok::comment) &&
2741 DeletedTokens.find(Res) == DeletedTokens.end()) {
2747 for (
auto *Left = Start; Left;) {
2748 auto *Right = NextNotDeleted(*Left);
2751 if (Left->is(LK) && Right->is(RK)) {
2752 deleteToken(DeleteLeft ? Left : Right);
2753 for (
auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
2764 template <
typename LeftKind,
typename RightKind>
2765 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
2766 cleanupPair(Start, LK, RK,
true);
2769 template <
typename LeftKind,
typename RightKind>
2770 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
2771 cleanupPair(Start, LK, RK,
false);
2775 inline void deleteToken(FormatToken *Tok) {
2777 DeletedTokens.insert(Tok);
2780 tooling::Replacements generateFixes() {
2781 tooling::Replacements Fixes;
2782 SmallVector<FormatToken *> Tokens;
2783 std::copy(DeletedTokens.begin(), DeletedTokens.end(),
2784 std::back_inserter(Tokens));
2790 while (Idx < Tokens.size()) {
2791 unsigned St = Idx, End = Idx;
2792 while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1])
2794 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
2795 Tokens[End]->Tok.getEndLoc());
2797 Fixes.add(tooling::Replacement(
Env.getSourceManager(), SR,
""));
2801 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
2802 assert(
false &&
"Fixes must not conflict!");
2813 struct FormatTokenLess {
2814 FormatTokenLess(
const SourceManager &
SM) :
SM(
SM) {}
2816 bool operator()(
const FormatToken *LHS,
const FormatToken *RHS)
const {
2817 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
2818 RHS->Tok.getLocation());
2824 std::set<FormatToken *, FormatTokenLess> DeletedTokens;
2827class ObjCHeaderStyleGuesser :
public TokenAnalyzer {
2829 ObjCHeaderStyleGuesser(
const Environment &
Env,
const FormatStyle &Style)
2830 : TokenAnalyzer(
Env, Style), IsObjC(
false) {}
2832 std::pair<tooling::Replacements, unsigned>
2833 analyze(TokenAnnotator &Annotator,
2834 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2835 FormatTokenLexer &Tokens)
override {
2836 assert(Style.
Language == FormatStyle::LK_Cpp);
2837 IsObjC = guessIsObjC(
Env.getSourceManager(), AnnotatedLines,
2838 Tokens.getKeywords());
2839 tooling::Replacements Result;
2843 bool isObjC() {
return IsObjC; }
2847 guessIsObjC(
const SourceManager &SourceManager,
2848 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2849 const AdditionalKeywords &Keywords) {
2851 static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
2866 "FOUNDATION_EXPORT",
2867 "FOUNDATION_EXTERN",
2868 "NSAffineTransform",
2870 "NSAttributedString",
2889 "NSInvocationOperation",
2893 "NSMutableAttributedString",
2894 "NSMutableCharacterSet",
2896 "NSMutableDictionary",
2897 "NSMutableIndexSet",
2898 "NSMutableOrderedSet",
2902 "NSNumberFormatter",
2906 "NSOperationQueuePriority",
2910 "NSQualityOfService",
2913 "NSRegularExpression",
2924 "NS_ASSUME_NONNULL_BEGIN",
2929 for (
auto *Line : AnnotatedLines) {
2930 if (Line->First && (Line->First->TokenText.starts_with(
"#") ||
2931 Line->First->TokenText ==
"__pragma" ||
2932 Line->First->TokenText ==
"_Pragma")) {
2935 for (
const FormatToken *FormatTok = Line->First; FormatTok;
2936 FormatTok = FormatTok->Next) {
2937 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
2938 (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
2939 FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
2941 (FormatTok->Tok.isAnyIdentifier() &&
2942 std::binary_search(std::begin(FoundationIdentifiers),
2943 std::end(FoundationIdentifiers),
2944 FormatTok->TokenText)) ||
2945 FormatTok->is(TT_ObjCStringLiteral) ||
2946 FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,
2947 Keywords.kw_NS_ERROR_ENUM,
2948 Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,
2949 TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,
2950 TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,
2952 LLVM_DEBUG(llvm::dbgs()
2953 <<
"Detected ObjC at location "
2954 << FormatTok->Tok.getLocation().printToString(
2956 <<
" token: " << FormatTok->TokenText <<
" token type: "
2961 if (guessIsObjC(SourceManager, Line->Children, Keywords))
2978struct JavaImportDirective {
2991 for (
const auto &Range : Ranges) {
2992 if (Range.getOffset() < End &&
2993 Range.getOffset() + Range.getLength() > Start) {
3007static std::pair<unsigned, unsigned>
3011 unsigned OffsetToEOL = 0;
3012 for (
int i = 0, e = Includes.size(); i != e; ++i) {
3013 unsigned Start = Includes[Indices[i]].Offset;
3014 unsigned End = Start + Includes[Indices[i]].Text.size();
3015 if (!(Cursor >= Start && Cursor < End))
3017 CursorIndex = Indices[i];
3018 OffsetToEOL = End - Cursor;
3021 while (--i >= 0 && Includes[CursorIndex].
Text == Includes[Indices[i]].
Text)
3025 return std::make_pair(CursorIndex, OffsetToEOL);
3030 std::string NewCode;
3031 size_t Pos = 0, LastPos = 0;
3034 Pos = Code.find(
"\r\n", LastPos);
3035 if (Pos == LastPos) {
3039 if (Pos == std::string::npos) {
3040 NewCode += Code.substr(LastPos);
3043 NewCode += Code.substr(LastPos, Pos - LastPos) +
"\n";
3045 }
while (Pos != std::string::npos);
3063 const unsigned IncludesBeginOffset = Includes.front().Offset;
3064 const unsigned IncludesEndOffset =
3065 Includes.back().Offset + Includes.back().Text.size();
3066 const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
3067 if (!
affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
3070 llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size()));
3073 llvm::stable_sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
3074 const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
3075 const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
3076 return std::tie(Includes[LHSI].
Priority, LHSFilenameLower,
3078 std::tie(Includes[RHSI].
Priority, RHSFilenameLower,
3082 llvm::stable_sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
3090 unsigned CursorIndex;
3092 unsigned CursorToEOLOffset;
3094 std::tie(CursorIndex, CursorToEOLOffset) =
3099 Indices.erase(std::unique(Indices.begin(), Indices.end(),
3100 [&](
unsigned LHSI,
unsigned RHSI) {
3101 return Includes[LHSI].Text.trim() ==
3102 Includes[RHSI].Text.trim();
3106 int CurrentCategory = Includes.front().Category;
3114 if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) &&
3119 const auto OldCursor = Cursor ? *Cursor : 0;
3121 for (
unsigned Index : Indices) {
3122 if (!result.empty()) {
3126 CurrentCategory != Includes[Index].Category) {
3130 result += Includes[Index].Text;
3131 if (Cursor && CursorIndex == Index)
3132 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
3133 CurrentCategory = Includes[Index].Category;
3136 if (Cursor && *Cursor >= IncludesEndOffset)
3137 *Cursor += result.size() - IncludesBlockSize;
3142 IncludesBeginOffset, IncludesBlockSize)))) {
3144 *Cursor = OldCursor;
3149 FileName, Includes.front().Offset, IncludesBlockSize, result));
3153 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
3163 unsigned Prev = llvm::StringSwitch<size_t>(Code)
3164 .StartsWith(
"\xEF\xBB\xBF", 3)
3166 unsigned SearchFrom = 0;
3178 bool FirstIncludeBlock =
true;
3179 bool MainIncludeFound =
false;
3180 bool FormattingOff =
false;
3183 llvm::Regex RawStringRegex(
3184 "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\(");
3186 std::string RawStringTermination =
")\"";
3189 auto Pos = Code.find(
'\n', SearchFrom);
3191 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3193 StringRef Trimmed =
Line.trim();
3198 if (RawStringRegex.match(Trimmed, &RawStringMatches)) {
3199 std::string CharSequence = RawStringMatches[1].str();
3200 RawStringTermination =
")" + CharSequence +
"\"";
3201 FormattingOff =
true;
3204 if (Trimmed.contains(RawStringTermination))
3205 FormattingOff =
false;
3208 FormattingOff =
true;
3210 FormattingOff =
false;
3212 const bool EmptyLineSkipped =
3218 bool MergeWithNextLine = Trimmed.ends_with(
"\\");
3219 if (!FormattingOff && !MergeWithNextLine) {
3221 StringRef IncludeName = Matches[2];
3222 if (
Line.contains(
"/*") && !
Line.contains(
"*/")) {
3227 Pos = Code.find(
"*/", SearchFrom);
3229 Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev);
3233 !MainIncludeFound && FirstIncludeBlock);
3235 IncludeName, !MainIncludeFound && FirstIncludeBlock);
3237 MainIncludeFound =
true;
3238 IncludesInBlock.push_back(
3240 }
else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
3243 IncludesInBlock.clear();
3244 if (Trimmed.starts_with(
"#pragma hdrstop"))
3245 FirstIncludeBlock =
true;
3247 FirstIncludeBlock =
false;
3250 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3253 if (!MergeWithNextLine)
3255 SearchFrom = Pos + 1;
3257 if (!IncludesInBlock.empty()) {
3267 StringRef ImportIdentifier) {
3268 unsigned LongestMatchIndex =
UINT_MAX;
3269 unsigned LongestMatchLength = 0;
3272 if (ImportIdentifier.starts_with(GroupPrefix) &&
3273 GroupPrefix.length() > LongestMatchLength) {
3274 LongestMatchIndex = I;
3275 LongestMatchLength = GroupPrefix.length();
3278 return LongestMatchIndex;
3290 unsigned ImportsBeginOffset = Imports.front().Offset;
3291 unsigned ImportsEndOffset =
3292 Imports.back().Offset + Imports.back().Text.size();
3293 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;
3294 if (!
affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))
3298 llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size()));
3301 for (
const JavaImportDirective &Import : Imports)
3304 bool StaticImportAfterNormalImport =
3306 llvm::sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
3308 return std::make_tuple(!Imports[LHSI].
IsStatic ^
3309 StaticImportAfterNormalImport,
3311 std::make_tuple(!Imports[RHSI].
IsStatic ^
3312 StaticImportAfterNormalImport,
3317 Indices.erase(std::unique(Indices.begin(), Indices.end(),
3318 [&](
unsigned LHSI,
unsigned RHSI) {
3319 return Imports[LHSI].Text == Imports[RHSI].Text;
3323 bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
3327 for (
unsigned Index : Indices) {
3328 if (!result.empty()) {
3330 if (CurrentIsStatic != Imports[Index].
IsStatic ||
3336 result += CommentLine;
3339 result += Imports[Index].Text;
3340 CurrentIsStatic = Imports[Index].IsStatic;
3347 Imports.front().Offset, ImportsBlockSize)))) {
3352 ImportsBlockSize, result));
3356 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
3363const char JavaImportRegexPattern[] =
3364 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;";
3373 unsigned SearchFrom = 0;
3374 llvm::Regex ImportRegex(JavaImportRegexPattern);
3379 bool FormattingOff =
false;
3382 auto Pos = Code.find(
'\n', SearchFrom);
3384 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3386 StringRef Trimmed =
Line.trim();
3388 FormattingOff =
true;
3390 FormattingOff =
false;
3392 if (ImportRegex.match(
Line, &Matches)) {
3393 if (FormattingOff) {
3398 StringRef
Static = Matches[1];
3401 if (
Static.contains(
"static"))
3403 ImportsInBlock.push_back(
3406 }
else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) {
3411 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3413 SearchFrom = Pos + 1;
3415 if (!ImportsInBlock.empty())
3424 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
3427bool isLikelyXml(StringRef Code) {
return Code.ltrim().starts_with(
"<"); }
3431 StringRef
FileName,
unsigned *Cursor) {
3449template <
typename T>
3454 if (Replaces.
empty())
3457 auto NewCode = applyAllReplacements(Code, Replaces);
3459 return NewCode.takeError();
3464 ProcessFunc(Style, *NewCode, ChangedRanges,
FileName);
3466 return Replaces.
merge(FormatReplaces);
3475 std::vector<tooling::Range> Ranges,
3479 auto SortedReplaces =
3481 if (!SortedReplaces)
3482 return SortedReplaces.takeError();
3486 auto Reformat = [](
const FormatStyle &Style, StringRef Code,
3487 std::vector<tooling::Range> Ranges,
3502inline bool isHeaderDeletion(
const tooling::Replacement &Replace) {
3503 return Replace.getOffset() ==
UINT_MAX && Replace.getLength() == 1;
3507tooling::Replacements
3508fixCppIncludeInsertions(StringRef Code,
const tooling::Replacements &Replaces,
3513 tooling::Replacements HeaderInsertions;
3514 std::set<llvm::StringRef> HeadersToDelete;
3515 tooling::Replacements
Result;
3516 for (
const auto &R : Replaces) {
3517 if (isHeaderInsertion(R)) {
3520 llvm::consumeError(HeaderInsertions.add(R));
3521 }
else if (isHeaderDeletion(R)) {
3522 HeadersToDelete.insert(R.getReplacementText());
3523 }
else if (R.getOffset() ==
UINT_MAX) {
3524 llvm::errs() <<
"Insertions other than header #include insertion are "
3526 << R.getReplacementText() <<
"\n";
3528 llvm::consumeError(
Result.add(R));
3531 if (HeaderInsertions.empty() && HeadersToDelete.empty())
3534 StringRef
FileName = Replaces.begin()->getFilePath();
3537 for (
const auto &Header : HeadersToDelete) {
3538 tooling::Replacements Replaces =
3539 Includes.remove(Header.trim(
"\"<>"), Header.starts_with(
"<"));
3540 for (
const auto &R : Replaces) {
3541 auto Err =
Result.add(R);
3544 llvm::errs() <<
"Failed to add header deletion replacement for "
3545 << Header <<
": " << llvm::toString(std::move(Err))
3552 for (
const auto &R : HeaderInsertions) {
3556 assert(Matched &&
"Header insertion replacement must have replacement text "
3559 auto IncludeName = Matches[2];
3561 Includes.insert(IncludeName.trim(
"\"<>"), IncludeName.starts_with(
"<"),
3564 auto Err =
Result.add(*Replace);
3566 llvm::consumeError(std::move(Err));
3567 unsigned NewOffset =
3568 Result.getShiftedCodePosition(Replace->getOffset());
3569 auto Shifted = tooling::Replacement(
FileName, NewOffset, 0,
3570 Replace->getReplacementText());
3585 auto Cleanup = [](
const FormatStyle &Style, StringRef Code,
3592 fixCppIncludeInsertions(Code, Replaces, Style);
3597std::pair<tooling::Replacements, unsigned>
3600 unsigned NextStartColumn,
unsigned LastStartColumn, StringRef FileName,
3611 case FormatStyle::RCPS_SingleLine:
3612 case FormatStyle::RCPS_WithPreceding:
3628 std::vector<tooling::Range> Ranges(1,
tooling::Range(0, Code.size()));
3629 auto Env = Environment::make(Code,
FileName, Ranges, FirstStartColumn,
3630 NextStartColumn, LastStartColumn);
3635 Formatter(*
Env, Style, Status).process().first;
3637 Replaces = Replaces.
merge(
3640 if (applyAllReplacements(Code, Replaces))
3641 return {Replaces, 0};
3645 auto Env = Environment::make(Code,
FileName, Ranges, FirstStartColumn,
3646 NextStartColumn, LastStartColumn);
3650 typedef std::function<std::pair<tooling::Replacements, unsigned>(
3660 if (Style.
isCpp()) {
3667 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3668 return ParensRemover(
Env, S).process(
true);
3674 S.InsertBraces =
true;
3675 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3676 return BracesInserter(
Env, S).process(
true);
3682 S.RemoveBracesLLVM =
true;
3683 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3684 return BracesRemover(
Env, S).process(
true);
3690 S.RemoveSemicolon =
true;
3691 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3692 return SemiRemover(
Env, S).process();
3715 if (Style.
Language == FormatStyle::LK_ObjC &&
3725 return JavaScriptRequoter(
Env, Expanded).process(
true);
3730 return Formatter(
Env, Expanded, Status).process();
3736 return TrailingCommaInserter(
Env, Expanded).process();
3740 std::optional<std::string> CurrentCode;
3742 unsigned Penalty = 0;
3743 for (
size_t I = 0, E = Passes.size(); I < E; ++I) {
3744 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
3745 auto NewCode = applyAllReplacements(
3746 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
3748 Fixes = Fixes.
merge(PassFixes.first);
3749 Penalty += PassFixes.second;
3751 CurrentCode = std::move(*NewCode);
3752 Env = Environment::make(
3754 tooling::calculateRangesAfterReplacements(Fixes, Ranges),
3755 FirstStartColumn, NextStartColumn, LastStartColumn);
3768 StringRef OriginalCode = Code.substr(Fix.getOffset(), Fix.getLength());
3769 if (!OriginalCode.equals(Fix.getReplacementText())) {
3770 auto Err = NonNoOpFixes.
add(Fix);
3772 llvm::errs() <<
"Error adding replacements : "
3773 << llvm::toString(std::move(Err)) <<
"\n";
3777 Fixes = std::move(NonNoOpFixes);
3780 return {Fixes, Penalty};
3804 return Cleaner(*
Env, Style).process().first;
3809 StringRef
FileName,
bool *IncompleteFormat) {
3812 if (!Status.FormatComplete)
3813 *IncompleteFormat =
true;
3845 LangOpts.CPlusPlus = 1;
3856 LangOpts.LineComment = 1;
3857 bool AlternativeOperators = Style.
isCpp();
3858 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
3861 LangOpts.MicrosoftExt = 1;
3862 LangOpts.DeclSpecKeyword = 1;
3868 "Set coding style. <string> can be:\n"
3869 "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"
3870 " Mozilla, WebKit.\n"
3871 "2. 'file' to load style configuration from a\n"
3872 " .clang-format file in one of the parent directories\n"
3873 " of the source file (for stdin, see --assume-filename).\n"
3874 " If no .clang-format file is found, falls back to\n"
3875 " --fallback-style.\n"
3876 " --style=file is the default.\n"
3877 "3. 'file:<format_file_path>' to explicitly specify\n"
3878 " the configuration file.\n"
3879 "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n"
3880 " --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
3885 if (
FileName.ends_with_insensitive(
".js") ||
3886 FileName.ends_with_insensitive(
".mjs") ||
3887 FileName.ends_with_insensitive(
".ts")) {
3892 if (
FileName.ends_with_insensitive(
".proto") ||
3893 FileName.ends_with_insensitive(
".protodevel")) {
3899 if (
FileName.ends_with_insensitive(
".txtpb") ||
3900 FileName.ends_with_insensitive(
".textpb") ||
3901 FileName.ends_with_insensitive(
".pb.txt") ||
3902 FileName.ends_with_insensitive(
".textproto") ||
3903 FileName.ends_with_insensitive(
".asciipb")) {
3906 if (
FileName.ends_with_insensitive(
".td"))
3908 if (
FileName.ends_with_insensitive(
".cs"))
3910 if (
FileName.ends_with_insensitive(
".json"))
3912 if (
FileName.ends_with_insensitive(
".sv") ||
3913 FileName.ends_with_insensitive(
".svh") ||
3914 FileName.ends_with_insensitive(
".v") ||
3915 FileName.ends_with_insensitive(
".vh")) {
3924 auto Extension = llvm::sys::path::extension(
FileName);
3927 if (!Code.empty() && (Extension.empty() || Extension ==
".h")) {
3932 if (Guesser.isObjC())
3936 return GuessedLanguage;
3944llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
3947 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
3948 FS->getBufferForFile(ConfigFile.str());
3949 if (
auto EC =
Text.getError())
3957 StringRef FallbackStyleName,
3958 StringRef Code, llvm::vfs::FileSystem *FS,
3959 bool AllowUnknownOptions) {
3966 ChildFormatTextToApply;
3968 if (StyleName.starts_with(
"{")) {
3970 StringRef Source =
"<command-line>";
3971 if (std::error_code ec =
3973 AllowUnknownOptions)) {
3980 ChildFormatTextToApply.emplace_back(
3981 llvm::MemoryBuffer::getMemBuffer(StyleName, Source,
false));
3985 FS = llvm::vfs::getRealFileSystem().get();
3990 StyleName.starts_with_insensitive(
"file:")) {
3991 auto ConfigFile = StyleName.substr(5);
3992 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
3994 if (
auto EC =
Text.getError()) {
3999 LLVM_DEBUG(llvm::dbgs()
4000 <<
"Using configuration file " << ConfigFile <<
"\n");
4008 ChildFormatTextToApply.emplace_back(std::move(*
Text));
4022 if (std::error_code EC = FS->makeAbsolute(Path))
4028 auto dropDiagnosticHandler = [](
const llvm::SMDiagnostic &,
void *) {};
4030 auto applyChildFormatTexts = [&](
FormatStyle *Style) {
4031 for (
const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) {
4033 dropDiagnosticHandler);
4036 static_cast<void>(EC);
4042 FilesToLookFor.push_back(
".clang-format");
4043 FilesToLookFor.push_back(
"_clang-format");
4046 for (StringRef Directory = Path; !Directory.empty();
4047 Directory = llvm::sys::path::parent_path(Directory)) {
4048 auto Status = FS->status(Directory);
4050 Status->getType() != llvm::sys::fs::file_type::directory_file) {
4054 for (
const auto &F : FilesToLookFor) {
4057 llvm::sys::path::append(ConfigFile, F);
4058 LLVM_DEBUG(llvm::dbgs() <<
"Trying " << ConfigFile <<
"...\n");
4060 Status = FS->status(ConfigFile);
4062 Status->getType() != llvm::sys::fs::file_type::regular_file) {
4066 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
4068 if (
auto EC =
Text.getError()) {
4073 if (!UnsuitableConfigFiles.empty())
4074 UnsuitableConfigFiles.append(
", ");
4075 UnsuitableConfigFiles.append(ConfigFile);
4079 LLVM_DEBUG(llvm::dbgs()
4080 <<
"Using configuration file " << ConfigFile <<
"\n");
4083 if (!ChildFormatTextToApply.empty()) {
4084 LLVM_DEBUG(llvm::dbgs() <<
"Applying child configurations\n");
4085 applyChildFormatTexts(&Style);
4090 LLVM_DEBUG(llvm::dbgs() <<
"Inherits parent configuration\n");
4095 ChildFormatTextToApply.emplace_back(std::move(*
Text));
4105 if (!UnsuitableConfigFiles.empty()) {
4108 UnsuitableConfigFiles);
4111 if (!ChildFormatTextToApply.empty()) {
4112 LLVM_DEBUG(llvm::dbgs()
4113 <<
"Applying child configurations on fallback style\n");
4114 applyChildFormatTexts(&FallbackStyle);
4117 return FallbackStyle;
4121 if (Comment == (On ?
"/* clang-format on */" :
"/* clang-format off */"))
4124 static const char ClangFormatOn[] =
"// clang-format on";
4125 static const char ClangFormatOff[] =
"// clang-format off";
4126 const unsigned Size = (On ?
sizeof ClangFormatOn :
sizeof ClangFormatOff) - 1;
4128 return Comment.starts_with(On ? ClangFormatOn : ClangFormatOff) &&
4129 (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)