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 break; 805 case FormatStyle::BS_Whitesmiths: 806 Expanded.BraceWrapping.AfterCaseLabel = true; 807 Expanded.BraceWrapping.AfterClass = true; 808 Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; 809 Expanded.BraceWrapping.AfterEnum = true; 810 Expanded.BraceWrapping.AfterFunction = true; 811 Expanded.BraceWrapping.AfterNamespace = true; 812 Expanded.BraceWrapping.AfterObjCDeclaration = true; 813 Expanded.BraceWrapping.AfterStruct = true; 814 Expanded.BraceWrapping.AfterExternBlock = true; 815 Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; 816 Expanded.BraceWrapping.BeforeCatch = true; 817 Expanded.BraceWrapping.BeforeElse = true; 818 Expanded.BraceWrapping.BeforeLambdaBody = true; 819 break; 820 case FormatStyle::BS_GNU: 821 Expanded.BraceWrapping = { 822 /*AfterCaseLabel=*/true, 823 /*AfterClass=*/true, 824 /*AfterControlStatement=*/FormatStyle::BWACS_Always, 825 /*AfterEnum=*/true, 826 /*AfterFunction=*/true, 827 /*AfterNamespace=*/true, 828 /*AfterObjCDeclaration=*/true, 829 /*AfterStruct=*/true, 830 /*AfterUnion=*/true, 831 /*AfterExternBlock=*/true, 832 /*BeforeCatch=*/true, 833 /*BeforeElse=*/true, 834 /*BeforeLambdaBody=*/false, 835 /*BeforeWhile=*/true, 836 /*IndentBraces=*/true, 837 /*SplitEmptyFunction=*/true, 838 /*SplitEmptyRecord=*/true, 839 /*SplitEmptyNamespace=*/true}; 840 Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; 841 break; 842 case FormatStyle::BS_WebKit: 843 Expanded.BraceWrapping.AfterFunction = true; 844 break; 845 default: 846 break; 847 } 848 return Expanded; 849 } 850 851 FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { 852 FormatStyle LLVMStyle; 853 LLVMStyle.Language = Language; 854 LLVMStyle.AccessModifierOffset = -2; 855 LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right; 856 LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align; 857 LLVMStyle.AlignOperands = FormatStyle::OAS_Align; 858 LLVMStyle.AlignTrailingComments = true; 859 LLVMStyle.AlignConsecutiveAssignments = false; 860 LLVMStyle.AlignConsecutiveBitFields = false; 861 LLVMStyle.AlignConsecutiveDeclarations = false; 862 LLVMStyle.AlignConsecutiveMacros = false; 863 LLVMStyle.AllowAllArgumentsOnNextLine = true; 864 LLVMStyle.AllowAllConstructorInitializersOnNextLine = true; 865 LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; 866 LLVMStyle.AllowShortEnumsOnASingleLine = true; 867 LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; 868 LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never; 869 LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; 870 LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 871 LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; 872 LLVMStyle.AllowShortLoopsOnASingleLine = false; 873 LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; 874 LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; 875 LLVMStyle.AlwaysBreakBeforeMultilineStrings = false; 876 LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine; 877 LLVMStyle.AttributeMacros.push_back("__capability"); 878 LLVMStyle.BinPackArguments = true; 879 LLVMStyle.BinPackParameters = true; 880 LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None; 881 LLVMStyle.BreakBeforeConceptDeclarations = true; 882 LLVMStyle.BreakBeforeTernaryOperators = true; 883 LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach; 884 LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false, 885 /*AfterClass=*/false, 886 /*AfterControlStatement=*/FormatStyle::BWACS_Never, 887 /*AfterEnum=*/false, 888 /*AfterFunction=*/false, 889 /*AfterNamespace=*/false, 890 /*AfterObjCDeclaration=*/false, 891 /*AfterStruct=*/false, 892 /*AfterUnion=*/false, 893 /*AfterExternBlock=*/false, 894 /*BeforeCatch=*/false, 895 /*BeforeElse=*/false, 896 /*BeforeLambdaBody=*/false, 897 /*BeforeWhile=*/false, 898 /*IndentBraces=*/false, 899 /*SplitEmptyFunction=*/true, 900 /*SplitEmptyRecord=*/true, 901 /*SplitEmptyNamespace=*/true}; 902 LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; 903 LLVMStyle.BreakAfterJavaFieldAnnotations = false; 904 LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; 905 LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon; 906 LLVMStyle.BreakStringLiterals = true; 907 LLVMStyle.ColumnLimit = 80; 908 LLVMStyle.CommentPragmas = "^ IWYU pragma:"; 909 LLVMStyle.CompactNamespaces = false; 910 LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false; 911 LLVMStyle.ConstructorInitializerIndentWidth = 4; 912 LLVMStyle.ContinuationIndentWidth = 4; 913 LLVMStyle.Cpp11BracedListStyle = true; 914 LLVMStyle.DeriveLineEnding = true; 915 LLVMStyle.DerivePointerAlignment = false; 916 LLVMStyle.ExperimentalAutoDetectBinPacking = false; 917 LLVMStyle.FixNamespaceComments = true; 918 LLVMStyle.ForEachMacros.push_back("foreach"); 919 LLVMStyle.ForEachMacros.push_back("Q_FOREACH"); 920 LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH"); 921 LLVMStyle.IncludeStyle.IncludeCategories = { 922 {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false}, 923 {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false}, 924 {".*", 1, 0, false}}; 925 LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$"; 926 LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve; 927 LLVMStyle.IndentCaseLabels = false; 928 LLVMStyle.IndentCaseBlocks = false; 929 LLVMStyle.IndentGotoLabels = true; 930 LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None; 931 LLVMStyle.IndentRequires = false; 932 LLVMStyle.IndentWrappedFunctionNames = false; 933 LLVMStyle.IndentWidth = 2; 934 LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None; 935 LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave; 936 LLVMStyle.JavaScriptWrapImports = true; 937 LLVMStyle.TabWidth = 8; 938 LLVMStyle.MaxEmptyLinesToKeep = 1; 939 LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true; 940 LLVMStyle.NamespaceIndentation = FormatStyle::NI_None; 941 LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto; 942 LLVMStyle.ObjCBlockIndentWidth = 2; 943 LLVMStyle.ObjCBreakBeforeNestedBlockParam = true; 944 LLVMStyle.ObjCSpaceAfterProperty = false; 945 LLVMStyle.ObjCSpaceBeforeProtocolList = true; 946 LLVMStyle.PointerAlignment = FormatStyle::PAS_Right; 947 LLVMStyle.SpacesBeforeTrailingComments = 1; 948 LLVMStyle.Standard = FormatStyle::LS_Latest; 949 LLVMStyle.UseCRLF = false; 950 LLVMStyle.UseTab = FormatStyle::UT_Never; 951 LLVMStyle.ReflowComments = true; 952 LLVMStyle.SpacesInParentheses = false; 953 LLVMStyle.SpacesInSquareBrackets = false; 954 LLVMStyle.SpaceInEmptyBlock = false; 955 LLVMStyle.SpaceInEmptyParentheses = false; 956 LLVMStyle.SpacesInContainerLiterals = true; 957 LLVMStyle.SpacesInCStyleCastParentheses = false; 958 LLVMStyle.SpaceAfterCStyleCast = false; 959 LLVMStyle.SpaceAfterLogicalNot = false; 960 LLVMStyle.SpaceAfterTemplateKeyword = true; 961 LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default; 962 LLVMStyle.SpaceBeforeCaseColon = false; 963 LLVMStyle.SpaceBeforeCtorInitializerColon = true; 964 LLVMStyle.SpaceBeforeInheritanceColon = true; 965 LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements; 966 LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true; 967 LLVMStyle.SpaceBeforeAssignmentOperators = true; 968 LLVMStyle.SpaceBeforeCpp11BracedList = false; 969 LLVMStyle.SpaceBeforeSquareBrackets = false; 970 LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both; 971 LLVMStyle.SpacesInAngles = false; 972 LLVMStyle.SpacesInConditionalStatement = false; 973 974 LLVMStyle.PenaltyBreakAssignment = prec::Assignment; 975 LLVMStyle.PenaltyBreakComment = 300; 976 LLVMStyle.PenaltyBreakFirstLessLess = 120; 977 LLVMStyle.PenaltyBreakString = 1000; 978 LLVMStyle.PenaltyExcessCharacter = 1000000; 979 LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60; 980 LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19; 981 LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational; 982 LLVMStyle.PenaltyIndentedWhitespace = 0; 983 984 LLVMStyle.DisableFormat = false; 985 LLVMStyle.SortIncludes = true; 986 LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before; 987 LLVMStyle.SortUsingDeclarations = true; 988 LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT"); 989 LLVMStyle.StatementMacros.push_back("Q_UNUSED"); 990 LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION"); 991 LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE"); 992 LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE"); 993 LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE"); 994 LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME"); 995 LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME"); 996 997 // Defaults that differ when not C++. 998 if (Language == FormatStyle::LK_TableGen) { 999 LLVMStyle.SpacesInContainerLiterals = false; 1000 } 1001 1002 return LLVMStyle; 1003 } 1004 1005 FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { 1006 if (Language == FormatStyle::LK_TextProto) { 1007 FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto); 1008 GoogleStyle.Language = FormatStyle::LK_TextProto; 1009 1010 return GoogleStyle; 1011 } 1012 1013 FormatStyle GoogleStyle = getLLVMStyle(Language); 1014 1015 GoogleStyle.AccessModifierOffset = -1; 1016 GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left; 1017 GoogleStyle.AllowShortIfStatementsOnASingleLine = 1018 FormatStyle::SIS_WithoutElse; 1019 GoogleStyle.AllowShortLoopsOnASingleLine = true; 1020 GoogleStyle.AlwaysBreakBeforeMultilineStrings = true; 1021 GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; 1022 GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true; 1023 GoogleStyle.DerivePointerAlignment = true; 1024 GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false}, 1025 {"^<.*\\.h>", 1, 0, false}, 1026 {"^<.*", 2, 0, false}, 1027 {".*", 3, 0, false}}; 1028 GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$"; 1029 GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 1030 GoogleStyle.IndentCaseLabels = true; 1031 GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false; 1032 GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never; 1033 GoogleStyle.ObjCSpaceAfterProperty = false; 1034 GoogleStyle.ObjCSpaceBeforeProtocolList = true; 1035 GoogleStyle.PointerAlignment = FormatStyle::PAS_Left; 1036 GoogleStyle.RawStringFormats = { 1037 { 1038 FormatStyle::LK_Cpp, 1039 /*Delimiters=*/ 1040 { 1041 "cc", 1042 "CC", 1043 "cpp", 1044 "Cpp", 1045 "CPP", 1046 "c++", 1047 "C++", 1048 }, 1049 /*EnclosingFunctionNames=*/ 1050 {}, 1051 /*CanonicalDelimiter=*/"", 1052 /*BasedOnStyle=*/"google", 1053 }, 1054 { 1055 FormatStyle::LK_TextProto, 1056 /*Delimiters=*/ 1057 { 1058 "pb", 1059 "PB", 1060 "proto", 1061 "PROTO", 1062 }, 1063 /*EnclosingFunctionNames=*/ 1064 { 1065 "EqualsProto", 1066 "EquivToProto", 1067 "PARSE_PARTIAL_TEXT_PROTO", 1068 "PARSE_TEST_PROTO", 1069 "PARSE_TEXT_PROTO", 1070 "ParseTextOrDie", 1071 "ParseTextProtoOrDie", 1072 "ParseTestProto", 1073 "ParsePartialTestProto", 1074 }, 1075 /*CanonicalDelimiter=*/"", 1076 /*BasedOnStyle=*/"google", 1077 }, 1078 }; 1079 GoogleStyle.SpacesBeforeTrailingComments = 2; 1080 GoogleStyle.Standard = FormatStyle::LS_Auto; 1081 1082 GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200; 1083 GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1; 1084 1085 if (Language == FormatStyle::LK_Java) { 1086 GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; 1087 GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign; 1088 GoogleStyle.AlignTrailingComments = false; 1089 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 1090 GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1091 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 1092 GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; 1093 GoogleStyle.ColumnLimit = 100; 1094 GoogleStyle.SpaceAfterCStyleCast = true; 1095 GoogleStyle.SpacesBeforeTrailingComments = 1; 1096 } else if (Language == FormatStyle::LK_JavaScript) { 1097 GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; 1098 GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign; 1099 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 1100 // TODO: still under discussion whether to switch to SLS_All. 1101 GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty; 1102 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 1103 GoogleStyle.BreakBeforeTernaryOperators = false; 1104 // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is 1105 // commonly followed by overlong URLs. 1106 GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)"; 1107 // TODO: enable once decided, in particular re disabling bin packing. 1108 // https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma 1109 // GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped; 1110 GoogleStyle.MaxEmptyLinesToKeep = 3; 1111 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All; 1112 GoogleStyle.SpacesInContainerLiterals = false; 1113 GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single; 1114 GoogleStyle.JavaScriptWrapImports = false; 1115 } else if (Language == FormatStyle::LK_Proto) { 1116 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 1117 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 1118 GoogleStyle.SpacesInContainerLiterals = false; 1119 GoogleStyle.Cpp11BracedListStyle = false; 1120 // This affects protocol buffer options specifications and text protos. 1121 // Text protos are currently mostly formatted inside C++ raw string literals 1122 // and often the current breaking behavior of string literals is not 1123 // beneficial there. Investigate turning this on once proper string reflow 1124 // has been implemented. 1125 GoogleStyle.BreakStringLiterals = false; 1126 } else if (Language == FormatStyle::LK_ObjC) { 1127 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 1128 GoogleStyle.ColumnLimit = 100; 1129 // "Regroup" doesn't work well for ObjC yet (main header heuristic, 1130 // relationship between ObjC standard library headers and other heades, 1131 // #imports, etc.) 1132 GoogleStyle.IncludeStyle.IncludeBlocks = 1133 tooling::IncludeStyle::IBS_Preserve; 1134 } else if (Language == FormatStyle::LK_CSharp) { 1135 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 1136 GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1137 GoogleStyle.BreakStringLiterals = false; 1138 GoogleStyle.ColumnLimit = 100; 1139 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All; 1140 } 1141 1142 return GoogleStyle; 1143 } 1144 1145 FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) { 1146 FormatStyle ChromiumStyle = getGoogleStyle(Language); 1147 1148 // Disable include reordering across blocks in Chromium code. 1149 // - clang-format tries to detect that foo.h is the "main" header for 1150 // foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium 1151 // uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc, 1152 // _private.cc, _impl.cc etc) in different permutations 1153 // (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a 1154 // better default for Chromium code. 1155 // - The default for .cc and .mm files is different (r357695) for Google style 1156 // for the same reason. The plan is to unify this again once the main 1157 // header detection works for Google's ObjC code, but this hasn't happened 1158 // yet. Since Chromium has some ObjC code, switching Chromium is blocked 1159 // on that. 1160 // - Finally, "If include reordering is harmful, put things in different 1161 // blocks to prevent it" has been a recommendation for a long time that 1162 // people are used to. We'll need a dev education push to change this to 1163 // "If include reordering is harmful, put things in a different block and 1164 // _prepend that with a comment_ to prevent it" before changing behavior. 1165 ChromiumStyle.IncludeStyle.IncludeBlocks = 1166 tooling::IncludeStyle::IBS_Preserve; 1167 1168 if (Language == FormatStyle::LK_Java) { 1169 ChromiumStyle.AllowShortIfStatementsOnASingleLine = 1170 FormatStyle::SIS_WithoutElse; 1171 ChromiumStyle.BreakAfterJavaFieldAnnotations = true; 1172 ChromiumStyle.ContinuationIndentWidth = 8; 1173 ChromiumStyle.IndentWidth = 4; 1174 // See styleguide for import groups: 1175 // https://chromium.googlesource.com/chromium/src/+/master/styleguide/java/java.md#Import-Order 1176 ChromiumStyle.JavaImportGroups = { 1177 "android", 1178 "androidx", 1179 "com", 1180 "dalvik", 1181 "junit", 1182 "org", 1183 "com.google.android.apps.chrome", 1184 "org.chromium", 1185 "java", 1186 "javax", 1187 }; 1188 ChromiumStyle.SortIncludes = true; 1189 } else if (Language == FormatStyle::LK_JavaScript) { 1190 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1191 ChromiumStyle.AllowShortLoopsOnASingleLine = false; 1192 } else { 1193 ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false; 1194 ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 1195 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1196 ChromiumStyle.AllowShortLoopsOnASingleLine = false; 1197 ChromiumStyle.BinPackParameters = false; 1198 ChromiumStyle.DerivePointerAlignment = false; 1199 if (Language == FormatStyle::LK_ObjC) 1200 ChromiumStyle.ColumnLimit = 80; 1201 } 1202 return ChromiumStyle; 1203 } 1204 1205 FormatStyle getMozillaStyle() { 1206 FormatStyle MozillaStyle = getLLVMStyle(); 1207 MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false; 1208 MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 1209 MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel; 1210 MozillaStyle.AlwaysBreakAfterDefinitionReturnType = 1211 FormatStyle::DRTBS_TopLevel; 1212 MozillaStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; 1213 MozillaStyle.BinPackParameters = false; 1214 MozillaStyle.BinPackArguments = false; 1215 MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla; 1216 MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 1217 MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma; 1218 MozillaStyle.ConstructorInitializerIndentWidth = 2; 1219 MozillaStyle.ContinuationIndentWidth = 2; 1220 MozillaStyle.Cpp11BracedListStyle = false; 1221 MozillaStyle.FixNamespaceComments = false; 1222 MozillaStyle.IndentCaseLabels = true; 1223 MozillaStyle.ObjCSpaceAfterProperty = true; 1224 MozillaStyle.ObjCSpaceBeforeProtocolList = false; 1225 MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200; 1226 MozillaStyle.PointerAlignment = FormatStyle::PAS_Left; 1227 MozillaStyle.SpaceAfterTemplateKeyword = false; 1228 return MozillaStyle; 1229 } 1230 1231 FormatStyle getWebKitStyle() { 1232 FormatStyle Style = getLLVMStyle(); 1233 Style.AccessModifierOffset = -4; 1234 Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; 1235 Style.AlignOperands = FormatStyle::OAS_DontAlign; 1236 Style.AlignTrailingComments = false; 1237 Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty; 1238 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 1239 Style.BreakBeforeBraces = FormatStyle::BS_WebKit; 1240 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 1241 Style.Cpp11BracedListStyle = false; 1242 Style.ColumnLimit = 0; 1243 Style.FixNamespaceComments = false; 1244 Style.IndentWidth = 4; 1245 Style.NamespaceIndentation = FormatStyle::NI_Inner; 1246 Style.ObjCBlockIndentWidth = 4; 1247 Style.ObjCSpaceAfterProperty = true; 1248 Style.PointerAlignment = FormatStyle::PAS_Left; 1249 Style.SpaceBeforeCpp11BracedList = true; 1250 Style.SpaceInEmptyBlock = true; 1251 return Style; 1252 } 1253 1254 FormatStyle getGNUStyle() { 1255 FormatStyle Style = getLLVMStyle(); 1256 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; 1257 Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; 1258 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 1259 Style.BreakBeforeBraces = FormatStyle::BS_GNU; 1260 Style.BreakBeforeTernaryOperators = true; 1261 Style.Cpp11BracedListStyle = false; 1262 Style.ColumnLimit = 79; 1263 Style.FixNamespaceComments = false; 1264 Style.SpaceBeforeParens = FormatStyle::SBPO_Always; 1265 Style.Standard = FormatStyle::LS_Cpp03; 1266 return Style; 1267 } 1268 1269 FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) { 1270 FormatStyle Style = getLLVMStyle(Language); 1271 Style.ColumnLimit = 120; 1272 Style.TabWidth = 4; 1273 Style.IndentWidth = 4; 1274 Style.UseTab = FormatStyle::UT_Never; 1275 Style.BreakBeforeBraces = FormatStyle::BS_Custom; 1276 Style.BraceWrapping.AfterClass = true; 1277 Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; 1278 Style.BraceWrapping.AfterEnum = true; 1279 Style.BraceWrapping.AfterFunction = true; 1280 Style.BraceWrapping.AfterNamespace = true; 1281 Style.BraceWrapping.AfterObjCDeclaration = true; 1282 Style.BraceWrapping.AfterStruct = true; 1283 Style.BraceWrapping.AfterExternBlock = true; 1284 Style.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; 1285 Style.BraceWrapping.BeforeCatch = true; 1286 Style.BraceWrapping.BeforeElse = true; 1287 Style.BraceWrapping.BeforeWhile = false; 1288 Style.PenaltyReturnTypeOnItsOwnLine = 1000; 1289 Style.AllowShortEnumsOnASingleLine = false; 1290 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; 1291 Style.AllowShortCaseLabelsOnASingleLine = false; 1292 Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1293 Style.AllowShortLoopsOnASingleLine = false; 1294 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; 1295 Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; 1296 return Style; 1297 } 1298 1299 FormatStyle getNoStyle() { 1300 FormatStyle NoStyle = getLLVMStyle(); 1301 NoStyle.DisableFormat = true; 1302 NoStyle.SortIncludes = false; 1303 NoStyle.SortUsingDeclarations = false; 1304 return NoStyle; 1305 } 1306 1307 bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language, 1308 FormatStyle *Style) { 1309 if (Name.equals_lower("llvm")) { 1310 *Style = getLLVMStyle(Language); 1311 } else if (Name.equals_lower("chromium")) { 1312 *Style = getChromiumStyle(Language); 1313 } else if (Name.equals_lower("mozilla")) { 1314 *Style = getMozillaStyle(); 1315 } else if (Name.equals_lower("google")) { 1316 *Style = getGoogleStyle(Language); 1317 } else if (Name.equals_lower("webkit")) { 1318 *Style = getWebKitStyle(); 1319 } else if (Name.equals_lower("gnu")) { 1320 *Style = getGNUStyle(); 1321 } else if (Name.equals_lower("microsoft")) { 1322 *Style = getMicrosoftStyle(Language); 1323 } else if (Name.equals_lower("none")) { 1324 *Style = getNoStyle(); 1325 } else { 1326 return false; 1327 } 1328 1329 Style->Language = Language; 1330 return true; 1331 } 1332 1333 std::error_code parseConfiguration(llvm::MemoryBufferRef Config, 1334 FormatStyle *Style, 1335 bool AllowUnknownOptions) { 1336 assert(Style); 1337 FormatStyle::LanguageKind Language = Style->Language; 1338 assert(Language != FormatStyle::LK_None); 1339 if (Config.getBuffer().trim().empty()) 1340 return make_error_code(ParseError::Error); 1341 Style->StyleSet.Clear(); 1342 std::vector<FormatStyle> Styles; 1343 llvm::yaml::Input Input(Config); 1344 // DocumentListTraits<vector<FormatStyle>> uses the context to get default 1345 // values for the fields, keys for which are missing from the configuration. 1346 // Mapping also uses the context to get the language to find the correct 1347 // base style. 1348 Input.setContext(Style); 1349 Input.setAllowUnknownKeys(AllowUnknownOptions); 1350 Input >> Styles; 1351 if (Input.error()) 1352 return Input.error(); 1353 1354 for (unsigned i = 0; i < Styles.size(); ++i) { 1355 // Ensures that only the first configuration can skip the Language option. 1356 if (Styles[i].Language == FormatStyle::LK_None && i != 0) 1357 return make_error_code(ParseError::Error); 1358 // Ensure that each language is configured at most once. 1359 for (unsigned j = 0; j < i; ++j) { 1360 if (Styles[i].Language == Styles[j].Language) { 1361 LLVM_DEBUG(llvm::dbgs() 1362 << "Duplicate languages in the config file on positions " 1363 << j << " and " << i << "\n"); 1364 return make_error_code(ParseError::Error); 1365 } 1366 } 1367 } 1368 // Look for a suitable configuration starting from the end, so we can 1369 // find the configuration for the specific language first, and the default 1370 // configuration (which can only be at slot 0) after it. 1371 FormatStyle::FormatStyleSet StyleSet; 1372 bool LanguageFound = false; 1373 for (int i = Styles.size() - 1; i >= 0; --i) { 1374 if (Styles[i].Language != FormatStyle::LK_None) 1375 StyleSet.Add(Styles[i]); 1376 if (Styles[i].Language == Language) 1377 LanguageFound = true; 1378 } 1379 if (!LanguageFound) { 1380 if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None) 1381 return make_error_code(ParseError::Unsuitable); 1382 FormatStyle DefaultStyle = Styles[0]; 1383 DefaultStyle.Language = Language; 1384 StyleSet.Add(std::move(DefaultStyle)); 1385 } 1386 *Style = *StyleSet.Get(Language); 1387 if (Style->InsertTrailingCommas != FormatStyle::TCS_None && 1388 Style->BinPackArguments) { 1389 // See comment on FormatStyle::TSC_Wrapped. 1390 return make_error_code(ParseError::BinPackTrailingCommaConflict); 1391 } 1392 return make_error_code(ParseError::Success); 1393 } 1394 1395 std::string configurationAsText(const FormatStyle &Style) { 1396 std::string Text; 1397 llvm::raw_string_ostream Stream(Text); 1398 llvm::yaml::Output Output(Stream); 1399 // We use the same mapping method for input and output, so we need a non-const 1400 // reference here. 1401 FormatStyle NonConstStyle = expandPresets(Style); 1402 Output << NonConstStyle; 1403 return Stream.str(); 1404 } 1405 1406 llvm::Optional<FormatStyle> 1407 FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const { 1408 if (!Styles) 1409 return None; 1410 auto It = Styles->find(Language); 1411 if (It == Styles->end()) 1412 return None; 1413 FormatStyle Style = It->second; 1414 Style.StyleSet = *this; 1415 return Style; 1416 } 1417 1418 void FormatStyle::FormatStyleSet::Add(FormatStyle Style) { 1419 assert(Style.Language != LK_None && 1420 "Cannot add a style for LK_None to a StyleSet"); 1421 assert( 1422 !Style.StyleSet.Styles && 1423 "Cannot add a style associated with an existing StyleSet to a StyleSet"); 1424 if (!Styles) 1425 Styles = std::make_shared<MapType>(); 1426 (*Styles)[Style.Language] = std::move(Style); 1427 } 1428 1429 void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); } 1430 1431 llvm::Optional<FormatStyle> 1432 FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const { 1433 return StyleSet.Get(Language); 1434 } 1435 1436 namespace { 1437 1438 class JavaScriptRequoter : public TokenAnalyzer { 1439 public: 1440 JavaScriptRequoter(const Environment &Env, const FormatStyle &Style) 1441 : TokenAnalyzer(Env, Style) {} 1442 1443 std::pair<tooling::Replacements, unsigned> 1444 analyze(TokenAnnotator &Annotator, 1445 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1446 FormatTokenLexer &Tokens) override { 1447 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 1448 tooling::Replacements Result; 1449 requoteJSStringLiteral(AnnotatedLines, Result); 1450 return {Result, 0}; 1451 } 1452 1453 private: 1454 // Replaces double/single-quoted string literal as appropriate, re-escaping 1455 // the contents in the process. 1456 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines, 1457 tooling::Replacements &Result) { 1458 for (AnnotatedLine *Line : Lines) { 1459 requoteJSStringLiteral(Line->Children, Result); 1460 if (!Line->Affected) 1461 continue; 1462 for (FormatToken *FormatTok = Line->First; FormatTok; 1463 FormatTok = FormatTok->Next) { 1464 StringRef Input = FormatTok->TokenText; 1465 if (FormatTok->Finalized || !FormatTok->isStringLiteral() || 1466 // NB: testing for not starting with a double quote to avoid 1467 // breaking `template strings`. 1468 (Style.JavaScriptQuotes == FormatStyle::JSQS_Single && 1469 !Input.startswith("\"")) || 1470 (Style.JavaScriptQuotes == FormatStyle::JSQS_Double && 1471 !Input.startswith("\'"))) 1472 continue; 1473 1474 // Change start and end quote. 1475 bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single; 1476 SourceLocation Start = FormatTok->Tok.getLocation(); 1477 auto Replace = [&](SourceLocation Start, unsigned Length, 1478 StringRef ReplacementText) { 1479 auto Err = Result.add(tooling::Replacement( 1480 Env.getSourceManager(), Start, Length, ReplacementText)); 1481 // FIXME: handle error. For now, print error message and skip the 1482 // replacement for release version. 1483 if (Err) { 1484 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 1485 assert(false); 1486 } 1487 }; 1488 Replace(Start, 1, IsSingle ? "'" : "\""); 1489 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1, 1490 IsSingle ? "'" : "\""); 1491 1492 // Escape internal quotes. 1493 bool Escaped = false; 1494 for (size_t i = 1; i < Input.size() - 1; i++) { 1495 switch (Input[i]) { 1496 case '\\': 1497 if (!Escaped && i + 1 < Input.size() && 1498 ((IsSingle && Input[i + 1] == '"') || 1499 (!IsSingle && Input[i + 1] == '\''))) { 1500 // Remove this \, it's escaping a " or ' that no longer needs 1501 // escaping 1502 Replace(Start.getLocWithOffset(i), 1, ""); 1503 continue; 1504 } 1505 Escaped = !Escaped; 1506 break; 1507 case '\"': 1508 case '\'': 1509 if (!Escaped && IsSingle == (Input[i] == '\'')) { 1510 // Escape the quote. 1511 Replace(Start.getLocWithOffset(i), 0, "\\"); 1512 } 1513 Escaped = false; 1514 break; 1515 default: 1516 Escaped = false; 1517 break; 1518 } 1519 } 1520 } 1521 } 1522 } 1523 }; 1524 1525 class Formatter : public TokenAnalyzer { 1526 public: 1527 Formatter(const Environment &Env, const FormatStyle &Style, 1528 FormattingAttemptStatus *Status) 1529 : TokenAnalyzer(Env, Style), Status(Status) {} 1530 1531 std::pair<tooling::Replacements, unsigned> 1532 analyze(TokenAnnotator &Annotator, 1533 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1534 FormatTokenLexer &Tokens) override { 1535 tooling::Replacements Result; 1536 deriveLocalStyle(AnnotatedLines); 1537 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 1538 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1539 Annotator.calculateFormattingInformation(*AnnotatedLines[i]); 1540 } 1541 Annotator.setCommentLineLevels(AnnotatedLines); 1542 1543 WhitespaceManager Whitespaces( 1544 Env.getSourceManager(), Style, 1545 Style.DeriveLineEnding 1546 ? inputUsesCRLF( 1547 Env.getSourceManager().getBufferData(Env.getFileID()), 1548 Style.UseCRLF) 1549 : Style.UseCRLF); 1550 ContinuationIndenter Indenter(Style, Tokens.getKeywords(), 1551 Env.getSourceManager(), Whitespaces, Encoding, 1552 BinPackInconclusiveFunctions); 1553 unsigned Penalty = 1554 UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, 1555 Tokens.getKeywords(), Env.getSourceManager(), 1556 Status) 1557 .format(AnnotatedLines, /*DryRun=*/false, 1558 /*AdditionalIndent=*/0, 1559 /*FixBadIndentation=*/false, 1560 /*FirstStartColumn=*/Env.getFirstStartColumn(), 1561 /*NextStartColumn=*/Env.getNextStartColumn(), 1562 /*LastStartColumn=*/Env.getLastStartColumn()); 1563 for (const auto &R : Whitespaces.generateReplacements()) 1564 if (Result.add(R)) 1565 return std::make_pair(Result, 0); 1566 return std::make_pair(Result, Penalty); 1567 } 1568 1569 private: 1570 static bool inputUsesCRLF(StringRef Text, bool DefaultToCRLF) { 1571 size_t LF = Text.count('\n'); 1572 size_t CR = Text.count('\r') * 2; 1573 return LF == CR ? DefaultToCRLF : CR > LF; 1574 } 1575 1576 bool 1577 hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) { 1578 for (const AnnotatedLine *Line : Lines) { 1579 if (hasCpp03IncompatibleFormat(Line->Children)) 1580 return true; 1581 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) { 1582 if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) { 1583 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener)) 1584 return true; 1585 if (Tok->is(TT_TemplateCloser) && 1586 Tok->Previous->is(TT_TemplateCloser)) 1587 return true; 1588 } 1589 } 1590 } 1591 return false; 1592 } 1593 1594 int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) { 1595 int AlignmentDiff = 0; 1596 for (const AnnotatedLine *Line : Lines) { 1597 AlignmentDiff += countVariableAlignments(Line->Children); 1598 for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) { 1599 if (!Tok->is(TT_PointerOrReference)) 1600 continue; 1601 bool SpaceBefore = 1602 Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd(); 1603 bool SpaceAfter = Tok->Next->WhitespaceRange.getBegin() != 1604 Tok->Next->WhitespaceRange.getEnd(); 1605 if (SpaceBefore && !SpaceAfter) 1606 ++AlignmentDiff; 1607 if (!SpaceBefore && SpaceAfter) 1608 --AlignmentDiff; 1609 } 1610 } 1611 return AlignmentDiff; 1612 } 1613 1614 void 1615 deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 1616 bool HasBinPackedFunction = false; 1617 bool HasOnePerLineFunction = false; 1618 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1619 if (!AnnotatedLines[i]->First->Next) 1620 continue; 1621 FormatToken *Tok = AnnotatedLines[i]->First->Next; 1622 while (Tok->Next) { 1623 if (Tok->is(PPK_BinPacked)) 1624 HasBinPackedFunction = true; 1625 if (Tok->is(PPK_OnePerLine)) 1626 HasOnePerLineFunction = true; 1627 1628 Tok = Tok->Next; 1629 } 1630 } 1631 if (Style.DerivePointerAlignment) 1632 Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0 1633 ? FormatStyle::PAS_Left 1634 : FormatStyle::PAS_Right; 1635 if (Style.Standard == FormatStyle::LS_Auto) 1636 Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines) 1637 ? FormatStyle::LS_Latest 1638 : FormatStyle::LS_Cpp03; 1639 BinPackInconclusiveFunctions = 1640 HasBinPackedFunction || !HasOnePerLineFunction; 1641 } 1642 1643 bool BinPackInconclusiveFunctions; 1644 FormattingAttemptStatus *Status; 1645 }; 1646 1647 /// TrailingCommaInserter inserts trailing commas into container literals. 1648 /// E.g.: 1649 /// const x = [ 1650 /// 1, 1651 /// ]; 1652 /// TrailingCommaInserter runs after formatting. To avoid causing a required 1653 /// reformatting (and thus reflow), it never inserts a comma that'd exceed the 1654 /// ColumnLimit. 1655 /// 1656 /// Because trailing commas disable binpacking of arrays, TrailingCommaInserter 1657 /// is conceptually incompatible with bin packing. 1658 class TrailingCommaInserter : public TokenAnalyzer { 1659 public: 1660 TrailingCommaInserter(const Environment &Env, const FormatStyle &Style) 1661 : TokenAnalyzer(Env, Style) {} 1662 1663 std::pair<tooling::Replacements, unsigned> 1664 analyze(TokenAnnotator &Annotator, 1665 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1666 FormatTokenLexer &Tokens) override { 1667 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 1668 tooling::Replacements Result; 1669 insertTrailingCommas(AnnotatedLines, Result); 1670 return {Result, 0}; 1671 } 1672 1673 private: 1674 /// Inserts trailing commas in [] and {} initializers if they wrap over 1675 /// multiple lines. 1676 void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines, 1677 tooling::Replacements &Result) { 1678 for (AnnotatedLine *Line : Lines) { 1679 insertTrailingCommas(Line->Children, Result); 1680 if (!Line->Affected) 1681 continue; 1682 for (FormatToken *FormatTok = Line->First; FormatTok; 1683 FormatTok = FormatTok->Next) { 1684 if (FormatTok->NewlinesBefore == 0) 1685 continue; 1686 FormatToken *Matching = FormatTok->MatchingParen; 1687 if (!Matching || !FormatTok->getPreviousNonComment()) 1688 continue; 1689 if (!(FormatTok->is(tok::r_square) && 1690 Matching->is(TT_ArrayInitializerLSquare)) && 1691 !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) 1692 continue; 1693 FormatToken *Prev = FormatTok->getPreviousNonComment(); 1694 if (Prev->is(tok::comma) || Prev->is(tok::semi)) 1695 continue; 1696 // getEndLoc is not reliably set during re-lexing, use text length 1697 // instead. 1698 SourceLocation Start = 1699 Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size()); 1700 // If inserting a comma would push the code over the column limit, skip 1701 // this location - it'd introduce an unstable formatting due to the 1702 // required reflow. 1703 unsigned ColumnNumber = 1704 Env.getSourceManager().getSpellingColumnNumber(Start); 1705 if (ColumnNumber > Style.ColumnLimit) 1706 continue; 1707 // Comma insertions cannot conflict with each other, and this pass has a 1708 // clean set of Replacements, so the operation below cannot fail. 1709 cantFail(Result.add( 1710 tooling::Replacement(Env.getSourceManager(), Start, 0, ","))); 1711 } 1712 } 1713 } 1714 }; 1715 1716 // This class clean up the erroneous/redundant code around the given ranges in 1717 // file. 1718 class Cleaner : public TokenAnalyzer { 1719 public: 1720 Cleaner(const Environment &Env, const FormatStyle &Style) 1721 : TokenAnalyzer(Env, Style), 1722 DeletedTokens(FormatTokenLess(Env.getSourceManager())) {} 1723 1724 // FIXME: eliminate unused parameters. 1725 std::pair<tooling::Replacements, unsigned> 1726 analyze(TokenAnnotator &Annotator, 1727 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1728 FormatTokenLexer &Tokens) override { 1729 // FIXME: in the current implementation the granularity of affected range 1730 // is an annotated line. However, this is not sufficient. Furthermore, 1731 // redundant code introduced by replacements does not necessarily 1732 // intercept with ranges of replacements that result in the redundancy. 1733 // To determine if some redundant code is actually introduced by 1734 // replacements(e.g. deletions), we need to come up with a more 1735 // sophisticated way of computing affected ranges. 1736 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 1737 1738 checkEmptyNamespace(AnnotatedLines); 1739 1740 for (auto *Line : AnnotatedLines) 1741 cleanupLine(Line); 1742 1743 return {generateFixes(), 0}; 1744 } 1745 1746 private: 1747 void cleanupLine(AnnotatedLine *Line) { 1748 for (auto *Child : Line->Children) { 1749 cleanupLine(Child); 1750 } 1751 1752 if (Line->Affected) { 1753 cleanupRight(Line->First, tok::comma, tok::comma); 1754 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma); 1755 cleanupRight(Line->First, tok::l_paren, tok::comma); 1756 cleanupLeft(Line->First, tok::comma, tok::r_paren); 1757 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace); 1758 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace); 1759 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal); 1760 } 1761 } 1762 1763 bool containsOnlyComments(const AnnotatedLine &Line) { 1764 for (FormatToken *Tok = Line.First; Tok != nullptr; Tok = Tok->Next) { 1765 if (Tok->isNot(tok::comment)) 1766 return false; 1767 } 1768 return true; 1769 } 1770 1771 // Iterate through all lines and remove any empty (nested) namespaces. 1772 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 1773 std::set<unsigned> DeletedLines; 1774 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1775 auto &Line = *AnnotatedLines[i]; 1776 if (Line.startsWithNamespace()) { 1777 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines); 1778 } 1779 } 1780 1781 for (auto Line : DeletedLines) { 1782 FormatToken *Tok = AnnotatedLines[Line]->First; 1783 while (Tok) { 1784 deleteToken(Tok); 1785 Tok = Tok->Next; 1786 } 1787 } 1788 } 1789 1790 // The function checks if the namespace, which starts from \p CurrentLine, and 1791 // its nested namespaces are empty and delete them if they are empty. It also 1792 // sets \p NewLine to the last line checked. 1793 // Returns true if the current namespace is empty. 1794 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1795 unsigned CurrentLine, unsigned &NewLine, 1796 std::set<unsigned> &DeletedLines) { 1797 unsigned InitLine = CurrentLine, End = AnnotatedLines.size(); 1798 if (Style.BraceWrapping.AfterNamespace) { 1799 // If the left brace is in a new line, we should consume it first so that 1800 // it does not make the namespace non-empty. 1801 // FIXME: error handling if there is no left brace. 1802 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) { 1803 NewLine = CurrentLine; 1804 return false; 1805 } 1806 } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) { 1807 return false; 1808 } 1809 while (++CurrentLine < End) { 1810 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace)) 1811 break; 1812 1813 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) { 1814 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine, 1815 DeletedLines)) 1816 return false; 1817 CurrentLine = NewLine; 1818 continue; 1819 } 1820 1821 if (containsOnlyComments(*AnnotatedLines[CurrentLine])) 1822 continue; 1823 1824 // If there is anything other than comments or nested namespaces in the 1825 // current namespace, the namespace cannot be empty. 1826 NewLine = CurrentLine; 1827 return false; 1828 } 1829 1830 NewLine = CurrentLine; 1831 if (CurrentLine >= End) 1832 return false; 1833 1834 // Check if the empty namespace is actually affected by changed ranges. 1835 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange( 1836 AnnotatedLines[InitLine]->First->Tok.getLocation(), 1837 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) 1838 return false; 1839 1840 for (unsigned i = InitLine; i <= CurrentLine; ++i) { 1841 DeletedLines.insert(i); 1842 } 1843 1844 return true; 1845 } 1846 1847 // Checks pairs {start, start->next},..., {end->previous, end} and deletes one 1848 // of the token in the pair if the left token has \p LK token kind and the 1849 // right token has \p RK token kind. If \p DeleteLeft is true, the left token 1850 // is deleted on match; otherwise, the right token is deleted. 1851 template <typename LeftKind, typename RightKind> 1852 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK, 1853 bool DeleteLeft) { 1854 auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * { 1855 for (auto *Res = Tok.Next; Res; Res = Res->Next) 1856 if (!Res->is(tok::comment) && 1857 DeletedTokens.find(Res) == DeletedTokens.end()) 1858 return Res; 1859 return nullptr; 1860 }; 1861 for (auto *Left = Start; Left;) { 1862 auto *Right = NextNotDeleted(*Left); 1863 if (!Right) 1864 break; 1865 if (Left->is(LK) && Right->is(RK)) { 1866 deleteToken(DeleteLeft ? Left : Right); 1867 for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next) 1868 deleteToken(Tok); 1869 // If the right token is deleted, we should keep the left token 1870 // unchanged and pair it with the new right token. 1871 if (!DeleteLeft) 1872 continue; 1873 } 1874 Left = Right; 1875 } 1876 } 1877 1878 template <typename LeftKind, typename RightKind> 1879 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) { 1880 cleanupPair(Start, LK, RK, /*DeleteLeft=*/true); 1881 } 1882 1883 template <typename LeftKind, typename RightKind> 1884 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) { 1885 cleanupPair(Start, LK, RK, /*DeleteLeft=*/false); 1886 } 1887 1888 // Delete the given token. 1889 inline void deleteToken(FormatToken *Tok) { 1890 if (Tok) 1891 DeletedTokens.insert(Tok); 1892 } 1893 1894 tooling::Replacements generateFixes() { 1895 tooling::Replacements Fixes; 1896 std::vector<FormatToken *> Tokens; 1897 std::copy(DeletedTokens.begin(), DeletedTokens.end(), 1898 std::back_inserter(Tokens)); 1899 1900 // Merge multiple continuous token deletions into one big deletion so that 1901 // the number of replacements can be reduced. This makes computing affected 1902 // ranges more efficient when we run reformat on the changed code. 1903 unsigned Idx = 0; 1904 while (Idx < Tokens.size()) { 1905 unsigned St = Idx, End = Idx; 1906 while ((End + 1) < Tokens.size() && 1907 Tokens[End]->Next == Tokens[End + 1]) { 1908 End++; 1909 } 1910 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(), 1911 Tokens[End]->Tok.getEndLoc()); 1912 auto Err = 1913 Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, "")); 1914 // FIXME: better error handling. for now just print error message and skip 1915 // for the release version. 1916 if (Err) { 1917 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 1918 assert(false && "Fixes must not conflict!"); 1919 } 1920 Idx = End + 1; 1921 } 1922 1923 return Fixes; 1924 } 1925 1926 // Class for less-than inequality comparason for the set `RedundantTokens`. 1927 // We store tokens in the order they appear in the translation unit so that 1928 // we do not need to sort them in `generateFixes()`. 1929 struct FormatTokenLess { 1930 FormatTokenLess(const SourceManager &SM) : SM(SM) {} 1931 1932 bool operator()(const FormatToken *LHS, const FormatToken *RHS) const { 1933 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(), 1934 RHS->Tok.getLocation()); 1935 } 1936 const SourceManager &SM; 1937 }; 1938 1939 // Tokens to be deleted. 1940 std::set<FormatToken *, FormatTokenLess> DeletedTokens; 1941 }; 1942 1943 class ObjCHeaderStyleGuesser : public TokenAnalyzer { 1944 public: 1945 ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style) 1946 : TokenAnalyzer(Env, Style), IsObjC(false) {} 1947 1948 std::pair<tooling::Replacements, unsigned> 1949 analyze(TokenAnnotator &Annotator, 1950 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1951 FormatTokenLexer &Tokens) override { 1952 assert(Style.Language == FormatStyle::LK_Cpp); 1953 IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines, 1954 Tokens.getKeywords()); 1955 tooling::Replacements Result; 1956 return {Result, 0}; 1957 } 1958 1959 bool isObjC() { return IsObjC; } 1960 1961 private: 1962 static bool 1963 guessIsObjC(const SourceManager &SourceManager, 1964 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1965 const AdditionalKeywords &Keywords) { 1966 // Keep this array sorted, since we are binary searching over it. 1967 static constexpr llvm::StringLiteral FoundationIdentifiers[] = { 1968 "CGFloat", 1969 "CGPoint", 1970 "CGPointMake", 1971 "CGPointZero", 1972 "CGRect", 1973 "CGRectEdge", 1974 "CGRectInfinite", 1975 "CGRectMake", 1976 "CGRectNull", 1977 "CGRectZero", 1978 "CGSize", 1979 "CGSizeMake", 1980 "CGVector", 1981 "CGVectorMake", 1982 "NSAffineTransform", 1983 "NSArray", 1984 "NSAttributedString", 1985 "NSBlockOperation", 1986 "NSBundle", 1987 "NSCache", 1988 "NSCalendar", 1989 "NSCharacterSet", 1990 "NSCountedSet", 1991 "NSData", 1992 "NSDataDetector", 1993 "NSDecimal", 1994 "NSDecimalNumber", 1995 "NSDictionary", 1996 "NSEdgeInsets", 1997 "NSHashTable", 1998 "NSIndexPath", 1999 "NSIndexSet", 2000 "NSInteger", 2001 "NSInvocationOperation", 2002 "NSLocale", 2003 "NSMapTable", 2004 "NSMutableArray", 2005 "NSMutableAttributedString", 2006 "NSMutableCharacterSet", 2007 "NSMutableData", 2008 "NSMutableDictionary", 2009 "NSMutableIndexSet", 2010 "NSMutableOrderedSet", 2011 "NSMutableSet", 2012 "NSMutableString", 2013 "NSNumber", 2014 "NSNumberFormatter", 2015 "NSObject", 2016 "NSOperation", 2017 "NSOperationQueue", 2018 "NSOperationQueuePriority", 2019 "NSOrderedSet", 2020 "NSPoint", 2021 "NSPointerArray", 2022 "NSQualityOfService", 2023 "NSRange", 2024 "NSRect", 2025 "NSRegularExpression", 2026 "NSSet", 2027 "NSSize", 2028 "NSString", 2029 "NSTimeZone", 2030 "NSUInteger", 2031 "NSURL", 2032 "NSURLComponents", 2033 "NSURLQueryItem", 2034 "NSUUID", 2035 "NSValue", 2036 "UIImage", 2037 "UIView", 2038 }; 2039 2040 for (auto Line : AnnotatedLines) { 2041 if (Line->First && (Line->First->TokenText.startswith("#") || 2042 Line->First->TokenText == "__pragma" || 2043 Line->First->TokenText == "_Pragma")) 2044 continue; 2045 for (const FormatToken *FormatTok = Line->First; FormatTok; 2046 FormatTok = FormatTok->Next) { 2047 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) && 2048 (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword || 2049 FormatTok->isOneOf(tok::numeric_constant, tok::l_square, 2050 tok::l_brace))) || 2051 (FormatTok->Tok.isAnyIdentifier() && 2052 std::binary_search(std::begin(FoundationIdentifiers), 2053 std::end(FoundationIdentifiers), 2054 FormatTok->TokenText)) || 2055 FormatTok->is(TT_ObjCStringLiteral) || 2056 FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM, 2057 Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace, 2058 TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn, 2059 TT_ObjCMethodExpr, TT_ObjCMethodSpecifier, 2060 TT_ObjCProperty)) { 2061 LLVM_DEBUG(llvm::dbgs() 2062 << "Detected ObjC at location " 2063 << FormatTok->Tok.getLocation().printToString( 2064 SourceManager) 2065 << " token: " << FormatTok->TokenText << " token type: " 2066 << getTokenTypeName(FormatTok->getType()) << "\n"); 2067 return true; 2068 } 2069 if (guessIsObjC(SourceManager, Line->Children, Keywords)) 2070 return true; 2071 } 2072 } 2073 return false; 2074 } 2075 2076 bool IsObjC; 2077 }; 2078 2079 struct IncludeDirective { 2080 StringRef Filename; 2081 StringRef Text; 2082 unsigned Offset; 2083 int Category; 2084 int Priority; 2085 }; 2086 2087 struct JavaImportDirective { 2088 StringRef Identifier; 2089 StringRef Text; 2090 unsigned Offset; 2091 std::vector<StringRef> AssociatedCommentLines; 2092 bool IsStatic; 2093 }; 2094 2095 } // end anonymous namespace 2096 2097 // Determines whether 'Ranges' intersects with ('Start', 'End'). 2098 static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start, 2099 unsigned End) { 2100 for (auto Range : Ranges) { 2101 if (Range.getOffset() < End && 2102 Range.getOffset() + Range.getLength() > Start) 2103 return true; 2104 } 2105 return false; 2106 } 2107 2108 // Returns a pair (Index, OffsetToEOL) describing the position of the cursor 2109 // before sorting/deduplicating. Index is the index of the include under the 2110 // cursor in the original set of includes. If this include has duplicates, it is 2111 // the index of the first of the duplicates as the others are going to be 2112 // removed. OffsetToEOL describes the cursor's position relative to the end of 2113 // its current line. 2114 // If `Cursor` is not on any #include, `Index` will be UINT_MAX. 2115 static std::pair<unsigned, unsigned> 2116 FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes, 2117 const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) { 2118 unsigned CursorIndex = UINT_MAX; 2119 unsigned OffsetToEOL = 0; 2120 for (int i = 0, e = Includes.size(); i != e; ++i) { 2121 unsigned Start = Includes[Indices[i]].Offset; 2122 unsigned End = Start + Includes[Indices[i]].Text.size(); 2123 if (!(Cursor >= Start && Cursor < End)) 2124 continue; 2125 CursorIndex = Indices[i]; 2126 OffsetToEOL = End - Cursor; 2127 // Put the cursor on the only remaining #include among the duplicate 2128 // #includes. 2129 while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text) 2130 CursorIndex = i; 2131 break; 2132 } 2133 return std::make_pair(CursorIndex, OffsetToEOL); 2134 } 2135 2136 // Replace all "\r\n" with "\n". 2137 std::string replaceCRLF(const std::string &Code) { 2138 std::string NewCode; 2139 size_t Pos = 0, LastPos = 0; 2140 2141 do { 2142 Pos = Code.find("\r\n", LastPos); 2143 if (Pos == LastPos) { 2144 LastPos++; 2145 continue; 2146 } 2147 if (Pos == std::string::npos) { 2148 NewCode += Code.substr(LastPos); 2149 break; 2150 } 2151 NewCode += Code.substr(LastPos, Pos - LastPos) + "\n"; 2152 LastPos = Pos + 2; 2153 } while (Pos != std::string::npos); 2154 2155 return NewCode; 2156 } 2157 2158 // Sorts and deduplicate a block of includes given by 'Includes' alphabetically 2159 // adding the necessary replacement to 'Replaces'. 'Includes' must be in strict 2160 // source order. 2161 // #include directives with the same text will be deduplicated, and only the 2162 // first #include in the duplicate #includes remains. If the `Cursor` is 2163 // provided and put on a deleted #include, it will be moved to the remaining 2164 // #include in the duplicate #includes. 2165 static void sortCppIncludes(const FormatStyle &Style, 2166 const SmallVectorImpl<IncludeDirective> &Includes, 2167 ArrayRef<tooling::Range> Ranges, StringRef FileName, 2168 StringRef Code, tooling::Replacements &Replaces, 2169 unsigned *Cursor) { 2170 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 2171 unsigned IncludesBeginOffset = Includes.front().Offset; 2172 unsigned IncludesEndOffset = 2173 Includes.back().Offset + Includes.back().Text.size(); 2174 unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset; 2175 if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset)) 2176 return; 2177 SmallVector<unsigned, 16> Indices; 2178 for (unsigned i = 0, e = Includes.size(); i != e; ++i) { 2179 Indices.push_back(i); 2180 } 2181 llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 2182 return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) < 2183 std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename); 2184 }); 2185 // The index of the include on which the cursor will be put after 2186 // sorting/deduplicating. 2187 unsigned CursorIndex; 2188 // The offset from cursor to the end of line. 2189 unsigned CursorToEOLOffset; 2190 if (Cursor) 2191 std::tie(CursorIndex, CursorToEOLOffset) = 2192 FindCursorIndex(Includes, Indices, *Cursor); 2193 2194 // Deduplicate #includes. 2195 Indices.erase(std::unique(Indices.begin(), Indices.end(), 2196 [&](unsigned LHSI, unsigned RHSI) { 2197 return Includes[LHSI].Text.trim() == 2198 Includes[RHSI].Text.trim(); 2199 }), 2200 Indices.end()); 2201 2202 int CurrentCategory = Includes.front().Category; 2203 2204 // If the #includes are out of order, we generate a single replacement fixing 2205 // the entire block. Otherwise, no replacement is generated. 2206 // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not 2207 // enough as additional newlines might be added or removed across #include 2208 // blocks. This we handle below by generating the updated #imclude blocks and 2209 // comparing it to the original. 2210 if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) && 2211 Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) 2212 return; 2213 2214 std::string result; 2215 for (unsigned Index : Indices) { 2216 if (!result.empty()) { 2217 result += "\n"; 2218 if (Style.IncludeStyle.IncludeBlocks == 2219 tooling::IncludeStyle::IBS_Regroup && 2220 CurrentCategory != Includes[Index].Category) 2221 result += "\n"; 2222 } 2223 result += Includes[Index].Text; 2224 if (Cursor && CursorIndex == Index) 2225 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset; 2226 CurrentCategory = Includes[Index].Category; 2227 } 2228 2229 // If the #includes are out of order, we generate a single replacement fixing 2230 // the entire range of blocks. Otherwise, no replacement is generated. 2231 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 2232 IncludesBeginOffset, IncludesBlockSize)))) 2233 return; 2234 2235 auto Err = Replaces.add(tooling::Replacement( 2236 FileName, Includes.front().Offset, IncludesBlockSize, result)); 2237 // FIXME: better error handling. For now, just skip the replacement for the 2238 // release version. 2239 if (Err) { 2240 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 2241 assert(false); 2242 } 2243 } 2244 2245 namespace { 2246 2247 const char CppIncludeRegexPattern[] = 2248 R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))"; 2249 2250 } // anonymous namespace 2251 2252 tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code, 2253 ArrayRef<tooling::Range> Ranges, 2254 StringRef FileName, 2255 tooling::Replacements &Replaces, 2256 unsigned *Cursor) { 2257 unsigned Prev = llvm::StringSwitch<size_t>(Code) 2258 .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM 2259 .Default(0); 2260 unsigned SearchFrom = 0; 2261 llvm::Regex IncludeRegex(CppIncludeRegexPattern); 2262 SmallVector<StringRef, 4> Matches; 2263 SmallVector<IncludeDirective, 16> IncludesInBlock; 2264 2265 // In compiled files, consider the first #include to be the main #include of 2266 // the file if it is not a system #include. This ensures that the header 2267 // doesn't have hidden dependencies 2268 // (http://llvm.org/docs/CodingStandards.html#include-style). 2269 // 2270 // FIXME: Do some sanity checking, e.g. edit distance of the base name, to fix 2271 // cases where the first #include is unlikely to be the main header. 2272 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 2273 bool FirstIncludeBlock = true; 2274 bool MainIncludeFound = false; 2275 bool FormattingOff = false; 2276 2277 for (;;) { 2278 auto Pos = Code.find('\n', SearchFrom); 2279 StringRef Line = 2280 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 2281 2282 StringRef Trimmed = Line.trim(); 2283 if (Trimmed == "// clang-format off" || Trimmed == "/* clang-format off */") 2284 FormattingOff = true; 2285 else if (Trimmed == "// clang-format on" || 2286 Trimmed == "/* clang-format on */") 2287 FormattingOff = false; 2288 2289 const bool EmptyLineSkipped = 2290 Trimmed.empty() && 2291 (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge || 2292 Style.IncludeStyle.IncludeBlocks == 2293 tooling::IncludeStyle::IBS_Regroup); 2294 2295 bool MergeWithNextLine = Trimmed.endswith("\\"); 2296 if (!FormattingOff && !MergeWithNextLine) { 2297 if (IncludeRegex.match(Line, &Matches)) { 2298 StringRef IncludeName = Matches[2]; 2299 int Category = Categories.getIncludePriority( 2300 IncludeName, 2301 /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock); 2302 int Priority = Categories.getSortIncludePriority( 2303 IncludeName, !MainIncludeFound && FirstIncludeBlock); 2304 if (Category == 0) 2305 MainIncludeFound = true; 2306 IncludesInBlock.push_back( 2307 {IncludeName, Line, Prev, Category, Priority}); 2308 } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) { 2309 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, 2310 Replaces, Cursor); 2311 IncludesInBlock.clear(); 2312 if (Trimmed.startswith("#pragma hdrstop")) // Precompiled headers. 2313 FirstIncludeBlock = true; 2314 else 2315 FirstIncludeBlock = false; 2316 } 2317 } 2318 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 2319 break; 2320 2321 if (!MergeWithNextLine) 2322 Prev = Pos + 1; 2323 SearchFrom = Pos + 1; 2324 } 2325 if (!IncludesInBlock.empty()) { 2326 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces, 2327 Cursor); 2328 } 2329 return Replaces; 2330 } 2331 2332 // Returns group number to use as a first order sort on imports. Gives UINT_MAX 2333 // if the import does not match any given groups. 2334 static unsigned findJavaImportGroup(const FormatStyle &Style, 2335 StringRef ImportIdentifier) { 2336 unsigned LongestMatchIndex = UINT_MAX; 2337 unsigned LongestMatchLength = 0; 2338 for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) { 2339 std::string GroupPrefix = Style.JavaImportGroups[I]; 2340 if (ImportIdentifier.startswith(GroupPrefix) && 2341 GroupPrefix.length() > LongestMatchLength) { 2342 LongestMatchIndex = I; 2343 LongestMatchLength = GroupPrefix.length(); 2344 } 2345 } 2346 return LongestMatchIndex; 2347 } 2348 2349 // Sorts and deduplicates a block of includes given by 'Imports' based on 2350 // JavaImportGroups, then adding the necessary replacement to 'Replaces'. 2351 // Import declarations with the same text will be deduplicated. Between each 2352 // import group, a newline is inserted, and within each import group, a 2353 // lexicographic sort based on ASCII value is performed. 2354 static void sortJavaImports(const FormatStyle &Style, 2355 const SmallVectorImpl<JavaImportDirective> &Imports, 2356 ArrayRef<tooling::Range> Ranges, StringRef FileName, 2357 StringRef Code, tooling::Replacements &Replaces) { 2358 unsigned ImportsBeginOffset = Imports.front().Offset; 2359 unsigned ImportsEndOffset = 2360 Imports.back().Offset + Imports.back().Text.size(); 2361 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset; 2362 if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset)) 2363 return; 2364 SmallVector<unsigned, 16> Indices; 2365 SmallVector<unsigned, 16> JavaImportGroups; 2366 for (unsigned i = 0, e = Imports.size(); i != e; ++i) { 2367 Indices.push_back(i); 2368 JavaImportGroups.push_back( 2369 findJavaImportGroup(Style, Imports[i].Identifier)); 2370 } 2371 bool StaticImportAfterNormalImport = 2372 Style.SortJavaStaticImport == FormatStyle::SJSIO_After; 2373 llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 2374 // Negating IsStatic to push static imports above non-static imports. 2375 return std::make_tuple(!Imports[LHSI].IsStatic ^ 2376 StaticImportAfterNormalImport, 2377 JavaImportGroups[LHSI], Imports[LHSI].Identifier) < 2378 std::make_tuple(!Imports[RHSI].IsStatic ^ 2379 StaticImportAfterNormalImport, 2380 JavaImportGroups[RHSI], Imports[RHSI].Identifier); 2381 }); 2382 2383 // Deduplicate imports. 2384 Indices.erase(std::unique(Indices.begin(), Indices.end(), 2385 [&](unsigned LHSI, unsigned RHSI) { 2386 return Imports[LHSI].Text == Imports[RHSI].Text; 2387 }), 2388 Indices.end()); 2389 2390 bool CurrentIsStatic = Imports[Indices.front()].IsStatic; 2391 unsigned CurrentImportGroup = JavaImportGroups[Indices.front()]; 2392 2393 std::string result; 2394 for (unsigned Index : Indices) { 2395 if (!result.empty()) { 2396 result += "\n"; 2397 if (CurrentIsStatic != Imports[Index].IsStatic || 2398 CurrentImportGroup != JavaImportGroups[Index]) 2399 result += "\n"; 2400 } 2401 for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) { 2402 result += CommentLine; 2403 result += "\n"; 2404 } 2405 result += Imports[Index].Text; 2406 CurrentIsStatic = Imports[Index].IsStatic; 2407 CurrentImportGroup = JavaImportGroups[Index]; 2408 } 2409 2410 // If the imports are out of order, we generate a single replacement fixing 2411 // the entire block. Otherwise, no replacement is generated. 2412 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 2413 Imports.front().Offset, ImportsBlockSize)))) 2414 return; 2415 2416 auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset, 2417 ImportsBlockSize, result)); 2418 // FIXME: better error handling. For now, just skip the replacement for the 2419 // release version. 2420 if (Err) { 2421 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 2422 assert(false); 2423 } 2424 } 2425 2426 namespace { 2427 2428 const char JavaImportRegexPattern[] = 2429 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;"; 2430 2431 } // anonymous namespace 2432 2433 tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code, 2434 ArrayRef<tooling::Range> Ranges, 2435 StringRef FileName, 2436 tooling::Replacements &Replaces) { 2437 unsigned Prev = 0; 2438 unsigned SearchFrom = 0; 2439 llvm::Regex ImportRegex(JavaImportRegexPattern); 2440 SmallVector<StringRef, 4> Matches; 2441 SmallVector<JavaImportDirective, 16> ImportsInBlock; 2442 std::vector<StringRef> AssociatedCommentLines; 2443 2444 bool FormattingOff = false; 2445 2446 for (;;) { 2447 auto Pos = Code.find('\n', SearchFrom); 2448 StringRef Line = 2449 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 2450 2451 StringRef Trimmed = Line.trim(); 2452 if (Trimmed == "// clang-format off") 2453 FormattingOff = true; 2454 else if (Trimmed == "// clang-format on") 2455 FormattingOff = false; 2456 2457 if (ImportRegex.match(Line, &Matches)) { 2458 if (FormattingOff) { 2459 // If at least one import line has formatting turned off, turn off 2460 // formatting entirely. 2461 return Replaces; 2462 } 2463 StringRef Static = Matches[1]; 2464 StringRef Identifier = Matches[2]; 2465 bool IsStatic = false; 2466 if (Static.contains("static")) { 2467 IsStatic = true; 2468 } 2469 ImportsInBlock.push_back( 2470 {Identifier, Line, Prev, AssociatedCommentLines, IsStatic}); 2471 AssociatedCommentLines.clear(); 2472 } else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) { 2473 // Associating comments within the imports with the nearest import below 2474 AssociatedCommentLines.push_back(Line); 2475 } 2476 Prev = Pos + 1; 2477 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 2478 break; 2479 SearchFrom = Pos + 1; 2480 } 2481 if (!ImportsInBlock.empty()) 2482 sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces); 2483 return Replaces; 2484 } 2485 2486 bool isMpegTS(StringRef Code) { 2487 // MPEG transport streams use the ".ts" file extension. clang-format should 2488 // not attempt to format those. MPEG TS' frame format starts with 0x47 every 2489 // 189 bytes - detect that and return. 2490 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47; 2491 } 2492 2493 bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); } 2494 2495 tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, 2496 ArrayRef<tooling::Range> Ranges, 2497 StringRef FileName, unsigned *Cursor) { 2498 tooling::Replacements Replaces; 2499 if (!Style.SortIncludes) 2500 return Replaces; 2501 if (isLikelyXml(Code)) 2502 return Replaces; 2503 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript && 2504 isMpegTS(Code)) 2505 return Replaces; 2506 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript) 2507 return sortJavaScriptImports(Style, Code, Ranges, FileName); 2508 if (Style.Language == FormatStyle::LanguageKind::LK_Java) 2509 return sortJavaImports(Style, Code, Ranges, FileName, Replaces); 2510 sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor); 2511 return Replaces; 2512 } 2513 2514 template <typename T> 2515 static llvm::Expected<tooling::Replacements> 2516 processReplacements(T ProcessFunc, StringRef Code, 2517 const tooling::Replacements &Replaces, 2518 const FormatStyle &Style) { 2519 if (Replaces.empty()) 2520 return tooling::Replacements(); 2521 2522 auto NewCode = applyAllReplacements(Code, Replaces); 2523 if (!NewCode) 2524 return NewCode.takeError(); 2525 std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges(); 2526 StringRef FileName = Replaces.begin()->getFilePath(); 2527 2528 tooling::Replacements FormatReplaces = 2529 ProcessFunc(Style, *NewCode, ChangedRanges, FileName); 2530 2531 return Replaces.merge(FormatReplaces); 2532 } 2533 2534 llvm::Expected<tooling::Replacements> 2535 formatReplacements(StringRef Code, const tooling::Replacements &Replaces, 2536 const FormatStyle &Style) { 2537 // We need to use lambda function here since there are two versions of 2538 // `sortIncludes`. 2539 auto SortIncludes = [](const FormatStyle &Style, StringRef Code, 2540 std::vector<tooling::Range> Ranges, 2541 StringRef FileName) -> tooling::Replacements { 2542 return sortIncludes(Style, Code, Ranges, FileName); 2543 }; 2544 auto SortedReplaces = 2545 processReplacements(SortIncludes, Code, Replaces, Style); 2546 if (!SortedReplaces) 2547 return SortedReplaces.takeError(); 2548 2549 // We need to use lambda function here since there are two versions of 2550 // `reformat`. 2551 auto Reformat = [](const FormatStyle &Style, StringRef Code, 2552 std::vector<tooling::Range> Ranges, 2553 StringRef FileName) -> tooling::Replacements { 2554 return reformat(Style, Code, Ranges, FileName); 2555 }; 2556 return processReplacements(Reformat, Code, *SortedReplaces, Style); 2557 } 2558 2559 namespace { 2560 2561 inline bool isHeaderInsertion(const tooling::Replacement &Replace) { 2562 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 && 2563 llvm::Regex(CppIncludeRegexPattern) 2564 .match(Replace.getReplacementText()); 2565 } 2566 2567 inline bool isHeaderDeletion(const tooling::Replacement &Replace) { 2568 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1; 2569 } 2570 2571 // FIXME: insert empty lines between newly created blocks. 2572 tooling::Replacements 2573 fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces, 2574 const FormatStyle &Style) { 2575 if (!Style.isCpp()) 2576 return Replaces; 2577 2578 tooling::Replacements HeaderInsertions; 2579 std::set<llvm::StringRef> HeadersToDelete; 2580 tooling::Replacements Result; 2581 for (const auto &R : Replaces) { 2582 if (isHeaderInsertion(R)) { 2583 // Replacements from \p Replaces must be conflict-free already, so we can 2584 // simply consume the error. 2585 llvm::consumeError(HeaderInsertions.add(R)); 2586 } else if (isHeaderDeletion(R)) { 2587 HeadersToDelete.insert(R.getReplacementText()); 2588 } else if (R.getOffset() == UINT_MAX) { 2589 llvm::errs() << "Insertions other than header #include insertion are " 2590 "not supported! " 2591 << R.getReplacementText() << "\n"; 2592 } else { 2593 llvm::consumeError(Result.add(R)); 2594 } 2595 } 2596 if (HeaderInsertions.empty() && HeadersToDelete.empty()) 2597 return Replaces; 2598 2599 StringRef FileName = Replaces.begin()->getFilePath(); 2600 tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle); 2601 2602 for (const auto &Header : HeadersToDelete) { 2603 tooling::Replacements Replaces = 2604 Includes.remove(Header.trim("\"<>"), Header.startswith("<")); 2605 for (const auto &R : Replaces) { 2606 auto Err = Result.add(R); 2607 if (Err) { 2608 // Ignore the deletion on conflict. 2609 llvm::errs() << "Failed to add header deletion replacement for " 2610 << Header << ": " << llvm::toString(std::move(Err)) 2611 << "\n"; 2612 } 2613 } 2614 } 2615 2616 llvm::Regex IncludeRegex = llvm::Regex(CppIncludeRegexPattern); 2617 llvm::SmallVector<StringRef, 4> Matches; 2618 for (const auto &R : HeaderInsertions) { 2619 auto IncludeDirective = R.getReplacementText(); 2620 bool Matched = IncludeRegex.match(IncludeDirective, &Matches); 2621 assert(Matched && "Header insertion replacement must have replacement text " 2622 "'#include ...'"); 2623 (void)Matched; 2624 auto IncludeName = Matches[2]; 2625 auto Replace = 2626 Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<")); 2627 if (Replace) { 2628 auto Err = Result.add(*Replace); 2629 if (Err) { 2630 llvm::consumeError(std::move(Err)); 2631 unsigned NewOffset = 2632 Result.getShiftedCodePosition(Replace->getOffset()); 2633 auto Shifted = tooling::Replacement(FileName, NewOffset, 0, 2634 Replace->getReplacementText()); 2635 Result = Result.merge(tooling::Replacements(Shifted)); 2636 } 2637 } 2638 } 2639 return Result; 2640 } 2641 2642 } // anonymous namespace 2643 2644 llvm::Expected<tooling::Replacements> 2645 cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, 2646 const FormatStyle &Style) { 2647 // We need to use lambda function here since there are two versions of 2648 // `cleanup`. 2649 auto Cleanup = [](const FormatStyle &Style, StringRef Code, 2650 std::vector<tooling::Range> Ranges, 2651 StringRef FileName) -> tooling::Replacements { 2652 return cleanup(Style, Code, Ranges, FileName); 2653 }; 2654 // Make header insertion replacements insert new headers into correct blocks. 2655 tooling::Replacements NewReplaces = 2656 fixCppIncludeInsertions(Code, Replaces, Style); 2657 return processReplacements(Cleanup, Code, NewReplaces, Style); 2658 } 2659 2660 namespace internal { 2661 std::pair<tooling::Replacements, unsigned> 2662 reformat(const FormatStyle &Style, StringRef Code, 2663 ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn, 2664 unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName, 2665 FormattingAttemptStatus *Status) { 2666 FormatStyle Expanded = expandPresets(Style); 2667 if (Expanded.DisableFormat) 2668 return {tooling::Replacements(), 0}; 2669 if (isLikelyXml(Code)) 2670 return {tooling::Replacements(), 0}; 2671 if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code)) 2672 return {tooling::Replacements(), 0}; 2673 2674 typedef std::function<std::pair<tooling::Replacements, unsigned>( 2675 const Environment &)> 2676 AnalyzerPass; 2677 SmallVector<AnalyzerPass, 4> Passes; 2678 2679 if (Style.Language == FormatStyle::LK_Cpp) { 2680 if (Style.FixNamespaceComments) 2681 Passes.emplace_back([&](const Environment &Env) { 2682 return NamespaceEndCommentsFixer(Env, Expanded).process(); 2683 }); 2684 2685 if (Style.SortUsingDeclarations) 2686 Passes.emplace_back([&](const Environment &Env) { 2687 return UsingDeclarationsSorter(Env, Expanded).process(); 2688 }); 2689 } 2690 2691 if (Style.Language == FormatStyle::LK_JavaScript && 2692 Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) 2693 Passes.emplace_back([&](const Environment &Env) { 2694 return JavaScriptRequoter(Env, Expanded).process(); 2695 }); 2696 2697 Passes.emplace_back([&](const Environment &Env) { 2698 return Formatter(Env, Expanded, Status).process(); 2699 }); 2700 2701 if (Style.Language == FormatStyle::LK_JavaScript && 2702 Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) 2703 Passes.emplace_back([&](const Environment &Env) { 2704 return TrailingCommaInserter(Env, Expanded).process(); 2705 }); 2706 2707 auto Env = 2708 std::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn, 2709 NextStartColumn, LastStartColumn); 2710 llvm::Optional<std::string> CurrentCode = None; 2711 tooling::Replacements Fixes; 2712 unsigned Penalty = 0; 2713 for (size_t I = 0, E = Passes.size(); I < E; ++I) { 2714 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env); 2715 auto NewCode = applyAllReplacements( 2716 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first); 2717 if (NewCode) { 2718 Fixes = Fixes.merge(PassFixes.first); 2719 Penalty += PassFixes.second; 2720 if (I + 1 < E) { 2721 CurrentCode = std::move(*NewCode); 2722 Env = std::make_unique<Environment>( 2723 *CurrentCode, FileName, 2724 tooling::calculateRangesAfterReplacements(Fixes, Ranges), 2725 FirstStartColumn, NextStartColumn, LastStartColumn); 2726 } 2727 } 2728 } 2729 2730 return {Fixes, Penalty}; 2731 } 2732 } // namespace internal 2733 2734 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 2735 ArrayRef<tooling::Range> Ranges, 2736 StringRef FileName, 2737 FormattingAttemptStatus *Status) { 2738 return internal::reformat(Style, Code, Ranges, 2739 /*FirstStartColumn=*/0, 2740 /*NextStartColumn=*/0, 2741 /*LastStartColumn=*/0, FileName, Status) 2742 .first; 2743 } 2744 2745 tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, 2746 ArrayRef<tooling::Range> Ranges, 2747 StringRef FileName) { 2748 // cleanups only apply to C++ (they mostly concern ctor commas etc.) 2749 if (Style.Language != FormatStyle::LK_Cpp) 2750 return tooling::Replacements(); 2751 return Cleaner(Environment(Code, FileName, Ranges), Style).process().first; 2752 } 2753 2754 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 2755 ArrayRef<tooling::Range> Ranges, 2756 StringRef FileName, bool *IncompleteFormat) { 2757 FormattingAttemptStatus Status; 2758 auto Result = reformat(Style, Code, Ranges, FileName, &Status); 2759 if (!Status.FormatComplete) 2760 *IncompleteFormat = true; 2761 return Result; 2762 } 2763 2764 tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, 2765 StringRef Code, 2766 ArrayRef<tooling::Range> Ranges, 2767 StringRef FileName) { 2768 return NamespaceEndCommentsFixer(Environment(Code, FileName, Ranges), Style) 2769 .process() 2770 .first; 2771 } 2772 2773 tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, 2774 StringRef Code, 2775 ArrayRef<tooling::Range> Ranges, 2776 StringRef FileName) { 2777 return UsingDeclarationsSorter(Environment(Code, FileName, Ranges), Style) 2778 .process() 2779 .first; 2780 } 2781 2782 LangOptions getFormattingLangOpts(const FormatStyle &Style) { 2783 LangOptions LangOpts; 2784 2785 FormatStyle::LanguageStandard LexingStd = Style.Standard; 2786 if (LexingStd == FormatStyle::LS_Auto) 2787 LexingStd = FormatStyle::LS_Latest; 2788 if (LexingStd == FormatStyle::LS_Latest) 2789 LexingStd = FormatStyle::LS_Cpp20; 2790 LangOpts.CPlusPlus = 1; 2791 LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11; 2792 LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14; 2793 LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17; 2794 LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20; 2795 LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20; 2796 2797 LangOpts.LineComment = 1; 2798 bool AlternativeOperators = Style.isCpp(); 2799 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0; 2800 LangOpts.Bool = 1; 2801 LangOpts.ObjC = 1; 2802 LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally. 2803 LangOpts.DeclSpecKeyword = 1; // To get __declspec. 2804 LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict. 2805 return LangOpts; 2806 } 2807 2808 const char *StyleOptionHelpDescription = 2809 "Coding style, currently supports:\n" 2810 " LLVM, GNU, Google, Chromium, Microsoft, Mozilla, WebKit.\n" 2811 "Use -style=file to load style configuration from\n" 2812 ".clang-format file located in one of the parent\n" 2813 "directories of the source file (or current\n" 2814 "directory for stdin).\n" 2815 "Use -style=\"{key: value, ...}\" to set specific\n" 2816 "parameters, e.g.:\n" 2817 " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""; 2818 2819 static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) { 2820 if (FileName.endswith(".java")) 2821 return FormatStyle::LK_Java; 2822 if (FileName.endswith_lower(".js") || FileName.endswith_lower(".mjs") || 2823 FileName.endswith_lower(".ts")) 2824 return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript. 2825 if (FileName.endswith(".m") || FileName.endswith(".mm")) 2826 return FormatStyle::LK_ObjC; 2827 if (FileName.endswith_lower(".proto") || 2828 FileName.endswith_lower(".protodevel")) 2829 return FormatStyle::LK_Proto; 2830 if (FileName.endswith_lower(".textpb") || 2831 FileName.endswith_lower(".pb.txt") || 2832 FileName.endswith_lower(".textproto") || 2833 FileName.endswith_lower(".asciipb")) 2834 return FormatStyle::LK_TextProto; 2835 if (FileName.endswith_lower(".td")) 2836 return FormatStyle::LK_TableGen; 2837 if (FileName.endswith_lower(".cs")) 2838 return FormatStyle::LK_CSharp; 2839 return FormatStyle::LK_Cpp; 2840 } 2841 2842 FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) { 2843 const auto GuessedLanguage = getLanguageByFileName(FileName); 2844 if (GuessedLanguage == FormatStyle::LK_Cpp) { 2845 auto Extension = llvm::sys::path::extension(FileName); 2846 // If there's no file extension (or it's .h), we need to check the contents 2847 // of the code to see if it contains Objective-C. 2848 if (Extension.empty() || Extension == ".h") { 2849 auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName; 2850 Environment Env(Code, NonEmptyFileName, /*Ranges=*/{}); 2851 ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle()); 2852 Guesser.process(); 2853 if (Guesser.isObjC()) 2854 return FormatStyle::LK_ObjC; 2855 } 2856 } 2857 return GuessedLanguage; 2858 } 2859 2860 const char *DefaultFormatStyle = "file"; 2861 2862 const char *DefaultFallbackStyle = "LLVM"; 2863 2864 llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, 2865 StringRef FallbackStyleName, 2866 StringRef Code, llvm::vfs::FileSystem *FS, 2867 bool AllowUnknownOptions) { 2868 if (!FS) { 2869 FS = llvm::vfs::getRealFileSystem().get(); 2870 } 2871 FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code)); 2872 2873 FormatStyle FallbackStyle = getNoStyle(); 2874 if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle)) 2875 return make_string_error("Invalid fallback style \"" + FallbackStyleName); 2876 2877 if (StyleName.startswith("{")) { 2878 // Parse YAML/JSON style from the command line. 2879 if (std::error_code ec = parseConfiguration( 2880 llvm::MemoryBufferRef(StyleName, "<command-line>"), &Style, 2881 AllowUnknownOptions)) 2882 return make_string_error("Error parsing -style: " + ec.message()); 2883 return Style; 2884 } 2885 2886 if (!StyleName.equals_lower("file")) { 2887 if (!getPredefinedStyle(StyleName, Style.Language, &Style)) 2888 return make_string_error("Invalid value for -style"); 2889 return Style; 2890 } 2891 2892 // Look for .clang-format/_clang-format file in the file's parent directories. 2893 SmallString<128> UnsuitableConfigFiles; 2894 SmallString<128> Path(FileName); 2895 if (std::error_code EC = FS->makeAbsolute(Path)) 2896 return make_string_error(EC.message()); 2897 2898 llvm::SmallVector<std::string, 2> FilesToLookFor; 2899 FilesToLookFor.push_back(".clang-format"); 2900 FilesToLookFor.push_back("_clang-format"); 2901 2902 for (StringRef Directory = Path; !Directory.empty(); 2903 Directory = llvm::sys::path::parent_path(Directory)) { 2904 2905 auto Status = FS->status(Directory); 2906 if (!Status || 2907 Status->getType() != llvm::sys::fs::file_type::directory_file) { 2908 continue; 2909 } 2910 2911 for (const auto &F : FilesToLookFor) { 2912 SmallString<128> ConfigFile(Directory); 2913 2914 llvm::sys::path::append(ConfigFile, F); 2915 LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); 2916 2917 Status = FS->status(ConfigFile.str()); 2918 2919 if (Status && 2920 (Status->getType() == llvm::sys::fs::file_type::regular_file)) { 2921 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 2922 FS->getBufferForFile(ConfigFile.str()); 2923 if (std::error_code EC = Text.getError()) 2924 return make_string_error(EC.message()); 2925 if (std::error_code ec = 2926 parseConfiguration(*Text.get(), &Style, AllowUnknownOptions)) { 2927 if (ec == ParseError::Unsuitable) { 2928 if (!UnsuitableConfigFiles.empty()) 2929 UnsuitableConfigFiles.append(", "); 2930 UnsuitableConfigFiles.append(ConfigFile); 2931 continue; 2932 } 2933 return make_string_error("Error reading " + ConfigFile + ": " + 2934 ec.message()); 2935 } 2936 LLVM_DEBUG(llvm::dbgs() 2937 << "Using configuration file " << ConfigFile << "\n"); 2938 return Style; 2939 } 2940 } 2941 } 2942 if (!UnsuitableConfigFiles.empty()) 2943 return make_string_error("Configuration file(s) do(es) not support " + 2944 getLanguageName(Style.Language) + ": " + 2945 UnsuitableConfigFiles); 2946 return FallbackStyle; 2947 } 2948 2949 } // namespace format 2950 } // namespace clang 2951