blob: b709e9f84a77d7f8c78d5de799d0ebf79df419bd [file] [log] [blame]
Daniel Jasperf7935112012-12-03 18:12:45 +00001//===--- Format.cpp - Format C++ code -------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief This file implements functions declared in Format.h. This will be
12/// split into separate files as we go.
13///
Daniel Jasperf7935112012-12-03 18:12:45 +000014//===----------------------------------------------------------------------===//
15
Daniel Jasper85c472d2015-09-29 07:53:08 +000016#include "clang/Format/Format.h"
Eric Liu4cfb88a2016-04-25 15:09:22 +000017#include "AffectedRangeManager.h"
Daniel Jasperde0328a2013-08-16 11:20:30 +000018#include "ContinuationIndenter.h"
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +000019#include "FormatInternal.h"
Martin Probstc4a0dd42016-05-20 11:24:24 +000020#include "FormatTokenLexer.h"
Krasimir Georgiev7cb267a2017-02-27 13:28:36 +000021#include "NamespaceEndCommentsFixer.h"
Martin Probstc4a0dd42016-05-20 11:24:24 +000022#include "SortJavaScriptImports.h"
23#include "TokenAnalyzer.h"
Daniel Jasper7a6d09b2013-01-29 21:01:14 +000024#include "TokenAnnotator.h"
Daniel Jasper0df50932014-12-10 19:00:42 +000025#include "UnwrappedLineFormatter.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000026#include "UnwrappedLineParser.h"
Krasimir Georgievb03877a2017-06-21 12:03:12 +000027#include "UsingDeclarationsSorter.h"
Alexander Kornienkocb45bc12013-04-15 14:28:00 +000028#include "WhitespaceManager.h"
Daniel Jasperec04c0d2013-05-16 10:40:07 +000029#include "clang/Basic/Diagnostic.h"
Benjamin Kramerf3ca26982014-05-10 16:31:55 +000030#include "clang/Basic/DiagnosticOptions.h"
Chandler Carruth44eb4f62013-01-02 10:28:36 +000031#include "clang/Basic/SourceManager.h"
Marianne Mailhot-Sarrasin4988fa12016-04-14 14:47:37 +000032#include "clang/Basic/VirtualFileSystem.h"
Daniel Jasperf7935112012-12-03 18:12:45 +000033#include "clang/Lex/Lexer.h"
Alexander Kornienkoffd6d042013-03-27 11:52:18 +000034#include "llvm/ADT/STLExtras.h"
Ben Hamiltone2e3e672018-01-17 17:33:08 +000035#include "llvm/ADT/StringRef.h"
Manuel Klimek2ef908e2013-02-13 10:46:36 +000036#include "llvm/Support/Allocator.h"
Manuel Klimek24998102013-01-16 14:55:28 +000037#include "llvm/Support/Debug.h"
Edwin Vaned544aa72013-09-30 13:31:48 +000038#include "llvm/Support/Path.h"
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +000039#include "llvm/Support/Regex.h"
Chandler Carruth5553d0d2014-01-07 11:51:46 +000040#include "llvm/Support/YAMLTraits.h"
Martin Probst081f1762016-06-01 15:19:53 +000041#include <algorithm>
Eric Liu4cfb88a2016-04-25 15:09:22 +000042#include <memory>
Daniel Jasper8b529712012-12-04 13:02:32 +000043#include <string>
44
Chandler Carruth10346662014-04-22 03:17:02 +000045#define DEBUG_TYPE "format-formatter"
46
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +000047using clang::format::FormatStyle;
48
NAKAMURA Takumi057a9422017-11-01 04:43:22 +000049LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::IncludeCategory)
50LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat)
Daniel Jaspere1e43192014-04-01 12:55:11 +000051
Alexander Kornienkod6538332013-05-07 15:32:14 +000052namespace llvm {
53namespace yaml {
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +000054template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
55 static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
56 IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
Daniel Jasperc58c70e2014-09-15 11:21:46 +000057 IO.enumCase(Value, "Java", FormatStyle::LK_Java);
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +000058 IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
Daniel Jasper03a04fe2016-12-12 12:42:29 +000059 IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);
Daniel Jasper7052ce62014-01-19 09:04:08 +000060 IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
Daniel Jasper498f5582015-12-25 08:53:31 +000061 IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);
Krasimir Georgiev26b144c2017-07-03 15:05:14 +000062 IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto);
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +000063 }
64};
65
66template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
67 static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
68 IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03);
69 IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03);
70 IO.enumCase(Value, "Cpp11", FormatStyle::LS_Cpp11);
71 IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11);
72 IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);
73 }
74};
75
76template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
77 static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {
78 IO.enumCase(Value, "Never", FormatStyle::UT_Never);
79 IO.enumCase(Value, "false", FormatStyle::UT_Never);
80 IO.enumCase(Value, "Always", FormatStyle::UT_Always);
81 IO.enumCase(Value, "true", FormatStyle::UT_Always);
82 IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation);
Marianne Mailhot-Sarrasin51fe2792016-04-14 14:52:26 +000083 IO.enumCase(Value, "ForContinuationAndIndentation",
84 FormatStyle::UT_ForContinuationAndIndentation);
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +000085 }
86};
87
Daniel Jasperabd1f572016-03-02 22:44:03 +000088template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {
89 static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) {
90 IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave);
91 IO.enumCase(Value, "Single", FormatStyle::JSQS_Single);
92 IO.enumCase(Value, "Double", FormatStyle::JSQS_Double);
93 }
94};
95
Daniel Jasperd74cf402014-04-08 12:46:38 +000096template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
97 static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
98 IO.enumCase(Value, "None", FormatStyle::SFS_None);
99 IO.enumCase(Value, "false", FormatStyle::SFS_None);
100 IO.enumCase(Value, "All", FormatStyle::SFS_All);
101 IO.enumCase(Value, "true", FormatStyle::SFS_All);
102 IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
Francois Ferrandd3f0e3d2017-06-21 13:56:02 +0000103 IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly);
Daniel Jasper9e709352014-11-26 10:43:58 +0000104 IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);
Daniel Jasperd74cf402014-04-08 12:46:38 +0000105 }
106};
107
Daniel Jasperac043c92014-09-15 11:11:00 +0000108template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> {
109 static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {
110 IO.enumCase(Value, "All", FormatStyle::BOS_All);
111 IO.enumCase(Value, "true", FormatStyle::BOS_All);
112 IO.enumCase(Value, "None", FormatStyle::BOS_None);
113 IO.enumCase(Value, "false", FormatStyle::BOS_None);
114 IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment);
115 }
116};
117
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +0000118template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
119 static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {
120 IO.enumCase(Value, "Attach", FormatStyle::BS_Attach);
121 IO.enumCase(Value, "Linux", FormatStyle::BS_Linux);
Birunthan Mohanathas305fa9c2015-07-12 03:13:54 +0000122 IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla);
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +0000123 IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);
124 IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
Alexander Kornienko3a33f022013-12-12 09:49:52 +0000125 IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
Roman Kashitsyn291f64f2015-08-10 13:43:19 +0000126 IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit);
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000127 IO.enumCase(Value, "Custom", FormatStyle::BS_Custom);
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +0000128 }
129};
130
Manuel Klimek89628f62017-09-20 09:51:03 +0000131template <>
132struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
133 static void
134 enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
Francois Ferranda6b6d512017-05-24 11:36:58 +0000135 IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon);
136 IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma);
137 IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon);
138 }
139};
140
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000141template <>
Krasimir Georgievad47c902017-08-30 14:34:57 +0000142struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
143 static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
144 IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
145 IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);
146 }
147};
148
149template <>
Zachary Turner448592e2015-12-18 22:20:15 +0000150struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
151 static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
152 IO.enumCase(Value, "None", FormatStyle::RTBS_None);
153 IO.enumCase(Value, "All", FormatStyle::RTBS_All);
154 IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel);
155 IO.enumCase(Value, "TopLevelDefinitions",
156 FormatStyle::RTBS_TopLevelDefinitions);
157 IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions);
158 }
159};
160
161template <>
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000162struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
163 static void
164 enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
Birunthan Mohanathasa0388a82015-06-29 15:30:42 +0000165 IO.enumCase(Value, "None", FormatStyle::DRTBS_None);
166 IO.enumCase(Value, "All", FormatStyle::DRTBS_All);
167 IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel);
168
169 // For backward compatibility.
170 IO.enumCase(Value, "false", FormatStyle::DRTBS_None);
171 IO.enumCase(Value, "true", FormatStyle::DRTBS_All);
172 }
173};
174
Alexander Kornienkod6538332013-05-07 15:32:14 +0000175template <>
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +0000176struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000177 static void enumeration(IO &IO,
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +0000178 FormatStyle::NamespaceIndentationKind &Value) {
179 IO.enumCase(Value, "None", FormatStyle::NI_None);
180 IO.enumCase(Value, "Inner", FormatStyle::NI_Inner);
181 IO.enumCase(Value, "All", FormatStyle::NI_All);
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000182 }
183};
184
Daniel Jasper6501f7e2015-10-27 12:38:37 +0000185template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> {
186 static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) {
187 IO.enumCase(Value, "Align", FormatStyle::BAS_Align);
188 IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign);
189 IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak);
190
191 // For backward compatibility.
192 IO.enumCase(Value, "true", FormatStyle::BAS_Align);
193 IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign);
194 }
195};
196
Manuel Klimek89628f62017-09-20 09:51:03 +0000197template <>
198struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
199 static void enumeration(IO &IO,
200 FormatStyle::EscapedNewlineAlignmentStyle &Value) {
Daniel Jasper7fdbb3f2017-05-08 15:08:00 +0000201 IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign);
202 IO.enumCase(Value, "Left", FormatStyle::ENAS_Left);
203 IO.enumCase(Value, "Right", FormatStyle::ENAS_Right);
204
205 // For backward compatibility.
206 IO.enumCase(Value, "true", FormatStyle::ENAS_Left);
207 IO.enumCase(Value, "false", FormatStyle::ENAS_Right);
208 }
209};
210
Jacques Pienaarfc275112015-02-18 23:48:37 +0000211template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
212 static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {
Daniel Jasper553d4872014-06-17 12:40:34 +0000213 IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
214 IO.enumCase(Value, "Left", FormatStyle::PAS_Left);
215 IO.enumCase(Value, "Right", FormatStyle::PAS_Right);
216
Alp Toker958027b2014-07-14 19:42:55 +0000217 // For backward compatibility.
Daniel Jasper553d4872014-06-17 12:40:34 +0000218 IO.enumCase(Value, "true", FormatStyle::PAS_Left);
219 IO.enumCase(Value, "false", FormatStyle::PAS_Right);
220 }
221};
222
223template <>
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +0000224struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
Manuel Klimeka8eb9142013-05-13 12:51:40 +0000225 static void enumeration(IO &IO,
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +0000226 FormatStyle::SpaceBeforeParensOptions &Value) {
227 IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
Alexander Kornienkofdca83d2013-12-10 10:18:34 +0000228 IO.enumCase(Value, "ControlStatements",
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +0000229 FormatStyle::SBPO_ControlStatements);
230 IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
Alexander Kornienkofdca83d2013-12-10 10:18:34 +0000231
232 // For backward compatibility.
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +0000233 IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
234 IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);
Alexander Kornienkofdca83d2013-12-10 10:18:34 +0000235 }
236};
237
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +0000238template <> struct MappingTraits<FormatStyle> {
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000239 static void mapping(IO &IO, FormatStyle &Style) {
240 // When reading, read the language first, we need it for getPredefinedStyle.
241 IO.mapOptional("Language", Style.Language);
242
Alexander Kornienko49149672013-05-10 11:56:10 +0000243 if (IO.outputting()) {
Jacques Pienaarfc275112015-02-18 23:48:37 +0000244 StringRef StylesArray[] = {"LLVM", "Google", "Chromium",
245 "Mozilla", "WebKit", "GNU"};
Alexander Kornienko49149672013-05-10 11:56:10 +0000246 ArrayRef<StringRef> Styles(StylesArray);
247 for (size_t i = 0, e = Styles.size(); i < e; ++i) {
248 StringRef StyleName(Styles[i]);
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +0000249 FormatStyle PredefinedStyle;
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000250 if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) &&
Alexander Kornienko006b5c82013-05-19 00:53:30 +0000251 Style == PredefinedStyle) {
Alexander Kornienko49149672013-05-10 11:56:10 +0000252 IO.mapOptional("# BasedOnStyle", StyleName);
253 break;
254 }
255 }
256 } else {
Alexander Kornienkod6538332013-05-07 15:32:14 +0000257 StringRef BasedOnStyle;
258 IO.mapOptional("BasedOnStyle", BasedOnStyle);
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000259 if (!BasedOnStyle.empty()) {
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000260 FormatStyle::LanguageKind OldLanguage = Style.Language;
261 FormatStyle::LanguageKind Language =
262 ((FormatStyle *)IO.getContext())->Language;
263 if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
Alexander Kornienko006b5c82013-05-19 00:53:30 +0000264 IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle));
265 return;
266 }
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000267 Style.Language = OldLanguage;
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000268 }
Alexander Kornienkod6538332013-05-07 15:32:14 +0000269 }
270
Birunthan Mohanathas50a6f912015-06-28 14:52:34 +0000271 // For backward compatibility.
272 if (!IO.outputting()) {
Daniel Jasper7fdbb3f2017-05-08 15:08:00 +0000273 IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines);
Birunthan Mohanathas50a6f912015-06-28 14:52:34 +0000274 IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
275 IO.mapOptional("IndentFunctionDeclarationAfterType",
276 Style.IndentWrappedFunctionNames);
277 IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
278 IO.mapOptional("SpaceAfterControlStatementKeyword",
279 Style.SpaceBeforeParens);
280 }
281
Alexander Kornienkod6538332013-05-07 15:32:14 +0000282 IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
Daniel Jasper3aa9a6a2014-11-18 23:55:27 +0000283 IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
Birunthan Mohanathas35cfbd72015-06-28 14:51:17 +0000284 IO.mapOptional("AlignConsecutiveAssignments",
285 Style.AlignConsecutiveAssignments);
Daniel Jaspere12597c2015-10-01 10:06:54 +0000286 IO.mapOptional("AlignConsecutiveDeclarations",
287 Style.AlignConsecutiveDeclarations);
Daniel Jasper7fdbb3f2017-05-08 15:08:00 +0000288 IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines);
Daniel Jasper3219e432014-12-02 13:24:51 +0000289 IO.mapOptional("AlignOperands", Style.AlignOperands);
Daniel Jasper552f4a72013-07-31 23:55:15 +0000290 IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
Alexander Kornienkod6538332013-05-07 15:32:14 +0000291 IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
292 Style.AllowAllParametersOfDeclarationOnNextLine);
Daniel Jasper17605d32014-05-14 09:33:35 +0000293 IO.mapOptional("AllowShortBlocksOnASingleLine",
294 Style.AllowShortBlocksOnASingleLine);
Daniel Jasperb87899b2014-09-10 13:11:45 +0000295 IO.mapOptional("AllowShortCaseLabelsOnASingleLine",
296 Style.AllowShortCaseLabelsOnASingleLine);
Birunthan Mohanathas35cfbd72015-06-28 14:51:17 +0000297 IO.mapOptional("AllowShortFunctionsOnASingleLine",
298 Style.AllowShortFunctionsOnASingleLine);
Alexander Kornienkod6538332013-05-07 15:32:14 +0000299 IO.mapOptional("AllowShortIfStatementsOnASingleLine",
300 Style.AllowShortIfStatementsOnASingleLine);
Daniel Jasper3a685df2013-05-16 12:12:21 +0000301 IO.mapOptional("AllowShortLoopsOnASingleLine",
302 Style.AllowShortLoopsOnASingleLine);
Daniel Jasperca4ea1c2014-08-05 12:16:31 +0000303 IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",
304 Style.AlwaysBreakAfterDefinitionReturnType);
Zachary Turner448592e2015-12-18 22:20:15 +0000305 IO.mapOptional("AlwaysBreakAfterReturnType",
306 Style.AlwaysBreakAfterReturnType);
307 // If AlwaysBreakAfterDefinitionReturnType was specified but
308 // AlwaysBreakAfterReturnType was not, initialize the latter from the
309 // former for backwards compatibility.
310 if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&
311 Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) {
312 if (Style.AlwaysBreakAfterDefinitionReturnType == FormatStyle::DRTBS_All)
313 Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
314 else if (Style.AlwaysBreakAfterDefinitionReturnType ==
315 FormatStyle::DRTBS_TopLevel)
316 Style.AlwaysBreakAfterReturnType =
317 FormatStyle::RTBS_TopLevelDefinitions;
318 }
319
Alexander Kornienko58611712013-07-04 12:02:44 +0000320 IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
321 Style.AlwaysBreakBeforeMultilineStrings);
Birunthan Mohanathas35cfbd72015-06-28 14:51:17 +0000322 IO.mapOptional("AlwaysBreakTemplateDeclarations",
323 Style.AlwaysBreakTemplateDeclarations);
324 IO.mapOptional("BinPackArguments", Style.BinPackArguments);
325 IO.mapOptional("BinPackParameters", Style.BinPackParameters);
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000326 IO.mapOptional("BraceWrapping", Style.BraceWrapping);
Daniel Jaspere33d4af2013-07-26 16:56:36 +0000327 IO.mapOptional("BreakBeforeBinaryOperators",
328 Style.BreakBeforeBinaryOperators);
Birunthan Mohanathas35cfbd72015-06-28 14:51:17 +0000329 IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
Francois Ferrande56a8292017-06-14 12:29:47 +0000330 IO.mapOptional("BreakBeforeInheritanceComma",
331 Style.BreakBeforeInheritanceComma);
Daniel Jasper165b29e2013-11-08 00:57:11 +0000332 IO.mapOptional("BreakBeforeTernaryOperators",
333 Style.BreakBeforeTernaryOperators);
Francois Ferranda6b6d512017-05-24 11:36:58 +0000334
335 bool BreakConstructorInitializersBeforeComma = false;
Daniel Jaspere33d4af2013-07-26 16:56:36 +0000336 IO.mapOptional("BreakConstructorInitializersBeforeComma",
Francois Ferranda6b6d512017-05-24 11:36:58 +0000337 BreakConstructorInitializersBeforeComma);
338 IO.mapOptional("BreakConstructorInitializers",
339 Style.BreakConstructorInitializers);
340 // If BreakConstructorInitializersBeforeComma was specified but
341 // BreakConstructorInitializers was not, initialize the latter from the
342 // former for backwards compatibility.
343 if (BreakConstructorInitializersBeforeComma &&
344 Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon)
345 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
346
Daniel Jaspere1a7b762016-02-01 11:21:02 +0000347 IO.mapOptional("BreakAfterJavaFieldAnnotations",
348 Style.BreakAfterJavaFieldAnnotations);
349 IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
Alexander Kornienkod6538332013-05-07 15:32:14 +0000350 IO.mapOptional("ColumnLimit", Style.ColumnLimit);
Birunthan Mohanathas35cfbd72015-06-28 14:51:17 +0000351 IO.mapOptional("CommentPragmas", Style.CommentPragmas);
Francois Ferrande56a8292017-06-14 12:29:47 +0000352 IO.mapOptional("CompactNamespaces", Style.CompactNamespaces);
Alexander Kornienkod6538332013-05-07 15:32:14 +0000353 IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
354 Style.ConstructorInitializerAllOnOneLineOrOnePerLine);
Daniel Jasper50d634b2014-10-28 16:53:38 +0000355 IO.mapOptional("ConstructorInitializerIndentWidth",
356 Style.ConstructorInitializerIndentWidth);
Birunthan Mohanathas35cfbd72015-06-28 14:51:17 +0000357 IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
358 IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
Daniel Jasper553d4872014-06-17 12:40:34 +0000359 IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
Birunthan Mohanathas35cfbd72015-06-28 14:51:17 +0000360 IO.mapOptional("DisableFormat", Style.DisableFormat);
Daniel Jasperb10cbc42013-07-10 14:02:49 +0000361 IO.mapOptional("ExperimentalAutoDetectBinPacking",
362 Style.ExperimentalAutoDetectBinPacking);
Krasimir Georgiev32eaa862017-03-01 15:35:39 +0000363 IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
Birunthan Mohanathas35cfbd72015-06-28 14:51:17 +0000364 IO.mapOptional("ForEachMacros", Style.ForEachMacros);
Krasimir Georgiev4c2c9c32017-11-27 13:23:45 +0000365 IO.mapOptional("IncludeBlocks", Style.IncludeBlocks);
Daniel Jasper8ce1b8d2015-10-06 11:54:18 +0000366 IO.mapOptional("IncludeCategories", Style.IncludeCategories);
Daniel Jasper9c8ff352016-03-21 14:11:27 +0000367 IO.mapOptional("IncludeIsMainRegex", Style.IncludeIsMainRegex);
Alexander Kornienkod6538332013-05-07 15:32:14 +0000368 IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
Krasimir Georgievad47c902017-08-30 14:34:57 +0000369 IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
Birunthan Mohanathas35cfbd72015-06-28 14:51:17 +0000370 IO.mapOptional("IndentWidth", Style.IndentWidth);
371 IO.mapOptional("IndentWrappedFunctionNames",
372 Style.IndentWrappedFunctionNames);
Martin Probst0cd74ee2016-06-13 16:39:50 +0000373 IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);
374 IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
Daniel Jaspera26fc5c2014-03-21 13:43:14 +0000375 IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
376 Style.KeepEmptyLinesAtTheStartOfBlocks);
Birunthan Mohanathasb001a0b2015-07-03 17:25:16 +0000377 IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
378 IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);
Birunthan Mohanathas35cfbd72015-06-28 14:51:17 +0000379 IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
Daniel Jasper65ee3472013-07-31 23:16:02 +0000380 IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
Daniel Jasper50d634b2014-10-28 16:53:38 +0000381 IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);
Daniel Jaspere9beea22014-01-28 15:20:33 +0000382 IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
Alexander Kornienkod6538332013-05-07 15:32:14 +0000383 IO.mapOptional("ObjCSpaceBeforeProtocolList",
384 Style.ObjCSpaceBeforeProtocolList);
Manuel Klimek89628f62017-09-20 09:51:03 +0000385 IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment);
Daniel Jasper33b909c2013-10-25 14:29:37 +0000386 IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",
387 Style.PenaltyBreakBeforeFirstCallParameter);
Alexander Kornienkodd7ece52013-06-07 16:02:52 +0000388 IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
Daniel Jasper4e9678f2013-07-11 20:41:21 +0000389 IO.mapOptional("PenaltyBreakFirstLessLess",
390 Style.PenaltyBreakFirstLessLess);
Birunthan Mohanathas35cfbd72015-06-28 14:51:17 +0000391 IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
Alexander Kornienkod6538332013-05-07 15:32:14 +0000392 IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
393 IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
394 Style.PenaltyReturnTypeOnItsOwnLine);
Daniel Jasper553d4872014-06-17 12:40:34 +0000395 IO.mapOptional("PointerAlignment", Style.PointerAlignment);
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +0000396 IO.mapOptional("RawStringFormats", Style.RawStringFormats);
Daniel Jaspera0a50392015-12-01 13:28:53 +0000397 IO.mapOptional("ReflowComments", Style.ReflowComments);
398 IO.mapOptional("SortIncludes", Style.SortIncludes);
Krasimir Georgievac16a202017-06-23 11:46:03 +0000399 IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);
Daniel Jasperdb986eb2014-09-03 07:37:29 +0000400 IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
Manuel Klimek89628f62017-09-20 09:51:03 +0000401 IO.mapOptional("SpaceAfterTemplateKeyword",
402 Style.SpaceAfterTemplateKeyword);
Daniel Jasperd94bff32013-09-25 15:15:02 +0000403 IO.mapOptional("SpaceBeforeAssignmentOperators",
404 Style.SpaceBeforeAssignmentOperators);
Birunthan Mohanathas35cfbd72015-06-28 14:51:17 +0000405 IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
406 IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
407 IO.mapOptional("SpacesBeforeTrailingComments",
408 Style.SpacesBeforeTrailingComments);
409 IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
410 IO.mapOptional("SpacesInContainerLiterals",
411 Style.SpacesInContainerLiterals);
412 IO.mapOptional("SpacesInCStyleCastParentheses",
413 Style.SpacesInCStyleCastParentheses);
414 IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
415 IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
416 IO.mapOptional("Standard", Style.Standard);
417 IO.mapOptional("TabWidth", Style.TabWidth);
418 IO.mapOptional("UseTab", Style.UseTab);
Alexander Kornienkod6538332013-05-07 15:32:14 +0000419 }
420};
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000421
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000422template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
423 static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
424 IO.mapOptional("AfterClass", Wrapping.AfterClass);
425 IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement);
426 IO.mapOptional("AfterEnum", Wrapping.AfterEnum);
427 IO.mapOptional("AfterFunction", Wrapping.AfterFunction);
428 IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace);
429 IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
430 IO.mapOptional("AfterStruct", Wrapping.AfterStruct);
431 IO.mapOptional("AfterUnion", Wrapping.AfterUnion);
Krasimir Georgievd6ce9372017-09-15 11:23:50 +0000432 IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000433 IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
434 IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
435 IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
Francois Ferrandad722562017-06-30 20:25:55 +0000436 IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);
437 IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);
438 IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000439 }
440};
441
Daniel Jasper8ce1b8d2015-10-06 11:54:18 +0000442template <> struct MappingTraits<FormatStyle::IncludeCategory> {
443 static void mapping(IO &IO, FormatStyle::IncludeCategory &Category) {
444 IO.mapOptional("Regex", Category.Regex);
445 IO.mapOptional("Priority", Category.Priority);
446 }
447};
448
Krasimir Georgiev4c2c9c32017-11-27 13:23:45 +0000449template <> struct ScalarEnumerationTraits<FormatStyle::IncludeBlocksStyle> {
450 static void enumeration(IO &IO, FormatStyle::IncludeBlocksStyle &Value) {
451 IO.enumCase(Value, "Preserve", FormatStyle::IBS_Preserve);
452 IO.enumCase(Value, "Merge", FormatStyle::IBS_Merge);
453 IO.enumCase(Value, "Regroup", FormatStyle::IBS_Regroup);
454 }
455};
456
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +0000457template <> struct MappingTraits<FormatStyle::RawStringFormat> {
458 static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +0000459 IO.mapOptional("Language", Format.Language);
Krasimir Georgiev4527f132018-01-17 12:24:59 +0000460 IO.mapOptional("Delimiters", Format.Delimiters);
Krasimir Georgiev2537e222018-01-17 16:17:26 +0000461 IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);
Krasimir Georgiev412ed092018-01-19 16:18:47 +0000462 IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter);
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +0000463 IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);
464 }
465};
466
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000467// Allows to read vector<FormatStyle> while keeping default values.
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000468// IO.getContext() should contain a pointer to the FormatStyle structure, that
469// will be used to get default values for missing keys.
470// If the first element has no Language specified, it will be treated as the
471// default one for the following elements.
Jacques Pienaarfc275112015-02-18 23:48:37 +0000472template <> struct DocumentListTraits<std::vector<FormatStyle>> {
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000473 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
474 return Seq.size();
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000475 }
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000476 static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq,
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +0000477 size_t Index) {
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000478 if (Index >= Seq.size()) {
479 assert(Index == Seq.size());
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +0000480 FormatStyle Template;
Krasimir Georgiev1696bb62017-11-09 15:12:17 +0000481 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000482 Template = Seq[0];
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000483 } else {
Daniel Jasperb05a81d2014-05-09 13:11:16 +0000484 Template = *((const FormatStyle *)IO.getContext());
Alexander Kornienko6d2c88e2013-12-10 10:30:34 +0000485 Template.Language = FormatStyle::LK_None;
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000486 }
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000487 Seq.resize(Index + 1, Template);
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000488 }
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000489 return Seq[Index];
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000490 }
491};
Daniel Jasperd89ae9d2015-09-23 08:30:47 +0000492} // namespace yaml
493} // namespace llvm
Alexander Kornienkod6538332013-05-07 15:32:14 +0000494
Daniel Jasperf7935112012-12-03 18:12:45 +0000495namespace clang {
496namespace format {
497
Rafael Espindola6d0d89b2014-06-12 03:31:26 +0000498const std::error_category &getParseCategory() {
Rafael Espindolad0136702014-06-12 02:50:04 +0000499 static ParseErrorCategory C;
500 return C;
501}
502std::error_code make_error_code(ParseError e) {
Rafael Espindola6d0d89b2014-06-12 03:31:26 +0000503 return std::error_code(static_cast<int>(e), getParseCategory());
Rafael Espindolad0136702014-06-12 02:50:04 +0000504}
505
Antonio Maiorano3adfb6a2017-01-17 00:12:27 +0000506inline llvm::Error make_string_error(const llvm::Twine &Message) {
507 return llvm::make_error<llvm::StringError>(Message,
508 llvm::inconvertibleErrorCode());
509}
510
Reid Kleckner6432d452016-10-19 23:39:55 +0000511const char *ParseErrorCategory::name() const noexcept {
Rafael Espindolad0136702014-06-12 02:50:04 +0000512 return "clang-format.parse_error";
513}
514
515std::string ParseErrorCategory::message(int EV) const {
516 switch (static_cast<ParseError>(EV)) {
517 case ParseError::Success:
518 return "Success";
519 case ParseError::Error:
520 return "Invalid argument";
521 case ParseError::Unsuitable:
522 return "Unsuitable";
523 }
Saleem Abdulrasoolfbfbaf62014-06-12 19:33:26 +0000524 llvm_unreachable("unexpected parse error");
Rafael Espindolad0136702014-06-12 02:50:04 +0000525}
526
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000527static FormatStyle expandPresets(const FormatStyle &Style) {
Daniel Jasper55bbe662015-10-07 04:06:10 +0000528 if (Style.BreakBeforeBraces == FormatStyle::BS_Custom)
529 return Style;
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000530 FormatStyle Expanded = Style;
Manuel Klimek89628f62017-09-20 09:51:03 +0000531 Expanded.BraceWrapping = {false, false, false, false, false,
532 false, false, false, false, false,
533 false, false, true, true, true};
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000534 switch (Style.BreakBeforeBraces) {
535 case FormatStyle::BS_Linux:
536 Expanded.BraceWrapping.AfterClass = true;
537 Expanded.BraceWrapping.AfterFunction = true;
538 Expanded.BraceWrapping.AfterNamespace = true;
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000539 break;
540 case FormatStyle::BS_Mozilla:
541 Expanded.BraceWrapping.AfterClass = true;
542 Expanded.BraceWrapping.AfterEnum = true;
543 Expanded.BraceWrapping.AfterFunction = true;
544 Expanded.BraceWrapping.AfterStruct = true;
545 Expanded.BraceWrapping.AfterUnion = true;
Krasimir Georgievd6ce9372017-09-15 11:23:50 +0000546 Expanded.BraceWrapping.AfterExternBlock = true;
Sylvestre Ledru82c9a0e2017-09-13 20:03:29 +0000547 Expanded.BraceWrapping.SplitEmptyFunction = true;
Francois Ferrandad722562017-06-30 20:25:55 +0000548 Expanded.BraceWrapping.SplitEmptyRecord = false;
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000549 break;
550 case FormatStyle::BS_Stroustrup:
551 Expanded.BraceWrapping.AfterFunction = true;
552 Expanded.BraceWrapping.BeforeCatch = true;
553 Expanded.BraceWrapping.BeforeElse = true;
554 break;
555 case FormatStyle::BS_Allman:
556 Expanded.BraceWrapping.AfterClass = true;
557 Expanded.BraceWrapping.AfterControlStatement = true;
558 Expanded.BraceWrapping.AfterEnum = true;
559 Expanded.BraceWrapping.AfterFunction = true;
560 Expanded.BraceWrapping.AfterNamespace = true;
561 Expanded.BraceWrapping.AfterObjCDeclaration = true;
562 Expanded.BraceWrapping.AfterStruct = true;
Krasimir Georgievd6ce9372017-09-15 11:23:50 +0000563 Expanded.BraceWrapping.AfterExternBlock = true;
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000564 Expanded.BraceWrapping.BeforeCatch = true;
565 Expanded.BraceWrapping.BeforeElse = true;
566 break;
567 case FormatStyle::BS_GNU:
Manuel Klimek89628f62017-09-20 09:51:03 +0000568 Expanded.BraceWrapping = {true, true, true, true, true, true, true, true,
569 true, true, true, true, true, true, true};
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000570 break;
571 case FormatStyle::BS_WebKit:
572 Expanded.BraceWrapping.AfterFunction = true;
573 break;
574 default:
575 break;
576 }
577 return Expanded;
578}
579
Daniel Jasperf7935112012-12-03 18:12:45 +0000580FormatStyle getLLVMStyle() {
581 FormatStyle LLVMStyle;
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000582 LLVMStyle.Language = FormatStyle::LK_Cpp;
Daniel Jasperf7935112012-12-03 18:12:45 +0000583 LLVMStyle.AccessModifierOffset = -2;
Daniel Jasper7fdbb3f2017-05-08 15:08:00 +0000584 LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
Daniel Jasper6501f7e2015-10-27 12:38:37 +0000585 LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
Daniel Jasper3219e432014-12-02 13:24:51 +0000586 LLVMStyle.AlignOperands = true;
Daniel Jasper552f4a72013-07-31 23:55:15 +0000587 LLVMStyle.AlignTrailingComments = true;
Daniel Jaspera44991332015-04-29 13:06:49 +0000588 LLVMStyle.AlignConsecutiveAssignments = false;
Daniel Jaspere12597c2015-10-01 10:06:54 +0000589 LLVMStyle.AlignConsecutiveDeclarations = false;
Daniel Jasperf7db4332013-01-29 16:03:49 +0000590 LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
Daniel Jasperd74cf402014-04-08 12:46:38 +0000591 LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
Daniel Jasper17605d32014-05-14 09:33:35 +0000592 LLVMStyle.AllowShortBlocksOnASingleLine = false;
Daniel Jasperb87899b2014-09-10 13:11:45 +0000593 LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
Daniel Jasper1b750ed2013-01-14 16:24:39 +0000594 LLVMStyle.AllowShortIfStatementsOnASingleLine = false;
Daniel Jasper3a685df2013-05-16 12:12:21 +0000595 LLVMStyle.AllowShortLoopsOnASingleLine = false;
Zachary Turner448592e2015-12-18 22:20:15 +0000596 LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
Birunthan Mohanathasa0388a82015-06-29 15:30:42 +0000597 LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
Alexander Kornienko58611712013-07-04 12:02:44 +0000598 LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
Daniel Jaspere33d4af2013-07-26 16:56:36 +0000599 LLVMStyle.AlwaysBreakTemplateDeclarations = false;
Daniel Jasper18210d72014-10-09 09:52:05 +0000600 LLVMStyle.BinPackArguments = true;
Francois Ferrande56a8292017-06-14 12:29:47 +0000601 LLVMStyle.BinPackParameters = true;
Daniel Jasperac043c92014-09-15 11:11:00 +0000602 LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
Daniel Jasper165b29e2013-11-08 00:57:11 +0000603 LLVMStyle.BreakBeforeTernaryOperators = true;
Daniel Jaspere33d4af2013-07-26 16:56:36 +0000604 LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
Manuel Klimek89628f62017-09-20 09:51:03 +0000605 LLVMStyle.BraceWrapping = {false, false, false, false, false,
606 false, false, false, false, false,
607 false, false, true, true, true};
Nico Weber2cd92f12015-10-15 16:03:01 +0000608 LLVMStyle.BreakAfterJavaFieldAnnotations = false;
Francois Ferranda6b6d512017-05-24 11:36:58 +0000609 LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
Andi-Bogdan Postelnicu0ef8ee12017-03-10 15:10:37 +0000610 LLVMStyle.BreakBeforeInheritanceComma = false;
Daniel Jaspere1a7b762016-02-01 11:21:02 +0000611 LLVMStyle.BreakStringLiterals = true;
Alexander Kornienkoc8602662013-05-06 14:11:27 +0000612 LLVMStyle.ColumnLimit = 80;
Daniel Jaspere1e43192014-04-01 12:55:11 +0000613 LLVMStyle.CommentPragmas = "^ IWYU pragma:";
Francois Ferrande56a8292017-06-14 12:29:47 +0000614 LLVMStyle.CompactNamespaces = false;
Alexander Kornienkoc8602662013-05-06 14:11:27 +0000615 LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false;
Daniel Jaspercdaffa42013-08-13 10:58:30 +0000616 LLVMStyle.ConstructorInitializerIndentWidth = 4;
Daniel Jaspere1e43192014-04-01 12:55:11 +0000617 LLVMStyle.ContinuationIndentWidth = 4;
Chandler Carruthf8b72662014-03-02 12:37:31 +0000618 LLVMStyle.Cpp11BracedListStyle = true;
Daniel Jasper553d4872014-06-17 12:40:34 +0000619 LLVMStyle.DerivePointerAlignment = false;
Daniel Jasperb10cbc42013-07-10 14:02:49 +0000620 LLVMStyle.ExperimentalAutoDetectBinPacking = false;
Krasimir Georgiev32eaa862017-03-01 15:35:39 +0000621 LLVMStyle.FixNamespaceComments = true;
Daniel Jaspere1e43192014-04-01 12:55:11 +0000622 LLVMStyle.ForEachMacros.push_back("foreach");
623 LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
624 LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
Daniel Jasper85c472d2015-09-29 07:53:08 +0000625 LLVMStyle.IncludeCategories = {{"^\"(llvm|llvm-c|clang|clang-c)/", 2},
Chandler Carruthd676ab12017-06-29 23:20:54 +0000626 {"^(<|\"(gtest|gmock|isl|json)/)", 3},
Daniel Jasper85c472d2015-09-29 07:53:08 +0000627 {".*", 1}};
Chandler Carruthd676ab12017-06-29 23:20:54 +0000628 LLVMStyle.IncludeIsMainRegex = "(Test)?$";
Krasimir Georgiev4c2c9c32017-11-27 13:23:45 +0000629 LLVMStyle.IncludeBlocks = FormatStyle::IBS_Preserve;
Alexander Kornienkoc8602662013-05-06 14:11:27 +0000630 LLVMStyle.IndentCaseLabels = false;
Krasimir Georgievad47c902017-08-30 14:34:57 +0000631 LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
Daniel Jasperc75e1ef2014-07-09 08:42:42 +0000632 LLVMStyle.IndentWrappedFunctionNames = false;
Daniel Jaspere33d4af2013-07-26 16:56:36 +0000633 LLVMStyle.IndentWidth = 2;
Martin Probstfb2342d2016-06-13 17:50:10 +0000634 LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
635 LLVMStyle.JavaScriptWrapImports = true;
Alexander Kornienkoebb43ca2013-09-05 14:08:34 +0000636 LLVMStyle.TabWidth = 8;
Alexander Kornienkoc8602662013-05-06 14:11:27 +0000637 LLVMStyle.MaxEmptyLinesToKeep = 1;
Daniel Jaspera26fc5c2014-03-21 13:43:14 +0000638 LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
Daniel Jasper65ee3472013-07-31 23:16:02 +0000639 LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
Daniel Jasper50d634b2014-10-28 16:53:38 +0000640 LLVMStyle.ObjCBlockIndentWidth = 2;
Daniel Jaspere9beea22014-01-28 15:20:33 +0000641 LLVMStyle.ObjCSpaceAfterProperty = false;
Nico Webera6087752013-01-10 20:12:55 +0000642 LLVMStyle.ObjCSpaceBeforeProtocolList = true;
Daniel Jasper553d4872014-06-17 12:40:34 +0000643 LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
Alexander Kornienkoc8602662013-05-06 14:11:27 +0000644 LLVMStyle.SpacesBeforeTrailingComments = 1;
Chandler Carruthf8b72662014-03-02 12:37:31 +0000645 LLVMStyle.Standard = FormatStyle::LS_Cpp11;
Alexander Kornienko3c3d09c2013-09-27 16:14:22 +0000646 LLVMStyle.UseTab = FormatStyle::UT_Never;
Daniel Jaspera0a50392015-12-01 13:28:53 +0000647 LLVMStyle.ReflowComments = true;
Daniel Jasperb55acad2013-08-20 12:36:34 +0000648 LLVMStyle.SpacesInParentheses = false;
Daniel Jasperad981f82014-08-26 11:41:14 +0000649 LLVMStyle.SpacesInSquareBrackets = false;
Daniel Jasperb55acad2013-08-20 12:36:34 +0000650 LLVMStyle.SpaceInEmptyParentheses = false;
Daniel Jasperb2e10a52014-01-15 15:09:08 +0000651 LLVMStyle.SpacesInContainerLiterals = true;
Daniel Jasperb55acad2013-08-20 12:36:34 +0000652 LLVMStyle.SpacesInCStyleCastParentheses = false;
Daniel Jasperdb986eb2014-09-03 07:37:29 +0000653 LLVMStyle.SpaceAfterCStyleCast = false;
Sylvestre Ledru83bbd572016-08-09 14:24:40 +0000654 LLVMStyle.SpaceAfterTemplateKeyword = true;
Alexander Kornienkofdca83d2013-12-10 10:18:34 +0000655 LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
Daniel Jasperd94bff32013-09-25 15:15:02 +0000656 LLVMStyle.SpaceBeforeAssignmentOperators = true;
Daniel Jasperdd978ae2013-10-29 14:52:02 +0000657 LLVMStyle.SpacesInAngles = false;
Daniel Jasper4e9678f2013-07-11 20:41:21 +0000658
Francois Ferrand9976efa2017-05-22 08:28:17 +0000659 LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
Daniel Jasper19a541e2013-12-19 16:45:34 +0000660 LLVMStyle.PenaltyBreakComment = 300;
Alexander Kornienkofe7a57f2013-12-10 15:42:15 +0000661 LLVMStyle.PenaltyBreakFirstLessLess = 120;
662 LLVMStyle.PenaltyBreakString = 1000;
663 LLVMStyle.PenaltyExcessCharacter = 1000000;
Daniel Jasper4e9678f2013-07-11 20:41:21 +0000664 LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
Daniel Jasper33b909c2013-10-25 14:29:37 +0000665 LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
Daniel Jasper4e9678f2013-07-11 20:41:21 +0000666
Daniel Jasperc64b09a2014-05-22 15:12:22 +0000667 LLVMStyle.DisableFormat = false;
Daniel Jasperda446772015-11-16 12:38:56 +0000668 LLVMStyle.SortIncludes = true;
Krasimir Georgievac16a202017-06-23 11:46:03 +0000669 LLVMStyle.SortUsingDeclarations = true;
Daniel Jasperc64b09a2014-05-22 15:12:22 +0000670
Daniel Jasperf7935112012-12-03 18:12:45 +0000671 return LLVMStyle;
672}
673
Nico Weber514ecc82014-02-02 20:50:45 +0000674FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
Krasimir Georgiev26b144c2017-07-03 15:05:14 +0000675 if (Language == FormatStyle::LK_TextProto) {
676 FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto);
677 GoogleStyle.Language = FormatStyle::LK_TextProto;
Krasimir Georgieveda222e2018-01-24 11:18:39 +0000678
679 // Text protos are currently mostly formatted inside C++ raw string literals
680 // and often the current breaking behavior of string literals is not
681 // beneficial there. Investigate turning this on once proper string reflow
682 // has been implemented.
683 GoogleStyle.BreakStringLiterals = false;
Krasimir Georgiev26b144c2017-07-03 15:05:14 +0000684 return GoogleStyle;
685 }
686
Alexander Kornienkofe7a57f2013-12-10 15:42:15 +0000687 FormatStyle GoogleStyle = getLLVMStyle();
Nico Weber514ecc82014-02-02 20:50:45 +0000688 GoogleStyle.Language = Language;
689
Daniel Jasperf7935112012-12-03 18:12:45 +0000690 GoogleStyle.AccessModifierOffset = -1;
Daniel Jasper7fdbb3f2017-05-08 15:08:00 +0000691 GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left;
Daniel Jasper085a2ed2013-04-24 13:46:00 +0000692 GoogleStyle.AllowShortIfStatementsOnASingleLine = true;
Daniel Jasper5bd0b9e2013-05-23 18:05:18 +0000693 GoogleStyle.AllowShortLoopsOnASingleLine = true;
Alexander Kornienko58611712013-07-04 12:02:44 +0000694 GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
Daniel Jaspere33d4af2013-07-26 16:56:36 +0000695 GoogleStyle.AlwaysBreakTemplateDeclarations = true;
Alexander Kornienkoc8602662013-05-06 14:11:27 +0000696 GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
Daniel Jasper553d4872014-06-17 12:40:34 +0000697 GoogleStyle.DerivePointerAlignment = true;
Krasimir Georgieva84e7872017-09-26 14:58:29 +0000698 GoogleStyle.IncludeCategories = {
699 {"^<ext/.*\\.h>", 2}, {"^<.*\\.h>", 1}, {"^<.*", 2}, {".*", 3}};
Daniel Jasper9c8ff352016-03-21 14:11:27 +0000700 GoogleStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
Alexander Kornienkoc8602662013-05-06 14:11:27 +0000701 GoogleStyle.IndentCaseLabels = true;
Daniel Jaspera26fc5c2014-03-21 13:43:14 +0000702 GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
Daniel Jaspere9beea22014-01-28 15:20:33 +0000703 GoogleStyle.ObjCSpaceAfterProperty = false;
Ben Hamiltonf84f1182018-01-18 18:37:16 +0000704 GoogleStyle.ObjCSpaceBeforeProtocolList = true;
Daniel Jasper553d4872014-06-17 12:40:34 +0000705 GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;
Krasimir Georgiev4527f132018-01-17 12:24:59 +0000706 GoogleStyle.RawStringFormats = {{
707 FormatStyle::LK_TextProto,
708 /*Delimiters=*/
709 {
710 "pb",
711 "PB",
712 "proto",
713 "PROTO",
714 "textproto",
715 "TEXTPROTO",
716 },
Krasimir Georgiev2537e222018-01-17 16:17:26 +0000717 /*EnclosingFunctionNames=*/
718 {
719 "EqualsProto",
720 "PARSE_TEXT_PROTO",
721 "ParseTextProto",
722 },
Krasimir Georgiev412ed092018-01-19 16:18:47 +0000723 /*CanonicalDelimiter=*/"",
Krasimir Georgiev4527f132018-01-17 12:24:59 +0000724 /*BasedOnStyle=*/"google",
725 }};
Alexander Kornienkoc8602662013-05-06 14:11:27 +0000726 GoogleStyle.SpacesBeforeTrailingComments = 2;
727 GoogleStyle.Standard = FormatStyle::LS_Auto;
Daniel Jasper4e9678f2013-07-11 20:41:21 +0000728
Daniel Jasper4e9678f2013-07-11 20:41:21 +0000729 GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
Daniel Jasper33b909c2013-10-25 14:29:37 +0000730 GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;
Daniel Jasper4e9678f2013-07-11 20:41:21 +0000731
Daniel Jasperc58c70e2014-09-15 11:21:46 +0000732 if (Language == FormatStyle::LK_Java) {
Daniel Jasper6501f7e2015-10-27 12:38:37 +0000733 GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
Daniel Jasper3219e432014-12-02 13:24:51 +0000734 GoogleStyle.AlignOperands = false;
Daniel Jasperfd4ed182015-01-04 20:40:45 +0000735 GoogleStyle.AlignTrailingComments = false;
Daniel Jasper9e709352014-11-26 10:43:58 +0000736 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
Daniel Jasperfd4ed182015-01-04 20:40:45 +0000737 GoogleStyle.AllowShortIfStatementsOnASingleLine = false;
Daniel Jasper1cd3c712015-01-14 12:24:59 +0000738 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
Daniel Jasperc58c70e2014-09-15 11:21:46 +0000739 GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
740 GoogleStyle.ColumnLimit = 100;
741 GoogleStyle.SpaceAfterCStyleCast = true;
Daniel Jasper61d81972014-11-14 08:22:46 +0000742 GoogleStyle.SpacesBeforeTrailingComments = 1;
Daniel Jasperc58c70e2014-09-15 11:21:46 +0000743 } else if (Language == FormatStyle::LK_JavaScript) {
Daniel Jasper6501f7e2015-10-27 12:38:37 +0000744 GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
Daniel Jasper41a2bf72015-12-21 13:52:19 +0000745 GoogleStyle.AlignOperands = false;
Daniel Jasper28d8a5a2016-09-07 23:01:13 +0000746 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
Daniel Jasper6501f7e2015-10-27 12:38:37 +0000747 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
Daniel Jaspere551bb72014-11-05 17:22:31 +0000748 GoogleStyle.BreakBeforeTernaryOperators = false;
Martin Probst2083f312017-05-09 12:45:48 +0000749 // taze:, triple slash directives (`/// <...`), @tag followed by { for a lot
750 // of JSDoc tags, and @see, which is commonly followed by overlong URLs.
751 GoogleStyle.CommentPragmas =
752 "(taze:|^/[ \t]*<|(@[A-Za-z_0-9-]+[ \\t]*{)|@see)";
Daniel Jasper8f83a902014-05-09 10:28:58 +0000753 GoogleStyle.MaxEmptyLinesToKeep = 3;
Martin Probstece8c0c2016-06-13 16:41:28 +0000754 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
Nico Weber514ecc82014-02-02 20:50:45 +0000755 GoogleStyle.SpacesInContainerLiterals = false;
Daniel Jasperabd1f572016-03-02 22:44:03 +0000756 GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single;
Martin Probst0cd74ee2016-06-13 16:39:50 +0000757 GoogleStyle.JavaScriptWrapImports = false;
Nico Weber514ecc82014-02-02 20:50:45 +0000758 } else if (Language == FormatStyle::LK_Proto) {
Daniel Jasperd74cf402014-04-08 12:46:38 +0000759 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
Daniel Jasper783bac62014-04-15 09:54:30 +0000760 GoogleStyle.SpacesInContainerLiterals = false;
Daniel Jasper03a04fe2016-12-12 12:42:29 +0000761 } else if (Language == FormatStyle::LK_ObjC) {
762 GoogleStyle.ColumnLimit = 100;
Nico Weber514ecc82014-02-02 20:50:45 +0000763 }
764
Daniel Jasperf7935112012-12-03 18:12:45 +0000765 return GoogleStyle;
766}
767
Nico Weber514ecc82014-02-02 20:50:45 +0000768FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
769 FormatStyle ChromiumStyle = getGoogleStyle(Language);
Nico Weber450425c2014-11-26 16:43:18 +0000770 if (Language == FormatStyle::LK_Java) {
Daniel Jasperfd4ed182015-01-04 20:40:45 +0000771 ChromiumStyle.AllowShortIfStatementsOnASingleLine = true;
Nico Weber2cd92f12015-10-15 16:03:01 +0000772 ChromiumStyle.BreakAfterJavaFieldAnnotations = true;
Nico Weber450425c2014-11-26 16:43:18 +0000773 ChromiumStyle.ContinuationIndentWidth = 8;
Nico Weber2cd92f12015-10-15 16:03:01 +0000774 ChromiumStyle.IndentWidth = 4;
Nico Weberea649692017-01-04 02:33:36 +0000775 } else if (Language == FormatStyle::LK_JavaScript) {
776 ChromiumStyle.AllowShortIfStatementsOnASingleLine = false;
777 ChromiumStyle.AllowShortLoopsOnASingleLine = false;
Nico Weber450425c2014-11-26 16:43:18 +0000778 } else {
779 ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
780 ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
781 ChromiumStyle.AllowShortIfStatementsOnASingleLine = false;
782 ChromiumStyle.AllowShortLoopsOnASingleLine = false;
783 ChromiumStyle.BinPackParameters = false;
784 ChromiumStyle.DerivePointerAlignment = false;
Nico Weber9e2bc302017-01-31 18:42:05 +0000785 if (Language == FormatStyle::LK_ObjC)
786 ChromiumStyle.ColumnLimit = 80;
Nico Weber450425c2014-11-26 16:43:18 +0000787 }
Daniel Jasper1b750ed2013-01-14 16:24:39 +0000788 return ChromiumStyle;
789}
790
Alexander Kornienkoc8602662013-05-06 14:11:27 +0000791FormatStyle getMozillaStyle() {
792 FormatStyle MozillaStyle = getLLVMStyle();
793 MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
Birunthan Mohanathasa0810022015-06-29 15:18:58 +0000794 MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
Manuel Klimek89628f62017-09-20 09:51:03 +0000795 MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel;
Birunthan Mohanathasa0388a82015-06-29 15:30:42 +0000796 MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
797 FormatStyle::DRTBS_TopLevel;
Birunthan Mohanathasa0810022015-06-29 15:18:58 +0000798 MozillaStyle.AlwaysBreakTemplateDeclarations = true;
Sylvestre Ledrudcb038d2016-12-14 16:09:29 +0000799 MozillaStyle.BinPackParameters = false;
800 MozillaStyle.BinPackArguments = false;
Birunthan Mohanathas305fa9c2015-07-12 03:13:54 +0000801 MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
Francois Ferranda6b6d512017-05-24 11:36:58 +0000802 MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
Andi-Bogdan Postelnicu0ef8ee12017-03-10 15:10:37 +0000803 MozillaStyle.BreakBeforeInheritanceComma = true;
Birunthan Mohanathasa0810022015-06-29 15:18:58 +0000804 MozillaStyle.ConstructorInitializerIndentWidth = 2;
805 MozillaStyle.ContinuationIndentWidth = 2;
Chandler Carruthf8b72662014-03-02 12:37:31 +0000806 MozillaStyle.Cpp11BracedListStyle = false;
Krasimir Georgiev32eaa862017-03-01 15:35:39 +0000807 MozillaStyle.FixNamespaceComments = false;
Alexander Kornienkoc8602662013-05-06 14:11:27 +0000808 MozillaStyle.IndentCaseLabels = true;
Daniel Jaspere9beea22014-01-28 15:20:33 +0000809 MozillaStyle.ObjCSpaceAfterProperty = true;
Alexander Kornienkoc8602662013-05-06 14:11:27 +0000810 MozillaStyle.ObjCSpaceBeforeProtocolList = false;
811 MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
Daniel Jasper553d4872014-06-17 12:40:34 +0000812 MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
Sylvestre Ledru83bbd572016-08-09 14:24:40 +0000813 MozillaStyle.SpaceAfterTemplateKeyword = false;
Alexander Kornienkoc8602662013-05-06 14:11:27 +0000814 return MozillaStyle;
815}
816
Daniel Jasperffefb3d2013-07-24 13:10:59 +0000817FormatStyle getWebKitStyle() {
818 FormatStyle Style = getLLVMStyle();
Daniel Jasper65ee3472013-07-31 23:16:02 +0000819 Style.AccessModifierOffset = -4;
Daniel Jasper6501f7e2015-10-27 12:38:37 +0000820 Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
Daniel Jasper3219e432014-12-02 13:24:51 +0000821 Style.AlignOperands = false;
Daniel Jasper552f4a72013-07-31 23:55:15 +0000822 Style.AlignTrailingComments = false;
Daniel Jasperac043c92014-09-15 11:11:00 +0000823 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
Roman Kashitsyn291f64f2015-08-10 13:43:19 +0000824 Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
Francois Ferranda6b6d512017-05-24 11:36:58 +0000825 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
Chandler Carruthf8b72662014-03-02 12:37:31 +0000826 Style.Cpp11BracedListStyle = false;
Daniel Jasper65ee3472013-07-31 23:16:02 +0000827 Style.ColumnLimit = 0;
Krasimir Georgiev32eaa862017-03-01 15:35:39 +0000828 Style.FixNamespaceComments = false;
Daniel Jaspere33d4af2013-07-26 16:56:36 +0000829 Style.IndentWidth = 4;
Daniel Jasper65ee3472013-07-31 23:16:02 +0000830 Style.NamespaceIndentation = FormatStyle::NI_Inner;
Daniel Jasper50d634b2014-10-28 16:53:38 +0000831 Style.ObjCBlockIndentWidth = 4;
Daniel Jaspere9beea22014-01-28 15:20:33 +0000832 Style.ObjCSpaceAfterProperty = true;
Daniel Jasper553d4872014-06-17 12:40:34 +0000833 Style.PointerAlignment = FormatStyle::PAS_Left;
Daniel Jasperffefb3d2013-07-24 13:10:59 +0000834 return Style;
835}
836
Alexander Kornienkofe7a57f2013-12-10 15:42:15 +0000837FormatStyle getGNUStyle() {
838 FormatStyle Style = getLLVMStyle();
Birunthan Mohanathasa0388a82015-06-29 15:30:42 +0000839 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
Zachary Turner448592e2015-12-18 22:20:15 +0000840 Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
Daniel Jasperac043c92014-09-15 11:11:00 +0000841 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
Alexander Kornienko3a33f022013-12-12 09:49:52 +0000842 Style.BreakBeforeBraces = FormatStyle::BS_GNU;
Alexander Kornienkofe7a57f2013-12-10 15:42:15 +0000843 Style.BreakBeforeTernaryOperators = true;
Chandler Carruthf8b72662014-03-02 12:37:31 +0000844 Style.Cpp11BracedListStyle = false;
Alexander Kornienkofe7a57f2013-12-10 15:42:15 +0000845 Style.ColumnLimit = 79;
Krasimir Georgiev32eaa862017-03-01 15:35:39 +0000846 Style.FixNamespaceComments = false;
Alexander Kornienkofe7a57f2013-12-10 15:42:15 +0000847 Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
Chandler Carruthf8b72662014-03-02 12:37:31 +0000848 Style.Standard = FormatStyle::LS_Cpp03;
Alexander Kornienkofe7a57f2013-12-10 15:42:15 +0000849 return Style;
850}
851
Daniel Jasperc64b09a2014-05-22 15:12:22 +0000852FormatStyle getNoStyle() {
853 FormatStyle NoStyle = getLLVMStyle();
854 NoStyle.DisableFormat = true;
Daniel Jasperda446772015-11-16 12:38:56 +0000855 NoStyle.SortIncludes = false;
Krasimir Georgievac16a202017-06-23 11:46:03 +0000856 NoStyle.SortUsingDeclarations = false;
Daniel Jasperc64b09a2014-05-22 15:12:22 +0000857 return NoStyle;
858}
859
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000860bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
861 FormatStyle *Style) {
862 if (Name.equals_lower("llvm")) {
Alexander Kornienko006b5c82013-05-19 00:53:30 +0000863 *Style = getLLVMStyle();
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000864 } else if (Name.equals_lower("chromium")) {
Nico Weber514ecc82014-02-02 20:50:45 +0000865 *Style = getChromiumStyle(Language);
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000866 } else if (Name.equals_lower("mozilla")) {
Alexander Kornienko006b5c82013-05-19 00:53:30 +0000867 *Style = getMozillaStyle();
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000868 } else if (Name.equals_lower("google")) {
Nico Weber514ecc82014-02-02 20:50:45 +0000869 *Style = getGoogleStyle(Language);
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000870 } else if (Name.equals_lower("webkit")) {
Daniel Jasperffefb3d2013-07-24 13:10:59 +0000871 *Style = getWebKitStyle();
Alexander Kornienkofe7a57f2013-12-10 15:42:15 +0000872 } else if (Name.equals_lower("gnu")) {
873 *Style = getGNUStyle();
Daniel Jasperc64b09a2014-05-22 15:12:22 +0000874 } else if (Name.equals_lower("none")) {
875 *Style = getNoStyle();
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000876 } else {
Alexander Kornienko006b5c82013-05-19 00:53:30 +0000877 return false;
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000878 }
Alexander Kornienkod6538332013-05-07 15:32:14 +0000879
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000880 Style->Language = Language;
Alexander Kornienko006b5c82013-05-19 00:53:30 +0000881 return true;
Alexander Kornienkod6538332013-05-07 15:32:14 +0000882}
883
Rafael Espindolac0809172014-06-12 14:02:15 +0000884std::error_code parseConfiguration(StringRef Text, FormatStyle *Style) {
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000885 assert(Style);
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000886 FormatStyle::LanguageKind Language = Style->Language;
887 assert(Language != FormatStyle::LK_None);
Alexander Kornienko06e00332013-05-20 15:18:01 +0000888 if (Text.trim().empty())
Rafael Espindolad0136702014-06-12 02:50:04 +0000889 return make_error_code(ParseError::Error);
Krasimir Georgiev54076fe2018-01-15 12:06:16 +0000890 Style->StyleSet.Clear();
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000891 std::vector<FormatStyle> Styles;
Alexander Kornienkod6538332013-05-07 15:32:14 +0000892 llvm::yaml::Input Input(Text);
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000893 // DocumentListTraits<vector<FormatStyle>> uses the context to get default
894 // values for the fields, keys for which are missing from the configuration.
895 // Mapping also uses the context to get the language to find the correct
896 // base style.
897 Input.setContext(Style);
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000898 Input >> Styles;
899 if (Input.error())
900 return Input.error();
901
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000902 for (unsigned i = 0; i < Styles.size(); ++i) {
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000903 // Ensures that only the first configuration can skip the Language option.
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000904 if (Styles[i].Language == FormatStyle::LK_None && i != 0)
Rafael Espindolad0136702014-06-12 02:50:04 +0000905 return make_error_code(ParseError::Error);
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000906 // Ensure that each language is configured at most once.
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000907 for (unsigned j = 0; j < i; ++j) {
908 if (Styles[i].Language == Styles[j].Language) {
909 DEBUG(llvm::dbgs()
910 << "Duplicate languages in the config file on positions " << j
911 << " and " << i << "\n");
Rafael Espindolad0136702014-06-12 02:50:04 +0000912 return make_error_code(ParseError::Error);
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000913 }
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000914 }
915 }
916 // Look for a suitable configuration starting from the end, so we can
917 // find the configuration for the specific language first, and the default
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000918 // configuration (which can only be at slot 0) after it.
Krasimir Georgiev54076fe2018-01-15 12:06:16 +0000919 FormatStyle::FormatStyleSet StyleSet;
920 bool LanguageFound = false;
Alexander Kornienkoc1637f12013-12-10 11:28:13 +0000921 for (int i = Styles.size() - 1; i >= 0; --i) {
Krasimir Georgiev54076fe2018-01-15 12:06:16 +0000922 if (Styles[i].Language != FormatStyle::LK_None)
923 StyleSet.Add(Styles[i]);
924 if (Styles[i].Language == Language)
925 LanguageFound = true;
Alexander Kornienkocabdd732013-11-29 15:19:43 +0000926 }
Krasimir Georgiev54076fe2018-01-15 12:06:16 +0000927 if (!LanguageFound) {
928 if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None)
929 return make_error_code(ParseError::Unsuitable);
930 FormatStyle DefaultStyle = Styles[0];
931 DefaultStyle.Language = Language;
932 StyleSet.Add(std::move(DefaultStyle));
933 }
934 *Style = *StyleSet.Get(Language);
935 return make_error_code(ParseError::Success);
Alexander Kornienkod6538332013-05-07 15:32:14 +0000936}
937
938std::string configurationAsText(const FormatStyle &Style) {
939 std::string Text;
940 llvm::raw_string_ostream Stream(Text);
941 llvm::yaml::Output Output(Stream);
942 // We use the same mapping method for input and output, so we need a non-const
943 // reference here.
Daniel Jasperc1bc38e2015-09-29 14:57:55 +0000944 FormatStyle NonConstStyle = expandPresets(Style);
Alexander Kornienkod6538332013-05-07 15:32:14 +0000945 Output << NonConstStyle;
Alexander Kornienko9a38ec22013-05-13 12:56:35 +0000946 return Stream.str();
Alexander Kornienkod6538332013-05-07 15:32:14 +0000947}
948
Krasimir Georgiev54076fe2018-01-15 12:06:16 +0000949llvm::Optional<FormatStyle>
950FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {
951 if (!Styles)
952 return None;
953 auto It = Styles->find(Language);
954 if (It == Styles->end())
955 return None;
956 FormatStyle Style = It->second;
957 Style.StyleSet = *this;
958 return Style;
959}
960
961void FormatStyle::FormatStyleSet::Add(FormatStyle Style) {
962 assert(Style.Language != LK_None &&
963 "Cannot add a style for LK_None to a StyleSet");
964 assert(
965 !Style.StyleSet.Styles &&
966 "Cannot add a style associated with an existing StyleSet to a StyleSet");
967 if (!Styles)
968 Styles = std::make_shared<MapType>();
969 (*Styles)[Style.Language] = std::move(Style);
970}
971
972void FormatStyle::FormatStyleSet::Clear() {
973 Styles.reset();
974}
975
976llvm::Optional<FormatStyle>
977FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {
978 return StyleSet.Get(Language);
979}
980
Craig Topperaf35e852013-06-30 22:29:28 +0000981namespace {
982
Daniel Jasper496c1992016-09-07 22:48:53 +0000983class JavaScriptRequoter : public TokenAnalyzer {
Eric Liu4cfb88a2016-04-25 15:09:22 +0000984public:
Daniel Jasper496c1992016-09-07 22:48:53 +0000985 JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)
986 : TokenAnalyzer(Env, Style) {}
Eric Liu4cfb88a2016-04-25 15:09:22 +0000987
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +0000988 std::pair<tooling::Replacements, unsigned>
Eric Liu4cfb88a2016-04-25 15:09:22 +0000989 analyze(TokenAnnotator &Annotator,
990 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
Martin Probsta9855af2016-09-02 14:29:48 +0000991 FormatTokenLexer &Tokens) override {
Eric Liu4cfb88a2016-04-25 15:09:22 +0000992 AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
993 AnnotatedLines.end());
Daniel Jasper496c1992016-09-07 22:48:53 +0000994 tooling::Replacements Result;
995 requoteJSStringLiteral(AnnotatedLines, Result);
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +0000996 return {Result, 0};
Alexander Kornienko62b85b92013-03-13 14:41:29 +0000997 }
998
999private:
Daniel Jasper496c1992016-09-07 22:48:53 +00001000 // Replaces double/single-quoted string literal as appropriate, re-escaping
1001 // the contents in the process.
Daniel Jasper97439922016-03-17 13:03:41 +00001002 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
Eric Liu4cfb88a2016-04-25 15:09:22 +00001003 tooling::Replacements &Result) {
Daniel Jasper97439922016-03-17 13:03:41 +00001004 for (AnnotatedLine *Line : Lines) {
1005 requoteJSStringLiteral(Line->Children, Result);
1006 if (!Line->Affected)
1007 continue;
1008 for (FormatToken *FormatTok = Line->First; FormatTok;
1009 FormatTok = FormatTok->Next) {
1010 StringRef Input = FormatTok->TokenText;
Martin Probsta1669792016-05-12 11:20:32 +00001011 if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
Daniel Jasper97439922016-03-17 13:03:41 +00001012 // NB: testing for not starting with a double quote to avoid
Daniel Jasper496c1992016-09-07 22:48:53 +00001013 // breaking `template strings`.
Eric Liu635423e2016-04-28 07:52:03 +00001014 (Style.JavaScriptQuotes == FormatStyle::JSQS_Single &&
Daniel Jasper97439922016-03-17 13:03:41 +00001015 !Input.startswith("\"")) ||
Eric Liu635423e2016-04-28 07:52:03 +00001016 (Style.JavaScriptQuotes == FormatStyle::JSQS_Double &&
Daniel Jasper97439922016-03-17 13:03:41 +00001017 !Input.startswith("\'")))
1018 continue;
1019
1020 // Change start and end quote.
Eric Liu635423e2016-04-28 07:52:03 +00001021 bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single;
Daniel Jasper97439922016-03-17 13:03:41 +00001022 SourceLocation Start = FormatTok->Tok.getLocation();
1023 auto Replace = [&](SourceLocation Start, unsigned Length,
1024 StringRef ReplacementText) {
Eric Liu40ef2fb2016-08-01 10:16:37 +00001025 auto Err = Result.add(tooling::Replacement(
1026 Env.getSourceManager(), Start, Length, ReplacementText));
1027 // FIXME: handle error. For now, print error message and skip the
1028 // replacement for release version.
Piotr Padlewski1ec383c2016-12-23 11:40:44 +00001029 if (Err) {
Eric Liu40ef2fb2016-08-01 10:16:37 +00001030 llvm::errs() << llvm::toString(std::move(Err)) << "\n";
Piotr Padlewski1ec383c2016-12-23 11:40:44 +00001031 assert(false);
1032 }
Daniel Jasper97439922016-03-17 13:03:41 +00001033 };
1034 Replace(Start, 1, IsSingle ? "'" : "\"");
1035 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
1036 IsSingle ? "'" : "\"");
1037
1038 // Escape internal quotes.
Daniel Jasper97439922016-03-17 13:03:41 +00001039 bool Escaped = false;
1040 for (size_t i = 1; i < Input.size() - 1; i++) {
1041 switch (Input[i]) {
Eric Liu4cfb88a2016-04-25 15:09:22 +00001042 case '\\':
1043 if (!Escaped && i + 1 < Input.size() &&
1044 ((IsSingle && Input[i + 1] == '"') ||
1045 (!IsSingle && Input[i + 1] == '\''))) {
1046 // Remove this \, it's escaping a " or ' that no longer needs
1047 // escaping
Eric Liu4cfb88a2016-04-25 15:09:22 +00001048 Replace(Start.getLocWithOffset(i), 1, "");
1049 continue;
1050 }
1051 Escaped = !Escaped;
1052 break;
1053 case '\"':
1054 case '\'':
1055 if (!Escaped && IsSingle == (Input[i] == '\'')) {
1056 // Escape the quote.
1057 Replace(Start.getLocWithOffset(i), 0, "\\");
Eric Liu4cfb88a2016-04-25 15:09:22 +00001058 }
1059 Escaped = false;
1060 break;
1061 default:
1062 Escaped = false;
1063 break;
Daniel Jasper97439922016-03-17 13:03:41 +00001064 }
1065 }
Daniel Jasper97439922016-03-17 13:03:41 +00001066 }
1067 }
1068 }
Daniel Jasper496c1992016-09-07 22:48:53 +00001069};
1070
1071class Formatter : public TokenAnalyzer {
1072public:
1073 Formatter(const Environment &Env, const FormatStyle &Style,
Krasimir Georgievbcda54b2017-04-21 14:35:20 +00001074 FormattingAttemptStatus *Status)
1075 : TokenAnalyzer(Env, Style), Status(Status) {}
Daniel Jasper496c1992016-09-07 22:48:53 +00001076
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00001077 std::pair<tooling::Replacements, unsigned>
Daniel Jasper496c1992016-09-07 22:48:53 +00001078 analyze(TokenAnnotator &Annotator,
1079 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1080 FormatTokenLexer &Tokens) override {
1081 tooling::Replacements Result;
1082 deriveLocalStyle(AnnotatedLines);
1083 AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
1084 AnnotatedLines.end());
1085 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
1086 Annotator.calculateFormattingInformation(*AnnotatedLines[i]);
1087 }
1088 Annotator.setCommentLineLevels(AnnotatedLines);
1089
1090 WhitespaceManager Whitespaces(
1091 Env.getSourceManager(), Style,
1092 inputUsesCRLF(Env.getSourceManager().getBufferData(Env.getFileID())));
1093 ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
1094 Env.getSourceManager(), Whitespaces, Encoding,
1095 BinPackInconclusiveFunctions);
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00001096 unsigned Penalty =
1097 UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,
1098 Tokens.getKeywords(), Env.getSourceManager(),
1099 Status)
1100 .format(AnnotatedLines, /*DryRun=*/false,
1101 /*AdditionalIndent=*/0,
1102 /*FixBadIndentation=*/false,
1103 /*FirstStartColumn=*/Env.getFirstStartColumn(),
1104 /*NextStartColumn=*/Env.getNextStartColumn(),
1105 /*LastStartColumn=*/Env.getLastStartColumn());
Daniel Jasper496c1992016-09-07 22:48:53 +00001106 for (const auto &R : Whitespaces.generateReplacements())
1107 if (Result.add(R))
Krasimir Georgieve56e9a42017-10-30 14:30:14 +00001108 return std::make_pair(Result, 0);
1109 return std::make_pair(Result, Penalty);
Daniel Jasper496c1992016-09-07 22:48:53 +00001110 }
1111
1112private:
Alexander Kornienko9e649af2013-09-11 12:25:57 +00001113 static bool inputUsesCRLF(StringRef Text) {
1114 return Text.count('\r') * 2 > Text.count('\n');
1115 }
1116
Daniel Jasper352f0df2015-07-18 16:35:30 +00001117 bool
1118 hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) {
Eric Liu4cfb88a2016-04-25 15:09:22 +00001119 for (const AnnotatedLine *Line : Lines) {
Daniel Jasper352f0df2015-07-18 16:35:30 +00001120 if (hasCpp03IncompatibleFormat(Line->Children))
1121 return true;
1122 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {
1123 if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) {
1124 if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
1125 return true;
1126 if (Tok->is(TT_TemplateCloser) &&
1127 Tok->Previous->is(TT_TemplateCloser))
1128 return true;
1129 }
1130 }
1131 }
1132 return false;
1133 }
1134
1135 int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) {
1136 int AlignmentDiff = 0;
Eric Liu4cfb88a2016-04-25 15:09:22 +00001137 for (const AnnotatedLine *Line : Lines) {
Daniel Jasper352f0df2015-07-18 16:35:30 +00001138 AlignmentDiff += countVariableAlignments(Line->Children);
1139 for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {
1140 if (!Tok->is(TT_PointerOrReference))
1141 continue;
1142 bool SpaceBefore =
1143 Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd();
1144 bool SpaceAfter = Tok->Next->WhitespaceRange.getBegin() !=
1145 Tok->Next->WhitespaceRange.getEnd();
1146 if (SpaceBefore && !SpaceAfter)
1147 ++AlignmentDiff;
1148 if (!SpaceBefore && SpaceAfter)
1149 --AlignmentDiff;
1150 }
1151 }
1152 return AlignmentDiff;
1153 }
1154
Manuel Klimek71814b42013-10-11 21:25:45 +00001155 void
1156 deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
Daniel Jasperb10cbc42013-07-10 14:02:49 +00001157 bool HasBinPackedFunction = false;
1158 bool HasOnePerLineFunction = false;
Daniel Jasper7fce3ab2013-02-06 14:22:40 +00001159 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +00001160 if (!AnnotatedLines[i]->First->Next)
Daniel Jasper7fce3ab2013-02-06 14:22:40 +00001161 continue;
Daniel Jasper9fe0e8d2013-09-05 09:29:45 +00001162 FormatToken *Tok = AnnotatedLines[i]->First->Next;
Manuel Klimek6e6310e2013-05-29 14:47:47 +00001163 while (Tok->Next) {
Daniel Jasperb10cbc42013-07-10 14:02:49 +00001164 if (Tok->PackingKind == PPK_BinPacked)
1165 HasBinPackedFunction = true;
1166 if (Tok->PackingKind == PPK_OnePerLine)
1167 HasOnePerLineFunction = true;
1168
Manuel Klimek6e6310e2013-05-29 14:47:47 +00001169 Tok = Tok->Next;
Daniel Jasper7fce3ab2013-02-06 14:22:40 +00001170 }
1171 }
Eric Liu635423e2016-04-28 07:52:03 +00001172 if (Style.DerivePointerAlignment)
1173 Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0
1174 ? FormatStyle::PAS_Left
1175 : FormatStyle::PAS_Right;
1176 if (Style.Standard == FormatStyle::LS_Auto)
1177 Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
1178 ? FormatStyle::LS_Cpp11
1179 : FormatStyle::LS_Cpp03;
Daniel Jasperb10cbc42013-07-10 14:02:49 +00001180 BinPackInconclusiveFunctions =
1181 HasBinPackedFunction || !HasOnePerLineFunction;
Daniel Jasper7fce3ab2013-02-06 14:22:40 +00001182 }
1183
Daniel Jasperb10cbc42013-07-10 14:02:49 +00001184 bool BinPackInconclusiveFunctions;
Krasimir Georgievbcda54b2017-04-21 14:35:20 +00001185 FormattingAttemptStatus *Status;
Eric Liu4cfb88a2016-04-25 15:09:22 +00001186};
1187
1188// This class clean up the erroneous/redundant code around the given ranges in
1189// file.
1190class Cleaner : public TokenAnalyzer {
1191public:
Eric Liu635423e2016-04-28 07:52:03 +00001192 Cleaner(const Environment &Env, const FormatStyle &Style)
1193 : TokenAnalyzer(Env, Style),
Eric Liu4cfb88a2016-04-25 15:09:22 +00001194 DeletedTokens(FormatTokenLess(Env.getSourceManager())) {}
1195
1196 // FIXME: eliminate unused parameters.
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00001197 std::pair<tooling::Replacements, unsigned>
Eric Liu4cfb88a2016-04-25 15:09:22 +00001198 analyze(TokenAnnotator &Annotator,
1199 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
Martin Probsta9855af2016-09-02 14:29:48 +00001200 FormatTokenLexer &Tokens) override {
Eric Liu4cfb88a2016-04-25 15:09:22 +00001201 // FIXME: in the current implementation the granularity of affected range
1202 // is an annotated line. However, this is not sufficient. Furthermore,
1203 // redundant code introduced by replacements does not necessarily
1204 // intercept with ranges of replacements that result in the redundancy.
1205 // To determine if some redundant code is actually introduced by
1206 // replacements(e.g. deletions), we need to come up with a more
1207 // sophisticated way of computing affected ranges.
1208 AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
1209 AnnotatedLines.end());
1210
1211 checkEmptyNamespace(AnnotatedLines);
1212
Eric Liuce5e4bc2016-05-18 08:02:56 +00001213 for (auto &Line : AnnotatedLines) {
1214 if (Line->Affected) {
1215 cleanupRight(Line->First, tok::comma, tok::comma);
1216 cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
Eric Liu2574d152016-09-13 15:02:43 +00001217 cleanupRight(Line->First, tok::l_paren, tok::comma);
1218 cleanupLeft(Line->First, tok::comma, tok::r_paren);
Eric Liuce5e4bc2016-05-18 08:02:56 +00001219 cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
1220 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
Malcolm Parsons5d8cdb82016-10-20 14:58:45 +00001221 cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
Eric Liuce5e4bc2016-05-18 08:02:56 +00001222 }
1223 }
1224
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00001225 return {generateFixes(), 0};
Eric Liu4cfb88a2016-04-25 15:09:22 +00001226 }
1227
1228private:
1229 bool containsOnlyComments(const AnnotatedLine &Line) {
1230 for (FormatToken *Tok = Line.First; Tok != nullptr; Tok = Tok->Next) {
1231 if (Tok->isNot(tok::comment))
1232 return false;
1233 }
1234 return true;
1235 }
1236
1237 // Iterate through all lines and remove any empty (nested) namespaces.
1238 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
Eric Liu7956c402016-10-05 15:49:01 +00001239 std::set<unsigned> DeletedLines;
Eric Liu4cfb88a2016-04-25 15:09:22 +00001240 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
1241 auto &Line = *AnnotatedLines[i];
1242 if (Line.startsWith(tok::kw_namespace) ||
1243 Line.startsWith(tok::kw_inline, tok::kw_namespace)) {
Eric Liu7956c402016-10-05 15:49:01 +00001244 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
Eric Liu4cfb88a2016-04-25 15:09:22 +00001245 }
1246 }
1247
1248 for (auto Line : DeletedLines) {
1249 FormatToken *Tok = AnnotatedLines[Line]->First;
1250 while (Tok) {
1251 deleteToken(Tok);
1252 Tok = Tok->Next;
1253 }
1254 }
1255 }
1256
1257 // The function checks if the namespace, which starts from \p CurrentLine, and
1258 // its nested namespaces are empty and delete them if they are empty. It also
1259 // sets \p NewLine to the last line checked.
1260 // Returns true if the current namespace is empty.
1261 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
Eric Liu7956c402016-10-05 15:49:01 +00001262 unsigned CurrentLine, unsigned &NewLine,
1263 std::set<unsigned> &DeletedLines) {
Eric Liu4cfb88a2016-04-25 15:09:22 +00001264 unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
Eric Liu635423e2016-04-28 07:52:03 +00001265 if (Style.BraceWrapping.AfterNamespace) {
Eric Liu4cfb88a2016-04-25 15:09:22 +00001266 // If the left brace is in a new line, we should consume it first so that
1267 // it does not make the namespace non-empty.
1268 // FIXME: error handling if there is no left brace.
1269 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
1270 NewLine = CurrentLine;
1271 return false;
1272 }
1273 } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
1274 return false;
1275 }
1276 while (++CurrentLine < End) {
1277 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
1278 break;
1279
1280 if (AnnotatedLines[CurrentLine]->startsWith(tok::kw_namespace) ||
1281 AnnotatedLines[CurrentLine]->startsWith(tok::kw_inline,
1282 tok::kw_namespace)) {
Eric Liu7956c402016-10-05 15:49:01 +00001283 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
1284 DeletedLines))
Eric Liu4cfb88a2016-04-25 15:09:22 +00001285 return false;
1286 CurrentLine = NewLine;
1287 continue;
1288 }
1289
1290 if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
1291 continue;
1292
1293 // If there is anything other than comments or nested namespaces in the
1294 // current namespace, the namespace cannot be empty.
1295 NewLine = CurrentLine;
1296 return false;
1297 }
1298
1299 NewLine = CurrentLine;
1300 if (CurrentLine >= End)
1301 return false;
1302
1303 // Check if the empty namespace is actually affected by changed ranges.
1304 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
1305 AnnotatedLines[InitLine]->First->Tok.getLocation(),
1306 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc())))
1307 return false;
1308
1309 for (unsigned i = InitLine; i <= CurrentLine; ++i) {
1310 DeletedLines.insert(i);
1311 }
1312
1313 return true;
1314 }
1315
Eric Liuce5e4bc2016-05-18 08:02:56 +00001316 // Checks pairs {start, start->next},..., {end->previous, end} and deletes one
1317 // of the token in the pair if the left token has \p LK token kind and the
1318 // right token has \p RK token kind. If \p DeleteLeft is true, the left token
1319 // is deleted on match; otherwise, the right token is deleted.
1320 template <typename LeftKind, typename RightKind>
1321 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
1322 bool DeleteLeft) {
1323 auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {
1324 for (auto *Res = Tok.Next; Res; Res = Res->Next)
1325 if (!Res->is(tok::comment) &&
1326 DeletedTokens.find(Res) == DeletedTokens.end())
1327 return Res;
1328 return nullptr;
1329 };
1330 for (auto *Left = Start; Left;) {
1331 auto *Right = NextNotDeleted(*Left);
1332 if (!Right)
1333 break;
1334 if (Left->is(LK) && Right->is(RK)) {
1335 deleteToken(DeleteLeft ? Left : Right);
Eric Liu01426ff2016-09-09 17:50:49 +00001336 for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
1337 deleteToken(Tok);
Eric Liuce5e4bc2016-05-18 08:02:56 +00001338 // If the right token is deleted, we should keep the left token
1339 // unchanged and pair it with the new right token.
1340 if (!DeleteLeft)
1341 continue;
1342 }
1343 Left = Right;
1344 }
1345 }
1346
1347 template <typename LeftKind, typename RightKind>
1348 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
1349 cleanupPair(Start, LK, RK, /*DeleteLeft=*/true);
1350 }
1351
1352 template <typename LeftKind, typename RightKind>
1353 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
1354 cleanupPair(Start, LK, RK, /*DeleteLeft=*/false);
1355 }
1356
Eric Liu4cfb88a2016-04-25 15:09:22 +00001357 // Delete the given token.
1358 inline void deleteToken(FormatToken *Tok) {
1359 if (Tok)
1360 DeletedTokens.insert(Tok);
1361 }
1362
1363 tooling::Replacements generateFixes() {
1364 tooling::Replacements Fixes;
1365 std::vector<FormatToken *> Tokens;
1366 std::copy(DeletedTokens.begin(), DeletedTokens.end(),
1367 std::back_inserter(Tokens));
1368
1369 // Merge multiple continuous token deletions into one big deletion so that
1370 // the number of replacements can be reduced. This makes computing affected
1371 // ranges more efficient when we run reformat on the changed code.
1372 unsigned Idx = 0;
1373 while (Idx < Tokens.size()) {
1374 unsigned St = Idx, End = Idx;
1375 while ((End + 1) < Tokens.size() &&
1376 Tokens[End]->Next == Tokens[End + 1]) {
1377 End++;
1378 }
1379 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
1380 Tokens[End]->Tok.getEndLoc());
Eric Liu40ef2fb2016-08-01 10:16:37 +00001381 auto Err =
1382 Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, ""));
1383 // FIXME: better error handling. for now just print error message and skip
1384 // for the release version.
Piotr Padlewski1ec383c2016-12-23 11:40:44 +00001385 if (Err) {
Eric Liu40ef2fb2016-08-01 10:16:37 +00001386 llvm::errs() << llvm::toString(std::move(Err)) << "\n";
Piotr Padlewski1ec383c2016-12-23 11:40:44 +00001387 assert(false && "Fixes must not conflict!");
1388 }
Eric Liu4cfb88a2016-04-25 15:09:22 +00001389 Idx = End + 1;
1390 }
1391
1392 return Fixes;
1393 }
1394
1395 // Class for less-than inequality comparason for the set `RedundantTokens`.
1396 // We store tokens in the order they appear in the translation unit so that
1397 // we do not need to sort them in `generateFixes()`.
1398 struct FormatTokenLess {
Eric Liu635423e2016-04-28 07:52:03 +00001399 FormatTokenLess(const SourceManager &SM) : SM(SM) {}
Eric Liu4cfb88a2016-04-25 15:09:22 +00001400
Eric Liu2874ac32016-05-18 08:14:49 +00001401 bool operator()(const FormatToken *LHS, const FormatToken *RHS) const {
Eric Liu4cfb88a2016-04-25 15:09:22 +00001402 return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
1403 RHS->Tok.getLocation());
1404 }
Eric Liu635423e2016-04-28 07:52:03 +00001405 const SourceManager &SM;
Eric Liu4cfb88a2016-04-25 15:09:22 +00001406 };
1407
1408 // Tokens to be deleted.
1409 std::set<FormatToken *, FormatTokenLess> DeletedTokens;
Daniel Jasperf7935112012-12-03 18:12:45 +00001410};
1411
Ben Hamiltone2e3e672018-01-17 17:33:08 +00001412class ObjCHeaderStyleGuesser : public TokenAnalyzer {
1413public:
1414 ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style)
1415 : TokenAnalyzer(Env, Style), IsObjC(false) {}
1416
1417 std::pair<tooling::Replacements, unsigned>
1418 analyze(TokenAnnotator &Annotator,
1419 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1420 FormatTokenLexer &Tokens) override {
1421 assert(Style.Language == FormatStyle::LK_Cpp);
1422 IsObjC = guessIsObjC(AnnotatedLines, Tokens.getKeywords());
1423 tooling::Replacements Result;
1424 return {Result, 0};
1425 }
1426
1427 bool isObjC() { return IsObjC; }
1428
1429private:
1430 static bool guessIsObjC(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1431 const AdditionalKeywords &Keywords) {
Krasimir Georgiev8e216782018-01-17 20:01:02 +00001432 // Keep this array sorted, since we are binary searching over it.
1433 static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
Ben Hamiltone2e3e672018-01-17 17:33:08 +00001434 "CGFloat",
1435 "NSAffineTransform",
1436 "NSArray",
1437 "NSAttributedString",
1438 "NSCache",
1439 "NSCharacterSet",
1440 "NSCountedSet",
1441 "NSData",
1442 "NSDataDetector",
1443 "NSDecimal",
1444 "NSDecimalNumber",
1445 "NSDictionary",
1446 "NSEdgeInsets",
1447 "NSHashTable",
1448 "NSIndexPath",
1449 "NSIndexSet",
1450 "NSInteger",
1451 "NSLocale",
1452 "NSMapTable",
1453 "NSMutableArray",
1454 "NSMutableAttributedString",
1455 "NSMutableCharacterSet",
1456 "NSMutableData",
1457 "NSMutableDictionary",
1458 "NSMutableIndexSet",
1459 "NSMutableOrderedSet",
1460 "NSMutableSet",
1461 "NSMutableString",
1462 "NSNumber",
1463 "NSNumberFormatter",
1464 "NSOrderedSet",
1465 "NSPoint",
1466 "NSPointerArray",
1467 "NSRange",
1468 "NSRect",
1469 "NSRegularExpression",
1470 "NSSet",
1471 "NSSize",
1472 "NSString",
1473 "NSUInteger",
1474 "NSURL",
1475 "NSURLComponents",
1476 "NSURLQueryItem",
1477 "NSUUID",
1478 };
1479
1480 for (auto &Line : AnnotatedLines) {
1481 for (FormatToken *FormatTok = Line->First->Next; FormatTok;
1482 FormatTok = FormatTok->Next) {
1483 if ((FormatTok->Previous->is(tok::at) &&
1484 (FormatTok->isObjCAtKeyword(tok::objc_interface) ||
1485 FormatTok->isObjCAtKeyword(tok::objc_implementation) ||
1486 FormatTok->isObjCAtKeyword(tok::objc_protocol) ||
1487 FormatTok->isObjCAtKeyword(tok::objc_end) ||
1488 FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
1489 tok::l_brace))) ||
1490 (FormatTok->Tok.isAnyIdentifier() &&
Krasimir Georgiev8e216782018-01-17 20:01:02 +00001491 std::binary_search(std::begin(FoundationIdentifiers),
1492 std::end(FoundationIdentifiers),
1493 FormatTok->TokenText)) ||
Ben Hamiltone2e3e672018-01-17 17:33:08 +00001494 FormatTok->is(TT_ObjCStringLiteral) ||
1495 FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,
1496 TT_ObjCBlockLBrace, TT_ObjCBlockLParen,
1497 TT_ObjCDecl, TT_ObjCForIn, TT_ObjCMethodExpr,
1498 TT_ObjCMethodSpecifier, TT_ObjCProperty)) {
1499 return true;
1500 }
1501 }
1502 }
1503 return false;
1504 }
1505
1506 bool IsObjC;
1507};
1508
Daniel Jasperd89ae9d2015-09-23 08:30:47 +00001509struct IncludeDirective {
1510 StringRef Filename;
1511 StringRef Text;
1512 unsigned Offset;
Daniel Jasperd2629dc2015-12-16 10:10:16 +00001513 int Category;
Daniel Jasperd89ae9d2015-09-23 08:30:47 +00001514};
1515
Craig Topperaf35e852013-06-30 22:29:28 +00001516} // end anonymous namespace
1517
Daniel Jasperd89ae9d2015-09-23 08:30:47 +00001518// Determines whether 'Ranges' intersects with ('Start', 'End').
1519static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start,
1520 unsigned End) {
1521 for (auto Range : Ranges) {
1522 if (Range.getOffset() < End &&
1523 Range.getOffset() + Range.getLength() > Start)
1524 return true;
1525 }
1526 return false;
1527}
1528
Eric Liua992afe2016-08-10 09:32:23 +00001529// Returns a pair (Index, OffsetToEOL) describing the position of the cursor
1530// before sorting/deduplicating. Index is the index of the include under the
1531// cursor in the original set of includes. If this include has duplicates, it is
1532// the index of the first of the duplicates as the others are going to be
1533// removed. OffsetToEOL describes the cursor's position relative to the end of
1534// its current line.
1535// If `Cursor` is not on any #include, `Index` will be UINT_MAX.
1536static std::pair<unsigned, unsigned>
1537FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes,
1538 const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) {
1539 unsigned CursorIndex = UINT_MAX;
1540 unsigned OffsetToEOL = 0;
1541 for (int i = 0, e = Includes.size(); i != e; ++i) {
1542 unsigned Start = Includes[Indices[i]].Offset;
1543 unsigned End = Start + Includes[Indices[i]].Text.size();
1544 if (!(Cursor >= Start && Cursor < End))
1545 continue;
1546 CursorIndex = Indices[i];
1547 OffsetToEOL = End - Cursor;
1548 // Put the cursor on the only remaining #include among the duplicate
1549 // #includes.
1550 while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text)
1551 CursorIndex = i;
1552 break;
1553 }
1554 return std::make_pair(CursorIndex, OffsetToEOL);
1555}
1556
1557// Sorts and deduplicate a block of includes given by 'Includes' alphabetically
1558// adding the necessary replacement to 'Replaces'. 'Includes' must be in strict
1559// source order.
1560// #include directives with the same text will be deduplicated, and only the
1561// first #include in the duplicate #includes remains. If the `Cursor` is
1562// provided and put on a deleted #include, it will be moved to the remaining
1563// #include in the duplicate #includes.
Martin Probstc4a0dd42016-05-20 11:24:24 +00001564static void sortCppIncludes(const FormatStyle &Style,
Eric Liua992afe2016-08-10 09:32:23 +00001565 const SmallVectorImpl<IncludeDirective> &Includes,
1566 ArrayRef<tooling::Range> Ranges, StringRef FileName,
1567 tooling::Replacements &Replaces, unsigned *Cursor) {
1568 unsigned IncludesBeginOffset = Includes.front().Offset;
Daniel Jasperd6a00782016-08-30 21:33:41 +00001569 unsigned IncludesEndOffset =
1570 Includes.back().Offset + Includes.back().Text.size();
1571 unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
1572 if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
Daniel Jasperd89ae9d2015-09-23 08:30:47 +00001573 return;
1574 SmallVector<unsigned, 16> Indices;
1575 for (unsigned i = 0, e = Includes.size(); i != e; ++i)
1576 Indices.push_back(i);
Daniel Jasper94a96fc2016-03-03 17:34:14 +00001577 std::stable_sort(
1578 Indices.begin(), Indices.end(), [&](unsigned LHSI, unsigned RHSI) {
1579 return std::tie(Includes[LHSI].Category, Includes[LHSI].Filename) <
1580 std::tie(Includes[RHSI].Category, Includes[RHSI].Filename);
1581 });
Eric Liua992afe2016-08-10 09:32:23 +00001582 // The index of the include on which the cursor will be put after
1583 // sorting/deduplicating.
1584 unsigned CursorIndex;
1585 // The offset from cursor to the end of line.
1586 unsigned CursorToEOLOffset;
1587 if (Cursor)
1588 std::tie(CursorIndex, CursorToEOLOffset) =
1589 FindCursorIndex(Includes, Indices, *Cursor);
1590
1591 // Deduplicate #includes.
1592 Indices.erase(std::unique(Indices.begin(), Indices.end(),
1593 [&](unsigned LHSI, unsigned RHSI) {
1594 return Includes[LHSI].Text == Includes[RHSI].Text;
1595 }),
1596 Indices.end());
Daniel Jasperd89ae9d2015-09-23 08:30:47 +00001597
Krasimir Georgiev4c2c9c32017-11-27 13:23:45 +00001598 int CurrentCategory = Includes.front().Category;
1599
Daniel Jasperd89ae9d2015-09-23 08:30:47 +00001600 // If the #includes are out of order, we generate a single replacement fixing
1601 // the entire block. Otherwise, no replacement is generated.
Eric Liua992afe2016-08-10 09:32:23 +00001602 if (Indices.size() == Includes.size() &&
Krasimir Georgiev4c2c9c32017-11-27 13:23:45 +00001603 std::is_sorted(Indices.begin(), Indices.end()) &&
1604 Style.IncludeBlocks == FormatStyle::IBS_Preserve)
Daniel Jasperd89ae9d2015-09-23 08:30:47 +00001605 return;
1606
Daniel Jasperb68aabf2015-11-23 08:36:35 +00001607 std::string result;
Daniel Jasperb68aabf2015-11-23 08:36:35 +00001608 for (unsigned Index : Indices) {
Krasimir Georgiev4c2c9c32017-11-27 13:23:45 +00001609 if (!result.empty()) {
Daniel Jasperb68aabf2015-11-23 08:36:35 +00001610 result += "\n";
Krasimir Georgiev4c2c9c32017-11-27 13:23:45 +00001611 if (Style.IncludeBlocks == FormatStyle::IBS_Regroup &&
1612 CurrentCategory != Includes[Index].Category)
1613 result += "\n";
1614 }
Daniel Jasperb68aabf2015-11-23 08:36:35 +00001615 result += Includes[Index].Text;
Eric Liua992afe2016-08-10 09:32:23 +00001616 if (Cursor && CursorIndex == Index)
1617 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
Krasimir Georgiev4c2c9c32017-11-27 13:23:45 +00001618 CurrentCategory = Includes[Index].Category;
Daniel Jasperd89ae9d2015-09-23 08:30:47 +00001619 }
1620
Eric Liu40ef2fb2016-08-01 10:16:37 +00001621 auto Err = Replaces.add(tooling::Replacement(
Eric Liua992afe2016-08-10 09:32:23 +00001622 FileName, Includes.front().Offset, IncludesBlockSize, result));
Eric Liu40ef2fb2016-08-01 10:16:37 +00001623 // FIXME: better error handling. For now, just skip the replacement for the
1624 // release version.
Piotr Padlewski1ec383c2016-12-23 11:40:44 +00001625 if (Err) {
Eric Liu40ef2fb2016-08-01 10:16:37 +00001626 llvm::errs() << llvm::toString(std::move(Err)) << "\n";
Piotr Padlewski1ec383c2016-12-23 11:40:44 +00001627 assert(false);
1628 }
Daniel Jasperd89ae9d2015-09-23 08:30:47 +00001629}
1630
Eric Liu659afd52016-05-31 13:34:20 +00001631namespace {
1632
1633// This class manages priorities of #include categories and calculates
1634// priorities for headers.
1635class IncludeCategoryManager {
1636public:
1637 IncludeCategoryManager(const FormatStyle &Style, StringRef FileName)
1638 : Style(Style), FileName(FileName) {
1639 FileStem = llvm::sys::path::stem(FileName);
1640 for (const auto &Category : Style.IncludeCategories)
Chandler Carruthd676ab12017-06-29 23:20:54 +00001641 CategoryRegexs.emplace_back(Category.Regex, llvm::Regex::IgnoreCase);
Eric Liu659afd52016-05-31 13:34:20 +00001642 IsMainFile = FileName.endswith(".c") || FileName.endswith(".cc") ||
1643 FileName.endswith(".cpp") || FileName.endswith(".c++") ||
1644 FileName.endswith(".cxx") || FileName.endswith(".m") ||
1645 FileName.endswith(".mm");
1646 }
1647
1648 // Returns the priority of the category which \p IncludeName belongs to.
1649 // If \p CheckMainHeader is true and \p IncludeName is a main header, returns
1650 // 0. Otherwise, returns the priority of the matching category or INT_MAX.
1651 int getIncludePriority(StringRef IncludeName, bool CheckMainHeader) {
1652 int Ret = INT_MAX;
1653 for (unsigned i = 0, e = CategoryRegexs.size(); i != e; ++i)
1654 if (CategoryRegexs[i].match(IncludeName)) {
1655 Ret = Style.IncludeCategories[i].Priority;
1656 break;
1657 }
1658 if (CheckMainHeader && IsMainFile && Ret > 0 && isMainHeader(IncludeName))
1659 Ret = 0;
1660 return Ret;
1661 }
1662
1663private:
1664 bool isMainHeader(StringRef IncludeName) const {
1665 if (!IncludeName.startswith("\""))
1666 return false;
1667 StringRef HeaderStem =
1668 llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(1));
Chandler Carruthd676ab12017-06-29 23:20:54 +00001669 if (FileStem.startswith(HeaderStem) ||
1670 FileStem.startswith_lower(HeaderStem)) {
Eric Liu659afd52016-05-31 13:34:20 +00001671 llvm::Regex MainIncludeRegex(
Chandler Carruthd676ab12017-06-29 23:20:54 +00001672 (HeaderStem + Style.IncludeIsMainRegex).str(),
1673 llvm::Regex::IgnoreCase);
Eric Liu659afd52016-05-31 13:34:20 +00001674 if (MainIncludeRegex.match(FileStem))
1675 return true;
1676 }
1677 return false;
1678 }
1679
1680 const FormatStyle &Style;
1681 bool IsMainFile;
1682 StringRef FileName;
1683 StringRef FileStem;
1684 SmallVector<llvm::Regex, 4> CategoryRegexs;
1685};
1686
1687const char IncludeRegexPattern[] =
1688 R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))";
1689
1690} // anonymous namespace
1691
Martin Probstc4a0dd42016-05-20 11:24:24 +00001692tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
1693 ArrayRef<tooling::Range> Ranges,
1694 StringRef FileName,
1695 tooling::Replacements &Replaces,
1696 unsigned *Cursor) {
Daniel Jasperd89ae9d2015-09-23 08:30:47 +00001697 unsigned Prev = 0;
1698 unsigned SearchFrom = 0;
Eric Liu659afd52016-05-31 13:34:20 +00001699 llvm::Regex IncludeRegex(IncludeRegexPattern);
Daniel Jasperd89ae9d2015-09-23 08:30:47 +00001700 SmallVector<StringRef, 4> Matches;
1701 SmallVector<IncludeDirective, 16> IncludesInBlock;
Daniel Jasper85c472d2015-09-29 07:53:08 +00001702
1703 // In compiled files, consider the first #include to be the main #include of
1704 // the file if it is not a system #include. This ensures that the header
1705 // doesn't have hidden dependencies
1706 // (http://llvm.org/docs/CodingStandards.html#include-style).
1707 //
1708 // FIXME: Do some sanity checking, e.g. edit distance of the base name, to fix
1709 // cases where the first #include is unlikely to be the main header.
Eric Liu659afd52016-05-31 13:34:20 +00001710 IncludeCategoryManager Categories(Style, FileName);
Daniel Jasper32d75fa2015-12-21 13:40:49 +00001711 bool FirstIncludeBlock = true;
Daniel Jaspera252f5d2015-12-21 17:28:24 +00001712 bool MainIncludeFound = false;
Daniel Jasper9b8c7c72015-11-21 09:17:08 +00001713 bool FormattingOff = false;
1714
Daniel Jasperd89ae9d2015-09-23 08:30:47 +00001715 for (;;) {
1716 auto Pos = Code.find('\n', SearchFrom);
1717 StringRef Line =
1718 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
Daniel Jasper9b8c7c72015-11-21 09:17:08 +00001719
1720 StringRef Trimmed = Line.trim();
1721 if (Trimmed == "// clang-format off")
1722 FormattingOff = true;
1723 else if (Trimmed == "// clang-format on")
1724 FormattingOff = false;
1725
Krasimir Georgiev4c2c9c32017-11-27 13:23:45 +00001726 const bool EmptyLineSkipped =
1727 Trimmed.empty() && (Style.IncludeBlocks == FormatStyle::IBS_Merge ||
1728 Style.IncludeBlocks == FormatStyle::IBS_Regroup);
1729
Daniel Jasper9b8c7c72015-11-21 09:17:08 +00001730 if (!FormattingOff && !Line.endswith("\\")) {
Daniel Jasperd89ae9d2015-09-23 08:30:47 +00001731 if (IncludeRegex.match(Line, &Matches)) {
Nico Weberff063702015-10-21 17:13:45 +00001732 StringRef IncludeName = Matches[2];
Eric Liu659afd52016-05-31 13:34:20 +00001733 int Category = Categories.getIncludePriority(
1734 IncludeName,
1735 /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock);
1736 if (Category == 0)
1737 MainIncludeFound = true;
Nico Weberff063702015-10-21 17:13:45 +00001738 IncludesInBlock.push_back({IncludeName, Line, Prev, Category});
Krasimir Georgiev4c2c9c32017-11-27 13:23:45 +00001739 } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
Martin Probstc4a0dd42016-05-20 11:24:24 +00001740 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces,
1741 Cursor);
Daniel Jasperd89ae9d2015-09-23 08:30:47 +00001742 IncludesInBlock.clear();
Daniel Jasper32d75fa2015-12-21 13:40:49 +00001743 FirstIncludeBlock = false;
Daniel Jasperd89ae9d2015-09-23 08:30:47 +00001744 }
1745 Prev = Pos + 1;
1746 }
1747 if (Pos == StringRef::npos || Pos + 1 == Code.size())
1748 break;
1749 SearchFrom = Pos + 1;
1750 }
1751 if (!IncludesInBlock.empty())
Martin Probstc4a0dd42016-05-20 11:24:24 +00001752 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces, Cursor);
1753 return Replaces;
1754}
1755
Martin Probstfa37b182017-01-27 09:09:11 +00001756bool isMpegTS(StringRef Code) {
1757 // MPEG transport streams use the ".ts" file extension. clang-format should
1758 // not attempt to format those. MPEG TS' frame format starts with 0x47 every
1759 // 189 bytes - detect that and return.
1760 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
1761}
1762
Manuel Klimek89628f62017-09-20 09:51:03 +00001763bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); }
Krasimir Georgieva2e7d0d2017-08-29 13:51:38 +00001764
Martin Probstc4a0dd42016-05-20 11:24:24 +00001765tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
1766 ArrayRef<tooling::Range> Ranges,
1767 StringRef FileName, unsigned *Cursor) {
1768 tooling::Replacements Replaces;
1769 if (!Style.SortIncludes)
1770 return Replaces;
Krasimir Georgiev86873032017-08-29 13:57:31 +00001771 if (isLikelyXml(Code))
1772 return Replaces;
1773 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript &&
1774 isMpegTS(Code))
Martin Probstfa37b182017-01-27 09:09:11 +00001775 return Replaces;
Martin Probstc4a0dd42016-05-20 11:24:24 +00001776 if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript)
1777 return sortJavaScriptImports(Style, Code, Ranges, FileName);
1778 sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor);
Daniel Jasperd89ae9d2015-09-23 08:30:47 +00001779 return Replaces;
1780}
1781
Eric Liu4cfb88a2016-04-25 15:09:22 +00001782template <typename T>
Eric Liu4f8d9942016-07-11 13:53:12 +00001783static llvm::Expected<tooling::Replacements>
Eric Liu4cfb88a2016-04-25 15:09:22 +00001784processReplacements(T ProcessFunc, StringRef Code,
1785 const tooling::Replacements &Replaces,
1786 const FormatStyle &Style) {
Manuel Klimekb12e5a52016-03-01 12:37:30 +00001787 if (Replaces.empty())
1788 return tooling::Replacements();
1789
Eric Liu4f8d9942016-07-11 13:53:12 +00001790 auto NewCode = applyAllReplacements(Code, Replaces);
1791 if (!NewCode)
1792 return NewCode.takeError();
Eric Liu40ef2fb2016-08-01 10:16:37 +00001793 std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();
Manuel Klimekb12e5a52016-03-01 12:37:30 +00001794 StringRef FileName = Replaces.begin()->getFilePath();
Eric Liu4cfb88a2016-04-25 15:09:22 +00001795
Manuel Klimekb12e5a52016-03-01 12:37:30 +00001796 tooling::Replacements FormatReplaces =
Eric Liu4f8d9942016-07-11 13:53:12 +00001797 ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
Manuel Klimekb12e5a52016-03-01 12:37:30 +00001798
Eric Liu40ef2fb2016-08-01 10:16:37 +00001799 return Replaces.merge(FormatReplaces);
Manuel Klimekb12e5a52016-03-01 12:37:30 +00001800}
1801
Eric Liu4f8d9942016-07-11 13:53:12 +00001802llvm::Expected<tooling::Replacements>
1803formatReplacements(StringRef Code, const tooling::Replacements &Replaces,
1804 const FormatStyle &Style) {
Eric Liu4cfb88a2016-04-25 15:09:22 +00001805 // We need to use lambda function here since there are two versions of
Eric Liubaf58c22016-05-18 13:43:48 +00001806 // `sortIncludes`.
1807 auto SortIncludes = [](const FormatStyle &Style, StringRef Code,
1808 std::vector<tooling::Range> Ranges,
1809 StringRef FileName) -> tooling::Replacements {
1810 return sortIncludes(Style, Code, Ranges, FileName);
1811 };
Eric Liu4f8d9942016-07-11 13:53:12 +00001812 auto SortedReplaces =
Eric Liubaf58c22016-05-18 13:43:48 +00001813 processReplacements(SortIncludes, Code, Replaces, Style);
Eric Liu4f8d9942016-07-11 13:53:12 +00001814 if (!SortedReplaces)
1815 return SortedReplaces.takeError();
Eric Liubaf58c22016-05-18 13:43:48 +00001816
1817 // We need to use lambda function here since there are two versions of
Eric Liu4cfb88a2016-04-25 15:09:22 +00001818 // `reformat`.
1819 auto Reformat = [](const FormatStyle &Style, StringRef Code,
1820 std::vector<tooling::Range> Ranges,
1821 StringRef FileName) -> tooling::Replacements {
1822 return reformat(Style, Code, Ranges, FileName);
1823 };
Eric Liu4f8d9942016-07-11 13:53:12 +00001824 return processReplacements(Reformat, Code, *SortedReplaces, Style);
Eric Liu4cfb88a2016-04-25 15:09:22 +00001825}
1826
Eric Liu659afd52016-05-31 13:34:20 +00001827namespace {
1828
1829inline bool isHeaderInsertion(const tooling::Replacement &Replace) {
Eric Liuc0d3a802016-09-23 15:10:56 +00001830 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 &&
Eric Liu659afd52016-05-31 13:34:20 +00001831 llvm::Regex(IncludeRegexPattern).match(Replace.getReplacementText());
1832}
1833
Eric Liuc0d3a802016-09-23 15:10:56 +00001834inline bool isHeaderDeletion(const tooling::Replacement &Replace) {
1835 return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1;
1836}
1837
Eric Liu964782a2016-12-02 11:01:43 +00001838// Returns the offset after skipping a sequence of tokens, matched by \p
1839// GetOffsetAfterSequence, from the start of the code.
1840// \p GetOffsetAfterSequence should be a function that matches a sequence of
1841// tokens and returns an offset after the sequence.
1842unsigned getOffsetAfterTokenSequence(
1843 StringRef FileName, StringRef Code, const FormatStyle &Style,
Krasimir Georgiev317c5392017-03-08 09:13:25 +00001844 llvm::function_ref<unsigned(const SourceManager &, Lexer &, Token &)>
1845 GetOffsetAfterSequence) {
Eric Liu964782a2016-12-02 11:01:43 +00001846 std::unique_ptr<Environment> Env =
1847 Environment::CreateVirtualEnvironment(Code, FileName, /*Ranges=*/{});
1848 const SourceManager &SourceMgr = Env->getSourceManager();
1849 Lexer Lex(Env->getFileID(), SourceMgr.getBuffer(Env->getFileID()), SourceMgr,
1850 getFormattingLangOpts(Style));
1851 Token Tok;
1852 // Get the first token.
1853 Lex.LexFromRawLexer(Tok);
Krasimir Georgiev317c5392017-03-08 09:13:25 +00001854 return GetOffsetAfterSequence(SourceMgr, Lex, Tok);
Eric Liu35288322016-06-06 11:00:13 +00001855}
1856
1857// Check if a sequence of tokens is like "#<Name> <raw_identifier>". If it is,
1858// \p Tok will be the token after this directive; otherwise, it can be any token
1859// after the given \p Tok (including \p Tok).
1860bool checkAndConsumeDirectiveWithName(Lexer &Lex, StringRef Name, Token &Tok) {
1861 bool Matched = Tok.is(tok::hash) && !Lex.LexFromRawLexer(Tok) &&
1862 Tok.is(tok::raw_identifier) &&
1863 Tok.getRawIdentifier() == Name && !Lex.LexFromRawLexer(Tok) &&
Eric Liu93459d32016-12-19 10:41:05 +00001864 Tok.is(tok::raw_identifier);
Eric Liu35288322016-06-06 11:00:13 +00001865 if (Matched)
1866 Lex.LexFromRawLexer(Tok);
1867 return Matched;
1868}
1869
Eric Liu964782a2016-12-02 11:01:43 +00001870void skipComments(Lexer &Lex, Token &Tok) {
1871 while (Tok.is(tok::comment))
1872 if (Lex.LexFromRawLexer(Tok))
1873 return;
1874}
1875
1876// Returns the offset after header guard directives and any comments
1877// before/after header guards. If no header guard presents in the code, this
1878// will returns the offset after skipping all comments from the start of the
1879// code.
Eric Liu35288322016-06-06 11:00:13 +00001880unsigned getOffsetAfterHeaderGuardsAndComments(StringRef FileName,
1881 StringRef Code,
Eric Liu43d67b62016-06-11 11:45:08 +00001882 const FormatStyle &Style) {
Eric Liu964782a2016-12-02 11:01:43 +00001883 return getOffsetAfterTokenSequence(
1884 FileName, Code, Style,
1885 [](const SourceManager &SM, Lexer &Lex, Token Tok) {
1886 skipComments(Lex, Tok);
1887 unsigned InitialOffset = SM.getFileOffset(Tok.getLocation());
1888 if (checkAndConsumeDirectiveWithName(Lex, "ifndef", Tok)) {
1889 skipComments(Lex, Tok);
1890 if (checkAndConsumeDirectiveWithName(Lex, "define", Tok))
1891 return SM.getFileOffset(Tok.getLocation());
1892 }
1893 return InitialOffset;
1894 });
1895}
1896
1897// Check if a sequence of tokens is like
1898// "#include ("header.h" | <header.h>)".
1899// If it is, \p Tok will be the token after this directive; otherwise, it can be
1900// any token after the given \p Tok (including \p Tok).
1901bool checkAndConsumeInclusiveDirective(Lexer &Lex, Token &Tok) {
1902 auto Matched = [&]() {
1903 Lex.LexFromRawLexer(Tok);
1904 return true;
1905 };
1906 if (Tok.is(tok::hash) && !Lex.LexFromRawLexer(Tok) &&
1907 Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == "include") {
1908 if (Lex.LexFromRawLexer(Tok))
1909 return false;
1910 if (Tok.is(tok::string_literal))
1911 return Matched();
1912 if (Tok.is(tok::less)) {
1913 while (!Lex.LexFromRawLexer(Tok) && Tok.isNot(tok::greater)) {
1914 }
1915 if (Tok.is(tok::greater))
1916 return Matched();
1917 }
Eric Liu35288322016-06-06 11:00:13 +00001918 }
Eric Liu964782a2016-12-02 11:01:43 +00001919 return false;
1920}
1921
1922// Returns the offset of the last #include directive after which a new
1923// #include can be inserted. This ignores #include's after the #include block(s)
1924// in the beginning of a file to avoid inserting headers into code sections
1925// where new #include's should not be added by default.
1926// These code sections include:
1927// - raw string literals (containing #include).
1928// - #if blocks.
1929// - Special #include's among declarations (e.g. functions).
1930//
1931// If no #include after which a new #include can be inserted, this returns the
1932// offset after skipping all comments from the start of the code.
1933// Inserting after an #include is not allowed if it comes after code that is not
1934// #include (e.g. pre-processing directive that is not #include, declarations).
1935unsigned getMaxHeaderInsertionOffset(StringRef FileName, StringRef Code,
1936 const FormatStyle &Style) {
1937 return getOffsetAfterTokenSequence(
1938 FileName, Code, Style,
1939 [](const SourceManager &SM, Lexer &Lex, Token Tok) {
1940 skipComments(Lex, Tok);
1941 unsigned MaxOffset = SM.getFileOffset(Tok.getLocation());
1942 while (checkAndConsumeInclusiveDirective(Lex, Tok))
1943 MaxOffset = SM.getFileOffset(Tok.getLocation());
1944 return MaxOffset;
1945 });
Eric Liu35288322016-06-06 11:00:13 +00001946}
1947
Eric Liuc0d3a802016-09-23 15:10:56 +00001948bool isDeletedHeader(llvm::StringRef HeaderName,
Benjamin Kramerebac56e2016-11-24 15:42:29 +00001949 const std::set<llvm::StringRef> &HeadersToDelete) {
1950 return HeadersToDelete.count(HeaderName) ||
1951 HeadersToDelete.count(HeaderName.trim("\"<>"));
Eric Liuc0d3a802016-09-23 15:10:56 +00001952}
1953
Eric Liu659afd52016-05-31 13:34:20 +00001954// FIXME: insert empty lines between newly created blocks.
1955tooling::Replacements
1956fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
1957 const FormatStyle &Style) {
Daniel Jasper1dbc2102017-03-31 13:30:24 +00001958 if (!Style.isCpp())
Eric Liu659afd52016-05-31 13:34:20 +00001959 return Replaces;
1960
1961 tooling::Replacements HeaderInsertions;
Eric Liuc0d3a802016-09-23 15:10:56 +00001962 std::set<llvm::StringRef> HeadersToDelete;
Eric Liu40ef2fb2016-08-01 10:16:37 +00001963 tooling::Replacements Result;
Eric Liu659afd52016-05-31 13:34:20 +00001964 for (const auto &R : Replaces) {
Eric Liu40ef2fb2016-08-01 10:16:37 +00001965 if (isHeaderInsertion(R)) {
1966 // Replacements from \p Replaces must be conflict-free already, so we can
1967 // simply consume the error.
1968 llvm::consumeError(HeaderInsertions.add(R));
Eric Liuc0d3a802016-09-23 15:10:56 +00001969 } else if (isHeaderDeletion(R)) {
1970 HeadersToDelete.insert(R.getReplacementText());
Eric Liu40ef2fb2016-08-01 10:16:37 +00001971 } else if (R.getOffset() == UINT_MAX) {
Eric Liu659afd52016-05-31 13:34:20 +00001972 llvm::errs() << "Insertions other than header #include insertion are "
1973 "not supported! "
1974 << R.getReplacementText() << "\n";
Eric Liu40ef2fb2016-08-01 10:16:37 +00001975 } else {
1976 llvm::consumeError(Result.add(R));
1977 }
Eric Liu659afd52016-05-31 13:34:20 +00001978 }
Eric Liuc0d3a802016-09-23 15:10:56 +00001979 if (HeaderInsertions.empty() && HeadersToDelete.empty())
Eric Liu659afd52016-05-31 13:34:20 +00001980 return Replaces;
Eric Liu659afd52016-05-31 13:34:20 +00001981
1982 llvm::Regex IncludeRegex(IncludeRegexPattern);
1983 llvm::Regex DefineRegex(R"(^[\t\ ]*#[\t\ ]*define[\t\ ]*[^\\]*$)");
1984 SmallVector<StringRef, 4> Matches;
1985
1986 StringRef FileName = Replaces.begin()->getFilePath();
1987 IncludeCategoryManager Categories(Style, FileName);
1988
1989 // Record the offset of the end of the last include in each category.
1990 std::map<int, int> CategoryEndOffsets;
1991 // All possible priorities.
1992 // Add 0 for main header and INT_MAX for headers that are not in any category.
1993 std::set<int> Priorities = {0, INT_MAX};
1994 for (const auto &Category : Style.IncludeCategories)
1995 Priorities.insert(Category.Priority);
1996 int FirstIncludeOffset = -1;
Eric Liu35288322016-06-06 11:00:13 +00001997 // All new headers should be inserted after this offset.
1998 unsigned MinInsertOffset =
1999 getOffsetAfterHeaderGuardsAndComments(FileName, Code, Style);
Eric Liu303baf52016-06-03 12:52:59 +00002000 StringRef TrimmedCode = Code.drop_front(MinInsertOffset);
Eric Liu21d10322016-12-09 11:45:50 +00002001 // Max insertion offset in the original code.
Eric Liu964782a2016-12-02 11:01:43 +00002002 unsigned MaxInsertOffset =
Eric Liu21d10322016-12-09 11:45:50 +00002003 MinInsertOffset +
Eric Liu964782a2016-12-02 11:01:43 +00002004 getMaxHeaderInsertionOffset(FileName, TrimmedCode, Style);
Eric Liu659afd52016-05-31 13:34:20 +00002005 SmallVector<StringRef, 32> Lines;
Eric Liu303baf52016-06-03 12:52:59 +00002006 TrimmedCode.split(Lines, '\n');
Eric Liu35288322016-06-06 11:00:13 +00002007 unsigned Offset = MinInsertOffset;
2008 unsigned NextLineOffset;
Eric Liu3753f912016-06-14 14:09:21 +00002009 std::set<StringRef> ExistingIncludes;
Eric Liu659afd52016-05-31 13:34:20 +00002010 for (auto Line : Lines) {
Eric Liu35288322016-06-06 11:00:13 +00002011 NextLineOffset = std::min(Code.size(), Offset + Line.size() + 1);
Eric Liu659afd52016-05-31 13:34:20 +00002012 if (IncludeRegex.match(Line, &Matches)) {
Eric Liuc0d3a802016-09-23 15:10:56 +00002013 // The header name with quotes or angle brackets.
Eric Liu659afd52016-05-31 13:34:20 +00002014 StringRef IncludeName = Matches[2];
Eric Liu3753f912016-06-14 14:09:21 +00002015 ExistingIncludes.insert(IncludeName);
Eric Liu964782a2016-12-02 11:01:43 +00002016 // Only record the offset of current #include if we can insert after it.
2017 if (Offset <= MaxInsertOffset) {
2018 int Category = Categories.getIncludePriority(
2019 IncludeName, /*CheckMainHeader=*/FirstIncludeOffset < 0);
2020 CategoryEndOffsets[Category] = NextLineOffset;
2021 if (FirstIncludeOffset < 0)
2022 FirstIncludeOffset = Offset;
2023 }
Eric Liuc0d3a802016-09-23 15:10:56 +00002024 if (isDeletedHeader(IncludeName, HeadersToDelete)) {
2025 // If this is the last line without trailing newline, we need to make
2026 // sure we don't delete across the file boundary.
2027 unsigned Length = std::min(Line.size() + 1, Code.size() - Offset);
2028 llvm::Error Err =
2029 Result.add(tooling::Replacement(FileName, Offset, Length, ""));
2030 if (Err) {
2031 // Ignore the deletion on conflict.
2032 llvm::errs() << "Failed to add header deletion replacement for "
2033 << IncludeName << ": " << llvm::toString(std::move(Err))
2034 << "\n";
2035 }
2036 }
Eric Liu659afd52016-05-31 13:34:20 +00002037 }
Eric Liu35288322016-06-06 11:00:13 +00002038 Offset = NextLineOffset;
Eric Liu659afd52016-05-31 13:34:20 +00002039 }
2040
2041 // Populate CategoryEndOfssets:
2042 // - Ensure that CategoryEndOffset[Highest] is always populated.
2043 // - If CategoryEndOffset[Priority] isn't set, use the next higher value that
2044 // is set, up to CategoryEndOffset[Highest].
Eric Liu659afd52016-05-31 13:34:20 +00002045 auto Highest = Priorities.begin();
2046 if (CategoryEndOffsets.find(*Highest) == CategoryEndOffsets.end()) {
2047 if (FirstIncludeOffset >= 0)
2048 CategoryEndOffsets[*Highest] = FirstIncludeOffset;
2049 else
Eric Liu303baf52016-06-03 12:52:59 +00002050 CategoryEndOffsets[*Highest] = MinInsertOffset;
Eric Liu659afd52016-05-31 13:34:20 +00002051 }
2052 // By this point, CategoryEndOffset[Highest] is always set appropriately:
2053 // - to an appropriate location before/after existing #includes, or
2054 // - to right after the header guard, or
2055 // - to the beginning of the file.
2056 for (auto I = ++Priorities.begin(), E = Priorities.end(); I != E; ++I)
2057 if (CategoryEndOffsets.find(*I) == CategoryEndOffsets.end())
2058 CategoryEndOffsets[*I] = CategoryEndOffsets[*std::prev(I)];
2059
Eric Liu11a42372016-10-05 15:42:19 +00002060 bool NeedNewLineAtEnd = !Code.empty() && Code.back() != '\n';
Eric Liu659afd52016-05-31 13:34:20 +00002061 for (const auto &R : HeaderInsertions) {
2062 auto IncludeDirective = R.getReplacementText();
2063 bool Matched = IncludeRegex.match(IncludeDirective, &Matches);
2064 assert(Matched && "Header insertion replacement must have replacement text "
2065 "'#include ...'");
Benjamin Kramer1cb7ee12016-05-31 14:14:42 +00002066 (void)Matched;
Eric Liu659afd52016-05-31 13:34:20 +00002067 auto IncludeName = Matches[2];
Eric Liu3753f912016-06-14 14:09:21 +00002068 if (ExistingIncludes.find(IncludeName) != ExistingIncludes.end()) {
2069 DEBUG(llvm::dbgs() << "Skip adding existing include : " << IncludeName
2070 << "\n");
2071 continue;
2072 }
Eric Liu659afd52016-05-31 13:34:20 +00002073 int Category =
2074 Categories.getIncludePriority(IncludeName, /*CheckMainHeader=*/true);
2075 Offset = CategoryEndOffsets[Category];
2076 std::string NewInclude = !IncludeDirective.endswith("\n")
2077 ? (IncludeDirective + "\n").str()
2078 : IncludeDirective.str();
Eric Liu11a42372016-10-05 15:42:19 +00002079 // When inserting headers at end of the code, also append '\n' to the code
2080 // if it does not end with '\n'.
2081 if (NeedNewLineAtEnd && Offset == Code.size()) {
2082 NewInclude = "\n" + NewInclude;
2083 NeedNewLineAtEnd = false;
2084 }
Eric Liu40ef2fb2016-08-01 10:16:37 +00002085 auto NewReplace = tooling::Replacement(FileName, Offset, 0, NewInclude);
2086 auto Err = Result.add(NewReplace);
2087 if (Err) {
2088 llvm::consumeError(std::move(Err));
Eric Liu11a42372016-10-05 15:42:19 +00002089 unsigned NewOffset = Result.getShiftedCodePosition(Offset);
2090 NewReplace = tooling::Replacement(FileName, NewOffset, 0, NewInclude);
Eric Liu40ef2fb2016-08-01 10:16:37 +00002091 Result = Result.merge(tooling::Replacements(NewReplace));
2092 }
Eric Liu659afd52016-05-31 13:34:20 +00002093 }
2094 return Result;
2095}
2096
2097} // anonymous namespace
2098
Eric Liu4f8d9942016-07-11 13:53:12 +00002099llvm::Expected<tooling::Replacements>
Eric Liu4cfb88a2016-04-25 15:09:22 +00002100cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
2101 const FormatStyle &Style) {
2102 // We need to use lambda function here since there are two versions of
2103 // `cleanup`.
2104 auto Cleanup = [](const FormatStyle &Style, StringRef Code,
2105 std::vector<tooling::Range> Ranges,
2106 StringRef FileName) -> tooling::Replacements {
2107 return cleanup(Style, Code, Ranges, FileName);
2108 };
Eric Liu659afd52016-05-31 13:34:20 +00002109 // Make header insertion replacements insert new headers into correct blocks.
2110 tooling::Replacements NewReplaces =
2111 fixCppIncludeInsertions(Code, Replaces, Style);
2112 return processReplacements(Cleanup, Code, NewReplaces, Style);
Eric Liu4cfb88a2016-04-25 15:09:22 +00002113}
2114
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002115namespace internal {
2116std::pair<tooling::Replacements, unsigned>
2117reformat(const FormatStyle &Style, StringRef Code,
2118 ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,
2119 unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,
2120 FormattingAttemptStatus *Status) {
Eric Liu4cfb88a2016-04-25 15:09:22 +00002121 FormatStyle Expanded = expandPresets(Style);
2122 if (Expanded.DisableFormat)
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002123 return {tooling::Replacements(), 0};
Krasimir Georgiev86873032017-08-29 13:57:31 +00002124 if (isLikelyXml(Code))
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002125 return {tooling::Replacements(), 0};
Krasimir Georgiev86873032017-08-29 13:57:31 +00002126 if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code))
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002127 return {tooling::Replacements(), 0};
Daniel Jasper496c1992016-09-07 22:48:53 +00002128
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002129 typedef std::function<std::pair<tooling::Replacements, unsigned>(
2130 const Environment &)>
Krasimir Georgievac16a202017-06-23 11:46:03 +00002131 AnalyzerPass;
2132 SmallVector<AnalyzerPass, 4> Passes;
Krasimir Georgiev32eaa862017-03-01 15:35:39 +00002133
Krasimir Georgievac16a202017-06-23 11:46:03 +00002134 if (Style.Language == FormatStyle::LK_Cpp) {
2135 if (Style.FixNamespaceComments)
2136 Passes.emplace_back([&](const Environment &Env) {
2137 return NamespaceEndCommentsFixer(Env, Expanded).process();
2138 });
2139
2140 if (Style.SortUsingDeclarations)
2141 Passes.emplace_back([&](const Environment &Env) {
2142 return UsingDeclarationsSorter(Env, Expanded).process();
2143 });
Krasimir Georgiev32eaa862017-03-01 15:35:39 +00002144 }
2145
2146 if (Style.Language == FormatStyle::LK_JavaScript &&
Krasimir Georgievac16a202017-06-23 11:46:03 +00002147 Style.JavaScriptQuotes != FormatStyle::JSQS_Leave)
2148 Passes.emplace_back([&](const Environment &Env) {
2149 return JavaScriptRequoter(Env, Expanded).process();
2150 });
2151
2152 Passes.emplace_back([&](const Environment &Env) {
2153 return Formatter(Env, Expanded, Status).process();
2154 });
2155
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002156 std::unique_ptr<Environment> Env = Environment::CreateVirtualEnvironment(
2157 Code, FileName, Ranges, FirstStartColumn, NextStartColumn,
2158 LastStartColumn);
Krasimir Georgievac16a202017-06-23 11:46:03 +00002159 llvm::Optional<std::string> CurrentCode = None;
2160 tooling::Replacements Fixes;
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002161 unsigned Penalty = 0;
Krasimir Georgievac16a202017-06-23 11:46:03 +00002162 for (size_t I = 0, E = Passes.size(); I < E; ++I) {
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002163 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
Krasimir Georgievac16a202017-06-23 11:46:03 +00002164 auto NewCode = applyAllReplacements(
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002165 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
Krasimir Georgievac16a202017-06-23 11:46:03 +00002166 if (NewCode) {
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002167 Fixes = Fixes.merge(PassFixes.first);
2168 Penalty += PassFixes.second;
Krasimir Georgievac16a202017-06-23 11:46:03 +00002169 if (I + 1 < E) {
2170 CurrentCode = std::move(*NewCode);
2171 Env = Environment::CreateVirtualEnvironment(
2172 *CurrentCode, FileName,
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002173 tooling::calculateRangesAfterReplacements(Fixes, Ranges),
2174 FirstStartColumn, NextStartColumn, LastStartColumn);
Krasimir Georgievac16a202017-06-23 11:46:03 +00002175 }
2176 }
Daniel Jasper496c1992016-09-07 22:48:53 +00002177 }
2178
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002179 return {Fixes, Penalty};
2180}
2181} // namespace internal
2182
2183tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
2184 ArrayRef<tooling::Range> Ranges,
2185 StringRef FileName,
2186 FormattingAttemptStatus *Status) {
2187 return internal::reformat(Style, Code, Ranges,
2188 /*FirstStartColumn=*/0,
2189 /*NextStartColumn=*/0,
2190 /*LastStartColumn=*/0, FileName, Status)
2191 .first;
Eric Liu4cfb88a2016-04-25 15:09:22 +00002192}
2193
Eric Liu4cfb88a2016-04-25 15:09:22 +00002194tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
2195 ArrayRef<tooling::Range> Ranges,
2196 StringRef FileName) {
Martin Probst816a9662017-05-29 08:41:11 +00002197 // cleanups only apply to C++ (they mostly concern ctor commas etc.)
2198 if (Style.Language != FormatStyle::LK_Cpp)
2199 return tooling::Replacements();
Eric Liu4cfb88a2016-04-25 15:09:22 +00002200 std::unique_ptr<Environment> Env =
Eric Liu635423e2016-04-28 07:52:03 +00002201 Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
2202 Cleaner Clean(*Env, Style);
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002203 return Clean.process().first;
Daniel Jasperec04c0d2013-05-16 10:40:07 +00002204}
2205
Krasimir Georgievbcda54b2017-04-21 14:35:20 +00002206tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
2207 ArrayRef<tooling::Range> Ranges,
2208 StringRef FileName, bool *IncompleteFormat) {
2209 FormattingAttemptStatus Status;
2210 auto Result = reformat(Style, Code, Ranges, FileName, &Status);
2211 if (!Status.FormatComplete)
2212 *IncompleteFormat = true;
2213 return Result;
2214}
2215
Krasimir Georgiev7cb267a2017-02-27 13:28:36 +00002216tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,
2217 StringRef Code,
2218 ArrayRef<tooling::Range> Ranges,
2219 StringRef FileName) {
2220 std::unique_ptr<Environment> Env =
2221 Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
2222 NamespaceEndCommentsFixer Fix(*Env, Style);
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002223 return Fix.process().first;
Krasimir Georgiev7cb267a2017-02-27 13:28:36 +00002224}
2225
Krasimir Georgievb03877a2017-06-21 12:03:12 +00002226tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
2227 StringRef Code,
2228 ArrayRef<tooling::Range> Ranges,
2229 StringRef FileName) {
2230 std::unique_ptr<Environment> Env =
2231 Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
2232 UsingDeclarationsSorter Sorter(*Env, Style);
Krasimir Georgiev9ad83fe2017-10-30 14:01:50 +00002233 return Sorter.process().first;
Krasimir Georgievb03877a2017-06-21 12:03:12 +00002234}
2235
Daniel Jasper4db69bd2014-09-04 18:23:42 +00002236LangOptions getFormattingLangOpts(const FormatStyle &Style) {
Daniel Jasperc1fa2812013-01-10 13:08:12 +00002237 LangOptions LangOpts;
2238 LangOpts.CPlusPlus = 1;
Daniel Jasper4db69bd2014-09-04 18:23:42 +00002239 LangOpts.CPlusPlus11 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
2240 LangOpts.CPlusPlus14 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
Aaron Ballmanc351fba2017-12-04 20:27:34 +00002241 LangOpts.CPlusPlus17 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
Richard Smithc70f1d62017-12-14 15:16:18 +00002242 LangOpts.CPlusPlus2a = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
Daniel Jasper55213652013-03-22 10:01:29 +00002243 LangOpts.LineComment = 1;
Daniel Jasper1dbc2102017-03-31 13:30:24 +00002244 bool AlternativeOperators = Style.isCpp();
Daniel Jasper30a24062014-11-14 09:02:28 +00002245 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
Daniel Jasperc1fa2812013-01-10 13:08:12 +00002246 LangOpts.Bool = 1;
2247 LangOpts.ObjC1 = 1;
2248 LangOpts.ObjC2 = 1;
Eric Liu4cfb88a2016-04-25 15:09:22 +00002249 LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally.
Saleem Abdulrasoold170c4b2015-10-04 17:51:05 +00002250 LangOpts.DeclSpecKeyword = 1; // To get __declspec.
Daniel Jasperc1fa2812013-01-10 13:08:12 +00002251 return LangOpts;
2252}
2253
Edwin Vaned544aa72013-09-30 13:31:48 +00002254const char *StyleOptionHelpDescription =
2255 "Coding style, currently supports:\n"
2256 " LLVM, Google, Chromium, Mozilla, WebKit.\n"
2257 "Use -style=file to load style configuration from\n"
2258 ".clang-format file located in one of the parent\n"
2259 "directories of the source file (or current\n"
2260 "directory for stdin).\n"
2261 "Use -style=\"{key: value, ...}\" to set specific\n"
2262 "parameters, e.g.:\n"
2263 " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
2264
Alexander Kornienkoc1637f12013-12-10 11:28:13 +00002265static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
Daniel Jasper498f5582015-12-25 08:53:31 +00002266 if (FileName.endswith(".java"))
Daniel Jasperc58c70e2014-09-15 11:21:46 +00002267 return FormatStyle::LK_Java;
Daniel Jasper498f5582015-12-25 08:53:31 +00002268 if (FileName.endswith_lower(".js") || FileName.endswith_lower(".ts"))
2269 return FormatStyle::LK_JavaScript; // JavaScript or TypeScript.
Daniel Jasper03a04fe2016-12-12 12:42:29 +00002270 if (FileName.endswith(".m") || FileName.endswith(".mm"))
2271 return FormatStyle::LK_ObjC;
Daniel Jasper498f5582015-12-25 08:53:31 +00002272 if (FileName.endswith_lower(".proto") ||
2273 FileName.endswith_lower(".protodevel"))
Daniel Jasper7052ce62014-01-19 09:04:08 +00002274 return FormatStyle::LK_Proto;
Krasimir Georgiev66496652017-11-17 15:10:49 +00002275 if (FileName.endswith_lower(".textpb") ||
2276 FileName.endswith_lower(".pb.txt") ||
2277 FileName.endswith_lower(".textproto") ||
2278 FileName.endswith_lower(".asciipb"))
2279 return FormatStyle::LK_TextProto;
Daniel Jasper498f5582015-12-25 08:53:31 +00002280 if (FileName.endswith_lower(".td"))
2281 return FormatStyle::LK_TableGen;
Alexander Kornienkoc1637f12013-12-10 11:28:13 +00002282 return FormatStyle::LK_Cpp;
Alexander Kornienkocabdd732013-11-29 15:19:43 +00002283}
2284
Antonio Maiorano3adfb6a2017-01-17 00:12:27 +00002285llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
Antonio Maiorano7eb75072017-01-20 01:22:42 +00002286 StringRef FallbackStyleName,
2287 StringRef Code, vfs::FileSystem *FS) {
Eric Liu547d8792016-03-24 13:22:42 +00002288 if (!FS) {
2289 FS = vfs::getRealFileSystem().get();
2290 }
Alexander Kornienkoc1637f12013-12-10 11:28:13 +00002291 FormatStyle Style = getLLVMStyle();
2292 Style.Language = getLanguageByFileName(FileName);
Daniel Jasper03a04fe2016-12-12 12:42:29 +00002293
Ben Hamiltone2e3e672018-01-17 17:33:08 +00002294 if (Style.Language == FormatStyle::LK_Cpp && FileName.endswith(".h")) {
2295 std::unique_ptr<Environment> Env =
2296 Environment::CreateVirtualEnvironment(Code, FileName, /*Ranges=*/{});
2297 ObjCHeaderStyleGuesser Guesser(*Env, Style);
2298 Guesser.process();
2299 if (Guesser.isObjC()) {
2300 Style.Language = FormatStyle::LK_ObjC;
2301 }
2302 }
Daniel Jasper03a04fe2016-12-12 12:42:29 +00002303
Antonio Maiorano7eb75072017-01-20 01:22:42 +00002304 FormatStyle FallbackStyle = getNoStyle();
2305 if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))
2306 return make_string_error("Invalid fallback style \"" + FallbackStyleName);
Edwin Vaned544aa72013-09-30 13:31:48 +00002307
2308 if (StyleName.startswith("{")) {
2309 // Parse YAML/JSON style from the command line.
Antonio Maiorano3adfb6a2017-01-17 00:12:27 +00002310 if (std::error_code ec = parseConfiguration(StyleName, &Style))
2311 return make_string_error("Error parsing -style: " + ec.message());
Edwin Vaned544aa72013-09-30 13:31:48 +00002312 return Style;
2313 }
2314
2315 if (!StyleName.equals_lower("file")) {
Alexander Kornienkoc1637f12013-12-10 11:28:13 +00002316 if (!getPredefinedStyle(StyleName, Style.Language, &Style))
Antonio Maiorano3adfb6a2017-01-17 00:12:27 +00002317 return make_string_error("Invalid value for -style");
Edwin Vaned544aa72013-09-30 13:31:48 +00002318 return Style;
2319 }
2320
Alexander Kornienkoc1637f12013-12-10 11:28:13 +00002321 // Look for .clang-format/_clang-format file in the file's parent directories.
Alexander Kornienkocabdd732013-11-29 15:19:43 +00002322 SmallString<128> UnsuitableConfigFiles;
Edwin Vaned544aa72013-09-30 13:31:48 +00002323 SmallString<128> Path(FileName);
Antonio Maiorano3adfb6a2017-01-17 00:12:27 +00002324 if (std::error_code EC = FS->makeAbsolute(Path))
2325 return make_string_error(EC.message());
Antonio Maiorano34c03762016-12-22 05:10:07 +00002326
Alexander Kornienkoe2e03872013-10-14 00:46:35 +00002327 for (StringRef Directory = Path; !Directory.empty();
Edwin Vaned544aa72013-09-30 13:31:48 +00002328 Directory = llvm::sys::path::parent_path(Directory)) {
Eric Liu547d8792016-03-24 13:22:42 +00002329
2330 auto Status = FS->status(Directory);
2331 if (!Status ||
2332 Status->getType() != llvm::sys::fs::file_type::directory_file) {
Edwin Vaned544aa72013-09-30 13:31:48 +00002333 continue;
Eric Liu547d8792016-03-24 13:22:42 +00002334 }
2335
Edwin Vaned544aa72013-09-30 13:31:48 +00002336 SmallString<128> ConfigFile(Directory);
2337
2338 llvm::sys::path::append(ConfigFile, ".clang-format");
2339 DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
Eric Liud4758322016-03-24 13:22:37 +00002340
Eric Liu547d8792016-03-24 13:22:42 +00002341 Status = FS->status(ConfigFile.str());
Antonio Maiorano3adfb6a2017-01-17 00:12:27 +00002342 bool FoundConfigFile =
Eric Liu547d8792016-03-24 13:22:42 +00002343 Status && (Status->getType() == llvm::sys::fs::file_type::regular_file);
Antonio Maiorano3adfb6a2017-01-17 00:12:27 +00002344 if (!FoundConfigFile) {
Edwin Vaned544aa72013-09-30 13:31:48 +00002345 // Try _clang-format too, since dotfiles are not commonly used on Windows.
2346 ConfigFile = Directory;
2347 llvm::sys::path::append(ConfigFile, "_clang-format");
2348 DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
Eric Liu547d8792016-03-24 13:22:42 +00002349 Status = FS->status(ConfigFile.str());
Antonio Maiorano3adfb6a2017-01-17 00:12:27 +00002350 FoundConfigFile = Status && (Status->getType() ==
2351 llvm::sys::fs::file_type::regular_file);
Edwin Vaned544aa72013-09-30 13:31:48 +00002352 }
2353
Antonio Maiorano3adfb6a2017-01-17 00:12:27 +00002354 if (FoundConfigFile) {
Rafael Espindola2d2b4202014-07-06 17:43:24 +00002355 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
Eric Liu547d8792016-03-24 13:22:42 +00002356 FS->getBufferForFile(ConfigFile.str());
Antonio Maiorano3adfb6a2017-01-17 00:12:27 +00002357 if (std::error_code EC = Text.getError())
2358 return make_string_error(EC.message());
Rafael Espindola2d2b4202014-07-06 17:43:24 +00002359 if (std::error_code ec =
2360 parseConfiguration(Text.get()->getBuffer(), &Style)) {
Rafael Espindolad0136702014-06-12 02:50:04 +00002361 if (ec == ParseError::Unsuitable) {
Alexander Kornienkocabdd732013-11-29 15:19:43 +00002362 if (!UnsuitableConfigFiles.empty())
2363 UnsuitableConfigFiles.append(", ");
2364 UnsuitableConfigFiles.append(ConfigFile);
Alexander Kornienkobc4ae442013-12-02 15:21:38 +00002365 continue;
Alexander Kornienkocabdd732013-11-29 15:19:43 +00002366 }
Antonio Maiorano3adfb6a2017-01-17 00:12:27 +00002367 return make_string_error("Error reading " + ConfigFile + ": " +
2368 ec.message());
Edwin Vaned544aa72013-09-30 13:31:48 +00002369 }
2370 DEBUG(llvm::dbgs() << "Using configuration file " << ConfigFile << "\n");
2371 return Style;
2372 }
2373 }
Antonio Maiorano3adfb6a2017-01-17 00:12:27 +00002374 if (!UnsuitableConfigFiles.empty())
2375 return make_string_error("Configuration file(s) do(es) not support " +
2376 getLanguageName(Style.Language) + ": " +
2377 UnsuitableConfigFiles);
Antonio Maiorano7eb75072017-01-20 01:22:42 +00002378 return FallbackStyle;
Edwin Vaned544aa72013-09-30 13:31:48 +00002379}
2380
Daniel Jasper8d1832e2013-01-07 13:26:07 +00002381} // namespace format
2382} // namespace clang