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