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