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