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 return GoogleStyle; 679 } 680 681 FormatStyle GoogleStyle = getLLVMStyle(); 682 GoogleStyle.Language = Language; 683 684 GoogleStyle.AccessModifierOffset = -1; 685 GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left; 686 GoogleStyle.AllowShortIfStatementsOnASingleLine = true; 687 GoogleStyle.AllowShortLoopsOnASingleLine = true; 688 GoogleStyle.AlwaysBreakBeforeMultilineStrings = true; 689 GoogleStyle.AlwaysBreakTemplateDeclarations = true; 690 GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true; 691 GoogleStyle.DerivePointerAlignment = true; 692 GoogleStyle.IncludeCategories = { 693 {"^<ext/.*\\.h>", 2}, {"^<.*\\.h>", 1}, {"^<.*", 2}, {".*", 3}}; 694 GoogleStyle.IncludeIsMainRegex = "([-_](test|unittest))?$"; 695 GoogleStyle.IndentCaseLabels = true; 696 GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false; 697 GoogleStyle.ObjCSpaceAfterProperty = false; 698 GoogleStyle.ObjCSpaceBeforeProtocolList = true; 699 GoogleStyle.PointerAlignment = FormatStyle::PAS_Left; 700 GoogleStyle.RawStringFormats = {{ 701 FormatStyle::LK_TextProto, 702 /*Delimiters=*/ 703 { 704 "pb", 705 "PB", 706 "proto", 707 "PROTO", 708 "textproto", 709 "TEXTPROTO", 710 }, 711 /*EnclosingFunctionNames=*/ 712 { 713 "EqualsProto", 714 "PARSE_TEXT_PROTO", 715 "ParseTextProto", 716 }, 717 /*CanonicalDelimiter=*/"", 718 /*BasedOnStyle=*/"google", 719 }}; 720 GoogleStyle.SpacesBeforeTrailingComments = 2; 721 GoogleStyle.Standard = FormatStyle::LS_Auto; 722 723 GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200; 724 GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1; 725 726 if (Language == FormatStyle::LK_Java) { 727 GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; 728 GoogleStyle.AlignOperands = false; 729 GoogleStyle.AlignTrailingComments = false; 730 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 731 GoogleStyle.AllowShortIfStatementsOnASingleLine = false; 732 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 733 GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; 734 GoogleStyle.ColumnLimit = 100; 735 GoogleStyle.SpaceAfterCStyleCast = true; 736 GoogleStyle.SpacesBeforeTrailingComments = 1; 737 } else if (Language == FormatStyle::LK_JavaScript) { 738 GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; 739 GoogleStyle.AlignOperands = false; 740 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 741 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 742 GoogleStyle.BreakBeforeTernaryOperators = false; 743 // taze:, triple slash directives (`/// <...`), @tag followed by { for a lot 744 // of JSDoc tags, and @see, which is commonly followed by overlong URLs. 745 GoogleStyle.CommentPragmas = 746 "(taze:|^/[ \t]*<|(@[A-Za-z_0-9-]+[ \\t]*{)|@see)"; 747 GoogleStyle.MaxEmptyLinesToKeep = 3; 748 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All; 749 GoogleStyle.SpacesInContainerLiterals = false; 750 GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single; 751 GoogleStyle.JavaScriptWrapImports = false; 752 } else if (Language == FormatStyle::LK_Proto) { 753 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; 754 GoogleStyle.SpacesInContainerLiterals = false; 755 } else if (Language == FormatStyle::LK_ObjC) { 756 GoogleStyle.ColumnLimit = 100; 757 } 758 759 return GoogleStyle; 760 } 761 762 FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) { 763 FormatStyle ChromiumStyle = getGoogleStyle(Language); 764 if (Language == FormatStyle::LK_Java) { 765 ChromiumStyle.AllowShortIfStatementsOnASingleLine = true; 766 ChromiumStyle.BreakAfterJavaFieldAnnotations = true; 767 ChromiumStyle.ContinuationIndentWidth = 8; 768 ChromiumStyle.IndentWidth = 4; 769 } else if (Language == FormatStyle::LK_JavaScript) { 770 ChromiumStyle.AllowShortIfStatementsOnASingleLine = false; 771 ChromiumStyle.AllowShortLoopsOnASingleLine = false; 772 } else { 773 ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false; 774 ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 775 ChromiumStyle.AllowShortIfStatementsOnASingleLine = false; 776 ChromiumStyle.AllowShortLoopsOnASingleLine = false; 777 ChromiumStyle.BinPackParameters = false; 778 ChromiumStyle.DerivePointerAlignment = false; 779 if (Language == FormatStyle::LK_ObjC) 780 ChromiumStyle.ColumnLimit = 80; 781 } 782 return ChromiumStyle; 783 } 784 785 FormatStyle getMozillaStyle() { 786 FormatStyle MozillaStyle = getLLVMStyle(); 787 MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false; 788 MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 789 MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel; 790 MozillaStyle.AlwaysBreakAfterDefinitionReturnType = 791 FormatStyle::DRTBS_TopLevel; 792 MozillaStyle.AlwaysBreakTemplateDeclarations = true; 793 MozillaStyle.BinPackParameters = false; 794 MozillaStyle.BinPackArguments = false; 795 MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla; 796 MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 797 MozillaStyle.BreakBeforeInheritanceComma = true; 798 MozillaStyle.ConstructorInitializerIndentWidth = 2; 799 MozillaStyle.ContinuationIndentWidth = 2; 800 MozillaStyle.Cpp11BracedListStyle = false; 801 MozillaStyle.FixNamespaceComments = false; 802 MozillaStyle.IndentCaseLabels = true; 803 MozillaStyle.ObjCSpaceAfterProperty = true; 804 MozillaStyle.ObjCSpaceBeforeProtocolList = false; 805 MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200; 806 MozillaStyle.PointerAlignment = FormatStyle::PAS_Left; 807 MozillaStyle.SpaceAfterTemplateKeyword = false; 808 return MozillaStyle; 809 } 810 811 FormatStyle getWebKitStyle() { 812 FormatStyle Style = getLLVMStyle(); 813 Style.AccessModifierOffset = -4; 814 Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; 815 Style.AlignOperands = false; 816 Style.AlignTrailingComments = false; 817 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 818 Style.BreakBeforeBraces = FormatStyle::BS_WebKit; 819 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 820 Style.Cpp11BracedListStyle = false; 821 Style.ColumnLimit = 0; 822 Style.FixNamespaceComments = false; 823 Style.IndentWidth = 4; 824 Style.NamespaceIndentation = FormatStyle::NI_Inner; 825 Style.ObjCBlockIndentWidth = 4; 826 Style.ObjCSpaceAfterProperty = true; 827 Style.PointerAlignment = FormatStyle::PAS_Left; 828 return Style; 829 } 830 831 FormatStyle getGNUStyle() { 832 FormatStyle Style = getLLVMStyle(); 833 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; 834 Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; 835 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 836 Style.BreakBeforeBraces = FormatStyle::BS_GNU; 837 Style.BreakBeforeTernaryOperators = true; 838 Style.Cpp11BracedListStyle = false; 839 Style.ColumnLimit = 79; 840 Style.FixNamespaceComments = false; 841 Style.SpaceBeforeParens = FormatStyle::SBPO_Always; 842 Style.Standard = FormatStyle::LS_Cpp03; 843 return Style; 844 } 845 846 FormatStyle getNoStyle() { 847 FormatStyle NoStyle = getLLVMStyle(); 848 NoStyle.DisableFormat = true; 849 NoStyle.SortIncludes = false; 850 NoStyle.SortUsingDeclarations = false; 851 return NoStyle; 852 } 853 854 bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language, 855 FormatStyle *Style) { 856 if (Name.equals_lower("llvm")) { 857 *Style = getLLVMStyle(); 858 } else if (Name.equals_lower("chromium")) { 859 *Style = getChromiumStyle(Language); 860 } else if (Name.equals_lower("mozilla")) { 861 *Style = getMozillaStyle(); 862 } else if (Name.equals_lower("google")) { 863 *Style = getGoogleStyle(Language); 864 } else if (Name.equals_lower("webkit")) { 865 *Style = getWebKitStyle(); 866 } else if (Name.equals_lower("gnu")) { 867 *Style = getGNUStyle(); 868 } else if (Name.equals_lower("none")) { 869 *Style = getNoStyle(); 870 } else { 871 return false; 872 } 873 874 Style->Language = Language; 875 return true; 876 } 877 878 std::error_code parseConfiguration(StringRef Text, FormatStyle *Style) { 879 assert(Style); 880 FormatStyle::LanguageKind Language = Style->Language; 881 assert(Language != FormatStyle::LK_None); 882 if (Text.trim().empty()) 883 return make_error_code(ParseError::Error); 884 Style->StyleSet.Clear(); 885 std::vector<FormatStyle> Styles; 886 llvm::yaml::Input Input(Text); 887 // DocumentListTraits<vector<FormatStyle>> uses the context to get default 888 // values for the fields, keys for which are missing from the configuration. 889 // Mapping also uses the context to get the language to find the correct 890 // base style. 891 Input.setContext(Style); 892 Input >> Styles; 893 if (Input.error()) 894 return Input.error(); 895 896 for (unsigned i = 0; i < Styles.size(); ++i) { 897 // Ensures that only the first configuration can skip the Language option. 898 if (Styles[i].Language == FormatStyle::LK_None && i != 0) 899 return make_error_code(ParseError::Error); 900 // Ensure that each language is configured at most once. 901 for (unsigned j = 0; j < i; ++j) { 902 if (Styles[i].Language == Styles[j].Language) { 903 DEBUG(llvm::dbgs() 904 << "Duplicate languages in the config file on positions " << j 905 << " and " << i << "\n"); 906 return make_error_code(ParseError::Error); 907 } 908 } 909 } 910 // Look for a suitable configuration starting from the end, so we can 911 // find the configuration for the specific language first, and the default 912 // configuration (which can only be at slot 0) after it. 913 FormatStyle::FormatStyleSet StyleSet; 914 bool LanguageFound = false; 915 for (int i = Styles.size() - 1; i >= 0; --i) { 916 if (Styles[i].Language != FormatStyle::LK_None) 917 StyleSet.Add(Styles[i]); 918 if (Styles[i].Language == Language) 919 LanguageFound = true; 920 } 921 if (!LanguageFound) { 922 if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None) 923 return make_error_code(ParseError::Unsuitable); 924 FormatStyle DefaultStyle = Styles[0]; 925 DefaultStyle.Language = Language; 926 StyleSet.Add(std::move(DefaultStyle)); 927 } 928 *Style = *StyleSet.Get(Language); 929 return make_error_code(ParseError::Success); 930 } 931 932 std::string configurationAsText(const FormatStyle &Style) { 933 std::string Text; 934 llvm::raw_string_ostream Stream(Text); 935 llvm::yaml::Output Output(Stream); 936 // We use the same mapping method for input and output, so we need a non-const 937 // reference here. 938 FormatStyle NonConstStyle = expandPresets(Style); 939 Output << NonConstStyle; 940 return Stream.str(); 941 } 942 943 llvm::Optional<FormatStyle> 944 FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const { 945 if (!Styles) 946 return None; 947 auto It = Styles->find(Language); 948 if (It == Styles->end()) 949 return None; 950 FormatStyle Style = It->second; 951 Style.StyleSet = *this; 952 return Style; 953 } 954 955 void FormatStyle::FormatStyleSet::Add(FormatStyle Style) { 956 assert(Style.Language != LK_None && 957 "Cannot add a style for LK_None to a StyleSet"); 958 assert( 959 !Style.StyleSet.Styles && 960 "Cannot add a style associated with an existing StyleSet to a StyleSet"); 961 if (!Styles) 962 Styles = std::make_shared<MapType>(); 963 (*Styles)[Style.Language] = std::move(Style); 964 } 965 966 void FormatStyle::FormatStyleSet::Clear() { 967 Styles.reset(); 968 } 969 970 llvm::Optional<FormatStyle> 971 FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const { 972 return StyleSet.Get(Language); 973 } 974 975 namespace { 976 977 class JavaScriptRequoter : public TokenAnalyzer { 978 public: 979 JavaScriptRequoter(const Environment &Env, const FormatStyle &Style) 980 : TokenAnalyzer(Env, Style) {} 981 982 std::pair<tooling::Replacements, unsigned> 983 analyze(TokenAnnotator &Annotator, 984 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 985 FormatTokenLexer &Tokens) override { 986 AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(), 987 AnnotatedLines.end()); 988 tooling::Replacements Result; 989 requoteJSStringLiteral(AnnotatedLines, Result); 990 return {Result, 0}; 991 } 992 993 private: 994 // Replaces double/single-quoted string literal as appropriate, re-escaping 995 // the contents in the process. 996 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines, 997 tooling::Replacements &Result) { 998 for (AnnotatedLine *Line : Lines) { 999 requoteJSStringLiteral(Line->Children, Result); 1000 if (!Line->Affected) 1001 continue; 1002 for (FormatToken *FormatTok = Line->First; FormatTok; 1003 FormatTok = FormatTok->Next) { 1004 StringRef Input = FormatTok->TokenText; 1005 if (FormatTok->Finalized || !FormatTok->isStringLiteral() || 1006 // NB: testing for not starting with a double quote to avoid 1007 // breaking `template strings`. 1008 (Style.JavaScriptQuotes == FormatStyle::JSQS_Single && 1009 !Input.startswith("\"")) || 1010 (Style.JavaScriptQuotes == FormatStyle::JSQS_Double && 1011 !Input.startswith("\'"))) 1012 continue; 1013 1014 // Change start and end quote. 1015 bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single; 1016 SourceLocation Start = FormatTok->Tok.getLocation(); 1017 auto Replace = [&](SourceLocation Start, unsigned Length, 1018 StringRef ReplacementText) { 1019 auto Err = Result.add(tooling::Replacement( 1020 Env.getSourceManager(), Start, Length, ReplacementText)); 1021 // FIXME: handle error. For now, print error message and skip the 1022 // replacement for release version. 1023 if (Err) { 1024 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 1025 assert(false); 1026 } 1027 }; 1028 Replace(Start, 1, IsSingle ? "'" : "\""); 1029 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1, 1030 IsSingle ? "'" : "\""); 1031 1032 // Escape internal quotes. 1033 bool Escaped = false; 1034 for (size_t i = 1; i < Input.size() - 1; i++) { 1035 switch (Input[i]) { 1036 case '\\': 1037 if (!Escaped && i + 1 < Input.size() && 1038 ((IsSingle && Input[i + 1] == '"') || 1039 (!IsSingle && Input[i + 1] == '\''))) { 1040 // Remove this \, it's escaping a " or ' that no longer needs 1041 // escaping 1042 Replace(Start.getLocWithOffset(i), 1, ""); 1043 continue; 1044 } 1045 Escaped = !Escaped; 1046 break; 1047 case '\"': 1048 case '\'': 1049 if (!Escaped && IsSingle == (Input[i] == '\'')) { 1050 // Escape the quote. 1051 Replace(Start.getLocWithOffset(i), 0, "\\"); 1052 } 1053 Escaped = false; 1054 break; 1055 default: 1056 Escaped = false; 1057 break; 1058 } 1059 } 1060 } 1061 } 1062 } 1063 }; 1064 1065 class Formatter : public TokenAnalyzer { 1066 public: 1067 Formatter(const Environment &Env, const FormatStyle &Style, 1068 FormattingAttemptStatus *Status) 1069 : TokenAnalyzer(Env, Style), Status(Status) {} 1070 1071 std::pair<tooling::Replacements, unsigned> 1072 analyze(TokenAnnotator &Annotator, 1073 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1074 FormatTokenLexer &Tokens) override { 1075 tooling::Replacements Result; 1076 deriveLocalStyle(AnnotatedLines); 1077 AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(), 1078 AnnotatedLines.end()); 1079 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1080 Annotator.calculateFormattingInformation(*AnnotatedLines[i]); 1081 } 1082 Annotator.setCommentLineLevels(AnnotatedLines); 1083 1084 WhitespaceManager Whitespaces( 1085 Env.getSourceManager(), Style, 1086 inputUsesCRLF(Env.getSourceManager().getBufferData(Env.getFileID()))); 1087 ContinuationIndenter Indenter(Style, Tokens.getKeywords(), 1088 Env.getSourceManager(), Whitespaces, Encoding, 1089 BinPackInconclusiveFunctions); 1090 unsigned Penalty = 1091 UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, 1092 Tokens.getKeywords(), Env.getSourceManager(), 1093 Status) 1094 .format(AnnotatedLines, /*DryRun=*/false, 1095 /*AdditionalIndent=*/0, 1096 /*FixBadIndentation=*/false, 1097 /*FirstStartColumn=*/Env.getFirstStartColumn(), 1098 /*NextStartColumn=*/Env.getNextStartColumn(), 1099 /*LastStartColumn=*/Env.getLastStartColumn()); 1100 for (const auto &R : Whitespaces.generateReplacements()) 1101 if (Result.add(R)) 1102 return std::make_pair(Result, 0); 1103 return std::make_pair(Result, Penalty); 1104 } 1105 1106 private: 1107 static bool inputUsesCRLF(StringRef Text) { 1108 return Text.count('\r') * 2 > Text.count('\n'); 1109 } 1110 1111 bool 1112 hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) { 1113 for (const AnnotatedLine *Line : Lines) { 1114 if (hasCpp03IncompatibleFormat(Line->Children)) 1115 return true; 1116 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) { 1117 if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) { 1118 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener)) 1119 return true; 1120 if (Tok->is(TT_TemplateCloser) && 1121 Tok->Previous->is(TT_TemplateCloser)) 1122 return true; 1123 } 1124 } 1125 } 1126 return false; 1127 } 1128 1129 int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) { 1130 int AlignmentDiff = 0; 1131 for (const AnnotatedLine *Line : Lines) { 1132 AlignmentDiff += countVariableAlignments(Line->Children); 1133 for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) { 1134 if (!Tok->is(TT_PointerOrReference)) 1135 continue; 1136 bool SpaceBefore = 1137 Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd(); 1138 bool SpaceAfter = Tok->Next->WhitespaceRange.getBegin() != 1139 Tok->Next->WhitespaceRange.getEnd(); 1140 if (SpaceBefore && !SpaceAfter) 1141 ++AlignmentDiff; 1142 if (!SpaceBefore && SpaceAfter) 1143 --AlignmentDiff; 1144 } 1145 } 1146 return AlignmentDiff; 1147 } 1148 1149 void 1150 deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 1151 bool HasBinPackedFunction = false; 1152 bool HasOnePerLineFunction = false; 1153 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1154 if (!AnnotatedLines[i]->First->Next) 1155 continue; 1156 FormatToken *Tok = AnnotatedLines[i]->First->Next; 1157 while (Tok->Next) { 1158 if (Tok->PackingKind == PPK_BinPacked) 1159 HasBinPackedFunction = true; 1160 if (Tok->PackingKind == PPK_OnePerLine) 1161 HasOnePerLineFunction = true; 1162 1163 Tok = Tok->Next; 1164 } 1165 } 1166 if (Style.DerivePointerAlignment) 1167 Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0 1168 ? FormatStyle::PAS_Left 1169 : FormatStyle::PAS_Right; 1170 if (Style.Standard == FormatStyle::LS_Auto) 1171 Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines) 1172 ? FormatStyle::LS_Cpp11 1173 : FormatStyle::LS_Cpp03; 1174 BinPackInconclusiveFunctions = 1175 HasBinPackedFunction || !HasOnePerLineFunction; 1176 } 1177 1178 bool BinPackInconclusiveFunctions; 1179 FormattingAttemptStatus *Status; 1180 }; 1181 1182 // This class clean up the erroneous/redundant code around the given ranges in 1183 // file. 1184 class Cleaner : public TokenAnalyzer { 1185 public: 1186 Cleaner(const Environment &Env, const FormatStyle &Style) 1187 : TokenAnalyzer(Env, Style), 1188 DeletedTokens(FormatTokenLess(Env.getSourceManager())) {} 1189 1190 // FIXME: eliminate unused parameters. 1191 std::pair<tooling::Replacements, unsigned> 1192 analyze(TokenAnnotator &Annotator, 1193 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1194 FormatTokenLexer &Tokens) override { 1195 // FIXME: in the current implementation the granularity of affected range 1196 // is an annotated line. However, this is not sufficient. Furthermore, 1197 // redundant code introduced by replacements does not necessarily 1198 // intercept with ranges of replacements that result in the redundancy. 1199 // To determine if some redundant code is actually introduced by 1200 // replacements(e.g. deletions), we need to come up with a more 1201 // sophisticated way of computing affected ranges. 1202 AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(), 1203 AnnotatedLines.end()); 1204 1205 checkEmptyNamespace(AnnotatedLines); 1206 1207 for (auto &Line : AnnotatedLines) { 1208 if (Line->Affected) { 1209 cleanupRight(Line->First, tok::comma, tok::comma); 1210 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma); 1211 cleanupRight(Line->First, tok::l_paren, tok::comma); 1212 cleanupLeft(Line->First, tok::comma, tok::r_paren); 1213 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace); 1214 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace); 1215 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal); 1216 } 1217 } 1218 1219 return {generateFixes(), 0}; 1220 } 1221 1222 private: 1223 bool containsOnlyComments(const AnnotatedLine &Line) { 1224 for (FormatToken *Tok = Line.First; Tok != nullptr; Tok = Tok->Next) { 1225 if (Tok->isNot(tok::comment)) 1226 return false; 1227 } 1228 return true; 1229 } 1230 1231 // Iterate through all lines and remove any empty (nested) namespaces. 1232 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 1233 std::set<unsigned> DeletedLines; 1234 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1235 auto &Line = *AnnotatedLines[i]; 1236 if (Line.startsWith(tok::kw_namespace) || 1237 Line.startsWith(tok::kw_inline, tok::kw_namespace)) { 1238 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines); 1239 } 1240 } 1241 1242 for (auto Line : DeletedLines) { 1243 FormatToken *Tok = AnnotatedLines[Line]->First; 1244 while (Tok) { 1245 deleteToken(Tok); 1246 Tok = Tok->Next; 1247 } 1248 } 1249 } 1250 1251 // The function checks if the namespace, which starts from \p CurrentLine, and 1252 // its nested namespaces are empty and delete them if they are empty. It also 1253 // sets \p NewLine to the last line checked. 1254 // Returns true if the current namespace is empty. 1255 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1256 unsigned CurrentLine, unsigned &NewLine, 1257 std::set<unsigned> &DeletedLines) { 1258 unsigned InitLine = CurrentLine, End = AnnotatedLines.size(); 1259 if (Style.BraceWrapping.AfterNamespace) { 1260 // If the left brace is in a new line, we should consume it first so that 1261 // it does not make the namespace non-empty. 1262 // FIXME: error handling if there is no left brace. 1263 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) { 1264 NewLine = CurrentLine; 1265 return false; 1266 } 1267 } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) { 1268 return false; 1269 } 1270 while (++CurrentLine < End) { 1271 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace)) 1272 break; 1273 1274 if (AnnotatedLines[CurrentLine]->startsWith(tok::kw_namespace) || 1275 AnnotatedLines[CurrentLine]->startsWith(tok::kw_inline, 1276 tok::kw_namespace)) { 1277 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine, 1278 DeletedLines)) 1279 return false; 1280 CurrentLine = NewLine; 1281 continue; 1282 } 1283 1284 if (containsOnlyComments(*AnnotatedLines[CurrentLine])) 1285 continue; 1286 1287 // If there is anything other than comments or nested namespaces in the 1288 // current namespace, the namespace cannot be empty. 1289 NewLine = CurrentLine; 1290 return false; 1291 } 1292 1293 NewLine = CurrentLine; 1294 if (CurrentLine >= End) 1295 return false; 1296 1297 // Check if the empty namespace is actually affected by changed ranges. 1298 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange( 1299 AnnotatedLines[InitLine]->First->Tok.getLocation(), 1300 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) 1301 return false; 1302 1303 for (unsigned i = InitLine; i <= CurrentLine; ++i) { 1304 DeletedLines.insert(i); 1305 } 1306 1307 return true; 1308 } 1309 1310 // Checks pairs {start, start->next},..., {end->previous, end} and deletes one 1311 // of the token in the pair if the left token has \p LK token kind and the 1312 // right token has \p RK token kind. If \p DeleteLeft is true, the left token 1313 // is deleted on match; otherwise, the right token is deleted. 1314 template <typename LeftKind, typename RightKind> 1315 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK, 1316 bool DeleteLeft) { 1317 auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * { 1318 for (auto *Res = Tok.Next; Res; Res = Res->Next) 1319 if (!Res->is(tok::comment) && 1320 DeletedTokens.find(Res) == DeletedTokens.end()) 1321 return Res; 1322 return nullptr; 1323 }; 1324 for (auto *Left = Start; Left;) { 1325 auto *Right = NextNotDeleted(*Left); 1326 if (!Right) 1327 break; 1328 if (Left->is(LK) && Right->is(RK)) { 1329 deleteToken(DeleteLeft ? Left : Right); 1330 for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next) 1331 deleteToken(Tok); 1332 // If the right token is deleted, we should keep the left token 1333 // unchanged and pair it with the new right token. 1334 if (!DeleteLeft) 1335 continue; 1336 } 1337 Left = Right; 1338 } 1339 } 1340 1341 template <typename LeftKind, typename RightKind> 1342 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) { 1343 cleanupPair(Start, LK, RK, /*DeleteLeft=*/true); 1344 } 1345 1346 template <typename LeftKind, typename RightKind> 1347 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) { 1348 cleanupPair(Start, LK, RK, /*DeleteLeft=*/false); 1349 } 1350 1351 // Delete the given token. 1352 inline void deleteToken(FormatToken *Tok) { 1353 if (Tok) 1354 DeletedTokens.insert(Tok); 1355 } 1356 1357 tooling::Replacements generateFixes() { 1358 tooling::Replacements Fixes; 1359 std::vector<FormatToken *> Tokens; 1360 std::copy(DeletedTokens.begin(), DeletedTokens.end(), 1361 std::back_inserter(Tokens)); 1362 1363 // Merge multiple continuous token deletions into one big deletion so that 1364 // the number of replacements can be reduced. This makes computing affected 1365 // ranges more efficient when we run reformat on the changed code. 1366 unsigned Idx = 0; 1367 while (Idx < Tokens.size()) { 1368 unsigned St = Idx, End = Idx; 1369 while ((End + 1) < Tokens.size() && 1370 Tokens[End]->Next == Tokens[End + 1]) { 1371 End++; 1372 } 1373 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(), 1374 Tokens[End]->Tok.getEndLoc()); 1375 auto Err = 1376 Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, "")); 1377 // FIXME: better error handling. for now just print error message and skip 1378 // for the release version. 1379 if (Err) { 1380 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 1381 assert(false && "Fixes must not conflict!"); 1382 } 1383 Idx = End + 1; 1384 } 1385 1386 return Fixes; 1387 } 1388 1389 // Class for less-than inequality comparason for the set `RedundantTokens`. 1390 // We store tokens in the order they appear in the translation unit so that 1391 // we do not need to sort them in `generateFixes()`. 1392 struct FormatTokenLess { 1393 FormatTokenLess(const SourceManager &SM) : SM(SM) {} 1394 1395 bool operator()(const FormatToken *LHS, const FormatToken *RHS) const { 1396 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(), 1397 RHS->Tok.getLocation()); 1398 } 1399 const SourceManager &SM; 1400 }; 1401 1402 // Tokens to be deleted. 1403 std::set<FormatToken *, FormatTokenLess> DeletedTokens; 1404 }; 1405 1406 class ObjCHeaderStyleGuesser : public TokenAnalyzer { 1407 public: 1408 ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style) 1409 : TokenAnalyzer(Env, Style), IsObjC(false) {} 1410 1411 std::pair<tooling::Replacements, unsigned> 1412 analyze(TokenAnnotator &Annotator, 1413 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1414 FormatTokenLexer &Tokens) override { 1415 assert(Style.Language == FormatStyle::LK_Cpp); 1416 IsObjC = guessIsObjC(AnnotatedLines, Tokens.getKeywords()); 1417 tooling::Replacements Result; 1418 return {Result, 0}; 1419 } 1420 1421 bool isObjC() { return IsObjC; } 1422 1423 private: 1424 static bool guessIsObjC(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1425 const AdditionalKeywords &Keywords) { 1426 // Keep this array sorted, since we are binary searching over it. 1427 static constexpr llvm::StringLiteral FoundationIdentifiers[] = { 1428 "CGFloat", 1429 "NSAffineTransform", 1430 "NSArray", 1431 "NSAttributedString", 1432 "NSCache", 1433 "NSCharacterSet", 1434 "NSCountedSet", 1435 "NSData", 1436 "NSDataDetector", 1437 "NSDecimal", 1438 "NSDecimalNumber", 1439 "NSDictionary", 1440 "NSEdgeInsets", 1441 "NSHashTable", 1442 "NSIndexPath", 1443 "NSIndexSet", 1444 "NSInteger", 1445 "NSLocale", 1446 "NSMapTable", 1447 "NSMutableArray", 1448 "NSMutableAttributedString", 1449 "NSMutableCharacterSet", 1450 "NSMutableData", 1451 "NSMutableDictionary", 1452 "NSMutableIndexSet", 1453 "NSMutableOrderedSet", 1454 "NSMutableSet", 1455 "NSMutableString", 1456 "NSNumber", 1457 "NSNumberFormatter", 1458 "NSOrderedSet", 1459 "NSPoint", 1460 "NSPointerArray", 1461 "NSRange", 1462 "NSRect", 1463 "NSRegularExpression", 1464 "NSSet", 1465 "NSSize", 1466 "NSString", 1467 "NSUInteger", 1468 "NSURL", 1469 "NSURLComponents", 1470 "NSURLQueryItem", 1471 "NSUUID", 1472 }; 1473 1474 for (auto &Line : AnnotatedLines) { 1475 for (FormatToken *FormatTok = Line->First->Next; FormatTok; 1476 FormatTok = FormatTok->Next) { 1477 if ((FormatTok->Previous->is(tok::at) && 1478 (FormatTok->isObjCAtKeyword(tok::objc_interface) || 1479 FormatTok->isObjCAtKeyword(tok::objc_implementation) || 1480 FormatTok->isObjCAtKeyword(tok::objc_protocol) || 1481 FormatTok->isObjCAtKeyword(tok::objc_end) || 1482 FormatTok->isOneOf(tok::numeric_constant, tok::l_square, 1483 tok::l_brace))) || 1484 (FormatTok->Tok.isAnyIdentifier() && 1485 std::binary_search(std::begin(FoundationIdentifiers), 1486 std::end(FoundationIdentifiers), 1487 FormatTok->TokenText)) || 1488 FormatTok->is(TT_ObjCStringLiteral) || 1489 FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS, 1490 TT_ObjCBlockLBrace, TT_ObjCBlockLParen, 1491 TT_ObjCDecl, TT_ObjCForIn, TT_ObjCMethodExpr, 1492 TT_ObjCMethodSpecifier, TT_ObjCProperty)) { 1493 return true; 1494 } 1495 } 1496 } 1497 return false; 1498 } 1499 1500 bool IsObjC; 1501 }; 1502 1503 struct IncludeDirective { 1504 StringRef Filename; 1505 StringRef Text; 1506 unsigned Offset; 1507 int Category; 1508 }; 1509 1510 } // end anonymous namespace 1511 1512 // Determines whether 'Ranges' intersects with ('Start', 'End'). 1513 static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start, 1514 unsigned End) { 1515 for (auto Range : Ranges) { 1516 if (Range.getOffset() < End && 1517 Range.getOffset() + Range.getLength() > Start) 1518 return true; 1519 } 1520 return false; 1521 } 1522 1523 // Returns a pair (Index, OffsetToEOL) describing the position of the cursor 1524 // before sorting/deduplicating. Index is the index of the include under the 1525 // cursor in the original set of includes. If this include has duplicates, it is 1526 // the index of the first of the duplicates as the others are going to be 1527 // removed. OffsetToEOL describes the cursor's position relative to the end of 1528 // its current line. 1529 // If `Cursor` is not on any #include, `Index` will be UINT_MAX. 1530 static std::pair<unsigned, unsigned> 1531 FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes, 1532 const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) { 1533 unsigned CursorIndex = UINT_MAX; 1534 unsigned OffsetToEOL = 0; 1535 for (int i = 0, e = Includes.size(); i != e; ++i) { 1536 unsigned Start = Includes[Indices[i]].Offset; 1537 unsigned End = Start + Includes[Indices[i]].Text.size(); 1538 if (!(Cursor >= Start && Cursor < End)) 1539 continue; 1540 CursorIndex = Indices[i]; 1541 OffsetToEOL = End - Cursor; 1542 // Put the cursor on the only remaining #include among the duplicate 1543 // #includes. 1544 while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text) 1545 CursorIndex = i; 1546 break; 1547 } 1548 return std::make_pair(CursorIndex, OffsetToEOL); 1549 } 1550 1551 // Sorts and deduplicate a block of includes given by 'Includes' alphabetically 1552 // adding the necessary replacement to 'Replaces'. 'Includes' must be in strict 1553 // source order. 1554 // #include directives with the same text will be deduplicated, and only the 1555 // first #include in the duplicate #includes remains. If the `Cursor` is 1556 // provided and put on a deleted #include, it will be moved to the remaining 1557 // #include in the duplicate #includes. 1558 static void sortCppIncludes(const FormatStyle &Style, 1559 const SmallVectorImpl<IncludeDirective> &Includes, 1560 ArrayRef<tooling::Range> Ranges, StringRef FileName, 1561 tooling::Replacements &Replaces, unsigned *Cursor) { 1562 unsigned IncludesBeginOffset = Includes.front().Offset; 1563 unsigned IncludesEndOffset = 1564 Includes.back().Offset + Includes.back().Text.size(); 1565 unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset; 1566 if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset)) 1567 return; 1568 SmallVector<unsigned, 16> Indices; 1569 for (unsigned i = 0, e = Includes.size(); i != e; ++i) 1570 Indices.push_back(i); 1571 std::stable_sort( 1572 Indices.begin(), Indices.end(), [&](unsigned LHSI, unsigned RHSI) { 1573 return std::tie(Includes[LHSI].Category, Includes[LHSI].Filename) < 1574 std::tie(Includes[RHSI].Category, Includes[RHSI].Filename); 1575 }); 1576 // The index of the include on which the cursor will be put after 1577 // sorting/deduplicating. 1578 unsigned CursorIndex; 1579 // The offset from cursor to the end of line. 1580 unsigned CursorToEOLOffset; 1581 if (Cursor) 1582 std::tie(CursorIndex, CursorToEOLOffset) = 1583 FindCursorIndex(Includes, Indices, *Cursor); 1584 1585 // Deduplicate #includes. 1586 Indices.erase(std::unique(Indices.begin(), Indices.end(), 1587 [&](unsigned LHSI, unsigned RHSI) { 1588 return Includes[LHSI].Text == Includes[RHSI].Text; 1589 }), 1590 Indices.end()); 1591 1592 int CurrentCategory = Includes.front().Category; 1593 1594 // If the #includes are out of order, we generate a single replacement fixing 1595 // the entire block. Otherwise, no replacement is generated. 1596 if (Indices.size() == Includes.size() && 1597 std::is_sorted(Indices.begin(), Indices.end()) && 1598 Style.IncludeBlocks == FormatStyle::IBS_Preserve) 1599 return; 1600 1601 std::string result; 1602 for (unsigned Index : Indices) { 1603 if (!result.empty()) { 1604 result += "\n"; 1605 if (Style.IncludeBlocks == FormatStyle::IBS_Regroup && 1606 CurrentCategory != Includes[Index].Category) 1607 result += "\n"; 1608 } 1609 result += Includes[Index].Text; 1610 if (Cursor && CursorIndex == Index) 1611 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset; 1612 CurrentCategory = Includes[Index].Category; 1613 } 1614 1615 auto Err = Replaces.add(tooling::Replacement( 1616 FileName, Includes.front().Offset, IncludesBlockSize, result)); 1617 // FIXME: better error handling. For now, just skip the replacement for the 1618 // release version. 1619 if (Err) { 1620 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 1621 assert(false); 1622 } 1623 } 1624 1625 namespace { 1626 1627 // This class manages priorities of #include categories and calculates 1628 // priorities for headers. 1629 class IncludeCategoryManager { 1630 public: 1631 IncludeCategoryManager(const FormatStyle &Style, StringRef FileName) 1632 : Style(Style), FileName(FileName) { 1633 FileStem = llvm::sys::path::stem(FileName); 1634 for (const auto &Category : Style.IncludeCategories) 1635 CategoryRegexs.emplace_back(Category.Regex, llvm::Regex::IgnoreCase); 1636 IsMainFile = FileName.endswith(".c") || FileName.endswith(".cc") || 1637 FileName.endswith(".cpp") || FileName.endswith(".c++") || 1638 FileName.endswith(".cxx") || FileName.endswith(".m") || 1639 FileName.endswith(".mm"); 1640 } 1641 1642 // Returns the priority of the category which \p IncludeName belongs to. 1643 // If \p CheckMainHeader is true and \p IncludeName is a main header, returns 1644 // 0. Otherwise, returns the priority of the matching category or INT_MAX. 1645 int getIncludePriority(StringRef IncludeName, bool CheckMainHeader) { 1646 int Ret = INT_MAX; 1647 for (unsigned i = 0, e = CategoryRegexs.size(); i != e; ++i) 1648 if (CategoryRegexs[i].match(IncludeName)) { 1649 Ret = Style.IncludeCategories[i].Priority; 1650 break; 1651 } 1652 if (CheckMainHeader && IsMainFile && Ret > 0 && isMainHeader(IncludeName)) 1653 Ret = 0; 1654 return Ret; 1655 } 1656 1657 private: 1658 bool isMainHeader(StringRef IncludeName) const { 1659 if (!IncludeName.startswith("\"")) 1660 return false; 1661 StringRef HeaderStem = 1662 llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(1)); 1663 if (FileStem.startswith(HeaderStem) || 1664 FileStem.startswith_lower(HeaderStem)) { 1665 llvm::Regex MainIncludeRegex( 1666 (HeaderStem + Style.IncludeIsMainRegex).str(), 1667 llvm::Regex::IgnoreCase); 1668 if (MainIncludeRegex.match(FileStem)) 1669 return true; 1670 } 1671 return false; 1672 } 1673 1674 const FormatStyle &Style; 1675 bool IsMainFile; 1676 StringRef FileName; 1677 StringRef FileStem; 1678 SmallVector<llvm::Regex, 4> CategoryRegexs; 1679 }; 1680 1681 const char IncludeRegexPattern[] = 1682 R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))"; 1683 1684 } // anonymous namespace 1685 1686 tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code, 1687 ArrayRef<tooling::Range> Ranges, 1688 StringRef FileName, 1689 tooling::Replacements &Replaces, 1690 unsigned *Cursor) { 1691 unsigned Prev = 0; 1692 unsigned SearchFrom = 0; 1693 llvm::Regex IncludeRegex(IncludeRegexPattern); 1694 SmallVector<StringRef, 4> Matches; 1695 SmallVector<IncludeDirective, 16> IncludesInBlock; 1696 1697 // In compiled files, consider the first #include to be the main #include of 1698 // the file if it is not a system #include. This ensures that the header 1699 // doesn't have hidden dependencies 1700 // (http://llvm.org/docs/CodingStandards.html#include-style). 1701 // 1702 // FIXME: Do some sanity checking, e.g. edit distance of the base name, to fix 1703 // cases where the first #include is unlikely to be the main header. 1704 IncludeCategoryManager Categories(Style, FileName); 1705 bool FirstIncludeBlock = true; 1706 bool MainIncludeFound = false; 1707 bool FormattingOff = false; 1708 1709 for (;;) { 1710 auto Pos = Code.find('\n', SearchFrom); 1711 StringRef Line = 1712 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 1713 1714 StringRef Trimmed = Line.trim(); 1715 if (Trimmed == "// clang-format off") 1716 FormattingOff = true; 1717 else if (Trimmed == "// clang-format on") 1718 FormattingOff = false; 1719 1720 const bool EmptyLineSkipped = 1721 Trimmed.empty() && (Style.IncludeBlocks == FormatStyle::IBS_Merge || 1722 Style.IncludeBlocks == FormatStyle::IBS_Regroup); 1723 1724 if (!FormattingOff && !Line.endswith("\\")) { 1725 if (IncludeRegex.match(Line, &Matches)) { 1726 StringRef IncludeName = Matches[2]; 1727 int Category = Categories.getIncludePriority( 1728 IncludeName, 1729 /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock); 1730 if (Category == 0) 1731 MainIncludeFound = true; 1732 IncludesInBlock.push_back({IncludeName, Line, Prev, Category}); 1733 } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) { 1734 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces, 1735 Cursor); 1736 IncludesInBlock.clear(); 1737 FirstIncludeBlock = false; 1738 } 1739 Prev = Pos + 1; 1740 } 1741 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 1742 break; 1743 SearchFrom = Pos + 1; 1744 } 1745 if (!IncludesInBlock.empty()) 1746 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces, Cursor); 1747 return Replaces; 1748 } 1749 1750 bool isMpegTS(StringRef Code) { 1751 // MPEG transport streams use the ".ts" file extension. clang-format should 1752 // not attempt to format those. MPEG TS' frame format starts with 0x47 every 1753 // 189 bytes - detect that and return. 1754 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47; 1755 } 1756 1757 bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); } 1758 1759 tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, 1760 ArrayRef<tooling::Range> Ranges, 1761 StringRef FileName, unsigned *Cursor) { 1762 tooling::Replacements Replaces; 1763 if (!Style.SortIncludes) 1764 return Replaces; 1765 if (isLikelyXml(Code)) 1766 return Replaces; 1767 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript && 1768 isMpegTS(Code)) 1769 return Replaces; 1770 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript) 1771 return sortJavaScriptImports(Style, Code, Ranges, FileName); 1772 sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor); 1773 return Replaces; 1774 } 1775 1776 template <typename T> 1777 static llvm::Expected<tooling::Replacements> 1778 processReplacements(T ProcessFunc, StringRef Code, 1779 const tooling::Replacements &Replaces, 1780 const FormatStyle &Style) { 1781 if (Replaces.empty()) 1782 return tooling::Replacements(); 1783 1784 auto NewCode = applyAllReplacements(Code, Replaces); 1785 if (!NewCode) 1786 return NewCode.takeError(); 1787 std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges(); 1788 StringRef FileName = Replaces.begin()->getFilePath(); 1789 1790 tooling::Replacements FormatReplaces = 1791 ProcessFunc(Style, *NewCode, ChangedRanges, FileName); 1792 1793 return Replaces.merge(FormatReplaces); 1794 } 1795 1796 llvm::Expected<tooling::Replacements> 1797 formatReplacements(StringRef Code, const tooling::Replacements &Replaces, 1798 const FormatStyle &Style) { 1799 // We need to use lambda function here since there are two versions of 1800 // `sortIncludes`. 1801 auto SortIncludes = [](const FormatStyle &Style, StringRef Code, 1802 std::vector<tooling::Range> Ranges, 1803 StringRef FileName) -> tooling::Replacements { 1804 return sortIncludes(Style, Code, Ranges, FileName); 1805 }; 1806 auto SortedReplaces = 1807 processReplacements(SortIncludes, Code, Replaces, Style); 1808 if (!SortedReplaces) 1809 return SortedReplaces.takeError(); 1810 1811 // We need to use lambda function here since there are two versions of 1812 // `reformat`. 1813 auto Reformat = [](const FormatStyle &Style, StringRef Code, 1814 std::vector<tooling::Range> Ranges, 1815 StringRef FileName) -> tooling::Replacements { 1816 return reformat(Style, Code, Ranges, FileName); 1817 }; 1818 return processReplacements(Reformat, Code, *SortedReplaces, Style); 1819 } 1820 1821 namespace { 1822 1823 inline bool isHeaderInsertion(const tooling::Replacement &Replace) { 1824 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 && 1825 llvm::Regex(IncludeRegexPattern).match(Replace.getReplacementText()); 1826 } 1827 1828 inline bool isHeaderDeletion(const tooling::Replacement &Replace) { 1829 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1; 1830 } 1831 1832 // Returns the offset after skipping a sequence of tokens, matched by \p 1833 // GetOffsetAfterSequence, from the start of the code. 1834 // \p GetOffsetAfterSequence should be a function that matches a sequence of 1835 // tokens and returns an offset after the sequence. 1836 unsigned getOffsetAfterTokenSequence( 1837 StringRef FileName, StringRef Code, const FormatStyle &Style, 1838 llvm::function_ref<unsigned(const SourceManager &, Lexer &, Token &)> 1839 GetOffsetAfterSequence) { 1840 std::unique_ptr<Environment> Env = 1841 Environment::CreateVirtualEnvironment(Code, FileName, /*Ranges=*/{}); 1842 const SourceManager &SourceMgr = Env->getSourceManager(); 1843 Lexer Lex(Env->getFileID(), SourceMgr.getBuffer(Env->getFileID()), SourceMgr, 1844 getFormattingLangOpts(Style)); 1845 Token Tok; 1846 // Get the first token. 1847 Lex.LexFromRawLexer(Tok); 1848 return GetOffsetAfterSequence(SourceMgr, Lex, Tok); 1849 } 1850 1851 // Check if a sequence of tokens is like "#<Name> <raw_identifier>". If it is, 1852 // \p Tok will be the token after this directive; otherwise, it can be any token 1853 // after the given \p Tok (including \p Tok). 1854 bool checkAndConsumeDirectiveWithName(Lexer &Lex, StringRef Name, Token &Tok) { 1855 bool Matched = Tok.is(tok::hash) && !Lex.LexFromRawLexer(Tok) && 1856 Tok.is(tok::raw_identifier) && 1857 Tok.getRawIdentifier() == Name && !Lex.LexFromRawLexer(Tok) && 1858 Tok.is(tok::raw_identifier); 1859 if (Matched) 1860 Lex.LexFromRawLexer(Tok); 1861 return Matched; 1862 } 1863 1864 void skipComments(Lexer &Lex, Token &Tok) { 1865 while (Tok.is(tok::comment)) 1866 if (Lex.LexFromRawLexer(Tok)) 1867 return; 1868 } 1869 1870 // Returns the offset after header guard directives and any comments 1871 // before/after header guards. If no header guard presents in the code, this 1872 // will returns the offset after skipping all comments from the start of the 1873 // code. 1874 unsigned getOffsetAfterHeaderGuardsAndComments(StringRef FileName, 1875 StringRef Code, 1876 const FormatStyle &Style) { 1877 return getOffsetAfterTokenSequence( 1878 FileName, Code, Style, 1879 [](const SourceManager &SM, Lexer &Lex, Token Tok) { 1880 skipComments(Lex, Tok); 1881 unsigned InitialOffset = SM.getFileOffset(Tok.getLocation()); 1882 if (checkAndConsumeDirectiveWithName(Lex, "ifndef", Tok)) { 1883 skipComments(Lex, Tok); 1884 if (checkAndConsumeDirectiveWithName(Lex, "define", Tok)) 1885 return SM.getFileOffset(Tok.getLocation()); 1886 } 1887 return InitialOffset; 1888 }); 1889 } 1890 1891 // Check if a sequence of tokens is like 1892 // "#include ("header.h" | <header.h>)". 1893 // If it is, \p Tok will be the token after this directive; otherwise, it can be 1894 // any token after the given \p Tok (including \p Tok). 1895 bool checkAndConsumeInclusiveDirective(Lexer &Lex, Token &Tok) { 1896 auto Matched = [&]() { 1897 Lex.LexFromRawLexer(Tok); 1898 return true; 1899 }; 1900 if (Tok.is(tok::hash) && !Lex.LexFromRawLexer(Tok) && 1901 Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == "include") { 1902 if (Lex.LexFromRawLexer(Tok)) 1903 return false; 1904 if (Tok.is(tok::string_literal)) 1905 return Matched(); 1906 if (Tok.is(tok::less)) { 1907 while (!Lex.LexFromRawLexer(Tok) && Tok.isNot(tok::greater)) { 1908 } 1909 if (Tok.is(tok::greater)) 1910 return Matched(); 1911 } 1912 } 1913 return false; 1914 } 1915 1916 // Returns the offset of the last #include directive after which a new 1917 // #include can be inserted. This ignores #include's after the #include block(s) 1918 // in the beginning of a file to avoid inserting headers into code sections 1919 // where new #include's should not be added by default. 1920 // These code sections include: 1921 // - raw string literals (containing #include). 1922 // - #if blocks. 1923 // - Special #include's among declarations (e.g. functions). 1924 // 1925 // If no #include after which a new #include can be inserted, this returns the 1926 // offset after skipping all comments from the start of the code. 1927 // Inserting after an #include is not allowed if it comes after code that is not 1928 // #include (e.g. pre-processing directive that is not #include, declarations). 1929 unsigned getMaxHeaderInsertionOffset(StringRef FileName, StringRef Code, 1930 const FormatStyle &Style) { 1931 return getOffsetAfterTokenSequence( 1932 FileName, Code, Style, 1933 [](const SourceManager &SM, Lexer &Lex, Token Tok) { 1934 skipComments(Lex, Tok); 1935 unsigned MaxOffset = SM.getFileOffset(Tok.getLocation()); 1936 while (checkAndConsumeInclusiveDirective(Lex, Tok)) 1937 MaxOffset = SM.getFileOffset(Tok.getLocation()); 1938 return MaxOffset; 1939 }); 1940 } 1941 1942 bool isDeletedHeader(llvm::StringRef HeaderName, 1943 const std::set<llvm::StringRef> &HeadersToDelete) { 1944 return HeadersToDelete.count(HeaderName) || 1945 HeadersToDelete.count(HeaderName.trim("\"<>")); 1946 } 1947 1948 // FIXME: insert empty lines between newly created blocks. 1949 tooling::Replacements 1950 fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces, 1951 const FormatStyle &Style) { 1952 if (!Style.isCpp()) 1953 return Replaces; 1954 1955 tooling::Replacements HeaderInsertions; 1956 std::set<llvm::StringRef> HeadersToDelete; 1957 tooling::Replacements Result; 1958 for (const auto &R : Replaces) { 1959 if (isHeaderInsertion(R)) { 1960 // Replacements from \p Replaces must be conflict-free already, so we can 1961 // simply consume the error. 1962 llvm::consumeError(HeaderInsertions.add(R)); 1963 } else if (isHeaderDeletion(R)) { 1964 HeadersToDelete.insert(R.getReplacementText()); 1965 } else if (R.getOffset() == UINT_MAX) { 1966 llvm::errs() << "Insertions other than header #include insertion are " 1967 "not supported! " 1968 << R.getReplacementText() << "\n"; 1969 } else { 1970 llvm::consumeError(Result.add(R)); 1971 } 1972 } 1973 if (HeaderInsertions.empty() && HeadersToDelete.empty()) 1974 return Replaces; 1975 1976 llvm::Regex IncludeRegex(IncludeRegexPattern); 1977 llvm::Regex DefineRegex(R"(^[\t\ ]*#[\t\ ]*define[\t\ ]*[^\\]*$)"); 1978 SmallVector<StringRef, 4> Matches; 1979 1980 StringRef FileName = Replaces.begin()->getFilePath(); 1981 IncludeCategoryManager Categories(Style, FileName); 1982 1983 // Record the offset of the end of the last include in each category. 1984 std::map<int, int> CategoryEndOffsets; 1985 // All possible priorities. 1986 // Add 0 for main header and INT_MAX for headers that are not in any category. 1987 std::set<int> Priorities = {0, INT_MAX}; 1988 for (const auto &Category : Style.IncludeCategories) 1989 Priorities.insert(Category.Priority); 1990 int FirstIncludeOffset = -1; 1991 // All new headers should be inserted after this offset. 1992 unsigned MinInsertOffset = 1993 getOffsetAfterHeaderGuardsAndComments(FileName, Code, Style); 1994 StringRef TrimmedCode = Code.drop_front(MinInsertOffset); 1995 // Max insertion offset in the original code. 1996 unsigned MaxInsertOffset = 1997 MinInsertOffset + 1998 getMaxHeaderInsertionOffset(FileName, TrimmedCode, Style); 1999 SmallVector<StringRef, 32> Lines; 2000 TrimmedCode.split(Lines, '\n'); 2001 unsigned Offset = MinInsertOffset; 2002 unsigned NextLineOffset; 2003 std::set<StringRef> ExistingIncludes; 2004 for (auto Line : Lines) { 2005 NextLineOffset = std::min(Code.size(), Offset + Line.size() + 1); 2006 if (IncludeRegex.match(Line, &Matches)) { 2007 // The header name with quotes or angle brackets. 2008 StringRef IncludeName = Matches[2]; 2009 ExistingIncludes.insert(IncludeName); 2010 // Only record the offset of current #include if we can insert after it. 2011 if (Offset <= MaxInsertOffset) { 2012 int Category = Categories.getIncludePriority( 2013 IncludeName, /*CheckMainHeader=*/FirstIncludeOffset < 0); 2014 CategoryEndOffsets[Category] = NextLineOffset; 2015 if (FirstIncludeOffset < 0) 2016 FirstIncludeOffset = Offset; 2017 } 2018 if (isDeletedHeader(IncludeName, HeadersToDelete)) { 2019 // If this is the last line without trailing newline, we need to make 2020 // sure we don't delete across the file boundary. 2021 unsigned Length = std::min(Line.size() + 1, Code.size() - Offset); 2022 llvm::Error Err = 2023 Result.add(tooling::Replacement(FileName, Offset, Length, "")); 2024 if (Err) { 2025 // Ignore the deletion on conflict. 2026 llvm::errs() << "Failed to add header deletion replacement for " 2027 << IncludeName << ": " << llvm::toString(std::move(Err)) 2028 << "\n"; 2029 } 2030 } 2031 } 2032 Offset = NextLineOffset; 2033 } 2034 2035 // Populate CategoryEndOfssets: 2036 // - Ensure that CategoryEndOffset[Highest] is always populated. 2037 // - If CategoryEndOffset[Priority] isn't set, use the next higher value that 2038 // is set, up to CategoryEndOffset[Highest]. 2039 auto Highest = Priorities.begin(); 2040 if (CategoryEndOffsets.find(*Highest) == CategoryEndOffsets.end()) { 2041 if (FirstIncludeOffset >= 0) 2042 CategoryEndOffsets[*Highest] = FirstIncludeOffset; 2043 else 2044 CategoryEndOffsets[*Highest] = MinInsertOffset; 2045 } 2046 // By this point, CategoryEndOffset[Highest] is always set appropriately: 2047 // - to an appropriate location before/after existing #includes, or 2048 // - to right after the header guard, or 2049 // - to the beginning of the file. 2050 for (auto I = ++Priorities.begin(), E = Priorities.end(); I != E; ++I) 2051 if (CategoryEndOffsets.find(*I) == CategoryEndOffsets.end()) 2052 CategoryEndOffsets[*I] = CategoryEndOffsets[*std::prev(I)]; 2053 2054 bool NeedNewLineAtEnd = !Code.empty() && Code.back() != '\n'; 2055 for (const auto &R : HeaderInsertions) { 2056 auto IncludeDirective = R.getReplacementText(); 2057 bool Matched = IncludeRegex.match(IncludeDirective, &Matches); 2058 assert(Matched && "Header insertion replacement must have replacement text " 2059 "'#include ...'"); 2060 (void)Matched; 2061 auto IncludeName = Matches[2]; 2062 if (ExistingIncludes.find(IncludeName) != ExistingIncludes.end()) { 2063 DEBUG(llvm::dbgs() << "Skip adding existing include : " << IncludeName 2064 << "\n"); 2065 continue; 2066 } 2067 int Category = 2068 Categories.getIncludePriority(IncludeName, /*CheckMainHeader=*/true); 2069 Offset = CategoryEndOffsets[Category]; 2070 std::string NewInclude = !IncludeDirective.endswith("\n") 2071 ? (IncludeDirective + "\n").str() 2072 : IncludeDirective.str(); 2073 // When inserting headers at end of the code, also append '\n' to the code 2074 // if it does not end with '\n'. 2075 if (NeedNewLineAtEnd && Offset == Code.size()) { 2076 NewInclude = "\n" + NewInclude; 2077 NeedNewLineAtEnd = false; 2078 } 2079 auto NewReplace = tooling::Replacement(FileName, Offset, 0, NewInclude); 2080 auto Err = Result.add(NewReplace); 2081 if (Err) { 2082 llvm::consumeError(std::move(Err)); 2083 unsigned NewOffset = Result.getShiftedCodePosition(Offset); 2084 NewReplace = tooling::Replacement(FileName, NewOffset, 0, NewInclude); 2085 Result = Result.merge(tooling::Replacements(NewReplace)); 2086 } 2087 } 2088 return Result; 2089 } 2090 2091 } // anonymous namespace 2092 2093 llvm::Expected<tooling::Replacements> 2094 cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, 2095 const FormatStyle &Style) { 2096 // We need to use lambda function here since there are two versions of 2097 // `cleanup`. 2098 auto Cleanup = [](const FormatStyle &Style, StringRef Code, 2099 std::vector<tooling::Range> Ranges, 2100 StringRef FileName) -> tooling::Replacements { 2101 return cleanup(Style, Code, Ranges, FileName); 2102 }; 2103 // Make header insertion replacements insert new headers into correct blocks. 2104 tooling::Replacements NewReplaces = 2105 fixCppIncludeInsertions(Code, Replaces, Style); 2106 return processReplacements(Cleanup, Code, NewReplaces, Style); 2107 } 2108 2109 namespace internal { 2110 std::pair<tooling::Replacements, unsigned> 2111 reformat(const FormatStyle &Style, StringRef Code, 2112 ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn, 2113 unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName, 2114 FormattingAttemptStatus *Status) { 2115 FormatStyle Expanded = expandPresets(Style); 2116 if (Expanded.DisableFormat) 2117 return {tooling::Replacements(), 0}; 2118 if (isLikelyXml(Code)) 2119 return {tooling::Replacements(), 0}; 2120 if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code)) 2121 return {tooling::Replacements(), 0}; 2122 2123 typedef std::function<std::pair<tooling::Replacements, unsigned>( 2124 const Environment &)> 2125 AnalyzerPass; 2126 SmallVector<AnalyzerPass, 4> Passes; 2127 2128 if (Style.Language == FormatStyle::LK_Cpp) { 2129 if (Style.FixNamespaceComments) 2130 Passes.emplace_back([&](const Environment &Env) { 2131 return NamespaceEndCommentsFixer(Env, Expanded).process(); 2132 }); 2133 2134 if (Style.SortUsingDeclarations) 2135 Passes.emplace_back([&](const Environment &Env) { 2136 return UsingDeclarationsSorter(Env, Expanded).process(); 2137 }); 2138 } 2139 2140 if (Style.Language == FormatStyle::LK_JavaScript && 2141 Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) 2142 Passes.emplace_back([&](const Environment &Env) { 2143 return JavaScriptRequoter(Env, Expanded).process(); 2144 }); 2145 2146 Passes.emplace_back([&](const Environment &Env) { 2147 return Formatter(Env, Expanded, Status).process(); 2148 }); 2149 2150 std::unique_ptr<Environment> Env = Environment::CreateVirtualEnvironment( 2151 Code, FileName, Ranges, FirstStartColumn, NextStartColumn, 2152 LastStartColumn); 2153 llvm::Optional<std::string> CurrentCode = None; 2154 tooling::Replacements Fixes; 2155 unsigned Penalty = 0; 2156 for (size_t I = 0, E = Passes.size(); I < E; ++I) { 2157 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env); 2158 auto NewCode = applyAllReplacements( 2159 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first); 2160 if (NewCode) { 2161 Fixes = Fixes.merge(PassFixes.first); 2162 Penalty += PassFixes.second; 2163 if (I + 1 < E) { 2164 CurrentCode = std::move(*NewCode); 2165 Env = Environment::CreateVirtualEnvironment( 2166 *CurrentCode, FileName, 2167 tooling::calculateRangesAfterReplacements(Fixes, Ranges), 2168 FirstStartColumn, NextStartColumn, LastStartColumn); 2169 } 2170 } 2171 } 2172 2173 return {Fixes, Penalty}; 2174 } 2175 } // namespace internal 2176 2177 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 2178 ArrayRef<tooling::Range> Ranges, 2179 StringRef FileName, 2180 FormattingAttemptStatus *Status) { 2181 return internal::reformat(Style, Code, Ranges, 2182 /*FirstStartColumn=*/0, 2183 /*NextStartColumn=*/0, 2184 /*LastStartColumn=*/0, FileName, Status) 2185 .first; 2186 } 2187 2188 tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, 2189 ArrayRef<tooling::Range> Ranges, 2190 StringRef FileName) { 2191 // cleanups only apply to C++ (they mostly concern ctor commas etc.) 2192 if (Style.Language != FormatStyle::LK_Cpp) 2193 return tooling::Replacements(); 2194 std::unique_ptr<Environment> Env = 2195 Environment::CreateVirtualEnvironment(Code, FileName, Ranges); 2196 Cleaner Clean(*Env, Style); 2197 return Clean.process().first; 2198 } 2199 2200 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 2201 ArrayRef<tooling::Range> Ranges, 2202 StringRef FileName, bool *IncompleteFormat) { 2203 FormattingAttemptStatus Status; 2204 auto Result = reformat(Style, Code, Ranges, FileName, &Status); 2205 if (!Status.FormatComplete) 2206 *IncompleteFormat = true; 2207 return Result; 2208 } 2209 2210 tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, 2211 StringRef Code, 2212 ArrayRef<tooling::Range> Ranges, 2213 StringRef FileName) { 2214 std::unique_ptr<Environment> Env = 2215 Environment::CreateVirtualEnvironment(Code, FileName, Ranges); 2216 NamespaceEndCommentsFixer Fix(*Env, Style); 2217 return Fix.process().first; 2218 } 2219 2220 tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, 2221 StringRef Code, 2222 ArrayRef<tooling::Range> Ranges, 2223 StringRef FileName) { 2224 std::unique_ptr<Environment> Env = 2225 Environment::CreateVirtualEnvironment(Code, FileName, Ranges); 2226 UsingDeclarationsSorter Sorter(*Env, Style); 2227 return Sorter.process().first; 2228 } 2229 2230 LangOptions getFormattingLangOpts(const FormatStyle &Style) { 2231 LangOptions LangOpts; 2232 LangOpts.CPlusPlus = 1; 2233 LangOpts.CPlusPlus11 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1; 2234 LangOpts.CPlusPlus14 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1; 2235 LangOpts.CPlusPlus17 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1; 2236 LangOpts.CPlusPlus2a = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1; 2237 LangOpts.LineComment = 1; 2238 bool AlternativeOperators = Style.isCpp(); 2239 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0; 2240 LangOpts.Bool = 1; 2241 LangOpts.ObjC1 = 1; 2242 LangOpts.ObjC2 = 1; 2243 LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally. 2244 LangOpts.DeclSpecKeyword = 1; // To get __declspec. 2245 return LangOpts; 2246 } 2247 2248 const char *StyleOptionHelpDescription = 2249 "Coding style, currently supports:\n" 2250 " LLVM, Google, Chromium, Mozilla, WebKit.\n" 2251 "Use -style=file to load style configuration from\n" 2252 ".clang-format file located in one of the parent\n" 2253 "directories of the source file (or current\n" 2254 "directory for stdin).\n" 2255 "Use -style=\"{key: value, ...}\" to set specific\n" 2256 "parameters, e.g.:\n" 2257 " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""; 2258 2259 static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) { 2260 if (FileName.endswith(".java")) 2261 return FormatStyle::LK_Java; 2262 if (FileName.endswith_lower(".js") || FileName.endswith_lower(".ts")) 2263 return FormatStyle::LK_JavaScript; // JavaScript or TypeScript. 2264 if (FileName.endswith(".m") || FileName.endswith(".mm")) 2265 return FormatStyle::LK_ObjC; 2266 if (FileName.endswith_lower(".proto") || 2267 FileName.endswith_lower(".protodevel")) 2268 return FormatStyle::LK_Proto; 2269 if (FileName.endswith_lower(".textpb") || 2270 FileName.endswith_lower(".pb.txt") || 2271 FileName.endswith_lower(".textproto") || 2272 FileName.endswith_lower(".asciipb")) 2273 return FormatStyle::LK_TextProto; 2274 if (FileName.endswith_lower(".td")) 2275 return FormatStyle::LK_TableGen; 2276 return FormatStyle::LK_Cpp; 2277 } 2278 2279 llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, 2280 StringRef FallbackStyleName, 2281 StringRef Code, vfs::FileSystem *FS) { 2282 if (!FS) { 2283 FS = vfs::getRealFileSystem().get(); 2284 } 2285 FormatStyle Style = getLLVMStyle(); 2286 Style.Language = getLanguageByFileName(FileName); 2287 2288 if (Style.Language == FormatStyle::LK_Cpp && FileName.endswith(".h")) { 2289 std::unique_ptr<Environment> Env = 2290 Environment::CreateVirtualEnvironment(Code, FileName, /*Ranges=*/{}); 2291 ObjCHeaderStyleGuesser Guesser(*Env, Style); 2292 Guesser.process(); 2293 if (Guesser.isObjC()) { 2294 Style.Language = FormatStyle::LK_ObjC; 2295 } 2296 } 2297 2298 FormatStyle FallbackStyle = getNoStyle(); 2299 if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle)) 2300 return make_string_error("Invalid fallback style \"" + FallbackStyleName); 2301 2302 if (StyleName.startswith("{")) { 2303 // Parse YAML/JSON style from the command line. 2304 if (std::error_code ec = parseConfiguration(StyleName, &Style)) 2305 return make_string_error("Error parsing -style: " + ec.message()); 2306 return Style; 2307 } 2308 2309 if (!StyleName.equals_lower("file")) { 2310 if (!getPredefinedStyle(StyleName, Style.Language, &Style)) 2311 return make_string_error("Invalid value for -style"); 2312 return Style; 2313 } 2314 2315 // Look for .clang-format/_clang-format file in the file's parent directories. 2316 SmallString<128> UnsuitableConfigFiles; 2317 SmallString<128> Path(FileName); 2318 if (std::error_code EC = FS->makeAbsolute(Path)) 2319 return make_string_error(EC.message()); 2320 2321 for (StringRef Directory = Path; !Directory.empty(); 2322 Directory = llvm::sys::path::parent_path(Directory)) { 2323 2324 auto Status = FS->status(Directory); 2325 if (!Status || 2326 Status->getType() != llvm::sys::fs::file_type::directory_file) { 2327 continue; 2328 } 2329 2330 SmallString<128> ConfigFile(Directory); 2331 2332 llvm::sys::path::append(ConfigFile, ".clang-format"); 2333 DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); 2334 2335 Status = FS->status(ConfigFile.str()); 2336 bool FoundConfigFile = 2337 Status && (Status->getType() == llvm::sys::fs::file_type::regular_file); 2338 if (!FoundConfigFile) { 2339 // Try _clang-format too, since dotfiles are not commonly used on Windows. 2340 ConfigFile = Directory; 2341 llvm::sys::path::append(ConfigFile, "_clang-format"); 2342 DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); 2343 Status = FS->status(ConfigFile.str()); 2344 FoundConfigFile = Status && (Status->getType() == 2345 llvm::sys::fs::file_type::regular_file); 2346 } 2347 2348 if (FoundConfigFile) { 2349 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 2350 FS->getBufferForFile(ConfigFile.str()); 2351 if (std::error_code EC = Text.getError()) 2352 return make_string_error(EC.message()); 2353 if (std::error_code ec = 2354 parseConfiguration(Text.get()->getBuffer(), &Style)) { 2355 if (ec == ParseError::Unsuitable) { 2356 if (!UnsuitableConfigFiles.empty()) 2357 UnsuitableConfigFiles.append(", "); 2358 UnsuitableConfigFiles.append(ConfigFile); 2359 continue; 2360 } 2361 return make_string_error("Error reading " + ConfigFile + ": " + 2362 ec.message()); 2363 } 2364 DEBUG(llvm::dbgs() << "Using configuration file " << ConfigFile << "\n"); 2365 return Style; 2366 } 2367 } 2368 if (!UnsuitableConfigFiles.empty()) 2369 return make_string_error("Configuration file(s) do(es) not support " + 2370 getLanguageName(Style.Language) + ": " + 2371 UnsuitableConfigFiles); 2372 return FallbackStyle; 2373 } 2374 2375 } // namespace format 2376 } // namespace clang 2377