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