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"
62template <>
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);
115struct 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);
124struct 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);
133template <>
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);
143template <>
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);
152struct 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);
162template <>
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);
176template <>
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);
199template <>
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);
213struct 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);
229struct 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);
244struct 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);
253struct 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);
263struct 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);
274struct 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);
288struct 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);
302struct 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);
316struct 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);
326struct 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);
338struct 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);
348template <>
struct MappingTraits<
FormatStyle::IntegerLiteralSeparatorStyle> {
349 static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &
Base) {
350 IO.mapOptional(
"Binary",
Base.Binary);
351 IO.mapOptional(
"BinaryMinDigits",
Base.BinaryMinDigits);
352 IO.mapOptional(
"Decimal",
Base.Decimal);
353 IO.mapOptional(
"DecimalMinDigits",
Base.DecimalMinDigits);
354 IO.mapOptional(
"Hex",
Base.Hex);
355 IO.mapOptional(
"HexMinDigits",
Base.HexMinDigits);
359template <>
struct ScalarEnumerationTraits<
FormatStyle::JavaScriptQuoteStyle> {
361 IO.enumCase(
Value,
"Leave", FormatStyle::JSQS_Leave);
362 IO.enumCase(
Value,
"Single", FormatStyle::JSQS_Single);
363 IO.enumCase(
Value,
"Double", FormatStyle::JSQS_Double);
367template <>
struct ScalarEnumerationTraits<
FormatStyle::LanguageKind> {
369 IO.enumCase(
Value,
"Cpp", FormatStyle::LK_Cpp);
370 IO.enumCase(
Value,
"Java", FormatStyle::LK_Java);
371 IO.enumCase(
Value,
"JavaScript", FormatStyle::LK_JavaScript);
372 IO.enumCase(
Value,
"ObjC", FormatStyle::LK_ObjC);
373 IO.enumCase(
Value,
"Proto", FormatStyle::LK_Proto);
374 IO.enumCase(
Value,
"TableGen", FormatStyle::LK_TableGen);
375 IO.enumCase(
Value,
"TextProto", FormatStyle::LK_TextProto);
376 IO.enumCase(
Value,
"CSharp", FormatStyle::LK_CSharp);
377 IO.enumCase(
Value,
"Json", FormatStyle::LK_Json);
378 IO.enumCase(
Value,
"Verilog", FormatStyle::LK_Verilog);
382template <>
struct ScalarEnumerationTraits<
FormatStyle::LanguageStandard> {
384 IO.enumCase(
Value,
"c++03", FormatStyle::LS_Cpp03);
385 IO.enumCase(
Value,
"C++03", FormatStyle::LS_Cpp03);
386 IO.enumCase(
Value,
"Cpp03", FormatStyle::LS_Cpp03);
388 IO.enumCase(
Value,
"c++11", FormatStyle::LS_Cpp11);
389 IO.enumCase(
Value,
"C++11", FormatStyle::LS_Cpp11);
391 IO.enumCase(
Value,
"c++14", FormatStyle::LS_Cpp14);
392 IO.enumCase(
Value,
"c++17", FormatStyle::LS_Cpp17);
393 IO.enumCase(
Value,
"c++20", FormatStyle::LS_Cpp20);
395 IO.enumCase(
Value,
"Latest", FormatStyle::LS_Latest);
396 IO.enumCase(
Value,
"Cpp11", FormatStyle::LS_Latest);
397 IO.enumCase(
Value,
"Auto", FormatStyle::LS_Auto);
402struct ScalarEnumerationTraits<
FormatStyle::LambdaBodyIndentationKind> {
404 FormatStyle::LambdaBodyIndentationKind &
Value) {
405 IO.enumCase(
Value,
"Signature", FormatStyle::LBI_Signature);
406 IO.enumCase(
Value,
"OuterScope", FormatStyle::LBI_OuterScope);
410template <>
struct ScalarEnumerationTraits<
FormatStyle::LineEndingStyle> {
412 IO.enumCase(
Value,
"LF", FormatStyle::LE_LF);
413 IO.enumCase(
Value,
"CRLF", FormatStyle::LE_CRLF);
414 IO.enumCase(
Value,
"DeriveLF", FormatStyle::LE_DeriveLF);
415 IO.enumCase(
Value,
"DeriveCRLF", FormatStyle::LE_DeriveCRLF);
420struct ScalarEnumerationTraits<
FormatStyle::NamespaceIndentationKind> {
422 FormatStyle::NamespaceIndentationKind &
Value) {
423 IO.enumCase(
Value,
"None", FormatStyle::NI_None);
424 IO.enumCase(
Value,
"Inner", FormatStyle::NI_Inner);
425 IO.enumCase(
Value,
"All", FormatStyle::NI_All);
429template <>
struct ScalarEnumerationTraits<
FormatStyle::OperandAlignmentStyle> {
431 IO.enumCase(
Value,
"DontAlign", FormatStyle::OAS_DontAlign);
432 IO.enumCase(
Value,
"Align", FormatStyle::OAS_Align);
433 IO.enumCase(
Value,
"AlignAfterOperator",
434 FormatStyle::OAS_AlignAfterOperator);
437 IO.enumCase(
Value,
"true", FormatStyle::OAS_Align);
438 IO.enumCase(
Value,
"false", FormatStyle::OAS_DontAlign);
443struct ScalarEnumerationTraits<
FormatStyle::PackConstructorInitializersStyle> {
446 IO.enumCase(
Value,
"Never", FormatStyle::PCIS_Never);
447 IO.enumCase(
Value,
"BinPack", FormatStyle::PCIS_BinPack);
448 IO.enumCase(
Value,
"CurrentLine", FormatStyle::PCIS_CurrentLine);
449 IO.enumCase(
Value,
"NextLine", FormatStyle::PCIS_NextLine);
450 IO.enumCase(
Value,
"NextLineOnly", FormatStyle::PCIS_NextLineOnly);
454template <>
struct ScalarEnumerationTraits<
FormatStyle::PointerAlignmentStyle> {
456 IO.enumCase(
Value,
"Middle", FormatStyle::PAS_Middle);
457 IO.enumCase(
Value,
"Left", FormatStyle::PAS_Left);
458 IO.enumCase(
Value,
"Right", FormatStyle::PAS_Right);
461 IO.enumCase(
Value,
"true", FormatStyle::PAS_Left);
462 IO.enumCase(
Value,
"false", FormatStyle::PAS_Right);
467struct ScalarEnumerationTraits<
FormatStyle::PPDirectiveIndentStyle> {
469 IO.enumCase(
Value,
"None", FormatStyle::PPDIS_None);
470 IO.enumCase(
Value,
"AfterHash", FormatStyle::PPDIS_AfterHash);
471 IO.enumCase(
Value,
"BeforeHash", FormatStyle::PPDIS_BeforeHash);
476struct ScalarEnumerationTraits<
FormatStyle::QualifierAlignmentStyle> {
478 IO.enumCase(
Value,
"Leave", FormatStyle::QAS_Leave);
479 IO.enumCase(
Value,
"Left", FormatStyle::QAS_Left);
480 IO.enumCase(
Value,
"Right", FormatStyle::QAS_Right);
481 IO.enumCase(
Value,
"Custom", FormatStyle::QAS_Custom);
486 static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
487 IO.mapOptional(
"Language", Format.Language);
488 IO.mapOptional(
"Delimiters", Format.Delimiters);
489 IO.mapOptional(
"EnclosingFunctions", Format.EnclosingFunctions);
490 IO.mapOptional(
"CanonicalDelimiter", Format.CanonicalDelimiter);
491 IO.mapOptional(
"BasedOnStyle", Format.BasedOnStyle);
496struct ScalarEnumerationTraits<
FormatStyle::ReferenceAlignmentStyle> {
498 IO.enumCase(
Value,
"Pointer", FormatStyle::RAS_Pointer);
499 IO.enumCase(
Value,
"Middle", FormatStyle::RAS_Middle);
500 IO.enumCase(
Value,
"Left", FormatStyle::RAS_Left);
501 IO.enumCase(
Value,
"Right", FormatStyle::RAS_Right);
506struct ScalarEnumerationTraits<
FormatStyle::RequiresClausePositionStyle> {
508 FormatStyle::RequiresClausePositionStyle &
Value) {
509 IO.enumCase(
Value,
"OwnLine", FormatStyle::RCPS_OwnLine);
510 IO.enumCase(
Value,
"WithPreceding", FormatStyle::RCPS_WithPreceding);
511 IO.enumCase(
Value,
"WithFollowing", FormatStyle::RCPS_WithFollowing);
512 IO.enumCase(
Value,
"SingleLine", FormatStyle::RCPS_SingleLine);
517struct ScalarEnumerationTraits<
FormatStyle::RequiresExpressionIndentationKind> {
520 IO.enumCase(
Value,
"Keyword", FormatStyle::REI_Keyword);
521 IO.enumCase(
Value,
"OuterScope", FormatStyle::REI_OuterScope);
526struct ScalarEnumerationTraits<
FormatStyle::ReturnTypeBreakingStyle> {
528 IO.enumCase(
Value,
"None", FormatStyle::RTBS_None);
529 IO.enumCase(
Value,
"All", FormatStyle::RTBS_All);
530 IO.enumCase(
Value,
"TopLevel", FormatStyle::RTBS_TopLevel);
531 IO.enumCase(
Value,
"TopLevelDefinitions",
532 FormatStyle::RTBS_TopLevelDefinitions);
533 IO.enumCase(
Value,
"AllDefinitions", FormatStyle::RTBS_AllDefinitions);
538struct ScalarEnumerationTraits<
FormatStyle::SeparateDefinitionStyle> {
540 IO.enumCase(
Value,
"Leave", FormatStyle::SDS_Leave);
541 IO.enumCase(
Value,
"Always", FormatStyle::SDS_Always);
542 IO.enumCase(
Value,
"Never", FormatStyle::SDS_Never);
546template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortBlockStyle> {
548 IO.enumCase(
Value,
"Never", FormatStyle::SBS_Never);
549 IO.enumCase(
Value,
"false", FormatStyle::SBS_Never);
550 IO.enumCase(
Value,
"Always", FormatStyle::SBS_Always);
551 IO.enumCase(
Value,
"true", FormatStyle::SBS_Always);
552 IO.enumCase(
Value,
"Empty", FormatStyle::SBS_Empty);
556template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortFunctionStyle> {
558 IO.enumCase(
Value,
"None", FormatStyle::SFS_None);
559 IO.enumCase(
Value,
"false", FormatStyle::SFS_None);
560 IO.enumCase(
Value,
"All", FormatStyle::SFS_All);
561 IO.enumCase(
Value,
"true", FormatStyle::SFS_All);
562 IO.enumCase(
Value,
"Inline", FormatStyle::SFS_Inline);
563 IO.enumCase(
Value,
"InlineOnly", FormatStyle::SFS_InlineOnly);
564 IO.enumCase(
Value,
"Empty", FormatStyle::SFS_Empty);
568template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortIfStyle> {
570 IO.enumCase(
Value,
"Never", FormatStyle::SIS_Never);
571 IO.enumCase(
Value,
"WithoutElse", FormatStyle::SIS_WithoutElse);
572 IO.enumCase(
Value,
"OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf);
573 IO.enumCase(
Value,
"AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse);
576 IO.enumCase(
Value,
"Always", FormatStyle::SIS_OnlyFirstIf);
577 IO.enumCase(
Value,
"false", FormatStyle::SIS_Never);
578 IO.enumCase(
Value,
"true", FormatStyle::SIS_WithoutElse);
582template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortLambdaStyle> {
584 IO.enumCase(
Value,
"None", FormatStyle::SLS_None);
585 IO.enumCase(
Value,
"false", FormatStyle::SLS_None);
586 IO.enumCase(
Value,
"Empty", FormatStyle::SLS_Empty);
587 IO.enumCase(
Value,
"Inline", FormatStyle::SLS_Inline);
588 IO.enumCase(
Value,
"All", FormatStyle::SLS_All);
589 IO.enumCase(
Value,
"true", FormatStyle::SLS_All);
593template <>
struct ScalarEnumerationTraits<
FormatStyle::SortIncludesOptions> {
595 IO.enumCase(
Value,
"Never", FormatStyle::SI_Never);
596 IO.enumCase(
Value,
"CaseInsensitive", FormatStyle::SI_CaseInsensitive);
597 IO.enumCase(
Value,
"CaseSensitive", FormatStyle::SI_CaseSensitive);
600 IO.enumCase(
Value,
"false", FormatStyle::SI_Never);
601 IO.enumCase(
Value,
"true", FormatStyle::SI_CaseSensitive);
606struct ScalarEnumerationTraits<
FormatStyle::SortJavaStaticImportOptions> {
608 FormatStyle::SortJavaStaticImportOptions &
Value) {
609 IO.enumCase(
Value,
"Before", FormatStyle::SJSIO_Before);
610 IO.enumCase(
Value,
"After", FormatStyle::SJSIO_After);
615struct ScalarEnumerationTraits<
FormatStyle::SortUsingDeclarationsOptions> {
617 FormatStyle::SortUsingDeclarationsOptions &
Value) {
618 IO.enumCase(
Value,
"Never", FormatStyle::SUD_Never);
619 IO.enumCase(
Value,
"Lexicographic", FormatStyle::SUD_Lexicographic);
620 IO.enumCase(
Value,
"LexicographicNumeric",
621 FormatStyle::SUD_LexicographicNumeric);
624 IO.enumCase(
Value,
"false", FormatStyle::SUD_Never);
625 IO.enumCase(
Value,
"true", FormatStyle::SUD_LexicographicNumeric);
630struct ScalarEnumerationTraits<
FormatStyle::SpaceAroundPointerQualifiersStyle> {
633 IO.enumCase(
Value,
"Default", FormatStyle::SAPQ_Default);
634 IO.enumCase(
Value,
"Before", FormatStyle::SAPQ_Before);
635 IO.enumCase(
Value,
"After", FormatStyle::SAPQ_After);
636 IO.enumCase(
Value,
"Both", FormatStyle::SAPQ_Both);
640template <>
struct MappingTraits<
FormatStyle::SpaceBeforeParensCustom> {
641 static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) {
642 IO.mapOptional(
"AfterControlStatements", Spacing.AfterControlStatements);
643 IO.mapOptional(
"AfterForeachMacros", Spacing.AfterForeachMacros);
644 IO.mapOptional(
"AfterFunctionDefinitionName",
645 Spacing.AfterFunctionDefinitionName);
646 IO.mapOptional(
"AfterFunctionDeclarationName",
647 Spacing.AfterFunctionDeclarationName);
648 IO.mapOptional(
"AfterIfMacros", Spacing.AfterIfMacros);
649 IO.mapOptional(
"AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
650 IO.mapOptional(
"AfterRequiresInClause", Spacing.AfterRequiresInClause);
651 IO.mapOptional(
"AfterRequiresInExpression",
652 Spacing.AfterRequiresInExpression);
653 IO.mapOptional(
"BeforeNonEmptyParentheses",
654 Spacing.BeforeNonEmptyParentheses);
659struct ScalarEnumerationTraits<
FormatStyle::SpaceBeforeParensStyle> {
661 IO.enumCase(
Value,
"Never", FormatStyle::SBPO_Never);
662 IO.enumCase(
Value,
"ControlStatements",
663 FormatStyle::SBPO_ControlStatements);
664 IO.enumCase(
Value,
"ControlStatementsExceptControlMacros",
665 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
666 IO.enumCase(
Value,
"NonEmptyParentheses",
667 FormatStyle::SBPO_NonEmptyParentheses);
668 IO.enumCase(
Value,
"Always", FormatStyle::SBPO_Always);
669 IO.enumCase(
Value,
"Custom", FormatStyle::SBPO_Custom);
672 IO.enumCase(
Value,
"false", FormatStyle::SBPO_Never);
673 IO.enumCase(
Value,
"true", FormatStyle::SBPO_ControlStatements);
674 IO.enumCase(
Value,
"ControlStatementsExceptForEachMacros",
675 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
679template <>
struct ScalarEnumerationTraits<
FormatStyle::SpacesInAnglesStyle> {
681 IO.enumCase(
Value,
"Never", FormatStyle::SIAS_Never);
682 IO.enumCase(
Value,
"Always", FormatStyle::SIAS_Always);
683 IO.enumCase(
Value,
"Leave", FormatStyle::SIAS_Leave);
686 IO.enumCase(
Value,
"false", FormatStyle::SIAS_Never);
687 IO.enumCase(
Value,
"true", FormatStyle::SIAS_Always);
691template <>
struct MappingTraits<
FormatStyle::SpacesInLineComment> {
692 static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
694 int signedMaximum =
static_cast<int>(Space.Maximum);
695 IO.mapOptional(
"Minimum", Space.Minimum);
696 IO.mapOptional(
"Maximum", signedMaximum);
697 Space.Maximum =
static_cast<unsigned>(signedMaximum);
699 if (Space.Maximum != -1u)
700 Space.Minimum = std::min(Space.Minimum, Space.Maximum);
704template <>
struct ScalarEnumerationTraits<
FormatStyle::TrailingCommaStyle> {
706 IO.enumCase(
Value,
"None", FormatStyle::TCS_None);
707 IO.enumCase(
Value,
"Wrapped", FormatStyle::TCS_Wrapped);
712struct ScalarEnumerationTraits<
FormatStyle::TrailingCommentsAlignmentKinds> {
714 FormatStyle::TrailingCommentsAlignmentKinds &
Value) {
715 IO.enumCase(
Value,
"Leave", FormatStyle::TCAS_Leave);
716 IO.enumCase(
Value,
"Always", FormatStyle::TCAS_Always);
717 IO.enumCase(
Value,
"Never", FormatStyle::TCAS_Never);
721template <>
struct MappingTraits<
FormatStyle::TrailingCommentsAlignmentStyle> {
723 FormatStyle::TrailingCommentsAlignmentStyle &
Value) {
724 IO.enumCase(
Value,
"Leave",
725 FormatStyle::TrailingCommentsAlignmentStyle(
726 {FormatStyle::TCAS_Leave, 0}));
728 IO.enumCase(
Value,
"Always",
729 FormatStyle::TrailingCommentsAlignmentStyle(
730 {FormatStyle::TCAS_Always, 0}));
732 IO.enumCase(
Value,
"Never",
733 FormatStyle::TrailingCommentsAlignmentStyle(
734 {FormatStyle::TCAS_Never, 0}));
737 IO.enumCase(
Value,
"true",
738 FormatStyle::TrailingCommentsAlignmentStyle(
739 {FormatStyle::TCAS_Always, 0}));
740 IO.enumCase(
Value,
"false",
741 FormatStyle::TrailingCommentsAlignmentStyle(
742 {FormatStyle::TCAS_Never, 0}));
746 FormatStyle::TrailingCommentsAlignmentStyle &
Value) {
747 IO.mapOptional(
"Kind",
Value.Kind);
748 IO.mapOptional(
"OverEmptyLines",
Value.OverEmptyLines);
752template <>
struct ScalarEnumerationTraits<
FormatStyle::UseTabStyle> {
754 IO.enumCase(
Value,
"Never", FormatStyle::UT_Never);
755 IO.enumCase(
Value,
"false", FormatStyle::UT_Never);
756 IO.enumCase(
Value,
"Always", FormatStyle::UT_Always);
757 IO.enumCase(
Value,
"true", FormatStyle::UT_Always);
758 IO.enumCase(
Value,
"ForIndentation", FormatStyle::UT_ForIndentation);
759 IO.enumCase(
Value,
"ForContinuationAndIndentation",
760 FormatStyle::UT_ForContinuationAndIndentation);
761 IO.enumCase(
Value,
"AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);
768 IO.mapOptional(
"Language", Style.
Language);
770 StringRef BasedOnStyle;
771 if (IO.outputting()) {
772 StringRef Styles[] = {
"LLVM",
"Google",
"Chromium",
"Mozilla",
773 "WebKit",
"GNU",
"Microsoft"};
774 for (StringRef StyleName : Styles) {
776 if (getPredefinedStyle(StyleName, Style.
Language, &PredefinedStyle) &&
777 Style == PredefinedStyle) {
778 IO.mapOptional(
"# BasedOnStyle", StyleName);
779 BasedOnStyle = StyleName;
784 IO.mapOptional(
"BasedOnStyle", BasedOnStyle);
785 if (!BasedOnStyle.empty()) {
786 FormatStyle::LanguageKind OldLanguage = Style.
Language;
787 FormatStyle::LanguageKind Language =
789 if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
790 IO.setError(Twine(
"Unknown value for BasedOnStyle: ", BasedOnStyle));
808 const bool IsGoogleOrChromium = BasedOnStyle.equals_insensitive(
"google") ||
809 BasedOnStyle.equals_insensitive(
"chromium");
810 bool OnCurrentLine = IsGoogleOrChromium;
811 bool OnNextLine =
true;
813 bool BreakBeforeInheritanceComma =
false;
814 bool BreakConstructorInitializersBeforeComma =
false;
816 bool DeriveLineEnding =
true;
817 bool UseCRLF =
false;
820 if (!IO.outputting()) {
822 IO.mapOptional(
"AllowAllConstructorInitializersOnNextLine", OnNextLine);
823 IO.mapOptional(
"BreakBeforeInheritanceComma",
824 BreakBeforeInheritanceComma);
825 IO.mapOptional(
"BreakConstructorInitializersBeforeComma",
826 BreakConstructorInitializersBeforeComma);
827 IO.mapOptional(
"ConstructorInitializerAllOnOneLineOrOnePerLine",
829 IO.mapOptional(
"DeriveLineEnding", DeriveLineEnding);
831 IO.mapOptional(
"IndentFunctionDeclarationAfterType",
835 IO.mapOptional(
"SpaceAfterControlStatementKeyword",
837 IO.mapOptional(
"UseCRLF", UseCRLF);
843 IO.mapOptional(
"AlignConsecutiveAssignments",
845 IO.mapOptional(
"AlignConsecutiveBitFields",
847 IO.mapOptional(
"AlignConsecutiveDeclarations",
853 IO.mapOptional(
"AllowAllArgumentsOnNextLine",
855 IO.mapOptional(
"AllowAllParametersOfDeclarationOnNextLine",
857 IO.mapOptional(
"AllowShortBlocksOnASingleLine",
859 IO.mapOptional(
"AllowShortCaseLabelsOnASingleLine",
861 IO.mapOptional(
"AllowShortEnumsOnASingleLine",
863 IO.mapOptional(
"AllowShortFunctionsOnASingleLine",
865 IO.mapOptional(
"AllowShortIfStatementsOnASingleLine",
867 IO.mapOptional(
"AllowShortLambdasOnASingleLine",
869 IO.mapOptional(
"AllowShortLoopsOnASingleLine",
871 IO.mapOptional(
"AlwaysBreakAfterDefinitionReturnType",
873 IO.mapOptional(
"AlwaysBreakAfterReturnType",
875 IO.mapOptional(
"AlwaysBreakBeforeMultilineStrings",
877 IO.mapOptional(
"AlwaysBreakTemplateDeclarations",
883 IO.mapOptional(
"BracedInitializerIndentWidth",
887 IO.mapOptional(
"BreakAfterJavaFieldAnnotations",
890 IO.mapOptional(
"BreakBeforeBinaryOperators",
892 IO.mapOptional(
"BreakBeforeConceptDeclarations",
895 IO.mapOptional(
"BreakBeforeInlineASMColon",
897 IO.mapOptional(
"BreakBeforeTernaryOperators",
899 IO.mapOptional(
"BreakConstructorInitializers",
906 IO.mapOptional(
"ConstructorInitializerIndentWidth",
912 IO.mapOptional(
"EmptyLineAfterAccessModifier",
914 IO.mapOptional(
"EmptyLineBeforeAccessModifier",
916 IO.mapOptional(
"ExperimentalAutoDetectBinPacking",
920 IO.mapOptional(
"IfMacros", Style.
IfMacros);
924 IO.mapOptional(
"IncludeIsMainSourceRegex",
934 IO.mapOptional(
"IndentWrappedFunctionNames",
943 IO.mapOptional(
"KeepEmptyLinesAtTheStartOfBlocks",
946 IO.mapOptional(
"LineEnding", Style.
LineEnding);
954 IO.mapOptional(
"ObjCBreakBeforeNestedBlockParam",
957 IO.mapOptional(
"ObjCSpaceBeforeProtocolList",
959 IO.mapOptional(
"PackConstructorInitializers",
962 IO.mapOptional(
"PenaltyBreakBeforeFirstCallParameter",
965 IO.mapOptional(
"PenaltyBreakFirstLessLess",
967 IO.mapOptional(
"PenaltyBreakOpenParenthesis",
970 IO.mapOptional(
"PenaltyBreakTemplateDeclaration",
973 IO.mapOptional(
"PenaltyIndentedWhitespace",
975 IO.mapOptional(
"PenaltyReturnTypeOnItsOwnLine",
993 IO.mapOptional(
"RequiresExpressionIndentation",
1002 IO.mapOptional(
"SpaceAfterTemplateKeyword",
1004 IO.mapOptional(
"SpaceAroundPointerQualifiers",
1006 IO.mapOptional(
"SpaceBeforeAssignmentOperators",
1009 IO.mapOptional(
"SpaceBeforeCpp11BracedList",
1011 IO.mapOptional(
"SpaceBeforeCtorInitializerColon",
1013 IO.mapOptional(
"SpaceBeforeInheritanceColon",
1018 IO.mapOptional(
"SpaceBeforeRangeBasedForLoopColon",
1020 IO.mapOptional(
"SpaceBeforeSquareBrackets",
1024 IO.mapOptional(
"SpacesBeforeTrailingComments",
1027 IO.mapOptional(
"SpacesInConditionalStatement",
1029 IO.mapOptional(
"SpacesInContainerLiterals",
1031 IO.mapOptional(
"SpacesInCStyleCastParentheses",
1033 IO.mapOptional(
"SpacesInLineCommentPrefix",
1037 IO.mapOptional(
"Standard", Style.
Standard);
1038 IO.mapOptional(
"StatementAttributeLikeMacros",
1041 IO.mapOptional(
"TabWidth", Style.
TabWidth);
1043 IO.mapOptional(
"UseTab", Style.
UseTab);
1044 IO.mapOptional(
"VerilogBreakBetweenInstancePorts",
1046 IO.mapOptional(
"WhitespaceSensitiveMacros",
1048 IO.mapOptional(
"Macros", Style.
Macros);
1056 FormatStyle::DRTBS_All) {
1059 FormatStyle::DRTBS_TopLevel) {
1061 FormatStyle::RTBS_TopLevelDefinitions;
1067 if (BreakBeforeInheritanceComma &&
1075 if (BreakConstructorInitializersBeforeComma &&
1080 if (!IsGoogleOrChromium) {
1084 ? FormatStyle::PCIS_NextLine
1085 : FormatStyle::PCIS_CurrentLine;
1088 FormatStyle::PCIS_NextLine) {
1091 else if (!OnNextLine)
1095 if (Style.
LineEnding == FormatStyle::LE_DeriveLF) {
1096 if (!DeriveLineEnding)
1097 Style.
LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF;
1099 Style.
LineEnding = FormatStyle::LE_DeriveCRLF;
1109template <>
struct DocumentListTraits<
std::vector<FormatStyle>> {
1110 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
1115 if (Index >= Seq.size()) {
1116 assert(Index == Seq.size());
1118 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
1121 Template = *((
const FormatStyle *)IO.getContext());
1122 Template.
Language = FormatStyle::LK_None;
1124 Seq.resize(Index + 1, Template);
1144 return llvm::make_error<llvm::StringError>(Message,
1145 llvm::inconvertibleErrorCode());
1149 return "clang-format.parse_error";
1157 return "Invalid argument";
1159 return "Unsuitable";
1161 return "trailing comma insertion cannot be used with bin packing";
1163 return "Invalid qualifier specified in QualifierOrder";
1165 return "Duplicate qualifier specified in QualifierOrder";
1167 return "Missing type in QualifierOrder";
1169 return "Missing QualifierOrder";
1171 llvm_unreachable(
"unexpected parse error");
1388 LLVMStyle.
IfMacros.push_back(
"KJ_IF_MAYBE");
1390 {
"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0,
false},
1391 {
"^(<|\"(gtest|gmock|isl|json)/)", 3, 0,
false},
1392 {
".*", 1, 0,
false}};
1527 {
"^<.*\\.h>", 1, 0,
false},
1528 {
"^<.*", 2, 0,
false},
1529 {
".*", 3, 0,
false}};
1570 "PARSE_PARTIAL_TEXT_PROTO",
1574 "ParseTextProtoOrDie",
1576 "ParsePartialTestProto",
1687 "com.google.android.apps.chrome",
1706 return ChromiumStyle;
1732 return MozillaStyle;
1814 if (Name.equals_insensitive(
"llvm"))
1816 else if (Name.equals_insensitive(
"chromium"))
1818 else if (Name.equals_insensitive(
"mozilla"))
1820 else if (Name.equals_insensitive(
"google"))
1822 else if (Name.equals_insensitive(
"webkit"))
1824 else if (Name.equals_insensitive(
"gnu"))
1826 else if (Name.equals_insensitive(
"microsoft"))
1828 else if (Name.equals_insensitive(
"none"))
1830 else if (Name.equals_insensitive(
"inheritparentconfig"))
1846 if (Qualifier ==
"type")
1850 if (token == tok::identifier)
1855 std::set<std::string> UniqueQualifiers(Style->
QualifierOrder.begin(),
1858 LLVM_DEBUG(llvm::dbgs()
1860 <<
" vs " << UniqueQualifiers.size() <<
"\n");
1873 llvm::SourceMgr::DiagHandlerTy DiagHandler,
1874 void *DiagHandlerCtxt) {
1878 if (Config.getBuffer().trim().empty())
1880 Style->StyleSet.
Clear();
1881 std::vector<FormatStyle> Styles;
1882 llvm::yaml::Input Input(Config,
nullptr, DiagHandler,
1888 Input.setContext(Style);
1889 Input.setAllowUnknownKeys(AllowUnknownOptions);
1892 return Input.error();
1894 for (
unsigned i = 0; i < Styles.size(); ++i) {
1899 for (
unsigned j = 0; j < i; ++j) {
1901 LLVM_DEBUG(llvm::dbgs()
1902 <<
"Duplicate languages in the config file on positions "
1903 << j <<
" and " << i <<
"\n");
1912 bool LanguageFound =
false;
1913 for (
const FormatStyle &Style : llvm::reverse(Styles)) {
1915 StyleSet.
Add(Style);
1917 LanguageFound =
true;
1919 if (!LanguageFound) {
1924 StyleSet.
Add(std::move(DefaultStyle));
1939 llvm::raw_string_ostream Stream(
Text);
1940 llvm::yaml::Output Output(Stream);
1946 Output << NonConstStyle;
1948 return Stream.str();
1951std::optional<FormatStyle>
1954 return std::nullopt;
1956 if (It == Styles->end())
1957 return std::nullopt;
1959 Style.StyleSet = *
this;
1965 "Cannot add a style for LK_None to a StyleSet");
1967 !Style.StyleSet.Styles &&
1968 "Cannot add a style associated with an existing StyleSet to a StyleSet");
1970 Styles = std::make_shared<MapType>();
1971 (*Styles)[Style.
Language] = std::move(Style);
1976std::optional<FormatStyle>
1988 std::pair<tooling::Replacements, unsigned>
1989 analyze(TokenAnnotator &Annotator,
1991 FormatTokenLexer &Tokens)
override {
1992 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
1994 insertBraces(AnnotatedLines, Result);
1999 void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2000 tooling::Replacements &Result) {
2001 const auto &SourceMgr =
Env.getSourceManager();
2002 int OpeningBraceSurplus = 0;
2003 for (AnnotatedLine *Line : Lines) {
2004 insertBraces(Line->Children, Result);
2005 if (!Line->Affected && OpeningBraceSurplus == 0)
2007 for (FormatToken *Token = Line->First; Token && !Token->Finalized;
2008 Token = Token->Next) {
2009 int BraceCount = Token->BraceCount;
2010 if (BraceCount == 0)
2013 if (BraceCount < 0) {
2014 assert(BraceCount == -1);
2015 if (!Line->Affected)
2017 Brace = Token->is(tok::comment) ?
"\n{" :
"{";
2018 ++OpeningBraceSurplus;
2020 if (OpeningBraceSurplus == 0)
2022 if (OpeningBraceSurplus < BraceCount)
2023 BraceCount = OpeningBraceSurplus;
2024 Brace =
'\n' + std::string(BraceCount,
'}');
2025 OpeningBraceSurplus -= BraceCount;
2027 Token->BraceCount = 0;
2028 const auto Start = Token->Tok.getEndLoc();
2029 cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0,
Brace)));
2032 assert(OpeningBraceSurplus == 0);
2036class BracesRemover :
public TokenAnalyzer {
2039 : TokenAnalyzer(
Env, Style) {}
2041 std::pair<tooling::Replacements, unsigned>
2042 analyze(TokenAnnotator &Annotator,
2043 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2044 FormatTokenLexer &Tokens)
override {
2045 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2046 tooling::Replacements Result;
2047 removeBraces(AnnotatedLines, Result);
2052 void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2053 tooling::Replacements &Result) {
2054 const auto &SourceMgr =
Env.getSourceManager();
2055 const auto End = Lines.end();
2056 for (
auto I = Lines.begin(); I != End; ++I) {
2057 const auto Line = *I;
2058 removeBraces(Line->Children, Result);
2059 if (!Line->Affected)
2061 const auto NextLine = I + 1 == End ? nullptr : I[1];
2062 for (
auto Token = Line->First; Token && !Token->Finalized;
2063 Token = Token->Next) {
2064 if (!Token->Optional)
2066 if (!Token->isOneOf(tok::l_brace, tok::r_brace))
2068 auto Next = Token->Next;
2069 assert(Next || Token == Line->Last);
2070 if (!Next && NextLine)
2071 Next = NextLine->First;
2072 SourceLocation Start;
2073 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2074 Start = Token->Tok.getLocation();
2075 Next->WhitespaceRange = Token->WhitespaceRange;
2077 Start = Token->WhitespaceRange.getBegin();
2080 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2081 cantFail(Result.add(tooling::Replacement(SourceMgr, Range,
"")));
2087class SemiRemover :
public TokenAnalyzer {
2090 : TokenAnalyzer(
Env, Style) {}
2092 std::pair<tooling::Replacements, unsigned>
2093 analyze(TokenAnnotator &Annotator,
2094 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2095 FormatTokenLexer &Tokens)
override {
2096 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2097 tooling::Replacements Result;
2098 removeSemi(AnnotatedLines, Result);
2103 void removeSemi(SmallVectorImpl<AnnotatedLine *> &Lines,
2104 tooling::Replacements &Result) {
2105 const auto &SourceMgr =
Env.getSourceManager();
2106 const auto End = Lines.end();
2107 for (
auto I = Lines.begin(); I != End; ++I) {
2108 const auto Line = *I;
2109 removeSemi(Line->Children, Result);
2110 if (!Line->Affected)
2112 const auto NextLine = I + 1 == End ? nullptr : I[1];
2113 for (
auto Token = Line->First; Token && !Token->Finalized;
2114 Token = Token->Next) {
2115 if (!Token->Optional)
2117 if (Token->isNot(tok::semi))
2119 auto Next = Token->Next;
2120 assert(Next || Token == Line->Last);
2121 if (!Next && NextLine)
2122 Next = NextLine->First;
2123 SourceLocation Start;
2124 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2125 Start = Token->Tok.getLocation();
2126 Next->WhitespaceRange = Token->WhitespaceRange;
2128 Start = Token->WhitespaceRange.getBegin();
2131 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2132 cantFail(Result.add(tooling::Replacement(SourceMgr, Range,
"")));
2138class JavaScriptRequoter :
public TokenAnalyzer {
2140 JavaScriptRequoter(
const Environment &
Env,
const FormatStyle &Style)
2141 : TokenAnalyzer(
Env, Style) {}
2143 std::pair<tooling::Replacements, unsigned>
2144 analyze(TokenAnnotator &Annotator,
2145 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2146 FormatTokenLexer &Tokens)
override {
2147 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2148 tooling::Replacements Result;
2149 requoteJSStringLiteral(AnnotatedLines, Result);
2156 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
2157 tooling::Replacements &Result) {
2158 for (AnnotatedLine *Line : Lines) {
2159 requoteJSStringLiteral(Line->Children, Result);
2160 if (!Line->Affected)
2162 for (FormatToken *FormatTok = Line->First; FormatTok;
2163 FormatTok = FormatTok->Next) {
2164 StringRef Input = FormatTok->TokenText;
2165 if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
2169 !Input.startswith(
"\"")) ||
2171 !Input.startswith(
"\'"))) {
2177 SourceLocation Start = FormatTok->Tok.getLocation();
2178 auto Replace = [&](SourceLocation Start,
unsigned Length,
2179 StringRef ReplacementText) {
2180 auto Err = Result.add(tooling::Replacement(
2181 Env.getSourceManager(), Start, Length, ReplacementText));
2185 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
2189 Replace(Start, 1, IsSingle ?
"'" :
"\"");
2190 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
2191 IsSingle ?
"'" :
"\"");
2194 bool Escaped =
false;
2195 for (
size_t i = 1; i < Input.size() - 1; i++) {
2198 if (!Escaped && i + 1 < Input.size() &&
2199 ((IsSingle && Input[i + 1] ==
'"') ||
2200 (!IsSingle && Input[i + 1] ==
'\''))) {
2203 Replace(Start.getLocWithOffset(i), 1,
"");
2210 if (!Escaped && IsSingle == (Input[i] ==
'\'')) {
2212 Replace(Start.getLocWithOffset(i), 0,
"\\");
2226class Formatter :
public TokenAnalyzer {
2229 FormattingAttemptStatus *Status)
2230 : TokenAnalyzer(
Env, Style), Status(Status) {}
2232 std::pair<tooling::Replacements, unsigned>
2233 analyze(TokenAnnotator &Annotator,
2234 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2235 FormatTokenLexer &Tokens)
override {
2236 tooling::Replacements Result;
2237 deriveLocalStyle(AnnotatedLines);
2238 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2239 for (AnnotatedLine *Line : AnnotatedLines)
2240 Annotator.calculateFormattingInformation(*Line);
2241 Annotator.setCommentLineLevels(AnnotatedLines);
2243 WhitespaceManager Whitespaces(
2244 Env.getSourceManager(), Style,
2246 ? WhitespaceManager::inputUsesCRLF(
2247 Env.getSourceManager().getBufferData(
Env.getFileID()),
2248 Style.
LineEnding == FormatStyle::LE_DeriveCRLF)
2250 ContinuationIndenter
Indenter(Style, Tokens.getKeywords(),
2251 Env.getSourceManager(), Whitespaces, Encoding,
2252 BinPackInconclusiveFunctions);
2254 UnwrappedLineFormatter(&
Indenter, &Whitespaces, Style,
2255 Tokens.getKeywords(),
Env.getSourceManager(),
2257 .format(AnnotatedLines,
false,
2260 Env.getFirstStartColumn(),
2261 Env.getNextStartColumn(),
2262 Env.getLastStartColumn());
2263 for (
const auto &R : Whitespaces.generateReplacements())
2265 return std::make_pair(Result, 0);
2266 return std::make_pair(Result, Penalty);
2271 hasCpp03IncompatibleFormat(
const SmallVectorImpl<AnnotatedLine *> &Lines) {
2272 for (
const AnnotatedLine *Line : Lines) {
2273 if (hasCpp03IncompatibleFormat(Line->Children))
2275 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {
2276 if (!Tok->hasWhitespaceBefore()) {
2277 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
2279 if (Tok->is(TT_TemplateCloser) &&
2280 Tok->Previous->is(TT_TemplateCloser)) {
2289 int countVariableAlignments(
const SmallVectorImpl<AnnotatedLine *> &Lines) {
2290 int AlignmentDiff = 0;
2291 for (
const AnnotatedLine *Line : Lines) {
2292 AlignmentDiff += countVariableAlignments(Line->Children);
2293 for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {
2294 if (!Tok->is(TT_PointerOrReference))
2297 if (
const auto *Prev = Tok->getPreviousNonComment()) {
2298 if (Prev->is(tok::r_paren) && Prev->MatchingParen) {
2299 if (
const auto *Func =
2300 Prev->MatchingParen->getPreviousNonComment()) {
2301 if (Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName,
2302 TT_OverloadedOperator)) {
2308 bool SpaceBefore = Tok->hasWhitespaceBefore();
2309 bool SpaceAfter = Tok->Next->hasWhitespaceBefore();
2310 if (SpaceBefore && !SpaceAfter)
2312 if (!SpaceBefore && SpaceAfter)
2316 return AlignmentDiff;
2320 deriveLocalStyle(
const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2321 bool HasBinPackedFunction =
false;
2322 bool HasOnePerLineFunction =
false;
2323 for (AnnotatedLine *Line : AnnotatedLines) {
2324 if (!Line->First->Next)
2326 FormatToken *Tok = Line->First->Next;
2328 if (Tok->is(PPK_BinPacked))
2329 HasBinPackedFunction =
true;
2330 if (Tok->is(PPK_OnePerLine))
2331 HasOnePerLineFunction =
true;
2337 const auto NetRightCount = countVariableAlignments(AnnotatedLines);
2338 if (NetRightCount > 0)
2340 else if (NetRightCount < 0)
2344 if (Style.
Standard == FormatStyle::LS_Auto) {
2345 Style.
Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
2346 ? FormatStyle::LS_Latest
2347 : FormatStyle::LS_Cpp03;
2349 BinPackInconclusiveFunctions =
2350 HasBinPackedFunction || !HasOnePerLineFunction;
2353 bool BinPackInconclusiveFunctions;
2354 FormattingAttemptStatus *Status;
2368class TrailingCommaInserter :
public TokenAnalyzer {
2370 TrailingCommaInserter(
const Environment &
Env,
const FormatStyle &Style)
2371 : TokenAnalyzer(
Env, Style) {}
2373 std::pair<tooling::Replacements, unsigned>
2374 analyze(TokenAnnotator &Annotator,
2375 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2376 FormatTokenLexer &Tokens)
override {
2377 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2378 tooling::Replacements Result;
2379 insertTrailingCommas(AnnotatedLines, Result);
2386 void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,
2387 tooling::Replacements &Result) {
2388 for (AnnotatedLine *Line : Lines) {
2389 insertTrailingCommas(Line->Children, Result);
2390 if (!Line->Affected)
2392 for (FormatToken *FormatTok = Line->First; FormatTok;
2393 FormatTok = FormatTok->Next) {
2394 if (FormatTok->NewlinesBefore == 0)
2396 FormatToken *Matching = FormatTok->MatchingParen;
2397 if (!Matching || !FormatTok->getPreviousNonComment())
2399 if (!(FormatTok->is(tok::r_square) &&
2400 Matching->is(TT_ArrayInitializerLSquare)) &&
2401 !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) {
2404 FormatToken *Prev = FormatTok->getPreviousNonComment();
2405 if (Prev->is(tok::comma) || Prev->is(tok::semi))
2409 SourceLocation Start =
2410 Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size());
2414 unsigned ColumnNumber =
2415 Env.getSourceManager().getSpellingColumnNumber(Start);
2420 cantFail(Result.add(
2421 tooling::Replacement(
Env.getSourceManager(), Start, 0,
",")));
2429class Cleaner :
public TokenAnalyzer {
2432 : TokenAnalyzer(
Env, Style),
2433 DeletedTokens(FormatTokenLess(
Env.getSourceManager())) {}
2436 std::pair<tooling::Replacements, unsigned>
2437 analyze(TokenAnnotator &Annotator,
2438 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2439 FormatTokenLexer &Tokens)
override {
2447 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2449 checkEmptyNamespace(AnnotatedLines);
2451 for (
auto *Line : AnnotatedLines)
2454 return {generateFixes(), 0};
2458 void cleanupLine(AnnotatedLine *Line) {
2459 for (
auto *Child : Line->Children)
2462 if (Line->Affected) {
2463 cleanupRight(Line->First, tok::comma, tok::comma);
2464 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
2465 cleanupRight(Line->First, tok::l_paren, tok::comma);
2466 cleanupLeft(Line->First, tok::comma, tok::r_paren);
2467 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
2468 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
2469 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
2473 bool containsOnlyComments(
const AnnotatedLine &Line) {
2474 for (FormatToken *Tok = Line.First; Tok; Tok = Tok->Next)
2475 if (Tok->isNot(tok::comment))
2481 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2482 std::set<unsigned> DeletedLines;
2483 for (
unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
2484 auto &Line = *AnnotatedLines[i];
2485 if (Line.startsWithNamespace())
2486 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
2489 for (
auto Line : DeletedLines) {
2490 FormatToken *Tok = AnnotatedLines[Line]->First;
2502 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2503 unsigned CurrentLine,
unsigned &
NewLine,
2504 std::set<unsigned> &DeletedLines) {
2505 unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
2510 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
2514 }
else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
2517 while (++CurrentLine < End) {
2518 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
2521 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
2522 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine,
NewLine,
2530 if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
2540 if (CurrentLine >= End)
2544 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
2545 AnnotatedLines[InitLine]->First->Tok.getLocation(),
2546 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) {
2550 for (
unsigned i = InitLine; i <= CurrentLine; ++i)
2551 DeletedLines.insert(i);
2560 template <
typename LeftKind,
typename RightKind>
2561 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
2563 auto NextNotDeleted = [
this](
const FormatToken &Tok) -> FormatToken * {
2564 for (
auto *Res = Tok.Next; Res; Res = Res->Next) {
2565 if (!Res->is(tok::comment) &&
2566 DeletedTokens.find(Res) == DeletedTokens.end()) {
2572 for (
auto *Left = Start; Left;) {
2573 auto *Right = NextNotDeleted(*Left);
2576 if (Left->is(LK) && Right->is(RK)) {
2577 deleteToken(DeleteLeft ? Left : Right);
2578 for (
auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
2589 template <
typename LeftKind,
typename RightKind>
2590 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
2591 cleanupPair(Start, LK, RK,
true);
2594 template <
typename LeftKind,
typename RightKind>
2595 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
2596 cleanupPair(Start, LK, RK,
false);
2600 inline void deleteToken(FormatToken *Tok) {
2602 DeletedTokens.insert(Tok);
2605 tooling::Replacements generateFixes() {
2606 tooling::Replacements Fixes;
2607 SmallVector<FormatToken *> Tokens;
2608 std::copy(DeletedTokens.begin(), DeletedTokens.end(),
2609 std::back_inserter(Tokens));
2615 while (Idx < Tokens.size()) {
2616 unsigned St = Idx, End = Idx;
2617 while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1])
2619 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
2620 Tokens[End]->Tok.getEndLoc());
2622 Fixes.add(tooling::Replacement(
Env.getSourceManager(), SR,
""));
2626 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
2627 assert(
false &&
"Fixes must not conflict!");
2638 struct FormatTokenLess {
2639 FormatTokenLess(
const SourceManager &
SM) :
SM(
SM) {}
2641 bool operator()(
const FormatToken *LHS,
const FormatToken *RHS)
const {
2642 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
2643 RHS->Tok.getLocation());
2649 std::set<FormatToken *, FormatTokenLess> DeletedTokens;
2652class ObjCHeaderStyleGuesser :
public TokenAnalyzer {
2654 ObjCHeaderStyleGuesser(
const Environment &
Env,
const FormatStyle &Style)
2655 : TokenAnalyzer(
Env, Style), IsObjC(
false) {}
2657 std::pair<tooling::Replacements, unsigned>
2658 analyze(TokenAnnotator &Annotator,
2659 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2660 FormatTokenLexer &Tokens)
override {
2661 assert(Style.
Language == FormatStyle::LK_Cpp);
2662 IsObjC = guessIsObjC(
Env.getSourceManager(), AnnotatedLines,
2663 Tokens.getKeywords());
2664 tooling::Replacements Result;
2668 bool isObjC() {
return IsObjC; }
2672 guessIsObjC(
const SourceManager &SourceManager,
2673 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2674 const AdditionalKeywords &Keywords) {
2676 static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
2691 "FOUNDATION_EXPORT",
2692 "FOUNDATION_EXTERN",
2693 "NSAffineTransform",
2695 "NSAttributedString",
2714 "NSInvocationOperation",
2718 "NSMutableAttributedString",
2719 "NSMutableCharacterSet",
2721 "NSMutableDictionary",
2722 "NSMutableIndexSet",
2723 "NSMutableOrderedSet",
2727 "NSNumberFormatter",
2731 "NSOperationQueuePriority",
2735 "NSQualityOfService",
2738 "NSRegularExpression",
2749 "NS_ASSUME_NONNULL_BEGIN",
2754 for (
auto *Line : AnnotatedLines) {
2755 if (Line->First && (Line->First->TokenText.startswith(
"#") ||
2756 Line->First->TokenText ==
"__pragma" ||
2757 Line->First->TokenText ==
"_Pragma")) {
2760 for (
const FormatToken *FormatTok = Line->First; FormatTok;
2761 FormatTok = FormatTok->Next) {
2762 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
2763 (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
2764 FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
2766 (FormatTok->Tok.isAnyIdentifier() &&
2767 std::binary_search(std::begin(FoundationIdentifiers),
2768 std::end(FoundationIdentifiers),
2769 FormatTok->TokenText)) ||
2770 FormatTok->is(TT_ObjCStringLiteral) ||
2771 FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,
2772 Keywords.kw_NS_ERROR_ENUM,
2773 Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,
2774 TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,
2775 TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,
2777 LLVM_DEBUG(llvm::dbgs()
2778 <<
"Detected ObjC at location "
2779 << FormatTok->Tok.getLocation().printToString(
2781 <<
" token: " << FormatTok->TokenText <<
" token type: "
2785 if (guessIsObjC(SourceManager, Line->Children, Keywords))
2803struct JavaImportDirective {
2816 for (
const auto &Range : Ranges) {
2817 if (Range.getOffset() < End &&
2818 Range.getOffset() + Range.getLength() > Start) {
2832static std::pair<unsigned, unsigned>
2836 unsigned OffsetToEOL = 0;
2837 for (
int i = 0, e = Includes.size(); i != e; ++i) {
2838 unsigned Start = Includes[Indices[i]].Offset;
2839 unsigned End = Start + Includes[Indices[i]].Text.size();
2840 if (!(Cursor >= Start && Cursor < End))
2842 CursorIndex = Indices[i];
2843 OffsetToEOL = End - Cursor;
2846 while (--i >= 0 && Includes[CursorIndex].
Text == Includes[Indices[i]].
Text)
2850 return std::make_pair(CursorIndex, OffsetToEOL);
2855 std::string NewCode;
2856 size_t Pos = 0, LastPos = 0;
2859 Pos = Code.find(
"\r\n", LastPos);
2860 if (Pos == LastPos) {
2864 if (Pos == std::string::npos) {
2865 NewCode += Code.substr(LastPos);
2868 NewCode += Code.substr(LastPos, Pos - LastPos) +
"\n";
2870 }
while (Pos != std::string::npos);
2888 const unsigned IncludesBeginOffset = Includes.front().Offset;
2889 const unsigned IncludesEndOffset =
2890 Includes.back().Offset + Includes.back().Text.size();
2891 const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
2892 if (!
affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
2895 llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size()));
2898 llvm::stable_sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
2899 const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
2900 const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
2901 return std::tie(Includes[LHSI].
Priority, LHSFilenameLower,
2903 std::tie(Includes[RHSI].
Priority, RHSFilenameLower,
2907 llvm::stable_sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
2915 unsigned CursorIndex;
2917 unsigned CursorToEOLOffset;
2919 std::tie(CursorIndex, CursorToEOLOffset) =
2924 Indices.erase(std::unique(Indices.begin(), Indices.end(),
2925 [&](
unsigned LHSI,
unsigned RHSI) {
2926 return Includes[LHSI].Text.trim() ==
2927 Includes[RHSI].Text.trim();
2931 int CurrentCategory = Includes.front().Category;
2939 if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) &&
2945 for (
unsigned Index : Indices) {
2946 if (!result.empty()) {
2950 CurrentCategory != Includes[Index].Category) {
2954 result += Includes[Index].Text;
2955 if (Cursor && CursorIndex == Index)
2956 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
2957 CurrentCategory = Includes[Index].Category;
2960 if (Cursor && *Cursor >= IncludesEndOffset)
2961 *Cursor += result.size() - IncludesBlockSize;
2966 IncludesBeginOffset, IncludesBlockSize)))) {
2971 FileName, Includes.front().Offset, IncludesBlockSize, result));
2975 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
2985 unsigned Prev = llvm::StringSwitch<size_t>(Code)
2986 .StartsWith(
"\xEF\xBB\xBF", 3)
2988 unsigned SearchFrom = 0;
3000 bool FirstIncludeBlock =
true;
3001 bool MainIncludeFound =
false;
3002 bool FormattingOff =
false;
3005 llvm::Regex RawStringRegex(
3006 "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\(");
3008 std::string RawStringTermination =
")\"";
3011 auto Pos = Code.find(
'\n', SearchFrom);
3013 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3015 StringRef Trimmed = Line.trim();
3020 if (RawStringRegex.match(Trimmed, &RawStringMatches)) {
3021 std::string CharSequence = RawStringMatches[1].str();
3022 RawStringTermination =
")" + CharSequence +
"\"";
3023 FormattingOff =
true;
3026 if (Trimmed.contains(RawStringTermination))
3027 FormattingOff =
false;
3030 FormattingOff =
true;
3032 FormattingOff =
false;
3034 const bool EmptyLineSkipped =
3040 bool MergeWithNextLine = Trimmed.endswith(
"\\");
3041 if (!FormattingOff && !MergeWithNextLine) {
3043 StringRef IncludeName = Matches[2];
3044 if (Line.contains(
"/*") && !Line.contains(
"*/")) {
3049 Pos = Code.find(
"*/", SearchFrom);
3051 Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev);
3055 !MainIncludeFound && FirstIncludeBlock);
3057 IncludeName, !MainIncludeFound && FirstIncludeBlock);
3059 MainIncludeFound =
true;
3060 IncludesInBlock.push_back(
3062 }
else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
3065 IncludesInBlock.clear();
3066 if (Trimmed.startswith(
"#pragma hdrstop"))
3067 FirstIncludeBlock =
true;
3069 FirstIncludeBlock =
false;
3072 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3075 if (!MergeWithNextLine)
3077 SearchFrom = Pos + 1;
3079 if (!IncludesInBlock.empty()) {
3080 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces,
3089 StringRef ImportIdentifier) {
3090 unsigned LongestMatchIndex =
UINT_MAX;
3091 unsigned LongestMatchLength = 0;
3094 if (ImportIdentifier.startswith(GroupPrefix) &&
3095 GroupPrefix.length() > LongestMatchLength) {
3096 LongestMatchIndex = I;
3097 LongestMatchLength = GroupPrefix.length();
3100 return LongestMatchIndex;
3112 unsigned ImportsBeginOffset = Imports.front().Offset;
3113 unsigned ImportsEndOffset =
3114 Imports.back().Offset + Imports.back().Text.size();
3115 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;
3116 if (!
affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))
3120 llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size()));
3123 for (
const JavaImportDirective &Import : Imports)
3126 bool StaticImportAfterNormalImport =
3128 llvm::sort(Indices, [&](
unsigned LHSI,
unsigned RHSI) {
3130 return std::make_tuple(!Imports[LHSI].
IsStatic ^
3131 StaticImportAfterNormalImport,
3133 std::make_tuple(!Imports[RHSI].
IsStatic ^
3134 StaticImportAfterNormalImport,
3139 Indices.erase(std::unique(Indices.begin(), Indices.end(),
3140 [&](
unsigned LHSI,
unsigned RHSI) {
3141 return Imports[LHSI].Text == Imports[RHSI].Text;
3145 bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
3149 for (
unsigned Index : Indices) {
3150 if (!result.empty()) {
3152 if (CurrentIsStatic != Imports[Index].
IsStatic ||
3158 result += CommentLine;
3161 result += Imports[Index].Text;
3162 CurrentIsStatic = Imports[Index].IsStatic;
3169 Imports.front().Offset, ImportsBlockSize)))) {
3174 ImportsBlockSize, result));
3178 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
3185const char JavaImportRegexPattern[] =
3186 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;";
3195 unsigned SearchFrom = 0;
3196 llvm::Regex ImportRegex(JavaImportRegexPattern);
3201 bool FormattingOff =
false;
3204 auto Pos = Code.find(
'\n', SearchFrom);
3206 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3208 StringRef Trimmed = Line.trim();
3210 FormattingOff =
true;
3212 FormattingOff =
false;
3214 if (ImportRegex.match(Line, &Matches)) {
3215 if (FormattingOff) {
3220 StringRef Static = Matches[1];
3223 if (Static.contains(
"static"))
3225 ImportsInBlock.push_back(
3228 }
else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) {
3233 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3235 SearchFrom = Pos + 1;
3237 if (!ImportsInBlock.empty())
3238 sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces);
3246 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
3249bool isLikelyXml(StringRef Code) {
return Code.ltrim().startswith(
"<"); }
3253 StringRef FileName,
unsigned *Cursor) {
3271template <
typename T>
3276 if (Replaces.
empty())
3279 auto NewCode = applyAllReplacements(Code, Replaces);
3281 return NewCode.takeError();
3283 StringRef FileName = Replaces.
begin()->getFilePath();
3286 ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
3288 return Replaces.
merge(FormatReplaces);
3297 std::vector<tooling::Range> Ranges,
3301 auto SortedReplaces =
3303 if (!SortedReplaces)
3304 return SortedReplaces.takeError();
3308 auto Reformat = [](
const FormatStyle &Style, StringRef Code,
3309 std::vector<tooling::Range> Ranges,
3311 return reformat(Style, Code, Ranges, FileName);
3324inline bool isHeaderDeletion(
const tooling::Replacement &Replace) {
3325 return Replace.getOffset() ==
UINT_MAX && Replace.getLength() == 1;
3329tooling::Replacements
3330fixCppIncludeInsertions(StringRef Code,
const tooling::Replacements &Replaces,
3335 tooling::Replacements HeaderInsertions;
3336 std::set<llvm::StringRef> HeadersToDelete;
3337 tooling::Replacements
Result;
3338 for (
const auto &R : Replaces) {
3339 if (isHeaderInsertion(R)) {
3342 llvm::consumeError(HeaderInsertions.add(R));
3343 }
else if (isHeaderDeletion(R)) {
3344 HeadersToDelete.insert(R.getReplacementText());
3345 }
else if (R.getOffset() ==
UINT_MAX) {
3346 llvm::errs() <<
"Insertions other than header #include insertion are "
3348 << R.getReplacementText() <<
"\n";
3350 llvm::consumeError(
Result.add(R));
3353 if (HeaderInsertions.empty() && HeadersToDelete.empty())
3356 StringRef FileName = Replaces.begin()->getFilePath();
3357 tooling::HeaderIncludes Includes(FileName, Code, Style.
IncludeStyle);
3359 for (
const auto &Header : HeadersToDelete) {
3360 tooling::Replacements Replaces =
3361 Includes.remove(Header.trim(
"\"<>"), Header.startswith(
"<"));
3362 for (
const auto &R : Replaces) {
3363 auto Err =
Result.add(R);
3366 llvm::errs() <<
"Failed to add header deletion replacement for "
3367 << Header <<
": " << llvm::toString(std::move(Err))
3374 for (
const auto &R : HeaderInsertions) {
3378 assert(Matched &&
"Header insertion replacement must have replacement text "
3381 auto IncludeName = Matches[2];
3383 Includes.insert(IncludeName.trim(
"\"<>"), IncludeName.startswith(
"<"),
3386 auto Err =
Result.add(*Replace);
3388 llvm::consumeError(std::move(Err));
3389 unsigned NewOffset =
3390 Result.getShiftedCodePosition(Replace->getOffset());
3391 auto Shifted = tooling::Replacement(FileName, NewOffset, 0,
3392 Replace->getReplacementText());
3407 auto Cleanup = [](
const FormatStyle &Style, StringRef Code,
3408 std::vector<tooling::Range> Ranges,
3410 return cleanup(Style, Code, Ranges, FileName);
3414 fixCppIncludeInsertions(Code, Replaces, Style);
3419std::pair<tooling::Replacements, unsigned>
3422 unsigned NextStartColumn,
unsigned LastStartColumn, StringRef FileName,
3431 case FormatStyle::RCPS_SingleLine:
3432 case FormatStyle::RCPS_WithPreceding:
3448 std::vector<tooling::Range> Ranges(1,
tooling::Range(0, Code.size()));
3449 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
3450 NextStartColumn, LastStartColumn);
3455 Formatter(*
Env, Style, Status).process().first;
3457 Replaces = Replaces.
merge(
3460 if (applyAllReplacements(Code, Replaces))
3461 return {Replaces, 0};
3465 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
3466 NextStartColumn, LastStartColumn);
3470 typedef std::function<std::pair<tooling::Replacements, unsigned>(
3479 if (Style.
isCpp()) {
3483 FirstStartColumn, NextStartColumn,
3484 LastStartColumn, FileName)
3491 S.InsertBraces =
true;
3492 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3493 return BracesInserter(
Env, S).process(
true);
3499 S.RemoveBracesLLVM =
true;
3500 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3501 return BracesRemover(
Env, S).process(
true);
3507 S.RemoveSemicolon =
true;
3508 Passes.emplace_back([&, S = std::move(S)](
const Environment &
Env) {
3509 return SemiRemover(
Env, S).process(
true);
3535 return JavaScriptRequoter(
Env, Expanded).process(
true);
3540 return Formatter(
Env, Expanded, Status).process();
3546 return TrailingCommaInserter(
Env, Expanded).process();
3550 std::optional<std::string> CurrentCode;
3552 unsigned Penalty = 0;
3553 for (
size_t I = 0, E = Passes.size(); I < E; ++I) {
3554 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
3555 auto NewCode = applyAllReplacements(
3556 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
3558 Fixes = Fixes.
merge(PassFixes.first);
3559 Penalty += PassFixes.second;
3561 CurrentCode = std::move(*NewCode);
3562 Env = Environment::make(
3563 *CurrentCode, FileName,
3564 tooling::calculateRangesAfterReplacements(Fixes, Ranges),
3565 FirstStartColumn, NextStartColumn, LastStartColumn);
3572 return {Fixes, Penalty};
3583 0, FileName, Status)
3589 StringRef FileName) {
3596 return Cleaner(*
Env, Style).process().first;
3601 StringRef FileName,
bool *IncompleteFormat) {
3604 if (!Status.FormatComplete)
3605 *IncompleteFormat =
true;
3612 StringRef FileName) {
3622 StringRef FileName) {
3632 StringRef FileName) {
3647 LangOpts.CPlusPlus = 1;
3658 LangOpts.LineComment = 1;
3659 bool AlternativeOperators = Style.
isCpp();
3660 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
3663 LangOpts.MicrosoftExt = 1;
3664 LangOpts.DeclSpecKeyword = 1;
3670 "Set coding style. <string> can be:\n"
3671 "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"
3672 " Mozilla, WebKit.\n"
3673 "2. 'file' to load style configuration from a\n"
3674 " .clang-format file in one of the parent directories\n"
3675 " of the source file (for stdin, see --assume-filename).\n"
3676 " If no .clang-format file is found, falls back to\n"
3677 " --fallback-style.\n"
3678 " --style=file is the default.\n"
3679 "3. 'file:<format_file_path>' to explicitly specify\n"
3680 " the configuration file.\n"
3681 "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n"
3682 " --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
3685 if (FileName.endswith(
".java"))
3687 if (FileName.ends_with_insensitive(
".js") ||
3688 FileName.ends_with_insensitive(
".mjs") ||
3689 FileName.ends_with_insensitive(
".ts")) {
3692 if (FileName.endswith(
".m") || FileName.endswith(
".mm"))
3694 if (FileName.ends_with_insensitive(
".proto") ||
3695 FileName.ends_with_insensitive(
".protodevel")) {
3698 if (FileName.ends_with_insensitive(
".textpb") ||
3699 FileName.ends_with_insensitive(
".pb.txt") ||
3700 FileName.ends_with_insensitive(
".textproto") ||
3701 FileName.ends_with_insensitive(
".asciipb")) {
3704 if (FileName.ends_with_insensitive(
".td"))
3706 if (FileName.ends_with_insensitive(
".cs"))
3708 if (FileName.ends_with_insensitive(
".json"))
3710 if (FileName.ends_with_insensitive(
".sv") ||
3711 FileName.ends_with_insensitive(
".svh") ||
3712 FileName.ends_with_insensitive(
".v") ||
3713 FileName.ends_with_insensitive(
".vh")) {
3722 auto Extension = llvm::sys::path::extension(FileName);
3725 if (Extension.empty() || Extension ==
".h") {
3726 auto NonEmptyFileName = FileName.empty() ?
"guess.h" : FileName;
3730 if (Guesser.isObjC())
3734 return GuessedLanguage;
3742llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
3745 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
3746 FS->getBufferForFile(ConfigFile.str());
3747 if (
auto EC =
Text.getError())
3755 StringRef FallbackStyleName,
3756 StringRef Code, llvm::vfs::FileSystem *FS,
3757 bool AllowUnknownOptions) {
3759 FS = llvm::vfs::getRealFileSystem().get();
3767 ChildFormatTextToApply;
3769 if (StyleName.startswith(
"{")) {
3771 StringRef Source =
"<command-line>";
3772 if (std::error_code ec =
3774 AllowUnknownOptions)) {
3778 ChildFormatTextToApply.emplace_back(
3779 llvm::MemoryBuffer::getMemBuffer(StyleName, Source,
false));
3787 StyleName.starts_with_insensitive(
"file:")) {
3788 auto ConfigFile = StyleName.substr(5);
3789 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
3791 if (
auto EC =
Text.getError()) {
3796 LLVM_DEBUG(llvm::dbgs()
3797 <<
"Using configuration file " << ConfigFile <<
"\n");
3804 FileName = ConfigFile;
3805 ChildFormatTextToApply.emplace_back(std::move(*
Text));
3824 if (std::error_code EC = FS->makeAbsolute(Path))
3828 FilesToLookFor.push_back(
".clang-format");
3829 FilesToLookFor.push_back(
"_clang-format");
3831 auto dropDiagnosticHandler = [](
const llvm::SMDiagnostic &,
void *) {};
3833 auto applyChildFormatTexts = [&](
FormatStyle *Style) {
3834 for (
const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) {
3836 dropDiagnosticHandler);
3839 static_cast<void>(EC);
3843 for (StringRef Directory = Path; !Directory.empty();
3844 Directory = llvm::sys::path::parent_path(Directory)) {
3846 auto Status = FS->status(Directory);
3848 Status->getType() != llvm::sys::fs::file_type::directory_file) {
3852 for (
const auto &F : FilesToLookFor) {
3855 llvm::sys::path::append(ConfigFile, F);
3856 LLVM_DEBUG(llvm::dbgs() <<
"Trying " << ConfigFile <<
"...\n");
3858 Status = FS->status(ConfigFile.str());
3861 (Status->getType() == llvm::sys::fs::file_type::regular_file)) {
3862 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
3864 if (
auto EC =
Text.getError()) {
3866 if (!UnsuitableConfigFiles.empty())
3867 UnsuitableConfigFiles.append(
", ");
3868 UnsuitableConfigFiles.append(ConfigFile);
3874 LLVM_DEBUG(llvm::dbgs()
3875 <<
"Using configuration file " << ConfigFile <<
"\n");
3878 if (ChildFormatTextToApply.empty())
3881 LLVM_DEBUG(llvm::dbgs() <<
"Applying child configurations\n");
3882 applyChildFormatTexts(&Style);
3887 LLVM_DEBUG(llvm::dbgs() <<
"Inherits parent configuration\n");
3892 ChildFormatTextToApply.emplace_back(std::move(*
Text));
3902 if (!UnsuitableConfigFiles.empty()) {
3905 UnsuitableConfigFiles);
3908 if (!ChildFormatTextToApply.empty()) {
3909 LLVM_DEBUG(llvm::dbgs()
3910 <<
"Applying child configurations on fallback style\n");
3911 applyChildFormatTexts(&FallbackStyle);
3914 return FallbackStyle;
3918 if (Comment == (On ?
"/* clang-format on */" :
"/* clang-format off */"))
3921 static const char ClangFormatOn[] =
"// clang-format on";
3922 static const char ClangFormatOff[] =
"// clang-format off";
3923 const unsigned Size = (On ?
sizeof ClangFormatOn :
sizeof ClangFormatOff) - 1;
3925 return Comment.startswith(On ? ClangFormatOn : ClangFormatOff) &&
3926 (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 LeftRightQualifierAlignmentFixer, a TokenAnalyzer that enforces either east or wes...
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.
@ C
Languages that the frontend can parse and compile.
@ Result
The result type of a method or function.
YAML serialization mapping.