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