38 #include "llvm/ADT/STLExtras.h"
39 #include "llvm/ADT/Sequence.h"
40 #include "llvm/ADT/StringRef.h"
41 #include "llvm/Support/Allocator.h"
42 #include "llvm/Support/Debug.h"
43 #include "llvm/Support/Path.h"
44 #include "llvm/Support/Regex.h"
45 #include "llvm/Support/VirtualFileSystem.h"
46 #include "llvm/Support/YAMLTraits.h"
52 #include <unordered_map>
54 #define DEBUG_TYPE "format-formatter"
62 template <>
struct MappingTraits<
FormatStyle::AlignConsecutiveStyle> {
64 IO.enumCase(
Value,
"None",
65 FormatStyle::AlignConsecutiveStyle(
69 IO.enumCase(
Value,
"Consecutive",
70 FormatStyle::AlignConsecutiveStyle(
74 IO.enumCase(
Value,
"AcrossEmptyLines",
75 FormatStyle::AlignConsecutiveStyle(
79 IO.enumCase(
Value,
"AcrossComments",
80 FormatStyle::AlignConsecutiveStyle({
true,
85 IO.enumCase(
Value,
"AcrossEmptyLinesAndComments",
86 FormatStyle::AlignConsecutiveStyle({
true,
93 IO.enumCase(
Value,
"true",
94 FormatStyle::AlignConsecutiveStyle(
98 IO.enumCase(
Value,
"false",
99 FormatStyle::AlignConsecutiveStyle(
105 static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &
Value) {
106 IO.mapOptional(
"Enabled",
Value.Enabled);
107 IO.mapOptional(
"AcrossEmptyLines",
Value.AcrossEmptyLines);
108 IO.mapOptional(
"AcrossComments",
Value.AcrossComments);
109 IO.mapOptional(
"AlignCompound",
Value.AlignCompound);
110 IO.mapOptional(
"PadOperators",
Value.PadOperators);
115 struct ScalarEnumerationTraits<
FormatStyle::AttributeBreakingStyle> {
117 IO.enumCase(
Value,
"Always", FormatStyle::ABS_Always);
118 IO.enumCase(
Value,
"Leave", FormatStyle::ABS_Leave);
119 IO.enumCase(
Value,
"Never", FormatStyle::ABS_Never);
124 struct ScalarEnumerationTraits<
FormatStyle::ArrayInitializerAlignmentStyle> {
126 FormatStyle::ArrayInitializerAlignmentStyle &
Value) {
127 IO.enumCase(
Value,
"None", FormatStyle::AIAS_None);
128 IO.enumCase(
Value,
"Left", FormatStyle::AIAS_Left);
129 IO.enumCase(
Value,
"Right", FormatStyle::AIAS_Right);
133 template <>
struct ScalarEnumerationTraits<
FormatStyle::BinaryOperatorStyle> {
135 IO.enumCase(
Value,
"All", FormatStyle::BOS_All);
136 IO.enumCase(
Value,
"true", FormatStyle::BOS_All);
137 IO.enumCase(
Value,
"None", FormatStyle::BOS_None);
138 IO.enumCase(
Value,
"false", FormatStyle::BOS_None);
139 IO.enumCase(
Value,
"NonAssignment", FormatStyle::BOS_NonAssignment);
143 template <>
struct ScalarEnumerationTraits<
FormatStyle::BinPackStyle> {
145 IO.enumCase(
Value,
"Auto", FormatStyle::BPS_Auto);
146 IO.enumCase(
Value,
"Always", FormatStyle::BPS_Always);
147 IO.enumCase(
Value,
"Never", FormatStyle::BPS_Never);
152 struct ScalarEnumerationTraits<
FormatStyle::BitFieldColonSpacingStyle> {
154 FormatStyle::BitFieldColonSpacingStyle &
Value) {
155 IO.enumCase(
Value,
"Both", FormatStyle::BFCS_Both);
156 IO.enumCase(
Value,
"None", FormatStyle::BFCS_None);
157 IO.enumCase(
Value,
"Before", FormatStyle::BFCS_Before);
158 IO.enumCase(
Value,
"After", FormatStyle::BFCS_After);
162 template <>
struct ScalarEnumerationTraits<
FormatStyle::BraceBreakingStyle> {
164 IO.enumCase(
Value,
"Attach", FormatStyle::BS_Attach);
165 IO.enumCase(
Value,
"Linux", FormatStyle::BS_Linux);
166 IO.enumCase(
Value,
"Mozilla", FormatStyle::BS_Mozilla);
167 IO.enumCase(
Value,
"Stroustrup", FormatStyle::BS_Stroustrup);
168 IO.enumCase(
Value,
"Allman", FormatStyle::BS_Allman);
169 IO.enumCase(
Value,
"Whitesmiths", FormatStyle::BS_Whitesmiths);
170 IO.enumCase(
Value,
"GNU", FormatStyle::BS_GNU);
171 IO.enumCase(
Value,
"WebKit", FormatStyle::BS_WebKit);
172 IO.enumCase(
Value,
"Custom", FormatStyle::BS_Custom);
176 template <>
struct MappingTraits<
FormatStyle::BraceWrappingFlags> {
177 static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
178 IO.mapOptional(
"AfterCaseLabel", Wrapping.AfterCaseLabel);
179 IO.mapOptional(
"AfterClass", Wrapping.AfterClass);
180 IO.mapOptional(
"AfterControlStatement", Wrapping.AfterControlStatement);
181 IO.mapOptional(
"AfterEnum", Wrapping.AfterEnum);
182 IO.mapOptional(
"AfterExternBlock", Wrapping.AfterExternBlock);
183 IO.mapOptional(
"AfterFunction", Wrapping.AfterFunction);
184 IO.mapOptional(
"AfterNamespace", Wrapping.AfterNamespace);
185 IO.mapOptional(
"AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
186 IO.mapOptional(
"AfterStruct", Wrapping.AfterStruct);
187 IO.mapOptional(
"AfterUnion", Wrapping.AfterUnion);
188 IO.mapOptional(
"BeforeCatch", Wrapping.BeforeCatch);
189 IO.mapOptional(
"BeforeElse", Wrapping.BeforeElse);
190 IO.mapOptional(
"BeforeLambdaBody", Wrapping.BeforeLambdaBody);
191 IO.mapOptional(
"BeforeWhile", Wrapping.BeforeWhile);
192 IO.mapOptional(
"IndentBraces", Wrapping.IndentBraces);
193 IO.mapOptional(
"SplitEmptyFunction", Wrapping.SplitEmptyFunction);
194 IO.mapOptional(
"SplitEmptyRecord", Wrapping.SplitEmptyRecord);
195 IO.mapOptional(
"SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
199 template <>
struct ScalarEnumerationTraits<
FormatStyle::BracketAlignmentStyle> {
201 IO.enumCase(
Value,
"Align", FormatStyle::BAS_Align);
202 IO.enumCase(
Value,
"DontAlign", FormatStyle::BAS_DontAlign);
203 IO.enumCase(
Value,
"AlwaysBreak", FormatStyle::BAS_AlwaysBreak);
204 IO.enumCase(
Value,
"BlockIndent", FormatStyle::BAS_BlockIndent);
207 IO.enumCase(
Value,
"true", FormatStyle::BAS_Align);
208 IO.enumCase(
Value,
"false", FormatStyle::BAS_DontAlign);
213 struct ScalarEnumerationTraits<
214 FormatStyle::BraceWrappingAfterControlStatementStyle> {
217 FormatStyle::BraceWrappingAfterControlStatementStyle &
Value) {
218 IO.enumCase(
Value,
"Never", FormatStyle::BWACS_Never);
219 IO.enumCase(
Value,
"MultiLine", FormatStyle::BWACS_MultiLine);
220 IO.enumCase(
Value,
"Always", FormatStyle::BWACS_Always);
223 IO.enumCase(
Value,
"false", FormatStyle::BWACS_Never);
224 IO.enumCase(
Value,
"true", FormatStyle::BWACS_Always);
229 struct ScalarEnumerationTraits<
230 FormatStyle::BreakBeforeConceptDeclarationsStyle> {
233 IO.enumCase(
Value,
"Never", FormatStyle::BBCDS_Never);
234 IO.enumCase(
Value,
"Allowed", FormatStyle::BBCDS_Allowed);
235 IO.enumCase(
Value,
"Always", FormatStyle::BBCDS_Always);
238 IO.enumCase(
Value,
"true", FormatStyle::BBCDS_Always);
239 IO.enumCase(
Value,
"false", FormatStyle::BBCDS_Allowed);
244 struct ScalarEnumerationTraits<
FormatStyle::BreakBeforeInlineASMColonStyle> {
246 FormatStyle::BreakBeforeInlineASMColonStyle &
Value) {
247 IO.enumCase(
Value,
"Never", FormatStyle::BBIAS_Never);
248 IO.enumCase(
Value,
"OnlyMultiline", FormatStyle::BBIAS_OnlyMultiline);
249 IO.enumCase(
Value,
"Always", FormatStyle::BBIAS_Always);
253 struct ScalarEnumerationTraits<
FormatStyle::BreakConstructorInitializersStyle> {
256 IO.enumCase(
Value,
"BeforeColon", FormatStyle::BCIS_BeforeColon);
257 IO.enumCase(
Value,
"BeforeComma", FormatStyle::BCIS_BeforeComma);
258 IO.enumCase(
Value,
"AfterColon", FormatStyle::BCIS_AfterColon);
263 struct ScalarEnumerationTraits<
FormatStyle::BreakInheritanceListStyle> {
265 FormatStyle::BreakInheritanceListStyle &
Value) {
266 IO.enumCase(
Value,
"BeforeColon", FormatStyle::BILS_BeforeColon);
267 IO.enumCase(
Value,
"BeforeComma", FormatStyle::BILS_BeforeComma);
268 IO.enumCase(
Value,
"AfterColon", FormatStyle::BILS_AfterColon);
269 IO.enumCase(
Value,
"AfterComma", FormatStyle::BILS_AfterComma);
274 struct ScalarEnumerationTraits<
FormatStyle::BreakTemplateDeclarationsStyle> {
276 FormatStyle::BreakTemplateDeclarationsStyle &
Value) {
277 IO.enumCase(
Value,
"No", FormatStyle::BTDS_No);
278 IO.enumCase(
Value,
"MultiLine", FormatStyle::BTDS_MultiLine);
279 IO.enumCase(
Value,
"Yes", FormatStyle::BTDS_Yes);
282 IO.enumCase(
Value,
"false", FormatStyle::BTDS_MultiLine);
283 IO.enumCase(
Value,
"true", FormatStyle::BTDS_Yes);
288 struct ScalarEnumerationTraits<
FormatStyle::DefinitionReturnTypeBreakingStyle> {
291 IO.enumCase(
Value,
"None", FormatStyle::DRTBS_None);
292 IO.enumCase(
Value,
"All", FormatStyle::DRTBS_All);
293 IO.enumCase(
Value,
"TopLevel", FormatStyle::DRTBS_TopLevel);
296 IO.enumCase(
Value,
"false", FormatStyle::DRTBS_None);
297 IO.enumCase(
Value,
"true", FormatStyle::DRTBS_All);
302 struct ScalarEnumerationTraits<
FormatStyle::EscapedNewlineAlignmentStyle> {
304 FormatStyle::EscapedNewlineAlignmentStyle &
Value) {
305 IO.enumCase(
Value,
"DontAlign", FormatStyle::ENAS_DontAlign);
306 IO.enumCase(
Value,
"Left", FormatStyle::ENAS_Left);
307 IO.enumCase(
Value,
"Right", FormatStyle::ENAS_Right);
310 IO.enumCase(
Value,
"true", FormatStyle::ENAS_Left);
311 IO.enumCase(
Value,
"false", FormatStyle::ENAS_Right);
316 struct ScalarEnumerationTraits<
FormatStyle::EmptyLineAfterAccessModifierStyle> {
319 IO.enumCase(
Value,
"Never", FormatStyle::ELAAMS_Never);
320 IO.enumCase(
Value,
"Leave", FormatStyle::ELAAMS_Leave);
321 IO.enumCase(
Value,
"Always", FormatStyle::ELAAMS_Always);
326 struct ScalarEnumerationTraits<
330 IO.enumCase(
Value,
"Never", FormatStyle::ELBAMS_Never);
331 IO.enumCase(
Value,
"Leave", FormatStyle::ELBAMS_Leave);
332 IO.enumCase(
Value,
"LogicalBlock", FormatStyle::ELBAMS_LogicalBlock);
333 IO.enumCase(
Value,
"Always", FormatStyle::ELBAMS_Always);
338 struct ScalarEnumerationTraits<
FormatStyle::IndentExternBlockStyle> {
340 IO.enumCase(
Value,
"AfterExternBlock", FormatStyle::IEBS_AfterExternBlock);
341 IO.enumCase(
Value,
"Indent", FormatStyle::IEBS_Indent);
342 IO.enumCase(
Value,
"NoIndent", FormatStyle::IEBS_NoIndent);
343 IO.enumCase(
Value,
"true", FormatStyle::IEBS_Indent);
344 IO.enumCase(
Value,
"false", FormatStyle::IEBS_NoIndent);
348 template <>
struct MappingTraits<
FormatStyle::IntegerLiteralSeparatorStyle> {
349 static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &
Base) {
350 IO.mapOptional(
"Binary",
Base.Binary);
351 IO.mapOptional(
"Decimal",
Base.Decimal);
352 IO.mapOptional(
"Hex",
Base.Hex);
356 template <>
struct ScalarEnumerationTraits<
FormatStyle::JavaScriptQuoteStyle> {
358 IO.enumCase(
Value,
"Leave", FormatStyle::JSQS_Leave);
359 IO.enumCase(
Value,
"Single", FormatStyle::JSQS_Single);
360 IO.enumCase(
Value,
"Double", FormatStyle::JSQS_Double);
364 template <>
struct ScalarEnumerationTraits<
FormatStyle::LanguageKind> {
366 IO.enumCase(
Value,
"Cpp", FormatStyle::LK_Cpp);
367 IO.enumCase(
Value,
"Java", FormatStyle::LK_Java);
368 IO.enumCase(
Value,
"JavaScript", FormatStyle::LK_JavaScript);
369 IO.enumCase(
Value,
"ObjC", FormatStyle::LK_ObjC);
370 IO.enumCase(
Value,
"Proto", FormatStyle::LK_Proto);
371 IO.enumCase(
Value,
"TableGen", FormatStyle::LK_TableGen);
372 IO.enumCase(
Value,
"TextProto", FormatStyle::LK_TextProto);
373 IO.enumCase(
Value,
"CSharp", FormatStyle::LK_CSharp);
374 IO.enumCase(
Value,
"Json", FormatStyle::LK_Json);
378 template <>
struct ScalarEnumerationTraits<
FormatStyle::LanguageStandard> {
380 IO.enumCase(
Value,
"c++03", FormatStyle::LS_Cpp03);
381 IO.enumCase(
Value,
"C++03", FormatStyle::LS_Cpp03);
382 IO.enumCase(
Value,
"Cpp03", FormatStyle::LS_Cpp03);
384 IO.enumCase(
Value,
"c++11", FormatStyle::LS_Cpp11);
385 IO.enumCase(
Value,
"C++11", FormatStyle::LS_Cpp11);
387 IO.enumCase(
Value,
"c++14", FormatStyle::LS_Cpp14);
388 IO.enumCase(
Value,
"c++17", FormatStyle::LS_Cpp17);
389 IO.enumCase(
Value,
"c++20", FormatStyle::LS_Cpp20);
391 IO.enumCase(
Value,
"Latest", FormatStyle::LS_Latest);
392 IO.enumCase(
Value,
"Cpp11", FormatStyle::LS_Latest);
393 IO.enumCase(
Value,
"Auto", FormatStyle::LS_Auto);
398 struct ScalarEnumerationTraits<
FormatStyle::LambdaBodyIndentationKind> {
400 FormatStyle::LambdaBodyIndentationKind &
Value) {
401 IO.enumCase(
Value,
"Signature", FormatStyle::LBI_Signature);
402 IO.enumCase(
Value,
"OuterScope", FormatStyle::LBI_OuterScope);
406 template <>
struct ScalarEnumerationTraits<
FormatStyle::LineEndingStyle> {
408 IO.enumCase(
Value,
"LF", FormatStyle::LE_LF);
409 IO.enumCase(
Value,
"CRLF", FormatStyle::LE_CRLF);
410 IO.enumCase(
Value,
"DeriveLF", FormatStyle::LE_DeriveLF);
411 IO.enumCase(
Value,
"DeriveCRLF", FormatStyle::LE_DeriveCRLF);
416 struct ScalarEnumerationTraits<
FormatStyle::NamespaceIndentationKind> {
418 FormatStyle::NamespaceIndentationKind &
Value) {
419 IO.enumCase(
Value,
"None", FormatStyle::NI_None);
420 IO.enumCase(
Value,
"Inner", FormatStyle::NI_Inner);
421 IO.enumCase(
Value,
"All", FormatStyle::NI_All);
425 template <>
struct ScalarEnumerationTraits<
FormatStyle::OperandAlignmentStyle> {
427 IO.enumCase(
Value,
"DontAlign", FormatStyle::OAS_DontAlign);
428 IO.enumCase(
Value,
"Align", FormatStyle::OAS_Align);
429 IO.enumCase(
Value,
"AlignAfterOperator",
430 FormatStyle::OAS_AlignAfterOperator);
433 IO.enumCase(
Value,
"true", FormatStyle::OAS_Align);
434 IO.enumCase(
Value,
"false", FormatStyle::OAS_DontAlign);
439 struct ScalarEnumerationTraits<
FormatStyle::PackConstructorInitializersStyle> {
442 IO.enumCase(
Value,
"Never", FormatStyle::PCIS_Never);
443 IO.enumCase(
Value,
"BinPack", FormatStyle::PCIS_BinPack);
444 IO.enumCase(
Value,
"CurrentLine", FormatStyle::PCIS_CurrentLine);
445 IO.enumCase(
Value,
"NextLine", FormatStyle::PCIS_NextLine);
449 template <>
struct ScalarEnumerationTraits<
FormatStyle::PointerAlignmentStyle> {
451 IO.enumCase(
Value,
"Middle", FormatStyle::PAS_Middle);
452 IO.enumCase(
Value,
"Left", FormatStyle::PAS_Left);
453 IO.enumCase(
Value,
"Right", FormatStyle::PAS_Right);
456 IO.enumCase(
Value,
"true", FormatStyle::PAS_Left);
457 IO.enumCase(
Value,
"false", FormatStyle::PAS_Right);
462 struct ScalarEnumerationTraits<
FormatStyle::PPDirectiveIndentStyle> {
464 IO.enumCase(
Value,
"None", FormatStyle::PPDIS_None);
465 IO.enumCase(
Value,
"AfterHash", FormatStyle::PPDIS_AfterHash);
466 IO.enumCase(
Value,
"BeforeHash", FormatStyle::PPDIS_BeforeHash);
471 struct ScalarEnumerationTraits<
FormatStyle::QualifierAlignmentStyle> {
473 IO.enumCase(
Value,
"Leave", FormatStyle::QAS_Leave);
474 IO.enumCase(
Value,
"Left", FormatStyle::QAS_Left);
475 IO.enumCase(
Value,
"Right", FormatStyle::QAS_Right);
476 IO.enumCase(
Value,
"Custom", FormatStyle::QAS_Custom);
481 static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
482 IO.mapOptional(
"Language", Format.Language);
483 IO.mapOptional(
"Delimiters", Format.Delimiters);
484 IO.mapOptional(
"EnclosingFunctions", Format.EnclosingFunctions);
485 IO.mapOptional(
"CanonicalDelimiter", Format.CanonicalDelimiter);
486 IO.mapOptional(
"BasedOnStyle", Format.BasedOnStyle);
491 struct ScalarEnumerationTraits<
FormatStyle::ReferenceAlignmentStyle> {
493 IO.enumCase(
Value,
"Pointer", FormatStyle::RAS_Pointer);
494 IO.enumCase(
Value,
"Middle", FormatStyle::RAS_Middle);
495 IO.enumCase(
Value,
"Left", FormatStyle::RAS_Left);
496 IO.enumCase(
Value,
"Right", FormatStyle::RAS_Right);
501 struct ScalarEnumerationTraits<
FormatStyle::RequiresClausePositionStyle> {
503 FormatStyle::RequiresClausePositionStyle &
Value) {
504 IO.enumCase(
Value,
"OwnLine", FormatStyle::RCPS_OwnLine);
505 IO.enumCase(
Value,
"WithPreceding", FormatStyle::RCPS_WithPreceding);
506 IO.enumCase(
Value,
"WithFollowing", FormatStyle::RCPS_WithFollowing);
507 IO.enumCase(
Value,
"SingleLine", FormatStyle::RCPS_SingleLine);
512 struct ScalarEnumerationTraits<
FormatStyle::RequiresExpressionIndentationKind> {
515 IO.enumCase(
Value,
"Keyword", FormatStyle::REI_Keyword);
516 IO.enumCase(
Value,
"OuterScope", FormatStyle::REI_OuterScope);
521 struct ScalarEnumerationTraits<
FormatStyle::ReturnTypeBreakingStyle> {
523 IO.enumCase(
Value,
"None", FormatStyle::RTBS_None);
524 IO.enumCase(
Value,
"All", FormatStyle::RTBS_All);
525 IO.enumCase(
Value,
"TopLevel", FormatStyle::RTBS_TopLevel);
526 IO.enumCase(
Value,
"TopLevelDefinitions",
527 FormatStyle::RTBS_TopLevelDefinitions);
528 IO.enumCase(
Value,
"AllDefinitions", FormatStyle::RTBS_AllDefinitions);
533 struct ScalarEnumerationTraits<
FormatStyle::SeparateDefinitionStyle> {
535 IO.enumCase(
Value,
"Leave", FormatStyle::SDS_Leave);
536 IO.enumCase(
Value,
"Always", FormatStyle::SDS_Always);
537 IO.enumCase(
Value,
"Never", FormatStyle::SDS_Never);
541 template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortBlockStyle> {
543 IO.enumCase(
Value,
"Never", FormatStyle::SBS_Never);
544 IO.enumCase(
Value,
"false", FormatStyle::SBS_Never);
545 IO.enumCase(
Value,
"Always", FormatStyle::SBS_Always);
546 IO.enumCase(
Value,
"true", FormatStyle::SBS_Always);
547 IO.enumCase(
Value,
"Empty", FormatStyle::SBS_Empty);
551 template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortFunctionStyle> {
553 IO.enumCase(
Value,
"None", FormatStyle::SFS_None);
554 IO.enumCase(
Value,
"false", FormatStyle::SFS_None);
555 IO.enumCase(
Value,
"All", FormatStyle::SFS_All);
556 IO.enumCase(
Value,
"true", FormatStyle::SFS_All);
557 IO.enumCase(
Value,
"Inline", FormatStyle::SFS_Inline);
558 IO.enumCase(
Value,
"InlineOnly", FormatStyle::SFS_InlineOnly);
559 IO.enumCase(
Value,
"Empty", FormatStyle::SFS_Empty);
563 template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortIfStyle> {
565 IO.enumCase(
Value,
"Never", FormatStyle::SIS_Never);
566 IO.enumCase(
Value,
"WithoutElse", FormatStyle::SIS_WithoutElse);
567 IO.enumCase(
Value,
"OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf);
568 IO.enumCase(
Value,
"AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse);
571 IO.enumCase(
Value,
"Always", FormatStyle::SIS_OnlyFirstIf);
572 IO.enumCase(
Value,
"false", FormatStyle::SIS_Never);
573 IO.enumCase(
Value,
"true", FormatStyle::SIS_WithoutElse);
577 template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortLambdaStyle> {
579 IO.enumCase(
Value,
"None", FormatStyle::SLS_None);
580 IO.enumCase(
Value,
"false", FormatStyle::SLS_None);
581 IO.enumCase(
Value,
"Empty", FormatStyle::SLS_Empty);
582 IO.enumCase(
Value,
"Inline", FormatStyle::SLS_Inline);
583 IO.enumCase(
Value,
"All", FormatStyle::SLS_All);
584 IO.enumCase(
Value,
"true", FormatStyle::SLS_All);
588 template <>
struct ScalarEnumerationTraits<
FormatStyle::SortIncludesOptions> {
590 IO.enumCase(
Value,
"Never", FormatStyle::SI_Never);
591 IO.enumCase(
Value,
"CaseInsensitive", FormatStyle::SI_CaseInsensitive);
592 IO.enumCase(
Value,
"CaseSensitive", FormatStyle::SI_CaseSensitive);
595 IO.enumCase(
Value,
"false", FormatStyle::SI_Never);
596 IO.enumCase(
Value,
"true", FormatStyle::SI_CaseSensitive);
601 struct ScalarEnumerationTraits<
FormatStyle::SortJavaStaticImportOptions> {
603 FormatStyle::SortJavaStaticImportOptions &
Value) {
604 IO.enumCase(
Value,
"Before", FormatStyle::SJSIO_Before);
605 IO.enumCase(
Value,
"After", FormatStyle::SJSIO_After);
610 struct ScalarEnumerationTraits<
FormatStyle::SortUsingDeclarationsOptions> {
612 FormatStyle::SortUsingDeclarationsOptions &
Value) {
613 IO.enumCase(
Value,
"Never", FormatStyle::SUD_Never);
614 IO.enumCase(
Value,
"Lexicographic", FormatStyle::SUD_Lexicographic);
615 IO.enumCase(
Value,
"LexicographicNumeric",
616 FormatStyle::SUD_LexicographicNumeric);
619 IO.enumCase(
Value,
"false", FormatStyle::SUD_Never);
620 IO.enumCase(
Value,
"true", FormatStyle::SUD_LexicographicNumeric);
625 struct ScalarEnumerationTraits<
FormatStyle::SpaceAroundPointerQualifiersStyle> {
628 IO.enumCase(
Value,
"Default", FormatStyle::SAPQ_Default);
629 IO.enumCase(
Value,
"Before", FormatStyle::SAPQ_Before);
630 IO.enumCase(
Value,
"After", FormatStyle::SAPQ_After);
631 IO.enumCase(
Value,
"Both", FormatStyle::SAPQ_Both);
635 template <>
struct MappingTraits<
FormatStyle::SpaceBeforeParensCustom> {
636 static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) {
637 IO.mapOptional(
"AfterControlStatements", Spacing.AfterControlStatements);
638 IO.mapOptional(
"AfterForeachMacros", Spacing.AfterForeachMacros);
639 IO.mapOptional(
"AfterFunctionDefinitionName",
640 Spacing.AfterFunctionDefinitionName);
641 IO.mapOptional(
"AfterFunctionDeclarationName",
642 Spacing.AfterFunctionDeclarationName);
643 IO.mapOptional(
"AfterIfMacros", Spacing.AfterIfMacros);
644 IO.mapOptional(
"AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
645 IO.mapOptional(
"AfterRequiresInClause", Spacing.AfterRequiresInClause);
646 IO.mapOptional(
"AfterRequiresInExpression",
647 Spacing.AfterRequiresInExpression);
648 IO.mapOptional(
"BeforeNonEmptyParentheses",
649 Spacing.BeforeNonEmptyParentheses);
654 struct ScalarEnumerationTraits<
FormatStyle::SpaceBeforeParensStyle> {
656 IO.enumCase(
Value,
"Never", FormatStyle::SBPO_Never);
657 IO.enumCase(
Value,
"ControlStatements",
658 FormatStyle::SBPO_ControlStatements);
659 IO.enumCase(
Value,
"ControlStatementsExceptControlMacros",
660 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
661 IO.enumCase(
Value,
"NonEmptyParentheses",
662 FormatStyle::SBPO_NonEmptyParentheses);
663 IO.enumCase(
Value,
"Always", FormatStyle::SBPO_Always);
664 IO.enumCase(
Value,
"Custom", FormatStyle::SBPO_Custom);
667 IO.enumCase(
Value,
"false", FormatStyle::SBPO_Never);
668 IO.enumCase(
Value,
"true", FormatStyle::SBPO_ControlStatements);
669 IO.enumCase(
Value,
"ControlStatementsExceptForEachMacros",
670 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
674 template <>
struct ScalarEnumerationTraits<
FormatStyle::SpacesInAnglesStyle> {
676 IO.enumCase(
Value,
"Never", FormatStyle::SIAS_Never);
677 IO.enumCase(
Value,
"Always", FormatStyle::SIAS_Always);
678 IO.enumCase(
Value,
"Leave", FormatStyle::SIAS_Leave);
681 IO.enumCase(
Value,
"false", FormatStyle::SIAS_Never);
682 IO.enumCase(
Value,
"true", FormatStyle::SIAS_Always);
686 template <>
struct MappingTraits<
FormatStyle::SpacesInLineComment> {
687 static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
689 int signedMaximum =
static_cast<int>(Space.Maximum);
690 IO.mapOptional(
"Minimum", Space.Minimum);
691 IO.mapOptional(
"Maximum", signedMaximum);
692 Space.Maximum =
static_cast<unsigned>(signedMaximum);
694 if (Space.Maximum != -1u)
695 Space.Minimum =
std::min(Space.Minimum, Space.Maximum);
699 template <>
struct ScalarEnumerationTraits<
FormatStyle::TrailingCommaStyle> {
701 IO.enumCase(
Value,
"None", FormatStyle::TCS_None);
702 IO.enumCase(
Value,
"Wrapped", FormatStyle::TCS_Wrapped);
707 struct ScalarEnumerationTraits<
FormatStyle::TrailingCommentsAlignmentKinds> {
709 FormatStyle::TrailingCommentsAlignmentKinds &
Value) {
710 IO.enumCase(
Value,
"Leave", FormatStyle::TCAS_Leave);
711 IO.enumCase(
Value,
"Always", FormatStyle::TCAS_Always);
712 IO.enumCase(
Value,
"Never", FormatStyle::TCAS_Never);
716 template <>
struct MappingTraits<
FormatStyle::TrailingCommentsAlignmentStyle> {
718 FormatStyle::TrailingCommentsAlignmentStyle &
Value) {
719 IO.enumCase(
Value,
"Leave",
720 FormatStyle::TrailingCommentsAlignmentStyle(
721 {FormatStyle::TCAS_Leave, 1}));
723 IO.enumCase(
Value,
"Always",
724 FormatStyle::TrailingCommentsAlignmentStyle(
725 {FormatStyle::TCAS_Always, 1}));
727 IO.enumCase(
Value,
"Never",
728 FormatStyle::TrailingCommentsAlignmentStyle(
729 {FormatStyle::TCAS_Never, 1}));
732 IO.enumCase(
Value,
"true",
733 FormatStyle::TrailingCommentsAlignmentStyle(
734 {FormatStyle::TCAS_Always, 1}));
735 IO.enumCase(
Value,
"false",
736 FormatStyle::TrailingCommentsAlignmentStyle(
737 {FormatStyle::TCAS_Never, 1}));
741 FormatStyle::TrailingCommentsAlignmentStyle &
Value) {
742 IO.mapOptional(
"Kind",
Value.Kind);
743 IO.mapOptional(
"OverEmptyLines",
Value.OverEmptyLines);
747 template <>
struct ScalarEnumerationTraits<
FormatStyle::UseTabStyle> {
749 IO.enumCase(
Value,
"Never", FormatStyle::UT_Never);
750 IO.enumCase(
Value,
"false", FormatStyle::UT_Never);
751 IO.enumCase(
Value,
"Always", FormatStyle::UT_Always);
752 IO.enumCase(
Value,
"true", FormatStyle::UT_Always);
753 IO.enumCase(
Value,
"ForIndentation", FormatStyle::UT_ForIndentation);
754 IO.enumCase(
Value,
"ForContinuationAndIndentation",
755 FormatStyle::UT_ForContinuationAndIndentation);
756 IO.enumCase(
Value,
"AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);
763 IO.mapOptional(
"Language", Style.
Language);
765 StringRef BasedOnStyle;
766 if (IO.outputting()) {
767 StringRef Styles[] = {
"LLVM",
"Google",
"Chromium",
"Mozilla",
768 "WebKit",
"GNU",
"Microsoft"};
769 for (StringRef StyleName : Styles) {
772 Style == PredefinedStyle) {
773 IO.mapOptional(
"# BasedOnStyle", StyleName);
774 BasedOnStyle = StyleName;
779 IO.mapOptional(
"BasedOnStyle", BasedOnStyle);
780 if (!BasedOnStyle.empty()) {
781 FormatStyle::LanguageKind OldLanguage = Style.
Language;
782 FormatStyle::LanguageKind
Language =
785 IO.setError(Twine(
"Unknown value for BasedOnStyle: ", BasedOnStyle));
803 const bool IsGoogleOrChromium = BasedOnStyle.equals_insensitive(
"google") ||
804 BasedOnStyle.equals_insensitive(
"chromium");
805 bool OnCurrentLine = IsGoogleOrChromium;
806 bool OnNextLine =
true;
808 bool BreakBeforeInheritanceComma =
false;
809 bool BreakConstructorInitializersBeforeComma =
false;
811 bool DeriveLineEnding =
true;
812 bool UseCRLF =
false;
815 if (!IO.outputting()) {
817 IO.mapOptional(
"AllowAllConstructorInitializersOnNextLine", OnNextLine);
818 IO.mapOptional(
"BreakBeforeInheritanceComma",
819 BreakBeforeInheritanceComma);
820 IO.mapOptional(
"BreakConstructorInitializersBeforeComma",
821 BreakConstructorInitializersBeforeComma);
822 IO.mapOptional(
"ConstructorInitializerAllOnOneLineOrOnePerLine",
824 IO.mapOptional(
"DeriveLineEnding", DeriveLineEnding);
826 IO.mapOptional(
"IndentFunctionDeclarationAfterType",
830 IO.mapOptional(
"SpaceAfterControlStatementKeyword",
832 IO.mapOptional(
"UseCRLF", UseCRLF);
838 IO.mapOptional(
"AlignConsecutiveAssignments",
840 IO.mapOptional(
"AlignConsecutiveBitFields",
842 IO.mapOptional(
"AlignConsecutiveDeclarations",
848 IO.mapOptional(
"AllowAllArgumentsOnNextLine",
850 IO.mapOptional(
"AllowAllParametersOfDeclarationOnNextLine",
852 IO.mapOptional(
"AllowShortBlocksOnASingleLine",
854 IO.mapOptional(
"AllowShortCaseLabelsOnASingleLine",
856 IO.mapOptional(
"AllowShortEnumsOnASingleLine",
858 IO.mapOptional(
"AllowShortFunctionsOnASingleLine",
860 IO.mapOptional(
"AllowShortIfStatementsOnASingleLine",
862 IO.mapOptional(
"AllowShortLambdasOnASingleLine",
864 IO.mapOptional(
"AllowShortLoopsOnASingleLine",
866 IO.mapOptional(
"AlwaysBreakAfterDefinitionReturnType",
868 IO.mapOptional(
"AlwaysBreakAfterReturnType",
870 IO.mapOptional(
"AlwaysBreakBeforeMultilineStrings",
872 IO.mapOptional(
"AlwaysBreakTemplateDeclarations",
880 IO.mapOptional(
"BreakAfterJavaFieldAnnotations",
883 IO.mapOptional(
"BreakBeforeBinaryOperators",
885 IO.mapOptional(
"BreakBeforeConceptDeclarations",
888 IO.mapOptional(
"BreakBeforeInlineASMColon",
890 IO.mapOptional(
"BreakBeforeTernaryOperators",
892 IO.mapOptional(
"BreakConstructorInitializers",
899 IO.mapOptional(
"ConstructorInitializerIndentWidth",
905 IO.mapOptional(
"EmptyLineAfterAccessModifier",
907 IO.mapOptional(
"EmptyLineBeforeAccessModifier",
909 IO.mapOptional(
"ExperimentalAutoDetectBinPacking",
913 IO.mapOptional(
"IfMacros", Style.
IfMacros);
917 IO.mapOptional(
"IncludeIsMainSourceRegex",
927 IO.mapOptional(
"IndentWrappedFunctionNames",
936 IO.mapOptional(
"KeepEmptyLinesAtTheStartOfBlocks",
939 IO.mapOptional(
"LineEnding", Style.
LineEnding);
947 IO.mapOptional(
"ObjCBreakBeforeNestedBlockParam",
950 IO.mapOptional(
"ObjCSpaceBeforeProtocolList",
952 IO.mapOptional(
"PackConstructorInitializers",
955 IO.mapOptional(
"PenaltyBreakBeforeFirstCallParameter",
958 IO.mapOptional(
"PenaltyBreakFirstLessLess",
960 IO.mapOptional(
"PenaltyBreakOpenParenthesis",
963 IO.mapOptional(
"PenaltyBreakTemplateDeclaration",
966 IO.mapOptional(
"PenaltyIndentedWhitespace",
968 IO.mapOptional(
"PenaltyReturnTypeOnItsOwnLine",
986 IO.mapOptional(
"RequiresExpressionIndentation",
995 IO.mapOptional(
"SpaceAfterTemplateKeyword",
997 IO.mapOptional(
"SpaceAroundPointerQualifiers",
999 IO.mapOptional(
"SpaceBeforeAssignmentOperators",
1002 IO.mapOptional(
"SpaceBeforeCpp11BracedList",
1004 IO.mapOptional(
"SpaceBeforeCtorInitializerColon",
1006 IO.mapOptional(
"SpaceBeforeInheritanceColon",
1010 IO.mapOptional(
"SpaceBeforeRangeBasedForLoopColon",
1012 IO.mapOptional(
"SpaceBeforeSquareBrackets",
1016 IO.mapOptional(
"SpacesBeforeTrailingComments",
1019 IO.mapOptional(
"SpacesInConditionalStatement",
1021 IO.mapOptional(
"SpacesInContainerLiterals",
1023 IO.mapOptional(
"SpacesInCStyleCastParentheses",
1025 IO.mapOptional(
"SpacesInLineCommentPrefix",
1029 IO.mapOptional(
"Standard", Style.
Standard);
1030 IO.mapOptional(
"StatementAttributeLikeMacros",
1033 IO.mapOptional(
"TabWidth", Style.
TabWidth);
1035 IO.mapOptional(
"UseTab", Style.
UseTab);
1036 IO.mapOptional(
"WhitespaceSensitiveMacros",
1045 FormatStyle::DRTBS_All) {
1048 FormatStyle::DRTBS_TopLevel) {
1050 FormatStyle::RTBS_TopLevelDefinitions;
1056 if (BreakBeforeInheritanceComma &&
1064 if (BreakConstructorInitializersBeforeComma &&
1069 if (!IsGoogleOrChromium) {
1073 ? FormatStyle::PCIS_NextLine
1074 : FormatStyle::PCIS_CurrentLine;
1077 FormatStyle::PCIS_NextLine) {
1080 else if (!OnNextLine)
1084 if (Style.
LineEnding == FormatStyle::LE_DeriveLF) {
1085 if (!DeriveLineEnding)
1086 Style.
LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF;
1088 Style.
LineEnding = FormatStyle::LE_DeriveCRLF;
1098 template <>
struct DocumentListTraits<
std::vector<FormatStyle>> {
1099 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
1104 if (Index >= Seq.size()) {
1105 assert(Index == Seq.size());
1107 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
1110 Template = *((
const FormatStyle *)IO.getContext());
1111 Template.
Language = FormatStyle::LK_None;
1113 Seq.resize(Index + 1, Template);
1133 return llvm::make_error<llvm::StringError>(Message,
1134 llvm::inconvertibleErrorCode());
1138 return "clang-format.parse_error";
1146 return "Invalid argument";
1148 return "Unsuitable";
1150 return "trailing comma insertion cannot be used with bin packing";
1152 return "Invalid qualifier specified in QualifierOrder";
1154 return "Duplicate qualifier specified in QualifierOrder";
1156 return "Missing type in QualifierOrder";
1158 return "Missing QualifierOrder";
1160 llvm_unreachable(
"unexpected parse error");
1376 LLVMStyle.
IfMacros.push_back(
"KJ_IF_MAYBE");
1378 {
"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0,
false},
1379 {
"^(<|\"(gtest|gmock|isl|json)/)", 3, 0,
false},
1380 {
".*", 1, 0,
false}};
1509 {
"^<.*\\.h>", 1, 0,
false},
1510 {
"^<.*", 2, 0,
false},
1511 {
".*", 3, 0,
false}};
1552 "PARSE_PARTIAL_TEXT_PROTO",
1556 "ParseTextProtoOrDie",
1558 "ParsePartialTestProto",
1669 "com.google.android.apps.chrome",
1688 return ChromiumStyle;
1714 return MozillaStyle;
1796 if (Name.equals_insensitive(
"llvm"))
1798 else if (Name.equals_insensitive(
"chromium"))
1800 else if (Name.equals_insensitive(
"mozilla"))
1802 else if (Name.equals_insensitive(
"google"))
1804 else if (Name.equals_insensitive(
"webkit"))
1806 else if (Name.equals_insensitive(
"gnu"))
1808 else if (Name.equals_insensitive(
"microsoft"))
1810 else if (Name.equals_insensitive(
"none"))
1812 else if (Name.equals_insensitive(
"inheritparentconfig"))
1828 if (Qualifier ==
"type")
1832 if (token == tok::identifier)
1837 std::set<std::string> UniqueQualifiers(Style->
QualifierOrder.begin(),
1840 LLVM_DEBUG(llvm::dbgs()
1842 <<
" vs " << UniqueQualifiers.size() <<
"\n");
1855 llvm::SourceMgr::DiagHandlerTy DiagHandler,
1856 void *DiagHandlerCtxt) {
1860 if (Config.getBuffer().trim().empty())
1862 Style->StyleSet.
Clear();
1863 std::vector<FormatStyle> Styles;
1864 llvm::yaml::Input Input(Config,
nullptr, DiagHandler,
1870 Input.setContext(Style);
1871 Input.setAllowUnknownKeys(AllowUnknownOptions);
1874 return Input.error();
1876 for (
unsigned i = 0; i < Styles.size(); ++i) {
1881 for (
unsigned j = 0; j < i; ++j) {
1883 LLVM_DEBUG(llvm::dbgs()
1884 <<
"Duplicate languages in the config file on positions "
1885 << j <<
" and " << i <<
"\n");
1894 bool LanguageFound =
false;
1895 for (
const FormatStyle &Style : llvm::reverse(Styles)) {
1897 StyleSet.
Add(Style);
1899 LanguageFound =
true;
1901 if (!LanguageFound) {
1906 StyleSet.
Add(std::move(DefaultStyle));
1921 llvm::raw_string_ostream Stream(
Text);
1922 llvm::yaml::Output Output(Stream);
1928 Output << NonConstStyle;
1930 return Stream.str();
1933 std::optional<FormatStyle>
1936 return std::nullopt;
1938 if (It == Styles->end())
1939 return std::nullopt;
1941 Style.StyleSet = *
this;
1947 "Cannot add a style for LK_None to a StyleSet");
1949 !Style.StyleSet.Styles &&
1950 "Cannot add a style associated with an existing StyleSet to a StyleSet");
1952 Styles = std::make_shared<MapType>();
1953 (*Styles)[Style.
Language] = std::move(Style);
1958 std::optional<FormatStyle>
1970 std::pair<tooling::Replacements, unsigned>
1971 analyze(TokenAnnotator &Annotator,
1973 FormatTokenLexer &Tokens)
override {
1974 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
1976 insertBraces(AnnotatedLines, Result);
1981 void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
1982 tooling::Replacements &Result) {
1983 const auto &SourceMgr = Env.getSourceManager();
1984 int OpeningBraceSurplus = 0;
1985 for (AnnotatedLine *
Line : Lines) {
1986 insertBraces(
Line->Children, Result);
1987 if (!
Line->Affected && OpeningBraceSurplus == 0)
1989 for (FormatToken *Token =
Line->First; Token && !Token->Finalized;
1990 Token = Token->Next) {
1991 int BraceCount = Token->BraceCount;
1992 if (BraceCount == 0)
1995 if (BraceCount < 0) {
1996 assert(BraceCount == -1);
1997 if (!
Line->Affected)
1999 Brace = Token->is(tok::comment) ?
"\n{" :
"{";
2000 ++OpeningBraceSurplus;
2002 if (OpeningBraceSurplus == 0)
2004 if (OpeningBraceSurplus < BraceCount)
2005 BraceCount = OpeningBraceSurplus;
2007 OpeningBraceSurplus -= BraceCount;
2009 Token->BraceCount = 0;
2010 const auto Start = Token->Tok.getEndLoc();
2011 cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0,
Brace)));
2014 assert(OpeningBraceSurplus == 0);
2018 class BracesRemover :
public TokenAnalyzer {
2020 BracesRemover(
const Environment &Env,
const FormatStyle &Style)
2021 : TokenAnalyzer(Env, Style) {}
2023 std::pair<tooling::Replacements, unsigned>
2024 analyze(TokenAnnotator &Annotator,
2025 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2026 FormatTokenLexer &Tokens)
override {
2027 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2028 tooling::Replacements Result;
2029 removeBraces(AnnotatedLines, Result);
2034 void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2035 tooling::Replacements &Result) {
2036 const auto &SourceMgr = Env.getSourceManager();
2037 const auto End = Lines.end();
2038 for (
auto I = Lines.begin(); I !=
End; ++I) {
2039 const auto Line = *I;
2040 removeBraces(
Line->Children, Result);
2041 if (!
Line->Affected)
2043 const auto NextLine = I + 1 ==
End ? nullptr : I[1];
2044 for (
auto Token =
Line->First; Token && !Token->Finalized;
2045 Token = Token->Next) {
2046 if (!Token->Optional)
2048 if (!Token->isOneOf(tok::l_brace, tok::r_brace))
2050 auto Next = Token->Next;
2051 assert(Next || Token ==
Line->Last);
2052 if (!Next && NextLine)
2053 Next = NextLine->First;
2054 SourceLocation Start;
2055 if (Next && Next->NewlinesBefore == 0 && Next->isNot(
tok::eof)) {
2056 Start = Token->Tok.getLocation();
2057 Next->WhitespaceRange = Token->WhitespaceRange;
2059 Start = Token->WhitespaceRange.getBegin();
2063 cantFail(Result.add(tooling::Replacement(SourceMgr, Range,
"")));
2069 class SemiRemover :
public TokenAnalyzer {
2071 SemiRemover(
const Environment &Env,
const FormatStyle &Style)
2072 : TokenAnalyzer(Env, Style) {}
2074 std::pair<tooling::Replacements, unsigned>
2075 analyze(TokenAnnotator &Annotator,
2076 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2077 FormatTokenLexer &Tokens)
override {
2078 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2079 tooling::Replacements Result;
2080 removeSemi(AnnotatedLines, Result);
2085 void removeSemi(SmallVectorImpl<AnnotatedLine *> &Lines,
2086 tooling::Replacements &Result) {
2087 const auto &SourceMgr = Env.getSourceManager();
2088 const auto End = Lines.end();
2089 for (
auto I = Lines.begin(); I !=
End; ++I) {
2090 const auto Line = *I;
2091 removeSemi(
Line->Children, Result);
2092 if (!
Line->Affected)
2094 const auto NextLine = I + 1 ==
End ? nullptr : I[1];
2095 for (
auto Token =
Line->First; Token && !Token->Finalized;
2096 Token = Token->Next) {
2097 if (!Token->Optional)
2099 if (Token->isNot(tok::semi))
2101 auto Next = Token->Next;
2102 assert(Next || Token ==
Line->Last);
2103 if (!Next && NextLine)
2104 Next = NextLine->First;
2105 SourceLocation Start;
2106 if (Next && Next->NewlinesBefore == 0 && Next->isNot(
tok::eof)) {
2107 Start = Token->Tok.getLocation();
2108 Next->WhitespaceRange = Token->WhitespaceRange;
2110 Start = Token->WhitespaceRange.getBegin();
2114 cantFail(Result.add(tooling::Replacement(SourceMgr, Range,
"")));
2120 class JavaScriptRequoter :
public TokenAnalyzer {
2122 JavaScriptRequoter(
const Environment &Env,
const FormatStyle &Style)
2123 : TokenAnalyzer(Env, Style) {}
2125 std::pair<tooling::Replacements, unsigned>
2126 analyze(TokenAnnotator &Annotator,
2127 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2128 FormatTokenLexer &Tokens)
override {
2129 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2130 tooling::Replacements Result;
2131 requoteJSStringLiteral(AnnotatedLines, Result);
2138 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
2139 tooling::Replacements &Result) {
2140 for (AnnotatedLine *
Line : Lines) {
2141 requoteJSStringLiteral(
Line->Children, Result);
2142 if (!
Line->Affected)
2144 for (FormatToken *FormatTok =
Line->First; FormatTok;
2145 FormatTok = FormatTok->Next) {
2146 StringRef Input = FormatTok->TokenText;
2147 if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
2151 !Input.startswith(
"\"")) ||
2153 !Input.startswith(
"\'"))) {
2159 SourceLocation Start = FormatTok->Tok.getLocation();
2160 auto Replace = [&](SourceLocation Start,
unsigned Length,
2161 StringRef ReplacementText) {
2162 auto Err = Result.add(tooling::Replacement(
2163 Env.getSourceManager(), Start, Length, ReplacementText));
2171 Replace(Start, 1, IsSingle ?
"'" :
"\"");
2172 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
2173 IsSingle ?
"'" :
"\"");
2176 bool Escaped =
false;
2177 for (
size_t i = 1; i < Input.size() - 1; i++) {
2180 if (!Escaped && i + 1 < Input.size() &&
2181 ((IsSingle && Input[i + 1] ==
'"') ||
2182 (!IsSingle && Input[i + 1] ==
'\''))) {
2185 Replace(Start.getLocWithOffset(i), 1,
"");
2192 if (!Escaped && IsSingle == (Input[i] ==
'\'')) {
2194 Replace(Start.getLocWithOffset(i), 0,
"\\");
2208 class Formatter :
public TokenAnalyzer {
2210 Formatter(
const Environment &Env,
const FormatStyle &Style,
2211 FormattingAttemptStatus *Status)
2212 : TokenAnalyzer(Env, Style), Status(Status) {}
2214 std::pair<tooling::Replacements, unsigned>
2215 analyze(TokenAnnotator &Annotator,
2216 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2217 FormatTokenLexer &Tokens)
override {
2218 tooling::Replacements Result;
2219 deriveLocalStyle(AnnotatedLines);
2220 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2221 for (AnnotatedLine *
Line : AnnotatedLines)
2222 Annotator.calculateFormattingInformation(*
Line);
2223 Annotator.setCommentLineLevels(AnnotatedLines);
2225 WhitespaceManager Whitespaces(
2226 Env.getSourceManager(), Style,
2229 Env.getSourceManager().getBufferData(Env.getFileID()),
2232 ContinuationIndenter
Indenter(Style, Tokens.getKeywords(),
2233 Env.getSourceManager(), Whitespaces,
Encoding,
2234 BinPackInconclusiveFunctions);
2236 UnwrappedLineFormatter(&
Indenter, &Whitespaces, Style,
2237 Tokens.getKeywords(), Env.getSourceManager(),
2239 .format(AnnotatedLines,
false,
2242 Env.getFirstStartColumn(),
2243 Env.getNextStartColumn(),
2244 Env.getLastStartColumn());
2245 for (
const auto &R : Whitespaces.generateReplacements())
2247 return std::make_pair(Result, 0);
2248 return std::make_pair(Result, Penalty);
2253 hasCpp03IncompatibleFormat(
const SmallVectorImpl<AnnotatedLine *> &Lines) {
2254 for (
const AnnotatedLine *
Line : Lines) {
2255 if (hasCpp03IncompatibleFormat(
Line->Children))
2257 for (FormatToken *Tok =
Line->First->Next; Tok; Tok = Tok->Next) {
2258 if (!Tok->hasWhitespaceBefore()) {
2259 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
2261 if (Tok->is(TT_TemplateCloser) &&
2262 Tok->Previous->is(TT_TemplateCloser)) {
2271 int countVariableAlignments(
const SmallVectorImpl<AnnotatedLine *> &Lines) {
2272 int AlignmentDiff = 0;
2273 for (
const AnnotatedLine *
Line : Lines) {
2274 AlignmentDiff += countVariableAlignments(
Line->Children);
2275 for (FormatToken *Tok =
Line->First; Tok && Tok->Next; Tok = Tok->Next) {
2276 if (!Tok->is(TT_PointerOrReference))
2279 if (
const auto *Prev = Tok->getPreviousNonComment()) {
2280 if (Prev->is(tok::r_paren) && Prev->MatchingParen) {
2281 if (
const auto *Func =
2282 Prev->MatchingParen->getPreviousNonComment()) {
2283 if (Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName,
2284 TT_OverloadedOperator)) {
2290 bool SpaceBefore = Tok->hasWhitespaceBefore();
2291 bool SpaceAfter = Tok->Next->hasWhitespaceBefore();
2292 if (SpaceBefore && !SpaceAfter)
2294 if (!SpaceBefore && SpaceAfter)
2298 return AlignmentDiff;
2302 deriveLocalStyle(
const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2303 bool HasBinPackedFunction =
false;
2304 bool HasOnePerLineFunction =
false;
2305 for (AnnotatedLine *
Line : AnnotatedLines) {
2306 if (!
Line->First->Next)
2308 FormatToken *Tok =
Line->First->Next;
2311 HasBinPackedFunction =
true;
2313 HasOnePerLineFunction =
true;
2319 const auto NetRightCount = countVariableAlignments(AnnotatedLines);
2320 if (NetRightCount > 0)
2322 else if (NetRightCount < 0)
2327 Style.
Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
2331 BinPackInconclusiveFunctions =
2332 HasBinPackedFunction || !HasOnePerLineFunction;
2335 bool BinPackInconclusiveFunctions;
2336 FormattingAttemptStatus *Status;
2350 class TrailingCommaInserter :
public TokenAnalyzer {
2352 TrailingCommaInserter(
const Environment &Env,
const FormatStyle &Style)
2353 : TokenAnalyzer(Env, Style) {}
2355 std::pair<tooling::Replacements, unsigned>
2356 analyze(TokenAnnotator &Annotator,
2357 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2358 FormatTokenLexer &Tokens)
override {
2359 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2360 tooling::Replacements Result;
2361 insertTrailingCommas(AnnotatedLines, Result);
2368 void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,
2369 tooling::Replacements &Result) {
2370 for (AnnotatedLine *
Line : Lines) {
2371 insertTrailingCommas(
Line->Children, Result);
2372 if (!
Line->Affected)
2374 for (FormatToken *FormatTok =
Line->First; FormatTok;
2375 FormatTok = FormatTok->Next) {
2376 if (FormatTok->NewlinesBefore == 0)
2378 FormatToken *Matching = FormatTok->MatchingParen;
2379 if (!Matching || !FormatTok->getPreviousNonComment())
2381 if (!(FormatTok->is(tok::r_square) &&
2382 Matching->is(TT_ArrayInitializerLSquare)) &&
2383 !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) {
2386 FormatToken *Prev = FormatTok->getPreviousNonComment();
2387 if (Prev->is(tok::comma) || Prev->is(tok::semi))
2391 SourceLocation Start =
2392 Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size());
2396 unsigned ColumnNumber =
2397 Env.getSourceManager().getSpellingColumnNumber(Start);
2402 cantFail(Result.add(
2403 tooling::Replacement(Env.getSourceManager(), Start, 0,
",")));
2411 class Cleaner :
public TokenAnalyzer {
2413 Cleaner(
const Environment &Env,
const FormatStyle &Style)
2414 : TokenAnalyzer(Env, Style),
2415 DeletedTokens(FormatTokenLess(Env.getSourceManager())) {}
2418 std::pair<tooling::Replacements, unsigned>
2419 analyze(TokenAnnotator &Annotator,
2420 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2421 FormatTokenLexer &Tokens)
override {
2429 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2431 checkEmptyNamespace(AnnotatedLines);
2433 for (
auto *
Line : AnnotatedLines)
2436 return {generateFixes(), 0};
2440 void cleanupLine(AnnotatedLine *
Line) {
2441 for (
auto *Child :
Line->Children)
2444 if (
Line->Affected) {
2445 cleanupRight(
Line->First, tok::comma, tok::comma);
2446 cleanupRight(
Line->First, TT_CtorInitializerColon, tok::comma);
2447 cleanupRight(
Line->First, tok::l_paren, tok::comma);
2448 cleanupLeft(
Line->First, tok::comma, tok::r_paren);
2449 cleanupLeft(
Line->First, TT_CtorInitializerComma, tok::l_brace);
2450 cleanupLeft(
Line->First, TT_CtorInitializerColon, tok::l_brace);
2451 cleanupLeft(
Line->First, TT_CtorInitializerColon, tok::equal);
2455 bool containsOnlyComments(
const AnnotatedLine &
Line) {
2456 for (FormatToken *Tok =
Line.First; Tok !=
nullptr; Tok = Tok->Next)
2457 if (Tok->isNot(tok::comment))
2463 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2464 std::set<unsigned> DeletedLines;
2465 for (
unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
2466 auto &
Line = *AnnotatedLines[i];
2467 if (
Line.startsWithNamespace())
2468 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
2471 for (
auto Line : DeletedLines) {
2472 FormatToken *Tok = AnnotatedLines[
Line]->First;
2484 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2485 unsigned CurrentLine,
unsigned &
NewLine,
2486 std::set<unsigned> &DeletedLines) {
2487 unsigned InitLine = CurrentLine,
End = AnnotatedLines.size();
2492 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
2496 }
else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
2499 while (++CurrentLine <
End) {
2500 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
2503 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
2504 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine,
NewLine,
2512 if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
2522 if (CurrentLine >=
End)
2527 AnnotatedLines[InitLine]->First->Tok.getLocation(),
2528 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) {
2532 for (
unsigned i = InitLine; i <= CurrentLine; ++i)
2533 DeletedLines.insert(i);
2542 template <
typename LeftKind,
typename RightKind>
2543 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
2545 auto NextNotDeleted = [
this](
const FormatToken &Tok) -> FormatToken * {
2546 for (
auto *Res = Tok.Next; Res; Res = Res->Next) {
2547 if (!Res->is(tok::comment) &&
2548 DeletedTokens.find(Res) == DeletedTokens.end()) {
2554 for (
auto *Left = Start; Left;) {
2555 auto *Right = NextNotDeleted(*Left);
2558 if (Left->is(LK) && Right->is(RK)) {
2559 deleteToken(DeleteLeft ? Left : Right);
2560 for (
auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
2571 template <
typename LeftKind,
typename RightKind>
2572 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
2573 cleanupPair(Start, LK, RK,
true);
2576 template <
typename LeftKind,
typename RightKind>
2577 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
2578 cleanupPair(Start, LK, RK,
false);
2582 inline void deleteToken(FormatToken *Tok) {
2584 DeletedTokens.insert(Tok);
2587 tooling::Replacements generateFixes() {
2588 tooling::Replacements Fixes;
2589 SmallVector<FormatToken *> Tokens;
2590 std::copy(DeletedTokens.begin(), DeletedTokens.end(),
2591 std::back_inserter(Tokens));
2597 while (Idx < Tokens.size()) {
2598 unsigned St = Idx,
End = Idx;
2599 while ((
End + 1) < Tokens.size() && Tokens[
End]->Next == Tokens[
End + 1])
2602 Tokens[
End]->Tok.getEndLoc());
2604 Fixes.add(tooling::Replacement(Env.getSourceManager(), SR,
""));
2609 assert(
false &&
"Fixes must not conflict!");
2620 struct FormatTokenLess {
2621 FormatTokenLess(
const SourceManager &
SM) :
SM(
SM) {}
2623 bool operator()(
const FormatToken *LHS,
const FormatToken *RHS)
const {
2624 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
2625 RHS->Tok.getLocation());
2631 std::set<FormatToken *, FormatTokenLess> DeletedTokens;
2634 class ObjCHeaderStyleGuesser :
public TokenAnalyzer {
2636 ObjCHeaderStyleGuesser(
const Environment &Env,
const FormatStyle &Style)
2637 : TokenAnalyzer(Env, Style), IsObjC(
false) {}
2639 std::pair<tooling::Replacements, unsigned>
2640 analyze(TokenAnnotator &Annotator,
2641 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2642 FormatTokenLexer &Tokens)
override {
2644 IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines,
2645 Tokens.getKeywords());
2646 tooling::Replacements Result;
2650 bool isObjC() {
return IsObjC; }
2654 guessIsObjC(
const SourceManager &SourceManager,
2655 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2656 const AdditionalKeywords &Keywords) {
2658 static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
2673 "NSAffineTransform",
2675 "NSAttributedString",
2692 "NSInvocationOperation",
2696 "NSMutableAttributedString",
2697 "NSMutableCharacterSet",
2699 "NSMutableDictionary",
2700 "NSMutableIndexSet",
2701 "NSMutableOrderedSet",
2705 "NSNumberFormatter",
2709 "NSOperationQueuePriority",
2713 "NSQualityOfService",
2716 "NSRegularExpression",
2731 for (
auto *
Line : AnnotatedLines) {
2732 if (
Line->First && (
Line->First->TokenText.startswith(
"#") ||
2733 Line->First->TokenText ==
"__pragma" ||
2734 Line->First->TokenText ==
"_Pragma")) {
2737 for (
const FormatToken *FormatTok =
Line->First; FormatTok;
2738 FormatTok = FormatTok->Next) {
2739 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
2740 (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
2741 FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
2743 (FormatTok->Tok.isAnyIdentifier() &&
2744 std::binary_search(std::begin(FoundationIdentifiers),
2745 std::end(FoundationIdentifiers),
2746 FormatTok->TokenText)) ||
2747 FormatTok->is(TT_ObjCStringLiteral) ||
2748 FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,
2749 Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,
2750 TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,
2751 TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,
2753 LLVM_DEBUG(llvm::dbgs()
2754 <<
"Detected ObjC at location "
2755 << FormatTok->Tok.getLocation().printToString(
2757 <<
" token: " << FormatTok->TokenText <<
" token type: "
2761 if (guessIsObjC(SourceManager,
Line->Children, Keywords))
2779 struct JavaImportDirective {
2792 for (
auto Range : Ranges) {
2793 if (Range.getOffset() <
End &&
2794 Range.getOffset() + Range.getLength() > Start) {
2808 static std::pair<unsigned, unsigned>
2812 unsigned OffsetToEOL = 0;
2813 for (
int i = 0, e = Includes.size(); i != e; ++i) {
2814 unsigned Start = Includes[Indices[i]].Offset;
2815 unsigned End = Start + Includes[Indices[i]].Text.size();
2818 CursorIndex = Indices[i];
2822 while (--i >= 0 && Includes[CursorIndex].
Text == Includes[Indices[i]].
Text)
2826 return std::make_pair(CursorIndex, OffsetToEOL);
2832 size_t Pos = 0, LastPos = 0;
2835 Pos = Code.find(
"\r\n", LastPos);
2836 if (Pos == LastPos) {
2840 if (Pos == std::string::npos) {
2841 NewCode += Code.substr(LastPos);
2844 NewCode += Code.substr(LastPos, Pos - LastPos) +
"\n";
2846 }
while (Pos != std::string::npos);
2864 const unsigned IncludesBeginOffset = Includes.front().Offset;
2865 const unsigned IncludesEndOffset =
2866 Includes.back().Offset + Includes.back().Text.size();
2867 const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
2868 if (!
affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
2871 llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size()));
2874 llvm::stable_sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
2875 const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
2876 const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
2877 return std::tie(Includes[LHSI].
Priority, LHSFilenameLower,
2879 std::tie(Includes[RHSI].
Priority, RHSFilenameLower,
2883 llvm::stable_sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
2891 unsigned CursorIndex;
2893 unsigned CursorToEOLOffset;
2895 std::tie(CursorIndex, CursorToEOLOffset) =
2900 Indices.erase(std::unique(Indices.begin(), Indices.end(),
2901 [&](
unsigned LHSI,
unsigned RHSI) {
2902 return Includes[LHSI].Text.trim() ==
2903 Includes[RHSI].Text.trim();
2907 int CurrentCategory = Includes.front().Category;
2915 if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) &&
2921 for (
unsigned Index : Indices) {
2922 if (!result.empty()) {
2926 CurrentCategory != Includes[Index].Category) {
2930 result += Includes[Index].Text;
2931 if (
Cursor && CursorIndex == Index)
2932 *
Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
2933 CurrentCategory = Includes[Index].Category;
2937 *
Cursor += result.size() - IncludesBlockSize;
2942 IncludesBeginOffset, IncludesBlockSize)))) {
2947 FileName, Includes.front().Offset, IncludesBlockSize, result));
2961 unsigned Prev = llvm::StringSwitch<size_t>(Code)
2962 .StartsWith(
"\xEF\xBB\xBF", 3)
2964 unsigned SearchFrom = 0;
2976 bool FirstIncludeBlock =
true;
2977 bool MainIncludeFound =
false;
2978 bool FormattingOff =
false;
2981 llvm::Regex RawStringRegex(
2982 "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\(");
2987 auto Pos = Code.find(
'\n', SearchFrom);
2989 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
2991 StringRef Trimmed =
Line.trim();
2996 if (RawStringRegex.match(Trimmed, &RawStringMatches)) {
2997 std::string CharSequence = RawStringMatches[1].str();
2998 RawStringTermination =
")" + CharSequence +
"\"";
2999 FormattingOff =
true;
3002 if (Trimmed.contains(RawStringTermination))
3003 FormattingOff =
false;
3005 if (Trimmed ==
"// clang-format off" ||
3006 Trimmed ==
"/* clang-format off */") {
3007 FormattingOff =
true;
3008 }
else if (Trimmed ==
"// clang-format on" ||
3009 Trimmed ==
"/* clang-format on */") {
3010 FormattingOff =
false;
3013 const bool EmptyLineSkipped =
3019 bool MergeWithNextLine = Trimmed.endswith(
"\\");
3020 if (!FormattingOff && !MergeWithNextLine) {
3022 StringRef IncludeName = Matches[2];
3023 if (
Line.contains(
"/*") && !
Line.contains(
"*/")) {
3028 Pos = Code.find(
"*/", SearchFrom);
3030 Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev);
3034 !MainIncludeFound && FirstIncludeBlock);
3036 IncludeName, !MainIncludeFound && FirstIncludeBlock);
3038 MainIncludeFound =
true;
3039 IncludesInBlock.push_back(
3041 }
else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
3044 IncludesInBlock.clear();
3045 if (Trimmed.startswith(
"#pragma hdrstop"))
3046 FirstIncludeBlock =
true;
3048 FirstIncludeBlock =
false;
3051 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3054 if (!MergeWithNextLine)
3056 SearchFrom = Pos + 1;
3058 if (!IncludesInBlock.empty()) {
3059 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces,
3068 StringRef ImportIdentifier) {
3069 unsigned LongestMatchIndex =
UINT_MAX;
3070 unsigned LongestMatchLength = 0;
3073 if (ImportIdentifier.startswith(GroupPrefix) &&
3074 GroupPrefix.length() > LongestMatchLength) {
3075 LongestMatchIndex = I;
3076 LongestMatchLength = GroupPrefix.length();
3079 return LongestMatchIndex;
3091 unsigned ImportsBeginOffset = Imports.front().Offset;
3092 unsigned ImportsEndOffset =
3093 Imports.back().Offset + Imports.back().Text.size();
3094 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;
3095 if (!
affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))
3099 llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size()));
3102 for (
const JavaImportDirective &Import : Imports)
3105 bool StaticImportAfterNormalImport =
3107 llvm::sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
3109 return std::make_tuple(!Imports[LHSI].
IsStatic ^
3110 StaticImportAfterNormalImport,
3112 std::make_tuple(!Imports[RHSI].
IsStatic ^
3113 StaticImportAfterNormalImport,
3118 Indices.erase(std::unique(Indices.begin(), Indices.end(),
3119 [&](
unsigned LHSI,
unsigned RHSI) {
3120 return Imports[LHSI].Text == Imports[RHSI].Text;
3124 bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
3128 for (
unsigned Index : Indices) {
3129 if (!result.empty()) {
3131 if (CurrentIsStatic != Imports[Index].
IsStatic ||
3137 result += CommentLine;
3140 result += Imports[Index].Text;
3141 CurrentIsStatic = Imports[Index].IsStatic;
3148 Imports.front().Offset, ImportsBlockSize)))) {
3153 ImportsBlockSize, result));
3164 const char JavaImportRegexPattern[] =
3165 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;";
3174 unsigned SearchFrom = 0;
3175 llvm::Regex ImportRegex(JavaImportRegexPattern);
3180 bool FormattingOff =
false;
3183 auto Pos = Code.find(
'\n', SearchFrom);
3185 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3187 StringRef Trimmed =
Line.trim();
3188 if (Trimmed ==
"// clang-format off")
3189 FormattingOff =
true;
3190 else if (Trimmed ==
"// clang-format on")
3191 FormattingOff =
false;
3193 if (ImportRegex.match(
Line, &Matches)) {
3194 if (FormattingOff) {
3199 StringRef Static = Matches[1];
3202 if (Static.contains(
"static"))
3204 ImportsInBlock.push_back(
3207 }
else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) {
3212 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3214 SearchFrom = Pos + 1;
3216 if (!ImportsInBlock.empty())
3217 sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces);
3225 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
3228 bool isLikelyXml(StringRef Code) {
return Code.ltrim().startswith(
"<"); }
3232 StringRef FileName,
unsigned *
Cursor) {
3238 if (Style.
Language == FormatStyle::LanguageKind::LK_JavaScript &&
3242 if (Style.
Language == FormatStyle::LanguageKind::LK_JavaScript)
3244 if (Style.
Language == FormatStyle::LanguageKind::LK_Java)
3250 template <
typename T>
3255 if (Replaces.
empty())
3260 return NewCode.takeError();
3262 StringRef FileName = Replaces.
begin()->getFilePath();
3265 ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
3267 return Replaces.
merge(FormatReplaces);
3276 std::vector<tooling::Range> Ranges,
3280 auto SortedReplaces =
3282 if (!SortedReplaces)
3283 return SortedReplaces.takeError();
3287 auto Reformat = [](
const FormatStyle &Style, StringRef Code,
3288 std::vector<tooling::Range> Ranges,
3290 return reformat(Style, Code, Ranges, FileName);
3303 inline bool isHeaderDeletion(
const tooling::Replacement &Replace) {
3304 return Replace.getOffset() ==
UINT_MAX && Replace.getLength() == 1;
3308 tooling::Replacements
3309 fixCppIncludeInsertions(StringRef Code,
const tooling::Replacements &Replaces,
3314 tooling::Replacements HeaderInsertions;
3315 std::set<llvm::StringRef> HeadersToDelete;
3316 tooling::Replacements Result;
3317 for (
const auto &R : Replaces) {
3318 if (isHeaderInsertion(R)) {
3321 llvm::consumeError(HeaderInsertions.add(R));
3322 }
else if (isHeaderDeletion(R)) {
3323 HeadersToDelete.insert(R.getReplacementText());
3324 }
else if (R.getOffset() ==
UINT_MAX) {
3325 llvm::errs() <<
"Insertions other than header #include insertion are "
3327 << R.getReplacementText() <<
"\n";
3329 llvm::consumeError(Result.add(R));
3332 if (HeaderInsertions.empty() && HeadersToDelete.empty())
3335 StringRef FileName = Replaces.begin()->getFilePath();
3336 tooling::HeaderIncludes Includes(FileName, Code, Style.
IncludeStyle);
3338 for (
const auto &Header : HeadersToDelete) {
3339 tooling::Replacements Replaces =
3340 Includes.remove(Header.trim(
"\"<>"), Header.startswith(
"<"));
3341 for (
const auto &R : Replaces) {
3342 auto Err = Result.add(R);
3345 llvm::errs() <<
"Failed to add header deletion replacement for "
3353 for (
const auto &R : HeaderInsertions) {
3357 assert(Matched &&
"Header insertion replacement must have replacement text "
3360 auto IncludeName = Matches[2];
3362 Includes.insert(IncludeName.trim(
"\"<>"), IncludeName.startswith(
"<"),
3365 auto Err = Result.add(*Replace);
3367 llvm::consumeError(std::move(Err));
3368 unsigned NewOffset =
3369 Result.getShiftedCodePosition(Replace->getOffset());
3370 auto Shifted = tooling::Replacement(FileName, NewOffset, 0,
3371 Replace->getReplacementText());
3372 Result = Result.merge(tooling::Replacements(Shifted));
3386 auto Cleanup = [](
const FormatStyle &Style, StringRef Code,
3387 std::vector<tooling::Range> Ranges,
3389 return cleanup(Style, Code, Ranges, FileName);
3393 fixCppIncludeInsertions(Code, Replaces, Style);
3397 namespace internal {
3398 std::pair<tooling::Replacements, unsigned>
3401 unsigned NextStartColumn,
unsigned LastStartColumn, StringRef FileName,
3427 std::vector<tooling::Range> Ranges(1,
tooling::Range(0, Code.size()));
3429 NextStartColumn, LastStartColumn);
3434 Formatter(*Env, Style, Status).process().first;
3439 return {Replaces, 0};
3445 NextStartColumn, LastStartColumn);
3449 typedef std::function<std::pair<tooling::Replacements, unsigned>(
3458 if (Style.
isCpp()) {
3462 FirstStartColumn, NextStartColumn,
3463 LastStartColumn, FileName)
3470 S.InsertBraces =
true;
3471 Passes.emplace_back([&, S](
const Environment &Env) {
3472 return BracesInserter(Env, S).process(
true);
3478 S.RemoveBracesLLVM =
true;
3479 Passes.emplace_back([&, S](
const Environment &Env) {
3480 return BracesRemover(Env, S).process(
true);
3486 S.RemoveSemicolon =
true;
3487 Passes.emplace_back([&, S](
const Environment &Env) {
3488 return SemiRemover(Env, S).process(
true);
3514 return JavaScriptRequoter(Env, Expanded).process(
true);
3519 return Formatter(Env, Expanded, Status).process();
3525 return TrailingCommaInserter(Env, Expanded).process();
3529 std::optional<std::string> CurrentCode;
3531 unsigned Penalty = 0;
3532 for (
size_t I = 0, E = Passes.size(); I < E; ++I) {
3533 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
3535 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
3537 Fixes = Fixes.
merge(PassFixes.first);
3538 Penalty += PassFixes.second;
3540 CurrentCode = std::move(*NewCode);
3542 *CurrentCode, FileName,
3544 FirstStartColumn, NextStartColumn, LastStartColumn);
3551 return {Fixes, Penalty};
3562 0, FileName, Status)
3568 StringRef FileName) {
3575 return Cleaner(*Env, Style).process().first;
3580 StringRef FileName,
bool *IncompleteFormat) {
3582 auto Result =
reformat(Style, Code, Ranges, FileName, &Status);
3583 if (!Status.FormatComplete)
3584 *IncompleteFormat =
true;
3591 StringRef FileName) {
3601 StringRef FileName) {
3611 StringRef FileName) {
3626 LangOpts.CPlusPlus = 1;
3637 LangOpts.LineComment = 1;
3638 bool AlternativeOperators = Style.
isCpp();
3639 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
3642 LangOpts.MicrosoftExt = 1;
3643 LangOpts.DeclSpecKeyword = 1;
3649 "Set coding style. <string> can be:\n"
3650 "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"
3651 " Mozilla, WebKit.\n"
3652 "2. 'file' to load style configuration from a\n"
3653 " .clang-format file in one of the parent directories\n"
3654 " of the source file (for stdin, see --assume-filename).\n"
3655 " If no .clang-format file is found, falls back to\n"
3656 " --fallback-style.\n"
3657 " --style=file is the default.\n"
3658 "3. 'file:<format_file_path>' to explicitly specify\n"
3659 " the configuration file.\n"
3660 "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n"
3661 " --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
3664 if (FileName.endswith(
".java"))
3666 if (FileName.endswith_insensitive(
".js") ||
3667 FileName.endswith_insensitive(
".mjs") ||
3668 FileName.endswith_insensitive(
".ts")) {
3671 if (FileName.endswith(
".m") || FileName.endswith(
".mm"))
3673 if (FileName.endswith_insensitive(
".proto") ||
3674 FileName.endswith_insensitive(
".protodevel")) {
3677 if (FileName.endswith_insensitive(
".textpb") ||
3678 FileName.endswith_insensitive(
".pb.txt") ||
3679 FileName.endswith_insensitive(
".textproto") ||
3680 FileName.endswith_insensitive(
".asciipb")) {
3683 if (FileName.endswith_insensitive(
".td"))
3685 if (FileName.endswith_insensitive(
".cs"))
3687 if (FileName.endswith_insensitive(
".json"))
3689 if (FileName.endswith_insensitive(
".sv") ||
3690 FileName.endswith_insensitive(
".svh") ||
3691 FileName.endswith_insensitive(
".v") ||
3692 FileName.endswith_insensitive(
".vh")) {
3701 auto Extension = llvm::sys::path::extension(FileName);
3704 if (Extension.empty() || Extension ==
".h") {
3705 auto NonEmptyFileName = FileName.empty() ?
"guess.h" : FileName;
3709 if (Guesser.isObjC())
3713 return GuessedLanguage;
3721 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
3724 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
3725 FS->getBufferForFile(ConfigFile.str());
3726 if (
auto EC =
Text.getError())
3734 StringRef FallbackStyleName,
3735 StringRef Code, llvm::vfs::FileSystem *FS,
3736 bool AllowUnknownOptions) {
3738 FS = llvm::vfs::getRealFileSystem().get();
3746 ChildFormatTextToApply;
3748 if (StyleName.startswith(
"{")) {
3750 StringRef Source =
"<command-line>";
3751 if (std::error_code ec =
3753 AllowUnknownOptions)) {
3757 ChildFormatTextToApply.emplace_back(
3758 llvm::MemoryBuffer::getMemBuffer(StyleName, Source,
false));
3766 StyleName.startswith_insensitive(
"file:")) {
3767 auto ConfigFile = StyleName.substr(5);
3768 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
3770 if (
auto EC =
Text.getError()) {
3775 LLVM_DEBUG(llvm::dbgs()
3776 <<
"Using configuration file " << ConfigFile <<
"\n");
3783 FileName = ConfigFile;
3784 ChildFormatTextToApply.emplace_back(std::move(*
Text));
3803 if (std::error_code EC = FS->makeAbsolute(Path))
3807 FilesToLookFor.push_back(
".clang-format");
3808 FilesToLookFor.push_back(
"_clang-format");
3810 auto dropDiagnosticHandler = [](
const llvm::SMDiagnostic &,
void *) {};
3812 auto applyChildFormatTexts = [&](
FormatStyle *Style) {
3813 for (
const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) {
3815 dropDiagnosticHandler);
3818 static_cast<void>(EC);
3822 for (StringRef Directory = Path; !Directory.empty();
3823 Directory = llvm::sys::path::parent_path(Directory)) {
3825 auto Status = FS->status(Directory);
3827 Status->getType() != llvm::sys::fs::file_type::directory_file) {
3831 for (
const auto &F : FilesToLookFor) {
3834 llvm::sys::path::append(ConfigFile, F);
3835 LLVM_DEBUG(llvm::dbgs() <<
"Trying " << ConfigFile <<
"...\n");
3837 Status = FS->status(ConfigFile.str());
3840 (Status->getType() == llvm::sys::fs::file_type::regular_file)) {
3841 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
3843 if (
auto EC =
Text.getError()) {
3845 if (!UnsuitableConfigFiles.empty())
3846 UnsuitableConfigFiles.append(
", ");
3847 UnsuitableConfigFiles.append(ConfigFile);
3853 LLVM_DEBUG(llvm::dbgs()
3854 <<
"Using configuration file " << ConfigFile <<
"\n");
3857 if (ChildFormatTextToApply.empty())
3860 LLVM_DEBUG(llvm::dbgs() <<
"Applying child configurations\n");
3861 applyChildFormatTexts(&Style);
3866 LLVM_DEBUG(llvm::dbgs() <<
"Inherits parent configuration\n");
3871 ChildFormatTextToApply.emplace_back(std::move(*
Text));
3881 if (!UnsuitableConfigFiles.empty()) {
3884 UnsuitableConfigFiles);
3887 if (!ChildFormatTextToApply.empty()) {
3888 LLVM_DEBUG(llvm::dbgs()
3889 <<
"Applying child configurations on fallback style\n");
3890 applyChildFormatTexts(&FallbackStyle);
3893 return FallbackStyle;