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("AfterOverloadedOperator", Spacing.AfterOverloadedOperator); 872 IO.mapOptional("BeforeNonEmptyParentheses", 873 Spacing.BeforeNonEmptyParentheses); 874 } 875 }; 876 877 template <> struct MappingTraits<FormatStyle::RawStringFormat> { 878 static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) { 879 IO.mapOptional("Language", Format.Language); 880 IO.mapOptional("Delimiters", Format.Delimiters); 881 IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions); 882 IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter); 883 IO.mapOptional("BasedOnStyle", Format.BasedOnStyle); 884 } 885 }; 886 887 template <> struct MappingTraits<FormatStyle::SpacesInLineComment> { 888 static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) { 889 // Transform the maximum to signed, to parse "-1" correctly 890 int signedMaximum = static_cast<int>(Space.Maximum); 891 IO.mapOptional("Minimum", Space.Minimum); 892 IO.mapOptional("Maximum", signedMaximum); 893 Space.Maximum = static_cast<unsigned>(signedMaximum); 894 895 if (Space.Maximum != -1u) { 896 Space.Minimum = std::min(Space.Minimum, Space.Maximum); 897 } 898 } 899 }; 900 901 // Allows to read vector<FormatStyle> while keeping default values. 902 // IO.getContext() should contain a pointer to the FormatStyle structure, that 903 // will be used to get default values for missing keys. 904 // If the first element has no Language specified, it will be treated as the 905 // default one for the following elements. 906 template <> struct DocumentListTraits<std::vector<FormatStyle>> { 907 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) { 908 return Seq.size(); 909 } 910 static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq, 911 size_t Index) { 912 if (Index >= Seq.size()) { 913 assert(Index == Seq.size()); 914 FormatStyle Template; 915 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) { 916 Template = Seq[0]; 917 } else { 918 Template = *((const FormatStyle *)IO.getContext()); 919 Template.Language = FormatStyle::LK_None; 920 } 921 Seq.resize(Index + 1, Template); 922 } 923 return Seq[Index]; 924 } 925 }; 926 } // namespace yaml 927 } // namespace llvm 928 929 namespace clang { 930 namespace format { 931 932 const std::error_category &getParseCategory() { 933 static const ParseErrorCategory C{}; 934 return C; 935 } 936 std::error_code make_error_code(ParseError e) { 937 return std::error_code(static_cast<int>(e), getParseCategory()); 938 } 939 940 inline llvm::Error make_string_error(const llvm::Twine &Message) { 941 return llvm::make_error<llvm::StringError>(Message, 942 llvm::inconvertibleErrorCode()); 943 } 944 945 const char *ParseErrorCategory::name() const noexcept { 946 return "clang-format.parse_error"; 947 } 948 949 std::string ParseErrorCategory::message(int EV) const { 950 switch (static_cast<ParseError>(EV)) { 951 case ParseError::Success: 952 return "Success"; 953 case ParseError::Error: 954 return "Invalid argument"; 955 case ParseError::Unsuitable: 956 return "Unsuitable"; 957 case ParseError::BinPackTrailingCommaConflict: 958 return "trailing comma insertion cannot be used with bin packing"; 959 case ParseError::InvalidQualifierSpecified: 960 return "Invalid qualifier specified in QualifierOrder"; 961 case ParseError::DuplicateQualifierSpecified: 962 return "Duplicate qualifier specified in QualfierOrder"; 963 case ParseError::MissingQualifierType: 964 return "Missing type in QualfierOrder"; 965 case ParseError::MissingQualifierOrder: 966 return "Missing QualfierOrder"; 967 } 968 llvm_unreachable("unexpected parse error"); 969 } 970 971 static void expandPresetsBraceWrapping(FormatStyle &Expanded) { 972 if (Expanded.BreakBeforeBraces == FormatStyle::BS_Custom) 973 return; 974 Expanded.BraceWrapping = {/*AfterCaseLabel=*/false, 975 /*AfterClass=*/false, 976 /*AfterControlStatement=*/FormatStyle::BWACS_Never, 977 /*AfterEnum=*/false, 978 /*AfterFunction=*/false, 979 /*AfterNamespace=*/false, 980 /*AfterObjCDeclaration=*/false, 981 /*AfterStruct=*/false, 982 /*AfterUnion=*/false, 983 /*AfterExternBlock=*/false, 984 /*BeforeCatch=*/false, 985 /*BeforeElse=*/false, 986 /*BeforeLambdaBody=*/false, 987 /*BeforeWhile=*/false, 988 /*IndentBraces=*/false, 989 /*SplitEmptyFunction=*/true, 990 /*SplitEmptyRecord=*/true, 991 /*SplitEmptyNamespace=*/true}; 992 switch (Expanded.BreakBeforeBraces) { 993 case FormatStyle::BS_Linux: 994 Expanded.BraceWrapping.AfterClass = true; 995 Expanded.BraceWrapping.AfterFunction = true; 996 Expanded.BraceWrapping.AfterNamespace = true; 997 break; 998 case FormatStyle::BS_Mozilla: 999 Expanded.BraceWrapping.AfterClass = true; 1000 Expanded.BraceWrapping.AfterEnum = true; 1001 Expanded.BraceWrapping.AfterFunction = true; 1002 Expanded.BraceWrapping.AfterStruct = true; 1003 Expanded.BraceWrapping.AfterUnion = true; 1004 Expanded.BraceWrapping.AfterExternBlock = true; 1005 Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; 1006 Expanded.BraceWrapping.SplitEmptyFunction = true; 1007 Expanded.BraceWrapping.SplitEmptyRecord = false; 1008 break; 1009 case FormatStyle::BS_Stroustrup: 1010 Expanded.BraceWrapping.AfterFunction = true; 1011 Expanded.BraceWrapping.BeforeCatch = true; 1012 Expanded.BraceWrapping.BeforeElse = true; 1013 break; 1014 case FormatStyle::BS_Allman: 1015 Expanded.BraceWrapping.AfterCaseLabel = true; 1016 Expanded.BraceWrapping.AfterClass = true; 1017 Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; 1018 Expanded.BraceWrapping.AfterEnum = true; 1019 Expanded.BraceWrapping.AfterFunction = true; 1020 Expanded.BraceWrapping.AfterNamespace = true; 1021 Expanded.BraceWrapping.AfterObjCDeclaration = true; 1022 Expanded.BraceWrapping.AfterStruct = true; 1023 Expanded.BraceWrapping.AfterUnion = true; 1024 Expanded.BraceWrapping.AfterExternBlock = true; 1025 Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; 1026 Expanded.BraceWrapping.BeforeCatch = true; 1027 Expanded.BraceWrapping.BeforeElse = true; 1028 Expanded.BraceWrapping.BeforeLambdaBody = true; 1029 break; 1030 case FormatStyle::BS_Whitesmiths: 1031 Expanded.BraceWrapping.AfterCaseLabel = true; 1032 Expanded.BraceWrapping.AfterClass = true; 1033 Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; 1034 Expanded.BraceWrapping.AfterEnum = true; 1035 Expanded.BraceWrapping.AfterFunction = true; 1036 Expanded.BraceWrapping.AfterNamespace = true; 1037 Expanded.BraceWrapping.AfterObjCDeclaration = true; 1038 Expanded.BraceWrapping.AfterStruct = true; 1039 Expanded.BraceWrapping.AfterExternBlock = true; 1040 Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; 1041 Expanded.BraceWrapping.BeforeCatch = true; 1042 Expanded.BraceWrapping.BeforeElse = true; 1043 Expanded.BraceWrapping.BeforeLambdaBody = true; 1044 break; 1045 case FormatStyle::BS_GNU: 1046 Expanded.BraceWrapping = { 1047 /*AfterCaseLabel=*/true, 1048 /*AfterClass=*/true, 1049 /*AfterControlStatement=*/FormatStyle::BWACS_Always, 1050 /*AfterEnum=*/true, 1051 /*AfterFunction=*/true, 1052 /*AfterNamespace=*/true, 1053 /*AfterObjCDeclaration=*/true, 1054 /*AfterStruct=*/true, 1055 /*AfterUnion=*/true, 1056 /*AfterExternBlock=*/true, 1057 /*BeforeCatch=*/true, 1058 /*BeforeElse=*/true, 1059 /*BeforeLambdaBody=*/false, 1060 /*BeforeWhile=*/true, 1061 /*IndentBraces=*/true, 1062 /*SplitEmptyFunction=*/true, 1063 /*SplitEmptyRecord=*/true, 1064 /*SplitEmptyNamespace=*/true}; 1065 Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; 1066 break; 1067 case FormatStyle::BS_WebKit: 1068 Expanded.BraceWrapping.AfterFunction = true; 1069 break; 1070 default: 1071 break; 1072 } 1073 } 1074 1075 static void expandPresetsSpaceBeforeParens(FormatStyle &Expanded) { 1076 if (Expanded.SpaceBeforeParens == FormatStyle::SBPO_Custom) 1077 return; 1078 // Reset all flags 1079 Expanded.SpaceBeforeParensOptions = {}; 1080 1081 switch (Expanded.SpaceBeforeParens) { 1082 case FormatStyle::SBPO_Never: 1083 break; 1084 case FormatStyle::SBPO_ControlStatements: 1085 Expanded.SpaceBeforeParensOptions.AfterControlStatements = true; 1086 Expanded.SpaceBeforeParensOptions.AfterForeachMacros = true; 1087 Expanded.SpaceBeforeParensOptions.AfterIfMacros = true; 1088 break; 1089 case FormatStyle::SBPO_ControlStatementsExceptControlMacros: 1090 Expanded.SpaceBeforeParensOptions.AfterControlStatements = true; 1091 break; 1092 case FormatStyle::SBPO_NonEmptyParentheses: 1093 Expanded.SpaceBeforeParensOptions.BeforeNonEmptyParentheses = true; 1094 break; 1095 case FormatStyle::SBPO_Always: 1096 break; 1097 default: 1098 break; 1099 } 1100 } 1101 1102 FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { 1103 FormatStyle LLVMStyle; 1104 LLVMStyle.InheritsParentConfig = false; 1105 LLVMStyle.Language = Language; 1106 LLVMStyle.AccessModifierOffset = -2; 1107 LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right; 1108 LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align; 1109 LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None; 1110 LLVMStyle.AlignOperands = FormatStyle::OAS_Align; 1111 LLVMStyle.AlignTrailingComments = true; 1112 LLVMStyle.AlignConsecutiveAssignments = FormatStyle::ACS_None; 1113 LLVMStyle.AlignConsecutiveBitFields = FormatStyle::ACS_None; 1114 LLVMStyle.AlignConsecutiveDeclarations = FormatStyle::ACS_None; 1115 LLVMStyle.AlignConsecutiveMacros = FormatStyle::ACS_None; 1116 LLVMStyle.AllowAllArgumentsOnNextLine = true; 1117 LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; 1118 LLVMStyle.AllowShortEnumsOnASingleLine = true; 1119 LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; 1120 LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never; 1121 LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; 1122 LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1123 LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; 1124 LLVMStyle.AllowShortLoopsOnASingleLine = false; 1125 LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; 1126 LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; 1127 LLVMStyle.AlwaysBreakBeforeMultilineStrings = false; 1128 LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine; 1129 LLVMStyle.AttributeMacros.push_back("__capability"); 1130 LLVMStyle.BinPackArguments = true; 1131 LLVMStyle.BinPackParameters = true; 1132 LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None; 1133 LLVMStyle.BreakBeforeConceptDeclarations = true; 1134 LLVMStyle.BreakBeforeTernaryOperators = true; 1135 LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach; 1136 LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false, 1137 /*AfterClass=*/false, 1138 /*AfterControlStatement=*/FormatStyle::BWACS_Never, 1139 /*AfterEnum=*/false, 1140 /*AfterFunction=*/false, 1141 /*AfterNamespace=*/false, 1142 /*AfterObjCDeclaration=*/false, 1143 /*AfterStruct=*/false, 1144 /*AfterUnion=*/false, 1145 /*AfterExternBlock=*/false, 1146 /*BeforeCatch=*/false, 1147 /*BeforeElse=*/false, 1148 /*BeforeLambdaBody=*/false, 1149 /*BeforeWhile=*/false, 1150 /*IndentBraces=*/false, 1151 /*SplitEmptyFunction=*/true, 1152 /*SplitEmptyRecord=*/true, 1153 /*SplitEmptyNamespace=*/true}; 1154 LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; 1155 LLVMStyle.BreakAfterJavaFieldAnnotations = false; 1156 LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; 1157 LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon; 1158 LLVMStyle.BreakStringLiterals = true; 1159 LLVMStyle.ColumnLimit = 80; 1160 LLVMStyle.CommentPragmas = "^ IWYU pragma:"; 1161 LLVMStyle.CompactNamespaces = false; 1162 LLVMStyle.ConstructorInitializerIndentWidth = 4; 1163 LLVMStyle.ContinuationIndentWidth = 4; 1164 LLVMStyle.Cpp11BracedListStyle = true; 1165 1166 // Off by default Qualifier ordering 1167 LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave; 1168 1169 LLVMStyle.DeriveLineEnding = true; 1170 LLVMStyle.DerivePointerAlignment = false; 1171 LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never; 1172 LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock; 1173 LLVMStyle.ExperimentalAutoDetectBinPacking = false; 1174 LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack; 1175 LLVMStyle.FixNamespaceComments = true; 1176 LLVMStyle.ForEachMacros.push_back("foreach"); 1177 LLVMStyle.ForEachMacros.push_back("Q_FOREACH"); 1178 LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH"); 1179 LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE"); 1180 LLVMStyle.IncludeStyle.IncludeCategories = { 1181 {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false}, 1182 {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false}, 1183 {".*", 1, 0, false}}; 1184 LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$"; 1185 LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve; 1186 LLVMStyle.IndentAccessModifiers = false; 1187 LLVMStyle.IndentCaseLabels = false; 1188 LLVMStyle.IndentCaseBlocks = false; 1189 LLVMStyle.IndentGotoLabels = true; 1190 LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None; 1191 LLVMStyle.IndentRequires = false; 1192 LLVMStyle.IndentWrappedFunctionNames = false; 1193 LLVMStyle.IndentWidth = 2; 1194 LLVMStyle.PPIndentWidth = -1; 1195 LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None; 1196 LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave; 1197 LLVMStyle.JavaScriptWrapImports = true; 1198 LLVMStyle.TabWidth = 8; 1199 LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature; 1200 LLVMStyle.MaxEmptyLinesToKeep = 1; 1201 LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true; 1202 LLVMStyle.NamespaceIndentation = FormatStyle::NI_None; 1203 LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto; 1204 LLVMStyle.ObjCBlockIndentWidth = 2; 1205 LLVMStyle.ObjCBreakBeforeNestedBlockParam = true; 1206 LLVMStyle.ObjCSpaceAfterProperty = false; 1207 LLVMStyle.ObjCSpaceBeforeProtocolList = true; 1208 LLVMStyle.PointerAlignment = FormatStyle::PAS_Right; 1209 LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer; 1210 LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave; 1211 LLVMStyle.ShortNamespaceLines = 1; 1212 LLVMStyle.SpacesBeforeTrailingComments = 1; 1213 LLVMStyle.Standard = FormatStyle::LS_Latest; 1214 LLVMStyle.UseCRLF = false; 1215 LLVMStyle.UseTab = FormatStyle::UT_Never; 1216 LLVMStyle.ReflowComments = true; 1217 LLVMStyle.SpacesInParentheses = false; 1218 LLVMStyle.SpacesInSquareBrackets = false; 1219 LLVMStyle.SpaceInEmptyBlock = false; 1220 LLVMStyle.SpaceInEmptyParentheses = false; 1221 LLVMStyle.SpacesInContainerLiterals = true; 1222 LLVMStyle.SpacesInCStyleCastParentheses = false; 1223 LLVMStyle.SpacesInLineCommentPrefix = {/*Minimum=*/1, /*Maximum=*/-1u}; 1224 LLVMStyle.SpaceAfterCStyleCast = false; 1225 LLVMStyle.SpaceAfterLogicalNot = false; 1226 LLVMStyle.SpaceAfterTemplateKeyword = true; 1227 LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default; 1228 LLVMStyle.SpaceBeforeCaseColon = false; 1229 LLVMStyle.SpaceBeforeCtorInitializerColon = true; 1230 LLVMStyle.SpaceBeforeInheritanceColon = true; 1231 LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements; 1232 LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true; 1233 LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true; 1234 LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true; 1235 LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true; 1236 LLVMStyle.SpaceBeforeAssignmentOperators = true; 1237 LLVMStyle.SpaceBeforeCpp11BracedList = false; 1238 LLVMStyle.SpaceBeforeSquareBrackets = false; 1239 LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both; 1240 LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never; 1241 LLVMStyle.SpacesInConditionalStatement = false; 1242 1243 LLVMStyle.PenaltyBreakAssignment = prec::Assignment; 1244 LLVMStyle.PenaltyBreakComment = 300; 1245 LLVMStyle.PenaltyBreakFirstLessLess = 120; 1246 LLVMStyle.PenaltyBreakString = 1000; 1247 LLVMStyle.PenaltyExcessCharacter = 1000000; 1248 LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60; 1249 LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19; 1250 LLVMStyle.PenaltyBreakOpenParenthesis = 0; 1251 LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational; 1252 LLVMStyle.PenaltyIndentedWhitespace = 0; 1253 1254 LLVMStyle.DisableFormat = false; 1255 LLVMStyle.SortIncludes = FormatStyle::SI_CaseSensitive; 1256 LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before; 1257 LLVMStyle.SortUsingDeclarations = true; 1258 LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT"); 1259 LLVMStyle.StatementMacros.push_back("Q_UNUSED"); 1260 LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION"); 1261 LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE"); 1262 LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE"); 1263 LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE"); 1264 LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME"); 1265 LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME"); 1266 1267 // Defaults that differ when not C++. 1268 if (Language == FormatStyle::LK_TableGen) { 1269 LLVMStyle.SpacesInContainerLiterals = false; 1270 } 1271 if (LLVMStyle.isJson()) { 1272 LLVMStyle.ColumnLimit = 0; 1273 } 1274 1275 return LLVMStyle; 1276 } 1277 1278 FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { 1279 if (Language == FormatStyle::LK_TextProto) { 1280 FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto); 1281 GoogleStyle.Language = FormatStyle::LK_TextProto; 1282 1283 return GoogleStyle; 1284 } 1285 1286 FormatStyle GoogleStyle = getLLVMStyle(Language); 1287 1288 GoogleStyle.AccessModifierOffset = -1; 1289 GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left; 1290 GoogleStyle.AllowShortIfStatementsOnASingleLine = 1291 FormatStyle::SIS_WithoutElse; 1292 GoogleStyle.AllowShortLoopsOnASingleLine = true; 1293 GoogleStyle.AlwaysBreakBeforeMultilineStrings = true; 1294 GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; 1295 GoogleStyle.DerivePointerAlignment = true; 1296 GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false}, 1297 {"^<.*\\.h>", 1, 0, false}, 1298 {"^<.*", 2, 0, false}, 1299 {".*", 3, 0, false}}; 1300 GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$"; 1301 GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 1302 GoogleStyle.IndentCaseLabels = true; 1303 GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false; 1304 GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never; 1305 GoogleStyle.ObjCSpaceAfterProperty = false; 1306 GoogleStyle.ObjCSpaceBeforeProtocolList = true; 1307 GoogleStyle.PackConstructorInitializers = FormatStyle::PCIS_NextLine; 1308 GoogleStyle.PointerAlignment = FormatStyle::PAS_Left; 1309 GoogleStyle.RawStringFormats = { 1310 { 1311 FormatStyle::LK_Cpp, 1312 /*Delimiters=*/ 1313 { 1314 "cc", 1315 "CC", 1316 "cpp", 1317 "Cpp", 1318 "CPP", 1319 "c++", 1320 "C++", 1321 }, 1322 /*EnclosingFunctionNames=*/ 1323 {}, 1324 /*CanonicalDelimiter=*/"", 1325 /*BasedOnStyle=*/"google", 1326 }, 1327 { 1328 FormatStyle::LK_TextProto, 1329 /*Delimiters=*/ 1330 { 1331 "pb", 1332 "PB", 1333 "proto", 1334 "PROTO", 1335 }, 1336 /*EnclosingFunctionNames=*/ 1337 { 1338 "EqualsProto", 1339 "EquivToProto", 1340 "PARSE_PARTIAL_TEXT_PROTO", 1341 "PARSE_TEST_PROTO", 1342 "PARSE_TEXT_PROTO", 1343 "ParseTextOrDie", 1344 "ParseTextProtoOrDie", 1345 "ParseTestProto", 1346 "ParsePartialTestProto", 1347 }, 1348 /*CanonicalDelimiter=*/"pb", 1349 /*BasedOnStyle=*/"google", 1350 }, 1351 }; 1352 GoogleStyle.SpacesBeforeTrailingComments = 2; 1353 GoogleStyle.Standard = FormatStyle::LS_Auto; 1354 1355 GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200; 1356 GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1; 1357 1358 if (Language == FormatStyle::LK_Java) { 1359 GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; 1360 GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign; 1361 GoogleStyle.AlignTrailingComments = false; 1362 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 1363 GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1364 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 1365 GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; 1366 GoogleStyle.ColumnLimit = 100; 1367 GoogleStyle.SpaceAfterCStyleCast = true; 1368 GoogleStyle.SpacesBeforeTrailingComments = 1; 1369 } else if (Language == FormatStyle::LK_JavaScript) { 1370 GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; 1371 GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign; 1372 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 1373 // TODO: still under discussion whether to switch to SLS_All. 1374 GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty; 1375 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 1376 GoogleStyle.BreakBeforeTernaryOperators = false; 1377 // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is 1378 // commonly followed by overlong URLs. 1379 GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)"; 1380 // TODO: enable once decided, in particular re disabling bin packing. 1381 // https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma 1382 // GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped; 1383 GoogleStyle.MaxEmptyLinesToKeep = 3; 1384 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All; 1385 GoogleStyle.SpacesInContainerLiterals = false; 1386 GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single; 1387 GoogleStyle.JavaScriptWrapImports = false; 1388 } else if (Language == FormatStyle::LK_Proto) { 1389 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 1390 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 1391 GoogleStyle.SpacesInContainerLiterals = false; 1392 GoogleStyle.Cpp11BracedListStyle = false; 1393 // This affects protocol buffer options specifications and text protos. 1394 // Text protos are currently mostly formatted inside C++ raw string literals 1395 // and often the current breaking behavior of string literals is not 1396 // beneficial there. Investigate turning this on once proper string reflow 1397 // has been implemented. 1398 GoogleStyle.BreakStringLiterals = false; 1399 } else if (Language == FormatStyle::LK_ObjC) { 1400 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 1401 GoogleStyle.ColumnLimit = 100; 1402 // "Regroup" doesn't work well for ObjC yet (main header heuristic, 1403 // relationship between ObjC standard library headers and other heades, 1404 // #imports, etc.) 1405 GoogleStyle.IncludeStyle.IncludeBlocks = 1406 tooling::IncludeStyle::IBS_Preserve; 1407 } else if (Language == FormatStyle::LK_CSharp) { 1408 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 1409 GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1410 GoogleStyle.BreakStringLiterals = false; 1411 GoogleStyle.ColumnLimit = 100; 1412 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All; 1413 } 1414 1415 return GoogleStyle; 1416 } 1417 1418 FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) { 1419 FormatStyle ChromiumStyle = getGoogleStyle(Language); 1420 1421 // Disable include reordering across blocks in Chromium code. 1422 // - clang-format tries to detect that foo.h is the "main" header for 1423 // foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium 1424 // uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc, 1425 // _private.cc, _impl.cc etc) in different permutations 1426 // (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a 1427 // better default for Chromium code. 1428 // - The default for .cc and .mm files is different (r357695) for Google style 1429 // for the same reason. The plan is to unify this again once the main 1430 // header detection works for Google's ObjC code, but this hasn't happened 1431 // yet. Since Chromium has some ObjC code, switching Chromium is blocked 1432 // on that. 1433 // - Finally, "If include reordering is harmful, put things in different 1434 // blocks to prevent it" has been a recommendation for a long time that 1435 // people are used to. We'll need a dev education push to change this to 1436 // "If include reordering is harmful, put things in a different block and 1437 // _prepend that with a comment_ to prevent it" before changing behavior. 1438 ChromiumStyle.IncludeStyle.IncludeBlocks = 1439 tooling::IncludeStyle::IBS_Preserve; 1440 1441 if (Language == FormatStyle::LK_Java) { 1442 ChromiumStyle.AllowShortIfStatementsOnASingleLine = 1443 FormatStyle::SIS_WithoutElse; 1444 ChromiumStyle.BreakAfterJavaFieldAnnotations = true; 1445 ChromiumStyle.ContinuationIndentWidth = 8; 1446 ChromiumStyle.IndentWidth = 4; 1447 // See styleguide for import groups: 1448 // https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/java/java.md#Import-Order 1449 ChromiumStyle.JavaImportGroups = { 1450 "android", 1451 "androidx", 1452 "com", 1453 "dalvik", 1454 "junit", 1455 "org", 1456 "com.google.android.apps.chrome", 1457 "org.chromium", 1458 "java", 1459 "javax", 1460 }; 1461 ChromiumStyle.SortIncludes = FormatStyle::SI_CaseSensitive; 1462 } else if (Language == FormatStyle::LK_JavaScript) { 1463 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1464 ChromiumStyle.AllowShortLoopsOnASingleLine = false; 1465 } else { 1466 ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false; 1467 ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 1468 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1469 ChromiumStyle.AllowShortLoopsOnASingleLine = false; 1470 ChromiumStyle.BinPackParameters = false; 1471 ChromiumStyle.DerivePointerAlignment = false; 1472 if (Language == FormatStyle::LK_ObjC) 1473 ChromiumStyle.ColumnLimit = 80; 1474 } 1475 return ChromiumStyle; 1476 } 1477 1478 FormatStyle getMozillaStyle() { 1479 FormatStyle MozillaStyle = getLLVMStyle(); 1480 MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false; 1481 MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 1482 MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel; 1483 MozillaStyle.AlwaysBreakAfterDefinitionReturnType = 1484 FormatStyle::DRTBS_TopLevel; 1485 MozillaStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; 1486 MozillaStyle.BinPackParameters = false; 1487 MozillaStyle.BinPackArguments = false; 1488 MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla; 1489 MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 1490 MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma; 1491 MozillaStyle.ConstructorInitializerIndentWidth = 2; 1492 MozillaStyle.ContinuationIndentWidth = 2; 1493 MozillaStyle.Cpp11BracedListStyle = false; 1494 MozillaStyle.FixNamespaceComments = false; 1495 MozillaStyle.IndentCaseLabels = true; 1496 MozillaStyle.ObjCSpaceAfterProperty = true; 1497 MozillaStyle.ObjCSpaceBeforeProtocolList = false; 1498 MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200; 1499 MozillaStyle.PointerAlignment = FormatStyle::PAS_Left; 1500 MozillaStyle.SpaceAfterTemplateKeyword = false; 1501 return MozillaStyle; 1502 } 1503 1504 FormatStyle getWebKitStyle() { 1505 FormatStyle Style = getLLVMStyle(); 1506 Style.AccessModifierOffset = -4; 1507 Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; 1508 Style.AlignOperands = FormatStyle::OAS_DontAlign; 1509 Style.AlignTrailingComments = false; 1510 Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty; 1511 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 1512 Style.BreakBeforeBraces = FormatStyle::BS_WebKit; 1513 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 1514 Style.Cpp11BracedListStyle = false; 1515 Style.ColumnLimit = 0; 1516 Style.FixNamespaceComments = false; 1517 Style.IndentWidth = 4; 1518 Style.NamespaceIndentation = FormatStyle::NI_Inner; 1519 Style.ObjCBlockIndentWidth = 4; 1520 Style.ObjCSpaceAfterProperty = true; 1521 Style.PointerAlignment = FormatStyle::PAS_Left; 1522 Style.SpaceBeforeCpp11BracedList = true; 1523 Style.SpaceInEmptyBlock = true; 1524 return Style; 1525 } 1526 1527 FormatStyle getGNUStyle() { 1528 FormatStyle Style = getLLVMStyle(); 1529 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; 1530 Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; 1531 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 1532 Style.BreakBeforeBraces = FormatStyle::BS_GNU; 1533 Style.BreakBeforeTernaryOperators = true; 1534 Style.Cpp11BracedListStyle = false; 1535 Style.ColumnLimit = 79; 1536 Style.FixNamespaceComments = false; 1537 Style.SpaceBeforeParens = FormatStyle::SBPO_Always; 1538 Style.Standard = FormatStyle::LS_Cpp03; 1539 return Style; 1540 } 1541 1542 FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) { 1543 FormatStyle Style = getLLVMStyle(Language); 1544 Style.ColumnLimit = 120; 1545 Style.TabWidth = 4; 1546 Style.IndentWidth = 4; 1547 Style.UseTab = FormatStyle::UT_Never; 1548 Style.BreakBeforeBraces = FormatStyle::BS_Custom; 1549 Style.BraceWrapping.AfterClass = true; 1550 Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; 1551 Style.BraceWrapping.AfterEnum = true; 1552 Style.BraceWrapping.AfterFunction = true; 1553 Style.BraceWrapping.AfterNamespace = true; 1554 Style.BraceWrapping.AfterObjCDeclaration = true; 1555 Style.BraceWrapping.AfterStruct = true; 1556 Style.BraceWrapping.AfterExternBlock = true; 1557 Style.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; 1558 Style.BraceWrapping.BeforeCatch = true; 1559 Style.BraceWrapping.BeforeElse = true; 1560 Style.BraceWrapping.BeforeWhile = false; 1561 Style.PenaltyReturnTypeOnItsOwnLine = 1000; 1562 Style.AllowShortEnumsOnASingleLine = false; 1563 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; 1564 Style.AllowShortCaseLabelsOnASingleLine = false; 1565 Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1566 Style.AllowShortLoopsOnASingleLine = false; 1567 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; 1568 Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; 1569 return Style; 1570 } 1571 1572 FormatStyle getNoStyle() { 1573 FormatStyle NoStyle = getLLVMStyle(); 1574 NoStyle.DisableFormat = true; 1575 NoStyle.SortIncludes = FormatStyle::SI_Never; 1576 NoStyle.SortUsingDeclarations = false; 1577 return NoStyle; 1578 } 1579 1580 bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language, 1581 FormatStyle *Style) { 1582 if (Name.equals_insensitive("llvm")) { 1583 *Style = getLLVMStyle(Language); 1584 } else if (Name.equals_insensitive("chromium")) { 1585 *Style = getChromiumStyle(Language); 1586 } else if (Name.equals_insensitive("mozilla")) { 1587 *Style = getMozillaStyle(); 1588 } else if (Name.equals_insensitive("google")) { 1589 *Style = getGoogleStyle(Language); 1590 } else if (Name.equals_insensitive("webkit")) { 1591 *Style = getWebKitStyle(); 1592 } else if (Name.equals_insensitive("gnu")) { 1593 *Style = getGNUStyle(); 1594 } else if (Name.equals_insensitive("microsoft")) { 1595 *Style = getMicrosoftStyle(Language); 1596 } else if (Name.equals_insensitive("none")) { 1597 *Style = getNoStyle(); 1598 } else if (Name.equals_insensitive("inheritparentconfig")) { 1599 Style->InheritsParentConfig = true; 1600 } else { 1601 return false; 1602 } 1603 1604 Style->Language = Language; 1605 return true; 1606 } 1607 1608 ParseError validateQualifierOrder(FormatStyle *Style) { 1609 // If its empty then it means don't do anything. 1610 if (Style->QualifierOrder.empty()) 1611 return ParseError::MissingQualifierOrder; 1612 1613 // Ensure the list contains only currently valid qualifiers. 1614 for (const auto &Qualifier : Style->QualifierOrder) { 1615 if (Qualifier == "type") 1616 continue; 1617 auto token = 1618 LeftRightQualifierAlignmentFixer::getTokenFromQualifier(Qualifier); 1619 if (token == tok::identifier) 1620 return ParseError::InvalidQualifierSpecified; 1621 } 1622 // Ensure the list is unqiue (no duplicates). 1623 std::set<std::string> UniqueQualifiers(Style->QualifierOrder.begin(), 1624 Style->QualifierOrder.end()); 1625 if (Style->QualifierOrder.size() != UniqueQualifiers.size()) { 1626 LLVM_DEBUG(llvm::dbgs() 1627 << "Duplicate Qualifiers " << Style->QualifierOrder.size() 1628 << " vs " << UniqueQualifiers.size() << "\n"); 1629 return ParseError::DuplicateQualifierSpecified; 1630 } 1631 1632 auto type = std::find(Style->QualifierOrder.begin(), 1633 Style->QualifierOrder.end(), "type"); 1634 if (type == Style->QualifierOrder.end()) 1635 return ParseError::MissingQualifierType; 1636 return ParseError::Success; 1637 } 1638 1639 std::error_code parseConfiguration(llvm::MemoryBufferRef Config, 1640 FormatStyle *Style, bool AllowUnknownOptions, 1641 llvm::SourceMgr::DiagHandlerTy DiagHandler, 1642 void *DiagHandlerCtxt) { 1643 assert(Style); 1644 FormatStyle::LanguageKind Language = Style->Language; 1645 assert(Language != FormatStyle::LK_None); 1646 if (Config.getBuffer().trim().empty()) 1647 return make_error_code(ParseError::Error); 1648 Style->StyleSet.Clear(); 1649 std::vector<FormatStyle> Styles; 1650 llvm::yaml::Input Input(Config, /*Ctxt=*/nullptr, DiagHandler, 1651 DiagHandlerCtxt); 1652 // DocumentListTraits<vector<FormatStyle>> uses the context to get default 1653 // values for the fields, keys for which are missing from the configuration. 1654 // Mapping also uses the context to get the language to find the correct 1655 // base style. 1656 Input.setContext(Style); 1657 Input.setAllowUnknownKeys(AllowUnknownOptions); 1658 Input >> Styles; 1659 if (Input.error()) 1660 return Input.error(); 1661 1662 for (unsigned i = 0; i < Styles.size(); ++i) { 1663 // Ensures that only the first configuration can skip the Language option. 1664 if (Styles[i].Language == FormatStyle::LK_None && i != 0) 1665 return make_error_code(ParseError::Error); 1666 // Ensure that each language is configured at most once. 1667 for (unsigned j = 0; j < i; ++j) { 1668 if (Styles[i].Language == Styles[j].Language) { 1669 LLVM_DEBUG(llvm::dbgs() 1670 << "Duplicate languages in the config file on positions " 1671 << j << " and " << i << "\n"); 1672 return make_error_code(ParseError::Error); 1673 } 1674 } 1675 } 1676 // Look for a suitable configuration starting from the end, so we can 1677 // find the configuration for the specific language first, and the default 1678 // configuration (which can only be at slot 0) after it. 1679 FormatStyle::FormatStyleSet StyleSet; 1680 bool LanguageFound = false; 1681 for (int i = Styles.size() - 1; i >= 0; --i) { 1682 if (Styles[i].Language != FormatStyle::LK_None) 1683 StyleSet.Add(Styles[i]); 1684 if (Styles[i].Language == Language) 1685 LanguageFound = true; 1686 } 1687 if (!LanguageFound) { 1688 if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None) 1689 return make_error_code(ParseError::Unsuitable); 1690 FormatStyle DefaultStyle = Styles[0]; 1691 DefaultStyle.Language = Language; 1692 StyleSet.Add(std::move(DefaultStyle)); 1693 } 1694 *Style = *StyleSet.Get(Language); 1695 if (Style->InsertTrailingCommas != FormatStyle::TCS_None && 1696 Style->BinPackArguments) { 1697 // See comment on FormatStyle::TSC_Wrapped. 1698 return make_error_code(ParseError::BinPackTrailingCommaConflict); 1699 } 1700 if (Style->QualifierAlignment != FormatStyle::QAS_Leave) 1701 return make_error_code(validateQualifierOrder(Style)); 1702 return make_error_code(ParseError::Success); 1703 } 1704 1705 std::string configurationAsText(const FormatStyle &Style) { 1706 std::string Text; 1707 llvm::raw_string_ostream Stream(Text); 1708 llvm::yaml::Output Output(Stream); 1709 // We use the same mapping method for input and output, so we need a non-const 1710 // reference here. 1711 FormatStyle NonConstStyle = Style; 1712 expandPresetsBraceWrapping(NonConstStyle); 1713 expandPresetsSpaceBeforeParens(NonConstStyle); 1714 Output << NonConstStyle; 1715 1716 return Stream.str(); 1717 } 1718 1719 llvm::Optional<FormatStyle> 1720 FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const { 1721 if (!Styles) 1722 return None; 1723 auto It = Styles->find(Language); 1724 if (It == Styles->end()) 1725 return None; 1726 FormatStyle Style = It->second; 1727 Style.StyleSet = *this; 1728 return Style; 1729 } 1730 1731 void FormatStyle::FormatStyleSet::Add(FormatStyle Style) { 1732 assert(Style.Language != LK_None && 1733 "Cannot add a style for LK_None to a StyleSet"); 1734 assert( 1735 !Style.StyleSet.Styles && 1736 "Cannot add a style associated with an existing StyleSet to a StyleSet"); 1737 if (!Styles) 1738 Styles = std::make_shared<MapType>(); 1739 (*Styles)[Style.Language] = std::move(Style); 1740 } 1741 1742 void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); } 1743 1744 llvm::Optional<FormatStyle> 1745 FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const { 1746 return StyleSet.Get(Language); 1747 } 1748 1749 namespace { 1750 1751 class JavaScriptRequoter : public TokenAnalyzer { 1752 public: 1753 JavaScriptRequoter(const Environment &Env, const FormatStyle &Style) 1754 : TokenAnalyzer(Env, Style) {} 1755 1756 std::pair<tooling::Replacements, unsigned> 1757 analyze(TokenAnnotator &Annotator, 1758 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1759 FormatTokenLexer &Tokens) override { 1760 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 1761 tooling::Replacements Result; 1762 requoteJSStringLiteral(AnnotatedLines, Result); 1763 return {Result, 0}; 1764 } 1765 1766 private: 1767 // Replaces double/single-quoted string literal as appropriate, re-escaping 1768 // the contents in the process. 1769 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines, 1770 tooling::Replacements &Result) { 1771 for (AnnotatedLine *Line : Lines) { 1772 requoteJSStringLiteral(Line->Children, Result); 1773 if (!Line->Affected) 1774 continue; 1775 for (FormatToken *FormatTok = Line->First; FormatTok; 1776 FormatTok = FormatTok->Next) { 1777 StringRef Input = FormatTok->TokenText; 1778 if (FormatTok->Finalized || !FormatTok->isStringLiteral() || 1779 // NB: testing for not starting with a double quote to avoid 1780 // breaking `template strings`. 1781 (Style.JavaScriptQuotes == FormatStyle::JSQS_Single && 1782 !Input.startswith("\"")) || 1783 (Style.JavaScriptQuotes == FormatStyle::JSQS_Double && 1784 !Input.startswith("\'"))) 1785 continue; 1786 1787 // Change start and end quote. 1788 bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single; 1789 SourceLocation Start = FormatTok->Tok.getLocation(); 1790 auto Replace = [&](SourceLocation Start, unsigned Length, 1791 StringRef ReplacementText) { 1792 auto Err = Result.add(tooling::Replacement( 1793 Env.getSourceManager(), Start, Length, ReplacementText)); 1794 // FIXME: handle error. For now, print error message and skip the 1795 // replacement for release version. 1796 if (Err) { 1797 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 1798 assert(false); 1799 } 1800 }; 1801 Replace(Start, 1, IsSingle ? "'" : "\""); 1802 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1, 1803 IsSingle ? "'" : "\""); 1804 1805 // Escape internal quotes. 1806 bool Escaped = false; 1807 for (size_t i = 1; i < Input.size() - 1; i++) { 1808 switch (Input[i]) { 1809 case '\\': 1810 if (!Escaped && i + 1 < Input.size() && 1811 ((IsSingle && Input[i + 1] == '"') || 1812 (!IsSingle && Input[i + 1] == '\''))) { 1813 // Remove this \, it's escaping a " or ' that no longer needs 1814 // escaping 1815 Replace(Start.getLocWithOffset(i), 1, ""); 1816 continue; 1817 } 1818 Escaped = !Escaped; 1819 break; 1820 case '\"': 1821 case '\'': 1822 if (!Escaped && IsSingle == (Input[i] == '\'')) { 1823 // Escape the quote. 1824 Replace(Start.getLocWithOffset(i), 0, "\\"); 1825 } 1826 Escaped = false; 1827 break; 1828 default: 1829 Escaped = false; 1830 break; 1831 } 1832 } 1833 } 1834 } 1835 } 1836 }; 1837 1838 class Formatter : public TokenAnalyzer { 1839 public: 1840 Formatter(const Environment &Env, const FormatStyle &Style, 1841 FormattingAttemptStatus *Status) 1842 : TokenAnalyzer(Env, Style), Status(Status) {} 1843 1844 std::pair<tooling::Replacements, unsigned> 1845 analyze(TokenAnnotator &Annotator, 1846 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1847 FormatTokenLexer &Tokens) override { 1848 tooling::Replacements Result; 1849 deriveLocalStyle(AnnotatedLines); 1850 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 1851 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1852 Annotator.calculateFormattingInformation(*AnnotatedLines[i]); 1853 } 1854 Annotator.setCommentLineLevels(AnnotatedLines); 1855 1856 WhitespaceManager Whitespaces( 1857 Env.getSourceManager(), Style, 1858 Style.DeriveLineEnding 1859 ? WhitespaceManager::inputUsesCRLF( 1860 Env.getSourceManager().getBufferData(Env.getFileID()), 1861 Style.UseCRLF) 1862 : Style.UseCRLF); 1863 ContinuationIndenter Indenter(Style, Tokens.getKeywords(), 1864 Env.getSourceManager(), Whitespaces, Encoding, 1865 BinPackInconclusiveFunctions); 1866 unsigned Penalty = 1867 UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, 1868 Tokens.getKeywords(), Env.getSourceManager(), 1869 Status) 1870 .format(AnnotatedLines, /*DryRun=*/false, 1871 /*AdditionalIndent=*/0, 1872 /*FixBadIndentation=*/false, 1873 /*FirstStartColumn=*/Env.getFirstStartColumn(), 1874 /*NextStartColumn=*/Env.getNextStartColumn(), 1875 /*LastStartColumn=*/Env.getLastStartColumn()); 1876 for (const auto &R : Whitespaces.generateReplacements()) 1877 if (Result.add(R)) 1878 return std::make_pair(Result, 0); 1879 return std::make_pair(Result, Penalty); 1880 } 1881 1882 private: 1883 bool 1884 hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) { 1885 for (const AnnotatedLine *Line : Lines) { 1886 if (hasCpp03IncompatibleFormat(Line->Children)) 1887 return true; 1888 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) { 1889 if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) { 1890 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener)) 1891 return true; 1892 if (Tok->is(TT_TemplateCloser) && 1893 Tok->Previous->is(TT_TemplateCloser)) 1894 return true; 1895 } 1896 } 1897 } 1898 return false; 1899 } 1900 1901 int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) { 1902 int AlignmentDiff = 0; 1903 for (const AnnotatedLine *Line : Lines) { 1904 AlignmentDiff += countVariableAlignments(Line->Children); 1905 for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) { 1906 if (!Tok->is(TT_PointerOrReference)) 1907 continue; 1908 bool SpaceBefore = 1909 Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd(); 1910 bool SpaceAfter = Tok->Next->WhitespaceRange.getBegin() != 1911 Tok->Next->WhitespaceRange.getEnd(); 1912 if (SpaceBefore && !SpaceAfter) 1913 ++AlignmentDiff; 1914 if (!SpaceBefore && SpaceAfter) 1915 --AlignmentDiff; 1916 } 1917 } 1918 return AlignmentDiff; 1919 } 1920 1921 void 1922 deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 1923 bool HasBinPackedFunction = false; 1924 bool HasOnePerLineFunction = false; 1925 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1926 if (!AnnotatedLines[i]->First->Next) 1927 continue; 1928 FormatToken *Tok = AnnotatedLines[i]->First->Next; 1929 while (Tok->Next) { 1930 if (Tok->is(PPK_BinPacked)) 1931 HasBinPackedFunction = true; 1932 if (Tok->is(PPK_OnePerLine)) 1933 HasOnePerLineFunction = true; 1934 1935 Tok = Tok->Next; 1936 } 1937 } 1938 if (Style.DerivePointerAlignment) { 1939 Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0 1940 ? FormatStyle::PAS_Left 1941 : FormatStyle::PAS_Right; 1942 Style.ReferenceAlignment = FormatStyle::RAS_Pointer; 1943 } 1944 if (Style.Standard == FormatStyle::LS_Auto) 1945 Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines) 1946 ? FormatStyle::LS_Latest 1947 : FormatStyle::LS_Cpp03; 1948 BinPackInconclusiveFunctions = 1949 HasBinPackedFunction || !HasOnePerLineFunction; 1950 } 1951 1952 bool BinPackInconclusiveFunctions; 1953 FormattingAttemptStatus *Status; 1954 }; 1955 1956 /// TrailingCommaInserter inserts trailing commas into container literals. 1957 /// E.g.: 1958 /// const x = [ 1959 /// 1, 1960 /// ]; 1961 /// TrailingCommaInserter runs after formatting. To avoid causing a required 1962 /// reformatting (and thus reflow), it never inserts a comma that'd exceed the 1963 /// ColumnLimit. 1964 /// 1965 /// Because trailing commas disable binpacking of arrays, TrailingCommaInserter 1966 /// is conceptually incompatible with bin packing. 1967 class TrailingCommaInserter : public TokenAnalyzer { 1968 public: 1969 TrailingCommaInserter(const Environment &Env, const FormatStyle &Style) 1970 : TokenAnalyzer(Env, Style) {} 1971 1972 std::pair<tooling::Replacements, unsigned> 1973 analyze(TokenAnnotator &Annotator, 1974 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1975 FormatTokenLexer &Tokens) override { 1976 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 1977 tooling::Replacements Result; 1978 insertTrailingCommas(AnnotatedLines, Result); 1979 return {Result, 0}; 1980 } 1981 1982 private: 1983 /// Inserts trailing commas in [] and {} initializers if they wrap over 1984 /// multiple lines. 1985 void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines, 1986 tooling::Replacements &Result) { 1987 for (AnnotatedLine *Line : Lines) { 1988 insertTrailingCommas(Line->Children, Result); 1989 if (!Line->Affected) 1990 continue; 1991 for (FormatToken *FormatTok = Line->First; FormatTok; 1992 FormatTok = FormatTok->Next) { 1993 if (FormatTok->NewlinesBefore == 0) 1994 continue; 1995 FormatToken *Matching = FormatTok->MatchingParen; 1996 if (!Matching || !FormatTok->getPreviousNonComment()) 1997 continue; 1998 if (!(FormatTok->is(tok::r_square) && 1999 Matching->is(TT_ArrayInitializerLSquare)) && 2000 !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) 2001 continue; 2002 FormatToken *Prev = FormatTok->getPreviousNonComment(); 2003 if (Prev->is(tok::comma) || Prev->is(tok::semi)) 2004 continue; 2005 // getEndLoc is not reliably set during re-lexing, use text length 2006 // instead. 2007 SourceLocation Start = 2008 Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size()); 2009 // If inserting a comma would push the code over the column limit, skip 2010 // this location - it'd introduce an unstable formatting due to the 2011 // required reflow. 2012 unsigned ColumnNumber = 2013 Env.getSourceManager().getSpellingColumnNumber(Start); 2014 if (ColumnNumber > Style.ColumnLimit) 2015 continue; 2016 // Comma insertions cannot conflict with each other, and this pass has a 2017 // clean set of Replacements, so the operation below cannot fail. 2018 cantFail(Result.add( 2019 tooling::Replacement(Env.getSourceManager(), Start, 0, ","))); 2020 } 2021 } 2022 } 2023 }; 2024 2025 // This class clean up the erroneous/redundant code around the given ranges in 2026 // file. 2027 class Cleaner : public TokenAnalyzer { 2028 public: 2029 Cleaner(const Environment &Env, const FormatStyle &Style) 2030 : TokenAnalyzer(Env, Style), 2031 DeletedTokens(FormatTokenLess(Env.getSourceManager())) {} 2032 2033 // FIXME: eliminate unused parameters. 2034 std::pair<tooling::Replacements, unsigned> 2035 analyze(TokenAnnotator &Annotator, 2036 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2037 FormatTokenLexer &Tokens) override { 2038 // FIXME: in the current implementation the granularity of affected range 2039 // is an annotated line. However, this is not sufficient. Furthermore, 2040 // redundant code introduced by replacements does not necessarily 2041 // intercept with ranges of replacements that result in the redundancy. 2042 // To determine if some redundant code is actually introduced by 2043 // replacements(e.g. deletions), we need to come up with a more 2044 // sophisticated way of computing affected ranges. 2045 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2046 2047 checkEmptyNamespace(AnnotatedLines); 2048 2049 for (auto *Line : AnnotatedLines) 2050 cleanupLine(Line); 2051 2052 return {generateFixes(), 0}; 2053 } 2054 2055 private: 2056 void cleanupLine(AnnotatedLine *Line) { 2057 for (auto *Child : Line->Children) { 2058 cleanupLine(Child); 2059 } 2060 2061 if (Line->Affected) { 2062 cleanupRight(Line->First, tok::comma, tok::comma); 2063 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma); 2064 cleanupRight(Line->First, tok::l_paren, tok::comma); 2065 cleanupLeft(Line->First, tok::comma, tok::r_paren); 2066 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace); 2067 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace); 2068 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal); 2069 } 2070 } 2071 2072 bool containsOnlyComments(const AnnotatedLine &Line) { 2073 for (FormatToken *Tok = Line.First; Tok != nullptr; Tok = Tok->Next) { 2074 if (Tok->isNot(tok::comment)) 2075 return false; 2076 } 2077 return true; 2078 } 2079 2080 // Iterate through all lines and remove any empty (nested) namespaces. 2081 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 2082 std::set<unsigned> DeletedLines; 2083 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 2084 auto &Line = *AnnotatedLines[i]; 2085 if (Line.startsWithNamespace()) { 2086 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines); 2087 } 2088 } 2089 2090 for (auto Line : DeletedLines) { 2091 FormatToken *Tok = AnnotatedLines[Line]->First; 2092 while (Tok) { 2093 deleteToken(Tok); 2094 Tok = Tok->Next; 2095 } 2096 } 2097 } 2098 2099 // The function checks if the namespace, which starts from \p CurrentLine, and 2100 // its nested namespaces are empty and delete them if they are empty. It also 2101 // sets \p NewLine to the last line checked. 2102 // Returns true if the current namespace is empty. 2103 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2104 unsigned CurrentLine, unsigned &NewLine, 2105 std::set<unsigned> &DeletedLines) { 2106 unsigned InitLine = CurrentLine, End = AnnotatedLines.size(); 2107 if (Style.BraceWrapping.AfterNamespace) { 2108 // If the left brace is in a new line, we should consume it first so that 2109 // it does not make the namespace non-empty. 2110 // FIXME: error handling if there is no left brace. 2111 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) { 2112 NewLine = CurrentLine; 2113 return false; 2114 } 2115 } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) { 2116 return false; 2117 } 2118 while (++CurrentLine < End) { 2119 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace)) 2120 break; 2121 2122 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) { 2123 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine, 2124 DeletedLines)) 2125 return false; 2126 CurrentLine = NewLine; 2127 continue; 2128 } 2129 2130 if (containsOnlyComments(*AnnotatedLines[CurrentLine])) 2131 continue; 2132 2133 // If there is anything other than comments or nested namespaces in the 2134 // current namespace, the namespace cannot be empty. 2135 NewLine = CurrentLine; 2136 return false; 2137 } 2138 2139 NewLine = CurrentLine; 2140 if (CurrentLine >= End) 2141 return false; 2142 2143 // Check if the empty namespace is actually affected by changed ranges. 2144 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange( 2145 AnnotatedLines[InitLine]->First->Tok.getLocation(), 2146 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) 2147 return false; 2148 2149 for (unsigned i = InitLine; i <= CurrentLine; ++i) { 2150 DeletedLines.insert(i); 2151 } 2152 2153 return true; 2154 } 2155 2156 // Checks pairs {start, start->next},..., {end->previous, end} and deletes one 2157 // of the token in the pair if the left token has \p LK token kind and the 2158 // right token has \p RK token kind. If \p DeleteLeft is true, the left token 2159 // is deleted on match; otherwise, the right token is deleted. 2160 template <typename LeftKind, typename RightKind> 2161 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK, 2162 bool DeleteLeft) { 2163 auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * { 2164 for (auto *Res = Tok.Next; Res; Res = Res->Next) 2165 if (!Res->is(tok::comment) && 2166 DeletedTokens.find(Res) == DeletedTokens.end()) 2167 return Res; 2168 return nullptr; 2169 }; 2170 for (auto *Left = Start; Left;) { 2171 auto *Right = NextNotDeleted(*Left); 2172 if (!Right) 2173 break; 2174 if (Left->is(LK) && Right->is(RK)) { 2175 deleteToken(DeleteLeft ? Left : Right); 2176 for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next) 2177 deleteToken(Tok); 2178 // If the right token is deleted, we should keep the left token 2179 // unchanged and pair it with the new right token. 2180 if (!DeleteLeft) 2181 continue; 2182 } 2183 Left = Right; 2184 } 2185 } 2186 2187 template <typename LeftKind, typename RightKind> 2188 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) { 2189 cleanupPair(Start, LK, RK, /*DeleteLeft=*/true); 2190 } 2191 2192 template <typename LeftKind, typename RightKind> 2193 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) { 2194 cleanupPair(Start, LK, RK, /*DeleteLeft=*/false); 2195 } 2196 2197 // Delete the given token. 2198 inline void deleteToken(FormatToken *Tok) { 2199 if (Tok) 2200 DeletedTokens.insert(Tok); 2201 } 2202 2203 tooling::Replacements generateFixes() { 2204 tooling::Replacements Fixes; 2205 std::vector<FormatToken *> Tokens; 2206 std::copy(DeletedTokens.begin(), DeletedTokens.end(), 2207 std::back_inserter(Tokens)); 2208 2209 // Merge multiple continuous token deletions into one big deletion so that 2210 // the number of replacements can be reduced. This makes computing affected 2211 // ranges more efficient when we run reformat on the changed code. 2212 unsigned Idx = 0; 2213 while (Idx < Tokens.size()) { 2214 unsigned St = Idx, End = Idx; 2215 while ((End + 1) < Tokens.size() && 2216 Tokens[End]->Next == Tokens[End + 1]) { 2217 ++End; 2218 } 2219 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(), 2220 Tokens[End]->Tok.getEndLoc()); 2221 auto Err = 2222 Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, "")); 2223 // FIXME: better error handling. for now just print error message and skip 2224 // for the release version. 2225 if (Err) { 2226 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 2227 assert(false && "Fixes must not conflict!"); 2228 } 2229 Idx = End + 1; 2230 } 2231 2232 return Fixes; 2233 } 2234 2235 // Class for less-than inequality comparason for the set `RedundantTokens`. 2236 // We store tokens in the order they appear in the translation unit so that 2237 // we do not need to sort them in `generateFixes()`. 2238 struct FormatTokenLess { 2239 FormatTokenLess(const SourceManager &SM) : SM(SM) {} 2240 2241 bool operator()(const FormatToken *LHS, const FormatToken *RHS) const { 2242 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(), 2243 RHS->Tok.getLocation()); 2244 } 2245 const SourceManager &SM; 2246 }; 2247 2248 // Tokens to be deleted. 2249 std::set<FormatToken *, FormatTokenLess> DeletedTokens; 2250 }; 2251 2252 class ObjCHeaderStyleGuesser : public TokenAnalyzer { 2253 public: 2254 ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style) 2255 : TokenAnalyzer(Env, Style), IsObjC(false) {} 2256 2257 std::pair<tooling::Replacements, unsigned> 2258 analyze(TokenAnnotator &Annotator, 2259 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2260 FormatTokenLexer &Tokens) override { 2261 assert(Style.Language == FormatStyle::LK_Cpp); 2262 IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines, 2263 Tokens.getKeywords()); 2264 tooling::Replacements Result; 2265 return {Result, 0}; 2266 } 2267 2268 bool isObjC() { return IsObjC; } 2269 2270 private: 2271 static bool 2272 guessIsObjC(const SourceManager &SourceManager, 2273 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2274 const AdditionalKeywords &Keywords) { 2275 // Keep this array sorted, since we are binary searching over it. 2276 static constexpr llvm::StringLiteral FoundationIdentifiers[] = { 2277 "CGFloat", 2278 "CGPoint", 2279 "CGPointMake", 2280 "CGPointZero", 2281 "CGRect", 2282 "CGRectEdge", 2283 "CGRectInfinite", 2284 "CGRectMake", 2285 "CGRectNull", 2286 "CGRectZero", 2287 "CGSize", 2288 "CGSizeMake", 2289 "CGVector", 2290 "CGVectorMake", 2291 "NSAffineTransform", 2292 "NSArray", 2293 "NSAttributedString", 2294 "NSBlockOperation", 2295 "NSBundle", 2296 "NSCache", 2297 "NSCalendar", 2298 "NSCharacterSet", 2299 "NSCountedSet", 2300 "NSData", 2301 "NSDataDetector", 2302 "NSDecimal", 2303 "NSDecimalNumber", 2304 "NSDictionary", 2305 "NSEdgeInsets", 2306 "NSHashTable", 2307 "NSIndexPath", 2308 "NSIndexSet", 2309 "NSInteger", 2310 "NSInvocationOperation", 2311 "NSLocale", 2312 "NSMapTable", 2313 "NSMutableArray", 2314 "NSMutableAttributedString", 2315 "NSMutableCharacterSet", 2316 "NSMutableData", 2317 "NSMutableDictionary", 2318 "NSMutableIndexSet", 2319 "NSMutableOrderedSet", 2320 "NSMutableSet", 2321 "NSMutableString", 2322 "NSNumber", 2323 "NSNumberFormatter", 2324 "NSObject", 2325 "NSOperation", 2326 "NSOperationQueue", 2327 "NSOperationQueuePriority", 2328 "NSOrderedSet", 2329 "NSPoint", 2330 "NSPointerArray", 2331 "NSQualityOfService", 2332 "NSRange", 2333 "NSRect", 2334 "NSRegularExpression", 2335 "NSSet", 2336 "NSSize", 2337 "NSString", 2338 "NSTimeZone", 2339 "NSUInteger", 2340 "NSURL", 2341 "NSURLComponents", 2342 "NSURLQueryItem", 2343 "NSUUID", 2344 "NSValue", 2345 "UIImage", 2346 "UIView", 2347 }; 2348 2349 for (auto Line : AnnotatedLines) { 2350 if (Line->First && (Line->First->TokenText.startswith("#") || 2351 Line->First->TokenText == "__pragma" || 2352 Line->First->TokenText == "_Pragma")) 2353 continue; 2354 for (const FormatToken *FormatTok = Line->First; FormatTok; 2355 FormatTok = FormatTok->Next) { 2356 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) && 2357 (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword || 2358 FormatTok->isOneOf(tok::numeric_constant, tok::l_square, 2359 tok::l_brace))) || 2360 (FormatTok->Tok.isAnyIdentifier() && 2361 std::binary_search(std::begin(FoundationIdentifiers), 2362 std::end(FoundationIdentifiers), 2363 FormatTok->TokenText)) || 2364 FormatTok->is(TT_ObjCStringLiteral) || 2365 FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM, 2366 Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace, 2367 TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn, 2368 TT_ObjCMethodExpr, TT_ObjCMethodSpecifier, 2369 TT_ObjCProperty)) { 2370 LLVM_DEBUG(llvm::dbgs() 2371 << "Detected ObjC at location " 2372 << FormatTok->Tok.getLocation().printToString( 2373 SourceManager) 2374 << " token: " << FormatTok->TokenText << " token type: " 2375 << getTokenTypeName(FormatTok->getType()) << "\n"); 2376 return true; 2377 } 2378 if (guessIsObjC(SourceManager, Line->Children, Keywords)) 2379 return true; 2380 } 2381 } 2382 return false; 2383 } 2384 2385 bool IsObjC; 2386 }; 2387 2388 struct IncludeDirective { 2389 StringRef Filename; 2390 StringRef Text; 2391 unsigned Offset; 2392 int Category; 2393 int Priority; 2394 }; 2395 2396 struct JavaImportDirective { 2397 StringRef Identifier; 2398 StringRef Text; 2399 unsigned Offset; 2400 std::vector<StringRef> AssociatedCommentLines; 2401 bool IsStatic; 2402 }; 2403 2404 } // end anonymous namespace 2405 2406 // Determines whether 'Ranges' intersects with ('Start', 'End'). 2407 static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start, 2408 unsigned End) { 2409 for (auto Range : Ranges) { 2410 if (Range.getOffset() < End && 2411 Range.getOffset() + Range.getLength() > Start) 2412 return true; 2413 } 2414 return false; 2415 } 2416 2417 // Returns a pair (Index, OffsetToEOL) describing the position of the cursor 2418 // before sorting/deduplicating. Index is the index of the include under the 2419 // cursor in the original set of includes. If this include has duplicates, it is 2420 // the index of the first of the duplicates as the others are going to be 2421 // removed. OffsetToEOL describes the cursor's position relative to the end of 2422 // its current line. 2423 // If `Cursor` is not on any #include, `Index` will be UINT_MAX. 2424 static std::pair<unsigned, unsigned> 2425 FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes, 2426 const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) { 2427 unsigned CursorIndex = UINT_MAX; 2428 unsigned OffsetToEOL = 0; 2429 for (int i = 0, e = Includes.size(); i != e; ++i) { 2430 unsigned Start = Includes[Indices[i]].Offset; 2431 unsigned End = Start + Includes[Indices[i]].Text.size(); 2432 if (!(Cursor >= Start && Cursor < End)) 2433 continue; 2434 CursorIndex = Indices[i]; 2435 OffsetToEOL = End - Cursor; 2436 // Put the cursor on the only remaining #include among the duplicate 2437 // #includes. 2438 while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text) 2439 CursorIndex = i; 2440 break; 2441 } 2442 return std::make_pair(CursorIndex, OffsetToEOL); 2443 } 2444 2445 // Replace all "\r\n" with "\n". 2446 std::string replaceCRLF(const std::string &Code) { 2447 std::string NewCode; 2448 size_t Pos = 0, LastPos = 0; 2449 2450 do { 2451 Pos = Code.find("\r\n", LastPos); 2452 if (Pos == LastPos) { 2453 ++LastPos; 2454 continue; 2455 } 2456 if (Pos == std::string::npos) { 2457 NewCode += Code.substr(LastPos); 2458 break; 2459 } 2460 NewCode += Code.substr(LastPos, Pos - LastPos) + "\n"; 2461 LastPos = Pos + 2; 2462 } while (Pos != std::string::npos); 2463 2464 return NewCode; 2465 } 2466 2467 // Sorts and deduplicate a block of includes given by 'Includes' alphabetically 2468 // adding the necessary replacement to 'Replaces'. 'Includes' must be in strict 2469 // source order. 2470 // #include directives with the same text will be deduplicated, and only the 2471 // first #include in the duplicate #includes remains. If the `Cursor` is 2472 // provided and put on a deleted #include, it will be moved to the remaining 2473 // #include in the duplicate #includes. 2474 static void sortCppIncludes(const FormatStyle &Style, 2475 const SmallVectorImpl<IncludeDirective> &Includes, 2476 ArrayRef<tooling::Range> Ranges, StringRef FileName, 2477 StringRef Code, tooling::Replacements &Replaces, 2478 unsigned *Cursor) { 2479 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 2480 unsigned IncludesBeginOffset = Includes.front().Offset; 2481 unsigned IncludesEndOffset = 2482 Includes.back().Offset + Includes.back().Text.size(); 2483 unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset; 2484 if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset)) 2485 return; 2486 SmallVector<unsigned, 16> Indices; 2487 for (unsigned i = 0, e = Includes.size(); i != e; ++i) { 2488 Indices.push_back(i); 2489 } 2490 2491 if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) { 2492 llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 2493 const auto LHSFilenameLower = Includes[LHSI].Filename.lower(); 2494 const auto RHSFilenameLower = Includes[RHSI].Filename.lower(); 2495 return std::tie(Includes[LHSI].Priority, LHSFilenameLower, 2496 Includes[LHSI].Filename) < 2497 std::tie(Includes[RHSI].Priority, RHSFilenameLower, 2498 Includes[RHSI].Filename); 2499 }); 2500 } else { 2501 llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 2502 return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) < 2503 std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename); 2504 }); 2505 } 2506 2507 // The index of the include on which the cursor will be put after 2508 // sorting/deduplicating. 2509 unsigned CursorIndex; 2510 // The offset from cursor to the end of line. 2511 unsigned CursorToEOLOffset; 2512 if (Cursor) 2513 std::tie(CursorIndex, CursorToEOLOffset) = 2514 FindCursorIndex(Includes, Indices, *Cursor); 2515 2516 // Deduplicate #includes. 2517 Indices.erase(std::unique(Indices.begin(), Indices.end(), 2518 [&](unsigned LHSI, unsigned RHSI) { 2519 return Includes[LHSI].Text.trim() == 2520 Includes[RHSI].Text.trim(); 2521 }), 2522 Indices.end()); 2523 2524 int CurrentCategory = Includes.front().Category; 2525 2526 // If the #includes are out of order, we generate a single replacement fixing 2527 // the entire block. Otherwise, no replacement is generated. 2528 // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not 2529 // enough as additional newlines might be added or removed across #include 2530 // blocks. This we handle below by generating the updated #imclude blocks and 2531 // comparing it to the original. 2532 if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) && 2533 Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) 2534 return; 2535 2536 std::string result; 2537 for (unsigned Index : Indices) { 2538 if (!result.empty()) { 2539 result += "\n"; 2540 if (Style.IncludeStyle.IncludeBlocks == 2541 tooling::IncludeStyle::IBS_Regroup && 2542 CurrentCategory != Includes[Index].Category) 2543 result += "\n"; 2544 } 2545 result += Includes[Index].Text; 2546 if (Cursor && CursorIndex == Index) 2547 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset; 2548 CurrentCategory = Includes[Index].Category; 2549 } 2550 2551 // If the #includes are out of order, we generate a single replacement fixing 2552 // the entire range of blocks. Otherwise, no replacement is generated. 2553 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 2554 IncludesBeginOffset, IncludesBlockSize)))) 2555 return; 2556 2557 auto Err = Replaces.add(tooling::Replacement( 2558 FileName, Includes.front().Offset, IncludesBlockSize, result)); 2559 // FIXME: better error handling. For now, just skip the replacement for the 2560 // release version. 2561 if (Err) { 2562 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 2563 assert(false); 2564 } 2565 } 2566 2567 namespace { 2568 2569 const char CppIncludeRegexPattern[] = 2570 R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))"; 2571 2572 } // anonymous namespace 2573 2574 tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code, 2575 ArrayRef<tooling::Range> Ranges, 2576 StringRef FileName, 2577 tooling::Replacements &Replaces, 2578 unsigned *Cursor) { 2579 unsigned Prev = llvm::StringSwitch<size_t>(Code) 2580 .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM 2581 .Default(0); 2582 unsigned SearchFrom = 0; 2583 llvm::Regex IncludeRegex(CppIncludeRegexPattern); 2584 SmallVector<StringRef, 4> Matches; 2585 SmallVector<IncludeDirective, 16> IncludesInBlock; 2586 2587 // In compiled files, consider the first #include to be the main #include of 2588 // the file if it is not a system #include. This ensures that the header 2589 // doesn't have hidden dependencies 2590 // (http://llvm.org/docs/CodingStandards.html#include-style). 2591 // 2592 // FIXME: Do some validation, e.g. edit distance of the base name, to fix 2593 // cases where the first #include is unlikely to be the main header. 2594 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 2595 bool FirstIncludeBlock = true; 2596 bool MainIncludeFound = false; 2597 bool FormattingOff = false; 2598 2599 // '[' must be the first and '-' the last character inside [...]. 2600 llvm::Regex RawStringRegex( 2601 "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\("); 2602 SmallVector<StringRef, 2> RawStringMatches; 2603 std::string RawStringTermination = ")\""; 2604 2605 for (;;) { 2606 auto Pos = Code.find('\n', SearchFrom); 2607 StringRef Line = 2608 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 2609 2610 StringRef Trimmed = Line.trim(); 2611 2612 // #includes inside raw string literals need to be ignored. 2613 // or we will sort the contents of the string. 2614 // Skip past until we think we are at the rawstring literal close. 2615 if (RawStringRegex.match(Trimmed, &RawStringMatches)) { 2616 std::string CharSequence = RawStringMatches[1].str(); 2617 RawStringTermination = ")" + CharSequence + "\""; 2618 FormattingOff = true; 2619 } 2620 2621 if (Trimmed.contains(RawStringTermination)) { 2622 FormattingOff = false; 2623 } 2624 2625 if (Trimmed == "// clang-format off" || Trimmed == "/* clang-format off */") 2626 FormattingOff = true; 2627 else if (Trimmed == "// clang-format on" || 2628 Trimmed == "/* clang-format on */") 2629 FormattingOff = false; 2630 2631 const bool EmptyLineSkipped = 2632 Trimmed.empty() && 2633 (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge || 2634 Style.IncludeStyle.IncludeBlocks == 2635 tooling::IncludeStyle::IBS_Regroup); 2636 2637 bool MergeWithNextLine = Trimmed.endswith("\\"); 2638 if (!FormattingOff && !MergeWithNextLine) { 2639 if (IncludeRegex.match(Line, &Matches)) { 2640 StringRef IncludeName = Matches[2]; 2641 int Category = Categories.getIncludePriority( 2642 IncludeName, 2643 /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock); 2644 int Priority = Categories.getSortIncludePriority( 2645 IncludeName, !MainIncludeFound && FirstIncludeBlock); 2646 if (Category == 0) 2647 MainIncludeFound = true; 2648 IncludesInBlock.push_back( 2649 {IncludeName, Line, Prev, Category, Priority}); 2650 } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) { 2651 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, 2652 Replaces, Cursor); 2653 IncludesInBlock.clear(); 2654 if (Trimmed.startswith("#pragma hdrstop")) // Precompiled headers. 2655 FirstIncludeBlock = true; 2656 else 2657 FirstIncludeBlock = false; 2658 } 2659 } 2660 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 2661 break; 2662 2663 if (!MergeWithNextLine) 2664 Prev = Pos + 1; 2665 SearchFrom = Pos + 1; 2666 } 2667 if (!IncludesInBlock.empty()) { 2668 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces, 2669 Cursor); 2670 } 2671 return Replaces; 2672 } 2673 2674 // Returns group number to use as a first order sort on imports. Gives UINT_MAX 2675 // if the import does not match any given groups. 2676 static unsigned findJavaImportGroup(const FormatStyle &Style, 2677 StringRef ImportIdentifier) { 2678 unsigned LongestMatchIndex = UINT_MAX; 2679 unsigned LongestMatchLength = 0; 2680 for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) { 2681 std::string GroupPrefix = Style.JavaImportGroups[I]; 2682 if (ImportIdentifier.startswith(GroupPrefix) && 2683 GroupPrefix.length() > LongestMatchLength) { 2684 LongestMatchIndex = I; 2685 LongestMatchLength = GroupPrefix.length(); 2686 } 2687 } 2688 return LongestMatchIndex; 2689 } 2690 2691 // Sorts and deduplicates a block of includes given by 'Imports' based on 2692 // JavaImportGroups, then adding the necessary replacement to 'Replaces'. 2693 // Import declarations with the same text will be deduplicated. Between each 2694 // import group, a newline is inserted, and within each import group, a 2695 // lexicographic sort based on ASCII value is performed. 2696 static void sortJavaImports(const FormatStyle &Style, 2697 const SmallVectorImpl<JavaImportDirective> &Imports, 2698 ArrayRef<tooling::Range> Ranges, StringRef FileName, 2699 StringRef Code, tooling::Replacements &Replaces) { 2700 unsigned ImportsBeginOffset = Imports.front().Offset; 2701 unsigned ImportsEndOffset = 2702 Imports.back().Offset + Imports.back().Text.size(); 2703 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset; 2704 if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset)) 2705 return; 2706 SmallVector<unsigned, 16> Indices; 2707 SmallVector<unsigned, 16> JavaImportGroups; 2708 for (unsigned i = 0, e = Imports.size(); i != e; ++i) { 2709 Indices.push_back(i); 2710 JavaImportGroups.push_back( 2711 findJavaImportGroup(Style, Imports[i].Identifier)); 2712 } 2713 bool StaticImportAfterNormalImport = 2714 Style.SortJavaStaticImport == FormatStyle::SJSIO_After; 2715 llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 2716 // Negating IsStatic to push static imports above non-static imports. 2717 return std::make_tuple(!Imports[LHSI].IsStatic ^ 2718 StaticImportAfterNormalImport, 2719 JavaImportGroups[LHSI], Imports[LHSI].Identifier) < 2720 std::make_tuple(!Imports[RHSI].IsStatic ^ 2721 StaticImportAfterNormalImport, 2722 JavaImportGroups[RHSI], Imports[RHSI].Identifier); 2723 }); 2724 2725 // Deduplicate imports. 2726 Indices.erase(std::unique(Indices.begin(), Indices.end(), 2727 [&](unsigned LHSI, unsigned RHSI) { 2728 return Imports[LHSI].Text == Imports[RHSI].Text; 2729 }), 2730 Indices.end()); 2731 2732 bool CurrentIsStatic = Imports[Indices.front()].IsStatic; 2733 unsigned CurrentImportGroup = JavaImportGroups[Indices.front()]; 2734 2735 std::string result; 2736 for (unsigned Index : Indices) { 2737 if (!result.empty()) { 2738 result += "\n"; 2739 if (CurrentIsStatic != Imports[Index].IsStatic || 2740 CurrentImportGroup != JavaImportGroups[Index]) 2741 result += "\n"; 2742 } 2743 for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) { 2744 result += CommentLine; 2745 result += "\n"; 2746 } 2747 result += Imports[Index].Text; 2748 CurrentIsStatic = Imports[Index].IsStatic; 2749 CurrentImportGroup = JavaImportGroups[Index]; 2750 } 2751 2752 // If the imports are out of order, we generate a single replacement fixing 2753 // the entire block. Otherwise, no replacement is generated. 2754 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 2755 Imports.front().Offset, ImportsBlockSize)))) 2756 return; 2757 2758 auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset, 2759 ImportsBlockSize, result)); 2760 // FIXME: better error handling. For now, just skip the replacement for the 2761 // release version. 2762 if (Err) { 2763 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 2764 assert(false); 2765 } 2766 } 2767 2768 namespace { 2769 2770 const char JavaImportRegexPattern[] = 2771 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;"; 2772 2773 } // anonymous namespace 2774 2775 tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code, 2776 ArrayRef<tooling::Range> Ranges, 2777 StringRef FileName, 2778 tooling::Replacements &Replaces) { 2779 unsigned Prev = 0; 2780 unsigned SearchFrom = 0; 2781 llvm::Regex ImportRegex(JavaImportRegexPattern); 2782 SmallVector<StringRef, 4> Matches; 2783 SmallVector<JavaImportDirective, 16> ImportsInBlock; 2784 std::vector<StringRef> AssociatedCommentLines; 2785 2786 bool FormattingOff = false; 2787 2788 for (;;) { 2789 auto Pos = Code.find('\n', SearchFrom); 2790 StringRef Line = 2791 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 2792 2793 StringRef Trimmed = Line.trim(); 2794 if (Trimmed == "// clang-format off") 2795 FormattingOff = true; 2796 else if (Trimmed == "// clang-format on") 2797 FormattingOff = false; 2798 2799 if (ImportRegex.match(Line, &Matches)) { 2800 if (FormattingOff) { 2801 // If at least one import line has formatting turned off, turn off 2802 // formatting entirely. 2803 return Replaces; 2804 } 2805 StringRef Static = Matches[1]; 2806 StringRef Identifier = Matches[2]; 2807 bool IsStatic = false; 2808 if (Static.contains("static")) { 2809 IsStatic = true; 2810 } 2811 ImportsInBlock.push_back( 2812 {Identifier, Line, Prev, AssociatedCommentLines, IsStatic}); 2813 AssociatedCommentLines.clear(); 2814 } else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) { 2815 // Associating comments within the imports with the nearest import below 2816 AssociatedCommentLines.push_back(Line); 2817 } 2818 Prev = Pos + 1; 2819 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 2820 break; 2821 SearchFrom = Pos + 1; 2822 } 2823 if (!ImportsInBlock.empty()) 2824 sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces); 2825 return Replaces; 2826 } 2827 2828 bool isMpegTS(StringRef Code) { 2829 // MPEG transport streams use the ".ts" file extension. clang-format should 2830 // not attempt to format those. MPEG TS' frame format starts with 0x47 every 2831 // 189 bytes - detect that and return. 2832 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47; 2833 } 2834 2835 bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); } 2836 2837 tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, 2838 ArrayRef<tooling::Range> Ranges, 2839 StringRef FileName, unsigned *Cursor) { 2840 tooling::Replacements Replaces; 2841 if (!Style.SortIncludes || Style.DisableFormat) 2842 return Replaces; 2843 if (isLikelyXml(Code)) 2844 return Replaces; 2845 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript && 2846 isMpegTS(Code)) 2847 return Replaces; 2848 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript) 2849 return sortJavaScriptImports(Style, Code, Ranges, FileName); 2850 if (Style.Language == FormatStyle::LanguageKind::LK_Java) 2851 return sortJavaImports(Style, Code, Ranges, FileName, Replaces); 2852 sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor); 2853 return Replaces; 2854 } 2855 2856 template <typename T> 2857 static llvm::Expected<tooling::Replacements> 2858 processReplacements(T ProcessFunc, StringRef Code, 2859 const tooling::Replacements &Replaces, 2860 const FormatStyle &Style) { 2861 if (Replaces.empty()) 2862 return tooling::Replacements(); 2863 2864 auto NewCode = applyAllReplacements(Code, Replaces); 2865 if (!NewCode) 2866 return NewCode.takeError(); 2867 std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges(); 2868 StringRef FileName = Replaces.begin()->getFilePath(); 2869 2870 tooling::Replacements FormatReplaces = 2871 ProcessFunc(Style, *NewCode, ChangedRanges, FileName); 2872 2873 return Replaces.merge(FormatReplaces); 2874 } 2875 2876 llvm::Expected<tooling::Replacements> 2877 formatReplacements(StringRef Code, const tooling::Replacements &Replaces, 2878 const FormatStyle &Style) { 2879 // We need to use lambda function here since there are two versions of 2880 // `sortIncludes`. 2881 auto SortIncludes = [](const FormatStyle &Style, StringRef Code, 2882 std::vector<tooling::Range> Ranges, 2883 StringRef FileName) -> tooling::Replacements { 2884 return sortIncludes(Style, Code, Ranges, FileName); 2885 }; 2886 auto SortedReplaces = 2887 processReplacements(SortIncludes, Code, Replaces, Style); 2888 if (!SortedReplaces) 2889 return SortedReplaces.takeError(); 2890 2891 // We need to use lambda function here since there are two versions of 2892 // `reformat`. 2893 auto Reformat = [](const FormatStyle &Style, StringRef Code, 2894 std::vector<tooling::Range> Ranges, 2895 StringRef FileName) -> tooling::Replacements { 2896 return reformat(Style, Code, Ranges, FileName); 2897 }; 2898 return processReplacements(Reformat, Code, *SortedReplaces, Style); 2899 } 2900 2901 namespace { 2902 2903 inline bool isHeaderInsertion(const tooling::Replacement &Replace) { 2904 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 && 2905 llvm::Regex(CppIncludeRegexPattern) 2906 .match(Replace.getReplacementText()); 2907 } 2908 2909 inline bool isHeaderDeletion(const tooling::Replacement &Replace) { 2910 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1; 2911 } 2912 2913 // FIXME: insert empty lines between newly created blocks. 2914 tooling::Replacements 2915 fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces, 2916 const FormatStyle &Style) { 2917 if (!Style.isCpp()) 2918 return Replaces; 2919 2920 tooling::Replacements HeaderInsertions; 2921 std::set<llvm::StringRef> HeadersToDelete; 2922 tooling::Replacements Result; 2923 for (const auto &R : Replaces) { 2924 if (isHeaderInsertion(R)) { 2925 // Replacements from \p Replaces must be conflict-free already, so we can 2926 // simply consume the error. 2927 llvm::consumeError(HeaderInsertions.add(R)); 2928 } else if (isHeaderDeletion(R)) { 2929 HeadersToDelete.insert(R.getReplacementText()); 2930 } else if (R.getOffset() == UINT_MAX) { 2931 llvm::errs() << "Insertions other than header #include insertion are " 2932 "not supported! " 2933 << R.getReplacementText() << "\n"; 2934 } else { 2935 llvm::consumeError(Result.add(R)); 2936 } 2937 } 2938 if (HeaderInsertions.empty() && HeadersToDelete.empty()) 2939 return Replaces; 2940 2941 StringRef FileName = Replaces.begin()->getFilePath(); 2942 tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle); 2943 2944 for (const auto &Header : HeadersToDelete) { 2945 tooling::Replacements Replaces = 2946 Includes.remove(Header.trim("\"<>"), Header.startswith("<")); 2947 for (const auto &R : Replaces) { 2948 auto Err = Result.add(R); 2949 if (Err) { 2950 // Ignore the deletion on conflict. 2951 llvm::errs() << "Failed to add header deletion replacement for " 2952 << Header << ": " << llvm::toString(std::move(Err)) 2953 << "\n"; 2954 } 2955 } 2956 } 2957 2958 llvm::Regex IncludeRegex = llvm::Regex(CppIncludeRegexPattern); 2959 llvm::SmallVector<StringRef, 4> Matches; 2960 for (const auto &R : HeaderInsertions) { 2961 auto IncludeDirective = R.getReplacementText(); 2962 bool Matched = IncludeRegex.match(IncludeDirective, &Matches); 2963 assert(Matched && "Header insertion replacement must have replacement text " 2964 "'#include ...'"); 2965 (void)Matched; 2966 auto IncludeName = Matches[2]; 2967 auto Replace = 2968 Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<")); 2969 if (Replace) { 2970 auto Err = Result.add(*Replace); 2971 if (Err) { 2972 llvm::consumeError(std::move(Err)); 2973 unsigned NewOffset = 2974 Result.getShiftedCodePosition(Replace->getOffset()); 2975 auto Shifted = tooling::Replacement(FileName, NewOffset, 0, 2976 Replace->getReplacementText()); 2977 Result = Result.merge(tooling::Replacements(Shifted)); 2978 } 2979 } 2980 } 2981 return Result; 2982 } 2983 2984 } // anonymous namespace 2985 2986 llvm::Expected<tooling::Replacements> 2987 cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, 2988 const FormatStyle &Style) { 2989 // We need to use lambda function here since there are two versions of 2990 // `cleanup`. 2991 auto Cleanup = [](const FormatStyle &Style, StringRef Code, 2992 std::vector<tooling::Range> Ranges, 2993 StringRef FileName) -> tooling::Replacements { 2994 return cleanup(Style, Code, Ranges, FileName); 2995 }; 2996 // Make header insertion replacements insert new headers into correct blocks. 2997 tooling::Replacements NewReplaces = 2998 fixCppIncludeInsertions(Code, Replaces, Style); 2999 return processReplacements(Cleanup, Code, NewReplaces, Style); 3000 } 3001 3002 namespace internal { 3003 std::pair<tooling::Replacements, unsigned> 3004 reformat(const FormatStyle &Style, StringRef Code, 3005 ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn, 3006 unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName, 3007 FormattingAttemptStatus *Status) { 3008 FormatStyle Expanded = Style; 3009 expandPresetsBraceWrapping(Expanded); 3010 expandPresetsSpaceBeforeParens(Expanded); 3011 if (Expanded.DisableFormat) 3012 return {tooling::Replacements(), 0}; 3013 if (isLikelyXml(Code)) 3014 return {tooling::Replacements(), 0}; 3015 if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code)) 3016 return {tooling::Replacements(), 0}; 3017 3018 // JSON only needs the formatting passing. 3019 if (Style.isJson()) { 3020 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); 3021 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn, 3022 NextStartColumn, LastStartColumn); 3023 if (!Env) 3024 return {}; 3025 // Perform the actual formatting pass. 3026 tooling::Replacements Replaces = 3027 Formatter(*Env, Style, Status).process().first; 3028 // add a replacement to remove the "x = " from the result. 3029 if (!Replaces.add(tooling::Replacement(FileName, 0, 4, ""))) { 3030 // apply the reformatting changes and the removal of "x = ". 3031 if (applyAllReplacements(Code, Replaces)) { 3032 return {Replaces, 0}; 3033 } 3034 } 3035 return {tooling::Replacements(), 0}; 3036 } 3037 3038 typedef std::function<std::pair<tooling::Replacements, unsigned>( 3039 const Environment &)> 3040 AnalyzerPass; 3041 SmallVector<AnalyzerPass, 4> Passes; 3042 3043 if (Style.isCpp() && Style.QualifierAlignment != FormatStyle::QAS_Leave) { 3044 Passes.emplace_back([&](const Environment &Env) { 3045 return QualifierAlignmentFixer(Env, Expanded, Code, Ranges, 3046 FirstStartColumn, NextStartColumn, 3047 LastStartColumn, FileName) 3048 .process(); 3049 }); 3050 } 3051 3052 if (Style.Language == FormatStyle::LK_Cpp) { 3053 if (Style.FixNamespaceComments) 3054 Passes.emplace_back([&](const Environment &Env) { 3055 return NamespaceEndCommentsFixer(Env, Expanded).process(); 3056 }); 3057 3058 if (Style.SortUsingDeclarations) 3059 Passes.emplace_back([&](const Environment &Env) { 3060 return UsingDeclarationsSorter(Env, Expanded).process(); 3061 }); 3062 } 3063 3064 if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) 3065 Passes.emplace_back([&](const Environment &Env) { 3066 return DefinitionBlockSeparator(Env, Expanded).process(); 3067 }); 3068 3069 if (Style.isJavaScript() && Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) 3070 Passes.emplace_back([&](const Environment &Env) { 3071 return JavaScriptRequoter(Env, Expanded).process(); 3072 }); 3073 3074 Passes.emplace_back([&](const Environment &Env) { 3075 return Formatter(Env, Expanded, Status).process(); 3076 }); 3077 3078 if (Style.isJavaScript() && 3079 Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) 3080 Passes.emplace_back([&](const Environment &Env) { 3081 return TrailingCommaInserter(Env, Expanded).process(); 3082 }); 3083 3084 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn, 3085 NextStartColumn, LastStartColumn); 3086 if (!Env) 3087 return {}; 3088 llvm::Optional<std::string> CurrentCode = None; 3089 tooling::Replacements Fixes; 3090 unsigned Penalty = 0; 3091 for (size_t I = 0, E = Passes.size(); I < E; ++I) { 3092 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env); 3093 auto NewCode = applyAllReplacements( 3094 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first); 3095 if (NewCode) { 3096 Fixes = Fixes.merge(PassFixes.first); 3097 Penalty += PassFixes.second; 3098 if (I + 1 < E) { 3099 CurrentCode = std::move(*NewCode); 3100 Env = Environment::make( 3101 *CurrentCode, FileName, 3102 tooling::calculateRangesAfterReplacements(Fixes, Ranges), 3103 FirstStartColumn, NextStartColumn, LastStartColumn); 3104 if (!Env) 3105 return {}; 3106 } 3107 } 3108 } 3109 3110 return {Fixes, Penalty}; 3111 } 3112 } // namespace internal 3113 3114 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 3115 ArrayRef<tooling::Range> Ranges, 3116 StringRef FileName, 3117 FormattingAttemptStatus *Status) { 3118 return internal::reformat(Style, Code, Ranges, 3119 /*FirstStartColumn=*/0, 3120 /*NextStartColumn=*/0, 3121 /*LastStartColumn=*/0, FileName, Status) 3122 .first; 3123 } 3124 3125 tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, 3126 ArrayRef<tooling::Range> Ranges, 3127 StringRef FileName) { 3128 // cleanups only apply to C++ (they mostly concern ctor commas etc.) 3129 if (Style.Language != FormatStyle::LK_Cpp) 3130 return tooling::Replacements(); 3131 auto Env = Environment::make(Code, FileName, Ranges); 3132 if (!Env) 3133 return {}; 3134 return Cleaner(*Env, Style).process().first; 3135 } 3136 3137 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 3138 ArrayRef<tooling::Range> Ranges, 3139 StringRef FileName, bool *IncompleteFormat) { 3140 FormattingAttemptStatus Status; 3141 auto Result = reformat(Style, Code, Ranges, FileName, &Status); 3142 if (!Status.FormatComplete) 3143 *IncompleteFormat = true; 3144 return Result; 3145 } 3146 3147 tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, 3148 StringRef Code, 3149 ArrayRef<tooling::Range> Ranges, 3150 StringRef FileName) { 3151 auto Env = Environment::make(Code, FileName, Ranges); 3152 if (!Env) 3153 return {}; 3154 return NamespaceEndCommentsFixer(*Env, Style).process().first; 3155 } 3156 3157 tooling::Replacements separateDefinitionBlocks(const FormatStyle &Style, 3158 StringRef Code, 3159 ArrayRef<tooling::Range> Ranges, 3160 StringRef FileName) { 3161 auto Env = Environment::make(Code, FileName, Ranges); 3162 if (!Env) 3163 return {}; 3164 return DefinitionBlockSeparator(*Env, Style).process().first; 3165 } 3166 3167 tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, 3168 StringRef Code, 3169 ArrayRef<tooling::Range> Ranges, 3170 StringRef FileName) { 3171 auto Env = Environment::make(Code, FileName, Ranges); 3172 if (!Env) 3173 return {}; 3174 return UsingDeclarationsSorter(*Env, Style).process().first; 3175 } 3176 3177 LangOptions getFormattingLangOpts(const FormatStyle &Style) { 3178 LangOptions LangOpts; 3179 3180 FormatStyle::LanguageStandard LexingStd = Style.Standard; 3181 if (LexingStd == FormatStyle::LS_Auto) 3182 LexingStd = FormatStyle::LS_Latest; 3183 if (LexingStd == FormatStyle::LS_Latest) 3184 LexingStd = FormatStyle::LS_Cpp20; 3185 LangOpts.CPlusPlus = 1; 3186 LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11; 3187 LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14; 3188 LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17; 3189 LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20; 3190 LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20; 3191 3192 LangOpts.LineComment = 1; 3193 bool AlternativeOperators = Style.isCpp(); 3194 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0; 3195 LangOpts.Bool = 1; 3196 LangOpts.ObjC = 1; 3197 LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally. 3198 LangOpts.DeclSpecKeyword = 1; // To get __declspec. 3199 LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict. 3200 return LangOpts; 3201 } 3202 3203 const char *StyleOptionHelpDescription = 3204 "Coding style, currently supports:\n" 3205 " LLVM, GNU, Google, Chromium, Microsoft, Mozilla, WebKit.\n" 3206 "Use -style=file to load style configuration from\n" 3207 ".clang-format file located in one of the parent\n" 3208 "directories of the source file (or current\n" 3209 "directory for stdin).\n" 3210 "Use -style=file:<format_file_path> to explicitly specify" 3211 "the configuration file.\n" 3212 "Use -style=\"{key: value, ...}\" to set specific\n" 3213 "parameters, e.g.:\n" 3214 " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""; 3215 3216 static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) { 3217 if (FileName.endswith(".java")) 3218 return FormatStyle::LK_Java; 3219 if (FileName.endswith_insensitive(".js") || 3220 FileName.endswith_insensitive(".mjs") || 3221 FileName.endswith_insensitive(".ts")) 3222 return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript. 3223 if (FileName.endswith(".m") || FileName.endswith(".mm")) 3224 return FormatStyle::LK_ObjC; 3225 if (FileName.endswith_insensitive(".proto") || 3226 FileName.endswith_insensitive(".protodevel")) 3227 return FormatStyle::LK_Proto; 3228 if (FileName.endswith_insensitive(".textpb") || 3229 FileName.endswith_insensitive(".pb.txt") || 3230 FileName.endswith_insensitive(".textproto") || 3231 FileName.endswith_insensitive(".asciipb")) 3232 return FormatStyle::LK_TextProto; 3233 if (FileName.endswith_insensitive(".td")) 3234 return FormatStyle::LK_TableGen; 3235 if (FileName.endswith_insensitive(".cs")) 3236 return FormatStyle::LK_CSharp; 3237 if (FileName.endswith_insensitive(".json")) 3238 return FormatStyle::LK_Json; 3239 return FormatStyle::LK_Cpp; 3240 } 3241 3242 FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) { 3243 const auto GuessedLanguage = getLanguageByFileName(FileName); 3244 if (GuessedLanguage == FormatStyle::LK_Cpp) { 3245 auto Extension = llvm::sys::path::extension(FileName); 3246 // If there's no file extension (or it's .h), we need to check the contents 3247 // of the code to see if it contains Objective-C. 3248 if (Extension.empty() || Extension == ".h") { 3249 auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName; 3250 Environment Env(Code, NonEmptyFileName, /*Ranges=*/{}); 3251 ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle()); 3252 Guesser.process(); 3253 if (Guesser.isObjC()) 3254 return FormatStyle::LK_ObjC; 3255 } 3256 } 3257 return GuessedLanguage; 3258 } 3259 3260 const char *DefaultFormatStyle = "file"; 3261 3262 const char *DefaultFallbackStyle = "LLVM"; 3263 3264 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> 3265 loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS, 3266 FormatStyle *Style, bool AllowUnknownOptions) { 3267 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 3268 FS->getBufferForFile(ConfigFile.str()); 3269 if (auto EC = Text.getError()) 3270 return EC; 3271 if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions)) 3272 return EC; 3273 return Text; 3274 } 3275 3276 llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, 3277 StringRef FallbackStyleName, 3278 StringRef Code, llvm::vfs::FileSystem *FS, 3279 bool AllowUnknownOptions) { 3280 if (!FS) { 3281 FS = llvm::vfs::getRealFileSystem().get(); 3282 } 3283 FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code)); 3284 3285 FormatStyle FallbackStyle = getNoStyle(); 3286 if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle)) 3287 return make_string_error("Invalid fallback style \"" + FallbackStyleName); 3288 3289 llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1> 3290 ChildFormatTextToApply; 3291 3292 if (StyleName.startswith("{")) { 3293 // Parse YAML/JSON style from the command line. 3294 StringRef Source = "<command-line>"; 3295 if (std::error_code ec = 3296 parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style, 3297 AllowUnknownOptions)) 3298 return make_string_error("Error parsing -style: " + ec.message()); 3299 if (Style.InheritsParentConfig) 3300 ChildFormatTextToApply.emplace_back( 3301 llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false)); 3302 else 3303 return Style; 3304 } 3305 3306 // User provided clang-format file using -style=file:path/to/format/file. 3307 if (!Style.InheritsParentConfig && 3308 StyleName.startswith_insensitive("file:")) { 3309 auto ConfigFile = StyleName.substr(5); 3310 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 3311 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions); 3312 if (auto EC = Text.getError()) 3313 return make_string_error("Error reading " + ConfigFile + ": " + 3314 EC.message()); 3315 3316 LLVM_DEBUG(llvm::dbgs() 3317 << "Using configuration file " << ConfigFile << "\n"); 3318 3319 if (!Style.InheritsParentConfig) 3320 return Style; 3321 3322 // Search for parent configs starting from the parent directory of 3323 // ConfigFile. 3324 FileName = ConfigFile; 3325 ChildFormatTextToApply.emplace_back(std::move(*Text)); 3326 } 3327 3328 // If the style inherits the parent configuration it is a command line 3329 // configuration, which wants to inherit, so we have to skip the check of the 3330 // StyleName. 3331 if (!Style.InheritsParentConfig && !StyleName.equals_insensitive("file")) { 3332 if (!getPredefinedStyle(StyleName, Style.Language, &Style)) 3333 return make_string_error("Invalid value for -style"); 3334 if (!Style.InheritsParentConfig) 3335 return Style; 3336 } 3337 3338 // Reset possible inheritance 3339 Style.InheritsParentConfig = false; 3340 3341 // Look for .clang-format/_clang-format file in the file's parent directories. 3342 SmallString<128> UnsuitableConfigFiles; 3343 SmallString<128> Path(FileName); 3344 if (std::error_code EC = FS->makeAbsolute(Path)) 3345 return make_string_error(EC.message()); 3346 3347 llvm::SmallVector<std::string, 2> FilesToLookFor; 3348 FilesToLookFor.push_back(".clang-format"); 3349 FilesToLookFor.push_back("_clang-format"); 3350 3351 auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {}; 3352 3353 auto applyChildFormatTexts = [&](FormatStyle *Style) { 3354 for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) { 3355 auto EC = parseConfiguration(*MemBuf, Style, AllowUnknownOptions, 3356 dropDiagnosticHandler); 3357 // It was already correctly parsed. 3358 assert(!EC); 3359 static_cast<void>(EC); 3360 } 3361 }; 3362 3363 for (StringRef Directory = Path; !Directory.empty(); 3364 Directory = llvm::sys::path::parent_path(Directory)) { 3365 3366 auto Status = FS->status(Directory); 3367 if (!Status || 3368 Status->getType() != llvm::sys::fs::file_type::directory_file) { 3369 continue; 3370 } 3371 3372 for (const auto &F : FilesToLookFor) { 3373 SmallString<128> ConfigFile(Directory); 3374 3375 llvm::sys::path::append(ConfigFile, F); 3376 LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); 3377 3378 Status = FS->status(ConfigFile.str()); 3379 3380 if (Status && 3381 (Status->getType() == llvm::sys::fs::file_type::regular_file)) { 3382 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 3383 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions); 3384 if (auto EC = Text.getError()) { 3385 if (EC == ParseError::Unsuitable) { 3386 if (!UnsuitableConfigFiles.empty()) 3387 UnsuitableConfigFiles.append(", "); 3388 UnsuitableConfigFiles.append(ConfigFile); 3389 continue; 3390 } 3391 return make_string_error("Error reading " + ConfigFile + ": " + 3392 EC.message()); 3393 } 3394 LLVM_DEBUG(llvm::dbgs() 3395 << "Using configuration file " << ConfigFile << "\n"); 3396 3397 if (!Style.InheritsParentConfig) { 3398 if (ChildFormatTextToApply.empty()) 3399 return Style; 3400 3401 LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n"); 3402 applyChildFormatTexts(&Style); 3403 3404 return Style; 3405 } 3406 3407 LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n"); 3408 3409 // Reset inheritance of style 3410 Style.InheritsParentConfig = false; 3411 3412 ChildFormatTextToApply.emplace_back(std::move(*Text)); 3413 3414 // Breaking out of the inner loop, since we don't want to parse 3415 // .clang-format AND _clang-format, if both exist. Then we continue the 3416 // inner loop (parent directories) in search for the parent 3417 // configuration. 3418 break; 3419 } 3420 } 3421 } 3422 if (!UnsuitableConfigFiles.empty()) 3423 return make_string_error("Configuration file(s) do(es) not support " + 3424 getLanguageName(Style.Language) + ": " + 3425 UnsuitableConfigFiles); 3426 3427 if (!ChildFormatTextToApply.empty()) { 3428 LLVM_DEBUG(llvm::dbgs() 3429 << "Applying child configurations on fallback style\n"); 3430 applyChildFormatTexts(&FallbackStyle); 3431 } 3432 3433 return FallbackStyle; 3434 } 3435 3436 } // namespace format 3437 } // namespace clang 3438