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