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 "ContinuationIndenter.h" 18 #include "FormatInternal.h" 19 #include "FormatTokenLexer.h" 20 #include "NamespaceEndCommentsFixer.h" 21 #include "SortJavaScriptImports.h" 22 #include "TokenAnalyzer.h" 23 #include "TokenAnnotator.h" 24 #include "UnwrappedLineFormatter.h" 25 #include "UnwrappedLineParser.h" 26 #include "UsingDeclarationsSorter.h" 27 #include "WhitespaceManager.h" 28 #include "clang/Basic/Diagnostic.h" 29 #include "clang/Basic/DiagnosticOptions.h" 30 #include "clang/Basic/SourceManager.h" 31 #include "clang/Lex/Lexer.h" 32 #include "clang/Tooling/Inclusions/HeaderIncludes.h" 33 #include "llvm/ADT/STLExtras.h" 34 #include "llvm/ADT/StringRef.h" 35 #include "llvm/Support/Allocator.h" 36 #include "llvm/Support/Debug.h" 37 #include "llvm/Support/Path.h" 38 #include "llvm/Support/Regex.h" 39 #include "llvm/Support/VirtualFileSystem.h" 40 #include "llvm/Support/YAMLTraits.h" 41 #include <algorithm> 42 #include <memory> 43 #include <mutex> 44 #include <string> 45 #include <unordered_map> 46 47 #define DEBUG_TYPE "format-formatter" 48 49 using clang::format::FormatStyle; 50 51 LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat) 52 53 namespace llvm { 54 namespace yaml { 55 template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> { 56 static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) { 57 IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp); 58 IO.enumCase(Value, "Java", FormatStyle::LK_Java); 59 IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript); 60 IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC); 61 IO.enumCase(Value, "Proto", FormatStyle::LK_Proto); 62 IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen); 63 IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto); 64 IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp); 65 } 66 }; 67 68 template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> { 69 static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) { 70 IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03); 71 IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias 72 IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias 73 74 IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11); 75 IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias 76 77 IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14); 78 IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17); 79 IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20); 80 81 IO.enumCase(Value, "Latest", FormatStyle::LS_Latest); 82 IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias 83 IO.enumCase(Value, "Auto", FormatStyle::LS_Auto); 84 } 85 }; 86 87 template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> { 88 static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) { 89 IO.enumCase(Value, "Never", FormatStyle::UT_Never); 90 IO.enumCase(Value, "false", FormatStyle::UT_Never); 91 IO.enumCase(Value, "Always", FormatStyle::UT_Always); 92 IO.enumCase(Value, "true", FormatStyle::UT_Always); 93 IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation); 94 IO.enumCase(Value, "ForContinuationAndIndentation", 95 FormatStyle::UT_ForContinuationAndIndentation); 96 } 97 }; 98 99 template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> { 100 static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) { 101 IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave); 102 IO.enumCase(Value, "Single", FormatStyle::JSQS_Single); 103 IO.enumCase(Value, "Double", FormatStyle::JSQS_Double); 104 } 105 }; 106 107 template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> { 108 static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) { 109 IO.enumCase(Value, "Never", FormatStyle::SBS_Never); 110 IO.enumCase(Value, "false", FormatStyle::SBS_Never); 111 IO.enumCase(Value, "Always", FormatStyle::SBS_Always); 112 IO.enumCase(Value, "true", FormatStyle::SBS_Always); 113 IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty); 114 } 115 }; 116 117 template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> { 118 static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) { 119 IO.enumCase(Value, "None", FormatStyle::SFS_None); 120 IO.enumCase(Value, "false", FormatStyle::SFS_None); 121 IO.enumCase(Value, "All", FormatStyle::SFS_All); 122 IO.enumCase(Value, "true", FormatStyle::SFS_All); 123 IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline); 124 IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly); 125 IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty); 126 } 127 }; 128 129 template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> { 130 static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) { 131 IO.enumCase(Value, "Never", FormatStyle::SIS_Never); 132 IO.enumCase(Value, "Always", FormatStyle::SIS_Always); 133 IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse); 134 135 // For backward compatibility. 136 IO.enumCase(Value, "false", FormatStyle::SIS_Never); 137 IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse); 138 } 139 }; 140 141 template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> { 142 static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) { 143 IO.enumCase(Value, "None", FormatStyle::SLS_None); 144 IO.enumCase(Value, "false", FormatStyle::SLS_None); 145 IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty); 146 IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline); 147 IO.enumCase(Value, "All", FormatStyle::SLS_All); 148 IO.enumCase(Value, "true", FormatStyle::SLS_All); 149 } 150 }; 151 152 template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> { 153 static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) { 154 IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto); 155 IO.enumCase(Value, "Always", FormatStyle::BPS_Always); 156 IO.enumCase(Value, "Never", FormatStyle::BPS_Never); 157 } 158 }; 159 160 template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> { 161 static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) { 162 IO.enumCase(Value, "All", FormatStyle::BOS_All); 163 IO.enumCase(Value, "true", FormatStyle::BOS_All); 164 IO.enumCase(Value, "None", FormatStyle::BOS_None); 165 IO.enumCase(Value, "false", FormatStyle::BOS_None); 166 IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment); 167 } 168 }; 169 170 template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> { 171 static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) { 172 IO.enumCase(Value, "Attach", FormatStyle::BS_Attach); 173 IO.enumCase(Value, "Linux", FormatStyle::BS_Linux); 174 IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla); 175 IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup); 176 IO.enumCase(Value, "Allman", FormatStyle::BS_Allman); 177 IO.enumCase(Value, "Whitesmiths", FormatStyle::BS_Whitesmiths); 178 IO.enumCase(Value, "GNU", FormatStyle::BS_GNU); 179 IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit); 180 IO.enumCase(Value, "Custom", FormatStyle::BS_Custom); 181 } 182 }; 183 184 template <> 185 struct ScalarEnumerationTraits< 186 FormatStyle::BraceWrappingAfterControlStatementStyle> { 187 static void 188 enumeration(IO &IO, 189 FormatStyle::BraceWrappingAfterControlStatementStyle &Value) { 190 IO.enumCase(Value, "false", FormatStyle::BWACS_Never); 191 IO.enumCase(Value, "true", FormatStyle::BWACS_Always); 192 IO.enumCase(Value, "Never", FormatStyle::BWACS_Never); 193 IO.enumCase(Value, "MultiLine", FormatStyle::BWACS_MultiLine); 194 IO.enumCase(Value, "Always", FormatStyle::BWACS_Always); 195 } 196 }; 197 198 template <> 199 struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> { 200 static void 201 enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) { 202 IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon); 203 IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma); 204 IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon); 205 } 206 }; 207 208 template <> 209 struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> { 210 static void enumeration(IO &IO, 211 FormatStyle::BreakInheritanceListStyle &Value) { 212 IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon); 213 IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma); 214 IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon); 215 } 216 }; 217 218 template <> 219 struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> { 220 static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) { 221 IO.enumCase(Value, "None", FormatStyle::PPDIS_None); 222 IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash); 223 IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash); 224 } 225 }; 226 227 template <> 228 struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> { 229 static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) { 230 IO.enumCase(Value, "None", FormatStyle::RTBS_None); 231 IO.enumCase(Value, "All", FormatStyle::RTBS_All); 232 IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel); 233 IO.enumCase(Value, "TopLevelDefinitions", 234 FormatStyle::RTBS_TopLevelDefinitions); 235 IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions); 236 } 237 }; 238 239 template <> 240 struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> { 241 static void enumeration(IO &IO, 242 FormatStyle::BreakTemplateDeclarationsStyle &Value) { 243 IO.enumCase(Value, "No", FormatStyle::BTDS_No); 244 IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine); 245 IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes); 246 247 // For backward compatibility. 248 IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine); 249 IO.enumCase(Value, "true", FormatStyle::BTDS_Yes); 250 } 251 }; 252 253 template <> 254 struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> { 255 static void 256 enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) { 257 IO.enumCase(Value, "None", FormatStyle::DRTBS_None); 258 IO.enumCase(Value, "All", FormatStyle::DRTBS_All); 259 IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel); 260 261 // For backward compatibility. 262 IO.enumCase(Value, "false", FormatStyle::DRTBS_None); 263 IO.enumCase(Value, "true", FormatStyle::DRTBS_All); 264 } 265 }; 266 267 template <> 268 struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> { 269 static void enumeration(IO &IO, 270 FormatStyle::NamespaceIndentationKind &Value) { 271 IO.enumCase(Value, "None", FormatStyle::NI_None); 272 IO.enumCase(Value, "Inner", FormatStyle::NI_Inner); 273 IO.enumCase(Value, "All", FormatStyle::NI_All); 274 } 275 }; 276 277 template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> { 278 static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) { 279 IO.enumCase(Value, "Align", FormatStyle::BAS_Align); 280 IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign); 281 IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak); 282 283 // For backward compatibility. 284 IO.enumCase(Value, "true", FormatStyle::BAS_Align); 285 IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign); 286 } 287 }; 288 289 template <> 290 struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> { 291 static void enumeration(IO &IO, 292 FormatStyle::EscapedNewlineAlignmentStyle &Value) { 293 IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign); 294 IO.enumCase(Value, "Left", FormatStyle::ENAS_Left); 295 IO.enumCase(Value, "Right", FormatStyle::ENAS_Right); 296 297 // For backward compatibility. 298 IO.enumCase(Value, "true", FormatStyle::ENAS_Left); 299 IO.enumCase(Value, "false", FormatStyle::ENAS_Right); 300 } 301 }; 302 303 template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> { 304 static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) { 305 IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle); 306 IO.enumCase(Value, "Left", FormatStyle::PAS_Left); 307 IO.enumCase(Value, "Right", FormatStyle::PAS_Right); 308 309 // For backward compatibility. 310 IO.enumCase(Value, "true", FormatStyle::PAS_Left); 311 IO.enumCase(Value, "false", FormatStyle::PAS_Right); 312 } 313 }; 314 315 template <> 316 struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> { 317 static void enumeration(IO &IO, 318 FormatStyle::SpaceBeforeParensOptions &Value) { 319 IO.enumCase(Value, "Never", FormatStyle::SBPO_Never); 320 IO.enumCase(Value, "ControlStatements", 321 FormatStyle::SBPO_ControlStatements); 322 IO.enumCase(Value, "NonEmptyParentheses", 323 FormatStyle::SBPO_NonEmptyParentheses); 324 IO.enumCase(Value, "Always", FormatStyle::SBPO_Always); 325 326 // For backward compatibility. 327 IO.enumCase(Value, "false", FormatStyle::SBPO_Never); 328 IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements); 329 } 330 }; 331 332 template <> struct MappingTraits<FormatStyle> { 333 static void mapping(IO &IO, FormatStyle &Style) { 334 // When reading, read the language first, we need it for getPredefinedStyle. 335 IO.mapOptional("Language", Style.Language); 336 337 if (IO.outputting()) { 338 StringRef StylesArray[] = {"LLVM", "Google", "Chromium", "Mozilla", 339 "WebKit", "GNU", "Microsoft"}; 340 ArrayRef<StringRef> Styles(StylesArray); 341 for (size_t i = 0, e = Styles.size(); i < e; ++i) { 342 StringRef StyleName(Styles[i]); 343 FormatStyle PredefinedStyle; 344 if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) && 345 Style == PredefinedStyle) { 346 IO.mapOptional("# BasedOnStyle", StyleName); 347 break; 348 } 349 } 350 } else { 351 StringRef BasedOnStyle; 352 IO.mapOptional("BasedOnStyle", BasedOnStyle); 353 if (!BasedOnStyle.empty()) { 354 FormatStyle::LanguageKind OldLanguage = Style.Language; 355 FormatStyle::LanguageKind Language = 356 ((FormatStyle *)IO.getContext())->Language; 357 if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) { 358 IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle)); 359 return; 360 } 361 Style.Language = OldLanguage; 362 } 363 } 364 365 // For backward compatibility. 366 if (!IO.outputting()) { 367 IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines); 368 IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment); 369 IO.mapOptional("IndentFunctionDeclarationAfterType", 370 Style.IndentWrappedFunctionNames); 371 IO.mapOptional("PointerBindsToType", Style.PointerAlignment); 372 IO.mapOptional("SpaceAfterControlStatementKeyword", 373 Style.SpaceBeforeParens); 374 } 375 376 IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset); 377 IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket); 378 IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros); 379 IO.mapOptional("AlignConsecutiveAssignments", 380 Style.AlignConsecutiveAssignments); 381 IO.mapOptional("AlignConsecutiveDeclarations", 382 Style.AlignConsecutiveDeclarations); 383 IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines); 384 IO.mapOptional("AlignOperands", Style.AlignOperands); 385 IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments); 386 IO.mapOptional("AllowAllArgumentsOnNextLine", 387 Style.AllowAllArgumentsOnNextLine); 388 IO.mapOptional("AllowAllConstructorInitializersOnNextLine", 389 Style.AllowAllConstructorInitializersOnNextLine); 390 IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine", 391 Style.AllowAllParametersOfDeclarationOnNextLine); 392 IO.mapOptional("AllowShortBlocksOnASingleLine", 393 Style.AllowShortBlocksOnASingleLine); 394 IO.mapOptional("AllowShortCaseLabelsOnASingleLine", 395 Style.AllowShortCaseLabelsOnASingleLine); 396 IO.mapOptional("AllowShortFunctionsOnASingleLine", 397 Style.AllowShortFunctionsOnASingleLine); 398 IO.mapOptional("AllowShortLambdasOnASingleLine", 399 Style.AllowShortLambdasOnASingleLine); 400 IO.mapOptional("AllowShortIfStatementsOnASingleLine", 401 Style.AllowShortIfStatementsOnASingleLine); 402 IO.mapOptional("AllowShortLoopsOnASingleLine", 403 Style.AllowShortLoopsOnASingleLine); 404 IO.mapOptional("AlwaysBreakAfterDefinitionReturnType", 405 Style.AlwaysBreakAfterDefinitionReturnType); 406 IO.mapOptional("AlwaysBreakAfterReturnType", 407 Style.AlwaysBreakAfterReturnType); 408 409 // If AlwaysBreakAfterDefinitionReturnType was specified but 410 // AlwaysBreakAfterReturnType was not, initialize the latter from the 411 // former for backwards compatibility. 412 if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None && 413 Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) { 414 if (Style.AlwaysBreakAfterDefinitionReturnType == FormatStyle::DRTBS_All) 415 Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; 416 else if (Style.AlwaysBreakAfterDefinitionReturnType == 417 FormatStyle::DRTBS_TopLevel) 418 Style.AlwaysBreakAfterReturnType = 419 FormatStyle::RTBS_TopLevelDefinitions; 420 } 421 422 IO.mapOptional("AlwaysBreakBeforeMultilineStrings", 423 Style.AlwaysBreakBeforeMultilineStrings); 424 IO.mapOptional("AlwaysBreakTemplateDeclarations", 425 Style.AlwaysBreakTemplateDeclarations); 426 IO.mapOptional("BinPackArguments", Style.BinPackArguments); 427 IO.mapOptional("BinPackParameters", Style.BinPackParameters); 428 IO.mapOptional("BraceWrapping", Style.BraceWrapping); 429 IO.mapOptional("BreakBeforeBinaryOperators", 430 Style.BreakBeforeBinaryOperators); 431 IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces); 432 433 bool BreakBeforeInheritanceComma = false; 434 IO.mapOptional("BreakBeforeInheritanceComma", BreakBeforeInheritanceComma); 435 IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList); 436 // If BreakBeforeInheritanceComma was specified but 437 // BreakInheritance was not, initialize the latter from the 438 // former for backwards compatibility. 439 if (BreakBeforeInheritanceComma && 440 Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) 441 Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma; 442 443 IO.mapOptional("BreakBeforeTernaryOperators", 444 Style.BreakBeforeTernaryOperators); 445 446 bool BreakConstructorInitializersBeforeComma = false; 447 IO.mapOptional("BreakConstructorInitializersBeforeComma", 448 BreakConstructorInitializersBeforeComma); 449 IO.mapOptional("BreakConstructorInitializers", 450 Style.BreakConstructorInitializers); 451 // If BreakConstructorInitializersBeforeComma was specified but 452 // BreakConstructorInitializers was not, initialize the latter from the 453 // former for backwards compatibility. 454 if (BreakConstructorInitializersBeforeComma && 455 Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon) 456 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 457 458 IO.mapOptional("BreakAfterJavaFieldAnnotations", 459 Style.BreakAfterJavaFieldAnnotations); 460 IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals); 461 IO.mapOptional("ColumnLimit", Style.ColumnLimit); 462 IO.mapOptional("CommentPragmas", Style.CommentPragmas); 463 IO.mapOptional("CompactNamespaces", Style.CompactNamespaces); 464 IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine", 465 Style.ConstructorInitializerAllOnOneLineOrOnePerLine); 466 IO.mapOptional("ConstructorInitializerIndentWidth", 467 Style.ConstructorInitializerIndentWidth); 468 IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth); 469 IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle); 470 IO.mapOptional("DeriveLineEnding", Style.DeriveLineEnding); 471 IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment); 472 IO.mapOptional("DisableFormat", Style.DisableFormat); 473 IO.mapOptional("ExperimentalAutoDetectBinPacking", 474 Style.ExperimentalAutoDetectBinPacking); 475 IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments); 476 IO.mapOptional("ForEachMacros", Style.ForEachMacros); 477 IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks); 478 IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories); 479 IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex); 480 IO.mapOptional("IncludeIsMainSourceRegex", 481 Style.IncludeStyle.IncludeIsMainSourceRegex); 482 IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels); 483 IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks); 484 IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels); 485 IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives); 486 IO.mapOptional("IndentWidth", Style.IndentWidth); 487 IO.mapOptional("IndentWrappedFunctionNames", 488 Style.IndentWrappedFunctionNames); 489 IO.mapOptional("JavaImportGroups", Style.JavaImportGroups); 490 IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes); 491 IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports); 492 IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks", 493 Style.KeepEmptyLinesAtTheStartOfBlocks); 494 IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin); 495 IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd); 496 IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep); 497 IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation); 498 IO.mapOptional("NamespaceMacros", Style.NamespaceMacros); 499 IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList); 500 IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth); 501 IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty); 502 IO.mapOptional("ObjCSpaceBeforeProtocolList", 503 Style.ObjCSpaceBeforeProtocolList); 504 IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment); 505 IO.mapOptional("PenaltyBreakBeforeFirstCallParameter", 506 Style.PenaltyBreakBeforeFirstCallParameter); 507 IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment); 508 IO.mapOptional("PenaltyBreakFirstLessLess", 509 Style.PenaltyBreakFirstLessLess); 510 IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString); 511 IO.mapOptional("PenaltyBreakTemplateDeclaration", 512 Style.PenaltyBreakTemplateDeclaration); 513 IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter); 514 IO.mapOptional("PenaltyReturnTypeOnItsOwnLine", 515 Style.PenaltyReturnTypeOnItsOwnLine); 516 IO.mapOptional("PointerAlignment", Style.PointerAlignment); 517 IO.mapOptional("RawStringFormats", Style.RawStringFormats); 518 IO.mapOptional("ReflowComments", Style.ReflowComments); 519 IO.mapOptional("SortIncludes", Style.SortIncludes); 520 IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations); 521 IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast); 522 IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot); 523 IO.mapOptional("SpaceAfterTemplateKeyword", 524 Style.SpaceAfterTemplateKeyword); 525 IO.mapOptional("SpaceBeforeAssignmentOperators", 526 Style.SpaceBeforeAssignmentOperators); 527 IO.mapOptional("SpaceBeforeCpp11BracedList", 528 Style.SpaceBeforeCpp11BracedList); 529 IO.mapOptional("SpaceBeforeCtorInitializerColon", 530 Style.SpaceBeforeCtorInitializerColon); 531 IO.mapOptional("SpaceBeforeInheritanceColon", 532 Style.SpaceBeforeInheritanceColon); 533 IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens); 534 IO.mapOptional("SpaceBeforeRangeBasedForLoopColon", 535 Style.SpaceBeforeRangeBasedForLoopColon); 536 IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock); 537 IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses); 538 IO.mapOptional("SpacesBeforeTrailingComments", 539 Style.SpacesBeforeTrailingComments); 540 IO.mapOptional("SpacesInAngles", Style.SpacesInAngles); 541 IO.mapOptional("SpacesInConditionalStatement", 542 Style.SpacesInConditionalStatement); 543 IO.mapOptional("SpacesInContainerLiterals", 544 Style.SpacesInContainerLiterals); 545 IO.mapOptional("SpacesInCStyleCastParentheses", 546 Style.SpacesInCStyleCastParentheses); 547 IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses); 548 IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets); 549 IO.mapOptional("SpaceBeforeSquareBrackets", 550 Style.SpaceBeforeSquareBrackets); 551 IO.mapOptional("Standard", Style.Standard); 552 IO.mapOptional("StatementMacros", Style.StatementMacros); 553 IO.mapOptional("TabWidth", Style.TabWidth); 554 IO.mapOptional("TypenameMacros", Style.TypenameMacros); 555 IO.mapOptional("UseCRLF", Style.UseCRLF); 556 IO.mapOptional("UseTab", Style.UseTab); 557 } 558 }; 559 560 template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> { 561 static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) { 562 IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel); 563 IO.mapOptional("AfterClass", Wrapping.AfterClass); 564 IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement); 565 IO.mapOptional("AfterEnum", Wrapping.AfterEnum); 566 IO.mapOptional("AfterFunction", Wrapping.AfterFunction); 567 IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace); 568 IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration); 569 IO.mapOptional("AfterStruct", Wrapping.AfterStruct); 570 IO.mapOptional("AfterUnion", Wrapping.AfterUnion); 571 IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock); 572 IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch); 573 IO.mapOptional("BeforeElse", Wrapping.BeforeElse); 574 IO.mapOptional("IndentBraces", Wrapping.IndentBraces); 575 IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction); 576 IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord); 577 IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace); 578 } 579 }; 580 581 template <> struct MappingTraits<FormatStyle::RawStringFormat> { 582 static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) { 583 IO.mapOptional("Language", Format.Language); 584 IO.mapOptional("Delimiters", Format.Delimiters); 585 IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions); 586 IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter); 587 IO.mapOptional("BasedOnStyle", Format.BasedOnStyle); 588 } 589 }; 590 591 // Allows to read vector<FormatStyle> while keeping default values. 592 // IO.getContext() should contain a pointer to the FormatStyle structure, that 593 // will be used to get default values for missing keys. 594 // If the first element has no Language specified, it will be treated as the 595 // default one for the following elements. 596 template <> struct DocumentListTraits<std::vector<FormatStyle>> { 597 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) { 598 return Seq.size(); 599 } 600 static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq, 601 size_t Index) { 602 if (Index >= Seq.size()) { 603 assert(Index == Seq.size()); 604 FormatStyle Template; 605 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) { 606 Template = Seq[0]; 607 } else { 608 Template = *((const FormatStyle *)IO.getContext()); 609 Template.Language = FormatStyle::LK_None; 610 } 611 Seq.resize(Index + 1, Template); 612 } 613 return Seq[Index]; 614 } 615 }; 616 } // namespace yaml 617 } // namespace llvm 618 619 namespace clang { 620 namespace format { 621 622 const std::error_category &getParseCategory() { 623 static const ParseErrorCategory C{}; 624 return C; 625 } 626 std::error_code make_error_code(ParseError e) { 627 return std::error_code(static_cast<int>(e), getParseCategory()); 628 } 629 630 inline llvm::Error make_string_error(const llvm::Twine &Message) { 631 return llvm::make_error<llvm::StringError>(Message, 632 llvm::inconvertibleErrorCode()); 633 } 634 635 const char *ParseErrorCategory::name() const noexcept { 636 return "clang-format.parse_error"; 637 } 638 639 std::string ParseErrorCategory::message(int EV) const { 640 switch (static_cast<ParseError>(EV)) { 641 case ParseError::Success: 642 return "Success"; 643 case ParseError::Error: 644 return "Invalid argument"; 645 case ParseError::Unsuitable: 646 return "Unsuitable"; 647 } 648 llvm_unreachable("unexpected parse error"); 649 } 650 651 static FormatStyle expandPresets(const FormatStyle &Style) { 652 if (Style.BreakBeforeBraces == FormatStyle::BS_Custom) 653 return Style; 654 FormatStyle Expanded = Style; 655 Expanded.BraceWrapping = {false, false, FormatStyle::BWACS_Never, 656 false, false, false, 657 false, false, false, 658 false, false, false, 659 false, true, true, 660 true}; 661 switch (Style.BreakBeforeBraces) { 662 case FormatStyle::BS_Linux: 663 Expanded.BraceWrapping.AfterClass = true; 664 Expanded.BraceWrapping.AfterFunction = true; 665 Expanded.BraceWrapping.AfterNamespace = true; 666 break; 667 case FormatStyle::BS_Mozilla: 668 Expanded.BraceWrapping.AfterClass = true; 669 Expanded.BraceWrapping.AfterEnum = true; 670 Expanded.BraceWrapping.AfterFunction = true; 671 Expanded.BraceWrapping.AfterStruct = true; 672 Expanded.BraceWrapping.AfterUnion = true; 673 Expanded.BraceWrapping.AfterExternBlock = true; 674 Expanded.BraceWrapping.SplitEmptyFunction = true; 675 Expanded.BraceWrapping.SplitEmptyRecord = false; 676 break; 677 case FormatStyle::BS_Stroustrup: 678 Expanded.BraceWrapping.AfterFunction = true; 679 Expanded.BraceWrapping.BeforeCatch = true; 680 Expanded.BraceWrapping.BeforeElse = true; 681 break; 682 case FormatStyle::BS_Allman: 683 Expanded.BraceWrapping.AfterCaseLabel = true; 684 Expanded.BraceWrapping.AfterClass = true; 685 Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; 686 Expanded.BraceWrapping.AfterEnum = true; 687 Expanded.BraceWrapping.AfterFunction = true; 688 Expanded.BraceWrapping.AfterNamespace = true; 689 Expanded.BraceWrapping.AfterObjCDeclaration = true; 690 Expanded.BraceWrapping.AfterStruct = true; 691 Expanded.BraceWrapping.AfterUnion = true; 692 Expanded.BraceWrapping.AfterExternBlock = true; 693 Expanded.BraceWrapping.BeforeCatch = true; 694 Expanded.BraceWrapping.BeforeElse = true; 695 break; 696 case FormatStyle::BS_Whitesmiths: 697 Expanded.BraceWrapping.AfterCaseLabel = true; 698 Expanded.BraceWrapping.AfterClass = true; 699 Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; 700 Expanded.BraceWrapping.AfterEnum = true; 701 Expanded.BraceWrapping.AfterFunction = true; 702 Expanded.BraceWrapping.AfterNamespace = true; 703 Expanded.BraceWrapping.AfterObjCDeclaration = true; 704 Expanded.BraceWrapping.AfterStruct = true; 705 Expanded.BraceWrapping.AfterExternBlock = true; 706 Expanded.BraceWrapping.BeforeCatch = true; 707 Expanded.BraceWrapping.BeforeElse = true; 708 break; 709 case FormatStyle::BS_GNU: 710 Expanded.BraceWrapping = {true, true, FormatStyle::BWACS_Always, 711 true, true, true, 712 true, true, true, 713 true, true, true, 714 true, true, true, 715 true}; 716 break; 717 case FormatStyle::BS_WebKit: 718 Expanded.BraceWrapping.AfterFunction = true; 719 break; 720 default: 721 break; 722 } 723 return Expanded; 724 } 725 726 FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { 727 FormatStyle LLVMStyle; 728 LLVMStyle.Language = Language; 729 LLVMStyle.AccessModifierOffset = -2; 730 LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right; 731 LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align; 732 LLVMStyle.AlignOperands = true; 733 LLVMStyle.AlignTrailingComments = true; 734 LLVMStyle.AlignConsecutiveAssignments = false; 735 LLVMStyle.AlignConsecutiveDeclarations = false; 736 LLVMStyle.AlignConsecutiveMacros = false; 737 LLVMStyle.AllowAllArgumentsOnNextLine = true; 738 LLVMStyle.AllowAllConstructorInitializersOnNextLine = true; 739 LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; 740 LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; 741 LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never; 742 LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; 743 LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 744 LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All; 745 LLVMStyle.AllowShortLoopsOnASingleLine = false; 746 LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; 747 LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; 748 LLVMStyle.AlwaysBreakBeforeMultilineStrings = false; 749 LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine; 750 LLVMStyle.BinPackArguments = true; 751 LLVMStyle.BinPackParameters = true; 752 LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None; 753 LLVMStyle.BreakBeforeTernaryOperators = true; 754 LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach; 755 LLVMStyle.BraceWrapping = {false, false, FormatStyle::BWACS_Never, 756 false, false, false, 757 false, false, false, 758 false, false, false, 759 false, true, true, 760 true}; 761 LLVMStyle.BreakAfterJavaFieldAnnotations = false; 762 LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; 763 LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon; 764 LLVMStyle.BreakStringLiterals = true; 765 LLVMStyle.ColumnLimit = 80; 766 LLVMStyle.CommentPragmas = "^ IWYU pragma:"; 767 LLVMStyle.CompactNamespaces = false; 768 LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false; 769 LLVMStyle.ConstructorInitializerIndentWidth = 4; 770 LLVMStyle.ContinuationIndentWidth = 4; 771 LLVMStyle.Cpp11BracedListStyle = true; 772 LLVMStyle.DeriveLineEnding = true; 773 LLVMStyle.DerivePointerAlignment = false; 774 LLVMStyle.ExperimentalAutoDetectBinPacking = false; 775 LLVMStyle.FixNamespaceComments = true; 776 LLVMStyle.ForEachMacros.push_back("foreach"); 777 LLVMStyle.ForEachMacros.push_back("Q_FOREACH"); 778 LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH"); 779 LLVMStyle.IncludeStyle.IncludeCategories = { 780 {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0}, 781 {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0}, 782 {".*", 1, 0}}; 783 LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$"; 784 LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve; 785 LLVMStyle.IndentCaseLabels = false; 786 LLVMStyle.IndentCaseBlocks = false; 787 LLVMStyle.IndentGotoLabels = true; 788 LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None; 789 LLVMStyle.IndentWrappedFunctionNames = false; 790 LLVMStyle.IndentWidth = 2; 791 LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave; 792 LLVMStyle.JavaScriptWrapImports = true; 793 LLVMStyle.TabWidth = 8; 794 LLVMStyle.MaxEmptyLinesToKeep = 1; 795 LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true; 796 LLVMStyle.NamespaceIndentation = FormatStyle::NI_None; 797 LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto; 798 LLVMStyle.ObjCBlockIndentWidth = 2; 799 LLVMStyle.ObjCSpaceAfterProperty = false; 800 LLVMStyle.ObjCSpaceBeforeProtocolList = true; 801 LLVMStyle.PointerAlignment = FormatStyle::PAS_Right; 802 LLVMStyle.SpacesBeforeTrailingComments = 1; 803 LLVMStyle.Standard = FormatStyle::LS_Latest; 804 LLVMStyle.UseCRLF = false; 805 LLVMStyle.UseTab = FormatStyle::UT_Never; 806 LLVMStyle.ReflowComments = true; 807 LLVMStyle.SpacesInParentheses = false; 808 LLVMStyle.SpacesInSquareBrackets = false; 809 LLVMStyle.SpaceInEmptyBlock = false; 810 LLVMStyle.SpaceInEmptyParentheses = false; 811 LLVMStyle.SpacesInContainerLiterals = true; 812 LLVMStyle.SpacesInCStyleCastParentheses = false; 813 LLVMStyle.SpaceAfterCStyleCast = false; 814 LLVMStyle.SpaceAfterLogicalNot = false; 815 LLVMStyle.SpaceAfterTemplateKeyword = true; 816 LLVMStyle.SpaceBeforeCtorInitializerColon = true; 817 LLVMStyle.SpaceBeforeInheritanceColon = true; 818 LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements; 819 LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true; 820 LLVMStyle.SpaceBeforeAssignmentOperators = true; 821 LLVMStyle.SpaceBeforeCpp11BracedList = false; 822 LLVMStyle.SpaceBeforeSquareBrackets = false; 823 LLVMStyle.SpacesInAngles = false; 824 LLVMStyle.SpacesInConditionalStatement = false; 825 826 LLVMStyle.PenaltyBreakAssignment = prec::Assignment; 827 LLVMStyle.PenaltyBreakComment = 300; 828 LLVMStyle.PenaltyBreakFirstLessLess = 120; 829 LLVMStyle.PenaltyBreakString = 1000; 830 LLVMStyle.PenaltyExcessCharacter = 1000000; 831 LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60; 832 LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19; 833 LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational; 834 835 LLVMStyle.DisableFormat = false; 836 LLVMStyle.SortIncludes = true; 837 LLVMStyle.SortUsingDeclarations = true; 838 LLVMStyle.StatementMacros.push_back("Q_UNUSED"); 839 LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION"); 840 841 // Defaults that differ when not C++. 842 if (Language == FormatStyle::LK_TableGen) { 843 LLVMStyle.SpacesInContainerLiterals = false; 844 } 845 846 return LLVMStyle; 847 } 848 849 FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { 850 if (Language == FormatStyle::LK_TextProto) { 851 FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto); 852 GoogleStyle.Language = FormatStyle::LK_TextProto; 853 854 return GoogleStyle; 855 } 856 857 FormatStyle GoogleStyle = getLLVMStyle(Language); 858 859 GoogleStyle.AccessModifierOffset = -1; 860 GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left; 861 GoogleStyle.AllowShortIfStatementsOnASingleLine = 862 FormatStyle::SIS_WithoutElse; 863 GoogleStyle.AllowShortLoopsOnASingleLine = true; 864 GoogleStyle.AlwaysBreakBeforeMultilineStrings = true; 865 GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; 866 GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true; 867 GoogleStyle.DerivePointerAlignment = true; 868 GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0}, 869 {"^<.*\\.h>", 1, 0}, 870 {"^<.*", 2, 0}, 871 {".*", 3, 0}}; 872 GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$"; 873 GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; 874 GoogleStyle.IndentCaseLabels = true; 875 GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false; 876 GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never; 877 GoogleStyle.ObjCSpaceAfterProperty = false; 878 GoogleStyle.ObjCSpaceBeforeProtocolList = true; 879 GoogleStyle.PointerAlignment = FormatStyle::PAS_Left; 880 GoogleStyle.RawStringFormats = { 881 { 882 FormatStyle::LK_Cpp, 883 /*Delimiters=*/ 884 { 885 "cc", 886 "CC", 887 "cpp", 888 "Cpp", 889 "CPP", 890 "c++", 891 "C++", 892 }, 893 /*EnclosingFunctionNames=*/ 894 {}, 895 /*CanonicalDelimiter=*/"", 896 /*BasedOnStyle=*/"google", 897 }, 898 { 899 FormatStyle::LK_TextProto, 900 /*Delimiters=*/ 901 { 902 "pb", 903 "PB", 904 "proto", 905 "PROTO", 906 }, 907 /*EnclosingFunctionNames=*/ 908 { 909 "EqualsProto", 910 "EquivToProto", 911 "PARSE_PARTIAL_TEXT_PROTO", 912 "PARSE_TEST_PROTO", 913 "PARSE_TEXT_PROTO", 914 "ParseTextOrDie", 915 "ParseTextProtoOrDie", 916 }, 917 /*CanonicalDelimiter=*/"", 918 /*BasedOnStyle=*/"google", 919 }, 920 }; 921 GoogleStyle.SpacesBeforeTrailingComments = 2; 922 GoogleStyle.Standard = FormatStyle::LS_Auto; 923 924 GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200; 925 GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1; 926 927 if (Language == FormatStyle::LK_Java) { 928 GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; 929 GoogleStyle.AlignOperands = false; 930 GoogleStyle.AlignTrailingComments = false; 931 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 932 GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 933 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 934 GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; 935 GoogleStyle.ColumnLimit = 100; 936 GoogleStyle.SpaceAfterCStyleCast = true; 937 GoogleStyle.SpacesBeforeTrailingComments = 1; 938 } else if (Language == FormatStyle::LK_JavaScript) { 939 GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; 940 GoogleStyle.AlignOperands = false; 941 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 942 // TODO: still under discussion whether to switch to SLS_All. 943 GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty; 944 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 945 GoogleStyle.BreakBeforeTernaryOperators = false; 946 // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is 947 // commonly followed by overlong URLs. 948 GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)"; 949 GoogleStyle.MaxEmptyLinesToKeep = 3; 950 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All; 951 GoogleStyle.SpacesInContainerLiterals = false; 952 GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single; 953 GoogleStyle.JavaScriptWrapImports = false; 954 } else if (Language == FormatStyle::LK_Proto) { 955 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 956 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 957 GoogleStyle.SpacesInContainerLiterals = false; 958 GoogleStyle.Cpp11BracedListStyle = false; 959 // This affects protocol buffer options specifications and text protos. 960 // Text protos are currently mostly formatted inside C++ raw string literals 961 // and often the current breaking behavior of string literals is not 962 // beneficial there. Investigate turning this on once proper string reflow 963 // has been implemented. 964 GoogleStyle.BreakStringLiterals = false; 965 } else if (Language == FormatStyle::LK_ObjC) { 966 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 967 GoogleStyle.ColumnLimit = 100; 968 // "Regroup" doesn't work well for ObjC yet (main header heuristic, 969 // relationship between ObjC standard library headers and other heades, 970 // #imports, etc.) 971 GoogleStyle.IncludeStyle.IncludeBlocks = 972 tooling::IncludeStyle::IBS_Preserve; 973 } 974 975 return GoogleStyle; 976 } 977 978 FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) { 979 FormatStyle ChromiumStyle = getGoogleStyle(Language); 980 981 // Disable include reordering across blocks in Chromium code. 982 // - clang-format tries to detect that foo.h is the "main" header for 983 // foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium 984 // uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc, 985 // _private.cc, _impl.cc etc) in different permutations 986 // (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a 987 // better default for Chromium code. 988 // - The default for .cc and .mm files is different (r357695) for Google style 989 // for the same reason. The plan is to unify this again once the main 990 // header detection works for Google's ObjC code, but this hasn't happened 991 // yet. Since Chromium has some ObjC code, switching Chromium is blocked 992 // on that. 993 // - Finally, "If include reordering is harmful, put things in different 994 // blocks to prevent it" has been a recommendation for a long time that 995 // people are used to. We'll need a dev education push to change this to 996 // "If include reordering is harmful, put things in a different block and 997 // _prepend that with a comment_ to prevent it" before changing behavior. 998 ChromiumStyle.IncludeStyle.IncludeBlocks = 999 tooling::IncludeStyle::IBS_Preserve; 1000 1001 if (Language == FormatStyle::LK_Java) { 1002 ChromiumStyle.AllowShortIfStatementsOnASingleLine = 1003 FormatStyle::SIS_WithoutElse; 1004 ChromiumStyle.BreakAfterJavaFieldAnnotations = true; 1005 ChromiumStyle.ContinuationIndentWidth = 8; 1006 ChromiumStyle.IndentWidth = 4; 1007 // See styleguide for import groups: 1008 // https://chromium.googlesource.com/chromium/src/+/master/styleguide/java/java.md#Import-Order 1009 ChromiumStyle.JavaImportGroups = { 1010 "android", 1011 "androidx", 1012 "com", 1013 "dalvik", 1014 "junit", 1015 "org", 1016 "com.google.android.apps.chrome", 1017 "org.chromium", 1018 "java", 1019 "javax", 1020 }; 1021 ChromiumStyle.SortIncludes = true; 1022 } else if (Language == FormatStyle::LK_JavaScript) { 1023 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1024 ChromiumStyle.AllowShortLoopsOnASingleLine = false; 1025 } else { 1026 ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false; 1027 ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 1028 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1029 ChromiumStyle.AllowShortLoopsOnASingleLine = false; 1030 ChromiumStyle.BinPackParameters = false; 1031 ChromiumStyle.DerivePointerAlignment = false; 1032 if (Language == FormatStyle::LK_ObjC) 1033 ChromiumStyle.ColumnLimit = 80; 1034 } 1035 return ChromiumStyle; 1036 } 1037 1038 FormatStyle getMozillaStyle() { 1039 FormatStyle MozillaStyle = getLLVMStyle(); 1040 MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false; 1041 MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 1042 MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel; 1043 MozillaStyle.AlwaysBreakAfterDefinitionReturnType = 1044 FormatStyle::DRTBS_TopLevel; 1045 MozillaStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; 1046 MozillaStyle.BinPackParameters = false; 1047 MozillaStyle.BinPackArguments = false; 1048 MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla; 1049 MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 1050 MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma; 1051 MozillaStyle.ConstructorInitializerIndentWidth = 2; 1052 MozillaStyle.ContinuationIndentWidth = 2; 1053 MozillaStyle.Cpp11BracedListStyle = false; 1054 MozillaStyle.FixNamespaceComments = false; 1055 MozillaStyle.IndentCaseLabels = true; 1056 MozillaStyle.ObjCSpaceAfterProperty = true; 1057 MozillaStyle.ObjCSpaceBeforeProtocolList = false; 1058 MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200; 1059 MozillaStyle.PointerAlignment = FormatStyle::PAS_Left; 1060 MozillaStyle.SpaceAfterTemplateKeyword = false; 1061 return MozillaStyle; 1062 } 1063 1064 FormatStyle getWebKitStyle() { 1065 FormatStyle Style = getLLVMStyle(); 1066 Style.AccessModifierOffset = -4; 1067 Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; 1068 Style.AlignOperands = false; 1069 Style.AlignTrailingComments = false; 1070 Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty; 1071 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 1072 Style.BreakBeforeBraces = FormatStyle::BS_WebKit; 1073 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 1074 Style.Cpp11BracedListStyle = false; 1075 Style.ColumnLimit = 0; 1076 Style.FixNamespaceComments = false; 1077 Style.IndentWidth = 4; 1078 Style.NamespaceIndentation = FormatStyle::NI_Inner; 1079 Style.ObjCBlockIndentWidth = 4; 1080 Style.ObjCSpaceAfterProperty = true; 1081 Style.PointerAlignment = FormatStyle::PAS_Left; 1082 Style.SpaceBeforeCpp11BracedList = true; 1083 Style.SpaceInEmptyBlock = true; 1084 return Style; 1085 } 1086 1087 FormatStyle getGNUStyle() { 1088 FormatStyle Style = getLLVMStyle(); 1089 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; 1090 Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; 1091 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 1092 Style.BreakBeforeBraces = FormatStyle::BS_GNU; 1093 Style.BreakBeforeTernaryOperators = true; 1094 Style.Cpp11BracedListStyle = false; 1095 Style.ColumnLimit = 79; 1096 Style.FixNamespaceComments = false; 1097 Style.SpaceBeforeParens = FormatStyle::SBPO_Always; 1098 Style.Standard = FormatStyle::LS_Cpp03; 1099 return Style; 1100 } 1101 1102 FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) { 1103 FormatStyle Style = getLLVMStyle(Language); 1104 Style.ColumnLimit = 120; 1105 Style.TabWidth = 4; 1106 Style.IndentWidth = 4; 1107 Style.UseTab = FormatStyle::UT_Never; 1108 Style.BreakBeforeBraces = FormatStyle::BS_Custom; 1109 Style.BraceWrapping.AfterClass = true; 1110 Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; 1111 Style.BraceWrapping.AfterEnum = true; 1112 Style.BraceWrapping.AfterFunction = true; 1113 Style.BraceWrapping.AfterNamespace = true; 1114 Style.BraceWrapping.AfterObjCDeclaration = true; 1115 Style.BraceWrapping.AfterStruct = true; 1116 Style.BraceWrapping.AfterExternBlock = true; 1117 Style.BraceWrapping.BeforeCatch = true; 1118 Style.BraceWrapping.BeforeElse = true; 1119 Style.PenaltyReturnTypeOnItsOwnLine = 1000; 1120 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; 1121 Style.AllowShortCaseLabelsOnASingleLine = false; 1122 Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1123 Style.AllowShortLoopsOnASingleLine = false; 1124 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; 1125 Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; 1126 return Style; 1127 } 1128 1129 FormatStyle getNoStyle() { 1130 FormatStyle NoStyle = getLLVMStyle(); 1131 NoStyle.DisableFormat = true; 1132 NoStyle.SortIncludes = false; 1133 NoStyle.SortUsingDeclarations = false; 1134 return NoStyle; 1135 } 1136 1137 bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language, 1138 FormatStyle *Style) { 1139 if (Name.equals_lower("llvm")) { 1140 *Style = getLLVMStyle(Language); 1141 } else if (Name.equals_lower("chromium")) { 1142 *Style = getChromiumStyle(Language); 1143 } else if (Name.equals_lower("mozilla")) { 1144 *Style = getMozillaStyle(); 1145 } else if (Name.equals_lower("google")) { 1146 *Style = getGoogleStyle(Language); 1147 } else if (Name.equals_lower("webkit")) { 1148 *Style = getWebKitStyle(); 1149 } else if (Name.equals_lower("gnu")) { 1150 *Style = getGNUStyle(); 1151 } else if (Name.equals_lower("microsoft")) { 1152 *Style = getMicrosoftStyle(Language); 1153 } else if (Name.equals_lower("none")) { 1154 *Style = getNoStyle(); 1155 } else { 1156 return false; 1157 } 1158 1159 Style->Language = Language; 1160 return true; 1161 } 1162 1163 std::error_code parseConfiguration(StringRef Text, FormatStyle *Style) { 1164 assert(Style); 1165 FormatStyle::LanguageKind Language = Style->Language; 1166 assert(Language != FormatStyle::LK_None); 1167 if (Text.trim().empty()) 1168 return make_error_code(ParseError::Error); 1169 Style->StyleSet.Clear(); 1170 std::vector<FormatStyle> Styles; 1171 llvm::yaml::Input Input(Text); 1172 // DocumentListTraits<vector<FormatStyle>> uses the context to get default 1173 // values for the fields, keys for which are missing from the configuration. 1174 // Mapping also uses the context to get the language to find the correct 1175 // base style. 1176 Input.setContext(Style); 1177 Input >> Styles; 1178 if (Input.error()) 1179 return Input.error(); 1180 1181 for (unsigned i = 0; i < Styles.size(); ++i) { 1182 // Ensures that only the first configuration can skip the Language option. 1183 if (Styles[i].Language == FormatStyle::LK_None && i != 0) 1184 return make_error_code(ParseError::Error); 1185 // Ensure that each language is configured at most once. 1186 for (unsigned j = 0; j < i; ++j) { 1187 if (Styles[i].Language == Styles[j].Language) { 1188 LLVM_DEBUG(llvm::dbgs() 1189 << "Duplicate languages in the config file on positions " 1190 << j << " and " << i << "\n"); 1191 return make_error_code(ParseError::Error); 1192 } 1193 } 1194 } 1195 // Look for a suitable configuration starting from the end, so we can 1196 // find the configuration for the specific language first, and the default 1197 // configuration (which can only be at slot 0) after it. 1198 FormatStyle::FormatStyleSet StyleSet; 1199 bool LanguageFound = false; 1200 for (int i = Styles.size() - 1; i >= 0; --i) { 1201 if (Styles[i].Language != FormatStyle::LK_None) 1202 StyleSet.Add(Styles[i]); 1203 if (Styles[i].Language == Language) 1204 LanguageFound = true; 1205 } 1206 if (!LanguageFound) { 1207 if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None) 1208 return make_error_code(ParseError::Unsuitable); 1209 FormatStyle DefaultStyle = Styles[0]; 1210 DefaultStyle.Language = Language; 1211 StyleSet.Add(std::move(DefaultStyle)); 1212 } 1213 *Style = *StyleSet.Get(Language); 1214 return make_error_code(ParseError::Success); 1215 } 1216 1217 std::string configurationAsText(const FormatStyle &Style) { 1218 std::string Text; 1219 llvm::raw_string_ostream Stream(Text); 1220 llvm::yaml::Output Output(Stream); 1221 // We use the same mapping method for input and output, so we need a non-const 1222 // reference here. 1223 FormatStyle NonConstStyle = expandPresets(Style); 1224 Output << NonConstStyle; 1225 return Stream.str(); 1226 } 1227 1228 llvm::Optional<FormatStyle> 1229 FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const { 1230 if (!Styles) 1231 return None; 1232 auto It = Styles->find(Language); 1233 if (It == Styles->end()) 1234 return None; 1235 FormatStyle Style = It->second; 1236 Style.StyleSet = *this; 1237 return Style; 1238 } 1239 1240 void FormatStyle::FormatStyleSet::Add(FormatStyle Style) { 1241 assert(Style.Language != LK_None && 1242 "Cannot add a style for LK_None to a StyleSet"); 1243 assert( 1244 !Style.StyleSet.Styles && 1245 "Cannot add a style associated with an existing StyleSet to a StyleSet"); 1246 if (!Styles) 1247 Styles = std::make_shared<MapType>(); 1248 (*Styles)[Style.Language] = std::move(Style); 1249 } 1250 1251 void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); } 1252 1253 llvm::Optional<FormatStyle> 1254 FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const { 1255 return StyleSet.Get(Language); 1256 } 1257 1258 namespace { 1259 1260 class JavaScriptRequoter : public TokenAnalyzer { 1261 public: 1262 JavaScriptRequoter(const Environment &Env, const FormatStyle &Style) 1263 : TokenAnalyzer(Env, Style) {} 1264 1265 std::pair<tooling::Replacements, unsigned> 1266 analyze(TokenAnnotator &Annotator, 1267 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1268 FormatTokenLexer &Tokens) override { 1269 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 1270 tooling::Replacements Result; 1271 requoteJSStringLiteral(AnnotatedLines, Result); 1272 return {Result, 0}; 1273 } 1274 1275 private: 1276 // Replaces double/single-quoted string literal as appropriate, re-escaping 1277 // the contents in the process. 1278 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines, 1279 tooling::Replacements &Result) { 1280 for (AnnotatedLine *Line : Lines) { 1281 requoteJSStringLiteral(Line->Children, Result); 1282 if (!Line->Affected) 1283 continue; 1284 for (FormatToken *FormatTok = Line->First; FormatTok; 1285 FormatTok = FormatTok->Next) { 1286 StringRef Input = FormatTok->TokenText; 1287 if (FormatTok->Finalized || !FormatTok->isStringLiteral() || 1288 // NB: testing for not starting with a double quote to avoid 1289 // breaking `template strings`. 1290 (Style.JavaScriptQuotes == FormatStyle::JSQS_Single && 1291 !Input.startswith("\"")) || 1292 (Style.JavaScriptQuotes == FormatStyle::JSQS_Double && 1293 !Input.startswith("\'"))) 1294 continue; 1295 1296 // Change start and end quote. 1297 bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single; 1298 SourceLocation Start = FormatTok->Tok.getLocation(); 1299 auto Replace = [&](SourceLocation Start, unsigned Length, 1300 StringRef ReplacementText) { 1301 auto Err = Result.add(tooling::Replacement( 1302 Env.getSourceManager(), Start, Length, ReplacementText)); 1303 // FIXME: handle error. For now, print error message and skip the 1304 // replacement for release version. 1305 if (Err) { 1306 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 1307 assert(false); 1308 } 1309 }; 1310 Replace(Start, 1, IsSingle ? "'" : "\""); 1311 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1, 1312 IsSingle ? "'" : "\""); 1313 1314 // Escape internal quotes. 1315 bool Escaped = false; 1316 for (size_t i = 1; i < Input.size() - 1; i++) { 1317 switch (Input[i]) { 1318 case '\\': 1319 if (!Escaped && i + 1 < Input.size() && 1320 ((IsSingle && Input[i + 1] == '"') || 1321 (!IsSingle && Input[i + 1] == '\''))) { 1322 // Remove this \, it's escaping a " or ' that no longer needs 1323 // escaping 1324 Replace(Start.getLocWithOffset(i), 1, ""); 1325 continue; 1326 } 1327 Escaped = !Escaped; 1328 break; 1329 case '\"': 1330 case '\'': 1331 if (!Escaped && IsSingle == (Input[i] == '\'')) { 1332 // Escape the quote. 1333 Replace(Start.getLocWithOffset(i), 0, "\\"); 1334 } 1335 Escaped = false; 1336 break; 1337 default: 1338 Escaped = false; 1339 break; 1340 } 1341 } 1342 } 1343 } 1344 } 1345 }; 1346 1347 class Formatter : public TokenAnalyzer { 1348 public: 1349 Formatter(const Environment &Env, const FormatStyle &Style, 1350 FormattingAttemptStatus *Status) 1351 : TokenAnalyzer(Env, Style), Status(Status) {} 1352 1353 std::pair<tooling::Replacements, unsigned> 1354 analyze(TokenAnnotator &Annotator, 1355 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1356 FormatTokenLexer &Tokens) override { 1357 tooling::Replacements Result; 1358 deriveLocalStyle(AnnotatedLines); 1359 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 1360 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1361 Annotator.calculateFormattingInformation(*AnnotatedLines[i]); 1362 } 1363 Annotator.setCommentLineLevels(AnnotatedLines); 1364 1365 WhitespaceManager Whitespaces( 1366 Env.getSourceManager(), Style, 1367 Style.DeriveLineEnding 1368 ? inputUsesCRLF( 1369 Env.getSourceManager().getBufferData(Env.getFileID()), 1370 Style.UseCRLF) 1371 : Style.UseCRLF); 1372 ContinuationIndenter Indenter(Style, Tokens.getKeywords(), 1373 Env.getSourceManager(), Whitespaces, Encoding, 1374 BinPackInconclusiveFunctions); 1375 unsigned Penalty = 1376 UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, 1377 Tokens.getKeywords(), Env.getSourceManager(), 1378 Status) 1379 .format(AnnotatedLines, /*DryRun=*/false, 1380 /*AdditionalIndent=*/0, 1381 /*FixBadIndentation=*/false, 1382 /*FirstStartColumn=*/Env.getFirstStartColumn(), 1383 /*NextStartColumn=*/Env.getNextStartColumn(), 1384 /*LastStartColumn=*/Env.getLastStartColumn()); 1385 for (const auto &R : Whitespaces.generateReplacements()) 1386 if (Result.add(R)) 1387 return std::make_pair(Result, 0); 1388 return std::make_pair(Result, Penalty); 1389 } 1390 1391 private: 1392 static bool inputUsesCRLF(StringRef Text, bool DefaultToCRLF) { 1393 size_t LF = Text.count('\n'); 1394 size_t CR = Text.count('\r') * 2; 1395 return LF == CR ? DefaultToCRLF : CR > LF; 1396 } 1397 1398 bool 1399 hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) { 1400 for (const AnnotatedLine *Line : Lines) { 1401 if (hasCpp03IncompatibleFormat(Line->Children)) 1402 return true; 1403 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) { 1404 if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) { 1405 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener)) 1406 return true; 1407 if (Tok->is(TT_TemplateCloser) && 1408 Tok->Previous->is(TT_TemplateCloser)) 1409 return true; 1410 } 1411 } 1412 } 1413 return false; 1414 } 1415 1416 int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) { 1417 int AlignmentDiff = 0; 1418 for (const AnnotatedLine *Line : Lines) { 1419 AlignmentDiff += countVariableAlignments(Line->Children); 1420 for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) { 1421 if (!Tok->is(TT_PointerOrReference)) 1422 continue; 1423 bool SpaceBefore = 1424 Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd(); 1425 bool SpaceAfter = Tok->Next->WhitespaceRange.getBegin() != 1426 Tok->Next->WhitespaceRange.getEnd(); 1427 if (SpaceBefore && !SpaceAfter) 1428 ++AlignmentDiff; 1429 if (!SpaceBefore && SpaceAfter) 1430 --AlignmentDiff; 1431 } 1432 } 1433 return AlignmentDiff; 1434 } 1435 1436 void 1437 deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 1438 bool HasBinPackedFunction = false; 1439 bool HasOnePerLineFunction = false; 1440 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1441 if (!AnnotatedLines[i]->First->Next) 1442 continue; 1443 FormatToken *Tok = AnnotatedLines[i]->First->Next; 1444 while (Tok->Next) { 1445 if (Tok->PackingKind == PPK_BinPacked) 1446 HasBinPackedFunction = true; 1447 if (Tok->PackingKind == PPK_OnePerLine) 1448 HasOnePerLineFunction = true; 1449 1450 Tok = Tok->Next; 1451 } 1452 } 1453 if (Style.DerivePointerAlignment) 1454 Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0 1455 ? FormatStyle::PAS_Left 1456 : FormatStyle::PAS_Right; 1457 if (Style.Standard == FormatStyle::LS_Auto) 1458 Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines) 1459 ? FormatStyle::LS_Latest 1460 : FormatStyle::LS_Cpp03; 1461 BinPackInconclusiveFunctions = 1462 HasBinPackedFunction || !HasOnePerLineFunction; 1463 } 1464 1465 bool BinPackInconclusiveFunctions; 1466 FormattingAttemptStatus *Status; 1467 }; 1468 1469 // This class clean up the erroneous/redundant code around the given ranges in 1470 // file. 1471 class Cleaner : public TokenAnalyzer { 1472 public: 1473 Cleaner(const Environment &Env, const FormatStyle &Style) 1474 : TokenAnalyzer(Env, Style), 1475 DeletedTokens(FormatTokenLess(Env.getSourceManager())) {} 1476 1477 // FIXME: eliminate unused parameters. 1478 std::pair<tooling::Replacements, unsigned> 1479 analyze(TokenAnnotator &Annotator, 1480 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1481 FormatTokenLexer &Tokens) override { 1482 // FIXME: in the current implementation the granularity of affected range 1483 // is an annotated line. However, this is not sufficient. Furthermore, 1484 // redundant code introduced by replacements does not necessarily 1485 // intercept with ranges of replacements that result in the redundancy. 1486 // To determine if some redundant code is actually introduced by 1487 // replacements(e.g. deletions), we need to come up with a more 1488 // sophisticated way of computing affected ranges. 1489 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 1490 1491 checkEmptyNamespace(AnnotatedLines); 1492 1493 for (auto *Line : AnnotatedLines) 1494 cleanupLine(Line); 1495 1496 return {generateFixes(), 0}; 1497 } 1498 1499 private: 1500 void cleanupLine(AnnotatedLine *Line) { 1501 for (auto *Child : Line->Children) { 1502 cleanupLine(Child); 1503 } 1504 1505 if (Line->Affected) { 1506 cleanupRight(Line->First, tok::comma, tok::comma); 1507 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma); 1508 cleanupRight(Line->First, tok::l_paren, tok::comma); 1509 cleanupLeft(Line->First, tok::comma, tok::r_paren); 1510 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace); 1511 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace); 1512 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal); 1513 } 1514 } 1515 1516 bool containsOnlyComments(const AnnotatedLine &Line) { 1517 for (FormatToken *Tok = Line.First; Tok != nullptr; Tok = Tok->Next) { 1518 if (Tok->isNot(tok::comment)) 1519 return false; 1520 } 1521 return true; 1522 } 1523 1524 // Iterate through all lines and remove any empty (nested) namespaces. 1525 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 1526 std::set<unsigned> DeletedLines; 1527 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1528 auto &Line = *AnnotatedLines[i]; 1529 if (Line.startsWithNamespace()) { 1530 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines); 1531 } 1532 } 1533 1534 for (auto Line : DeletedLines) { 1535 FormatToken *Tok = AnnotatedLines[Line]->First; 1536 while (Tok) { 1537 deleteToken(Tok); 1538 Tok = Tok->Next; 1539 } 1540 } 1541 } 1542 1543 // The function checks if the namespace, which starts from \p CurrentLine, and 1544 // its nested namespaces are empty and delete them if they are empty. It also 1545 // sets \p NewLine to the last line checked. 1546 // Returns true if the current namespace is empty. 1547 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1548 unsigned CurrentLine, unsigned &NewLine, 1549 std::set<unsigned> &DeletedLines) { 1550 unsigned InitLine = CurrentLine, End = AnnotatedLines.size(); 1551 if (Style.BraceWrapping.AfterNamespace) { 1552 // If the left brace is in a new line, we should consume it first so that 1553 // it does not make the namespace non-empty. 1554 // FIXME: error handling if there is no left brace. 1555 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) { 1556 NewLine = CurrentLine; 1557 return false; 1558 } 1559 } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) { 1560 return false; 1561 } 1562 while (++CurrentLine < End) { 1563 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace)) 1564 break; 1565 1566 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) { 1567 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine, 1568 DeletedLines)) 1569 return false; 1570 CurrentLine = NewLine; 1571 continue; 1572 } 1573 1574 if (containsOnlyComments(*AnnotatedLines[CurrentLine])) 1575 continue; 1576 1577 // If there is anything other than comments or nested namespaces in the 1578 // current namespace, the namespace cannot be empty. 1579 NewLine = CurrentLine; 1580 return false; 1581 } 1582 1583 NewLine = CurrentLine; 1584 if (CurrentLine >= End) 1585 return false; 1586 1587 // Check if the empty namespace is actually affected by changed ranges. 1588 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange( 1589 AnnotatedLines[InitLine]->First->Tok.getLocation(), 1590 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) 1591 return false; 1592 1593 for (unsigned i = InitLine; i <= CurrentLine; ++i) { 1594 DeletedLines.insert(i); 1595 } 1596 1597 return true; 1598 } 1599 1600 // Checks pairs {start, start->next},..., {end->previous, end} and deletes one 1601 // of the token in the pair if the left token has \p LK token kind and the 1602 // right token has \p RK token kind. If \p DeleteLeft is true, the left token 1603 // is deleted on match; otherwise, the right token is deleted. 1604 template <typename LeftKind, typename RightKind> 1605 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK, 1606 bool DeleteLeft) { 1607 auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * { 1608 for (auto *Res = Tok.Next; Res; Res = Res->Next) 1609 if (!Res->is(tok::comment) && 1610 DeletedTokens.find(Res) == DeletedTokens.end()) 1611 return Res; 1612 return nullptr; 1613 }; 1614 for (auto *Left = Start; Left;) { 1615 auto *Right = NextNotDeleted(*Left); 1616 if (!Right) 1617 break; 1618 if (Left->is(LK) && Right->is(RK)) { 1619 deleteToken(DeleteLeft ? Left : Right); 1620 for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next) 1621 deleteToken(Tok); 1622 // If the right token is deleted, we should keep the left token 1623 // unchanged and pair it with the new right token. 1624 if (!DeleteLeft) 1625 continue; 1626 } 1627 Left = Right; 1628 } 1629 } 1630 1631 template <typename LeftKind, typename RightKind> 1632 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) { 1633 cleanupPair(Start, LK, RK, /*DeleteLeft=*/true); 1634 } 1635 1636 template <typename LeftKind, typename RightKind> 1637 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) { 1638 cleanupPair(Start, LK, RK, /*DeleteLeft=*/false); 1639 } 1640 1641 // Delete the given token. 1642 inline void deleteToken(FormatToken *Tok) { 1643 if (Tok) 1644 DeletedTokens.insert(Tok); 1645 } 1646 1647 tooling::Replacements generateFixes() { 1648 tooling::Replacements Fixes; 1649 std::vector<FormatToken *> Tokens; 1650 std::copy(DeletedTokens.begin(), DeletedTokens.end(), 1651 std::back_inserter(Tokens)); 1652 1653 // Merge multiple continuous token deletions into one big deletion so that 1654 // the number of replacements can be reduced. This makes computing affected 1655 // ranges more efficient when we run reformat on the changed code. 1656 unsigned Idx = 0; 1657 while (Idx < Tokens.size()) { 1658 unsigned St = Idx, End = Idx; 1659 while ((End + 1) < Tokens.size() && 1660 Tokens[End]->Next == Tokens[End + 1]) { 1661 End++; 1662 } 1663 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(), 1664 Tokens[End]->Tok.getEndLoc()); 1665 auto Err = 1666 Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, "")); 1667 // FIXME: better error handling. for now just print error message and skip 1668 // for the release version. 1669 if (Err) { 1670 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 1671 assert(false && "Fixes must not conflict!"); 1672 } 1673 Idx = End + 1; 1674 } 1675 1676 return Fixes; 1677 } 1678 1679 // Class for less-than inequality comparason for the set `RedundantTokens`. 1680 // We store tokens in the order they appear in the translation unit so that 1681 // we do not need to sort them in `generateFixes()`. 1682 struct FormatTokenLess { 1683 FormatTokenLess(const SourceManager &SM) : SM(SM) {} 1684 1685 bool operator()(const FormatToken *LHS, const FormatToken *RHS) const { 1686 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(), 1687 RHS->Tok.getLocation()); 1688 } 1689 const SourceManager &SM; 1690 }; 1691 1692 // Tokens to be deleted. 1693 std::set<FormatToken *, FormatTokenLess> DeletedTokens; 1694 }; 1695 1696 class ObjCHeaderStyleGuesser : public TokenAnalyzer { 1697 public: 1698 ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style) 1699 : TokenAnalyzer(Env, Style), IsObjC(false) {} 1700 1701 std::pair<tooling::Replacements, unsigned> 1702 analyze(TokenAnnotator &Annotator, 1703 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1704 FormatTokenLexer &Tokens) override { 1705 assert(Style.Language == FormatStyle::LK_Cpp); 1706 IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines, 1707 Tokens.getKeywords()); 1708 tooling::Replacements Result; 1709 return {Result, 0}; 1710 } 1711 1712 bool isObjC() { return IsObjC; } 1713 1714 private: 1715 static bool 1716 guessIsObjC(const SourceManager &SourceManager, 1717 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1718 const AdditionalKeywords &Keywords) { 1719 // Keep this array sorted, since we are binary searching over it. 1720 static constexpr llvm::StringLiteral FoundationIdentifiers[] = { 1721 "CGFloat", 1722 "CGPoint", 1723 "CGPointMake", 1724 "CGPointZero", 1725 "CGRect", 1726 "CGRectEdge", 1727 "CGRectInfinite", 1728 "CGRectMake", 1729 "CGRectNull", 1730 "CGRectZero", 1731 "CGSize", 1732 "CGSizeMake", 1733 "CGVector", 1734 "CGVectorMake", 1735 "NSAffineTransform", 1736 "NSArray", 1737 "NSAttributedString", 1738 "NSBlockOperation", 1739 "NSBundle", 1740 "NSCache", 1741 "NSCalendar", 1742 "NSCharacterSet", 1743 "NSCountedSet", 1744 "NSData", 1745 "NSDataDetector", 1746 "NSDecimal", 1747 "NSDecimalNumber", 1748 "NSDictionary", 1749 "NSEdgeInsets", 1750 "NSHashTable", 1751 "NSIndexPath", 1752 "NSIndexSet", 1753 "NSInteger", 1754 "NSInvocationOperation", 1755 "NSLocale", 1756 "NSMapTable", 1757 "NSMutableArray", 1758 "NSMutableAttributedString", 1759 "NSMutableCharacterSet", 1760 "NSMutableData", 1761 "NSMutableDictionary", 1762 "NSMutableIndexSet", 1763 "NSMutableOrderedSet", 1764 "NSMutableSet", 1765 "NSMutableString", 1766 "NSNumber", 1767 "NSNumberFormatter", 1768 "NSObject", 1769 "NSOperation", 1770 "NSOperationQueue", 1771 "NSOperationQueuePriority", 1772 "NSOrderedSet", 1773 "NSPoint", 1774 "NSPointerArray", 1775 "NSQualityOfService", 1776 "NSRange", 1777 "NSRect", 1778 "NSRegularExpression", 1779 "NSSet", 1780 "NSSize", 1781 "NSString", 1782 "NSTimeZone", 1783 "NSUInteger", 1784 "NSURL", 1785 "NSURLComponents", 1786 "NSURLQueryItem", 1787 "NSUUID", 1788 "NSValue", 1789 "UIImage", 1790 "UIView", 1791 }; 1792 1793 for (auto Line : AnnotatedLines) { 1794 for (const FormatToken *FormatTok = Line->First; FormatTok; 1795 FormatTok = FormatTok->Next) { 1796 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) && 1797 (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword || 1798 FormatTok->isOneOf(tok::numeric_constant, tok::l_square, 1799 tok::l_brace))) || 1800 (FormatTok->Tok.isAnyIdentifier() && 1801 std::binary_search(std::begin(FoundationIdentifiers), 1802 std::end(FoundationIdentifiers), 1803 FormatTok->TokenText)) || 1804 FormatTok->is(TT_ObjCStringLiteral) || 1805 FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM, 1806 Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace, 1807 TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn, 1808 TT_ObjCMethodExpr, TT_ObjCMethodSpecifier, 1809 TT_ObjCProperty)) { 1810 LLVM_DEBUG(llvm::dbgs() 1811 << "Detected ObjC at location " 1812 << FormatTok->Tok.getLocation().printToString( 1813 SourceManager) 1814 << " token: " << FormatTok->TokenText << " token type: " 1815 << getTokenTypeName(FormatTok->Type) << "\n"); 1816 return true; 1817 } 1818 if (guessIsObjC(SourceManager, Line->Children, Keywords)) 1819 return true; 1820 } 1821 } 1822 return false; 1823 } 1824 1825 bool IsObjC; 1826 }; 1827 1828 struct IncludeDirective { 1829 StringRef Filename; 1830 StringRef Text; 1831 unsigned Offset; 1832 int Category; 1833 int Priority; 1834 }; 1835 1836 struct JavaImportDirective { 1837 StringRef Identifier; 1838 StringRef Text; 1839 unsigned Offset; 1840 std::vector<StringRef> AssociatedCommentLines; 1841 bool IsStatic; 1842 }; 1843 1844 } // end anonymous namespace 1845 1846 // Determines whether 'Ranges' intersects with ('Start', 'End'). 1847 static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start, 1848 unsigned End) { 1849 for (auto Range : Ranges) { 1850 if (Range.getOffset() < End && 1851 Range.getOffset() + Range.getLength() > Start) 1852 return true; 1853 } 1854 return false; 1855 } 1856 1857 // Returns a pair (Index, OffsetToEOL) describing the position of the cursor 1858 // before sorting/deduplicating. Index is the index of the include under the 1859 // cursor in the original set of includes. If this include has duplicates, it is 1860 // the index of the first of the duplicates as the others are going to be 1861 // removed. OffsetToEOL describes the cursor's position relative to the end of 1862 // its current line. 1863 // If `Cursor` is not on any #include, `Index` will be UINT_MAX. 1864 static std::pair<unsigned, unsigned> 1865 FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes, 1866 const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) { 1867 unsigned CursorIndex = UINT_MAX; 1868 unsigned OffsetToEOL = 0; 1869 for (int i = 0, e = Includes.size(); i != e; ++i) { 1870 unsigned Start = Includes[Indices[i]].Offset; 1871 unsigned End = Start + Includes[Indices[i]].Text.size(); 1872 if (!(Cursor >= Start && Cursor < End)) 1873 continue; 1874 CursorIndex = Indices[i]; 1875 OffsetToEOL = End - Cursor; 1876 // Put the cursor on the only remaining #include among the duplicate 1877 // #includes. 1878 while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text) 1879 CursorIndex = i; 1880 break; 1881 } 1882 return std::make_pair(CursorIndex, OffsetToEOL); 1883 } 1884 1885 // Replace all "\r\n" with "\n". 1886 std::string replaceCRLF(const std::string &Code) { 1887 std::string NewCode; 1888 size_t Pos = 0, LastPos = 0; 1889 1890 do { 1891 Pos = Code.find("\r\n", LastPos); 1892 if (Pos == LastPos) { 1893 LastPos++; 1894 continue; 1895 } 1896 if (Pos == std::string::npos) { 1897 NewCode += Code.substr(LastPos); 1898 break; 1899 } 1900 NewCode += Code.substr(LastPos, Pos - LastPos) + "\n"; 1901 LastPos = Pos + 2; 1902 } while (Pos != std::string::npos); 1903 1904 return NewCode; 1905 } 1906 1907 // Sorts and deduplicate a block of includes given by 'Includes' alphabetically 1908 // adding the necessary replacement to 'Replaces'. 'Includes' must be in strict 1909 // source order. 1910 // #include directives with the same text will be deduplicated, and only the 1911 // first #include in the duplicate #includes remains. If the `Cursor` is 1912 // provided and put on a deleted #include, it will be moved to the remaining 1913 // #include in the duplicate #includes. 1914 static void sortCppIncludes(const FormatStyle &Style, 1915 const SmallVectorImpl<IncludeDirective> &Includes, 1916 ArrayRef<tooling::Range> Ranges, StringRef FileName, 1917 StringRef Code, tooling::Replacements &Replaces, 1918 unsigned *Cursor) { 1919 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 1920 unsigned IncludesBeginOffset = Includes.front().Offset; 1921 unsigned IncludesEndOffset = 1922 Includes.back().Offset + Includes.back().Text.size(); 1923 unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset; 1924 if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset)) 1925 return; 1926 SmallVector<unsigned, 16> Indices; 1927 for (unsigned i = 0, e = Includes.size(); i != e; ++i) { 1928 Indices.push_back(i); 1929 } 1930 llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 1931 return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) < 1932 std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename); 1933 }); 1934 // The index of the include on which the cursor will be put after 1935 // sorting/deduplicating. 1936 unsigned CursorIndex; 1937 // The offset from cursor to the end of line. 1938 unsigned CursorToEOLOffset; 1939 if (Cursor) 1940 std::tie(CursorIndex, CursorToEOLOffset) = 1941 FindCursorIndex(Includes, Indices, *Cursor); 1942 1943 // Deduplicate #includes. 1944 Indices.erase(std::unique(Indices.begin(), Indices.end(), 1945 [&](unsigned LHSI, unsigned RHSI) { 1946 return Includes[LHSI].Text == Includes[RHSI].Text; 1947 }), 1948 Indices.end()); 1949 1950 int CurrentCategory = Includes.front().Category; 1951 1952 // If the #includes are out of order, we generate a single replacement fixing 1953 // the entire block. Otherwise, no replacement is generated. 1954 // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not 1955 // enough as additional newlines might be added or removed across #include 1956 // blocks. This we handle below by generating the updated #imclude blocks and 1957 // comparing it to the original. 1958 if (Indices.size() == Includes.size() && 1959 std::is_sorted(Indices.begin(), Indices.end()) && 1960 Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) 1961 return; 1962 1963 std::string result; 1964 for (unsigned Index : Indices) { 1965 if (!result.empty()) { 1966 result += "\n"; 1967 if (Style.IncludeStyle.IncludeBlocks == 1968 tooling::IncludeStyle::IBS_Regroup && 1969 CurrentCategory != Includes[Index].Category) 1970 result += "\n"; 1971 } 1972 result += Includes[Index].Text; 1973 if (Cursor && CursorIndex == Index) 1974 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset; 1975 CurrentCategory = Includes[Index].Category; 1976 } 1977 1978 // If the #includes are out of order, we generate a single replacement fixing 1979 // the entire range of blocks. Otherwise, no replacement is generated. 1980 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 1981 IncludesBeginOffset, IncludesBlockSize)))) 1982 return; 1983 1984 auto Err = Replaces.add(tooling::Replacement( 1985 FileName, Includes.front().Offset, IncludesBlockSize, result)); 1986 // FIXME: better error handling. For now, just skip the replacement for the 1987 // release version. 1988 if (Err) { 1989 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 1990 assert(false); 1991 } 1992 } 1993 1994 namespace { 1995 1996 const char CppIncludeRegexPattern[] = 1997 R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))"; 1998 1999 } // anonymous namespace 2000 2001 tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code, 2002 ArrayRef<tooling::Range> Ranges, 2003 StringRef FileName, 2004 tooling::Replacements &Replaces, 2005 unsigned *Cursor) { 2006 unsigned Prev = 0; 2007 unsigned SearchFrom = 0; 2008 llvm::Regex IncludeRegex(CppIncludeRegexPattern); 2009 SmallVector<StringRef, 4> Matches; 2010 SmallVector<IncludeDirective, 16> IncludesInBlock; 2011 2012 // In compiled files, consider the first #include to be the main #include of 2013 // the file if it is not a system #include. This ensures that the header 2014 // doesn't have hidden dependencies 2015 // (http://llvm.org/docs/CodingStandards.html#include-style). 2016 // 2017 // FIXME: Do some sanity checking, e.g. edit distance of the base name, to fix 2018 // cases where the first #include is unlikely to be the main header. 2019 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 2020 bool FirstIncludeBlock = true; 2021 bool MainIncludeFound = false; 2022 bool FormattingOff = false; 2023 2024 for (;;) { 2025 auto Pos = Code.find('\n', SearchFrom); 2026 StringRef Line = 2027 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 2028 2029 StringRef Trimmed = Line.trim(); 2030 if (Trimmed == "// clang-format off" || Trimmed == "/* clang-format off */") 2031 FormattingOff = true; 2032 else if (Trimmed == "// clang-format on" || 2033 Trimmed == "/* clang-format on */") 2034 FormattingOff = false; 2035 2036 const bool EmptyLineSkipped = 2037 Trimmed.empty() && 2038 (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge || 2039 Style.IncludeStyle.IncludeBlocks == 2040 tooling::IncludeStyle::IBS_Regroup); 2041 2042 if (!FormattingOff && !Line.endswith("\\")) { 2043 if (IncludeRegex.match(Line, &Matches)) { 2044 StringRef IncludeName = Matches[2]; 2045 int Category = Categories.getIncludePriority( 2046 IncludeName, 2047 /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock); 2048 int Priority = Categories.getSortIncludePriority( 2049 IncludeName, !MainIncludeFound && FirstIncludeBlock); 2050 if (Category == 0) 2051 MainIncludeFound = true; 2052 IncludesInBlock.push_back( 2053 {IncludeName, Line, Prev, Category, Priority}); 2054 } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) { 2055 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, 2056 Replaces, Cursor); 2057 IncludesInBlock.clear(); 2058 FirstIncludeBlock = false; 2059 } 2060 Prev = Pos + 1; 2061 } 2062 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 2063 break; 2064 SearchFrom = Pos + 1; 2065 } 2066 if (!IncludesInBlock.empty()) { 2067 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces, 2068 Cursor); 2069 } 2070 return Replaces; 2071 } 2072 2073 // Returns group number to use as a first order sort on imports. Gives UINT_MAX 2074 // if the import does not match any given groups. 2075 static unsigned findJavaImportGroup(const FormatStyle &Style, 2076 StringRef ImportIdentifier) { 2077 unsigned LongestMatchIndex = UINT_MAX; 2078 unsigned LongestMatchLength = 0; 2079 for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) { 2080 std::string GroupPrefix = Style.JavaImportGroups[I]; 2081 if (ImportIdentifier.startswith(GroupPrefix) && 2082 GroupPrefix.length() > LongestMatchLength) { 2083 LongestMatchIndex = I; 2084 LongestMatchLength = GroupPrefix.length(); 2085 } 2086 } 2087 return LongestMatchIndex; 2088 } 2089 2090 // Sorts and deduplicates a block of includes given by 'Imports' based on 2091 // JavaImportGroups, then adding the necessary replacement to 'Replaces'. 2092 // Import declarations with the same text will be deduplicated. Between each 2093 // import group, a newline is inserted, and within each import group, a 2094 // lexicographic sort based on ASCII value is performed. 2095 static void sortJavaImports(const FormatStyle &Style, 2096 const SmallVectorImpl<JavaImportDirective> &Imports, 2097 ArrayRef<tooling::Range> Ranges, StringRef FileName, 2098 StringRef Code, tooling::Replacements &Replaces) { 2099 unsigned ImportsBeginOffset = Imports.front().Offset; 2100 unsigned ImportsEndOffset = 2101 Imports.back().Offset + Imports.back().Text.size(); 2102 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset; 2103 if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset)) 2104 return; 2105 SmallVector<unsigned, 16> Indices; 2106 SmallVector<unsigned, 16> JavaImportGroups; 2107 for (unsigned i = 0, e = Imports.size(); i != e; ++i) { 2108 Indices.push_back(i); 2109 JavaImportGroups.push_back( 2110 findJavaImportGroup(Style, Imports[i].Identifier)); 2111 } 2112 llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 2113 // Negating IsStatic to push static imports above non-static imports. 2114 return std::make_tuple(!Imports[LHSI].IsStatic, JavaImportGroups[LHSI], 2115 Imports[LHSI].Identifier) < 2116 std::make_tuple(!Imports[RHSI].IsStatic, JavaImportGroups[RHSI], 2117 Imports[RHSI].Identifier); 2118 }); 2119 2120 // Deduplicate imports. 2121 Indices.erase(std::unique(Indices.begin(), Indices.end(), 2122 [&](unsigned LHSI, unsigned RHSI) { 2123 return Imports[LHSI].Text == Imports[RHSI].Text; 2124 }), 2125 Indices.end()); 2126 2127 bool CurrentIsStatic = Imports[Indices.front()].IsStatic; 2128 unsigned CurrentImportGroup = JavaImportGroups[Indices.front()]; 2129 2130 std::string result; 2131 for (unsigned Index : Indices) { 2132 if (!result.empty()) { 2133 result += "\n"; 2134 if (CurrentIsStatic != Imports[Index].IsStatic || 2135 CurrentImportGroup != JavaImportGroups[Index]) 2136 result += "\n"; 2137 } 2138 for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) { 2139 result += CommentLine; 2140 result += "\n"; 2141 } 2142 result += Imports[Index].Text; 2143 CurrentIsStatic = Imports[Index].IsStatic; 2144 CurrentImportGroup = JavaImportGroups[Index]; 2145 } 2146 2147 // If the imports are out of order, we generate a single replacement fixing 2148 // the entire block. Otherwise, no replacement is generated. 2149 if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr( 2150 Imports.front().Offset, ImportsBlockSize)))) 2151 return; 2152 2153 auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset, 2154 ImportsBlockSize, result)); 2155 // FIXME: better error handling. For now, just skip the replacement for the 2156 // release version. 2157 if (Err) { 2158 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 2159 assert(false); 2160 } 2161 } 2162 2163 namespace { 2164 2165 const char JavaImportRegexPattern[] = 2166 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;"; 2167 2168 } // anonymous namespace 2169 2170 tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code, 2171 ArrayRef<tooling::Range> Ranges, 2172 StringRef FileName, 2173 tooling::Replacements &Replaces) { 2174 unsigned Prev = 0; 2175 unsigned SearchFrom = 0; 2176 llvm::Regex ImportRegex(JavaImportRegexPattern); 2177 SmallVector<StringRef, 4> Matches; 2178 SmallVector<JavaImportDirective, 16> ImportsInBlock; 2179 std::vector<StringRef> AssociatedCommentLines; 2180 2181 bool FormattingOff = false; 2182 2183 for (;;) { 2184 auto Pos = Code.find('\n', SearchFrom); 2185 StringRef Line = 2186 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 2187 2188 StringRef Trimmed = Line.trim(); 2189 if (Trimmed == "// clang-format off") 2190 FormattingOff = true; 2191 else if (Trimmed == "// clang-format on") 2192 FormattingOff = false; 2193 2194 if (ImportRegex.match(Line, &Matches)) { 2195 if (FormattingOff) { 2196 // If at least one import line has formatting turned off, turn off 2197 // formatting entirely. 2198 return Replaces; 2199 } 2200 StringRef Static = Matches[1]; 2201 StringRef Identifier = Matches[2]; 2202 bool IsStatic = false; 2203 if (Static.contains("static")) { 2204 IsStatic = true; 2205 } 2206 ImportsInBlock.push_back( 2207 {Identifier, Line, Prev, AssociatedCommentLines, IsStatic}); 2208 AssociatedCommentLines.clear(); 2209 } else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) { 2210 // Associating comments within the imports with the nearest import below 2211 AssociatedCommentLines.push_back(Line); 2212 } 2213 Prev = Pos + 1; 2214 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 2215 break; 2216 SearchFrom = Pos + 1; 2217 } 2218 if (!ImportsInBlock.empty()) 2219 sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces); 2220 return Replaces; 2221 } 2222 2223 bool isMpegTS(StringRef Code) { 2224 // MPEG transport streams use the ".ts" file extension. clang-format should 2225 // not attempt to format those. MPEG TS' frame format starts with 0x47 every 2226 // 189 bytes - detect that and return. 2227 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47; 2228 } 2229 2230 bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); } 2231 2232 tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, 2233 ArrayRef<tooling::Range> Ranges, 2234 StringRef FileName, unsigned *Cursor) { 2235 tooling::Replacements Replaces; 2236 if (!Style.SortIncludes) 2237 return Replaces; 2238 if (isLikelyXml(Code)) 2239 return Replaces; 2240 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript && 2241 isMpegTS(Code)) 2242 return Replaces; 2243 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript) 2244 return sortJavaScriptImports(Style, Code, Ranges, FileName); 2245 if (Style.Language == FormatStyle::LanguageKind::LK_Java) 2246 return sortJavaImports(Style, Code, Ranges, FileName, Replaces); 2247 sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor); 2248 return Replaces; 2249 } 2250 2251 template <typename T> 2252 static llvm::Expected<tooling::Replacements> 2253 processReplacements(T ProcessFunc, StringRef Code, 2254 const tooling::Replacements &Replaces, 2255 const FormatStyle &Style) { 2256 if (Replaces.empty()) 2257 return tooling::Replacements(); 2258 2259 auto NewCode = applyAllReplacements(Code, Replaces); 2260 if (!NewCode) 2261 return NewCode.takeError(); 2262 std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges(); 2263 StringRef FileName = Replaces.begin()->getFilePath(); 2264 2265 tooling::Replacements FormatReplaces = 2266 ProcessFunc(Style, *NewCode, ChangedRanges, FileName); 2267 2268 return Replaces.merge(FormatReplaces); 2269 } 2270 2271 llvm::Expected<tooling::Replacements> 2272 formatReplacements(StringRef Code, const tooling::Replacements &Replaces, 2273 const FormatStyle &Style) { 2274 // We need to use lambda function here since there are two versions of 2275 // `sortIncludes`. 2276 auto SortIncludes = [](const FormatStyle &Style, StringRef Code, 2277 std::vector<tooling::Range> Ranges, 2278 StringRef FileName) -> tooling::Replacements { 2279 return sortIncludes(Style, Code, Ranges, FileName); 2280 }; 2281 auto SortedReplaces = 2282 processReplacements(SortIncludes, Code, Replaces, Style); 2283 if (!SortedReplaces) 2284 return SortedReplaces.takeError(); 2285 2286 // We need to use lambda function here since there are two versions of 2287 // `reformat`. 2288 auto Reformat = [](const FormatStyle &Style, StringRef Code, 2289 std::vector<tooling::Range> Ranges, 2290 StringRef FileName) -> tooling::Replacements { 2291 return reformat(Style, Code, Ranges, FileName); 2292 }; 2293 return processReplacements(Reformat, Code, *SortedReplaces, Style); 2294 } 2295 2296 namespace { 2297 2298 inline bool isHeaderInsertion(const tooling::Replacement &Replace) { 2299 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 && 2300 llvm::Regex(CppIncludeRegexPattern) 2301 .match(Replace.getReplacementText()); 2302 } 2303 2304 inline bool isHeaderDeletion(const tooling::Replacement &Replace) { 2305 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1; 2306 } 2307 2308 // FIXME: insert empty lines between newly created blocks. 2309 tooling::Replacements 2310 fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces, 2311 const FormatStyle &Style) { 2312 if (!Style.isCpp()) 2313 return Replaces; 2314 2315 tooling::Replacements HeaderInsertions; 2316 std::set<llvm::StringRef> HeadersToDelete; 2317 tooling::Replacements Result; 2318 for (const auto &R : Replaces) { 2319 if (isHeaderInsertion(R)) { 2320 // Replacements from \p Replaces must be conflict-free already, so we can 2321 // simply consume the error. 2322 llvm::consumeError(HeaderInsertions.add(R)); 2323 } else if (isHeaderDeletion(R)) { 2324 HeadersToDelete.insert(R.getReplacementText()); 2325 } else if (R.getOffset() == UINT_MAX) { 2326 llvm::errs() << "Insertions other than header #include insertion are " 2327 "not supported! " 2328 << R.getReplacementText() << "\n"; 2329 } else { 2330 llvm::consumeError(Result.add(R)); 2331 } 2332 } 2333 if (HeaderInsertions.empty() && HeadersToDelete.empty()) 2334 return Replaces; 2335 2336 StringRef FileName = Replaces.begin()->getFilePath(); 2337 tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle); 2338 2339 for (const auto &Header : HeadersToDelete) { 2340 tooling::Replacements Replaces = 2341 Includes.remove(Header.trim("\"<>"), Header.startswith("<")); 2342 for (const auto &R : Replaces) { 2343 auto Err = Result.add(R); 2344 if (Err) { 2345 // Ignore the deletion on conflict. 2346 llvm::errs() << "Failed to add header deletion replacement for " 2347 << Header << ": " << llvm::toString(std::move(Err)) 2348 << "\n"; 2349 } 2350 } 2351 } 2352 2353 llvm::Regex IncludeRegex = llvm::Regex(CppIncludeRegexPattern); 2354 llvm::SmallVector<StringRef, 4> Matches; 2355 for (const auto &R : HeaderInsertions) { 2356 auto IncludeDirective = R.getReplacementText(); 2357 bool Matched = IncludeRegex.match(IncludeDirective, &Matches); 2358 assert(Matched && "Header insertion replacement must have replacement text " 2359 "'#include ...'"); 2360 (void)Matched; 2361 auto IncludeName = Matches[2]; 2362 auto Replace = 2363 Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<")); 2364 if (Replace) { 2365 auto Err = Result.add(*Replace); 2366 if (Err) { 2367 llvm::consumeError(std::move(Err)); 2368 unsigned NewOffset = 2369 Result.getShiftedCodePosition(Replace->getOffset()); 2370 auto Shifted = tooling::Replacement(FileName, NewOffset, 0, 2371 Replace->getReplacementText()); 2372 Result = Result.merge(tooling::Replacements(Shifted)); 2373 } 2374 } 2375 } 2376 return Result; 2377 } 2378 2379 } // anonymous namespace 2380 2381 llvm::Expected<tooling::Replacements> 2382 cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, 2383 const FormatStyle &Style) { 2384 // We need to use lambda function here since there are two versions of 2385 // `cleanup`. 2386 auto Cleanup = [](const FormatStyle &Style, StringRef Code, 2387 std::vector<tooling::Range> Ranges, 2388 StringRef FileName) -> tooling::Replacements { 2389 return cleanup(Style, Code, Ranges, FileName); 2390 }; 2391 // Make header insertion replacements insert new headers into correct blocks. 2392 tooling::Replacements NewReplaces = 2393 fixCppIncludeInsertions(Code, Replaces, Style); 2394 return processReplacements(Cleanup, Code, NewReplaces, Style); 2395 } 2396 2397 namespace internal { 2398 std::pair<tooling::Replacements, unsigned> 2399 reformat(const FormatStyle &Style, StringRef Code, 2400 ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn, 2401 unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName, 2402 FormattingAttemptStatus *Status) { 2403 FormatStyle Expanded = expandPresets(Style); 2404 if (Expanded.DisableFormat) 2405 return {tooling::Replacements(), 0}; 2406 if (isLikelyXml(Code)) 2407 return {tooling::Replacements(), 0}; 2408 if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code)) 2409 return {tooling::Replacements(), 0}; 2410 2411 typedef std::function<std::pair<tooling::Replacements, unsigned>( 2412 const Environment &)> 2413 AnalyzerPass; 2414 SmallVector<AnalyzerPass, 4> Passes; 2415 2416 if (Style.Language == FormatStyle::LK_Cpp) { 2417 if (Style.FixNamespaceComments) 2418 Passes.emplace_back([&](const Environment &Env) { 2419 return NamespaceEndCommentsFixer(Env, Expanded).process(); 2420 }); 2421 2422 if (Style.SortUsingDeclarations) 2423 Passes.emplace_back([&](const Environment &Env) { 2424 return UsingDeclarationsSorter(Env, Expanded).process(); 2425 }); 2426 } 2427 2428 if (Style.Language == FormatStyle::LK_JavaScript && 2429 Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) 2430 Passes.emplace_back([&](const Environment &Env) { 2431 return JavaScriptRequoter(Env, Expanded).process(); 2432 }); 2433 2434 Passes.emplace_back([&](const Environment &Env) { 2435 return Formatter(Env, Expanded, Status).process(); 2436 }); 2437 2438 auto Env = 2439 std::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn, 2440 NextStartColumn, LastStartColumn); 2441 llvm::Optional<std::string> CurrentCode = None; 2442 tooling::Replacements Fixes; 2443 unsigned Penalty = 0; 2444 for (size_t I = 0, E = Passes.size(); I < E; ++I) { 2445 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env); 2446 auto NewCode = applyAllReplacements( 2447 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first); 2448 if (NewCode) { 2449 Fixes = Fixes.merge(PassFixes.first); 2450 Penalty += PassFixes.second; 2451 if (I + 1 < E) { 2452 CurrentCode = std::move(*NewCode); 2453 Env = std::make_unique<Environment>( 2454 *CurrentCode, FileName, 2455 tooling::calculateRangesAfterReplacements(Fixes, Ranges), 2456 FirstStartColumn, NextStartColumn, LastStartColumn); 2457 } 2458 } 2459 } 2460 2461 return {Fixes, Penalty}; 2462 } 2463 } // namespace internal 2464 2465 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 2466 ArrayRef<tooling::Range> Ranges, 2467 StringRef FileName, 2468 FormattingAttemptStatus *Status) { 2469 return internal::reformat(Style, Code, Ranges, 2470 /*FirstStartColumn=*/0, 2471 /*NextStartColumn=*/0, 2472 /*LastStartColumn=*/0, FileName, Status) 2473 .first; 2474 } 2475 2476 tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, 2477 ArrayRef<tooling::Range> Ranges, 2478 StringRef FileName) { 2479 // cleanups only apply to C++ (they mostly concern ctor commas etc.) 2480 if (Style.Language != FormatStyle::LK_Cpp) 2481 return tooling::Replacements(); 2482 return Cleaner(Environment(Code, FileName, Ranges), Style).process().first; 2483 } 2484 2485 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 2486 ArrayRef<tooling::Range> Ranges, 2487 StringRef FileName, bool *IncompleteFormat) { 2488 FormattingAttemptStatus Status; 2489 auto Result = reformat(Style, Code, Ranges, FileName, &Status); 2490 if (!Status.FormatComplete) 2491 *IncompleteFormat = true; 2492 return Result; 2493 } 2494 2495 tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, 2496 StringRef Code, 2497 ArrayRef<tooling::Range> Ranges, 2498 StringRef FileName) { 2499 return NamespaceEndCommentsFixer(Environment(Code, FileName, Ranges), Style) 2500 .process() 2501 .first; 2502 } 2503 2504 tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, 2505 StringRef Code, 2506 ArrayRef<tooling::Range> Ranges, 2507 StringRef FileName) { 2508 return UsingDeclarationsSorter(Environment(Code, FileName, Ranges), Style) 2509 .process() 2510 .first; 2511 } 2512 2513 LangOptions getFormattingLangOpts(const FormatStyle &Style) { 2514 LangOptions LangOpts; 2515 2516 FormatStyle::LanguageStandard LexingStd = Style.Standard; 2517 if (LexingStd == FormatStyle::LS_Auto) 2518 LexingStd = FormatStyle::LS_Latest; 2519 if (LexingStd == FormatStyle::LS_Latest) 2520 LexingStd = FormatStyle::LS_Cpp20; 2521 LangOpts.CPlusPlus = 1; 2522 LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11; 2523 LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14; 2524 LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17; 2525 LangOpts.CPlusPlus2a = LexingStd >= FormatStyle::LS_Cpp20; 2526 2527 LangOpts.LineComment = 1; 2528 bool AlternativeOperators = Style.isCpp(); 2529 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0; 2530 LangOpts.Bool = 1; 2531 LangOpts.ObjC = 1; 2532 LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally. 2533 LangOpts.DeclSpecKeyword = 1; // To get __declspec. 2534 return LangOpts; 2535 } 2536 2537 const char *StyleOptionHelpDescription = 2538 "Coding style, currently supports:\n" 2539 " LLVM, Google, Chromium, Mozilla, WebKit.\n" 2540 "Use -style=file to load style configuration from\n" 2541 ".clang-format file located in one of the parent\n" 2542 "directories of the source file (or current\n" 2543 "directory for stdin).\n" 2544 "Use -style=\"{key: value, ...}\" to set specific\n" 2545 "parameters, e.g.:\n" 2546 " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""; 2547 2548 static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) { 2549 if (FileName.endswith(".java")) 2550 return FormatStyle::LK_Java; 2551 if (FileName.endswith_lower(".js") || FileName.endswith_lower(".mjs") || 2552 FileName.endswith_lower(".ts")) 2553 return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript. 2554 if (FileName.endswith(".m") || FileName.endswith(".mm")) 2555 return FormatStyle::LK_ObjC; 2556 if (FileName.endswith_lower(".proto") || 2557 FileName.endswith_lower(".protodevel")) 2558 return FormatStyle::LK_Proto; 2559 if (FileName.endswith_lower(".textpb") || 2560 FileName.endswith_lower(".pb.txt") || 2561 FileName.endswith_lower(".textproto") || 2562 FileName.endswith_lower(".asciipb")) 2563 return FormatStyle::LK_TextProto; 2564 if (FileName.endswith_lower(".td")) 2565 return FormatStyle::LK_TableGen; 2566 if (FileName.endswith_lower(".cs")) 2567 return FormatStyle::LK_CSharp; 2568 return FormatStyle::LK_Cpp; 2569 } 2570 2571 FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) { 2572 const auto GuessedLanguage = getLanguageByFileName(FileName); 2573 if (GuessedLanguage == FormatStyle::LK_Cpp) { 2574 auto Extension = llvm::sys::path::extension(FileName); 2575 // If there's no file extension (or it's .h), we need to check the contents 2576 // of the code to see if it contains Objective-C. 2577 if (Extension.empty() || Extension == ".h") { 2578 auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName; 2579 Environment Env(Code, NonEmptyFileName, /*Ranges=*/{}); 2580 ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle()); 2581 Guesser.process(); 2582 if (Guesser.isObjC()) 2583 return FormatStyle::LK_ObjC; 2584 } 2585 } 2586 return GuessedLanguage; 2587 } 2588 2589 const char *DefaultFormatStyle = "file"; 2590 2591 const char *DefaultFallbackStyle = "LLVM"; 2592 2593 llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, 2594 StringRef FallbackStyleName, 2595 StringRef Code, 2596 llvm::vfs::FileSystem *FS) { 2597 if (!FS) { 2598 FS = llvm::vfs::getRealFileSystem().get(); 2599 } 2600 FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code)); 2601 2602 FormatStyle FallbackStyle = getNoStyle(); 2603 if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle)) 2604 return make_string_error("Invalid fallback style \"" + FallbackStyleName); 2605 2606 if (StyleName.startswith("{")) { 2607 // Parse YAML/JSON style from the command line. 2608 if (std::error_code ec = parseConfiguration(StyleName, &Style)) 2609 return make_string_error("Error parsing -style: " + ec.message()); 2610 return Style; 2611 } 2612 2613 if (!StyleName.equals_lower("file")) { 2614 if (!getPredefinedStyle(StyleName, Style.Language, &Style)) 2615 return make_string_error("Invalid value for -style"); 2616 return Style; 2617 } 2618 2619 // Look for .clang-format/_clang-format file in the file's parent directories. 2620 SmallString<128> UnsuitableConfigFiles; 2621 SmallString<128> Path(FileName); 2622 if (std::error_code EC = FS->makeAbsolute(Path)) 2623 return make_string_error(EC.message()); 2624 2625 llvm::SmallVector<std::string, 2> FilesToLookFor; 2626 FilesToLookFor.push_back(".clang-format"); 2627 FilesToLookFor.push_back("_clang-format"); 2628 2629 for (StringRef Directory = Path; !Directory.empty(); 2630 Directory = llvm::sys::path::parent_path(Directory)) { 2631 2632 auto Status = FS->status(Directory); 2633 if (!Status || 2634 Status->getType() != llvm::sys::fs::file_type::directory_file) { 2635 continue; 2636 } 2637 2638 for (const auto &F : FilesToLookFor) { 2639 SmallString<128> ConfigFile(Directory); 2640 2641 llvm::sys::path::append(ConfigFile, F); 2642 LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); 2643 2644 Status = FS->status(ConfigFile.str()); 2645 2646 if (Status && 2647 (Status->getType() == llvm::sys::fs::file_type::regular_file)) { 2648 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 2649 FS->getBufferForFile(ConfigFile.str()); 2650 if (std::error_code EC = Text.getError()) 2651 return make_string_error(EC.message()); 2652 if (std::error_code ec = 2653 parseConfiguration(Text.get()->getBuffer(), &Style)) { 2654 if (ec == ParseError::Unsuitable) { 2655 if (!UnsuitableConfigFiles.empty()) 2656 UnsuitableConfigFiles.append(", "); 2657 UnsuitableConfigFiles.append(ConfigFile); 2658 continue; 2659 } 2660 return make_string_error("Error reading " + ConfigFile + ": " + 2661 ec.message()); 2662 } 2663 LLVM_DEBUG(llvm::dbgs() 2664 << "Using configuration file " << ConfigFile << "\n"); 2665 return Style; 2666 } 2667 } 2668 } 2669 if (!UnsuitableConfigFiles.empty()) 2670 return make_string_error("Configuration file(s) do(es) not support " + 2671 getLanguageName(Style.Language) + ": " + 2672 UnsuitableConfigFiles); 2673 return FallbackStyle; 2674 } 2675 2676 } // namespace format 2677 } // namespace clang 2678