Format.cpp revision 296417
1249261Sdim//===--- Format.cpp - Format C++ code -------------------------------------===// 2249261Sdim// 3249261Sdim// The LLVM Compiler Infrastructure 4249261Sdim// 5249261Sdim// This file is distributed under the University of Illinois Open Source 6249261Sdim// License. See LICENSE.TXT for details. 7249261Sdim// 8249261Sdim//===----------------------------------------------------------------------===// 9249261Sdim/// 10249261Sdim/// \file 11249261Sdim/// \brief This file implements functions declared in Format.h. This will be 12249261Sdim/// split into separate files as we go. 13249261Sdim/// 14249261Sdim//===----------------------------------------------------------------------===// 15249261Sdim 16296417Sdim#include "clang/Format/Format.h" 17261991Sdim#include "ContinuationIndenter.h" 18249261Sdim#include "TokenAnnotator.h" 19280031Sdim#include "UnwrappedLineFormatter.h" 20249261Sdim#include "UnwrappedLineParser.h" 21251662Sdim#include "WhitespaceManager.h" 22249261Sdim#include "clang/Basic/Diagnostic.h" 23276479Sdim#include "clang/Basic/DiagnosticOptions.h" 24249261Sdim#include "clang/Basic/SourceManager.h" 25249261Sdim#include "clang/Lex/Lexer.h" 26249261Sdim#include "llvm/ADT/STLExtras.h" 27249261Sdim#include "llvm/Support/Allocator.h" 28249261Sdim#include "llvm/Support/Debug.h" 29276479Sdim#include "llvm/Support/Path.h" 30288943Sdim#include "llvm/Support/Regex.h" 31261991Sdim#include "llvm/Support/YAMLTraits.h" 32249261Sdim#include <queue> 33249261Sdim#include <string> 34249261Sdim 35276479Sdim#define DEBUG_TYPE "format-formatter" 36276479Sdim 37276479Sdimusing clang::format::FormatStyle; 38276479Sdim 39276479SdimLLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string) 40296417SdimLLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::IncludeCategory) 41276479Sdim 42261991Sdimnamespace llvm { 43261991Sdimnamespace yaml { 44276479Sdimtemplate <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> { 45276479Sdim static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) { 46276479Sdim IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp); 47280031Sdim IO.enumCase(Value, "Java", FormatStyle::LK_Java); 48276479Sdim IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript); 49276479Sdim IO.enumCase(Value, "Proto", FormatStyle::LK_Proto); 50296417Sdim IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen); 51261991Sdim } 52261991Sdim}; 53261991Sdim 54276479Sdimtemplate <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> { 55276479Sdim static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) { 56276479Sdim IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); 57276479Sdim IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); 58276479Sdim IO.enumCase(Value, "Cpp11", FormatStyle::LS_Cpp11); 59276479Sdim IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); 60276479Sdim IO.enumCase(Value, "Auto", FormatStyle::LS_Auto); 61276479Sdim } 62276479Sdim}; 63276479Sdim 64276479Sdimtemplate <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> { 65276479Sdim static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) { 66276479Sdim IO.enumCase(Value, "Never", FormatStyle::UT_Never); 67276479Sdim IO.enumCase(Value, "false", FormatStyle::UT_Never); 68276479Sdim IO.enumCase(Value, "Always", FormatStyle::UT_Always); 69276479Sdim IO.enumCase(Value, "true", FormatStyle::UT_Always); 70276479Sdim IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation); 71276479Sdim } 72276479Sdim}; 73276479Sdim 74276479Sdimtemplate <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> { 75276479Sdim static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) { 76276479Sdim IO.enumCase(Value, "None", FormatStyle::SFS_None); 77276479Sdim IO.enumCase(Value, "false", FormatStyle::SFS_None); 78276479Sdim IO.enumCase(Value, "All", FormatStyle::SFS_All); 79276479Sdim IO.enumCase(Value, "true", FormatStyle::SFS_All); 80276479Sdim IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline); 81280031Sdim IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty); 82276479Sdim } 83276479Sdim}; 84276479Sdim 85280031Sdimtemplate <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> { 86280031Sdim static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) { 87280031Sdim IO.enumCase(Value, "All", FormatStyle::BOS_All); 88280031Sdim IO.enumCase(Value, "true", FormatStyle::BOS_All); 89280031Sdim IO.enumCase(Value, "None", FormatStyle::BOS_None); 90280031Sdim IO.enumCase(Value, "false", FormatStyle::BOS_None); 91280031Sdim IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment); 92280031Sdim } 93280031Sdim}; 94280031Sdim 95276479Sdimtemplate <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> { 96276479Sdim static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) { 97276479Sdim IO.enumCase(Value, "Attach", FormatStyle::BS_Attach); 98276479Sdim IO.enumCase(Value, "Linux", FormatStyle::BS_Linux); 99288943Sdim IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla); 100276479Sdim IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup); 101276479Sdim IO.enumCase(Value, "Allman", FormatStyle::BS_Allman); 102276479Sdim IO.enumCase(Value, "GNU", FormatStyle::BS_GNU); 103296417Sdim IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit); 104296417Sdim IO.enumCase(Value, "Custom", FormatStyle::BS_Custom); 105276479Sdim } 106276479Sdim}; 107276479Sdim 108296417Sdimtemplate <> 109296417Sdimstruct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> { 110296417Sdim static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) { 111296417Sdim IO.enumCase(Value, "None", FormatStyle::RTBS_None); 112296417Sdim IO.enumCase(Value, "All", FormatStyle::RTBS_All); 113296417Sdim IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel); 114296417Sdim IO.enumCase(Value, "TopLevelDefinitions", 115296417Sdim FormatStyle::RTBS_TopLevelDefinitions); 116296417Sdim IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions); 117296417Sdim } 118296417Sdim}; 119296417Sdim 120296417Sdimtemplate <> 121296417Sdimstruct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> { 122296417Sdim static void 123296417Sdim enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) { 124288943Sdim IO.enumCase(Value, "None", FormatStyle::DRTBS_None); 125288943Sdim IO.enumCase(Value, "All", FormatStyle::DRTBS_All); 126288943Sdim IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel); 127288943Sdim 128288943Sdim // For backward compatibility. 129288943Sdim IO.enumCase(Value, "false", FormatStyle::DRTBS_None); 130288943Sdim IO.enumCase(Value, "true", FormatStyle::DRTBS_All); 131288943Sdim } 132288943Sdim}; 133288943Sdim 134261991Sdimtemplate <> 135276479Sdimstruct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> { 136261991Sdim static void enumeration(IO &IO, 137276479Sdim FormatStyle::NamespaceIndentationKind &Value) { 138276479Sdim IO.enumCase(Value, "None", FormatStyle::NI_None); 139276479Sdim IO.enumCase(Value, "Inner", FormatStyle::NI_Inner); 140276479Sdim IO.enumCase(Value, "All", FormatStyle::NI_All); 141261991Sdim } 142261991Sdim}; 143261991Sdim 144296417Sdimtemplate <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> { 145296417Sdim static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) { 146296417Sdim IO.enumCase(Value, "Align", FormatStyle::BAS_Align); 147296417Sdim IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign); 148296417Sdim IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak); 149296417Sdim 150296417Sdim // For backward compatibility. 151296417Sdim IO.enumCase(Value, "true", FormatStyle::BAS_Align); 152296417Sdim IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign); 153296417Sdim } 154296417Sdim}; 155296417Sdim 156288943Sdimtemplate <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> { 157288943Sdim static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) { 158276479Sdim IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle); 159276479Sdim IO.enumCase(Value, "Left", FormatStyle::PAS_Left); 160276479Sdim IO.enumCase(Value, "Right", FormatStyle::PAS_Right); 161276479Sdim 162276479Sdim // For backward compatibility. 163276479Sdim IO.enumCase(Value, "true", FormatStyle::PAS_Left); 164276479Sdim IO.enumCase(Value, "false", FormatStyle::PAS_Right); 165261991Sdim } 166261991Sdim}; 167261991Sdim 168261991Sdimtemplate <> 169276479Sdimstruct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> { 170276479Sdim static void enumeration(IO &IO, 171276479Sdim FormatStyle::SpaceBeforeParensOptions &Value) { 172276479Sdim IO.enumCase(Value, "Never", FormatStyle::SBPO_Never); 173276479Sdim IO.enumCase(Value, "ControlStatements", 174276479Sdim FormatStyle::SBPO_ControlStatements); 175276479Sdim IO.enumCase(Value, "Always", FormatStyle::SBPO_Always); 176276479Sdim 177276479Sdim // For backward compatibility. 178276479Sdim IO.enumCase(Value, "false", FormatStyle::SBPO_Never); 179276479Sdim IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements); 180261991Sdim } 181261991Sdim}; 182261991Sdim 183276479Sdimtemplate <> struct MappingTraits<FormatStyle> { 184276479Sdim static void mapping(IO &IO, FormatStyle &Style) { 185276479Sdim // When reading, read the language first, we need it for getPredefinedStyle. 186276479Sdim IO.mapOptional("Language", Style.Language); 187276479Sdim 188261991Sdim if (IO.outputting()) { 189288943Sdim StringRef StylesArray[] = {"LLVM", "Google", "Chromium", 190288943Sdim "Mozilla", "WebKit", "GNU"}; 191261991Sdim ArrayRef<StringRef> Styles(StylesArray); 192261991Sdim for (size_t i = 0, e = Styles.size(); i < e; ++i) { 193261991Sdim StringRef StyleName(Styles[i]); 194276479Sdim FormatStyle PredefinedStyle; 195276479Sdim if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) && 196261991Sdim Style == PredefinedStyle) { 197261991Sdim IO.mapOptional("# BasedOnStyle", StyleName); 198261991Sdim break; 199261991Sdim } 200261991Sdim } 201261991Sdim } else { 202261991Sdim StringRef BasedOnStyle; 203261991Sdim IO.mapOptional("BasedOnStyle", BasedOnStyle); 204276479Sdim if (!BasedOnStyle.empty()) { 205276479Sdim FormatStyle::LanguageKind OldLanguage = Style.Language; 206276479Sdim FormatStyle::LanguageKind Language = 207276479Sdim ((FormatStyle *)IO.getContext())->Language; 208276479Sdim if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) { 209261991Sdim IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle)); 210261991Sdim return; 211261991Sdim } 212276479Sdim Style.Language = OldLanguage; 213276479Sdim } 214261991Sdim } 215261991Sdim 216288943Sdim // For backward compatibility. 217288943Sdim if (!IO.outputting()) { 218288943Sdim IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment); 219288943Sdim IO.mapOptional("IndentFunctionDeclarationAfterType", 220288943Sdim Style.IndentWrappedFunctionNames); 221288943Sdim IO.mapOptional("PointerBindsToType", Style.PointerAlignment); 222288943Sdim IO.mapOptional("SpaceAfterControlStatementKeyword", 223288943Sdim Style.SpaceBeforeParens); 224288943Sdim } 225288943Sdim 226261991Sdim IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset); 227280031Sdim IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket); 228288943Sdim IO.mapOptional("AlignConsecutiveAssignments", 229288943Sdim Style.AlignConsecutiveAssignments); 230296417Sdim IO.mapOptional("AlignConsecutiveDeclarations", 231296417Sdim Style.AlignConsecutiveDeclarations); 232261991Sdim IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlinesLeft); 233280031Sdim IO.mapOptional("AlignOperands", Style.AlignOperands); 234261991Sdim IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments); 235261991Sdim IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine", 236261991Sdim Style.AllowAllParametersOfDeclarationOnNextLine); 237276479Sdim IO.mapOptional("AllowShortBlocksOnASingleLine", 238276479Sdim Style.AllowShortBlocksOnASingleLine); 239280031Sdim IO.mapOptional("AllowShortCaseLabelsOnASingleLine", 240280031Sdim Style.AllowShortCaseLabelsOnASingleLine); 241288943Sdim IO.mapOptional("AllowShortFunctionsOnASingleLine", 242288943Sdim Style.AllowShortFunctionsOnASingleLine); 243261991Sdim IO.mapOptional("AllowShortIfStatementsOnASingleLine", 244261991Sdim Style.AllowShortIfStatementsOnASingleLine); 245261991Sdim IO.mapOptional("AllowShortLoopsOnASingleLine", 246261991Sdim Style.AllowShortLoopsOnASingleLine); 247280031Sdim IO.mapOptional("AlwaysBreakAfterDefinitionReturnType", 248280031Sdim Style.AlwaysBreakAfterDefinitionReturnType); 249296417Sdim IO.mapOptional("AlwaysBreakAfterReturnType", 250296417Sdim Style.AlwaysBreakAfterReturnType); 251296417Sdim // If AlwaysBreakAfterDefinitionReturnType was specified but 252296417Sdim // AlwaysBreakAfterReturnType was not, initialize the latter from the 253296417Sdim // former for backwards compatibility. 254296417Sdim if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None && 255296417Sdim Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) { 256296417Sdim if (Style.AlwaysBreakAfterDefinitionReturnType == FormatStyle::DRTBS_All) 257296417Sdim Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; 258296417Sdim else if (Style.AlwaysBreakAfterDefinitionReturnType == 259296417Sdim FormatStyle::DRTBS_TopLevel) 260296417Sdim Style.AlwaysBreakAfterReturnType = 261296417Sdim FormatStyle::RTBS_TopLevelDefinitions; 262296417Sdim } 263296417Sdim 264288943Sdim IO.mapOptional("AlwaysBreakBeforeMultilineStrings", 265288943Sdim Style.AlwaysBreakBeforeMultilineStrings); 266261991Sdim IO.mapOptional("AlwaysBreakTemplateDeclarations", 267261991Sdim Style.AlwaysBreakTemplateDeclarations); 268288943Sdim IO.mapOptional("BinPackArguments", Style.BinPackArguments); 269288943Sdim IO.mapOptional("BinPackParameters", Style.BinPackParameters); 270296417Sdim IO.mapOptional("BraceWrapping", Style.BraceWrapping); 271261991Sdim IO.mapOptional("BreakBeforeBinaryOperators", 272261991Sdim Style.BreakBeforeBinaryOperators); 273288943Sdim IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces); 274261991Sdim IO.mapOptional("BreakBeforeTernaryOperators", 275261991Sdim Style.BreakBeforeTernaryOperators); 276261991Sdim IO.mapOptional("BreakConstructorInitializersBeforeComma", 277261991Sdim Style.BreakConstructorInitializersBeforeComma); 278261991Sdim IO.mapOptional("ColumnLimit", Style.ColumnLimit); 279288943Sdim IO.mapOptional("CommentPragmas", Style.CommentPragmas); 280261991Sdim IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine", 281261991Sdim Style.ConstructorInitializerAllOnOneLineOrOnePerLine); 282280031Sdim IO.mapOptional("ConstructorInitializerIndentWidth", 283280031Sdim Style.ConstructorInitializerIndentWidth); 284288943Sdim IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth); 285288943Sdim IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle); 286276479Sdim IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment); 287288943Sdim IO.mapOptional("DisableFormat", Style.DisableFormat); 288261991Sdim IO.mapOptional("ExperimentalAutoDetectBinPacking", 289261991Sdim Style.ExperimentalAutoDetectBinPacking); 290288943Sdim IO.mapOptional("ForEachMacros", Style.ForEachMacros); 291296417Sdim IO.mapOptional("IncludeCategories", Style.IncludeCategories); 292261991Sdim IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels); 293288943Sdim IO.mapOptional("IndentWidth", Style.IndentWidth); 294276479Sdim IO.mapOptional("IndentWrappedFunctionNames", 295276479Sdim Style.IndentWrappedFunctionNames); 296276479Sdim IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks", 297276479Sdim Style.KeepEmptyLinesAtTheStartOfBlocks); 298288943Sdim IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin); 299288943Sdim IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd); 300288943Sdim IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep); 301261991Sdim IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation); 302280031Sdim IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth); 303276479Sdim IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty); 304261991Sdim IO.mapOptional("ObjCSpaceBeforeProtocolList", 305261991Sdim Style.ObjCSpaceBeforeProtocolList); 306261991Sdim IO.mapOptional("PenaltyBreakBeforeFirstCallParameter", 307261991Sdim Style.PenaltyBreakBeforeFirstCallParameter); 308261991Sdim IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment); 309261991Sdim IO.mapOptional("PenaltyBreakFirstLessLess", 310261991Sdim Style.PenaltyBreakFirstLessLess); 311288943Sdim IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString); 312261991Sdim IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter); 313261991Sdim IO.mapOptional("PenaltyReturnTypeOnItsOwnLine", 314261991Sdim Style.PenaltyReturnTypeOnItsOwnLine); 315276479Sdim IO.mapOptional("PointerAlignment", Style.PointerAlignment); 316296417Sdim IO.mapOptional("ReflowComments", Style.ReflowComments); 317296417Sdim IO.mapOptional("SortIncludes", Style.SortIncludes); 318288943Sdim IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast); 319288943Sdim IO.mapOptional("SpaceBeforeAssignmentOperators", 320288943Sdim Style.SpaceBeforeAssignmentOperators); 321288943Sdim IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens); 322288943Sdim IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses); 323261991Sdim IO.mapOptional("SpacesBeforeTrailingComments", 324261991Sdim Style.SpacesBeforeTrailingComments); 325288943Sdim IO.mapOptional("SpacesInAngles", Style.SpacesInAngles); 326288943Sdim IO.mapOptional("SpacesInContainerLiterals", 327288943Sdim Style.SpacesInContainerLiterals); 328288943Sdim IO.mapOptional("SpacesInCStyleCastParentheses", 329288943Sdim Style.SpacesInCStyleCastParentheses); 330288943Sdim IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses); 331288943Sdim IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets); 332261991Sdim IO.mapOptional("Standard", Style.Standard); 333261991Sdim IO.mapOptional("TabWidth", Style.TabWidth); 334261991Sdim IO.mapOptional("UseTab", Style.UseTab); 335261991Sdim } 336261991Sdim}; 337276479Sdim 338296417Sdimtemplate <> struct MappingTraits<FormatStyle::BraceWrappingFlags> { 339296417Sdim static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) { 340296417Sdim IO.mapOptional("AfterClass", Wrapping.AfterClass); 341296417Sdim IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement); 342296417Sdim IO.mapOptional("AfterEnum", Wrapping.AfterEnum); 343296417Sdim IO.mapOptional("AfterFunction", Wrapping.AfterFunction); 344296417Sdim IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace); 345296417Sdim IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration); 346296417Sdim IO.mapOptional("AfterStruct", Wrapping.AfterStruct); 347296417Sdim IO.mapOptional("AfterUnion", Wrapping.AfterUnion); 348296417Sdim IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch); 349296417Sdim IO.mapOptional("BeforeElse", Wrapping.BeforeElse); 350296417Sdim IO.mapOptional("IndentBraces", Wrapping.IndentBraces); 351296417Sdim } 352296417Sdim}; 353296417Sdim 354296417Sdimtemplate <> struct MappingTraits<FormatStyle::IncludeCategory> { 355296417Sdim static void mapping(IO &IO, FormatStyle::IncludeCategory &Category) { 356296417Sdim IO.mapOptional("Regex", Category.Regex); 357296417Sdim IO.mapOptional("Priority", Category.Priority); 358296417Sdim } 359296417Sdim}; 360296417Sdim 361276479Sdim// Allows to read vector<FormatStyle> while keeping default values. 362276479Sdim// IO.getContext() should contain a pointer to the FormatStyle structure, that 363276479Sdim// will be used to get default values for missing keys. 364276479Sdim// If the first element has no Language specified, it will be treated as the 365276479Sdim// default one for the following elements. 366288943Sdimtemplate <> struct DocumentListTraits<std::vector<FormatStyle>> { 367276479Sdim static size_t size(IO &IO, std::vector<FormatStyle> &Seq) { 368276479Sdim return Seq.size(); 369276479Sdim } 370276479Sdim static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq, 371276479Sdim size_t Index) { 372276479Sdim if (Index >= Seq.size()) { 373276479Sdim assert(Index == Seq.size()); 374276479Sdim FormatStyle Template; 375276479Sdim if (Seq.size() > 0 && Seq[0].Language == FormatStyle::LK_None) { 376276479Sdim Template = Seq[0]; 377276479Sdim } else { 378276479Sdim Template = *((const FormatStyle *)IO.getContext()); 379276479Sdim Template.Language = FormatStyle::LK_None; 380276479Sdim } 381276479Sdim Seq.resize(Index + 1, Template); 382276479Sdim } 383276479Sdim return Seq[Index]; 384276479Sdim } 385276479Sdim}; 386296417Sdim} // namespace yaml 387296417Sdim} // namespace llvm 388261991Sdim 389249261Sdimnamespace clang { 390249261Sdimnamespace format { 391249261Sdim 392276479Sdimconst std::error_category &getParseCategory() { 393276479Sdim static ParseErrorCategory C; 394276479Sdim return C; 395261991Sdim} 396276479Sdimstd::error_code make_error_code(ParseError e) { 397276479Sdim return std::error_code(static_cast<int>(e), getParseCategory()); 398276479Sdim} 399261991Sdim 400276479Sdimconst char *ParseErrorCategory::name() const LLVM_NOEXCEPT { 401276479Sdim return "clang-format.parse_error"; 402276479Sdim} 403276479Sdim 404276479Sdimstd::string ParseErrorCategory::message(int EV) const { 405276479Sdim switch (static_cast<ParseError>(EV)) { 406276479Sdim case ParseError::Success: 407276479Sdim return "Success"; 408276479Sdim case ParseError::Error: 409276479Sdim return "Invalid argument"; 410276479Sdim case ParseError::Unsuitable: 411276479Sdim return "Unsuitable"; 412276479Sdim } 413276479Sdim llvm_unreachable("unexpected parse error"); 414276479Sdim} 415276479Sdim 416296417Sdimstatic FormatStyle expandPresets(const FormatStyle &Style) { 417296417Sdim if (Style.BreakBeforeBraces == FormatStyle::BS_Custom) 418296417Sdim return Style; 419296417Sdim FormatStyle Expanded = Style; 420296417Sdim Expanded.BraceWrapping = {false, false, false, false, false, false, 421296417Sdim false, false, false, false, false}; 422296417Sdim switch (Style.BreakBeforeBraces) { 423296417Sdim case FormatStyle::BS_Linux: 424296417Sdim Expanded.BraceWrapping.AfterClass = true; 425296417Sdim Expanded.BraceWrapping.AfterFunction = true; 426296417Sdim Expanded.BraceWrapping.AfterNamespace = true; 427296417Sdim break; 428296417Sdim case FormatStyle::BS_Mozilla: 429296417Sdim Expanded.BraceWrapping.AfterClass = true; 430296417Sdim Expanded.BraceWrapping.AfterEnum = true; 431296417Sdim Expanded.BraceWrapping.AfterFunction = true; 432296417Sdim Expanded.BraceWrapping.AfterStruct = true; 433296417Sdim Expanded.BraceWrapping.AfterUnion = true; 434296417Sdim break; 435296417Sdim case FormatStyle::BS_Stroustrup: 436296417Sdim Expanded.BraceWrapping.AfterFunction = true; 437296417Sdim Expanded.BraceWrapping.BeforeCatch = true; 438296417Sdim Expanded.BraceWrapping.BeforeElse = true; 439296417Sdim break; 440296417Sdim case FormatStyle::BS_Allman: 441296417Sdim Expanded.BraceWrapping.AfterClass = true; 442296417Sdim Expanded.BraceWrapping.AfterControlStatement = true; 443296417Sdim Expanded.BraceWrapping.AfterEnum = true; 444296417Sdim Expanded.BraceWrapping.AfterFunction = true; 445296417Sdim Expanded.BraceWrapping.AfterNamespace = true; 446296417Sdim Expanded.BraceWrapping.AfterObjCDeclaration = true; 447296417Sdim Expanded.BraceWrapping.AfterStruct = true; 448296417Sdim Expanded.BraceWrapping.BeforeCatch = true; 449296417Sdim Expanded.BraceWrapping.BeforeElse = true; 450296417Sdim break; 451296417Sdim case FormatStyle::BS_GNU: 452296417Sdim Expanded.BraceWrapping = {true, true, true, true, true, true, 453296417Sdim true, true, true, true, true}; 454296417Sdim break; 455296417Sdim case FormatStyle::BS_WebKit: 456296417Sdim Expanded.BraceWrapping.AfterFunction = true; 457296417Sdim break; 458296417Sdim default: 459296417Sdim break; 460296417Sdim } 461296417Sdim return Expanded; 462296417Sdim} 463296417Sdim 464249261SdimFormatStyle getLLVMStyle() { 465249261Sdim FormatStyle LLVMStyle; 466276479Sdim LLVMStyle.Language = FormatStyle::LK_Cpp; 467251662Sdim LLVMStyle.AccessModifierOffset = -2; 468251662Sdim LLVMStyle.AlignEscapedNewlinesLeft = false; 469296417Sdim LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align; 470280031Sdim LLVMStyle.AlignOperands = true; 471261991Sdim LLVMStyle.AlignTrailingComments = true; 472288943Sdim LLVMStyle.AlignConsecutiveAssignments = false; 473296417Sdim LLVMStyle.AlignConsecutiveDeclarations = false; 474251662Sdim LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; 475276479Sdim LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; 476276479Sdim LLVMStyle.AllowShortBlocksOnASingleLine = false; 477280031Sdim LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; 478251662Sdim LLVMStyle.AllowShortIfStatementsOnASingleLine = false; 479261991Sdim LLVMStyle.AllowShortLoopsOnASingleLine = false; 480296417Sdim LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; 481288943Sdim LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; 482261991Sdim LLVMStyle.AlwaysBreakBeforeMultilineStrings = false; 483261991Sdim LLVMStyle.AlwaysBreakTemplateDeclarations = false; 484251662Sdim LLVMStyle.BinPackParameters = true; 485280031Sdim LLVMStyle.BinPackArguments = true; 486280031Sdim LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None; 487261991Sdim LLVMStyle.BreakBeforeTernaryOperators = true; 488261991Sdim LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach; 489296417Sdim LLVMStyle.BraceWrapping = {false, false, false, false, false, false, 490296417Sdim false, false, false, false, false}; 491261991Sdim LLVMStyle.BreakConstructorInitializersBeforeComma = false; 492296417Sdim LLVMStyle.BreakAfterJavaFieldAnnotations = false; 493249261Sdim LLVMStyle.ColumnLimit = 80; 494276479Sdim LLVMStyle.CommentPragmas = "^ IWYU pragma:"; 495251662Sdim LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false; 496261991Sdim LLVMStyle.ConstructorInitializerIndentWidth = 4; 497276479Sdim LLVMStyle.ContinuationIndentWidth = 4; 498276479Sdim LLVMStyle.Cpp11BracedListStyle = true; 499276479Sdim LLVMStyle.DerivePointerAlignment = false; 500261991Sdim LLVMStyle.ExperimentalAutoDetectBinPacking = false; 501276479Sdim LLVMStyle.ForEachMacros.push_back("foreach"); 502276479Sdim LLVMStyle.ForEachMacros.push_back("Q_FOREACH"); 503276479Sdim LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH"); 504296417Sdim LLVMStyle.IncludeCategories = {{"^\"(llvm|llvm-c|clang|clang-c)/", 2}, 505296417Sdim {"^(<|\"(gtest|isl|json)/)", 3}, 506296417Sdim {".*", 1}}; 507249261Sdim LLVMStyle.IndentCaseLabels = false; 508276479Sdim LLVMStyle.IndentWrappedFunctionNames = false; 509261991Sdim LLVMStyle.IndentWidth = 2; 510261991Sdim LLVMStyle.TabWidth = 8; 511251662Sdim LLVMStyle.MaxEmptyLinesToKeep = 1; 512276479Sdim LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true; 513261991Sdim LLVMStyle.NamespaceIndentation = FormatStyle::NI_None; 514280031Sdim LLVMStyle.ObjCBlockIndentWidth = 2; 515276479Sdim LLVMStyle.ObjCSpaceAfterProperty = false; 516249261Sdim LLVMStyle.ObjCSpaceBeforeProtocolList = true; 517276479Sdim LLVMStyle.PointerAlignment = FormatStyle::PAS_Right; 518251662Sdim LLVMStyle.SpacesBeforeTrailingComments = 1; 519276479Sdim LLVMStyle.Standard = FormatStyle::LS_Cpp11; 520261991Sdim LLVMStyle.UseTab = FormatStyle::UT_Never; 521296417Sdim LLVMStyle.ReflowComments = true; 522261991Sdim LLVMStyle.SpacesInParentheses = false; 523280031Sdim LLVMStyle.SpacesInSquareBrackets = false; 524261991Sdim LLVMStyle.SpaceInEmptyParentheses = false; 525276479Sdim LLVMStyle.SpacesInContainerLiterals = true; 526261991Sdim LLVMStyle.SpacesInCStyleCastParentheses = false; 527280031Sdim LLVMStyle.SpaceAfterCStyleCast = false; 528276479Sdim LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements; 529261991Sdim LLVMStyle.SpaceBeforeAssignmentOperators = true; 530261991Sdim LLVMStyle.SpacesInAngles = false; 531261991Sdim 532276479Sdim LLVMStyle.PenaltyBreakComment = 300; 533276479Sdim LLVMStyle.PenaltyBreakFirstLessLess = 120; 534276479Sdim LLVMStyle.PenaltyBreakString = 1000; 535276479Sdim LLVMStyle.PenaltyExcessCharacter = 1000000; 536261991Sdim LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60; 537261991Sdim LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19; 538261991Sdim 539276479Sdim LLVMStyle.DisableFormat = false; 540296417Sdim LLVMStyle.SortIncludes = true; 541276479Sdim 542249261Sdim return LLVMStyle; 543249261Sdim} 544249261Sdim 545276479SdimFormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { 546276479Sdim FormatStyle GoogleStyle = getLLVMStyle(); 547276479Sdim GoogleStyle.Language = Language; 548276479Sdim 549251662Sdim GoogleStyle.AccessModifierOffset = -1; 550251662Sdim GoogleStyle.AlignEscapedNewlinesLeft = true; 551251662Sdim GoogleStyle.AllowShortIfStatementsOnASingleLine = true; 552261991Sdim GoogleStyle.AllowShortLoopsOnASingleLine = true; 553261991Sdim GoogleStyle.AlwaysBreakBeforeMultilineStrings = true; 554261991Sdim GoogleStyle.AlwaysBreakTemplateDeclarations = true; 555251662Sdim GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true; 556276479Sdim GoogleStyle.DerivePointerAlignment = true; 557296417Sdim GoogleStyle.IncludeCategories = {{"^<.*\\.h>", 1}, {"^<.*", 2}, {".*", 3}}; 558249261Sdim GoogleStyle.IndentCaseLabels = true; 559276479Sdim GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false; 560276479Sdim GoogleStyle.ObjCSpaceAfterProperty = false; 561249261Sdim GoogleStyle.ObjCSpaceBeforeProtocolList = false; 562276479Sdim GoogleStyle.PointerAlignment = FormatStyle::PAS_Left; 563251662Sdim GoogleStyle.SpacesBeforeTrailingComments = 2; 564251662Sdim GoogleStyle.Standard = FormatStyle::LS_Auto; 565261991Sdim 566261991Sdim GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200; 567261991Sdim GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1; 568261991Sdim 569280031Sdim if (Language == FormatStyle::LK_Java) { 570296417Sdim GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; 571280031Sdim GoogleStyle.AlignOperands = false; 572280031Sdim GoogleStyle.AlignTrailingComments = false; 573280031Sdim GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; 574280031Sdim GoogleStyle.AllowShortIfStatementsOnASingleLine = false; 575280031Sdim GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 576280031Sdim GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; 577280031Sdim GoogleStyle.ColumnLimit = 100; 578280031Sdim GoogleStyle.SpaceAfterCStyleCast = true; 579280031Sdim GoogleStyle.SpacesBeforeTrailingComments = 1; 580280031Sdim } else if (Language == FormatStyle::LK_JavaScript) { 581296417Sdim GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; 582296417Sdim GoogleStyle.AlignOperands = false; 583296417Sdim GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 584296417Sdim GoogleStyle.AlwaysBreakBeforeMultilineStrings = false; 585276479Sdim GoogleStyle.BreakBeforeTernaryOperators = false; 586296417Sdim GoogleStyle.CommentPragmas = "@(export|visibility) {"; 587276479Sdim GoogleStyle.MaxEmptyLinesToKeep = 3; 588276479Sdim GoogleStyle.SpacesInContainerLiterals = false; 589276479Sdim } else if (Language == FormatStyle::LK_Proto) { 590276479Sdim GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; 591276479Sdim GoogleStyle.SpacesInContainerLiterals = false; 592276479Sdim } 593276479Sdim 594249261Sdim return GoogleStyle; 595249261Sdim} 596249261Sdim 597276479SdimFormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) { 598276479Sdim FormatStyle ChromiumStyle = getGoogleStyle(Language); 599280031Sdim if (Language == FormatStyle::LK_Java) { 600280031Sdim ChromiumStyle.AllowShortIfStatementsOnASingleLine = true; 601296417Sdim ChromiumStyle.BreakAfterJavaFieldAnnotations = true; 602296417Sdim ChromiumStyle.ContinuationIndentWidth = 8; 603280031Sdim ChromiumStyle.IndentWidth = 4; 604280031Sdim } else { 605280031Sdim ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false; 606280031Sdim ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 607280031Sdim ChromiumStyle.AllowShortIfStatementsOnASingleLine = false; 608280031Sdim ChromiumStyle.AllowShortLoopsOnASingleLine = false; 609280031Sdim ChromiumStyle.BinPackParameters = false; 610280031Sdim ChromiumStyle.DerivePointerAlignment = false; 611280031Sdim } 612296417Sdim ChromiumStyle.SortIncludes = false; 613249261Sdim return ChromiumStyle; 614249261Sdim} 615249261Sdim 616251662SdimFormatStyle getMozillaStyle() { 617251662Sdim FormatStyle MozillaStyle = getLLVMStyle(); 618251662Sdim MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false; 619288943Sdim MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 620296417Sdim MozillaStyle.AlwaysBreakAfterReturnType = 621296417Sdim FormatStyle::RTBS_TopLevelDefinitions; 622288943Sdim MozillaStyle.AlwaysBreakAfterDefinitionReturnType = 623288943Sdim FormatStyle::DRTBS_TopLevel; 624288943Sdim MozillaStyle.AlwaysBreakTemplateDeclarations = true; 625288943Sdim MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla; 626288943Sdim MozillaStyle.BreakConstructorInitializersBeforeComma = true; 627288943Sdim MozillaStyle.ConstructorInitializerIndentWidth = 2; 628288943Sdim MozillaStyle.ContinuationIndentWidth = 2; 629276479Sdim MozillaStyle.Cpp11BracedListStyle = false; 630251662Sdim MozillaStyle.IndentCaseLabels = true; 631276479Sdim MozillaStyle.ObjCSpaceAfterProperty = true; 632251662Sdim MozillaStyle.ObjCSpaceBeforeProtocolList = false; 633251662Sdim MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200; 634276479Sdim MozillaStyle.PointerAlignment = FormatStyle::PAS_Left; 635251662Sdim return MozillaStyle; 636249261Sdim} 637249261Sdim 638261991SdimFormatStyle getWebKitStyle() { 639261991Sdim FormatStyle Style = getLLVMStyle(); 640261991Sdim Style.AccessModifierOffset = -4; 641296417Sdim Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign; 642280031Sdim Style.AlignOperands = false; 643261991Sdim Style.AlignTrailingComments = false; 644280031Sdim Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 645296417Sdim Style.BreakBeforeBraces = FormatStyle::BS_WebKit; 646261991Sdim Style.BreakConstructorInitializersBeforeComma = true; 647276479Sdim Style.Cpp11BracedListStyle = false; 648261991Sdim Style.ColumnLimit = 0; 649261991Sdim Style.IndentWidth = 4; 650261991Sdim Style.NamespaceIndentation = FormatStyle::NI_Inner; 651280031Sdim Style.ObjCBlockIndentWidth = 4; 652276479Sdim Style.ObjCSpaceAfterProperty = true; 653276479Sdim Style.PointerAlignment = FormatStyle::PAS_Left; 654276479Sdim Style.Standard = FormatStyle::LS_Cpp03; 655261991Sdim return Style; 656249261Sdim} 657249261Sdim 658276479SdimFormatStyle getGNUStyle() { 659276479Sdim FormatStyle Style = getLLVMStyle(); 660288943Sdim Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All; 661296417Sdim Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions; 662280031Sdim Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; 663276479Sdim Style.BreakBeforeBraces = FormatStyle::BS_GNU; 664276479Sdim Style.BreakBeforeTernaryOperators = true; 665276479Sdim Style.Cpp11BracedListStyle = false; 666276479Sdim Style.ColumnLimit = 79; 667276479Sdim Style.SpaceBeforeParens = FormatStyle::SBPO_Always; 668276479Sdim Style.Standard = FormatStyle::LS_Cpp03; 669276479Sdim return Style; 670276479Sdim} 671276479Sdim 672276479SdimFormatStyle getNoStyle() { 673276479Sdim FormatStyle NoStyle = getLLVMStyle(); 674276479Sdim NoStyle.DisableFormat = true; 675296417Sdim NoStyle.SortIncludes = false; 676276479Sdim return NoStyle; 677276479Sdim} 678276479Sdim 679276479Sdimbool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language, 680276479Sdim FormatStyle *Style) { 681276479Sdim if (Name.equals_lower("llvm")) { 682261991Sdim *Style = getLLVMStyle(); 683276479Sdim } else if (Name.equals_lower("chromium")) { 684276479Sdim *Style = getChromiumStyle(Language); 685276479Sdim } else if (Name.equals_lower("mozilla")) { 686261991Sdim *Style = getMozillaStyle(); 687276479Sdim } else if (Name.equals_lower("google")) { 688276479Sdim *Style = getGoogleStyle(Language); 689276479Sdim } else if (Name.equals_lower("webkit")) { 690261991Sdim *Style = getWebKitStyle(); 691276479Sdim } else if (Name.equals_lower("gnu")) { 692276479Sdim *Style = getGNUStyle(); 693276479Sdim } else if (Name.equals_lower("none")) { 694276479Sdim *Style = getNoStyle(); 695276479Sdim } else { 696261991Sdim return false; 697276479Sdim } 698249261Sdim 699276479Sdim Style->Language = Language; 700261991Sdim return true; 701261991Sdim} 702249261Sdim 703276479Sdimstd::error_code parseConfiguration(StringRef Text, FormatStyle *Style) { 704276479Sdim assert(Style); 705276479Sdim FormatStyle::LanguageKind Language = Style->Language; 706276479Sdim assert(Language != FormatStyle::LK_None); 707261991Sdim if (Text.trim().empty()) 708276479Sdim return make_error_code(ParseError::Error); 709276479Sdim 710276479Sdim std::vector<FormatStyle> Styles; 711261991Sdim llvm::yaml::Input Input(Text); 712276479Sdim // DocumentListTraits<vector<FormatStyle>> uses the context to get default 713276479Sdim // values for the fields, keys for which are missing from the configuration. 714276479Sdim // Mapping also uses the context to get the language to find the correct 715276479Sdim // base style. 716276479Sdim Input.setContext(Style); 717276479Sdim Input >> Styles; 718276479Sdim if (Input.error()) 719276479Sdim return Input.error(); 720276479Sdim 721276479Sdim for (unsigned i = 0; i < Styles.size(); ++i) { 722276479Sdim // Ensures that only the first configuration can skip the Language option. 723276479Sdim if (Styles[i].Language == FormatStyle::LK_None && i != 0) 724276479Sdim return make_error_code(ParseError::Error); 725276479Sdim // Ensure that each language is configured at most once. 726276479Sdim for (unsigned j = 0; j < i; ++j) { 727276479Sdim if (Styles[i].Language == Styles[j].Language) { 728276479Sdim DEBUG(llvm::dbgs() 729276479Sdim << "Duplicate languages in the config file on positions " << j 730276479Sdim << " and " << i << "\n"); 731276479Sdim return make_error_code(ParseError::Error); 732276479Sdim } 733276479Sdim } 734276479Sdim } 735276479Sdim // Look for a suitable configuration starting from the end, so we can 736276479Sdim // find the configuration for the specific language first, and the default 737276479Sdim // configuration (which can only be at slot 0) after it. 738276479Sdim for (int i = Styles.size() - 1; i >= 0; --i) { 739276479Sdim if (Styles[i].Language == Language || 740276479Sdim Styles[i].Language == FormatStyle::LK_None) { 741276479Sdim *Style = Styles[i]; 742276479Sdim Style->Language = Language; 743276479Sdim return make_error_code(ParseError::Success); 744276479Sdim } 745276479Sdim } 746276479Sdim return make_error_code(ParseError::Unsuitable); 747261991Sdim} 748249261Sdim 749261991Sdimstd::string configurationAsText(const FormatStyle &Style) { 750261991Sdim std::string Text; 751261991Sdim llvm::raw_string_ostream Stream(Text); 752261991Sdim llvm::yaml::Output Output(Stream); 753261991Sdim // We use the same mapping method for input and output, so we need a non-const 754261991Sdim // reference here. 755296417Sdim FormatStyle NonConstStyle = expandPresets(Style); 756261991Sdim Output << NonConstStyle; 757261991Sdim return Stream.str(); 758261991Sdim} 759249261Sdim 760261991Sdimnamespace { 761249261Sdim 762261991Sdimclass FormatTokenLexer { 763249261Sdimpublic: 764280031Sdim FormatTokenLexer(SourceManager &SourceMgr, FileID ID, FormatStyle &Style, 765261991Sdim encoding::Encoding Encoding) 766276479Sdim : FormatTok(nullptr), IsFirstToken(true), GreaterStashed(false), 767288943Sdim LessStashed(false), Column(0), TrailingWhitespace(0), 768288943Sdim SourceMgr(SourceMgr), ID(ID), Style(Style), 769288943Sdim IdentTable(getFormattingLangOpts(Style)), Keywords(IdentTable), 770288943Sdim Encoding(Encoding), FirstInLineIndex(0), FormattingDisabled(false), 771288943Sdim MacroBlockBeginRegex(Style.MacroBlockBegin), 772288943Sdim MacroBlockEndRegex(Style.MacroBlockEnd) { 773280031Sdim Lex.reset(new Lexer(ID, SourceMgr.getBuffer(ID), SourceMgr, 774280031Sdim getFormattingLangOpts(Style))); 775280031Sdim Lex->SetKeepWhitespaceMode(true); 776276479Sdim 777276479Sdim for (const std::string &ForEachMacro : Style.ForEachMacros) 778276479Sdim ForEachMacros.push_back(&IdentTable.get(ForEachMacro)); 779276479Sdim std::sort(ForEachMacros.begin(), ForEachMacros.end()); 780249261Sdim } 781249261Sdim 782261991Sdim ArrayRef<FormatToken *> lex() { 783261991Sdim assert(Tokens.empty()); 784276479Sdim assert(FirstInLineIndex == 0); 785261991Sdim do { 786261991Sdim Tokens.push_back(getNextToken()); 787296417Sdim if (Style.Language == FormatStyle::LK_JavaScript) 788296417Sdim tryParseJSRegexLiteral(); 789276479Sdim tryMergePreviousTokens(); 790288943Sdim if (Tokens.back()->NewlinesBefore > 0 || Tokens.back()->IsMultiline) 791276479Sdim FirstInLineIndex = Tokens.size() - 1; 792261991Sdim } while (Tokens.back()->Tok.isNot(tok::eof)); 793261991Sdim return Tokens; 794261991Sdim } 795261991Sdim 796280031Sdim const AdditionalKeywords &getKeywords() { return Keywords; } 797261991Sdim 798261991Sdimprivate: 799276479Sdim void tryMergePreviousTokens() { 800276479Sdim if (tryMerge_TMacro()) 801276479Sdim return; 802276479Sdim if (tryMergeConflictMarkers()) 803276479Sdim return; 804288943Sdim if (tryMergeLessLess()) 805288943Sdim return; 806276479Sdim 807276479Sdim if (Style.Language == FormatStyle::LK_JavaScript) { 808288943Sdim if (tryMergeTemplateString()) 809288943Sdim return; 810276479Sdim 811288943Sdim static const tok::TokenKind JSIdentity[] = {tok::equalequal, tok::equal}; 812288943Sdim static const tok::TokenKind JSNotIdentity[] = {tok::exclaimequal, 813288943Sdim tok::equal}; 814288943Sdim static const tok::TokenKind JSShiftEqual[] = {tok::greater, tok::greater, 815288943Sdim tok::greaterequal}; 816288943Sdim static const tok::TokenKind JSRightArrow[] = {tok::equal, tok::greater}; 817288943Sdim // FIXME: Investigate what token type gives the correct operator priority. 818288943Sdim if (tryMergeTokens(JSIdentity, TT_BinaryOperator)) 819276479Sdim return; 820288943Sdim if (tryMergeTokens(JSNotIdentity, TT_BinaryOperator)) 821276479Sdim return; 822288943Sdim if (tryMergeTokens(JSShiftEqual, TT_BinaryOperator)) 823276479Sdim return; 824288943Sdim if (tryMergeTokens(JSRightArrow, TT_JsFatArrow)) 825276479Sdim return; 826276479Sdim } 827276479Sdim } 828276479Sdim 829288943Sdim bool tryMergeLessLess() { 830288943Sdim // Merge X,less,less,Y into X,lessless,Y unless X or Y is less. 831288943Sdim if (Tokens.size() < 3) 832288943Sdim return false; 833288943Sdim 834288943Sdim bool FourthTokenIsLess = false; 835288943Sdim if (Tokens.size() > 3) 836288943Sdim FourthTokenIsLess = (Tokens.end() - 4)[0]->is(tok::less); 837288943Sdim 838288943Sdim auto First = Tokens.end() - 3; 839288943Sdim if (First[2]->is(tok::less) || First[1]->isNot(tok::less) || 840288943Sdim First[0]->isNot(tok::less) || FourthTokenIsLess) 841288943Sdim return false; 842288943Sdim 843288943Sdim // Only merge if there currently is no whitespace between the two "<". 844288943Sdim if (First[1]->WhitespaceRange.getBegin() != 845288943Sdim First[1]->WhitespaceRange.getEnd()) 846288943Sdim return false; 847288943Sdim 848288943Sdim First[0]->Tok.setKind(tok::lessless); 849288943Sdim First[0]->TokenText = "<<"; 850288943Sdim First[0]->ColumnWidth += 1; 851288943Sdim Tokens.erase(Tokens.end() - 2); 852288943Sdim return true; 853288943Sdim } 854288943Sdim 855288943Sdim bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds, TokenType NewType) { 856276479Sdim if (Tokens.size() < Kinds.size()) 857276479Sdim return false; 858276479Sdim 859276479Sdim SmallVectorImpl<FormatToken *>::const_iterator First = 860276479Sdim Tokens.end() - Kinds.size(); 861276479Sdim if (!First[0]->is(Kinds[0])) 862276479Sdim return false; 863276479Sdim unsigned AddLength = 0; 864276479Sdim for (unsigned i = 1; i < Kinds.size(); ++i) { 865288943Sdim if (!First[i]->is(Kinds[i]) || 866288943Sdim First[i]->WhitespaceRange.getBegin() != 867288943Sdim First[i]->WhitespaceRange.getEnd()) 868276479Sdim return false; 869276479Sdim AddLength += First[i]->TokenText.size(); 870276479Sdim } 871276479Sdim Tokens.resize(Tokens.size() - Kinds.size() + 1); 872276479Sdim First[0]->TokenText = StringRef(First[0]->TokenText.data(), 873276479Sdim First[0]->TokenText.size() + AddLength); 874276479Sdim First[0]->ColumnWidth += AddLength; 875288943Sdim First[0]->Type = NewType; 876276479Sdim return true; 877276479Sdim } 878276479Sdim 879296417Sdim // Returns \c true if \p Tok can only be followed by an operand in JavaScript. 880296417Sdim bool precedesOperand(FormatToken *Tok) { 881296417Sdim // NB: This is not entirely correct, as an r_paren can introduce an operand 882296417Sdim // location in e.g. `if (foo) /bar/.exec(...);`. That is a rare enough 883296417Sdim // corner case to not matter in practice, though. 884296417Sdim return Tok->isOneOf(tok::period, tok::l_paren, tok::comma, tok::l_brace, 885296417Sdim tok::r_brace, tok::l_square, tok::semi, tok::exclaim, 886296417Sdim tok::colon, tok::question, tok::tilde) || 887296417Sdim Tok->isOneOf(tok::kw_return, tok::kw_do, tok::kw_case, tok::kw_throw, 888296417Sdim tok::kw_else, tok::kw_new, tok::kw_delete, tok::kw_void, 889296417Sdim tok::kw_typeof, Keywords.kw_instanceof, 890296417Sdim Keywords.kw_in) || 891296417Sdim Tok->isBinaryOperator(); 892296417Sdim } 893296417Sdim 894296417Sdim bool canPrecedeRegexLiteral(FormatToken *Prev) { 895296417Sdim if (!Prev) 896296417Sdim return true; 897296417Sdim 898296417Sdim // Regex literals can only follow after prefix unary operators, not after 899296417Sdim // postfix unary operators. If the '++' is followed by a non-operand 900296417Sdim // introducing token, the slash here is the operand and not the start of a 901296417Sdim // regex. 902296417Sdim if (Prev->isOneOf(tok::plusplus, tok::minusminus)) 903296417Sdim return (Tokens.size() < 3 || precedesOperand(Tokens[Tokens.size() - 3])); 904296417Sdim 905296417Sdim // The previous token must introduce an operand location where regex 906296417Sdim // literals can occur. 907296417Sdim if (!precedesOperand(Prev)) 908276479Sdim return false; 909296417Sdim 910276479Sdim return true; 911276479Sdim } 912276479Sdim 913296417Sdim // Tries to parse a JavaScript Regex literal starting at the current token, 914296417Sdim // if that begins with a slash and is in a location where JavaScript allows 915296417Sdim // regex literals. Changes the current token to a regex literal and updates 916296417Sdim // its text if successful. 917296417Sdim void tryParseJSRegexLiteral() { 918296417Sdim FormatToken *RegexToken = Tokens.back(); 919296417Sdim if (!RegexToken->isOneOf(tok::slash, tok::slashequal)) 920296417Sdim return; 921288943Sdim 922296417Sdim FormatToken *Prev = nullptr; 923296417Sdim for (auto I = Tokens.rbegin() + 1, E = Tokens.rend(); I != E; ++I) { 924296417Sdim // NB: Because previous pointers are not initialized yet, this cannot use 925296417Sdim // Token.getPreviousNonComment. 926296417Sdim if ((*I)->isNot(tok::comment)) { 927296417Sdim Prev = *I; 928296417Sdim break; 929296417Sdim } 930288943Sdim } 931288943Sdim 932296417Sdim if (!canPrecedeRegexLiteral(Prev)) 933296417Sdim return; 934288943Sdim 935296417Sdim // 'Manually' lex ahead in the current file buffer. 936296417Sdim const char *Offset = Lex->getBufferLocation(); 937296417Sdim const char *RegexBegin = Offset - RegexToken->TokenText.size(); 938296417Sdim StringRef Buffer = Lex->getBuffer(); 939296417Sdim bool InCharacterClass = false; 940296417Sdim bool HaveClosingSlash = false; 941296417Sdim for (; !HaveClosingSlash && Offset != Buffer.end(); ++Offset) { 942296417Sdim // Regular expressions are terminated with a '/', which can only be 943296417Sdim // escaped using '\' or a character class between '[' and ']'. 944296417Sdim // See http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.5. 945296417Sdim switch (*Offset) { 946296417Sdim case '\\': 947296417Sdim // Skip the escaped character. 948296417Sdim ++Offset; 949296417Sdim break; 950296417Sdim case '[': 951296417Sdim InCharacterClass = true; 952296417Sdim break; 953296417Sdim case ']': 954296417Sdim InCharacterClass = false; 955296417Sdim break; 956296417Sdim case '/': 957296417Sdim if (!InCharacterClass) 958296417Sdim HaveClosingSlash = true; 959296417Sdim break; 960276479Sdim } 961296417Sdim } 962276479Sdim 963296417Sdim RegexToken->Type = TT_RegexLiteral; 964296417Sdim // Treat regex literals like other string_literals. 965296417Sdim RegexToken->Tok.setKind(tok::string_literal); 966296417Sdim RegexToken->TokenText = StringRef(RegexBegin, Offset - RegexBegin); 967296417Sdim RegexToken->ColumnWidth = RegexToken->TokenText.size(); 968296417Sdim 969296417Sdim resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset))); 970276479Sdim } 971276479Sdim 972288943Sdim bool tryMergeTemplateString() { 973288943Sdim if (Tokens.size() < 2) 974288943Sdim return false; 975288943Sdim 976288943Sdim FormatToken *EndBacktick = Tokens.back(); 977288943Sdim // Backticks get lexed as tok::unknown tokens. If a template string contains 978288943Sdim // a comment start, it gets lexed as a tok::comment, or tok::unknown if 979288943Sdim // unterminated. 980288943Sdim if (!EndBacktick->isOneOf(tok::comment, tok::string_literal, 981288943Sdim tok::char_constant, tok::unknown)) 982288943Sdim return false; 983288943Sdim size_t CommentBacktickPos = EndBacktick->TokenText.find('`'); 984288943Sdim // Unknown token that's not actually a backtick, or a comment that doesn't 985288943Sdim // contain a backtick. 986288943Sdim if (CommentBacktickPos == StringRef::npos) 987288943Sdim return false; 988288943Sdim 989288943Sdim unsigned TokenCount = 0; 990288943Sdim bool IsMultiline = false; 991288943Sdim unsigned EndColumnInFirstLine = 992288943Sdim EndBacktick->OriginalColumn + EndBacktick->ColumnWidth; 993288943Sdim for (auto I = Tokens.rbegin() + 1, E = Tokens.rend(); I != E; I++) { 994288943Sdim ++TokenCount; 995288943Sdim if (I[0]->IsMultiline) 996288943Sdim IsMultiline = true; 997288943Sdim 998288943Sdim // If there was a preceding template string, this must be the start of a 999288943Sdim // template string, not the end. 1000288943Sdim if (I[0]->is(TT_TemplateString)) 1001288943Sdim return false; 1002288943Sdim 1003288943Sdim if (I[0]->isNot(tok::unknown) || I[0]->TokenText != "`") { 1004288943Sdim // Keep track of the rhs offset of the last token to wrap across lines - 1005288943Sdim // its the rhs offset of the first line of the template string, used to 1006288943Sdim // determine its width. 1007288943Sdim if (I[0]->IsMultiline) 1008288943Sdim EndColumnInFirstLine = I[0]->OriginalColumn + I[0]->ColumnWidth; 1009288943Sdim // If the token has newlines, the token before it (if it exists) is the 1010288943Sdim // rhs end of the previous line. 1011288943Sdim if (I[0]->NewlinesBefore > 0 && (I + 1 != E)) { 1012288943Sdim EndColumnInFirstLine = I[1]->OriginalColumn + I[1]->ColumnWidth; 1013288943Sdim IsMultiline = true; 1014288943Sdim } 1015288943Sdim continue; 1016288943Sdim } 1017288943Sdim 1018288943Sdim Tokens.resize(Tokens.size() - TokenCount); 1019288943Sdim Tokens.back()->Type = TT_TemplateString; 1020288943Sdim const char *EndOffset = 1021288943Sdim EndBacktick->TokenText.data() + 1 + CommentBacktickPos; 1022288943Sdim if (CommentBacktickPos != 0) { 1023288943Sdim // If the backtick was not the first character (e.g. in a comment), 1024288943Sdim // re-lex after the backtick position. 1025288943Sdim SourceLocation Loc = EndBacktick->Tok.getLocation(); 1026288943Sdim resetLexer(SourceMgr.getFileOffset(Loc) + CommentBacktickPos + 1); 1027288943Sdim } 1028288943Sdim Tokens.back()->TokenText = 1029288943Sdim StringRef(Tokens.back()->TokenText.data(), 1030288943Sdim EndOffset - Tokens.back()->TokenText.data()); 1031288943Sdim 1032288943Sdim unsigned EndOriginalColumn = EndBacktick->OriginalColumn; 1033288943Sdim if (EndOriginalColumn == 0) { 1034288943Sdim SourceLocation Loc = EndBacktick->Tok.getLocation(); 1035288943Sdim EndOriginalColumn = SourceMgr.getSpellingColumnNumber(Loc); 1036288943Sdim } 1037288943Sdim // If the ` is further down within the token (e.g. in a comment). 1038288943Sdim EndOriginalColumn += CommentBacktickPos; 1039288943Sdim 1040288943Sdim if (IsMultiline) { 1041288943Sdim // ColumnWidth is from backtick to last token in line. 1042288943Sdim // LastLineColumnWidth is 0 to backtick. 1043288943Sdim // x = `some content 1044288943Sdim // until here`; 1045288943Sdim Tokens.back()->ColumnWidth = 1046288943Sdim EndColumnInFirstLine - Tokens.back()->OriginalColumn; 1047288943Sdim // +1 for the ` itself. 1048288943Sdim Tokens.back()->LastLineColumnWidth = EndOriginalColumn + 1; 1049288943Sdim Tokens.back()->IsMultiline = true; 1050288943Sdim } else { 1051288943Sdim // Token simply spans from start to end, +1 for the ` itself. 1052288943Sdim Tokens.back()->ColumnWidth = 1053288943Sdim EndOriginalColumn - Tokens.back()->OriginalColumn + 1; 1054288943Sdim } 1055288943Sdim return true; 1056288943Sdim } 1057288943Sdim return false; 1058288943Sdim } 1059288943Sdim 1060276479Sdim bool tryMerge_TMacro() { 1061261991Sdim if (Tokens.size() < 4) 1062276479Sdim return false; 1063261991Sdim FormatToken *Last = Tokens.back(); 1064261991Sdim if (!Last->is(tok::r_paren)) 1065276479Sdim return false; 1066261991Sdim 1067261991Sdim FormatToken *String = Tokens[Tokens.size() - 2]; 1068261991Sdim if (!String->is(tok::string_literal) || String->IsMultiline) 1069276479Sdim return false; 1070261991Sdim 1071261991Sdim if (!Tokens[Tokens.size() - 3]->is(tok::l_paren)) 1072276479Sdim return false; 1073261991Sdim 1074261991Sdim FormatToken *Macro = Tokens[Tokens.size() - 4]; 1075261991Sdim if (Macro->TokenText != "_T") 1076276479Sdim return false; 1077261991Sdim 1078261991Sdim const char *Start = Macro->TokenText.data(); 1079261991Sdim const char *End = Last->TokenText.data() + Last->TokenText.size(); 1080261991Sdim String->TokenText = StringRef(Start, End - Start); 1081261991Sdim String->IsFirst = Macro->IsFirst; 1082261991Sdim String->LastNewlineOffset = Macro->LastNewlineOffset; 1083261991Sdim String->WhitespaceRange = Macro->WhitespaceRange; 1084261991Sdim String->OriginalColumn = Macro->OriginalColumn; 1085261991Sdim String->ColumnWidth = encoding::columnWidthWithTabs( 1086261991Sdim String->TokenText, String->OriginalColumn, Style.TabWidth, Encoding); 1087288943Sdim String->NewlinesBefore = Macro->NewlinesBefore; 1088288943Sdim String->HasUnescapedNewline = Macro->HasUnescapedNewline; 1089261991Sdim 1090261991Sdim Tokens.pop_back(); 1091261991Sdim Tokens.pop_back(); 1092261991Sdim Tokens.pop_back(); 1093261991Sdim Tokens.back() = String; 1094276479Sdim return true; 1095261991Sdim } 1096261991Sdim 1097276479Sdim bool tryMergeConflictMarkers() { 1098276479Sdim if (Tokens.back()->NewlinesBefore == 0 && Tokens.back()->isNot(tok::eof)) 1099276479Sdim return false; 1100276479Sdim 1101276479Sdim // Conflict lines look like: 1102276479Sdim // <marker> <text from the vcs> 1103276479Sdim // For example: 1104276479Sdim // >>>>>>> /file/in/file/system at revision 1234 1105276479Sdim // 1106276479Sdim // We merge all tokens in a line that starts with a conflict marker 1107276479Sdim // into a single token with a special token type that the unwrapped line 1108276479Sdim // parser will use to correctly rebuild the underlying code. 1109276479Sdim 1110276479Sdim FileID ID; 1111276479Sdim // Get the position of the first token in the line. 1112276479Sdim unsigned FirstInLineOffset; 1113276479Sdim std::tie(ID, FirstInLineOffset) = SourceMgr.getDecomposedLoc( 1114276479Sdim Tokens[FirstInLineIndex]->getStartOfNonWhitespace()); 1115276479Sdim StringRef Buffer = SourceMgr.getBuffer(ID)->getBuffer(); 1116276479Sdim // Calculate the offset of the start of the current line. 1117276479Sdim auto LineOffset = Buffer.rfind('\n', FirstInLineOffset); 1118276479Sdim if (LineOffset == StringRef::npos) { 1119276479Sdim LineOffset = 0; 1120276479Sdim } else { 1121276479Sdim ++LineOffset; 1122276479Sdim } 1123276479Sdim 1124276479Sdim auto FirstSpace = Buffer.find_first_of(" \n", LineOffset); 1125276479Sdim StringRef LineStart; 1126276479Sdim if (FirstSpace == StringRef::npos) { 1127276479Sdim LineStart = Buffer.substr(LineOffset); 1128276479Sdim } else { 1129276479Sdim LineStart = Buffer.substr(LineOffset, FirstSpace - LineOffset); 1130276479Sdim } 1131276479Sdim 1132276479Sdim TokenType Type = TT_Unknown; 1133276479Sdim if (LineStart == "<<<<<<<" || LineStart == ">>>>") { 1134276479Sdim Type = TT_ConflictStart; 1135276479Sdim } else if (LineStart == "|||||||" || LineStart == "=======" || 1136276479Sdim LineStart == "====") { 1137276479Sdim Type = TT_ConflictAlternative; 1138276479Sdim } else if (LineStart == ">>>>>>>" || LineStart == "<<<<") { 1139276479Sdim Type = TT_ConflictEnd; 1140276479Sdim } 1141276479Sdim 1142276479Sdim if (Type != TT_Unknown) { 1143276479Sdim FormatToken *Next = Tokens.back(); 1144276479Sdim 1145276479Sdim Tokens.resize(FirstInLineIndex + 1); 1146276479Sdim // We do not need to build a complete token here, as we will skip it 1147276479Sdim // during parsing anyway (as we must not touch whitespace around conflict 1148276479Sdim // markers). 1149276479Sdim Tokens.back()->Type = Type; 1150276479Sdim Tokens.back()->Tok.setKind(tok::kw___unknown_anytype); 1151276479Sdim 1152276479Sdim Tokens.push_back(Next); 1153276479Sdim return true; 1154276479Sdim } 1155276479Sdim 1156276479Sdim return false; 1157276479Sdim } 1158276479Sdim 1159288943Sdim FormatToken *getStashedToken() { 1160288943Sdim // Create a synthesized second '>' or '<' token. 1161288943Sdim Token Tok = FormatTok->Tok; 1162288943Sdim StringRef TokenText = FormatTok->TokenText; 1163288943Sdim 1164288943Sdim unsigned OriginalColumn = FormatTok->OriginalColumn; 1165288943Sdim FormatTok = new (Allocator.Allocate()) FormatToken; 1166288943Sdim FormatTok->Tok = Tok; 1167288943Sdim SourceLocation TokLocation = 1168288943Sdim FormatTok->Tok.getLocation().getLocWithOffset(Tok.getLength() - 1); 1169288943Sdim FormatTok->Tok.setLocation(TokLocation); 1170288943Sdim FormatTok->WhitespaceRange = SourceRange(TokLocation, TokLocation); 1171288943Sdim FormatTok->TokenText = TokenText; 1172288943Sdim FormatTok->ColumnWidth = 1; 1173288943Sdim FormatTok->OriginalColumn = OriginalColumn + 1; 1174288943Sdim 1175288943Sdim return FormatTok; 1176288943Sdim } 1177288943Sdim 1178261991Sdim FormatToken *getNextToken() { 1179249261Sdim if (GreaterStashed) { 1180249261Sdim GreaterStashed = false; 1181288943Sdim return getStashedToken(); 1182249261Sdim } 1183288943Sdim if (LessStashed) { 1184288943Sdim LessStashed = false; 1185288943Sdim return getStashedToken(); 1186288943Sdim } 1187249261Sdim 1188261991Sdim FormatTok = new (Allocator.Allocate()) FormatToken; 1189261991Sdim readRawToken(*FormatTok); 1190261991Sdim SourceLocation WhitespaceStart = 1191261991Sdim FormatTok->Tok.getLocation().getLocWithOffset(-TrailingWhitespace); 1192261991Sdim FormatTok->IsFirst = IsFirstToken; 1193261991Sdim IsFirstToken = false; 1194249261Sdim 1195249261Sdim // Consume and record whitespace until we find a significant token. 1196261991Sdim unsigned WhitespaceLength = TrailingWhitespace; 1197261991Sdim while (FormatTok->Tok.is(tok::unknown)) { 1198288943Sdim StringRef Text = FormatTok->TokenText; 1199288943Sdim auto EscapesNewline = [&](int pos) { 1200288943Sdim // A '\r' here is just part of '\r\n'. Skip it. 1201288943Sdim if (pos >= 0 && Text[pos] == '\r') 1202288943Sdim --pos; 1203288943Sdim // See whether there is an odd number of '\' before this. 1204288943Sdim unsigned count = 0; 1205288943Sdim for (; pos >= 0; --pos, ++count) 1206288943Sdim if (Text[pos] != '\\') 1207288943Sdim break; 1208288943Sdim return count & 1; 1209288943Sdim }; 1210288943Sdim // FIXME: This miscounts tok:unknown tokens that are not just 1211288943Sdim // whitespace, e.g. a '`' character. 1212288943Sdim for (int i = 0, e = Text.size(); i != e; ++i) { 1213288943Sdim switch (Text[i]) { 1214261991Sdim case '\n': 1215261991Sdim ++FormatTok->NewlinesBefore; 1216288943Sdim FormatTok->HasUnescapedNewline = !EscapesNewline(i - 1); 1217261991Sdim FormatTok->LastNewlineOffset = WhitespaceLength + i + 1; 1218261991Sdim Column = 0; 1219261991Sdim break; 1220261991Sdim case '\r': 1221288943Sdim FormatTok->LastNewlineOffset = WhitespaceLength + i + 1; 1222288943Sdim Column = 0; 1223288943Sdim break; 1224261991Sdim case '\f': 1225261991Sdim case '\v': 1226261991Sdim Column = 0; 1227261991Sdim break; 1228261991Sdim case ' ': 1229261991Sdim ++Column; 1230261991Sdim break; 1231261991Sdim case '\t': 1232261991Sdim Column += Style.TabWidth - Column % Style.TabWidth; 1233261991Sdim break; 1234261991Sdim case '\\': 1235288943Sdim if (i + 1 == e || (Text[i + 1] != '\r' && Text[i + 1] != '\n')) 1236261991Sdim FormatTok->Type = TT_ImplicitStringLiteral; 1237261991Sdim break; 1238261991Sdim default: 1239261991Sdim FormatTok->Type = TT_ImplicitStringLiteral; 1240261991Sdim break; 1241261991Sdim } 1242296417Sdim if (FormatTok->Type == TT_ImplicitStringLiteral) 1243296417Sdim break; 1244261991Sdim } 1245249261Sdim 1246280031Sdim if (FormatTok->is(TT_ImplicitStringLiteral)) 1247261991Sdim break; 1248261991Sdim WhitespaceLength += FormatTok->Tok.getLength(); 1249249261Sdim 1250261991Sdim readRawToken(*FormatTok); 1251251662Sdim } 1252251662Sdim 1253249261Sdim // In case the token starts with escaped newlines, we want to 1254249261Sdim // take them into account as whitespace - this pattern is quite frequent 1255249261Sdim // in macro definitions. 1256249261Sdim // FIXME: Add a more explicit test. 1257261991Sdim while (FormatTok->TokenText.size() > 1 && FormatTok->TokenText[0] == '\\' && 1258261991Sdim FormatTok->TokenText[1] == '\n') { 1259276479Sdim ++FormatTok->NewlinesBefore; 1260261991Sdim WhitespaceLength += 2; 1261288943Sdim FormatTok->LastNewlineOffset = 2; 1262261991Sdim Column = 0; 1263261991Sdim FormatTok->TokenText = FormatTok->TokenText.substr(2); 1264249261Sdim } 1265249261Sdim 1266261991Sdim FormatTok->WhitespaceRange = SourceRange( 1267261991Sdim WhitespaceStart, WhitespaceStart.getLocWithOffset(WhitespaceLength)); 1268249261Sdim 1269261991Sdim FormatTok->OriginalColumn = Column; 1270261991Sdim 1271261991Sdim TrailingWhitespace = 0; 1272261991Sdim if (FormatTok->Tok.is(tok::comment)) { 1273261991Sdim // FIXME: Add the trimmed whitespace to Column. 1274261991Sdim StringRef UntrimmedText = FormatTok->TokenText; 1275261991Sdim FormatTok->TokenText = FormatTok->TokenText.rtrim(" \t\v\f"); 1276261991Sdim TrailingWhitespace = UntrimmedText.size() - FormatTok->TokenText.size(); 1277261991Sdim } else if (FormatTok->Tok.is(tok::raw_identifier)) { 1278261991Sdim IdentifierInfo &Info = IdentTable.get(FormatTok->TokenText); 1279261991Sdim FormatTok->Tok.setIdentifierInfo(&Info); 1280261991Sdim FormatTok->Tok.setKind(Info.getTokenID()); 1281280031Sdim if (Style.Language == FormatStyle::LK_Java && 1282296417Sdim FormatTok->isOneOf(tok::kw_struct, tok::kw_union, tok::kw_delete, 1283296417Sdim tok::kw_operator)) { 1284280031Sdim FormatTok->Tok.setKind(tok::identifier); 1285280031Sdim FormatTok->Tok.setIdentifierInfo(nullptr); 1286296417Sdim } else if (Style.Language == FormatStyle::LK_JavaScript && 1287296417Sdim FormatTok->isOneOf(tok::kw_struct, tok::kw_union, 1288296417Sdim tok::kw_operator)) { 1289296417Sdim FormatTok->Tok.setKind(tok::identifier); 1290296417Sdim FormatTok->Tok.setIdentifierInfo(nullptr); 1291280031Sdim } 1292261991Sdim } else if (FormatTok->Tok.is(tok::greatergreater)) { 1293261991Sdim FormatTok->Tok.setKind(tok::greater); 1294261991Sdim FormatTok->TokenText = FormatTok->TokenText.substr(0, 1); 1295249261Sdim GreaterStashed = true; 1296288943Sdim } else if (FormatTok->Tok.is(tok::lessless)) { 1297288943Sdim FormatTok->Tok.setKind(tok::less); 1298288943Sdim FormatTok->TokenText = FormatTok->TokenText.substr(0, 1); 1299288943Sdim LessStashed = true; 1300249261Sdim } 1301249261Sdim 1302261991Sdim // Now FormatTok is the next non-whitespace token. 1303261991Sdim 1304261991Sdim StringRef Text = FormatTok->TokenText; 1305261991Sdim size_t FirstNewlinePos = Text.find('\n'); 1306261991Sdim if (FirstNewlinePos == StringRef::npos) { 1307261991Sdim // FIXME: ColumnWidth actually depends on the start column, we need to 1308261991Sdim // take this into account when the token is moved. 1309261991Sdim FormatTok->ColumnWidth = 1310261991Sdim encoding::columnWidthWithTabs(Text, Column, Style.TabWidth, Encoding); 1311261991Sdim Column += FormatTok->ColumnWidth; 1312261991Sdim } else { 1313261991Sdim FormatTok->IsMultiline = true; 1314261991Sdim // FIXME: ColumnWidth actually depends on the start column, we need to 1315261991Sdim // take this into account when the token is moved. 1316261991Sdim FormatTok->ColumnWidth = encoding::columnWidthWithTabs( 1317261991Sdim Text.substr(0, FirstNewlinePos), Column, Style.TabWidth, Encoding); 1318261991Sdim 1319261991Sdim // The last line of the token always starts in column 0. 1320261991Sdim // Thus, the length can be precomputed even in the presence of tabs. 1321261991Sdim FormatTok->LastLineColumnWidth = encoding::columnWidthWithTabs( 1322261991Sdim Text.substr(Text.find_last_of('\n') + 1), 0, Style.TabWidth, 1323261991Sdim Encoding); 1324261991Sdim Column = FormatTok->LastLineColumnWidth; 1325261991Sdim } 1326261991Sdim 1327288943Sdim if (Style.Language == FormatStyle::LK_Cpp) { 1328288943Sdim if (!(Tokens.size() > 0 && Tokens.back()->Tok.getIdentifierInfo() && 1329288943Sdim Tokens.back()->Tok.getIdentifierInfo()->getPPKeywordID() == 1330288943Sdim tok::pp_define) && 1331288943Sdim std::find(ForEachMacros.begin(), ForEachMacros.end(), 1332288943Sdim FormatTok->Tok.getIdentifierInfo()) != ForEachMacros.end()) { 1333288943Sdim FormatTok->Type = TT_ForEachMacro; 1334288943Sdim } else if (FormatTok->is(tok::identifier)) { 1335288943Sdim if (MacroBlockBeginRegex.match(Text)) { 1336288943Sdim FormatTok->Type = TT_MacroBlockBegin; 1337288943Sdim } else if (MacroBlockEndRegex.match(Text)) { 1338288943Sdim FormatTok->Type = TT_MacroBlockEnd; 1339288943Sdim } 1340288943Sdim } 1341288943Sdim } 1342276479Sdim 1343249261Sdim return FormatTok; 1344249261Sdim } 1345249261Sdim 1346261991Sdim FormatToken *FormatTok; 1347261991Sdim bool IsFirstToken; 1348288943Sdim bool GreaterStashed, LessStashed; 1349261991Sdim unsigned Column; 1350261991Sdim unsigned TrailingWhitespace; 1351280031Sdim std::unique_ptr<Lexer> Lex; 1352249261Sdim SourceManager &SourceMgr; 1353280031Sdim FileID ID; 1354261991Sdim FormatStyle &Style; 1355249261Sdim IdentifierTable IdentTable; 1356280031Sdim AdditionalKeywords Keywords; 1357261991Sdim encoding::Encoding Encoding; 1358261991Sdim llvm::SpecificBumpPtrAllocator<FormatToken> Allocator; 1359276479Sdim // Index (in 'Tokens') of the last token that starts a new line. 1360276479Sdim unsigned FirstInLineIndex; 1361261991Sdim SmallVector<FormatToken *, 16> Tokens; 1362276479Sdim SmallVector<IdentifierInfo *, 8> ForEachMacros; 1363249261Sdim 1364280031Sdim bool FormattingDisabled; 1365280031Sdim 1366288943Sdim llvm::Regex MacroBlockBeginRegex; 1367288943Sdim llvm::Regex MacroBlockEndRegex; 1368288943Sdim 1369261991Sdim void readRawToken(FormatToken &Tok) { 1370280031Sdim Lex->LexFromRawLexer(Tok.Tok); 1371261991Sdim Tok.TokenText = StringRef(SourceMgr.getCharacterData(Tok.Tok.getLocation()), 1372261991Sdim Tok.Tok.getLength()); 1373261991Sdim // For formatting, treat unterminated string literals like normal string 1374261991Sdim // literals. 1375276479Sdim if (Tok.is(tok::unknown)) { 1376276479Sdim if (!Tok.TokenText.empty() && Tok.TokenText[0] == '"') { 1377276479Sdim Tok.Tok.setKind(tok::string_literal); 1378276479Sdim Tok.IsUnterminatedLiteral = true; 1379276479Sdim } else if (Style.Language == FormatStyle::LK_JavaScript && 1380276479Sdim Tok.TokenText == "''") { 1381276479Sdim Tok.Tok.setKind(tok::char_constant); 1382276479Sdim } 1383261991Sdim } 1384280031Sdim 1385280031Sdim if (Tok.is(tok::comment) && (Tok.TokenText == "// clang-format on" || 1386280031Sdim Tok.TokenText == "/* clang-format on */")) { 1387280031Sdim FormattingDisabled = false; 1388280031Sdim } 1389280031Sdim 1390280031Sdim Tok.Finalized = FormattingDisabled; 1391280031Sdim 1392280031Sdim if (Tok.is(tok::comment) && (Tok.TokenText == "// clang-format off" || 1393280031Sdim Tok.TokenText == "/* clang-format off */")) { 1394280031Sdim FormattingDisabled = true; 1395280031Sdim } 1396249261Sdim } 1397280031Sdim 1398280031Sdim void resetLexer(unsigned Offset) { 1399280031Sdim StringRef Buffer = SourceMgr.getBufferData(ID); 1400280031Sdim Lex.reset(new Lexer(SourceMgr.getLocForStartOfFile(ID), 1401280031Sdim getFormattingLangOpts(Style), Buffer.begin(), 1402280031Sdim Buffer.begin() + Offset, Buffer.end())); 1403280031Sdim Lex->SetKeepWhitespaceMode(true); 1404288943Sdim TrailingWhitespace = 0; 1405280031Sdim } 1406249261Sdim}; 1407249261Sdim 1408276479Sdimstatic StringRef getLanguageName(FormatStyle::LanguageKind Language) { 1409276479Sdim switch (Language) { 1410276479Sdim case FormatStyle::LK_Cpp: 1411276479Sdim return "C++"; 1412280031Sdim case FormatStyle::LK_Java: 1413280031Sdim return "Java"; 1414276479Sdim case FormatStyle::LK_JavaScript: 1415276479Sdim return "JavaScript"; 1416276479Sdim case FormatStyle::LK_Proto: 1417276479Sdim return "Proto"; 1418276479Sdim default: 1419276479Sdim return "Unknown"; 1420276479Sdim } 1421276479Sdim} 1422276479Sdim 1423249261Sdimclass Formatter : public UnwrappedLineConsumer { 1424249261Sdimpublic: 1425280031Sdim Formatter(const FormatStyle &Style, SourceManager &SourceMgr, FileID ID, 1426280031Sdim ArrayRef<CharSourceRange> Ranges) 1427280031Sdim : Style(Style), ID(ID), SourceMgr(SourceMgr), 1428280031Sdim Whitespaces(SourceMgr, Style, 1429280031Sdim inputUsesCRLF(SourceMgr.getBufferData(ID))), 1430261991Sdim Ranges(Ranges.begin(), Ranges.end()), UnwrappedLines(1), 1431280031Sdim Encoding(encoding::detectEncoding(SourceMgr.getBufferData(ID))) { 1432261991Sdim DEBUG(llvm::dbgs() << "File encoding: " 1433261991Sdim << (Encoding == encoding::Encoding_UTF8 ? "UTF8" 1434261991Sdim : "unknown") 1435261991Sdim << "\n"); 1436276479Sdim DEBUG(llvm::dbgs() << "Language: " << getLanguageName(Style.Language) 1437276479Sdim << "\n"); 1438261991Sdim } 1439249261Sdim 1440288943Sdim tooling::Replacements format(bool *IncompleteFormat) { 1441261991Sdim tooling::Replacements Result; 1442280031Sdim FormatTokenLexer Tokens(SourceMgr, ID, Style, Encoding); 1443249261Sdim 1444280031Sdim UnwrappedLineParser Parser(Style, Tokens.getKeywords(), Tokens.lex(), 1445280031Sdim *this); 1446288943Sdim Parser.parse(); 1447261991Sdim assert(UnwrappedLines.rbegin()->empty()); 1448261991Sdim for (unsigned Run = 0, RunE = UnwrappedLines.size(); Run + 1 != RunE; 1449261991Sdim ++Run) { 1450261991Sdim DEBUG(llvm::dbgs() << "Run " << Run << "...\n"); 1451261991Sdim SmallVector<AnnotatedLine *, 16> AnnotatedLines; 1452261991Sdim for (unsigned i = 0, e = UnwrappedLines[Run].size(); i != e; ++i) { 1453261991Sdim AnnotatedLines.push_back(new AnnotatedLine(UnwrappedLines[Run][i])); 1454261991Sdim } 1455261991Sdim tooling::Replacements RunResult = 1456288943Sdim format(AnnotatedLines, Tokens, IncompleteFormat); 1457261991Sdim DEBUG({ 1458261991Sdim llvm::dbgs() << "Replacements for run " << Run << ":\n"; 1459261991Sdim for (tooling::Replacements::iterator I = RunResult.begin(), 1460261991Sdim E = RunResult.end(); 1461261991Sdim I != E; ++I) { 1462261991Sdim llvm::dbgs() << I->toString() << "\n"; 1463261991Sdim } 1464261991Sdim }); 1465261991Sdim for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1466261991Sdim delete AnnotatedLines[i]; 1467261991Sdim } 1468261991Sdim Result.insert(RunResult.begin(), RunResult.end()); 1469261991Sdim Whitespaces.reset(); 1470261991Sdim } 1471261991Sdim return Result; 1472261991Sdim } 1473261991Sdim 1474261991Sdim tooling::Replacements format(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines, 1475288943Sdim FormatTokenLexer &Tokens, 1476288943Sdim bool *IncompleteFormat) { 1477280031Sdim TokenAnnotator Annotator(Style, Tokens.getKeywords()); 1478249261Sdim for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1479261991Sdim Annotator.annotate(*AnnotatedLines[i]); 1480249261Sdim } 1481261991Sdim deriveLocalStyle(AnnotatedLines); 1482249261Sdim for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1483261991Sdim Annotator.calculateFormattingInformation(*AnnotatedLines[i]); 1484251662Sdim } 1485276479Sdim computeAffectedLines(AnnotatedLines.begin(), AnnotatedLines.end()); 1486249261Sdim 1487261991Sdim Annotator.setCommentLineLevels(AnnotatedLines); 1488280031Sdim ContinuationIndenter Indenter(Style, Tokens.getKeywords(), SourceMgr, 1489280031Sdim Whitespaces, Encoding, 1490261991Sdim BinPackInconclusiveFunctions); 1491288943Sdim UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, Tokens.getKeywords(), 1492288943Sdim IncompleteFormat) 1493288943Sdim .format(AnnotatedLines); 1494249261Sdim return Whitespaces.generateReplacements(); 1495249261Sdim } 1496249261Sdim 1497249261Sdimprivate: 1498276479Sdim // Determines which lines are affected by the SourceRanges given as input. 1499276479Sdim // Returns \c true if at least one line between I and E or one of their 1500276479Sdim // children is affected. 1501276479Sdim bool computeAffectedLines(SmallVectorImpl<AnnotatedLine *>::iterator I, 1502276479Sdim SmallVectorImpl<AnnotatedLine *>::iterator E) { 1503276479Sdim bool SomeLineAffected = false; 1504276479Sdim const AnnotatedLine *PreviousLine = nullptr; 1505276479Sdim while (I != E) { 1506276479Sdim AnnotatedLine *Line = *I; 1507276479Sdim Line->LeadingEmptyLinesAffected = affectsLeadingEmptyLines(*Line->First); 1508276479Sdim 1509276479Sdim // If a line is part of a preprocessor directive, it needs to be formatted 1510276479Sdim // if any token within the directive is affected. 1511276479Sdim if (Line->InPPDirective) { 1512276479Sdim FormatToken *Last = Line->Last; 1513276479Sdim SmallVectorImpl<AnnotatedLine *>::iterator PPEnd = I + 1; 1514276479Sdim while (PPEnd != E && !(*PPEnd)->First->HasUnescapedNewline) { 1515276479Sdim Last = (*PPEnd)->Last; 1516276479Sdim ++PPEnd; 1517276479Sdim } 1518276479Sdim 1519276479Sdim if (affectsTokenRange(*Line->First, *Last, 1520276479Sdim /*IncludeLeadingNewlines=*/false)) { 1521276479Sdim SomeLineAffected = true; 1522276479Sdim markAllAsAffected(I, PPEnd); 1523276479Sdim } 1524276479Sdim I = PPEnd; 1525276479Sdim continue; 1526276479Sdim } 1527276479Sdim 1528276479Sdim if (nonPPLineAffected(Line, PreviousLine)) 1529276479Sdim SomeLineAffected = true; 1530276479Sdim 1531276479Sdim PreviousLine = Line; 1532276479Sdim ++I; 1533276479Sdim } 1534276479Sdim return SomeLineAffected; 1535276479Sdim } 1536276479Sdim 1537276479Sdim // Determines whether 'Line' is affected by the SourceRanges given as input. 1538276479Sdim // Returns \c true if line or one if its children is affected. 1539276479Sdim bool nonPPLineAffected(AnnotatedLine *Line, 1540276479Sdim const AnnotatedLine *PreviousLine) { 1541276479Sdim bool SomeLineAffected = false; 1542276479Sdim Line->ChildrenAffected = 1543276479Sdim computeAffectedLines(Line->Children.begin(), Line->Children.end()); 1544276479Sdim if (Line->ChildrenAffected) 1545276479Sdim SomeLineAffected = true; 1546276479Sdim 1547276479Sdim // Stores whether one of the line's tokens is directly affected. 1548276479Sdim bool SomeTokenAffected = false; 1549276479Sdim // Stores whether we need to look at the leading newlines of the next token 1550276479Sdim // in order to determine whether it was affected. 1551276479Sdim bool IncludeLeadingNewlines = false; 1552276479Sdim 1553276479Sdim // Stores whether the first child line of any of this line's tokens is 1554276479Sdim // affected. 1555276479Sdim bool SomeFirstChildAffected = false; 1556276479Sdim 1557276479Sdim for (FormatToken *Tok = Line->First; Tok; Tok = Tok->Next) { 1558276479Sdim // Determine whether 'Tok' was affected. 1559276479Sdim if (affectsTokenRange(*Tok, *Tok, IncludeLeadingNewlines)) 1560276479Sdim SomeTokenAffected = true; 1561276479Sdim 1562276479Sdim // Determine whether the first child of 'Tok' was affected. 1563276479Sdim if (!Tok->Children.empty() && Tok->Children.front()->Affected) 1564276479Sdim SomeFirstChildAffected = true; 1565276479Sdim 1566276479Sdim IncludeLeadingNewlines = Tok->Children.empty(); 1567276479Sdim } 1568276479Sdim 1569276479Sdim // Was this line moved, i.e. has it previously been on the same line as an 1570276479Sdim // affected line? 1571276479Sdim bool LineMoved = PreviousLine && PreviousLine->Affected && 1572276479Sdim Line->First->NewlinesBefore == 0; 1573276479Sdim 1574276479Sdim bool IsContinuedComment = 1575276479Sdim Line->First->is(tok::comment) && Line->First->Next == nullptr && 1576276479Sdim Line->First->NewlinesBefore < 2 && PreviousLine && 1577276479Sdim PreviousLine->Affected && PreviousLine->Last->is(tok::comment); 1578276479Sdim 1579276479Sdim if (SomeTokenAffected || SomeFirstChildAffected || LineMoved || 1580276479Sdim IsContinuedComment) { 1581276479Sdim Line->Affected = true; 1582276479Sdim SomeLineAffected = true; 1583276479Sdim } 1584276479Sdim return SomeLineAffected; 1585276479Sdim } 1586276479Sdim 1587276479Sdim // Marks all lines between I and E as well as all their children as affected. 1588276479Sdim void markAllAsAffected(SmallVectorImpl<AnnotatedLine *>::iterator I, 1589276479Sdim SmallVectorImpl<AnnotatedLine *>::iterator E) { 1590276479Sdim while (I != E) { 1591276479Sdim (*I)->Affected = true; 1592276479Sdim markAllAsAffected((*I)->Children.begin(), (*I)->Children.end()); 1593276479Sdim ++I; 1594276479Sdim } 1595276479Sdim } 1596276479Sdim 1597276479Sdim // Returns true if the range from 'First' to 'Last' intersects with one of the 1598276479Sdim // input ranges. 1599276479Sdim bool affectsTokenRange(const FormatToken &First, const FormatToken &Last, 1600276479Sdim bool IncludeLeadingNewlines) { 1601276479Sdim SourceLocation Start = First.WhitespaceRange.getBegin(); 1602276479Sdim if (!IncludeLeadingNewlines) 1603276479Sdim Start = Start.getLocWithOffset(First.LastNewlineOffset); 1604276479Sdim SourceLocation End = Last.getStartOfNonWhitespace(); 1605280031Sdim End = End.getLocWithOffset(Last.TokenText.size()); 1606276479Sdim CharSourceRange Range = CharSourceRange::getCharRange(Start, End); 1607276479Sdim return affectsCharSourceRange(Range); 1608276479Sdim } 1609276479Sdim 1610276479Sdim // Returns true if one of the input ranges intersect the leading empty lines 1611276479Sdim // before 'Tok'. 1612276479Sdim bool affectsLeadingEmptyLines(const FormatToken &Tok) { 1613276479Sdim CharSourceRange EmptyLineRange = CharSourceRange::getCharRange( 1614276479Sdim Tok.WhitespaceRange.getBegin(), 1615276479Sdim Tok.WhitespaceRange.getBegin().getLocWithOffset(Tok.LastNewlineOffset)); 1616276479Sdim return affectsCharSourceRange(EmptyLineRange); 1617276479Sdim } 1618276479Sdim 1619276479Sdim // Returns true if 'Range' intersects with one of the input ranges. 1620276479Sdim bool affectsCharSourceRange(const CharSourceRange &Range) { 1621276479Sdim for (SmallVectorImpl<CharSourceRange>::const_iterator I = Ranges.begin(), 1622276479Sdim E = Ranges.end(); 1623276479Sdim I != E; ++I) { 1624276479Sdim if (!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), I->getBegin()) && 1625276479Sdim !SourceMgr.isBeforeInTranslationUnit(I->getEnd(), Range.getBegin())) 1626276479Sdim return true; 1627276479Sdim } 1628276479Sdim return false; 1629276479Sdim } 1630276479Sdim 1631261991Sdim static bool inputUsesCRLF(StringRef Text) { 1632261991Sdim return Text.count('\r') * 2 > Text.count('\n'); 1633261991Sdim } 1634261991Sdim 1635296417Sdim bool 1636296417Sdim hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) { 1637296417Sdim for (const AnnotatedLine* Line : Lines) { 1638296417Sdim if (hasCpp03IncompatibleFormat(Line->Children)) 1639296417Sdim return true; 1640296417Sdim for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) { 1641296417Sdim if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) { 1642296417Sdim if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener)) 1643296417Sdim return true; 1644296417Sdim if (Tok->is(TT_TemplateCloser) && 1645296417Sdim Tok->Previous->is(TT_TemplateCloser)) 1646296417Sdim return true; 1647296417Sdim } 1648296417Sdim } 1649296417Sdim } 1650296417Sdim return false; 1651296417Sdim } 1652296417Sdim 1653296417Sdim int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) { 1654296417Sdim int AlignmentDiff = 0; 1655296417Sdim for (const AnnotatedLine* Line : Lines) { 1656296417Sdim AlignmentDiff += countVariableAlignments(Line->Children); 1657296417Sdim for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) { 1658296417Sdim if (!Tok->is(TT_PointerOrReference)) 1659296417Sdim continue; 1660296417Sdim bool SpaceBefore = 1661296417Sdim Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd(); 1662296417Sdim bool SpaceAfter = Tok->Next->WhitespaceRange.getBegin() != 1663296417Sdim Tok->Next->WhitespaceRange.getEnd(); 1664296417Sdim if (SpaceBefore && !SpaceAfter) 1665296417Sdim ++AlignmentDiff; 1666296417Sdim if (!SpaceBefore && SpaceAfter) 1667296417Sdim --AlignmentDiff; 1668296417Sdim } 1669296417Sdim } 1670296417Sdim return AlignmentDiff; 1671296417Sdim } 1672296417Sdim 1673261991Sdim void 1674261991Sdim deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { 1675261991Sdim bool HasBinPackedFunction = false; 1676261991Sdim bool HasOnePerLineFunction = false; 1677249261Sdim for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) { 1678261991Sdim if (!AnnotatedLines[i]->First->Next) 1679249261Sdim continue; 1680261991Sdim FormatToken *Tok = AnnotatedLines[i]->First->Next; 1681261991Sdim while (Tok->Next) { 1682261991Sdim if (Tok->PackingKind == PPK_BinPacked) 1683261991Sdim HasBinPackedFunction = true; 1684261991Sdim if (Tok->PackingKind == PPK_OnePerLine) 1685261991Sdim HasOnePerLineFunction = true; 1686261991Sdim 1687261991Sdim Tok = Tok->Next; 1688249261Sdim } 1689249261Sdim } 1690296417Sdim if (Style.DerivePointerAlignment) 1691296417Sdim Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0 1692296417Sdim ? FormatStyle::PAS_Left 1693296417Sdim : FormatStyle::PAS_Right; 1694296417Sdim if (Style.Standard == FormatStyle::LS_Auto) 1695296417Sdim Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines) 1696296417Sdim ? FormatStyle::LS_Cpp11 1697296417Sdim : FormatStyle::LS_Cpp03; 1698261991Sdim BinPackInconclusiveFunctions = 1699261991Sdim HasBinPackedFunction || !HasOnePerLineFunction; 1700249261Sdim } 1701249261Sdim 1702276479Sdim void consumeUnwrappedLine(const UnwrappedLine &TheLine) override { 1703261991Sdim assert(!UnwrappedLines.empty()); 1704261991Sdim UnwrappedLines.back().push_back(TheLine); 1705249261Sdim } 1706249261Sdim 1707276479Sdim void finishRun() override { 1708261991Sdim UnwrappedLines.push_back(SmallVector<UnwrappedLine, 16>()); 1709249261Sdim } 1710249261Sdim 1711261991Sdim FormatStyle Style; 1712280031Sdim FileID ID; 1713261991Sdim SourceManager &SourceMgr; 1714261991Sdim WhitespaceManager Whitespaces; 1715261991Sdim SmallVector<CharSourceRange, 8> Ranges; 1716261991Sdim SmallVector<SmallVector<UnwrappedLine, 16>, 2> UnwrappedLines; 1717249261Sdim 1718261991Sdim encoding::Encoding Encoding; 1719261991Sdim bool BinPackInconclusiveFunctions; 1720261991Sdim}; 1721249261Sdim 1722296417Sdimstruct IncludeDirective { 1723296417Sdim StringRef Filename; 1724296417Sdim StringRef Text; 1725296417Sdim unsigned Offset; 1726296417Sdim int Category; 1727296417Sdim}; 1728296417Sdim 1729261991Sdim} // end anonymous namespace 1730249261Sdim 1731296417Sdim// Determines whether 'Ranges' intersects with ('Start', 'End'). 1732296417Sdimstatic bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start, 1733296417Sdim unsigned End) { 1734296417Sdim for (auto Range : Ranges) { 1735296417Sdim if (Range.getOffset() < End && 1736296417Sdim Range.getOffset() + Range.getLength() > Start) 1737296417Sdim return true; 1738296417Sdim } 1739296417Sdim return false; 1740296417Sdim} 1741296417Sdim 1742296417Sdim// Sorts a block of includes given by 'Includes' alphabetically adding the 1743296417Sdim// necessary replacement to 'Replaces'. 'Includes' must be in strict source 1744296417Sdim// order. 1745296417Sdimstatic void sortIncludes(const FormatStyle &Style, 1746296417Sdim const SmallVectorImpl<IncludeDirective> &Includes, 1747296417Sdim ArrayRef<tooling::Range> Ranges, StringRef FileName, 1748296417Sdim tooling::Replacements &Replaces, unsigned *Cursor) { 1749296417Sdim if (!affectsRange(Ranges, Includes.front().Offset, 1750296417Sdim Includes.back().Offset + Includes.back().Text.size())) 1751296417Sdim return; 1752296417Sdim SmallVector<unsigned, 16> Indices; 1753296417Sdim for (unsigned i = 0, e = Includes.size(); i != e; ++i) 1754296417Sdim Indices.push_back(i); 1755296417Sdim std::sort(Indices.begin(), Indices.end(), [&](unsigned LHSI, unsigned RHSI) { 1756296417Sdim return std::tie(Includes[LHSI].Category, Includes[LHSI].Filename) < 1757296417Sdim std::tie(Includes[RHSI].Category, Includes[RHSI].Filename); 1758296417Sdim }); 1759296417Sdim 1760296417Sdim // If the #includes are out of order, we generate a single replacement fixing 1761296417Sdim // the entire block. Otherwise, no replacement is generated. 1762296417Sdim bool OutOfOrder = false; 1763296417Sdim for (unsigned i = 1, e = Indices.size(); i != e; ++i) { 1764296417Sdim if (Indices[i] != i) { 1765296417Sdim OutOfOrder = true; 1766296417Sdim break; 1767296417Sdim } 1768296417Sdim } 1769296417Sdim if (!OutOfOrder) 1770296417Sdim return; 1771296417Sdim 1772296417Sdim std::string result; 1773296417Sdim bool CursorMoved = false; 1774296417Sdim for (unsigned Index : Indices) { 1775296417Sdim if (!result.empty()) 1776296417Sdim result += "\n"; 1777296417Sdim result += Includes[Index].Text; 1778296417Sdim 1779296417Sdim if (Cursor && !CursorMoved) { 1780296417Sdim unsigned Start = Includes[Index].Offset; 1781296417Sdim unsigned End = Start + Includes[Index].Text.size(); 1782296417Sdim if (*Cursor >= Start && *Cursor < End) { 1783296417Sdim *Cursor = Includes.front().Offset + result.size() + *Cursor - End; 1784296417Sdim CursorMoved = true; 1785296417Sdim } 1786296417Sdim } 1787296417Sdim } 1788296417Sdim 1789296417Sdim // Sorting #includes shouldn't change their total number of characters. 1790296417Sdim // This would otherwise mess up 'Ranges'. 1791296417Sdim assert(result.size() == 1792296417Sdim Includes.back().Offset + Includes.back().Text.size() - 1793296417Sdim Includes.front().Offset); 1794296417Sdim 1795296417Sdim Replaces.insert(tooling::Replacement(FileName, Includes.front().Offset, 1796296417Sdim result.size(), result)); 1797296417Sdim} 1798296417Sdim 1799296417Sdimtooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, 1800296417Sdim ArrayRef<tooling::Range> Ranges, 1801296417Sdim StringRef FileName, unsigned *Cursor) { 1802296417Sdim tooling::Replacements Replaces; 1803296417Sdim if (!Style.SortIncludes) 1804296417Sdim return Replaces; 1805296417Sdim 1806296417Sdim unsigned Prev = 0; 1807296417Sdim unsigned SearchFrom = 0; 1808296417Sdim llvm::Regex IncludeRegex( 1809296417Sdim R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))"); 1810296417Sdim SmallVector<StringRef, 4> Matches; 1811296417Sdim SmallVector<IncludeDirective, 16> IncludesInBlock; 1812296417Sdim 1813296417Sdim // In compiled files, consider the first #include to be the main #include of 1814296417Sdim // the file if it is not a system #include. This ensures that the header 1815296417Sdim // doesn't have hidden dependencies 1816296417Sdim // (http://llvm.org/docs/CodingStandards.html#include-style). 1817296417Sdim // 1818296417Sdim // FIXME: Do some sanity checking, e.g. edit distance of the base name, to fix 1819296417Sdim // cases where the first #include is unlikely to be the main header. 1820296417Sdim bool IsSource = FileName.endswith(".c") || FileName.endswith(".cc") || 1821296417Sdim FileName.endswith(".cpp") || FileName.endswith(".c++") || 1822296417Sdim FileName.endswith(".cxx") || FileName.endswith(".m") || 1823296417Sdim FileName.endswith(".mm"); 1824296417Sdim StringRef FileStem = llvm::sys::path::stem(FileName); 1825296417Sdim bool FirstIncludeBlock = true; 1826296417Sdim bool MainIncludeFound = false; 1827296417Sdim 1828296417Sdim // Create pre-compiled regular expressions for the #include categories. 1829296417Sdim SmallVector<llvm::Regex, 4> CategoryRegexs; 1830296417Sdim for (const auto &Category : Style.IncludeCategories) 1831296417Sdim CategoryRegexs.emplace_back(Category.Regex); 1832296417Sdim 1833296417Sdim bool FormattingOff = false; 1834296417Sdim 1835296417Sdim for (;;) { 1836296417Sdim auto Pos = Code.find('\n', SearchFrom); 1837296417Sdim StringRef Line = 1838296417Sdim Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev); 1839296417Sdim 1840296417Sdim StringRef Trimmed = Line.trim(); 1841296417Sdim if (Trimmed == "// clang-format off") 1842296417Sdim FormattingOff = true; 1843296417Sdim else if (Trimmed == "// clang-format on") 1844296417Sdim FormattingOff = false; 1845296417Sdim 1846296417Sdim if (!FormattingOff && !Line.endswith("\\")) { 1847296417Sdim if (IncludeRegex.match(Line, &Matches)) { 1848296417Sdim StringRef IncludeName = Matches[2]; 1849296417Sdim int Category = INT_MAX; 1850296417Sdim for (unsigned i = 0, e = CategoryRegexs.size(); i != e; ++i) { 1851296417Sdim if (CategoryRegexs[i].match(IncludeName)) { 1852296417Sdim Category = Style.IncludeCategories[i].Priority; 1853296417Sdim break; 1854296417Sdim } 1855296417Sdim } 1856296417Sdim if (IsSource && !MainIncludeFound && Category > 0 && 1857296417Sdim FirstIncludeBlock && IncludeName.startswith("\"")) { 1858296417Sdim StringRef HeaderStem = 1859296417Sdim llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(1)); 1860296417Sdim if (FileStem.startswith(HeaderStem)) { 1861296417Sdim Category = 0; 1862296417Sdim MainIncludeFound = true; 1863296417Sdim } 1864296417Sdim } 1865296417Sdim IncludesInBlock.push_back({IncludeName, Line, Prev, Category}); 1866296417Sdim } else if (!IncludesInBlock.empty()) { 1867296417Sdim sortIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces, 1868296417Sdim Cursor); 1869296417Sdim IncludesInBlock.clear(); 1870296417Sdim FirstIncludeBlock = false; 1871296417Sdim } 1872296417Sdim Prev = Pos + 1; 1873296417Sdim } 1874296417Sdim if (Pos == StringRef::npos || Pos + 1 == Code.size()) 1875296417Sdim break; 1876296417Sdim SearchFrom = Pos + 1; 1877296417Sdim } 1878296417Sdim if (!IncludesInBlock.empty()) 1879296417Sdim sortIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces, Cursor); 1880296417Sdim return Replaces; 1881296417Sdim} 1882296417Sdim 1883280031Sdimtooling::Replacements reformat(const FormatStyle &Style, 1884280031Sdim SourceManager &SourceMgr, FileID ID, 1885288943Sdim ArrayRef<CharSourceRange> Ranges, 1886288943Sdim bool *IncompleteFormat) { 1887296417Sdim FormatStyle Expanded = expandPresets(Style); 1888296417Sdim if (Expanded.DisableFormat) 1889280031Sdim return tooling::Replacements(); 1890296417Sdim Formatter formatter(Expanded, SourceMgr, ID, Ranges); 1891288943Sdim return formatter.format(IncompleteFormat); 1892261991Sdim} 1893249261Sdim 1894261991Sdimtooling::Replacements reformat(const FormatStyle &Style, StringRef Code, 1895280031Sdim ArrayRef<tooling::Range> Ranges, 1896288943Sdim StringRef FileName, bool *IncompleteFormat) { 1897280031Sdim if (Style.DisableFormat) 1898280031Sdim return tooling::Replacements(); 1899280031Sdim 1900296417Sdim IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem( 1901296417Sdim new vfs::InMemoryFileSystem); 1902296417Sdim FileManager Files(FileSystemOptions(), InMemoryFileSystem); 1903261991Sdim DiagnosticsEngine Diagnostics( 1904261991Sdim IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), 1905261991Sdim new DiagnosticOptions); 1906261991Sdim SourceManager SourceMgr(Diagnostics, Files); 1907296417Sdim InMemoryFileSystem->addFile( 1908296417Sdim FileName, 0, llvm::MemoryBuffer::getMemBuffer( 1909296417Sdim Code, FileName, /*RequiresNullTerminator=*/false)); 1910296417Sdim FileID ID = SourceMgr.createFileID(Files.getFile(FileName), SourceLocation(), 1911296417Sdim clang::SrcMgr::C_User); 1912261991Sdim SourceLocation StartOfFile = SourceMgr.getLocForStartOfFile(ID); 1913261991Sdim std::vector<CharSourceRange> CharRanges; 1914280031Sdim for (const tooling::Range &Range : Ranges) { 1915280031Sdim SourceLocation Start = StartOfFile.getLocWithOffset(Range.getOffset()); 1916280031Sdim SourceLocation End = Start.getLocWithOffset(Range.getLength()); 1917261991Sdim CharRanges.push_back(CharSourceRange::getCharRange(Start, End)); 1918249261Sdim } 1919288943Sdim return reformat(Style, SourceMgr, ID, CharRanges, IncompleteFormat); 1920261991Sdim} 1921249261Sdim 1922280031SdimLangOptions getFormattingLangOpts(const FormatStyle &Style) { 1923261991Sdim LangOptions LangOpts; 1924261991Sdim LangOpts.CPlusPlus = 1; 1925280031Sdim LangOpts.CPlusPlus11 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1; 1926280031Sdim LangOpts.CPlusPlus14 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1; 1927261991Sdim LangOpts.LineComment = 1; 1928288943Sdim bool AlternativeOperators = Style.Language == FormatStyle::LK_Cpp; 1929280031Sdim LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0; 1930261991Sdim LangOpts.Bool = 1; 1931261991Sdim LangOpts.ObjC1 = 1; 1932261991Sdim LangOpts.ObjC2 = 1; 1933288943Sdim LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally. 1934296417Sdim LangOpts.DeclSpecKeyword = 1; // To get __declspec. 1935261991Sdim return LangOpts; 1936261991Sdim} 1937249261Sdim 1938261991Sdimconst char *StyleOptionHelpDescription = 1939261991Sdim "Coding style, currently supports:\n" 1940261991Sdim " LLVM, Google, Chromium, Mozilla, WebKit.\n" 1941261991Sdim "Use -style=file to load style configuration from\n" 1942261991Sdim ".clang-format file located in one of the parent\n" 1943261991Sdim "directories of the source file (or current\n" 1944261991Sdim "directory for stdin).\n" 1945261991Sdim "Use -style=\"{key: value, ...}\" to set specific\n" 1946261991Sdim "parameters, e.g.:\n" 1947261991Sdim " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""; 1948249261Sdim 1949276479Sdimstatic FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) { 1950296417Sdim if (FileName.endswith(".java")) 1951280031Sdim return FormatStyle::LK_Java; 1952296417Sdim if (FileName.endswith_lower(".js") || FileName.endswith_lower(".ts")) 1953296417Sdim return FormatStyle::LK_JavaScript; // JavaScript or TypeScript. 1954296417Sdim if (FileName.endswith_lower(".proto") || 1955296417Sdim FileName.endswith_lower(".protodevel")) 1956276479Sdim return FormatStyle::LK_Proto; 1957296417Sdim if (FileName.endswith_lower(".td")) 1958296417Sdim return FormatStyle::LK_TableGen; 1959276479Sdim return FormatStyle::LK_Cpp; 1960276479Sdim} 1961249261Sdim 1962276479SdimFormatStyle getStyle(StringRef StyleName, StringRef FileName, 1963276479Sdim StringRef FallbackStyle) { 1964276479Sdim FormatStyle Style = getLLVMStyle(); 1965276479Sdim Style.Language = getLanguageByFileName(FileName); 1966276479Sdim if (!getPredefinedStyle(FallbackStyle, Style.Language, &Style)) { 1967276479Sdim llvm::errs() << "Invalid fallback style \"" << FallbackStyle 1968276479Sdim << "\" using LLVM style\n"; 1969276479Sdim return Style; 1970276479Sdim } 1971276479Sdim 1972261991Sdim if (StyleName.startswith("{")) { 1973261991Sdim // Parse YAML/JSON style from the command line. 1974276479Sdim if (std::error_code ec = parseConfiguration(StyleName, &Style)) { 1975261991Sdim llvm::errs() << "Error parsing -style: " << ec.message() << ", using " 1976261991Sdim << FallbackStyle << " style\n"; 1977249261Sdim } 1978261991Sdim return Style; 1979249261Sdim } 1980249261Sdim 1981261991Sdim if (!StyleName.equals_lower("file")) { 1982276479Sdim if (!getPredefinedStyle(StyleName, Style.Language, &Style)) 1983261991Sdim llvm::errs() << "Invalid value for -style, using " << FallbackStyle 1984261991Sdim << " style\n"; 1985261991Sdim return Style; 1986249261Sdim } 1987249261Sdim 1988276479Sdim // Look for .clang-format/_clang-format file in the file's parent directories. 1989276479Sdim SmallString<128> UnsuitableConfigFiles; 1990261991Sdim SmallString<128> Path(FileName); 1991261991Sdim llvm::sys::fs::make_absolute(Path); 1992261991Sdim for (StringRef Directory = Path; !Directory.empty(); 1993261991Sdim Directory = llvm::sys::path::parent_path(Directory)) { 1994261991Sdim if (!llvm::sys::fs::is_directory(Directory)) 1995261991Sdim continue; 1996261991Sdim SmallString<128> ConfigFile(Directory); 1997249261Sdim 1998261991Sdim llvm::sys::path::append(ConfigFile, ".clang-format"); 1999261991Sdim DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); 2000261991Sdim bool IsFile = false; 2001261991Sdim // Ignore errors from is_regular_file: we only need to know if we can read 2002261991Sdim // the file or not. 2003261991Sdim llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile); 2004261991Sdim 2005261991Sdim if (!IsFile) { 2006261991Sdim // Try _clang-format too, since dotfiles are not commonly used on Windows. 2007261991Sdim ConfigFile = Directory; 2008261991Sdim llvm::sys::path::append(ConfigFile, "_clang-format"); 2009261991Sdim DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); 2010261991Sdim llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile); 2011249261Sdim } 2012249261Sdim 2013261991Sdim if (IsFile) { 2014276479Sdim llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = 2015276479Sdim llvm::MemoryBuffer::getFile(ConfigFile.c_str()); 2016276479Sdim if (std::error_code EC = Text.getError()) { 2017276479Sdim llvm::errs() << EC.message() << "\n"; 2018276479Sdim break; 2019261991Sdim } 2020276479Sdim if (std::error_code ec = 2021276479Sdim parseConfiguration(Text.get()->getBuffer(), &Style)) { 2022276479Sdim if (ec == ParseError::Unsuitable) { 2023276479Sdim if (!UnsuitableConfigFiles.empty()) 2024276479Sdim UnsuitableConfigFiles.append(", "); 2025276479Sdim UnsuitableConfigFiles.append(ConfigFile); 2026276479Sdim continue; 2027276479Sdim } 2028261991Sdim llvm::errs() << "Error reading " << ConfigFile << ": " << ec.message() 2029261991Sdim << "\n"; 2030276479Sdim break; 2031261991Sdim } 2032261991Sdim DEBUG(llvm::dbgs() << "Using configuration file " << ConfigFile << "\n"); 2033261991Sdim return Style; 2034249261Sdim } 2035249261Sdim } 2036276479Sdim if (!UnsuitableConfigFiles.empty()) { 2037276479Sdim llvm::errs() << "Configuration file(s) do(es) not support " 2038276479Sdim << getLanguageName(Style.Language) << ": " 2039276479Sdim << UnsuitableConfigFiles << "\n"; 2040276479Sdim } 2041261991Sdim return Style; 2042249261Sdim} 2043249261Sdim 2044249261Sdim} // namespace format 2045249261Sdim} // namespace clang 2046