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