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