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