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