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