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->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) { 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 = 1951 Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd(); 1952 bool SpaceAfter = Tok->Next->WhitespaceRange.getBegin() != 1953 Tok->Next->WhitespaceRange.getEnd(); 1954 if (SpaceBefore && !SpaceAfter) 1955 ++AlignmentDiff; 1956 if (!SpaceBefore && SpaceAfter) 1957 --AlignmentDiff; 1958 } 1959 } 1960 return AlignmentDiff; 1961 } 1962 1963 void 1964 deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 1965 bool HasBinPackedFunction = false; 1966 bool HasOnePerLineFunction = false; 1967 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1968 if (!AnnotatedLines[i]->First->Next) 1969 continue; 1970 FormatToken *Tok = AnnotatedLines[i]->First->Next; 1971 while (Tok->Next) { 1972 if (Tok->is(PPK_BinPacked)) 1973 HasBinPackedFunction = true; 1974 if (Tok->is(PPK_OnePerLine)) 1975 HasOnePerLineFunction = true; 1976 1977 Tok = Tok->Next; 1978 } 1979 } 1980 if (Style.DerivePointerAlignment) { 1981 Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0 1982 ? FormatStyle::PAS_Left 1983 : FormatStyle::PAS_Right; 1984 Style.ReferenceAlignment = FormatStyle::RAS_Pointer; 1985 } 1986 if (Style.Standard == FormatStyle::LS_Auto) 1987 Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines) 1988 ? FormatStyle::LS_Latest 1989 : FormatStyle::LS_Cpp03; 1990 BinPackInconclusiveFunctions = 1991 HasBinPackedFunction || !HasOnePerLineFunction; 1992 } 1993 1994 bool BinPackInconclusiveFunctions; 1995 FormattingAttemptStatus *Status; 1996 }; 1997 1998 /// TrailingCommaInserter inserts trailing commas into container literals. 1999 /// E.g.: 2000 /// const x = [ 2001 /// 1, 2002 /// ]; 2003 /// TrailingCommaInserter runs after formatting. To avoid causing a required 2004 /// reformatting (and thus reflow), it never inserts a comma that'd exceed the 2005 /// ColumnLimit. 2006 /// 2007 /// Because trailing commas disable binpacking of arrays, TrailingCommaInserter 2008 /// is conceptually incompatible with bin packing. 2009 class TrailingCommaInserter : public TokenAnalyzer { 2010 public: 2011 TrailingCommaInserter(const Environment &Env, const FormatStyle &Style) 2012 : TokenAnalyzer(Env, Style) {} 2013 2014 std::pair<tooling::Replacements, unsigned> 2015 analyze(TokenAnnotator &Annotator, 2016 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2017 FormatTokenLexer &Tokens) override { 2018 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2019 tooling::Replacements Result; 2020 insertTrailingCommas(AnnotatedLines, Result); 2021 return {Result, 0}; 2022 } 2023 2024 private: 2025 /// Inserts trailing commas in [] and {} initializers if they wrap over 2026 /// multiple lines. 2027 void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines, 2028 tooling::Replacements &Result) { 2029 for (AnnotatedLine *Line : Lines) { 2030 insertTrailingCommas(Line->Children, Result); 2031 if (!Line->Affected) 2032 continue; 2033 for (FormatToken *FormatTok = Line->First; FormatTok; 2034 FormatTok = FormatTok->Next) { 2035 if (FormatTok->NewlinesBefore == 0) 2036 continue; 2037 FormatToken *Matching = FormatTok->MatchingParen; 2038 if (!Matching || !FormatTok->getPreviousNonComment()) 2039 continue; 2040 if (!(FormatTok->is(tok::r_square) && 2041 Matching->is(TT_ArrayInitializerLSquare)) && 2042 !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) 2043 continue; 2044 FormatToken *Prev = FormatTok->getPreviousNonComment(); 2045 if (Prev->is(tok::comma) || Prev->is(tok::semi)) 2046 continue; 2047 // getEndLoc is not reliably set during re-lexing, use text length 2048 // instead. 2049 SourceLocation Start = 2050 Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size()); 2051 // If inserting a comma would push the code over the column limit, skip 2052 // this location - it'd introduce an unstable formatting due to the 2053 // required reflow. 2054 unsigned ColumnNumber = 2055 Env.getSourceManager().getSpellingColumnNumber(Start); 2056 if (ColumnNumber > Style.ColumnLimit) 2057 continue; 2058 // Comma insertions cannot conflict with each other, and this pass has a 2059 // clean set of Replacements, so the operation below cannot fail. 2060 cantFail(Result.add( 2061 tooling::Replacement(Env.getSourceManager(), Start, 0, ","))); 2062 } 2063 } 2064 } 2065 }; 2066 2067 // This class clean up the erroneous/redundant code around the given ranges in 2068 // file. 2069 class Cleaner : public TokenAnalyzer { 2070 public: 2071 Cleaner(const Environment &Env, const FormatStyle &Style) 2072 : TokenAnalyzer(Env, Style), 2073 DeletedTokens(FormatTokenLess(Env.getSourceManager())) {} 2074 2075 // FIXME: eliminate unused parameters. 2076 std::pair<tooling::Replacements, unsigned> 2077 analyze(TokenAnnotator &Annotator, 2078 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2079 FormatTokenLexer &Tokens) override { 2080 // FIXME: in the current implementation the granularity of affected range 2081 // is an annotated line. However, this is not sufficient. Furthermore, 2082 // redundant code introduced by replacements does not necessarily 2083 // intercept with ranges of replacements that result in the redundancy. 2084 // To determine if some redundant code is actually introduced by 2085 // replacements(e.g. deletions), we need to come up with a more 2086 // sophisticated way of computing affected ranges. 2087 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2088 2089 checkEmptyNamespace(AnnotatedLines); 2090 2091 for (auto *Line : AnnotatedLines) 2092 cleanupLine(Line); 2093 2094 return {generateFixes(), 0}; 2095 } 2096 2097 private: 2098 void cleanupLine(AnnotatedLine *Line) { 2099 for (auto *Child : Line->Children) { 2100 cleanupLine(Child); 2101 } 2102 2103 if (Line->Affected) { 2104 cleanupRight(Line->First, tok::comma, tok::comma); 2105 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma); 2106 cleanupRight(Line->First, tok::l_paren, tok::comma); 2107 cleanupLeft(Line->First, tok::comma, tok::r_paren); 2108 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace); 2109 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace); 2110 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal); 2111 } 2112 } 2113 2114 bool containsOnlyComments(const AnnotatedLine &Line) { 2115 for (FormatToken *Tok = Line.First; Tok != nullptr; Tok = Tok->Next) { 2116 if (Tok->isNot(tok::comment)) 2117 return false; 2118 } 2119 return true; 2120 } 2121 2122 // Iterate through all lines and remove any empty (nested) namespaces. 2123 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 2124 std::set<unsigned> DeletedLines; 2125 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 2126 auto &Line = *AnnotatedLines[i]; 2127 if (Line.startsWithNamespace()) { 2128 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines); 2129 } 2130 } 2131 2132 for (auto Line : DeletedLines) { 2133 FormatToken *Tok = AnnotatedLines[Line]->First; 2134 while (Tok) { 2135 deleteToken(Tok); 2136 Tok = Tok->Next; 2137 } 2138 } 2139 } 2140 2141 // The function checks if the namespace, which starts from \p CurrentLine, and 2142 // its nested namespaces are empty and delete them if they are empty. It also 2143 // sets \p NewLine to the last line checked. 2144 // Returns true if the current namespace is empty. 2145 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2146 unsigned CurrentLine, unsigned &NewLine, 2147 std::set<unsigned> &DeletedLines) { 2148 unsigned InitLine = CurrentLine, End = AnnotatedLines.size(); 2149 if (Style.BraceWrapping.AfterNamespace) { 2150 // If the left brace is in a new line, we should consume it first so that 2151 // it does not make the namespace non-empty. 2152 // FIXME: error handling if there is no left brace. 2153 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) { 2154 NewLine = CurrentLine; 2155 return false; 2156 } 2157 } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) { 2158 return false; 2159 } 2160 while (++CurrentLine < End) { 2161 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace)) 2162 break; 2163 2164 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) { 2165 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine, 2166 DeletedLines)) 2167 return false; 2168 CurrentLine = NewLine; 2169 continue; 2170 } 2171 2172 if (containsOnlyComments(*AnnotatedLines[CurrentLine])) 2173 continue; 2174 2175 // If there is anything other than comments or nested namespaces in the 2176 // current namespace, the namespace cannot be empty. 2177 NewLine = CurrentLine; 2178 return false; 2179 } 2180 2181 NewLine = CurrentLine; 2182 if (CurrentLine >= End) 2183 return false; 2184 2185 // Check if the empty namespace is actually affected by changed ranges. 2186 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange( 2187 AnnotatedLines[InitLine]->First->Tok.getLocation(), 2188 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) 2189 return false; 2190 2191 for (unsigned i = InitLine; i <= CurrentLine; ++i) { 2192 DeletedLines.insert(i); 2193 } 2194 2195 return true; 2196 } 2197 2198 // Checks pairs {start, start->next},..., {end->previous, end} and deletes one 2199 // of the token in the pair if the left token has \p LK token kind and the 2200 // right token has \p RK token kind. If \p DeleteLeft is true, the left token 2201 // is deleted on match; otherwise, the right token is deleted. 2202 template <typename LeftKind, typename RightKind> 2203 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK, 2204 bool DeleteLeft) { 2205 auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * { 2206 for (auto *Res = Tok.Next; Res; Res = Res->Next) 2207 if (!Res->is(tok::comment) && 2208 DeletedTokens.find(Res) == DeletedTokens.end()) 2209 return Res; 2210 return nullptr; 2211 }; 2212 for (auto *Left = Start; Left;) { 2213 auto *Right = NextNotDeleted(*Left); 2214 if (!Right) 2215 break; 2216 if (Left->is(LK) && Right->is(RK)) { 2217 deleteToken(DeleteLeft ? Left : Right); 2218 for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next) 2219 deleteToken(Tok); 2220 // If the right token is deleted, we should keep the left token 2221 // unchanged and pair it with the new right token. 2222 if (!DeleteLeft) 2223 continue; 2224 } 2225 Left = Right; 2226 } 2227 } 2228 2229 template <typename LeftKind, typename RightKind> 2230 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) { 2231 cleanupPair(Start, LK, RK, /*DeleteLeft=*/true); 2232 } 2233 2234 template <typename LeftKind, typename RightKind> 2235 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) { 2236 cleanupPair(Start, LK, RK, /*DeleteLeft=*/false); 2237 } 2238 2239 // Delete the given token. 2240 inline void deleteToken(FormatToken *Tok) { 2241 if (Tok) 2242 DeletedTokens.insert(Tok); 2243 } 2244 2245 tooling::Replacements generateFixes() { 2246 tooling::Replacements Fixes; 2247 std::vector<FormatToken *> Tokens; 2248 std::copy(DeletedTokens.begin(), DeletedTokens.end(), 2249 std::back_inserter(Tokens)); 2250 2251 // Merge multiple continuous token deletions into one big deletion so that 2252 // the number of replacements can be reduced. This makes computing affected 2253 // ranges more efficient when we run reformat on the changed code. 2254 unsigned Idx = 0; 2255 while (Idx < Tokens.size()) { 2256 unsigned St = Idx, End = Idx; 2257 while ((End + 1) < Tokens.size() && 2258 Tokens[End]->Next == Tokens[End + 1]) { 2259 ++End; 2260 } 2261 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(), 2262 Tokens[End]->Tok.getEndLoc()); 2263 auto Err = 2264 Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, "")); 2265 // FIXME: better error handling. for now just print error message and skip 2266 // for the release version. 2267 if (Err) { 2268 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 2269 assert(false && "Fixes must not conflict!"); 2270 } 2271 Idx = End + 1; 2272 } 2273 2274 return Fixes; 2275 } 2276 2277 // Class for less-than inequality comparason for the set `RedundantTokens`. 2278 // We store tokens in the order they appear in the translation unit so that 2279 // we do not need to sort them in `generateFixes()`. 2280 struct FormatTokenLess { 2281 FormatTokenLess(const SourceManager &SM) : SM(SM) {} 2282 2283 bool operator()(const FormatToken *LHS, const FormatToken *RHS) const { 2284 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(), 2285 RHS->Tok.getLocation()); 2286 } 2287 const SourceManager &SM; 2288 }; 2289 2290 // Tokens to be deleted. 2291 std::set<FormatToken *, FormatTokenLess> DeletedTokens; 2292 }; 2293 2294 class ObjCHeaderStyleGuesser : public TokenAnalyzer { 2295 public: 2296 ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style) 2297 : TokenAnalyzer(Env, Style), IsObjC(false) {} 2298 2299 std::pair<tooling::Replacements, unsigned> 2300 analyze(TokenAnnotator &Annotator, 2301 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2302 FormatTokenLexer &Tokens) override { 2303 assert(Style.Language == FormatStyle::LK_Cpp); 2304 IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines, 2305 Tokens.getKeywords()); 2306 tooling::Replacements Result; 2307 return {Result, 0}; 2308 } 2309 2310 bool isObjC() { return IsObjC; } 2311 2312 private: 2313 static bool 2314 guessIsObjC(const SourceManager &SourceManager, 2315 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2316 const AdditionalKeywords &Keywords) { 2317 // Keep this array sorted, since we are binary searching over it. 2318 static constexpr llvm::StringLiteral FoundationIdentifiers[] = { 2319 "CGFloat", 2320 "CGPoint", 2321 "CGPointMake", 2322 "CGPointZero", 2323 "CGRect", 2324 "CGRectEdge", 2325 "CGRectInfinite", 2326 "CGRectMake", 2327 "CGRectNull", 2328 "CGRectZero", 2329 "CGSize", 2330 "CGSizeMake", 2331 "CGVector", 2332 "CGVectorMake", 2333 "NSAffineTransform", 2334 "NSArray", 2335 "NSAttributedString", 2336 "NSBlockOperation", 2337 "NSBundle", 2338 "NSCache", 2339 "NSCalendar", 2340 "NSCharacterSet", 2341 "NSCountedSet", 2342 "NSData", 2343 "NSDataDetector", 2344 "NSDecimal", 2345 "NSDecimalNumber", 2346 "NSDictionary", 2347 "NSEdgeInsets", 2348 "NSHashTable", 2349 "NSIndexPath", 2350 "NSIndexSet", 2351 "NSInteger", 2352 "NSInvocationOperation", 2353 "NSLocale", 2354 "NSMapTable", 2355 "NSMutableArray", 2356 "NSMutableAttributedString", 2357 "NSMutableCharacterSet", 2358 "NSMutableData", 2359 "NSMutableDictionary", 2360 "NSMutableIndexSet", 2361 "NSMutableOrderedSet", 2362 "NSMutableSet", 2363 "NSMutableString", 2364 "NSNumber", 2365 "NSNumberFormatter", 2366 "NSObject", 2367 "NSOperation", 2368 "NSOperationQueue", 2369 "NSOperationQueuePriority", 2370 "NSOrderedSet", 2371 "NSPoint", 2372 "NSPointerArray", 2373 "NSQualityOfService", 2374 "NSRange", 2375 "NSRect", 2376 "NSRegularExpression", 2377 "NSSet", 2378 "NSSize", 2379 "NSString", 2380 "NSTimeZone", 2381 "NSUInteger", 2382 "NSURL", 2383 "NSURLComponents", 2384 "NSURLQueryItem", 2385 "NSUUID", 2386 "NSValue", 2387 "UIImage", 2388 "UIView", 2389 }; 2390 2391 for (auto Line : AnnotatedLines) { 2392 if (Line->First && (Line->First->TokenText.startswith("#") || 2393 Line->First->TokenText == "__pragma" || 2394 Line->First->TokenText == "_Pragma")) 2395 continue; 2396 for (const FormatToken *FormatTok = Line->First; FormatTok; 2397 FormatTok = FormatTok->Next) { 2398 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) && 2399 (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword || 2400 FormatTok->isOneOf(tok::numeric_constant, tok::l_square, 2401 tok::l_brace))) || 2402 (FormatTok->Tok.isAnyIdentifier() && 2403 std::binary_search(std::begin(FoundationIdentifiers), 2404 std::end(FoundationIdentifiers), 2405 FormatTok->TokenText)) || 2406 FormatTok->is(TT_ObjCStringLiteral) || 2407 FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM, 2408 Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace, 2409 TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn, 2410 TT_ObjCMethodExpr, TT_ObjCMethodSpecifier, 2411 TT_ObjCProperty)) { 2412 LLVM_DEBUG(llvm::dbgs() 2413 << "Detected ObjC at location " 2414 << FormatTok->Tok.getLocation().printToString( 2415 SourceManager) 2416 << " token: " << FormatTok->TokenText << " token type: " 2417 << getTokenTypeName(FormatTok->getType()) << "\n"); 2418 return true; 2419 } 2420 if (guessIsObjC(SourceManager, Line->Children, Keywords)) 2421 return true; 2422 } 2423 } 2424 return false; 2425 } 2426 2427 bool IsObjC; 2428 }; 2429 2430 struct IncludeDirective { 2431 StringRef Filename; 2432 StringRef Text; 2433 unsigned Offset; 2434 int Category; 2435 int Priority; 2436 }; 2437 2438 struct JavaImportDirective { 2439 StringRef Identifier; 2440 StringRef Text; 2441 unsigned Offset; 2442 std::vector<StringRef> AssociatedCommentLines; 2443 bool IsStatic; 2444 }; 2445 2446 } // end anonymous namespace 2447 2448 // Determines whether 'Ranges' intersects with ('Start', 'End'). 2449 static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start, 2450 unsigned End) { 2451 for (auto Range : Ranges) { 2452 if (Range.getOffset() < End && 2453 Range.getOffset() + Range.getLength() > Start) 2454 return true; 2455 } 2456 return false; 2457 } 2458 2459 // Returns a pair (Index, OffsetToEOL) describing the position of the cursor 2460 // before sorting/deduplicating. Index is the index of the include under the 2461 // cursor in the original set of includes. If this include has duplicates, it is 2462 // the index of the first of the duplicates as the others are going to be 2463 // removed. OffsetToEOL describes the cursor's position relative to the end of 2464 // its current line. 2465 // If `Cursor` is not on any #include, `Index` will be UINT_MAX. 2466 static std::pair<unsigned, unsigned> 2467 FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes, 2468 const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) { 2469 unsigned CursorIndex = UINT_MAX; 2470 unsigned OffsetToEOL = 0; 2471 for (int i = 0, e = Includes.size(); i != e; ++i) { 2472 unsigned Start = Includes[Indices[i]].Offset; 2473 unsigned End = Start + Includes[Indices[i]].Text.size(); 2474 if (!(Cursor >= Start && Cursor < End)) 2475 continue; 2476 CursorIndex = Indices[i]; 2477 OffsetToEOL = End - Cursor; 2478 // Put the cursor on the only remaining #include among the duplicate 2479 // #includes. 2480 while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text) 2481 CursorIndex = i; 2482 break; 2483 } 2484 return std::make_pair(CursorIndex, OffsetToEOL); 2485 } 2486 2487 // Replace all "\r\n" with "\n". 2488 std::string replaceCRLF(const std::string &Code) { 2489 std::string NewCode; 2490 size_t Pos = 0, LastPos = 0; 2491 2492 do { 2493 Pos = Code.find("\r\n", LastPos); 2494 if (Pos == LastPos) { 2495 ++LastPos; 2496 continue; 2497 } 2498 if (Pos == std::string::npos) { 2499 NewCode += Code.substr(LastPos); 2500 break; 2501 } 2502 NewCode += Code.substr(LastPos, Pos - LastPos) + "\n"; 2503 LastPos = Pos + 2; 2504 } while (Pos != std::string::npos); 2505 2506 return NewCode; 2507 } 2508 2509 // Sorts and deduplicate a block of includes given by 'Includes' alphabetically 2510 // adding the necessary replacement to 'Replaces'. 'Includes' must be in strict 2511 // source order. 2512 // #include directives with the same text will be deduplicated, and only the 2513 // first #include in the duplicate #includes remains. If the `Cursor` is 2514 // provided and put on a deleted #include, it will be moved to the remaining 2515 // #include in the duplicate #includes. 2516 static void sortCppIncludes(const FormatStyle &Style, 2517 const SmallVectorImpl<IncludeDirective> &Includes, 2518 ArrayRef<tooling::Range> Ranges, StringRef FileName, 2519 StringRef Code, tooling::Replacements &Replaces, 2520 unsigned *Cursor) { 2521 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 2522 unsigned IncludesBeginOffset = Includes.front().Offset; 2523 unsigned IncludesEndOffset = 2524 Includes.back().Offset + Includes.back().Text.size(); 2525 unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset; 2526 if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset)) 2527 return; 2528 SmallVector<unsigned, 16> Indices; 2529 for (unsigned i = 0, e = Includes.size(); i != e; ++i) { 2530 Indices.push_back(i); 2531 } 2532 2533 if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) { 2534 llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 2535 const auto LHSFilenameLower = Includes[LHSI].Filename.lower(); 2536 const auto RHSFilenameLower = Includes[RHSI].Filename.lower(); 2537 return std::tie(Includes[LHSI].Priority, LHSFilenameLower, 2538 Includes[LHSI].Filename) < 2539 std::tie(Includes[RHSI].Priority, RHSFilenameLower, 2540 Includes[RHSI].Filename); 2541 }); 2542 } else { 2543 llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 2544 return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) < 2545 std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename); 2546 }); 2547 } 2548 2549 // The index of the include on which the cursor will be put after 2550 // sorting/deduplicating. 2551 unsigned CursorIndex; 2552 // The offset from cursor to the end of line. 2553 unsigned CursorToEOLOffset; 2554 if (Cursor) 2555 std::tie(CursorIndex, CursorToEOLOffset) = 2556 FindCursorIndex(Includes, Indices, *Cursor); 2557 2558 // Deduplicate #includes. 2559 Indices.erase(std::unique(Indices.begin(), Indices.end(), 2560 [&](unsigned LHSI, unsigned RHSI) { 2561 return Includes[LHSI].Text.trim() == 2562 Includes[RHSI].Text.trim(); 2563 }), 2564 Indices.end()); 2565 2566 int CurrentCategory = Includes.front().Category; 2567 2568 // If the #includes are out of order, we generate a single replacement fixing 2569 // the entire block. Otherwise, no replacement is generated. 2570 // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not 2571 // enough as additional newlines might be added or removed across #include 2572 // blocks. This we handle below by generating the updated #imclude blocks and 2573 // comparing it to the original. 2574 if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) && 2575 Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) 2576 return; 2577 2578 std::string result; 2579 for (unsigned Index : Indices) { 2580 if (!result.empty()) { 2581 result += "\n"; 2582 if (Style.IncludeStyle.IncludeBlocks == 2583 tooling::IncludeStyle::IBS_Regroup && 2584 CurrentCategory != Includes[Index].Category) 2585 result += "\n"; 2586 } 2587 result += Includes[Index].Text; 2588 if (Cursor && CursorIndex == Index) 2589 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset; 2590 CurrentCategory = Includes[Index].Category; 2591 } 2592 2593 // If the #includes are out of order, we generate a single replacement fixing 2594 // the entire range of blocks. Otherwise, no replacement is generated. 2595 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 2596 IncludesBeginOffset, IncludesBlockSize)))) 2597 return; 2598 2599 auto Err = Replaces.add(tooling::Replacement( 2600 FileName, Includes.front().Offset, IncludesBlockSize, result)); 2601 // FIXME: better error handling. For now, just skip the replacement for the 2602 // release version. 2603 if (Err) { 2604 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 2605 assert(false); 2606 } 2607 } 2608 2609 namespace { 2610 2611 const char CppIncludeRegexPattern[] = 2612 R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))"; 2613 2614 } // anonymous namespace 2615 2616 tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code, 2617 ArrayRef<tooling::Range> Ranges, 2618 StringRef FileName, 2619 tooling::Replacements &Replaces, 2620 unsigned *Cursor) { 2621 unsigned Prev = llvm::StringSwitch<size_t>(Code) 2622 .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM 2623 .Default(0); 2624 unsigned SearchFrom = 0; 2625 llvm::Regex IncludeRegex(CppIncludeRegexPattern); 2626 SmallVector<StringRef, 4> Matches; 2627 SmallVector<IncludeDirective, 16> IncludesInBlock; 2628 2629 // In compiled files, consider the first #include to be the main #include of 2630 // the file if it is not a system #include. This ensures that the header 2631 // doesn't have hidden dependencies 2632 // (http://llvm.org/docs/CodingStandards.html#include-style). 2633 // 2634 // FIXME: Do some validation, e.g. edit distance of the base name, to fix 2635 // cases where the first #include is unlikely to be the main header. 2636 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 2637 bool FirstIncludeBlock = true; 2638 bool MainIncludeFound = false; 2639 bool FormattingOff = false; 2640 2641 // '[' must be the first and '-' the last character inside [...]. 2642 llvm::Regex RawStringRegex( 2643 "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\("); 2644 SmallVector<StringRef, 2> RawStringMatches; 2645 std::string RawStringTermination = ")\""; 2646 2647 for (;;) { 2648 auto Pos = Code.find('\n', SearchFrom); 2649 StringRef Line = 2650 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 2651 2652 StringRef Trimmed = Line.trim(); 2653 2654 // #includes inside raw string literals need to be ignored. 2655 // or we will sort the contents of the string. 2656 // Skip past until we think we are at the rawstring literal close. 2657 if (RawStringRegex.match(Trimmed, &RawStringMatches)) { 2658 std::string CharSequence = RawStringMatches[1].str(); 2659 RawStringTermination = ")" + CharSequence + "\""; 2660 FormattingOff = true; 2661 } 2662 2663 if (Trimmed.contains(RawStringTermination)) { 2664 FormattingOff = false; 2665 } 2666 2667 if (Trimmed == "// clang-format off" || Trimmed == "/* clang-format off */") 2668 FormattingOff = true; 2669 else if (Trimmed == "// clang-format on" || 2670 Trimmed == "/* clang-format on */") 2671 FormattingOff = false; 2672 2673 const bool EmptyLineSkipped = 2674 Trimmed.empty() && 2675 (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge || 2676 Style.IncludeStyle.IncludeBlocks == 2677 tooling::IncludeStyle::IBS_Regroup); 2678 2679 bool MergeWithNextLine = Trimmed.endswith("\\"); 2680 if (!FormattingOff && !MergeWithNextLine) { 2681 if (IncludeRegex.match(Line, &Matches)) { 2682 StringRef IncludeName = Matches[2]; 2683 int Category = Categories.getIncludePriority( 2684 IncludeName, 2685 /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock); 2686 int Priority = Categories.getSortIncludePriority( 2687 IncludeName, !MainIncludeFound && FirstIncludeBlock); 2688 if (Category == 0) 2689 MainIncludeFound = true; 2690 IncludesInBlock.push_back( 2691 {IncludeName, Line, Prev, Category, Priority}); 2692 } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) { 2693 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, 2694 Replaces, Cursor); 2695 IncludesInBlock.clear(); 2696 if (Trimmed.startswith("#pragma hdrstop")) // Precompiled headers. 2697 FirstIncludeBlock = true; 2698 else 2699 FirstIncludeBlock = false; 2700 } 2701 } 2702 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 2703 break; 2704 2705 if (!MergeWithNextLine) 2706 Prev = Pos + 1; 2707 SearchFrom = Pos + 1; 2708 } 2709 if (!IncludesInBlock.empty()) { 2710 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces, 2711 Cursor); 2712 } 2713 return Replaces; 2714 } 2715 2716 // Returns group number to use as a first order sort on imports. Gives UINT_MAX 2717 // if the import does not match any given groups. 2718 static unsigned findJavaImportGroup(const FormatStyle &Style, 2719 StringRef ImportIdentifier) { 2720 unsigned LongestMatchIndex = UINT_MAX; 2721 unsigned LongestMatchLength = 0; 2722 for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) { 2723 std::string GroupPrefix = Style.JavaImportGroups[I]; 2724 if (ImportIdentifier.startswith(GroupPrefix) && 2725 GroupPrefix.length() > LongestMatchLength) { 2726 LongestMatchIndex = I; 2727 LongestMatchLength = GroupPrefix.length(); 2728 } 2729 } 2730 return LongestMatchIndex; 2731 } 2732 2733 // Sorts and deduplicates a block of includes given by 'Imports' based on 2734 // JavaImportGroups, then adding the necessary replacement to 'Replaces'. 2735 // Import declarations with the same text will be deduplicated. Between each 2736 // import group, a newline is inserted, and within each import group, a 2737 // lexicographic sort based on ASCII value is performed. 2738 static void sortJavaImports(const FormatStyle &Style, 2739 const SmallVectorImpl<JavaImportDirective> &Imports, 2740 ArrayRef<tooling::Range> Ranges, StringRef FileName, 2741 StringRef Code, tooling::Replacements &Replaces) { 2742 unsigned ImportsBeginOffset = Imports.front().Offset; 2743 unsigned ImportsEndOffset = 2744 Imports.back().Offset + Imports.back().Text.size(); 2745 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset; 2746 if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset)) 2747 return; 2748 SmallVector<unsigned, 16> Indices; 2749 SmallVector<unsigned, 16> JavaImportGroups; 2750 for (unsigned i = 0, e = Imports.size(); i != e; ++i) { 2751 Indices.push_back(i); 2752 JavaImportGroups.push_back( 2753 findJavaImportGroup(Style, Imports[i].Identifier)); 2754 } 2755 bool StaticImportAfterNormalImport = 2756 Style.SortJavaStaticImport == FormatStyle::SJSIO_After; 2757 llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 2758 // Negating IsStatic to push static imports above non-static imports. 2759 return std::make_tuple(!Imports[LHSI].IsStatic ^ 2760 StaticImportAfterNormalImport, 2761 JavaImportGroups[LHSI], Imports[LHSI].Identifier) < 2762 std::make_tuple(!Imports[RHSI].IsStatic ^ 2763 StaticImportAfterNormalImport, 2764 JavaImportGroups[RHSI], Imports[RHSI].Identifier); 2765 }); 2766 2767 // Deduplicate imports. 2768 Indices.erase(std::unique(Indices.begin(), Indices.end(), 2769 [&](unsigned LHSI, unsigned RHSI) { 2770 return Imports[LHSI].Text == Imports[RHSI].Text; 2771 }), 2772 Indices.end()); 2773 2774 bool CurrentIsStatic = Imports[Indices.front()].IsStatic; 2775 unsigned CurrentImportGroup = JavaImportGroups[Indices.front()]; 2776 2777 std::string result; 2778 for (unsigned Index : Indices) { 2779 if (!result.empty()) { 2780 result += "\n"; 2781 if (CurrentIsStatic != Imports[Index].IsStatic || 2782 CurrentImportGroup != JavaImportGroups[Index]) 2783 result += "\n"; 2784 } 2785 for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) { 2786 result += CommentLine; 2787 result += "\n"; 2788 } 2789 result += Imports[Index].Text; 2790 CurrentIsStatic = Imports[Index].IsStatic; 2791 CurrentImportGroup = JavaImportGroups[Index]; 2792 } 2793 2794 // If the imports are out of order, we generate a single replacement fixing 2795 // the entire block. Otherwise, no replacement is generated. 2796 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 2797 Imports.front().Offset, ImportsBlockSize)))) 2798 return; 2799 2800 auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset, 2801 ImportsBlockSize, result)); 2802 // FIXME: better error handling. For now, just skip the replacement for the 2803 // release version. 2804 if (Err) { 2805 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 2806 assert(false); 2807 } 2808 } 2809 2810 namespace { 2811 2812 const char JavaImportRegexPattern[] = 2813 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;"; 2814 2815 } // anonymous namespace 2816 2817 tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code, 2818 ArrayRef<tooling::Range> Ranges, 2819 StringRef FileName, 2820 tooling::Replacements &Replaces) { 2821 unsigned Prev = 0; 2822 unsigned SearchFrom = 0; 2823 llvm::Regex ImportRegex(JavaImportRegexPattern); 2824 SmallVector<StringRef, 4> Matches; 2825 SmallVector<JavaImportDirective, 16> ImportsInBlock; 2826 std::vector<StringRef> AssociatedCommentLines; 2827 2828 bool FormattingOff = false; 2829 2830 for (;;) { 2831 auto Pos = Code.find('\n', SearchFrom); 2832 StringRef Line = 2833 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 2834 2835 StringRef Trimmed = Line.trim(); 2836 if (Trimmed == "// clang-format off") 2837 FormattingOff = true; 2838 else if (Trimmed == "// clang-format on") 2839 FormattingOff = false; 2840 2841 if (ImportRegex.match(Line, &Matches)) { 2842 if (FormattingOff) { 2843 // If at least one import line has formatting turned off, turn off 2844 // formatting entirely. 2845 return Replaces; 2846 } 2847 StringRef Static = Matches[1]; 2848 StringRef Identifier = Matches[2]; 2849 bool IsStatic = false; 2850 if (Static.contains("static")) { 2851 IsStatic = true; 2852 } 2853 ImportsInBlock.push_back( 2854 {Identifier, Line, Prev, AssociatedCommentLines, IsStatic}); 2855 AssociatedCommentLines.clear(); 2856 } else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) { 2857 // Associating comments within the imports with the nearest import below 2858 AssociatedCommentLines.push_back(Line); 2859 } 2860 Prev = Pos + 1; 2861 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 2862 break; 2863 SearchFrom = Pos + 1; 2864 } 2865 if (!ImportsInBlock.empty()) 2866 sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces); 2867 return Replaces; 2868 } 2869 2870 bool isMpegTS(StringRef Code) { 2871 // MPEG transport streams use the ".ts" file extension. clang-format should 2872 // not attempt to format those. MPEG TS' frame format starts with 0x47 every 2873 // 189 bytes - detect that and return. 2874 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47; 2875 } 2876 2877 bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); } 2878 2879 tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, 2880 ArrayRef<tooling::Range> Ranges, 2881 StringRef FileName, unsigned *Cursor) { 2882 tooling::Replacements Replaces; 2883 if (!Style.SortIncludes || Style.DisableFormat) 2884 return Replaces; 2885 if (isLikelyXml(Code)) 2886 return Replaces; 2887 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript && 2888 isMpegTS(Code)) 2889 return Replaces; 2890 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript) 2891 return sortJavaScriptImports(Style, Code, Ranges, FileName); 2892 if (Style.Language == FormatStyle::LanguageKind::LK_Java) 2893 return sortJavaImports(Style, Code, Ranges, FileName, Replaces); 2894 sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor); 2895 return Replaces; 2896 } 2897 2898 template <typename T> 2899 static llvm::Expected<tooling::Replacements> 2900 processReplacements(T ProcessFunc, StringRef Code, 2901 const tooling::Replacements &Replaces, 2902 const FormatStyle &Style) { 2903 if (Replaces.empty()) 2904 return tooling::Replacements(); 2905 2906 auto NewCode = applyAllReplacements(Code, Replaces); 2907 if (!NewCode) 2908 return NewCode.takeError(); 2909 std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges(); 2910 StringRef FileName = Replaces.begin()->getFilePath(); 2911 2912 tooling::Replacements FormatReplaces = 2913 ProcessFunc(Style, *NewCode, ChangedRanges, FileName); 2914 2915 return Replaces.merge(FormatReplaces); 2916 } 2917 2918 llvm::Expected<tooling::Replacements> 2919 formatReplacements(StringRef Code, const tooling::Replacements &Replaces, 2920 const FormatStyle &Style) { 2921 // We need to use lambda function here since there are two versions of 2922 // `sortIncludes`. 2923 auto SortIncludes = [](const FormatStyle &Style, StringRef Code, 2924 std::vector<tooling::Range> Ranges, 2925 StringRef FileName) -> tooling::Replacements { 2926 return sortIncludes(Style, Code, Ranges, FileName); 2927 }; 2928 auto SortedReplaces = 2929 processReplacements(SortIncludes, Code, Replaces, Style); 2930 if (!SortedReplaces) 2931 return SortedReplaces.takeError(); 2932 2933 // We need to use lambda function here since there are two versions of 2934 // `reformat`. 2935 auto Reformat = [](const FormatStyle &Style, StringRef Code, 2936 std::vector<tooling::Range> Ranges, 2937 StringRef FileName) -> tooling::Replacements { 2938 return reformat(Style, Code, Ranges, FileName); 2939 }; 2940 return processReplacements(Reformat, Code, *SortedReplaces, Style); 2941 } 2942 2943 namespace { 2944 2945 inline bool isHeaderInsertion(const tooling::Replacement &Replace) { 2946 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 && 2947 llvm::Regex(CppIncludeRegexPattern) 2948 .match(Replace.getReplacementText()); 2949 } 2950 2951 inline bool isHeaderDeletion(const tooling::Replacement &Replace) { 2952 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1; 2953 } 2954 2955 // FIXME: insert empty lines between newly created blocks. 2956 tooling::Replacements 2957 fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces, 2958 const FormatStyle &Style) { 2959 if (!Style.isCpp()) 2960 return Replaces; 2961 2962 tooling::Replacements HeaderInsertions; 2963 std::set<llvm::StringRef> HeadersToDelete; 2964 tooling::Replacements Result; 2965 for (const auto &R : Replaces) { 2966 if (isHeaderInsertion(R)) { 2967 // Replacements from \p Replaces must be conflict-free already, so we can 2968 // simply consume the error. 2969 llvm::consumeError(HeaderInsertions.add(R)); 2970 } else if (isHeaderDeletion(R)) { 2971 HeadersToDelete.insert(R.getReplacementText()); 2972 } else if (R.getOffset() == UINT_MAX) { 2973 llvm::errs() << "Insertions other than header #include insertion are " 2974 "not supported! " 2975 << R.getReplacementText() << "\n"; 2976 } else { 2977 llvm::consumeError(Result.add(R)); 2978 } 2979 } 2980 if (HeaderInsertions.empty() && HeadersToDelete.empty()) 2981 return Replaces; 2982 2983 StringRef FileName = Replaces.begin()->getFilePath(); 2984 tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle); 2985 2986 for (const auto &Header : HeadersToDelete) { 2987 tooling::Replacements Replaces = 2988 Includes.remove(Header.trim("\"<>"), Header.startswith("<")); 2989 for (const auto &R : Replaces) { 2990 auto Err = Result.add(R); 2991 if (Err) { 2992 // Ignore the deletion on conflict. 2993 llvm::errs() << "Failed to add header deletion replacement for " 2994 << Header << ": " << llvm::toString(std::move(Err)) 2995 << "\n"; 2996 } 2997 } 2998 } 2999 3000 llvm::Regex IncludeRegex = llvm::Regex(CppIncludeRegexPattern); 3001 llvm::SmallVector<StringRef, 4> Matches; 3002 for (const auto &R : HeaderInsertions) { 3003 auto IncludeDirective = R.getReplacementText(); 3004 bool Matched = IncludeRegex.match(IncludeDirective, &Matches); 3005 assert(Matched && "Header insertion replacement must have replacement text " 3006 "'#include ...'"); 3007 (void)Matched; 3008 auto IncludeName = Matches[2]; 3009 auto Replace = 3010 Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<")); 3011 if (Replace) { 3012 auto Err = Result.add(*Replace); 3013 if (Err) { 3014 llvm::consumeError(std::move(Err)); 3015 unsigned NewOffset = 3016 Result.getShiftedCodePosition(Replace->getOffset()); 3017 auto Shifted = tooling::Replacement(FileName, NewOffset, 0, 3018 Replace->getReplacementText()); 3019 Result = Result.merge(tooling::Replacements(Shifted)); 3020 } 3021 } 3022 } 3023 return Result; 3024 } 3025 3026 } // anonymous namespace 3027 3028 llvm::Expected<tooling::Replacements> 3029 cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, 3030 const FormatStyle &Style) { 3031 // We need to use lambda function here since there are two versions of 3032 // `cleanup`. 3033 auto Cleanup = [](const FormatStyle &Style, StringRef Code, 3034 std::vector<tooling::Range> Ranges, 3035 StringRef FileName) -> tooling::Replacements { 3036 return cleanup(Style, Code, Ranges, FileName); 3037 }; 3038 // Make header insertion replacements insert new headers into correct blocks. 3039 tooling::Replacements NewReplaces = 3040 fixCppIncludeInsertions(Code, Replaces, Style); 3041 return processReplacements(Cleanup, Code, NewReplaces, Style); 3042 } 3043 3044 namespace internal { 3045 std::pair<tooling::Replacements, unsigned> 3046 reformat(const FormatStyle &Style, StringRef Code, 3047 ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn, 3048 unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName, 3049 FormattingAttemptStatus *Status) { 3050 FormatStyle Expanded = Style; 3051 expandPresetsBraceWrapping(Expanded); 3052 expandPresetsSpaceBeforeParens(Expanded); 3053 if (Expanded.DisableFormat) 3054 return {tooling::Replacements(), 0}; 3055 if (isLikelyXml(Code)) 3056 return {tooling::Replacements(), 0}; 3057 if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code)) 3058 return {tooling::Replacements(), 0}; 3059 3060 // JSON only needs the formatting passing. 3061 if (Style.isJson()) { 3062 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); 3063 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn, 3064 NextStartColumn, LastStartColumn); 3065 if (!Env) 3066 return {}; 3067 // Perform the actual formatting pass. 3068 tooling::Replacements Replaces = 3069 Formatter(*Env, Style, Status).process().first; 3070 // add a replacement to remove the "x = " from the result. 3071 if (!Replaces.add(tooling::Replacement(FileName, 0, 4, ""))) { 3072 // apply the reformatting changes and the removal of "x = ". 3073 if (applyAllReplacements(Code, Replaces)) { 3074 return {Replaces, 0}; 3075 } 3076 } 3077 return {tooling::Replacements(), 0}; 3078 } 3079 3080 typedef std::function<std::pair<tooling::Replacements, unsigned>( 3081 const Environment &)> 3082 AnalyzerPass; 3083 SmallVector<AnalyzerPass, 4> Passes; 3084 3085 if (Style.isCpp() && Style.QualifierAlignment != FormatStyle::QAS_Leave) { 3086 Passes.emplace_back([&](const Environment &Env) { 3087 return QualifierAlignmentFixer(Env, Expanded, Code, Ranges, 3088 FirstStartColumn, NextStartColumn, 3089 LastStartColumn, FileName) 3090 .process(); 3091 }); 3092 } 3093 3094 if (Style.isCpp() && Style.RemoveBracesLLVM) 3095 Passes.emplace_back([&](const Environment &Env) { 3096 return BracesRemover(Env, Expanded).process(); 3097 }); 3098 3099 if (Style.Language == FormatStyle::LK_Cpp) { 3100 if (Style.FixNamespaceComments) 3101 Passes.emplace_back([&](const Environment &Env) { 3102 return NamespaceEndCommentsFixer(Env, Expanded).process(); 3103 }); 3104 3105 if (Style.SortUsingDeclarations) 3106 Passes.emplace_back([&](const Environment &Env) { 3107 return UsingDeclarationsSorter(Env, Expanded).process(); 3108 }); 3109 } 3110 3111 if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) 3112 Passes.emplace_back([&](const Environment &Env) { 3113 return DefinitionBlockSeparator(Env, Expanded).process(); 3114 }); 3115 3116 if (Style.isJavaScript() && Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) 3117 Passes.emplace_back([&](const Environment &Env) { 3118 return JavaScriptRequoter(Env, Expanded).process(); 3119 }); 3120 3121 Passes.emplace_back([&](const Environment &Env) { 3122 return Formatter(Env, Expanded, Status).process(); 3123 }); 3124 3125 if (Style.isJavaScript() && 3126 Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) 3127 Passes.emplace_back([&](const Environment &Env) { 3128 return TrailingCommaInserter(Env, Expanded).process(); 3129 }); 3130 3131 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn, 3132 NextStartColumn, LastStartColumn); 3133 if (!Env) 3134 return {}; 3135 llvm::Optional<std::string> CurrentCode = None; 3136 tooling::Replacements Fixes; 3137 unsigned Penalty = 0; 3138 for (size_t I = 0, E = Passes.size(); I < E; ++I) { 3139 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env); 3140 auto NewCode = applyAllReplacements( 3141 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first); 3142 if (NewCode) { 3143 Fixes = Fixes.merge(PassFixes.first); 3144 Penalty += PassFixes.second; 3145 if (I + 1 < E) { 3146 CurrentCode = std::move(*NewCode); 3147 Env = Environment::make( 3148 *CurrentCode, FileName, 3149 tooling::calculateRangesAfterReplacements(Fixes, Ranges), 3150 FirstStartColumn, NextStartColumn, LastStartColumn); 3151 if (!Env) 3152 return {}; 3153 } 3154 } 3155 } 3156 3157 return {Fixes, Penalty}; 3158 } 3159 } // namespace internal 3160 3161 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 3162 ArrayRef<tooling::Range> Ranges, 3163 StringRef FileName, 3164 FormattingAttemptStatus *Status) { 3165 return internal::reformat(Style, Code, Ranges, 3166 /*FirstStartColumn=*/0, 3167 /*NextStartColumn=*/0, 3168 /*LastStartColumn=*/0, FileName, Status) 3169 .first; 3170 } 3171 3172 tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, 3173 ArrayRef<tooling::Range> Ranges, 3174 StringRef FileName) { 3175 // cleanups only apply to C++ (they mostly concern ctor commas etc.) 3176 if (Style.Language != FormatStyle::LK_Cpp) 3177 return tooling::Replacements(); 3178 auto Env = Environment::make(Code, FileName, Ranges); 3179 if (!Env) 3180 return {}; 3181 return Cleaner(*Env, Style).process().first; 3182 } 3183 3184 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 3185 ArrayRef<tooling::Range> Ranges, 3186 StringRef FileName, bool *IncompleteFormat) { 3187 FormattingAttemptStatus Status; 3188 auto Result = reformat(Style, Code, Ranges, FileName, &Status); 3189 if (!Status.FormatComplete) 3190 *IncompleteFormat = true; 3191 return Result; 3192 } 3193 3194 tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, 3195 StringRef Code, 3196 ArrayRef<tooling::Range> Ranges, 3197 StringRef FileName) { 3198 auto Env = Environment::make(Code, FileName, Ranges); 3199 if (!Env) 3200 return {}; 3201 return NamespaceEndCommentsFixer(*Env, Style).process().first; 3202 } 3203 3204 tooling::Replacements separateDefinitionBlocks(const FormatStyle &Style, 3205 StringRef Code, 3206 ArrayRef<tooling::Range> Ranges, 3207 StringRef FileName) { 3208 auto Env = Environment::make(Code, FileName, Ranges); 3209 if (!Env) 3210 return {}; 3211 return DefinitionBlockSeparator(*Env, Style).process().first; 3212 } 3213 3214 tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, 3215 StringRef Code, 3216 ArrayRef<tooling::Range> Ranges, 3217 StringRef FileName) { 3218 auto Env = Environment::make(Code, FileName, Ranges); 3219 if (!Env) 3220 return {}; 3221 return UsingDeclarationsSorter(*Env, Style).process().first; 3222 } 3223 3224 LangOptions getFormattingLangOpts(const FormatStyle &Style) { 3225 LangOptions LangOpts; 3226 3227 FormatStyle::LanguageStandard LexingStd = Style.Standard; 3228 if (LexingStd == FormatStyle::LS_Auto) 3229 LexingStd = FormatStyle::LS_Latest; 3230 if (LexingStd == FormatStyle::LS_Latest) 3231 LexingStd = FormatStyle::LS_Cpp20; 3232 LangOpts.CPlusPlus = 1; 3233 LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11; 3234 LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14; 3235 LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17; 3236 LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20; 3237 LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20; 3238 3239 LangOpts.LineComment = 1; 3240 bool AlternativeOperators = Style.isCpp(); 3241 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0; 3242 LangOpts.Bool = 1; 3243 LangOpts.ObjC = 1; 3244 LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally. 3245 LangOpts.DeclSpecKeyword = 1; // To get __declspec. 3246 LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict. 3247 return LangOpts; 3248 } 3249 3250 const char *StyleOptionHelpDescription = 3251 "Coding style, currently supports:\n" 3252 " LLVM, GNU, Google, Chromium, Microsoft, Mozilla, WebKit.\n" 3253 "Use -style=file to load style configuration from\n" 3254 ".clang-format file located in one of the parent\n" 3255 "directories of the source file (or current\n" 3256 "directory for stdin).\n" 3257 "Use -style=file:<format_file_path> to explicitly specify" 3258 "the configuration file.\n" 3259 "Use -style=\"{key: value, ...}\" to set specific\n" 3260 "parameters, e.g.:\n" 3261 " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""; 3262 3263 static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) { 3264 if (FileName.endswith(".java")) 3265 return FormatStyle::LK_Java; 3266 if (FileName.endswith_insensitive(".js") || 3267 FileName.endswith_insensitive(".mjs") || 3268 FileName.endswith_insensitive(".ts")) 3269 return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript. 3270 if (FileName.endswith(".m") || FileName.endswith(".mm")) 3271 return FormatStyle::LK_ObjC; 3272 if (FileName.endswith_insensitive(".proto") || 3273 FileName.endswith_insensitive(".protodevel")) 3274 return FormatStyle::LK_Proto; 3275 if (FileName.endswith_insensitive(".textpb") || 3276 FileName.endswith_insensitive(".pb.txt") || 3277 FileName.endswith_insensitive(".textproto") || 3278 FileName.endswith_insensitive(".asciipb")) 3279 return FormatStyle::LK_TextProto; 3280 if (FileName.endswith_insensitive(".td")) 3281 return FormatStyle::LK_TableGen; 3282 if (FileName.endswith_insensitive(".cs")) 3283 return FormatStyle::LK_CSharp; 3284 if (FileName.endswith_insensitive(".json")) 3285 return FormatStyle::LK_Json; 3286 return FormatStyle::LK_Cpp; 3287 } 3288 3289 FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) { 3290 const auto GuessedLanguage = getLanguageByFileName(FileName); 3291 if (GuessedLanguage == FormatStyle::LK_Cpp) { 3292 auto Extension = llvm::sys::path::extension(FileName); 3293 // If there's no file extension (or it's .h), we need to check the contents 3294 // of the code to see if it contains Objective-C. 3295 if (Extension.empty() || Extension == ".h") { 3296 auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName; 3297 Environment Env(Code, NonEmptyFileName, /*Ranges=*/{}); 3298 ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle()); 3299 Guesser.process(); 3300 if (Guesser.isObjC()) 3301 return FormatStyle::LK_ObjC; 3302 } 3303 } 3304 return GuessedLanguage; 3305 } 3306 3307 const char *DefaultFormatStyle = "file"; 3308 3309 const char *DefaultFallbackStyle = "LLVM"; 3310 3311 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> 3312 loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS, 3313 FormatStyle *Style, bool AllowUnknownOptions) { 3314 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 3315 FS->getBufferForFile(ConfigFile.str()); 3316 if (auto EC = Text.getError()) 3317 return EC; 3318 if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions)) 3319 return EC; 3320 return Text; 3321 } 3322 3323 llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, 3324 StringRef FallbackStyleName, 3325 StringRef Code, llvm::vfs::FileSystem *FS, 3326 bool AllowUnknownOptions) { 3327 if (!FS) { 3328 FS = llvm::vfs::getRealFileSystem().get(); 3329 } 3330 FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code)); 3331 3332 FormatStyle FallbackStyle = getNoStyle(); 3333 if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle)) 3334 return make_string_error("Invalid fallback style \"" + FallbackStyleName); 3335 3336 llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1> 3337 ChildFormatTextToApply; 3338 3339 if (StyleName.startswith("{")) { 3340 // Parse YAML/JSON style from the command line. 3341 StringRef Source = "<command-line>"; 3342 if (std::error_code ec = 3343 parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style, 3344 AllowUnknownOptions)) 3345 return make_string_error("Error parsing -style: " + ec.message()); 3346 if (Style.InheritsParentConfig) 3347 ChildFormatTextToApply.emplace_back( 3348 llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false)); 3349 else 3350 return Style; 3351 } 3352 3353 // User provided clang-format file using -style=file:path/to/format/file. 3354 if (!Style.InheritsParentConfig && 3355 StyleName.startswith_insensitive("file:")) { 3356 auto ConfigFile = StyleName.substr(5); 3357 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 3358 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions); 3359 if (auto EC = Text.getError()) 3360 return make_string_error("Error reading " + ConfigFile + ": " + 3361 EC.message()); 3362 3363 LLVM_DEBUG(llvm::dbgs() 3364 << "Using configuration file " << ConfigFile << "\n"); 3365 3366 if (!Style.InheritsParentConfig) 3367 return Style; 3368 3369 // Search for parent configs starting from the parent directory of 3370 // ConfigFile. 3371 FileName = ConfigFile; 3372 ChildFormatTextToApply.emplace_back(std::move(*Text)); 3373 } 3374 3375 // If the style inherits the parent configuration it is a command line 3376 // configuration, which wants to inherit, so we have to skip the check of the 3377 // StyleName. 3378 if (!Style.InheritsParentConfig && !StyleName.equals_insensitive("file")) { 3379 if (!getPredefinedStyle(StyleName, Style.Language, &Style)) 3380 return make_string_error("Invalid value for -style"); 3381 if (!Style.InheritsParentConfig) 3382 return Style; 3383 } 3384 3385 // Reset possible inheritance 3386 Style.InheritsParentConfig = false; 3387 3388 // Look for .clang-format/_clang-format file in the file's parent directories. 3389 SmallString<128> UnsuitableConfigFiles; 3390 SmallString<128> Path(FileName); 3391 if (std::error_code EC = FS->makeAbsolute(Path)) 3392 return make_string_error(EC.message()); 3393 3394 llvm::SmallVector<std::string, 2> FilesToLookFor; 3395 FilesToLookFor.push_back(".clang-format"); 3396 FilesToLookFor.push_back("_clang-format"); 3397 3398 auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {}; 3399 3400 auto applyChildFormatTexts = [&](FormatStyle *Style) { 3401 for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) { 3402 auto EC = parseConfiguration(*MemBuf, Style, AllowUnknownOptions, 3403 dropDiagnosticHandler); 3404 // It was already correctly parsed. 3405 assert(!EC); 3406 static_cast<void>(EC); 3407 } 3408 }; 3409 3410 for (StringRef Directory = Path; !Directory.empty(); 3411 Directory = llvm::sys::path::parent_path(Directory)) { 3412 3413 auto Status = FS->status(Directory); 3414 if (!Status || 3415 Status->getType() != llvm::sys::fs::file_type::directory_file) { 3416 continue; 3417 } 3418 3419 for (const auto &F : FilesToLookFor) { 3420 SmallString<128> ConfigFile(Directory); 3421 3422 llvm::sys::path::append(ConfigFile, F); 3423 LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); 3424 3425 Status = FS->status(ConfigFile.str()); 3426 3427 if (Status && 3428 (Status->getType() == llvm::sys::fs::file_type::regular_file)) { 3429 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 3430 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions); 3431 if (auto EC = Text.getError()) { 3432 if (EC == ParseError::Unsuitable) { 3433 if (!UnsuitableConfigFiles.empty()) 3434 UnsuitableConfigFiles.append(", "); 3435 UnsuitableConfigFiles.append(ConfigFile); 3436 continue; 3437 } 3438 return make_string_error("Error reading " + ConfigFile + ": " + 3439 EC.message()); 3440 } 3441 LLVM_DEBUG(llvm::dbgs() 3442 << "Using configuration file " << ConfigFile << "\n"); 3443 3444 if (!Style.InheritsParentConfig) { 3445 if (ChildFormatTextToApply.empty()) 3446 return Style; 3447 3448 LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n"); 3449 applyChildFormatTexts(&Style); 3450 3451 return Style; 3452 } 3453 3454 LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n"); 3455 3456 // Reset inheritance of style 3457 Style.InheritsParentConfig = false; 3458 3459 ChildFormatTextToApply.emplace_back(std::move(*Text)); 3460 3461 // Breaking out of the inner loop, since we don't want to parse 3462 // .clang-format AND _clang-format, if both exist. Then we continue the 3463 // inner loop (parent directories) in search for the parent 3464 // configuration. 3465 break; 3466 } 3467 } 3468 } 3469 if (!UnsuitableConfigFiles.empty()) 3470 return make_string_error("Configuration file(s) do(es) not support " + 3471 getLanguageName(Style.Language) + ": " + 3472 UnsuitableConfigFiles); 3473 3474 if (!ChildFormatTextToApply.empty()) { 3475 LLVM_DEBUG(llvm::dbgs() 3476 << "Applying child configurations on fallback style\n"); 3477 applyChildFormatTexts(&FallbackStyle); 3478 } 3479 3480 return FallbackStyle; 3481 } 3482 3483 } // namespace format 3484 } // namespace clang 3485