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