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