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