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 llvm::Regex RawStringRegex( 2600 "R\"(([\\[A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'\\-]|])*)\\("); 2601 SmallVector<StringRef, 2> RawStringMatches; 2602 std::string RawStringTermination = ")\""; 2603 2604 for (;;) { 2605 auto Pos = Code.find('\n', SearchFrom); 2606 StringRef Line = 2607 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 2608 2609 StringRef Trimmed = Line.trim(); 2610 2611 // #includes inside raw string literals need to be ignored. 2612 // or we will sort the contents of the string. 2613 // Skip past until we think we are at the rawstring literal close. 2614 if (RawStringRegex.match(Trimmed, &RawStringMatches)) { 2615 std::string CharSequence = RawStringMatches[1].str(); 2616 RawStringTermination = ")" + CharSequence + "\""; 2617 FormattingOff = true; 2618 } 2619 2620 if (Trimmed.contains(RawStringTermination)) { 2621 FormattingOff = false; 2622 } 2623 2624 if (Trimmed == "// clang-format off" || Trimmed == "/* clang-format off */") 2625 FormattingOff = true; 2626 else if (Trimmed == "// clang-format on" || 2627 Trimmed == "/* clang-format on */") 2628 FormattingOff = false; 2629 2630 const bool EmptyLineSkipped = 2631 Trimmed.empty() && 2632 (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge || 2633 Style.IncludeStyle.IncludeBlocks == 2634 tooling::IncludeStyle::IBS_Regroup); 2635 2636 bool MergeWithNextLine = Trimmed.endswith("\\"); 2637 if (!FormattingOff && !MergeWithNextLine) { 2638 if (IncludeRegex.match(Line, &Matches)) { 2639 StringRef IncludeName = Matches[2]; 2640 int Category = Categories.getIncludePriority( 2641 IncludeName, 2642 /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock); 2643 int Priority = Categories.getSortIncludePriority( 2644 IncludeName, !MainIncludeFound && FirstIncludeBlock); 2645 if (Category == 0) 2646 MainIncludeFound = true; 2647 IncludesInBlock.push_back( 2648 {IncludeName, Line, Prev, Category, Priority}); 2649 } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) { 2650 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, 2651 Replaces, Cursor); 2652 IncludesInBlock.clear(); 2653 if (Trimmed.startswith("#pragma hdrstop")) // Precompiled headers. 2654 FirstIncludeBlock = true; 2655 else 2656 FirstIncludeBlock = false; 2657 } 2658 } 2659 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 2660 break; 2661 2662 if (!MergeWithNextLine) 2663 Prev = Pos + 1; 2664 SearchFrom = Pos + 1; 2665 } 2666 if (!IncludesInBlock.empty()) { 2667 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces, 2668 Cursor); 2669 } 2670 return Replaces; 2671 } 2672 2673 // Returns group number to use as a first order sort on imports. Gives UINT_MAX 2674 // if the import does not match any given groups. 2675 static unsigned findJavaImportGroup(const FormatStyle &Style, 2676 StringRef ImportIdentifier) { 2677 unsigned LongestMatchIndex = UINT_MAX; 2678 unsigned LongestMatchLength = 0; 2679 for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) { 2680 std::string GroupPrefix = Style.JavaImportGroups[I]; 2681 if (ImportIdentifier.startswith(GroupPrefix) && 2682 GroupPrefix.length() > LongestMatchLength) { 2683 LongestMatchIndex = I; 2684 LongestMatchLength = GroupPrefix.length(); 2685 } 2686 } 2687 return LongestMatchIndex; 2688 } 2689 2690 // Sorts and deduplicates a block of includes given by 'Imports' based on 2691 // JavaImportGroups, then adding the necessary replacement to 'Replaces'. 2692 // Import declarations with the same text will be deduplicated. Between each 2693 // import group, a newline is inserted, and within each import group, a 2694 // lexicographic sort based on ASCII value is performed. 2695 static void sortJavaImports(const FormatStyle &Style, 2696 const SmallVectorImpl<JavaImportDirective> &Imports, 2697 ArrayRef<tooling::Range> Ranges, StringRef FileName, 2698 StringRef Code, tooling::Replacements &Replaces) { 2699 unsigned ImportsBeginOffset = Imports.front().Offset; 2700 unsigned ImportsEndOffset = 2701 Imports.back().Offset + Imports.back().Text.size(); 2702 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset; 2703 if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset)) 2704 return; 2705 SmallVector<unsigned, 16> Indices; 2706 SmallVector<unsigned, 16> JavaImportGroups; 2707 for (unsigned i = 0, e = Imports.size(); i != e; ++i) { 2708 Indices.push_back(i); 2709 JavaImportGroups.push_back( 2710 findJavaImportGroup(Style, Imports[i].Identifier)); 2711 } 2712 bool StaticImportAfterNormalImport = 2713 Style.SortJavaStaticImport == FormatStyle::SJSIO_After; 2714 llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 2715 // Negating IsStatic to push static imports above non-static imports. 2716 return std::make_tuple(!Imports[LHSI].IsStatic ^ 2717 StaticImportAfterNormalImport, 2718 JavaImportGroups[LHSI], Imports[LHSI].Identifier) < 2719 std::make_tuple(!Imports[RHSI].IsStatic ^ 2720 StaticImportAfterNormalImport, 2721 JavaImportGroups[RHSI], Imports[RHSI].Identifier); 2722 }); 2723 2724 // Deduplicate imports. 2725 Indices.erase(std::unique(Indices.begin(), Indices.end(), 2726 [&](unsigned LHSI, unsigned RHSI) { 2727 return Imports[LHSI].Text == Imports[RHSI].Text; 2728 }), 2729 Indices.end()); 2730 2731 bool CurrentIsStatic = Imports[Indices.front()].IsStatic; 2732 unsigned CurrentImportGroup = JavaImportGroups[Indices.front()]; 2733 2734 std::string result; 2735 for (unsigned Index : Indices) { 2736 if (!result.empty()) { 2737 result += "\n"; 2738 if (CurrentIsStatic != Imports[Index].IsStatic || 2739 CurrentImportGroup != JavaImportGroups[Index]) 2740 result += "\n"; 2741 } 2742 for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) { 2743 result += CommentLine; 2744 result += "\n"; 2745 } 2746 result += Imports[Index].Text; 2747 CurrentIsStatic = Imports[Index].IsStatic; 2748 CurrentImportGroup = JavaImportGroups[Index]; 2749 } 2750 2751 // If the imports are out of order, we generate a single replacement fixing 2752 // the entire block. Otherwise, no replacement is generated. 2753 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 2754 Imports.front().Offset, ImportsBlockSize)))) 2755 return; 2756 2757 auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset, 2758 ImportsBlockSize, result)); 2759 // FIXME: better error handling. For now, just skip the replacement for the 2760 // release version. 2761 if (Err) { 2762 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 2763 assert(false); 2764 } 2765 } 2766 2767 namespace { 2768 2769 const char JavaImportRegexPattern[] = 2770 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;"; 2771 2772 } // anonymous namespace 2773 2774 tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code, 2775 ArrayRef<tooling::Range> Ranges, 2776 StringRef FileName, 2777 tooling::Replacements &Replaces) { 2778 unsigned Prev = 0; 2779 unsigned SearchFrom = 0; 2780 llvm::Regex ImportRegex(JavaImportRegexPattern); 2781 SmallVector<StringRef, 4> Matches; 2782 SmallVector<JavaImportDirective, 16> ImportsInBlock; 2783 std::vector<StringRef> AssociatedCommentLines; 2784 2785 bool FormattingOff = false; 2786 2787 for (;;) { 2788 auto Pos = Code.find('\n', SearchFrom); 2789 StringRef Line = 2790 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 2791 2792 StringRef Trimmed = Line.trim(); 2793 if (Trimmed == "// clang-format off") 2794 FormattingOff = true; 2795 else if (Trimmed == "// clang-format on") 2796 FormattingOff = false; 2797 2798 if (ImportRegex.match(Line, &Matches)) { 2799 if (FormattingOff) { 2800 // If at least one import line has formatting turned off, turn off 2801 // formatting entirely. 2802 return Replaces; 2803 } 2804 StringRef Static = Matches[1]; 2805 StringRef Identifier = Matches[2]; 2806 bool IsStatic = false; 2807 if (Static.contains("static")) { 2808 IsStatic = true; 2809 } 2810 ImportsInBlock.push_back( 2811 {Identifier, Line, Prev, AssociatedCommentLines, IsStatic}); 2812 AssociatedCommentLines.clear(); 2813 } else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) { 2814 // Associating comments within the imports with the nearest import below 2815 AssociatedCommentLines.push_back(Line); 2816 } 2817 Prev = Pos + 1; 2818 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 2819 break; 2820 SearchFrom = Pos + 1; 2821 } 2822 if (!ImportsInBlock.empty()) 2823 sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces); 2824 return Replaces; 2825 } 2826 2827 bool isMpegTS(StringRef Code) { 2828 // MPEG transport streams use the ".ts" file extension. clang-format should 2829 // not attempt to format those. MPEG TS' frame format starts with 0x47 every 2830 // 189 bytes - detect that and return. 2831 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47; 2832 } 2833 2834 bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); } 2835 2836 tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, 2837 ArrayRef<tooling::Range> Ranges, 2838 StringRef FileName, unsigned *Cursor) { 2839 tooling::Replacements Replaces; 2840 if (!Style.SortIncludes || Style.DisableFormat) 2841 return Replaces; 2842 if (isLikelyXml(Code)) 2843 return Replaces; 2844 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript && 2845 isMpegTS(Code)) 2846 return Replaces; 2847 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript) 2848 return sortJavaScriptImports(Style, Code, Ranges, FileName); 2849 if (Style.Language == FormatStyle::LanguageKind::LK_Java) 2850 return sortJavaImports(Style, Code, Ranges, FileName, Replaces); 2851 sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor); 2852 return Replaces; 2853 } 2854 2855 template <typename T> 2856 static llvm::Expected<tooling::Replacements> 2857 processReplacements(T ProcessFunc, StringRef Code, 2858 const tooling::Replacements &Replaces, 2859 const FormatStyle &Style) { 2860 if (Replaces.empty()) 2861 return tooling::Replacements(); 2862 2863 auto NewCode = applyAllReplacements(Code, Replaces); 2864 if (!NewCode) 2865 return NewCode.takeError(); 2866 std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges(); 2867 StringRef FileName = Replaces.begin()->getFilePath(); 2868 2869 tooling::Replacements FormatReplaces = 2870 ProcessFunc(Style, *NewCode, ChangedRanges, FileName); 2871 2872 return Replaces.merge(FormatReplaces); 2873 } 2874 2875 llvm::Expected<tooling::Replacements> 2876 formatReplacements(StringRef Code, const tooling::Replacements &Replaces, 2877 const FormatStyle &Style) { 2878 // We need to use lambda function here since there are two versions of 2879 // `sortIncludes`. 2880 auto SortIncludes = [](const FormatStyle &Style, StringRef Code, 2881 std::vector<tooling::Range> Ranges, 2882 StringRef FileName) -> tooling::Replacements { 2883 return sortIncludes(Style, Code, Ranges, FileName); 2884 }; 2885 auto SortedReplaces = 2886 processReplacements(SortIncludes, Code, Replaces, Style); 2887 if (!SortedReplaces) 2888 return SortedReplaces.takeError(); 2889 2890 // We need to use lambda function here since there are two versions of 2891 // `reformat`. 2892 auto Reformat = [](const FormatStyle &Style, StringRef Code, 2893 std::vector<tooling::Range> Ranges, 2894 StringRef FileName) -> tooling::Replacements { 2895 return reformat(Style, Code, Ranges, FileName); 2896 }; 2897 return processReplacements(Reformat, Code, *SortedReplaces, Style); 2898 } 2899 2900 namespace { 2901 2902 inline bool isHeaderInsertion(const tooling::Replacement &Replace) { 2903 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 && 2904 llvm::Regex(CppIncludeRegexPattern) 2905 .match(Replace.getReplacementText()); 2906 } 2907 2908 inline bool isHeaderDeletion(const tooling::Replacement &Replace) { 2909 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1; 2910 } 2911 2912 // FIXME: insert empty lines between newly created blocks. 2913 tooling::Replacements 2914 fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces, 2915 const FormatStyle &Style) { 2916 if (!Style.isCpp()) 2917 return Replaces; 2918 2919 tooling::Replacements HeaderInsertions; 2920 std::set<llvm::StringRef> HeadersToDelete; 2921 tooling::Replacements Result; 2922 for (const auto &R : Replaces) { 2923 if (isHeaderInsertion(R)) { 2924 // Replacements from \p Replaces must be conflict-free already, so we can 2925 // simply consume the error. 2926 llvm::consumeError(HeaderInsertions.add(R)); 2927 } else if (isHeaderDeletion(R)) { 2928 HeadersToDelete.insert(R.getReplacementText()); 2929 } else if (R.getOffset() == UINT_MAX) { 2930 llvm::errs() << "Insertions other than header #include insertion are " 2931 "not supported! " 2932 << R.getReplacementText() << "\n"; 2933 } else { 2934 llvm::consumeError(Result.add(R)); 2935 } 2936 } 2937 if (HeaderInsertions.empty() && HeadersToDelete.empty()) 2938 return Replaces; 2939 2940 StringRef FileName = Replaces.begin()->getFilePath(); 2941 tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle); 2942 2943 for (const auto &Header : HeadersToDelete) { 2944 tooling::Replacements Replaces = 2945 Includes.remove(Header.trim("\"<>"), Header.startswith("<")); 2946 for (const auto &R : Replaces) { 2947 auto Err = Result.add(R); 2948 if (Err) { 2949 // Ignore the deletion on conflict. 2950 llvm::errs() << "Failed to add header deletion replacement for " 2951 << Header << ": " << llvm::toString(std::move(Err)) 2952 << "\n"; 2953 } 2954 } 2955 } 2956 2957 llvm::Regex IncludeRegex = llvm::Regex(CppIncludeRegexPattern); 2958 llvm::SmallVector<StringRef, 4> Matches; 2959 for (const auto &R : HeaderInsertions) { 2960 auto IncludeDirective = R.getReplacementText(); 2961 bool Matched = IncludeRegex.match(IncludeDirective, &Matches); 2962 assert(Matched && "Header insertion replacement must have replacement text " 2963 "'#include ...'"); 2964 (void)Matched; 2965 auto IncludeName = Matches[2]; 2966 auto Replace = 2967 Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<")); 2968 if (Replace) { 2969 auto Err = Result.add(*Replace); 2970 if (Err) { 2971 llvm::consumeError(std::move(Err)); 2972 unsigned NewOffset = 2973 Result.getShiftedCodePosition(Replace->getOffset()); 2974 auto Shifted = tooling::Replacement(FileName, NewOffset, 0, 2975 Replace->getReplacementText()); 2976 Result = Result.merge(tooling::Replacements(Shifted)); 2977 } 2978 } 2979 } 2980 return Result; 2981 } 2982 2983 } // anonymous namespace 2984 2985 llvm::Expected<tooling::Replacements> 2986 cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, 2987 const FormatStyle &Style) { 2988 // We need to use lambda function here since there are two versions of 2989 // `cleanup`. 2990 auto Cleanup = [](const FormatStyle &Style, StringRef Code, 2991 std::vector<tooling::Range> Ranges, 2992 StringRef FileName) -> tooling::Replacements { 2993 return cleanup(Style, Code, Ranges, FileName); 2994 }; 2995 // Make header insertion replacements insert new headers into correct blocks. 2996 tooling::Replacements NewReplaces = 2997 fixCppIncludeInsertions(Code, Replaces, Style); 2998 return processReplacements(Cleanup, Code, NewReplaces, Style); 2999 } 3000 3001 namespace internal { 3002 std::pair<tooling::Replacements, unsigned> 3003 reformat(const FormatStyle &Style, StringRef Code, 3004 ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn, 3005 unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName, 3006 FormattingAttemptStatus *Status) { 3007 FormatStyle Expanded = Style; 3008 expandPresetsBraceWrapping(Expanded); 3009 expandPresetsSpaceBeforeParens(Expanded); 3010 if (Expanded.DisableFormat) 3011 return {tooling::Replacements(), 0}; 3012 if (isLikelyXml(Code)) 3013 return {tooling::Replacements(), 0}; 3014 if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code)) 3015 return {tooling::Replacements(), 0}; 3016 3017 // JSON only needs the formatting passing. 3018 if (Style.isJson()) { 3019 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); 3020 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn, 3021 NextStartColumn, LastStartColumn); 3022 if (!Env) 3023 return {}; 3024 // Perform the actual formatting pass. 3025 tooling::Replacements Replaces = 3026 Formatter(*Env, Style, Status).process().first; 3027 // add a replacement to remove the "x = " from the result. 3028 if (!Replaces.add(tooling::Replacement(FileName, 0, 4, ""))) { 3029 // apply the reformatting changes and the removal of "x = ". 3030 if (applyAllReplacements(Code, Replaces)) { 3031 return {Replaces, 0}; 3032 } 3033 } 3034 return {tooling::Replacements(), 0}; 3035 } 3036 3037 typedef std::function<std::pair<tooling::Replacements, unsigned>( 3038 const Environment &)> 3039 AnalyzerPass; 3040 SmallVector<AnalyzerPass, 4> Passes; 3041 3042 if (Style.isCpp() && Style.QualifierAlignment != FormatStyle::QAS_Leave) { 3043 Passes.emplace_back([&](const Environment &Env) { 3044 return QualifierAlignmentFixer(Env, Expanded, Code, Ranges, 3045 FirstStartColumn, NextStartColumn, 3046 LastStartColumn, FileName) 3047 .process(); 3048 }); 3049 } 3050 3051 if (Style.Language == FormatStyle::LK_Cpp) { 3052 if (Style.FixNamespaceComments) 3053 Passes.emplace_back([&](const Environment &Env) { 3054 return NamespaceEndCommentsFixer(Env, Expanded).process(); 3055 }); 3056 3057 if (Style.SortUsingDeclarations) 3058 Passes.emplace_back([&](const Environment &Env) { 3059 return UsingDeclarationsSorter(Env, Expanded).process(); 3060 }); 3061 } 3062 3063 if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) 3064 Passes.emplace_back([&](const Environment &Env) { 3065 return DefinitionBlockSeparator(Env, Expanded).process(); 3066 }); 3067 3068 if (Style.isJavaScript() && Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) 3069 Passes.emplace_back([&](const Environment &Env) { 3070 return JavaScriptRequoter(Env, Expanded).process(); 3071 }); 3072 3073 Passes.emplace_back([&](const Environment &Env) { 3074 return Formatter(Env, Expanded, Status).process(); 3075 }); 3076 3077 if (Style.isJavaScript() && 3078 Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) 3079 Passes.emplace_back([&](const Environment &Env) { 3080 return TrailingCommaInserter(Env, Expanded).process(); 3081 }); 3082 3083 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn, 3084 NextStartColumn, LastStartColumn); 3085 if (!Env) 3086 return {}; 3087 llvm::Optional<std::string> CurrentCode = None; 3088 tooling::Replacements Fixes; 3089 unsigned Penalty = 0; 3090 for (size_t I = 0, E = Passes.size(); I < E; ++I) { 3091 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env); 3092 auto NewCode = applyAllReplacements( 3093 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first); 3094 if (NewCode) { 3095 Fixes = Fixes.merge(PassFixes.first); 3096 Penalty += PassFixes.second; 3097 if (I + 1 < E) { 3098 CurrentCode = std::move(*NewCode); 3099 Env = Environment::make( 3100 *CurrentCode, FileName, 3101 tooling::calculateRangesAfterReplacements(Fixes, Ranges), 3102 FirstStartColumn, NextStartColumn, LastStartColumn); 3103 if (!Env) 3104 return {}; 3105 } 3106 } 3107 } 3108 3109 return {Fixes, Penalty}; 3110 } 3111 } // namespace internal 3112 3113 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 3114 ArrayRef<tooling::Range> Ranges, 3115 StringRef FileName, 3116 FormattingAttemptStatus *Status) { 3117 return internal::reformat(Style, Code, Ranges, 3118 /*FirstStartColumn=*/0, 3119 /*NextStartColumn=*/0, 3120 /*LastStartColumn=*/0, FileName, Status) 3121 .first; 3122 } 3123 3124 tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, 3125 ArrayRef<tooling::Range> Ranges, 3126 StringRef FileName) { 3127 // cleanups only apply to C++ (they mostly concern ctor commas etc.) 3128 if (Style.Language != FormatStyle::LK_Cpp) 3129 return tooling::Replacements(); 3130 auto Env = Environment::make(Code, FileName, Ranges); 3131 if (!Env) 3132 return {}; 3133 return Cleaner(*Env, Style).process().first; 3134 } 3135 3136 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 3137 ArrayRef<tooling::Range> Ranges, 3138 StringRef FileName, bool *IncompleteFormat) { 3139 FormattingAttemptStatus Status; 3140 auto Result = reformat(Style, Code, Ranges, FileName, &Status); 3141 if (!Status.FormatComplete) 3142 *IncompleteFormat = true; 3143 return Result; 3144 } 3145 3146 tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, 3147 StringRef Code, 3148 ArrayRef<tooling::Range> Ranges, 3149 StringRef FileName) { 3150 auto Env = Environment::make(Code, FileName, Ranges); 3151 if (!Env) 3152 return {}; 3153 return NamespaceEndCommentsFixer(*Env, Style).process().first; 3154 } 3155 3156 tooling::Replacements separateDefinitionBlocks(const FormatStyle &Style, 3157 StringRef Code, 3158 ArrayRef<tooling::Range> Ranges, 3159 StringRef FileName) { 3160 auto Env = Environment::make(Code, FileName, Ranges); 3161 if (!Env) 3162 return {}; 3163 return DefinitionBlockSeparator(*Env, Style).process().first; 3164 } 3165 3166 tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, 3167 StringRef Code, 3168 ArrayRef<tooling::Range> Ranges, 3169 StringRef FileName) { 3170 auto Env = Environment::make(Code, FileName, Ranges); 3171 if (!Env) 3172 return {}; 3173 return UsingDeclarationsSorter(*Env, Style).process().first; 3174 } 3175 3176 LangOptions getFormattingLangOpts(const FormatStyle &Style) { 3177 LangOptions LangOpts; 3178 3179 FormatStyle::LanguageStandard LexingStd = Style.Standard; 3180 if (LexingStd == FormatStyle::LS_Auto) 3181 LexingStd = FormatStyle::LS_Latest; 3182 if (LexingStd == FormatStyle::LS_Latest) 3183 LexingStd = FormatStyle::LS_Cpp20; 3184 LangOpts.CPlusPlus = 1; 3185 LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11; 3186 LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14; 3187 LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17; 3188 LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20; 3189 LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20; 3190 3191 LangOpts.LineComment = 1; 3192 bool AlternativeOperators = Style.isCpp(); 3193 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0; 3194 LangOpts.Bool = 1; 3195 LangOpts.ObjC = 1; 3196 LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally. 3197 LangOpts.DeclSpecKeyword = 1; // To get __declspec. 3198 LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict. 3199 return LangOpts; 3200 } 3201 3202 const char *StyleOptionHelpDescription = 3203 "Coding style, currently supports:\n" 3204 " LLVM, GNU, Google, Chromium, Microsoft, Mozilla, WebKit.\n" 3205 "Use -style=file to load style configuration from\n" 3206 ".clang-format file located in one of the parent\n" 3207 "directories of the source file (or current\n" 3208 "directory for stdin).\n" 3209 "Use -style=file:<format_file_path> to explicitly specify" 3210 "the configuration file.\n" 3211 "Use -style=\"{key: value, ...}\" to set specific\n" 3212 "parameters, e.g.:\n" 3213 " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""; 3214 3215 static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) { 3216 if (FileName.endswith(".java")) 3217 return FormatStyle::LK_Java; 3218 if (FileName.endswith_insensitive(".js") || 3219 FileName.endswith_insensitive(".mjs") || 3220 FileName.endswith_insensitive(".ts")) 3221 return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript. 3222 if (FileName.endswith(".m") || FileName.endswith(".mm")) 3223 return FormatStyle::LK_ObjC; 3224 if (FileName.endswith_insensitive(".proto") || 3225 FileName.endswith_insensitive(".protodevel")) 3226 return FormatStyle::LK_Proto; 3227 if (FileName.endswith_insensitive(".textpb") || 3228 FileName.endswith_insensitive(".pb.txt") || 3229 FileName.endswith_insensitive(".textproto") || 3230 FileName.endswith_insensitive(".asciipb")) 3231 return FormatStyle::LK_TextProto; 3232 if (FileName.endswith_insensitive(".td")) 3233 return FormatStyle::LK_TableGen; 3234 if (FileName.endswith_insensitive(".cs")) 3235 return FormatStyle::LK_CSharp; 3236 if (FileName.endswith_insensitive(".json")) 3237 return FormatStyle::LK_Json; 3238 return FormatStyle::LK_Cpp; 3239 } 3240 3241 FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) { 3242 const auto GuessedLanguage = getLanguageByFileName(FileName); 3243 if (GuessedLanguage == FormatStyle::LK_Cpp) { 3244 auto Extension = llvm::sys::path::extension(FileName); 3245 // If there's no file extension (or it's .h), we need to check the contents 3246 // of the code to see if it contains Objective-C. 3247 if (Extension.empty() || Extension == ".h") { 3248 auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName; 3249 Environment Env(Code, NonEmptyFileName, /*Ranges=*/{}); 3250 ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle()); 3251 Guesser.process(); 3252 if (Guesser.isObjC()) 3253 return FormatStyle::LK_ObjC; 3254 } 3255 } 3256 return GuessedLanguage; 3257 } 3258 3259 const char *DefaultFormatStyle = "file"; 3260 3261 const char *DefaultFallbackStyle = "LLVM"; 3262 3263 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> 3264 loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS, 3265 FormatStyle *Style, bool AllowUnknownOptions) { 3266 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 3267 FS->getBufferForFile(ConfigFile.str()); 3268 if (auto EC = Text.getError()) 3269 return EC; 3270 if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions)) 3271 return EC; 3272 return Text; 3273 } 3274 3275 llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, 3276 StringRef FallbackStyleName, 3277 StringRef Code, llvm::vfs::FileSystem *FS, 3278 bool AllowUnknownOptions) { 3279 if (!FS) { 3280 FS = llvm::vfs::getRealFileSystem().get(); 3281 } 3282 FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code)); 3283 3284 FormatStyle FallbackStyle = getNoStyle(); 3285 if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle)) 3286 return make_string_error("Invalid fallback style \"" + FallbackStyleName); 3287 3288 llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1> 3289 ChildFormatTextToApply; 3290 3291 if (StyleName.startswith("{")) { 3292 // Parse YAML/JSON style from the command line. 3293 StringRef Source = "<command-line>"; 3294 if (std::error_code ec = 3295 parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style, 3296 AllowUnknownOptions)) 3297 return make_string_error("Error parsing -style: " + ec.message()); 3298 if (Style.InheritsParentConfig) 3299 ChildFormatTextToApply.emplace_back( 3300 llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false)); 3301 else 3302 return Style; 3303 } 3304 3305 // User provided clang-format file using -style=file:path/to/format/file. 3306 if (!Style.InheritsParentConfig && 3307 StyleName.startswith_insensitive("file:")) { 3308 auto ConfigFile = StyleName.substr(5); 3309 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 3310 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions); 3311 if (auto EC = Text.getError()) 3312 return make_string_error("Error reading " + ConfigFile + ": " + 3313 EC.message()); 3314 3315 LLVM_DEBUG(llvm::dbgs() 3316 << "Using configuration file " << ConfigFile << "\n"); 3317 3318 if (!Style.InheritsParentConfig) 3319 return Style; 3320 3321 // Search for parent configs starting from the parent directory of 3322 // ConfigFile. 3323 FileName = ConfigFile; 3324 ChildFormatTextToApply.emplace_back(std::move(*Text)); 3325 } 3326 3327 // If the style inherits the parent configuration it is a command line 3328 // configuration, which wants to inherit, so we have to skip the check of the 3329 // StyleName. 3330 if (!Style.InheritsParentConfig && !StyleName.equals_insensitive("file")) { 3331 if (!getPredefinedStyle(StyleName, Style.Language, &Style)) 3332 return make_string_error("Invalid value for -style"); 3333 if (!Style.InheritsParentConfig) 3334 return Style; 3335 } 3336 3337 // Reset possible inheritance 3338 Style.InheritsParentConfig = false; 3339 3340 // Look for .clang-format/_clang-format file in the file's parent directories. 3341 SmallString<128> UnsuitableConfigFiles; 3342 SmallString<128> Path(FileName); 3343 if (std::error_code EC = FS->makeAbsolute(Path)) 3344 return make_string_error(EC.message()); 3345 3346 llvm::SmallVector<std::string, 2> FilesToLookFor; 3347 FilesToLookFor.push_back(".clang-format"); 3348 FilesToLookFor.push_back("_clang-format"); 3349 3350 auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {}; 3351 3352 auto applyChildFormatTexts = [&](FormatStyle *Style) { 3353 for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) { 3354 auto EC = parseConfiguration(*MemBuf, Style, AllowUnknownOptions, 3355 dropDiagnosticHandler); 3356 // It was already correctly parsed. 3357 assert(!EC); 3358 static_cast<void>(EC); 3359 } 3360 }; 3361 3362 for (StringRef Directory = Path; !Directory.empty(); 3363 Directory = llvm::sys::path::parent_path(Directory)) { 3364 3365 auto Status = FS->status(Directory); 3366 if (!Status || 3367 Status->getType() != llvm::sys::fs::file_type::directory_file) { 3368 continue; 3369 } 3370 3371 for (const auto &F : FilesToLookFor) { 3372 SmallString<128> ConfigFile(Directory); 3373 3374 llvm::sys::path::append(ConfigFile, F); 3375 LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); 3376 3377 Status = FS->status(ConfigFile.str()); 3378 3379 if (Status && 3380 (Status->getType() == llvm::sys::fs::file_type::regular_file)) { 3381 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 3382 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions); 3383 if (auto EC = Text.getError()) { 3384 if (EC == ParseError::Unsuitable) { 3385 if (!UnsuitableConfigFiles.empty()) 3386 UnsuitableConfigFiles.append(", "); 3387 UnsuitableConfigFiles.append(ConfigFile); 3388 continue; 3389 } 3390 return make_string_error("Error reading " + ConfigFile + ": " + 3391 EC.message()); 3392 } 3393 LLVM_DEBUG(llvm::dbgs() 3394 << "Using configuration file " << ConfigFile << "\n"); 3395 3396 if (!Style.InheritsParentConfig) { 3397 if (ChildFormatTextToApply.empty()) 3398 return Style; 3399 3400 LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n"); 3401 applyChildFormatTexts(&Style); 3402 3403 return Style; 3404 } 3405 3406 LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n"); 3407 3408 // Reset inheritance of style 3409 Style.InheritsParentConfig = false; 3410 3411 ChildFormatTextToApply.emplace_back(std::move(*Text)); 3412 3413 // Breaking out of the inner loop, since we don't want to parse 3414 // .clang-format AND _clang-format, if both exist. Then we continue the 3415 // inner loop (parent directories) in search for the parent 3416 // configuration. 3417 break; 3418 } 3419 } 3420 } 3421 if (!UnsuitableConfigFiles.empty()) 3422 return make_string_error("Configuration file(s) do(es) not support " + 3423 getLanguageName(Style.Language) + ": " + 3424 UnsuitableConfigFiles); 3425 3426 if (!ChildFormatTextToApply.empty()) { 3427 LLVM_DEBUG(llvm::dbgs() 3428 << "Applying child configurations on fallback style\n"); 3429 applyChildFormatTexts(&FallbackStyle); 3430 } 3431 3432 return FallbackStyle; 3433 } 3434 3435 } // namespace format 3436 } // namespace clang 3437