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