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