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