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