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