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