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