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 = 0; 2257 unsigned SearchFrom = 0; 2258 llvm::Regex IncludeRegex(CppIncludeRegexPattern); 2259 SmallVector<StringRef, 4> Matches; 2260 SmallVector<IncludeDirective, 16> IncludesInBlock; 2261 2262 // In compiled files, consider the first #include to be the main #include of 2263 // the file if it is not a system #include. This ensures that the header 2264 // doesn't have hidden dependencies 2265 // (http://llvm.org/docs/CodingStandards.html#include-style). 2266 // 2267 // FIXME: Do some sanity checking, e.g. edit distance of the base name, to fix 2268 // cases where the first #include is unlikely to be the main header. 2269 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 2270 bool FirstIncludeBlock = true; 2271 bool MainIncludeFound = false; 2272 bool FormattingOff = false; 2273 2274 for (;;) { 2275 auto Pos = Code.find('\n', SearchFrom); 2276 StringRef Line = 2277 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 2278 2279 StringRef Trimmed = Line.trim(); 2280 if (Trimmed == "// clang-format off" || Trimmed == "/* clang-format off */") 2281 FormattingOff = true; 2282 else if (Trimmed == "// clang-format on" || 2283 Trimmed == "/* clang-format on */") 2284 FormattingOff = false; 2285 2286 const bool EmptyLineSkipped = 2287 Trimmed.empty() && 2288 (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge || 2289 Style.IncludeStyle.IncludeBlocks == 2290 tooling::IncludeStyle::IBS_Regroup); 2291 2292 if (!FormattingOff && !Line.endswith("\\")) { 2293 if (IncludeRegex.match(Line, &Matches)) { 2294 StringRef IncludeName = Matches[2]; 2295 int Category = Categories.getIncludePriority( 2296 IncludeName, 2297 /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock); 2298 int Priority = Categories.getSortIncludePriority( 2299 IncludeName, !MainIncludeFound && FirstIncludeBlock); 2300 if (Category == 0) 2301 MainIncludeFound = true; 2302 IncludesInBlock.push_back( 2303 {IncludeName, Line, Prev, Category, Priority}); 2304 } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) { 2305 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, 2306 Replaces, Cursor); 2307 IncludesInBlock.clear(); 2308 FirstIncludeBlock = false; 2309 } 2310 Prev = Pos + 1; 2311 } 2312 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 2313 break; 2314 SearchFrom = Pos + 1; 2315 } 2316 if (!IncludesInBlock.empty()) { 2317 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces, 2318 Cursor); 2319 } 2320 return Replaces; 2321 } 2322 2323 // Returns group number to use as a first order sort on imports. Gives UINT_MAX 2324 // if the import does not match any given groups. 2325 static unsigned findJavaImportGroup(const FormatStyle &Style, 2326 StringRef ImportIdentifier) { 2327 unsigned LongestMatchIndex = UINT_MAX; 2328 unsigned LongestMatchLength = 0; 2329 for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) { 2330 std::string GroupPrefix = Style.JavaImportGroups[I]; 2331 if (ImportIdentifier.startswith(GroupPrefix) && 2332 GroupPrefix.length() > LongestMatchLength) { 2333 LongestMatchIndex = I; 2334 LongestMatchLength = GroupPrefix.length(); 2335 } 2336 } 2337 return LongestMatchIndex; 2338 } 2339 2340 // Sorts and deduplicates a block of includes given by 'Imports' based on 2341 // JavaImportGroups, then adding the necessary replacement to 'Replaces'. 2342 // Import declarations with the same text will be deduplicated. Between each 2343 // import group, a newline is inserted, and within each import group, a 2344 // lexicographic sort based on ASCII value is performed. 2345 static void sortJavaImports(const FormatStyle &Style, 2346 const SmallVectorImpl<JavaImportDirective> &Imports, 2347 ArrayRef<tooling::Range> Ranges, StringRef FileName, 2348 StringRef Code, tooling::Replacements &Replaces) { 2349 unsigned ImportsBeginOffset = Imports.front().Offset; 2350 unsigned ImportsEndOffset = 2351 Imports.back().Offset + Imports.back().Text.size(); 2352 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset; 2353 if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset)) 2354 return; 2355 SmallVector<unsigned, 16> Indices; 2356 SmallVector<unsigned, 16> JavaImportGroups; 2357 for (unsigned i = 0, e = Imports.size(); i != e; ++i) { 2358 Indices.push_back(i); 2359 JavaImportGroups.push_back( 2360 findJavaImportGroup(Style, Imports[i].Identifier)); 2361 } 2362 bool StaticImportAfterNormalImport = 2363 Style.SortJavaStaticImport == FormatStyle::SJSIO_After; 2364 llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 2365 // Negating IsStatic to push static imports above non-static imports. 2366 return std::make_tuple(!Imports[LHSI].IsStatic ^ 2367 StaticImportAfterNormalImport, 2368 JavaImportGroups[LHSI], Imports[LHSI].Identifier) < 2369 std::make_tuple(!Imports[RHSI].IsStatic ^ 2370 StaticImportAfterNormalImport, 2371 JavaImportGroups[RHSI], Imports[RHSI].Identifier); 2372 }); 2373 2374 // Deduplicate imports. 2375 Indices.erase(std::unique(Indices.begin(), Indices.end(), 2376 [&](unsigned LHSI, unsigned RHSI) { 2377 return Imports[LHSI].Text == Imports[RHSI].Text; 2378 }), 2379 Indices.end()); 2380 2381 bool CurrentIsStatic = Imports[Indices.front()].IsStatic; 2382 unsigned CurrentImportGroup = JavaImportGroups[Indices.front()]; 2383 2384 std::string result; 2385 for (unsigned Index : Indices) { 2386 if (!result.empty()) { 2387 result += "\n"; 2388 if (CurrentIsStatic != Imports[Index].IsStatic || 2389 CurrentImportGroup != JavaImportGroups[Index]) 2390 result += "\n"; 2391 } 2392 for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) { 2393 result += CommentLine; 2394 result += "\n"; 2395 } 2396 result += Imports[Index].Text; 2397 CurrentIsStatic = Imports[Index].IsStatic; 2398 CurrentImportGroup = JavaImportGroups[Index]; 2399 } 2400 2401 // If the imports are out of order, we generate a single replacement fixing 2402 // the entire block. Otherwise, no replacement is generated. 2403 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 2404 Imports.front().Offset, ImportsBlockSize)))) 2405 return; 2406 2407 auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset, 2408 ImportsBlockSize, result)); 2409 // FIXME: better error handling. For now, just skip the replacement for the 2410 // release version. 2411 if (Err) { 2412 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 2413 assert(false); 2414 } 2415 } 2416 2417 namespace { 2418 2419 const char JavaImportRegexPattern[] = 2420 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;"; 2421 2422 } // anonymous namespace 2423 2424 tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code, 2425 ArrayRef<tooling::Range> Ranges, 2426 StringRef FileName, 2427 tooling::Replacements &Replaces) { 2428 unsigned Prev = 0; 2429 unsigned SearchFrom = 0; 2430 llvm::Regex ImportRegex(JavaImportRegexPattern); 2431 SmallVector<StringRef, 4> Matches; 2432 SmallVector<JavaImportDirective, 16> ImportsInBlock; 2433 std::vector<StringRef> AssociatedCommentLines; 2434 2435 bool FormattingOff = false; 2436 2437 for (;;) { 2438 auto Pos = Code.find('\n', SearchFrom); 2439 StringRef Line = 2440 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 2441 2442 StringRef Trimmed = Line.trim(); 2443 if (Trimmed == "// clang-format off") 2444 FormattingOff = true; 2445 else if (Trimmed == "// clang-format on") 2446 FormattingOff = false; 2447 2448 if (ImportRegex.match(Line, &Matches)) { 2449 if (FormattingOff) { 2450 // If at least one import line has formatting turned off, turn off 2451 // formatting entirely. 2452 return Replaces; 2453 } 2454 StringRef Static = Matches[1]; 2455 StringRef Identifier = Matches[2]; 2456 bool IsStatic = false; 2457 if (Static.contains("static")) { 2458 IsStatic = true; 2459 } 2460 ImportsInBlock.push_back( 2461 {Identifier, Line, Prev, AssociatedCommentLines, IsStatic}); 2462 AssociatedCommentLines.clear(); 2463 } else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) { 2464 // Associating comments within the imports with the nearest import below 2465 AssociatedCommentLines.push_back(Line); 2466 } 2467 Prev = Pos + 1; 2468 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 2469 break; 2470 SearchFrom = Pos + 1; 2471 } 2472 if (!ImportsInBlock.empty()) 2473 sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces); 2474 return Replaces; 2475 } 2476 2477 bool isMpegTS(StringRef Code) { 2478 // MPEG transport streams use the ".ts" file extension. clang-format should 2479 // not attempt to format those. MPEG TS' frame format starts with 0x47 every 2480 // 189 bytes - detect that and return. 2481 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47; 2482 } 2483 2484 bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); } 2485 2486 tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, 2487 ArrayRef<tooling::Range> Ranges, 2488 StringRef FileName, unsigned *Cursor) { 2489 tooling::Replacements Replaces; 2490 if (!Style.SortIncludes) 2491 return Replaces; 2492 if (isLikelyXml(Code)) 2493 return Replaces; 2494 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript && 2495 isMpegTS(Code)) 2496 return Replaces; 2497 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript) 2498 return sortJavaScriptImports(Style, Code, Ranges, FileName); 2499 if (Style.Language == FormatStyle::LanguageKind::LK_Java) 2500 return sortJavaImports(Style, Code, Ranges, FileName, Replaces); 2501 sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor); 2502 return Replaces; 2503 } 2504 2505 template <typename T> 2506 static llvm::Expected<tooling::Replacements> 2507 processReplacements(T ProcessFunc, StringRef Code, 2508 const tooling::Replacements &Replaces, 2509 const FormatStyle &Style) { 2510 if (Replaces.empty()) 2511 return tooling::Replacements(); 2512 2513 auto NewCode = applyAllReplacements(Code, Replaces); 2514 if (!NewCode) 2515 return NewCode.takeError(); 2516 std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges(); 2517 StringRef FileName = Replaces.begin()->getFilePath(); 2518 2519 tooling::Replacements FormatReplaces = 2520 ProcessFunc(Style, *NewCode, ChangedRanges, FileName); 2521 2522 return Replaces.merge(FormatReplaces); 2523 } 2524 2525 llvm::Expected<tooling::Replacements> 2526 formatReplacements(StringRef Code, const tooling::Replacements &Replaces, 2527 const FormatStyle &Style) { 2528 // We need to use lambda function here since there are two versions of 2529 // `sortIncludes`. 2530 auto SortIncludes = [](const FormatStyle &Style, StringRef Code, 2531 std::vector<tooling::Range> Ranges, 2532 StringRef FileName) -> tooling::Replacements { 2533 return sortIncludes(Style, Code, Ranges, FileName); 2534 }; 2535 auto SortedReplaces = 2536 processReplacements(SortIncludes, Code, Replaces, Style); 2537 if (!SortedReplaces) 2538 return SortedReplaces.takeError(); 2539 2540 // We need to use lambda function here since there are two versions of 2541 // `reformat`. 2542 auto Reformat = [](const FormatStyle &Style, StringRef Code, 2543 std::vector<tooling::Range> Ranges, 2544 StringRef FileName) -> tooling::Replacements { 2545 return reformat(Style, Code, Ranges, FileName); 2546 }; 2547 return processReplacements(Reformat, Code, *SortedReplaces, Style); 2548 } 2549 2550 namespace { 2551 2552 inline bool isHeaderInsertion(const tooling::Replacement &Replace) { 2553 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 && 2554 llvm::Regex(CppIncludeRegexPattern) 2555 .match(Replace.getReplacementText()); 2556 } 2557 2558 inline bool isHeaderDeletion(const tooling::Replacement &Replace) { 2559 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1; 2560 } 2561 2562 // FIXME: insert empty lines between newly created blocks. 2563 tooling::Replacements 2564 fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces, 2565 const FormatStyle &Style) { 2566 if (!Style.isCpp()) 2567 return Replaces; 2568 2569 tooling::Replacements HeaderInsertions; 2570 std::set<llvm::StringRef> HeadersToDelete; 2571 tooling::Replacements Result; 2572 for (const auto &R : Replaces) { 2573 if (isHeaderInsertion(R)) { 2574 // Replacements from \p Replaces must be conflict-free already, so we can 2575 // simply consume the error. 2576 llvm::consumeError(HeaderInsertions.add(R)); 2577 } else if (isHeaderDeletion(R)) { 2578 HeadersToDelete.insert(R.getReplacementText()); 2579 } else if (R.getOffset() == UINT_MAX) { 2580 llvm::errs() << "Insertions other than header #include insertion are " 2581 "not supported! " 2582 << R.getReplacementText() << "\n"; 2583 } else { 2584 llvm::consumeError(Result.add(R)); 2585 } 2586 } 2587 if (HeaderInsertions.empty() && HeadersToDelete.empty()) 2588 return Replaces; 2589 2590 StringRef FileName = Replaces.begin()->getFilePath(); 2591 tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle); 2592 2593 for (const auto &Header : HeadersToDelete) { 2594 tooling::Replacements Replaces = 2595 Includes.remove(Header.trim("\"<>"), Header.startswith("<")); 2596 for (const auto &R : Replaces) { 2597 auto Err = Result.add(R); 2598 if (Err) { 2599 // Ignore the deletion on conflict. 2600 llvm::errs() << "Failed to add header deletion replacement for " 2601 << Header << ": " << llvm::toString(std::move(Err)) 2602 << "\n"; 2603 } 2604 } 2605 } 2606 2607 llvm::Regex IncludeRegex = llvm::Regex(CppIncludeRegexPattern); 2608 llvm::SmallVector<StringRef, 4> Matches; 2609 for (const auto &R : HeaderInsertions) { 2610 auto IncludeDirective = R.getReplacementText(); 2611 bool Matched = IncludeRegex.match(IncludeDirective, &Matches); 2612 assert(Matched && "Header insertion replacement must have replacement text " 2613 "'#include ...'"); 2614 (void)Matched; 2615 auto IncludeName = Matches[2]; 2616 auto Replace = 2617 Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<")); 2618 if (Replace) { 2619 auto Err = Result.add(*Replace); 2620 if (Err) { 2621 llvm::consumeError(std::move(Err)); 2622 unsigned NewOffset = 2623 Result.getShiftedCodePosition(Replace->getOffset()); 2624 auto Shifted = tooling::Replacement(FileName, NewOffset, 0, 2625 Replace->getReplacementText()); 2626 Result = Result.merge(tooling::Replacements(Shifted)); 2627 } 2628 } 2629 } 2630 return Result; 2631 } 2632 2633 } // anonymous namespace 2634 2635 llvm::Expected<tooling::Replacements> 2636 cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, 2637 const FormatStyle &Style) { 2638 // We need to use lambda function here since there are two versions of 2639 // `cleanup`. 2640 auto Cleanup = [](const FormatStyle &Style, StringRef Code, 2641 std::vector<tooling::Range> Ranges, 2642 StringRef FileName) -> tooling::Replacements { 2643 return cleanup(Style, Code, Ranges, FileName); 2644 }; 2645 // Make header insertion replacements insert new headers into correct blocks. 2646 tooling::Replacements NewReplaces = 2647 fixCppIncludeInsertions(Code, Replaces, Style); 2648 return processReplacements(Cleanup, Code, NewReplaces, Style); 2649 } 2650 2651 namespace internal { 2652 std::pair<tooling::Replacements, unsigned> 2653 reformat(const FormatStyle &Style, StringRef Code, 2654 ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn, 2655 unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName, 2656 FormattingAttemptStatus *Status) { 2657 FormatStyle Expanded = expandPresets(Style); 2658 if (Expanded.DisableFormat) 2659 return {tooling::Replacements(), 0}; 2660 if (isLikelyXml(Code)) 2661 return {tooling::Replacements(), 0}; 2662 if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code)) 2663 return {tooling::Replacements(), 0}; 2664 2665 typedef std::function<std::pair<tooling::Replacements, unsigned>( 2666 const Environment &)> 2667 AnalyzerPass; 2668 SmallVector<AnalyzerPass, 4> Passes; 2669 2670 if (Style.Language == FormatStyle::LK_Cpp) { 2671 if (Style.FixNamespaceComments) 2672 Passes.emplace_back([&](const Environment &Env) { 2673 return NamespaceEndCommentsFixer(Env, Expanded).process(); 2674 }); 2675 2676 if (Style.SortUsingDeclarations) 2677 Passes.emplace_back([&](const Environment &Env) { 2678 return UsingDeclarationsSorter(Env, Expanded).process(); 2679 }); 2680 } 2681 2682 if (Style.Language == FormatStyle::LK_JavaScript && 2683 Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) 2684 Passes.emplace_back([&](const Environment &Env) { 2685 return JavaScriptRequoter(Env, Expanded).process(); 2686 }); 2687 2688 Passes.emplace_back([&](const Environment &Env) { 2689 return Formatter(Env, Expanded, Status).process(); 2690 }); 2691 2692 if (Style.Language == FormatStyle::LK_JavaScript && 2693 Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) 2694 Passes.emplace_back([&](const Environment &Env) { 2695 return TrailingCommaInserter(Env, Expanded).process(); 2696 }); 2697 2698 auto Env = 2699 std::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn, 2700 NextStartColumn, LastStartColumn); 2701 llvm::Optional<std::string> CurrentCode = None; 2702 tooling::Replacements Fixes; 2703 unsigned Penalty = 0; 2704 for (size_t I = 0, E = Passes.size(); I < E; ++I) { 2705 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env); 2706 auto NewCode = applyAllReplacements( 2707 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first); 2708 if (NewCode) { 2709 Fixes = Fixes.merge(PassFixes.first); 2710 Penalty += PassFixes.second; 2711 if (I + 1 < E) { 2712 CurrentCode = std::move(*NewCode); 2713 Env = std::make_unique<Environment>( 2714 *CurrentCode, FileName, 2715 tooling::calculateRangesAfterReplacements(Fixes, Ranges), 2716 FirstStartColumn, NextStartColumn, LastStartColumn); 2717 } 2718 } 2719 } 2720 2721 return {Fixes, Penalty}; 2722 } 2723 } // namespace internal 2724 2725 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 2726 ArrayRef<tooling::Range> Ranges, 2727 StringRef FileName, 2728 FormattingAttemptStatus *Status) { 2729 return internal::reformat(Style, Code, Ranges, 2730 /*FirstStartColumn=*/0, 2731 /*NextStartColumn=*/0, 2732 /*LastStartColumn=*/0, FileName, Status) 2733 .first; 2734 } 2735 2736 tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, 2737 ArrayRef<tooling::Range> Ranges, 2738 StringRef FileName) { 2739 // cleanups only apply to C++ (they mostly concern ctor commas etc.) 2740 if (Style.Language != FormatStyle::LK_Cpp) 2741 return tooling::Replacements(); 2742 return Cleaner(Environment(Code, FileName, Ranges), Style).process().first; 2743 } 2744 2745 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 2746 ArrayRef<tooling::Range> Ranges, 2747 StringRef FileName, bool *IncompleteFormat) { 2748 FormattingAttemptStatus Status; 2749 auto Result = reformat(Style, Code, Ranges, FileName, &Status); 2750 if (!Status.FormatComplete) 2751 *IncompleteFormat = true; 2752 return Result; 2753 } 2754 2755 tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, 2756 StringRef Code, 2757 ArrayRef<tooling::Range> Ranges, 2758 StringRef FileName) { 2759 return NamespaceEndCommentsFixer(Environment(Code, FileName, Ranges), Style) 2760 .process() 2761 .first; 2762 } 2763 2764 tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, 2765 StringRef Code, 2766 ArrayRef<tooling::Range> Ranges, 2767 StringRef FileName) { 2768 return UsingDeclarationsSorter(Environment(Code, FileName, Ranges), Style) 2769 .process() 2770 .first; 2771 } 2772 2773 LangOptions getFormattingLangOpts(const FormatStyle &Style) { 2774 LangOptions LangOpts; 2775 2776 FormatStyle::LanguageStandard LexingStd = Style.Standard; 2777 if (LexingStd == FormatStyle::LS_Auto) 2778 LexingStd = FormatStyle::LS_Latest; 2779 if (LexingStd == FormatStyle::LS_Latest) 2780 LexingStd = FormatStyle::LS_Cpp20; 2781 LangOpts.CPlusPlus = 1; 2782 LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11; 2783 LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14; 2784 LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17; 2785 LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20; 2786 LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20; 2787 2788 LangOpts.LineComment = 1; 2789 bool AlternativeOperators = Style.isCpp(); 2790 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0; 2791 LangOpts.Bool = 1; 2792 LangOpts.ObjC = 1; 2793 LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally. 2794 LangOpts.DeclSpecKeyword = 1; // To get __declspec. 2795 LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict. 2796 return LangOpts; 2797 } 2798 2799 const char *StyleOptionHelpDescription = 2800 "Coding style, currently supports:\n" 2801 " LLVM, GNU, Google, Chromium, Microsoft, Mozilla, WebKit.\n" 2802 "Use -style=file to load style configuration from\n" 2803 ".clang-format file located in one of the parent\n" 2804 "directories of the source file (or current\n" 2805 "directory for stdin).\n" 2806 "Use -style=\"{key: value, ...}\" to set specific\n" 2807 "parameters, e.g.:\n" 2808 " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""; 2809 2810 static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) { 2811 if (FileName.endswith(".java")) 2812 return FormatStyle::LK_Java; 2813 if (FileName.endswith_lower(".js") || FileName.endswith_lower(".mjs") || 2814 FileName.endswith_lower(".ts")) 2815 return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript. 2816 if (FileName.endswith(".m") || FileName.endswith(".mm")) 2817 return FormatStyle::LK_ObjC; 2818 if (FileName.endswith_lower(".proto") || 2819 FileName.endswith_lower(".protodevel")) 2820 return FormatStyle::LK_Proto; 2821 if (FileName.endswith_lower(".textpb") || 2822 FileName.endswith_lower(".pb.txt") || 2823 FileName.endswith_lower(".textproto") || 2824 FileName.endswith_lower(".asciipb")) 2825 return FormatStyle::LK_TextProto; 2826 if (FileName.endswith_lower(".td")) 2827 return FormatStyle::LK_TableGen; 2828 if (FileName.endswith_lower(".cs")) 2829 return FormatStyle::LK_CSharp; 2830 return FormatStyle::LK_Cpp; 2831 } 2832 2833 FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) { 2834 const auto GuessedLanguage = getLanguageByFileName(FileName); 2835 if (GuessedLanguage == FormatStyle::LK_Cpp) { 2836 auto Extension = llvm::sys::path::extension(FileName); 2837 // If there's no file extension (or it's .h), we need to check the contents 2838 // of the code to see if it contains Objective-C. 2839 if (Extension.empty() || Extension == ".h") { 2840 auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName; 2841 Environment Env(Code, NonEmptyFileName, /*Ranges=*/{}); 2842 ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle()); 2843 Guesser.process(); 2844 if (Guesser.isObjC()) 2845 return FormatStyle::LK_ObjC; 2846 } 2847 } 2848 return GuessedLanguage; 2849 } 2850 2851 const char *DefaultFormatStyle = "file"; 2852 2853 const char *DefaultFallbackStyle = "LLVM"; 2854 2855 llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, 2856 StringRef FallbackStyleName, 2857 StringRef Code, llvm::vfs::FileSystem *FS, 2858 bool AllowUnknownOptions) { 2859 if (!FS) { 2860 FS = llvm::vfs::getRealFileSystem().get(); 2861 } 2862 FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code)); 2863 2864 FormatStyle FallbackStyle = getNoStyle(); 2865 if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle)) 2866 return make_string_error("Invalid fallback style \"" + FallbackStyleName); 2867 2868 if (StyleName.startswith("{")) { 2869 // Parse YAML/JSON style from the command line. 2870 if (std::error_code ec = parseConfiguration( 2871 llvm::MemoryBufferRef(StyleName, "<command-line>"), &Style, 2872 AllowUnknownOptions)) 2873 return make_string_error("Error parsing -style: " + ec.message()); 2874 return Style; 2875 } 2876 2877 if (!StyleName.equals_lower("file")) { 2878 if (!getPredefinedStyle(StyleName, Style.Language, &Style)) 2879 return make_string_error("Invalid value for -style"); 2880 return Style; 2881 } 2882 2883 // Look for .clang-format/_clang-format file in the file's parent directories. 2884 SmallString<128> UnsuitableConfigFiles; 2885 SmallString<128> Path(FileName); 2886 if (std::error_code EC = FS->makeAbsolute(Path)) 2887 return make_string_error(EC.message()); 2888 2889 llvm::SmallVector<std::string, 2> FilesToLookFor; 2890 FilesToLookFor.push_back(".clang-format"); 2891 FilesToLookFor.push_back("_clang-format"); 2892 2893 for (StringRef Directory = Path; !Directory.empty(); 2894 Directory = llvm::sys::path::parent_path(Directory)) { 2895 2896 auto Status = FS->status(Directory); 2897 if (!Status || 2898 Status->getType() != llvm::sys::fs::file_type::directory_file) { 2899 continue; 2900 } 2901 2902 for (const auto &F : FilesToLookFor) { 2903 SmallString<128> ConfigFile(Directory); 2904 2905 llvm::sys::path::append(ConfigFile, F); 2906 LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); 2907 2908 Status = FS->status(ConfigFile.str()); 2909 2910 if (Status && 2911 (Status->getType() == llvm::sys::fs::file_type::regular_file)) { 2912 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 2913 FS->getBufferForFile(ConfigFile.str()); 2914 if (std::error_code EC = Text.getError()) 2915 return make_string_error(EC.message()); 2916 if (std::error_code ec = 2917 parseConfiguration(*Text.get(), &Style, AllowUnknownOptions)) { 2918 if (ec == ParseError::Unsuitable) { 2919 if (!UnsuitableConfigFiles.empty()) 2920 UnsuitableConfigFiles.append(", "); 2921 UnsuitableConfigFiles.append(ConfigFile); 2922 continue; 2923 } 2924 return make_string_error("Error reading " + ConfigFile + ": " + 2925 ec.message()); 2926 } 2927 LLVM_DEBUG(llvm::dbgs() 2928 << "Using configuration file " << ConfigFile << "\n"); 2929 return Style; 2930 } 2931 } 2932 } 2933 if (!UnsuitableConfigFiles.empty()) 2934 return make_string_error("Configuration file(s) do(es) not support " + 2935 getLanguageName(Style.Language) + ": " + 2936 UnsuitableConfigFiles); 2937 return FallbackStyle; 2938 } 2939 2940 } // namespace format 2941 } // namespace clang 2942