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