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