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