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