1 //===--- Format.cpp - Format C++ code -------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file implements functions declared in Format.h. This will be 11 /// split into separate files as we go. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "clang/Format/Format.h" 16 #include "DefinitionBlockSeparator.h" 17 #include "IntegerLiteralSeparatorFixer.h" 18 #include "NamespaceEndCommentsFixer.h" 19 #include "ObjCPropertyAttributeOrderFixer.h" 20 #include "QualifierAlignmentFixer.h" 21 #include "SortJavaScriptImports.h" 22 #include "UnwrappedLineFormatter.h" 23 #include "UsingDeclarationsSorter.h" 24 #include "clang/Tooling/Inclusions/HeaderIncludes.h" 25 #include "llvm/ADT/Sequence.h" 26 #include <limits> 27 28 #define DEBUG_TYPE "format-formatter" 29 30 using clang::format::FormatStyle; 31 32 LLVM_YAML_IS_SEQUENCE_VECTOR(FormatStyle::RawStringFormat) 33 34 namespace llvm { 35 namespace yaml { 36 template <> 37 struct ScalarEnumerationTraits<FormatStyle::BreakBeforeNoexceptSpecifierStyle> { 38 static void 39 enumeration(IO &IO, FormatStyle::BreakBeforeNoexceptSpecifierStyle &Value) { 40 IO.enumCase(Value, "Never", FormatStyle::BBNSS_Never); 41 IO.enumCase(Value, "OnlyWithParen", FormatStyle::BBNSS_OnlyWithParen); 42 IO.enumCase(Value, "Always", FormatStyle::BBNSS_Always); 43 } 44 }; 45 46 template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> { 47 static void enumInput(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) { 48 IO.enumCase(Value, "None", FormatStyle::AlignConsecutiveStyle({})); 49 IO.enumCase(Value, "Consecutive", 50 FormatStyle::AlignConsecutiveStyle( 51 {/*Enabled=*/true, /*AcrossEmptyLines=*/false, 52 /*AcrossComments=*/false, /*AlignCompound=*/false, 53 /*AlignFunctionDeclarations=*/true, 54 /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); 55 IO.enumCase(Value, "AcrossEmptyLines", 56 FormatStyle::AlignConsecutiveStyle( 57 {/*Enabled=*/true, /*AcrossEmptyLines=*/true, 58 /*AcrossComments=*/false, /*AlignCompound=*/false, 59 /*AlignFunctionDeclarations=*/true, 60 /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); 61 IO.enumCase(Value, "AcrossComments", 62 FormatStyle::AlignConsecutiveStyle( 63 {/*Enabled=*/true, /*AcrossEmptyLines=*/false, 64 /*AcrossComments=*/true, /*AlignCompound=*/false, 65 /*AlignFunctionDeclarations=*/true, 66 /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); 67 IO.enumCase(Value, "AcrossEmptyLinesAndComments", 68 FormatStyle::AlignConsecutiveStyle( 69 {/*Enabled=*/true, /*AcrossEmptyLines=*/true, 70 /*AcrossComments=*/true, /*AlignCompound=*/false, 71 /*AlignFunctionDeclarations=*/true, 72 /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); 73 74 // For backward compatibility. 75 IO.enumCase(Value, "true", 76 FormatStyle::AlignConsecutiveStyle( 77 {/*Enabled=*/true, /*AcrossEmptyLines=*/false, 78 /*AcrossComments=*/false, /*AlignCompound=*/false, 79 /*AlignFunctionDeclarations=*/true, 80 /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); 81 IO.enumCase(Value, "false", FormatStyle::AlignConsecutiveStyle({})); 82 } 83 84 static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) { 85 IO.mapOptional("Enabled", Value.Enabled); 86 IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines); 87 IO.mapOptional("AcrossComments", Value.AcrossComments); 88 IO.mapOptional("AlignCompound", Value.AlignCompound); 89 IO.mapOptional("AlignFunctionDeclarations", 90 Value.AlignFunctionDeclarations); 91 IO.mapOptional("AlignFunctionPointers", Value.AlignFunctionPointers); 92 IO.mapOptional("PadOperators", Value.PadOperators); 93 } 94 }; 95 96 template <> 97 struct MappingTraits<FormatStyle::ShortCaseStatementsAlignmentStyle> { 98 static void mapping(IO &IO, 99 FormatStyle::ShortCaseStatementsAlignmentStyle &Value) { 100 IO.mapOptional("Enabled", Value.Enabled); 101 IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines); 102 IO.mapOptional("AcrossComments", Value.AcrossComments); 103 IO.mapOptional("AlignCaseArrows", Value.AlignCaseArrows); 104 IO.mapOptional("AlignCaseColons", Value.AlignCaseColons); 105 } 106 }; 107 108 template <> 109 struct ScalarEnumerationTraits<FormatStyle::AttributeBreakingStyle> { 110 static void enumeration(IO &IO, FormatStyle::AttributeBreakingStyle &Value) { 111 IO.enumCase(Value, "Always", FormatStyle::ABS_Always); 112 IO.enumCase(Value, "Leave", FormatStyle::ABS_Leave); 113 IO.enumCase(Value, "Never", FormatStyle::ABS_Never); 114 } 115 }; 116 117 template <> 118 struct ScalarEnumerationTraits<FormatStyle::ArrayInitializerAlignmentStyle> { 119 static void enumeration(IO &IO, 120 FormatStyle::ArrayInitializerAlignmentStyle &Value) { 121 IO.enumCase(Value, "None", FormatStyle::AIAS_None); 122 IO.enumCase(Value, "Left", FormatStyle::AIAS_Left); 123 IO.enumCase(Value, "Right", FormatStyle::AIAS_Right); 124 } 125 }; 126 127 template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> { 128 static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) { 129 IO.enumCase(Value, "All", FormatStyle::BOS_All); 130 IO.enumCase(Value, "true", FormatStyle::BOS_All); 131 IO.enumCase(Value, "None", FormatStyle::BOS_None); 132 IO.enumCase(Value, "false", FormatStyle::BOS_None); 133 IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment); 134 } 135 }; 136 137 template <> 138 struct ScalarEnumerationTraits<FormatStyle::BinPackParametersStyle> { 139 static void enumeration(IO &IO, FormatStyle::BinPackParametersStyle &Value) { 140 IO.enumCase(Value, "BinPack", FormatStyle::BPPS_BinPack); 141 IO.enumCase(Value, "OnePerLine", FormatStyle::BPPS_OnePerLine); 142 IO.enumCase(Value, "AlwaysOnePerLine", FormatStyle::BPPS_AlwaysOnePerLine); 143 144 // For backward compatibility. 145 IO.enumCase(Value, "true", FormatStyle::BPPS_BinPack); 146 IO.enumCase(Value, "false", FormatStyle::BPPS_OnePerLine); 147 } 148 }; 149 150 template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> { 151 static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) { 152 IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto); 153 IO.enumCase(Value, "Always", FormatStyle::BPS_Always); 154 IO.enumCase(Value, "Never", FormatStyle::BPS_Never); 155 } 156 }; 157 158 template <> 159 struct ScalarEnumerationTraits<FormatStyle::BitFieldColonSpacingStyle> { 160 static void enumeration(IO &IO, 161 FormatStyle::BitFieldColonSpacingStyle &Value) { 162 IO.enumCase(Value, "Both", FormatStyle::BFCS_Both); 163 IO.enumCase(Value, "None", FormatStyle::BFCS_None); 164 IO.enumCase(Value, "Before", FormatStyle::BFCS_Before); 165 IO.enumCase(Value, "After", FormatStyle::BFCS_After); 166 } 167 }; 168 169 template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> { 170 static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) { 171 IO.enumCase(Value, "Attach", FormatStyle::BS_Attach); 172 IO.enumCase(Value, "Linux", FormatStyle::BS_Linux); 173 IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla); 174 IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup); 175 IO.enumCase(Value, "Allman", FormatStyle::BS_Allman); 176 IO.enumCase(Value, "Whitesmiths", FormatStyle::BS_Whitesmiths); 177 IO.enumCase(Value, "GNU", FormatStyle::BS_GNU); 178 IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit); 179 IO.enumCase(Value, "Custom", FormatStyle::BS_Custom); 180 } 181 }; 182 183 template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> { 184 static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) { 185 IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel); 186 IO.mapOptional("AfterClass", Wrapping.AfterClass); 187 IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement); 188 IO.mapOptional("AfterEnum", Wrapping.AfterEnum); 189 IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock); 190 IO.mapOptional("AfterFunction", Wrapping.AfterFunction); 191 IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace); 192 IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration); 193 IO.mapOptional("AfterStruct", Wrapping.AfterStruct); 194 IO.mapOptional("AfterUnion", Wrapping.AfterUnion); 195 IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch); 196 IO.mapOptional("BeforeElse", Wrapping.BeforeElse); 197 IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody); 198 IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile); 199 IO.mapOptional("IndentBraces", Wrapping.IndentBraces); 200 IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction); 201 IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord); 202 IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace); 203 } 204 }; 205 206 template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> { 207 static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) { 208 IO.enumCase(Value, "Align", FormatStyle::BAS_Align); 209 IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign); 210 IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak); 211 IO.enumCase(Value, "BlockIndent", FormatStyle::BAS_BlockIndent); 212 213 // For backward compatibility. 214 IO.enumCase(Value, "true", FormatStyle::BAS_Align); 215 IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign); 216 } 217 }; 218 219 template <> 220 struct ScalarEnumerationTraits< 221 FormatStyle::BraceWrappingAfterControlStatementStyle> { 222 static void 223 enumeration(IO &IO, 224 FormatStyle::BraceWrappingAfterControlStatementStyle &Value) { 225 IO.enumCase(Value, "Never", FormatStyle::BWACS_Never); 226 IO.enumCase(Value, "MultiLine", FormatStyle::BWACS_MultiLine); 227 IO.enumCase(Value, "Always", FormatStyle::BWACS_Always); 228 229 // For backward compatibility. 230 IO.enumCase(Value, "false", FormatStyle::BWACS_Never); 231 IO.enumCase(Value, "true", FormatStyle::BWACS_Always); 232 } 233 }; 234 235 template <> 236 struct ScalarEnumerationTraits< 237 FormatStyle::BreakBeforeConceptDeclarationsStyle> { 238 static void 239 enumeration(IO &IO, FormatStyle::BreakBeforeConceptDeclarationsStyle &Value) { 240 IO.enumCase(Value, "Never", FormatStyle::BBCDS_Never); 241 IO.enumCase(Value, "Allowed", FormatStyle::BBCDS_Allowed); 242 IO.enumCase(Value, "Always", FormatStyle::BBCDS_Always); 243 244 // For backward compatibility. 245 IO.enumCase(Value, "true", FormatStyle::BBCDS_Always); 246 IO.enumCase(Value, "false", FormatStyle::BBCDS_Allowed); 247 } 248 }; 249 250 template <> 251 struct ScalarEnumerationTraits<FormatStyle::BreakBeforeInlineASMColonStyle> { 252 static void enumeration(IO &IO, 253 FormatStyle::BreakBeforeInlineASMColonStyle &Value) { 254 IO.enumCase(Value, "Never", FormatStyle::BBIAS_Never); 255 IO.enumCase(Value, "OnlyMultiline", FormatStyle::BBIAS_OnlyMultiline); 256 IO.enumCase(Value, "Always", FormatStyle::BBIAS_Always); 257 } 258 }; 259 260 template <> 261 struct ScalarEnumerationTraits<FormatStyle::BreakBinaryOperationsStyle> { 262 static void enumeration(IO &IO, 263 FormatStyle::BreakBinaryOperationsStyle &Value) { 264 IO.enumCase(Value, "Never", FormatStyle::BBO_Never); 265 IO.enumCase(Value, "OnePerLine", FormatStyle::BBO_OnePerLine); 266 IO.enumCase(Value, "RespectPrecedence", FormatStyle::BBO_RespectPrecedence); 267 } 268 }; 269 270 template <> 271 struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> { 272 static void 273 enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) { 274 IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon); 275 IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma); 276 IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon); 277 } 278 }; 279 280 template <> 281 struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> { 282 static void enumeration(IO &IO, 283 FormatStyle::BreakInheritanceListStyle &Value) { 284 IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon); 285 IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma); 286 IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon); 287 IO.enumCase(Value, "AfterComma", FormatStyle::BILS_AfterComma); 288 } 289 }; 290 291 template <> 292 struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> { 293 static void enumeration(IO &IO, 294 FormatStyle::BreakTemplateDeclarationsStyle &Value) { 295 IO.enumCase(Value, "Leave", FormatStyle::BTDS_Leave); 296 IO.enumCase(Value, "No", FormatStyle::BTDS_No); 297 IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine); 298 IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes); 299 300 // For backward compatibility. 301 IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine); 302 IO.enumCase(Value, "true", FormatStyle::BTDS_Yes); 303 } 304 }; 305 306 template <> struct ScalarEnumerationTraits<FormatStyle::DAGArgStyle> { 307 static void enumeration(IO &IO, FormatStyle::DAGArgStyle &Value) { 308 IO.enumCase(Value, "DontBreak", FormatStyle::DAS_DontBreak); 309 IO.enumCase(Value, "BreakElements", FormatStyle::DAS_BreakElements); 310 IO.enumCase(Value, "BreakAll", FormatStyle::DAS_BreakAll); 311 } 312 }; 313 314 template <> 315 struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> { 316 static void 317 enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) { 318 IO.enumCase(Value, "None", FormatStyle::DRTBS_None); 319 IO.enumCase(Value, "All", FormatStyle::DRTBS_All); 320 IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel); 321 322 // For backward compatibility. 323 IO.enumCase(Value, "false", FormatStyle::DRTBS_None); 324 IO.enumCase(Value, "true", FormatStyle::DRTBS_All); 325 } 326 }; 327 328 template <> 329 struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> { 330 static void enumeration(IO &IO, 331 FormatStyle::EscapedNewlineAlignmentStyle &Value) { 332 IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign); 333 IO.enumCase(Value, "Left", FormatStyle::ENAS_Left); 334 IO.enumCase(Value, "LeftWithLastLine", FormatStyle::ENAS_LeftWithLastLine); 335 IO.enumCase(Value, "Right", FormatStyle::ENAS_Right); 336 337 // For backward compatibility. 338 IO.enumCase(Value, "true", FormatStyle::ENAS_Left); 339 IO.enumCase(Value, "false", FormatStyle::ENAS_Right); 340 } 341 }; 342 343 template <> 344 struct ScalarEnumerationTraits<FormatStyle::EmptyLineAfterAccessModifierStyle> { 345 static void 346 enumeration(IO &IO, FormatStyle::EmptyLineAfterAccessModifierStyle &Value) { 347 IO.enumCase(Value, "Never", FormatStyle::ELAAMS_Never); 348 IO.enumCase(Value, "Leave", FormatStyle::ELAAMS_Leave); 349 IO.enumCase(Value, "Always", FormatStyle::ELAAMS_Always); 350 } 351 }; 352 353 template <> 354 struct ScalarEnumerationTraits< 355 FormatStyle::EmptyLineBeforeAccessModifierStyle> { 356 static void 357 enumeration(IO &IO, FormatStyle::EmptyLineBeforeAccessModifierStyle &Value) { 358 IO.enumCase(Value, "Never", FormatStyle::ELBAMS_Never); 359 IO.enumCase(Value, "Leave", FormatStyle::ELBAMS_Leave); 360 IO.enumCase(Value, "LogicalBlock", FormatStyle::ELBAMS_LogicalBlock); 361 IO.enumCase(Value, "Always", FormatStyle::ELBAMS_Always); 362 } 363 }; 364 365 template <> 366 struct ScalarEnumerationTraits<FormatStyle::EnumTrailingCommaStyle> { 367 static void enumeration(IO &IO, FormatStyle::EnumTrailingCommaStyle &Value) { 368 IO.enumCase(Value, "Leave", FormatStyle::ETC_Leave); 369 IO.enumCase(Value, "Insert", FormatStyle::ETC_Insert); 370 IO.enumCase(Value, "Remove", FormatStyle::ETC_Remove); 371 } 372 }; 373 374 template <> 375 struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> { 376 static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value) { 377 IO.enumCase(Value, "AfterExternBlock", FormatStyle::IEBS_AfterExternBlock); 378 IO.enumCase(Value, "Indent", FormatStyle::IEBS_Indent); 379 IO.enumCase(Value, "NoIndent", FormatStyle::IEBS_NoIndent); 380 IO.enumCase(Value, "true", FormatStyle::IEBS_Indent); 381 IO.enumCase(Value, "false", FormatStyle::IEBS_NoIndent); 382 } 383 }; 384 385 template <> struct MappingTraits<FormatStyle::IntegerLiteralSeparatorStyle> { 386 static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &Base) { 387 IO.mapOptional("Binary", Base.Binary); 388 IO.mapOptional("BinaryMinDigits", Base.BinaryMinDigits); 389 IO.mapOptional("Decimal", Base.Decimal); 390 IO.mapOptional("DecimalMinDigits", Base.DecimalMinDigits); 391 IO.mapOptional("Hex", Base.Hex); 392 IO.mapOptional("HexMinDigits", Base.HexMinDigits); 393 } 394 }; 395 396 template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> { 397 static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) { 398 IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave); 399 IO.enumCase(Value, "Single", FormatStyle::JSQS_Single); 400 IO.enumCase(Value, "Double", FormatStyle::JSQS_Double); 401 } 402 }; 403 404 template <> struct MappingTraits<FormatStyle::KeepEmptyLinesStyle> { 405 static void mapping(IO &IO, FormatStyle::KeepEmptyLinesStyle &Value) { 406 IO.mapOptional("AtEndOfFile", Value.AtEndOfFile); 407 IO.mapOptional("AtStartOfBlock", Value.AtStartOfBlock); 408 IO.mapOptional("AtStartOfFile", Value.AtStartOfFile); 409 } 410 }; 411 412 template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> { 413 static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) { 414 IO.enumCase(Value, "C", FormatStyle::LK_C); 415 IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp); 416 IO.enumCase(Value, "Java", FormatStyle::LK_Java); 417 IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript); 418 IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC); 419 IO.enumCase(Value, "Proto", FormatStyle::LK_Proto); 420 IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen); 421 IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto); 422 IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp); 423 IO.enumCase(Value, "Json", FormatStyle::LK_Json); 424 IO.enumCase(Value, "Verilog", FormatStyle::LK_Verilog); 425 } 426 }; 427 428 template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> { 429 static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) { 430 IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03); 431 IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias 432 IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias 433 434 IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11); 435 IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias 436 437 IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14); 438 IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17); 439 IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20); 440 441 IO.enumCase(Value, "Latest", FormatStyle::LS_Latest); 442 IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias 443 IO.enumCase(Value, "Auto", FormatStyle::LS_Auto); 444 } 445 }; 446 447 template <> 448 struct ScalarEnumerationTraits<FormatStyle::LambdaBodyIndentationKind> { 449 static void enumeration(IO &IO, 450 FormatStyle::LambdaBodyIndentationKind &Value) { 451 IO.enumCase(Value, "Signature", FormatStyle::LBI_Signature); 452 IO.enumCase(Value, "OuterScope", FormatStyle::LBI_OuterScope); 453 } 454 }; 455 456 template <> struct ScalarEnumerationTraits<FormatStyle::LineEndingStyle> { 457 static void enumeration(IO &IO, FormatStyle::LineEndingStyle &Value) { 458 IO.enumCase(Value, "LF", FormatStyle::LE_LF); 459 IO.enumCase(Value, "CRLF", FormatStyle::LE_CRLF); 460 IO.enumCase(Value, "DeriveLF", FormatStyle::LE_DeriveLF); 461 IO.enumCase(Value, "DeriveCRLF", FormatStyle::LE_DeriveCRLF); 462 } 463 }; 464 465 template <> 466 struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> { 467 static void enumeration(IO &IO, 468 FormatStyle::NamespaceIndentationKind &Value) { 469 IO.enumCase(Value, "None", FormatStyle::NI_None); 470 IO.enumCase(Value, "Inner", FormatStyle::NI_Inner); 471 IO.enumCase(Value, "All", FormatStyle::NI_All); 472 } 473 }; 474 475 template <> struct ScalarEnumerationTraits<FormatStyle::OperandAlignmentStyle> { 476 static void enumeration(IO &IO, FormatStyle::OperandAlignmentStyle &Value) { 477 IO.enumCase(Value, "DontAlign", FormatStyle::OAS_DontAlign); 478 IO.enumCase(Value, "Align", FormatStyle::OAS_Align); 479 IO.enumCase(Value, "AlignAfterOperator", 480 FormatStyle::OAS_AlignAfterOperator); 481 482 // For backward compatibility. 483 IO.enumCase(Value, "true", FormatStyle::OAS_Align); 484 IO.enumCase(Value, "false", FormatStyle::OAS_DontAlign); 485 } 486 }; 487 488 template <> 489 struct ScalarEnumerationTraits<FormatStyle::PackConstructorInitializersStyle> { 490 static void 491 enumeration(IO &IO, FormatStyle::PackConstructorInitializersStyle &Value) { 492 IO.enumCase(Value, "Never", FormatStyle::PCIS_Never); 493 IO.enumCase(Value, "BinPack", FormatStyle::PCIS_BinPack); 494 IO.enumCase(Value, "CurrentLine", FormatStyle::PCIS_CurrentLine); 495 IO.enumCase(Value, "NextLine", FormatStyle::PCIS_NextLine); 496 IO.enumCase(Value, "NextLineOnly", FormatStyle::PCIS_NextLineOnly); 497 } 498 }; 499 500 template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> { 501 static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) { 502 IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle); 503 IO.enumCase(Value, "Left", FormatStyle::PAS_Left); 504 IO.enumCase(Value, "Right", FormatStyle::PAS_Right); 505 506 // For backward compatibility. 507 IO.enumCase(Value, "true", FormatStyle::PAS_Left); 508 IO.enumCase(Value, "false", FormatStyle::PAS_Right); 509 } 510 }; 511 512 template <> 513 struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> { 514 static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) { 515 IO.enumCase(Value, "None", FormatStyle::PPDIS_None); 516 IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash); 517 IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash); 518 } 519 }; 520 521 template <> 522 struct ScalarEnumerationTraits<FormatStyle::QualifierAlignmentStyle> { 523 static void enumeration(IO &IO, FormatStyle::QualifierAlignmentStyle &Value) { 524 IO.enumCase(Value, "Leave", FormatStyle::QAS_Leave); 525 IO.enumCase(Value, "Left", FormatStyle::QAS_Left); 526 IO.enumCase(Value, "Right", FormatStyle::QAS_Right); 527 IO.enumCase(Value, "Custom", FormatStyle::QAS_Custom); 528 } 529 }; 530 531 template <> struct MappingTraits<FormatStyle::RawStringFormat> { 532 static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) { 533 IO.mapOptional("Language", Format.Language); 534 IO.mapOptional("Delimiters", Format.Delimiters); 535 IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions); 536 IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter); 537 IO.mapOptional("BasedOnStyle", Format.BasedOnStyle); 538 } 539 }; 540 541 template <> struct ScalarEnumerationTraits<FormatStyle::ReflowCommentsStyle> { 542 static void enumeration(IO &IO, FormatStyle::ReflowCommentsStyle &Value) { 543 IO.enumCase(Value, "Never", FormatStyle::RCS_Never); 544 IO.enumCase(Value, "IndentOnly", FormatStyle::RCS_IndentOnly); 545 IO.enumCase(Value, "Always", FormatStyle::RCS_Always); 546 // For backward compatibility: 547 IO.enumCase(Value, "false", FormatStyle::RCS_Never); 548 IO.enumCase(Value, "true", FormatStyle::RCS_Always); 549 } 550 }; 551 552 template <> 553 struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> { 554 static void enumeration(IO &IO, FormatStyle::ReferenceAlignmentStyle &Value) { 555 IO.enumCase(Value, "Pointer", FormatStyle::RAS_Pointer); 556 IO.enumCase(Value, "Middle", FormatStyle::RAS_Middle); 557 IO.enumCase(Value, "Left", FormatStyle::RAS_Left); 558 IO.enumCase(Value, "Right", FormatStyle::RAS_Right); 559 } 560 }; 561 562 template <> 563 struct ScalarEnumerationTraits<FormatStyle::RemoveParenthesesStyle> { 564 static void enumeration(IO &IO, FormatStyle::RemoveParenthesesStyle &Value) { 565 IO.enumCase(Value, "Leave", FormatStyle::RPS_Leave); 566 IO.enumCase(Value, "MultipleParentheses", 567 FormatStyle::RPS_MultipleParentheses); 568 IO.enumCase(Value, "ReturnStatement", FormatStyle::RPS_ReturnStatement); 569 } 570 }; 571 572 template <> 573 struct ScalarEnumerationTraits<FormatStyle::RequiresClausePositionStyle> { 574 static void enumeration(IO &IO, 575 FormatStyle::RequiresClausePositionStyle &Value) { 576 IO.enumCase(Value, "OwnLine", FormatStyle::RCPS_OwnLine); 577 IO.enumCase(Value, "OwnLineWithBrace", FormatStyle::RCPS_OwnLineWithBrace); 578 IO.enumCase(Value, "WithPreceding", FormatStyle::RCPS_WithPreceding); 579 IO.enumCase(Value, "WithFollowing", FormatStyle::RCPS_WithFollowing); 580 IO.enumCase(Value, "SingleLine", FormatStyle::RCPS_SingleLine); 581 } 582 }; 583 584 template <> 585 struct ScalarEnumerationTraits<FormatStyle::RequiresExpressionIndentationKind> { 586 static void 587 enumeration(IO &IO, FormatStyle::RequiresExpressionIndentationKind &Value) { 588 IO.enumCase(Value, "Keyword", FormatStyle::REI_Keyword); 589 IO.enumCase(Value, "OuterScope", FormatStyle::REI_OuterScope); 590 } 591 }; 592 593 template <> 594 struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> { 595 static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) { 596 IO.enumCase(Value, "None", FormatStyle::RTBS_None); 597 IO.enumCase(Value, "Automatic", FormatStyle::RTBS_Automatic); 598 IO.enumCase(Value, "ExceptShortType", FormatStyle::RTBS_ExceptShortType); 599 IO.enumCase(Value, "All", FormatStyle::RTBS_All); 600 IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel); 601 IO.enumCase(Value, "TopLevelDefinitions", 602 FormatStyle::RTBS_TopLevelDefinitions); 603 IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions); 604 } 605 }; 606 607 template <> 608 struct ScalarEnumerationTraits<FormatStyle::SeparateDefinitionStyle> { 609 static void enumeration(IO &IO, FormatStyle::SeparateDefinitionStyle &Value) { 610 IO.enumCase(Value, "Leave", FormatStyle::SDS_Leave); 611 IO.enumCase(Value, "Always", FormatStyle::SDS_Always); 612 IO.enumCase(Value, "Never", FormatStyle::SDS_Never); 613 } 614 }; 615 616 template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> { 617 static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) { 618 IO.enumCase(Value, "Never", FormatStyle::SBS_Never); 619 IO.enumCase(Value, "false", FormatStyle::SBS_Never); 620 IO.enumCase(Value, "Always", FormatStyle::SBS_Always); 621 IO.enumCase(Value, "true", FormatStyle::SBS_Always); 622 IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty); 623 } 624 }; 625 626 template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> { 627 static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) { 628 IO.enumCase(Value, "None", FormatStyle::SFS_None); 629 IO.enumCase(Value, "false", FormatStyle::SFS_None); 630 IO.enumCase(Value, "All", FormatStyle::SFS_All); 631 IO.enumCase(Value, "true", FormatStyle::SFS_All); 632 IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline); 633 IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly); 634 IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty); 635 } 636 }; 637 638 template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> { 639 static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) { 640 IO.enumCase(Value, "Never", FormatStyle::SIS_Never); 641 IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse); 642 IO.enumCase(Value, "OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf); 643 IO.enumCase(Value, "AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse); 644 645 // For backward compatibility. 646 IO.enumCase(Value, "Always", FormatStyle::SIS_OnlyFirstIf); 647 IO.enumCase(Value, "false", FormatStyle::SIS_Never); 648 IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse); 649 } 650 }; 651 652 template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> { 653 static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) { 654 IO.enumCase(Value, "None", FormatStyle::SLS_None); 655 IO.enumCase(Value, "false", FormatStyle::SLS_None); 656 IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty); 657 IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline); 658 IO.enumCase(Value, "All", FormatStyle::SLS_All); 659 IO.enumCase(Value, "true", FormatStyle::SLS_All); 660 } 661 }; 662 663 template <> struct MappingTraits<FormatStyle::SortIncludesOptions> { 664 static void enumInput(IO &IO, FormatStyle::SortIncludesOptions &Value) { 665 IO.enumCase(Value, "Never", FormatStyle::SortIncludesOptions({})); 666 IO.enumCase(Value, "CaseInsensitive", 667 FormatStyle::SortIncludesOptions({/*Enabled=*/true, 668 /*IgnoreCase=*/true})); 669 IO.enumCase(Value, "CaseSensitive", 670 FormatStyle::SortIncludesOptions({/*Enabled=*/true, 671 /*IgnoreCase=*/false})); 672 673 // For backward compatibility. 674 IO.enumCase(Value, "false", FormatStyle::SortIncludesOptions({})); 675 IO.enumCase(Value, "true", 676 FormatStyle::SortIncludesOptions({/*Enabled=*/true, 677 /*IgnoreCase=*/false})); 678 } 679 680 static void mapping(IO &IO, FormatStyle::SortIncludesOptions &Value) { 681 IO.mapOptional("Enabled", Value.Enabled); 682 IO.mapOptional("IgnoreCase", Value.IgnoreCase); 683 } 684 }; 685 686 template <> 687 struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> { 688 static void enumeration(IO &IO, 689 FormatStyle::SortJavaStaticImportOptions &Value) { 690 IO.enumCase(Value, "Before", FormatStyle::SJSIO_Before); 691 IO.enumCase(Value, "After", FormatStyle::SJSIO_After); 692 } 693 }; 694 695 template <> 696 struct ScalarEnumerationTraits<FormatStyle::SortUsingDeclarationsOptions> { 697 static void enumeration(IO &IO, 698 FormatStyle::SortUsingDeclarationsOptions &Value) { 699 IO.enumCase(Value, "Never", FormatStyle::SUD_Never); 700 IO.enumCase(Value, "Lexicographic", FormatStyle::SUD_Lexicographic); 701 IO.enumCase(Value, "LexicographicNumeric", 702 FormatStyle::SUD_LexicographicNumeric); 703 704 // For backward compatibility. 705 IO.enumCase(Value, "false", FormatStyle::SUD_Never); 706 IO.enumCase(Value, "true", FormatStyle::SUD_LexicographicNumeric); 707 } 708 }; 709 710 template <> 711 struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> { 712 static void 713 enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value) { 714 IO.enumCase(Value, "Default", FormatStyle::SAPQ_Default); 715 IO.enumCase(Value, "Before", FormatStyle::SAPQ_Before); 716 IO.enumCase(Value, "After", FormatStyle::SAPQ_After); 717 IO.enumCase(Value, "Both", FormatStyle::SAPQ_Both); 718 } 719 }; 720 721 template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> { 722 static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) { 723 IO.mapOptional("AfterControlStatements", Spacing.AfterControlStatements); 724 IO.mapOptional("AfterForeachMacros", Spacing.AfterForeachMacros); 725 IO.mapOptional("AfterFunctionDefinitionName", 726 Spacing.AfterFunctionDefinitionName); 727 IO.mapOptional("AfterFunctionDeclarationName", 728 Spacing.AfterFunctionDeclarationName); 729 IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros); 730 IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator); 731 IO.mapOptional("AfterPlacementOperator", Spacing.AfterPlacementOperator); 732 IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause); 733 IO.mapOptional("AfterRequiresInExpression", 734 Spacing.AfterRequiresInExpression); 735 IO.mapOptional("BeforeNonEmptyParentheses", 736 Spacing.BeforeNonEmptyParentheses); 737 } 738 }; 739 740 template <> 741 struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> { 742 static void enumeration(IO &IO, FormatStyle::SpaceBeforeParensStyle &Value) { 743 IO.enumCase(Value, "Never", FormatStyle::SBPO_Never); 744 IO.enumCase(Value, "ControlStatements", 745 FormatStyle::SBPO_ControlStatements); 746 IO.enumCase(Value, "ControlStatementsExceptControlMacros", 747 FormatStyle::SBPO_ControlStatementsExceptControlMacros); 748 IO.enumCase(Value, "NonEmptyParentheses", 749 FormatStyle::SBPO_NonEmptyParentheses); 750 IO.enumCase(Value, "Always", FormatStyle::SBPO_Always); 751 IO.enumCase(Value, "Custom", FormatStyle::SBPO_Custom); 752 753 // For backward compatibility. 754 IO.enumCase(Value, "false", FormatStyle::SBPO_Never); 755 IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements); 756 IO.enumCase(Value, "ControlStatementsExceptForEachMacros", 757 FormatStyle::SBPO_ControlStatementsExceptControlMacros); 758 } 759 }; 760 761 template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> { 762 static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value) { 763 IO.enumCase(Value, "Never", FormatStyle::SIAS_Never); 764 IO.enumCase(Value, "Always", FormatStyle::SIAS_Always); 765 IO.enumCase(Value, "Leave", FormatStyle::SIAS_Leave); 766 767 // For backward compatibility. 768 IO.enumCase(Value, "false", FormatStyle::SIAS_Never); 769 IO.enumCase(Value, "true", FormatStyle::SIAS_Always); 770 } 771 }; 772 773 template <> struct MappingTraits<FormatStyle::SpacesInLineComment> { 774 static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) { 775 // Transform the maximum to signed, to parse "-1" correctly 776 int signedMaximum = static_cast<int>(Space.Maximum); 777 IO.mapOptional("Minimum", Space.Minimum); 778 IO.mapOptional("Maximum", signedMaximum); 779 Space.Maximum = static_cast<unsigned>(signedMaximum); 780 781 if (Space.Maximum < std::numeric_limits<unsigned>::max()) 782 Space.Minimum = std::min(Space.Minimum, Space.Maximum); 783 } 784 }; 785 786 template <> struct MappingTraits<FormatStyle::SpacesInParensCustom> { 787 static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) { 788 IO.mapOptional("ExceptDoubleParentheses", Spaces.ExceptDoubleParentheses); 789 IO.mapOptional("InCStyleCasts", Spaces.InCStyleCasts); 790 IO.mapOptional("InConditionalStatements", Spaces.InConditionalStatements); 791 IO.mapOptional("InEmptyParentheses", Spaces.InEmptyParentheses); 792 IO.mapOptional("Other", Spaces.Other); 793 } 794 }; 795 796 template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInParensStyle> { 797 static void enumeration(IO &IO, FormatStyle::SpacesInParensStyle &Value) { 798 IO.enumCase(Value, "Never", FormatStyle::SIPO_Never); 799 IO.enumCase(Value, "Custom", FormatStyle::SIPO_Custom); 800 } 801 }; 802 803 template <> struct ScalarEnumerationTraits<FormatStyle::TrailingCommaStyle> { 804 static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) { 805 IO.enumCase(Value, "None", FormatStyle::TCS_None); 806 IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped); 807 } 808 }; 809 810 template <> 811 struct ScalarEnumerationTraits<FormatStyle::TrailingCommentsAlignmentKinds> { 812 static void enumeration(IO &IO, 813 FormatStyle::TrailingCommentsAlignmentKinds &Value) { 814 IO.enumCase(Value, "Leave", FormatStyle::TCAS_Leave); 815 IO.enumCase(Value, "Always", FormatStyle::TCAS_Always); 816 IO.enumCase(Value, "Never", FormatStyle::TCAS_Never); 817 } 818 }; 819 820 template <> struct MappingTraits<FormatStyle::TrailingCommentsAlignmentStyle> { 821 static void enumInput(IO &IO, 822 FormatStyle::TrailingCommentsAlignmentStyle &Value) { 823 IO.enumCase(Value, "Leave", 824 FormatStyle::TrailingCommentsAlignmentStyle( 825 {FormatStyle::TCAS_Leave, 0})); 826 827 IO.enumCase(Value, "Always", 828 FormatStyle::TrailingCommentsAlignmentStyle( 829 {FormatStyle::TCAS_Always, 0})); 830 831 IO.enumCase(Value, "Never", 832 FormatStyle::TrailingCommentsAlignmentStyle( 833 {FormatStyle::TCAS_Never, 0})); 834 835 // For backwards compatibility 836 IO.enumCase(Value, "true", 837 FormatStyle::TrailingCommentsAlignmentStyle( 838 {FormatStyle::TCAS_Always, 0})); 839 IO.enumCase(Value, "false", 840 FormatStyle::TrailingCommentsAlignmentStyle( 841 {FormatStyle::TCAS_Never, 0})); 842 } 843 844 static void mapping(IO &IO, 845 FormatStyle::TrailingCommentsAlignmentStyle &Value) { 846 IO.mapOptional("Kind", Value.Kind); 847 IO.mapOptional("OverEmptyLines", Value.OverEmptyLines); 848 } 849 }; 850 851 template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> { 852 static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) { 853 IO.enumCase(Value, "Never", FormatStyle::UT_Never); 854 IO.enumCase(Value, "false", FormatStyle::UT_Never); 855 IO.enumCase(Value, "Always", FormatStyle::UT_Always); 856 IO.enumCase(Value, "true", FormatStyle::UT_Always); 857 IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation); 858 IO.enumCase(Value, "ForContinuationAndIndentation", 859 FormatStyle::UT_ForContinuationAndIndentation); 860 IO.enumCase(Value, "AlignWithSpaces", FormatStyle::UT_AlignWithSpaces); 861 } 862 }; 863 864 template <> 865 struct ScalarEnumerationTraits< 866 FormatStyle::WrapNamespaceBodyWithEmptyLinesStyle> { 867 static void 868 enumeration(IO &IO, 869 FormatStyle::WrapNamespaceBodyWithEmptyLinesStyle &Value) { 870 IO.enumCase(Value, "Never", FormatStyle::WNBWELS_Never); 871 IO.enumCase(Value, "Always", FormatStyle::WNBWELS_Always); 872 IO.enumCase(Value, "Leave", FormatStyle::WNBWELS_Leave); 873 } 874 }; 875 876 template <> struct MappingTraits<FormatStyle> { 877 static void mapping(IO &IO, FormatStyle &Style) { 878 // When reading, read the language first, we need it for getPredefinedStyle. 879 IO.mapOptional("Language", Style.Language); 880 881 StringRef BasedOnStyle; 882 if (IO.outputting()) { 883 StringRef Styles[] = {"LLVM", "Google", "Chromium", "Mozilla", 884 "WebKit", "GNU", "Microsoft", "clang-format"}; 885 for (StringRef StyleName : Styles) { 886 FormatStyle PredefinedStyle; 887 if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) && 888 Style == PredefinedStyle) { 889 BasedOnStyle = StyleName; 890 break; 891 } 892 } 893 } else { 894 IO.mapOptional("BasedOnStyle", BasedOnStyle); 895 if (!BasedOnStyle.empty()) { 896 FormatStyle::LanguageKind OldLanguage = Style.Language; 897 FormatStyle::LanguageKind Language = 898 ((FormatStyle *)IO.getContext())->Language; 899 if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) { 900 IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle)); 901 return; 902 } 903 Style.Language = OldLanguage; 904 } 905 } 906 907 // Initialize some variables used in the parsing. The using logic is at the 908 // end. 909 910 // For backward compatibility: 911 // The default value of ConstructorInitializerAllOnOneLineOrOnePerLine was 912 // false unless BasedOnStyle was Google or Chromium whereas that of 913 // AllowAllConstructorInitializersOnNextLine was always true, so the 914 // equivalent default value of PackConstructorInitializers is PCIS_NextLine 915 // for Google/Chromium or PCIS_BinPack otherwise. If the deprecated options 916 // had a non-default value while PackConstructorInitializers has a default 917 // value, set the latter to an equivalent non-default value if needed. 918 const bool IsGoogleOrChromium = BasedOnStyle.equals_insensitive("google") || 919 BasedOnStyle.equals_insensitive("chromium"); 920 bool OnCurrentLine = IsGoogleOrChromium; 921 bool OnNextLine = true; 922 923 bool BreakBeforeInheritanceComma = false; 924 bool BreakConstructorInitializersBeforeComma = false; 925 926 bool DeriveLineEnding = true; 927 bool UseCRLF = false; 928 929 bool SpaceInEmptyParentheses = false; 930 bool SpacesInConditionalStatement = false; 931 bool SpacesInCStyleCastParentheses = false; 932 bool SpacesInParentheses = false; 933 934 // For backward compatibility. 935 if (!IO.outputting()) { 936 IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines); 937 IO.mapOptional("AllowAllConstructorInitializersOnNextLine", OnNextLine); 938 IO.mapOptional("AlwaysBreakAfterReturnType", Style.BreakAfterReturnType); 939 IO.mapOptional("AlwaysBreakTemplateDeclarations", 940 Style.BreakTemplateDeclarations); 941 IO.mapOptional("BreakBeforeInheritanceComma", 942 BreakBeforeInheritanceComma); 943 IO.mapOptional("BreakConstructorInitializersBeforeComma", 944 BreakConstructorInitializersBeforeComma); 945 IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine", 946 OnCurrentLine); 947 IO.mapOptional("DeriveLineEnding", DeriveLineEnding); 948 IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment); 949 IO.mapOptional("KeepEmptyLinesAtEOF", Style.KeepEmptyLines.AtEndOfFile); 950 IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks", 951 Style.KeepEmptyLines.AtStartOfBlock); 952 IO.mapOptional("IndentFunctionDeclarationAfterType", 953 Style.IndentWrappedFunctionNames); 954 IO.mapOptional("IndentRequires", Style.IndentRequiresClause); 955 IO.mapOptional("PointerBindsToType", Style.PointerAlignment); 956 IO.mapOptional("SpaceAfterControlStatementKeyword", 957 Style.SpaceBeforeParens); 958 IO.mapOptional("SpaceInEmptyParentheses", SpaceInEmptyParentheses); 959 IO.mapOptional("SpacesInConditionalStatement", 960 SpacesInConditionalStatement); 961 IO.mapOptional("SpacesInCStyleCastParentheses", 962 SpacesInCStyleCastParentheses); 963 IO.mapOptional("SpacesInParentheses", SpacesInParentheses); 964 IO.mapOptional("UseCRLF", UseCRLF); 965 } 966 967 IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset); 968 IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket); 969 IO.mapOptional("AlignArrayOfStructures", Style.AlignArrayOfStructures); 970 IO.mapOptional("AlignConsecutiveAssignments", 971 Style.AlignConsecutiveAssignments); 972 IO.mapOptional("AlignConsecutiveBitFields", 973 Style.AlignConsecutiveBitFields); 974 IO.mapOptional("AlignConsecutiveDeclarations", 975 Style.AlignConsecutiveDeclarations); 976 IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros); 977 IO.mapOptional("AlignConsecutiveShortCaseStatements", 978 Style.AlignConsecutiveShortCaseStatements); 979 IO.mapOptional("AlignConsecutiveTableGenBreakingDAGArgColons", 980 Style.AlignConsecutiveTableGenBreakingDAGArgColons); 981 IO.mapOptional("AlignConsecutiveTableGenCondOperatorColons", 982 Style.AlignConsecutiveTableGenCondOperatorColons); 983 IO.mapOptional("AlignConsecutiveTableGenDefinitionColons", 984 Style.AlignConsecutiveTableGenDefinitionColons); 985 IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines); 986 IO.mapOptional("AlignOperands", Style.AlignOperands); 987 IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments); 988 IO.mapOptional("AllowAllArgumentsOnNextLine", 989 Style.AllowAllArgumentsOnNextLine); 990 IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine", 991 Style.AllowAllParametersOfDeclarationOnNextLine); 992 IO.mapOptional("AllowBreakBeforeNoexceptSpecifier", 993 Style.AllowBreakBeforeNoexceptSpecifier); 994 IO.mapOptional("AllowShortBlocksOnASingleLine", 995 Style.AllowShortBlocksOnASingleLine); 996 IO.mapOptional("AllowShortCaseExpressionOnASingleLine", 997 Style.AllowShortCaseExpressionOnASingleLine); 998 IO.mapOptional("AllowShortCaseLabelsOnASingleLine", 999 Style.AllowShortCaseLabelsOnASingleLine); 1000 IO.mapOptional("AllowShortCompoundRequirementOnASingleLine", 1001 Style.AllowShortCompoundRequirementOnASingleLine); 1002 IO.mapOptional("AllowShortEnumsOnASingleLine", 1003 Style.AllowShortEnumsOnASingleLine); 1004 IO.mapOptional("AllowShortFunctionsOnASingleLine", 1005 Style.AllowShortFunctionsOnASingleLine); 1006 IO.mapOptional("AllowShortIfStatementsOnASingleLine", 1007 Style.AllowShortIfStatementsOnASingleLine); 1008 IO.mapOptional("AllowShortLambdasOnASingleLine", 1009 Style.AllowShortLambdasOnASingleLine); 1010 IO.mapOptional("AllowShortLoopsOnASingleLine", 1011 Style.AllowShortLoopsOnASingleLine); 1012 IO.mapOptional("AllowShortNamespacesOnASingleLine", 1013 Style.AllowShortNamespacesOnASingleLine); 1014 IO.mapOptional("AlwaysBreakAfterDefinitionReturnType", 1015 Style.AlwaysBreakAfterDefinitionReturnType); 1016 IO.mapOptional("AlwaysBreakBeforeMultilineStrings", 1017 Style.AlwaysBreakBeforeMultilineStrings); 1018 IO.mapOptional("AttributeMacros", Style.AttributeMacros); 1019 IO.mapOptional("BinPackArguments", Style.BinPackArguments); 1020 IO.mapOptional("BinPackLongBracedList", Style.BinPackLongBracedList); 1021 IO.mapOptional("BinPackParameters", Style.BinPackParameters); 1022 IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing); 1023 IO.mapOptional("BracedInitializerIndentWidth", 1024 Style.BracedInitializerIndentWidth); 1025 IO.mapOptional("BraceWrapping", Style.BraceWrapping); 1026 IO.mapOptional("BreakAdjacentStringLiterals", 1027 Style.BreakAdjacentStringLiterals); 1028 IO.mapOptional("BreakAfterAttributes", Style.BreakAfterAttributes); 1029 IO.mapOptional("BreakAfterJavaFieldAnnotations", 1030 Style.BreakAfterJavaFieldAnnotations); 1031 IO.mapOptional("BreakAfterReturnType", Style.BreakAfterReturnType); 1032 IO.mapOptional("BreakArrays", Style.BreakArrays); 1033 IO.mapOptional("BreakBeforeBinaryOperators", 1034 Style.BreakBeforeBinaryOperators); 1035 IO.mapOptional("BreakBeforeConceptDeclarations", 1036 Style.BreakBeforeConceptDeclarations); 1037 IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces); 1038 IO.mapOptional("BreakBeforeInlineASMColon", 1039 Style.BreakBeforeInlineASMColon); 1040 IO.mapOptional("BreakBeforeTemplateCloser", 1041 Style.BreakBeforeTemplateCloser); 1042 IO.mapOptional("BreakBeforeTernaryOperators", 1043 Style.BreakBeforeTernaryOperators); 1044 IO.mapOptional("BreakBinaryOperations", Style.BreakBinaryOperations); 1045 IO.mapOptional("BreakConstructorInitializers", 1046 Style.BreakConstructorInitializers); 1047 IO.mapOptional("BreakFunctionDefinitionParameters", 1048 Style.BreakFunctionDefinitionParameters); 1049 IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList); 1050 IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals); 1051 IO.mapOptional("BreakTemplateDeclarations", 1052 Style.BreakTemplateDeclarations); 1053 IO.mapOptional("ColumnLimit", Style.ColumnLimit); 1054 IO.mapOptional("CommentPragmas", Style.CommentPragmas); 1055 IO.mapOptional("CompactNamespaces", Style.CompactNamespaces); 1056 IO.mapOptional("ConstructorInitializerIndentWidth", 1057 Style.ConstructorInitializerIndentWidth); 1058 IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth); 1059 IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle); 1060 IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment); 1061 IO.mapOptional("DisableFormat", Style.DisableFormat); 1062 IO.mapOptional("EmptyLineAfterAccessModifier", 1063 Style.EmptyLineAfterAccessModifier); 1064 IO.mapOptional("EmptyLineBeforeAccessModifier", 1065 Style.EmptyLineBeforeAccessModifier); 1066 IO.mapOptional("EnumTrailingComma", Style.EnumTrailingComma); 1067 IO.mapOptional("ExperimentalAutoDetectBinPacking", 1068 Style.ExperimentalAutoDetectBinPacking); 1069 IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments); 1070 IO.mapOptional("ForEachMacros", Style.ForEachMacros); 1071 IO.mapOptional("IfMacros", Style.IfMacros); 1072 IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks); 1073 IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories); 1074 IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex); 1075 IO.mapOptional("IncludeIsMainSourceRegex", 1076 Style.IncludeStyle.IncludeIsMainSourceRegex); 1077 IO.mapOptional("IndentAccessModifiers", Style.IndentAccessModifiers); 1078 IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks); 1079 IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels); 1080 IO.mapOptional("IndentExportBlock", Style.IndentExportBlock); 1081 IO.mapOptional("IndentExternBlock", Style.IndentExternBlock); 1082 IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels); 1083 IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives); 1084 IO.mapOptional("IndentRequiresClause", Style.IndentRequiresClause); 1085 IO.mapOptional("IndentWidth", Style.IndentWidth); 1086 IO.mapOptional("IndentWrappedFunctionNames", 1087 Style.IndentWrappedFunctionNames); 1088 IO.mapOptional("InsertBraces", Style.InsertBraces); 1089 IO.mapOptional("InsertNewlineAtEOF", Style.InsertNewlineAtEOF); 1090 IO.mapOptional("InsertTrailingCommas", Style.InsertTrailingCommas); 1091 IO.mapOptional("IntegerLiteralSeparator", Style.IntegerLiteralSeparator); 1092 IO.mapOptional("JavaImportGroups", Style.JavaImportGroups); 1093 IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes); 1094 IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports); 1095 IO.mapOptional("KeepEmptyLines", Style.KeepEmptyLines); 1096 IO.mapOptional("KeepFormFeed", Style.KeepFormFeed); 1097 IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation); 1098 IO.mapOptional("LineEnding", Style.LineEnding); 1099 IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin); 1100 IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd); 1101 IO.mapOptional("Macros", Style.Macros); 1102 IO.mapOptional("MacrosSkippedByRemoveParentheses", 1103 Style.MacrosSkippedByRemoveParentheses); 1104 IO.mapOptional("MainIncludeChar", Style.IncludeStyle.MainIncludeChar); 1105 IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep); 1106 IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation); 1107 IO.mapOptional("NamespaceMacros", Style.NamespaceMacros); 1108 IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList); 1109 IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth); 1110 IO.mapOptional("ObjCBreakBeforeNestedBlockParam", 1111 Style.ObjCBreakBeforeNestedBlockParam); 1112 IO.mapOptional("ObjCPropertyAttributeOrder", 1113 Style.ObjCPropertyAttributeOrder); 1114 IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty); 1115 IO.mapOptional("ObjCSpaceBeforeProtocolList", 1116 Style.ObjCSpaceBeforeProtocolList); 1117 IO.mapOptional("OneLineFormatOffRegex", Style.OneLineFormatOffRegex); 1118 IO.mapOptional("PackConstructorInitializers", 1119 Style.PackConstructorInitializers); 1120 IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment); 1121 IO.mapOptional("PenaltyBreakBeforeFirstCallParameter", 1122 Style.PenaltyBreakBeforeFirstCallParameter); 1123 IO.mapOptional("PenaltyBreakBeforeMemberAccess", 1124 Style.PenaltyBreakBeforeMemberAccess); 1125 IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment); 1126 IO.mapOptional("PenaltyBreakFirstLessLess", 1127 Style.PenaltyBreakFirstLessLess); 1128 IO.mapOptional("PenaltyBreakOpenParenthesis", 1129 Style.PenaltyBreakOpenParenthesis); 1130 IO.mapOptional("PenaltyBreakScopeResolution", 1131 Style.PenaltyBreakScopeResolution); 1132 IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString); 1133 IO.mapOptional("PenaltyBreakTemplateDeclaration", 1134 Style.PenaltyBreakTemplateDeclaration); 1135 IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter); 1136 IO.mapOptional("PenaltyIndentedWhitespace", 1137 Style.PenaltyIndentedWhitespace); 1138 IO.mapOptional("PenaltyReturnTypeOnItsOwnLine", 1139 Style.PenaltyReturnTypeOnItsOwnLine); 1140 IO.mapOptional("PointerAlignment", Style.PointerAlignment); 1141 IO.mapOptional("PPIndentWidth", Style.PPIndentWidth); 1142 IO.mapOptional("QualifierAlignment", Style.QualifierAlignment); 1143 // Default Order for Left/Right based Qualifier alignment. 1144 if (Style.QualifierAlignment == FormatStyle::QAS_Right) 1145 Style.QualifierOrder = {"type", "const", "volatile"}; 1146 else if (Style.QualifierAlignment == FormatStyle::QAS_Left) 1147 Style.QualifierOrder = {"const", "volatile", "type"}; 1148 else if (Style.QualifierAlignment == FormatStyle::QAS_Custom) 1149 IO.mapOptional("QualifierOrder", Style.QualifierOrder); 1150 IO.mapOptional("RawStringFormats", Style.RawStringFormats); 1151 IO.mapOptional("ReferenceAlignment", Style.ReferenceAlignment); 1152 IO.mapOptional("ReflowComments", Style.ReflowComments); 1153 IO.mapOptional("RemoveBracesLLVM", Style.RemoveBracesLLVM); 1154 IO.mapOptional("RemoveEmptyLinesInUnwrappedLines", 1155 Style.RemoveEmptyLinesInUnwrappedLines); 1156 IO.mapOptional("RemoveParentheses", Style.RemoveParentheses); 1157 IO.mapOptional("RemoveSemicolon", Style.RemoveSemicolon); 1158 IO.mapOptional("RequiresClausePosition", Style.RequiresClausePosition); 1159 IO.mapOptional("RequiresExpressionIndentation", 1160 Style.RequiresExpressionIndentation); 1161 IO.mapOptional("SeparateDefinitionBlocks", Style.SeparateDefinitionBlocks); 1162 IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines); 1163 IO.mapOptional("SkipMacroDefinitionBody", Style.SkipMacroDefinitionBody); 1164 IO.mapOptional("SortIncludes", Style.SortIncludes); 1165 IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport); 1166 IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations); 1167 IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast); 1168 IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot); 1169 IO.mapOptional("SpaceAfterOperatorKeyword", 1170 Style.SpaceAfterOperatorKeyword); 1171 IO.mapOptional("SpaceAfterTemplateKeyword", 1172 Style.SpaceAfterTemplateKeyword); 1173 IO.mapOptional("SpaceAroundPointerQualifiers", 1174 Style.SpaceAroundPointerQualifiers); 1175 IO.mapOptional("SpaceBeforeAssignmentOperators", 1176 Style.SpaceBeforeAssignmentOperators); 1177 IO.mapOptional("SpaceBeforeCaseColon", Style.SpaceBeforeCaseColon); 1178 IO.mapOptional("SpaceBeforeCpp11BracedList", 1179 Style.SpaceBeforeCpp11BracedList); 1180 IO.mapOptional("SpaceBeforeCtorInitializerColon", 1181 Style.SpaceBeforeCtorInitializerColon); 1182 IO.mapOptional("SpaceBeforeInheritanceColon", 1183 Style.SpaceBeforeInheritanceColon); 1184 IO.mapOptional("SpaceBeforeJsonColon", Style.SpaceBeforeJsonColon); 1185 IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens); 1186 IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions); 1187 IO.mapOptional("SpaceBeforeRangeBasedForLoopColon", 1188 Style.SpaceBeforeRangeBasedForLoopColon); 1189 IO.mapOptional("SpaceBeforeSquareBrackets", 1190 Style.SpaceBeforeSquareBrackets); 1191 IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock); 1192 IO.mapOptional("SpacesBeforeTrailingComments", 1193 Style.SpacesBeforeTrailingComments); 1194 IO.mapOptional("SpacesInAngles", Style.SpacesInAngles); 1195 IO.mapOptional("SpacesInContainerLiterals", 1196 Style.SpacesInContainerLiterals); 1197 IO.mapOptional("SpacesInLineCommentPrefix", 1198 Style.SpacesInLineCommentPrefix); 1199 IO.mapOptional("SpacesInParens", Style.SpacesInParens); 1200 IO.mapOptional("SpacesInParensOptions", Style.SpacesInParensOptions); 1201 IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets); 1202 IO.mapOptional("Standard", Style.Standard); 1203 IO.mapOptional("StatementAttributeLikeMacros", 1204 Style.StatementAttributeLikeMacros); 1205 IO.mapOptional("StatementMacros", Style.StatementMacros); 1206 IO.mapOptional("TableGenBreakingDAGArgOperators", 1207 Style.TableGenBreakingDAGArgOperators); 1208 IO.mapOptional("TableGenBreakInsideDAGArg", 1209 Style.TableGenBreakInsideDAGArg); 1210 IO.mapOptional("TabWidth", Style.TabWidth); 1211 IO.mapOptional("TemplateNames", Style.TemplateNames); 1212 IO.mapOptional("TypeNames", Style.TypeNames); 1213 IO.mapOptional("TypenameMacros", Style.TypenameMacros); 1214 IO.mapOptional("UseTab", Style.UseTab); 1215 IO.mapOptional("VariableTemplates", Style.VariableTemplates); 1216 IO.mapOptional("VerilogBreakBetweenInstancePorts", 1217 Style.VerilogBreakBetweenInstancePorts); 1218 IO.mapOptional("WhitespaceSensitiveMacros", 1219 Style.WhitespaceSensitiveMacros); 1220 IO.mapOptional("WrapNamespaceBodyWithEmptyLines", 1221 Style.WrapNamespaceBodyWithEmptyLines); 1222 1223 // If AlwaysBreakAfterDefinitionReturnType was specified but 1224 // BreakAfterReturnType was not, initialize the latter from the former for 1225 // backwards compatibility. 1226 if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None && 1227 Style.BreakAfterReturnType == FormatStyle::RTBS_None) { 1228 if (Style.AlwaysBreakAfterDefinitionReturnType == 1229 FormatStyle::DRTBS_All) { 1230 Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; 1231 } else if (Style.AlwaysBreakAfterDefinitionReturnType == 1232 FormatStyle::DRTBS_TopLevel) { 1233 Style.BreakAfterReturnType = FormatStyle::RTBS_TopLevelDefinitions; 1234 } 1235 } 1236 1237 // If BreakBeforeInheritanceComma was specified but BreakInheritance was 1238 // not, initialize the latter from the former for backwards compatibility. 1239 if (BreakBeforeInheritanceComma && 1240 Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) { 1241 Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma; 1242 } 1243 1244 // If BreakConstructorInitializersBeforeComma was specified but 1245 // BreakConstructorInitializers was not, initialize the latter from the 1246 // former for backwards compatibility. 1247 if (BreakConstructorInitializersBeforeComma && 1248 Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon) { 1249 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 1250 } 1251 1252 if (!IsGoogleOrChromium) { 1253 if (Style.PackConstructorInitializers == FormatStyle::PCIS_BinPack && 1254 OnCurrentLine) { 1255 Style.PackConstructorInitializers = OnNextLine 1256 ? FormatStyle::PCIS_NextLine 1257 : FormatStyle::PCIS_CurrentLine; 1258 } 1259 } else if (Style.PackConstructorInitializers == 1260 FormatStyle::PCIS_NextLine) { 1261 if (!OnCurrentLine) 1262 Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack; 1263 else if (!OnNextLine) 1264 Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine; 1265 } 1266 1267 if (Style.LineEnding == FormatStyle::LE_DeriveLF) { 1268 if (!DeriveLineEnding) 1269 Style.LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF; 1270 else if (UseCRLF) 1271 Style.LineEnding = FormatStyle::LE_DeriveCRLF; 1272 } 1273 1274 if (Style.SpacesInParens != FormatStyle::SIPO_Custom && 1275 (SpacesInParentheses || SpaceInEmptyParentheses || 1276 SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) { 1277 if (SpacesInParentheses) { 1278 // For backward compatibility. 1279 Style.SpacesInParensOptions.ExceptDoubleParentheses = false; 1280 Style.SpacesInParensOptions.InConditionalStatements = true; 1281 Style.SpacesInParensOptions.InCStyleCasts = 1282 SpacesInCStyleCastParentheses; 1283 Style.SpacesInParensOptions.InEmptyParentheses = 1284 SpaceInEmptyParentheses; 1285 Style.SpacesInParensOptions.Other = true; 1286 } else { 1287 Style.SpacesInParensOptions = {}; 1288 Style.SpacesInParensOptions.InConditionalStatements = 1289 SpacesInConditionalStatement; 1290 Style.SpacesInParensOptions.InCStyleCasts = 1291 SpacesInCStyleCastParentheses; 1292 Style.SpacesInParensOptions.InEmptyParentheses = 1293 SpaceInEmptyParentheses; 1294 } 1295 Style.SpacesInParens = FormatStyle::SIPO_Custom; 1296 } 1297 } 1298 }; 1299 1300 // Allows to read vector<FormatStyle> while keeping default values. 1301 // IO.getContext() should contain a pointer to the FormatStyle structure, that 1302 // will be used to get default values for missing keys. 1303 // If the first element has no Language specified, it will be treated as the 1304 // default one for the following elements. 1305 template <> struct DocumentListTraits<std::vector<FormatStyle>> { 1306 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) { 1307 return Seq.size(); 1308 } 1309 static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq, 1310 size_t Index) { 1311 if (Index >= Seq.size()) { 1312 assert(Index == Seq.size()); 1313 FormatStyle Template; 1314 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) { 1315 Template = Seq[0]; 1316 } else { 1317 Template = *((const FormatStyle *)IO.getContext()); 1318 Template.Language = FormatStyle::LK_None; 1319 } 1320 Seq.resize(Index + 1, Template); 1321 } 1322 return Seq[Index]; 1323 } 1324 }; 1325 } // namespace yaml 1326 } // namespace llvm 1327 1328 namespace clang { 1329 namespace format { 1330 1331 const std::error_category &getParseCategory() { 1332 static const ParseErrorCategory C{}; 1333 return C; 1334 } 1335 std::error_code make_error_code(ParseError e) { 1336 return std::error_code(static_cast<int>(e), getParseCategory()); 1337 } 1338 1339 inline llvm::Error make_string_error(const Twine &Message) { 1340 return llvm::make_error<llvm::StringError>(Message, 1341 llvm::inconvertibleErrorCode()); 1342 } 1343 1344 const char *ParseErrorCategory::name() const noexcept { 1345 return "clang-format.parse_error"; 1346 } 1347 1348 std::string ParseErrorCategory::message(int EV) const { 1349 switch (static_cast<ParseError>(EV)) { 1350 case ParseError::Success: 1351 return "Success"; 1352 case ParseError::Error: 1353 return "Invalid argument"; 1354 case ParseError::Unsuitable: 1355 return "Unsuitable"; 1356 case ParseError::BinPackTrailingCommaConflict: 1357 return "trailing comma insertion cannot be used with bin packing"; 1358 case ParseError::InvalidQualifierSpecified: 1359 return "Invalid qualifier specified in QualifierOrder"; 1360 case ParseError::DuplicateQualifierSpecified: 1361 return "Duplicate qualifier specified in QualifierOrder"; 1362 case ParseError::MissingQualifierType: 1363 return "Missing type in QualifierOrder"; 1364 case ParseError::MissingQualifierOrder: 1365 return "Missing QualifierOrder"; 1366 } 1367 llvm_unreachable("unexpected parse error"); 1368 } 1369 1370 static void expandPresetsBraceWrapping(FormatStyle &Expanded) { 1371 if (Expanded.BreakBeforeBraces == FormatStyle::BS_Custom) 1372 return; 1373 Expanded.BraceWrapping = {/*AfterCaseLabel=*/false, 1374 /*AfterClass=*/false, 1375 /*AfterControlStatement=*/FormatStyle::BWACS_Never, 1376 /*AfterEnum=*/false, 1377 /*AfterFunction=*/false, 1378 /*AfterNamespace=*/false, 1379 /*AfterObjCDeclaration=*/false, 1380 /*AfterStruct=*/false, 1381 /*AfterUnion=*/false, 1382 /*AfterExternBlock=*/false, 1383 /*BeforeCatch=*/false, 1384 /*BeforeElse=*/false, 1385 /*BeforeLambdaBody=*/false, 1386 /*BeforeWhile=*/false, 1387 /*IndentBraces=*/false, 1388 /*SplitEmptyFunction=*/true, 1389 /*SplitEmptyRecord=*/true, 1390 /*SplitEmptyNamespace=*/true}; 1391 switch (Expanded.BreakBeforeBraces) { 1392 case FormatStyle::BS_Linux: 1393 Expanded.BraceWrapping.AfterClass = true; 1394 Expanded.BraceWrapping.AfterFunction = true; 1395 Expanded.BraceWrapping.AfterNamespace = true; 1396 break; 1397 case FormatStyle::BS_Mozilla: 1398 Expanded.BraceWrapping.AfterClass = true; 1399 Expanded.BraceWrapping.AfterEnum = true; 1400 Expanded.BraceWrapping.AfterFunction = true; 1401 Expanded.BraceWrapping.AfterStruct = true; 1402 Expanded.BraceWrapping.AfterUnion = true; 1403 Expanded.BraceWrapping.AfterExternBlock = true; 1404 Expanded.BraceWrapping.SplitEmptyFunction = true; 1405 Expanded.BraceWrapping.SplitEmptyRecord = false; 1406 break; 1407 case FormatStyle::BS_Stroustrup: 1408 Expanded.BraceWrapping.AfterFunction = true; 1409 Expanded.BraceWrapping.BeforeCatch = true; 1410 Expanded.BraceWrapping.BeforeElse = true; 1411 break; 1412 case FormatStyle::BS_Allman: 1413 Expanded.BraceWrapping.AfterCaseLabel = true; 1414 Expanded.BraceWrapping.AfterClass = true; 1415 Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; 1416 Expanded.BraceWrapping.AfterEnum = true; 1417 Expanded.BraceWrapping.AfterFunction = true; 1418 Expanded.BraceWrapping.AfterNamespace = true; 1419 Expanded.BraceWrapping.AfterObjCDeclaration = true; 1420 Expanded.BraceWrapping.AfterStruct = true; 1421 Expanded.BraceWrapping.AfterUnion = true; 1422 Expanded.BraceWrapping.AfterExternBlock = true; 1423 Expanded.BraceWrapping.BeforeCatch = true; 1424 Expanded.BraceWrapping.BeforeElse = true; 1425 Expanded.BraceWrapping.BeforeLambdaBody = true; 1426 break; 1427 case FormatStyle::BS_Whitesmiths: 1428 Expanded.BraceWrapping.AfterCaseLabel = true; 1429 Expanded.BraceWrapping.AfterClass = true; 1430 Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; 1431 Expanded.BraceWrapping.AfterEnum = true; 1432 Expanded.BraceWrapping.AfterFunction = true; 1433 Expanded.BraceWrapping.AfterNamespace = true; 1434 Expanded.BraceWrapping.AfterObjCDeclaration = true; 1435 Expanded.BraceWrapping.AfterStruct = true; 1436 Expanded.BraceWrapping.AfterExternBlock = true; 1437 Expanded.BraceWrapping.BeforeCatch = true; 1438 Expanded.BraceWrapping.BeforeElse = true; 1439 Expanded.BraceWrapping.BeforeLambdaBody = true; 1440 break; 1441 case FormatStyle::BS_GNU: 1442 Expanded.BraceWrapping = { 1443 /*AfterCaseLabel=*/true, 1444 /*AfterClass=*/true, 1445 /*AfterControlStatement=*/FormatStyle::BWACS_Always, 1446 /*AfterEnum=*/true, 1447 /*AfterFunction=*/true, 1448 /*AfterNamespace=*/true, 1449 /*AfterObjCDeclaration=*/true, 1450 /*AfterStruct=*/true, 1451 /*AfterUnion=*/true, 1452 /*AfterExternBlock=*/true, 1453 /*BeforeCatch=*/true, 1454 /*BeforeElse=*/true, 1455 /*BeforeLambdaBody=*/true, 1456 /*BeforeWhile=*/true, 1457 /*IndentBraces=*/true, 1458 /*SplitEmptyFunction=*/true, 1459 /*SplitEmptyRecord=*/true, 1460 /*SplitEmptyNamespace=*/true}; 1461 break; 1462 case FormatStyle::BS_WebKit: 1463 Expanded.BraceWrapping.AfterFunction = true; 1464 break; 1465 default: 1466 break; 1467 } 1468 } 1469 1470 static void expandPresetsSpaceBeforeParens(FormatStyle &Expanded) { 1471 if (Expanded.SpaceBeforeParens == FormatStyle::SBPO_Custom) 1472 return; 1473 // Reset all flags 1474 Expanded.SpaceBeforeParensOptions = {}; 1475 Expanded.SpaceBeforeParensOptions.AfterPlacementOperator = true; 1476 1477 switch (Expanded.SpaceBeforeParens) { 1478 case FormatStyle::SBPO_ControlStatements: 1479 Expanded.SpaceBeforeParensOptions.AfterControlStatements = true; 1480 Expanded.SpaceBeforeParensOptions.AfterForeachMacros = true; 1481 Expanded.SpaceBeforeParensOptions.AfterIfMacros = true; 1482 break; 1483 case FormatStyle::SBPO_ControlStatementsExceptControlMacros: 1484 Expanded.SpaceBeforeParensOptions.AfterControlStatements = true; 1485 break; 1486 case FormatStyle::SBPO_NonEmptyParentheses: 1487 Expanded.SpaceBeforeParensOptions.BeforeNonEmptyParentheses = true; 1488 break; 1489 default: 1490 break; 1491 } 1492 } 1493 1494 static void expandPresetsSpacesInParens(FormatStyle &Expanded) { 1495 if (Expanded.SpacesInParens == FormatStyle::SIPO_Custom) 1496 return; 1497 assert(Expanded.SpacesInParens == FormatStyle::SIPO_Never); 1498 // Reset all flags 1499 Expanded.SpacesInParensOptions = {}; 1500 } 1501 1502 FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { 1503 FormatStyle LLVMStyle; 1504 LLVMStyle.AccessModifierOffset = -2; 1505 LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align; 1506 LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None; 1507 LLVMStyle.AlignConsecutiveAssignments = {}; 1508 LLVMStyle.AlignConsecutiveAssignments.PadOperators = true; 1509 LLVMStyle.AlignConsecutiveBitFields = {}; 1510 LLVMStyle.AlignConsecutiveDeclarations = {}; 1511 LLVMStyle.AlignConsecutiveDeclarations.AlignFunctionDeclarations = true; 1512 LLVMStyle.AlignConsecutiveMacros = {}; 1513 LLVMStyle.AlignConsecutiveShortCaseStatements = {}; 1514 LLVMStyle.AlignConsecutiveTableGenBreakingDAGArgColons = {}; 1515 LLVMStyle.AlignConsecutiveTableGenCondOperatorColons = {}; 1516 LLVMStyle.AlignConsecutiveTableGenDefinitionColons = {}; 1517 LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right; 1518 LLVMStyle.AlignOperands = FormatStyle::OAS_Align; 1519 LLVMStyle.AlignTrailingComments = {}; 1520 LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always; 1521 LLVMStyle.AlignTrailingComments.OverEmptyLines = 0; 1522 LLVMStyle.AllowAllArgumentsOnNextLine = true; 1523 LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; 1524 LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never; 1525 LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never; 1526 LLVMStyle.AllowShortCaseExpressionOnASingleLine = true; 1527 LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; 1528 LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true; 1529 LLVMStyle.AllowShortEnumsOnASingleLine = true; 1530 LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; 1531 LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1532 LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; 1533 LLVMStyle.AllowShortLoopsOnASingleLine = false; 1534 LLVMStyle.AllowShortNamespacesOnASingleLine = false; 1535 LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; 1536 LLVMStyle.AlwaysBreakBeforeMultilineStrings = false; 1537 LLVMStyle.AttributeMacros.push_back("__capability"); 1538 LLVMStyle.BinPackArguments = true; 1539 LLVMStyle.BinPackLongBracedList = true; 1540 LLVMStyle.BinPackParameters = FormatStyle::BPPS_BinPack; 1541 LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both; 1542 LLVMStyle.BracedInitializerIndentWidth = -1; 1543 LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false, 1544 /*AfterClass=*/false, 1545 /*AfterControlStatement=*/FormatStyle::BWACS_Never, 1546 /*AfterEnum=*/false, 1547 /*AfterFunction=*/false, 1548 /*AfterNamespace=*/false, 1549 /*AfterObjCDeclaration=*/false, 1550 /*AfterStruct=*/false, 1551 /*AfterUnion=*/false, 1552 /*AfterExternBlock=*/false, 1553 /*BeforeCatch=*/false, 1554 /*BeforeElse=*/false, 1555 /*BeforeLambdaBody=*/false, 1556 /*BeforeWhile=*/false, 1557 /*IndentBraces=*/false, 1558 /*SplitEmptyFunction=*/true, 1559 /*SplitEmptyRecord=*/true, 1560 /*SplitEmptyNamespace=*/true}; 1561 LLVMStyle.BreakAdjacentStringLiterals = true; 1562 LLVMStyle.BreakAfterAttributes = FormatStyle::ABS_Leave; 1563 LLVMStyle.BreakAfterJavaFieldAnnotations = false; 1564 LLVMStyle.BreakAfterReturnType = FormatStyle::RTBS_None; 1565 LLVMStyle.BreakArrays = true; 1566 LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None; 1567 LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach; 1568 LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always; 1569 LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline; 1570 LLVMStyle.BreakBeforeTemplateCloser = false; 1571 LLVMStyle.BreakBeforeTernaryOperators = true; 1572 LLVMStyle.BreakBinaryOperations = FormatStyle::BBO_Never; 1573 LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; 1574 LLVMStyle.BreakFunctionDefinitionParameters = false; 1575 LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon; 1576 LLVMStyle.BreakStringLiterals = true; 1577 LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine; 1578 LLVMStyle.ColumnLimit = 80; 1579 LLVMStyle.CommentPragmas = "^ IWYU pragma:"; 1580 LLVMStyle.CompactNamespaces = false; 1581 LLVMStyle.ConstructorInitializerIndentWidth = 4; 1582 LLVMStyle.ContinuationIndentWidth = 4; 1583 LLVMStyle.Cpp11BracedListStyle = true; 1584 LLVMStyle.DerivePointerAlignment = false; 1585 LLVMStyle.DisableFormat = false; 1586 LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never; 1587 LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock; 1588 LLVMStyle.EnumTrailingComma = FormatStyle::ETC_Leave; 1589 LLVMStyle.ExperimentalAutoDetectBinPacking = false; 1590 LLVMStyle.FixNamespaceComments = true; 1591 LLVMStyle.ForEachMacros.push_back("foreach"); 1592 LLVMStyle.ForEachMacros.push_back("Q_FOREACH"); 1593 LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH"); 1594 LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE"); 1595 LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve; 1596 LLVMStyle.IncludeStyle.IncludeCategories = { 1597 {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false}, 1598 {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false}, 1599 {".*", 1, 0, false}}; 1600 LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$"; 1601 LLVMStyle.IncludeStyle.MainIncludeChar = tooling::IncludeStyle::MICD_Quote; 1602 LLVMStyle.IndentAccessModifiers = false; 1603 LLVMStyle.IndentCaseBlocks = false; 1604 LLVMStyle.IndentCaseLabels = false; 1605 LLVMStyle.IndentExportBlock = true; 1606 LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; 1607 LLVMStyle.IndentGotoLabels = true; 1608 LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None; 1609 LLVMStyle.IndentRequiresClause = true; 1610 LLVMStyle.IndentWidth = 2; 1611 LLVMStyle.IndentWrappedFunctionNames = false; 1612 LLVMStyle.InheritsParentConfig = false; 1613 LLVMStyle.InsertBraces = false; 1614 LLVMStyle.InsertNewlineAtEOF = false; 1615 LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None; 1616 LLVMStyle.IntegerLiteralSeparator = { 1617 /*Binary=*/0, /*BinaryMinDigits=*/0, 1618 /*Decimal=*/0, /*DecimalMinDigits=*/0, 1619 /*Hex=*/0, /*HexMinDigits=*/0}; 1620 LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave; 1621 LLVMStyle.JavaScriptWrapImports = true; 1622 LLVMStyle.KeepEmptyLines = { 1623 /*AtEndOfFile=*/false, 1624 /*AtStartOfBlock=*/true, 1625 /*AtStartOfFile=*/true, 1626 }; 1627 LLVMStyle.KeepFormFeed = false; 1628 LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature; 1629 LLVMStyle.Language = Language; 1630 LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF; 1631 LLVMStyle.MaxEmptyLinesToKeep = 1; 1632 LLVMStyle.NamespaceIndentation = FormatStyle::NI_None; 1633 LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto; 1634 LLVMStyle.ObjCBlockIndentWidth = 2; 1635 LLVMStyle.ObjCBreakBeforeNestedBlockParam = true; 1636 LLVMStyle.ObjCSpaceAfterProperty = false; 1637 LLVMStyle.ObjCSpaceBeforeProtocolList = true; 1638 LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack; 1639 LLVMStyle.PointerAlignment = FormatStyle::PAS_Right; 1640 LLVMStyle.PPIndentWidth = -1; 1641 LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave; 1642 LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer; 1643 LLVMStyle.ReflowComments = FormatStyle::RCS_Always; 1644 LLVMStyle.RemoveBracesLLVM = false; 1645 LLVMStyle.RemoveEmptyLinesInUnwrappedLines = false; 1646 LLVMStyle.RemoveParentheses = FormatStyle::RPS_Leave; 1647 LLVMStyle.RemoveSemicolon = false; 1648 LLVMStyle.RequiresClausePosition = FormatStyle::RCPS_OwnLine; 1649 LLVMStyle.RequiresExpressionIndentation = FormatStyle::REI_OuterScope; 1650 LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave; 1651 LLVMStyle.ShortNamespaceLines = 1; 1652 LLVMStyle.SkipMacroDefinitionBody = false; 1653 LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false}; 1654 LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before; 1655 LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric; 1656 LLVMStyle.SpaceAfterCStyleCast = false; 1657 LLVMStyle.SpaceAfterLogicalNot = false; 1658 LLVMStyle.SpaceAfterOperatorKeyword = false; 1659 LLVMStyle.SpaceAfterTemplateKeyword = true; 1660 LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default; 1661 LLVMStyle.SpaceBeforeAssignmentOperators = true; 1662 LLVMStyle.SpaceBeforeCaseColon = false; 1663 LLVMStyle.SpaceBeforeCpp11BracedList = false; 1664 LLVMStyle.SpaceBeforeCtorInitializerColon = true; 1665 LLVMStyle.SpaceBeforeInheritanceColon = true; 1666 LLVMStyle.SpaceBeforeJsonColon = false; 1667 LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements; 1668 LLVMStyle.SpaceBeforeParensOptions = {}; 1669 LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true; 1670 LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true; 1671 LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true; 1672 LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true; 1673 LLVMStyle.SpaceBeforeSquareBrackets = false; 1674 LLVMStyle.SpaceInEmptyBlock = false; 1675 LLVMStyle.SpacesBeforeTrailingComments = 1; 1676 LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never; 1677 LLVMStyle.SpacesInContainerLiterals = true; 1678 LLVMStyle.SpacesInLineCommentPrefix = { 1679 /*Minimum=*/1, /*Maximum=*/std::numeric_limits<unsigned>::max()}; 1680 LLVMStyle.SpacesInParens = FormatStyle::SIPO_Never; 1681 LLVMStyle.SpacesInSquareBrackets = false; 1682 LLVMStyle.Standard = FormatStyle::LS_Latest; 1683 LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT"); 1684 LLVMStyle.StatementMacros.push_back("Q_UNUSED"); 1685 LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION"); 1686 LLVMStyle.TableGenBreakingDAGArgOperators = {}; 1687 LLVMStyle.TableGenBreakInsideDAGArg = FormatStyle::DAS_DontBreak; 1688 LLVMStyle.TabWidth = 8; 1689 LLVMStyle.UseTab = FormatStyle::UT_Never; 1690 LLVMStyle.VerilogBreakBetweenInstancePorts = true; 1691 LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE"); 1692 LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME"); 1693 LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME"); 1694 LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE"); 1695 LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE"); 1696 LLVMStyle.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Leave; 1697 1698 LLVMStyle.PenaltyBreakAssignment = prec::Assignment; 1699 LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19; 1700 LLVMStyle.PenaltyBreakBeforeMemberAccess = 150; 1701 LLVMStyle.PenaltyBreakComment = 300; 1702 LLVMStyle.PenaltyBreakFirstLessLess = 120; 1703 LLVMStyle.PenaltyBreakOpenParenthesis = 0; 1704 LLVMStyle.PenaltyBreakScopeResolution = 500; 1705 LLVMStyle.PenaltyBreakString = 1000; 1706 LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational; 1707 LLVMStyle.PenaltyExcessCharacter = 1'000'000; 1708 LLVMStyle.PenaltyIndentedWhitespace = 0; 1709 LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60; 1710 1711 // Defaults that differ when not C++. 1712 switch (Language) { 1713 case FormatStyle::LK_TableGen: 1714 LLVMStyle.SpacesInContainerLiterals = false; 1715 break; 1716 case FormatStyle::LK_Json: 1717 LLVMStyle.ColumnLimit = 0; 1718 break; 1719 case FormatStyle::LK_Verilog: 1720 LLVMStyle.IndentCaseLabels = true; 1721 LLVMStyle.SpacesInContainerLiterals = false; 1722 break; 1723 default: 1724 break; 1725 } 1726 1727 return LLVMStyle; 1728 } 1729 1730 FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { 1731 if (Language == FormatStyle::LK_TextProto) { 1732 FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto); 1733 GoogleStyle.Language = FormatStyle::LK_TextProto; 1734 1735 return GoogleStyle; 1736 } 1737 1738 FormatStyle GoogleStyle = getLLVMStyle(Language); 1739 1740 GoogleStyle.AccessModifierOffset = -1; 1741 GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left; 1742 GoogleStyle.AllowShortIfStatementsOnASingleLine = 1743 FormatStyle::SIS_WithoutElse; 1744 GoogleStyle.AllowShortLoopsOnASingleLine = true; 1745 GoogleStyle.AlwaysBreakBeforeMultilineStrings = true; 1746 // Abseil aliases to clang's `_Nonnull`, `_Nullable` and `_Null_unspecified`. 1747 GoogleStyle.AttributeMacros.push_back("absl_nonnull"); 1748 GoogleStyle.AttributeMacros.push_back("absl_nullable"); 1749 GoogleStyle.AttributeMacros.push_back("absl_nullability_unknown"); 1750 GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes; 1751 GoogleStyle.DerivePointerAlignment = true; 1752 GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 1753 GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false}, 1754 {"^<.*\\.h>", 1, 0, false}, 1755 {"^<.*", 2, 0, false}, 1756 {".*", 3, 0, false}}; 1757 GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$"; 1758 GoogleStyle.IndentCaseLabels = true; 1759 GoogleStyle.KeepEmptyLines.AtStartOfBlock = false; 1760 GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never; 1761 GoogleStyle.ObjCSpaceAfterProperty = false; 1762 GoogleStyle.ObjCSpaceBeforeProtocolList = true; 1763 GoogleStyle.PackConstructorInitializers = FormatStyle::PCIS_NextLine; 1764 GoogleStyle.PointerAlignment = FormatStyle::PAS_Left; 1765 GoogleStyle.RawStringFormats = { 1766 { 1767 FormatStyle::LK_Cpp, 1768 /*Delimiters=*/ 1769 { 1770 "cc", 1771 "CC", 1772 "cpp", 1773 "Cpp", 1774 "CPP", 1775 "c++", 1776 "C++", 1777 }, 1778 /*EnclosingFunctionNames=*/ 1779 {}, 1780 /*CanonicalDelimiter=*/"", 1781 /*BasedOnStyle=*/"google", 1782 }, 1783 { 1784 FormatStyle::LK_TextProto, 1785 /*Delimiters=*/ 1786 { 1787 "pb", 1788 "PB", 1789 "proto", 1790 "PROTO", 1791 }, 1792 /*EnclosingFunctionNames=*/ 1793 { 1794 "EqualsProto", 1795 "EquivToProto", 1796 "PARSE_PARTIAL_TEXT_PROTO", 1797 "PARSE_TEST_PROTO", 1798 "PARSE_TEXT_PROTO", 1799 "ParseTextOrDie", 1800 "ParseTextProtoOrDie", 1801 "ParseTestProto", 1802 "ParsePartialTestProto", 1803 }, 1804 /*CanonicalDelimiter=*/"pb", 1805 /*BasedOnStyle=*/"google", 1806 }, 1807 }; 1808 1809 GoogleStyle.SpacesBeforeTrailingComments = 2; 1810 GoogleStyle.Standard = FormatStyle::LS_Auto; 1811 1812 GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1; 1813 GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200; 1814 1815 if (Language == FormatStyle::LK_Java) { 1816 GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; 1817 GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign; 1818 GoogleStyle.AlignTrailingComments = {}; 1819 GoogleStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Never; 1820 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 1821 GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1822 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 1823 GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; 1824 GoogleStyle.ColumnLimit = 100; 1825 GoogleStyle.SpaceAfterCStyleCast = true; 1826 GoogleStyle.SpacesBeforeTrailingComments = 1; 1827 } else if (Language == FormatStyle::LK_JavaScript) { 1828 GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; 1829 GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign; 1830 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 1831 // TODO: still under discussion whether to switch to SLS_All. 1832 GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty; 1833 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 1834 GoogleStyle.BreakBeforeTernaryOperators = false; 1835 // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is 1836 // commonly followed by overlong URLs. 1837 GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)"; 1838 // TODO: enable once decided, in particular re disabling bin packing. 1839 // https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma 1840 // GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped; 1841 GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single; 1842 GoogleStyle.JavaScriptWrapImports = false; 1843 GoogleStyle.MaxEmptyLinesToKeep = 3; 1844 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All; 1845 GoogleStyle.SpacesInContainerLiterals = false; 1846 } else if (Language == FormatStyle::LK_Proto) { 1847 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 1848 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 1849 // This affects protocol buffer options specifications and text protos. 1850 // Text protos are currently mostly formatted inside C++ raw string literals 1851 // and often the current breaking behavior of string literals is not 1852 // beneficial there. Investigate turning this on once proper string reflow 1853 // has been implemented. 1854 GoogleStyle.BreakStringLiterals = false; 1855 GoogleStyle.Cpp11BracedListStyle = false; 1856 GoogleStyle.SpacesInContainerLiterals = false; 1857 } else if (Language == FormatStyle::LK_ObjC) { 1858 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 1859 GoogleStyle.ColumnLimit = 100; 1860 // "Regroup" doesn't work well for ObjC yet (main header heuristic, 1861 // relationship between ObjC standard library headers and other heades, 1862 // #imports, etc.) 1863 GoogleStyle.IncludeStyle.IncludeBlocks = 1864 tooling::IncludeStyle::IBS_Preserve; 1865 } else if (Language == FormatStyle::LK_CSharp) { 1866 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 1867 GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1868 GoogleStyle.BreakStringLiterals = false; 1869 GoogleStyle.ColumnLimit = 100; 1870 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All; 1871 } 1872 1873 return GoogleStyle; 1874 } 1875 1876 FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) { 1877 FormatStyle ChromiumStyle = getGoogleStyle(Language); 1878 1879 // Disable include reordering across blocks in Chromium code. 1880 // - clang-format tries to detect that foo.h is the "main" header for 1881 // foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium 1882 // uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc, 1883 // _private.cc, _impl.cc etc) in different permutations 1884 // (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a 1885 // better default for Chromium code. 1886 // - The default for .cc and .mm files is different (r357695) for Google style 1887 // for the same reason. The plan is to unify this again once the main 1888 // header detection works for Google's ObjC code, but this hasn't happened 1889 // yet. Since Chromium has some ObjC code, switching Chromium is blocked 1890 // on that. 1891 // - Finally, "If include reordering is harmful, put things in different 1892 // blocks to prevent it" has been a recommendation for a long time that 1893 // people are used to. We'll need a dev education push to change this to 1894 // "If include reordering is harmful, put things in a different block and 1895 // _prepend that with a comment_ to prevent it" before changing behavior. 1896 ChromiumStyle.IncludeStyle.IncludeBlocks = 1897 tooling::IncludeStyle::IBS_Preserve; 1898 1899 if (Language == FormatStyle::LK_Java) { 1900 ChromiumStyle.AllowShortIfStatementsOnASingleLine = 1901 FormatStyle::SIS_WithoutElse; 1902 ChromiumStyle.BreakAfterJavaFieldAnnotations = true; 1903 ChromiumStyle.ContinuationIndentWidth = 8; 1904 ChromiumStyle.IndentWidth = 4; 1905 // See styleguide for import groups: 1906 // https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/java/java.md#Import-Order 1907 ChromiumStyle.JavaImportGroups = { 1908 "android", 1909 "androidx", 1910 "com", 1911 "dalvik", 1912 "junit", 1913 "org", 1914 "com.google.android.apps.chrome", 1915 "org.chromium", 1916 "java", 1917 "javax", 1918 }; 1919 } else if (Language == FormatStyle::LK_JavaScript) { 1920 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1921 ChromiumStyle.AllowShortLoopsOnASingleLine = false; 1922 } else { 1923 ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false; 1924 ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 1925 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1926 ChromiumStyle.AllowShortLoopsOnASingleLine = false; 1927 ChromiumStyle.BinPackParameters = FormatStyle::BPPS_OnePerLine; 1928 ChromiumStyle.DerivePointerAlignment = false; 1929 if (Language == FormatStyle::LK_ObjC) 1930 ChromiumStyle.ColumnLimit = 80; 1931 } 1932 return ChromiumStyle; 1933 } 1934 1935 FormatStyle getMozillaStyle() { 1936 FormatStyle MozillaStyle = getLLVMStyle(); 1937 MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false; 1938 MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 1939 MozillaStyle.AlwaysBreakAfterDefinitionReturnType = 1940 FormatStyle::DRTBS_TopLevel; 1941 MozillaStyle.BinPackArguments = false; 1942 MozillaStyle.BinPackParameters = FormatStyle::BPPS_OnePerLine; 1943 MozillaStyle.BreakAfterReturnType = FormatStyle::RTBS_TopLevel; 1944 MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla; 1945 MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 1946 MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma; 1947 MozillaStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes; 1948 MozillaStyle.ConstructorInitializerIndentWidth = 2; 1949 MozillaStyle.ContinuationIndentWidth = 2; 1950 MozillaStyle.Cpp11BracedListStyle = false; 1951 MozillaStyle.FixNamespaceComments = false; 1952 MozillaStyle.IndentCaseLabels = true; 1953 MozillaStyle.ObjCSpaceAfterProperty = true; 1954 MozillaStyle.ObjCSpaceBeforeProtocolList = false; 1955 MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200; 1956 MozillaStyle.PointerAlignment = FormatStyle::PAS_Left; 1957 MozillaStyle.SpaceAfterTemplateKeyword = false; 1958 return MozillaStyle; 1959 } 1960 1961 FormatStyle getWebKitStyle() { 1962 FormatStyle Style = getLLVMStyle(); 1963 Style.AccessModifierOffset = -4; 1964 Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; 1965 Style.AlignOperands = FormatStyle::OAS_DontAlign; 1966 Style.AlignTrailingComments = {}; 1967 Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Never; 1968 Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty; 1969 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 1970 Style.BreakBeforeBraces = FormatStyle::BS_WebKit; 1971 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 1972 Style.ColumnLimit = 0; 1973 Style.Cpp11BracedListStyle = false; 1974 Style.FixNamespaceComments = false; 1975 Style.IndentWidth = 4; 1976 Style.NamespaceIndentation = FormatStyle::NI_Inner; 1977 Style.ObjCBlockIndentWidth = 4; 1978 Style.ObjCSpaceAfterProperty = true; 1979 Style.PointerAlignment = FormatStyle::PAS_Left; 1980 Style.SpaceBeforeCpp11BracedList = true; 1981 Style.SpaceInEmptyBlock = true; 1982 return Style; 1983 } 1984 1985 FormatStyle getGNUStyle() { 1986 FormatStyle Style = getLLVMStyle(); 1987 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; 1988 Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; 1989 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 1990 Style.BreakBeforeBraces = FormatStyle::BS_GNU; 1991 Style.BreakBeforeTernaryOperators = true; 1992 Style.ColumnLimit = 79; 1993 Style.Cpp11BracedListStyle = false; 1994 Style.FixNamespaceComments = false; 1995 Style.KeepFormFeed = true; 1996 Style.SpaceBeforeParens = FormatStyle::SBPO_Always; 1997 return Style; 1998 } 1999 2000 FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) { 2001 FormatStyle Style = getLLVMStyle(Language); 2002 Style.ColumnLimit = 120; 2003 Style.TabWidth = 4; 2004 Style.IndentWidth = 4; 2005 Style.UseTab = FormatStyle::UT_Never; 2006 Style.BreakBeforeBraces = FormatStyle::BS_Custom; 2007 Style.BraceWrapping.AfterClass = true; 2008 Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; 2009 Style.BraceWrapping.AfterEnum = true; 2010 Style.BraceWrapping.AfterFunction = true; 2011 Style.BraceWrapping.AfterNamespace = true; 2012 Style.BraceWrapping.AfterObjCDeclaration = true; 2013 Style.BraceWrapping.AfterStruct = true; 2014 Style.BraceWrapping.AfterExternBlock = true; 2015 Style.BraceWrapping.BeforeCatch = true; 2016 Style.BraceWrapping.BeforeElse = true; 2017 Style.BraceWrapping.BeforeWhile = false; 2018 Style.PenaltyReturnTypeOnItsOwnLine = 1000; 2019 Style.AllowShortEnumsOnASingleLine = false; 2020 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; 2021 Style.AllowShortCaseLabelsOnASingleLine = false; 2022 Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 2023 Style.AllowShortLoopsOnASingleLine = false; 2024 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; 2025 Style.BreakAfterReturnType = FormatStyle::RTBS_None; 2026 return Style; 2027 } 2028 2029 FormatStyle getClangFormatStyle() { 2030 FormatStyle Style = getLLVMStyle(); 2031 Style.InsertBraces = true; 2032 Style.InsertNewlineAtEOF = true; 2033 Style.IntegerLiteralSeparator.Decimal = 3; 2034 Style.IntegerLiteralSeparator.DecimalMinDigits = 5; 2035 Style.LineEnding = FormatStyle::LE_LF; 2036 Style.RemoveBracesLLVM = true; 2037 Style.RemoveEmptyLinesInUnwrappedLines = true; 2038 Style.RemoveParentheses = FormatStyle::RPS_ReturnStatement; 2039 Style.RemoveSemicolon = true; 2040 return Style; 2041 } 2042 2043 FormatStyle getNoStyle() { 2044 FormatStyle NoStyle = getLLVMStyle(); 2045 NoStyle.DisableFormat = true; 2046 NoStyle.SortIncludes = {}; 2047 NoStyle.SortUsingDeclarations = FormatStyle::SUD_Never; 2048 return NoStyle; 2049 } 2050 2051 bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language, 2052 FormatStyle *Style) { 2053 if (Name.equals_insensitive("llvm")) 2054 *Style = getLLVMStyle(Language); 2055 else if (Name.equals_insensitive("chromium")) 2056 *Style = getChromiumStyle(Language); 2057 else if (Name.equals_insensitive("mozilla")) 2058 *Style = getMozillaStyle(); 2059 else if (Name.equals_insensitive("google")) 2060 *Style = getGoogleStyle(Language); 2061 else if (Name.equals_insensitive("webkit")) 2062 *Style = getWebKitStyle(); 2063 else if (Name.equals_insensitive("gnu")) 2064 *Style = getGNUStyle(); 2065 else if (Name.equals_insensitive("microsoft")) 2066 *Style = getMicrosoftStyle(Language); 2067 else if (Name.equals_insensitive("clang-format")) 2068 *Style = getClangFormatStyle(); 2069 else if (Name.equals_insensitive("none")) 2070 *Style = getNoStyle(); 2071 else if (Name.equals_insensitive("inheritparentconfig")) 2072 Style->InheritsParentConfig = true; 2073 else 2074 return false; 2075 2076 Style->Language = Language; 2077 return true; 2078 } 2079 2080 ParseError validateQualifierOrder(FormatStyle *Style) { 2081 // If its empty then it means don't do anything. 2082 if (Style->QualifierOrder.empty()) 2083 return ParseError::MissingQualifierOrder; 2084 2085 // Ensure the list contains only currently valid qualifiers. 2086 for (const auto &Qualifier : Style->QualifierOrder) { 2087 if (Qualifier == "type") 2088 continue; 2089 auto token = 2090 LeftRightQualifierAlignmentFixer::getTokenFromQualifier(Qualifier); 2091 if (token == tok::identifier) 2092 return ParseError::InvalidQualifierSpecified; 2093 } 2094 2095 // Ensure the list is unique (no duplicates). 2096 std::set<std::string> UniqueQualifiers(Style->QualifierOrder.begin(), 2097 Style->QualifierOrder.end()); 2098 if (Style->QualifierOrder.size() != UniqueQualifiers.size()) { 2099 LLVM_DEBUG(llvm::dbgs() 2100 << "Duplicate Qualifiers " << Style->QualifierOrder.size() 2101 << " vs " << UniqueQualifiers.size() << "\n"); 2102 return ParseError::DuplicateQualifierSpecified; 2103 } 2104 2105 // Ensure the list has 'type' in it. 2106 if (!llvm::is_contained(Style->QualifierOrder, "type")) 2107 return ParseError::MissingQualifierType; 2108 2109 return ParseError::Success; 2110 } 2111 2112 std::error_code parseConfiguration(llvm::MemoryBufferRef Config, 2113 FormatStyle *Style, bool AllowUnknownOptions, 2114 llvm::SourceMgr::DiagHandlerTy DiagHandler, 2115 void *DiagHandlerCtxt, bool IsDotHFile) { 2116 assert(Style); 2117 FormatStyle::LanguageKind Language = Style->Language; 2118 assert(Language != FormatStyle::LK_None); 2119 if (Config.getBuffer().trim().empty()) 2120 return make_error_code(ParseError::Success); 2121 Style->StyleSet.Clear(); 2122 std::vector<FormatStyle> Styles; 2123 llvm::yaml::Input Input(Config, /*Ctxt=*/nullptr, DiagHandler, 2124 DiagHandlerCtxt); 2125 // DocumentListTraits<vector<FormatStyle>> uses the context to get default 2126 // values for the fields, keys for which are missing from the configuration. 2127 // Mapping also uses the context to get the language to find the correct 2128 // base style. 2129 Input.setContext(Style); 2130 Input.setAllowUnknownKeys(AllowUnknownOptions); 2131 Input >> Styles; 2132 if (Input.error()) 2133 return Input.error(); 2134 2135 for (unsigned i = 0; i < Styles.size(); ++i) { 2136 // Ensures that only the first configuration can skip the Language option. 2137 if (Styles[i].Language == FormatStyle::LK_None && i != 0) 2138 return make_error_code(ParseError::Error); 2139 // Ensure that each language is configured at most once. 2140 for (unsigned j = 0; j < i; ++j) { 2141 if (Styles[i].Language == Styles[j].Language) { 2142 LLVM_DEBUG(llvm::dbgs() 2143 << "Duplicate languages in the config file on positions " 2144 << j << " and " << i << "\n"); 2145 return make_error_code(ParseError::Error); 2146 } 2147 } 2148 } 2149 // Look for a suitable configuration starting from the end, so we can 2150 // find the configuration for the specific language first, and the default 2151 // configuration (which can only be at slot 0) after it. 2152 FormatStyle::FormatStyleSet StyleSet; 2153 bool LanguageFound = false; 2154 for (const FormatStyle &Style : llvm::reverse(Styles)) { 2155 const auto Lang = Style.Language; 2156 if (Lang != FormatStyle::LK_None) 2157 StyleSet.Add(Style); 2158 if (Lang == Language || 2159 // For backward compatibility. 2160 (Lang == FormatStyle::LK_Cpp && Language == FormatStyle::LK_C)) { 2161 LanguageFound = true; 2162 } else if (IsDotHFile && Language == FormatStyle::LK_Cpp && 2163 (Lang == FormatStyle::LK_C || Lang == FormatStyle::LK_ObjC)) { 2164 Language = Lang; 2165 LanguageFound = true; 2166 } 2167 } 2168 if (!LanguageFound) { 2169 if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None) 2170 return make_error_code(ParseError::Unsuitable); 2171 FormatStyle DefaultStyle = Styles[0]; 2172 DefaultStyle.Language = Language; 2173 StyleSet.Add(std::move(DefaultStyle)); 2174 } 2175 *Style = *StyleSet.Get(Language); 2176 if (Style->InsertTrailingCommas != FormatStyle::TCS_None && 2177 Style->BinPackArguments) { 2178 // See comment on FormatStyle::TSC_Wrapped. 2179 return make_error_code(ParseError::BinPackTrailingCommaConflict); 2180 } 2181 if (Style->QualifierAlignment != FormatStyle::QAS_Leave) 2182 return make_error_code(validateQualifierOrder(Style)); 2183 return make_error_code(ParseError::Success); 2184 } 2185 2186 std::string configurationAsText(const FormatStyle &Style) { 2187 std::string Text; 2188 llvm::raw_string_ostream Stream(Text); 2189 llvm::yaml::Output Output(Stream); 2190 // We use the same mapping method for input and output, so we need a non-const 2191 // reference here. 2192 FormatStyle NonConstStyle = Style; 2193 expandPresetsBraceWrapping(NonConstStyle); 2194 expandPresetsSpaceBeforeParens(NonConstStyle); 2195 expandPresetsSpacesInParens(NonConstStyle); 2196 Output << NonConstStyle; 2197 2198 return Stream.str(); 2199 } 2200 2201 std::optional<FormatStyle> 2202 FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const { 2203 if (!Styles) 2204 return std::nullopt; 2205 auto It = Styles->find(Language); 2206 if (It == Styles->end()) { 2207 if (Language != FormatStyle::LK_C) 2208 return std::nullopt; 2209 // For backward compatibility. 2210 It = Styles->find(FormatStyle::LK_Cpp); 2211 if (It == Styles->end()) 2212 return std::nullopt; 2213 } 2214 FormatStyle Style = It->second; 2215 Style.StyleSet = *this; 2216 return Style; 2217 } 2218 2219 void FormatStyle::FormatStyleSet::Add(FormatStyle Style) { 2220 assert(Style.Language != LK_None && 2221 "Cannot add a style for LK_None to a StyleSet"); 2222 assert( 2223 !Style.StyleSet.Styles && 2224 "Cannot add a style associated with an existing StyleSet to a StyleSet"); 2225 if (!Styles) 2226 Styles = std::make_shared<MapType>(); 2227 (*Styles)[Style.Language] = std::move(Style); 2228 } 2229 2230 void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); } 2231 2232 std::optional<FormatStyle> 2233 FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const { 2234 return StyleSet.Get(Language); 2235 } 2236 2237 namespace { 2238 2239 void replaceToken(const FormatToken &Token, FormatToken *Next, 2240 const SourceManager &SourceMgr, tooling::Replacements &Result, 2241 StringRef Text = "") { 2242 const auto &Tok = Token.Tok; 2243 SourceLocation Start; 2244 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) { 2245 Start = Tok.getLocation(); 2246 Next->WhitespaceRange = Token.WhitespaceRange; 2247 } else { 2248 Start = Token.WhitespaceRange.getBegin(); 2249 } 2250 const auto &Range = CharSourceRange::getCharRange(Start, Tok.getEndLoc()); 2251 cantFail(Result.add(tooling::Replacement(SourceMgr, Range, Text))); 2252 } 2253 2254 class ParensRemover : public TokenAnalyzer { 2255 public: 2256 ParensRemover(const Environment &Env, const FormatStyle &Style) 2257 : TokenAnalyzer(Env, Style) {} 2258 2259 std::pair<tooling::Replacements, unsigned> 2260 analyze(TokenAnnotator &Annotator, 2261 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2262 FormatTokenLexer &Tokens) override { 2263 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2264 tooling::Replacements Result; 2265 removeParens(AnnotatedLines, Result); 2266 return {Result, 0}; 2267 } 2268 2269 private: 2270 void removeParens(SmallVectorImpl<AnnotatedLine *> &Lines, 2271 tooling::Replacements &Result) { 2272 const auto &SourceMgr = Env.getSourceManager(); 2273 for (auto *Line : Lines) { 2274 if (!Line->Children.empty()) 2275 removeParens(Line->Children, Result); 2276 if (!Line->Affected) 2277 continue; 2278 for (const auto *Token = Line->First; Token && !Token->Finalized; 2279 Token = Token->Next) { 2280 if (Token->Optional && Token->isOneOf(tok::l_paren, tok::r_paren)) 2281 replaceToken(*Token, Token->Next, SourceMgr, Result, " "); 2282 } 2283 } 2284 } 2285 }; 2286 2287 class BracesInserter : public TokenAnalyzer { 2288 public: 2289 BracesInserter(const Environment &Env, const FormatStyle &Style) 2290 : TokenAnalyzer(Env, Style) {} 2291 2292 std::pair<tooling::Replacements, unsigned> 2293 analyze(TokenAnnotator &Annotator, 2294 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2295 FormatTokenLexer &Tokens) override { 2296 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2297 tooling::Replacements Result; 2298 insertBraces(AnnotatedLines, Result); 2299 return {Result, 0}; 2300 } 2301 2302 private: 2303 void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines, 2304 tooling::Replacements &Result) { 2305 const auto &SourceMgr = Env.getSourceManager(); 2306 int OpeningBraceSurplus = 0; 2307 for (AnnotatedLine *Line : Lines) { 2308 if (!Line->Children.empty()) 2309 insertBraces(Line->Children, Result); 2310 if (!Line->Affected && OpeningBraceSurplus == 0) 2311 continue; 2312 for (FormatToken *Token = Line->First; Token && !Token->Finalized; 2313 Token = Token->Next) { 2314 int BraceCount = Token->BraceCount; 2315 if (BraceCount == 0) 2316 continue; 2317 std::string Brace; 2318 if (BraceCount < 0) { 2319 assert(BraceCount == -1); 2320 if (!Line->Affected) 2321 break; 2322 Brace = Token->is(tok::comment) ? "\n{" : "{"; 2323 ++OpeningBraceSurplus; 2324 } else { 2325 if (OpeningBraceSurplus == 0) 2326 break; 2327 if (OpeningBraceSurplus < BraceCount) 2328 BraceCount = OpeningBraceSurplus; 2329 Brace = '\n' + std::string(BraceCount, '}'); 2330 OpeningBraceSurplus -= BraceCount; 2331 } 2332 Token->BraceCount = 0; 2333 const auto Start = Token->Tok.getEndLoc(); 2334 cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0, Brace))); 2335 } 2336 } 2337 assert(OpeningBraceSurplus == 0); 2338 } 2339 }; 2340 2341 class BracesRemover : public TokenAnalyzer { 2342 public: 2343 BracesRemover(const Environment &Env, const FormatStyle &Style) 2344 : TokenAnalyzer(Env, Style) {} 2345 2346 std::pair<tooling::Replacements, unsigned> 2347 analyze(TokenAnnotator &Annotator, 2348 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2349 FormatTokenLexer &Tokens) override { 2350 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2351 tooling::Replacements Result; 2352 removeBraces(AnnotatedLines, Result); 2353 return {Result, 0}; 2354 } 2355 2356 private: 2357 void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines, 2358 tooling::Replacements &Result) { 2359 const auto &SourceMgr = Env.getSourceManager(); 2360 const auto *End = Lines.end(); 2361 for (const auto *I = Lines.begin(); I != End; ++I) { 2362 const auto &Line = *I; 2363 if (!Line->Children.empty()) 2364 removeBraces(Line->Children, Result); 2365 if (!Line->Affected) 2366 continue; 2367 const auto *NextLine = I + 1 == End ? nullptr : I[1]; 2368 for (const auto *Token = Line->First; Token && !Token->Finalized; 2369 Token = Token->Next) { 2370 if (!Token->Optional || !Token->isOneOf(tok::l_brace, tok::r_brace)) 2371 continue; 2372 auto *Next = Token->Next; 2373 assert(Next || Token == Line->Last); 2374 if (!Next && NextLine) 2375 Next = NextLine->First; 2376 replaceToken(*Token, Next, SourceMgr, Result); 2377 } 2378 } 2379 } 2380 }; 2381 2382 class SemiRemover : public TokenAnalyzer { 2383 public: 2384 SemiRemover(const Environment &Env, const FormatStyle &Style) 2385 : TokenAnalyzer(Env, Style) {} 2386 2387 std::pair<tooling::Replacements, unsigned> 2388 analyze(TokenAnnotator &Annotator, 2389 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2390 FormatTokenLexer &Tokens) override { 2391 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2392 tooling::Replacements Result; 2393 removeSemi(Annotator, AnnotatedLines, Result); 2394 return {Result, 0}; 2395 } 2396 2397 private: 2398 void removeSemi(TokenAnnotator &Annotator, 2399 SmallVectorImpl<AnnotatedLine *> &Lines, 2400 tooling::Replacements &Result) { 2401 auto PrecededByFunctionRBrace = [](const FormatToken &Tok) { 2402 const auto *Prev = Tok.Previous; 2403 if (!Prev || Prev->isNot(tok::r_brace)) 2404 return false; 2405 const auto *LBrace = Prev->MatchingParen; 2406 return LBrace && LBrace->is(TT_FunctionLBrace); 2407 }; 2408 const auto &SourceMgr = Env.getSourceManager(); 2409 const auto *End = Lines.end(); 2410 for (const auto *I = Lines.begin(); I != End; ++I) { 2411 const auto &Line = *I; 2412 if (!Line->Children.empty()) 2413 removeSemi(Annotator, Line->Children, Result); 2414 if (!Line->Affected) 2415 continue; 2416 Annotator.calculateFormattingInformation(*Line); 2417 const auto *NextLine = I + 1 == End ? nullptr : I[1]; 2418 for (const auto *Token = Line->First; Token && !Token->Finalized; 2419 Token = Token->Next) { 2420 if (Token->isNot(tok::semi) || 2421 (!Token->Optional && !PrecededByFunctionRBrace(*Token))) { 2422 continue; 2423 } 2424 auto *Next = Token->Next; 2425 assert(Next || Token == Line->Last); 2426 if (!Next && NextLine) 2427 Next = NextLine->First; 2428 replaceToken(*Token, Next, SourceMgr, Result); 2429 } 2430 } 2431 } 2432 }; 2433 2434 class EnumTrailingCommaEditor : public TokenAnalyzer { 2435 public: 2436 EnumTrailingCommaEditor(const Environment &Env, const FormatStyle &Style) 2437 : TokenAnalyzer(Env, Style) {} 2438 2439 std::pair<tooling::Replacements, unsigned> 2440 analyze(TokenAnnotator &Annotator, 2441 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2442 FormatTokenLexer &Tokens) override { 2443 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2444 tooling::Replacements Result; 2445 editEnumTrailingComma(AnnotatedLines, Result); 2446 return {Result, 0}; 2447 } 2448 2449 private: 2450 void editEnumTrailingComma(SmallVectorImpl<AnnotatedLine *> &Lines, 2451 tooling::Replacements &Result) { 2452 bool InEnumBraces = false; 2453 const FormatToken *BeforeRBrace = nullptr; 2454 const auto &SourceMgr = Env.getSourceManager(); 2455 for (auto *Line : Lines) { 2456 if (!Line->Children.empty()) 2457 editEnumTrailingComma(Line->Children, Result); 2458 for (const auto *Token = Line->First; Token && !Token->Finalized; 2459 Token = Token->Next) { 2460 if (Token->isNot(TT_EnumRBrace)) { 2461 if (Token->is(TT_EnumLBrace)) 2462 InEnumBraces = true; 2463 else if (InEnumBraces && Token->isNot(tok::comment)) 2464 BeforeRBrace = Line->Affected ? Token : nullptr; 2465 continue; 2466 } 2467 InEnumBraces = false; 2468 if (!BeforeRBrace) // Empty braces or Line not affected. 2469 continue; 2470 if (BeforeRBrace->is(tok::comma)) { 2471 if (Style.EnumTrailingComma == FormatStyle::ETC_Remove) 2472 replaceToken(*BeforeRBrace, BeforeRBrace->Next, SourceMgr, Result); 2473 } else if (Style.EnumTrailingComma == FormatStyle::ETC_Insert) { 2474 cantFail(Result.add(tooling::Replacement( 2475 SourceMgr, BeforeRBrace->Tok.getEndLoc(), 0, ","))); 2476 } 2477 BeforeRBrace = nullptr; 2478 } 2479 } 2480 } 2481 }; 2482 2483 class JavaScriptRequoter : public TokenAnalyzer { 2484 public: 2485 JavaScriptRequoter(const Environment &Env, const FormatStyle &Style) 2486 : TokenAnalyzer(Env, Style) {} 2487 2488 std::pair<tooling::Replacements, unsigned> 2489 analyze(TokenAnnotator &Annotator, 2490 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2491 FormatTokenLexer &Tokens) override { 2492 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2493 tooling::Replacements Result; 2494 requoteJSStringLiteral(AnnotatedLines, Result); 2495 return {Result, 0}; 2496 } 2497 2498 private: 2499 // Replaces double/single-quoted string literal as appropriate, re-escaping 2500 // the contents in the process. 2501 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines, 2502 tooling::Replacements &Result) { 2503 for (AnnotatedLine *Line : Lines) { 2504 requoteJSStringLiteral(Line->Children, Result); 2505 if (!Line->Affected) 2506 continue; 2507 for (FormatToken *FormatTok = Line->First; FormatTok; 2508 FormatTok = FormatTok->Next) { 2509 StringRef Input = FormatTok->TokenText; 2510 if (FormatTok->Finalized || !FormatTok->isStringLiteral() || 2511 // NB: testing for not starting with a double quote to avoid 2512 // breaking `template strings`. 2513 (Style.JavaScriptQuotes == FormatStyle::JSQS_Single && 2514 !Input.starts_with("\"")) || 2515 (Style.JavaScriptQuotes == FormatStyle::JSQS_Double && 2516 !Input.starts_with("\'"))) { 2517 continue; 2518 } 2519 2520 // Change start and end quote. 2521 bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single; 2522 SourceLocation Start = FormatTok->Tok.getLocation(); 2523 auto Replace = [&](SourceLocation Start, unsigned Length, 2524 StringRef ReplacementText) { 2525 auto Err = Result.add(tooling::Replacement( 2526 Env.getSourceManager(), Start, Length, ReplacementText)); 2527 // FIXME: handle error. For now, print error message and skip the 2528 // replacement for release version. 2529 if (Err) { 2530 llvm::errs() << toString(std::move(Err)) << "\n"; 2531 assert(false); 2532 } 2533 }; 2534 Replace(Start, 1, IsSingle ? "'" : "\""); 2535 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1, 2536 IsSingle ? "'" : "\""); 2537 2538 // Escape internal quotes. 2539 bool Escaped = false; 2540 for (size_t i = 1; i < Input.size() - 1; i++) { 2541 switch (Input[i]) { 2542 case '\\': 2543 if (!Escaped && i + 1 < Input.size() && 2544 ((IsSingle && Input[i + 1] == '"') || 2545 (!IsSingle && Input[i + 1] == '\''))) { 2546 // Remove this \, it's escaping a " or ' that no longer needs 2547 // escaping 2548 Replace(Start.getLocWithOffset(i), 1, ""); 2549 continue; 2550 } 2551 Escaped = !Escaped; 2552 break; 2553 case '\"': 2554 case '\'': 2555 if (!Escaped && IsSingle == (Input[i] == '\'')) { 2556 // Escape the quote. 2557 Replace(Start.getLocWithOffset(i), 0, "\\"); 2558 } 2559 Escaped = false; 2560 break; 2561 default: 2562 Escaped = false; 2563 break; 2564 } 2565 } 2566 } 2567 } 2568 } 2569 }; 2570 2571 class Formatter : public TokenAnalyzer { 2572 public: 2573 Formatter(const Environment &Env, const FormatStyle &Style, 2574 FormattingAttemptStatus *Status) 2575 : TokenAnalyzer(Env, Style), Status(Status) {} 2576 2577 std::pair<tooling::Replacements, unsigned> 2578 analyze(TokenAnnotator &Annotator, 2579 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2580 FormatTokenLexer &Tokens) override { 2581 tooling::Replacements Result; 2582 deriveLocalStyle(AnnotatedLines); 2583 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2584 for (AnnotatedLine *Line : AnnotatedLines) 2585 Annotator.calculateFormattingInformation(*Line); 2586 Annotator.setCommentLineLevels(AnnotatedLines); 2587 2588 WhitespaceManager Whitespaces( 2589 Env.getSourceManager(), Style, 2590 Style.LineEnding > FormatStyle::LE_CRLF 2591 ? WhitespaceManager::inputUsesCRLF( 2592 Env.getSourceManager().getBufferData(Env.getFileID()), 2593 Style.LineEnding == FormatStyle::LE_DeriveCRLF) 2594 : Style.LineEnding == FormatStyle::LE_CRLF); 2595 ContinuationIndenter Indenter(Style, Tokens.getKeywords(), 2596 Env.getSourceManager(), Whitespaces, Encoding, 2597 BinPackInconclusiveFunctions); 2598 unsigned Penalty = 2599 UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, 2600 Tokens.getKeywords(), Env.getSourceManager(), 2601 Status) 2602 .format(AnnotatedLines, /*DryRun=*/false, 2603 /*AdditionalIndent=*/0, 2604 /*FixBadIndentation=*/false, 2605 /*FirstStartColumn=*/Env.getFirstStartColumn(), 2606 /*NextStartColumn=*/Env.getNextStartColumn(), 2607 /*LastStartColumn=*/Env.getLastStartColumn()); 2608 for (const auto &R : Whitespaces.generateReplacements()) 2609 if (Result.add(R)) 2610 return std::make_pair(Result, 0); 2611 return std::make_pair(Result, Penalty); 2612 } 2613 2614 private: 2615 bool 2616 hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) { 2617 for (const AnnotatedLine *Line : Lines) { 2618 if (hasCpp03IncompatibleFormat(Line->Children)) 2619 return true; 2620 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) { 2621 if (!Tok->hasWhitespaceBefore()) { 2622 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener)) 2623 return true; 2624 if (Tok->is(TT_TemplateCloser) && 2625 Tok->Previous->is(TT_TemplateCloser)) { 2626 return true; 2627 } 2628 } 2629 } 2630 } 2631 return false; 2632 } 2633 2634 int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) { 2635 int AlignmentDiff = 0; 2636 for (const AnnotatedLine *Line : Lines) { 2637 AlignmentDiff += countVariableAlignments(Line->Children); 2638 for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) { 2639 if (Tok->isNot(TT_PointerOrReference)) 2640 continue; 2641 // Don't treat space in `void foo() &&` as evidence. 2642 if (const auto *Prev = Tok->getPreviousNonComment()) { 2643 if (Prev->is(tok::r_paren) && Prev->MatchingParen) { 2644 if (const auto *Func = 2645 Prev->MatchingParen->getPreviousNonComment()) { 2646 if (Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName, 2647 TT_OverloadedOperator)) { 2648 continue; 2649 } 2650 } 2651 } 2652 } 2653 bool SpaceBefore = Tok->hasWhitespaceBefore(); 2654 bool SpaceAfter = Tok->Next->hasWhitespaceBefore(); 2655 if (SpaceBefore && !SpaceAfter) 2656 ++AlignmentDiff; 2657 if (!SpaceBefore && SpaceAfter) 2658 --AlignmentDiff; 2659 } 2660 } 2661 return AlignmentDiff; 2662 } 2663 2664 void 2665 deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 2666 bool HasBinPackedFunction = false; 2667 bool HasOnePerLineFunction = false; 2668 for (AnnotatedLine *Line : AnnotatedLines) { 2669 if (!Line->First->Next) 2670 continue; 2671 FormatToken *Tok = Line->First->Next; 2672 while (Tok->Next) { 2673 if (Tok->is(PPK_BinPacked)) 2674 HasBinPackedFunction = true; 2675 if (Tok->is(PPK_OnePerLine)) 2676 HasOnePerLineFunction = true; 2677 2678 Tok = Tok->Next; 2679 } 2680 } 2681 if (Style.DerivePointerAlignment) { 2682 const auto NetRightCount = countVariableAlignments(AnnotatedLines); 2683 if (NetRightCount > 0) 2684 Style.PointerAlignment = FormatStyle::PAS_Right; 2685 else if (NetRightCount < 0) 2686 Style.PointerAlignment = FormatStyle::PAS_Left; 2687 Style.ReferenceAlignment = FormatStyle::RAS_Pointer; 2688 } 2689 if (Style.Standard == FormatStyle::LS_Auto) { 2690 Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines) 2691 ? FormatStyle::LS_Latest 2692 : FormatStyle::LS_Cpp03; 2693 } 2694 BinPackInconclusiveFunctions = 2695 HasBinPackedFunction || !HasOnePerLineFunction; 2696 } 2697 2698 bool BinPackInconclusiveFunctions; 2699 FormattingAttemptStatus *Status; 2700 }; 2701 2702 /// TrailingCommaInserter inserts trailing commas into container literals. 2703 /// E.g.: 2704 /// const x = [ 2705 /// 1, 2706 /// ]; 2707 /// TrailingCommaInserter runs after formatting. To avoid causing a required 2708 /// reformatting (and thus reflow), it never inserts a comma that'd exceed the 2709 /// ColumnLimit. 2710 /// 2711 /// Because trailing commas disable binpacking of arrays, TrailingCommaInserter 2712 /// is conceptually incompatible with bin packing. 2713 class TrailingCommaInserter : public TokenAnalyzer { 2714 public: 2715 TrailingCommaInserter(const Environment &Env, const FormatStyle &Style) 2716 : TokenAnalyzer(Env, Style) {} 2717 2718 std::pair<tooling::Replacements, unsigned> 2719 analyze(TokenAnnotator &Annotator, 2720 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2721 FormatTokenLexer &Tokens) override { 2722 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2723 tooling::Replacements Result; 2724 insertTrailingCommas(AnnotatedLines, Result); 2725 return {Result, 0}; 2726 } 2727 2728 private: 2729 /// Inserts trailing commas in [] and {} initializers if they wrap over 2730 /// multiple lines. 2731 void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines, 2732 tooling::Replacements &Result) { 2733 for (AnnotatedLine *Line : Lines) { 2734 insertTrailingCommas(Line->Children, Result); 2735 if (!Line->Affected) 2736 continue; 2737 for (FormatToken *FormatTok = Line->First; FormatTok; 2738 FormatTok = FormatTok->Next) { 2739 if (FormatTok->NewlinesBefore == 0) 2740 continue; 2741 FormatToken *Matching = FormatTok->MatchingParen; 2742 if (!Matching || !FormatTok->getPreviousNonComment()) 2743 continue; 2744 if (!(FormatTok->is(tok::r_square) && 2745 Matching->is(TT_ArrayInitializerLSquare)) && 2746 !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) { 2747 continue; 2748 } 2749 FormatToken *Prev = FormatTok->getPreviousNonComment(); 2750 if (Prev->is(tok::comma) || Prev->is(tok::semi)) 2751 continue; 2752 // getEndLoc is not reliably set during re-lexing, use text length 2753 // instead. 2754 SourceLocation Start = 2755 Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size()); 2756 // If inserting a comma would push the code over the column limit, skip 2757 // this location - it'd introduce an unstable formatting due to the 2758 // required reflow. 2759 unsigned ColumnNumber = 2760 Env.getSourceManager().getSpellingColumnNumber(Start); 2761 if (ColumnNumber > Style.ColumnLimit) 2762 continue; 2763 // Comma insertions cannot conflict with each other, and this pass has a 2764 // clean set of Replacements, so the operation below cannot fail. 2765 cantFail(Result.add( 2766 tooling::Replacement(Env.getSourceManager(), Start, 0, ","))); 2767 } 2768 } 2769 } 2770 }; 2771 2772 // This class clean up the erroneous/redundant code around the given ranges in 2773 // file. 2774 class Cleaner : public TokenAnalyzer { 2775 public: 2776 Cleaner(const Environment &Env, const FormatStyle &Style) 2777 : TokenAnalyzer(Env, Style), 2778 DeletedTokens(FormatTokenLess(Env.getSourceManager())) {} 2779 2780 // FIXME: eliminate unused parameters. 2781 std::pair<tooling::Replacements, unsigned> 2782 analyze(TokenAnnotator &Annotator, 2783 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2784 FormatTokenLexer &Tokens) override { 2785 // FIXME: in the current implementation the granularity of affected range 2786 // is an annotated line. However, this is not sufficient. Furthermore, 2787 // redundant code introduced by replacements does not necessarily 2788 // intercept with ranges of replacements that result in the redundancy. 2789 // To determine if some redundant code is actually introduced by 2790 // replacements(e.g. deletions), we need to come up with a more 2791 // sophisticated way of computing affected ranges. 2792 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2793 2794 checkEmptyNamespace(AnnotatedLines); 2795 2796 for (auto *Line : AnnotatedLines) 2797 cleanupLine(Line); 2798 2799 return {generateFixes(), 0}; 2800 } 2801 2802 private: 2803 void cleanupLine(AnnotatedLine *Line) { 2804 for (auto *Child : Line->Children) 2805 cleanupLine(Child); 2806 2807 if (Line->Affected) { 2808 cleanupRight(Line->First, tok::comma, tok::comma); 2809 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma); 2810 cleanupRight(Line->First, tok::l_paren, tok::comma); 2811 cleanupLeft(Line->First, tok::comma, tok::r_paren); 2812 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace); 2813 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace); 2814 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal); 2815 } 2816 } 2817 2818 bool containsOnlyComments(const AnnotatedLine &Line) { 2819 for (FormatToken *Tok = Line.First; Tok; Tok = Tok->Next) 2820 if (Tok->isNot(tok::comment)) 2821 return false; 2822 return true; 2823 } 2824 2825 // Iterate through all lines and remove any empty (nested) namespaces. 2826 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 2827 std::set<unsigned> DeletedLines; 2828 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 2829 auto &Line = *AnnotatedLines[i]; 2830 if (Line.startsWithNamespace()) 2831 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines); 2832 } 2833 2834 for (auto Line : DeletedLines) { 2835 FormatToken *Tok = AnnotatedLines[Line]->First; 2836 while (Tok) { 2837 deleteToken(Tok); 2838 Tok = Tok->Next; 2839 } 2840 } 2841 } 2842 2843 // The function checks if the namespace, which starts from \p CurrentLine, and 2844 // its nested namespaces are empty and delete them if they are empty. It also 2845 // sets \p NewLine to the last line checked. 2846 // Returns true if the current namespace is empty. 2847 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2848 unsigned CurrentLine, unsigned &NewLine, 2849 std::set<unsigned> &DeletedLines) { 2850 unsigned InitLine = CurrentLine, End = AnnotatedLines.size(); 2851 if (Style.BraceWrapping.AfterNamespace) { 2852 // If the left brace is in a new line, we should consume it first so that 2853 // it does not make the namespace non-empty. 2854 // FIXME: error handling if there is no left brace. 2855 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) { 2856 NewLine = CurrentLine; 2857 return false; 2858 } 2859 } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) { 2860 return false; 2861 } 2862 while (++CurrentLine < End) { 2863 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace)) 2864 break; 2865 2866 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) { 2867 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine, 2868 DeletedLines)) { 2869 return false; 2870 } 2871 CurrentLine = NewLine; 2872 continue; 2873 } 2874 2875 if (containsOnlyComments(*AnnotatedLines[CurrentLine])) 2876 continue; 2877 2878 // If there is anything other than comments or nested namespaces in the 2879 // current namespace, the namespace cannot be empty. 2880 NewLine = CurrentLine; 2881 return false; 2882 } 2883 2884 NewLine = CurrentLine; 2885 if (CurrentLine >= End) 2886 return false; 2887 2888 // Check if the empty namespace is actually affected by changed ranges. 2889 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange( 2890 AnnotatedLines[InitLine]->First->Tok.getLocation(), 2891 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) { 2892 return false; 2893 } 2894 2895 for (unsigned i = InitLine; i <= CurrentLine; ++i) 2896 DeletedLines.insert(i); 2897 2898 return true; 2899 } 2900 2901 // Checks pairs {start, start->next},..., {end->previous, end} and deletes one 2902 // of the token in the pair if the left token has \p LK token kind and the 2903 // right token has \p RK token kind. If \p DeleteLeft is true, the left token 2904 // is deleted on match; otherwise, the right token is deleted. 2905 template <typename LeftKind, typename RightKind> 2906 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK, 2907 bool DeleteLeft) { 2908 auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * { 2909 for (auto *Res = Tok.Next; Res; Res = Res->Next) { 2910 if (Res->isNot(tok::comment) && 2911 DeletedTokens.find(Res) == DeletedTokens.end()) { 2912 return Res; 2913 } 2914 } 2915 return nullptr; 2916 }; 2917 for (auto *Left = Start; Left;) { 2918 auto *Right = NextNotDeleted(*Left); 2919 if (!Right) 2920 break; 2921 if (Left->is(LK) && Right->is(RK)) { 2922 deleteToken(DeleteLeft ? Left : Right); 2923 for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next) 2924 deleteToken(Tok); 2925 // If the right token is deleted, we should keep the left token 2926 // unchanged and pair it with the new right token. 2927 if (!DeleteLeft) 2928 continue; 2929 } 2930 Left = Right; 2931 } 2932 } 2933 2934 template <typename LeftKind, typename RightKind> 2935 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) { 2936 cleanupPair(Start, LK, RK, /*DeleteLeft=*/true); 2937 } 2938 2939 template <typename LeftKind, typename RightKind> 2940 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) { 2941 cleanupPair(Start, LK, RK, /*DeleteLeft=*/false); 2942 } 2943 2944 // Delete the given token. 2945 inline void deleteToken(FormatToken *Tok) { 2946 if (Tok) 2947 DeletedTokens.insert(Tok); 2948 } 2949 2950 tooling::Replacements generateFixes() { 2951 tooling::Replacements Fixes; 2952 SmallVector<FormatToken *> Tokens; 2953 std::copy(DeletedTokens.begin(), DeletedTokens.end(), 2954 std::back_inserter(Tokens)); 2955 2956 // Merge multiple continuous token deletions into one big deletion so that 2957 // the number of replacements can be reduced. This makes computing affected 2958 // ranges more efficient when we run reformat on the changed code. 2959 unsigned Idx = 0; 2960 while (Idx < Tokens.size()) { 2961 unsigned St = Idx, End = Idx; 2962 while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1]) 2963 ++End; 2964 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(), 2965 Tokens[End]->Tok.getEndLoc()); 2966 auto Err = 2967 Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, "")); 2968 // FIXME: better error handling. for now just print error message and skip 2969 // for the release version. 2970 if (Err) { 2971 llvm::errs() << toString(std::move(Err)) << "\n"; 2972 assert(false && "Fixes must not conflict!"); 2973 } 2974 Idx = End + 1; 2975 } 2976 2977 return Fixes; 2978 } 2979 2980 // Class for less-than inequality comparason for the set `RedundantTokens`. 2981 // We store tokens in the order they appear in the translation unit so that 2982 // we do not need to sort them in `generateFixes()`. 2983 struct FormatTokenLess { 2984 FormatTokenLess(const SourceManager &SM) : SM(SM) {} 2985 2986 bool operator()(const FormatToken *LHS, const FormatToken *RHS) const { 2987 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(), 2988 RHS->Tok.getLocation()); 2989 } 2990 const SourceManager &SM; 2991 }; 2992 2993 // Tokens to be deleted. 2994 std::set<FormatToken *, FormatTokenLess> DeletedTokens; 2995 }; 2996 2997 class ObjCHeaderStyleGuesser : public TokenAnalyzer { 2998 public: 2999 ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style) 3000 : TokenAnalyzer(Env, Style), IsObjC(false) {} 3001 3002 std::pair<tooling::Replacements, unsigned> 3003 analyze(TokenAnnotator &Annotator, 3004 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 3005 FormatTokenLexer &Tokens) override { 3006 assert(Style.Language == FormatStyle::LK_Cpp); 3007 IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines, 3008 Tokens.getKeywords()); 3009 tooling::Replacements Result; 3010 return {Result, 0}; 3011 } 3012 3013 bool isObjC() { return IsObjC; } 3014 3015 private: 3016 static bool 3017 guessIsObjC(const SourceManager &SourceManager, 3018 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 3019 const AdditionalKeywords &Keywords) { 3020 // Keep this array sorted, since we are binary searching over it. 3021 static constexpr llvm::StringLiteral FoundationIdentifiers[] = { 3022 "CGFloat", 3023 "CGPoint", 3024 "CGPointMake", 3025 "CGPointZero", 3026 "CGRect", 3027 "CGRectEdge", 3028 "CGRectInfinite", 3029 "CGRectMake", 3030 "CGRectNull", 3031 "CGRectZero", 3032 "CGSize", 3033 "CGSizeMake", 3034 "CGVector", 3035 "CGVectorMake", 3036 "FOUNDATION_EXPORT", // This is an alias for FOUNDATION_EXTERN. 3037 "FOUNDATION_EXTERN", 3038 "NSAffineTransform", 3039 "NSArray", 3040 "NSAttributedString", 3041 "NSBlockOperation", 3042 "NSBundle", 3043 "NSCache", 3044 "NSCalendar", 3045 "NSCharacterSet", 3046 "NSCountedSet", 3047 "NSData", 3048 "NSDataDetector", 3049 "NSDecimal", 3050 "NSDecimalNumber", 3051 "NSDictionary", 3052 "NSEdgeInsets", 3053 "NSError", 3054 "NSErrorDomain", 3055 "NSHashTable", 3056 "NSIndexPath", 3057 "NSIndexSet", 3058 "NSInteger", 3059 "NSInvocationOperation", 3060 "NSLocale", 3061 "NSMapTable", 3062 "NSMutableArray", 3063 "NSMutableAttributedString", 3064 "NSMutableCharacterSet", 3065 "NSMutableData", 3066 "NSMutableDictionary", 3067 "NSMutableIndexSet", 3068 "NSMutableOrderedSet", 3069 "NSMutableSet", 3070 "NSMutableString", 3071 "NSNumber", 3072 "NSNumberFormatter", 3073 "NSObject", 3074 "NSOperation", 3075 "NSOperationQueue", 3076 "NSOperationQueuePriority", 3077 "NSOrderedSet", 3078 "NSPoint", 3079 "NSPointerArray", 3080 "NSQualityOfService", 3081 "NSRange", 3082 "NSRect", 3083 "NSRegularExpression", 3084 "NSSet", 3085 "NSSize", 3086 "NSString", 3087 "NSTimeZone", 3088 "NSUInteger", 3089 "NSURL", 3090 "NSURLComponents", 3091 "NSURLQueryItem", 3092 "NSUUID", 3093 "NSValue", 3094 "NS_ASSUME_NONNULL_BEGIN", 3095 "UIImage", 3096 "UIView", 3097 }; 3098 3099 for (auto *Line : AnnotatedLines) { 3100 if (Line->First && (Line->First->TokenText.starts_with("#") || 3101 Line->First->TokenText == "__pragma" || 3102 Line->First->TokenText == "_Pragma")) { 3103 continue; 3104 } 3105 for (const FormatToken *FormatTok = Line->First; FormatTok; 3106 FormatTok = FormatTok->Next) { 3107 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) && 3108 (FormatTok->isNot(tok::objc_not_keyword) || 3109 FormatTok->isOneOf(tok::numeric_constant, tok::l_square, 3110 tok::l_brace))) || 3111 (FormatTok->Tok.isAnyIdentifier() && 3112 llvm::binary_search(FoundationIdentifiers, 3113 FormatTok->TokenText)) || 3114 FormatTok->is(TT_ObjCStringLiteral) || 3115 FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM, 3116 Keywords.kw_NS_ERROR_ENUM, 3117 Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace, 3118 TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn, 3119 TT_ObjCMethodExpr, TT_ObjCMethodSpecifier, 3120 TT_ObjCProperty)) { 3121 LLVM_DEBUG(llvm::dbgs() 3122 << "Detected ObjC at location " 3123 << FormatTok->Tok.getLocation().printToString( 3124 SourceManager) 3125 << " token: " << FormatTok->TokenText << " token type: " 3126 << getTokenTypeName(FormatTok->getType()) << "\n"); 3127 return true; 3128 } 3129 } 3130 if (guessIsObjC(SourceManager, Line->Children, Keywords)) 3131 return true; 3132 } 3133 return false; 3134 } 3135 3136 bool IsObjC; 3137 }; 3138 3139 struct IncludeDirective { 3140 StringRef Filename; 3141 StringRef Text; 3142 unsigned Offset; 3143 int Category; 3144 int Priority; 3145 }; 3146 3147 struct JavaImportDirective { 3148 StringRef Identifier; 3149 StringRef Text; 3150 unsigned Offset; 3151 SmallVector<StringRef> AssociatedCommentLines; 3152 bool IsStatic; 3153 }; 3154 3155 } // end anonymous namespace 3156 3157 // Determines whether 'Ranges' intersects with ('Start', 'End'). 3158 static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start, 3159 unsigned End) { 3160 for (const auto &Range : Ranges) { 3161 if (Range.getOffset() < End && 3162 Range.getOffset() + Range.getLength() > Start) { 3163 return true; 3164 } 3165 } 3166 return false; 3167 } 3168 3169 // Returns a pair (Index, OffsetToEOL) describing the position of the cursor 3170 // before sorting/deduplicating. Index is the index of the include under the 3171 // cursor in the original set of includes. If this include has duplicates, it is 3172 // the index of the first of the duplicates as the others are going to be 3173 // removed. OffsetToEOL describes the cursor's position relative to the end of 3174 // its current line. 3175 // If `Cursor` is not on any #include, `Index` will be 3176 // std::numeric_limits<unsigned>::max(). 3177 static std::pair<unsigned, unsigned> 3178 FindCursorIndex(const ArrayRef<IncludeDirective> &Includes, 3179 const ArrayRef<unsigned> &Indices, unsigned Cursor) { 3180 unsigned CursorIndex = std::numeric_limits<unsigned>::max(); 3181 unsigned OffsetToEOL = 0; 3182 for (int i = 0, e = Includes.size(); i != e; ++i) { 3183 unsigned Start = Includes[Indices[i]].Offset; 3184 unsigned End = Start + Includes[Indices[i]].Text.size(); 3185 if (!(Cursor >= Start && Cursor < End)) 3186 continue; 3187 CursorIndex = Indices[i]; 3188 OffsetToEOL = End - Cursor; 3189 // Put the cursor on the only remaining #include among the duplicate 3190 // #includes. 3191 while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text) 3192 CursorIndex = i; 3193 break; 3194 } 3195 return std::make_pair(CursorIndex, OffsetToEOL); 3196 } 3197 3198 // Replace all "\r\n" with "\n". 3199 std::string replaceCRLF(const std::string &Code) { 3200 std::string NewCode; 3201 size_t Pos = 0, LastPos = 0; 3202 3203 do { 3204 Pos = Code.find("\r\n", LastPos); 3205 if (Pos == LastPos) { 3206 ++LastPos; 3207 continue; 3208 } 3209 if (Pos == std::string::npos) { 3210 NewCode += Code.substr(LastPos); 3211 break; 3212 } 3213 NewCode += Code.substr(LastPos, Pos - LastPos) + "\n"; 3214 LastPos = Pos + 2; 3215 } while (Pos != std::string::npos); 3216 3217 return NewCode; 3218 } 3219 3220 // Sorts and deduplicate a block of includes given by 'Includes' alphabetically 3221 // adding the necessary replacement to 'Replaces'. 'Includes' must be in strict 3222 // source order. 3223 // #include directives with the same text will be deduplicated, and only the 3224 // first #include in the duplicate #includes remains. If the `Cursor` is 3225 // provided and put on a deleted #include, it will be moved to the remaining 3226 // #include in the duplicate #includes. 3227 static void sortCppIncludes(const FormatStyle &Style, 3228 const ArrayRef<IncludeDirective> &Includes, 3229 ArrayRef<tooling::Range> Ranges, StringRef FileName, 3230 StringRef Code, tooling::Replacements &Replaces, 3231 unsigned *Cursor) { 3232 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 3233 const unsigned IncludesBeginOffset = Includes.front().Offset; 3234 const unsigned IncludesEndOffset = 3235 Includes.back().Offset + Includes.back().Text.size(); 3236 const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset; 3237 if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset)) 3238 return; 3239 SmallVector<unsigned, 16> Indices = 3240 llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size())); 3241 3242 if (Style.SortIncludes.Enabled && Style.SortIncludes.IgnoreCase) { 3243 stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 3244 const auto LHSFilenameLower = Includes[LHSI].Filename.lower(); 3245 const auto RHSFilenameLower = Includes[RHSI].Filename.lower(); 3246 return std::tie(Includes[LHSI].Priority, LHSFilenameLower, 3247 Includes[LHSI].Filename) < 3248 std::tie(Includes[RHSI].Priority, RHSFilenameLower, 3249 Includes[RHSI].Filename); 3250 }); 3251 } else { 3252 stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 3253 return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) < 3254 std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename); 3255 }); 3256 } 3257 3258 // The index of the include on which the cursor will be put after 3259 // sorting/deduplicating. 3260 unsigned CursorIndex; 3261 // The offset from cursor to the end of line. 3262 unsigned CursorToEOLOffset; 3263 if (Cursor) { 3264 std::tie(CursorIndex, CursorToEOLOffset) = 3265 FindCursorIndex(Includes, Indices, *Cursor); 3266 } 3267 3268 // Deduplicate #includes. 3269 Indices.erase(llvm::unique(Indices, 3270 [&](unsigned LHSI, unsigned RHSI) { 3271 return Includes[LHSI].Text.trim() == 3272 Includes[RHSI].Text.trim(); 3273 }), 3274 Indices.end()); 3275 3276 int CurrentCategory = Includes.front().Category; 3277 3278 // If the #includes are out of order, we generate a single replacement fixing 3279 // the entire block. Otherwise, no replacement is generated. 3280 // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not 3281 // enough as additional newlines might be added or removed across #include 3282 // blocks. This we handle below by generating the updated #include blocks and 3283 // comparing it to the original. 3284 if (Indices.size() == Includes.size() && is_sorted(Indices) && 3285 Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) { 3286 return; 3287 } 3288 3289 const auto OldCursor = Cursor ? *Cursor : 0; 3290 std::string result; 3291 for (unsigned Index : Indices) { 3292 if (!result.empty()) { 3293 result += "\n"; 3294 if (Style.IncludeStyle.IncludeBlocks == 3295 tooling::IncludeStyle::IBS_Regroup && 3296 CurrentCategory != Includes[Index].Category) { 3297 result += "\n"; 3298 } 3299 } 3300 result += Includes[Index].Text; 3301 if (Cursor && CursorIndex == Index) 3302 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset; 3303 CurrentCategory = Includes[Index].Category; 3304 } 3305 3306 if (Cursor && *Cursor >= IncludesEndOffset) 3307 *Cursor += result.size() - IncludesBlockSize; 3308 3309 // If the #includes are out of order, we generate a single replacement fixing 3310 // the entire range of blocks. Otherwise, no replacement is generated. 3311 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 3312 IncludesBeginOffset, IncludesBlockSize)))) { 3313 if (Cursor) 3314 *Cursor = OldCursor; 3315 return; 3316 } 3317 3318 auto Err = Replaces.add(tooling::Replacement( 3319 FileName, Includes.front().Offset, IncludesBlockSize, result)); 3320 // FIXME: better error handling. For now, just skip the replacement for the 3321 // release version. 3322 if (Err) { 3323 llvm::errs() << toString(std::move(Err)) << "\n"; 3324 assert(false); 3325 } 3326 } 3327 3328 tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code, 3329 ArrayRef<tooling::Range> Ranges, 3330 StringRef FileName, 3331 tooling::Replacements &Replaces, 3332 unsigned *Cursor) { 3333 unsigned Prev = llvm::StringSwitch<size_t>(Code) 3334 .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM 3335 .Default(0); 3336 unsigned SearchFrom = 0; 3337 SmallVector<StringRef, 4> Matches; 3338 SmallVector<IncludeDirective, 16> IncludesInBlock; 3339 3340 // In compiled files, consider the first #include to be the main #include of 3341 // the file if it is not a system #include. This ensures that the header 3342 // doesn't have hidden dependencies 3343 // (http://llvm.org/docs/CodingStandards.html#include-style). 3344 // 3345 // FIXME: Do some validation, e.g. edit distance of the base name, to fix 3346 // cases where the first #include is unlikely to be the main header. 3347 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 3348 bool FirstIncludeBlock = true; 3349 bool MainIncludeFound = false; 3350 bool FormattingOff = false; 3351 3352 // '[' must be the first and '-' the last character inside [...]. 3353 llvm::Regex RawStringRegex( 3354 "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\("); 3355 SmallVector<StringRef, 2> RawStringMatches; 3356 std::string RawStringTermination = ")\""; 3357 3358 for (const auto Size = Code.size(); SearchFrom < Size;) { 3359 size_t Pos = SearchFrom; 3360 if (Code[SearchFrom] != '\n') { 3361 do { // Search for the first newline while skipping line splices. 3362 ++Pos; 3363 Pos = Code.find('\n', Pos); 3364 } while (Pos != StringRef::npos && Code[Pos - 1] == '\\'); 3365 } 3366 3367 StringRef Line = 3368 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 3369 3370 StringRef Trimmed = Line.trim(); 3371 3372 // #includes inside raw string literals need to be ignored. 3373 // or we will sort the contents of the string. 3374 // Skip past until we think we are at the rawstring literal close. 3375 if (RawStringRegex.match(Trimmed, &RawStringMatches)) { 3376 std::string CharSequence = RawStringMatches[1].str(); 3377 RawStringTermination = ")" + CharSequence + "\""; 3378 FormattingOff = true; 3379 } 3380 3381 if (Trimmed.contains(RawStringTermination)) 3382 FormattingOff = false; 3383 3384 bool IsBlockComment = false; 3385 3386 if (isClangFormatOff(Trimmed)) { 3387 FormattingOff = true; 3388 } else if (isClangFormatOn(Trimmed)) { 3389 FormattingOff = false; 3390 } else if (Trimmed.starts_with("/*")) { 3391 IsBlockComment = true; 3392 Pos = Code.find("*/", SearchFrom + 2); 3393 } 3394 3395 const bool EmptyLineSkipped = 3396 Trimmed.empty() && 3397 (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge || 3398 Style.IncludeStyle.IncludeBlocks == 3399 tooling::IncludeStyle::IBS_Regroup); 3400 3401 bool MergeWithNextLine = Trimmed.ends_with("\\"); 3402 if (!FormattingOff && !MergeWithNextLine) { 3403 if (!IsBlockComment && 3404 tooling::HeaderIncludes::IncludeRegex.match(Trimmed, &Matches)) { 3405 StringRef IncludeName = Matches[2]; 3406 if (Trimmed.contains("/*") && !Trimmed.contains("*/")) { 3407 // #include with a start of a block comment, but without the end. 3408 // Need to keep all the lines until the end of the comment together. 3409 // FIXME: This is somehow simplified check that probably does not work 3410 // correctly if there are multiple comments on a line. 3411 Pos = Code.find("*/", SearchFrom); 3412 Line = Code.substr( 3413 Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev); 3414 } 3415 int Category = Categories.getIncludePriority( 3416 IncludeName, 3417 /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock); 3418 int Priority = Categories.getSortIncludePriority( 3419 IncludeName, !MainIncludeFound && FirstIncludeBlock); 3420 if (Category == 0) 3421 MainIncludeFound = true; 3422 IncludesInBlock.push_back( 3423 {IncludeName, Line, Prev, Category, Priority}); 3424 } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) { 3425 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, 3426 Replaces, Cursor); 3427 IncludesInBlock.clear(); 3428 if (Trimmed.starts_with("#pragma hdrstop")) // Precompiled headers. 3429 FirstIncludeBlock = true; 3430 else 3431 FirstIncludeBlock = false; 3432 } 3433 } 3434 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 3435 break; 3436 3437 if (!MergeWithNextLine) 3438 Prev = Pos + 1; 3439 SearchFrom = Pos + 1; 3440 } 3441 if (!IncludesInBlock.empty()) { 3442 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces, 3443 Cursor); 3444 } 3445 return Replaces; 3446 } 3447 3448 // Returns group number to use as a first order sort on imports. Gives 3449 // std::numeric_limits<unsigned>::max() if the import does not match any given 3450 // groups. 3451 static unsigned findJavaImportGroup(const FormatStyle &Style, 3452 StringRef ImportIdentifier) { 3453 unsigned LongestMatchIndex = std::numeric_limits<unsigned>::max(); 3454 unsigned LongestMatchLength = 0; 3455 for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) { 3456 const std::string &GroupPrefix = Style.JavaImportGroups[I]; 3457 if (ImportIdentifier.starts_with(GroupPrefix) && 3458 GroupPrefix.length() > LongestMatchLength) { 3459 LongestMatchIndex = I; 3460 LongestMatchLength = GroupPrefix.length(); 3461 } 3462 } 3463 return LongestMatchIndex; 3464 } 3465 3466 // Sorts and deduplicates a block of includes given by 'Imports' based on 3467 // JavaImportGroups, then adding the necessary replacement to 'Replaces'. 3468 // Import declarations with the same text will be deduplicated. Between each 3469 // import group, a newline is inserted, and within each import group, a 3470 // lexicographic sort based on ASCII value is performed. 3471 static void sortJavaImports(const FormatStyle &Style, 3472 const ArrayRef<JavaImportDirective> &Imports, 3473 ArrayRef<tooling::Range> Ranges, StringRef FileName, 3474 StringRef Code, tooling::Replacements &Replaces) { 3475 unsigned ImportsBeginOffset = Imports.front().Offset; 3476 unsigned ImportsEndOffset = 3477 Imports.back().Offset + Imports.back().Text.size(); 3478 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset; 3479 if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset)) 3480 return; 3481 3482 SmallVector<unsigned, 16> Indices = 3483 llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size())); 3484 SmallVector<unsigned, 16> JavaImportGroups; 3485 JavaImportGroups.reserve(Imports.size()); 3486 for (const JavaImportDirective &Import : Imports) 3487 JavaImportGroups.push_back(findJavaImportGroup(Style, Import.Identifier)); 3488 3489 bool StaticImportAfterNormalImport = 3490 Style.SortJavaStaticImport == FormatStyle::SJSIO_After; 3491 sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 3492 // Negating IsStatic to push static imports above non-static imports. 3493 return std::make_tuple(!Imports[LHSI].IsStatic ^ 3494 StaticImportAfterNormalImport, 3495 JavaImportGroups[LHSI], Imports[LHSI].Identifier) < 3496 std::make_tuple(!Imports[RHSI].IsStatic ^ 3497 StaticImportAfterNormalImport, 3498 JavaImportGroups[RHSI], Imports[RHSI].Identifier); 3499 }); 3500 3501 // Deduplicate imports. 3502 Indices.erase(llvm::unique(Indices, 3503 [&](unsigned LHSI, unsigned RHSI) { 3504 return Imports[LHSI].Text == Imports[RHSI].Text; 3505 }), 3506 Indices.end()); 3507 3508 bool CurrentIsStatic = Imports[Indices.front()].IsStatic; 3509 unsigned CurrentImportGroup = JavaImportGroups[Indices.front()]; 3510 3511 std::string result; 3512 for (unsigned Index : Indices) { 3513 if (!result.empty()) { 3514 result += "\n"; 3515 if (CurrentIsStatic != Imports[Index].IsStatic || 3516 CurrentImportGroup != JavaImportGroups[Index]) { 3517 result += "\n"; 3518 } 3519 } 3520 for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) { 3521 result += CommentLine; 3522 result += "\n"; 3523 } 3524 result += Imports[Index].Text; 3525 CurrentIsStatic = Imports[Index].IsStatic; 3526 CurrentImportGroup = JavaImportGroups[Index]; 3527 } 3528 3529 // If the imports are out of order, we generate a single replacement fixing 3530 // the entire block. Otherwise, no replacement is generated. 3531 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 3532 Imports.front().Offset, ImportsBlockSize)))) { 3533 return; 3534 } 3535 3536 auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset, 3537 ImportsBlockSize, result)); 3538 // FIXME: better error handling. For now, just skip the replacement for the 3539 // release version. 3540 if (Err) { 3541 llvm::errs() << toString(std::move(Err)) << "\n"; 3542 assert(false); 3543 } 3544 } 3545 3546 namespace { 3547 3548 const char JavaImportRegexPattern[] = 3549 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;"; 3550 3551 } // anonymous namespace 3552 3553 tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code, 3554 ArrayRef<tooling::Range> Ranges, 3555 StringRef FileName, 3556 tooling::Replacements &Replaces) { 3557 unsigned Prev = 0; 3558 unsigned SearchFrom = 0; 3559 llvm::Regex ImportRegex(JavaImportRegexPattern); 3560 SmallVector<StringRef, 4> Matches; 3561 SmallVector<JavaImportDirective, 16> ImportsInBlock; 3562 SmallVector<StringRef> AssociatedCommentLines; 3563 3564 bool FormattingOff = false; 3565 3566 for (;;) { 3567 auto Pos = Code.find('\n', SearchFrom); 3568 StringRef Line = 3569 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 3570 3571 StringRef Trimmed = Line.trim(); 3572 if (isClangFormatOff(Trimmed)) 3573 FormattingOff = true; 3574 else if (isClangFormatOn(Trimmed)) 3575 FormattingOff = false; 3576 3577 if (ImportRegex.match(Line, &Matches)) { 3578 if (FormattingOff) { 3579 // If at least one import line has formatting turned off, turn off 3580 // formatting entirely. 3581 return Replaces; 3582 } 3583 StringRef Static = Matches[1]; 3584 StringRef Identifier = Matches[2]; 3585 bool IsStatic = false; 3586 if (Static.contains("static")) 3587 IsStatic = true; 3588 ImportsInBlock.push_back( 3589 {Identifier, Line, Prev, AssociatedCommentLines, IsStatic}); 3590 AssociatedCommentLines.clear(); 3591 } else if (!Trimmed.empty() && !ImportsInBlock.empty()) { 3592 // Associating comments within the imports with the nearest import below 3593 AssociatedCommentLines.push_back(Line); 3594 } 3595 Prev = Pos + 1; 3596 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 3597 break; 3598 SearchFrom = Pos + 1; 3599 } 3600 if (!ImportsInBlock.empty()) 3601 sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces); 3602 return Replaces; 3603 } 3604 3605 bool isMpegTS(StringRef Code) { 3606 // MPEG transport streams use the ".ts" file extension. clang-format should 3607 // not attempt to format those. MPEG TS' frame format starts with 0x47 every 3608 // 189 bytes - detect that and return. 3609 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47; 3610 } 3611 3612 bool isLikelyXml(StringRef Code) { return Code.ltrim().starts_with("<"); } 3613 3614 tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, 3615 ArrayRef<tooling::Range> Ranges, 3616 StringRef FileName, unsigned *Cursor) { 3617 tooling::Replacements Replaces; 3618 if (!Style.SortIncludes.Enabled || Style.DisableFormat) 3619 return Replaces; 3620 if (isLikelyXml(Code)) 3621 return Replaces; 3622 if (Style.isJavaScript()) { 3623 if (isMpegTS(Code)) 3624 return Replaces; 3625 return sortJavaScriptImports(Style, Code, Ranges, FileName); 3626 } 3627 if (Style.isJava()) 3628 return sortJavaImports(Style, Code, Ranges, FileName, Replaces); 3629 if (Style.isCpp()) 3630 sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor); 3631 return Replaces; 3632 } 3633 3634 template <typename T> 3635 static Expected<tooling::Replacements> 3636 processReplacements(T ProcessFunc, StringRef Code, 3637 const tooling::Replacements &Replaces, 3638 const FormatStyle &Style) { 3639 if (Replaces.empty()) 3640 return tooling::Replacements(); 3641 3642 auto NewCode = applyAllReplacements(Code, Replaces); 3643 if (!NewCode) 3644 return NewCode.takeError(); 3645 std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges(); 3646 StringRef FileName = Replaces.begin()->getFilePath(); 3647 3648 tooling::Replacements FormatReplaces = 3649 ProcessFunc(Style, *NewCode, ChangedRanges, FileName); 3650 3651 return Replaces.merge(FormatReplaces); 3652 } 3653 3654 Expected<tooling::Replacements> 3655 formatReplacements(StringRef Code, const tooling::Replacements &Replaces, 3656 const FormatStyle &Style) { 3657 // We need to use lambda function here since there are two versions of 3658 // `sortIncludes`. 3659 auto SortIncludes = [](const FormatStyle &Style, StringRef Code, 3660 std::vector<tooling::Range> Ranges, 3661 StringRef FileName) -> tooling::Replacements { 3662 return sortIncludes(Style, Code, Ranges, FileName); 3663 }; 3664 auto SortedReplaces = 3665 processReplacements(SortIncludes, Code, Replaces, Style); 3666 if (!SortedReplaces) 3667 return SortedReplaces.takeError(); 3668 3669 // We need to use lambda function here since there are two versions of 3670 // `reformat`. 3671 auto Reformat = [](const FormatStyle &Style, StringRef Code, 3672 std::vector<tooling::Range> Ranges, 3673 StringRef FileName) -> tooling::Replacements { 3674 return reformat(Style, Code, Ranges, FileName); 3675 }; 3676 return processReplacements(Reformat, Code, *SortedReplaces, Style); 3677 } 3678 3679 namespace { 3680 3681 inline bool isHeaderInsertion(const tooling::Replacement &Replace) { 3682 return Replace.getOffset() == std::numeric_limits<unsigned>::max() && 3683 Replace.getLength() == 0 && 3684 tooling::HeaderIncludes::IncludeRegex.match( 3685 Replace.getReplacementText()); 3686 } 3687 3688 inline bool isHeaderDeletion(const tooling::Replacement &Replace) { 3689 return Replace.getOffset() == std::numeric_limits<unsigned>::max() && 3690 Replace.getLength() == 1; 3691 } 3692 3693 // FIXME: insert empty lines between newly created blocks. 3694 tooling::Replacements 3695 fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces, 3696 const FormatStyle &Style) { 3697 if (!Style.isCpp()) 3698 return Replaces; 3699 3700 tooling::Replacements HeaderInsertions; 3701 std::set<StringRef> HeadersToDelete; 3702 tooling::Replacements Result; 3703 for (const auto &R : Replaces) { 3704 if (isHeaderInsertion(R)) { 3705 // Replacements from \p Replaces must be conflict-free already, so we can 3706 // simply consume the error. 3707 consumeError(HeaderInsertions.add(R)); 3708 } else if (isHeaderDeletion(R)) { 3709 HeadersToDelete.insert(R.getReplacementText()); 3710 } else if (R.getOffset() == std::numeric_limits<unsigned>::max()) { 3711 llvm::errs() << "Insertions other than header #include insertion are " 3712 "not supported! " 3713 << R.getReplacementText() << "\n"; 3714 } else { 3715 consumeError(Result.add(R)); 3716 } 3717 } 3718 if (HeaderInsertions.empty() && HeadersToDelete.empty()) 3719 return Replaces; 3720 3721 StringRef FileName = Replaces.begin()->getFilePath(); 3722 tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle); 3723 3724 for (const auto &Header : HeadersToDelete) { 3725 tooling::Replacements Replaces = 3726 Includes.remove(Header.trim("\"<>"), Header.starts_with("<")); 3727 for (const auto &R : Replaces) { 3728 auto Err = Result.add(R); 3729 if (Err) { 3730 // Ignore the deletion on conflict. 3731 llvm::errs() << "Failed to add header deletion replacement for " 3732 << Header << ": " << toString(std::move(Err)) << "\n"; 3733 } 3734 } 3735 } 3736 3737 SmallVector<StringRef, 4> Matches; 3738 for (const auto &R : HeaderInsertions) { 3739 auto IncludeDirective = R.getReplacementText(); 3740 bool Matched = 3741 tooling::HeaderIncludes::IncludeRegex.match(IncludeDirective, &Matches); 3742 assert(Matched && "Header insertion replacement must have replacement text " 3743 "'#include ...'"); 3744 (void)Matched; 3745 auto IncludeName = Matches[2]; 3746 auto Replace = 3747 Includes.insert(IncludeName.trim("\"<>"), IncludeName.starts_with("<"), 3748 tooling::IncludeDirective::Include); 3749 if (Replace) { 3750 auto Err = Result.add(*Replace); 3751 if (Err) { 3752 consumeError(std::move(Err)); 3753 unsigned NewOffset = 3754 Result.getShiftedCodePosition(Replace->getOffset()); 3755 auto Shifted = tooling::Replacement(FileName, NewOffset, 0, 3756 Replace->getReplacementText()); 3757 Result = Result.merge(tooling::Replacements(Shifted)); 3758 } 3759 } 3760 } 3761 return Result; 3762 } 3763 3764 } // anonymous namespace 3765 3766 Expected<tooling::Replacements> 3767 cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, 3768 const FormatStyle &Style) { 3769 // We need to use lambda function here since there are two versions of 3770 // `cleanup`. 3771 auto Cleanup = [](const FormatStyle &Style, StringRef Code, 3772 ArrayRef<tooling::Range> Ranges, 3773 StringRef FileName) -> tooling::Replacements { 3774 return cleanup(Style, Code, Ranges, FileName); 3775 }; 3776 // Make header insertion replacements insert new headers into correct blocks. 3777 tooling::Replacements NewReplaces = 3778 fixCppIncludeInsertions(Code, Replaces, Style); 3779 return cantFail(processReplacements(Cleanup, Code, NewReplaces, Style)); 3780 } 3781 3782 namespace internal { 3783 std::pair<tooling::Replacements, unsigned> 3784 reformat(const FormatStyle &Style, StringRef Code, 3785 ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn, 3786 unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName, 3787 FormattingAttemptStatus *Status) { 3788 FormatStyle Expanded = Style; 3789 expandPresetsBraceWrapping(Expanded); 3790 expandPresetsSpaceBeforeParens(Expanded); 3791 expandPresetsSpacesInParens(Expanded); 3792 Expanded.InsertBraces = false; 3793 Expanded.RemoveBracesLLVM = false; 3794 Expanded.RemoveParentheses = FormatStyle::RPS_Leave; 3795 Expanded.RemoveSemicolon = false; 3796 switch (Expanded.RequiresClausePosition) { 3797 case FormatStyle::RCPS_SingleLine: 3798 case FormatStyle::RCPS_WithPreceding: 3799 Expanded.IndentRequiresClause = false; 3800 break; 3801 default: 3802 break; 3803 } 3804 3805 if (Expanded.DisableFormat) 3806 return {tooling::Replacements(), 0}; 3807 if (isLikelyXml(Code)) 3808 return {tooling::Replacements(), 0}; 3809 if (Expanded.isJavaScript() && isMpegTS(Code)) 3810 return {tooling::Replacements(), 0}; 3811 3812 // JSON only needs the formatting passing. 3813 if (Style.isJson()) { 3814 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); 3815 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn, 3816 NextStartColumn, LastStartColumn); 3817 if (!Env) 3818 return {}; 3819 // Perform the actual formatting pass. 3820 tooling::Replacements Replaces = 3821 Formatter(*Env, Style, Status).process().first; 3822 // add a replacement to remove the "x = " from the result. 3823 if (Code.starts_with("x = ")) { 3824 Replaces = Replaces.merge( 3825 tooling::Replacements(tooling::Replacement(FileName, 0, 4, ""))); 3826 } 3827 // apply the reformatting changes and the removal of "x = ". 3828 if (applyAllReplacements(Code, Replaces)) 3829 return {Replaces, 0}; 3830 return {tooling::Replacements(), 0}; 3831 } 3832 3833 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn, 3834 NextStartColumn, LastStartColumn); 3835 if (!Env) 3836 return {}; 3837 3838 typedef std::function<std::pair<tooling::Replacements, unsigned>( 3839 const Environment &)> 3840 AnalyzerPass; 3841 3842 SmallVector<AnalyzerPass, 16> Passes; 3843 3844 Passes.emplace_back([&](const Environment &Env) { 3845 return IntegerLiteralSeparatorFixer().process(Env, Expanded); 3846 }); 3847 3848 if (Style.isCpp()) { 3849 if (Style.QualifierAlignment != FormatStyle::QAS_Leave) 3850 addQualifierAlignmentFixerPasses(Expanded, Passes); 3851 3852 if (Style.RemoveParentheses != FormatStyle::RPS_Leave) { 3853 FormatStyle S = Expanded; 3854 S.RemoveParentheses = Style.RemoveParentheses; 3855 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) { 3856 return ParensRemover(Env, S).process(/*SkipAnnotation=*/true); 3857 }); 3858 } 3859 3860 if (Style.InsertBraces) { 3861 FormatStyle S = Expanded; 3862 S.InsertBraces = true; 3863 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) { 3864 return BracesInserter(Env, S).process(/*SkipAnnotation=*/true); 3865 }); 3866 } 3867 3868 if (Style.RemoveBracesLLVM) { 3869 FormatStyle S = Expanded; 3870 S.RemoveBracesLLVM = true; 3871 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) { 3872 return BracesRemover(Env, S).process(/*SkipAnnotation=*/true); 3873 }); 3874 } 3875 3876 if (Style.RemoveSemicolon) { 3877 FormatStyle S = Expanded; 3878 S.RemoveSemicolon = true; 3879 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) { 3880 return SemiRemover(Env, S).process(); 3881 }); 3882 } 3883 3884 if (Style.EnumTrailingComma != FormatStyle::ETC_Leave) { 3885 Passes.emplace_back([&](const Environment &Env) { 3886 return EnumTrailingCommaEditor(Env, Expanded) 3887 .process(/*SkipAnnotation=*/true); 3888 }); 3889 } 3890 3891 if (Style.FixNamespaceComments) { 3892 Passes.emplace_back([&](const Environment &Env) { 3893 return NamespaceEndCommentsFixer(Env, Expanded).process(); 3894 }); 3895 } 3896 3897 if (Style.SortUsingDeclarations != FormatStyle::SUD_Never) { 3898 Passes.emplace_back([&](const Environment &Env) { 3899 return UsingDeclarationsSorter(Env, Expanded).process(); 3900 }); 3901 } 3902 } 3903 3904 if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) { 3905 Passes.emplace_back([&](const Environment &Env) { 3906 return DefinitionBlockSeparator(Env, Expanded).process(); 3907 }); 3908 } 3909 3910 if (Style.Language == FormatStyle::LK_ObjC && 3911 !Style.ObjCPropertyAttributeOrder.empty()) { 3912 Passes.emplace_back([&](const Environment &Env) { 3913 return ObjCPropertyAttributeOrderFixer(Env, Expanded).process(); 3914 }); 3915 } 3916 3917 if (Style.isJavaScript() && 3918 Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) { 3919 Passes.emplace_back([&](const Environment &Env) { 3920 return JavaScriptRequoter(Env, Expanded).process(/*SkipAnnotation=*/true); 3921 }); 3922 } 3923 3924 Passes.emplace_back([&](const Environment &Env) { 3925 return Formatter(Env, Expanded, Status).process(); 3926 }); 3927 3928 if (Style.isJavaScript() && 3929 Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) { 3930 Passes.emplace_back([&](const Environment &Env) { 3931 return TrailingCommaInserter(Env, Expanded).process(); 3932 }); 3933 } 3934 3935 std::optional<std::string> CurrentCode; 3936 tooling::Replacements Fixes; 3937 unsigned Penalty = 0; 3938 for (size_t I = 0, E = Passes.size(); I < E; ++I) { 3939 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env); 3940 auto NewCode = applyAllReplacements( 3941 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first); 3942 if (NewCode) { 3943 Fixes = Fixes.merge(PassFixes.first); 3944 Penalty += PassFixes.second; 3945 if (I + 1 < E) { 3946 CurrentCode = std::move(*NewCode); 3947 Env = Environment::make( 3948 *CurrentCode, FileName, 3949 tooling::calculateRangesAfterReplacements(Fixes, Ranges), 3950 FirstStartColumn, NextStartColumn, LastStartColumn); 3951 if (!Env) 3952 return {}; 3953 } 3954 } 3955 } 3956 3957 if (Style.QualifierAlignment != FormatStyle::QAS_Leave) { 3958 // Don't make replacements that replace nothing. QualifierAlignment can 3959 // produce them if one of its early passes changes e.g. `const volatile` to 3960 // `volatile const` and then a later pass changes it back again. 3961 tooling::Replacements NonNoOpFixes; 3962 for (const tooling::Replacement &Fix : Fixes) { 3963 StringRef OriginalCode = Code.substr(Fix.getOffset(), Fix.getLength()); 3964 if (OriginalCode != Fix.getReplacementText()) { 3965 auto Err = NonNoOpFixes.add(Fix); 3966 if (Err) { 3967 llvm::errs() << "Error adding replacements : " 3968 << toString(std::move(Err)) << "\n"; 3969 } 3970 } 3971 } 3972 Fixes = std::move(NonNoOpFixes); 3973 } 3974 3975 return {Fixes, Penalty}; 3976 } 3977 } // namespace internal 3978 3979 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 3980 ArrayRef<tooling::Range> Ranges, 3981 StringRef FileName, 3982 FormattingAttemptStatus *Status) { 3983 return internal::reformat(Style, Code, Ranges, 3984 /*FirstStartColumn=*/0, 3985 /*NextStartColumn=*/0, 3986 /*LastStartColumn=*/0, FileName, Status) 3987 .first; 3988 } 3989 3990 tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, 3991 ArrayRef<tooling::Range> Ranges, 3992 StringRef FileName) { 3993 // cleanups only apply to C++ (they mostly concern ctor commas etc.) 3994 if (Style.Language != FormatStyle::LK_Cpp) 3995 return tooling::Replacements(); 3996 auto Env = Environment::make(Code, FileName, Ranges); 3997 if (!Env) 3998 return {}; 3999 return Cleaner(*Env, Style).process().first; 4000 } 4001 4002 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 4003 ArrayRef<tooling::Range> Ranges, 4004 StringRef FileName, bool *IncompleteFormat) { 4005 FormattingAttemptStatus Status; 4006 auto Result = reformat(Style, Code, Ranges, FileName, &Status); 4007 if (!Status.FormatComplete) 4008 *IncompleteFormat = true; 4009 return Result; 4010 } 4011 4012 tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, 4013 StringRef Code, 4014 ArrayRef<tooling::Range> Ranges, 4015 StringRef FileName) { 4016 auto Env = Environment::make(Code, FileName, Ranges); 4017 if (!Env) 4018 return {}; 4019 return NamespaceEndCommentsFixer(*Env, Style).process().first; 4020 } 4021 4022 tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, 4023 StringRef Code, 4024 ArrayRef<tooling::Range> Ranges, 4025 StringRef FileName) { 4026 auto Env = Environment::make(Code, FileName, Ranges); 4027 if (!Env) 4028 return {}; 4029 return UsingDeclarationsSorter(*Env, Style).process().first; 4030 } 4031 4032 LangOptions getFormattingLangOpts(const FormatStyle &Style) { 4033 LangOptions LangOpts; 4034 4035 auto LexingStd = Style.Standard; 4036 if (LexingStd == FormatStyle::LS_Auto || LexingStd == FormatStyle::LS_Latest) 4037 LexingStd = FormatStyle::LS_Cpp20; 4038 4039 const bool SinceCpp11 = LexingStd >= FormatStyle::LS_Cpp11; 4040 const bool SinceCpp20 = LexingStd >= FormatStyle::LS_Cpp20; 4041 4042 switch (Style.Language) { 4043 case FormatStyle::LK_C: 4044 LangOpts.C11 = 1; 4045 break; 4046 case FormatStyle::LK_Cpp: 4047 case FormatStyle::LK_ObjC: 4048 LangOpts.CXXOperatorNames = 1; 4049 LangOpts.CPlusPlus11 = SinceCpp11; 4050 LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14; 4051 LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17; 4052 LangOpts.CPlusPlus20 = SinceCpp20; 4053 [[fallthrough]]; 4054 default: 4055 LangOpts.CPlusPlus = 1; 4056 } 4057 4058 LangOpts.Char8 = SinceCpp20; 4059 // Turning on digraphs in standards before C++0x is error-prone, because e.g. 4060 // the sequence "<::" will be unconditionally treated as "[:". 4061 // Cf. Lexer::LexTokenInternal. 4062 LangOpts.Digraphs = SinceCpp11; 4063 4064 LangOpts.LineComment = 1; 4065 LangOpts.Bool = 1; 4066 LangOpts.ObjC = 1; 4067 LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally. 4068 LangOpts.DeclSpecKeyword = 1; // To get __declspec. 4069 LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict. 4070 4071 return LangOpts; 4072 } 4073 4074 const char *StyleOptionHelpDescription = 4075 "Set coding style. <string> can be:\n" 4076 "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n" 4077 " Mozilla, WebKit.\n" 4078 "2. 'file' to load style configuration from a\n" 4079 " .clang-format file in one of the parent directories\n" 4080 " of the source file (for stdin, see --assume-filename).\n" 4081 " If no .clang-format file is found, falls back to\n" 4082 " --fallback-style.\n" 4083 " --style=file is the default.\n" 4084 "3. 'file:<format_file_path>' to explicitly specify\n" 4085 " the configuration file.\n" 4086 "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n" 4087 " --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""; 4088 4089 static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) { 4090 if (FileName.ends_with(".c")) 4091 return FormatStyle::LK_C; 4092 if (FileName.ends_with(".java")) 4093 return FormatStyle::LK_Java; 4094 if (FileName.ends_with_insensitive(".js") || 4095 FileName.ends_with_insensitive(".mjs") || 4096 FileName.ends_with_insensitive(".cjs") || 4097 FileName.ends_with_insensitive(".ts")) { 4098 return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript. 4099 } 4100 if (FileName.ends_with(".m") || FileName.ends_with(".mm")) 4101 return FormatStyle::LK_ObjC; 4102 if (FileName.ends_with_insensitive(".proto") || 4103 FileName.ends_with_insensitive(".protodevel")) { 4104 return FormatStyle::LK_Proto; 4105 } 4106 // txtpb is the canonical extension, and textproto is the legacy canonical 4107 // extension 4108 // https://protobuf.dev/reference/protobuf/textformat-spec/#text-format-files 4109 if (FileName.ends_with_insensitive(".txtpb") || 4110 FileName.ends_with_insensitive(".textpb") || 4111 FileName.ends_with_insensitive(".pb.txt") || 4112 FileName.ends_with_insensitive(".textproto") || 4113 FileName.ends_with_insensitive(".asciipb")) { 4114 return FormatStyle::LK_TextProto; 4115 } 4116 if (FileName.ends_with_insensitive(".td")) 4117 return FormatStyle::LK_TableGen; 4118 if (FileName.ends_with_insensitive(".cs")) 4119 return FormatStyle::LK_CSharp; 4120 if (FileName.ends_with_insensitive(".json") || 4121 FileName.ends_with_insensitive(".ipynb")) { 4122 return FormatStyle::LK_Json; 4123 } 4124 if (FileName.ends_with_insensitive(".sv") || 4125 FileName.ends_with_insensitive(".svh") || 4126 FileName.ends_with_insensitive(".v") || 4127 FileName.ends_with_insensitive(".vh")) { 4128 return FormatStyle::LK_Verilog; 4129 } 4130 return FormatStyle::LK_Cpp; 4131 } 4132 4133 static FormatStyle::LanguageKind getLanguageByComment(const Environment &Env) { 4134 const auto ID = Env.getFileID(); 4135 const auto &SourceMgr = Env.getSourceManager(); 4136 4137 LangOptions LangOpts; 4138 LangOpts.CPlusPlus = 1; 4139 LangOpts.LineComment = 1; 4140 4141 Lexer Lex(ID, SourceMgr.getBufferOrFake(ID), SourceMgr, LangOpts); 4142 Lex.SetCommentRetentionState(true); 4143 4144 for (Token Tok; !Lex.LexFromRawLexer(Tok) && Tok.is(tok::comment);) { 4145 auto Text = StringRef(SourceMgr.getCharacterData(Tok.getLocation()), 4146 Tok.getLength()); 4147 if (!Text.consume_front("// clang-format Language:")) 4148 continue; 4149 4150 Text = Text.trim(); 4151 if (Text == "C") 4152 return FormatStyle::LK_C; 4153 if (Text == "Cpp") 4154 return FormatStyle::LK_Cpp; 4155 if (Text == "ObjC") 4156 return FormatStyle::LK_ObjC; 4157 } 4158 4159 return FormatStyle::LK_None; 4160 } 4161 4162 FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) { 4163 const auto GuessedLanguage = getLanguageByFileName(FileName); 4164 if (GuessedLanguage == FormatStyle::LK_Cpp) { 4165 auto Extension = llvm::sys::path::extension(FileName); 4166 // If there's no file extension (or it's .h), we need to check the contents 4167 // of the code to see if it contains Objective-C. 4168 if (!Code.empty() && (Extension.empty() || Extension == ".h")) { 4169 auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName; 4170 Environment Env(Code, NonEmptyFileName, /*Ranges=*/{}); 4171 if (const auto Language = getLanguageByComment(Env); 4172 Language != FormatStyle::LK_None) { 4173 return Language; 4174 } 4175 ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle()); 4176 Guesser.process(); 4177 if (Guesser.isObjC()) 4178 return FormatStyle::LK_ObjC; 4179 } 4180 } 4181 return GuessedLanguage; 4182 } 4183 4184 // Update StyleOptionHelpDescription above when changing this. 4185 const char *DefaultFormatStyle = "file"; 4186 4187 const char *DefaultFallbackStyle = "LLVM"; 4188 4189 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> 4190 loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS, 4191 FormatStyle *Style, bool AllowUnknownOptions, 4192 llvm::SourceMgr::DiagHandlerTy DiagHandler, 4193 bool IsDotHFile) { 4194 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 4195 FS->getBufferForFile(ConfigFile.str()); 4196 if (auto EC = Text.getError()) 4197 return EC; 4198 if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions, 4199 DiagHandler, /*DiagHandlerCtx=*/nullptr, 4200 IsDotHFile)) { 4201 return EC; 4202 } 4203 return Text; 4204 } 4205 4206 Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, 4207 StringRef FallbackStyleName, StringRef Code, 4208 llvm::vfs::FileSystem *FS, 4209 bool AllowUnknownOptions, 4210 llvm::SourceMgr::DiagHandlerTy DiagHandler) { 4211 FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code)); 4212 FormatStyle FallbackStyle = getNoStyle(); 4213 if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle)) 4214 return make_string_error("Invalid fallback style: " + FallbackStyleName); 4215 4216 SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1> ChildFormatTextToApply; 4217 4218 if (StyleName.starts_with("{")) { 4219 // Parse YAML/JSON style from the command line. 4220 StringRef Source = "<command-line>"; 4221 if (std::error_code ec = 4222 parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style, 4223 AllowUnknownOptions, DiagHandler)) { 4224 return make_string_error("Error parsing -style: " + ec.message()); 4225 } 4226 4227 if (!Style.InheritsParentConfig) 4228 return Style; 4229 4230 ChildFormatTextToApply.emplace_back( 4231 llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false)); 4232 } 4233 4234 if (!FS) 4235 FS = llvm::vfs::getRealFileSystem().get(); 4236 assert(FS); 4237 4238 const bool IsDotHFile = FileName.ends_with(".h"); 4239 4240 // User provided clang-format file using -style=file:path/to/format/file. 4241 if (!Style.InheritsParentConfig && 4242 StyleName.starts_with_insensitive("file:")) { 4243 auto ConfigFile = StyleName.substr(5); 4244 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 4245 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions, 4246 DiagHandler, IsDotHFile); 4247 if (auto EC = Text.getError()) { 4248 return make_string_error("Error reading " + ConfigFile + ": " + 4249 EC.message()); 4250 } 4251 4252 LLVM_DEBUG(llvm::dbgs() 4253 << "Using configuration file " << ConfigFile << "\n"); 4254 4255 if (!Style.InheritsParentConfig) 4256 return Style; 4257 4258 // Search for parent configs starting from the parent directory of 4259 // ConfigFile. 4260 FileName = ConfigFile; 4261 ChildFormatTextToApply.emplace_back(std::move(*Text)); 4262 } 4263 4264 // If the style inherits the parent configuration it is a command line 4265 // configuration, which wants to inherit, so we have to skip the check of the 4266 // StyleName. 4267 if (!Style.InheritsParentConfig && !StyleName.equals_insensitive("file")) { 4268 if (!getPredefinedStyle(StyleName, Style.Language, &Style)) 4269 return make_string_error("Invalid value for -style"); 4270 if (!Style.InheritsParentConfig) 4271 return Style; 4272 } 4273 4274 SmallString<128> Path(FileName); 4275 if (std::error_code EC = FS->makeAbsolute(Path)) 4276 return make_string_error(EC.message()); 4277 4278 // Reset possible inheritance 4279 Style.InheritsParentConfig = false; 4280 4281 auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {}; 4282 4283 auto applyChildFormatTexts = [&](FormatStyle *Style) { 4284 for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) { 4285 auto EC = 4286 parseConfiguration(*MemBuf, Style, AllowUnknownOptions, 4287 DiagHandler ? DiagHandler : dropDiagnosticHandler); 4288 // It was already correctly parsed. 4289 assert(!EC); 4290 static_cast<void>(EC); 4291 } 4292 }; 4293 4294 // Look for .clang-format/_clang-format file in the file's parent directories. 4295 SmallVector<std::string, 2> FilesToLookFor; 4296 FilesToLookFor.push_back(".clang-format"); 4297 FilesToLookFor.push_back("_clang-format"); 4298 4299 SmallString<128> UnsuitableConfigFiles; 4300 for (StringRef Directory = Path; !Directory.empty(); 4301 Directory = llvm::sys::path::parent_path(Directory)) { 4302 auto Status = FS->status(Directory); 4303 if (!Status || 4304 Status->getType() != llvm::sys::fs::file_type::directory_file) { 4305 continue; 4306 } 4307 4308 for (const auto &F : FilesToLookFor) { 4309 SmallString<128> ConfigFile(Directory); 4310 4311 llvm::sys::path::append(ConfigFile, F); 4312 LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); 4313 4314 Status = FS->status(ConfigFile); 4315 if (!Status || 4316 Status->getType() != llvm::sys::fs::file_type::regular_file) { 4317 continue; 4318 } 4319 4320 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 4321 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions, 4322 DiagHandler, IsDotHFile); 4323 if (auto EC = Text.getError()) { 4324 if (EC != ParseError::Unsuitable) { 4325 return make_string_error("Error reading " + ConfigFile + ": " + 4326 EC.message()); 4327 } 4328 if (!UnsuitableConfigFiles.empty()) 4329 UnsuitableConfigFiles.append(", "); 4330 UnsuitableConfigFiles.append(ConfigFile); 4331 continue; 4332 } 4333 4334 LLVM_DEBUG(llvm::dbgs() 4335 << "Using configuration file " << ConfigFile << "\n"); 4336 4337 if (!Style.InheritsParentConfig) { 4338 if (!ChildFormatTextToApply.empty()) { 4339 LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n"); 4340 applyChildFormatTexts(&Style); 4341 } 4342 return Style; 4343 } 4344 4345 LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n"); 4346 4347 // Reset inheritance of style 4348 Style.InheritsParentConfig = false; 4349 4350 ChildFormatTextToApply.emplace_back(std::move(*Text)); 4351 4352 // Breaking out of the inner loop, since we don't want to parse 4353 // .clang-format AND _clang-format, if both exist. Then we continue the 4354 // outer loop (parent directories) in search for the parent 4355 // configuration. 4356 break; 4357 } 4358 } 4359 4360 if (!UnsuitableConfigFiles.empty()) { 4361 return make_string_error("Configuration file(s) do(es) not support " + 4362 getLanguageName(Style.Language) + ": " + 4363 UnsuitableConfigFiles); 4364 } 4365 4366 if (!ChildFormatTextToApply.empty()) { 4367 LLVM_DEBUG(llvm::dbgs() 4368 << "Applying child configurations on fallback style\n"); 4369 applyChildFormatTexts(&FallbackStyle); 4370 } 4371 4372 return FallbackStyle; 4373 } 4374 4375 static bool isClangFormatOnOff(StringRef Comment, bool On) { 4376 if (Comment == (On ? "/* clang-format on */" : "/* clang-format off */")) 4377 return true; 4378 4379 static const char ClangFormatOn[] = "// clang-format on"; 4380 static const char ClangFormatOff[] = "// clang-format off"; 4381 const unsigned Size = (On ? sizeof ClangFormatOn : sizeof ClangFormatOff) - 1; 4382 4383 return Comment.starts_with(On ? ClangFormatOn : ClangFormatOff) && 4384 (Comment.size() == Size || Comment[Size] == ':'); 4385 } 4386 4387 bool isClangFormatOn(StringRef Comment) { 4388 return isClangFormatOnOff(Comment, /*On=*/true); 4389 } 4390 4391 bool isClangFormatOff(StringRef Comment) { 4392 return isClangFormatOnOff(Comment, /*On=*/false); 4393 } 4394 4395 } // namespace format 4396 } // namespace clang 4397