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