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