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