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