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