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