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