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 // "Regroup" doesn't work well for ObjC yet (main header heuristic, 881 // relationship between ObjC standard library headers and other heades, 882 // #imports, etc.) 883 GoogleStyle.IncludeStyle.IncludeBlocks = 884 tooling::IncludeStyle::IBS_Preserve; 885 } 886 887 return GoogleStyle; 888 } 889 890 FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) { 891 FormatStyle ChromiumStyle = getGoogleStyle(Language); 892 if (Language == FormatStyle::LK_Java) { 893 ChromiumStyle.AllowShortIfStatementsOnASingleLine = 894 FormatStyle::SIS_WithoutElse; 895 ChromiumStyle.BreakAfterJavaFieldAnnotations = true; 896 ChromiumStyle.ContinuationIndentWidth = 8; 897 ChromiumStyle.IndentWidth = 4; 898 // See styleguide for import groups: 899 // https://chromium.googlesource.com/chromium/src/+/master/styleguide/java/java.md#Import-Order 900 ChromiumStyle.JavaImportGroups = { 901 "android", 902 "androidx", 903 "com", 904 "dalvik", 905 "junit", 906 "org", 907 "com.google.android.apps.chrome", 908 "org.chromium", 909 "java", 910 "javax", 911 }; 912 ChromiumStyle.SortIncludes = true; 913 } else if (Language == FormatStyle::LK_JavaScript) { 914 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 915 ChromiumStyle.AllowShortLoopsOnASingleLine = false; 916 } else { 917 ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false; 918 ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 919 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 920 ChromiumStyle.AllowShortLoopsOnASingleLine = false; 921 ChromiumStyle.BinPackParameters = false; 922 ChromiumStyle.DerivePointerAlignment = false; 923 if (Language == FormatStyle::LK_ObjC) 924 ChromiumStyle.ColumnLimit = 80; 925 } 926 return ChromiumStyle; 927 } 928 929 FormatStyle getMozillaStyle() { 930 FormatStyle MozillaStyle = getLLVMStyle(); 931 MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false; 932 MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 933 MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel; 934 MozillaStyle.AlwaysBreakAfterDefinitionReturnType = 935 FormatStyle::DRTBS_TopLevel; 936 MozillaStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; 937 MozillaStyle.BinPackParameters = false; 938 MozillaStyle.BinPackArguments = false; 939 MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla; 940 MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 941 MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma; 942 MozillaStyle.ConstructorInitializerIndentWidth = 2; 943 MozillaStyle.ContinuationIndentWidth = 2; 944 MozillaStyle.Cpp11BracedListStyle = false; 945 MozillaStyle.FixNamespaceComments = false; 946 MozillaStyle.IndentCaseLabels = true; 947 MozillaStyle.ObjCSpaceAfterProperty = true; 948 MozillaStyle.ObjCSpaceBeforeProtocolList = false; 949 MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200; 950 MozillaStyle.PointerAlignment = FormatStyle::PAS_Left; 951 MozillaStyle.SpaceAfterTemplateKeyword = false; 952 return MozillaStyle; 953 } 954 955 FormatStyle getWebKitStyle() { 956 FormatStyle Style = getLLVMStyle(); 957 Style.AccessModifierOffset = -4; 958 Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; 959 Style.AlignOperands = false; 960 Style.AlignTrailingComments = false; 961 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 962 Style.BreakBeforeBraces = FormatStyle::BS_WebKit; 963 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; 964 Style.Cpp11BracedListStyle = false; 965 Style.ColumnLimit = 0; 966 Style.FixNamespaceComments = false; 967 Style.IndentWidth = 4; 968 Style.NamespaceIndentation = FormatStyle::NI_Inner; 969 Style.ObjCBlockIndentWidth = 4; 970 Style.ObjCSpaceAfterProperty = true; 971 Style.PointerAlignment = FormatStyle::PAS_Left; 972 Style.SpaceBeforeCpp11BracedList = true; 973 return Style; 974 } 975 976 FormatStyle getGNUStyle() { 977 FormatStyle Style = getLLVMStyle(); 978 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; 979 Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; 980 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 981 Style.BreakBeforeBraces = FormatStyle::BS_GNU; 982 Style.BreakBeforeTernaryOperators = true; 983 Style.Cpp11BracedListStyle = false; 984 Style.ColumnLimit = 79; 985 Style.FixNamespaceComments = false; 986 Style.SpaceBeforeParens = FormatStyle::SBPO_Always; 987 Style.Standard = FormatStyle::LS_Cpp03; 988 return Style; 989 } 990 991 FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) { 992 FormatStyle Style = getLLVMStyle(); 993 Style.ColumnLimit = 120; 994 Style.TabWidth = 4; 995 Style.IndentWidth = 4; 996 Style.UseTab = FormatStyle::UT_Never; 997 Style.BreakBeforeBraces = FormatStyle::BS_Custom; 998 Style.BraceWrapping.AfterClass = true; 999 Style.BraceWrapping.AfterControlStatement = true; 1000 Style.BraceWrapping.AfterEnum = true; 1001 Style.BraceWrapping.AfterFunction = true; 1002 Style.BraceWrapping.AfterNamespace = true; 1003 Style.BraceWrapping.AfterObjCDeclaration = true; 1004 Style.BraceWrapping.AfterStruct = true; 1005 Style.BraceWrapping.AfterExternBlock = true; 1006 Style.BraceWrapping.BeforeCatch = true; 1007 Style.BraceWrapping.BeforeElse = true; 1008 Style.PenaltyReturnTypeOnItsOwnLine = 1000; 1009 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; 1010 Style.AllowShortBlocksOnASingleLine = false; 1011 Style.AllowShortCaseLabelsOnASingleLine = false; 1012 Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never; 1013 Style.AllowShortLoopsOnASingleLine = false; 1014 return Style; 1015 } 1016 1017 FormatStyle getNoStyle() { 1018 FormatStyle NoStyle = getLLVMStyle(); 1019 NoStyle.DisableFormat = true; 1020 NoStyle.SortIncludes = false; 1021 NoStyle.SortUsingDeclarations = false; 1022 return NoStyle; 1023 } 1024 1025 bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language, 1026 FormatStyle *Style) { 1027 if (Name.equals_lower("llvm")) { 1028 *Style = getLLVMStyle(Language); 1029 } else if (Name.equals_lower("chromium")) { 1030 *Style = getChromiumStyle(Language); 1031 } else if (Name.equals_lower("mozilla")) { 1032 *Style = getMozillaStyle(); 1033 } else if (Name.equals_lower("google")) { 1034 *Style = getGoogleStyle(Language); 1035 } else if (Name.equals_lower("webkit")) { 1036 *Style = getWebKitStyle(); 1037 } else if (Name.equals_lower("gnu")) { 1038 *Style = getGNUStyle(); 1039 } else if (Name.equals_lower("microsoft")) { 1040 *Style = getMicrosoftStyle(Language); 1041 } else if (Name.equals_lower("none")) { 1042 *Style = getNoStyle(); 1043 } else { 1044 return false; 1045 } 1046 1047 Style->Language = Language; 1048 return true; 1049 } 1050 1051 std::error_code parseConfiguration(StringRef Text, FormatStyle *Style) { 1052 assert(Style); 1053 FormatStyle::LanguageKind Language = Style->Language; 1054 assert(Language != FormatStyle::LK_None); 1055 if (Text.trim().empty()) 1056 return make_error_code(ParseError::Error); 1057 Style->StyleSet.Clear(); 1058 std::vector<FormatStyle> Styles; 1059 llvm::yaml::Input Input(Text); 1060 // DocumentListTraits<vector<FormatStyle>> uses the context to get default 1061 // values for the fields, keys for which are missing from the configuration. 1062 // Mapping also uses the context to get the language to find the correct 1063 // base style. 1064 Input.setContext(Style); 1065 Input >> Styles; 1066 if (Input.error()) 1067 return Input.error(); 1068 1069 for (unsigned i = 0; i < Styles.size(); ++i) { 1070 // Ensures that only the first configuration can skip the Language option. 1071 if (Styles[i].Language == FormatStyle::LK_None && i != 0) 1072 return make_error_code(ParseError::Error); 1073 // Ensure that each language is configured at most once. 1074 for (unsigned j = 0; j < i; ++j) { 1075 if (Styles[i].Language == Styles[j].Language) { 1076 LLVM_DEBUG(llvm::dbgs() 1077 << "Duplicate languages in the config file on positions " 1078 << j << " and " << i << "\n"); 1079 return make_error_code(ParseError::Error); 1080 } 1081 } 1082 } 1083 // Look for a suitable configuration starting from the end, so we can 1084 // find the configuration for the specific language first, and the default 1085 // configuration (which can only be at slot 0) after it. 1086 FormatStyle::FormatStyleSet StyleSet; 1087 bool LanguageFound = false; 1088 for (int i = Styles.size() - 1; i >= 0; --i) { 1089 if (Styles[i].Language != FormatStyle::LK_None) 1090 StyleSet.Add(Styles[i]); 1091 if (Styles[i].Language == Language) 1092 LanguageFound = true; 1093 } 1094 if (!LanguageFound) { 1095 if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None) 1096 return make_error_code(ParseError::Unsuitable); 1097 FormatStyle DefaultStyle = Styles[0]; 1098 DefaultStyle.Language = Language; 1099 StyleSet.Add(std::move(DefaultStyle)); 1100 } 1101 *Style = *StyleSet.Get(Language); 1102 return make_error_code(ParseError::Success); 1103 } 1104 1105 std::string configurationAsText(const FormatStyle &Style) { 1106 std::string Text; 1107 llvm::raw_string_ostream Stream(Text); 1108 llvm::yaml::Output Output(Stream); 1109 // We use the same mapping method for input and output, so we need a non-const 1110 // reference here. 1111 FormatStyle NonConstStyle = expandPresets(Style); 1112 Output << NonConstStyle; 1113 return Stream.str(); 1114 } 1115 1116 llvm::Optional<FormatStyle> 1117 FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const { 1118 if (!Styles) 1119 return None; 1120 auto It = Styles->find(Language); 1121 if (It == Styles->end()) 1122 return None; 1123 FormatStyle Style = It->second; 1124 Style.StyleSet = *this; 1125 return Style; 1126 } 1127 1128 void FormatStyle::FormatStyleSet::Add(FormatStyle Style) { 1129 assert(Style.Language != LK_None && 1130 "Cannot add a style for LK_None to a StyleSet"); 1131 assert( 1132 !Style.StyleSet.Styles && 1133 "Cannot add a style associated with an existing StyleSet to a StyleSet"); 1134 if (!Styles) 1135 Styles = std::make_shared<MapType>(); 1136 (*Styles)[Style.Language] = std::move(Style); 1137 } 1138 1139 void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); } 1140 1141 llvm::Optional<FormatStyle> 1142 FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const { 1143 return StyleSet.Get(Language); 1144 } 1145 1146 namespace { 1147 1148 class JavaScriptRequoter : public TokenAnalyzer { 1149 public: 1150 JavaScriptRequoter(const Environment &Env, const FormatStyle &Style) 1151 : TokenAnalyzer(Env, Style) {} 1152 1153 std::pair<tooling::Replacements, unsigned> 1154 analyze(TokenAnnotator &Annotator, 1155 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1156 FormatTokenLexer &Tokens) override { 1157 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 1158 tooling::Replacements Result; 1159 requoteJSStringLiteral(AnnotatedLines, Result); 1160 return {Result, 0}; 1161 } 1162 1163 private: 1164 // Replaces double/single-quoted string literal as appropriate, re-escaping 1165 // the contents in the process. 1166 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines, 1167 tooling::Replacements &Result) { 1168 for (AnnotatedLine *Line : Lines) { 1169 requoteJSStringLiteral(Line->Children, Result); 1170 if (!Line->Affected) 1171 continue; 1172 for (FormatToken *FormatTok = Line->First; FormatTok; 1173 FormatTok = FormatTok->Next) { 1174 StringRef Input = FormatTok->TokenText; 1175 if (FormatTok->Finalized || !FormatTok->isStringLiteral() || 1176 // NB: testing for not starting with a double quote to avoid 1177 // breaking `template strings`. 1178 (Style.JavaScriptQuotes == FormatStyle::JSQS_Single && 1179 !Input.startswith("\"")) || 1180 (Style.JavaScriptQuotes == FormatStyle::JSQS_Double && 1181 !Input.startswith("\'"))) 1182 continue; 1183 1184 // Change start and end quote. 1185 bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single; 1186 SourceLocation Start = FormatTok->Tok.getLocation(); 1187 auto Replace = [&](SourceLocation Start, unsigned Length, 1188 StringRef ReplacementText) { 1189 auto Err = Result.add(tooling::Replacement( 1190 Env.getSourceManager(), Start, Length, ReplacementText)); 1191 // FIXME: handle error. For now, print error message and skip the 1192 // replacement for release version. 1193 if (Err) { 1194 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 1195 assert(false); 1196 } 1197 }; 1198 Replace(Start, 1, IsSingle ? "'" : "\""); 1199 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1, 1200 IsSingle ? "'" : "\""); 1201 1202 // Escape internal quotes. 1203 bool Escaped = false; 1204 for (size_t i = 1; i < Input.size() - 1; i++) { 1205 switch (Input[i]) { 1206 case '\\': 1207 if (!Escaped && i + 1 < Input.size() && 1208 ((IsSingle && Input[i + 1] == '"') || 1209 (!IsSingle && Input[i + 1] == '\''))) { 1210 // Remove this \, it's escaping a " or ' that no longer needs 1211 // escaping 1212 Replace(Start.getLocWithOffset(i), 1, ""); 1213 continue; 1214 } 1215 Escaped = !Escaped; 1216 break; 1217 case '\"': 1218 case '\'': 1219 if (!Escaped && IsSingle == (Input[i] == '\'')) { 1220 // Escape the quote. 1221 Replace(Start.getLocWithOffset(i), 0, "\\"); 1222 } 1223 Escaped = false; 1224 break; 1225 default: 1226 Escaped = false; 1227 break; 1228 } 1229 } 1230 } 1231 } 1232 } 1233 }; 1234 1235 class Formatter : public TokenAnalyzer { 1236 public: 1237 Formatter(const Environment &Env, const FormatStyle &Style, 1238 FormattingAttemptStatus *Status) 1239 : TokenAnalyzer(Env, Style), Status(Status) {} 1240 1241 std::pair<tooling::Replacements, unsigned> 1242 analyze(TokenAnnotator &Annotator, 1243 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1244 FormatTokenLexer &Tokens) override { 1245 tooling::Replacements Result; 1246 deriveLocalStyle(AnnotatedLines); 1247 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 1248 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1249 Annotator.calculateFormattingInformation(*AnnotatedLines[i]); 1250 } 1251 Annotator.setCommentLineLevels(AnnotatedLines); 1252 1253 WhitespaceManager Whitespaces( 1254 Env.getSourceManager(), Style, 1255 inputUsesCRLF(Env.getSourceManager().getBufferData(Env.getFileID()))); 1256 ContinuationIndenter Indenter(Style, Tokens.getKeywords(), 1257 Env.getSourceManager(), Whitespaces, Encoding, 1258 BinPackInconclusiveFunctions); 1259 unsigned Penalty = 1260 UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, 1261 Tokens.getKeywords(), Env.getSourceManager(), 1262 Status) 1263 .format(AnnotatedLines, /*DryRun=*/false, 1264 /*AdditionalIndent=*/0, 1265 /*FixBadIndentation=*/false, 1266 /*FirstStartColumn=*/Env.getFirstStartColumn(), 1267 /*NextStartColumn=*/Env.getNextStartColumn(), 1268 /*LastStartColumn=*/Env.getLastStartColumn()); 1269 for (const auto &R : Whitespaces.generateReplacements()) 1270 if (Result.add(R)) 1271 return std::make_pair(Result, 0); 1272 return std::make_pair(Result, Penalty); 1273 } 1274 1275 private: 1276 static bool inputUsesCRLF(StringRef Text) { 1277 return Text.count('\r') * 2 > Text.count('\n'); 1278 } 1279 1280 bool 1281 hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) { 1282 for (const AnnotatedLine *Line : Lines) { 1283 if (hasCpp03IncompatibleFormat(Line->Children)) 1284 return true; 1285 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) { 1286 if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) { 1287 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener)) 1288 return true; 1289 if (Tok->is(TT_TemplateCloser) && 1290 Tok->Previous->is(TT_TemplateCloser)) 1291 return true; 1292 } 1293 } 1294 } 1295 return false; 1296 } 1297 1298 int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) { 1299 int AlignmentDiff = 0; 1300 for (const AnnotatedLine *Line : Lines) { 1301 AlignmentDiff += countVariableAlignments(Line->Children); 1302 for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) { 1303 if (!Tok->is(TT_PointerOrReference)) 1304 continue; 1305 bool SpaceBefore = 1306 Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd(); 1307 bool SpaceAfter = Tok->Next->WhitespaceRange.getBegin() != 1308 Tok->Next->WhitespaceRange.getEnd(); 1309 if (SpaceBefore && !SpaceAfter) 1310 ++AlignmentDiff; 1311 if (!SpaceBefore && SpaceAfter) 1312 --AlignmentDiff; 1313 } 1314 } 1315 return AlignmentDiff; 1316 } 1317 1318 void 1319 deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 1320 bool HasBinPackedFunction = false; 1321 bool HasOnePerLineFunction = false; 1322 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1323 if (!AnnotatedLines[i]->First->Next) 1324 continue; 1325 FormatToken *Tok = AnnotatedLines[i]->First->Next; 1326 while (Tok->Next) { 1327 if (Tok->PackingKind == PPK_BinPacked) 1328 HasBinPackedFunction = true; 1329 if (Tok->PackingKind == PPK_OnePerLine) 1330 HasOnePerLineFunction = true; 1331 1332 Tok = Tok->Next; 1333 } 1334 } 1335 if (Style.DerivePointerAlignment) 1336 Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0 1337 ? FormatStyle::PAS_Left 1338 : FormatStyle::PAS_Right; 1339 if (Style.Standard == FormatStyle::LS_Auto) 1340 Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines) 1341 ? FormatStyle::LS_Cpp11 1342 : FormatStyle::LS_Cpp03; 1343 BinPackInconclusiveFunctions = 1344 HasBinPackedFunction || !HasOnePerLineFunction; 1345 } 1346 1347 bool BinPackInconclusiveFunctions; 1348 FormattingAttemptStatus *Status; 1349 }; 1350 1351 // This class clean up the erroneous/redundant code around the given ranges in 1352 // file. 1353 class Cleaner : public TokenAnalyzer { 1354 public: 1355 Cleaner(const Environment &Env, const FormatStyle &Style) 1356 : TokenAnalyzer(Env, Style), 1357 DeletedTokens(FormatTokenLess(Env.getSourceManager())) {} 1358 1359 // FIXME: eliminate unused parameters. 1360 std::pair<tooling::Replacements, unsigned> 1361 analyze(TokenAnnotator &Annotator, 1362 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1363 FormatTokenLexer &Tokens) override { 1364 // FIXME: in the current implementation the granularity of affected range 1365 // is an annotated line. However, this is not sufficient. Furthermore, 1366 // redundant code introduced by replacements does not necessarily 1367 // intercept with ranges of replacements that result in the redundancy. 1368 // To determine if some redundant code is actually introduced by 1369 // replacements(e.g. deletions), we need to come up with a more 1370 // sophisticated way of computing affected ranges. 1371 AffectedRangeMgr.computeAffectedLines(AnnotatedLines); 1372 1373 checkEmptyNamespace(AnnotatedLines); 1374 1375 for (auto &Line : AnnotatedLines) { 1376 if (Line->Affected) { 1377 cleanupRight(Line->First, tok::comma, tok::comma); 1378 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma); 1379 cleanupRight(Line->First, tok::l_paren, tok::comma); 1380 cleanupLeft(Line->First, tok::comma, tok::r_paren); 1381 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace); 1382 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace); 1383 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal); 1384 } 1385 } 1386 1387 return {generateFixes(), 0}; 1388 } 1389 1390 private: 1391 bool containsOnlyComments(const AnnotatedLine &Line) { 1392 for (FormatToken *Tok = Line.First; Tok != nullptr; Tok = Tok->Next) { 1393 if (Tok->isNot(tok::comment)) 1394 return false; 1395 } 1396 return true; 1397 } 1398 1399 // Iterate through all lines and remove any empty (nested) namespaces. 1400 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 1401 std::set<unsigned> DeletedLines; 1402 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1403 auto &Line = *AnnotatedLines[i]; 1404 if (Line.startsWithNamespace()) { 1405 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines); 1406 } 1407 } 1408 1409 for (auto Line : DeletedLines) { 1410 FormatToken *Tok = AnnotatedLines[Line]->First; 1411 while (Tok) { 1412 deleteToken(Tok); 1413 Tok = Tok->Next; 1414 } 1415 } 1416 } 1417 1418 // The function checks if the namespace, which starts from \p CurrentLine, and 1419 // its nested namespaces are empty and delete them if they are empty. It also 1420 // sets \p NewLine to the last line checked. 1421 // Returns true if the current namespace is empty. 1422 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1423 unsigned CurrentLine, unsigned &NewLine, 1424 std::set<unsigned> &DeletedLines) { 1425 unsigned InitLine = CurrentLine, End = AnnotatedLines.size(); 1426 if (Style.BraceWrapping.AfterNamespace) { 1427 // If the left brace is in a new line, we should consume it first so that 1428 // it does not make the namespace non-empty. 1429 // FIXME: error handling if there is no left brace. 1430 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) { 1431 NewLine = CurrentLine; 1432 return false; 1433 } 1434 } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) { 1435 return false; 1436 } 1437 while (++CurrentLine < End) { 1438 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace)) 1439 break; 1440 1441 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) { 1442 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine, 1443 DeletedLines)) 1444 return false; 1445 CurrentLine = NewLine; 1446 continue; 1447 } 1448 1449 if (containsOnlyComments(*AnnotatedLines[CurrentLine])) 1450 continue; 1451 1452 // If there is anything other than comments or nested namespaces in the 1453 // current namespace, the namespace cannot be empty. 1454 NewLine = CurrentLine; 1455 return false; 1456 } 1457 1458 NewLine = CurrentLine; 1459 if (CurrentLine >= End) 1460 return false; 1461 1462 // Check if the empty namespace is actually affected by changed ranges. 1463 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange( 1464 AnnotatedLines[InitLine]->First->Tok.getLocation(), 1465 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) 1466 return false; 1467 1468 for (unsigned i = InitLine; i <= CurrentLine; ++i) { 1469 DeletedLines.insert(i); 1470 } 1471 1472 return true; 1473 } 1474 1475 // Checks pairs {start, start->next},..., {end->previous, end} and deletes one 1476 // of the token in the pair if the left token has \p LK token kind and the 1477 // right token has \p RK token kind. If \p DeleteLeft is true, the left token 1478 // is deleted on match; otherwise, the right token is deleted. 1479 template <typename LeftKind, typename RightKind> 1480 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK, 1481 bool DeleteLeft) { 1482 auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * { 1483 for (auto *Res = Tok.Next; Res; Res = Res->Next) 1484 if (!Res->is(tok::comment) && 1485 DeletedTokens.find(Res) == DeletedTokens.end()) 1486 return Res; 1487 return nullptr; 1488 }; 1489 for (auto *Left = Start; Left;) { 1490 auto *Right = NextNotDeleted(*Left); 1491 if (!Right) 1492 break; 1493 if (Left->is(LK) && Right->is(RK)) { 1494 deleteToken(DeleteLeft ? Left : Right); 1495 for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next) 1496 deleteToken(Tok); 1497 // If the right token is deleted, we should keep the left token 1498 // unchanged and pair it with the new right token. 1499 if (!DeleteLeft) 1500 continue; 1501 } 1502 Left = Right; 1503 } 1504 } 1505 1506 template <typename LeftKind, typename RightKind> 1507 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) { 1508 cleanupPair(Start, LK, RK, /*DeleteLeft=*/true); 1509 } 1510 1511 template <typename LeftKind, typename RightKind> 1512 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) { 1513 cleanupPair(Start, LK, RK, /*DeleteLeft=*/false); 1514 } 1515 1516 // Delete the given token. 1517 inline void deleteToken(FormatToken *Tok) { 1518 if (Tok) 1519 DeletedTokens.insert(Tok); 1520 } 1521 1522 tooling::Replacements generateFixes() { 1523 tooling::Replacements Fixes; 1524 std::vector<FormatToken *> Tokens; 1525 std::copy(DeletedTokens.begin(), DeletedTokens.end(), 1526 std::back_inserter(Tokens)); 1527 1528 // Merge multiple continuous token deletions into one big deletion so that 1529 // the number of replacements can be reduced. This makes computing affected 1530 // ranges more efficient when we run reformat on the changed code. 1531 unsigned Idx = 0; 1532 while (Idx < Tokens.size()) { 1533 unsigned St = Idx, End = Idx; 1534 while ((End + 1) < Tokens.size() && 1535 Tokens[End]->Next == Tokens[End + 1]) { 1536 End++; 1537 } 1538 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(), 1539 Tokens[End]->Tok.getEndLoc()); 1540 auto Err = 1541 Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, "")); 1542 // FIXME: better error handling. for now just print error message and skip 1543 // for the release version. 1544 if (Err) { 1545 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 1546 assert(false && "Fixes must not conflict!"); 1547 } 1548 Idx = End + 1; 1549 } 1550 1551 return Fixes; 1552 } 1553 1554 // Class for less-than inequality comparason for the set `RedundantTokens`. 1555 // We store tokens in the order they appear in the translation unit so that 1556 // we do not need to sort them in `generateFixes()`. 1557 struct FormatTokenLess { 1558 FormatTokenLess(const SourceManager &SM) : SM(SM) {} 1559 1560 bool operator()(const FormatToken *LHS, const FormatToken *RHS) const { 1561 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(), 1562 RHS->Tok.getLocation()); 1563 } 1564 const SourceManager &SM; 1565 }; 1566 1567 // Tokens to be deleted. 1568 std::set<FormatToken *, FormatTokenLess> DeletedTokens; 1569 }; 1570 1571 class ObjCHeaderStyleGuesser : public TokenAnalyzer { 1572 public: 1573 ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style) 1574 : TokenAnalyzer(Env, Style), IsObjC(false) {} 1575 1576 std::pair<tooling::Replacements, unsigned> 1577 analyze(TokenAnnotator &Annotator, 1578 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1579 FormatTokenLexer &Tokens) override { 1580 assert(Style.Language == FormatStyle::LK_Cpp); 1581 IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines, 1582 Tokens.getKeywords()); 1583 tooling::Replacements Result; 1584 return {Result, 0}; 1585 } 1586 1587 bool isObjC() { return IsObjC; } 1588 1589 private: 1590 static bool 1591 guessIsObjC(const SourceManager &SourceManager, 1592 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1593 const AdditionalKeywords &Keywords) { 1594 // Keep this array sorted, since we are binary searching over it. 1595 static constexpr llvm::StringLiteral FoundationIdentifiers[] = { 1596 "CGFloat", 1597 "CGPoint", 1598 "CGPointMake", 1599 "CGPointZero", 1600 "CGRect", 1601 "CGRectEdge", 1602 "CGRectInfinite", 1603 "CGRectMake", 1604 "CGRectNull", 1605 "CGRectZero", 1606 "CGSize", 1607 "CGSizeMake", 1608 "CGVector", 1609 "CGVectorMake", 1610 "NSAffineTransform", 1611 "NSArray", 1612 "NSAttributedString", 1613 "NSBlockOperation", 1614 "NSBundle", 1615 "NSCache", 1616 "NSCalendar", 1617 "NSCharacterSet", 1618 "NSCountedSet", 1619 "NSData", 1620 "NSDataDetector", 1621 "NSDecimal", 1622 "NSDecimalNumber", 1623 "NSDictionary", 1624 "NSEdgeInsets", 1625 "NSHashTable", 1626 "NSIndexPath", 1627 "NSIndexSet", 1628 "NSInteger", 1629 "NSInvocationOperation", 1630 "NSLocale", 1631 "NSMapTable", 1632 "NSMutableArray", 1633 "NSMutableAttributedString", 1634 "NSMutableCharacterSet", 1635 "NSMutableData", 1636 "NSMutableDictionary", 1637 "NSMutableIndexSet", 1638 "NSMutableOrderedSet", 1639 "NSMutableSet", 1640 "NSMutableString", 1641 "NSNumber", 1642 "NSNumberFormatter", 1643 "NSObject", 1644 "NSOperation", 1645 "NSOperationQueue", 1646 "NSOperationQueuePriority", 1647 "NSOrderedSet", 1648 "NSPoint", 1649 "NSPointerArray", 1650 "NSQualityOfService", 1651 "NSRange", 1652 "NSRect", 1653 "NSRegularExpression", 1654 "NSSet", 1655 "NSSize", 1656 "NSString", 1657 "NSTimeZone", 1658 "NSUInteger", 1659 "NSURL", 1660 "NSURLComponents", 1661 "NSURLQueryItem", 1662 "NSUUID", 1663 "NSValue", 1664 "UIImage", 1665 "UIView", 1666 }; 1667 1668 for (auto Line : AnnotatedLines) { 1669 for (const FormatToken *FormatTok = Line->First; FormatTok; 1670 FormatTok = FormatTok->Next) { 1671 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) && 1672 (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword || 1673 FormatTok->isOneOf(tok::numeric_constant, tok::l_square, 1674 tok::l_brace))) || 1675 (FormatTok->Tok.isAnyIdentifier() && 1676 std::binary_search(std::begin(FoundationIdentifiers), 1677 std::end(FoundationIdentifiers), 1678 FormatTok->TokenText)) || 1679 FormatTok->is(TT_ObjCStringLiteral) || 1680 FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS, 1681 TT_ObjCBlockLBrace, TT_ObjCBlockLParen, 1682 TT_ObjCDecl, TT_ObjCForIn, TT_ObjCMethodExpr, 1683 TT_ObjCMethodSpecifier, TT_ObjCProperty)) { 1684 LLVM_DEBUG(llvm::dbgs() 1685 << "Detected ObjC at location " 1686 << FormatTok->Tok.getLocation().printToString( 1687 SourceManager) 1688 << " token: " << FormatTok->TokenText << " token type: " 1689 << getTokenTypeName(FormatTok->Type) << "\n"); 1690 return true; 1691 } 1692 if (guessIsObjC(SourceManager, Line->Children, Keywords)) 1693 return true; 1694 } 1695 } 1696 return false; 1697 } 1698 1699 bool IsObjC; 1700 }; 1701 1702 struct IncludeDirective { 1703 StringRef Filename; 1704 StringRef Text; 1705 unsigned Offset; 1706 int Category; 1707 }; 1708 1709 struct JavaImportDirective { 1710 StringRef Identifier; 1711 StringRef Text; 1712 unsigned Offset; 1713 std::vector<StringRef> AssociatedCommentLines; 1714 bool IsStatic; 1715 }; 1716 1717 } // end anonymous namespace 1718 1719 // Determines whether 'Ranges' intersects with ('Start', 'End'). 1720 static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start, 1721 unsigned End) { 1722 for (auto Range : Ranges) { 1723 if (Range.getOffset() < End && 1724 Range.getOffset() + Range.getLength() > Start) 1725 return true; 1726 } 1727 return false; 1728 } 1729 1730 // Returns a pair (Index, OffsetToEOL) describing the position of the cursor 1731 // before sorting/deduplicating. Index is the index of the include under the 1732 // cursor in the original set of includes. If this include has duplicates, it is 1733 // the index of the first of the duplicates as the others are going to be 1734 // removed. OffsetToEOL describes the cursor's position relative to the end of 1735 // its current line. 1736 // If `Cursor` is not on any #include, `Index` will be UINT_MAX. 1737 static std::pair<unsigned, unsigned> 1738 FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes, 1739 const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) { 1740 unsigned CursorIndex = UINT_MAX; 1741 unsigned OffsetToEOL = 0; 1742 for (int i = 0, e = Includes.size(); i != e; ++i) { 1743 unsigned Start = Includes[Indices[i]].Offset; 1744 unsigned End = Start + Includes[Indices[i]].Text.size(); 1745 if (!(Cursor >= Start && Cursor < End)) 1746 continue; 1747 CursorIndex = Indices[i]; 1748 OffsetToEOL = End - Cursor; 1749 // Put the cursor on the only remaining #include among the duplicate 1750 // #includes. 1751 while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text) 1752 CursorIndex = i; 1753 break; 1754 } 1755 return std::make_pair(CursorIndex, OffsetToEOL); 1756 } 1757 1758 // Sorts and deduplicate a block of includes given by 'Includes' alphabetically 1759 // adding the necessary replacement to 'Replaces'. 'Includes' must be in strict 1760 // source order. 1761 // #include directives with the same text will be deduplicated, and only the 1762 // first #include in the duplicate #includes remains. If the `Cursor` is 1763 // provided and put on a deleted #include, it will be moved to the remaining 1764 // #include in the duplicate #includes. 1765 static void sortCppIncludes(const FormatStyle &Style, 1766 const SmallVectorImpl<IncludeDirective> &Includes, 1767 ArrayRef<tooling::Range> Ranges, StringRef FileName, 1768 StringRef Code, 1769 tooling::Replacements &Replaces, unsigned *Cursor) { 1770 unsigned IncludesBeginOffset = Includes.front().Offset; 1771 unsigned IncludesEndOffset = 1772 Includes.back().Offset + Includes.back().Text.size(); 1773 unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset; 1774 if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset)) 1775 return; 1776 SmallVector<unsigned, 16> Indices; 1777 for (unsigned i = 0, e = Includes.size(); i != e; ++i) 1778 Indices.push_back(i); 1779 std::stable_sort( 1780 Indices.begin(), Indices.end(), [&](unsigned LHSI, unsigned RHSI) { 1781 return std::tie(Includes[LHSI].Category, Includes[LHSI].Filename) < 1782 std::tie(Includes[RHSI].Category, Includes[RHSI].Filename); 1783 }); 1784 // The index of the include on which the cursor will be put after 1785 // sorting/deduplicating. 1786 unsigned CursorIndex; 1787 // The offset from cursor to the end of line. 1788 unsigned CursorToEOLOffset; 1789 if (Cursor) 1790 std::tie(CursorIndex, CursorToEOLOffset) = 1791 FindCursorIndex(Includes, Indices, *Cursor); 1792 1793 // Deduplicate #includes. 1794 Indices.erase(std::unique(Indices.begin(), Indices.end(), 1795 [&](unsigned LHSI, unsigned RHSI) { 1796 return Includes[LHSI].Text == Includes[RHSI].Text; 1797 }), 1798 Indices.end()); 1799 1800 int CurrentCategory = Includes.front().Category; 1801 1802 // If the #includes are out of order, we generate a single replacement fixing 1803 // the entire block. Otherwise, no replacement is generated. 1804 // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not 1805 // enough as additional newlines might be added or removed across #include 1806 // blocks. This we handle below by generating the updated #imclude blocks and 1807 // comparing it to the original. 1808 if (Indices.size() == Includes.size() && 1809 std::is_sorted(Indices.begin(), Indices.end()) && 1810 Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) 1811 return; 1812 1813 std::string result; 1814 for (unsigned Index : Indices) { 1815 if (!result.empty()) { 1816 result += "\n"; 1817 if (Style.IncludeStyle.IncludeBlocks == 1818 tooling::IncludeStyle::IBS_Regroup && 1819 CurrentCategory != Includes[Index].Category) 1820 result += "\n"; 1821 } 1822 result += Includes[Index].Text; 1823 if (Cursor && CursorIndex == Index) 1824 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset; 1825 CurrentCategory = Includes[Index].Category; 1826 } 1827 1828 // If the #includes are out of order, we generate a single replacement fixing 1829 // the entire range of blocks. Otherwise, no replacement is generated. 1830 if (result == Code.substr(IncludesBeginOffset, IncludesBlockSize)) 1831 return; 1832 1833 auto Err = Replaces.add(tooling::Replacement( 1834 FileName, Includes.front().Offset, IncludesBlockSize, result)); 1835 // FIXME: better error handling. For now, just skip the replacement for the 1836 // release version. 1837 if (Err) { 1838 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 1839 assert(false); 1840 } 1841 } 1842 1843 namespace { 1844 1845 const char CppIncludeRegexPattern[] = 1846 R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))"; 1847 1848 } // anonymous namespace 1849 1850 tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code, 1851 ArrayRef<tooling::Range> Ranges, 1852 StringRef FileName, 1853 tooling::Replacements &Replaces, 1854 unsigned *Cursor) { 1855 unsigned Prev = 0; 1856 unsigned SearchFrom = 0; 1857 llvm::Regex IncludeRegex(CppIncludeRegexPattern); 1858 SmallVector<StringRef, 4> Matches; 1859 SmallVector<IncludeDirective, 16> IncludesInBlock; 1860 1861 // In compiled files, consider the first #include to be the main #include of 1862 // the file if it is not a system #include. This ensures that the header 1863 // doesn't have hidden dependencies 1864 // (http://llvm.org/docs/CodingStandards.html#include-style). 1865 // 1866 // FIXME: Do some sanity checking, e.g. edit distance of the base name, to fix 1867 // cases where the first #include is unlikely to be the main header. 1868 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName); 1869 bool FirstIncludeBlock = true; 1870 bool MainIncludeFound = false; 1871 bool FormattingOff = false; 1872 1873 for (;;) { 1874 auto Pos = Code.find('\n', SearchFrom); 1875 StringRef Line = 1876 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 1877 1878 StringRef Trimmed = Line.trim(); 1879 if (Trimmed == "// clang-format off" || Trimmed == "/* clang-format off */") 1880 FormattingOff = true; 1881 else if (Trimmed == "// clang-format on" || 1882 Trimmed == "/* clang-format on */") 1883 FormattingOff = false; 1884 1885 const bool EmptyLineSkipped = 1886 Trimmed.empty() && 1887 (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge || 1888 Style.IncludeStyle.IncludeBlocks == 1889 tooling::IncludeStyle::IBS_Regroup); 1890 1891 if (!FormattingOff && !Line.endswith("\\")) { 1892 if (IncludeRegex.match(Line, &Matches)) { 1893 StringRef IncludeName = Matches[2]; 1894 int Category = Categories.getIncludePriority( 1895 IncludeName, 1896 /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock); 1897 if (Category == 0) 1898 MainIncludeFound = true; 1899 IncludesInBlock.push_back({IncludeName, Line, Prev, Category}); 1900 } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) { 1901 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, 1902 Replaces, Cursor); 1903 IncludesInBlock.clear(); 1904 FirstIncludeBlock = false; 1905 } 1906 Prev = Pos + 1; 1907 } 1908 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 1909 break; 1910 SearchFrom = Pos + 1; 1911 } 1912 if (!IncludesInBlock.empty()) { 1913 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces, 1914 Cursor); 1915 } 1916 return Replaces; 1917 } 1918 1919 // Returns group number to use as a first order sort on imports. Gives UINT_MAX 1920 // if the import does not match any given groups. 1921 static unsigned findJavaImportGroup(const FormatStyle &Style, 1922 StringRef ImportIdentifier) { 1923 unsigned LongestMatchIndex = UINT_MAX; 1924 unsigned LongestMatchLength = 0; 1925 for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) { 1926 std::string GroupPrefix = Style.JavaImportGroups[I]; 1927 if (ImportIdentifier.startswith(GroupPrefix) && 1928 GroupPrefix.length() > LongestMatchLength) { 1929 LongestMatchIndex = I; 1930 LongestMatchLength = GroupPrefix.length(); 1931 } 1932 } 1933 return LongestMatchIndex; 1934 } 1935 1936 // Sorts and deduplicates a block of includes given by 'Imports' based on 1937 // JavaImportGroups, then adding the necessary replacement to 'Replaces'. 1938 // Import declarations with the same text will be deduplicated. Between each 1939 // import group, a newline is inserted, and within each import group, a 1940 // lexicographic sort based on ASCII value is performed. 1941 static void sortJavaImports(const FormatStyle &Style, 1942 const SmallVectorImpl<JavaImportDirective> &Imports, 1943 ArrayRef<tooling::Range> Ranges, StringRef FileName, 1944 StringRef Code, tooling::Replacements &Replaces) { 1945 unsigned ImportsBeginOffset = Imports.front().Offset; 1946 unsigned ImportsEndOffset = 1947 Imports.back().Offset + Imports.back().Text.size(); 1948 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset; 1949 if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset)) 1950 return; 1951 SmallVector<unsigned, 16> Indices; 1952 SmallVector<unsigned, 16> JavaImportGroups; 1953 for (unsigned i = 0, e = Imports.size(); i != e; ++i) { 1954 Indices.push_back(i); 1955 JavaImportGroups.push_back( 1956 findJavaImportGroup(Style, Imports[i].Identifier)); 1957 } 1958 llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) { 1959 // Negating IsStatic to push static imports above non-static imports. 1960 return std::make_tuple(!Imports[LHSI].IsStatic, JavaImportGroups[LHSI], 1961 Imports[LHSI].Identifier) < 1962 std::make_tuple(!Imports[RHSI].IsStatic, JavaImportGroups[RHSI], 1963 Imports[RHSI].Identifier); 1964 }); 1965 1966 // Deduplicate imports. 1967 Indices.erase(std::unique(Indices.begin(), Indices.end(), 1968 [&](unsigned LHSI, unsigned RHSI) { 1969 return Imports[LHSI].Text == Imports[RHSI].Text; 1970 }), 1971 Indices.end()); 1972 1973 bool CurrentIsStatic = Imports[Indices.front()].IsStatic; 1974 unsigned CurrentImportGroup = JavaImportGroups[Indices.front()]; 1975 1976 std::string result; 1977 for (unsigned Index : Indices) { 1978 if (!result.empty()) { 1979 result += "\n"; 1980 if (CurrentIsStatic != Imports[Index].IsStatic || 1981 CurrentImportGroup != JavaImportGroups[Index]) 1982 result += "\n"; 1983 } 1984 for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) { 1985 result += CommentLine; 1986 result += "\n"; 1987 } 1988 result += Imports[Index].Text; 1989 CurrentIsStatic = Imports[Index].IsStatic; 1990 CurrentImportGroup = JavaImportGroups[Index]; 1991 } 1992 1993 // If the imports are out of order, we generate a single replacement fixing 1994 // the entire block. Otherwise, no replacement is generated. 1995 if (result == Code.substr(Imports.front().Offset, ImportsBlockSize)) 1996 return; 1997 1998 auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset, 1999 ImportsBlockSize, result)); 2000 // FIXME: better error handling. For now, just skip the replacement for the 2001 // release version. 2002 if (Err) { 2003 llvm::errs() << llvm::toString(std::move(Err)) << "\n"; 2004 assert(false); 2005 } 2006 } 2007 2008 namespace { 2009 2010 const char JavaImportRegexPattern[] = 2011 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;"; 2012 2013 } // anonymous namespace 2014 2015 tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code, 2016 ArrayRef<tooling::Range> Ranges, 2017 StringRef FileName, 2018 tooling::Replacements &Replaces) { 2019 unsigned Prev = 0; 2020 unsigned SearchFrom = 0; 2021 llvm::Regex ImportRegex(JavaImportRegexPattern); 2022 SmallVector<StringRef, 4> Matches; 2023 SmallVector<JavaImportDirective, 16> ImportsInBlock; 2024 std::vector<StringRef> AssociatedCommentLines; 2025 2026 bool FormattingOff = false; 2027 2028 for (;;) { 2029 auto Pos = Code.find('\n', SearchFrom); 2030 StringRef Line = 2031 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 2032 2033 StringRef Trimmed = Line.trim(); 2034 if (Trimmed == "// clang-format off") 2035 FormattingOff = true; 2036 else if (Trimmed == "// clang-format on") 2037 FormattingOff = false; 2038 2039 if (ImportRegex.match(Line, &Matches)) { 2040 if (FormattingOff) { 2041 // If at least one import line has formatting turned off, turn off 2042 // formatting entirely. 2043 return Replaces; 2044 } 2045 StringRef Static = Matches[1]; 2046 StringRef Identifier = Matches[2]; 2047 bool IsStatic = false; 2048 if (Static.contains("static")) { 2049 IsStatic = true; 2050 } 2051 ImportsInBlock.push_back( 2052 {Identifier, Line, Prev, AssociatedCommentLines, IsStatic}); 2053 AssociatedCommentLines.clear(); 2054 } else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) { 2055 // Associating comments within the imports with the nearest import below 2056 AssociatedCommentLines.push_back(Line); 2057 } 2058 Prev = Pos + 1; 2059 if (Pos == StringRef::npos || Pos + 1 == Code.size()) 2060 break; 2061 SearchFrom = Pos + 1; 2062 } 2063 if (!ImportsInBlock.empty()) 2064 sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces); 2065 return Replaces; 2066 } 2067 2068 bool isMpegTS(StringRef Code) { 2069 // MPEG transport streams use the ".ts" file extension. clang-format should 2070 // not attempt to format those. MPEG TS' frame format starts with 0x47 every 2071 // 189 bytes - detect that and return. 2072 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47; 2073 } 2074 2075 bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); } 2076 2077 tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, 2078 ArrayRef<tooling::Range> Ranges, 2079 StringRef FileName, unsigned *Cursor) { 2080 tooling::Replacements Replaces; 2081 if (!Style.SortIncludes) 2082 return Replaces; 2083 if (isLikelyXml(Code)) 2084 return Replaces; 2085 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript && 2086 isMpegTS(Code)) 2087 return Replaces; 2088 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript) 2089 return sortJavaScriptImports(Style, Code, Ranges, FileName); 2090 if (Style.Language == FormatStyle::LanguageKind::LK_Java) 2091 return sortJavaImports(Style, Code, Ranges, FileName, Replaces); 2092 sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor); 2093 return Replaces; 2094 } 2095 2096 template <typename T> 2097 static llvm::Expected<tooling::Replacements> 2098 processReplacements(T ProcessFunc, StringRef Code, 2099 const tooling::Replacements &Replaces, 2100 const FormatStyle &Style) { 2101 if (Replaces.empty()) 2102 return tooling::Replacements(); 2103 2104 auto NewCode = applyAllReplacements(Code, Replaces); 2105 if (!NewCode) 2106 return NewCode.takeError(); 2107 std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges(); 2108 StringRef FileName = Replaces.begin()->getFilePath(); 2109 2110 tooling::Replacements FormatReplaces = 2111 ProcessFunc(Style, *NewCode, ChangedRanges, FileName); 2112 2113 return Replaces.merge(FormatReplaces); 2114 } 2115 2116 llvm::Expected<tooling::Replacements> 2117 formatReplacements(StringRef Code, const tooling::Replacements &Replaces, 2118 const FormatStyle &Style) { 2119 // We need to use lambda function here since there are two versions of 2120 // `sortIncludes`. 2121 auto SortIncludes = [](const FormatStyle &Style, StringRef Code, 2122 std::vector<tooling::Range> Ranges, 2123 StringRef FileName) -> tooling::Replacements { 2124 return sortIncludes(Style, Code, Ranges, FileName); 2125 }; 2126 auto SortedReplaces = 2127 processReplacements(SortIncludes, Code, Replaces, Style); 2128 if (!SortedReplaces) 2129 return SortedReplaces.takeError(); 2130 2131 // We need to use lambda function here since there are two versions of 2132 // `reformat`. 2133 auto Reformat = [](const FormatStyle &Style, StringRef Code, 2134 std::vector<tooling::Range> Ranges, 2135 StringRef FileName) -> tooling::Replacements { 2136 return reformat(Style, Code, Ranges, FileName); 2137 }; 2138 return processReplacements(Reformat, Code, *SortedReplaces, Style); 2139 } 2140 2141 namespace { 2142 2143 inline bool isHeaderInsertion(const tooling::Replacement &Replace) { 2144 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 && 2145 llvm::Regex(CppIncludeRegexPattern) 2146 .match(Replace.getReplacementText()); 2147 } 2148 2149 inline bool isHeaderDeletion(const tooling::Replacement &Replace) { 2150 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1; 2151 } 2152 2153 // FIXME: insert empty lines between newly created blocks. 2154 tooling::Replacements 2155 fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces, 2156 const FormatStyle &Style) { 2157 if (!Style.isCpp()) 2158 return Replaces; 2159 2160 tooling::Replacements HeaderInsertions; 2161 std::set<llvm::StringRef> HeadersToDelete; 2162 tooling::Replacements Result; 2163 for (const auto &R : Replaces) { 2164 if (isHeaderInsertion(R)) { 2165 // Replacements from \p Replaces must be conflict-free already, so we can 2166 // simply consume the error. 2167 llvm::consumeError(HeaderInsertions.add(R)); 2168 } else if (isHeaderDeletion(R)) { 2169 HeadersToDelete.insert(R.getReplacementText()); 2170 } else if (R.getOffset() == UINT_MAX) { 2171 llvm::errs() << "Insertions other than header #include insertion are " 2172 "not supported! " 2173 << R.getReplacementText() << "\n"; 2174 } else { 2175 llvm::consumeError(Result.add(R)); 2176 } 2177 } 2178 if (HeaderInsertions.empty() && HeadersToDelete.empty()) 2179 return Replaces; 2180 2181 StringRef FileName = Replaces.begin()->getFilePath(); 2182 tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle); 2183 2184 for (const auto &Header : HeadersToDelete) { 2185 tooling::Replacements Replaces = 2186 Includes.remove(Header.trim("\"<>"), Header.startswith("<")); 2187 for (const auto &R : Replaces) { 2188 auto Err = Result.add(R); 2189 if (Err) { 2190 // Ignore the deletion on conflict. 2191 llvm::errs() << "Failed to add header deletion replacement for " 2192 << Header << ": " << llvm::toString(std::move(Err)) 2193 << "\n"; 2194 } 2195 } 2196 } 2197 2198 llvm::Regex IncludeRegex = llvm::Regex(CppIncludeRegexPattern); 2199 llvm::SmallVector<StringRef, 4> Matches; 2200 for (const auto &R : HeaderInsertions) { 2201 auto IncludeDirective = R.getReplacementText(); 2202 bool Matched = IncludeRegex.match(IncludeDirective, &Matches); 2203 assert(Matched && "Header insertion replacement must have replacement text " 2204 "'#include ...'"); 2205 (void)Matched; 2206 auto IncludeName = Matches[2]; 2207 auto Replace = 2208 Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<")); 2209 if (Replace) { 2210 auto Err = Result.add(*Replace); 2211 if (Err) { 2212 llvm::consumeError(std::move(Err)); 2213 unsigned NewOffset = 2214 Result.getShiftedCodePosition(Replace->getOffset()); 2215 auto Shifted = tooling::Replacement(FileName, NewOffset, 0, 2216 Replace->getReplacementText()); 2217 Result = Result.merge(tooling::Replacements(Shifted)); 2218 } 2219 } 2220 } 2221 return Result; 2222 } 2223 2224 } // anonymous namespace 2225 2226 llvm::Expected<tooling::Replacements> 2227 cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, 2228 const FormatStyle &Style) { 2229 // We need to use lambda function here since there are two versions of 2230 // `cleanup`. 2231 auto Cleanup = [](const FormatStyle &Style, StringRef Code, 2232 std::vector<tooling::Range> Ranges, 2233 StringRef FileName) -> tooling::Replacements { 2234 return cleanup(Style, Code, Ranges, FileName); 2235 }; 2236 // Make header insertion replacements insert new headers into correct blocks. 2237 tooling::Replacements NewReplaces = 2238 fixCppIncludeInsertions(Code, Replaces, Style); 2239 return processReplacements(Cleanup, Code, NewReplaces, Style); 2240 } 2241 2242 namespace internal { 2243 std::pair<tooling::Replacements, unsigned> 2244 reformat(const FormatStyle &Style, StringRef Code, 2245 ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn, 2246 unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName, 2247 FormattingAttemptStatus *Status) { 2248 FormatStyle Expanded = expandPresets(Style); 2249 if (Expanded.DisableFormat) 2250 return {tooling::Replacements(), 0}; 2251 if (isLikelyXml(Code)) 2252 return {tooling::Replacements(), 0}; 2253 if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code)) 2254 return {tooling::Replacements(), 0}; 2255 2256 typedef std::function<std::pair<tooling::Replacements, unsigned>( 2257 const Environment &)> 2258 AnalyzerPass; 2259 SmallVector<AnalyzerPass, 4> Passes; 2260 2261 if (Style.Language == FormatStyle::LK_Cpp) { 2262 if (Style.FixNamespaceComments) 2263 Passes.emplace_back([&](const Environment &Env) { 2264 return NamespaceEndCommentsFixer(Env, Expanded).process(); 2265 }); 2266 2267 if (Style.SortUsingDeclarations) 2268 Passes.emplace_back([&](const Environment &Env) { 2269 return UsingDeclarationsSorter(Env, Expanded).process(); 2270 }); 2271 } 2272 2273 if (Style.Language == FormatStyle::LK_JavaScript && 2274 Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) 2275 Passes.emplace_back([&](const Environment &Env) { 2276 return JavaScriptRequoter(Env, Expanded).process(); 2277 }); 2278 2279 Passes.emplace_back([&](const Environment &Env) { 2280 return Formatter(Env, Expanded, Status).process(); 2281 }); 2282 2283 auto Env = 2284 llvm::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn, 2285 NextStartColumn, LastStartColumn); 2286 llvm::Optional<std::string> CurrentCode = None; 2287 tooling::Replacements Fixes; 2288 unsigned Penalty = 0; 2289 for (size_t I = 0, E = Passes.size(); I < E; ++I) { 2290 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env); 2291 auto NewCode = applyAllReplacements( 2292 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first); 2293 if (NewCode) { 2294 Fixes = Fixes.merge(PassFixes.first); 2295 Penalty += PassFixes.second; 2296 if (I + 1 < E) { 2297 CurrentCode = std::move(*NewCode); 2298 Env = llvm::make_unique<Environment>( 2299 *CurrentCode, FileName, 2300 tooling::calculateRangesAfterReplacements(Fixes, Ranges), 2301 FirstStartColumn, NextStartColumn, LastStartColumn); 2302 } 2303 } 2304 } 2305 2306 return {Fixes, Penalty}; 2307 } 2308 } // namespace internal 2309 2310 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 2311 ArrayRef<tooling::Range> Ranges, 2312 StringRef FileName, 2313 FormattingAttemptStatus *Status) { 2314 return internal::reformat(Style, Code, Ranges, 2315 /*FirstStartColumn=*/0, 2316 /*NextStartColumn=*/0, 2317 /*LastStartColumn=*/0, FileName, Status) 2318 .first; 2319 } 2320 2321 tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, 2322 ArrayRef<tooling::Range> Ranges, 2323 StringRef FileName) { 2324 // cleanups only apply to C++ (they mostly concern ctor commas etc.) 2325 if (Style.Language != FormatStyle::LK_Cpp) 2326 return tooling::Replacements(); 2327 return Cleaner(Environment(Code, FileName, Ranges), Style).process().first; 2328 } 2329 2330 tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 2331 ArrayRef<tooling::Range> Ranges, 2332 StringRef FileName, bool *IncompleteFormat) { 2333 FormattingAttemptStatus Status; 2334 auto Result = reformat(Style, Code, Ranges, FileName, &Status); 2335 if (!Status.FormatComplete) 2336 *IncompleteFormat = true; 2337 return Result; 2338 } 2339 2340 tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, 2341 StringRef Code, 2342 ArrayRef<tooling::Range> Ranges, 2343 StringRef FileName) { 2344 return NamespaceEndCommentsFixer(Environment(Code, FileName, Ranges), Style) 2345 .process() 2346 .first; 2347 } 2348 2349 tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, 2350 StringRef Code, 2351 ArrayRef<tooling::Range> Ranges, 2352 StringRef FileName) { 2353 return UsingDeclarationsSorter(Environment(Code, FileName, Ranges), Style) 2354 .process() 2355 .first; 2356 } 2357 2358 LangOptions getFormattingLangOpts(const FormatStyle &Style) { 2359 LangOptions LangOpts; 2360 LangOpts.CPlusPlus = 1; 2361 LangOpts.CPlusPlus11 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1; 2362 LangOpts.CPlusPlus14 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1; 2363 LangOpts.CPlusPlus17 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1; 2364 LangOpts.CPlusPlus2a = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1; 2365 LangOpts.LineComment = 1; 2366 bool AlternativeOperators = Style.isCpp(); 2367 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0; 2368 LangOpts.Bool = 1; 2369 LangOpts.ObjC = 1; 2370 LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally. 2371 LangOpts.DeclSpecKeyword = 1; // To get __declspec. 2372 return LangOpts; 2373 } 2374 2375 const char *StyleOptionHelpDescription = 2376 "Coding style, currently supports:\n" 2377 " LLVM, Google, Chromium, Mozilla, WebKit.\n" 2378 "Use -style=file to load style configuration from\n" 2379 ".clang-format file located in one of the parent\n" 2380 "directories of the source file (or current\n" 2381 "directory for stdin).\n" 2382 "Use -style=\"{key: value, ...}\" to set specific\n" 2383 "parameters, e.g.:\n" 2384 " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""; 2385 2386 static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) { 2387 if (FileName.endswith(".java")) 2388 return FormatStyle::LK_Java; 2389 if (FileName.endswith_lower(".js") || FileName.endswith_lower(".ts")) 2390 return FormatStyle::LK_JavaScript; // JavaScript or TypeScript. 2391 if (FileName.endswith(".m") || FileName.endswith(".mm")) 2392 return FormatStyle::LK_ObjC; 2393 if (FileName.endswith_lower(".proto") || 2394 FileName.endswith_lower(".protodevel")) 2395 return FormatStyle::LK_Proto; 2396 if (FileName.endswith_lower(".textpb") || 2397 FileName.endswith_lower(".pb.txt") || 2398 FileName.endswith_lower(".textproto") || 2399 FileName.endswith_lower(".asciipb")) 2400 return FormatStyle::LK_TextProto; 2401 if (FileName.endswith_lower(".td")) 2402 return FormatStyle::LK_TableGen; 2403 if (FileName.endswith_lower(".cs")) 2404 return FormatStyle::LK_CSharp; 2405 return FormatStyle::LK_Cpp; 2406 } 2407 2408 FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) { 2409 const auto GuessedLanguage = getLanguageByFileName(FileName); 2410 if (GuessedLanguage == FormatStyle::LK_Cpp) { 2411 auto Extension = llvm::sys::path::extension(FileName); 2412 // If there's no file extension (or it's .h), we need to check the contents 2413 // of the code to see if it contains Objective-C. 2414 if (Extension.empty() || Extension == ".h") { 2415 auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName; 2416 Environment Env(Code, NonEmptyFileName, /*Ranges=*/{}); 2417 ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle()); 2418 Guesser.process(); 2419 if (Guesser.isObjC()) 2420 return FormatStyle::LK_ObjC; 2421 } 2422 } 2423 return GuessedLanguage; 2424 } 2425 2426 const char *DefaultFormatStyle = "file"; 2427 2428 const char *DefaultFallbackStyle = "LLVM"; 2429 2430 llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, 2431 StringRef FallbackStyleName, 2432 StringRef Code, 2433 llvm::vfs::FileSystem *FS) { 2434 if (!FS) { 2435 FS = llvm::vfs::getRealFileSystem().get(); 2436 } 2437 FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code)); 2438 2439 FormatStyle FallbackStyle = getNoStyle(); 2440 if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle)) 2441 return make_string_error("Invalid fallback style \"" + FallbackStyleName); 2442 2443 if (StyleName.startswith("{")) { 2444 // Parse YAML/JSON style from the command line. 2445 if (std::error_code ec = parseConfiguration(StyleName, &Style)) 2446 return make_string_error("Error parsing -style: " + ec.message()); 2447 return Style; 2448 } 2449 2450 if (!StyleName.equals_lower("file")) { 2451 if (!getPredefinedStyle(StyleName, Style.Language, &Style)) 2452 return make_string_error("Invalid value for -style"); 2453 return Style; 2454 } 2455 2456 // Look for .clang-format/_clang-format file in the file's parent directories. 2457 SmallString<128> UnsuitableConfigFiles; 2458 SmallString<128> Path(FileName); 2459 if (std::error_code EC = FS->makeAbsolute(Path)) 2460 return make_string_error(EC.message()); 2461 2462 for (StringRef Directory = Path; !Directory.empty(); 2463 Directory = llvm::sys::path::parent_path(Directory)) { 2464 2465 auto Status = FS->status(Directory); 2466 if (!Status || 2467 Status->getType() != llvm::sys::fs::file_type::directory_file) { 2468 continue; 2469 } 2470 2471 SmallString<128> ConfigFile(Directory); 2472 2473 llvm::sys::path::append(ConfigFile, ".clang-format"); 2474 LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); 2475 2476 Status = FS->status(ConfigFile.str()); 2477 bool FoundConfigFile = 2478 Status && (Status->getType() == llvm::sys::fs::file_type::regular_file); 2479 if (!FoundConfigFile) { 2480 // Try _clang-format too, since dotfiles are not commonly used on Windows. 2481 ConfigFile = Directory; 2482 llvm::sys::path::append(ConfigFile, "_clang-format"); 2483 LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); 2484 Status = FS->status(ConfigFile.str()); 2485 FoundConfigFile = Status && (Status->getType() == 2486 llvm::sys::fs::file_type::regular_file); 2487 } 2488 2489 if (FoundConfigFile) { 2490 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 2491 FS->getBufferForFile(ConfigFile.str()); 2492 if (std::error_code EC = Text.getError()) 2493 return make_string_error(EC.message()); 2494 if (std::error_code ec = 2495 parseConfiguration(Text.get()->getBuffer(), &Style)) { 2496 if (ec == ParseError::Unsuitable) { 2497 if (!UnsuitableConfigFiles.empty()) 2498 UnsuitableConfigFiles.append(", "); 2499 UnsuitableConfigFiles.append(ConfigFile); 2500 continue; 2501 } 2502 return make_string_error("Error reading " + ConfigFile + ": " + 2503 ec.message()); 2504 } 2505 LLVM_DEBUG(llvm::dbgs() 2506 << "Using configuration file " << ConfigFile << "\n"); 2507 return Style; 2508 } 2509 } 2510 if (!UnsuitableConfigFiles.empty()) 2511 return make_string_error("Configuration file(s) do(es) not support " + 2512 getLanguageName(Style.Language) + ": " + 2513 UnsuitableConfigFiles); 2514 return FallbackStyle; 2515 } 2516 2517 } // namespace format 2518 } // namespace clang 2519