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