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