39#include "llvm/ADT/STLExtras.h"
40#include "llvm/ADT/Sequence.h"
41#include "llvm/ADT/StringRef.h"
42#include "llvm/Support/Allocator.h"
43#include "llvm/Support/Debug.h"
44#include "llvm/Support/Path.h"
45#include "llvm/Support/Regex.h"
46#include "llvm/Support/VirtualFileSystem.h"
47#include "llvm/Support/YAMLTraits.h"
53#include <unordered_map>
55#define DEBUG_TYPE "format-formatter"
64struct ScalarEnumerationTraits<
FormatStyle::BreakBeforeNoexceptSpecifierStyle> {
67 IO.enumCase(
Value,
"Never", FormatStyle::BBNSS_Never);
68 IO.enumCase(
Value,
"OnlyWithParen", FormatStyle::BBNSS_OnlyWithParen);
69 IO.enumCase(
Value,
"Always", FormatStyle::BBNSS_Always);
73template <>
struct MappingTraits<
FormatStyle::AlignConsecutiveStyle> {
75 IO.enumCase(
Value,
"None",
76 FormatStyle::AlignConsecutiveStyle(
80 IO.enumCase(
Value,
"Consecutive",
81 FormatStyle::AlignConsecutiveStyle(
85 IO.enumCase(
Value,
"AcrossEmptyLines",
86 FormatStyle::AlignConsecutiveStyle(
90 IO.enumCase(
Value,
"AcrossComments",
91 FormatStyle::AlignConsecutiveStyle({
true,
96 IO.enumCase(
Value,
"AcrossEmptyLinesAndComments",
97 FormatStyle::AlignConsecutiveStyle({
true,
104 IO.enumCase(
Value,
"true",
105 FormatStyle::AlignConsecutiveStyle(
109 IO.enumCase(
Value,
"false",
110 FormatStyle::AlignConsecutiveStyle(
116 static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &
Value) {
117 IO.mapOptional(
"Enabled",
Value.Enabled);
118 IO.mapOptional(
"AcrossEmptyLines",
Value.AcrossEmptyLines);
119 IO.mapOptional(
"AcrossComments",
Value.AcrossComments);
120 IO.mapOptional(
"AlignCompound",
Value.AlignCompound);
121 IO.mapOptional(
"PadOperators",
Value.PadOperators);
126struct MappingTraits<
FormatStyle::ShortCaseStatementsAlignmentStyle> {
128 FormatStyle::ShortCaseStatementsAlignmentStyle &
Value) {
129 IO.mapOptional(
"Enabled",
Value.Enabled);
130 IO.mapOptional(
"AcrossEmptyLines",
Value.AcrossEmptyLines);
131 IO.mapOptional(
"AcrossComments",
Value.AcrossComments);
132 IO.mapOptional(
"AlignCaseColons",
Value.AlignCaseColons);
137struct ScalarEnumerationTraits<
FormatStyle::AttributeBreakingStyle> {
139 IO.enumCase(
Value,
"Always", FormatStyle::ABS_Always);
140 IO.enumCase(
Value,
"Leave", FormatStyle::ABS_Leave);
141 IO.enumCase(
Value,
"Never", FormatStyle::ABS_Never);
146struct ScalarEnumerationTraits<
FormatStyle::ArrayInitializerAlignmentStyle> {
148 FormatStyle::ArrayInitializerAlignmentStyle &
Value) {
149 IO.enumCase(
Value,
"None", FormatStyle::AIAS_None);
150 IO.enumCase(
Value,
"Left", FormatStyle::AIAS_Left);
151 IO.enumCase(
Value,
"Right", FormatStyle::AIAS_Right);
155template <>
struct ScalarEnumerationTraits<
FormatStyle::BinaryOperatorStyle> {
157 IO.enumCase(
Value,
"All", FormatStyle::BOS_All);
158 IO.enumCase(
Value,
"true", FormatStyle::BOS_All);
159 IO.enumCase(
Value,
"None", FormatStyle::BOS_None);
160 IO.enumCase(
Value,
"false", FormatStyle::BOS_None);
161 IO.enumCase(
Value,
"NonAssignment", FormatStyle::BOS_NonAssignment);
165template <>
struct ScalarEnumerationTraits<
FormatStyle::BinPackStyle> {
167 IO.enumCase(
Value,
"Auto", FormatStyle::BPS_Auto);
168 IO.enumCase(
Value,
"Always", FormatStyle::BPS_Always);
169 IO.enumCase(
Value,
"Never", FormatStyle::BPS_Never);
174struct ScalarEnumerationTraits<
FormatStyle::BitFieldColonSpacingStyle> {
176 FormatStyle::BitFieldColonSpacingStyle &
Value) {
177 IO.enumCase(
Value,
"Both", FormatStyle::BFCS_Both);
178 IO.enumCase(
Value,
"None", FormatStyle::BFCS_None);
179 IO.enumCase(
Value,
"Before", FormatStyle::BFCS_Before);
180 IO.enumCase(
Value,
"After", FormatStyle::BFCS_After);
184template <>
struct ScalarEnumerationTraits<
FormatStyle::BraceBreakingStyle> {
186 IO.enumCase(
Value,
"Attach", FormatStyle::BS_Attach);
187 IO.enumCase(
Value,
"Linux", FormatStyle::BS_Linux);
188 IO.enumCase(
Value,
"Mozilla", FormatStyle::BS_Mozilla);
189 IO.enumCase(
Value,
"Stroustrup", FormatStyle::BS_Stroustrup);
190 IO.enumCase(
Value,
"Allman", FormatStyle::BS_Allman);
191 IO.enumCase(
Value,
"Whitesmiths", FormatStyle::BS_Whitesmiths);
192 IO.enumCase(
Value,
"GNU", FormatStyle::BS_GNU);
193 IO.enumCase(
Value,
"WebKit", FormatStyle::BS_WebKit);
194 IO.enumCase(
Value,
"Custom", FormatStyle::BS_Custom);
198template <>
struct MappingTraits<
FormatStyle::BraceWrappingFlags> {
199 static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
200 IO.mapOptional(
"AfterCaseLabel", Wrapping.AfterCaseLabel);
201 IO.mapOptional(
"AfterClass", Wrapping.AfterClass);
202 IO.mapOptional(
"AfterControlStatement", Wrapping.AfterControlStatement);
203 IO.mapOptional(
"AfterEnum", Wrapping.AfterEnum);
204 IO.mapOptional(
"AfterExternBlock", Wrapping.AfterExternBlock);
205 IO.mapOptional(
"AfterFunction", Wrapping.AfterFunction);
206 IO.mapOptional(
"AfterNamespace", Wrapping.AfterNamespace);
207 IO.mapOptional(
"AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
208 IO.mapOptional(
"AfterStruct", Wrapping.AfterStruct);
209 IO.mapOptional(
"AfterUnion", Wrapping.AfterUnion);
210 IO.mapOptional(
"BeforeCatch", Wrapping.BeforeCatch);
211 IO.mapOptional(
"BeforeElse", Wrapping.BeforeElse);
212 IO.mapOptional(
"BeforeLambdaBody", Wrapping.BeforeLambdaBody);
213 IO.mapOptional(
"BeforeWhile", Wrapping.BeforeWhile);
214 IO.mapOptional(
"IndentBraces", Wrapping.IndentBraces);
215 IO.mapOptional(
"SplitEmptyFunction", Wrapping.SplitEmptyFunction);
216 IO.mapOptional(
"SplitEmptyRecord", Wrapping.SplitEmptyRecord);
217 IO.mapOptional(
"SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
221template <>
struct ScalarEnumerationTraits<
FormatStyle::BracketAlignmentStyle> {
223 IO.enumCase(
Value,
"Align", FormatStyle::BAS_Align);
224 IO.enumCase(
Value,
"DontAlign", FormatStyle::BAS_DontAlign);
225 IO.enumCase(
Value,
"AlwaysBreak", FormatStyle::BAS_AlwaysBreak);
226 IO.enumCase(
Value,
"BlockIndent", FormatStyle::BAS_BlockIndent);
229 IO.enumCase(
Value,
"true", FormatStyle::BAS_Align);
230 IO.enumCase(
Value,
"false", FormatStyle::BAS_DontAlign);
235struct ScalarEnumerationTraits<
236 FormatStyle::BraceWrappingAfterControlStatementStyle> {
239 FormatStyle::BraceWrappingAfterControlStatementStyle &
Value) {
240 IO.enumCase(
Value,
"Never", FormatStyle::BWACS_Never);
241 IO.enumCase(
Value,
"MultiLine", FormatStyle::BWACS_MultiLine);
242 IO.enumCase(
Value,
"Always", FormatStyle::BWACS_Always);
245 IO.enumCase(
Value,
"false", FormatStyle::BWACS_Never);
246 IO.enumCase(
Value,
"true", FormatStyle::BWACS_Always);
251struct ScalarEnumerationTraits<
252 FormatStyle::BreakBeforeConceptDeclarationsStyle> {
255 IO.enumCase(
Value,
"Never", FormatStyle::BBCDS_Never);
256 IO.enumCase(
Value,
"Allowed", FormatStyle::BBCDS_Allowed);
257 IO.enumCase(
Value,
"Always", FormatStyle::BBCDS_Always);
260 IO.enumCase(
Value,
"true", FormatStyle::BBCDS_Always);
261 IO.enumCase(
Value,
"false", FormatStyle::BBCDS_Allowed);
266struct ScalarEnumerationTraits<
FormatStyle::BreakBeforeInlineASMColonStyle> {
268 FormatStyle::BreakBeforeInlineASMColonStyle &
Value) {
269 IO.enumCase(
Value,
"Never", FormatStyle::BBIAS_Never);
270 IO.enumCase(
Value,
"OnlyMultiline", FormatStyle::BBIAS_OnlyMultiline);
271 IO.enumCase(
Value,
"Always", FormatStyle::BBIAS_Always);
276struct ScalarEnumerationTraits<
FormatStyle::BreakConstructorInitializersStyle> {
279 IO.enumCase(
Value,
"BeforeColon", FormatStyle::BCIS_BeforeColon);
280 IO.enumCase(
Value,
"BeforeComma", FormatStyle::BCIS_BeforeComma);
281 IO.enumCase(
Value,
"AfterColon", FormatStyle::BCIS_AfterColon);
286struct ScalarEnumerationTraits<
FormatStyle::BreakInheritanceListStyle> {
288 FormatStyle::BreakInheritanceListStyle &
Value) {
289 IO.enumCase(
Value,
"BeforeColon", FormatStyle::BILS_BeforeColon);
290 IO.enumCase(
Value,
"BeforeComma", FormatStyle::BILS_BeforeComma);
291 IO.enumCase(
Value,
"AfterColon", FormatStyle::BILS_AfterColon);
292 IO.enumCase(
Value,
"AfterComma", FormatStyle::BILS_AfterComma);
297struct ScalarEnumerationTraits<
FormatStyle::BreakTemplateDeclarationsStyle> {
299 FormatStyle::BreakTemplateDeclarationsStyle &
Value) {
300 IO.enumCase(
Value,
"No", FormatStyle::BTDS_No);
301 IO.enumCase(
Value,
"MultiLine", FormatStyle::BTDS_MultiLine);
302 IO.enumCase(
Value,
"Yes", FormatStyle::BTDS_Yes);
305 IO.enumCase(
Value,
"false", FormatStyle::BTDS_MultiLine);
306 IO.enumCase(
Value,
"true", FormatStyle::BTDS_Yes);
311struct ScalarEnumerationTraits<
FormatStyle::DefinitionReturnTypeBreakingStyle> {
314 IO.enumCase(
Value,
"None", FormatStyle::DRTBS_None);
315 IO.enumCase(
Value,
"All", FormatStyle::DRTBS_All);
316 IO.enumCase(
Value,
"TopLevel", FormatStyle::DRTBS_TopLevel);
319 IO.enumCase(
Value,
"false", FormatStyle::DRTBS_None);
320 IO.enumCase(
Value,
"true", FormatStyle::DRTBS_All);
325struct ScalarEnumerationTraits<
FormatStyle::EscapedNewlineAlignmentStyle> {
327 FormatStyle::EscapedNewlineAlignmentStyle &
Value) {
328 IO.enumCase(
Value,
"DontAlign", FormatStyle::ENAS_DontAlign);
329 IO.enumCase(
Value,
"Left", FormatStyle::ENAS_Left);
330 IO.enumCase(
Value,
"Right", FormatStyle::ENAS_Right);
333 IO.enumCase(
Value,
"true", FormatStyle::ENAS_Left);
334 IO.enumCase(
Value,
"false", FormatStyle::ENAS_Right);
339struct ScalarEnumerationTraits<
FormatStyle::EmptyLineAfterAccessModifierStyle> {
342 IO.enumCase(
Value,
"Never", FormatStyle::ELAAMS_Never);
343 IO.enumCase(
Value,
"Leave", FormatStyle::ELAAMS_Leave);
344 IO.enumCase(
Value,
"Always", FormatStyle::ELAAMS_Always);
349struct ScalarEnumerationTraits<
353 IO.enumCase(
Value,
"Never", FormatStyle::ELBAMS_Never);
354 IO.enumCase(
Value,
"Leave", FormatStyle::ELBAMS_Leave);
355 IO.enumCase(
Value,
"LogicalBlock", FormatStyle::ELBAMS_LogicalBlock);
356 IO.enumCase(
Value,
"Always", FormatStyle::ELBAMS_Always);
361struct ScalarEnumerationTraits<
FormatStyle::IndentExternBlockStyle> {
363 IO.enumCase(
Value,
"AfterExternBlock", FormatStyle::IEBS_AfterExternBlock);
364 IO.enumCase(
Value,
"Indent", FormatStyle::IEBS_Indent);
365 IO.enumCase(
Value,
"NoIndent", FormatStyle::IEBS_NoIndent);
366 IO.enumCase(
Value,
"true", FormatStyle::IEBS_Indent);
367 IO.enumCase(
Value,
"false", FormatStyle::IEBS_NoIndent);
371template <>
struct MappingTraits<
FormatStyle::IntegerLiteralSeparatorStyle> {
372 static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &
Base) {
373 IO.mapOptional(
"Binary",
Base.Binary);
374 IO.mapOptional(
"BinaryMinDigits",
Base.BinaryMinDigits);
375 IO.mapOptional(
"Decimal",
Base.Decimal);
376 IO.mapOptional(
"DecimalMinDigits",
Base.DecimalMinDigits);
377 IO.mapOptional(
"Hex",
Base.Hex);
378 IO.mapOptional(
"HexMinDigits",
Base.HexMinDigits);
382template <>
struct ScalarEnumerationTraits<
FormatStyle::JavaScriptQuoteStyle> {
384 IO.enumCase(
Value,
"Leave", FormatStyle::JSQS_Leave);
385 IO.enumCase(
Value,
"Single", FormatStyle::JSQS_Single);
386 IO.enumCase(
Value,
"Double", FormatStyle::JSQS_Double);
390template <>
struct ScalarEnumerationTraits<
FormatStyle::LanguageKind> {
392 IO.enumCase(
Value,
"Cpp", FormatStyle::LK_Cpp);
393 IO.enumCase(
Value,
"Java", FormatStyle::LK_Java);
394 IO.enumCase(
Value,
"JavaScript", FormatStyle::LK_JavaScript);
395 IO.enumCase(
Value,
"ObjC", FormatStyle::LK_ObjC);
396 IO.enumCase(
Value,
"Proto", FormatStyle::LK_Proto);
397 IO.enumCase(
Value,
"TableGen", FormatStyle::LK_TableGen);
398 IO.enumCase(
Value,
"TextProto", FormatStyle::LK_TextProto);
399 IO.enumCase(
Value,
"CSharp", FormatStyle::LK_CSharp);
400 IO.enumCase(
Value,
"Json", FormatStyle::LK_Json);
401 IO.enumCase(
Value,
"Verilog", FormatStyle::LK_Verilog);
405template <>
struct ScalarEnumerationTraits<
FormatStyle::LanguageStandard> {
407 IO.enumCase(
Value,
"c++03", FormatStyle::LS_Cpp03);
408 IO.enumCase(
Value,
"C++03", FormatStyle::LS_Cpp03);
409 IO.enumCase(
Value,
"Cpp03", FormatStyle::LS_Cpp03);
411 IO.enumCase(
Value,
"c++11", FormatStyle::LS_Cpp11);
412 IO.enumCase(
Value,
"C++11", FormatStyle::LS_Cpp11);
414 IO.enumCase(
Value,
"c++14", FormatStyle::LS_Cpp14);
415 IO.enumCase(
Value,
"c++17", FormatStyle::LS_Cpp17);
416 IO.enumCase(
Value,
"c++20", FormatStyle::LS_Cpp20);
418 IO.enumCase(
Value,
"Latest", FormatStyle::LS_Latest);
419 IO.enumCase(
Value,
"Cpp11", FormatStyle::LS_Latest);
420 IO.enumCase(
Value,
"Auto", FormatStyle::LS_Auto);
425struct ScalarEnumerationTraits<
FormatStyle::LambdaBodyIndentationKind> {
427 FormatStyle::LambdaBodyIndentationKind &
Value) {
428 IO.enumCase(
Value,
"Signature", FormatStyle::LBI_Signature);
429 IO.enumCase(
Value,
"OuterScope", FormatStyle::LBI_OuterScope);
433template <>
struct ScalarEnumerationTraits<
FormatStyle::LineEndingStyle> {
435 IO.enumCase(
Value,
"LF", FormatStyle::LE_LF);
436 IO.enumCase(
Value,
"CRLF", FormatStyle::LE_CRLF);
437 IO.enumCase(
Value,
"DeriveLF", FormatStyle::LE_DeriveLF);
438 IO.enumCase(
Value,
"DeriveCRLF", FormatStyle::LE_DeriveCRLF);
443struct ScalarEnumerationTraits<
FormatStyle::NamespaceIndentationKind> {
445 FormatStyle::NamespaceIndentationKind &
Value) {
446 IO.enumCase(
Value,
"None", FormatStyle::NI_None);
447 IO.enumCase(
Value,
"Inner", FormatStyle::NI_Inner);
448 IO.enumCase(
Value,
"All", FormatStyle::NI_All);
452template <>
struct ScalarEnumerationTraits<
FormatStyle::OperandAlignmentStyle> {
454 IO.enumCase(
Value,
"DontAlign", FormatStyle::OAS_DontAlign);
455 IO.enumCase(
Value,
"Align", FormatStyle::OAS_Align);
456 IO.enumCase(
Value,
"AlignAfterOperator",
457 FormatStyle::OAS_AlignAfterOperator);
460 IO.enumCase(
Value,
"true", FormatStyle::OAS_Align);
461 IO.enumCase(
Value,
"false", FormatStyle::OAS_DontAlign);
466struct ScalarEnumerationTraits<
FormatStyle::PackConstructorInitializersStyle> {
469 IO.enumCase(
Value,
"Never", FormatStyle::PCIS_Never);
470 IO.enumCase(
Value,
"BinPack", FormatStyle::PCIS_BinPack);
471 IO.enumCase(
Value,
"CurrentLine", FormatStyle::PCIS_CurrentLine);
472 IO.enumCase(
Value,
"NextLine", FormatStyle::PCIS_NextLine);
473 IO.enumCase(
Value,
"NextLineOnly", FormatStyle::PCIS_NextLineOnly);
477template <>
struct ScalarEnumerationTraits<
FormatStyle::PointerAlignmentStyle> {
479 IO.enumCase(
Value,
"Middle", FormatStyle::PAS_Middle);
480 IO.enumCase(
Value,
"Left", FormatStyle::PAS_Left);
481 IO.enumCase(
Value,
"Right", FormatStyle::PAS_Right);
484 IO.enumCase(
Value,
"true", FormatStyle::PAS_Left);
485 IO.enumCase(
Value,
"false", FormatStyle::PAS_Right);
490struct ScalarEnumerationTraits<
FormatStyle::PPDirectiveIndentStyle> {
492 IO.enumCase(
Value,
"None", FormatStyle::PPDIS_None);
493 IO.enumCase(
Value,
"AfterHash", FormatStyle::PPDIS_AfterHash);
494 IO.enumCase(
Value,
"BeforeHash", FormatStyle::PPDIS_BeforeHash);
499struct ScalarEnumerationTraits<
FormatStyle::QualifierAlignmentStyle> {
501 IO.enumCase(
Value,
"Leave", FormatStyle::QAS_Leave);
502 IO.enumCase(
Value,
"Left", FormatStyle::QAS_Left);
503 IO.enumCase(
Value,
"Right", FormatStyle::QAS_Right);
504 IO.enumCase(
Value,
"Custom", FormatStyle::QAS_Custom);
510 FormatStyle::SpaceBeforeParensCustom::AfterPlacementOperatorStyle> {
513 FormatStyle::SpaceBeforeParensCustom::AfterPlacementOperatorStyle
515 IO.enumCase(
Value,
"Always",
516 FormatStyle::SpaceBeforeParensCustom::APO_Always);
517 IO.enumCase(
Value,
"Never",
518 FormatStyle::SpaceBeforeParensCustom::APO_Never);
519 IO.enumCase(
Value,
"Leave",
520 FormatStyle::SpaceBeforeParensCustom::APO_Leave);
525 static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
526 IO.mapOptional(
"Language", Format.Language);
527 IO.mapOptional(
"Delimiters", Format.Delimiters);
528 IO.mapOptional(
"EnclosingFunctions", Format.EnclosingFunctions);
529 IO.mapOptional(
"CanonicalDelimiter", Format.CanonicalDelimiter);
530 IO.mapOptional(
"BasedOnStyle", Format.BasedOnStyle);
535struct ScalarEnumerationTraits<
FormatStyle::ReferenceAlignmentStyle> {
537 IO.enumCase(
Value,
"Pointer", FormatStyle::RAS_Pointer);
538 IO.enumCase(
Value,
"Middle", FormatStyle::RAS_Middle);
539 IO.enumCase(
Value,
"Left", FormatStyle::RAS_Left);
540 IO.enumCase(
Value,
"Right", FormatStyle::RAS_Right);
545struct ScalarEnumerationTraits<
FormatStyle::RemoveParenthesesStyle> {
547 IO.enumCase(
Value,
"Leave", FormatStyle::RPS_Leave);
548 IO.enumCase(
Value,
"MultipleParentheses",
549 FormatStyle::RPS_MultipleParentheses);
550 IO.enumCase(
Value,
"ReturnStatement", FormatStyle::RPS_ReturnStatement);
555struct ScalarEnumerationTraits<
FormatStyle::RequiresClausePositionStyle> {
557 FormatStyle::RequiresClausePositionStyle &
Value) {
558 IO.enumCase(
Value,
"OwnLine", FormatStyle::RCPS_OwnLine);
559 IO.enumCase(
Value,
"WithPreceding", FormatStyle::RCPS_WithPreceding);
560 IO.enumCase(
Value,
"WithFollowing", FormatStyle::RCPS_WithFollowing);
561 IO.enumCase(
Value,
"SingleLine", FormatStyle::RCPS_SingleLine);
566struct ScalarEnumerationTraits<
FormatStyle::RequiresExpressionIndentationKind> {
569 IO.enumCase(
Value,
"Keyword", FormatStyle::REI_Keyword);
570 IO.enumCase(
Value,
"OuterScope", FormatStyle::REI_OuterScope);
575struct ScalarEnumerationTraits<
FormatStyle::ReturnTypeBreakingStyle> {
577 IO.enumCase(
Value,
"None", FormatStyle::RTBS_None);
578 IO.enumCase(
Value,
"All", FormatStyle::RTBS_All);
579 IO.enumCase(
Value,
"TopLevel", FormatStyle::RTBS_TopLevel);
580 IO.enumCase(
Value,
"TopLevelDefinitions",
581 FormatStyle::RTBS_TopLevelDefinitions);
582 IO.enumCase(
Value,
"AllDefinitions", FormatStyle::RTBS_AllDefinitions);
587struct ScalarEnumerationTraits<
FormatStyle::SeparateDefinitionStyle> {
589 IO.enumCase(
Value,
"Leave", FormatStyle::SDS_Leave);
590 IO.enumCase(
Value,
"Always", FormatStyle::SDS_Always);
591 IO.enumCase(
Value,
"Never", FormatStyle::SDS_Never);
595template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortBlockStyle> {
597 IO.enumCase(
Value,
"Never", FormatStyle::SBS_Never);
598 IO.enumCase(
Value,
"false", FormatStyle::SBS_Never);
599 IO.enumCase(
Value,
"Always", FormatStyle::SBS_Always);
600 IO.enumCase(
Value,
"true", FormatStyle::SBS_Always);
601 IO.enumCase(
Value,
"Empty", FormatStyle::SBS_Empty);
605template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortFunctionStyle> {
607 IO.enumCase(
Value,
"None", FormatStyle::SFS_None);
608 IO.enumCase(
Value,
"false", FormatStyle::SFS_None);
609 IO.enumCase(
Value,
"All", FormatStyle::SFS_All);
610 IO.enumCase(
Value,
"true", FormatStyle::SFS_All);
611 IO.enumCase(
Value,
"Inline", FormatStyle::SFS_Inline);
612 IO.enumCase(
Value,
"InlineOnly", FormatStyle::SFS_InlineOnly);
613 IO.enumCase(
Value,
"Empty", FormatStyle::SFS_Empty);
617template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortIfStyle> {
619 IO.enumCase(
Value,
"Never", FormatStyle::SIS_Never);
620 IO.enumCase(
Value,
"WithoutElse", FormatStyle::SIS_WithoutElse);
621 IO.enumCase(
Value,
"OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf);
622 IO.enumCase(
Value,
"AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse);
625 IO.enumCase(
Value,
"Always", FormatStyle::SIS_OnlyFirstIf);
626 IO.enumCase(
Value,
"false", FormatStyle::SIS_Never);
627 IO.enumCase(
Value,
"true", FormatStyle::SIS_WithoutElse);
631template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortLambdaStyle> {
633 IO.enumCase(
Value,
"None", FormatStyle::SLS_None);
634 IO.enumCase(
Value,
"false", FormatStyle::SLS_None);
635 IO.enumCase(
Value,
"Empty", FormatStyle::SLS_Empty);
636 IO.enumCase(
Value,
"Inline", FormatStyle::SLS_Inline);
637 IO.enumCase(
Value,
"All", FormatStyle::SLS_All);
638 IO.enumCase(
Value,
"true", FormatStyle::SLS_All);
642template <>
struct ScalarEnumerationTraits<
FormatStyle::SortIncludesOptions> {
644 IO.enumCase(
Value,
"Never", FormatStyle::SI_Never);
645 IO.enumCase(
Value,
"CaseInsensitive", FormatStyle::SI_CaseInsensitive);
646 IO.enumCase(
Value,
"CaseSensitive", FormatStyle::SI_CaseSensitive);
649 IO.enumCase(
Value,
"false", FormatStyle::SI_Never);
650 IO.enumCase(
Value,
"true", FormatStyle::SI_CaseSensitive);
655struct ScalarEnumerationTraits<
FormatStyle::SortJavaStaticImportOptions> {
657 FormatStyle::SortJavaStaticImportOptions &
Value) {
658 IO.enumCase(
Value,
"Before", FormatStyle::SJSIO_Before);
659 IO.enumCase(
Value,
"After", FormatStyle::SJSIO_After);
664struct ScalarEnumerationTraits<
FormatStyle::SortUsingDeclarationsOptions> {
666 FormatStyle::SortUsingDeclarationsOptions &
Value) {
667 IO.enumCase(
Value,
"Never", FormatStyle::SUD_Never);
668 IO.enumCase(
Value,
"Lexicographic", FormatStyle::SUD_Lexicographic);
669 IO.enumCase(
Value,
"LexicographicNumeric",
670 FormatStyle::SUD_LexicographicNumeric);
673 IO.enumCase(
Value,
"false", FormatStyle::SUD_Never);
674 IO.enumCase(
Value,
"true", FormatStyle::SUD_LexicographicNumeric);
679struct ScalarEnumerationTraits<
FormatStyle::SpaceAroundPointerQualifiersStyle> {
682 IO.enumCase(
Value,
"Default", FormatStyle::SAPQ_Default);
683 IO.enumCase(
Value,
"Before", FormatStyle::SAPQ_Before);
684 IO.enumCase(
Value,
"After", FormatStyle::SAPQ_After);
685 IO.enumCase(
Value,
"Both", FormatStyle::SAPQ_Both);
689template <>
struct MappingTraits<
FormatStyle::SpaceBeforeParensCustom> {
690 static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) {
691 IO.mapOptional(
"AfterControlStatements", Spacing.AfterControlStatements);
692 IO.mapOptional(
"AfterForeachMacros", Spacing.AfterForeachMacros);
693 IO.mapOptional(
"AfterFunctionDefinitionName",
694 Spacing.AfterFunctionDefinitionName);
695 IO.mapOptional(
"AfterFunctionDeclarationName",
696 Spacing.AfterFunctionDeclarationName);
697 IO.mapOptional(
"AfterIfMacros", Spacing.AfterIfMacros);
698 IO.mapOptional(
"AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
699 IO.mapOptional(
"AfterPlacementOperator", Spacing.AfterPlacementOperator);
700 IO.mapOptional(
"AfterRequiresInClause", Spacing.AfterRequiresInClause);
701 IO.mapOptional(
"AfterRequiresInExpression",
702 Spacing.AfterRequiresInExpression);
703 IO.mapOptional(
"BeforeNonEmptyParentheses",
704 Spacing.BeforeNonEmptyParentheses);
709struct ScalarEnumerationTraits<
FormatStyle::SpaceBeforeParensStyle> {
711 IO.enumCase(
Value,
"Never", FormatStyle::SBPO_Never);
712 IO.enumCase(
Value,
"ControlStatements",
713 FormatStyle::SBPO_ControlStatements);
714 IO.enumCase(
Value,
"ControlStatementsExceptControlMacros",
715 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
716 IO.enumCase(
Value,
"NonEmptyParentheses",
717 FormatStyle::SBPO_NonEmptyParentheses);
718 IO.enumCase(
Value,
"Always", FormatStyle::SBPO_Always);
719 IO.enumCase(
Value,
"Custom", FormatStyle::SBPO_Custom);
722 IO.enumCase(
Value,
"false", FormatStyle::SBPO_Never);
723 IO.enumCase(
Value,
"true", FormatStyle::SBPO_ControlStatements);
724 IO.enumCase(
Value,
"ControlStatementsExceptForEachMacros",
725 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
729template <>
struct ScalarEnumerationTraits<
FormatStyle::SpacesInAnglesStyle> {
731 IO.enumCase(
Value,
"Never", FormatStyle::SIAS_Never);
732 IO.enumCase(
Value,
"Always", FormatStyle::SIAS_Always);
733 IO.enumCase(
Value,
"Leave", FormatStyle::SIAS_Leave);
736 IO.enumCase(
Value,
"false", FormatStyle::SIAS_Never);
737 IO.enumCase(
Value,
"true", FormatStyle::SIAS_Always);
741template <>
struct MappingTraits<
FormatStyle::SpacesInLineComment> {
742 static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
744 int signedMaximum =
static_cast<int>(Space.Maximum);
745 IO.mapOptional(
"Minimum", Space.Minimum);
746 IO.mapOptional(
"Maximum", signedMaximum);
747 Space.Maximum =
static_cast<unsigned>(signedMaximum);
749 if (Space.Maximum != -1u)
750 Space.Minimum = std::min(Space.Minimum, Space.Maximum);
754template <>
struct MappingTraits<
FormatStyle::SpacesInParensCustom> {
755 static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) {
756 IO.mapOptional(
"InCStyleCasts", Spaces.InCStyleCasts);
757 IO.mapOptional(
"InConditionalStatements", Spaces.InConditionalStatements);
758 IO.mapOptional(
"InEmptyParentheses", Spaces.InEmptyParentheses);
759 IO.mapOptional(
"Other", Spaces.Other);
763template <>
struct ScalarEnumerationTraits<
FormatStyle::SpacesInParensStyle> {
765 IO.enumCase(
Value,
"Never", FormatStyle::SIPO_Never);
766 IO.enumCase(
Value,
"Custom", FormatStyle::SIPO_Custom);
770template <>
struct ScalarEnumerationTraits<
FormatStyle::TrailingCommaStyle> {
772 IO.enumCase(
Value,
"None", FormatStyle::TCS_None);
773 IO.enumCase(
Value,
"Wrapped", FormatStyle::TCS_Wrapped);
778struct ScalarEnumerationTraits<
FormatStyle::TrailingCommentsAlignmentKinds> {
780 FormatStyle::TrailingCommentsAlignmentKinds &
Value) {
781 IO.enumCase(
Value,
"Leave", FormatStyle::TCAS_Leave);
782 IO.enumCase(
Value,
"Always", FormatStyle::TCAS_Always);
783 IO.enumCase(
Value,
"Never", FormatStyle::TCAS_Never);
787template <>
struct MappingTraits<
FormatStyle::TrailingCommentsAlignmentStyle> {
789 FormatStyle::TrailingCommentsAlignmentStyle &
Value) {
790 IO.enumCase(
Value,
"Leave",
791 FormatStyle::TrailingCommentsAlignmentStyle(
792 {FormatStyle::TCAS_Leave, 0}));
794 IO.enumCase(
Value,
"Always",
795 FormatStyle::TrailingCommentsAlignmentStyle(
796 {FormatStyle::TCAS_Always, 0}));
798 IO.enumCase(
Value,
"Never",
799 FormatStyle::TrailingCommentsAlignmentStyle(
800 {FormatStyle::TCAS_Never, 0}));
803 IO.enumCase(
Value,
"true",
804 FormatStyle::TrailingCommentsAlignmentStyle(
805 {FormatStyle::TCAS_Always, 0}));
806 IO.enumCase(
Value,
"false",
807 FormatStyle::TrailingCommentsAlignmentStyle(
808 {FormatStyle::TCAS_Never, 0}));
812 FormatStyle::TrailingCommentsAlignmentStyle &
Value) {
813 IO.mapOptional(
"Kind",
Value.Kind);
814 IO.mapOptional(
"OverEmptyLines",
Value.OverEmptyLines);
818template <>
struct ScalarEnumerationTraits<
FormatStyle::UseTabStyle> {
820 IO.enumCase(
Value,
"Never", FormatStyle::UT_Never);
821 IO.enumCase(
Value,
"false", FormatStyle::UT_Never);
822 IO.enumCase(
Value,
"Always", FormatStyle::UT_Always);
823 IO.enumCase(
Value,
"true", FormatStyle::UT_Always);
824 IO.enumCase(
Value,
"ForIndentation", FormatStyle::UT_ForIndentation);
825 IO.enumCase(
Value,
"ForContinuationAndIndentation",
826 FormatStyle::UT_ForContinuationAndIndentation);
827 IO.enumCase(
Value,
"AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);
834 IO.mapOptional(
"Language", Style.
Language);
836 StringRef BasedOnStyle;
837 if (IO.outputting()) {
838 StringRef Styles[] = {
"LLVM",
"Google",
"Chromium",
"Mozilla",
839 "WebKit",
"GNU",
"Microsoft",
"clang-format"};
840 for (StringRef StyleName : Styles) {
842 if (getPredefinedStyle(StyleName, Style.
Language, &PredefinedStyle) &&
843 Style == PredefinedStyle) {
844 IO.mapOptional(
"# BasedOnStyle", StyleName);
845 BasedOnStyle = StyleName;
850 IO.mapOptional(
"BasedOnStyle", BasedOnStyle);
851 if (!BasedOnStyle.empty()) {
852 FormatStyle::LanguageKind OldLanguage = Style.
Language;
853 FormatStyle::LanguageKind Language =
855 if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
856 IO.setError(Twine(
"Unknown value for BasedOnStyle: ", BasedOnStyle));
874 const bool IsGoogleOrChromium = BasedOnStyle.equals_insensitive(
"google") ||
875 BasedOnStyle.equals_insensitive(
"chromium");
876 bool OnCurrentLine = IsGoogleOrChromium;
877 bool OnNextLine =
true;
879 bool BreakBeforeInheritanceComma =
false;
880 bool BreakConstructorInitializersBeforeComma =
false;
882 bool DeriveLineEnding =
true;
883 bool UseCRLF =
false;
885 bool SpaceInEmptyParentheses =
false;
886 bool SpacesInConditionalStatement =
false;
887 bool SpacesInCStyleCastParentheses =
false;
888 bool SpacesInParentheses =
false;
891 if (!IO.outputting()) {
893 IO.mapOptional(
"AllowAllConstructorInitializersOnNextLine", OnNextLine);
894 IO.mapOptional(
"BreakBeforeInheritanceComma",
895 BreakBeforeInheritanceComma);
896 IO.mapOptional(
"BreakConstructorInitializersBeforeComma",
897 BreakConstructorInitializersBeforeComma);
898 IO.mapOptional(
"ConstructorInitializerAllOnOneLineOrOnePerLine",
900 IO.mapOptional(
"DeriveLineEnding", DeriveLineEnding);
902 IO.mapOptional(
"IndentFunctionDeclarationAfterType",
906 IO.mapOptional(
"SpaceAfterControlStatementKeyword",
908 IO.mapOptional(
"SpaceInEmptyParentheses", SpaceInEmptyParentheses);
909 IO.mapOptional(
"SpacesInConditionalStatement",
910 SpacesInConditionalStatement);
911 IO.mapOptional(
"SpacesInCStyleCastParentheses",
912 SpacesInCStyleCastParentheses);
913 IO.mapOptional(
"SpacesInParentheses", SpacesInParentheses);
914 IO.mapOptional(
"UseCRLF", UseCRLF);
920 IO.mapOptional(
"AlignConsecutiveAssignments",
922 IO.mapOptional(
"AlignConsecutiveBitFields",
924 IO.mapOptional(
"AlignConsecutiveDeclarations",
927 IO.mapOptional(
"AlignConsecutiveShortCaseStatements",
932 IO.mapOptional(
"AllowAllArgumentsOnNextLine",
934 IO.mapOptional(
"AllowAllParametersOfDeclarationOnNextLine",
936 IO.mapOptional(
"AllowBreakBeforeNoexceptSpecifier",
938 IO.mapOptional(
"AllowShortBlocksOnASingleLine",
940 IO.mapOptional(
"AllowShortCaseLabelsOnASingleLine",
942 IO.mapOptional(
"AllowShortCompoundRequirementOnASingleLine",
944 IO.mapOptional(
"AllowShortEnumsOnASingleLine",
946 IO.mapOptional(
"AllowShortFunctionsOnASingleLine",
948 IO.mapOptional(
"AllowShortIfStatementsOnASingleLine",
950 IO.mapOptional(
"AllowShortLambdasOnASingleLine",
952 IO.mapOptional(
"AllowShortLoopsOnASingleLine",
954 IO.mapOptional(
"AlwaysBreakAfterDefinitionReturnType",
956 IO.mapOptional(
"AlwaysBreakAfterReturnType",
958 IO.mapOptional(
"AlwaysBreakBeforeMultilineStrings",
960 IO.mapOptional(
"AlwaysBreakTemplateDeclarations",
966 IO.mapOptional(
"BracedInitializerIndentWidth",
969 IO.mapOptional(
"BreakAdjacentStringLiterals",
972 IO.mapOptional(
"BreakAfterJavaFieldAnnotations",
975 IO.mapOptional(
"BreakBeforeBinaryOperators",
977 IO.mapOptional(
"BreakBeforeConceptDeclarations",
980 IO.mapOptional(
"BreakBeforeInlineASMColon",
982 IO.mapOptional(
"BreakBeforeTernaryOperators",
984 IO.mapOptional(
"BreakConstructorInitializers",
991 IO.mapOptional(
"ConstructorInitializerIndentWidth",
997 IO.mapOptional(
"EmptyLineAfterAccessModifier",
999 IO.mapOptional(
"EmptyLineBeforeAccessModifier",
1001 IO.mapOptional(
"ExperimentalAutoDetectBinPacking",
1005 IO.mapOptional(
"IfMacros", Style.
IfMacros);
1009 IO.mapOptional(
"IncludeIsMainSourceRegex",
1019 IO.mapOptional(
"IndentWrappedFunctionNames",
1028 IO.mapOptional(
"KeepEmptyLinesAtTheStartOfBlocks",
1032 IO.mapOptional(
"LineEnding", Style.
LineEnding);
1035 IO.mapOptional(
"Macros", Style.
Macros);
1041 IO.mapOptional(
"ObjCBreakBeforeNestedBlockParam",
1043 IO.mapOptional(
"ObjCPropertyAttributeOrder",
1046 IO.mapOptional(
"ObjCSpaceBeforeProtocolList",
1048 IO.mapOptional(
"PackConstructorInitializers",
1051 IO.mapOptional(
"PenaltyBreakBeforeFirstCallParameter",
1054 IO.mapOptional(
"PenaltyBreakFirstLessLess",
1056 IO.mapOptional(
"PenaltyBreakOpenParenthesis",
1059 IO.mapOptional(
"PenaltyBreakTemplateDeclaration",
1062 IO.mapOptional(
"PenaltyIndentedWhitespace",
1064 IO.mapOptional(
"PenaltyReturnTypeOnItsOwnLine",
1083 IO.mapOptional(
"RequiresExpressionIndentation",
1092 IO.mapOptional(
"SpaceAfterTemplateKeyword",
1094 IO.mapOptional(
"SpaceAroundPointerQualifiers",
1096 IO.mapOptional(
"SpaceBeforeAssignmentOperators",
1099 IO.mapOptional(
"SpaceBeforeCpp11BracedList",
1101 IO.mapOptional(
"SpaceBeforeCtorInitializerColon",
1103 IO.mapOptional(
"SpaceBeforeInheritanceColon",
1108 IO.mapOptional(
"SpaceBeforeRangeBasedForLoopColon",
1110 IO.mapOptional(
"SpaceBeforeSquareBrackets",
1113 IO.mapOptional(
"SpacesBeforeTrailingComments",
1116 IO.mapOptional(
"SpacesInContainerLiterals",
1118 IO.mapOptional(
"SpacesInLineCommentPrefix",
1123 IO.mapOptional(
"Standard", Style.
Standard);
1124 IO.mapOptional(
"StatementAttributeLikeMacros",
1127 IO.mapOptional(
"TabWidth", Style.
TabWidth);
1128 IO.mapOptional(
"TypeNames", Style.
TypeNames);
1130 IO.mapOptional(
"UseTab", Style.
UseTab);
1131 IO.mapOptional(
"VerilogBreakBetweenInstancePorts",
1133 IO.mapOptional(
"WhitespaceSensitiveMacros",
1142 FormatStyle::DRTBS_All) {
1145 FormatStyle::DRTBS_TopLevel) {
1147 FormatStyle::RTBS_TopLevelDefinitions;
1153 if (BreakBeforeInheritanceComma &&
1161 if (BreakConstructorInitializersBeforeComma &&
1166 if (!IsGoogleOrChromium) {
1170 ? FormatStyle::PCIS_NextLine
1171 : FormatStyle::PCIS_CurrentLine;
1174 FormatStyle::PCIS_NextLine) {
1177 else if (!OnNextLine)
1181 if (Style.
LineEnding == FormatStyle::LE_DeriveLF) {
1182 if (!DeriveLineEnding)
1183 Style.
LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF;
1185 Style.
LineEnding = FormatStyle::LE_DeriveCRLF;
1189 (SpacesInParentheses || SpaceInEmptyParentheses ||
1190 SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) {
1191 if (SpacesInParentheses) {
1196 SpacesInCStyleCastParentheses;
1198 SpaceInEmptyParentheses;
1203 SpacesInConditionalStatement;
1205 SpacesInCStyleCastParentheses;
1207 SpaceInEmptyParentheses;
1219template <>
struct DocumentListTraits<
std::vector<FormatStyle>> {
1220 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
1225 if (Index >= Seq.size()) {
1226 assert(Index == Seq.size());
1228 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
1231 Template = *((
const FormatStyle *)IO.getContext());
1232 Template.
Language = FormatStyle::LK_None;
1234 Seq.resize(Index + 1, Template);
1254 return llvm::make_error<llvm::StringError>(Message,
1255 llvm::inconvertibleErrorCode());
1259 return "clang-format.parse_error";
1267 return "Invalid argument";
1269 return "Unsuitable";
1271 return "trailing comma insertion cannot be used with bin packing";
1273 return "Invalid qualifier specified in QualifierOrder";
1275 return "Duplicate qualifier specified in QualifierOrder";
1277 return "Missing type in QualifierOrder";
1279 return "Missing QualifierOrder";
1281 llvm_unreachable(
"unexpected parse error");
1512 LLVMStyle.
IfMacros.push_back(
"KJ_IF_MAYBE");
1514 {
"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0,
false},
1515 {
"^(<|\"(gtest|gmock|isl|json)/)", 3, 0,
false},
1516 {
".*", 1, 0,
false}};
1650 {
"^<.*\\.h>", 1, 0,
false},
1651 {
"^<.*", 2, 0,
false},
1652 {
".*", 3, 0,
false}};
1693 "PARSE_PARTIAL_TEXT_PROTO",
1697 "ParseTextProtoOrDie",
1699 "ParsePartialTestProto",
1810 "com.google.android.apps.chrome",
1829 return ChromiumStyle;
1855 return MozillaStyle;
1947 if (Name.equals_insensitive(
"llvm"))
1949 else if (Name.equals_insensitive(
"chromium"))
1951 else if (Name.equals_insensitive(
"mozilla"))
1953 else if (Name.equals_insensitive(
"google"))
1955 else if (Name.equals_insensitive(
"webkit"))
1957 else if (Name.equals_insensitive(
"gnu"))
1959 else if (Name.equals_insensitive(
"microsoft"))
1961 else if (Name.equals_insensitive(
"clang-format"))
1963 else if (Name.equals_insensitive(
"none"))
1965 else if (Name.equals_insensitive(
"inheritparentconfig"))
1981 if (Qualifier ==
"type")
1985 if (token == tok::identifier)
1990 std::set<std::string> UniqueQualifiers(Style->
QualifierOrder.begin(),
1993 LLVM_DEBUG(llvm::dbgs()
1995 <<
" vs " << UniqueQualifiers.size() <<
"\n");
2008 llvm::SourceMgr::DiagHandlerTy DiagHandler,
2009 void *DiagHandlerCtxt) {
2013 if (Config.getBuffer().trim().empty())
2015 Style->StyleSet.
Clear();
2016 std::vector<FormatStyle> Styles;
2017 llvm::yaml::Input Input(Config,
nullptr, DiagHandler,
2023 Input.setContext(Style);
2024 Input.setAllowUnknownKeys(AllowUnknownOptions);
2027 return Input.error();
2029 for (
unsigned i = 0; i < Styles.size(); ++i) {
2034 for (
unsigned j = 0; j < i; ++j) {
2036 LLVM_DEBUG(llvm::dbgs()
2037 <<
"Duplicate languages in the config file on positions "
2038 << j <<
" and " << i <<
"\n");
2047 bool LanguageFound =
false;
2048 for (
const FormatStyle &Style : llvm::reverse(Styles)) {
2050 StyleSet.
Add(Style);
2052 LanguageFound =
true;
2054 if (!LanguageFound) {
2059 StyleSet.
Add(std::move(DefaultStyle));
2074 llvm::raw_string_ostream Stream(
Text);
2075 llvm::yaml::Output Output(Stream);
2082 Output << NonConstStyle;
2084 return Stream.str();
2087std::optional<FormatStyle>
2090 return std::nullopt;
2092 if (It == Styles->end())
2093 return std::nullopt;
2095 Style.StyleSet = *
this;
2101 "Cannot add a style for LK_None to a StyleSet");
2103 !Style.StyleSet.Styles &&
2104 "Cannot add a style associated with an existing StyleSet to a StyleSet");
2106 Styles = std::make_shared<MapType>();
2107 (*Styles)[Style.
Language] = std::move(Style);
2112std::optional<FormatStyle>
2124 std::pair<tooling::Replacements, unsigned>
2125 analyze(TokenAnnotator &Annotator,
2127 FormatTokenLexer &Tokens)
override {
2128 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2130 removeParens(AnnotatedLines, Result);
2135 void removeParens(SmallVectorImpl<AnnotatedLine *> &Lines,
2136 tooling::Replacements &Result) {
2137 const auto &SourceMgr =
Env.getSourceManager();
2138 for (
auto *Line : Lines) {
2139 removeParens(Line->Children, Result);
2140 if (!Line->Affected)
2142 for (
const auto *Token = Line->First; Token && !Token->Finalized;
2143 Token = Token->Next) {
2144 if (!Token->Optional || !Token->isOneOf(tok::l_paren, tok::r_paren))
2146 auto *Next = Token->Next;
2147 assert(Next && Next->isNot(tok::eof));
2148 SourceLocation Start;
2149 if (Next->NewlinesBefore == 0) {
2150 Start = Token->Tok.getLocation();
2151 Next->WhitespaceRange = Token->WhitespaceRange;
2153 Start = Token->WhitespaceRange.getBegin();
2156 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2157 cantFail(Result.add(tooling::Replacement(SourceMgr, Range,
" ")));
2163class BracesInserter :
public TokenAnalyzer {
2166 : TokenAnalyzer(
Env, Style) {}
2168 std::pair<tooling::Replacements, unsigned>
2169 analyze(TokenAnnotator &Annotator,
2170 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2171 FormatTokenLexer &Tokens)
override {
2172 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2173 tooling::Replacements Result;
2174 insertBraces(AnnotatedLines, Result);
2179 void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2180 tooling::Replacements &Result) {
2181 const auto &SourceMgr =
Env.getSourceManager();
2182 int OpeningBraceSurplus = 0;
2183 for (AnnotatedLine *Line : Lines) {
2184 insertBraces(Line->Children, Result);
2185 if (!Line->Affected && OpeningBraceSurplus == 0)
2187 for (FormatToken *Token = Line->First; Token && !Token->Finalized;
2188 Token = Token->Next) {
2189 int BraceCount = Token->BraceCount;
2190 if (BraceCount == 0)
2193 if (BraceCount < 0) {
2194 assert(BraceCount == -1);
2195 if (!Line->Affected)
2197 Brace = Token->is(tok::comment) ?
"\n{" :
"{";
2198 ++OpeningBraceSurplus;
2200 if (OpeningBraceSurplus == 0)
2202 if (OpeningBraceSurplus < BraceCount)
2203 BraceCount = OpeningBraceSurplus;
2204 Brace =
'\n' + std::string(BraceCount,
'}');
2205 OpeningBraceSurplus -= BraceCount;
2207 Token->BraceCount = 0;
2208 const auto Start = Token->Tok.getEndLoc();
2209 cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0,
Brace)));
2212 assert(OpeningBraceSurplus == 0);
2216class BracesRemover :
public TokenAnalyzer {
2219 : TokenAnalyzer(
Env, Style) {}
2221 std::pair<tooling::Replacements, unsigned>
2222 analyze(TokenAnnotator &Annotator,
2223 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2224 FormatTokenLexer &Tokens)
override {
2225 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2226 tooling::Replacements Result;
2227 removeBraces(AnnotatedLines, Result);
2232 void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2233 tooling::Replacements &Result) {
2234 const auto &SourceMgr =
Env.getSourceManager();
2235 const auto End = Lines.end();
2236 for (
auto I = Lines.begin(); I != End; ++I) {
2237 const auto Line = *I;
2238 removeBraces(Line->Children, Result);
2239 if (!Line->Affected)
2241 const auto NextLine = I + 1 == End ? nullptr : I[1];
2242 for (
auto Token = Line->First; Token && !Token->Finalized;
2243 Token = Token->Next) {
2244 if (!Token->Optional)
2246 if (!Token->isOneOf(tok::l_brace, tok::r_brace))
2248 auto Next = Token->Next;
2249 assert(Next || Token == Line->Last);
2250 if (!Next && NextLine)
2251 Next = NextLine->First;
2252 SourceLocation Start;
2253 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2254 Start = Token->Tok.getLocation();
2255 Next->WhitespaceRange = Token->WhitespaceRange;
2257 Start = Token->WhitespaceRange.getBegin();
2260 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2261 cantFail(Result.add(tooling::Replacement(SourceMgr, Range,
"")));
2267class SemiRemover :
public TokenAnalyzer {
2270 : TokenAnalyzer(
Env, Style) {}
2272 std::pair<tooling::Replacements, unsigned>
2273 analyze(TokenAnnotator &Annotator,
2274 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2275 FormatTokenLexer &Tokens)
override {
2276 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2277 tooling::Replacements Result;
2278 removeSemi(AnnotatedLines, Result);
2283 void removeSemi(SmallVectorImpl<AnnotatedLine *> &Lines,
2284 tooling::Replacements &Result) {
2285 const auto &SourceMgr =
Env.getSourceManager();
2286 const auto End = Lines.end();
2287 for (
auto I = Lines.begin(); I != End; ++I) {
2288 const auto Line = *I;
2289 removeSemi(Line->Children, Result);
2290 if (!Line->Affected)
2292 const auto NextLine = I + 1 == End ? nullptr : I[1];
2293 for (
auto Token = Line->First; Token && !Token->Finalized;
2294 Token = Token->Next) {
2295 if (!Token->Optional)
2297 if (Token->isNot(tok::semi))
2299 auto Next = Token->Next;
2300 assert(Next || Token == Line->Last);
2301 if (!Next && NextLine)
2302 Next = NextLine->First;
2303 SourceLocation Start;
2304 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2305 Start = Token->Tok.getLocation();
2306 Next->WhitespaceRange = Token->WhitespaceRange;
2308 Start = Token->WhitespaceRange.getBegin();
2311 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2312 cantFail(Result.add(tooling::Replacement(SourceMgr, Range,
"")));
2318class JavaScriptRequoter :
public TokenAnalyzer {
2320 JavaScriptRequoter(
const Environment &
Env,
const FormatStyle &Style)
2321 : TokenAnalyzer(
Env, Style) {}
2323 std::pair<tooling::Replacements, unsigned>
2324 analyze(TokenAnnotator &Annotator,
2325 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2326 FormatTokenLexer &Tokens)
override {
2327 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2328 tooling::Replacements Result;
2329 requoteJSStringLiteral(AnnotatedLines, Result);
2336 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
2337 tooling::Replacements &Result) {
2338 for (AnnotatedLine *Line : Lines) {
2339 requoteJSStringLiteral(Line->Children, Result);
2340 if (!Line->Affected)
2342 for (FormatToken *FormatTok = Line->First; FormatTok;
2343 FormatTok = FormatTok->Next) {
2344 StringRef Input = FormatTok->TokenText;
2345 if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
2349 !Input.startswith(
"\"")) ||
2351 !Input.startswith(
"\'"))) {
2357 SourceLocation Start = FormatTok->Tok.getLocation();
2358 auto Replace = [&](SourceLocation Start,
unsigned Length,
2359 StringRef ReplacementText) {
2360 auto Err = Result.add(tooling::Replacement(
2361 Env.getSourceManager(), Start, Length, ReplacementText));
2365 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
2369 Replace(Start, 1, IsSingle ?
"'" :
"\"");
2370 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
2371 IsSingle ?
"'" :
"\"");
2374 bool Escaped =
false;
2375 for (
size_t i = 1; i < Input.size() - 1; i++) {
2378 if (!Escaped && i + 1 < Input.size() &&
2379 ((IsSingle && Input[i + 1] ==
'"') ||
2380 (!IsSingle && Input[i + 1] ==
'\''))) {
2383 Replace(Start.getLocWithOffset(i), 1,
"");
2390 if (!Escaped && IsSingle == (Input[i] ==
'\'')) {
2392 Replace(Start.getLocWithOffset(i), 0,
"\\");
2406class Formatter :
public TokenAnalyzer {
2409 FormattingAttemptStatus *Status)
2410 : TokenAnalyzer(
Env, Style), Status(Status) {}
2412 std::pair<tooling::Replacements, unsigned>
2413 analyze(TokenAnnotator &Annotator,
2414 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2415 FormatTokenLexer &Tokens)
override {
2416 tooling::Replacements Result;
2417 deriveLocalStyle(AnnotatedLines);
2418 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2419 for (AnnotatedLine *Line : AnnotatedLines)
2420 Annotator.calculateFormattingInformation(*Line);
2421 Annotator.setCommentLineLevels(AnnotatedLines);
2423 WhitespaceManager Whitespaces(
2424 Env.getSourceManager(), Style,
2426 ? WhitespaceManager::inputUsesCRLF(
2427 Env.getSourceManager().getBufferData(
Env.getFileID()),
2428 Style.
LineEnding == FormatStyle::LE_DeriveCRLF)
2430 ContinuationIndenter
Indenter(Style, Tokens.getKeywords(),
2431 Env.getSourceManager(), Whitespaces, Encoding,
2432 BinPackInconclusiveFunctions);
2434 UnwrappedLineFormatter(&
Indenter, &Whitespaces, Style,
2435 Tokens.getKeywords(),
Env.getSourceManager(),
2437 .format(AnnotatedLines,
false,
2440 Env.getFirstStartColumn(),
2441 Env.getNextStartColumn(),
2442 Env.getLastStartColumn());
2443 for (
const auto &R : Whitespaces.generateReplacements())
2445 return std::make_pair(Result, 0);
2446 return std::make_pair(Result, Penalty);
2451 hasCpp03IncompatibleFormat(
const SmallVectorImpl<AnnotatedLine *> &Lines) {
2452 for (
const AnnotatedLine *Line : Lines) {
2453 if (hasCpp03IncompatibleFormat(Line->Children))
2455 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {
2456 if (!Tok->hasWhitespaceBefore()) {
2457 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
2459 if (Tok->is(TT_TemplateCloser) &&
2460 Tok->Previous->is(TT_TemplateCloser)) {
2469 int countVariableAlignments(
const SmallVectorImpl<AnnotatedLine *> &Lines) {
2470 int AlignmentDiff = 0;
2471 for (
const AnnotatedLine *Line : Lines) {
2472 AlignmentDiff += countVariableAlignments(Line->Children);
2473 for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {
2474 if (Tok->isNot(TT_PointerOrReference))
2477 if (
const auto *Prev = Tok->getPreviousNonComment()) {
2478 if (Prev->is(tok::r_paren) && Prev->MatchingParen) {
2479 if (
const auto *Func =
2480 Prev->MatchingParen->getPreviousNonComment()) {
2481 if (
Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName,
2482 TT_OverloadedOperator)) {
2488 bool SpaceBefore = Tok->hasWhitespaceBefore();
2489 bool SpaceAfter = Tok->Next->hasWhitespaceBefore();
2490 if (SpaceBefore && !SpaceAfter)
2492 if (!SpaceBefore && SpaceAfter)
2496 return AlignmentDiff;
2500 deriveLocalStyle(
const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2501 bool HasBinPackedFunction =
false;
2502 bool HasOnePerLineFunction =
false;
2503 for (AnnotatedLine *Line : AnnotatedLines) {
2504 if (!Line->First->Next)
2506 FormatToken *Tok = Line->First->Next;
2508 if (Tok->is(PPK_BinPacked))
2509 HasBinPackedFunction =
true;
2510 if (Tok->is(PPK_OnePerLine))
2511 HasOnePerLineFunction =
true;
2517 const auto NetRightCount = countVariableAlignments(AnnotatedLines);
2518 if (NetRightCount > 0)
2520 else if (NetRightCount < 0)
2524 if (Style.
Standard == FormatStyle::LS_Auto) {
2525 Style.
Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
2526 ? FormatStyle::LS_Latest
2527 : FormatStyle::LS_Cpp03;
2529 BinPackInconclusiveFunctions =
2530 HasBinPackedFunction || !HasOnePerLineFunction;
2533 bool BinPackInconclusiveFunctions;
2534 FormattingAttemptStatus *Status;
2548class TrailingCommaInserter :
public TokenAnalyzer {
2550 TrailingCommaInserter(
const Environment &
Env,
const FormatStyle &Style)
2551 : TokenAnalyzer(
Env, Style) {}
2553 std::pair<tooling::Replacements, unsigned>
2554 analyze(TokenAnnotator &Annotator,
2555 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2556 FormatTokenLexer &Tokens)
override {
2557 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2558 tooling::Replacements Result;
2559 insertTrailingCommas(AnnotatedLines, Result);
2566 void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,
2567 tooling::Replacements &Result) {
2568 for (AnnotatedLine *Line : Lines) {
2569 insertTrailingCommas(Line->Children, Result);
2570 if (!Line->Affected)
2572 for (FormatToken *FormatTok = Line->First; FormatTok;
2573 FormatTok = FormatTok->Next) {
2574 if (FormatTok->NewlinesBefore == 0)
2576 FormatToken *Matching = FormatTok->MatchingParen;
2577 if (!Matching || !FormatTok->getPreviousNonComment())
2579 if (!(FormatTok->is(tok::r_square) &&
2580 Matching->is(TT_ArrayInitializerLSquare)) &&
2581 !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) {
2584 FormatToken *Prev = FormatTok->getPreviousNonComment();
2585 if (Prev->is(tok::comma) || Prev->is(tok::semi))
2589 SourceLocation Start =
2590 Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size());
2594 unsigned ColumnNumber =
2595 Env.getSourceManager().getSpellingColumnNumber(Start);
2600 cantFail(Result.add(
2601 tooling::Replacement(
Env.getSourceManager(), Start, 0,
",")));
2609class Cleaner :
public TokenAnalyzer {
2612 : TokenAnalyzer(
Env, Style),
2613 DeletedTokens(FormatTokenLess(
Env.getSourceManager())) {}
2616 std::pair<tooling::Replacements, unsigned>
2617 analyze(TokenAnnotator &Annotator,
2618 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2619 FormatTokenLexer &Tokens)
override {
2627 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2629 checkEmptyNamespace(AnnotatedLines);
2631 for (
auto *Line : AnnotatedLines)
2634 return {generateFixes(), 0};
2638 void cleanupLine(AnnotatedLine *Line) {
2639 for (
auto *Child : Line->Children)
2642 if (Line->Affected) {
2643 cleanupRight(Line->First, tok::comma, tok::comma);
2644 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
2645 cleanupRight(Line->First, tok::l_paren, tok::comma);
2646 cleanupLeft(Line->First, tok::comma, tok::r_paren);
2647 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
2648 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
2649 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
2653 bool containsOnlyComments(
const AnnotatedLine &Line) {
2654 for (FormatToken *Tok = Line.First; Tok; Tok = Tok->Next)
2655 if (Tok->isNot(tok::comment))
2661 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2662 std::set<unsigned> DeletedLines;
2663 for (
unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
2664 auto &Line = *AnnotatedLines[i];
2665 if (Line.startsWithNamespace())
2666 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
2669 for (
auto Line : DeletedLines) {
2670 FormatToken *Tok = AnnotatedLines[Line]->First;
2682 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2683 unsigned CurrentLine,
unsigned &
NewLine,
2684 std::set<unsigned> &DeletedLines) {
2685 unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
2690 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
2694 }
else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
2697 while (++CurrentLine < End) {
2698 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
2701 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
2702 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine,
NewLine,
2710 if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
2720 if (CurrentLine >= End)
2724 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
2725 AnnotatedLines[InitLine]->First->Tok.getLocation(),
2726 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) {
2730 for (
unsigned i = InitLine; i <= CurrentLine; ++i)
2731 DeletedLines.insert(i);
2740 template <
typename LeftKind,
typename RightKind>
2741 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
2743 auto NextNotDeleted = [
this](
const FormatToken &Tok) -> FormatToken * {
2744 for (
auto *Res = Tok.Next; Res; Res = Res->Next) {
2745 if (Res->isNot(tok::comment) &&
2746 DeletedTokens.find(Res) == DeletedTokens.end()) {
2752 for (
auto *Left = Start; Left;) {
2753 auto *Right = NextNotDeleted(*Left);
2756 if (Left->is(LK) && Right->is(RK)) {
2757 deleteToken(DeleteLeft ? Left : Right);
2758 for (
auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
2769 template <
typename LeftKind,
typename RightKind>
2770 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
2771 cleanupPair(Start, LK, RK,
true);
2774 template <
typename LeftKind,
typename RightKind>
2775 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
2776 cleanupPair(Start, LK, RK,
false);
2780 inline void deleteToken(FormatToken *Tok) {
2782 DeletedTokens.insert(Tok);
2785 tooling::Replacements generateFixes() {
2786 tooling::Replacements Fixes;
2787 SmallVector<FormatToken *> Tokens;
2788 std::copy(DeletedTokens.begin(), DeletedTokens.end(),
2789 std::back_inserter(Tokens));
2795 while (Idx < Tokens.size()) {
2796 unsigned St = Idx, End = Idx;
2797 while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1])
2799 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
2800 Tokens[End]->Tok.getEndLoc());
2802 Fixes.add(tooling::Replacement(
Env.getSourceManager(), SR,
""));
2806 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
2807 assert(
false &&
"Fixes must not conflict!");
2818 struct FormatTokenLess {
2819 FormatTokenLess(
const SourceManager &
SM) :
SM(
SM) {}
2821 bool operator()(
const FormatToken *LHS,
const FormatToken *RHS)
const {
2822 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
2823 RHS->Tok.getLocation());
2829 std::set<FormatToken *, FormatTokenLess> DeletedTokens;
2832class ObjCHeaderStyleGuesser :
public TokenAnalyzer {
2834 ObjCHeaderStyleGuesser(
const Environment &
Env,
const FormatStyle &Style)
2835 : TokenAnalyzer(
Env, Style), IsObjC(
false) {}
2837 std::pair<tooling::Replacements, unsigned>
2838 analyze(TokenAnnotator &Annotator,
2839 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2840 FormatTokenLexer &Tokens)
override {
2841 assert(Style.
Language == FormatStyle::LK_Cpp);
2842 IsObjC = guessIsObjC(
Env.getSourceManager(), AnnotatedLines,
2843 Tokens.getKeywords());
2844 tooling::Replacements Result;
2848 bool isObjC() {
return IsObjC; }
2852 guessIsObjC(
const SourceManager &SourceManager,
2853 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2854 const AdditionalKeywords &Keywords) {
2856 static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
2871 "FOUNDATION_EXPORT",
2872 "FOUNDATION_EXTERN",
2873 "NSAffineTransform",
2875 "NSAttributedString",
2894 "NSInvocationOperation",
2898 "NSMutableAttributedString",
2899 "NSMutableCharacterSet",
2901 "NSMutableDictionary",
2902 "NSMutableIndexSet",
2903 "NSMutableOrderedSet",
2907 "NSNumberFormatter",
2911 "NSOperationQueuePriority",
2915 "NSQualityOfService",
2918 "NSRegularExpression",
2929 "NS_ASSUME_NONNULL_BEGIN",
2934 for (
auto *Line : AnnotatedLines) {
2935 if (Line->First && (Line->First->TokenText.startswith(
"#") ||
2936 Line->First->TokenText ==
"__pragma" ||
2937 Line->First->TokenText ==
"_Pragma")) {
2940 for (
const FormatToken *FormatTok = Line->First; FormatTok;
2941 FormatTok = FormatTok->Next) {
2942 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
2943 (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
2944 FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
2946 (FormatTok->Tok.isAnyIdentifier() &&
2947 std::binary_search(std::begin(FoundationIdentifiers),
2948 std::end(FoundationIdentifiers),
2949 FormatTok->TokenText)) ||
2950 FormatTok->is(TT_ObjCStringLiteral) ||
2951 FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,
2952 Keywords.kw_NS_ERROR_ENUM,
2953 Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,
2954 TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,
2955 TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,
2957 LLVM_DEBUG(llvm::dbgs()
2958 <<
"Detected ObjC at location "
2959 << FormatTok->Tok.getLocation().printToString(
2961 <<
" token: " << FormatTok->TokenText <<
" token type: "
2965 if (guessIsObjC(SourceManager, Line->Children, Keywords))
2983struct JavaImportDirective {
2996 for (
const auto &Range : Ranges) {
2997 if (Range.getOffset() < End &&
2998 Range.getOffset() + Range.getLength() > Start) {
3012static std::pair<unsigned, unsigned>
3016 unsigned OffsetToEOL = 0;
3017 for (
int i = 0, e = Includes.size(); i != e; ++i) {
3018 unsigned Start = Includes[Indices[i]].Offset;
3019 unsigned End = Start + Includes[Indices[i]].Text.size();
3020 if (!(Cursor >= Start && Cursor < End))
3022 CursorIndex = Indices[i];
3023 OffsetToEOL = End - Cursor;
3026 while (--i >= 0 && Includes[CursorIndex].
Text == Includes[Indices[i]].
Text)
3030 return std::make_pair(CursorIndex, OffsetToEOL);
3035 std::string NewCode;
3036 size_t Pos = 0, LastPos = 0;
3039 Pos = Code.find(
"\r\n", LastPos);
3040 if (Pos == LastPos) {
3044 if (Pos == std::string::npos) {
3045 NewCode += Code.substr(LastPos);
3048 NewCode += Code.substr(LastPos, Pos - LastPos) +
"\n";
3050 }
while (Pos != std::string::npos);
3068 const unsigned IncludesBeginOffset = Includes.front().Offset;
3069 const unsigned IncludesEndOffset =
3070 Includes.back().Offset + Includes.back().Text.size();
3071 const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
3072 if (!
affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
3075 llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size()));
3078 llvm::stable_sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
3079 const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
3080 const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
3081 return std::tie(Includes[LHSI].
Priority, LHSFilenameLower,
3083 std::tie(Includes[RHSI].
Priority, RHSFilenameLower,
3087 llvm::stable_sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
3095 unsigned CursorIndex;
3097 unsigned CursorToEOLOffset;
3099 std::tie(CursorIndex, CursorToEOLOffset) =
3104 Indices.erase(std::unique(Indices.begin(), Indices.end(),
3105 [&](
unsigned LHSI,
unsigned RHSI) {
3106 return Includes[LHSI].Text.trim() ==
3107 Includes[RHSI].Text.trim();
3111 int CurrentCategory = Includes.front().Category;
3119 if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) &&
3125 for (
unsigned Index : Indices) {
3126 if (!result.empty()) {
3130 CurrentCategory != Includes[Index].Category) {
3134 result += Includes[Index].Text;
3135 if (Cursor && CursorIndex == Index)
3136 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
3137 CurrentCategory = Includes[Index].Category;
3140 if (Cursor && *Cursor >= IncludesEndOffset)
3141 *Cursor += result.size() - IncludesBlockSize;
3146 IncludesBeginOffset, IncludesBlockSize)))) {
3151 FileName, Includes.front().Offset, IncludesBlockSize, result));
3155 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
3165 unsigned Prev = llvm::StringSwitch<size_t>(Code)
3166 .StartsWith(
"\xEF\xBB\xBF", 3)
3168 unsigned SearchFrom = 0;
3180 bool FirstIncludeBlock =
true;
3181 bool MainIncludeFound =
false;
3182 bool FormattingOff =
false;
3185 llvm::Regex RawStringRegex(
3186 "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\(");
3188 std::string RawStringTermination =
")\"";
3191 auto Pos = Code.find(
'\n', SearchFrom);
3193 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3195 StringRef Trimmed =
Line.trim();
3200 if (RawStringRegex.match(Trimmed, &RawStringMatches)) {
3201 std::string CharSequence = RawStringMatches[1].str();
3202 RawStringTermination =
")" + CharSequence +
"\"";
3203 FormattingOff =
true;
3206 if (Trimmed.contains(RawStringTermination))
3207 FormattingOff =
false;
3210 FormattingOff =
true;
3212 FormattingOff =
false;
3214 const bool EmptyLineSkipped =
3220 bool MergeWithNextLine = Trimmed.endswith(
"\\");
3221 if (!FormattingOff && !MergeWithNextLine) {
3223 StringRef IncludeName = Matches[2];
3224 if (
Line.contains(
"/*") && !
Line.contains(
"*/")) {
3229 Pos = Code.find(
"*/", SearchFrom);
3231 Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev);
3235 !MainIncludeFound && FirstIncludeBlock);
3237 IncludeName, !MainIncludeFound && FirstIncludeBlock);
3239 MainIncludeFound =
true;
3240 IncludesInBlock.push_back(
3242 }
else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
3245 IncludesInBlock.clear();
3246 if (Trimmed.startswith(
"#pragma hdrstop"))
3247 FirstIncludeBlock =
true;
3249 FirstIncludeBlock =
false;
3252 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3255 if (!MergeWithNextLine)
3257 SearchFrom = Pos + 1;
3259 if (!IncludesInBlock.empty()) {
3269 StringRef ImportIdentifier) {
3270 unsigned LongestMatchIndex =
UINT_MAX;
3271 unsigned LongestMatchLength = 0;
3274 if (ImportIdentifier.startswith(GroupPrefix) &&
3275 GroupPrefix.length() > LongestMatchLength) {
3276 LongestMatchIndex = I;
3277 LongestMatchLength = GroupPrefix.length();
3280 return LongestMatchIndex;
3292 unsigned ImportsBeginOffset = Imports.front().Offset;
3293 unsigned ImportsEndOffset =
3294 Imports.back().Offset + Imports.back().Text.size();
3295 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;
3296 if (!
affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))
3300 llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size()));
3303 for (
const JavaImportDirective &Import : Imports)
3306 bool StaticImportAfterNormalImport =
3308 llvm::sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
3310 return std::make_tuple(!Imports[LHSI].
IsStatic ^
3311 StaticImportAfterNormalImport,
3313 std::make_tuple(!Imports[RHSI].
IsStatic ^
3314 StaticImportAfterNormalImport,
3319 Indices.erase(std::unique(Indices.begin(), Indices.end(),
3320 [&](
unsigned LHSI,
unsigned RHSI) {
3321 return Imports[LHSI].Text == Imports[RHSI].Text;
3325 bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
3329 for (
unsigned Index : Indices) {
3330 if (!result.empty()) {
3332 if (CurrentIsStatic != Imports[Index].
IsStatic ||
3338 result += CommentLine;
3341 result += Imports[Index].Text;
3342 CurrentIsStatic = Imports[Index].IsStatic;
3349 Imports.front().Offset, ImportsBlockSize)))) {
3354 ImportsBlockSize, result));
3358 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
3365const char JavaImportRegexPattern[] =
3366 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;";
3375 unsigned SearchFrom = 0;
3376 llvm::Regex ImportRegex(JavaImportRegexPattern);
3381 bool FormattingOff =
false;
3384 auto Pos = Code.find(
'\n', SearchFrom);
3386 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3388 StringRef Trimmed =
Line.trim();
3390 FormattingOff =
true;
3392 FormattingOff =
false;
3394 if (ImportRegex.match(
Line, &Matches)) {
3395 if (FormattingOff) {
3400 StringRef
Static = Matches[1];
3403 if (
Static.contains(
"static"))
3405 ImportsInBlock.push_back(
3408 }
else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) {
3413 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3415 SearchFrom = Pos + 1;
3417 if (!ImportsInBlock.empty())
3426 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
3429bool isLikelyXml(StringRef Code) {
return Code.ltrim().startswith(
"<"); }
3433 StringRef
FileName,
unsigned *Cursor) {
3451template <
typename T>
3456 if (Replaces.
empty())
3459 auto NewCode = applyAllReplacements(Code, Replaces);
3461 return NewCode.takeError();
3466 ProcessFunc(Style, *NewCode, ChangedRanges,
FileName);
3468 return Replaces.
merge(FormatReplaces);
3477 std::vector<tooling::Range> Ranges,
3481 auto SortedReplaces =
3483 if (!SortedReplaces)
3484 return SortedReplaces.takeError();
3488 auto Reformat = [](
const FormatStyle &Style, StringRef Code,
3489 std::vector<tooling::Range> Ranges,
3504inline bool isHeaderDeletion(
const tooling::Replacement &Replace) {
3505 return Replace.getOffset() ==
UINT_MAX && Replace.getLength() == 1;
3509tooling::Replacements
3510fixCppIncludeInsertions(StringRef Code,
const tooling::Replacements &Replaces,
3515 tooling::Replacements HeaderInsertions;
3516 std::set<llvm::StringRef> HeadersToDelete;
3517 tooling::Replacements
Result;
3518 for (
const auto &R : Replaces) {
3519 if (isHeaderInsertion(R)) {
3522 llvm::consumeError(HeaderInsertions.add(R));
3523 }
else if (isHeaderDeletion(R)) {
3524 HeadersToDelete.insert(R.getReplacementText());
3525 }
else if (R.getOffset() ==
UINT_MAX) {
3526 llvm::errs() <<
"Insertions other than header #include insertion are "
3528 << R.getReplacementText() <<
"\n";
3530 llvm::consumeError(
Result.add(R));
3533 if (HeaderInsertions.empty() && HeadersToDelete.empty())
3536 StringRef
FileName = Replaces.begin()->getFilePath();
3539 for (
const auto &Header : HeadersToDelete) {
3540 tooling::Replacements Replaces =
3541 Includes.remove(Header.trim(
"\"<>"), Header.startswith(
"<"));
3542 for (
const auto &R : Replaces) {
3543 auto Err =
Result.add(R);
3546 llvm::errs() <<
"Failed to add header deletion replacement for "
3547 << Header <<
": " << llvm::toString(std::move(Err))
3554 for (
const auto &R : HeaderInsertions) {
3558 assert(Matched &&
"Header insertion replacement must have replacement text "
3561 auto IncludeName = Matches[2];
3563 Includes.insert(IncludeName.trim(
"\"<>"), IncludeName.startswith(
"<"),
3566 auto Err =
Result.add(*Replace);
3568 llvm::consumeError(std::move(Err));
3569 unsigned NewOffset =
3570 Result.getShiftedCodePosition(Replace->getOffset());
3571 auto Shifted = tooling::Replacement(
FileName, NewOffset, 0,
3572 Replace->getReplacementText());
3587 auto Cleanup = [](
const FormatStyle &Style, StringRef Code,
3588 std::vector<tooling::Range> Ranges,
3594 fixCppIncludeInsertions(Code, Replaces, Style);
3599std::pair<tooling::Replacements, unsigned>
3602 unsigned NextStartColumn,
unsigned LastStartColumn, StringRef FileName,
3613 case FormatStyle::RCPS_SingleLine:
3614 case FormatStyle::RCPS_WithPreceding:
3630 std::vector<tooling::Range> Ranges(1,
tooling::Range(0, Code.size()));
3631 auto Env = Environment::make(Code,
FileName, Ranges, FirstStartColumn,
3632 NextStartColumn, LastStartColumn);
3637 Formatter(*
Env, Style, Status).process().first;
3639 Replaces = Replaces.
merge(
3642 if (applyAllReplacements(Code, Replaces))
3643 return {Replaces, 0};
3647 auto Env = Environment::make(Code,
FileName, Ranges, FirstStartColumn,
3648 NextStartColumn, LastStartColumn);
3652 typedef std::function<std::pair<tooling::Replacements, unsigned>(
3662 if (Style.
isCpp()) {
3669 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3670 return ParensRemover(
Env, S).process(
true);
3676 S.InsertBraces =
true;
3677 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3678 return BracesInserter(
Env, S).process(
true);
3684 S.RemoveBracesLLVM =
true;
3685 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3686 return BracesRemover(
Env, S).process(
true);
3692 S.RemoveSemicolon =
true;
3693 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3694 return SemiRemover(
Env, S).process(
true);
3717 if (Style.
Language == FormatStyle::LK_ObjC &&
3727 return JavaScriptRequoter(
Env, Expanded).process(
true);
3732 return Formatter(
Env, Expanded, Status).process();
3738 return TrailingCommaInserter(
Env, Expanded).process();
3742 std::optional<std::string> CurrentCode;
3744 unsigned Penalty = 0;
3745 for (
size_t I = 0, E = Passes.size(); I < E; ++I) {
3746 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
3747 auto NewCode = applyAllReplacements(
3748 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
3750 Fixes = Fixes.
merge(PassFixes.first);
3751 Penalty += PassFixes.second;
3753 CurrentCode = std::move(*NewCode);
3754 Env = Environment::make(
3756 tooling::calculateRangesAfterReplacements(Fixes, Ranges),
3757 FirstStartColumn, NextStartColumn, LastStartColumn);
3770 StringRef OriginalCode = Code.substr(Fix.getOffset(), Fix.getLength());
3771 if (!OriginalCode.equals(Fix.getReplacementText())) {
3772 auto Err = NonNoOpFixes.
add(Fix);
3774 llvm::errs() <<
"Error adding replacements : "
3775 << llvm::toString(std::move(Err)) <<
"\n";
3779 Fixes = std::move(NonNoOpFixes);
3782 return {Fixes, Penalty};
3806 return Cleaner(*
Env, Style).process().first;
3811 StringRef
FileName,
bool *IncompleteFormat) {
3814 if (!Status.FormatComplete)
3815 *IncompleteFormat =
true;
3847 LangOpts.CPlusPlus = 1;
3858 LangOpts.LineComment = 1;
3859 bool AlternativeOperators = Style.
isCpp();
3860 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
3863 LangOpts.MicrosoftExt = 1;
3864 LangOpts.DeclSpecKeyword = 1;
3870 "Set coding style. <string> can be:\n"
3871 "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"
3872 " Mozilla, WebKit.\n"
3873 "2. 'file' to load style configuration from a\n"
3874 " .clang-format file in one of the parent directories\n"
3875 " of the source file (for stdin, see --assume-filename).\n"
3876 " If no .clang-format file is found, falls back to\n"
3877 " --fallback-style.\n"
3878 " --style=file is the default.\n"
3879 "3. 'file:<format_file_path>' to explicitly specify\n"
3880 " the configuration file.\n"
3881 "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n"
3882 " --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
3887 if (
FileName.ends_with_insensitive(
".js") ||
3888 FileName.ends_with_insensitive(
".mjs") ||
3889 FileName.ends_with_insensitive(
".ts")) {
3894 if (
FileName.ends_with_insensitive(
".proto") ||
3895 FileName.ends_with_insensitive(
".protodevel")) {
3898 if (
FileName.ends_with_insensitive(
".textpb") ||
3899 FileName.ends_with_insensitive(
".pb.txt") ||
3900 FileName.ends_with_insensitive(
".textproto") ||
3901 FileName.ends_with_insensitive(
".asciipb")) {
3904 if (
FileName.ends_with_insensitive(
".td"))
3906 if (
FileName.ends_with_insensitive(
".cs"))
3908 if (
FileName.ends_with_insensitive(
".json"))
3910 if (
FileName.ends_with_insensitive(
".sv") ||
3911 FileName.ends_with_insensitive(
".svh") ||
3912 FileName.ends_with_insensitive(
".v") ||
3913 FileName.ends_with_insensitive(
".vh")) {
3922 auto Extension = llvm::sys::path::extension(
FileName);
3925 if (Extension.empty() || Extension ==
".h") {
3930 if (Guesser.isObjC())
3934 return GuessedLanguage;
3942llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
3945 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
3946 FS->getBufferForFile(ConfigFile.str());
3947 if (
auto EC =
Text.getError())
3955 StringRef FallbackStyleName,
3956 StringRef Code, llvm::vfs::FileSystem *FS,
3957 bool AllowUnknownOptions) {
3959 FS = llvm::vfs::getRealFileSystem().get();
3967 ChildFormatTextToApply;
3969 if (StyleName.startswith(
"{")) {
3971 StringRef Source =
"<command-line>";
3972 if (std::error_code ec =
3974 AllowUnknownOptions)) {
3978 ChildFormatTextToApply.emplace_back(
3979 llvm::MemoryBuffer::getMemBuffer(StyleName, Source,
false));
3987 StyleName.starts_with_insensitive(
"file:")) {
3988 auto ConfigFile = StyleName.substr(5);
3989 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
3991 if (
auto EC =
Text.getError()) {
3996 LLVM_DEBUG(llvm::dbgs()
3997 <<
"Using configuration file " << ConfigFile <<
"\n");
4005 ChildFormatTextToApply.emplace_back(std::move(*
Text));
4024 if (std::error_code EC = FS->makeAbsolute(Path))
4028 FilesToLookFor.push_back(
".clang-format");
4029 FilesToLookFor.push_back(
"_clang-format");
4031 auto dropDiagnosticHandler = [](
const llvm::SMDiagnostic &,
void *) {};
4033 auto applyChildFormatTexts = [&](
FormatStyle *Style) {
4034 for (
const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) {
4036 dropDiagnosticHandler);
4039 static_cast<void>(EC);
4043 for (StringRef Directory = Path; !Directory.empty();
4044 Directory = llvm::sys::path::parent_path(Directory)) {
4046 auto Status = FS->status(Directory);
4048 Status->getType() != llvm::sys::fs::file_type::directory_file) {
4052 for (
const auto &F : FilesToLookFor) {
4055 llvm::sys::path::append(ConfigFile, F);
4056 LLVM_DEBUG(llvm::dbgs() <<
"Trying " << ConfigFile <<
"...\n");
4058 Status = FS->status(ConfigFile.str());
4061 (Status->getType() == llvm::sys::fs::file_type::regular_file)) {
4062 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
4064 if (
auto EC =
Text.getError()) {
4066 if (!UnsuitableConfigFiles.empty())
4067 UnsuitableConfigFiles.append(
", ");
4068 UnsuitableConfigFiles.append(ConfigFile);
4074 LLVM_DEBUG(llvm::dbgs()
4075 <<
"Using configuration file " << ConfigFile <<
"\n");
4078 if (ChildFormatTextToApply.empty())
4081 LLVM_DEBUG(llvm::dbgs() <<
"Applying child configurations\n");
4082 applyChildFormatTexts(&Style);
4087 LLVM_DEBUG(llvm::dbgs() <<
"Inherits parent configuration\n");
4092 ChildFormatTextToApply.emplace_back(std::move(*
Text));
4102 if (!UnsuitableConfigFiles.empty()) {
4105 UnsuitableConfigFiles);
4108 if (!ChildFormatTextToApply.empty()) {
4109 LLVM_DEBUG(llvm::dbgs()
4110 <<
"Applying child configurations on fallback style\n");
4111 applyChildFormatTexts(&FallbackStyle);
4114 return FallbackStyle;
4118 if (Comment == (On ?
"/* clang-format on */" :
"/* clang-format off */"))
4121 static const char ClangFormatOn[] =
"// clang-format on";
4122 static const char ClangFormatOff[] =
"// clang-format off";
4123 const unsigned Size = (On ?
sizeof ClangFormatOn :
sizeof ClangFormatOff) - 1;
4125 return Comment.startswith(On ? ClangFormatOn : ClangFormatOff) &&
4126 (Comment.size() == Size || Comment[Size] ==
':');
AffectedRangeManager class manages affected ranges in the code.
Defines the Diagnostic-related interfaces.
Declares BreakableToken, BreakableStringLiteral, BreakableComment, BreakableBlockComment and Breakabl...
This file implements an indenter that manages the indentation of continuations.
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.
Defines the SourceManager interface.
This file declares an abstract TokenAnalyzer, and associated helper classes.
This file implements a token annotator, i.e.
This file contains the declaration of the UnwrappedLineParser, which turns a stream of tokens into Un...
This file declares UsingDeclarationsSorter, a TokenAnalyzer that sorts consecutive using declarations...
WhitespaceManager class manages whitespace around tokens and their replacements.
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).
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.