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