xref: /minix3/external/bsd/llvm/dist/clang/lib/Format/Format.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===--- Format.cpp - Format C++ code -------------------------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc ///
10f4a2713aSLionel Sambuc /// \file
11f4a2713aSLionel Sambuc /// \brief This file implements functions declared in Format.h. This will be
12f4a2713aSLionel Sambuc /// split into separate files as we go.
13f4a2713aSLionel Sambuc ///
14f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
15f4a2713aSLionel Sambuc 
16f4a2713aSLionel Sambuc #include "ContinuationIndenter.h"
17f4a2713aSLionel Sambuc #include "TokenAnnotator.h"
18*0a6a1f1dSLionel Sambuc #include "UnwrappedLineFormatter.h"
19f4a2713aSLionel Sambuc #include "UnwrappedLineParser.h"
20f4a2713aSLionel Sambuc #include "WhitespaceManager.h"
21f4a2713aSLionel Sambuc #include "clang/Basic/Diagnostic.h"
22*0a6a1f1dSLionel Sambuc #include "clang/Basic/DiagnosticOptions.h"
23f4a2713aSLionel Sambuc #include "clang/Basic/SourceManager.h"
24f4a2713aSLionel Sambuc #include "clang/Format/Format.h"
25f4a2713aSLionel Sambuc #include "clang/Lex/Lexer.h"
26f4a2713aSLionel Sambuc #include "llvm/ADT/STLExtras.h"
27f4a2713aSLionel Sambuc #include "llvm/Support/Allocator.h"
28f4a2713aSLionel Sambuc #include "llvm/Support/Debug.h"
29f4a2713aSLionel Sambuc #include "llvm/Support/Path.h"
30*0a6a1f1dSLionel Sambuc #include "llvm/Support/YAMLTraits.h"
31f4a2713aSLionel Sambuc #include <queue>
32f4a2713aSLionel Sambuc #include <string>
33f4a2713aSLionel Sambuc 
34*0a6a1f1dSLionel Sambuc #define DEBUG_TYPE "format-formatter"
35*0a6a1f1dSLionel Sambuc 
36*0a6a1f1dSLionel Sambuc using clang::format::FormatStyle;
37*0a6a1f1dSLionel Sambuc 
38*0a6a1f1dSLionel Sambuc LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string)
39*0a6a1f1dSLionel Sambuc 
40f4a2713aSLionel Sambuc namespace llvm {
41f4a2713aSLionel Sambuc namespace yaml {
42*0a6a1f1dSLionel Sambuc template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
enumerationllvm::yaml::ScalarEnumerationTraits43*0a6a1f1dSLionel Sambuc   static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
44*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
45*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Java", FormatStyle::LK_Java);
46*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
47*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
48*0a6a1f1dSLionel Sambuc   }
49*0a6a1f1dSLionel Sambuc };
50*0a6a1f1dSLionel Sambuc 
51*0a6a1f1dSLionel Sambuc template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
enumerationllvm::yaml::ScalarEnumerationTraits52*0a6a1f1dSLionel Sambuc   static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
53*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03);
54*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03);
55*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Cpp11", FormatStyle::LS_Cpp11);
56*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11);
57*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);
58*0a6a1f1dSLionel Sambuc   }
59*0a6a1f1dSLionel Sambuc };
60*0a6a1f1dSLionel Sambuc 
61*0a6a1f1dSLionel Sambuc template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits62*0a6a1f1dSLionel Sambuc   static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {
63*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Never", FormatStyle::UT_Never);
64*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "false", FormatStyle::UT_Never);
65*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Always", FormatStyle::UT_Always);
66*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "true", FormatStyle::UT_Always);
67*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation);
68*0a6a1f1dSLionel Sambuc   }
69*0a6a1f1dSLionel Sambuc };
70*0a6a1f1dSLionel Sambuc 
71*0a6a1f1dSLionel Sambuc template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits72*0a6a1f1dSLionel Sambuc   static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
73*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "None", FormatStyle::SFS_None);
74*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "false", FormatStyle::SFS_None);
75*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "All", FormatStyle::SFS_All);
76*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "true", FormatStyle::SFS_All);
77*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
78*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);
79*0a6a1f1dSLionel Sambuc   }
80*0a6a1f1dSLionel Sambuc };
81*0a6a1f1dSLionel Sambuc 
82*0a6a1f1dSLionel Sambuc template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits83*0a6a1f1dSLionel Sambuc   static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {
84*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "All", FormatStyle::BOS_All);
85*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "true", FormatStyle::BOS_All);
86*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "None", FormatStyle::BOS_None);
87*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "false", FormatStyle::BOS_None);
88*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment);
89*0a6a1f1dSLionel Sambuc   }
90*0a6a1f1dSLionel Sambuc };
91*0a6a1f1dSLionel Sambuc 
92*0a6a1f1dSLionel Sambuc template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits93*0a6a1f1dSLionel Sambuc   static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {
94*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Attach", FormatStyle::BS_Attach);
95*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Linux", FormatStyle::BS_Linux);
96*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);
97*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
98*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
99*0a6a1f1dSLionel Sambuc   }
100*0a6a1f1dSLionel Sambuc };
101*0a6a1f1dSLionel Sambuc 
102f4a2713aSLionel Sambuc template <>
103*0a6a1f1dSLionel Sambuc struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
enumerationllvm::yaml::ScalarEnumerationTraits104f4a2713aSLionel Sambuc   static void enumeration(IO &IO,
105*0a6a1f1dSLionel Sambuc                           FormatStyle::NamespaceIndentationKind &Value) {
106*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "None", FormatStyle::NI_None);
107*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Inner", FormatStyle::NI_Inner);
108*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "All", FormatStyle::NI_All);
109f4a2713aSLionel Sambuc   }
110f4a2713aSLionel Sambuc };
111f4a2713aSLionel Sambuc 
112f4a2713aSLionel Sambuc template <>
113*0a6a1f1dSLionel Sambuc struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits114f4a2713aSLionel Sambuc   static void enumeration(IO &IO,
115*0a6a1f1dSLionel Sambuc                           FormatStyle::PointerAlignmentStyle &Value) {
116*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
117*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Left", FormatStyle::PAS_Left);
118*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Right", FormatStyle::PAS_Right);
119*0a6a1f1dSLionel Sambuc 
120*0a6a1f1dSLionel Sambuc     // For backward compatibility.
121*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "true", FormatStyle::PAS_Left);
122*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "false", FormatStyle::PAS_Right);
123f4a2713aSLionel Sambuc   }
124f4a2713aSLionel Sambuc };
125f4a2713aSLionel Sambuc 
126f4a2713aSLionel Sambuc template <>
127*0a6a1f1dSLionel Sambuc struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
enumerationllvm::yaml::ScalarEnumerationTraits128*0a6a1f1dSLionel Sambuc   static void enumeration(IO &IO,
129*0a6a1f1dSLionel Sambuc                           FormatStyle::SpaceBeforeParensOptions &Value) {
130*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
131*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "ControlStatements",
132*0a6a1f1dSLionel Sambuc                 FormatStyle::SBPO_ControlStatements);
133*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
134*0a6a1f1dSLionel Sambuc 
135*0a6a1f1dSLionel Sambuc     // For backward compatibility.
136*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
137*0a6a1f1dSLionel Sambuc     IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);
138f4a2713aSLionel Sambuc   }
139f4a2713aSLionel Sambuc };
140f4a2713aSLionel Sambuc 
141*0a6a1f1dSLionel Sambuc template <> struct MappingTraits<FormatStyle> {
mappingllvm::yaml::MappingTraits142*0a6a1f1dSLionel Sambuc   static void mapping(IO &IO, FormatStyle &Style) {
143*0a6a1f1dSLionel Sambuc     // When reading, read the language first, we need it for getPredefinedStyle.
144*0a6a1f1dSLionel Sambuc     IO.mapOptional("Language", Style.Language);
145f4a2713aSLionel Sambuc 
146f4a2713aSLionel Sambuc     if (IO.outputting()) {
147f4a2713aSLionel Sambuc       StringRef StylesArray[] = { "LLVM",    "Google", "Chromium",
148*0a6a1f1dSLionel Sambuc                                   "Mozilla", "WebKit", "GNU" };
149f4a2713aSLionel Sambuc       ArrayRef<StringRef> Styles(StylesArray);
150f4a2713aSLionel Sambuc       for (size_t i = 0, e = Styles.size(); i < e; ++i) {
151f4a2713aSLionel Sambuc         StringRef StyleName(Styles[i]);
152*0a6a1f1dSLionel Sambuc         FormatStyle PredefinedStyle;
153*0a6a1f1dSLionel Sambuc         if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) &&
154f4a2713aSLionel Sambuc             Style == PredefinedStyle) {
155f4a2713aSLionel Sambuc           IO.mapOptional("# BasedOnStyle", StyleName);
156f4a2713aSLionel Sambuc           break;
157f4a2713aSLionel Sambuc         }
158f4a2713aSLionel Sambuc       }
159f4a2713aSLionel Sambuc     } else {
160f4a2713aSLionel Sambuc       StringRef BasedOnStyle;
161f4a2713aSLionel Sambuc       IO.mapOptional("BasedOnStyle", BasedOnStyle);
162*0a6a1f1dSLionel Sambuc       if (!BasedOnStyle.empty()) {
163*0a6a1f1dSLionel Sambuc         FormatStyle::LanguageKind OldLanguage = Style.Language;
164*0a6a1f1dSLionel Sambuc         FormatStyle::LanguageKind Language =
165*0a6a1f1dSLionel Sambuc             ((FormatStyle *)IO.getContext())->Language;
166*0a6a1f1dSLionel Sambuc         if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
167f4a2713aSLionel Sambuc           IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle));
168f4a2713aSLionel Sambuc           return;
169f4a2713aSLionel Sambuc         }
170*0a6a1f1dSLionel Sambuc         Style.Language = OldLanguage;
171*0a6a1f1dSLionel Sambuc       }
172f4a2713aSLionel Sambuc     }
173f4a2713aSLionel Sambuc 
174f4a2713aSLionel Sambuc     IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
175*0a6a1f1dSLionel Sambuc     IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
176f4a2713aSLionel Sambuc     IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlinesLeft);
177*0a6a1f1dSLionel Sambuc     IO.mapOptional("AlignOperands", Style.AlignOperands);
178f4a2713aSLionel Sambuc     IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
179f4a2713aSLionel Sambuc     IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
180f4a2713aSLionel Sambuc                    Style.AllowAllParametersOfDeclarationOnNextLine);
181*0a6a1f1dSLionel Sambuc     IO.mapOptional("AllowShortBlocksOnASingleLine",
182*0a6a1f1dSLionel Sambuc                    Style.AllowShortBlocksOnASingleLine);
183*0a6a1f1dSLionel Sambuc     IO.mapOptional("AllowShortCaseLabelsOnASingleLine",
184*0a6a1f1dSLionel Sambuc                    Style.AllowShortCaseLabelsOnASingleLine);
185f4a2713aSLionel Sambuc     IO.mapOptional("AllowShortIfStatementsOnASingleLine",
186f4a2713aSLionel Sambuc                    Style.AllowShortIfStatementsOnASingleLine);
187f4a2713aSLionel Sambuc     IO.mapOptional("AllowShortLoopsOnASingleLine",
188f4a2713aSLionel Sambuc                    Style.AllowShortLoopsOnASingleLine);
189*0a6a1f1dSLionel Sambuc     IO.mapOptional("AllowShortFunctionsOnASingleLine",
190*0a6a1f1dSLionel Sambuc                    Style.AllowShortFunctionsOnASingleLine);
191*0a6a1f1dSLionel Sambuc     IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",
192*0a6a1f1dSLionel Sambuc                    Style.AlwaysBreakAfterDefinitionReturnType);
193f4a2713aSLionel Sambuc     IO.mapOptional("AlwaysBreakTemplateDeclarations",
194f4a2713aSLionel Sambuc                    Style.AlwaysBreakTemplateDeclarations);
195f4a2713aSLionel Sambuc     IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
196f4a2713aSLionel Sambuc                    Style.AlwaysBreakBeforeMultilineStrings);
197f4a2713aSLionel Sambuc     IO.mapOptional("BreakBeforeBinaryOperators",
198f4a2713aSLionel Sambuc                    Style.BreakBeforeBinaryOperators);
199f4a2713aSLionel Sambuc     IO.mapOptional("BreakBeforeTernaryOperators",
200f4a2713aSLionel Sambuc                    Style.BreakBeforeTernaryOperators);
201f4a2713aSLionel Sambuc     IO.mapOptional("BreakConstructorInitializersBeforeComma",
202f4a2713aSLionel Sambuc                    Style.BreakConstructorInitializersBeforeComma);
203f4a2713aSLionel Sambuc     IO.mapOptional("BinPackParameters", Style.BinPackParameters);
204*0a6a1f1dSLionel Sambuc     IO.mapOptional("BinPackArguments", Style.BinPackArguments);
205f4a2713aSLionel Sambuc     IO.mapOptional("ColumnLimit", Style.ColumnLimit);
206f4a2713aSLionel Sambuc     IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
207f4a2713aSLionel Sambuc                    Style.ConstructorInitializerAllOnOneLineOrOnePerLine);
208*0a6a1f1dSLionel Sambuc     IO.mapOptional("ConstructorInitializerIndentWidth",
209*0a6a1f1dSLionel Sambuc                    Style.ConstructorInitializerIndentWidth);
210*0a6a1f1dSLionel Sambuc     IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
211f4a2713aSLionel Sambuc     IO.mapOptional("ExperimentalAutoDetectBinPacking",
212f4a2713aSLionel Sambuc                    Style.ExperimentalAutoDetectBinPacking);
213f4a2713aSLionel Sambuc     IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
214*0a6a1f1dSLionel Sambuc     IO.mapOptional("IndentWrappedFunctionNames",
215*0a6a1f1dSLionel Sambuc                    Style.IndentWrappedFunctionNames);
216*0a6a1f1dSLionel Sambuc     IO.mapOptional("IndentFunctionDeclarationAfterType",
217*0a6a1f1dSLionel Sambuc                    Style.IndentWrappedFunctionNames);
218f4a2713aSLionel Sambuc     IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
219*0a6a1f1dSLionel Sambuc     IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
220*0a6a1f1dSLionel Sambuc                    Style.KeepEmptyLinesAtTheStartOfBlocks);
221f4a2713aSLionel Sambuc     IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
222*0a6a1f1dSLionel Sambuc     IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);
223*0a6a1f1dSLionel Sambuc     IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
224f4a2713aSLionel Sambuc     IO.mapOptional("ObjCSpaceBeforeProtocolList",
225f4a2713aSLionel Sambuc                    Style.ObjCSpaceBeforeProtocolList);
226f4a2713aSLionel Sambuc     IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",
227f4a2713aSLionel Sambuc                    Style.PenaltyBreakBeforeFirstCallParameter);
228f4a2713aSLionel Sambuc     IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
229f4a2713aSLionel Sambuc     IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
230f4a2713aSLionel Sambuc     IO.mapOptional("PenaltyBreakFirstLessLess",
231f4a2713aSLionel Sambuc                    Style.PenaltyBreakFirstLessLess);
232f4a2713aSLionel Sambuc     IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
233f4a2713aSLionel Sambuc     IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
234f4a2713aSLionel Sambuc                    Style.PenaltyReturnTypeOnItsOwnLine);
235*0a6a1f1dSLionel Sambuc     IO.mapOptional("PointerAlignment", Style.PointerAlignment);
236f4a2713aSLionel Sambuc     IO.mapOptional("SpacesBeforeTrailingComments",
237f4a2713aSLionel Sambuc                    Style.SpacesBeforeTrailingComments);
238f4a2713aSLionel Sambuc     IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
239f4a2713aSLionel Sambuc     IO.mapOptional("Standard", Style.Standard);
240f4a2713aSLionel Sambuc     IO.mapOptional("IndentWidth", Style.IndentWidth);
241f4a2713aSLionel Sambuc     IO.mapOptional("TabWidth", Style.TabWidth);
242f4a2713aSLionel Sambuc     IO.mapOptional("UseTab", Style.UseTab);
243f4a2713aSLionel Sambuc     IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
244f4a2713aSLionel Sambuc     IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
245*0a6a1f1dSLionel Sambuc     IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
246f4a2713aSLionel Sambuc     IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
247f4a2713aSLionel Sambuc     IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
248f4a2713aSLionel Sambuc     IO.mapOptional("SpacesInCStyleCastParentheses",
249f4a2713aSLionel Sambuc                    Style.SpacesInCStyleCastParentheses);
250*0a6a1f1dSLionel Sambuc     IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
251*0a6a1f1dSLionel Sambuc     IO.mapOptional("SpacesInContainerLiterals",
252*0a6a1f1dSLionel Sambuc                    Style.SpacesInContainerLiterals);
253f4a2713aSLionel Sambuc     IO.mapOptional("SpaceBeforeAssignmentOperators",
254f4a2713aSLionel Sambuc                    Style.SpaceBeforeAssignmentOperators);
255f4a2713aSLionel Sambuc     IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
256*0a6a1f1dSLionel Sambuc     IO.mapOptional("CommentPragmas", Style.CommentPragmas);
257*0a6a1f1dSLionel Sambuc     IO.mapOptional("ForEachMacros", Style.ForEachMacros);
258*0a6a1f1dSLionel Sambuc 
259*0a6a1f1dSLionel Sambuc     // For backward compatibility.
260*0a6a1f1dSLionel Sambuc     if (!IO.outputting()) {
261*0a6a1f1dSLionel Sambuc       IO.mapOptional("SpaceAfterControlStatementKeyword",
262*0a6a1f1dSLionel Sambuc                      Style.SpaceBeforeParens);
263*0a6a1f1dSLionel Sambuc       IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
264*0a6a1f1dSLionel Sambuc       IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
265*0a6a1f1dSLionel Sambuc     }
266*0a6a1f1dSLionel Sambuc     IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
267*0a6a1f1dSLionel Sambuc     IO.mapOptional("DisableFormat", Style.DisableFormat);
268*0a6a1f1dSLionel Sambuc   }
269*0a6a1f1dSLionel Sambuc };
270*0a6a1f1dSLionel Sambuc 
271*0a6a1f1dSLionel Sambuc // Allows to read vector<FormatStyle> while keeping default values.
272*0a6a1f1dSLionel Sambuc // IO.getContext() should contain a pointer to the FormatStyle structure, that
273*0a6a1f1dSLionel Sambuc // will be used to get default values for missing keys.
274*0a6a1f1dSLionel Sambuc // If the first element has no Language specified, it will be treated as the
275*0a6a1f1dSLionel Sambuc // default one for the following elements.
276*0a6a1f1dSLionel Sambuc template <> struct DocumentListTraits<std::vector<FormatStyle> > {
sizellvm::yaml::DocumentListTraits277*0a6a1f1dSLionel Sambuc   static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
278*0a6a1f1dSLionel Sambuc     return Seq.size();
279*0a6a1f1dSLionel Sambuc   }
elementllvm::yaml::DocumentListTraits280*0a6a1f1dSLionel Sambuc   static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq,
281*0a6a1f1dSLionel Sambuc                               size_t Index) {
282*0a6a1f1dSLionel Sambuc     if (Index >= Seq.size()) {
283*0a6a1f1dSLionel Sambuc       assert(Index == Seq.size());
284*0a6a1f1dSLionel Sambuc       FormatStyle Template;
285*0a6a1f1dSLionel Sambuc       if (Seq.size() > 0 && Seq[0].Language == FormatStyle::LK_None) {
286*0a6a1f1dSLionel Sambuc         Template = Seq[0];
287*0a6a1f1dSLionel Sambuc       } else {
288*0a6a1f1dSLionel Sambuc         Template = *((const FormatStyle *)IO.getContext());
289*0a6a1f1dSLionel Sambuc         Template.Language = FormatStyle::LK_None;
290*0a6a1f1dSLionel Sambuc       }
291*0a6a1f1dSLionel Sambuc       Seq.resize(Index + 1, Template);
292*0a6a1f1dSLionel Sambuc     }
293*0a6a1f1dSLionel Sambuc     return Seq[Index];
294f4a2713aSLionel Sambuc   }
295f4a2713aSLionel Sambuc };
296f4a2713aSLionel Sambuc }
297f4a2713aSLionel Sambuc }
298f4a2713aSLionel Sambuc 
299f4a2713aSLionel Sambuc namespace clang {
300f4a2713aSLionel Sambuc namespace format {
301f4a2713aSLionel Sambuc 
getParseCategory()302*0a6a1f1dSLionel Sambuc const std::error_category &getParseCategory() {
303*0a6a1f1dSLionel Sambuc   static ParseErrorCategory C;
304*0a6a1f1dSLionel Sambuc   return C;
305*0a6a1f1dSLionel Sambuc }
make_error_code(ParseError e)306*0a6a1f1dSLionel Sambuc std::error_code make_error_code(ParseError e) {
307*0a6a1f1dSLionel Sambuc   return std::error_code(static_cast<int>(e), getParseCategory());
308*0a6a1f1dSLionel Sambuc }
309*0a6a1f1dSLionel Sambuc 
name() const310*0a6a1f1dSLionel Sambuc const char *ParseErrorCategory::name() const LLVM_NOEXCEPT {
311*0a6a1f1dSLionel Sambuc   return "clang-format.parse_error";
312*0a6a1f1dSLionel Sambuc }
313*0a6a1f1dSLionel Sambuc 
message(int EV) const314*0a6a1f1dSLionel Sambuc std::string ParseErrorCategory::message(int EV) const {
315*0a6a1f1dSLionel Sambuc   switch (static_cast<ParseError>(EV)) {
316*0a6a1f1dSLionel Sambuc   case ParseError::Success:
317*0a6a1f1dSLionel Sambuc     return "Success";
318*0a6a1f1dSLionel Sambuc   case ParseError::Error:
319*0a6a1f1dSLionel Sambuc     return "Invalid argument";
320*0a6a1f1dSLionel Sambuc   case ParseError::Unsuitable:
321*0a6a1f1dSLionel Sambuc     return "Unsuitable";
322*0a6a1f1dSLionel Sambuc   }
323*0a6a1f1dSLionel Sambuc   llvm_unreachable("unexpected parse error");
324f4a2713aSLionel Sambuc }
325f4a2713aSLionel Sambuc 
getLLVMStyle()326f4a2713aSLionel Sambuc FormatStyle getLLVMStyle() {
327f4a2713aSLionel Sambuc   FormatStyle LLVMStyle;
328*0a6a1f1dSLionel Sambuc   LLVMStyle.Language = FormatStyle::LK_Cpp;
329f4a2713aSLionel Sambuc   LLVMStyle.AccessModifierOffset = -2;
330f4a2713aSLionel Sambuc   LLVMStyle.AlignEscapedNewlinesLeft = false;
331*0a6a1f1dSLionel Sambuc   LLVMStyle.AlignAfterOpenBracket = true;
332*0a6a1f1dSLionel Sambuc   LLVMStyle.AlignOperands = true;
333f4a2713aSLionel Sambuc   LLVMStyle.AlignTrailingComments = true;
334f4a2713aSLionel Sambuc   LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
335*0a6a1f1dSLionel Sambuc   LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
336*0a6a1f1dSLionel Sambuc   LLVMStyle.AllowShortBlocksOnASingleLine = false;
337*0a6a1f1dSLionel Sambuc   LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
338f4a2713aSLionel Sambuc   LLVMStyle.AllowShortIfStatementsOnASingleLine = false;
339f4a2713aSLionel Sambuc   LLVMStyle.AllowShortLoopsOnASingleLine = false;
340*0a6a1f1dSLionel Sambuc   LLVMStyle.AlwaysBreakAfterDefinitionReturnType = false;
341f4a2713aSLionel Sambuc   LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
342f4a2713aSLionel Sambuc   LLVMStyle.AlwaysBreakTemplateDeclarations = false;
343f4a2713aSLionel Sambuc   LLVMStyle.BinPackParameters = true;
344*0a6a1f1dSLionel Sambuc   LLVMStyle.BinPackArguments = true;
345*0a6a1f1dSLionel Sambuc   LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
346f4a2713aSLionel Sambuc   LLVMStyle.BreakBeforeTernaryOperators = true;
347f4a2713aSLionel Sambuc   LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
348f4a2713aSLionel Sambuc   LLVMStyle.BreakConstructorInitializersBeforeComma = false;
349f4a2713aSLionel Sambuc   LLVMStyle.ColumnLimit = 80;
350*0a6a1f1dSLionel Sambuc   LLVMStyle.CommentPragmas = "^ IWYU pragma:";
351f4a2713aSLionel Sambuc   LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false;
352f4a2713aSLionel Sambuc   LLVMStyle.ConstructorInitializerIndentWidth = 4;
353*0a6a1f1dSLionel Sambuc   LLVMStyle.ContinuationIndentWidth = 4;
354*0a6a1f1dSLionel Sambuc   LLVMStyle.Cpp11BracedListStyle = true;
355*0a6a1f1dSLionel Sambuc   LLVMStyle.DerivePointerAlignment = false;
356f4a2713aSLionel Sambuc   LLVMStyle.ExperimentalAutoDetectBinPacking = false;
357*0a6a1f1dSLionel Sambuc   LLVMStyle.ForEachMacros.push_back("foreach");
358*0a6a1f1dSLionel Sambuc   LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
359*0a6a1f1dSLionel Sambuc   LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
360f4a2713aSLionel Sambuc   LLVMStyle.IndentCaseLabels = false;
361*0a6a1f1dSLionel Sambuc   LLVMStyle.IndentWrappedFunctionNames = false;
362f4a2713aSLionel Sambuc   LLVMStyle.IndentWidth = 2;
363f4a2713aSLionel Sambuc   LLVMStyle.TabWidth = 8;
364f4a2713aSLionel Sambuc   LLVMStyle.MaxEmptyLinesToKeep = 1;
365*0a6a1f1dSLionel Sambuc   LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
366f4a2713aSLionel Sambuc   LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
367*0a6a1f1dSLionel Sambuc   LLVMStyle.ObjCBlockIndentWidth = 2;
368*0a6a1f1dSLionel Sambuc   LLVMStyle.ObjCSpaceAfterProperty = false;
369f4a2713aSLionel Sambuc   LLVMStyle.ObjCSpaceBeforeProtocolList = true;
370*0a6a1f1dSLionel Sambuc   LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
371f4a2713aSLionel Sambuc   LLVMStyle.SpacesBeforeTrailingComments = 1;
372*0a6a1f1dSLionel Sambuc   LLVMStyle.Standard = FormatStyle::LS_Cpp11;
373f4a2713aSLionel Sambuc   LLVMStyle.UseTab = FormatStyle::UT_Never;
374f4a2713aSLionel Sambuc   LLVMStyle.SpacesInParentheses = false;
375*0a6a1f1dSLionel Sambuc   LLVMStyle.SpacesInSquareBrackets = false;
376f4a2713aSLionel Sambuc   LLVMStyle.SpaceInEmptyParentheses = false;
377*0a6a1f1dSLionel Sambuc   LLVMStyle.SpacesInContainerLiterals = true;
378f4a2713aSLionel Sambuc   LLVMStyle.SpacesInCStyleCastParentheses = false;
379*0a6a1f1dSLionel Sambuc   LLVMStyle.SpaceAfterCStyleCast = false;
380*0a6a1f1dSLionel Sambuc   LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
381f4a2713aSLionel Sambuc   LLVMStyle.SpaceBeforeAssignmentOperators = true;
382f4a2713aSLionel Sambuc   LLVMStyle.SpacesInAngles = false;
383f4a2713aSLionel Sambuc 
384*0a6a1f1dSLionel Sambuc   LLVMStyle.PenaltyBreakComment = 300;
385*0a6a1f1dSLionel Sambuc   LLVMStyle.PenaltyBreakFirstLessLess = 120;
386*0a6a1f1dSLionel Sambuc   LLVMStyle.PenaltyBreakString = 1000;
387*0a6a1f1dSLionel Sambuc   LLVMStyle.PenaltyExcessCharacter = 1000000;
388f4a2713aSLionel Sambuc   LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
389f4a2713aSLionel Sambuc   LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
390f4a2713aSLionel Sambuc 
391*0a6a1f1dSLionel Sambuc   LLVMStyle.DisableFormat = false;
392*0a6a1f1dSLionel Sambuc 
393f4a2713aSLionel Sambuc   return LLVMStyle;
394f4a2713aSLionel Sambuc }
395f4a2713aSLionel Sambuc 
getGoogleStyle(FormatStyle::LanguageKind Language)396*0a6a1f1dSLionel Sambuc FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
397*0a6a1f1dSLionel Sambuc   FormatStyle GoogleStyle = getLLVMStyle();
398*0a6a1f1dSLionel Sambuc   GoogleStyle.Language = Language;
399*0a6a1f1dSLionel Sambuc 
400f4a2713aSLionel Sambuc   GoogleStyle.AccessModifierOffset = -1;
401f4a2713aSLionel Sambuc   GoogleStyle.AlignEscapedNewlinesLeft = true;
402f4a2713aSLionel Sambuc   GoogleStyle.AllowShortIfStatementsOnASingleLine = true;
403f4a2713aSLionel Sambuc   GoogleStyle.AllowShortLoopsOnASingleLine = true;
404f4a2713aSLionel Sambuc   GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
405f4a2713aSLionel Sambuc   GoogleStyle.AlwaysBreakTemplateDeclarations = true;
406f4a2713aSLionel Sambuc   GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
407*0a6a1f1dSLionel Sambuc   GoogleStyle.DerivePointerAlignment = true;
408f4a2713aSLionel Sambuc   GoogleStyle.IndentCaseLabels = true;
409*0a6a1f1dSLionel Sambuc   GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
410*0a6a1f1dSLionel Sambuc   GoogleStyle.ObjCSpaceAfterProperty = false;
411f4a2713aSLionel Sambuc   GoogleStyle.ObjCSpaceBeforeProtocolList = false;
412*0a6a1f1dSLionel Sambuc   GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;
413f4a2713aSLionel Sambuc   GoogleStyle.SpacesBeforeTrailingComments = 2;
414f4a2713aSLionel Sambuc   GoogleStyle.Standard = FormatStyle::LS_Auto;
415f4a2713aSLionel Sambuc 
416f4a2713aSLionel Sambuc   GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
417f4a2713aSLionel Sambuc   GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;
418f4a2713aSLionel Sambuc 
419*0a6a1f1dSLionel Sambuc   if (Language == FormatStyle::LK_Java) {
420*0a6a1f1dSLionel Sambuc     GoogleStyle.AlignAfterOpenBracket = false;
421*0a6a1f1dSLionel Sambuc     GoogleStyle.AlignOperands = false;
422*0a6a1f1dSLionel Sambuc     GoogleStyle.AlignTrailingComments = false;
423*0a6a1f1dSLionel Sambuc     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
424*0a6a1f1dSLionel Sambuc     GoogleStyle.AllowShortIfStatementsOnASingleLine = false;
425*0a6a1f1dSLionel Sambuc     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
426*0a6a1f1dSLionel Sambuc     GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
427*0a6a1f1dSLionel Sambuc     GoogleStyle.ColumnLimit = 100;
428*0a6a1f1dSLionel Sambuc     GoogleStyle.SpaceAfterCStyleCast = true;
429*0a6a1f1dSLionel Sambuc     GoogleStyle.SpacesBeforeTrailingComments = 1;
430*0a6a1f1dSLionel Sambuc   } else if (Language == FormatStyle::LK_JavaScript) {
431*0a6a1f1dSLionel Sambuc     GoogleStyle.BreakBeforeTernaryOperators = false;
432*0a6a1f1dSLionel Sambuc     GoogleStyle.MaxEmptyLinesToKeep = 3;
433*0a6a1f1dSLionel Sambuc     GoogleStyle.SpacesInContainerLiterals = false;
434*0a6a1f1dSLionel Sambuc     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
435*0a6a1f1dSLionel Sambuc     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
436*0a6a1f1dSLionel Sambuc   } else if (Language == FormatStyle::LK_Proto) {
437*0a6a1f1dSLionel Sambuc     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
438*0a6a1f1dSLionel Sambuc     GoogleStyle.SpacesInContainerLiterals = false;
439*0a6a1f1dSLionel Sambuc   }
440*0a6a1f1dSLionel Sambuc 
441f4a2713aSLionel Sambuc   return GoogleStyle;
442f4a2713aSLionel Sambuc }
443f4a2713aSLionel Sambuc 
getChromiumStyle(FormatStyle::LanguageKind Language)444*0a6a1f1dSLionel Sambuc FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
445*0a6a1f1dSLionel Sambuc   FormatStyle ChromiumStyle = getGoogleStyle(Language);
446*0a6a1f1dSLionel Sambuc   if (Language == FormatStyle::LK_Java) {
447*0a6a1f1dSLionel Sambuc     ChromiumStyle.AllowShortIfStatementsOnASingleLine = true;
448*0a6a1f1dSLionel Sambuc     ChromiumStyle.IndentWidth = 4;
449*0a6a1f1dSLionel Sambuc     ChromiumStyle.ContinuationIndentWidth = 8;
450*0a6a1f1dSLionel Sambuc   } else {
451f4a2713aSLionel Sambuc     ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
452*0a6a1f1dSLionel Sambuc     ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
453f4a2713aSLionel Sambuc     ChromiumStyle.AllowShortIfStatementsOnASingleLine = false;
454f4a2713aSLionel Sambuc     ChromiumStyle.AllowShortLoopsOnASingleLine = false;
455f4a2713aSLionel Sambuc     ChromiumStyle.BinPackParameters = false;
456*0a6a1f1dSLionel Sambuc     ChromiumStyle.DerivePointerAlignment = false;
457*0a6a1f1dSLionel Sambuc   }
458f4a2713aSLionel Sambuc   return ChromiumStyle;
459f4a2713aSLionel Sambuc }
460f4a2713aSLionel Sambuc 
getMozillaStyle()461f4a2713aSLionel Sambuc FormatStyle getMozillaStyle() {
462f4a2713aSLionel Sambuc   FormatStyle MozillaStyle = getLLVMStyle();
463f4a2713aSLionel Sambuc   MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
464*0a6a1f1dSLionel Sambuc   MozillaStyle.Cpp11BracedListStyle = false;
465f4a2713aSLionel Sambuc   MozillaStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
466*0a6a1f1dSLionel Sambuc   MozillaStyle.DerivePointerAlignment = true;
467f4a2713aSLionel Sambuc   MozillaStyle.IndentCaseLabels = true;
468*0a6a1f1dSLionel Sambuc   MozillaStyle.ObjCSpaceAfterProperty = true;
469f4a2713aSLionel Sambuc   MozillaStyle.ObjCSpaceBeforeProtocolList = false;
470f4a2713aSLionel Sambuc   MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
471*0a6a1f1dSLionel Sambuc   MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
472*0a6a1f1dSLionel Sambuc   MozillaStyle.Standard = FormatStyle::LS_Cpp03;
473f4a2713aSLionel Sambuc   return MozillaStyle;
474f4a2713aSLionel Sambuc }
475f4a2713aSLionel Sambuc 
getWebKitStyle()476f4a2713aSLionel Sambuc FormatStyle getWebKitStyle() {
477f4a2713aSLionel Sambuc   FormatStyle Style = getLLVMStyle();
478f4a2713aSLionel Sambuc   Style.AccessModifierOffset = -4;
479*0a6a1f1dSLionel Sambuc   Style.AlignAfterOpenBracket = false;
480*0a6a1f1dSLionel Sambuc   Style.AlignOperands = false;
481f4a2713aSLionel Sambuc   Style.AlignTrailingComments = false;
482*0a6a1f1dSLionel Sambuc   Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
483f4a2713aSLionel Sambuc   Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup;
484f4a2713aSLionel Sambuc   Style.BreakConstructorInitializersBeforeComma = true;
485*0a6a1f1dSLionel Sambuc   Style.Cpp11BracedListStyle = false;
486f4a2713aSLionel Sambuc   Style.ColumnLimit = 0;
487f4a2713aSLionel Sambuc   Style.IndentWidth = 4;
488f4a2713aSLionel Sambuc   Style.NamespaceIndentation = FormatStyle::NI_Inner;
489*0a6a1f1dSLionel Sambuc   Style.ObjCBlockIndentWidth = 4;
490*0a6a1f1dSLionel Sambuc   Style.ObjCSpaceAfterProperty = true;
491*0a6a1f1dSLionel Sambuc   Style.PointerAlignment = FormatStyle::PAS_Left;
492*0a6a1f1dSLionel Sambuc   Style.Standard = FormatStyle::LS_Cpp03;
493f4a2713aSLionel Sambuc   return Style;
494f4a2713aSLionel Sambuc }
495f4a2713aSLionel Sambuc 
getGNUStyle()496*0a6a1f1dSLionel Sambuc FormatStyle getGNUStyle() {
497*0a6a1f1dSLionel Sambuc   FormatStyle Style = getLLVMStyle();
498*0a6a1f1dSLionel Sambuc   Style.AlwaysBreakAfterDefinitionReturnType = true;
499*0a6a1f1dSLionel Sambuc   Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
500*0a6a1f1dSLionel Sambuc   Style.BreakBeforeBraces = FormatStyle::BS_GNU;
501*0a6a1f1dSLionel Sambuc   Style.BreakBeforeTernaryOperators = true;
502*0a6a1f1dSLionel Sambuc   Style.Cpp11BracedListStyle = false;
503*0a6a1f1dSLionel Sambuc   Style.ColumnLimit = 79;
504*0a6a1f1dSLionel Sambuc   Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
505*0a6a1f1dSLionel Sambuc   Style.Standard = FormatStyle::LS_Cpp03;
506*0a6a1f1dSLionel Sambuc   return Style;
507*0a6a1f1dSLionel Sambuc }
508f4a2713aSLionel Sambuc 
getNoStyle()509*0a6a1f1dSLionel Sambuc FormatStyle getNoStyle() {
510*0a6a1f1dSLionel Sambuc   FormatStyle NoStyle = getLLVMStyle();
511*0a6a1f1dSLionel Sambuc   NoStyle.DisableFormat = true;
512*0a6a1f1dSLionel Sambuc   return NoStyle;
513*0a6a1f1dSLionel Sambuc }
514*0a6a1f1dSLionel Sambuc 
getPredefinedStyle(StringRef Name,FormatStyle::LanguageKind Language,FormatStyle * Style)515*0a6a1f1dSLionel Sambuc bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
516*0a6a1f1dSLionel Sambuc                         FormatStyle *Style) {
517*0a6a1f1dSLionel Sambuc   if (Name.equals_lower("llvm")) {
518*0a6a1f1dSLionel Sambuc     *Style = getLLVMStyle();
519*0a6a1f1dSLionel Sambuc   } else if (Name.equals_lower("chromium")) {
520*0a6a1f1dSLionel Sambuc     *Style = getChromiumStyle(Language);
521*0a6a1f1dSLionel Sambuc   } else if (Name.equals_lower("mozilla")) {
522*0a6a1f1dSLionel Sambuc     *Style = getMozillaStyle();
523*0a6a1f1dSLionel Sambuc   } else if (Name.equals_lower("google")) {
524*0a6a1f1dSLionel Sambuc     *Style = getGoogleStyle(Language);
525*0a6a1f1dSLionel Sambuc   } else if (Name.equals_lower("webkit")) {
526*0a6a1f1dSLionel Sambuc     *Style = getWebKitStyle();
527*0a6a1f1dSLionel Sambuc   } else if (Name.equals_lower("gnu")) {
528*0a6a1f1dSLionel Sambuc     *Style = getGNUStyle();
529*0a6a1f1dSLionel Sambuc   } else if (Name.equals_lower("none")) {
530*0a6a1f1dSLionel Sambuc     *Style = getNoStyle();
531*0a6a1f1dSLionel Sambuc   } else {
532*0a6a1f1dSLionel Sambuc     return false;
533*0a6a1f1dSLionel Sambuc   }
534*0a6a1f1dSLionel Sambuc 
535*0a6a1f1dSLionel Sambuc   Style->Language = Language;
536f4a2713aSLionel Sambuc   return true;
537f4a2713aSLionel Sambuc }
538f4a2713aSLionel Sambuc 
parseConfiguration(StringRef Text,FormatStyle * Style)539*0a6a1f1dSLionel Sambuc std::error_code parseConfiguration(StringRef Text, FormatStyle *Style) {
540*0a6a1f1dSLionel Sambuc   assert(Style);
541*0a6a1f1dSLionel Sambuc   FormatStyle::LanguageKind Language = Style->Language;
542*0a6a1f1dSLionel Sambuc   assert(Language != FormatStyle::LK_None);
543f4a2713aSLionel Sambuc   if (Text.trim().empty())
544*0a6a1f1dSLionel Sambuc     return make_error_code(ParseError::Error);
545*0a6a1f1dSLionel Sambuc 
546*0a6a1f1dSLionel Sambuc   std::vector<FormatStyle> Styles;
547f4a2713aSLionel Sambuc   llvm::yaml::Input Input(Text);
548*0a6a1f1dSLionel Sambuc   // DocumentListTraits<vector<FormatStyle>> uses the context to get default
549*0a6a1f1dSLionel Sambuc   // values for the fields, keys for which are missing from the configuration.
550*0a6a1f1dSLionel Sambuc   // Mapping also uses the context to get the language to find the correct
551*0a6a1f1dSLionel Sambuc   // base style.
552*0a6a1f1dSLionel Sambuc   Input.setContext(Style);
553*0a6a1f1dSLionel Sambuc   Input >> Styles;
554*0a6a1f1dSLionel Sambuc   if (Input.error())
555f4a2713aSLionel Sambuc     return Input.error();
556*0a6a1f1dSLionel Sambuc 
557*0a6a1f1dSLionel Sambuc   for (unsigned i = 0; i < Styles.size(); ++i) {
558*0a6a1f1dSLionel Sambuc     // Ensures that only the first configuration can skip the Language option.
559*0a6a1f1dSLionel Sambuc     if (Styles[i].Language == FormatStyle::LK_None && i != 0)
560*0a6a1f1dSLionel Sambuc       return make_error_code(ParseError::Error);
561*0a6a1f1dSLionel Sambuc     // Ensure that each language is configured at most once.
562*0a6a1f1dSLionel Sambuc     for (unsigned j = 0; j < i; ++j) {
563*0a6a1f1dSLionel Sambuc       if (Styles[i].Language == Styles[j].Language) {
564*0a6a1f1dSLionel Sambuc         DEBUG(llvm::dbgs()
565*0a6a1f1dSLionel Sambuc               << "Duplicate languages in the config file on positions " << j
566*0a6a1f1dSLionel Sambuc               << " and " << i << "\n");
567*0a6a1f1dSLionel Sambuc         return make_error_code(ParseError::Error);
568*0a6a1f1dSLionel Sambuc       }
569*0a6a1f1dSLionel Sambuc     }
570*0a6a1f1dSLionel Sambuc   }
571*0a6a1f1dSLionel Sambuc   // Look for a suitable configuration starting from the end, so we can
572*0a6a1f1dSLionel Sambuc   // find the configuration for the specific language first, and the default
573*0a6a1f1dSLionel Sambuc   // configuration (which can only be at slot 0) after it.
574*0a6a1f1dSLionel Sambuc   for (int i = Styles.size() - 1; i >= 0; --i) {
575*0a6a1f1dSLionel Sambuc     if (Styles[i].Language == Language ||
576*0a6a1f1dSLionel Sambuc         Styles[i].Language == FormatStyle::LK_None) {
577*0a6a1f1dSLionel Sambuc       *Style = Styles[i];
578*0a6a1f1dSLionel Sambuc       Style->Language = Language;
579*0a6a1f1dSLionel Sambuc       return make_error_code(ParseError::Success);
580*0a6a1f1dSLionel Sambuc     }
581*0a6a1f1dSLionel Sambuc   }
582*0a6a1f1dSLionel Sambuc   return make_error_code(ParseError::Unsuitable);
583f4a2713aSLionel Sambuc }
584f4a2713aSLionel Sambuc 
configurationAsText(const FormatStyle & Style)585f4a2713aSLionel Sambuc std::string configurationAsText(const FormatStyle &Style) {
586f4a2713aSLionel Sambuc   std::string Text;
587f4a2713aSLionel Sambuc   llvm::raw_string_ostream Stream(Text);
588f4a2713aSLionel Sambuc   llvm::yaml::Output Output(Stream);
589f4a2713aSLionel Sambuc   // We use the same mapping method for input and output, so we need a non-const
590f4a2713aSLionel Sambuc   // reference here.
591f4a2713aSLionel Sambuc   FormatStyle NonConstStyle = Style;
592f4a2713aSLionel Sambuc   Output << NonConstStyle;
593f4a2713aSLionel Sambuc   return Stream.str();
594f4a2713aSLionel Sambuc }
595f4a2713aSLionel Sambuc 
596f4a2713aSLionel Sambuc namespace {
597f4a2713aSLionel Sambuc 
598f4a2713aSLionel Sambuc class FormatTokenLexer {
599f4a2713aSLionel Sambuc public:
FormatTokenLexer(SourceManager & SourceMgr,FileID ID,FormatStyle & Style,encoding::Encoding Encoding)600*0a6a1f1dSLionel Sambuc   FormatTokenLexer(SourceManager &SourceMgr, FileID ID, FormatStyle &Style,
601f4a2713aSLionel Sambuc                    encoding::Encoding Encoding)
602*0a6a1f1dSLionel Sambuc       : FormatTok(nullptr), IsFirstToken(true), GreaterStashed(false),
603*0a6a1f1dSLionel Sambuc         Column(0), TrailingWhitespace(0), SourceMgr(SourceMgr), ID(ID),
604*0a6a1f1dSLionel Sambuc         Style(Style), IdentTable(getFormattingLangOpts(Style)),
605*0a6a1f1dSLionel Sambuc         Keywords(IdentTable), Encoding(Encoding), FirstInLineIndex(0),
606*0a6a1f1dSLionel Sambuc         FormattingDisabled(false) {
607*0a6a1f1dSLionel Sambuc     Lex.reset(new Lexer(ID, SourceMgr.getBuffer(ID), SourceMgr,
608*0a6a1f1dSLionel Sambuc                         getFormattingLangOpts(Style)));
609*0a6a1f1dSLionel Sambuc     Lex->SetKeepWhitespaceMode(true);
610*0a6a1f1dSLionel Sambuc 
611*0a6a1f1dSLionel Sambuc     for (const std::string &ForEachMacro : Style.ForEachMacros)
612*0a6a1f1dSLionel Sambuc       ForEachMacros.push_back(&IdentTable.get(ForEachMacro));
613*0a6a1f1dSLionel Sambuc     std::sort(ForEachMacros.begin(), ForEachMacros.end());
614f4a2713aSLionel Sambuc   }
615f4a2713aSLionel Sambuc 
lex()616f4a2713aSLionel Sambuc   ArrayRef<FormatToken *> lex() {
617f4a2713aSLionel Sambuc     assert(Tokens.empty());
618*0a6a1f1dSLionel Sambuc     assert(FirstInLineIndex == 0);
619f4a2713aSLionel Sambuc     do {
620f4a2713aSLionel Sambuc       Tokens.push_back(getNextToken());
621*0a6a1f1dSLionel Sambuc       tryMergePreviousTokens();
622*0a6a1f1dSLionel Sambuc       if (Tokens.back()->NewlinesBefore > 0)
623*0a6a1f1dSLionel Sambuc         FirstInLineIndex = Tokens.size() - 1;
624f4a2713aSLionel Sambuc     } while (Tokens.back()->Tok.isNot(tok::eof));
625f4a2713aSLionel Sambuc     return Tokens;
626f4a2713aSLionel Sambuc   }
627f4a2713aSLionel Sambuc 
getKeywords()628*0a6a1f1dSLionel Sambuc   const AdditionalKeywords &getKeywords() { return Keywords; }
629f4a2713aSLionel Sambuc 
630f4a2713aSLionel Sambuc private:
tryMergePreviousTokens()631*0a6a1f1dSLionel Sambuc   void tryMergePreviousTokens() {
632*0a6a1f1dSLionel Sambuc     if (tryMerge_TMacro())
633f4a2713aSLionel Sambuc       return;
634*0a6a1f1dSLionel Sambuc     if (tryMergeConflictMarkers())
635*0a6a1f1dSLionel Sambuc       return;
636*0a6a1f1dSLionel Sambuc 
637*0a6a1f1dSLionel Sambuc     if (Style.Language == FormatStyle::LK_JavaScript) {
638*0a6a1f1dSLionel Sambuc       if (tryMergeJSRegexLiteral())
639*0a6a1f1dSLionel Sambuc         return;
640*0a6a1f1dSLionel Sambuc       if (tryMergeEscapeSequence())
641*0a6a1f1dSLionel Sambuc         return;
642*0a6a1f1dSLionel Sambuc 
643*0a6a1f1dSLionel Sambuc       static tok::TokenKind JSIdentity[] = { tok::equalequal, tok::equal };
644*0a6a1f1dSLionel Sambuc       static tok::TokenKind JSNotIdentity[] = { tok::exclaimequal, tok::equal };
645*0a6a1f1dSLionel Sambuc       static tok::TokenKind JSShiftEqual[] = { tok::greater, tok::greater,
646*0a6a1f1dSLionel Sambuc                                                tok::greaterequal };
647*0a6a1f1dSLionel Sambuc       static tok::TokenKind JSRightArrow[] = { tok::equal, tok::greater };
648*0a6a1f1dSLionel Sambuc       // FIXME: We probably need to change token type to mimic operator with the
649*0a6a1f1dSLionel Sambuc       // correct priority.
650*0a6a1f1dSLionel Sambuc       if (tryMergeTokens(JSIdentity))
651*0a6a1f1dSLionel Sambuc         return;
652*0a6a1f1dSLionel Sambuc       if (tryMergeTokens(JSNotIdentity))
653*0a6a1f1dSLionel Sambuc         return;
654*0a6a1f1dSLionel Sambuc       if (tryMergeTokens(JSShiftEqual))
655*0a6a1f1dSLionel Sambuc         return;
656*0a6a1f1dSLionel Sambuc       if (tryMergeTokens(JSRightArrow))
657*0a6a1f1dSLionel Sambuc         return;
658*0a6a1f1dSLionel Sambuc     }
659*0a6a1f1dSLionel Sambuc   }
660*0a6a1f1dSLionel Sambuc 
tryMergeTokens(ArrayRef<tok::TokenKind> Kinds)661*0a6a1f1dSLionel Sambuc   bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds) {
662*0a6a1f1dSLionel Sambuc     if (Tokens.size() < Kinds.size())
663*0a6a1f1dSLionel Sambuc       return false;
664*0a6a1f1dSLionel Sambuc 
665*0a6a1f1dSLionel Sambuc     SmallVectorImpl<FormatToken *>::const_iterator First =
666*0a6a1f1dSLionel Sambuc         Tokens.end() - Kinds.size();
667*0a6a1f1dSLionel Sambuc     if (!First[0]->is(Kinds[0]))
668*0a6a1f1dSLionel Sambuc       return false;
669*0a6a1f1dSLionel Sambuc     unsigned AddLength = 0;
670*0a6a1f1dSLionel Sambuc     for (unsigned i = 1; i < Kinds.size(); ++i) {
671*0a6a1f1dSLionel Sambuc       if (!First[i]->is(Kinds[i]) || First[i]->WhitespaceRange.getBegin() !=
672*0a6a1f1dSLionel Sambuc                                          First[i]->WhitespaceRange.getEnd())
673*0a6a1f1dSLionel Sambuc         return false;
674*0a6a1f1dSLionel Sambuc       AddLength += First[i]->TokenText.size();
675*0a6a1f1dSLionel Sambuc     }
676*0a6a1f1dSLionel Sambuc     Tokens.resize(Tokens.size() - Kinds.size() + 1);
677*0a6a1f1dSLionel Sambuc     First[0]->TokenText = StringRef(First[0]->TokenText.data(),
678*0a6a1f1dSLionel Sambuc                                     First[0]->TokenText.size() + AddLength);
679*0a6a1f1dSLionel Sambuc     First[0]->ColumnWidth += AddLength;
680*0a6a1f1dSLionel Sambuc     return true;
681*0a6a1f1dSLionel Sambuc   }
682*0a6a1f1dSLionel Sambuc 
683*0a6a1f1dSLionel Sambuc   // Tries to merge an escape sequence, i.e. a "\\" and the following
684*0a6a1f1dSLionel Sambuc   // character. Use e.g. inside JavaScript regex literals.
tryMergeEscapeSequence()685*0a6a1f1dSLionel Sambuc   bool tryMergeEscapeSequence() {
686*0a6a1f1dSLionel Sambuc     if (Tokens.size() < 2)
687*0a6a1f1dSLionel Sambuc       return false;
688*0a6a1f1dSLionel Sambuc     FormatToken *Previous = Tokens[Tokens.size() - 2];
689*0a6a1f1dSLionel Sambuc     if (Previous->isNot(tok::unknown) || Previous->TokenText != "\\")
690*0a6a1f1dSLionel Sambuc       return false;
691*0a6a1f1dSLionel Sambuc     ++Previous->ColumnWidth;
692*0a6a1f1dSLionel Sambuc     StringRef Text = Previous->TokenText;
693*0a6a1f1dSLionel Sambuc     Previous->TokenText = StringRef(Text.data(), Text.size() + 1);
694*0a6a1f1dSLionel Sambuc     resetLexer(SourceMgr.getFileOffset(Tokens.back()->Tok.getLocation()) + 1);
695*0a6a1f1dSLionel Sambuc     Tokens.resize(Tokens.size() - 1);
696*0a6a1f1dSLionel Sambuc     Column = Previous->OriginalColumn + Previous->ColumnWidth;
697*0a6a1f1dSLionel Sambuc     return true;
698*0a6a1f1dSLionel Sambuc   }
699*0a6a1f1dSLionel Sambuc 
700*0a6a1f1dSLionel Sambuc   // Try to determine whether the current token ends a JavaScript regex literal.
701*0a6a1f1dSLionel Sambuc   // We heuristically assume that this is a regex literal if we find two
702*0a6a1f1dSLionel Sambuc   // unescaped slashes on a line and the token before the first slash is one of
703*0a6a1f1dSLionel Sambuc   // "(;,{}![:?", a binary operator or 'return', as those cannot be followed by
704*0a6a1f1dSLionel Sambuc   // a division.
tryMergeJSRegexLiteral()705*0a6a1f1dSLionel Sambuc   bool tryMergeJSRegexLiteral() {
706*0a6a1f1dSLionel Sambuc     if (Tokens.size() < 2)
707*0a6a1f1dSLionel Sambuc       return false;
708*0a6a1f1dSLionel Sambuc     // If a regex literal ends in "\//", this gets represented by an unknown
709*0a6a1f1dSLionel Sambuc     // token "\" and a comment.
710*0a6a1f1dSLionel Sambuc     bool MightEndWithEscapedSlash =
711*0a6a1f1dSLionel Sambuc         Tokens.back()->is(tok::comment) &&
712*0a6a1f1dSLionel Sambuc         Tokens.back()->TokenText.startswith("//") &&
713*0a6a1f1dSLionel Sambuc         Tokens[Tokens.size() - 2]->TokenText == "\\";
714*0a6a1f1dSLionel Sambuc     if (!MightEndWithEscapedSlash &&
715*0a6a1f1dSLionel Sambuc         (Tokens.back()->isNot(tok::slash) ||
716*0a6a1f1dSLionel Sambuc          (Tokens[Tokens.size() - 2]->is(tok::unknown) &&
717*0a6a1f1dSLionel Sambuc           Tokens[Tokens.size() - 2]->TokenText == "\\")))
718*0a6a1f1dSLionel Sambuc       return false;
719*0a6a1f1dSLionel Sambuc     unsigned TokenCount = 0;
720*0a6a1f1dSLionel Sambuc     unsigned LastColumn = Tokens.back()->OriginalColumn;
721*0a6a1f1dSLionel Sambuc     for (auto I = Tokens.rbegin() + 1, E = Tokens.rend(); I != E; ++I) {
722*0a6a1f1dSLionel Sambuc       ++TokenCount;
723*0a6a1f1dSLionel Sambuc       if (I[0]->is(tok::slash) && I + 1 != E &&
724*0a6a1f1dSLionel Sambuc           (I[1]->isOneOf(tok::l_paren, tok::semi, tok::l_brace, tok::r_brace,
725*0a6a1f1dSLionel Sambuc                          tok::exclaim, tok::l_square, tok::colon, tok::comma,
726*0a6a1f1dSLionel Sambuc                          tok::question, tok::kw_return) ||
727*0a6a1f1dSLionel Sambuc            I[1]->isBinaryOperator())) {
728*0a6a1f1dSLionel Sambuc         if (MightEndWithEscapedSlash) {
729*0a6a1f1dSLionel Sambuc           // This regex literal ends in '\//'. Skip past the '//' of the last
730*0a6a1f1dSLionel Sambuc           // token and re-start lexing from there.
731*0a6a1f1dSLionel Sambuc           SourceLocation Loc = Tokens.back()->Tok.getLocation();
732*0a6a1f1dSLionel Sambuc           resetLexer(SourceMgr.getFileOffset(Loc) + 2);
733*0a6a1f1dSLionel Sambuc         }
734*0a6a1f1dSLionel Sambuc         Tokens.resize(Tokens.size() - TokenCount);
735*0a6a1f1dSLionel Sambuc         Tokens.back()->Tok.setKind(tok::unknown);
736*0a6a1f1dSLionel Sambuc         Tokens.back()->Type = TT_RegexLiteral;
737*0a6a1f1dSLionel Sambuc         Tokens.back()->ColumnWidth += LastColumn - I[0]->OriginalColumn;
738*0a6a1f1dSLionel Sambuc         return true;
739*0a6a1f1dSLionel Sambuc       }
740*0a6a1f1dSLionel Sambuc 
741*0a6a1f1dSLionel Sambuc       // There can't be a newline inside a regex literal.
742*0a6a1f1dSLionel Sambuc       if (I[0]->NewlinesBefore > 0)
743*0a6a1f1dSLionel Sambuc         return false;
744*0a6a1f1dSLionel Sambuc     }
745*0a6a1f1dSLionel Sambuc     return false;
746*0a6a1f1dSLionel Sambuc   }
747*0a6a1f1dSLionel Sambuc 
tryMerge_TMacro()748*0a6a1f1dSLionel Sambuc   bool tryMerge_TMacro() {
749*0a6a1f1dSLionel Sambuc     if (Tokens.size() < 4)
750*0a6a1f1dSLionel Sambuc       return false;
751f4a2713aSLionel Sambuc     FormatToken *Last = Tokens.back();
752f4a2713aSLionel Sambuc     if (!Last->is(tok::r_paren))
753*0a6a1f1dSLionel Sambuc       return false;
754f4a2713aSLionel Sambuc 
755f4a2713aSLionel Sambuc     FormatToken *String = Tokens[Tokens.size() - 2];
756f4a2713aSLionel Sambuc     if (!String->is(tok::string_literal) || String->IsMultiline)
757*0a6a1f1dSLionel Sambuc       return false;
758f4a2713aSLionel Sambuc 
759f4a2713aSLionel Sambuc     if (!Tokens[Tokens.size() - 3]->is(tok::l_paren))
760*0a6a1f1dSLionel Sambuc       return false;
761f4a2713aSLionel Sambuc 
762f4a2713aSLionel Sambuc     FormatToken *Macro = Tokens[Tokens.size() - 4];
763f4a2713aSLionel Sambuc     if (Macro->TokenText != "_T")
764*0a6a1f1dSLionel Sambuc       return false;
765f4a2713aSLionel Sambuc 
766f4a2713aSLionel Sambuc     const char *Start = Macro->TokenText.data();
767f4a2713aSLionel Sambuc     const char *End = Last->TokenText.data() + Last->TokenText.size();
768f4a2713aSLionel Sambuc     String->TokenText = StringRef(Start, End - Start);
769f4a2713aSLionel Sambuc     String->IsFirst = Macro->IsFirst;
770f4a2713aSLionel Sambuc     String->LastNewlineOffset = Macro->LastNewlineOffset;
771f4a2713aSLionel Sambuc     String->WhitespaceRange = Macro->WhitespaceRange;
772f4a2713aSLionel Sambuc     String->OriginalColumn = Macro->OriginalColumn;
773f4a2713aSLionel Sambuc     String->ColumnWidth = encoding::columnWidthWithTabs(
774f4a2713aSLionel Sambuc         String->TokenText, String->OriginalColumn, Style.TabWidth, Encoding);
775f4a2713aSLionel Sambuc 
776f4a2713aSLionel Sambuc     Tokens.pop_back();
777f4a2713aSLionel Sambuc     Tokens.pop_back();
778f4a2713aSLionel Sambuc     Tokens.pop_back();
779f4a2713aSLionel Sambuc     Tokens.back() = String;
780*0a6a1f1dSLionel Sambuc     return true;
781*0a6a1f1dSLionel Sambuc   }
782*0a6a1f1dSLionel Sambuc 
tryMergeConflictMarkers()783*0a6a1f1dSLionel Sambuc   bool tryMergeConflictMarkers() {
784*0a6a1f1dSLionel Sambuc     if (Tokens.back()->NewlinesBefore == 0 && Tokens.back()->isNot(tok::eof))
785*0a6a1f1dSLionel Sambuc       return false;
786*0a6a1f1dSLionel Sambuc 
787*0a6a1f1dSLionel Sambuc     // Conflict lines look like:
788*0a6a1f1dSLionel Sambuc     // <marker> <text from the vcs>
789*0a6a1f1dSLionel Sambuc     // For example:
790*0a6a1f1dSLionel Sambuc     // >>>>>>> /file/in/file/system at revision 1234
791*0a6a1f1dSLionel Sambuc     //
792*0a6a1f1dSLionel Sambuc     // We merge all tokens in a line that starts with a conflict marker
793*0a6a1f1dSLionel Sambuc     // into a single token with a special token type that the unwrapped line
794*0a6a1f1dSLionel Sambuc     // parser will use to correctly rebuild the underlying code.
795*0a6a1f1dSLionel Sambuc 
796*0a6a1f1dSLionel Sambuc     FileID ID;
797*0a6a1f1dSLionel Sambuc     // Get the position of the first token in the line.
798*0a6a1f1dSLionel Sambuc     unsigned FirstInLineOffset;
799*0a6a1f1dSLionel Sambuc     std::tie(ID, FirstInLineOffset) = SourceMgr.getDecomposedLoc(
800*0a6a1f1dSLionel Sambuc         Tokens[FirstInLineIndex]->getStartOfNonWhitespace());
801*0a6a1f1dSLionel Sambuc     StringRef Buffer = SourceMgr.getBuffer(ID)->getBuffer();
802*0a6a1f1dSLionel Sambuc     // Calculate the offset of the start of the current line.
803*0a6a1f1dSLionel Sambuc     auto LineOffset = Buffer.rfind('\n', FirstInLineOffset);
804*0a6a1f1dSLionel Sambuc     if (LineOffset == StringRef::npos) {
805*0a6a1f1dSLionel Sambuc       LineOffset = 0;
806*0a6a1f1dSLionel Sambuc     } else {
807*0a6a1f1dSLionel Sambuc       ++LineOffset;
808*0a6a1f1dSLionel Sambuc     }
809*0a6a1f1dSLionel Sambuc 
810*0a6a1f1dSLionel Sambuc     auto FirstSpace = Buffer.find_first_of(" \n", LineOffset);
811*0a6a1f1dSLionel Sambuc     StringRef LineStart;
812*0a6a1f1dSLionel Sambuc     if (FirstSpace == StringRef::npos) {
813*0a6a1f1dSLionel Sambuc       LineStart = Buffer.substr(LineOffset);
814*0a6a1f1dSLionel Sambuc     } else {
815*0a6a1f1dSLionel Sambuc       LineStart = Buffer.substr(LineOffset, FirstSpace - LineOffset);
816*0a6a1f1dSLionel Sambuc     }
817*0a6a1f1dSLionel Sambuc 
818*0a6a1f1dSLionel Sambuc     TokenType Type = TT_Unknown;
819*0a6a1f1dSLionel Sambuc     if (LineStart == "<<<<<<<" || LineStart == ">>>>") {
820*0a6a1f1dSLionel Sambuc       Type = TT_ConflictStart;
821*0a6a1f1dSLionel Sambuc     } else if (LineStart == "|||||||" || LineStart == "=======" ||
822*0a6a1f1dSLionel Sambuc                LineStart == "====") {
823*0a6a1f1dSLionel Sambuc       Type = TT_ConflictAlternative;
824*0a6a1f1dSLionel Sambuc     } else if (LineStart == ">>>>>>>" || LineStart == "<<<<") {
825*0a6a1f1dSLionel Sambuc       Type = TT_ConflictEnd;
826*0a6a1f1dSLionel Sambuc     }
827*0a6a1f1dSLionel Sambuc 
828*0a6a1f1dSLionel Sambuc     if (Type != TT_Unknown) {
829*0a6a1f1dSLionel Sambuc       FormatToken *Next = Tokens.back();
830*0a6a1f1dSLionel Sambuc 
831*0a6a1f1dSLionel Sambuc       Tokens.resize(FirstInLineIndex + 1);
832*0a6a1f1dSLionel Sambuc       // We do not need to build a complete token here, as we will skip it
833*0a6a1f1dSLionel Sambuc       // during parsing anyway (as we must not touch whitespace around conflict
834*0a6a1f1dSLionel Sambuc       // markers).
835*0a6a1f1dSLionel Sambuc       Tokens.back()->Type = Type;
836*0a6a1f1dSLionel Sambuc       Tokens.back()->Tok.setKind(tok::kw___unknown_anytype);
837*0a6a1f1dSLionel Sambuc 
838*0a6a1f1dSLionel Sambuc       Tokens.push_back(Next);
839*0a6a1f1dSLionel Sambuc       return true;
840*0a6a1f1dSLionel Sambuc     }
841*0a6a1f1dSLionel Sambuc 
842*0a6a1f1dSLionel Sambuc     return false;
843f4a2713aSLionel Sambuc   }
844f4a2713aSLionel Sambuc 
getNextToken()845f4a2713aSLionel Sambuc   FormatToken *getNextToken() {
846f4a2713aSLionel Sambuc     if (GreaterStashed) {
847f4a2713aSLionel Sambuc       // Create a synthesized second '>' token.
848f4a2713aSLionel Sambuc       // FIXME: Increment Column and set OriginalColumn.
849f4a2713aSLionel Sambuc       Token Greater = FormatTok->Tok;
850f4a2713aSLionel Sambuc       FormatTok = new (Allocator.Allocate()) FormatToken;
851f4a2713aSLionel Sambuc       FormatTok->Tok = Greater;
852f4a2713aSLionel Sambuc       SourceLocation GreaterLocation =
853f4a2713aSLionel Sambuc           FormatTok->Tok.getLocation().getLocWithOffset(1);
854f4a2713aSLionel Sambuc       FormatTok->WhitespaceRange =
855f4a2713aSLionel Sambuc           SourceRange(GreaterLocation, GreaterLocation);
856f4a2713aSLionel Sambuc       FormatTok->TokenText = ">";
857f4a2713aSLionel Sambuc       FormatTok->ColumnWidth = 1;
858f4a2713aSLionel Sambuc       GreaterStashed = false;
859f4a2713aSLionel Sambuc       return FormatTok;
860f4a2713aSLionel Sambuc     }
861f4a2713aSLionel Sambuc 
862f4a2713aSLionel Sambuc     FormatTok = new (Allocator.Allocate()) FormatToken;
863f4a2713aSLionel Sambuc     readRawToken(*FormatTok);
864f4a2713aSLionel Sambuc     SourceLocation WhitespaceStart =
865f4a2713aSLionel Sambuc         FormatTok->Tok.getLocation().getLocWithOffset(-TrailingWhitespace);
866f4a2713aSLionel Sambuc     FormatTok->IsFirst = IsFirstToken;
867f4a2713aSLionel Sambuc     IsFirstToken = false;
868f4a2713aSLionel Sambuc 
869f4a2713aSLionel Sambuc     // Consume and record whitespace until we find a significant token.
870f4a2713aSLionel Sambuc     unsigned WhitespaceLength = TrailingWhitespace;
871f4a2713aSLionel Sambuc     while (FormatTok->Tok.is(tok::unknown)) {
872f4a2713aSLionel Sambuc       for (int i = 0, e = FormatTok->TokenText.size(); i != e; ++i) {
873f4a2713aSLionel Sambuc         switch (FormatTok->TokenText[i]) {
874f4a2713aSLionel Sambuc         case '\n':
875f4a2713aSLionel Sambuc           ++FormatTok->NewlinesBefore;
876f4a2713aSLionel Sambuc           // FIXME: This is technically incorrect, as it could also
877f4a2713aSLionel Sambuc           // be a literal backslash at the end of the line.
878f4a2713aSLionel Sambuc           if (i == 0 || (FormatTok->TokenText[i - 1] != '\\' &&
879f4a2713aSLionel Sambuc                          (FormatTok->TokenText[i - 1] != '\r' || i == 1 ||
880f4a2713aSLionel Sambuc                           FormatTok->TokenText[i - 2] != '\\')))
881f4a2713aSLionel Sambuc             FormatTok->HasUnescapedNewline = true;
882f4a2713aSLionel Sambuc           FormatTok->LastNewlineOffset = WhitespaceLength + i + 1;
883f4a2713aSLionel Sambuc           Column = 0;
884f4a2713aSLionel Sambuc           break;
885f4a2713aSLionel Sambuc         case '\r':
886f4a2713aSLionel Sambuc         case '\f':
887f4a2713aSLionel Sambuc         case '\v':
888f4a2713aSLionel Sambuc           Column = 0;
889f4a2713aSLionel Sambuc           break;
890f4a2713aSLionel Sambuc         case ' ':
891f4a2713aSLionel Sambuc           ++Column;
892f4a2713aSLionel Sambuc           break;
893f4a2713aSLionel Sambuc         case '\t':
894f4a2713aSLionel Sambuc           Column += Style.TabWidth - Column % Style.TabWidth;
895f4a2713aSLionel Sambuc           break;
896f4a2713aSLionel Sambuc         case '\\':
897f4a2713aSLionel Sambuc           if (i + 1 == e || (FormatTok->TokenText[i + 1] != '\r' &&
898f4a2713aSLionel Sambuc                              FormatTok->TokenText[i + 1] != '\n'))
899f4a2713aSLionel Sambuc             FormatTok->Type = TT_ImplicitStringLiteral;
900f4a2713aSLionel Sambuc           break;
901f4a2713aSLionel Sambuc         default:
902f4a2713aSLionel Sambuc           FormatTok->Type = TT_ImplicitStringLiteral;
903f4a2713aSLionel Sambuc           ++Column;
904f4a2713aSLionel Sambuc           break;
905f4a2713aSLionel Sambuc         }
906f4a2713aSLionel Sambuc       }
907f4a2713aSLionel Sambuc 
908*0a6a1f1dSLionel Sambuc       if (FormatTok->is(TT_ImplicitStringLiteral))
909f4a2713aSLionel Sambuc         break;
910f4a2713aSLionel Sambuc       WhitespaceLength += FormatTok->Tok.getLength();
911f4a2713aSLionel Sambuc 
912f4a2713aSLionel Sambuc       readRawToken(*FormatTok);
913f4a2713aSLionel Sambuc     }
914f4a2713aSLionel Sambuc 
915f4a2713aSLionel Sambuc     // In case the token starts with escaped newlines, we want to
916f4a2713aSLionel Sambuc     // take them into account as whitespace - this pattern is quite frequent
917f4a2713aSLionel Sambuc     // in macro definitions.
918f4a2713aSLionel Sambuc     // FIXME: Add a more explicit test.
919f4a2713aSLionel Sambuc     while (FormatTok->TokenText.size() > 1 && FormatTok->TokenText[0] == '\\' &&
920f4a2713aSLionel Sambuc            FormatTok->TokenText[1] == '\n') {
921*0a6a1f1dSLionel Sambuc       ++FormatTok->NewlinesBefore;
922f4a2713aSLionel Sambuc       WhitespaceLength += 2;
923f4a2713aSLionel Sambuc       Column = 0;
924f4a2713aSLionel Sambuc       FormatTok->TokenText = FormatTok->TokenText.substr(2);
925f4a2713aSLionel Sambuc     }
926f4a2713aSLionel Sambuc 
927f4a2713aSLionel Sambuc     FormatTok->WhitespaceRange = SourceRange(
928f4a2713aSLionel Sambuc         WhitespaceStart, WhitespaceStart.getLocWithOffset(WhitespaceLength));
929f4a2713aSLionel Sambuc 
930f4a2713aSLionel Sambuc     FormatTok->OriginalColumn = Column;
931f4a2713aSLionel Sambuc 
932f4a2713aSLionel Sambuc     TrailingWhitespace = 0;
933f4a2713aSLionel Sambuc     if (FormatTok->Tok.is(tok::comment)) {
934f4a2713aSLionel Sambuc       // FIXME: Add the trimmed whitespace to Column.
935f4a2713aSLionel Sambuc       StringRef UntrimmedText = FormatTok->TokenText;
936f4a2713aSLionel Sambuc       FormatTok->TokenText = FormatTok->TokenText.rtrim(" \t\v\f");
937f4a2713aSLionel Sambuc       TrailingWhitespace = UntrimmedText.size() - FormatTok->TokenText.size();
938f4a2713aSLionel Sambuc     } else if (FormatTok->Tok.is(tok::raw_identifier)) {
939f4a2713aSLionel Sambuc       IdentifierInfo &Info = IdentTable.get(FormatTok->TokenText);
940f4a2713aSLionel Sambuc       FormatTok->Tok.setIdentifierInfo(&Info);
941f4a2713aSLionel Sambuc       FormatTok->Tok.setKind(Info.getTokenID());
942*0a6a1f1dSLionel Sambuc       if (Style.Language == FormatStyle::LK_Java &&
943*0a6a1f1dSLionel Sambuc           FormatTok->isOneOf(tok::kw_struct, tok::kw_union, tok::kw_delete)) {
944*0a6a1f1dSLionel Sambuc         FormatTok->Tok.setKind(tok::identifier);
945*0a6a1f1dSLionel Sambuc         FormatTok->Tok.setIdentifierInfo(nullptr);
946*0a6a1f1dSLionel Sambuc       }
947f4a2713aSLionel Sambuc     } else if (FormatTok->Tok.is(tok::greatergreater)) {
948f4a2713aSLionel Sambuc       FormatTok->Tok.setKind(tok::greater);
949f4a2713aSLionel Sambuc       FormatTok->TokenText = FormatTok->TokenText.substr(0, 1);
950f4a2713aSLionel Sambuc       GreaterStashed = true;
951f4a2713aSLionel Sambuc     }
952f4a2713aSLionel Sambuc 
953f4a2713aSLionel Sambuc     // Now FormatTok is the next non-whitespace token.
954f4a2713aSLionel Sambuc 
955f4a2713aSLionel Sambuc     StringRef Text = FormatTok->TokenText;
956f4a2713aSLionel Sambuc     size_t FirstNewlinePos = Text.find('\n');
957f4a2713aSLionel Sambuc     if (FirstNewlinePos == StringRef::npos) {
958f4a2713aSLionel Sambuc       // FIXME: ColumnWidth actually depends on the start column, we need to
959f4a2713aSLionel Sambuc       // take this into account when the token is moved.
960f4a2713aSLionel Sambuc       FormatTok->ColumnWidth =
961f4a2713aSLionel Sambuc           encoding::columnWidthWithTabs(Text, Column, Style.TabWidth, Encoding);
962f4a2713aSLionel Sambuc       Column += FormatTok->ColumnWidth;
963f4a2713aSLionel Sambuc     } else {
964f4a2713aSLionel Sambuc       FormatTok->IsMultiline = true;
965f4a2713aSLionel Sambuc       // FIXME: ColumnWidth actually depends on the start column, we need to
966f4a2713aSLionel Sambuc       // take this into account when the token is moved.
967f4a2713aSLionel Sambuc       FormatTok->ColumnWidth = encoding::columnWidthWithTabs(
968f4a2713aSLionel Sambuc           Text.substr(0, FirstNewlinePos), Column, Style.TabWidth, Encoding);
969f4a2713aSLionel Sambuc 
970f4a2713aSLionel Sambuc       // The last line of the token always starts in column 0.
971f4a2713aSLionel Sambuc       // Thus, the length can be precomputed even in the presence of tabs.
972f4a2713aSLionel Sambuc       FormatTok->LastLineColumnWidth = encoding::columnWidthWithTabs(
973f4a2713aSLionel Sambuc           Text.substr(Text.find_last_of('\n') + 1), 0, Style.TabWidth,
974f4a2713aSLionel Sambuc           Encoding);
975f4a2713aSLionel Sambuc       Column = FormatTok->LastLineColumnWidth;
976f4a2713aSLionel Sambuc     }
977f4a2713aSLionel Sambuc 
978*0a6a1f1dSLionel Sambuc     FormatTok->IsForEachMacro =
979*0a6a1f1dSLionel Sambuc         std::binary_search(ForEachMacros.begin(), ForEachMacros.end(),
980*0a6a1f1dSLionel Sambuc                            FormatTok->Tok.getIdentifierInfo());
981*0a6a1f1dSLionel Sambuc 
982f4a2713aSLionel Sambuc     return FormatTok;
983f4a2713aSLionel Sambuc   }
984f4a2713aSLionel Sambuc 
985f4a2713aSLionel Sambuc   FormatToken *FormatTok;
986f4a2713aSLionel Sambuc   bool IsFirstToken;
987f4a2713aSLionel Sambuc   bool GreaterStashed;
988f4a2713aSLionel Sambuc   unsigned Column;
989f4a2713aSLionel Sambuc   unsigned TrailingWhitespace;
990*0a6a1f1dSLionel Sambuc   std::unique_ptr<Lexer> Lex;
991f4a2713aSLionel Sambuc   SourceManager &SourceMgr;
992*0a6a1f1dSLionel Sambuc   FileID ID;
993f4a2713aSLionel Sambuc   FormatStyle &Style;
994f4a2713aSLionel Sambuc   IdentifierTable IdentTable;
995*0a6a1f1dSLionel Sambuc   AdditionalKeywords Keywords;
996f4a2713aSLionel Sambuc   encoding::Encoding Encoding;
997f4a2713aSLionel Sambuc   llvm::SpecificBumpPtrAllocator<FormatToken> Allocator;
998*0a6a1f1dSLionel Sambuc   // Index (in 'Tokens') of the last token that starts a new line.
999*0a6a1f1dSLionel Sambuc   unsigned FirstInLineIndex;
1000f4a2713aSLionel Sambuc   SmallVector<FormatToken *, 16> Tokens;
1001*0a6a1f1dSLionel Sambuc   SmallVector<IdentifierInfo *, 8> ForEachMacros;
1002*0a6a1f1dSLionel Sambuc 
1003*0a6a1f1dSLionel Sambuc   bool FormattingDisabled;
1004f4a2713aSLionel Sambuc 
readRawToken(FormatToken & Tok)1005f4a2713aSLionel Sambuc   void readRawToken(FormatToken &Tok) {
1006*0a6a1f1dSLionel Sambuc     Lex->LexFromRawLexer(Tok.Tok);
1007f4a2713aSLionel Sambuc     Tok.TokenText = StringRef(SourceMgr.getCharacterData(Tok.Tok.getLocation()),
1008f4a2713aSLionel Sambuc                               Tok.Tok.getLength());
1009f4a2713aSLionel Sambuc     // For formatting, treat unterminated string literals like normal string
1010f4a2713aSLionel Sambuc     // literals.
1011*0a6a1f1dSLionel Sambuc     if (Tok.is(tok::unknown)) {
1012*0a6a1f1dSLionel Sambuc       if (!Tok.TokenText.empty() && Tok.TokenText[0] == '"') {
1013f4a2713aSLionel Sambuc         Tok.Tok.setKind(tok::string_literal);
1014f4a2713aSLionel Sambuc         Tok.IsUnterminatedLiteral = true;
1015*0a6a1f1dSLionel Sambuc       } else if (Style.Language == FormatStyle::LK_JavaScript &&
1016*0a6a1f1dSLionel Sambuc                  Tok.TokenText == "''") {
1017*0a6a1f1dSLionel Sambuc         Tok.Tok.setKind(tok::char_constant);
1018f4a2713aSLionel Sambuc       }
1019f4a2713aSLionel Sambuc     }
1020*0a6a1f1dSLionel Sambuc 
1021*0a6a1f1dSLionel Sambuc     if (Tok.is(tok::comment) && (Tok.TokenText == "// clang-format on" ||
1022*0a6a1f1dSLionel Sambuc                                  Tok.TokenText == "/* clang-format on */")) {
1023*0a6a1f1dSLionel Sambuc       FormattingDisabled = false;
1024*0a6a1f1dSLionel Sambuc     }
1025*0a6a1f1dSLionel Sambuc 
1026*0a6a1f1dSLionel Sambuc     Tok.Finalized = FormattingDisabled;
1027*0a6a1f1dSLionel Sambuc 
1028*0a6a1f1dSLionel Sambuc     if (Tok.is(tok::comment) && (Tok.TokenText == "// clang-format off" ||
1029*0a6a1f1dSLionel Sambuc                                  Tok.TokenText == "/* clang-format off */")) {
1030*0a6a1f1dSLionel Sambuc       FormattingDisabled = true;
1031*0a6a1f1dSLionel Sambuc     }
1032*0a6a1f1dSLionel Sambuc   }
1033*0a6a1f1dSLionel Sambuc 
resetLexer(unsigned Offset)1034*0a6a1f1dSLionel Sambuc   void resetLexer(unsigned Offset) {
1035*0a6a1f1dSLionel Sambuc     StringRef Buffer = SourceMgr.getBufferData(ID);
1036*0a6a1f1dSLionel Sambuc     Lex.reset(new Lexer(SourceMgr.getLocForStartOfFile(ID),
1037*0a6a1f1dSLionel Sambuc                         getFormattingLangOpts(Style), Buffer.begin(),
1038*0a6a1f1dSLionel Sambuc                         Buffer.begin() + Offset, Buffer.end()));
1039*0a6a1f1dSLionel Sambuc     Lex->SetKeepWhitespaceMode(true);
1040*0a6a1f1dSLionel Sambuc   }
1041f4a2713aSLionel Sambuc };
1042f4a2713aSLionel Sambuc 
getLanguageName(FormatStyle::LanguageKind Language)1043*0a6a1f1dSLionel Sambuc static StringRef getLanguageName(FormatStyle::LanguageKind Language) {
1044*0a6a1f1dSLionel Sambuc   switch (Language) {
1045*0a6a1f1dSLionel Sambuc   case FormatStyle::LK_Cpp:
1046*0a6a1f1dSLionel Sambuc     return "C++";
1047*0a6a1f1dSLionel Sambuc   case FormatStyle::LK_Java:
1048*0a6a1f1dSLionel Sambuc     return "Java";
1049*0a6a1f1dSLionel Sambuc   case FormatStyle::LK_JavaScript:
1050*0a6a1f1dSLionel Sambuc     return "JavaScript";
1051*0a6a1f1dSLionel Sambuc   case FormatStyle::LK_Proto:
1052*0a6a1f1dSLionel Sambuc     return "Proto";
1053*0a6a1f1dSLionel Sambuc   default:
1054*0a6a1f1dSLionel Sambuc     return "Unknown";
1055*0a6a1f1dSLionel Sambuc   }
1056*0a6a1f1dSLionel Sambuc }
1057*0a6a1f1dSLionel Sambuc 
1058f4a2713aSLionel Sambuc class Formatter : public UnwrappedLineConsumer {
1059f4a2713aSLionel Sambuc public:
Formatter(const FormatStyle & Style,SourceManager & SourceMgr,FileID ID,ArrayRef<CharSourceRange> Ranges)1060*0a6a1f1dSLionel Sambuc   Formatter(const FormatStyle &Style, SourceManager &SourceMgr, FileID ID,
1061*0a6a1f1dSLionel Sambuc             ArrayRef<CharSourceRange> Ranges)
1062*0a6a1f1dSLionel Sambuc       : Style(Style), ID(ID), SourceMgr(SourceMgr),
1063*0a6a1f1dSLionel Sambuc         Whitespaces(SourceMgr, Style,
1064*0a6a1f1dSLionel Sambuc                     inputUsesCRLF(SourceMgr.getBufferData(ID))),
1065f4a2713aSLionel Sambuc         Ranges(Ranges.begin(), Ranges.end()), UnwrappedLines(1),
1066*0a6a1f1dSLionel Sambuc         Encoding(encoding::detectEncoding(SourceMgr.getBufferData(ID))) {
1067f4a2713aSLionel Sambuc     DEBUG(llvm::dbgs() << "File encoding: "
1068f4a2713aSLionel Sambuc                        << (Encoding == encoding::Encoding_UTF8 ? "UTF8"
1069f4a2713aSLionel Sambuc                                                                : "unknown")
1070f4a2713aSLionel Sambuc                        << "\n");
1071*0a6a1f1dSLionel Sambuc     DEBUG(llvm::dbgs() << "Language: " << getLanguageName(Style.Language)
1072*0a6a1f1dSLionel Sambuc                        << "\n");
1073f4a2713aSLionel Sambuc   }
1074f4a2713aSLionel Sambuc 
format()1075f4a2713aSLionel Sambuc   tooling::Replacements format() {
1076f4a2713aSLionel Sambuc     tooling::Replacements Result;
1077*0a6a1f1dSLionel Sambuc     FormatTokenLexer Tokens(SourceMgr, ID, Style, Encoding);
1078f4a2713aSLionel Sambuc 
1079*0a6a1f1dSLionel Sambuc     UnwrappedLineParser Parser(Style, Tokens.getKeywords(), Tokens.lex(),
1080*0a6a1f1dSLionel Sambuc                                *this);
1081f4a2713aSLionel Sambuc     bool StructuralError = Parser.parse();
1082f4a2713aSLionel Sambuc     assert(UnwrappedLines.rbegin()->empty());
1083f4a2713aSLionel Sambuc     for (unsigned Run = 0, RunE = UnwrappedLines.size(); Run + 1 != RunE;
1084f4a2713aSLionel Sambuc          ++Run) {
1085f4a2713aSLionel Sambuc       DEBUG(llvm::dbgs() << "Run " << Run << "...\n");
1086f4a2713aSLionel Sambuc       SmallVector<AnnotatedLine *, 16> AnnotatedLines;
1087f4a2713aSLionel Sambuc       for (unsigned i = 0, e = UnwrappedLines[Run].size(); i != e; ++i) {
1088f4a2713aSLionel Sambuc         AnnotatedLines.push_back(new AnnotatedLine(UnwrappedLines[Run][i]));
1089f4a2713aSLionel Sambuc       }
1090f4a2713aSLionel Sambuc       tooling::Replacements RunResult =
1091f4a2713aSLionel Sambuc           format(AnnotatedLines, StructuralError, Tokens);
1092f4a2713aSLionel Sambuc       DEBUG({
1093f4a2713aSLionel Sambuc         llvm::dbgs() << "Replacements for run " << Run << ":\n";
1094f4a2713aSLionel Sambuc         for (tooling::Replacements::iterator I = RunResult.begin(),
1095f4a2713aSLionel Sambuc                                              E = RunResult.end();
1096f4a2713aSLionel Sambuc              I != E; ++I) {
1097f4a2713aSLionel Sambuc           llvm::dbgs() << I->toString() << "\n";
1098f4a2713aSLionel Sambuc         }
1099f4a2713aSLionel Sambuc       });
1100f4a2713aSLionel Sambuc       for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
1101f4a2713aSLionel Sambuc         delete AnnotatedLines[i];
1102f4a2713aSLionel Sambuc       }
1103f4a2713aSLionel Sambuc       Result.insert(RunResult.begin(), RunResult.end());
1104f4a2713aSLionel Sambuc       Whitespaces.reset();
1105f4a2713aSLionel Sambuc     }
1106f4a2713aSLionel Sambuc     return Result;
1107f4a2713aSLionel Sambuc   }
1108f4a2713aSLionel Sambuc 
format(SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,bool StructuralError,FormatTokenLexer & Tokens)1109f4a2713aSLionel Sambuc   tooling::Replacements format(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1110f4a2713aSLionel Sambuc                                bool StructuralError, FormatTokenLexer &Tokens) {
1111*0a6a1f1dSLionel Sambuc     TokenAnnotator Annotator(Style, Tokens.getKeywords());
1112f4a2713aSLionel Sambuc     for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
1113f4a2713aSLionel Sambuc       Annotator.annotate(*AnnotatedLines[i]);
1114f4a2713aSLionel Sambuc     }
1115f4a2713aSLionel Sambuc     deriveLocalStyle(AnnotatedLines);
1116f4a2713aSLionel Sambuc     for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
1117f4a2713aSLionel Sambuc       Annotator.calculateFormattingInformation(*AnnotatedLines[i]);
1118f4a2713aSLionel Sambuc     }
1119*0a6a1f1dSLionel Sambuc     computeAffectedLines(AnnotatedLines.begin(), AnnotatedLines.end());
1120f4a2713aSLionel Sambuc 
1121f4a2713aSLionel Sambuc     Annotator.setCommentLineLevels(AnnotatedLines);
1122*0a6a1f1dSLionel Sambuc     ContinuationIndenter Indenter(Style, Tokens.getKeywords(), SourceMgr,
1123*0a6a1f1dSLionel Sambuc                                   Whitespaces, Encoding,
1124f4a2713aSLionel Sambuc                                   BinPackInconclusiveFunctions);
1125*0a6a1f1dSLionel Sambuc     UnwrappedLineFormatter Formatter(&Indenter, &Whitespaces, Style);
1126f4a2713aSLionel Sambuc     Formatter.format(AnnotatedLines, /*DryRun=*/false);
1127f4a2713aSLionel Sambuc     return Whitespaces.generateReplacements();
1128f4a2713aSLionel Sambuc   }
1129f4a2713aSLionel Sambuc 
1130f4a2713aSLionel Sambuc private:
1131*0a6a1f1dSLionel Sambuc   // Determines which lines are affected by the SourceRanges given as input.
1132*0a6a1f1dSLionel Sambuc   // Returns \c true if at least one line between I and E or one of their
1133*0a6a1f1dSLionel Sambuc   // children is affected.
computeAffectedLines(SmallVectorImpl<AnnotatedLine * >::iterator I,SmallVectorImpl<AnnotatedLine * >::iterator E)1134*0a6a1f1dSLionel Sambuc   bool computeAffectedLines(SmallVectorImpl<AnnotatedLine *>::iterator I,
1135*0a6a1f1dSLionel Sambuc                             SmallVectorImpl<AnnotatedLine *>::iterator E) {
1136*0a6a1f1dSLionel Sambuc     bool SomeLineAffected = false;
1137*0a6a1f1dSLionel Sambuc     const AnnotatedLine *PreviousLine = nullptr;
1138*0a6a1f1dSLionel Sambuc     while (I != E) {
1139*0a6a1f1dSLionel Sambuc       AnnotatedLine *Line = *I;
1140*0a6a1f1dSLionel Sambuc       Line->LeadingEmptyLinesAffected = affectsLeadingEmptyLines(*Line->First);
1141*0a6a1f1dSLionel Sambuc 
1142*0a6a1f1dSLionel Sambuc       // If a line is part of a preprocessor directive, it needs to be formatted
1143*0a6a1f1dSLionel Sambuc       // if any token within the directive is affected.
1144*0a6a1f1dSLionel Sambuc       if (Line->InPPDirective) {
1145*0a6a1f1dSLionel Sambuc         FormatToken *Last = Line->Last;
1146*0a6a1f1dSLionel Sambuc         SmallVectorImpl<AnnotatedLine *>::iterator PPEnd = I + 1;
1147*0a6a1f1dSLionel Sambuc         while (PPEnd != E && !(*PPEnd)->First->HasUnescapedNewline) {
1148*0a6a1f1dSLionel Sambuc           Last = (*PPEnd)->Last;
1149*0a6a1f1dSLionel Sambuc           ++PPEnd;
1150*0a6a1f1dSLionel Sambuc         }
1151*0a6a1f1dSLionel Sambuc 
1152*0a6a1f1dSLionel Sambuc         if (affectsTokenRange(*Line->First, *Last,
1153*0a6a1f1dSLionel Sambuc                               /*IncludeLeadingNewlines=*/false)) {
1154*0a6a1f1dSLionel Sambuc           SomeLineAffected = true;
1155*0a6a1f1dSLionel Sambuc           markAllAsAffected(I, PPEnd);
1156*0a6a1f1dSLionel Sambuc         }
1157*0a6a1f1dSLionel Sambuc         I = PPEnd;
1158*0a6a1f1dSLionel Sambuc         continue;
1159*0a6a1f1dSLionel Sambuc       }
1160*0a6a1f1dSLionel Sambuc 
1161*0a6a1f1dSLionel Sambuc       if (nonPPLineAffected(Line, PreviousLine))
1162*0a6a1f1dSLionel Sambuc         SomeLineAffected = true;
1163*0a6a1f1dSLionel Sambuc 
1164*0a6a1f1dSLionel Sambuc       PreviousLine = Line;
1165*0a6a1f1dSLionel Sambuc       ++I;
1166*0a6a1f1dSLionel Sambuc     }
1167*0a6a1f1dSLionel Sambuc     return SomeLineAffected;
1168*0a6a1f1dSLionel Sambuc   }
1169*0a6a1f1dSLionel Sambuc 
1170*0a6a1f1dSLionel Sambuc   // Determines whether 'Line' is affected by the SourceRanges given as input.
1171*0a6a1f1dSLionel Sambuc   // Returns \c true if line or one if its children is affected.
nonPPLineAffected(AnnotatedLine * Line,const AnnotatedLine * PreviousLine)1172*0a6a1f1dSLionel Sambuc   bool nonPPLineAffected(AnnotatedLine *Line,
1173*0a6a1f1dSLionel Sambuc                          const AnnotatedLine *PreviousLine) {
1174*0a6a1f1dSLionel Sambuc     bool SomeLineAffected = false;
1175*0a6a1f1dSLionel Sambuc     Line->ChildrenAffected =
1176*0a6a1f1dSLionel Sambuc         computeAffectedLines(Line->Children.begin(), Line->Children.end());
1177*0a6a1f1dSLionel Sambuc     if (Line->ChildrenAffected)
1178*0a6a1f1dSLionel Sambuc       SomeLineAffected = true;
1179*0a6a1f1dSLionel Sambuc 
1180*0a6a1f1dSLionel Sambuc     // Stores whether one of the line's tokens is directly affected.
1181*0a6a1f1dSLionel Sambuc     bool SomeTokenAffected = false;
1182*0a6a1f1dSLionel Sambuc     // Stores whether we need to look at the leading newlines of the next token
1183*0a6a1f1dSLionel Sambuc     // in order to determine whether it was affected.
1184*0a6a1f1dSLionel Sambuc     bool IncludeLeadingNewlines = false;
1185*0a6a1f1dSLionel Sambuc 
1186*0a6a1f1dSLionel Sambuc     // Stores whether the first child line of any of this line's tokens is
1187*0a6a1f1dSLionel Sambuc     // affected.
1188*0a6a1f1dSLionel Sambuc     bool SomeFirstChildAffected = false;
1189*0a6a1f1dSLionel Sambuc 
1190*0a6a1f1dSLionel Sambuc     for (FormatToken *Tok = Line->First; Tok; Tok = Tok->Next) {
1191*0a6a1f1dSLionel Sambuc       // Determine whether 'Tok' was affected.
1192*0a6a1f1dSLionel Sambuc       if (affectsTokenRange(*Tok, *Tok, IncludeLeadingNewlines))
1193*0a6a1f1dSLionel Sambuc         SomeTokenAffected = true;
1194*0a6a1f1dSLionel Sambuc 
1195*0a6a1f1dSLionel Sambuc       // Determine whether the first child of 'Tok' was affected.
1196*0a6a1f1dSLionel Sambuc       if (!Tok->Children.empty() && Tok->Children.front()->Affected)
1197*0a6a1f1dSLionel Sambuc         SomeFirstChildAffected = true;
1198*0a6a1f1dSLionel Sambuc 
1199*0a6a1f1dSLionel Sambuc       IncludeLeadingNewlines = Tok->Children.empty();
1200*0a6a1f1dSLionel Sambuc     }
1201*0a6a1f1dSLionel Sambuc 
1202*0a6a1f1dSLionel Sambuc     // Was this line moved, i.e. has it previously been on the same line as an
1203*0a6a1f1dSLionel Sambuc     // affected line?
1204*0a6a1f1dSLionel Sambuc     bool LineMoved = PreviousLine && PreviousLine->Affected &&
1205*0a6a1f1dSLionel Sambuc                      Line->First->NewlinesBefore == 0;
1206*0a6a1f1dSLionel Sambuc 
1207*0a6a1f1dSLionel Sambuc     bool IsContinuedComment =
1208*0a6a1f1dSLionel Sambuc         Line->First->is(tok::comment) && Line->First->Next == nullptr &&
1209*0a6a1f1dSLionel Sambuc         Line->First->NewlinesBefore < 2 && PreviousLine &&
1210*0a6a1f1dSLionel Sambuc         PreviousLine->Affected && PreviousLine->Last->is(tok::comment);
1211*0a6a1f1dSLionel Sambuc 
1212*0a6a1f1dSLionel Sambuc     if (SomeTokenAffected || SomeFirstChildAffected || LineMoved ||
1213*0a6a1f1dSLionel Sambuc         IsContinuedComment) {
1214*0a6a1f1dSLionel Sambuc       Line->Affected = true;
1215*0a6a1f1dSLionel Sambuc       SomeLineAffected = true;
1216*0a6a1f1dSLionel Sambuc     }
1217*0a6a1f1dSLionel Sambuc     return SomeLineAffected;
1218*0a6a1f1dSLionel Sambuc   }
1219*0a6a1f1dSLionel Sambuc 
1220*0a6a1f1dSLionel Sambuc   // Marks all lines between I and E as well as all their children as affected.
markAllAsAffected(SmallVectorImpl<AnnotatedLine * >::iterator I,SmallVectorImpl<AnnotatedLine * >::iterator E)1221*0a6a1f1dSLionel Sambuc   void markAllAsAffected(SmallVectorImpl<AnnotatedLine *>::iterator I,
1222*0a6a1f1dSLionel Sambuc                          SmallVectorImpl<AnnotatedLine *>::iterator E) {
1223*0a6a1f1dSLionel Sambuc     while (I != E) {
1224*0a6a1f1dSLionel Sambuc       (*I)->Affected = true;
1225*0a6a1f1dSLionel Sambuc       markAllAsAffected((*I)->Children.begin(), (*I)->Children.end());
1226*0a6a1f1dSLionel Sambuc       ++I;
1227*0a6a1f1dSLionel Sambuc     }
1228*0a6a1f1dSLionel Sambuc   }
1229*0a6a1f1dSLionel Sambuc 
1230*0a6a1f1dSLionel Sambuc   // Returns true if the range from 'First' to 'Last' intersects with one of the
1231*0a6a1f1dSLionel Sambuc   // input ranges.
affectsTokenRange(const FormatToken & First,const FormatToken & Last,bool IncludeLeadingNewlines)1232*0a6a1f1dSLionel Sambuc   bool affectsTokenRange(const FormatToken &First, const FormatToken &Last,
1233*0a6a1f1dSLionel Sambuc                          bool IncludeLeadingNewlines) {
1234*0a6a1f1dSLionel Sambuc     SourceLocation Start = First.WhitespaceRange.getBegin();
1235*0a6a1f1dSLionel Sambuc     if (!IncludeLeadingNewlines)
1236*0a6a1f1dSLionel Sambuc       Start = Start.getLocWithOffset(First.LastNewlineOffset);
1237*0a6a1f1dSLionel Sambuc     SourceLocation End = Last.getStartOfNonWhitespace();
1238*0a6a1f1dSLionel Sambuc     End = End.getLocWithOffset(Last.TokenText.size());
1239*0a6a1f1dSLionel Sambuc     CharSourceRange Range = CharSourceRange::getCharRange(Start, End);
1240*0a6a1f1dSLionel Sambuc     return affectsCharSourceRange(Range);
1241*0a6a1f1dSLionel Sambuc   }
1242*0a6a1f1dSLionel Sambuc 
1243*0a6a1f1dSLionel Sambuc   // Returns true if one of the input ranges intersect the leading empty lines
1244*0a6a1f1dSLionel Sambuc   // before 'Tok'.
affectsLeadingEmptyLines(const FormatToken & Tok)1245*0a6a1f1dSLionel Sambuc   bool affectsLeadingEmptyLines(const FormatToken &Tok) {
1246*0a6a1f1dSLionel Sambuc     CharSourceRange EmptyLineRange = CharSourceRange::getCharRange(
1247*0a6a1f1dSLionel Sambuc         Tok.WhitespaceRange.getBegin(),
1248*0a6a1f1dSLionel Sambuc         Tok.WhitespaceRange.getBegin().getLocWithOffset(Tok.LastNewlineOffset));
1249*0a6a1f1dSLionel Sambuc     return affectsCharSourceRange(EmptyLineRange);
1250*0a6a1f1dSLionel Sambuc   }
1251*0a6a1f1dSLionel Sambuc 
1252*0a6a1f1dSLionel Sambuc   // Returns true if 'Range' intersects with one of the input ranges.
affectsCharSourceRange(const CharSourceRange & Range)1253*0a6a1f1dSLionel Sambuc   bool affectsCharSourceRange(const CharSourceRange &Range) {
1254*0a6a1f1dSLionel Sambuc     for (SmallVectorImpl<CharSourceRange>::const_iterator I = Ranges.begin(),
1255*0a6a1f1dSLionel Sambuc                                                           E = Ranges.end();
1256*0a6a1f1dSLionel Sambuc          I != E; ++I) {
1257*0a6a1f1dSLionel Sambuc       if (!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), I->getBegin()) &&
1258*0a6a1f1dSLionel Sambuc           !SourceMgr.isBeforeInTranslationUnit(I->getEnd(), Range.getBegin()))
1259*0a6a1f1dSLionel Sambuc         return true;
1260*0a6a1f1dSLionel Sambuc     }
1261*0a6a1f1dSLionel Sambuc     return false;
1262*0a6a1f1dSLionel Sambuc   }
1263*0a6a1f1dSLionel Sambuc 
inputUsesCRLF(StringRef Text)1264f4a2713aSLionel Sambuc   static bool inputUsesCRLF(StringRef Text) {
1265f4a2713aSLionel Sambuc     return Text.count('\r') * 2 > Text.count('\n');
1266f4a2713aSLionel Sambuc   }
1267f4a2713aSLionel Sambuc 
1268f4a2713aSLionel Sambuc   void
deriveLocalStyle(const SmallVectorImpl<AnnotatedLine * > & AnnotatedLines)1269f4a2713aSLionel Sambuc   deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
1270f4a2713aSLionel Sambuc     unsigned CountBoundToVariable = 0;
1271f4a2713aSLionel Sambuc     unsigned CountBoundToType = 0;
1272f4a2713aSLionel Sambuc     bool HasCpp03IncompatibleFormat = false;
1273f4a2713aSLionel Sambuc     bool HasBinPackedFunction = false;
1274f4a2713aSLionel Sambuc     bool HasOnePerLineFunction = false;
1275f4a2713aSLionel Sambuc     for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
1276f4a2713aSLionel Sambuc       if (!AnnotatedLines[i]->First->Next)
1277f4a2713aSLionel Sambuc         continue;
1278f4a2713aSLionel Sambuc       FormatToken *Tok = AnnotatedLines[i]->First->Next;
1279f4a2713aSLionel Sambuc       while (Tok->Next) {
1280*0a6a1f1dSLionel Sambuc         if (Tok->is(TT_PointerOrReference)) {
1281f4a2713aSLionel Sambuc           bool SpacesBefore =
1282f4a2713aSLionel Sambuc               Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd();
1283f4a2713aSLionel Sambuc           bool SpacesAfter = Tok->Next->WhitespaceRange.getBegin() !=
1284f4a2713aSLionel Sambuc                              Tok->Next->WhitespaceRange.getEnd();
1285f4a2713aSLionel Sambuc           if (SpacesBefore && !SpacesAfter)
1286f4a2713aSLionel Sambuc             ++CountBoundToVariable;
1287f4a2713aSLionel Sambuc           else if (!SpacesBefore && SpacesAfter)
1288f4a2713aSLionel Sambuc             ++CountBoundToType;
1289f4a2713aSLionel Sambuc         }
1290f4a2713aSLionel Sambuc 
1291f4a2713aSLionel Sambuc         if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) {
1292*0a6a1f1dSLionel Sambuc           if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
1293f4a2713aSLionel Sambuc             HasCpp03IncompatibleFormat = true;
1294*0a6a1f1dSLionel Sambuc           if (Tok->is(TT_TemplateCloser) &&
1295*0a6a1f1dSLionel Sambuc               Tok->Previous->is(TT_TemplateCloser))
1296f4a2713aSLionel Sambuc             HasCpp03IncompatibleFormat = true;
1297f4a2713aSLionel Sambuc         }
1298f4a2713aSLionel Sambuc 
1299f4a2713aSLionel Sambuc         if (Tok->PackingKind == PPK_BinPacked)
1300f4a2713aSLionel Sambuc           HasBinPackedFunction = true;
1301f4a2713aSLionel Sambuc         if (Tok->PackingKind == PPK_OnePerLine)
1302f4a2713aSLionel Sambuc           HasOnePerLineFunction = true;
1303f4a2713aSLionel Sambuc 
1304f4a2713aSLionel Sambuc         Tok = Tok->Next;
1305f4a2713aSLionel Sambuc       }
1306f4a2713aSLionel Sambuc     }
1307*0a6a1f1dSLionel Sambuc     if (Style.DerivePointerAlignment) {
1308f4a2713aSLionel Sambuc       if (CountBoundToType > CountBoundToVariable)
1309*0a6a1f1dSLionel Sambuc         Style.PointerAlignment = FormatStyle::PAS_Left;
1310f4a2713aSLionel Sambuc       else if (CountBoundToType < CountBoundToVariable)
1311*0a6a1f1dSLionel Sambuc         Style.PointerAlignment = FormatStyle::PAS_Right;
1312f4a2713aSLionel Sambuc     }
1313f4a2713aSLionel Sambuc     if (Style.Standard == FormatStyle::LS_Auto) {
1314f4a2713aSLionel Sambuc       Style.Standard = HasCpp03IncompatibleFormat ? FormatStyle::LS_Cpp11
1315f4a2713aSLionel Sambuc                                                   : FormatStyle::LS_Cpp03;
1316f4a2713aSLionel Sambuc     }
1317f4a2713aSLionel Sambuc     BinPackInconclusiveFunctions =
1318f4a2713aSLionel Sambuc         HasBinPackedFunction || !HasOnePerLineFunction;
1319f4a2713aSLionel Sambuc   }
1320f4a2713aSLionel Sambuc 
consumeUnwrappedLine(const UnwrappedLine & TheLine)1321*0a6a1f1dSLionel Sambuc   void consumeUnwrappedLine(const UnwrappedLine &TheLine) override {
1322f4a2713aSLionel Sambuc     assert(!UnwrappedLines.empty());
1323f4a2713aSLionel Sambuc     UnwrappedLines.back().push_back(TheLine);
1324f4a2713aSLionel Sambuc   }
1325f4a2713aSLionel Sambuc 
finishRun()1326*0a6a1f1dSLionel Sambuc   void finishRun() override {
1327f4a2713aSLionel Sambuc     UnwrappedLines.push_back(SmallVector<UnwrappedLine, 16>());
1328f4a2713aSLionel Sambuc   }
1329f4a2713aSLionel Sambuc 
1330f4a2713aSLionel Sambuc   FormatStyle Style;
1331*0a6a1f1dSLionel Sambuc   FileID ID;
1332f4a2713aSLionel Sambuc   SourceManager &SourceMgr;
1333f4a2713aSLionel Sambuc   WhitespaceManager Whitespaces;
1334f4a2713aSLionel Sambuc   SmallVector<CharSourceRange, 8> Ranges;
1335f4a2713aSLionel Sambuc   SmallVector<SmallVector<UnwrappedLine, 16>, 2> UnwrappedLines;
1336f4a2713aSLionel Sambuc 
1337f4a2713aSLionel Sambuc   encoding::Encoding Encoding;
1338f4a2713aSLionel Sambuc   bool BinPackInconclusiveFunctions;
1339f4a2713aSLionel Sambuc };
1340f4a2713aSLionel Sambuc 
1341f4a2713aSLionel Sambuc } // end anonymous namespace
1342f4a2713aSLionel Sambuc 
reformat(const FormatStyle & Style,Lexer & Lex,SourceManager & SourceMgr,ArrayRef<CharSourceRange> Ranges)1343f4a2713aSLionel Sambuc tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
1344f4a2713aSLionel Sambuc                                SourceManager &SourceMgr,
1345*0a6a1f1dSLionel Sambuc                                ArrayRef<CharSourceRange> Ranges) {
1346*0a6a1f1dSLionel Sambuc   if (Style.DisableFormat)
1347*0a6a1f1dSLionel Sambuc     return tooling::Replacements();
1348*0a6a1f1dSLionel Sambuc   return reformat(Style, SourceMgr,
1349*0a6a1f1dSLionel Sambuc                   SourceMgr.getFileID(Lex.getSourceLocation()), Ranges);
1350*0a6a1f1dSLionel Sambuc }
1351*0a6a1f1dSLionel Sambuc 
reformat(const FormatStyle & Style,SourceManager & SourceMgr,FileID ID,ArrayRef<CharSourceRange> Ranges)1352*0a6a1f1dSLionel Sambuc tooling::Replacements reformat(const FormatStyle &Style,
1353*0a6a1f1dSLionel Sambuc                                SourceManager &SourceMgr, FileID ID,
1354*0a6a1f1dSLionel Sambuc                                ArrayRef<CharSourceRange> Ranges) {
1355*0a6a1f1dSLionel Sambuc   if (Style.DisableFormat)
1356*0a6a1f1dSLionel Sambuc     return tooling::Replacements();
1357*0a6a1f1dSLionel Sambuc   Formatter formatter(Style, SourceMgr, ID, Ranges);
1358f4a2713aSLionel Sambuc   return formatter.format();
1359f4a2713aSLionel Sambuc }
1360f4a2713aSLionel Sambuc 
reformat(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName)1361f4a2713aSLionel Sambuc tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
1362*0a6a1f1dSLionel Sambuc                                ArrayRef<tooling::Range> Ranges,
1363f4a2713aSLionel Sambuc                                StringRef FileName) {
1364*0a6a1f1dSLionel Sambuc   if (Style.DisableFormat)
1365*0a6a1f1dSLionel Sambuc     return tooling::Replacements();
1366*0a6a1f1dSLionel Sambuc 
1367f4a2713aSLionel Sambuc   FileManager Files((FileSystemOptions()));
1368f4a2713aSLionel Sambuc   DiagnosticsEngine Diagnostics(
1369f4a2713aSLionel Sambuc       IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
1370f4a2713aSLionel Sambuc       new DiagnosticOptions);
1371f4a2713aSLionel Sambuc   SourceManager SourceMgr(Diagnostics, Files);
1372*0a6a1f1dSLionel Sambuc   std::unique_ptr<llvm::MemoryBuffer> Buf =
1373*0a6a1f1dSLionel Sambuc       llvm::MemoryBuffer::getMemBuffer(Code, FileName);
1374f4a2713aSLionel Sambuc   const clang::FileEntry *Entry =
1375f4a2713aSLionel Sambuc       Files.getVirtualFile(FileName, Buf->getBufferSize(), 0);
1376*0a6a1f1dSLionel Sambuc   SourceMgr.overrideFileContents(Entry, std::move(Buf));
1377f4a2713aSLionel Sambuc   FileID ID =
1378f4a2713aSLionel Sambuc       SourceMgr.createFileID(Entry, SourceLocation(), clang::SrcMgr::C_User);
1379f4a2713aSLionel Sambuc   SourceLocation StartOfFile = SourceMgr.getLocForStartOfFile(ID);
1380f4a2713aSLionel Sambuc   std::vector<CharSourceRange> CharRanges;
1381*0a6a1f1dSLionel Sambuc   for (const tooling::Range &Range : Ranges) {
1382*0a6a1f1dSLionel Sambuc     SourceLocation Start = StartOfFile.getLocWithOffset(Range.getOffset());
1383*0a6a1f1dSLionel Sambuc     SourceLocation End = Start.getLocWithOffset(Range.getLength());
1384f4a2713aSLionel Sambuc     CharRanges.push_back(CharSourceRange::getCharRange(Start, End));
1385f4a2713aSLionel Sambuc   }
1386*0a6a1f1dSLionel Sambuc   return reformat(Style, SourceMgr, ID, CharRanges);
1387f4a2713aSLionel Sambuc }
1388f4a2713aSLionel Sambuc 
getFormattingLangOpts(const FormatStyle & Style)1389*0a6a1f1dSLionel Sambuc LangOptions getFormattingLangOpts(const FormatStyle &Style) {
1390f4a2713aSLionel Sambuc   LangOptions LangOpts;
1391f4a2713aSLionel Sambuc   LangOpts.CPlusPlus = 1;
1392*0a6a1f1dSLionel Sambuc   LangOpts.CPlusPlus11 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
1393*0a6a1f1dSLionel Sambuc   LangOpts.CPlusPlus14 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
1394f4a2713aSLionel Sambuc   LangOpts.LineComment = 1;
1395*0a6a1f1dSLionel Sambuc   bool AlternativeOperators = Style.Language != FormatStyle::LK_JavaScript &&
1396*0a6a1f1dSLionel Sambuc                               Style.Language != FormatStyle::LK_Java;
1397*0a6a1f1dSLionel Sambuc   LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
1398f4a2713aSLionel Sambuc   LangOpts.Bool = 1;
1399f4a2713aSLionel Sambuc   LangOpts.ObjC1 = 1;
1400f4a2713aSLionel Sambuc   LangOpts.ObjC2 = 1;
1401f4a2713aSLionel Sambuc   return LangOpts;
1402f4a2713aSLionel Sambuc }
1403f4a2713aSLionel Sambuc 
1404f4a2713aSLionel Sambuc const char *StyleOptionHelpDescription =
1405f4a2713aSLionel Sambuc     "Coding style, currently supports:\n"
1406f4a2713aSLionel Sambuc     "  LLVM, Google, Chromium, Mozilla, WebKit.\n"
1407f4a2713aSLionel Sambuc     "Use -style=file to load style configuration from\n"
1408f4a2713aSLionel Sambuc     ".clang-format file located in one of the parent\n"
1409f4a2713aSLionel Sambuc     "directories of the source file (or current\n"
1410f4a2713aSLionel Sambuc     "directory for stdin).\n"
1411f4a2713aSLionel Sambuc     "Use -style=\"{key: value, ...}\" to set specific\n"
1412f4a2713aSLionel Sambuc     "parameters, e.g.:\n"
1413f4a2713aSLionel Sambuc     "  -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
1414f4a2713aSLionel Sambuc 
getLanguageByFileName(StringRef FileName)1415*0a6a1f1dSLionel Sambuc static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
1416*0a6a1f1dSLionel Sambuc   if (FileName.endswith(".java")) {
1417*0a6a1f1dSLionel Sambuc     return FormatStyle::LK_Java;
1418*0a6a1f1dSLionel Sambuc   } else if (FileName.endswith_lower(".js")) {
1419*0a6a1f1dSLionel Sambuc     return FormatStyle::LK_JavaScript;
1420*0a6a1f1dSLionel Sambuc   } else if (FileName.endswith_lower(".proto") ||
1421*0a6a1f1dSLionel Sambuc              FileName.endswith_lower(".protodevel")) {
1422*0a6a1f1dSLionel Sambuc     return FormatStyle::LK_Proto;
1423*0a6a1f1dSLionel Sambuc   }
1424*0a6a1f1dSLionel Sambuc   return FormatStyle::LK_Cpp;
1425*0a6a1f1dSLionel Sambuc }
1426*0a6a1f1dSLionel Sambuc 
getStyle(StringRef StyleName,StringRef FileName,StringRef FallbackStyle)1427*0a6a1f1dSLionel Sambuc FormatStyle getStyle(StringRef StyleName, StringRef FileName,
1428*0a6a1f1dSLionel Sambuc                      StringRef FallbackStyle) {
1429*0a6a1f1dSLionel Sambuc   FormatStyle Style = getLLVMStyle();
1430*0a6a1f1dSLionel Sambuc   Style.Language = getLanguageByFileName(FileName);
1431*0a6a1f1dSLionel Sambuc   if (!getPredefinedStyle(FallbackStyle, Style.Language, &Style)) {
1432*0a6a1f1dSLionel Sambuc     llvm::errs() << "Invalid fallback style \"" << FallbackStyle
1433*0a6a1f1dSLionel Sambuc                  << "\" using LLVM style\n";
1434*0a6a1f1dSLionel Sambuc     return Style;
1435*0a6a1f1dSLionel Sambuc   }
1436f4a2713aSLionel Sambuc 
1437f4a2713aSLionel Sambuc   if (StyleName.startswith("{")) {
1438f4a2713aSLionel Sambuc     // Parse YAML/JSON style from the command line.
1439*0a6a1f1dSLionel Sambuc     if (std::error_code ec = parseConfiguration(StyleName, &Style)) {
1440f4a2713aSLionel Sambuc       llvm::errs() << "Error parsing -style: " << ec.message() << ", using "
1441f4a2713aSLionel Sambuc                    << FallbackStyle << " style\n";
1442f4a2713aSLionel Sambuc     }
1443f4a2713aSLionel Sambuc     return Style;
1444f4a2713aSLionel Sambuc   }
1445f4a2713aSLionel Sambuc 
1446f4a2713aSLionel Sambuc   if (!StyleName.equals_lower("file")) {
1447*0a6a1f1dSLionel Sambuc     if (!getPredefinedStyle(StyleName, Style.Language, &Style))
1448f4a2713aSLionel Sambuc       llvm::errs() << "Invalid value for -style, using " << FallbackStyle
1449f4a2713aSLionel Sambuc                    << " style\n";
1450f4a2713aSLionel Sambuc     return Style;
1451f4a2713aSLionel Sambuc   }
1452f4a2713aSLionel Sambuc 
1453*0a6a1f1dSLionel Sambuc   // Look for .clang-format/_clang-format file in the file's parent directories.
1454*0a6a1f1dSLionel Sambuc   SmallString<128> UnsuitableConfigFiles;
1455f4a2713aSLionel Sambuc   SmallString<128> Path(FileName);
1456f4a2713aSLionel Sambuc   llvm::sys::fs::make_absolute(Path);
1457f4a2713aSLionel Sambuc   for (StringRef Directory = Path; !Directory.empty();
1458f4a2713aSLionel Sambuc        Directory = llvm::sys::path::parent_path(Directory)) {
1459f4a2713aSLionel Sambuc     if (!llvm::sys::fs::is_directory(Directory))
1460f4a2713aSLionel Sambuc       continue;
1461f4a2713aSLionel Sambuc     SmallString<128> ConfigFile(Directory);
1462f4a2713aSLionel Sambuc 
1463f4a2713aSLionel Sambuc     llvm::sys::path::append(ConfigFile, ".clang-format");
1464f4a2713aSLionel Sambuc     DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
1465f4a2713aSLionel Sambuc     bool IsFile = false;
1466f4a2713aSLionel Sambuc     // Ignore errors from is_regular_file: we only need to know if we can read
1467f4a2713aSLionel Sambuc     // the file or not.
1468f4a2713aSLionel Sambuc     llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile);
1469f4a2713aSLionel Sambuc 
1470f4a2713aSLionel Sambuc     if (!IsFile) {
1471f4a2713aSLionel Sambuc       // Try _clang-format too, since dotfiles are not commonly used on Windows.
1472f4a2713aSLionel Sambuc       ConfigFile = Directory;
1473f4a2713aSLionel Sambuc       llvm::sys::path::append(ConfigFile, "_clang-format");
1474f4a2713aSLionel Sambuc       DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
1475f4a2713aSLionel Sambuc       llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile);
1476f4a2713aSLionel Sambuc     }
1477f4a2713aSLionel Sambuc 
1478f4a2713aSLionel Sambuc     if (IsFile) {
1479*0a6a1f1dSLionel Sambuc       llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
1480*0a6a1f1dSLionel Sambuc           llvm::MemoryBuffer::getFile(ConfigFile.c_str());
1481*0a6a1f1dSLionel Sambuc       if (std::error_code EC = Text.getError()) {
1482*0a6a1f1dSLionel Sambuc         llvm::errs() << EC.message() << "\n";
1483*0a6a1f1dSLionel Sambuc         break;
1484*0a6a1f1dSLionel Sambuc       }
1485*0a6a1f1dSLionel Sambuc       if (std::error_code ec =
1486*0a6a1f1dSLionel Sambuc               parseConfiguration(Text.get()->getBuffer(), &Style)) {
1487*0a6a1f1dSLionel Sambuc         if (ec == ParseError::Unsuitable) {
1488*0a6a1f1dSLionel Sambuc           if (!UnsuitableConfigFiles.empty())
1489*0a6a1f1dSLionel Sambuc             UnsuitableConfigFiles.append(", ");
1490*0a6a1f1dSLionel Sambuc           UnsuitableConfigFiles.append(ConfigFile);
1491f4a2713aSLionel Sambuc           continue;
1492f4a2713aSLionel Sambuc         }
1493f4a2713aSLionel Sambuc         llvm::errs() << "Error reading " << ConfigFile << ": " << ec.message()
1494f4a2713aSLionel Sambuc                      << "\n";
1495*0a6a1f1dSLionel Sambuc         break;
1496f4a2713aSLionel Sambuc       }
1497f4a2713aSLionel Sambuc       DEBUG(llvm::dbgs() << "Using configuration file " << ConfigFile << "\n");
1498f4a2713aSLionel Sambuc       return Style;
1499f4a2713aSLionel Sambuc     }
1500f4a2713aSLionel Sambuc   }
1501f4a2713aSLionel Sambuc   llvm::errs() << "Can't find usable .clang-format, using " << FallbackStyle
1502f4a2713aSLionel Sambuc                << " style\n";
1503*0a6a1f1dSLionel Sambuc   if (!UnsuitableConfigFiles.empty()) {
1504*0a6a1f1dSLionel Sambuc     llvm::errs() << "Configuration file(s) do(es) not support "
1505*0a6a1f1dSLionel Sambuc                  << getLanguageName(Style.Language) << ": "
1506*0a6a1f1dSLionel Sambuc                  << UnsuitableConfigFiles << "\n";
1507*0a6a1f1dSLionel Sambuc   }
1508f4a2713aSLionel Sambuc   return Style;
1509f4a2713aSLionel Sambuc }
1510f4a2713aSLionel Sambuc 
1511f4a2713aSLionel Sambuc } // namespace format
1512f4a2713aSLionel Sambuc } // namespace clang
1513