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