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