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