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