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