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("PenaltyBreakString", Style.PenaltyBreakString); 1058 IO.mapOptional("PenaltyBreakTemplateDeclaration", 1059 Style.PenaltyBreakTemplateDeclaration); 1060 IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter); 1061 IO.mapOptional("PenaltyIndentedWhitespace", 1062 Style.PenaltyIndentedWhitespace); 1063 IO.mapOptional("PenaltyReturnTypeOnItsOwnLine", 1064 Style.PenaltyReturnTypeOnItsOwnLine); 1065 IO.mapOptional("PointerAlignment", Style.PointerAlignment); 1066 IO.mapOptional("PPIndentWidth", Style.PPIndentWidth); 1067 IO.mapOptional("QualifierAlignment", Style.QualifierAlignment); 1068 // Default Order for Left/Right based Qualifier alignment. 1069 if (Style.QualifierAlignment == FormatStyle::QAS_Right) 1070 Style.QualifierOrder = {"type", "const", "volatile"}; 1071 else if (Style.QualifierAlignment == FormatStyle::QAS_Left) 1072 Style.QualifierOrder = {"const", "volatile", "type"}; 1073 else if (Style.QualifierAlignment == FormatStyle::QAS_Custom) 1074 IO.mapOptional("QualifierOrder", Style.QualifierOrder); 1075 IO.mapOptional("RawStringFormats", Style.RawStringFormats); 1076 IO.mapOptional("ReferenceAlignment", Style.ReferenceAlignment); 1077 IO.mapOptional("ReflowComments", Style.ReflowComments); 1078 IO.mapOptional("RemoveBracesLLVM", Style.RemoveBracesLLVM); 1079 IO.mapOptional("RemoveParentheses", Style.RemoveParentheses); 1080 IO.mapOptional("RemoveSemicolon", Style.RemoveSemicolon); 1081 IO.mapOptional("RequiresClausePosition", Style.RequiresClausePosition); 1082 IO.mapOptional("RequiresExpressionIndentation", 1083 Style.RequiresExpressionIndentation); 1084 IO.mapOptional("SeparateDefinitionBlocks", Style.SeparateDefinitionBlocks); 1085 IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines); 1086 IO.mapOptional("SortIncludes", Style.SortIncludes); 1087 IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport); 1088 IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations); 1089 IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast); 1090 IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot); 1091 IO.mapOptional("SpaceAfterTemplateKeyword", 1092 Style.SpaceAfterTemplateKeyword); 1093 IO.mapOptional("SpaceAroundPointerQualifiers", 1094 Style.SpaceAroundPointerQualifiers); 1095 IO.mapOptional("SpaceBeforeAssignmentOperators", 1096 Style.SpaceBeforeAssignmentOperators); 1097 IO.mapOptional("SpaceBeforeCaseColon", Style.SpaceBeforeCaseColon); 1098 IO.mapOptional("SpaceBeforeCpp11BracedList", 1099 Style.SpaceBeforeCpp11BracedList); 1100 IO.mapOptional("SpaceBeforeCtorInitializerColon", 1101 Style.SpaceBeforeCtorInitializerColon); 1102 IO.mapOptional("SpaceBeforeInheritanceColon", 1103 Style.SpaceBeforeInheritanceColon); 1104 IO.mapOptional("SpaceBeforeJsonColon", Style.SpaceBeforeJsonColon); 1105 IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens); 1106 IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions); 1107 IO.mapOptional("SpaceBeforeRangeBasedForLoopColon", 1108 Style.SpaceBeforeRangeBasedForLoopColon); 1109 IO.mapOptional("SpaceBeforeSquareBrackets", 1110 Style.SpaceBeforeSquareBrackets); 1111 IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock); 1112 IO.mapOptional("SpacesBeforeTrailingComments", 1113 Style.SpacesBeforeTrailingComments); 1114 IO.mapOptional("SpacesInAngles", Style.SpacesInAngles); 1115 IO.mapOptional("SpacesInContainerLiterals", 1116 Style.SpacesInContainerLiterals); 1117 IO.mapOptional("SpacesInLineCommentPrefix", 1118 Style.SpacesInLineCommentPrefix); 1119 IO.mapOptional("SpacesInParens", Style.SpacesInParens); 1120 IO.mapOptional("SpacesInParensOptions", Style.SpacesInParensOptions); 1121 IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets); 1122 IO.mapOptional("Standard", Style.Standard); 1123 IO.mapOptional("StatementAttributeLikeMacros", 1124 Style.StatementAttributeLikeMacros); 1125 IO.mapOptional("StatementMacros", Style.StatementMacros); 1126 IO.mapOptional("TabWidth", Style.TabWidth); 1127 IO.mapOptional("TypeNames", Style.TypeNames); 1128 IO.mapOptional("TypenameMacros", Style.TypenameMacros); 1129 IO.mapOptional("UseTab", Style.UseTab); 1130 IO.mapOptional("VerilogBreakBetweenInstancePorts", 1131 Style.VerilogBreakBetweenInstancePorts); 1132 IO.mapOptional("WhitespaceSensitiveMacros", 1133 Style.WhitespaceSensitiveMacros); 1134 1135 // If AlwaysBreakAfterDefinitionReturnType was specified but 1136 // AlwaysBreakAfterReturnType was not, initialize the latter from the 1137 // former for backwards compatibility. 1138 if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None && 1139 Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) { 1140 if (Style.AlwaysBreakAfterDefinitionReturnType == 1141 FormatStyle::DRTBS_All) { 1142 Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; 1143 } else if (Style.AlwaysBreakAfterDefinitionReturnType == 1144 FormatStyle::DRTBS_TopLevel) { 1145 Style.AlwaysBreakAfterReturnType = 1146 FormatStyle::RTBS_TopLevelDefinitions; 1147 } 1148 } 1149 1150 // If BreakBeforeInheritanceComma was specified but BreakInheritance was 1151 // not, initialize the latter from the former for backwards compatibility. 1152 if (BreakBeforeInheritanceComma && 1153 Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) { 1154 Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma; 1155 } 1156 1157 // If BreakConstructorInitializersBeforeComma was specified but 1158 // BreakConstructorInitializers was not, initialize the latter from the 1159 // former for backwards compatibility. 1160 if (BreakConstructorInitializersBeforeComma && 1161 Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon) { 1162 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 1163 } 1164 1165 if (!IsGoogleOrChromium) { 1166 if (Style.PackConstructorInitializers == FormatStyle::PCIS_BinPack && 1167 OnCurrentLine) { 1168 Style.PackConstructorInitializers = OnNextLine 1169 ? FormatStyle::PCIS_NextLine 1170 : FormatStyle::PCIS_CurrentLine; 1171 } 1172 } else if (Style.PackConstructorInitializers == 1173 FormatStyle::PCIS_NextLine) { 1174 if (!OnCurrentLine) 1175 Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack; 1176 else if (!OnNextLine) 1177 Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine; 1178 } 1179 1180 if (Style.LineEnding == FormatStyle::LE_DeriveLF) { 1181 if (!DeriveLineEnding) 1182 Style.LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF; 1183 else if (UseCRLF) 1184 Style.LineEnding = FormatStyle::LE_DeriveCRLF; 1185 } 1186 1187 if (Style.SpacesInParens != FormatStyle::SIPO_Custom && 1188 (SpacesInParentheses || SpaceInEmptyParentheses || 1189 SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) { 1190 if (SpacesInParentheses) { 1191 // set all options except InCStyleCasts and InEmptyParentheses 1192 // to true for backward compatibility. 1193 Style.SpacesInParensOptions.InConditionalStatements = true; 1194 Style.SpacesInParensOptions.InCStyleCasts = 1195 SpacesInCStyleCastParentheses; 1196 Style.SpacesInParensOptions.InEmptyParentheses = 1197 SpaceInEmptyParentheses; 1198 Style.SpacesInParensOptions.Other = true; 1199 } else { 1200 Style.SpacesInParensOptions = {}; 1201 Style.SpacesInParensOptions.InConditionalStatements = 1202 SpacesInConditionalStatement; 1203 Style.SpacesInParensOptions.InCStyleCasts = 1204 SpacesInCStyleCastParentheses; 1205 Style.SpacesInParensOptions.InEmptyParentheses = 1206 SpaceInEmptyParentheses; 1207 } 1208 Style.SpacesInParens = FormatStyle::SIPO_Custom; 1209 } 1210 } 1211 }; 1212 1213 // Allows to read vector<FormatStyle> while keeping default values. 1214 // IO.getContext() should contain a pointer to the FormatStyle structure, that 1215 // will be used to get default values for missing keys. 1216 // If the first element has no Language specified, it will be treated as the 1217 // default one for the following elements. 1218 template <> struct DocumentListTraits<std::vector<FormatStyle>> { 1219 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) { 1220 return Seq.size(); 1221 } 1222 static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq, 1223 size_t Index) { 1224 if (Index >= Seq.size()) { 1225 assert(Index == Seq.size()); 1226 FormatStyle Template; 1227 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) { 1228 Template = Seq[0]; 1229 } else { 1230 Template = *((const FormatStyle *)IO.getContext()); 1231 Template.Language = FormatStyle::LK_None; 1232 } 1233 Seq.resize(Index + 1, Template); 1234 } 1235 return Seq[Index]; 1236 } 1237 }; 1238 } // namespace yaml 1239 } // namespace llvm 1240 1241 namespace clang { 1242 namespace format { 1243 1244 const std::error_category &getParseCategory() { 1245 static const ParseErrorCategory C{}; 1246 return C; 1247 } 1248 std::error_code make_error_code(ParseError e) { 1249 return std::error_code(static_cast<int>(e), getParseCategory()); 1250 } 1251 1252 inline llvm::Error make_string_error(const llvm::Twine &Message) { 1253 return llvm::make_error<llvm::StringError>(Message, 1254 llvm::inconvertibleErrorCode()); 1255 } 1256 1257 const char *ParseErrorCategory::name() const noexcept { 1258 return "clang-format.parse_error"; 1259 } 1260 1261 std::string ParseErrorCategory::message(int EV) const { 1262 switch (static_cast<ParseError>(EV)) { 1263 case ParseError::Success: 1264 return "Success"; 1265 case ParseError::Error: 1266 return "Invalid argument"; 1267 case ParseError::Unsuitable: 1268 return "Unsuitable"; 1269 case ParseError::BinPackTrailingCommaConflict: 1270 return "trailing comma insertion cannot be used with bin packing"; 1271 case ParseError::InvalidQualifierSpecified: 1272 return "Invalid qualifier specified in QualifierOrder"; 1273 case ParseError::DuplicateQualifierSpecified: 1274 return "Duplicate qualifier specified in QualifierOrder"; 1275 case ParseError::MissingQualifierType: 1276 return "Missing type in QualifierOrder"; 1277 case ParseError::MissingQualifierOrder: 1278 return "Missing QualifierOrder"; 1279 } 1280 llvm_unreachable("unexpected parse error"); 1281 } 1282 1283 static void expandPresetsBraceWrapping(FormatStyle &Expanded) { 1284 if (Expanded.BreakBeforeBraces == FormatStyle::BS_Custom) 1285 return; 1286 Expanded.BraceWrapping = {/*AfterCaseLabel=*/false, 1287 /*AfterClass=*/false, 1288 /*AfterControlStatement=*/FormatStyle::BWACS_Never, 1289 /*AfterEnum=*/false, 1290 /*AfterFunction=*/false, 1291 /*AfterNamespace=*/false, 1292 /*AfterObjCDeclaration=*/false, 1293 /*AfterStruct=*/false, 1294 /*AfterUnion=*/false, 1295 /*AfterExternBlock=*/false, 1296 /*BeforeCatch=*/false, 1297 /*BeforeElse=*/false, 1298 /*BeforeLambdaBody=*/false, 1299 /*BeforeWhile=*/false, 1300 /*IndentBraces=*/false, 1301 /*SplitEmptyFunction=*/true, 1302 /*SplitEmptyRecord=*/true, 1303 /*SplitEmptyNamespace=*/true}; 1304 switch (Expanded.BreakBeforeBraces) { 1305 case FormatStyle::BS_Linux: 1306 Expanded.BraceWrapping.AfterClass = true; 1307 Expanded.BraceWrapping.AfterFunction = true; 1308 Expanded.BraceWrapping.AfterNamespace = true; 1309 break; 1310 case FormatStyle::BS_Mozilla: 1311 Expanded.BraceWrapping.AfterClass = true; 1312 Expanded.BraceWrapping.AfterEnum = true; 1313 Expanded.BraceWrapping.AfterFunction = true; 1314 Expanded.BraceWrapping.AfterStruct = true; 1315 Expanded.BraceWrapping.AfterUnion = true; 1316 Expanded.BraceWrapping.AfterExternBlock = true; 1317 Expanded.BraceWrapping.SplitEmptyFunction = true; 1318 Expanded.BraceWrapping.SplitEmptyRecord = false; 1319 break; 1320 case FormatStyle::BS_Stroustrup: 1321 Expanded.BraceWrapping.AfterFunction = true; 1322 Expanded.BraceWrapping.BeforeCatch = true; 1323 Expanded.BraceWrapping.BeforeElse = true; 1324 break; 1325 case FormatStyle::BS_Allman: 1326 Expanded.BraceWrapping.AfterCaseLabel = true; 1327 Expanded.BraceWrapping.AfterClass = true; 1328 Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; 1329 Expanded.BraceWrapping.AfterEnum = true; 1330 Expanded.BraceWrapping.AfterFunction = true; 1331 Expanded.BraceWrapping.AfterNamespace = true; 1332 Expanded.BraceWrapping.AfterObjCDeclaration = true; 1333 Expanded.BraceWrapping.AfterStruct = true; 1334 Expanded.BraceWrapping.AfterUnion = true; 1335 Expanded.BraceWrapping.AfterExternBlock = true; 1336 Expanded.BraceWrapping.BeforeCatch = true; 1337 Expanded.BraceWrapping.BeforeElse = true; 1338 Expanded.BraceWrapping.BeforeLambdaBody = true; 1339 break; 1340 case FormatStyle::BS_Whitesmiths: 1341 Expanded.BraceWrapping.AfterCaseLabel = true; 1342 Expanded.BraceWrapping.AfterClass = true; 1343 Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; 1344 Expanded.BraceWrapping.AfterEnum = true; 1345 Expanded.BraceWrapping.AfterFunction = true; 1346 Expanded.BraceWrapping.AfterNamespace = true; 1347 Expanded.BraceWrapping.AfterObjCDeclaration = true; 1348 Expanded.BraceWrapping.AfterStruct = true; 1349 Expanded.BraceWrapping.AfterExternBlock = true; 1350 Expanded.BraceWrapping.BeforeCatch = true; 1351 Expanded.BraceWrapping.BeforeElse = true; 1352 Expanded.BraceWrapping.BeforeLambdaBody = true; 1353 break; 1354 case FormatStyle::BS_GNU: 1355 Expanded.BraceWrapping = { 1356 /*AfterCaseLabel=*/true, 1357 /*AfterClass=*/true, 1358 /*AfterControlStatement=*/FormatStyle::BWACS_Always, 1359 /*AfterEnum=*/true, 1360 /*AfterFunction=*/true, 1361 /*AfterNamespace=*/true, 1362 /*AfterObjCDeclaration=*/true, 1363 /*AfterStruct=*/true, 1364 /*AfterUnion=*/true, 1365 /*AfterExternBlock=*/true, 1366 /*BeforeCatch=*/true, 1367 /*BeforeElse=*/true, 1368 /*BeforeLambdaBody=*/false, 1369 /*BeforeWhile=*/true, 1370 /*IndentBraces=*/true, 1371 /*SplitEmptyFunction=*/true, 1372 /*SplitEmptyRecord=*/true, 1373 /*SplitEmptyNamespace=*/true}; 1374 break; 1375 case FormatStyle::BS_WebKit: 1376 Expanded.BraceWrapping.AfterFunction = true; 1377 break; 1378 default: 1379 break; 1380 } 1381 } 1382 1383 static void expandPresetsSpaceBeforeParens(FormatStyle &Expanded) { 1384 if (Expanded.SpaceBeforeParens == FormatStyle::SBPO_Custom) 1385 return; 1386 // Reset all flags 1387 Expanded.SpaceBeforeParensOptions = {}; 1388 1389 switch (Expanded.SpaceBeforeParens) { 1390 case FormatStyle::SBPO_Never: 1391 Expanded.SpaceBeforeParensOptions.AfterPlacementOperator = 1392 FormatStyle::SpaceBeforeParensCustom::APO_Never; 1393 break; 1394 case FormatStyle::SBPO_ControlStatements: 1395 Expanded.SpaceBeforeParensOptions.AfterControlStatements = true; 1396 Expanded.SpaceBeforeParensOptions.AfterForeachMacros = true; 1397 Expanded.SpaceBeforeParensOptions.AfterIfMacros = true; 1398 break; 1399 case FormatStyle::SBPO_ControlStatementsExceptControlMacros: 1400 Expanded.SpaceBeforeParensOptions.AfterControlStatements = true; 1401 break; 1402 case FormatStyle::SBPO_NonEmptyParentheses: 1403 Expanded.SpaceBeforeParensOptions.BeforeNonEmptyParentheses = true; 1404 break; 1405 case FormatStyle::SBPO_Always: 1406 break; 1407 default: 1408 break; 1409 } 1410 } 1411 1412 static void expandPresetsSpacesInParens(FormatStyle &Expanded) { 1413 if (Expanded.SpacesInParens == FormatStyle::SIPO_Custom) 1414 return; 1415 assert(Expanded.SpacesInParens == FormatStyle::SIPO_Never); 1416 // Reset all flags 1417 Expanded.SpacesInParensOptions = {}; 1418 } 1419 1420 FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { 1421 FormatStyle LLVMStyle; 1422 LLVMStyle.InheritsParentConfig = false; 1423 LLVMStyle.Language = Language; 1424 LLVMStyle.AccessModifierOffset = -2; 1425 LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right; 1426 LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align; 1427 LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None; 1428 LLVMStyle.AlignOperands = FormatStyle::OAS_Align; 1429 LLVMStyle.AlignConsecutiveAssignments = {}; 1430 LLVMStyle.AlignConsecutiveAssignments.Enabled = false; 1431 LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false; 1432 LLVMStyle.AlignConsecutiveAssignments.AcrossComments = false; 1433 LLVMStyle.AlignConsecutiveAssignments.AlignCompound = false; 1434 LLVMStyle.AlignConsecutiveAssignments.AlignFunctionPointers = false; 1435 LLVMStyle.AlignConsecutiveAssignments.PadOperators = true; 1436 LLVMStyle.AlignConsecutiveBitFields = {}; 1437 LLVMStyle.AlignConsecutiveDeclarations = {}; 1438 LLVMStyle.AlignConsecutiveMacros = {}; 1439 LLVMStyle.AlignConsecutiveShortCaseStatements = {}; 1440 LLVMStyle.AlignTrailingComments = {}; 1441 LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always; 1442 LLVMStyle.AlignTrailingComments.OverEmptyLines = 0; 1443 LLVMStyle.AllowAllArgumentsOnNextLine = true; 1444 LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; 1445 LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never; 1446 LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; 1447 LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true; 1448 LLVMStyle.AllowShortEnumsOnASingleLine = true; 1449 LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; 1450 LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1451 LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; 1452 LLVMStyle.AllowShortLoopsOnASingleLine = false; 1453 LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; 1454 LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; 1455 LLVMStyle.AlwaysBreakBeforeMultilineStrings = false; 1456 LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine; 1457 LLVMStyle.AttributeMacros.push_back("__capability"); 1458 LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both; 1459 LLVMStyle.BinPackArguments = true; 1460 LLVMStyle.BinPackParameters = true; 1461 LLVMStyle.BracedInitializerIndentWidth = std::nullopt; 1462 LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false, 1463 /*AfterClass=*/false, 1464 /*AfterControlStatement=*/FormatStyle::BWACS_Never, 1465 /*AfterEnum=*/false, 1466 /*AfterFunction=*/false, 1467 /*AfterNamespace=*/false, 1468 /*AfterObjCDeclaration=*/false, 1469 /*AfterStruct=*/false, 1470 /*AfterUnion=*/false, 1471 /*AfterExternBlock=*/false, 1472 /*BeforeCatch=*/false, 1473 /*BeforeElse=*/false, 1474 /*BeforeLambdaBody=*/false, 1475 /*BeforeWhile=*/false, 1476 /*IndentBraces=*/false, 1477 /*SplitEmptyFunction=*/true, 1478 /*SplitEmptyRecord=*/true, 1479 /*SplitEmptyNamespace=*/true}; 1480 LLVMStyle.BreakAdjacentStringLiterals = true; 1481 LLVMStyle.BreakAfterAttributes = FormatStyle::ABS_Leave; 1482 LLVMStyle.BreakAfterJavaFieldAnnotations = false; 1483 LLVMStyle.BreakArrays = true; 1484 LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None; 1485 LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach; 1486 LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always; 1487 LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline; 1488 LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never; 1489 LLVMStyle.BreakBeforeTernaryOperators = true; 1490 LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; 1491 LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon; 1492 LLVMStyle.BreakStringLiterals = true; 1493 LLVMStyle.ColumnLimit = 80; 1494 LLVMStyle.CommentPragmas = "^ IWYU pragma:"; 1495 LLVMStyle.CompactNamespaces = false; 1496 LLVMStyle.ConstructorInitializerIndentWidth = 4; 1497 LLVMStyle.ContinuationIndentWidth = 4; 1498 LLVMStyle.Cpp11BracedListStyle = true; 1499 LLVMStyle.DerivePointerAlignment = false; 1500 LLVMStyle.DisableFormat = false; 1501 LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never; 1502 LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock; 1503 LLVMStyle.ExperimentalAutoDetectBinPacking = false; 1504 LLVMStyle.FixNamespaceComments = true; 1505 LLVMStyle.ForEachMacros.push_back("foreach"); 1506 LLVMStyle.ForEachMacros.push_back("Q_FOREACH"); 1507 LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH"); 1508 LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE"); 1509 LLVMStyle.IncludeStyle.IncludeCategories = { 1510 {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false}, 1511 {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false}, 1512 {".*", 1, 0, false}}; 1513 LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$"; 1514 LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve; 1515 LLVMStyle.IndentAccessModifiers = false; 1516 LLVMStyle.IndentCaseLabels = false; 1517 LLVMStyle.IndentCaseBlocks = false; 1518 LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; 1519 LLVMStyle.IndentGotoLabels = true; 1520 LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None; 1521 LLVMStyle.IndentRequiresClause = true; 1522 LLVMStyle.IndentWidth = 2; 1523 LLVMStyle.IndentWrappedFunctionNames = false; 1524 LLVMStyle.InsertBraces = false; 1525 LLVMStyle.InsertNewlineAtEOF = false; 1526 LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None; 1527 LLVMStyle.IntegerLiteralSeparator = { 1528 /*Binary=*/0, /*BinaryMinDigits=*/0, 1529 /*Decimal=*/0, /*DecimalMinDigits=*/0, 1530 /*Hex=*/0, /*HexMinDigits=*/0}; 1531 LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave; 1532 LLVMStyle.JavaScriptWrapImports = true; 1533 LLVMStyle.KeepEmptyLinesAtEOF = false; 1534 LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true; 1535 LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature; 1536 LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF; 1537 LLVMStyle.MaxEmptyLinesToKeep = 1; 1538 LLVMStyle.NamespaceIndentation = FormatStyle::NI_None; 1539 LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto; 1540 LLVMStyle.ObjCBlockIndentWidth = 2; 1541 LLVMStyle.ObjCBreakBeforeNestedBlockParam = true; 1542 LLVMStyle.ObjCSpaceAfterProperty = false; 1543 LLVMStyle.ObjCSpaceBeforeProtocolList = true; 1544 LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack; 1545 LLVMStyle.PointerAlignment = FormatStyle::PAS_Right; 1546 LLVMStyle.PPIndentWidth = -1; 1547 LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave; 1548 LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer; 1549 LLVMStyle.ReflowComments = true; 1550 LLVMStyle.RemoveBracesLLVM = false; 1551 LLVMStyle.RemoveParentheses = FormatStyle::RPS_Leave; 1552 LLVMStyle.RemoveSemicolon = false; 1553 LLVMStyle.RequiresClausePosition = FormatStyle::RCPS_OwnLine; 1554 LLVMStyle.RequiresExpressionIndentation = FormatStyle::REI_OuterScope; 1555 LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave; 1556 LLVMStyle.ShortNamespaceLines = 1; 1557 LLVMStyle.SortIncludes = FormatStyle::SI_CaseSensitive; 1558 LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before; 1559 LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric; 1560 LLVMStyle.SpaceAfterCStyleCast = false; 1561 LLVMStyle.SpaceAfterLogicalNot = false; 1562 LLVMStyle.SpaceAfterTemplateKeyword = true; 1563 LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default; 1564 LLVMStyle.SpaceBeforeCaseColon = false; 1565 LLVMStyle.SpaceBeforeCtorInitializerColon = true; 1566 LLVMStyle.SpaceBeforeInheritanceColon = true; 1567 LLVMStyle.SpaceBeforeJsonColon = false; 1568 LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements; 1569 LLVMStyle.SpaceBeforeParensOptions = {}; 1570 LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true; 1571 LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true; 1572 LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true; 1573 LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true; 1574 LLVMStyle.SpaceBeforeAssignmentOperators = true; 1575 LLVMStyle.SpaceBeforeCpp11BracedList = false; 1576 LLVMStyle.SpaceBeforeSquareBrackets = false; 1577 LLVMStyle.SpaceInEmptyBlock = false; 1578 LLVMStyle.SpacesBeforeTrailingComments = 1; 1579 LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never; 1580 LLVMStyle.SpacesInContainerLiterals = true; 1581 LLVMStyle.SpacesInLineCommentPrefix = {/*Minimum=*/1, /*Maximum=*/-1u}; 1582 LLVMStyle.SpacesInParens = FormatStyle::SIPO_Never; 1583 LLVMStyle.SpacesInSquareBrackets = false; 1584 LLVMStyle.Standard = FormatStyle::LS_Latest; 1585 LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT"); 1586 LLVMStyle.StatementMacros.push_back("Q_UNUSED"); 1587 LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION"); 1588 LLVMStyle.TabWidth = 8; 1589 LLVMStyle.UseTab = FormatStyle::UT_Never; 1590 LLVMStyle.VerilogBreakBetweenInstancePorts = true; 1591 LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE"); 1592 LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME"); 1593 LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME"); 1594 LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE"); 1595 LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE"); 1596 1597 LLVMStyle.PenaltyBreakAssignment = prec::Assignment; 1598 LLVMStyle.PenaltyBreakComment = 300; 1599 LLVMStyle.PenaltyBreakFirstLessLess = 120; 1600 LLVMStyle.PenaltyBreakString = 1000; 1601 LLVMStyle.PenaltyExcessCharacter = 1000000; 1602 LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60; 1603 LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19; 1604 LLVMStyle.PenaltyBreakOpenParenthesis = 0; 1605 LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational; 1606 LLVMStyle.PenaltyIndentedWhitespace = 0; 1607 1608 // Defaults that differ when not C++. 1609 switch (Language) { 1610 case FormatStyle::LK_TableGen: 1611 LLVMStyle.SpacesInContainerLiterals = false; 1612 break; 1613 case FormatStyle::LK_Json: 1614 LLVMStyle.ColumnLimit = 0; 1615 break; 1616 case FormatStyle::LK_Verilog: 1617 LLVMStyle.IndentCaseLabels = true; 1618 LLVMStyle.SpacesInContainerLiterals = false; 1619 break; 1620 default: 1621 break; 1622 } 1623 1624 return LLVMStyle; 1625 } 1626 1627 FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { 1628 if (Language == FormatStyle::LK_TextProto) { 1629 FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto); 1630 GoogleStyle.Language = FormatStyle::LK_TextProto; 1631 1632 return GoogleStyle; 1633 } 1634 1635 FormatStyle GoogleStyle = getLLVMStyle(Language); 1636 1637 GoogleStyle.AccessModifierOffset = -1; 1638 GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left; 1639 GoogleStyle.AllowShortIfStatementsOnASingleLine = 1640 FormatStyle::SIS_WithoutElse; 1641 GoogleStyle.AllowShortLoopsOnASingleLine = true; 1642 GoogleStyle.AlwaysBreakBeforeMultilineStrings = true; 1643 GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; 1644 GoogleStyle.DerivePointerAlignment = true; 1645 GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false}, 1646 {"^<.*\\.h>", 1, 0, false}, 1647 {"^<.*", 2, 0, false}, 1648 {".*", 3, 0, false}}; 1649 GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$"; 1650 GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 1651 GoogleStyle.IndentCaseLabels = true; 1652 GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false; 1653 GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never; 1654 GoogleStyle.ObjCSpaceAfterProperty = false; 1655 GoogleStyle.ObjCSpaceBeforeProtocolList = true; 1656 GoogleStyle.PackConstructorInitializers = FormatStyle::PCIS_NextLine; 1657 GoogleStyle.PointerAlignment = FormatStyle::PAS_Left; 1658 GoogleStyle.RawStringFormats = { 1659 { 1660 FormatStyle::LK_Cpp, 1661 /*Delimiters=*/ 1662 { 1663 "cc", 1664 "CC", 1665 "cpp", 1666 "Cpp", 1667 "CPP", 1668 "c++", 1669 "C++", 1670 }, 1671 /*EnclosingFunctionNames=*/ 1672 {}, 1673 /*CanonicalDelimiter=*/"", 1674 /*BasedOnStyle=*/"google", 1675 }, 1676 { 1677 FormatStyle::LK_TextProto, 1678 /*Delimiters=*/ 1679 { 1680 "pb", 1681 "PB", 1682 "proto", 1683 "PROTO", 1684 }, 1685 /*EnclosingFunctionNames=*/ 1686 { 1687 "EqualsProto", 1688 "EquivToProto", 1689 "PARSE_PARTIAL_TEXT_PROTO", 1690 "PARSE_TEST_PROTO", 1691 "PARSE_TEXT_PROTO", 1692 "ParseTextOrDie", 1693 "ParseTextProtoOrDie", 1694 "ParseTestProto", 1695 "ParsePartialTestProto", 1696 }, 1697 /*CanonicalDelimiter=*/"pb", 1698 /*BasedOnStyle=*/"google", 1699 }, 1700 }; 1701 GoogleStyle.AttributeMacros.push_back("GUARDED_BY"); 1702 GoogleStyle.AttributeMacros.push_back("ABSL_GUARDED_BY"); 1703 1704 GoogleStyle.SpacesBeforeTrailingComments = 2; 1705 GoogleStyle.Standard = FormatStyle::LS_Auto; 1706 1707 GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200; 1708 GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1; 1709 1710 if (Language == FormatStyle::LK_Java) { 1711 GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; 1712 GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign; 1713 GoogleStyle.AlignTrailingComments = {}; 1714 GoogleStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Never; 1715 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 1716 GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1717 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 1718 GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; 1719 GoogleStyle.ColumnLimit = 100; 1720 GoogleStyle.SpaceAfterCStyleCast = true; 1721 GoogleStyle.SpacesBeforeTrailingComments = 1; 1722 } else if (Language == FormatStyle::LK_JavaScript) { 1723 GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; 1724 GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign; 1725 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 1726 // TODO: still under discussion whether to switch to SLS_All. 1727 GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty; 1728 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 1729 GoogleStyle.BreakBeforeTernaryOperators = false; 1730 // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is 1731 // commonly followed by overlong URLs. 1732 GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)"; 1733 // TODO: enable once decided, in particular re disabling bin packing. 1734 // https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma 1735 // GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped; 1736 GoogleStyle.MaxEmptyLinesToKeep = 3; 1737 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All; 1738 GoogleStyle.SpacesInContainerLiterals = false; 1739 GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single; 1740 GoogleStyle.JavaScriptWrapImports = false; 1741 } else if (Language == FormatStyle::LK_Proto) { 1742 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 1743 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 1744 GoogleStyle.SpacesInContainerLiterals = false; 1745 GoogleStyle.Cpp11BracedListStyle = false; 1746 // This affects protocol buffer options specifications and text protos. 1747 // Text protos are currently mostly formatted inside C++ raw string literals 1748 // and often the current breaking behavior of string literals is not 1749 // beneficial there. Investigate turning this on once proper string reflow 1750 // has been implemented. 1751 GoogleStyle.BreakStringLiterals = false; 1752 } else if (Language == FormatStyle::LK_ObjC) { 1753 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 1754 GoogleStyle.ColumnLimit = 100; 1755 // "Regroup" doesn't work well for ObjC yet (main header heuristic, 1756 // relationship between ObjC standard library headers and other heades, 1757 // #imports, etc.) 1758 GoogleStyle.IncludeStyle.IncludeBlocks = 1759 tooling::IncludeStyle::IBS_Preserve; 1760 } else if (Language == FormatStyle::LK_CSharp) { 1761 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 1762 GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1763 GoogleStyle.BreakStringLiterals = false; 1764 GoogleStyle.ColumnLimit = 100; 1765 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All; 1766 } 1767 1768 return GoogleStyle; 1769 } 1770 1771 FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) { 1772 FormatStyle ChromiumStyle = getGoogleStyle(Language); 1773 1774 // Disable include reordering across blocks in Chromium code. 1775 // - clang-format tries to detect that foo.h is the "main" header for 1776 // foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium 1777 // uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc, 1778 // _private.cc, _impl.cc etc) in different permutations 1779 // (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a 1780 // better default for Chromium code. 1781 // - The default for .cc and .mm files is different (r357695) for Google style 1782 // for the same reason. The plan is to unify this again once the main 1783 // header detection works for Google's ObjC code, but this hasn't happened 1784 // yet. Since Chromium has some ObjC code, switching Chromium is blocked 1785 // on that. 1786 // - Finally, "If include reordering is harmful, put things in different 1787 // blocks to prevent it" has been a recommendation for a long time that 1788 // people are used to. We'll need a dev education push to change this to 1789 // "If include reordering is harmful, put things in a different block and 1790 // _prepend that with a comment_ to prevent it" before changing behavior. 1791 ChromiumStyle.IncludeStyle.IncludeBlocks = 1792 tooling::IncludeStyle::IBS_Preserve; 1793 1794 if (Language == FormatStyle::LK_Java) { 1795 ChromiumStyle.AllowShortIfStatementsOnASingleLine = 1796 FormatStyle::SIS_WithoutElse; 1797 ChromiumStyle.BreakAfterJavaFieldAnnotations = true; 1798 ChromiumStyle.ContinuationIndentWidth = 8; 1799 ChromiumStyle.IndentWidth = 4; 1800 // See styleguide for import groups: 1801 // https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/java/java.md#Import-Order 1802 ChromiumStyle.JavaImportGroups = { 1803 "android", 1804 "androidx", 1805 "com", 1806 "dalvik", 1807 "junit", 1808 "org", 1809 "com.google.android.apps.chrome", 1810 "org.chromium", 1811 "java", 1812 "javax", 1813 }; 1814 ChromiumStyle.SortIncludes = FormatStyle::SI_CaseSensitive; 1815 } else if (Language == FormatStyle::LK_JavaScript) { 1816 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1817 ChromiumStyle.AllowShortLoopsOnASingleLine = false; 1818 } else { 1819 ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false; 1820 ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 1821 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1822 ChromiumStyle.AllowShortLoopsOnASingleLine = false; 1823 ChromiumStyle.BinPackParameters = false; 1824 ChromiumStyle.DerivePointerAlignment = false; 1825 if (Language == FormatStyle::LK_ObjC) 1826 ChromiumStyle.ColumnLimit = 80; 1827 } 1828 return ChromiumStyle; 1829 } 1830 1831 FormatStyle getMozillaStyle() { 1832 FormatStyle MozillaStyle = getLLVMStyle(); 1833 MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false; 1834 MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 1835 MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel; 1836 MozillaStyle.AlwaysBreakAfterDefinitionReturnType = 1837 FormatStyle::DRTBS_TopLevel; 1838 MozillaStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; 1839 MozillaStyle.BinPackParameters = false; 1840 MozillaStyle.BinPackArguments = false; 1841 MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla; 1842 MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 1843 MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma; 1844 MozillaStyle.ConstructorInitializerIndentWidth = 2; 1845 MozillaStyle.ContinuationIndentWidth = 2; 1846 MozillaStyle.Cpp11BracedListStyle = false; 1847 MozillaStyle.FixNamespaceComments = false; 1848 MozillaStyle.IndentCaseLabels = true; 1849 MozillaStyle.ObjCSpaceAfterProperty = true; 1850 MozillaStyle.ObjCSpaceBeforeProtocolList = false; 1851 MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200; 1852 MozillaStyle.PointerAlignment = FormatStyle::PAS_Left; 1853 MozillaStyle.SpaceAfterTemplateKeyword = false; 1854 return MozillaStyle; 1855 } 1856 1857 FormatStyle getWebKitStyle() { 1858 FormatStyle Style = getLLVMStyle(); 1859 Style.AccessModifierOffset = -4; 1860 Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; 1861 Style.AlignOperands = FormatStyle::OAS_DontAlign; 1862 Style.AlignTrailingComments = {}; 1863 Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Never; 1864 Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty; 1865 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 1866 Style.BreakBeforeBraces = FormatStyle::BS_WebKit; 1867 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 1868 Style.Cpp11BracedListStyle = false; 1869 Style.ColumnLimit = 0; 1870 Style.FixNamespaceComments = false; 1871 Style.IndentWidth = 4; 1872 Style.NamespaceIndentation = FormatStyle::NI_Inner; 1873 Style.ObjCBlockIndentWidth = 4; 1874 Style.ObjCSpaceAfterProperty = true; 1875 Style.PointerAlignment = FormatStyle::PAS_Left; 1876 Style.SpaceBeforeCpp11BracedList = true; 1877 Style.SpaceInEmptyBlock = true; 1878 return Style; 1879 } 1880 1881 FormatStyle getGNUStyle() { 1882 FormatStyle Style = getLLVMStyle(); 1883 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; 1884 Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; 1885 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 1886 Style.BreakBeforeBraces = FormatStyle::BS_GNU; 1887 Style.BreakBeforeTernaryOperators = true; 1888 Style.Cpp11BracedListStyle = false; 1889 Style.ColumnLimit = 79; 1890 Style.FixNamespaceComments = false; 1891 Style.SpaceBeforeParens = FormatStyle::SBPO_Always; 1892 Style.Standard = FormatStyle::LS_Cpp03; 1893 return Style; 1894 } 1895 1896 FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) { 1897 FormatStyle Style = getLLVMStyle(Language); 1898 Style.ColumnLimit = 120; 1899 Style.TabWidth = 4; 1900 Style.IndentWidth = 4; 1901 Style.UseTab = FormatStyle::UT_Never; 1902 Style.BreakBeforeBraces = FormatStyle::BS_Custom; 1903 Style.BraceWrapping.AfterClass = true; 1904 Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; 1905 Style.BraceWrapping.AfterEnum = true; 1906 Style.BraceWrapping.AfterFunction = true; 1907 Style.BraceWrapping.AfterNamespace = true; 1908 Style.BraceWrapping.AfterObjCDeclaration = true; 1909 Style.BraceWrapping.AfterStruct = true; 1910 Style.BraceWrapping.AfterExternBlock = true; 1911 Style.BraceWrapping.BeforeCatch = true; 1912 Style.BraceWrapping.BeforeElse = true; 1913 Style.BraceWrapping.BeforeWhile = false; 1914 Style.PenaltyReturnTypeOnItsOwnLine = 1000; 1915 Style.AllowShortEnumsOnASingleLine = false; 1916 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; 1917 Style.AllowShortCaseLabelsOnASingleLine = false; 1918 Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1919 Style.AllowShortLoopsOnASingleLine = false; 1920 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; 1921 Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; 1922 return Style; 1923 } 1924 1925 FormatStyle getClangFormatStyle() { 1926 FormatStyle Style = getLLVMStyle(); 1927 Style.InsertBraces = true; 1928 Style.InsertNewlineAtEOF = true; 1929 Style.LineEnding = FormatStyle::LE_LF; 1930 Style.RemoveBracesLLVM = true; 1931 Style.RemoveParentheses = FormatStyle::RPS_ReturnStatement; 1932 return Style; 1933 } 1934 1935 FormatStyle getNoStyle() { 1936 FormatStyle NoStyle = getLLVMStyle(); 1937 NoStyle.DisableFormat = true; 1938 NoStyle.SortIncludes = FormatStyle::SI_Never; 1939 NoStyle.SortUsingDeclarations = FormatStyle::SUD_Never; 1940 return NoStyle; 1941 } 1942 1943 bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language, 1944 FormatStyle *Style) { 1945 if (Name.equals_insensitive("llvm")) 1946 *Style = getLLVMStyle(Language); 1947 else if (Name.equals_insensitive("chromium")) 1948 *Style = getChromiumStyle(Language); 1949 else if (Name.equals_insensitive("mozilla")) 1950 *Style = getMozillaStyle(); 1951 else if (Name.equals_insensitive("google")) 1952 *Style = getGoogleStyle(Language); 1953 else if (Name.equals_insensitive("webkit")) 1954 *Style = getWebKitStyle(); 1955 else if (Name.equals_insensitive("gnu")) 1956 *Style = getGNUStyle(); 1957 else if (Name.equals_insensitive("microsoft")) 1958 *Style = getMicrosoftStyle(Language); 1959 else if (Name.equals_insensitive("clang-format")) 1960 *Style = getClangFormatStyle(); 1961 else if (Name.equals_insensitive("none")) 1962 *Style = getNoStyle(); 1963 else if (Name.equals_insensitive("inheritparentconfig")) 1964 Style->InheritsParentConfig = true; 1965 else 1966 return false; 1967 1968 Style->Language = Language; 1969 return true; 1970 } 1971 1972 ParseError validateQualifierOrder(FormatStyle *Style) { 1973 // If its empty then it means don't do anything. 1974 if (Style->QualifierOrder.empty()) 1975 return ParseError::MissingQualifierOrder; 1976 1977 // Ensure the list contains only currently valid qualifiers. 1978 for (const auto &Qualifier : Style->QualifierOrder) { 1979 if (Qualifier == "type") 1980 continue; 1981 auto token = 1982 LeftRightQualifierAlignmentFixer::getTokenFromQualifier(Qualifier); 1983 if (token == tok::identifier) 1984 return ParseError::InvalidQualifierSpecified; 1985 } 1986 1987 // Ensure the list is unique (no duplicates). 1988 std::set<std::string> UniqueQualifiers(Style->QualifierOrder.begin(), 1989 Style->QualifierOrder.end()); 1990 if (Style->QualifierOrder.size() != UniqueQualifiers.size()) { 1991 LLVM_DEBUG(llvm::dbgs() 1992 << "Duplicate Qualifiers " << Style->QualifierOrder.size() 1993 << " vs " << UniqueQualifiers.size() << "\n"); 1994 return ParseError::DuplicateQualifierSpecified; 1995 } 1996 1997 // Ensure the list has 'type' in it. 1998 if (!llvm::is_contained(Style->QualifierOrder, "type")) 1999 return ParseError::MissingQualifierType; 2000 2001 return ParseError::Success; 2002 } 2003 2004 std::error_code parseConfiguration(llvm::MemoryBufferRef Config, 2005 FormatStyle *Style, bool AllowUnknownOptions, 2006 llvm::SourceMgr::DiagHandlerTy DiagHandler, 2007 void *DiagHandlerCtxt) { 2008 assert(Style); 2009 FormatStyle::LanguageKind Language = Style->Language; 2010 assert(Language != FormatStyle::LK_None); 2011 if (Config.getBuffer().trim().empty()) 2012 return make_error_code(ParseError::Success); 2013 Style->StyleSet.Clear(); 2014 std::vector<FormatStyle> Styles; 2015 llvm::yaml::Input Input(Config, /*Ctxt=*/nullptr, DiagHandler, 2016 DiagHandlerCtxt); 2017 // DocumentListTraits<vector<FormatStyle>> uses the context to get default 2018 // values for the fields, keys for which are missing from the configuration. 2019 // Mapping also uses the context to get the language to find the correct 2020 // base style. 2021 Input.setContext(Style); 2022 Input.setAllowUnknownKeys(AllowUnknownOptions); 2023 Input >> Styles; 2024 if (Input.error()) 2025 return Input.error(); 2026 2027 for (unsigned i = 0; i < Styles.size(); ++i) { 2028 // Ensures that only the first configuration can skip the Language option. 2029 if (Styles[i].Language == FormatStyle::LK_None && i != 0) 2030 return make_error_code(ParseError::Error); 2031 // Ensure that each language is configured at most once. 2032 for (unsigned j = 0; j < i; ++j) { 2033 if (Styles[i].Language == Styles[j].Language) { 2034 LLVM_DEBUG(llvm::dbgs() 2035 << "Duplicate languages in the config file on positions " 2036 << j << " and " << i << "\n"); 2037 return make_error_code(ParseError::Error); 2038 } 2039 } 2040 } 2041 // Look for a suitable configuration starting from the end, so we can 2042 // find the configuration for the specific language first, and the default 2043 // configuration (which can only be at slot 0) after it. 2044 FormatStyle::FormatStyleSet StyleSet; 2045 bool LanguageFound = false; 2046 for (const FormatStyle &Style : llvm::reverse(Styles)) { 2047 if (Style.Language != FormatStyle::LK_None) 2048 StyleSet.Add(Style); 2049 if (Style.Language == Language) 2050 LanguageFound = true; 2051 } 2052 if (!LanguageFound) { 2053 if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None) 2054 return make_error_code(ParseError::Unsuitable); 2055 FormatStyle DefaultStyle = Styles[0]; 2056 DefaultStyle.Language = Language; 2057 StyleSet.Add(std::move(DefaultStyle)); 2058 } 2059 *Style = *StyleSet.Get(Language); 2060 if (Style->InsertTrailingCommas != FormatStyle::TCS_None && 2061 Style->BinPackArguments) { 2062 // See comment on FormatStyle::TSC_Wrapped. 2063 return make_error_code(ParseError::BinPackTrailingCommaConflict); 2064 } 2065 if (Style->QualifierAlignment != FormatStyle::QAS_Leave) 2066 return make_error_code(validateQualifierOrder(Style)); 2067 return make_error_code(ParseError::Success); 2068 } 2069 2070 std::string configurationAsText(const FormatStyle &Style) { 2071 std::string Text; 2072 llvm::raw_string_ostream Stream(Text); 2073 llvm::yaml::Output Output(Stream); 2074 // We use the same mapping method for input and output, so we need a non-const 2075 // reference here. 2076 FormatStyle NonConstStyle = Style; 2077 expandPresetsBraceWrapping(NonConstStyle); 2078 expandPresetsSpaceBeforeParens(NonConstStyle); 2079 expandPresetsSpacesInParens(NonConstStyle); 2080 Output << NonConstStyle; 2081 2082 return Stream.str(); 2083 } 2084 2085 std::optional<FormatStyle> 2086 FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const { 2087 if (!Styles) 2088 return std::nullopt; 2089 auto It = Styles->find(Language); 2090 if (It == Styles->end()) 2091 return std::nullopt; 2092 FormatStyle Style = It->second; 2093 Style.StyleSet = *this; 2094 return Style; 2095 } 2096 2097 void FormatStyle::FormatStyleSet::Add(FormatStyle Style) { 2098 assert(Style.Language != LK_None && 2099 "Cannot add a style for LK_None to a StyleSet"); 2100 assert( 2101 !Style.StyleSet.Styles && 2102 "Cannot add a style associated with an existing StyleSet to a StyleSet"); 2103 if (!Styles) 2104 Styles = std::make_shared<MapType>(); 2105 (*Styles)[Style.Language] = std::move(Style); 2106 } 2107 2108 void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); } 2109 2110 std::optional<FormatStyle> 2111 FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const { 2112 return StyleSet.Get(Language); 2113 } 2114 2115 namespace { 2116 2117 class ParensRemover : public TokenAnalyzer { 2118 public: 2119 ParensRemover(const Environment &Env, const FormatStyle &Style) 2120 : TokenAnalyzer(Env, Style) {} 2121 2122 std::pair<tooling::Replacements, unsigned> 2123 analyze(TokenAnnotator &Annotator, 2124 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2125 FormatTokenLexer &Tokens) override { 2126 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2127 tooling::Replacements Result; 2128 removeParens(AnnotatedLines, Result); 2129 return {Result, 0}; 2130 } 2131 2132 private: 2133 void removeParens(SmallVectorImpl<AnnotatedLine *> &Lines, 2134 tooling::Replacements &Result) { 2135 const auto &SourceMgr = Env.getSourceManager(); 2136 for (auto *Line : Lines) { 2137 removeParens(Line->Children, Result); 2138 if (!Line->Affected) 2139 continue; 2140 for (const auto *Token = Line->First; Token && !Token->Finalized; 2141 Token = Token->Next) { 2142 if (!Token->Optional || !Token->isOneOf(tok::l_paren, tok::r_paren)) 2143 continue; 2144 auto *Next = Token->Next; 2145 assert(Next && Next->isNot(tok::eof)); 2146 SourceLocation Start; 2147 if (Next->NewlinesBefore == 0) { 2148 Start = Token->Tok.getLocation(); 2149 Next->WhitespaceRange = Token->WhitespaceRange; 2150 } else { 2151 Start = Token->WhitespaceRange.getBegin(); 2152 } 2153 const auto &Range = 2154 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc()); 2155 cantFail(Result.add(tooling::Replacement(SourceMgr, Range, " "))); 2156 } 2157 } 2158 } 2159 }; 2160 2161 class BracesInserter : public TokenAnalyzer { 2162 public: 2163 BracesInserter(const Environment &Env, const FormatStyle &Style) 2164 : TokenAnalyzer(Env, Style) {} 2165 2166 std::pair<tooling::Replacements, unsigned> 2167 analyze(TokenAnnotator &Annotator, 2168 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2169 FormatTokenLexer &Tokens) override { 2170 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2171 tooling::Replacements Result; 2172 insertBraces(AnnotatedLines, Result); 2173 return {Result, 0}; 2174 } 2175 2176 private: 2177 void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines, 2178 tooling::Replacements &Result) { 2179 const auto &SourceMgr = Env.getSourceManager(); 2180 int OpeningBraceSurplus = 0; 2181 for (AnnotatedLine *Line : Lines) { 2182 insertBraces(Line->Children, Result); 2183 if (!Line->Affected && OpeningBraceSurplus == 0) 2184 continue; 2185 for (FormatToken *Token = Line->First; Token && !Token->Finalized; 2186 Token = Token->Next) { 2187 int BraceCount = Token->BraceCount; 2188 if (BraceCount == 0) 2189 continue; 2190 std::string Brace; 2191 if (BraceCount < 0) { 2192 assert(BraceCount == -1); 2193 if (!Line->Affected) 2194 break; 2195 Brace = Token->is(tok::comment) ? "\n{" : "{"; 2196 ++OpeningBraceSurplus; 2197 } else { 2198 if (OpeningBraceSurplus == 0) 2199 break; 2200 if (OpeningBraceSurplus < BraceCount) 2201 BraceCount = OpeningBraceSurplus; 2202 Brace = '\n' + std::string(BraceCount, '}'); 2203 OpeningBraceSurplus -= BraceCount; 2204 } 2205 Token->BraceCount = 0; 2206 const auto Start = Token->Tok.getEndLoc(); 2207 cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0, Brace))); 2208 } 2209 } 2210 assert(OpeningBraceSurplus == 0); 2211 } 2212 }; 2213 2214 class BracesRemover : public TokenAnalyzer { 2215 public: 2216 BracesRemover(const Environment &Env, const FormatStyle &Style) 2217 : TokenAnalyzer(Env, Style) {} 2218 2219 std::pair<tooling::Replacements, unsigned> 2220 analyze(TokenAnnotator &Annotator, 2221 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2222 FormatTokenLexer &Tokens) override { 2223 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2224 tooling::Replacements Result; 2225 removeBraces(AnnotatedLines, Result); 2226 return {Result, 0}; 2227 } 2228 2229 private: 2230 void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines, 2231 tooling::Replacements &Result) { 2232 const auto &SourceMgr = Env.getSourceManager(); 2233 const auto End = Lines.end(); 2234 for (auto I = Lines.begin(); I != End; ++I) { 2235 const auto Line = *I; 2236 removeBraces(Line->Children, Result); 2237 if (!Line->Affected) 2238 continue; 2239 const auto NextLine = I + 1 == End ? nullptr : I[1]; 2240 for (auto Token = Line->First; Token && !Token->Finalized; 2241 Token = Token->Next) { 2242 if (!Token->Optional) 2243 continue; 2244 if (!Token->isOneOf(tok::l_brace, tok::r_brace)) 2245 continue; 2246 auto Next = Token->Next; 2247 assert(Next || Token == Line->Last); 2248 if (!Next && NextLine) 2249 Next = NextLine->First; 2250 SourceLocation Start; 2251 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) { 2252 Start = Token->Tok.getLocation(); 2253 Next->WhitespaceRange = Token->WhitespaceRange; 2254 } else { 2255 Start = Token->WhitespaceRange.getBegin(); 2256 } 2257 const auto Range = 2258 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc()); 2259 cantFail(Result.add(tooling::Replacement(SourceMgr, Range, ""))); 2260 } 2261 } 2262 } 2263 }; 2264 2265 class SemiRemover : public TokenAnalyzer { 2266 public: 2267 SemiRemover(const Environment &Env, const FormatStyle &Style) 2268 : TokenAnalyzer(Env, Style) {} 2269 2270 std::pair<tooling::Replacements, unsigned> 2271 analyze(TokenAnnotator &Annotator, 2272 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2273 FormatTokenLexer &Tokens) override { 2274 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2275 tooling::Replacements Result; 2276 removeSemi(AnnotatedLines, Result); 2277 return {Result, 0}; 2278 } 2279 2280 private: 2281 void removeSemi(SmallVectorImpl<AnnotatedLine *> &Lines, 2282 tooling::Replacements &Result) { 2283 const auto &SourceMgr = Env.getSourceManager(); 2284 const auto End = Lines.end(); 2285 for (auto I = Lines.begin(); I != End; ++I) { 2286 const auto Line = *I; 2287 removeSemi(Line->Children, Result); 2288 if (!Line->Affected) 2289 continue; 2290 const auto NextLine = I + 1 == End ? nullptr : I[1]; 2291 for (auto Token = Line->First; Token && !Token->Finalized; 2292 Token = Token->Next) { 2293 if (!Token->Optional) 2294 continue; 2295 if (Token->isNot(tok::semi)) 2296 continue; 2297 auto Next = Token->Next; 2298 assert(Next || Token == Line->Last); 2299 if (!Next && NextLine) 2300 Next = NextLine->First; 2301 SourceLocation Start; 2302 if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) { 2303 Start = Token->Tok.getLocation(); 2304 Next->WhitespaceRange = Token->WhitespaceRange; 2305 } else { 2306 Start = Token->WhitespaceRange.getBegin(); 2307 } 2308 const auto Range = 2309 CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc()); 2310 cantFail(Result.add(tooling::Replacement(SourceMgr, Range, ""))); 2311 } 2312 } 2313 } 2314 }; 2315 2316 class JavaScriptRequoter : public TokenAnalyzer { 2317 public: 2318 JavaScriptRequoter(const Environment &Env, const FormatStyle &Style) 2319 : TokenAnalyzer(Env, Style) {} 2320 2321 std::pair<tooling::Replacements, unsigned> 2322 analyze(TokenAnnotator &Annotator, 2323 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2324 FormatTokenLexer &Tokens) override { 2325 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2326 tooling::Replacements Result; 2327 requoteJSStringLiteral(AnnotatedLines, Result); 2328 return {Result, 0}; 2329 } 2330 2331 private: 2332 // Replaces double/single-quoted string literal as appropriate, re-escaping 2333 // the contents in the process. 2334 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines, 2335 tooling::Replacements &Result) { 2336 for (AnnotatedLine *Line : Lines) { 2337 requoteJSStringLiteral(Line->Children, Result); 2338 if (!Line->Affected) 2339 continue; 2340 for (FormatToken *FormatTok = Line->First; FormatTok; 2341 FormatTok = FormatTok->Next) { 2342 StringRef Input = FormatTok->TokenText; 2343 if (FormatTok->Finalized || !FormatTok->isStringLiteral() || 2344 // NB: testing for not starting with a double quote to avoid 2345 // breaking `template strings`. 2346 (Style.JavaScriptQuotes == FormatStyle::JSQS_Single && 2347 !Input.starts_with("\"")) || 2348 (Style.JavaScriptQuotes == FormatStyle::JSQS_Double && 2349 !Input.starts_with("\'"))) { 2350 continue; 2351 } 2352 2353 // Change start and end quote. 2354 bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single; 2355 SourceLocation Start = FormatTok->Tok.getLocation(); 2356 auto Replace = [&](SourceLocation Start, unsigned Length, 2357 StringRef ReplacementText) { 2358 auto Err = Result.add(tooling::Replacement( 2359 Env.getSourceManager(), Start, Length, ReplacementText)); 2360 // FIXME: handle error. For now, print error message and skip the 2361 // replacement for release version. 2362 if (Err) { 2363 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 2364 assert(false); 2365 } 2366 }; 2367 Replace(Start, 1, IsSingle ? "'" : "\""); 2368 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1, 2369 IsSingle ? "'" : "\""); 2370 2371 // Escape internal quotes. 2372 bool Escaped = false; 2373 for (size_t i = 1; i < Input.size() - 1; i++) { 2374 switch (Input[i]) { 2375 case '\\': 2376 if (!Escaped && i + 1 < Input.size() && 2377 ((IsSingle && Input[i + 1] == '"') || 2378 (!IsSingle && Input[i + 1] == '\''))) { 2379 // Remove this \, it's escaping a " or ' that no longer needs 2380 // escaping 2381 Replace(Start.getLocWithOffset(i), 1, ""); 2382 continue; 2383 } 2384 Escaped = !Escaped; 2385 break; 2386 case '\"': 2387 case '\'': 2388 if (!Escaped && IsSingle == (Input[i] == '\'')) { 2389 // Escape the quote. 2390 Replace(Start.getLocWithOffset(i), 0, "\\"); 2391 } 2392 Escaped = false; 2393 break; 2394 default: 2395 Escaped = false; 2396 break; 2397 } 2398 } 2399 } 2400 } 2401 } 2402 }; 2403 2404 class Formatter : public TokenAnalyzer { 2405 public: 2406 Formatter(const Environment &Env, const FormatStyle &Style, 2407 FormattingAttemptStatus *Status) 2408 : TokenAnalyzer(Env, Style), Status(Status) {} 2409 2410 std::pair<tooling::Replacements, unsigned> 2411 analyze(TokenAnnotator &Annotator, 2412 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2413 FormatTokenLexer &Tokens) override { 2414 tooling::Replacements Result; 2415 deriveLocalStyle(AnnotatedLines); 2416 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2417 for (AnnotatedLine *Line : AnnotatedLines) 2418 Annotator.calculateFormattingInformation(*Line); 2419 Annotator.setCommentLineLevels(AnnotatedLines); 2420 2421 WhitespaceManager Whitespaces( 2422 Env.getSourceManager(), Style, 2423 Style.LineEnding > FormatStyle::LE_CRLF 2424 ? WhitespaceManager::inputUsesCRLF( 2425 Env.getSourceManager().getBufferData(Env.getFileID()), 2426 Style.LineEnding == FormatStyle::LE_DeriveCRLF) 2427 : Style.LineEnding == FormatStyle::LE_CRLF); 2428 ContinuationIndenter Indenter(Style, Tokens.getKeywords(), 2429 Env.getSourceManager(), Whitespaces, Encoding, 2430 BinPackInconclusiveFunctions); 2431 unsigned Penalty = 2432 UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, 2433 Tokens.getKeywords(), Env.getSourceManager(), 2434 Status) 2435 .format(AnnotatedLines, /*DryRun=*/false, 2436 /*AdditionalIndent=*/0, 2437 /*FixBadIndentation=*/false, 2438 /*FirstStartColumn=*/Env.getFirstStartColumn(), 2439 /*NextStartColumn=*/Env.getNextStartColumn(), 2440 /*LastStartColumn=*/Env.getLastStartColumn()); 2441 for (const auto &R : Whitespaces.generateReplacements()) 2442 if (Result.add(R)) 2443 return std::make_pair(Result, 0); 2444 return std::make_pair(Result, Penalty); 2445 } 2446 2447 private: 2448 bool 2449 hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) { 2450 for (const AnnotatedLine *Line : Lines) { 2451 if (hasCpp03IncompatibleFormat(Line->Children)) 2452 return true; 2453 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) { 2454 if (!Tok->hasWhitespaceBefore()) { 2455 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener)) 2456 return true; 2457 if (Tok->is(TT_TemplateCloser) && 2458 Tok->Previous->is(TT_TemplateCloser)) { 2459 return true; 2460 } 2461 } 2462 } 2463 } 2464 return false; 2465 } 2466 2467 int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) { 2468 int AlignmentDiff = 0; 2469 for (const AnnotatedLine *Line : Lines) { 2470 AlignmentDiff += countVariableAlignments(Line->Children); 2471 for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) { 2472 if (Tok->isNot(TT_PointerOrReference)) 2473 continue; 2474 // Don't treat space in `void foo() &&` as evidence. 2475 if (const auto *Prev = Tok->getPreviousNonComment()) { 2476 if (Prev->is(tok::r_paren) && Prev->MatchingParen) { 2477 if (const auto *Func = 2478 Prev->MatchingParen->getPreviousNonComment()) { 2479 if (Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName, 2480 TT_OverloadedOperator)) { 2481 continue; 2482 } 2483 } 2484 } 2485 } 2486 bool SpaceBefore = Tok->hasWhitespaceBefore(); 2487 bool SpaceAfter = Tok->Next->hasWhitespaceBefore(); 2488 if (SpaceBefore && !SpaceAfter) 2489 ++AlignmentDiff; 2490 if (!SpaceBefore && SpaceAfter) 2491 --AlignmentDiff; 2492 } 2493 } 2494 return AlignmentDiff; 2495 } 2496 2497 void 2498 deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 2499 bool HasBinPackedFunction = false; 2500 bool HasOnePerLineFunction = false; 2501 for (AnnotatedLine *Line : AnnotatedLines) { 2502 if (!Line->First->Next) 2503 continue; 2504 FormatToken *Tok = Line->First->Next; 2505 while (Tok->Next) { 2506 if (Tok->is(PPK_BinPacked)) 2507 HasBinPackedFunction = true; 2508 if (Tok->is(PPK_OnePerLine)) 2509 HasOnePerLineFunction = true; 2510 2511 Tok = Tok->Next; 2512 } 2513 } 2514 if (Style.DerivePointerAlignment) { 2515 const auto NetRightCount = countVariableAlignments(AnnotatedLines); 2516 if (NetRightCount > 0) 2517 Style.PointerAlignment = FormatStyle::PAS_Right; 2518 else if (NetRightCount < 0) 2519 Style.PointerAlignment = FormatStyle::PAS_Left; 2520 Style.ReferenceAlignment = FormatStyle::RAS_Pointer; 2521 } 2522 if (Style.Standard == FormatStyle::LS_Auto) { 2523 Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines) 2524 ? FormatStyle::LS_Latest 2525 : FormatStyle::LS_Cpp03; 2526 } 2527 BinPackInconclusiveFunctions = 2528 HasBinPackedFunction || !HasOnePerLineFunction; 2529 } 2530 2531 bool BinPackInconclusiveFunctions; 2532 FormattingAttemptStatus *Status; 2533 }; 2534 2535 /// TrailingCommaInserter inserts trailing commas into container literals. 2536 /// E.g.: 2537 /// const x = [ 2538 /// 1, 2539 /// ]; 2540 /// TrailingCommaInserter runs after formatting. To avoid causing a required 2541 /// reformatting (and thus reflow), it never inserts a comma that'd exceed the 2542 /// ColumnLimit. 2543 /// 2544 /// Because trailing commas disable binpacking of arrays, TrailingCommaInserter 2545 /// is conceptually incompatible with bin packing. 2546 class TrailingCommaInserter : public TokenAnalyzer { 2547 public: 2548 TrailingCommaInserter(const Environment &Env, const FormatStyle &Style) 2549 : TokenAnalyzer(Env, Style) {} 2550 2551 std::pair<tooling::Replacements, unsigned> 2552 analyze(TokenAnnotator &Annotator, 2553 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2554 FormatTokenLexer &Tokens) override { 2555 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2556 tooling::Replacements Result; 2557 insertTrailingCommas(AnnotatedLines, Result); 2558 return {Result, 0}; 2559 } 2560 2561 private: 2562 /// Inserts trailing commas in [] and {} initializers if they wrap over 2563 /// multiple lines. 2564 void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines, 2565 tooling::Replacements &Result) { 2566 for (AnnotatedLine *Line : Lines) { 2567 insertTrailingCommas(Line->Children, Result); 2568 if (!Line->Affected) 2569 continue; 2570 for (FormatToken *FormatTok = Line->First; FormatTok; 2571 FormatTok = FormatTok->Next) { 2572 if (FormatTok->NewlinesBefore == 0) 2573 continue; 2574 FormatToken *Matching = FormatTok->MatchingParen; 2575 if (!Matching || !FormatTok->getPreviousNonComment()) 2576 continue; 2577 if (!(FormatTok->is(tok::r_square) && 2578 Matching->is(TT_ArrayInitializerLSquare)) && 2579 !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) { 2580 continue; 2581 } 2582 FormatToken *Prev = FormatTok->getPreviousNonComment(); 2583 if (Prev->is(tok::comma) || Prev->is(tok::semi)) 2584 continue; 2585 // getEndLoc is not reliably set during re-lexing, use text length 2586 // instead. 2587 SourceLocation Start = 2588 Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size()); 2589 // If inserting a comma would push the code over the column limit, skip 2590 // this location - it'd introduce an unstable formatting due to the 2591 // required reflow. 2592 unsigned ColumnNumber = 2593 Env.getSourceManager().getSpellingColumnNumber(Start); 2594 if (ColumnNumber > Style.ColumnLimit) 2595 continue; 2596 // Comma insertions cannot conflict with each other, and this pass has a 2597 // clean set of Replacements, so the operation below cannot fail. 2598 cantFail(Result.add( 2599 tooling::Replacement(Env.getSourceManager(), Start, 0, ","))); 2600 } 2601 } 2602 } 2603 }; 2604 2605 // This class clean up the erroneous/redundant code around the given ranges in 2606 // file. 2607 class Cleaner : public TokenAnalyzer { 2608 public: 2609 Cleaner(const Environment &Env, const FormatStyle &Style) 2610 : TokenAnalyzer(Env, Style), 2611 DeletedTokens(FormatTokenLess(Env.getSourceManager())) {} 2612 2613 // FIXME: eliminate unused parameters. 2614 std::pair<tooling::Replacements, unsigned> 2615 analyze(TokenAnnotator &Annotator, 2616 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2617 FormatTokenLexer &Tokens) override { 2618 // FIXME: in the current implementation the granularity of affected range 2619 // is an annotated line. However, this is not sufficient. Furthermore, 2620 // redundant code introduced by replacements does not necessarily 2621 // intercept with ranges of replacements that result in the redundancy. 2622 // To determine if some redundant code is actually introduced by 2623 // replacements(e.g. deletions), we need to come up with a more 2624 // sophisticated way of computing affected ranges. 2625 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 2626 2627 checkEmptyNamespace(AnnotatedLines); 2628 2629 for (auto *Line : AnnotatedLines) 2630 cleanupLine(Line); 2631 2632 return {generateFixes(), 0}; 2633 } 2634 2635 private: 2636 void cleanupLine(AnnotatedLine *Line) { 2637 for (auto *Child : Line->Children) 2638 cleanupLine(Child); 2639 2640 if (Line->Affected) { 2641 cleanupRight(Line->First, tok::comma, tok::comma); 2642 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma); 2643 cleanupRight(Line->First, tok::l_paren, tok::comma); 2644 cleanupLeft(Line->First, tok::comma, tok::r_paren); 2645 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace); 2646 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace); 2647 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal); 2648 } 2649 } 2650 2651 bool containsOnlyComments(const AnnotatedLine &Line) { 2652 for (FormatToken *Tok = Line.First; Tok; Tok = Tok->Next) 2653 if (Tok->isNot(tok::comment)) 2654 return false; 2655 return true; 2656 } 2657 2658 // Iterate through all lines and remove any empty (nested) namespaces. 2659 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 2660 std::set<unsigned> DeletedLines; 2661 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 2662 auto &Line = *AnnotatedLines[i]; 2663 if (Line.startsWithNamespace()) 2664 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines); 2665 } 2666 2667 for (auto Line : DeletedLines) { 2668 FormatToken *Tok = AnnotatedLines[Line]->First; 2669 while (Tok) { 2670 deleteToken(Tok); 2671 Tok = Tok->Next; 2672 } 2673 } 2674 } 2675 2676 // The function checks if the namespace, which starts from \p CurrentLine, and 2677 // its nested namespaces are empty and delete them if they are empty. It also 2678 // sets \p NewLine to the last line checked. 2679 // Returns true if the current namespace is empty. 2680 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2681 unsigned CurrentLine, unsigned &NewLine, 2682 std::set<unsigned> &DeletedLines) { 2683 unsigned InitLine = CurrentLine, End = AnnotatedLines.size(); 2684 if (Style.BraceWrapping.AfterNamespace) { 2685 // If the left brace is in a new line, we should consume it first so that 2686 // it does not make the namespace non-empty. 2687 // FIXME: error handling if there is no left brace. 2688 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) { 2689 NewLine = CurrentLine; 2690 return false; 2691 } 2692 } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) { 2693 return false; 2694 } 2695 while (++CurrentLine < End) { 2696 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace)) 2697 break; 2698 2699 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) { 2700 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine, 2701 DeletedLines)) { 2702 return false; 2703 } 2704 CurrentLine = NewLine; 2705 continue; 2706 } 2707 2708 if (containsOnlyComments(*AnnotatedLines[CurrentLine])) 2709 continue; 2710 2711 // If there is anything other than comments or nested namespaces in the 2712 // current namespace, the namespace cannot be empty. 2713 NewLine = CurrentLine; 2714 return false; 2715 } 2716 2717 NewLine = CurrentLine; 2718 if (CurrentLine >= End) 2719 return false; 2720 2721 // Check if the empty namespace is actually affected by changed ranges. 2722 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange( 2723 AnnotatedLines[InitLine]->First->Tok.getLocation(), 2724 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) { 2725 return false; 2726 } 2727 2728 for (unsigned i = InitLine; i <= CurrentLine; ++i) 2729 DeletedLines.insert(i); 2730 2731 return true; 2732 } 2733 2734 // Checks pairs {start, start->next},..., {end->previous, end} and deletes one 2735 // of the token in the pair if the left token has \p LK token kind and the 2736 // right token has \p RK token kind. If \p DeleteLeft is true, the left token 2737 // is deleted on match; otherwise, the right token is deleted. 2738 template <typename LeftKind, typename RightKind> 2739 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK, 2740 bool DeleteLeft) { 2741 auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * { 2742 for (auto *Res = Tok.Next; Res; Res = Res->Next) { 2743 if (Res->isNot(tok::comment) && 2744 DeletedTokens.find(Res) == DeletedTokens.end()) { 2745 return Res; 2746 } 2747 } 2748 return nullptr; 2749 }; 2750 for (auto *Left = Start; Left;) { 2751 auto *Right = NextNotDeleted(*Left); 2752 if (!Right) 2753 break; 2754 if (Left->is(LK) && Right->is(RK)) { 2755 deleteToken(DeleteLeft ? Left : Right); 2756 for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next) 2757 deleteToken(Tok); 2758 // If the right token is deleted, we should keep the left token 2759 // unchanged and pair it with the new right token. 2760 if (!DeleteLeft) 2761 continue; 2762 } 2763 Left = Right; 2764 } 2765 } 2766 2767 template <typename LeftKind, typename RightKind> 2768 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) { 2769 cleanupPair(Start, LK, RK, /*DeleteLeft=*/true); 2770 } 2771 2772 template <typename LeftKind, typename RightKind> 2773 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) { 2774 cleanupPair(Start, LK, RK, /*DeleteLeft=*/false); 2775 } 2776 2777 // Delete the given token. 2778 inline void deleteToken(FormatToken *Tok) { 2779 if (Tok) 2780 DeletedTokens.insert(Tok); 2781 } 2782 2783 tooling::Replacements generateFixes() { 2784 tooling::Replacements Fixes; 2785 SmallVector<FormatToken *> Tokens; 2786 std::copy(DeletedTokens.begin(), DeletedTokens.end(), 2787 std::back_inserter(Tokens)); 2788 2789 // Merge multiple continuous token deletions into one big deletion so that 2790 // the number of replacements can be reduced. This makes computing affected 2791 // ranges more efficient when we run reformat on the changed code. 2792 unsigned Idx = 0; 2793 while (Idx < Tokens.size()) { 2794 unsigned St = Idx, End = Idx; 2795 while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1]) 2796 ++End; 2797 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(), 2798 Tokens[End]->Tok.getEndLoc()); 2799 auto Err = 2800 Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, "")); 2801 // FIXME: better error handling. for now just print error message and skip 2802 // for the release version. 2803 if (Err) { 2804 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 2805 assert(false && "Fixes must not conflict!"); 2806 } 2807 Idx = End + 1; 2808 } 2809 2810 return Fixes; 2811 } 2812 2813 // Class for less-than inequality comparason for the set `RedundantTokens`. 2814 // We store tokens in the order they appear in the translation unit so that 2815 // we do not need to sort them in `generateFixes()`. 2816 struct FormatTokenLess { 2817 FormatTokenLess(const SourceManager &SM) : SM(SM) {} 2818 2819 bool operator()(const FormatToken *LHS, const FormatToken *RHS) const { 2820 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(), 2821 RHS->Tok.getLocation()); 2822 } 2823 const SourceManager &SM; 2824 }; 2825 2826 // Tokens to be deleted. 2827 std::set<FormatToken *, FormatTokenLess> DeletedTokens; 2828 }; 2829 2830 class ObjCHeaderStyleGuesser : public TokenAnalyzer { 2831 public: 2832 ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style) 2833 : TokenAnalyzer(Env, Style), IsObjC(false) {} 2834 2835 std::pair<tooling::Replacements, unsigned> 2836 analyze(TokenAnnotator &Annotator, 2837 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2838 FormatTokenLexer &Tokens) override { 2839 assert(Style.Language == FormatStyle::LK_Cpp); 2840 IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines, 2841 Tokens.getKeywords()); 2842 tooling::Replacements Result; 2843 return {Result, 0}; 2844 } 2845 2846 bool isObjC() { return IsObjC; } 2847 2848 private: 2849 static bool 2850 guessIsObjC(const SourceManager &SourceManager, 2851 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 2852 const AdditionalKeywords &Keywords) { 2853 // Keep this array sorted, since we are binary searching over it. 2854 static constexpr llvm::StringLiteral FoundationIdentifiers[] = { 2855 "CGFloat", 2856 "CGPoint", 2857 "CGPointMake", 2858 "CGPointZero", 2859 "CGRect", 2860 "CGRectEdge", 2861 "CGRectInfinite", 2862 "CGRectMake", 2863 "CGRectNull", 2864 "CGRectZero", 2865 "CGSize", 2866 "CGSizeMake", 2867 "CGVector", 2868 "CGVectorMake", 2869 "FOUNDATION_EXPORT", // This is an alias for FOUNDATION_EXTERN. 2870 "FOUNDATION_EXTERN", 2871 "NSAffineTransform", 2872 "NSArray", 2873 "NSAttributedString", 2874 "NSBlockOperation", 2875 "NSBundle", 2876 "NSCache", 2877 "NSCalendar", 2878 "NSCharacterSet", 2879 "NSCountedSet", 2880 "NSData", 2881 "NSDataDetector", 2882 "NSDecimal", 2883 "NSDecimalNumber", 2884 "NSDictionary", 2885 "NSEdgeInsets", 2886 "NSError", 2887 "NSErrorDomain", 2888 "NSHashTable", 2889 "NSIndexPath", 2890 "NSIndexSet", 2891 "NSInteger", 2892 "NSInvocationOperation", 2893 "NSLocale", 2894 "NSMapTable", 2895 "NSMutableArray", 2896 "NSMutableAttributedString", 2897 "NSMutableCharacterSet", 2898 "NSMutableData", 2899 "NSMutableDictionary", 2900 "NSMutableIndexSet", 2901 "NSMutableOrderedSet", 2902 "NSMutableSet", 2903 "NSMutableString", 2904 "NSNumber", 2905 "NSNumberFormatter", 2906 "NSObject", 2907 "NSOperation", 2908 "NSOperationQueue", 2909 "NSOperationQueuePriority", 2910 "NSOrderedSet", 2911 "NSPoint", 2912 "NSPointerArray", 2913 "NSQualityOfService", 2914 "NSRange", 2915 "NSRect", 2916 "NSRegularExpression", 2917 "NSSet", 2918 "NSSize", 2919 "NSString", 2920 "NSTimeZone", 2921 "NSUInteger", 2922 "NSURL", 2923 "NSURLComponents", 2924 "NSURLQueryItem", 2925 "NSUUID", 2926 "NSValue", 2927 "NS_ASSUME_NONNULL_BEGIN", 2928 "UIImage", 2929 "UIView", 2930 }; 2931 2932 for (auto *Line : AnnotatedLines) { 2933 if (Line->First && (Line->First->TokenText.starts_with("#") || 2934 Line->First->TokenText == "__pragma" || 2935 Line->First->TokenText == "_Pragma")) { 2936 continue; 2937 } 2938 for (const FormatToken *FormatTok = Line->First; FormatTok; 2939 FormatTok = FormatTok->Next) { 2940 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) && 2941 (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword || 2942 FormatTok->isOneOf(tok::numeric_constant, tok::l_square, 2943 tok::l_brace))) || 2944 (FormatTok->Tok.isAnyIdentifier() && 2945 std::binary_search(std::begin(FoundationIdentifiers), 2946 std::end(FoundationIdentifiers), 2947 FormatTok->TokenText)) || 2948 FormatTok->is(TT_ObjCStringLiteral) || 2949 FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM, 2950 Keywords.kw_NS_ERROR_ENUM, 2951 Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace, 2952 TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn, 2953 TT_ObjCMethodExpr, TT_ObjCMethodSpecifier, 2954 TT_ObjCProperty)) { 2955 LLVM_DEBUG(llvm::dbgs() 2956 << "Detected ObjC at location " 2957 << FormatTok->Tok.getLocation().printToString( 2958 SourceManager) 2959 << " token: " << FormatTok->TokenText << " token type: " 2960 << getTokenTypeName(FormatTok->getType()) << "\n"); 2961 return true; 2962 } 2963 if (guessIsObjC(SourceManager, Line->Children, Keywords)) 2964 return true; 2965 } 2966 } 2967 return false; 2968 } 2969 2970 bool IsObjC; 2971 }; 2972 2973 struct IncludeDirective { 2974 StringRef Filename; 2975 StringRef Text; 2976 unsigned Offset; 2977 int Category; 2978 int Priority; 2979 }; 2980 2981 struct JavaImportDirective { 2982 StringRef Identifier; 2983 StringRef Text; 2984 unsigned Offset; 2985 SmallVector<StringRef> AssociatedCommentLines; 2986 bool IsStatic; 2987 }; 2988 2989 } // end anonymous namespace 2990 2991 // Determines whether 'Ranges' intersects with ('Start', 'End'). 2992 static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start, 2993 unsigned End) { 2994 for (const auto &Range : Ranges) { 2995 if (Range.getOffset() < End && 2996 Range.getOffset() + Range.getLength() > Start) { 2997 return true; 2998 } 2999 } 3000 return false; 3001 } 3002 3003 // Returns a pair (Index, OffsetToEOL) describing the position of the cursor 3004 // before sorting/deduplicating. Index is the index of the include under the 3005 // cursor in the original set of includes. If this include has duplicates, it is 3006 // the index of the first of the duplicates as the others are going to be 3007 // removed. OffsetToEOL describes the cursor's position relative to the end of 3008 // its current line. 3009 // If `Cursor` is not on any #include, `Index` will be UINT_MAX. 3010 static std::pair<unsigned, unsigned> 3011 FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes, 3012 const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) { 3013 unsigned CursorIndex = UINT_MAX; 3014 unsigned OffsetToEOL = 0; 3015 for (int i = 0, e = Includes.size(); i != e; ++i) { 3016 unsigned Start = Includes[Indices[i]].Offset; 3017 unsigned End = Start + Includes[Indices[i]].Text.size(); 3018 if (!(Cursor >= Start && Cursor < End)) 3019 continue; 3020 CursorIndex = Indices[i]; 3021 OffsetToEOL = End - Cursor; 3022 // Put the cursor on the only remaining #include among the duplicate 3023 // #includes. 3024 while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text) 3025 CursorIndex = i; 3026 break; 3027 } 3028 return std::make_pair(CursorIndex, OffsetToEOL); 3029 } 3030 3031 // Replace all "\r\n" with "\n". 3032 std::string replaceCRLF(const std::string &Code) { 3033 std::string NewCode; 3034 size_t Pos = 0, LastPos = 0; 3035 3036 do { 3037 Pos = Code.find("\r\n", LastPos); 3038 if (Pos == LastPos) { 3039 ++LastPos; 3040 continue; 3041 } 3042 if (Pos == std::string::npos) { 3043 NewCode += Code.substr(LastPos); 3044 break; 3045 } 3046 NewCode += Code.substr(LastPos, Pos - LastPos) + "\n"; 3047 LastPos = Pos + 2; 3048 } while (Pos != std::string::npos); 3049 3050 return NewCode; 3051 } 3052 3053 // Sorts and deduplicate a block of includes given by 'Includes' alphabetically 3054 // adding the necessary replacement to 'Replaces'. 'Includes' must be in strict 3055 // source order. 3056 // #include directives with the same text will be deduplicated, and only the 3057 // first #include in the duplicate #includes remains. If the `Cursor` is 3058 // provided and put on a deleted #include, it will be moved to the remaining 3059 // #include in the duplicate #includes. 3060 static void sortCppIncludes(const FormatStyle &Style, 3061 const SmallVectorImpl<IncludeDirective> &Includes, 3062 ArrayRef<tooling::Range> Ranges, StringRef FileName, 3063 StringRef Code, tooling::Replacements &Replaces, 3064 unsigned *Cursor) { 3065 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 3066 const unsigned IncludesBeginOffset = Includes.front().Offset; 3067 const unsigned IncludesEndOffset = 3068 Includes.back().Offset + Includes.back().Text.size(); 3069 const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset; 3070 if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset)) 3071 return; 3072 SmallVector<unsigned, 16> Indices = 3073 llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size())); 3074 3075 if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) { 3076 llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 3077 const auto LHSFilenameLower = Includes[LHSI].Filename.lower(); 3078 const auto RHSFilenameLower = Includes[RHSI].Filename.lower(); 3079 return std::tie(Includes[LHSI].Priority, LHSFilenameLower, 3080 Includes[LHSI].Filename) < 3081 std::tie(Includes[RHSI].Priority, RHSFilenameLower, 3082 Includes[RHSI].Filename); 3083 }); 3084 } else { 3085 llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 3086 return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) < 3087 std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename); 3088 }); 3089 } 3090 3091 // The index of the include on which the cursor will be put after 3092 // sorting/deduplicating. 3093 unsigned CursorIndex; 3094 // The offset from cursor to the end of line. 3095 unsigned CursorToEOLOffset; 3096 if (Cursor) { 3097 std::tie(CursorIndex, CursorToEOLOffset) = 3098 FindCursorIndex(Includes, Indices, *Cursor); 3099 } 3100 3101 // Deduplicate #includes. 3102 Indices.erase(std::unique(Indices.begin(), Indices.end(), 3103 [&](unsigned LHSI, unsigned RHSI) { 3104 return Includes[LHSI].Text.trim() == 3105 Includes[RHSI].Text.trim(); 3106 }), 3107 Indices.end()); 3108 3109 int CurrentCategory = Includes.front().Category; 3110 3111 // If the #includes are out of order, we generate a single replacement fixing 3112 // the entire block. Otherwise, no replacement is generated. 3113 // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not 3114 // enough as additional newlines might be added or removed across #include 3115 // blocks. This we handle below by generating the updated #include blocks and 3116 // comparing it to the original. 3117 if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) && 3118 Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) { 3119 return; 3120 } 3121 3122 std::string result; 3123 for (unsigned Index : Indices) { 3124 if (!result.empty()) { 3125 result += "\n"; 3126 if (Style.IncludeStyle.IncludeBlocks == 3127 tooling::IncludeStyle::IBS_Regroup && 3128 CurrentCategory != Includes[Index].Category) { 3129 result += "\n"; 3130 } 3131 } 3132 result += Includes[Index].Text; 3133 if (Cursor && CursorIndex == Index) 3134 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset; 3135 CurrentCategory = Includes[Index].Category; 3136 } 3137 3138 if (Cursor && *Cursor >= IncludesEndOffset) 3139 *Cursor += result.size() - IncludesBlockSize; 3140 3141 // If the #includes are out of order, we generate a single replacement fixing 3142 // the entire range of blocks. Otherwise, no replacement is generated. 3143 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 3144 IncludesBeginOffset, IncludesBlockSize)))) { 3145 return; 3146 } 3147 3148 auto Err = Replaces.add(tooling::Replacement( 3149 FileName, Includes.front().Offset, IncludesBlockSize, result)); 3150 // FIXME: better error handling. For now, just skip the replacement for the 3151 // release version. 3152 if (Err) { 3153 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 3154 assert(false); 3155 } 3156 } 3157 3158 tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code, 3159 ArrayRef<tooling::Range> Ranges, 3160 StringRef FileName, 3161 tooling::Replacements &Replaces, 3162 unsigned *Cursor) { 3163 unsigned Prev = llvm::StringSwitch<size_t>(Code) 3164 .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM 3165 .Default(0); 3166 unsigned SearchFrom = 0; 3167 SmallVector<StringRef, 4> Matches; 3168 SmallVector<IncludeDirective, 16> IncludesInBlock; 3169 3170 // In compiled files, consider the first #include to be the main #include of 3171 // the file if it is not a system #include. This ensures that the header 3172 // doesn't have hidden dependencies 3173 // (http://llvm.org/docs/CodingStandards.html#include-style). 3174 // 3175 // FIXME: Do some validation, e.g. edit distance of the base name, to fix 3176 // cases where the first #include is unlikely to be the main header. 3177 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 3178 bool FirstIncludeBlock = true; 3179 bool MainIncludeFound = false; 3180 bool FormattingOff = false; 3181 3182 // '[' must be the first and '-' the last character inside [...]. 3183 llvm::Regex RawStringRegex( 3184 "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\("); 3185 SmallVector<StringRef, 2> RawStringMatches; 3186 std::string RawStringTermination = ")\""; 3187 3188 for (;;) { 3189 auto Pos = Code.find('\n', SearchFrom); 3190 StringRef Line = 3191 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 3192 3193 StringRef Trimmed = Line.trim(); 3194 3195 // #includes inside raw string literals need to be ignored. 3196 // or we will sort the contents of the string. 3197 // Skip past until we think we are at the rawstring literal close. 3198 if (RawStringRegex.match(Trimmed, &RawStringMatches)) { 3199 std::string CharSequence = RawStringMatches[1].str(); 3200 RawStringTermination = ")" + CharSequence + "\""; 3201 FormattingOff = true; 3202 } 3203 3204 if (Trimmed.contains(RawStringTermination)) 3205 FormattingOff = false; 3206 3207 if (isClangFormatOff(Trimmed)) 3208 FormattingOff = true; 3209 else if (isClangFormatOn(Trimmed)) 3210 FormattingOff = false; 3211 3212 const bool EmptyLineSkipped = 3213 Trimmed.empty() && 3214 (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge || 3215 Style.IncludeStyle.IncludeBlocks == 3216 tooling::IncludeStyle::IBS_Regroup); 3217 3218 bool MergeWithNextLine = Trimmed.ends_with("\\"); 3219 if (!FormattingOff && !MergeWithNextLine) { 3220 if (tooling::HeaderIncludes::IncludeRegex.match(Line, &Matches)) { 3221 StringRef IncludeName = Matches[2]; 3222 if (Line.contains("/*") && !Line.contains("*/")) { 3223 // #include with a start of a block comment, but without the end. 3224 // Need to keep all the lines until the end of the comment together. 3225 // FIXME: This is somehow simplified check that probably does not work 3226 // correctly if there are multiple comments on a line. 3227 Pos = Code.find("*/", SearchFrom); 3228 Line = Code.substr( 3229 Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev); 3230 } 3231 int Category = Categories.getIncludePriority( 3232 IncludeName, 3233 /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock); 3234 int Priority = Categories.getSortIncludePriority( 3235 IncludeName, !MainIncludeFound && FirstIncludeBlock); 3236 if (Category == 0) 3237 MainIncludeFound = true; 3238 IncludesInBlock.push_back( 3239 {IncludeName, Line, Prev, Category, Priority}); 3240 } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) { 3241 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, 3242 Replaces, Cursor); 3243 IncludesInBlock.clear(); 3244 if (Trimmed.starts_with("#pragma hdrstop")) // Precompiled headers. 3245 FirstIncludeBlock = true; 3246 else 3247 FirstIncludeBlock = false; 3248 } 3249 } 3250 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 3251 break; 3252 3253 if (!MergeWithNextLine) 3254 Prev = Pos + 1; 3255 SearchFrom = Pos + 1; 3256 } 3257 if (!IncludesInBlock.empty()) { 3258 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces, 3259 Cursor); 3260 } 3261 return Replaces; 3262 } 3263 3264 // Returns group number to use as a first order sort on imports. Gives UINT_MAX 3265 // if the import does not match any given groups. 3266 static unsigned findJavaImportGroup(const FormatStyle &Style, 3267 StringRef ImportIdentifier) { 3268 unsigned LongestMatchIndex = UINT_MAX; 3269 unsigned LongestMatchLength = 0; 3270 for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) { 3271 const std::string &GroupPrefix = Style.JavaImportGroups[I]; 3272 if (ImportIdentifier.starts_with(GroupPrefix) && 3273 GroupPrefix.length() > LongestMatchLength) { 3274 LongestMatchIndex = I; 3275 LongestMatchLength = GroupPrefix.length(); 3276 } 3277 } 3278 return LongestMatchIndex; 3279 } 3280 3281 // Sorts and deduplicates a block of includes given by 'Imports' based on 3282 // JavaImportGroups, then adding the necessary replacement to 'Replaces'. 3283 // Import declarations with the same text will be deduplicated. Between each 3284 // import group, a newline is inserted, and within each import group, a 3285 // lexicographic sort based on ASCII value is performed. 3286 static void sortJavaImports(const FormatStyle &Style, 3287 const SmallVectorImpl<JavaImportDirective> &Imports, 3288 ArrayRef<tooling::Range> Ranges, StringRef FileName, 3289 StringRef Code, tooling::Replacements &Replaces) { 3290 unsigned ImportsBeginOffset = Imports.front().Offset; 3291 unsigned ImportsEndOffset = 3292 Imports.back().Offset + Imports.back().Text.size(); 3293 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset; 3294 if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset)) 3295 return; 3296 3297 SmallVector<unsigned, 16> Indices = 3298 llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size())); 3299 SmallVector<unsigned, 16> JavaImportGroups; 3300 JavaImportGroups.reserve(Imports.size()); 3301 for (const JavaImportDirective &Import : Imports) 3302 JavaImportGroups.push_back(findJavaImportGroup(Style, Import.Identifier)); 3303 3304 bool StaticImportAfterNormalImport = 3305 Style.SortJavaStaticImport == FormatStyle::SJSIO_After; 3306 llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 3307 // Negating IsStatic to push static imports above non-static imports. 3308 return std::make_tuple(!Imports[LHSI].IsStatic ^ 3309 StaticImportAfterNormalImport, 3310 JavaImportGroups[LHSI], Imports[LHSI].Identifier) < 3311 std::make_tuple(!Imports[RHSI].IsStatic ^ 3312 StaticImportAfterNormalImport, 3313 JavaImportGroups[RHSI], Imports[RHSI].Identifier); 3314 }); 3315 3316 // Deduplicate imports. 3317 Indices.erase(std::unique(Indices.begin(), Indices.end(), 3318 [&](unsigned LHSI, unsigned RHSI) { 3319 return Imports[LHSI].Text == Imports[RHSI].Text; 3320 }), 3321 Indices.end()); 3322 3323 bool CurrentIsStatic = Imports[Indices.front()].IsStatic; 3324 unsigned CurrentImportGroup = JavaImportGroups[Indices.front()]; 3325 3326 std::string result; 3327 for (unsigned Index : Indices) { 3328 if (!result.empty()) { 3329 result += "\n"; 3330 if (CurrentIsStatic != Imports[Index].IsStatic || 3331 CurrentImportGroup != JavaImportGroups[Index]) { 3332 result += "\n"; 3333 } 3334 } 3335 for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) { 3336 result += CommentLine; 3337 result += "\n"; 3338 } 3339 result += Imports[Index].Text; 3340 CurrentIsStatic = Imports[Index].IsStatic; 3341 CurrentImportGroup = JavaImportGroups[Index]; 3342 } 3343 3344 // If the imports are out of order, we generate a single replacement fixing 3345 // the entire block. Otherwise, no replacement is generated. 3346 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 3347 Imports.front().Offset, ImportsBlockSize)))) { 3348 return; 3349 } 3350 3351 auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset, 3352 ImportsBlockSize, result)); 3353 // FIXME: better error handling. For now, just skip the replacement for the 3354 // release version. 3355 if (Err) { 3356 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 3357 assert(false); 3358 } 3359 } 3360 3361 namespace { 3362 3363 const char JavaImportRegexPattern[] = 3364 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;"; 3365 3366 } // anonymous namespace 3367 3368 tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code, 3369 ArrayRef<tooling::Range> Ranges, 3370 StringRef FileName, 3371 tooling::Replacements &Replaces) { 3372 unsigned Prev = 0; 3373 unsigned SearchFrom = 0; 3374 llvm::Regex ImportRegex(JavaImportRegexPattern); 3375 SmallVector<StringRef, 4> Matches; 3376 SmallVector<JavaImportDirective, 16> ImportsInBlock; 3377 SmallVector<StringRef> AssociatedCommentLines; 3378 3379 bool FormattingOff = false; 3380 3381 for (;;) { 3382 auto Pos = Code.find('\n', SearchFrom); 3383 StringRef Line = 3384 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 3385 3386 StringRef Trimmed = Line.trim(); 3387 if (isClangFormatOff(Trimmed)) 3388 FormattingOff = true; 3389 else if (isClangFormatOn(Trimmed)) 3390 FormattingOff = false; 3391 3392 if (ImportRegex.match(Line, &Matches)) { 3393 if (FormattingOff) { 3394 // If at least one import line has formatting turned off, turn off 3395 // formatting entirely. 3396 return Replaces; 3397 } 3398 StringRef Static = Matches[1]; 3399 StringRef Identifier = Matches[2]; 3400 bool IsStatic = false; 3401 if (Static.contains("static")) 3402 IsStatic = true; 3403 ImportsInBlock.push_back( 3404 {Identifier, Line, Prev, AssociatedCommentLines, IsStatic}); 3405 AssociatedCommentLines.clear(); 3406 } else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) { 3407 // Associating comments within the imports with the nearest import below 3408 AssociatedCommentLines.push_back(Line); 3409 } 3410 Prev = Pos + 1; 3411 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 3412 break; 3413 SearchFrom = Pos + 1; 3414 } 3415 if (!ImportsInBlock.empty()) 3416 sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces); 3417 return Replaces; 3418 } 3419 3420 bool isMpegTS(StringRef Code) { 3421 // MPEG transport streams use the ".ts" file extension. clang-format should 3422 // not attempt to format those. MPEG TS' frame format starts with 0x47 every 3423 // 189 bytes - detect that and return. 3424 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47; 3425 } 3426 3427 bool isLikelyXml(StringRef Code) { return Code.ltrim().starts_with("<"); } 3428 3429 tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, 3430 ArrayRef<tooling::Range> Ranges, 3431 StringRef FileName, unsigned *Cursor) { 3432 tooling::Replacements Replaces; 3433 if (!Style.SortIncludes || Style.DisableFormat) 3434 return Replaces; 3435 if (isLikelyXml(Code)) 3436 return Replaces; 3437 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript && 3438 isMpegTS(Code)) { 3439 return Replaces; 3440 } 3441 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript) 3442 return sortJavaScriptImports(Style, Code, Ranges, FileName); 3443 if (Style.Language == FormatStyle::LanguageKind::LK_Java) 3444 return sortJavaImports(Style, Code, Ranges, FileName, Replaces); 3445 sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor); 3446 return Replaces; 3447 } 3448 3449 template <typename T> 3450 static llvm::Expected<tooling::Replacements> 3451 processReplacements(T ProcessFunc, StringRef Code, 3452 const tooling::Replacements &Replaces, 3453 const FormatStyle &Style) { 3454 if (Replaces.empty()) 3455 return tooling::Replacements(); 3456 3457 auto NewCode = applyAllReplacements(Code, Replaces); 3458 if (!NewCode) 3459 return NewCode.takeError(); 3460 std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges(); 3461 StringRef FileName = Replaces.begin()->getFilePath(); 3462 3463 tooling::Replacements FormatReplaces = 3464 ProcessFunc(Style, *NewCode, ChangedRanges, FileName); 3465 3466 return Replaces.merge(FormatReplaces); 3467 } 3468 3469 llvm::Expected<tooling::Replacements> 3470 formatReplacements(StringRef Code, const tooling::Replacements &Replaces, 3471 const FormatStyle &Style) { 3472 // We need to use lambda function here since there are two versions of 3473 // `sortIncludes`. 3474 auto SortIncludes = [](const FormatStyle &Style, StringRef Code, 3475 std::vector<tooling::Range> Ranges, 3476 StringRef FileName) -> tooling::Replacements { 3477 return sortIncludes(Style, Code, Ranges, FileName); 3478 }; 3479 auto SortedReplaces = 3480 processReplacements(SortIncludes, Code, Replaces, Style); 3481 if (!SortedReplaces) 3482 return SortedReplaces.takeError(); 3483 3484 // We need to use lambda function here since there are two versions of 3485 // `reformat`. 3486 auto Reformat = [](const FormatStyle &Style, StringRef Code, 3487 std::vector<tooling::Range> Ranges, 3488 StringRef FileName) -> tooling::Replacements { 3489 return reformat(Style, Code, Ranges, FileName); 3490 }; 3491 return processReplacements(Reformat, Code, *SortedReplaces, Style); 3492 } 3493 3494 namespace { 3495 3496 inline bool isHeaderInsertion(const tooling::Replacement &Replace) { 3497 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 && 3498 tooling::HeaderIncludes::IncludeRegex.match( 3499 Replace.getReplacementText()); 3500 } 3501 3502 inline bool isHeaderDeletion(const tooling::Replacement &Replace) { 3503 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1; 3504 } 3505 3506 // FIXME: insert empty lines between newly created blocks. 3507 tooling::Replacements 3508 fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces, 3509 const FormatStyle &Style) { 3510 if (!Style.isCpp()) 3511 return Replaces; 3512 3513 tooling::Replacements HeaderInsertions; 3514 std::set<llvm::StringRef> HeadersToDelete; 3515 tooling::Replacements Result; 3516 for (const auto &R : Replaces) { 3517 if (isHeaderInsertion(R)) { 3518 // Replacements from \p Replaces must be conflict-free already, so we can 3519 // simply consume the error. 3520 llvm::consumeError(HeaderInsertions.add(R)); 3521 } else if (isHeaderDeletion(R)) { 3522 HeadersToDelete.insert(R.getReplacementText()); 3523 } else if (R.getOffset() == UINT_MAX) { 3524 llvm::errs() << "Insertions other than header #include insertion are " 3525 "not supported! " 3526 << R.getReplacementText() << "\n"; 3527 } else { 3528 llvm::consumeError(Result.add(R)); 3529 } 3530 } 3531 if (HeaderInsertions.empty() && HeadersToDelete.empty()) 3532 return Replaces; 3533 3534 StringRef FileName = Replaces.begin()->getFilePath(); 3535 tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle); 3536 3537 for (const auto &Header : HeadersToDelete) { 3538 tooling::Replacements Replaces = 3539 Includes.remove(Header.trim("\"<>"), Header.starts_with("<")); 3540 for (const auto &R : Replaces) { 3541 auto Err = Result.add(R); 3542 if (Err) { 3543 // Ignore the deletion on conflict. 3544 llvm::errs() << "Failed to add header deletion replacement for " 3545 << Header << ": " << llvm::toString(std::move(Err)) 3546 << "\n"; 3547 } 3548 } 3549 } 3550 3551 llvm::SmallVector<StringRef, 4> Matches; 3552 for (const auto &R : HeaderInsertions) { 3553 auto IncludeDirective = R.getReplacementText(); 3554 bool Matched = 3555 tooling::HeaderIncludes::IncludeRegex.match(IncludeDirective, &Matches); 3556 assert(Matched && "Header insertion replacement must have replacement text " 3557 "'#include ...'"); 3558 (void)Matched; 3559 auto IncludeName = Matches[2]; 3560 auto Replace = 3561 Includes.insert(IncludeName.trim("\"<>"), IncludeName.starts_with("<"), 3562 tooling::IncludeDirective::Include); 3563 if (Replace) { 3564 auto Err = Result.add(*Replace); 3565 if (Err) { 3566 llvm::consumeError(std::move(Err)); 3567 unsigned NewOffset = 3568 Result.getShiftedCodePosition(Replace->getOffset()); 3569 auto Shifted = tooling::Replacement(FileName, NewOffset, 0, 3570 Replace->getReplacementText()); 3571 Result = Result.merge(tooling::Replacements(Shifted)); 3572 } 3573 } 3574 } 3575 return Result; 3576 } 3577 3578 } // anonymous namespace 3579 3580 llvm::Expected<tooling::Replacements> 3581 cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, 3582 const FormatStyle &Style) { 3583 // We need to use lambda function here since there are two versions of 3584 // `cleanup`. 3585 auto Cleanup = [](const FormatStyle &Style, StringRef Code, 3586 std::vector<tooling::Range> Ranges, 3587 StringRef FileName) -> tooling::Replacements { 3588 return cleanup(Style, Code, Ranges, FileName); 3589 }; 3590 // Make header insertion replacements insert new headers into correct blocks. 3591 tooling::Replacements NewReplaces = 3592 fixCppIncludeInsertions(Code, Replaces, Style); 3593 return cantFail(processReplacements(Cleanup, Code, NewReplaces, Style)); 3594 } 3595 3596 namespace internal { 3597 std::pair<tooling::Replacements, unsigned> 3598 reformat(const FormatStyle &Style, StringRef Code, 3599 ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn, 3600 unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName, 3601 FormattingAttemptStatus *Status) { 3602 FormatStyle Expanded = Style; 3603 expandPresetsBraceWrapping(Expanded); 3604 expandPresetsSpaceBeforeParens(Expanded); 3605 expandPresetsSpacesInParens(Expanded); 3606 Expanded.InsertBraces = false; 3607 Expanded.RemoveBracesLLVM = false; 3608 Expanded.RemoveParentheses = FormatStyle::RPS_Leave; 3609 Expanded.RemoveSemicolon = false; 3610 switch (Expanded.RequiresClausePosition) { 3611 case FormatStyle::RCPS_SingleLine: 3612 case FormatStyle::RCPS_WithPreceding: 3613 Expanded.IndentRequiresClause = false; 3614 break; 3615 default: 3616 break; 3617 } 3618 3619 if (Expanded.DisableFormat) 3620 return {tooling::Replacements(), 0}; 3621 if (isLikelyXml(Code)) 3622 return {tooling::Replacements(), 0}; 3623 if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code)) 3624 return {tooling::Replacements(), 0}; 3625 3626 // JSON only needs the formatting passing. 3627 if (Style.isJson()) { 3628 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size())); 3629 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn, 3630 NextStartColumn, LastStartColumn); 3631 if (!Env) 3632 return {}; 3633 // Perform the actual formatting pass. 3634 tooling::Replacements Replaces = 3635 Formatter(*Env, Style, Status).process().first; 3636 // add a replacement to remove the "x = " from the result. 3637 Replaces = Replaces.merge( 3638 tooling::Replacements(tooling::Replacement(FileName, 0, 4, ""))); 3639 // apply the reformatting changes and the removal of "x = ". 3640 if (applyAllReplacements(Code, Replaces)) 3641 return {Replaces, 0}; 3642 return {tooling::Replacements(), 0}; 3643 } 3644 3645 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn, 3646 NextStartColumn, LastStartColumn); 3647 if (!Env) 3648 return {}; 3649 3650 typedef std::function<std::pair<tooling::Replacements, unsigned>( 3651 const Environment &)> 3652 AnalyzerPass; 3653 3654 SmallVector<AnalyzerPass, 16> Passes; 3655 3656 Passes.emplace_back([&](const Environment &Env) { 3657 return IntegerLiteralSeparatorFixer().process(Env, Expanded); 3658 }); 3659 3660 if (Style.isCpp()) { 3661 if (Style.QualifierAlignment != FormatStyle::QAS_Leave) 3662 addQualifierAlignmentFixerPasses(Expanded, Passes); 3663 3664 if (Style.RemoveParentheses != FormatStyle::RPS_Leave) { 3665 FormatStyle S = Expanded; 3666 S.RemoveParentheses = Style.RemoveParentheses; 3667 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) { 3668 return ParensRemover(Env, S).process(/*SkipAnnotation=*/true); 3669 }); 3670 } 3671 3672 if (Style.InsertBraces) { 3673 FormatStyle S = Expanded; 3674 S.InsertBraces = true; 3675 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) { 3676 return BracesInserter(Env, S).process(/*SkipAnnotation=*/true); 3677 }); 3678 } 3679 3680 if (Style.RemoveBracesLLVM) { 3681 FormatStyle S = Expanded; 3682 S.RemoveBracesLLVM = true; 3683 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) { 3684 return BracesRemover(Env, S).process(/*SkipAnnotation=*/true); 3685 }); 3686 } 3687 3688 if (Style.RemoveSemicolon) { 3689 FormatStyle S = Expanded; 3690 S.RemoveSemicolon = true; 3691 Passes.emplace_back([&, S = std::move(S)](const Environment &Env) { 3692 return SemiRemover(Env, S).process(/*SkipAnnotation=*/true); 3693 }); 3694 } 3695 3696 if (Style.FixNamespaceComments) { 3697 Passes.emplace_back([&](const Environment &Env) { 3698 return NamespaceEndCommentsFixer(Env, Expanded).process(); 3699 }); 3700 } 3701 3702 if (Style.SortUsingDeclarations != FormatStyle::SUD_Never) { 3703 Passes.emplace_back([&](const Environment &Env) { 3704 return UsingDeclarationsSorter(Env, Expanded).process(); 3705 }); 3706 } 3707 } 3708 3709 if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) { 3710 Passes.emplace_back([&](const Environment &Env) { 3711 return DefinitionBlockSeparator(Env, Expanded).process(); 3712 }); 3713 } 3714 3715 if (Style.Language == FormatStyle::LK_ObjC && 3716 !Style.ObjCPropertyAttributeOrder.empty()) { 3717 Passes.emplace_back([&](const Environment &Env) { 3718 return ObjCPropertyAttributeOrderFixer(Env, Expanded).process(); 3719 }); 3720 } 3721 3722 if (Style.isJavaScript() && 3723 Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) { 3724 Passes.emplace_back([&](const Environment &Env) { 3725 return JavaScriptRequoter(Env, Expanded).process(/*SkipAnnotation=*/true); 3726 }); 3727 } 3728 3729 Passes.emplace_back([&](const Environment &Env) { 3730 return Formatter(Env, Expanded, Status).process(); 3731 }); 3732 3733 if (Style.isJavaScript() && 3734 Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) { 3735 Passes.emplace_back([&](const Environment &Env) { 3736 return TrailingCommaInserter(Env, Expanded).process(); 3737 }); 3738 } 3739 3740 std::optional<std::string> CurrentCode; 3741 tooling::Replacements Fixes; 3742 unsigned Penalty = 0; 3743 for (size_t I = 0, E = Passes.size(); I < E; ++I) { 3744 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env); 3745 auto NewCode = applyAllReplacements( 3746 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first); 3747 if (NewCode) { 3748 Fixes = Fixes.merge(PassFixes.first); 3749 Penalty += PassFixes.second; 3750 if (I + 1 < E) { 3751 CurrentCode = std::move(*NewCode); 3752 Env = Environment::make( 3753 *CurrentCode, FileName, 3754 tooling::calculateRangesAfterReplacements(Fixes, Ranges), 3755 FirstStartColumn, NextStartColumn, LastStartColumn); 3756 if (!Env) 3757 return {}; 3758 } 3759 } 3760 } 3761 3762 if (Style.QualifierAlignment != FormatStyle::QAS_Leave) { 3763 // Don't make replacements that replace nothing. QualifierAlignment can 3764 // produce them if one of its early passes changes e.g. `const volatile` to 3765 // `volatile const` and then a later pass changes it back again. 3766 tooling::Replacements NonNoOpFixes; 3767 for (const tooling::Replacement &Fix : Fixes) { 3768 StringRef OriginalCode = Code.substr(Fix.getOffset(), Fix.getLength()); 3769 if (!OriginalCode.equals(Fix.getReplacementText())) { 3770 auto Err = NonNoOpFixes.add(Fix); 3771 if (Err) { 3772 llvm::errs() << "Error adding replacements : " 3773 << llvm::toString(std::move(Err)) << "\n"; 3774 } 3775 } 3776 } 3777 Fixes = std::move(NonNoOpFixes); 3778 } 3779 3780 return {Fixes, Penalty}; 3781 } 3782 } // namespace internal 3783 3784 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 3785 ArrayRef<tooling::Range> Ranges, 3786 StringRef FileName, 3787 FormattingAttemptStatus *Status) { 3788 return internal::reformat(Style, Code, Ranges, 3789 /*FirstStartColumn=*/0, 3790 /*NextStartColumn=*/0, 3791 /*LastStartColumn=*/0, FileName, Status) 3792 .first; 3793 } 3794 3795 tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, 3796 ArrayRef<tooling::Range> Ranges, 3797 StringRef FileName) { 3798 // cleanups only apply to C++ (they mostly concern ctor commas etc.) 3799 if (Style.Language != FormatStyle::LK_Cpp) 3800 return tooling::Replacements(); 3801 auto Env = Environment::make(Code, FileName, Ranges); 3802 if (!Env) 3803 return {}; 3804 return Cleaner(*Env, Style).process().first; 3805 } 3806 3807 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 3808 ArrayRef<tooling::Range> Ranges, 3809 StringRef FileName, bool *IncompleteFormat) { 3810 FormattingAttemptStatus Status; 3811 auto Result = reformat(Style, Code, Ranges, FileName, &Status); 3812 if (!Status.FormatComplete) 3813 *IncompleteFormat = true; 3814 return Result; 3815 } 3816 3817 tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, 3818 StringRef Code, 3819 ArrayRef<tooling::Range> Ranges, 3820 StringRef FileName) { 3821 auto Env = Environment::make(Code, FileName, Ranges); 3822 if (!Env) 3823 return {}; 3824 return NamespaceEndCommentsFixer(*Env, Style).process().first; 3825 } 3826 3827 tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, 3828 StringRef Code, 3829 ArrayRef<tooling::Range> Ranges, 3830 StringRef FileName) { 3831 auto Env = Environment::make(Code, FileName, Ranges); 3832 if (!Env) 3833 return {}; 3834 return UsingDeclarationsSorter(*Env, Style).process().first; 3835 } 3836 3837 LangOptions getFormattingLangOpts(const FormatStyle &Style) { 3838 LangOptions LangOpts; 3839 3840 FormatStyle::LanguageStandard LexingStd = Style.Standard; 3841 if (LexingStd == FormatStyle::LS_Auto) 3842 LexingStd = FormatStyle::LS_Latest; 3843 if (LexingStd == FormatStyle::LS_Latest) 3844 LexingStd = FormatStyle::LS_Cpp20; 3845 LangOpts.CPlusPlus = 1; 3846 LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11; 3847 LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14; 3848 LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17; 3849 LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20; 3850 LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20; 3851 // Turning on digraphs in standards before C++0x is error-prone, because e.g. 3852 // the sequence "<::" will be unconditionally treated as "[:". 3853 // Cf. Lexer::LexTokenInternal. 3854 LangOpts.Digraphs = LexingStd >= FormatStyle::LS_Cpp11; 3855 3856 LangOpts.LineComment = 1; 3857 bool AlternativeOperators = Style.isCpp(); 3858 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0; 3859 LangOpts.Bool = 1; 3860 LangOpts.ObjC = 1; 3861 LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally. 3862 LangOpts.DeclSpecKeyword = 1; // To get __declspec. 3863 LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict. 3864 return LangOpts; 3865 } 3866 3867 const char *StyleOptionHelpDescription = 3868 "Set coding style. <string> can be:\n" 3869 "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n" 3870 " Mozilla, WebKit.\n" 3871 "2. 'file' to load style configuration from a\n" 3872 " .clang-format file in one of the parent directories\n" 3873 " of the source file (for stdin, see --assume-filename).\n" 3874 " If no .clang-format file is found, falls back to\n" 3875 " --fallback-style.\n" 3876 " --style=file is the default.\n" 3877 "3. 'file:<format_file_path>' to explicitly specify\n" 3878 " the configuration file.\n" 3879 "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n" 3880 " --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""; 3881 3882 static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) { 3883 if (FileName.ends_with(".java")) 3884 return FormatStyle::LK_Java; 3885 if (FileName.ends_with_insensitive(".js") || 3886 FileName.ends_with_insensitive(".mjs") || 3887 FileName.ends_with_insensitive(".ts")) { 3888 return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript. 3889 } 3890 if (FileName.ends_with(".m") || FileName.ends_with(".mm")) 3891 return FormatStyle::LK_ObjC; 3892 if (FileName.ends_with_insensitive(".proto") || 3893 FileName.ends_with_insensitive(".protodevel")) { 3894 return FormatStyle::LK_Proto; 3895 } 3896 if (FileName.ends_with_insensitive(".textpb") || 3897 FileName.ends_with_insensitive(".pb.txt") || 3898 FileName.ends_with_insensitive(".textproto") || 3899 FileName.ends_with_insensitive(".asciipb")) { 3900 return FormatStyle::LK_TextProto; 3901 } 3902 if (FileName.ends_with_insensitive(".td")) 3903 return FormatStyle::LK_TableGen; 3904 if (FileName.ends_with_insensitive(".cs")) 3905 return FormatStyle::LK_CSharp; 3906 if (FileName.ends_with_insensitive(".json")) 3907 return FormatStyle::LK_Json; 3908 if (FileName.ends_with_insensitive(".sv") || 3909 FileName.ends_with_insensitive(".svh") || 3910 FileName.ends_with_insensitive(".v") || 3911 FileName.ends_with_insensitive(".vh")) { 3912 return FormatStyle::LK_Verilog; 3913 } 3914 return FormatStyle::LK_Cpp; 3915 } 3916 3917 FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) { 3918 const auto GuessedLanguage = getLanguageByFileName(FileName); 3919 if (GuessedLanguage == FormatStyle::LK_Cpp) { 3920 auto Extension = llvm::sys::path::extension(FileName); 3921 // If there's no file extension (or it's .h), we need to check the contents 3922 // of the code to see if it contains Objective-C. 3923 if (Extension.empty() || Extension == ".h") { 3924 auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName; 3925 Environment Env(Code, NonEmptyFileName, /*Ranges=*/{}); 3926 ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle()); 3927 Guesser.process(); 3928 if (Guesser.isObjC()) 3929 return FormatStyle::LK_ObjC; 3930 } 3931 } 3932 return GuessedLanguage; 3933 } 3934 3935 // Update StyleOptionHelpDescription above when changing this. 3936 const char *DefaultFormatStyle = "file"; 3937 3938 const char *DefaultFallbackStyle = "LLVM"; 3939 3940 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> 3941 loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS, 3942 FormatStyle *Style, bool AllowUnknownOptions) { 3943 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 3944 FS->getBufferForFile(ConfigFile.str()); 3945 if (auto EC = Text.getError()) 3946 return EC; 3947 if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions)) 3948 return EC; 3949 return Text; 3950 } 3951 3952 llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, 3953 StringRef FallbackStyleName, 3954 StringRef Code, llvm::vfs::FileSystem *FS, 3955 bool AllowUnknownOptions) { 3956 FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code)); 3957 FormatStyle FallbackStyle = getNoStyle(); 3958 if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle)) 3959 return make_string_error("Invalid fallback style: " + FallbackStyleName); 3960 3961 llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1> 3962 ChildFormatTextToApply; 3963 3964 if (StyleName.starts_with("{")) { 3965 // Parse YAML/JSON style from the command line. 3966 StringRef Source = "<command-line>"; 3967 if (std::error_code ec = 3968 parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style, 3969 AllowUnknownOptions)) { 3970 return make_string_error("Error parsing -style: " + ec.message()); 3971 } 3972 3973 if (!Style.InheritsParentConfig) 3974 return Style; 3975 3976 ChildFormatTextToApply.emplace_back( 3977 llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false)); 3978 } 3979 3980 if (!FS) 3981 FS = llvm::vfs::getRealFileSystem().get(); 3982 assert(FS); 3983 3984 // User provided clang-format file using -style=file:path/to/format/file. 3985 if (!Style.InheritsParentConfig && 3986 StyleName.starts_with_insensitive("file:")) { 3987 auto ConfigFile = StyleName.substr(5); 3988 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 3989 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions); 3990 if (auto EC = Text.getError()) { 3991 return make_string_error("Error reading " + ConfigFile + ": " + 3992 EC.message()); 3993 } 3994 3995 LLVM_DEBUG(llvm::dbgs() 3996 << "Using configuration file " << ConfigFile << "\n"); 3997 3998 if (!Style.InheritsParentConfig) 3999 return Style; 4000 4001 // Search for parent configs starting from the parent directory of 4002 // ConfigFile. 4003 FileName = ConfigFile; 4004 ChildFormatTextToApply.emplace_back(std::move(*Text)); 4005 } 4006 4007 // If the style inherits the parent configuration it is a command line 4008 // configuration, which wants to inherit, so we have to skip the check of the 4009 // StyleName. 4010 if (!Style.InheritsParentConfig && !StyleName.equals_insensitive("file")) { 4011 if (!getPredefinedStyle(StyleName, Style.Language, &Style)) 4012 return make_string_error("Invalid value for -style"); 4013 if (!Style.InheritsParentConfig) 4014 return Style; 4015 } 4016 4017 SmallString<128> Path(FileName); 4018 if (std::error_code EC = FS->makeAbsolute(Path)) 4019 return make_string_error(EC.message()); 4020 4021 // Reset possible inheritance 4022 Style.InheritsParentConfig = false; 4023 4024 auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {}; 4025 4026 auto applyChildFormatTexts = [&](FormatStyle *Style) { 4027 for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) { 4028 auto EC = parseConfiguration(*MemBuf, Style, AllowUnknownOptions, 4029 dropDiagnosticHandler); 4030 // It was already correctly parsed. 4031 assert(!EC); 4032 static_cast<void>(EC); 4033 } 4034 }; 4035 4036 // Look for .clang-format/_clang-format file in the file's parent directories. 4037 llvm::SmallVector<std::string, 2> FilesToLookFor; 4038 FilesToLookFor.push_back(".clang-format"); 4039 FilesToLookFor.push_back("_clang-format"); 4040 4041 SmallString<128> UnsuitableConfigFiles; 4042 for (StringRef Directory = Path; !Directory.empty(); 4043 Directory = llvm::sys::path::parent_path(Directory)) { 4044 auto Status = FS->status(Directory); 4045 if (!Status || 4046 Status->getType() != llvm::sys::fs::file_type::directory_file) { 4047 continue; 4048 } 4049 4050 for (const auto &F : FilesToLookFor) { 4051 SmallString<128> ConfigFile(Directory); 4052 4053 llvm::sys::path::append(ConfigFile, F); 4054 LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); 4055 4056 Status = FS->status(ConfigFile); 4057 if (!Status || 4058 Status->getType() != llvm::sys::fs::file_type::regular_file) { 4059 continue; 4060 } 4061 4062 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 4063 loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions); 4064 if (auto EC = Text.getError()) { 4065 if (EC != ParseError::Unsuitable) { 4066 return make_string_error("Error reading " + ConfigFile + ": " + 4067 EC.message()); 4068 } 4069 if (!UnsuitableConfigFiles.empty()) 4070 UnsuitableConfigFiles.append(", "); 4071 UnsuitableConfigFiles.append(ConfigFile); 4072 continue; 4073 } 4074 4075 LLVM_DEBUG(llvm::dbgs() 4076 << "Using configuration file " << ConfigFile << "\n"); 4077 4078 if (!Style.InheritsParentConfig) { 4079 if (!ChildFormatTextToApply.empty()) { 4080 LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n"); 4081 applyChildFormatTexts(&Style); 4082 } 4083 return Style; 4084 } 4085 4086 LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n"); 4087 4088 // Reset inheritance of style 4089 Style.InheritsParentConfig = false; 4090 4091 ChildFormatTextToApply.emplace_back(std::move(*Text)); 4092 4093 // Breaking out of the inner loop, since we don't want to parse 4094 // .clang-format AND _clang-format, if both exist. Then we continue the 4095 // outer loop (parent directories) in search for the parent 4096 // configuration. 4097 break; 4098 } 4099 } 4100 4101 if (!UnsuitableConfigFiles.empty()) { 4102 return make_string_error("Configuration file(s) do(es) not support " + 4103 getLanguageName(Style.Language) + ": " + 4104 UnsuitableConfigFiles); 4105 } 4106 4107 if (!ChildFormatTextToApply.empty()) { 4108 LLVM_DEBUG(llvm::dbgs() 4109 << "Applying child configurations on fallback style\n"); 4110 applyChildFormatTexts(&FallbackStyle); 4111 } 4112 4113 return FallbackStyle; 4114 } 4115 4116 static bool isClangFormatOnOff(StringRef Comment, bool On) { 4117 if (Comment == (On ? "/* clang-format on */" : "/* clang-format off */")) 4118 return true; 4119 4120 static const char ClangFormatOn[] = "// clang-format on"; 4121 static const char ClangFormatOff[] = "// clang-format off"; 4122 const unsigned Size = (On ? sizeof ClangFormatOn : sizeof ClangFormatOff) - 1; 4123 4124 return Comment.starts_with(On ? ClangFormatOn : ClangFormatOff) && 4125 (Comment.size() == Size || Comment[Size] == ':'); 4126 } 4127 4128 bool isClangFormatOn(StringRef Comment) { 4129 return isClangFormatOnOff(Comment, /*On=*/true); 4130 } 4131 4132 bool isClangFormatOff(StringRef Comment) { 4133 return isClangFormatOnOff(Comment, /*On=*/false); 4134 } 4135 4136 } // namespace format 4137 } // namespace clang 4138