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