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