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::Success); 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 || 1902 (Token->Next->isOneOf(tok::kw_else, tok::comment) && 1903 Token->Next->NewlinesBefore > 0) 1904 ? Token->WhitespaceRange.getBegin() 1905 : Token->Tok.getLocation(); 1906 const auto Range = 1907 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc()); 1908 cantFail(Result.add(tooling::Replacement(SourceMgr, Range, ""))); 1909 } 1910 } 1911 } 1912 }; 1913 1914 class JavaScriptRequoter : public TokenAnalyzer { 1915 public: 1916 JavaScriptRequoter(const Environment &Env, const FormatStyle &Style) 1917 : TokenAnalyzer(Env, Style) {} 1918 1919 std::pair<tooling::Replacements, unsigned> 1920 analyze(TokenAnnotator &Annotator, 1921 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1922 FormatTokenLexer &Tokens) override { 1923 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 1924 tooling::Replacements Result; 1925 requoteJSStringLiteral(AnnotatedLines, Result); 1926 return {Result, 0}; 1927 } 1928 1929 private: 1930 // Replaces double/single-quoted string literal as appropriate, re-escaping 1931 // the contents in the process. 1932 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines, 1933 tooling::Replacements &Result) { 1934 for (AnnotatedLine *Line : Lines) { 1935 requoteJSStringLiteral(Line->Children, Result); 1936 if (!Line->Affected) 1937 continue; 1938 for (FormatToken *FormatTok = Line->First; FormatTok; 1939 FormatTok = FormatTok->Next) { 1940 StringRef Input = FormatTok->TokenText; 1941 if (FormatTok->Finalized || !FormatTok->isStringLiteral() || 1942 // NB: testing for not starting with a double quote to avoid 1943 // breaking `template strings`. 1944 (Style.JavaScriptQuotes == FormatStyle::JSQS_Single && 1945 !Input.startswith("\"")) || 1946 (Style.JavaScriptQuotes == FormatStyle::JSQS_Double && 1947 !Input.startswith("\'"))) 1948 continue; 1949 1950 // Change start and end quote. 1951 bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single; 1952 SourceLocation Start = FormatTok->Tok.getLocation(); 1953 auto Replace = [&](SourceLocation Start, unsigned Length, 1954 StringRef ReplacementText) { 1955 auto Err = Result.add(tooling::Replacement( 1956 Env.getSourceManager(), Start, Length, ReplacementText)); 1957 // FIXME: handle error. For now, print error message and skip the 1958 // replacement for release version. 1959 if (Err) { 1960 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 1961 assert(false); 1962 } 1963 }; 1964 Replace(Start, 1, IsSingle ? "'" : "\""); 1965 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1, 1966 IsSingle ? "'" : "\""); 1967 1968 // Escape internal quotes. 1969 bool Escaped = false; 1970 for (size_t i = 1; i < Input.size() - 1; i++) { 1971 switch (Input[i]) { 1972 case '\\': 1973 if (!Escaped && i + 1 < Input.size() && 1974 ((IsSingle && Input[i + 1] == '"') || 1975 (!IsSingle && Input[i + 1] == '\''))) { 1976 // Remove this \, it's escaping a " or ' that no longer needs 1977 // escaping 1978 Replace(Start.getLocWithOffset(i), 1, ""); 1979 continue; 1980 } 1981 Escaped = !Escaped; 1982 break; 1983 case '\"': 1984 case '\'': 1985 if (!Escaped && IsSingle == (Input[i] == '\'')) { 1986 // Escape the quote. 1987 Replace(Start.getLocWithOffset(i), 0, "\\"); 1988 } 1989 Escaped = false; 1990 break; 1991 default: 1992 Escaped = false; 1993 break; 1994 } 1995 } 1996 } 1997 } 1998 } 1999 }; 2000 2001 class Formatter : public TokenAnalyzer { 2002 public: 2003 Formatter(const Environment &Env, const FormatStyle &Style, 2004 FormattingAttemptStatus *Status) 2005 : TokenAnalyzer(Env, Style), Status(Status) {} 2006 2007 std::pair<tooling::Replacements, unsigned> 2008 analyze(TokenAnnotator &Annotator, 2009 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2010 FormatTokenLexer &Tokens) override { 2011 tooling::Replacements Result; 2012 deriveLocalStyle(AnnotatedLines); 2013 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2014 for (AnnotatedLine *Line : AnnotatedLines) 2015 Annotator.calculateFormattingInformation(*Line); 2016 Annotator.setCommentLineLevels(AnnotatedLines); 2017 2018 WhitespaceManager Whitespaces( 2019 Env.getSourceManager(), Style, 2020 Style.DeriveLineEnding 2021 ? WhitespaceManager::inputUsesCRLF( 2022 Env.getSourceManager().getBufferData(Env.getFileID()), 2023 Style.UseCRLF) 2024 : Style.UseCRLF); 2025 ContinuationIndenter Indenter(Style, Tokens.getKeywords(), 2026 Env.getSourceManager(), Whitespaces, Encoding, 2027 BinPackInconclusiveFunctions); 2028 unsigned Penalty = 2029 UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, 2030 Tokens.getKeywords(), Env.getSourceManager(), 2031 Status) 2032 .format(AnnotatedLines, /*DryRun=*/false, 2033 /*AdditionalIndent=*/0, 2034 /*FixBadIndentation=*/false, 2035 /*FirstStartColumn=*/Env.getFirstStartColumn(), 2036 /*NextStartColumn=*/Env.getNextStartColumn(), 2037 /*LastStartColumn=*/Env.getLastStartColumn()); 2038 for (const auto &R : Whitespaces.generateReplacements()) 2039 if (Result.add(R)) 2040 return std::make_pair(Result, 0); 2041 return std::make_pair(Result, Penalty); 2042 } 2043 2044 private: 2045 bool 2046 hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) { 2047 for (const AnnotatedLine *Line : Lines) { 2048 if (hasCpp03IncompatibleFormat(Line->Children)) 2049 return true; 2050 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) { 2051 if (!Tok->hasWhitespaceBefore()) { 2052 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener)) 2053 return true; 2054 if (Tok->is(TT_TemplateCloser) && 2055 Tok->Previous->is(TT_TemplateCloser)) 2056 return true; 2057 } 2058 } 2059 } 2060 return false; 2061 } 2062 2063 int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) { 2064 int AlignmentDiff = 0; 2065 for (const AnnotatedLine *Line : Lines) { 2066 AlignmentDiff += countVariableAlignments(Line->Children); 2067 for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) { 2068 if (!Tok->is(TT_PointerOrReference)) 2069 continue; 2070 // Don't treat space in `void foo() &&` as evidence. 2071 if (const auto *Prev = Tok->getPreviousNonComment()) { 2072 if (Prev->is(tok::r_paren) && Prev->MatchingParen) 2073 if (const auto *Func = Prev->MatchingParen->getPreviousNonComment()) 2074 if (Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName, 2075 TT_OverloadedOperator)) 2076 continue; 2077 } 2078 bool SpaceBefore = Tok->hasWhitespaceBefore(); 2079 bool SpaceAfter = Tok->Next->hasWhitespaceBefore(); 2080 if (SpaceBefore && !SpaceAfter) 2081 ++AlignmentDiff; 2082 if (!SpaceBefore && SpaceAfter) 2083 --AlignmentDiff; 2084 } 2085 } 2086 return AlignmentDiff; 2087 } 2088 2089 void 2090 deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 2091 bool HasBinPackedFunction = false; 2092 bool HasOnePerLineFunction = false; 2093 for (AnnotatedLine *Line : AnnotatedLines) { 2094 if (!Line->First->Next) 2095 continue; 2096 FormatToken *Tok = Line->First->Next; 2097 while (Tok->Next) { 2098 if (Tok->is(PPK_BinPacked)) 2099 HasBinPackedFunction = true; 2100 if (Tok->is(PPK_OnePerLine)) 2101 HasOnePerLineFunction = true; 2102 2103 Tok = Tok->Next; 2104 } 2105 } 2106 if (Style.DerivePointerAlignment) { 2107 Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0 2108 ? FormatStyle::PAS_Left 2109 : FormatStyle::PAS_Right; 2110 Style.ReferenceAlignment = FormatStyle::RAS_Pointer; 2111 } 2112 if (Style.Standard == FormatStyle::LS_Auto) 2113 Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines) 2114 ? FormatStyle::LS_Latest 2115 : FormatStyle::LS_Cpp03; 2116 BinPackInconclusiveFunctions = 2117 HasBinPackedFunction || !HasOnePerLineFunction; 2118 } 2119 2120 bool BinPackInconclusiveFunctions; 2121 FormattingAttemptStatus *Status; 2122 }; 2123 2124 /// TrailingCommaInserter inserts trailing commas into container literals. 2125 /// E.g.: 2126 /// const x = [ 2127 /// 1, 2128 /// ]; 2129 /// TrailingCommaInserter runs after formatting. To avoid causing a required 2130 /// reformatting (and thus reflow), it never inserts a comma that'd exceed the 2131 /// ColumnLimit. 2132 /// 2133 /// Because trailing commas disable binpacking of arrays, TrailingCommaInserter 2134 /// is conceptually incompatible with bin packing. 2135 class TrailingCommaInserter : public TokenAnalyzer { 2136 public: 2137 TrailingCommaInserter(const Environment &Env, const FormatStyle &Style) 2138 : TokenAnalyzer(Env, Style) {} 2139 2140 std::pair<tooling::Replacements, unsigned> 2141 analyze(TokenAnnotator &Annotator, 2142 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2143 FormatTokenLexer &Tokens) override { 2144 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2145 tooling::Replacements Result; 2146 insertTrailingCommas(AnnotatedLines, Result); 2147 return {Result, 0}; 2148 } 2149 2150 private: 2151 /// Inserts trailing commas in [] and {} initializers if they wrap over 2152 /// multiple lines. 2153 void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines, 2154 tooling::Replacements &Result) { 2155 for (AnnotatedLine *Line : Lines) { 2156 insertTrailingCommas(Line->Children, Result); 2157 if (!Line->Affected) 2158 continue; 2159 for (FormatToken *FormatTok = Line->First; FormatTok; 2160 FormatTok = FormatTok->Next) { 2161 if (FormatTok->NewlinesBefore == 0) 2162 continue; 2163 FormatToken *Matching = FormatTok->MatchingParen; 2164 if (!Matching || !FormatTok->getPreviousNonComment()) 2165 continue; 2166 if (!(FormatTok->is(tok::r_square) && 2167 Matching->is(TT_ArrayInitializerLSquare)) && 2168 !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) 2169 continue; 2170 FormatToken *Prev = FormatTok->getPreviousNonComment(); 2171 if (Prev->is(tok::comma) || Prev->is(tok::semi)) 2172 continue; 2173 // getEndLoc is not reliably set during re-lexing, use text length 2174 // instead. 2175 SourceLocation Start = 2176 Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size()); 2177 // If inserting a comma would push the code over the column limit, skip 2178 // this location - it'd introduce an unstable formatting due to the 2179 // required reflow. 2180 unsigned ColumnNumber = 2181 Env.getSourceManager().getSpellingColumnNumber(Start); 2182 if (ColumnNumber > Style.ColumnLimit) 2183 continue; 2184 // Comma insertions cannot conflict with each other, and this pass has a 2185 // clean set of Replacements, so the operation below cannot fail. 2186 cantFail(Result.add( 2187 tooling::Replacement(Env.getSourceManager(), Start, 0, ","))); 2188 } 2189 } 2190 } 2191 }; 2192 2193 // This class clean up the erroneous/redundant code around the given ranges in 2194 // file. 2195 class Cleaner : public TokenAnalyzer { 2196 public: 2197 Cleaner(const Environment &Env, const FormatStyle &Style) 2198 : TokenAnalyzer(Env, Style), 2199 DeletedTokens(FormatTokenLess(Env.getSourceManager())) {} 2200 2201 // FIXME: eliminate unused parameters. 2202 std::pair<tooling::Replacements, unsigned> 2203 analyze(TokenAnnotator &Annotator, 2204 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2205 FormatTokenLexer &Tokens) override { 2206 // FIXME: in the current implementation the granularity of affected range 2207 // is an annotated line. However, this is not sufficient. Furthermore, 2208 // redundant code introduced by replacements does not necessarily 2209 // intercept with ranges of replacements that result in the redundancy. 2210 // To determine if some redundant code is actually introduced by 2211 // replacements(e.g. deletions), we need to come up with a more 2212 // sophisticated way of computing affected ranges. 2213 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2214 2215 checkEmptyNamespace(AnnotatedLines); 2216 2217 for (auto *Line : AnnotatedLines) 2218 cleanupLine(Line); 2219 2220 return {generateFixes(), 0}; 2221 } 2222 2223 private: 2224 void cleanupLine(AnnotatedLine *Line) { 2225 for (auto *Child : Line->Children) 2226 cleanupLine(Child); 2227 2228 if (Line->Affected) { 2229 cleanupRight(Line->First, tok::comma, tok::comma); 2230 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma); 2231 cleanupRight(Line->First, tok::l_paren, tok::comma); 2232 cleanupLeft(Line->First, tok::comma, tok::r_paren); 2233 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace); 2234 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace); 2235 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal); 2236 } 2237 } 2238 2239 bool containsOnlyComments(const AnnotatedLine &Line) { 2240 for (FormatToken *Tok = Line.First; Tok != nullptr; Tok = Tok->Next) 2241 if (Tok->isNot(tok::comment)) 2242 return false; 2243 return true; 2244 } 2245 2246 // Iterate through all lines and remove any empty (nested) namespaces. 2247 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 2248 std::set<unsigned> DeletedLines; 2249 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 2250 auto &Line = *AnnotatedLines[i]; 2251 if (Line.startsWithNamespace()) 2252 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines); 2253 } 2254 2255 for (auto Line : DeletedLines) { 2256 FormatToken *Tok = AnnotatedLines[Line]->First; 2257 while (Tok) { 2258 deleteToken(Tok); 2259 Tok = Tok->Next; 2260 } 2261 } 2262 } 2263 2264 // The function checks if the namespace, which starts from \p CurrentLine, and 2265 // its nested namespaces are empty and delete them if they are empty. It also 2266 // sets \p NewLine to the last line checked. 2267 // Returns true if the current namespace is empty. 2268 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2269 unsigned CurrentLine, unsigned &NewLine, 2270 std::set<unsigned> &DeletedLines) { 2271 unsigned InitLine = CurrentLine, End = AnnotatedLines.size(); 2272 if (Style.BraceWrapping.AfterNamespace) { 2273 // If the left brace is in a new line, we should consume it first so that 2274 // it does not make the namespace non-empty. 2275 // FIXME: error handling if there is no left brace. 2276 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) { 2277 NewLine = CurrentLine; 2278 return false; 2279 } 2280 } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) { 2281 return false; 2282 } 2283 while (++CurrentLine < End) { 2284 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace)) 2285 break; 2286 2287 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) { 2288 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine, 2289 DeletedLines)) 2290 return false; 2291 CurrentLine = NewLine; 2292 continue; 2293 } 2294 2295 if (containsOnlyComments(*AnnotatedLines[CurrentLine])) 2296 continue; 2297 2298 // If there is anything other than comments or nested namespaces in the 2299 // current namespace, the namespace cannot be empty. 2300 NewLine = CurrentLine; 2301 return false; 2302 } 2303 2304 NewLine = CurrentLine; 2305 if (CurrentLine >= End) 2306 return false; 2307 2308 // Check if the empty namespace is actually affected by changed ranges. 2309 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange( 2310 AnnotatedLines[InitLine]->First->Tok.getLocation(), 2311 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) 2312 return false; 2313 2314 for (unsigned i = InitLine; i <= CurrentLine; ++i) 2315 DeletedLines.insert(i); 2316 2317 return true; 2318 } 2319 2320 // Checks pairs {start, start->next},..., {end->previous, end} and deletes one 2321 // of the token in the pair if the left token has \p LK token kind and the 2322 // right token has \p RK token kind. If \p DeleteLeft is true, the left token 2323 // is deleted on match; otherwise, the right token is deleted. 2324 template <typename LeftKind, typename RightKind> 2325 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK, 2326 bool DeleteLeft) { 2327 auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * { 2328 for (auto *Res = Tok.Next; Res; Res = Res->Next) 2329 if (!Res->is(tok::comment) && 2330 DeletedTokens.find(Res) == DeletedTokens.end()) 2331 return Res; 2332 return nullptr; 2333 }; 2334 for (auto *Left = Start; Left;) { 2335 auto *Right = NextNotDeleted(*Left); 2336 if (!Right) 2337 break; 2338 if (Left->is(LK) && Right->is(RK)) { 2339 deleteToken(DeleteLeft ? Left : Right); 2340 for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next) 2341 deleteToken(Tok); 2342 // If the right token is deleted, we should keep the left token 2343 // unchanged and pair it with the new right token. 2344 if (!DeleteLeft) 2345 continue; 2346 } 2347 Left = Right; 2348 } 2349 } 2350 2351 template <typename LeftKind, typename RightKind> 2352 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) { 2353 cleanupPair(Start, LK, RK, /*DeleteLeft=*/true); 2354 } 2355 2356 template <typename LeftKind, typename RightKind> 2357 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) { 2358 cleanupPair(Start, LK, RK, /*DeleteLeft=*/false); 2359 } 2360 2361 // Delete the given token. 2362 inline void deleteToken(FormatToken *Tok) { 2363 if (Tok) 2364 DeletedTokens.insert(Tok); 2365 } 2366 2367 tooling::Replacements generateFixes() { 2368 tooling::Replacements Fixes; 2369 std::vector<FormatToken *> Tokens; 2370 std::copy(DeletedTokens.begin(), DeletedTokens.end(), 2371 std::back_inserter(Tokens)); 2372 2373 // Merge multiple continuous token deletions into one big deletion so that 2374 // the number of replacements can be reduced. This makes computing affected 2375 // ranges more efficient when we run reformat on the changed code. 2376 unsigned Idx = 0; 2377 while (Idx < Tokens.size()) { 2378 unsigned St = Idx, End = Idx; 2379 while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1]) 2380 ++End; 2381 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(), 2382 Tokens[End]->Tok.getEndLoc()); 2383 auto Err = 2384 Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, "")); 2385 // FIXME: better error handling. for now just print error message and skip 2386 // for the release version. 2387 if (Err) { 2388 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 2389 assert(false && "Fixes must not conflict!"); 2390 } 2391 Idx = End + 1; 2392 } 2393 2394 return Fixes; 2395 } 2396 2397 // Class for less-than inequality comparason for the set `RedundantTokens`. 2398 // We store tokens in the order they appear in the translation unit so that 2399 // we do not need to sort them in `generateFixes()`. 2400 struct FormatTokenLess { 2401 FormatTokenLess(const SourceManager &SM) : SM(SM) {} 2402 2403 bool operator()(const FormatToken *LHS, const FormatToken *RHS) const { 2404 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(), 2405 RHS->Tok.getLocation()); 2406 } 2407 const SourceManager &SM; 2408 }; 2409 2410 // Tokens to be deleted. 2411 std::set<FormatToken *, FormatTokenLess> DeletedTokens; 2412 }; 2413 2414 class ObjCHeaderStyleGuesser : public TokenAnalyzer { 2415 public: 2416 ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style) 2417 : TokenAnalyzer(Env, Style), IsObjC(false) {} 2418 2419 std::pair<tooling::Replacements, unsigned> 2420 analyze(TokenAnnotator &Annotator, 2421 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2422 FormatTokenLexer &Tokens) override { 2423 assert(Style.Language == FormatStyle::LK_Cpp); 2424 IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines, 2425 Tokens.getKeywords()); 2426 tooling::Replacements Result; 2427 return {Result, 0}; 2428 } 2429 2430 bool isObjC() { return IsObjC; } 2431 2432 private: 2433 static bool 2434 guessIsObjC(const SourceManager &SourceManager, 2435 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2436 const AdditionalKeywords &Keywords) { 2437 // Keep this array sorted, since we are binary searching over it. 2438 static constexpr llvm::StringLiteral FoundationIdentifiers[] = { 2439 "CGFloat", 2440 "CGPoint", 2441 "CGPointMake", 2442 "CGPointZero", 2443 "CGRect", 2444 "CGRectEdge", 2445 "CGRectInfinite", 2446 "CGRectMake", 2447 "CGRectNull", 2448 "CGRectZero", 2449 "CGSize", 2450 "CGSizeMake", 2451 "CGVector", 2452 "CGVectorMake", 2453 "NSAffineTransform", 2454 "NSArray", 2455 "NSAttributedString", 2456 "NSBlockOperation", 2457 "NSBundle", 2458 "NSCache", 2459 "NSCalendar", 2460 "NSCharacterSet", 2461 "NSCountedSet", 2462 "NSData", 2463 "NSDataDetector", 2464 "NSDecimal", 2465 "NSDecimalNumber", 2466 "NSDictionary", 2467 "NSEdgeInsets", 2468 "NSHashTable", 2469 "NSIndexPath", 2470 "NSIndexSet", 2471 "NSInteger", 2472 "NSInvocationOperation", 2473 "NSLocale", 2474 "NSMapTable", 2475 "NSMutableArray", 2476 "NSMutableAttributedString", 2477 "NSMutableCharacterSet", 2478 "NSMutableData", 2479 "NSMutableDictionary", 2480 "NSMutableIndexSet", 2481 "NSMutableOrderedSet", 2482 "NSMutableSet", 2483 "NSMutableString", 2484 "NSNumber", 2485 "NSNumberFormatter", 2486 "NSObject", 2487 "NSOperation", 2488 "NSOperationQueue", 2489 "NSOperationQueuePriority", 2490 "NSOrderedSet", 2491 "NSPoint", 2492 "NSPointerArray", 2493 "NSQualityOfService", 2494 "NSRange", 2495 "NSRect", 2496 "NSRegularExpression", 2497 "NSSet", 2498 "NSSize", 2499 "NSString", 2500 "NSTimeZone", 2501 "NSUInteger", 2502 "NSURL", 2503 "NSURLComponents", 2504 "NSURLQueryItem", 2505 "NSUUID", 2506 "NSValue", 2507 "UIImage", 2508 "UIView", 2509 }; 2510 2511 for (auto Line : AnnotatedLines) { 2512 if (Line->First && (Line->First->TokenText.startswith("#") || 2513 Line->First->TokenText == "__pragma" || 2514 Line->First->TokenText == "_Pragma")) 2515 continue; 2516 for (const FormatToken *FormatTok = Line->First; FormatTok; 2517 FormatTok = FormatTok->Next) { 2518 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) && 2519 (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword || 2520 FormatTok->isOneOf(tok::numeric_constant, tok::l_square, 2521 tok::l_brace))) || 2522 (FormatTok->Tok.isAnyIdentifier() && 2523 std::binary_search(std::begin(FoundationIdentifiers), 2524 std::end(FoundationIdentifiers), 2525 FormatTok->TokenText)) || 2526 FormatTok->is(TT_ObjCStringLiteral) || 2527 FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM, 2528 Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace, 2529 TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn, 2530 TT_ObjCMethodExpr, TT_ObjCMethodSpecifier, 2531 TT_ObjCProperty)) { 2532 LLVM_DEBUG(llvm::dbgs() 2533 << "Detected ObjC at location " 2534 << FormatTok->Tok.getLocation().printToString( 2535 SourceManager) 2536 << " token: " << FormatTok->TokenText << " token type: " 2537 << getTokenTypeName(FormatTok->getType()) << "\n"); 2538 return true; 2539 } 2540 if (guessIsObjC(SourceManager, Line->Children, Keywords)) 2541 return true; 2542 } 2543 } 2544 return false; 2545 } 2546 2547 bool IsObjC; 2548 }; 2549 2550 struct IncludeDirective { 2551 StringRef Filename; 2552 StringRef Text; 2553 unsigned Offset; 2554 int Category; 2555 int Priority; 2556 }; 2557 2558 struct JavaImportDirective { 2559 StringRef Identifier; 2560 StringRef Text; 2561 unsigned Offset; 2562 std::vector<StringRef> AssociatedCommentLines; 2563 bool IsStatic; 2564 }; 2565 2566 } // end anonymous namespace 2567 2568 // Determines whether 'Ranges' intersects with ('Start', 'End'). 2569 static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start, 2570 unsigned End) { 2571 for (auto Range : Ranges) 2572 if (Range.getOffset() < End && 2573 Range.getOffset() + Range.getLength() > Start) 2574 return true; 2575 return false; 2576 } 2577 2578 // Returns a pair (Index, OffsetToEOL) describing the position of the cursor 2579 // before sorting/deduplicating. Index is the index of the include under the 2580 // cursor in the original set of includes. If this include has duplicates, it is 2581 // the index of the first of the duplicates as the others are going to be 2582 // removed. OffsetToEOL describes the cursor's position relative to the end of 2583 // its current line. 2584 // If `Cursor` is not on any #include, `Index` will be UINT_MAX. 2585 static std::pair<unsigned, unsigned> 2586 FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes, 2587 const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) { 2588 unsigned CursorIndex = UINT_MAX; 2589 unsigned OffsetToEOL = 0; 2590 for (int i = 0, e = Includes.size(); i != e; ++i) { 2591 unsigned Start = Includes[Indices[i]].Offset; 2592 unsigned End = Start + Includes[Indices[i]].Text.size(); 2593 if (!(Cursor >= Start && Cursor < End)) 2594 continue; 2595 CursorIndex = Indices[i]; 2596 OffsetToEOL = End - Cursor; 2597 // Put the cursor on the only remaining #include among the duplicate 2598 // #includes. 2599 while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text) 2600 CursorIndex = i; 2601 break; 2602 } 2603 return std::make_pair(CursorIndex, OffsetToEOL); 2604 } 2605 2606 // Replace all "\r\n" with "\n". 2607 std::string replaceCRLF(const std::string &Code) { 2608 std::string NewCode; 2609 size_t Pos = 0, LastPos = 0; 2610 2611 do { 2612 Pos = Code.find("\r\n", LastPos); 2613 if (Pos == LastPos) { 2614 ++LastPos; 2615 continue; 2616 } 2617 if (Pos == std::string::npos) { 2618 NewCode += Code.substr(LastPos); 2619 break; 2620 } 2621 NewCode += Code.substr(LastPos, Pos - LastPos) + "\n"; 2622 LastPos = Pos + 2; 2623 } while (Pos != std::string::npos); 2624 2625 return NewCode; 2626 } 2627 2628 // Sorts and deduplicate a block of includes given by 'Includes' alphabetically 2629 // adding the necessary replacement to 'Replaces'. 'Includes' must be in strict 2630 // source order. 2631 // #include directives with the same text will be deduplicated, and only the 2632 // first #include in the duplicate #includes remains. If the `Cursor` is 2633 // provided and put on a deleted #include, it will be moved to the remaining 2634 // #include in the duplicate #includes. 2635 static void sortCppIncludes(const FormatStyle &Style, 2636 const SmallVectorImpl<IncludeDirective> &Includes, 2637 ArrayRef<tooling::Range> Ranges, StringRef FileName, 2638 StringRef Code, tooling::Replacements &Replaces, 2639 unsigned *Cursor) { 2640 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 2641 const unsigned IncludesBeginOffset = Includes.front().Offset; 2642 const unsigned IncludesEndOffset = 2643 Includes.back().Offset + Includes.back().Text.size(); 2644 const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset; 2645 if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset)) 2646 return; 2647 SmallVector<unsigned, 16> Indices = 2648 llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size())); 2649 2650 if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) 2651 llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 2652 const auto LHSFilenameLower = Includes[LHSI].Filename.lower(); 2653 const auto RHSFilenameLower = Includes[RHSI].Filename.lower(); 2654 return std::tie(Includes[LHSI].Priority, LHSFilenameLower, 2655 Includes[LHSI].Filename) < 2656 std::tie(Includes[RHSI].Priority, RHSFilenameLower, 2657 Includes[RHSI].Filename); 2658 }); 2659 else 2660 llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 2661 return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) < 2662 std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename); 2663 }); 2664 2665 // The index of the include on which the cursor will be put after 2666 // sorting/deduplicating. 2667 unsigned CursorIndex; 2668 // The offset from cursor to the end of line. 2669 unsigned CursorToEOLOffset; 2670 if (Cursor) 2671 std::tie(CursorIndex, CursorToEOLOffset) = 2672 FindCursorIndex(Includes, Indices, *Cursor); 2673 2674 // Deduplicate #includes. 2675 Indices.erase(std::unique(Indices.begin(), Indices.end(), 2676 [&](unsigned LHSI, unsigned RHSI) { 2677 return Includes[LHSI].Text.trim() == 2678 Includes[RHSI].Text.trim(); 2679 }), 2680 Indices.end()); 2681 2682 int CurrentCategory = Includes.front().Category; 2683 2684 // If the #includes are out of order, we generate a single replacement fixing 2685 // the entire block. Otherwise, no replacement is generated. 2686 // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not 2687 // enough as additional newlines might be added or removed across #include 2688 // blocks. This we handle below by generating the updated #include blocks and 2689 // comparing it to the original. 2690 if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) && 2691 Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) 2692 return; 2693 2694 std::string result; 2695 for (unsigned Index : Indices) { 2696 if (!result.empty()) { 2697 result += "\n"; 2698 if (Style.IncludeStyle.IncludeBlocks == 2699 tooling::IncludeStyle::IBS_Regroup && 2700 CurrentCategory != Includes[Index].Category) 2701 result += "\n"; 2702 } 2703 result += Includes[Index].Text; 2704 if (Cursor && CursorIndex == Index) 2705 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset; 2706 CurrentCategory = Includes[Index].Category; 2707 } 2708 2709 if (Cursor && *Cursor >= IncludesEndOffset) 2710 *Cursor += result.size() - IncludesBlockSize; 2711 2712 // If the #includes are out of order, we generate a single replacement fixing 2713 // the entire range of blocks. Otherwise, no replacement is generated. 2714 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 2715 IncludesBeginOffset, IncludesBlockSize)))) 2716 return; 2717 2718 auto Err = Replaces.add(tooling::Replacement( 2719 FileName, Includes.front().Offset, IncludesBlockSize, result)); 2720 // FIXME: better error handling. For now, just skip the replacement for the 2721 // release version. 2722 if (Err) { 2723 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 2724 assert(false); 2725 } 2726 } 2727 2728 namespace { 2729 2730 const char CppIncludeRegexPattern[] = 2731 R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))"; 2732 2733 } // anonymous namespace 2734 2735 tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code, 2736 ArrayRef<tooling::Range> Ranges, 2737 StringRef FileName, 2738 tooling::Replacements &Replaces, 2739 unsigned *Cursor) { 2740 unsigned Prev = llvm::StringSwitch<size_t>(Code) 2741 .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM 2742 .Default(0); 2743 unsigned SearchFrom = 0; 2744 llvm::Regex IncludeRegex(CppIncludeRegexPattern); 2745 SmallVector<StringRef, 4> Matches; 2746 SmallVector<IncludeDirective, 16> IncludesInBlock; 2747 2748 // In compiled files, consider the first #include to be the main #include of 2749 // the file if it is not a system #include. This ensures that the header 2750 // doesn't have hidden dependencies 2751 // (http://llvm.org/docs/CodingStandards.html#include-style). 2752 // 2753 // FIXME: Do some validation, e.g. edit distance of the base name, to fix 2754 // cases where the first #include is unlikely to be the main header. 2755 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 2756 bool FirstIncludeBlock = true; 2757 bool MainIncludeFound = false; 2758 bool FormattingOff = false; 2759 2760 // '[' must be the first and '-' the last character inside [...]. 2761 llvm::Regex RawStringRegex( 2762 "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\("); 2763 SmallVector<StringRef, 2> RawStringMatches; 2764 std::string RawStringTermination = ")\""; 2765 2766 for (;;) { 2767 auto Pos = Code.find('\n', SearchFrom); 2768 StringRef Line = 2769 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 2770 2771 StringRef Trimmed = Line.trim(); 2772 2773 // #includes inside raw string literals need to be ignored. 2774 // or we will sort the contents of the string. 2775 // Skip past until we think we are at the rawstring literal close. 2776 if (RawStringRegex.match(Trimmed, &RawStringMatches)) { 2777 std::string CharSequence = RawStringMatches[1].str(); 2778 RawStringTermination = ")" + CharSequence + "\""; 2779 FormattingOff = true; 2780 } 2781 2782 if (Trimmed.contains(RawStringTermination)) 2783 FormattingOff = false; 2784 2785 if (Trimmed == "// clang-format off" || Trimmed == "/* clang-format off */") 2786 FormattingOff = true; 2787 else if (Trimmed == "// clang-format on" || 2788 Trimmed == "/* clang-format on */") 2789 FormattingOff = false; 2790 2791 const bool EmptyLineSkipped = 2792 Trimmed.empty() && 2793 (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge || 2794 Style.IncludeStyle.IncludeBlocks == 2795 tooling::IncludeStyle::IBS_Regroup); 2796 2797 bool MergeWithNextLine = Trimmed.endswith("\\"); 2798 if (!FormattingOff && !MergeWithNextLine) { 2799 if (IncludeRegex.match(Line, &Matches)) { 2800 StringRef IncludeName = Matches[2]; 2801 if (Line.contains("/*") && !Line.contains("*/")) { 2802 // #include with a start of a block comment, but without the end. 2803 // Need to keep all the lines until the end of the comment together. 2804 // FIXME: This is somehow simplified check that probably does not work 2805 // correctly if there are multiple comments on a line. 2806 Pos = Code.find("*/", SearchFrom); 2807 Line = Code.substr( 2808 Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev); 2809 } 2810 int Category = Categories.getIncludePriority( 2811 IncludeName, 2812 /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock); 2813 int Priority = Categories.getSortIncludePriority( 2814 IncludeName, !MainIncludeFound && FirstIncludeBlock); 2815 if (Category == 0) 2816 MainIncludeFound = true; 2817 IncludesInBlock.push_back( 2818 {IncludeName, Line, Prev, Category, Priority}); 2819 } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) { 2820 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, 2821 Replaces, Cursor); 2822 IncludesInBlock.clear(); 2823 if (Trimmed.startswith("#pragma hdrstop")) // Precompiled headers. 2824 FirstIncludeBlock = true; 2825 else 2826 FirstIncludeBlock = false; 2827 } 2828 } 2829 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 2830 break; 2831 2832 if (!MergeWithNextLine) 2833 Prev = Pos + 1; 2834 SearchFrom = Pos + 1; 2835 } 2836 if (!IncludesInBlock.empty()) { 2837 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces, 2838 Cursor); 2839 } 2840 return Replaces; 2841 } 2842 2843 // Returns group number to use as a first order sort on imports. Gives UINT_MAX 2844 // if the import does not match any given groups. 2845 static unsigned findJavaImportGroup(const FormatStyle &Style, 2846 StringRef ImportIdentifier) { 2847 unsigned LongestMatchIndex = UINT_MAX; 2848 unsigned LongestMatchLength = 0; 2849 for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) { 2850 const std::string &GroupPrefix = Style.JavaImportGroups[I]; 2851 if (ImportIdentifier.startswith(GroupPrefix) && 2852 GroupPrefix.length() > LongestMatchLength) { 2853 LongestMatchIndex = I; 2854 LongestMatchLength = GroupPrefix.length(); 2855 } 2856 } 2857 return LongestMatchIndex; 2858 } 2859 2860 // Sorts and deduplicates a block of includes given by 'Imports' based on 2861 // JavaImportGroups, then adding the necessary replacement to 'Replaces'. 2862 // Import declarations with the same text will be deduplicated. Between each 2863 // import group, a newline is inserted, and within each import group, a 2864 // lexicographic sort based on ASCII value is performed. 2865 static void sortJavaImports(const FormatStyle &Style, 2866 const SmallVectorImpl<JavaImportDirective> &Imports, 2867 ArrayRef<tooling::Range> Ranges, StringRef FileName, 2868 StringRef Code, tooling::Replacements &Replaces) { 2869 unsigned ImportsBeginOffset = Imports.front().Offset; 2870 unsigned ImportsEndOffset = 2871 Imports.back().Offset + Imports.back().Text.size(); 2872 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset; 2873 if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset)) 2874 return; 2875 2876 SmallVector<unsigned, 16> Indices = 2877 llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size())); 2878 SmallVector<unsigned, 16> JavaImportGroups; 2879 JavaImportGroups.reserve(Imports.size()); 2880 for (const JavaImportDirective &Import : Imports) 2881 JavaImportGroups.push_back(findJavaImportGroup(Style, Import.Identifier)); 2882 2883 bool StaticImportAfterNormalImport = 2884 Style.SortJavaStaticImport == FormatStyle::SJSIO_After; 2885 llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 2886 // Negating IsStatic to push static imports above non-static imports. 2887 return std::make_tuple(!Imports[LHSI].IsStatic ^ 2888 StaticImportAfterNormalImport, 2889 JavaImportGroups[LHSI], Imports[LHSI].Identifier) < 2890 std::make_tuple(!Imports[RHSI].IsStatic ^ 2891 StaticImportAfterNormalImport, 2892 JavaImportGroups[RHSI], Imports[RHSI].Identifier); 2893 }); 2894 2895 // Deduplicate imports. 2896 Indices.erase(std::unique(Indices.begin(), Indices.end(), 2897 [&](unsigned LHSI, unsigned RHSI) { 2898 return Imports[LHSI].Text == Imports[RHSI].Text; 2899 }), 2900 Indices.end()); 2901 2902 bool CurrentIsStatic = Imports[Indices.front()].IsStatic; 2903 unsigned CurrentImportGroup = JavaImportGroups[Indices.front()]; 2904 2905 std::string result; 2906 for (unsigned Index : Indices) { 2907 if (!result.empty()) { 2908 result += "\n"; 2909 if (CurrentIsStatic != Imports[Index].IsStatic || 2910 CurrentImportGroup != JavaImportGroups[Index]) 2911 result += "\n"; 2912 } 2913 for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) { 2914 result += CommentLine; 2915 result += "\n"; 2916 } 2917 result += Imports[Index].Text; 2918 CurrentIsStatic = Imports[Index].IsStatic; 2919 CurrentImportGroup = JavaImportGroups[Index]; 2920 } 2921 2922 // If the imports are out of order, we generate a single replacement fixing 2923 // the entire block. Otherwise, no replacement is generated. 2924 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 2925 Imports.front().Offset, ImportsBlockSize)))) 2926 return; 2927 2928 auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset, 2929 ImportsBlockSize, result)); 2930 // FIXME: better error handling. For now, just skip the replacement for the 2931 // release version. 2932 if (Err) { 2933 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 2934 assert(false); 2935 } 2936 } 2937 2938 namespace { 2939 2940 const char JavaImportRegexPattern[] = 2941 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;"; 2942 2943 } // anonymous namespace 2944 2945 tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code, 2946 ArrayRef<tooling::Range> Ranges, 2947 StringRef FileName, 2948 tooling::Replacements &Replaces) { 2949 unsigned Prev = 0; 2950 unsigned SearchFrom = 0; 2951 llvm::Regex ImportRegex(JavaImportRegexPattern); 2952 SmallVector<StringRef, 4> Matches; 2953 SmallVector<JavaImportDirective, 16> ImportsInBlock; 2954 std::vector<StringRef> AssociatedCommentLines; 2955 2956 bool FormattingOff = false; 2957 2958 for (;;) { 2959 auto Pos = Code.find('\n', SearchFrom); 2960 StringRef Line = 2961 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 2962 2963 StringRef Trimmed = Line.trim(); 2964 if (Trimmed == "// clang-format off") 2965 FormattingOff = true; 2966 else if (Trimmed == "// clang-format on") 2967 FormattingOff = false; 2968 2969 if (ImportRegex.match(Line, &Matches)) { 2970 if (FormattingOff) { 2971 // If at least one import line has formatting turned off, turn off 2972 // formatting entirely. 2973 return Replaces; 2974 } 2975 StringRef Static = Matches[1]; 2976 StringRef Identifier = Matches[2]; 2977 bool IsStatic = false; 2978 if (Static.contains("static")) 2979 IsStatic = true; 2980 ImportsInBlock.push_back( 2981 {Identifier, Line, Prev, AssociatedCommentLines, IsStatic}); 2982 AssociatedCommentLines.clear(); 2983 } else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) { 2984 // Associating comments within the imports with the nearest import below 2985 AssociatedCommentLines.push_back(Line); 2986 } 2987 Prev = Pos + 1; 2988 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 2989 break; 2990 SearchFrom = Pos + 1; 2991 } 2992 if (!ImportsInBlock.empty()) 2993 sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces); 2994 return Replaces; 2995 } 2996 2997 bool isMpegTS(StringRef Code) { 2998 // MPEG transport streams use the ".ts" file extension. clang-format should 2999 // not attempt to format those. MPEG TS' frame format starts with 0x47 every 3000 // 189 bytes - detect that and return. 3001 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47; 3002 } 3003 3004 bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); } 3005 3006 tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, 3007 ArrayRef<tooling::Range> Ranges, 3008 StringRef FileName, unsigned *Cursor) { 3009 tooling::Replacements Replaces; 3010 if (!Style.SortIncludes || Style.DisableFormat) 3011 return Replaces; 3012 if (isLikelyXml(Code)) 3013 return Replaces; 3014 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript && 3015 isMpegTS(Code)) 3016 return Replaces; 3017 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript) 3018 return sortJavaScriptImports(Style, Code, Ranges, FileName); 3019 if (Style.Language == FormatStyle::LanguageKind::LK_Java) 3020 return sortJavaImports(Style, Code, Ranges, FileName, Replaces); 3021 sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor); 3022 return Replaces; 3023 } 3024 3025 template <typename T> 3026 static llvm::Expected<tooling::Replacements> 3027 processReplacements(T ProcessFunc, StringRef Code, 3028 const tooling::Replacements &Replaces, 3029 const FormatStyle &Style) { 3030 if (Replaces.empty()) 3031 return tooling::Replacements(); 3032 3033 auto NewCode = applyAllReplacements(Code, Replaces); 3034 if (!NewCode) 3035 return NewCode.takeError(); 3036 std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges(); 3037 StringRef FileName = Replaces.begin()->getFilePath(); 3038 3039 tooling::Replacements FormatReplaces = 3040 ProcessFunc(Style, *NewCode, ChangedRanges, FileName); 3041 3042 return Replaces.merge(FormatReplaces); 3043 } 3044 3045 llvm::Expected<tooling::Replacements> 3046 formatReplacements(StringRef Code, const tooling::Replacements &Replaces, 3047 const FormatStyle &Style) { 3048 // We need to use lambda function here since there are two versions of 3049 // `sortIncludes`. 3050 auto SortIncludes = [](const FormatStyle &Style, StringRef Code, 3051 std::vector<tooling::Range> Ranges, 3052 StringRef FileName) -> tooling::Replacements { 3053 return sortIncludes(Style, Code, Ranges, FileName); 3054 }; 3055 auto SortedReplaces = 3056 processReplacements(SortIncludes, Code, Replaces, Style); 3057 if (!SortedReplaces) 3058 return SortedReplaces.takeError(); 3059 3060 // We need to use lambda function here since there are two versions of 3061 // `reformat`. 3062 auto Reformat = [](const FormatStyle &Style, StringRef Code, 3063 std::vector<tooling::Range> Ranges, 3064 StringRef FileName) -> tooling::Replacements { 3065 return reformat(Style, Code, Ranges, FileName); 3066 }; 3067 return processReplacements(Reformat, Code, *SortedReplaces, Style); 3068 } 3069 3070 namespace { 3071 3072 inline bool isHeaderInsertion(const tooling::Replacement &Replace) { 3073 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 && 3074 llvm::Regex(CppIncludeRegexPattern) 3075 .match(Replace.getReplacementText()); 3076 } 3077 3078 inline bool isHeaderDeletion(const tooling::Replacement &Replace) { 3079 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1; 3080 } 3081 3082 // FIXME: insert empty lines between newly created blocks. 3083 tooling::Replacements 3084 fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces, 3085 const FormatStyle &Style) { 3086 if (!Style.isCpp()) 3087 return Replaces; 3088 3089 tooling::Replacements HeaderInsertions; 3090 std::set<llvm::StringRef> HeadersToDelete; 3091 tooling::Replacements Result; 3092 for (const auto &R : Replaces) { 3093 if (isHeaderInsertion(R)) { 3094 // Replacements from \p Replaces must be conflict-free already, so we can 3095 // simply consume the error. 3096 llvm::consumeError(HeaderInsertions.add(R)); 3097 } else if (isHeaderDeletion(R)) { 3098 HeadersToDelete.insert(R.getReplacementText()); 3099 } else if (R.getOffset() == UINT_MAX) { 3100 llvm::errs() << "Insertions other than header #include insertion are " 3101 "not supported! " 3102 << R.getReplacementText() << "\n"; 3103 } else { 3104 llvm::consumeError(Result.add(R)); 3105 } 3106 } 3107 if (HeaderInsertions.empty() && HeadersToDelete.empty()) 3108 return Replaces; 3109 3110 StringRef FileName = Replaces.begin()->getFilePath(); 3111 tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle); 3112 3113 for (const auto &Header : HeadersToDelete) { 3114 tooling::Replacements Replaces = 3115 Includes.remove(Header.trim("\"<>"), Header.startswith("<")); 3116 for (const auto &R : Replaces) { 3117 auto Err = Result.add(R); 3118 if (Err) { 3119 // Ignore the deletion on conflict. 3120 llvm::errs() << "Failed to add header deletion replacement for " 3121 << Header << ": " << llvm::toString(std::move(Err)) 3122 << "\n"; 3123 } 3124 } 3125 } 3126 3127 llvm::Regex IncludeRegex = llvm::Regex(CppIncludeRegexPattern); 3128 llvm::SmallVector<StringRef, 4> Matches; 3129 for (const auto &R : HeaderInsertions) { 3130 auto IncludeDirective = R.getReplacementText(); 3131 bool Matched = IncludeRegex.match(IncludeDirective, &Matches); 3132 assert(Matched && "Header insertion replacement must have replacement text " 3133 "'#include ...'"); 3134 (void)Matched; 3135 auto IncludeName = Matches[2]; 3136 auto Replace = 3137 Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<")); 3138 if (Replace) { 3139 auto Err = Result.add(*Replace); 3140 if (Err) { 3141 llvm::consumeError(std::move(Err)); 3142 unsigned NewOffset = 3143 Result.getShiftedCodePosition(Replace->getOffset()); 3144 auto Shifted = tooling::Replacement(FileName, NewOffset, 0, 3145 Replace->getReplacementText()); 3146 Result = Result.merge(tooling::Replacements(Shifted)); 3147 } 3148 } 3149 } 3150 return Result; 3151 } 3152 3153 } // anonymous namespace 3154 3155 llvm::Expected<tooling::Replacements> 3156 cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, 3157 const FormatStyle &Style) { 3158 // We need to use lambda function here since there are two versions of 3159 // `cleanup`. 3160 auto Cleanup = [](const FormatStyle &Style, StringRef Code, 3161 std::vector<tooling::Range> Ranges, 3162 StringRef FileName) -> tooling::Replacements { 3163 return cleanup(Style, Code, Ranges, FileName); 3164 }; 3165 // Make header insertion replacements insert new headers into correct blocks. 3166 tooling::Replacements NewReplaces = 3167 fixCppIncludeInsertions(Code, Replaces, Style); 3168 return processReplacements(Cleanup, Code, NewReplaces, Style); 3169 } 3170 3171 namespace internal { 3172 std::pair<tooling::Replacements, unsigned> 3173 reformat(const FormatStyle &Style, StringRef Code, 3174 ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn, 3175 unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName, 3176 FormattingAttemptStatus *Status) { 3177 FormatStyle Expanded = Style; 3178 expandPresetsBraceWrapping(Expanded); 3179 expandPresetsSpaceBeforeParens(Expanded); 3180 switch (Expanded.RequiresClausePosition) { 3181 case FormatStyle::RCPS_SingleLine: 3182 case FormatStyle::RCPS_WithPreceding: 3183 Expanded.IndentRequiresClause = false; 3184 break; 3185 default: 3186 break; 3187 } 3188 3189 if (Expanded.DisableFormat) 3190 return {tooling::Replacements(), 0}; 3191 if (isLikelyXml(Code)) 3192 return {tooling::Replacements(), 0}; 3193 if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code)) 3194 return {tooling::Replacements(), 0}; 3195 3196 // JSON only needs the formatting passing. 3197 if (Style.isJson()) { 3198 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); 3199 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn, 3200 NextStartColumn, LastStartColumn); 3201 if (!Env) 3202 return {}; 3203 // Perform the actual formatting pass. 3204 tooling::Replacements Replaces = 3205 Formatter(*Env, Style, Status).process().first; 3206 // add a replacement to remove the "x = " from the result. 3207 if (!Replaces.add(tooling::Replacement(FileName, 0, 4, ""))) { 3208 // apply the reformatting changes and the removal of "x = ". 3209 if (applyAllReplacements(Code, Replaces)) 3210 return {Replaces, 0}; 3211 } 3212 return {tooling::Replacements(), 0}; 3213 } 3214 3215 typedef std::function<std::pair<tooling::Replacements, unsigned>( 3216 const Environment &)> 3217 AnalyzerPass; 3218 SmallVector<AnalyzerPass, 8> Passes; 3219 3220 if (Style.isCpp()) { 3221 if (Style.QualifierAlignment != FormatStyle::QAS_Leave) { 3222 Passes.emplace_back([&](const Environment &Env) { 3223 return QualifierAlignmentFixer(Env, Expanded, Code, Ranges, 3224 FirstStartColumn, NextStartColumn, 3225 LastStartColumn, FileName) 3226 .process(); 3227 }); 3228 } 3229 3230 if (Style.InsertBraces) 3231 Passes.emplace_back([&](const Environment &Env) { 3232 return BracesInserter(Env, Expanded).process(); 3233 }); 3234 3235 if (Style.RemoveBracesLLVM) 3236 Passes.emplace_back([&](const Environment &Env) { 3237 return BracesRemover(Env, Expanded).process(); 3238 }); 3239 3240 if (Style.FixNamespaceComments) 3241 Passes.emplace_back([&](const Environment &Env) { 3242 return NamespaceEndCommentsFixer(Env, Expanded).process(); 3243 }); 3244 3245 if (Style.SortUsingDeclarations) 3246 Passes.emplace_back([&](const Environment &Env) { 3247 return UsingDeclarationsSorter(Env, Expanded).process(); 3248 }); 3249 } 3250 3251 if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) 3252 Passes.emplace_back([&](const Environment &Env) { 3253 return DefinitionBlockSeparator(Env, Expanded).process(); 3254 }); 3255 3256 if (Style.isJavaScript() && Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) 3257 Passes.emplace_back([&](const Environment &Env) { 3258 return JavaScriptRequoter(Env, Expanded).process(); 3259 }); 3260 3261 Passes.emplace_back([&](const Environment &Env) { 3262 return Formatter(Env, Expanded, Status).process(); 3263 }); 3264 3265 if (Style.isJavaScript() && 3266 Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) 3267 Passes.emplace_back([&](const Environment &Env) { 3268 return TrailingCommaInserter(Env, Expanded).process(); 3269 }); 3270 3271 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn, 3272 NextStartColumn, LastStartColumn); 3273 if (!Env) 3274 return {}; 3275 llvm::Optional<std::string> CurrentCode = None; 3276 tooling::Replacements Fixes; 3277 unsigned Penalty = 0; 3278 for (size_t I = 0, E = Passes.size(); I < E; ++I) { 3279 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env); 3280 auto NewCode = applyAllReplacements( 3281 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first); 3282 if (NewCode) { 3283 Fixes = Fixes.merge(PassFixes.first); 3284 Penalty += PassFixes.second; 3285 if (I + 1 < E) { 3286 CurrentCode = std::move(*NewCode); 3287 Env = Environment::make( 3288 *CurrentCode, FileName, 3289 tooling::calculateRangesAfterReplacements(Fixes, Ranges), 3290 FirstStartColumn, NextStartColumn, LastStartColumn); 3291 if (!Env) 3292 return {}; 3293 } 3294 } 3295 } 3296 3297 return {Fixes, Penalty}; 3298 } 3299 } // namespace internal 3300 3301 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 3302 ArrayRef<tooling::Range> Ranges, 3303 StringRef FileName, 3304 FormattingAttemptStatus *Status) { 3305 return internal::reformat(Style, Code, Ranges, 3306 /*FirstStartColumn=*/0, 3307 /*NextStartColumn=*/0, 3308 /*LastStartColumn=*/0, FileName, Status) 3309 .first; 3310 } 3311 3312 tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, 3313 ArrayRef<tooling::Range> Ranges, 3314 StringRef FileName) { 3315 // cleanups only apply to C++ (they mostly concern ctor commas etc.) 3316 if (Style.Language != FormatStyle::LK_Cpp) 3317 return tooling::Replacements(); 3318 auto Env = Environment::make(Code, FileName, Ranges); 3319 if (!Env) 3320 return {}; 3321 return Cleaner(*Env, Style).process().first; 3322 } 3323 3324 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 3325 ArrayRef<tooling::Range> Ranges, 3326 StringRef FileName, bool *IncompleteFormat) { 3327 FormattingAttemptStatus Status; 3328 auto Result = reformat(Style, Code, Ranges, FileName, &Status); 3329 if (!Status.FormatComplete) 3330 *IncompleteFormat = true; 3331 return Result; 3332 } 3333 3334 tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, 3335 StringRef Code, 3336 ArrayRef<tooling::Range> Ranges, 3337 StringRef FileName) { 3338 auto Env = Environment::make(Code, FileName, Ranges); 3339 if (!Env) 3340 return {}; 3341 return NamespaceEndCommentsFixer(*Env, Style).process().first; 3342 } 3343 3344 tooling::Replacements separateDefinitionBlocks(const FormatStyle &Style, 3345 StringRef Code, 3346 ArrayRef<tooling::Range> Ranges, 3347 StringRef FileName) { 3348 auto Env = Environment::make(Code, FileName, Ranges); 3349 if (!Env) 3350 return {}; 3351 return DefinitionBlockSeparator(*Env, Style).process().first; 3352 } 3353 3354 tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, 3355 StringRef Code, 3356 ArrayRef<tooling::Range> Ranges, 3357 StringRef FileName) { 3358 auto Env = Environment::make(Code, FileName, Ranges); 3359 if (!Env) 3360 return {}; 3361 return UsingDeclarationsSorter(*Env, Style).process().first; 3362 } 3363 3364 LangOptions getFormattingLangOpts(const FormatStyle &Style) { 3365 LangOptions LangOpts; 3366 3367 FormatStyle::LanguageStandard LexingStd = Style.Standard; 3368 if (LexingStd == FormatStyle::LS_Auto) 3369 LexingStd = FormatStyle::LS_Latest; 3370 if (LexingStd == FormatStyle::LS_Latest) 3371 LexingStd = FormatStyle::LS_Cpp20; 3372 LangOpts.CPlusPlus = 1; 3373 LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11; 3374 LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14; 3375 LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17; 3376 LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20; 3377 LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20; 3378 // Turning on digraphs in standards before C++0x is error-prone, because e.g. 3379 // the sequence "<::" will be unconditionally treated as "[:". 3380 // Cf. Lexer::LexTokenInternal. 3381 LangOpts.Digraphs = LexingStd >= FormatStyle::LS_Cpp11; 3382 3383 LangOpts.LineComment = 1; 3384 bool AlternativeOperators = Style.isCpp(); 3385 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0; 3386 LangOpts.Bool = 1; 3387 LangOpts.ObjC = 1; 3388 LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally. 3389 LangOpts.DeclSpecKeyword = 1; // To get __declspec. 3390 LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict. 3391 return LangOpts; 3392 } 3393 3394 const char *StyleOptionHelpDescription = 3395 "Coding style, currently supports:\n" 3396 " LLVM, GNU, Google, Chromium, Microsoft, Mozilla, WebKit.\n" 3397 "Use -style=file to load style configuration from\n" 3398 ".clang-format file located in one of the parent\n" 3399 "directories of the source file (or current\n" 3400 "directory for stdin).\n" 3401 "Use -style=file:<format_file_path> to explicitly specify\n" 3402 "the configuration file.\n" 3403 "Use -style=\"{key: value, ...}\" to set specific\n" 3404 "parameters, e.g.:\n" 3405 " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""; 3406 3407 static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) { 3408 if (FileName.endswith(".java")) 3409 return FormatStyle::LK_Java; 3410 if (FileName.endswith_insensitive(".js") || 3411 FileName.endswith_insensitive(".mjs") || 3412 FileName.endswith_insensitive(".ts")) 3413 return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript. 3414 if (FileName.endswith(".m") || FileName.endswith(".mm")) 3415 return FormatStyle::LK_ObjC; 3416 if (FileName.endswith_insensitive(".proto") || 3417 FileName.endswith_insensitive(".protodevel")) 3418 return FormatStyle::LK_Proto; 3419 if (FileName.endswith_insensitive(".textpb") || 3420 FileName.endswith_insensitive(".pb.txt") || 3421 FileName.endswith_insensitive(".textproto") || 3422 FileName.endswith_insensitive(".asciipb")) 3423 return FormatStyle::LK_TextProto; 3424 if (FileName.endswith_insensitive(".td")) 3425 return FormatStyle::LK_TableGen; 3426 if (FileName.endswith_insensitive(".cs")) 3427 return FormatStyle::LK_CSharp; 3428 if (FileName.endswith_insensitive(".json")) 3429 return FormatStyle::LK_Json; 3430 return FormatStyle::LK_Cpp; 3431 } 3432 3433 FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) { 3434 const auto GuessedLanguage = getLanguageByFileName(FileName); 3435 if (GuessedLanguage == FormatStyle::LK_Cpp) { 3436 auto Extension = llvm::sys::path::extension(FileName); 3437 // If there's no file extension (or it's .h), we need to check the contents 3438 // of the code to see if it contains Objective-C. 3439 if (Extension.empty() || Extension == ".h") { 3440 auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName; 3441 Environment Env(Code, NonEmptyFileName, /*Ranges=*/{}); 3442 ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle()); 3443 Guesser.process(); 3444 if (Guesser.isObjC()) 3445 return FormatStyle::LK_ObjC; 3446 } 3447 } 3448 return GuessedLanguage; 3449 } 3450 3451 const char *DefaultFormatStyle = "file"; 3452 3453 const char *DefaultFallbackStyle = "LLVM"; 3454 3455 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> 3456 loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS, 3457 FormatStyle *Style, bool AllowUnknownOptions) { 3458 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 3459 FS->getBufferForFile(ConfigFile.str()); 3460 if (auto EC = Text.getError()) 3461 return EC; 3462 if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions)) 3463 return EC; 3464 return Text; 3465 } 3466 3467 llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, 3468 StringRef FallbackStyleName, 3469 StringRef Code, llvm::vfs::FileSystem *FS, 3470 bool AllowUnknownOptions) { 3471 if (!FS) 3472 FS = llvm::vfs::getRealFileSystem().get(); 3473 FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code)); 3474 3475 FormatStyle FallbackStyle = getNoStyle(); 3476 if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle)) 3477 return make_string_error("Invalid fallback style \"" + FallbackStyleName); 3478 3479 llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1> 3480 ChildFormatTextToApply; 3481 3482 if (StyleName.startswith("{")) { 3483 // Parse YAML/JSON style from the command line. 3484 StringRef Source = "<command-line>"; 3485 if (std::error_code ec = 3486 parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style, 3487 AllowUnknownOptions)) 3488 return make_string_error("Error parsing -style: " + ec.message()); 3489 if (Style.InheritsParentConfig) 3490 ChildFormatTextToApply.emplace_back( 3491 llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false)); 3492 else 3493 return Style; 3494 } 3495 3496 // User provided clang-format file using -style=file:path/to/format/file. 3497 if (!Style.InheritsParentConfig && 3498 StyleName.startswith_insensitive("file:")) { 3499 auto ConfigFile = StyleName.substr(5); 3500 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 3501 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions); 3502 if (auto EC = Text.getError()) 3503 return make_string_error("Error reading " + ConfigFile + ": " + 3504 EC.message()); 3505 3506 LLVM_DEBUG(llvm::dbgs() 3507 << "Using configuration file " << ConfigFile << "\n"); 3508 3509 if (!Style.InheritsParentConfig) 3510 return Style; 3511 3512 // Search for parent configs starting from the parent directory of 3513 // ConfigFile. 3514 FileName = ConfigFile; 3515 ChildFormatTextToApply.emplace_back(std::move(*Text)); 3516 } 3517 3518 // If the style inherits the parent configuration it is a command line 3519 // configuration, which wants to inherit, so we have to skip the check of the 3520 // StyleName. 3521 if (!Style.InheritsParentConfig && !StyleName.equals_insensitive("file")) { 3522 if (!getPredefinedStyle(StyleName, Style.Language, &Style)) 3523 return make_string_error("Invalid value for -style"); 3524 if (!Style.InheritsParentConfig) 3525 return Style; 3526 } 3527 3528 // Reset possible inheritance 3529 Style.InheritsParentConfig = false; 3530 3531 // Look for .clang-format/_clang-format file in the file's parent directories. 3532 SmallString<128> UnsuitableConfigFiles; 3533 SmallString<128> Path(FileName); 3534 if (std::error_code EC = FS->makeAbsolute(Path)) 3535 return make_string_error(EC.message()); 3536 3537 llvm::SmallVector<std::string, 2> FilesToLookFor; 3538 FilesToLookFor.push_back(".clang-format"); 3539 FilesToLookFor.push_back("_clang-format"); 3540 3541 auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {}; 3542 3543 auto applyChildFormatTexts = [&](FormatStyle *Style) { 3544 for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) { 3545 auto EC = parseConfiguration(*MemBuf, Style, AllowUnknownOptions, 3546 dropDiagnosticHandler); 3547 // It was already correctly parsed. 3548 assert(!EC); 3549 static_cast<void>(EC); 3550 } 3551 }; 3552 3553 for (StringRef Directory = Path; !Directory.empty(); 3554 Directory = llvm::sys::path::parent_path(Directory)) { 3555 3556 auto Status = FS->status(Directory); 3557 if (!Status || 3558 Status->getType() != llvm::sys::fs::file_type::directory_file) 3559 continue; 3560 3561 for (const auto &F : FilesToLookFor) { 3562 SmallString<128> ConfigFile(Directory); 3563 3564 llvm::sys::path::append(ConfigFile, F); 3565 LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); 3566 3567 Status = FS->status(ConfigFile.str()); 3568 3569 if (Status && 3570 (Status->getType() == llvm::sys::fs::file_type::regular_file)) { 3571 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 3572 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions); 3573 if (auto EC = Text.getError()) { 3574 if (EC == ParseError::Unsuitable) { 3575 if (!UnsuitableConfigFiles.empty()) 3576 UnsuitableConfigFiles.append(", "); 3577 UnsuitableConfigFiles.append(ConfigFile); 3578 continue; 3579 } 3580 return make_string_error("Error reading " + ConfigFile + ": " + 3581 EC.message()); 3582 } 3583 LLVM_DEBUG(llvm::dbgs() 3584 << "Using configuration file " << ConfigFile << "\n"); 3585 3586 if (!Style.InheritsParentConfig) { 3587 if (ChildFormatTextToApply.empty()) 3588 return Style; 3589 3590 LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n"); 3591 applyChildFormatTexts(&Style); 3592 3593 return Style; 3594 } 3595 3596 LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n"); 3597 3598 // Reset inheritance of style 3599 Style.InheritsParentConfig = false; 3600 3601 ChildFormatTextToApply.emplace_back(std::move(*Text)); 3602 3603 // Breaking out of the inner loop, since we don't want to parse 3604 // .clang-format AND _clang-format, if both exist. Then we continue the 3605 // inner loop (parent directories) in search for the parent 3606 // configuration. 3607 break; 3608 } 3609 } 3610 } 3611 if (!UnsuitableConfigFiles.empty()) 3612 return make_string_error("Configuration file(s) do(es) not support " + 3613 getLanguageName(Style.Language) + ": " + 3614 UnsuitableConfigFiles); 3615 3616 if (!ChildFormatTextToApply.empty()) { 3617 LLVM_DEBUG(llvm::dbgs() 3618 << "Applying child configurations on fallback style\n"); 3619 applyChildFormatTexts(&FallbackStyle); 3620 } 3621 3622 return FallbackStyle; 3623 } 3624 3625 } // namespace format 3626 } // namespace clang 3627