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