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