1//===--- Format.cpp - Format C++ code -------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file implements functions declared in Format.h. This will be
11/// split into separate files as we go.
12///
13//===----------------------------------------------------------------------===//
14
15#include "clang/Format/Format.h"
16#include "DefinitionBlockSeparator.h"
17#include "IntegerLiteralSeparatorFixer.h"
18#include "NamespaceEndCommentsFixer.h"
19#include "NumericLiteralCaseFixer.h"
20#include "ObjCPropertyAttributeOrderFixer.h"
21#include "QualifierAlignmentFixer.h"
22#include "SortJavaScriptImports.h"
23#include "UnwrappedLineFormatter.h"
24#include "UsingDeclarationsSorter.h"
25#include "clang/Tooling/Inclusions/HeaderIncludes.h"
26#include "llvm/ADT/Sequence.h"
27#include <limits>
28
29#define DEBUG_TYPE "format-formatter"
30
31using clang::format::FormatStyle;
32
33LLVM_YAML_IS_SEQUENCE_VECTOR(FormatStyle::RawStringFormat)
34LLVM_YAML_IS_SEQUENCE_VECTOR(FormatStyle::BinaryOperationBreakRule)
35LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tok::TokenKind)
36
37enum BracketAlignmentStyle : int8_t {
38 BAS_Align,
39 BAS_DontAlign,
40 BAS_AlwaysBreak,
41 BAS_BlockIndent
42};
43
44namespace llvm {
45namespace yaml {
46template <>
47struct ScalarEnumerationTraits<FormatStyle::BreakBeforeNoexceptSpecifierStyle> {
48 static void
49 enumeration(IO &IO, FormatStyle::BreakBeforeNoexceptSpecifierStyle &Value) {
50 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::BBNSS_Never);
51 IO.enumCase(Val&: Value, Str: "OnlyWithParen", ConstVal: FormatStyle::BBNSS_OnlyWithParen);
52 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::BBNSS_Always);
53 }
54};
55
56template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {
57 static void enumInput(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
58 IO.enumCase(Val&: Value, Str: "None", ConstVal: FormatStyle::AlignConsecutiveStyle({}));
59 IO.enumCase(Val&: Value, Str: "Consecutive",
60 ConstVal: FormatStyle::AlignConsecutiveStyle(
61 {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
62 /*AcrossComments=*/false, /*AlignCompound=*/false,
63 /*AlignFunctionDeclarations=*/true,
64 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
65 IO.enumCase(Val&: Value, Str: "AcrossEmptyLines",
66 ConstVal: FormatStyle::AlignConsecutiveStyle(
67 {/*Enabled=*/true, /*AcrossEmptyLines=*/true,
68 /*AcrossComments=*/false, /*AlignCompound=*/false,
69 /*AlignFunctionDeclarations=*/true,
70 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
71 IO.enumCase(Val&: Value, Str: "AcrossComments",
72 ConstVal: FormatStyle::AlignConsecutiveStyle(
73 {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
74 /*AcrossComments=*/true, /*AlignCompound=*/false,
75 /*AlignFunctionDeclarations=*/true,
76 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
77 IO.enumCase(Val&: Value, Str: "AcrossEmptyLinesAndComments",
78 ConstVal: FormatStyle::AlignConsecutiveStyle(
79 {/*Enabled=*/true, /*AcrossEmptyLines=*/true,
80 /*AcrossComments=*/true, /*AlignCompound=*/false,
81 /*AlignFunctionDeclarations=*/true,
82 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
83
84 // For backward compatibility.
85 IO.enumCase(Val&: Value, Str: "true",
86 ConstVal: FormatStyle::AlignConsecutiveStyle(
87 {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
88 /*AcrossComments=*/false, /*AlignCompound=*/false,
89 /*AlignFunctionDeclarations=*/true,
90 /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
91 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::AlignConsecutiveStyle({}));
92 }
93
94 static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
95 IO.mapOptional(Key: "Enabled", Val&: Value.Enabled);
96 IO.mapOptional(Key: "AcrossEmptyLines", Val&: Value.AcrossEmptyLines);
97 IO.mapOptional(Key: "AcrossComments", Val&: Value.AcrossComments);
98 IO.mapOptional(Key: "AlignCompound", Val&: Value.AlignCompound);
99 IO.mapOptional(Key: "AlignFunctionDeclarations",
100 Val&: Value.AlignFunctionDeclarations);
101 IO.mapOptional(Key: "AlignFunctionPointers", Val&: Value.AlignFunctionPointers);
102 IO.mapOptional(Key: "PadOperators", Val&: Value.PadOperators);
103 }
104};
105
106template <>
107struct MappingTraits<FormatStyle::ShortCaseStatementsAlignmentStyle> {
108 static void mapping(IO &IO,
109 FormatStyle::ShortCaseStatementsAlignmentStyle &Value) {
110 IO.mapOptional(Key: "Enabled", Val&: Value.Enabled);
111 IO.mapOptional(Key: "AcrossEmptyLines", Val&: Value.AcrossEmptyLines);
112 IO.mapOptional(Key: "AcrossComments", Val&: Value.AcrossComments);
113 IO.mapOptional(Key: "AlignCaseArrows", Val&: Value.AlignCaseArrows);
114 IO.mapOptional(Key: "AlignCaseColons", Val&: Value.AlignCaseColons);
115 }
116};
117
118template <>
119struct ScalarEnumerationTraits<FormatStyle::AttributeBreakingStyle> {
120 static void enumeration(IO &IO, FormatStyle::AttributeBreakingStyle &Value) {
121 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::ABS_Always);
122 IO.enumCase(Val&: Value, Str: "Leave", ConstVal: FormatStyle::ABS_Leave);
123 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::ABS_Never);
124 }
125};
126
127template <>
128struct ScalarEnumerationTraits<FormatStyle::ArrayInitializerAlignmentStyle> {
129 static void enumeration(IO &IO,
130 FormatStyle::ArrayInitializerAlignmentStyle &Value) {
131 IO.enumCase(Val&: Value, Str: "None", ConstVal: FormatStyle::AIAS_None);
132 IO.enumCase(Val&: Value, Str: "Left", ConstVal: FormatStyle::AIAS_Left);
133 IO.enumCase(Val&: Value, Str: "Right", ConstVal: FormatStyle::AIAS_Right);
134 }
135};
136
137template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> {
138 static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {
139 IO.enumCase(Val&: Value, Str: "All", ConstVal: FormatStyle::BOS_All);
140 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::BOS_All);
141 IO.enumCase(Val&: Value, Str: "None", ConstVal: FormatStyle::BOS_None);
142 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::BOS_None);
143 IO.enumCase(Val&: Value, Str: "NonAssignment", ConstVal: FormatStyle::BOS_NonAssignment);
144 }
145};
146
147template <>
148struct ScalarEnumerationTraits<FormatStyle::BinPackParametersStyle> {
149 static void enumeration(IO &IO, FormatStyle::BinPackParametersStyle &Value) {
150 IO.enumCase(Val&: Value, Str: "BinPack", ConstVal: FormatStyle::BPPS_BinPack);
151 IO.enumCase(Val&: Value, Str: "OnePerLine", ConstVal: FormatStyle::BPPS_OnePerLine);
152 IO.enumCase(Val&: Value, Str: "AlwaysOnePerLine", ConstVal: FormatStyle::BPPS_AlwaysOnePerLine);
153
154 // For backward compatibility.
155 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::BPPS_BinPack);
156 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::BPPS_OnePerLine);
157 }
158};
159
160template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {
161 static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) {
162 IO.enumCase(Val&: Value, Str: "Auto", ConstVal: FormatStyle::BPS_Auto);
163 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::BPS_Always);
164 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::BPS_Never);
165 }
166};
167
168template <>
169struct ScalarEnumerationTraits<FormatStyle::BitFieldColonSpacingStyle> {
170 static void enumeration(IO &IO,
171 FormatStyle::BitFieldColonSpacingStyle &Value) {
172 IO.enumCase(Val&: Value, Str: "Both", ConstVal: FormatStyle::BFCS_Both);
173 IO.enumCase(Val&: Value, Str: "None", ConstVal: FormatStyle::BFCS_None);
174 IO.enumCase(Val&: Value, Str: "Before", ConstVal: FormatStyle::BFCS_Before);
175 IO.enumCase(Val&: Value, Str: "After", ConstVal: FormatStyle::BFCS_After);
176 }
177};
178
179template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
180 static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {
181 IO.enumCase(Val&: Value, Str: "Attach", ConstVal: FormatStyle::BS_Attach);
182 IO.enumCase(Val&: Value, Str: "Linux", ConstVal: FormatStyle::BS_Linux);
183 IO.enumCase(Val&: Value, Str: "Mozilla", ConstVal: FormatStyle::BS_Mozilla);
184 IO.enumCase(Val&: Value, Str: "Stroustrup", ConstVal: FormatStyle::BS_Stroustrup);
185 IO.enumCase(Val&: Value, Str: "Allman", ConstVal: FormatStyle::BS_Allman);
186 IO.enumCase(Val&: Value, Str: "Whitesmiths", ConstVal: FormatStyle::BS_Whitesmiths);
187 IO.enumCase(Val&: Value, Str: "GNU", ConstVal: FormatStyle::BS_GNU);
188 IO.enumCase(Val&: Value, Str: "WebKit", ConstVal: FormatStyle::BS_WebKit);
189 IO.enumCase(Val&: Value, Str: "Custom", ConstVal: FormatStyle::BS_Custom);
190 }
191};
192
193template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
194 static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
195 IO.mapOptional(Key: "AfterCaseLabel", Val&: Wrapping.AfterCaseLabel);
196 IO.mapOptional(Key: "AfterClass", Val&: Wrapping.AfterClass);
197 IO.mapOptional(Key: "AfterControlStatement", Val&: Wrapping.AfterControlStatement);
198 IO.mapOptional(Key: "AfterEnum", Val&: Wrapping.AfterEnum);
199 IO.mapOptional(Key: "AfterExternBlock", Val&: Wrapping.AfterExternBlock);
200 IO.mapOptional(Key: "AfterFunction", Val&: Wrapping.AfterFunction);
201 IO.mapOptional(Key: "AfterNamespace", Val&: Wrapping.AfterNamespace);
202 IO.mapOptional(Key: "AfterObjCDeclaration", Val&: Wrapping.AfterObjCDeclaration);
203 IO.mapOptional(Key: "AfterStruct", Val&: Wrapping.AfterStruct);
204 IO.mapOptional(Key: "AfterUnion", Val&: Wrapping.AfterUnion);
205 IO.mapOptional(Key: "BeforeCatch", Val&: Wrapping.BeforeCatch);
206 IO.mapOptional(Key: "BeforeElse", Val&: Wrapping.BeforeElse);
207 IO.mapOptional(Key: "BeforeLambdaBody", Val&: Wrapping.BeforeLambdaBody);
208 IO.mapOptional(Key: "BeforeWhile", Val&: Wrapping.BeforeWhile);
209 IO.mapOptional(Key: "IndentBraces", Val&: Wrapping.IndentBraces);
210 IO.mapOptional(Key: "SplitEmptyFunction", Val&: Wrapping.SplitEmptyFunction);
211 IO.mapOptional(Key: "SplitEmptyRecord", Val&: Wrapping.SplitEmptyRecord);
212 IO.mapOptional(Key: "SplitEmptyNamespace", Val&: Wrapping.SplitEmptyNamespace);
213 }
214};
215
216template <> struct ScalarEnumerationTraits<BracketAlignmentStyle> {
217 static void enumeration(IO &IO, BracketAlignmentStyle &Value) {
218 IO.enumCase(Val&: Value, Str: "Align", ConstVal: BAS_Align);
219 IO.enumCase(Val&: Value, Str: "DontAlign", ConstVal: BAS_DontAlign);
220
221 // For backward compatibility.
222 IO.enumCase(Val&: Value, Str: "true", ConstVal: BAS_Align);
223 IO.enumCase(Val&: Value, Str: "false", ConstVal: BAS_DontAlign);
224 IO.enumCase(Val&: Value, Str: "AlwaysBreak", ConstVal: BAS_AlwaysBreak);
225 IO.enumCase(Val&: Value, Str: "BlockIndent", ConstVal: BAS_BlockIndent);
226 }
227};
228
229template <>
230struct ScalarEnumerationTraits<
231 FormatStyle::BraceWrappingAfterControlStatementStyle> {
232 static void
233 enumeration(IO &IO,
234 FormatStyle::BraceWrappingAfterControlStatementStyle &Value) {
235 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::BWACS_Never);
236 IO.enumCase(Val&: Value, Str: "MultiLine", ConstVal: FormatStyle::BWACS_MultiLine);
237 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::BWACS_Always);
238
239 // For backward compatibility.
240 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::BWACS_Never);
241 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::BWACS_Always);
242 }
243};
244
245template <>
246struct ScalarEnumerationTraits<
247 FormatStyle::BreakBeforeConceptDeclarationsStyle> {
248 static void
249 enumeration(IO &IO, FormatStyle::BreakBeforeConceptDeclarationsStyle &Value) {
250 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::BBCDS_Never);
251 IO.enumCase(Val&: Value, Str: "Allowed", ConstVal: FormatStyle::BBCDS_Allowed);
252 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::BBCDS_Always);
253
254 // For backward compatibility.
255 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::BBCDS_Always);
256 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::BBCDS_Allowed);
257 }
258};
259
260template <>
261struct ScalarEnumerationTraits<FormatStyle::BreakBeforeInlineASMColonStyle> {
262 static void enumeration(IO &IO,
263 FormatStyle::BreakBeforeInlineASMColonStyle &Value) {
264 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::BBIAS_Never);
265 IO.enumCase(Val&: Value, Str: "OnlyMultiline", ConstVal: FormatStyle::BBIAS_OnlyMultiline);
266 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::BBIAS_Always);
267 }
268};
269
270template <>
271struct ScalarEnumerationTraits<FormatStyle::BreakBinaryOperationsStyle> {
272 static void enumeration(IO &IO,
273 FormatStyle::BreakBinaryOperationsStyle &Value) {
274 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::BBO_Never);
275 IO.enumCase(Val&: Value, Str: "OnePerLine", ConstVal: FormatStyle::BBO_OnePerLine);
276 IO.enumCase(Val&: Value, Str: "RespectPrecedence", ConstVal: FormatStyle::BBO_RespectPrecedence);
277 }
278};
279
280template <> struct ScalarTraits<clang::tok::TokenKind> {
281 static void output(const clang::tok::TokenKind &Value, void *,
282 llvm::raw_ostream &Out) {
283 if (const char *Spelling = clang::tok::getPunctuatorSpelling(Kind: Value))
284 Out << Spelling;
285 else
286 Out << clang::tok::getTokenName(Kind: Value);
287 }
288
289 static StringRef input(StringRef Scalar, void *,
290 clang::tok::TokenKind &Value) {
291 // Map operator spelling strings to tok::TokenKind.
292#define PUNCTUATOR(Name, Spelling) \
293 if (Scalar == Spelling) { \
294 Value = clang::tok::Name; \
295 return {}; \
296 }
297#include "clang/Basic/TokenKinds.def"
298 return "unknown operator";
299 }
300
301 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
302};
303
304template <> struct MappingTraits<FormatStyle::BinaryOperationBreakRule> {
305 static void mapping(IO &IO, FormatStyle::BinaryOperationBreakRule &Value) {
306 IO.mapOptional(Key: "Operators", Val&: Value.Operators);
307 // Default to OnePerLine since a per-operator rule with Never is a no-op.
308 if (!IO.outputting())
309 Value.Style = FormatStyle::BBO_OnePerLine;
310 IO.mapOptional(Key: "Style", Val&: Value.Style);
311 IO.mapOptional(Key: "MinChainLength", Val&: Value.MinChainLength);
312 }
313};
314
315template <> struct MappingTraits<FormatStyle::BreakBinaryOperationsOptions> {
316 static void enumInput(IO &IO,
317 FormatStyle::BreakBinaryOperationsOptions &Value) {
318 IO.enumCase(Val&: Value, Str: "Never",
319 ConstVal: FormatStyle::BreakBinaryOperationsOptions(
320 {.Default: FormatStyle::BBO_Never, .PerOperator: {}}));
321 IO.enumCase(Val&: Value, Str: "OnePerLine",
322 ConstVal: FormatStyle::BreakBinaryOperationsOptions(
323 {.Default: FormatStyle::BBO_OnePerLine, .PerOperator: {}}));
324 IO.enumCase(Val&: Value, Str: "RespectPrecedence",
325 ConstVal: FormatStyle::BreakBinaryOperationsOptions(
326 {.Default: FormatStyle::BBO_RespectPrecedence, .PerOperator: {}}));
327 }
328
329 static void mapping(IO &IO,
330 FormatStyle::BreakBinaryOperationsOptions &Value) {
331 IO.mapOptional(Key: "Default", Val&: Value.Default);
332 IO.mapOptional(Key: "PerOperator", Val&: Value.PerOperator);
333 }
334};
335
336template <>
337struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
338 static void
339 enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
340 IO.enumCase(Val&: Value, Str: "BeforeColon", ConstVal: FormatStyle::BCIS_BeforeColon);
341 IO.enumCase(Val&: Value, Str: "BeforeComma", ConstVal: FormatStyle::BCIS_BeforeComma);
342 IO.enumCase(Val&: Value, Str: "AfterColon", ConstVal: FormatStyle::BCIS_AfterColon);
343 IO.enumCase(Val&: Value, Str: "AfterComma", ConstVal: FormatStyle::BCIS_AfterComma);
344 }
345};
346
347template <>
348struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {
349 static void enumeration(IO &IO,
350 FormatStyle::BreakInheritanceListStyle &Value) {
351 IO.enumCase(Val&: Value, Str: "BeforeColon", ConstVal: FormatStyle::BILS_BeforeColon);
352 IO.enumCase(Val&: Value, Str: "BeforeComma", ConstVal: FormatStyle::BILS_BeforeComma);
353 IO.enumCase(Val&: Value, Str: "AfterColon", ConstVal: FormatStyle::BILS_AfterColon);
354 IO.enumCase(Val&: Value, Str: "AfterComma", ConstVal: FormatStyle::BILS_AfterComma);
355 }
356};
357
358template <>
359struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
360 static void enumeration(IO &IO,
361 FormatStyle::BreakTemplateDeclarationsStyle &Value) {
362 IO.enumCase(Val&: Value, Str: "Leave", ConstVal: FormatStyle::BTDS_Leave);
363 IO.enumCase(Val&: Value, Str: "No", ConstVal: FormatStyle::BTDS_No);
364 IO.enumCase(Val&: Value, Str: "MultiLine", ConstVal: FormatStyle::BTDS_MultiLine);
365 IO.enumCase(Val&: Value, Str: "Yes", ConstVal: FormatStyle::BTDS_Yes);
366
367 // For backward compatibility.
368 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::BTDS_MultiLine);
369 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::BTDS_Yes);
370 }
371};
372
373template <> struct ScalarEnumerationTraits<FormatStyle::BracedListStyle> {
374 static void enumeration(IO &IO, FormatStyle::BracedListStyle &Value) {
375 IO.enumCase(Val&: Value, Str: "Block", ConstVal: FormatStyle::BLS_Block);
376 IO.enumCase(Val&: Value, Str: "FunctionCall", ConstVal: FormatStyle::BLS_FunctionCall);
377 IO.enumCase(Val&: Value, Str: "AlignFirstComment", ConstVal: FormatStyle::BLS_AlignFirstComment);
378
379 // For backward compatibility.
380 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::BLS_Block);
381 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::BLS_AlignFirstComment);
382 }
383};
384
385template <> struct ScalarEnumerationTraits<FormatStyle::DAGArgStyle> {
386 static void enumeration(IO &IO, FormatStyle::DAGArgStyle &Value) {
387 IO.enumCase(Val&: Value, Str: "DontBreak", ConstVal: FormatStyle::DAS_DontBreak);
388 IO.enumCase(Val&: Value, Str: "BreakElements", ConstVal: FormatStyle::DAS_BreakElements);
389 IO.enumCase(Val&: Value, Str: "BreakAll", ConstVal: FormatStyle::DAS_BreakAll);
390 }
391};
392
393template <>
394struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
395 static void
396 enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
397 IO.enumCase(Val&: Value, Str: "None", ConstVal: FormatStyle::DRTBS_None);
398 IO.enumCase(Val&: Value, Str: "All", ConstVal: FormatStyle::DRTBS_All);
399 IO.enumCase(Val&: Value, Str: "TopLevel", ConstVal: FormatStyle::DRTBS_TopLevel);
400
401 // For backward compatibility.
402 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::DRTBS_None);
403 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::DRTBS_All);
404 }
405};
406
407template <>
408struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
409 static void enumeration(IO &IO,
410 FormatStyle::EscapedNewlineAlignmentStyle &Value) {
411 IO.enumCase(Val&: Value, Str: "DontAlign", ConstVal: FormatStyle::ENAS_DontAlign);
412 IO.enumCase(Val&: Value, Str: "Left", ConstVal: FormatStyle::ENAS_Left);
413 IO.enumCase(Val&: Value, Str: "LeftWithLastLine", ConstVal: FormatStyle::ENAS_LeftWithLastLine);
414 IO.enumCase(Val&: Value, Str: "Right", ConstVal: FormatStyle::ENAS_Right);
415
416 // For backward compatibility.
417 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::ENAS_Left);
418 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::ENAS_Right);
419 }
420};
421
422template <>
423struct ScalarEnumerationTraits<FormatStyle::EmptyLineAfterAccessModifierStyle> {
424 static void
425 enumeration(IO &IO, FormatStyle::EmptyLineAfterAccessModifierStyle &Value) {
426 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::ELAAMS_Never);
427 IO.enumCase(Val&: Value, Str: "Leave", ConstVal: FormatStyle::ELAAMS_Leave);
428 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::ELAAMS_Always);
429 }
430};
431
432template <>
433struct ScalarEnumerationTraits<
434 FormatStyle::EmptyLineBeforeAccessModifierStyle> {
435 static void
436 enumeration(IO &IO, FormatStyle::EmptyLineBeforeAccessModifierStyle &Value) {
437 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::ELBAMS_Never);
438 IO.enumCase(Val&: Value, Str: "Leave", ConstVal: FormatStyle::ELBAMS_Leave);
439 IO.enumCase(Val&: Value, Str: "LogicalBlock", ConstVal: FormatStyle::ELBAMS_LogicalBlock);
440 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::ELBAMS_Always);
441 }
442};
443
444template <>
445struct ScalarEnumerationTraits<FormatStyle::EnumTrailingCommaStyle> {
446 static void enumeration(IO &IO, FormatStyle::EnumTrailingCommaStyle &Value) {
447 IO.enumCase(Val&: Value, Str: "Leave", ConstVal: FormatStyle::ETC_Leave);
448 IO.enumCase(Val&: Value, Str: "Insert", ConstVal: FormatStyle::ETC_Insert);
449 IO.enumCase(Val&: Value, Str: "Remove", ConstVal: FormatStyle::ETC_Remove);
450 }
451};
452
453template <>
454struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> {
455 static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value) {
456 IO.enumCase(Val&: Value, Str: "AfterExternBlock", ConstVal: FormatStyle::IEBS_AfterExternBlock);
457 IO.enumCase(Val&: Value, Str: "Indent", ConstVal: FormatStyle::IEBS_Indent);
458 IO.enumCase(Val&: Value, Str: "NoIndent", ConstVal: FormatStyle::IEBS_NoIndent);
459 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::IEBS_Indent);
460 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::IEBS_NoIndent);
461 }
462};
463
464template <> struct MappingTraits<FormatStyle::IntegerLiteralSeparatorStyle> {
465 static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &Base) {
466 IO.mapOptional(Key: "Binary", Val&: Base.Binary);
467 IO.mapOptional(Key: "BinaryMinDigitsInsert", Val&: Base.BinaryMinDigitsInsert);
468 IO.mapOptional(Key: "BinaryMaxDigitsRemove", Val&: Base.BinaryMaxDigitsRemove);
469 IO.mapOptional(Key: "Decimal", Val&: Base.Decimal);
470 IO.mapOptional(Key: "DecimalMinDigitsInsert", Val&: Base.DecimalMinDigitsInsert);
471 IO.mapOptional(Key: "DecimalMaxDigitsRemove", Val&: Base.DecimalMaxDigitsRemove);
472 IO.mapOptional(Key: "Hex", Val&: Base.Hex);
473 IO.mapOptional(Key: "HexMinDigitsInsert", Val&: Base.HexMinDigitsInsert);
474 IO.mapOptional(Key: "HexMaxDigitsRemove", Val&: Base.HexMaxDigitsRemove);
475
476 // For backward compatibility.
477 IO.mapOptional(Key: "BinaryMinDigits", Val&: Base.BinaryMinDigitsInsert);
478 IO.mapOptional(Key: "DecimalMinDigits", Val&: Base.DecimalMinDigitsInsert);
479 IO.mapOptional(Key: "HexMinDigits", Val&: Base.HexMinDigitsInsert);
480 }
481};
482
483template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {
484 static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) {
485 IO.enumCase(Val&: Value, Str: "Leave", ConstVal: FormatStyle::JSQS_Leave);
486 IO.enumCase(Val&: Value, Str: "Single", ConstVal: FormatStyle::JSQS_Single);
487 IO.enumCase(Val&: Value, Str: "Double", ConstVal: FormatStyle::JSQS_Double);
488 }
489};
490
491template <> struct MappingTraits<FormatStyle::KeepEmptyLinesStyle> {
492 static void mapping(IO &IO, FormatStyle::KeepEmptyLinesStyle &Value) {
493 IO.mapOptional(Key: "AtEndOfFile", Val&: Value.AtEndOfFile);
494 IO.mapOptional(Key: "AtStartOfBlock", Val&: Value.AtStartOfBlock);
495 IO.mapOptional(Key: "AtStartOfFile", Val&: Value.AtStartOfFile);
496 }
497};
498
499template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
500 static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
501 IO.enumCase(Val&: Value, Str: "C", ConstVal: FormatStyle::LK_C);
502 IO.enumCase(Val&: Value, Str: "Cpp", ConstVal: FormatStyle::LK_Cpp);
503 IO.enumCase(Val&: Value, Str: "Java", ConstVal: FormatStyle::LK_Java);
504 IO.enumCase(Val&: Value, Str: "JavaScript", ConstVal: FormatStyle::LK_JavaScript);
505 IO.enumCase(Val&: Value, Str: "ObjC", ConstVal: FormatStyle::LK_ObjC);
506 IO.enumCase(Val&: Value, Str: "Proto", ConstVal: FormatStyle::LK_Proto);
507 IO.enumCase(Val&: Value, Str: "TableGen", ConstVal: FormatStyle::LK_TableGen);
508 IO.enumCase(Val&: Value, Str: "TextProto", ConstVal: FormatStyle::LK_TextProto);
509 IO.enumCase(Val&: Value, Str: "CSharp", ConstVal: FormatStyle::LK_CSharp);
510 IO.enumCase(Val&: Value, Str: "Json", ConstVal: FormatStyle::LK_Json);
511 IO.enumCase(Val&: Value, Str: "Verilog", ConstVal: FormatStyle::LK_Verilog);
512 }
513};
514
515template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
516 static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
517 IO.enumCase(Val&: Value, Str: "c++03", ConstVal: FormatStyle::LS_Cpp03);
518 IO.enumCase(Val&: Value, Str: "C++03", ConstVal: FormatStyle::LS_Cpp03); // Legacy alias
519 IO.enumCase(Val&: Value, Str: "Cpp03", ConstVal: FormatStyle::LS_Cpp03); // Legacy alias
520
521 IO.enumCase(Val&: Value, Str: "c++11", ConstVal: FormatStyle::LS_Cpp11);
522 IO.enumCase(Val&: Value, Str: "C++11", ConstVal: FormatStyle::LS_Cpp11); // Legacy alias
523
524 IO.enumCase(Val&: Value, Str: "c++14", ConstVal: FormatStyle::LS_Cpp14);
525 IO.enumCase(Val&: Value, Str: "c++17", ConstVal: FormatStyle::LS_Cpp17);
526 IO.enumCase(Val&: Value, Str: "c++20", ConstVal: FormatStyle::LS_Cpp20);
527
528 IO.enumCase(Val&: Value, Str: "Latest", ConstVal: FormatStyle::LS_Latest);
529 IO.enumCase(Val&: Value, Str: "Cpp11", ConstVal: FormatStyle::LS_Latest); // Legacy alias
530 IO.enumCase(Val&: Value, Str: "Auto", ConstVal: FormatStyle::LS_Auto);
531 }
532};
533
534template <>
535struct ScalarEnumerationTraits<FormatStyle::LambdaBodyIndentationKind> {
536 static void enumeration(IO &IO,
537 FormatStyle::LambdaBodyIndentationKind &Value) {
538 IO.enumCase(Val&: Value, Str: "Signature", ConstVal: FormatStyle::LBI_Signature);
539 IO.enumCase(Val&: Value, Str: "OuterScope", ConstVal: FormatStyle::LBI_OuterScope);
540 }
541};
542
543template <> struct ScalarEnumerationTraits<FormatStyle::LineEndingStyle> {
544 static void enumeration(IO &IO, FormatStyle::LineEndingStyle &Value) {
545 IO.enumCase(Val&: Value, Str: "LF", ConstVal: FormatStyle::LE_LF);
546 IO.enumCase(Val&: Value, Str: "CRLF", ConstVal: FormatStyle::LE_CRLF);
547 IO.enumCase(Val&: Value, Str: "DeriveLF", ConstVal: FormatStyle::LE_DeriveLF);
548 IO.enumCase(Val&: Value, Str: "DeriveCRLF", ConstVal: FormatStyle::LE_DeriveCRLF);
549 }
550};
551
552template <>
553struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
554 static void enumeration(IO &IO,
555 FormatStyle::NamespaceIndentationKind &Value) {
556 IO.enumCase(Val&: Value, Str: "None", ConstVal: FormatStyle::NI_None);
557 IO.enumCase(Val&: Value, Str: "Inner", ConstVal: FormatStyle::NI_Inner);
558 IO.enumCase(Val&: Value, Str: "All", ConstVal: FormatStyle::NI_All);
559 }
560};
561
562template <>
563struct ScalarEnumerationTraits<FormatStyle::NumericLiteralComponentStyle> {
564 static void enumeration(IO &IO,
565 FormatStyle::NumericLiteralComponentStyle &Value) {
566 IO.enumCase(Val&: Value, Str: "Leave", ConstVal: FormatStyle::NLCS_Leave);
567 IO.enumCase(Val&: Value, Str: "Upper", ConstVal: FormatStyle::NLCS_Upper);
568 IO.enumCase(Val&: Value, Str: "Lower", ConstVal: FormatStyle::NLCS_Lower);
569 }
570};
571
572template <> struct MappingTraits<FormatStyle::NumericLiteralCaseStyle> {
573 static void mapping(IO &IO, FormatStyle::NumericLiteralCaseStyle &Value) {
574 IO.mapOptional(Key: "ExponentLetter", Val&: Value.ExponentLetter);
575 IO.mapOptional(Key: "HexDigit", Val&: Value.HexDigit);
576 IO.mapOptional(Key: "Prefix", Val&: Value.Prefix);
577 IO.mapOptional(Key: "Suffix", Val&: Value.Suffix);
578 }
579};
580
581template <> struct ScalarEnumerationTraits<FormatStyle::OperandAlignmentStyle> {
582 static void enumeration(IO &IO, FormatStyle::OperandAlignmentStyle &Value) {
583 IO.enumCase(Val&: Value, Str: "DontAlign", ConstVal: FormatStyle::OAS_DontAlign);
584 IO.enumCase(Val&: Value, Str: "Align", ConstVal: FormatStyle::OAS_Align);
585 IO.enumCase(Val&: Value, Str: "AlignAfterOperator",
586 ConstVal: FormatStyle::OAS_AlignAfterOperator);
587
588 // For backward compatibility.
589 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::OAS_Align);
590 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::OAS_DontAlign);
591 }
592};
593
594template <>
595struct ScalarEnumerationTraits<FormatStyle::PackConstructorInitializersStyle> {
596 static void
597 enumeration(IO &IO, FormatStyle::PackConstructorInitializersStyle &Value) {
598 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::PCIS_Never);
599 IO.enumCase(Val&: Value, Str: "BinPack", ConstVal: FormatStyle::PCIS_BinPack);
600 IO.enumCase(Val&: Value, Str: "CurrentLine", ConstVal: FormatStyle::PCIS_CurrentLine);
601 IO.enumCase(Val&: Value, Str: "NextLine", ConstVal: FormatStyle::PCIS_NextLine);
602 IO.enumCase(Val&: Value, Str: "NextLineOnly", ConstVal: FormatStyle::PCIS_NextLineOnly);
603 }
604};
605
606template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
607 static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {
608 IO.enumCase(Val&: Value, Str: "Middle", ConstVal: FormatStyle::PAS_Middle);
609 IO.enumCase(Val&: Value, Str: "Left", ConstVal: FormatStyle::PAS_Left);
610 IO.enumCase(Val&: Value, Str: "Right", ConstVal: FormatStyle::PAS_Right);
611
612 // For backward compatibility.
613 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::PAS_Left);
614 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::PAS_Right);
615 }
616};
617
618template <>
619struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
620 static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
621 IO.enumCase(Val&: Value, Str: "None", ConstVal: FormatStyle::PPDIS_None);
622 IO.enumCase(Val&: Value, Str: "AfterHash", ConstVal: FormatStyle::PPDIS_AfterHash);
623 IO.enumCase(Val&: Value, Str: "BeforeHash", ConstVal: FormatStyle::PPDIS_BeforeHash);
624 IO.enumCase(Val&: Value, Str: "Leave", ConstVal: FormatStyle::PPDIS_Leave);
625 }
626};
627
628template <>
629struct ScalarEnumerationTraits<FormatStyle::QualifierAlignmentStyle> {
630 static void enumeration(IO &IO, FormatStyle::QualifierAlignmentStyle &Value) {
631 IO.enumCase(Val&: Value, Str: "Leave", ConstVal: FormatStyle::QAS_Leave);
632 IO.enumCase(Val&: Value, Str: "Left", ConstVal: FormatStyle::QAS_Left);
633 IO.enumCase(Val&: Value, Str: "Right", ConstVal: FormatStyle::QAS_Right);
634 IO.enumCase(Val&: Value, Str: "Custom", ConstVal: FormatStyle::QAS_Custom);
635 }
636};
637
638template <> struct MappingTraits<FormatStyle::RawStringFormat> {
639 static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
640 IO.mapOptional(Key: "Language", Val&: Format.Language);
641 IO.mapOptional(Key: "Delimiters", Val&: Format.Delimiters);
642 IO.mapOptional(Key: "EnclosingFunctions", Val&: Format.EnclosingFunctions);
643 IO.mapOptional(Key: "CanonicalDelimiter", Val&: Format.CanonicalDelimiter);
644 IO.mapOptional(Key: "BasedOnStyle", Val&: Format.BasedOnStyle);
645 }
646};
647
648template <> struct ScalarEnumerationTraits<FormatStyle::ReflowCommentsStyle> {
649 static void enumeration(IO &IO, FormatStyle::ReflowCommentsStyle &Value) {
650 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::RCS_Never);
651 IO.enumCase(Val&: Value, Str: "IndentOnly", ConstVal: FormatStyle::RCS_IndentOnly);
652 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::RCS_Always);
653 // For backward compatibility:
654 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::RCS_Never);
655 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::RCS_Always);
656 }
657};
658
659template <>
660struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> {
661 static void enumeration(IO &IO, FormatStyle::ReferenceAlignmentStyle &Value) {
662 IO.enumCase(Val&: Value, Str: "Pointer", ConstVal: FormatStyle::RAS_Pointer);
663 IO.enumCase(Val&: Value, Str: "Middle", ConstVal: FormatStyle::RAS_Middle);
664 IO.enumCase(Val&: Value, Str: "Left", ConstVal: FormatStyle::RAS_Left);
665 IO.enumCase(Val&: Value, Str: "Right", ConstVal: FormatStyle::RAS_Right);
666 }
667};
668
669template <>
670struct ScalarEnumerationTraits<FormatStyle::RemoveParenthesesStyle> {
671 static void enumeration(IO &IO, FormatStyle::RemoveParenthesesStyle &Value) {
672 IO.enumCase(Val&: Value, Str: "Leave", ConstVal: FormatStyle::RPS_Leave);
673 IO.enumCase(Val&: Value, Str: "MultipleParentheses",
674 ConstVal: FormatStyle::RPS_MultipleParentheses);
675 IO.enumCase(Val&: Value, Str: "ReturnStatement", ConstVal: FormatStyle::RPS_ReturnStatement);
676 }
677};
678
679template <>
680struct ScalarEnumerationTraits<FormatStyle::RequiresClausePositionStyle> {
681 static void enumeration(IO &IO,
682 FormatStyle::RequiresClausePositionStyle &Value) {
683 IO.enumCase(Val&: Value, Str: "OwnLine", ConstVal: FormatStyle::RCPS_OwnLine);
684 IO.enumCase(Val&: Value, Str: "OwnLineWithBrace", ConstVal: FormatStyle::RCPS_OwnLineWithBrace);
685 IO.enumCase(Val&: Value, Str: "WithPreceding", ConstVal: FormatStyle::RCPS_WithPreceding);
686 IO.enumCase(Val&: Value, Str: "WithFollowing", ConstVal: FormatStyle::RCPS_WithFollowing);
687 IO.enumCase(Val&: Value, Str: "SingleLine", ConstVal: FormatStyle::RCPS_SingleLine);
688 }
689};
690
691template <>
692struct ScalarEnumerationTraits<FormatStyle::RequiresExpressionIndentationKind> {
693 static void
694 enumeration(IO &IO, FormatStyle::RequiresExpressionIndentationKind &Value) {
695 IO.enumCase(Val&: Value, Str: "Keyword", ConstVal: FormatStyle::REI_Keyword);
696 IO.enumCase(Val&: Value, Str: "OuterScope", ConstVal: FormatStyle::REI_OuterScope);
697 }
698};
699
700template <>
701struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
702 static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
703 IO.enumCase(Val&: Value, Str: "None", ConstVal: FormatStyle::RTBS_None);
704 IO.enumCase(Val&: Value, Str: "Automatic", ConstVal: FormatStyle::RTBS_Automatic);
705 IO.enumCase(Val&: Value, Str: "ExceptShortType", ConstVal: FormatStyle::RTBS_ExceptShortType);
706 IO.enumCase(Val&: Value, Str: "All", ConstVal: FormatStyle::RTBS_All);
707 IO.enumCase(Val&: Value, Str: "TopLevel", ConstVal: FormatStyle::RTBS_TopLevel);
708 IO.enumCase(Val&: Value, Str: "TopLevelDefinitions",
709 ConstVal: FormatStyle::RTBS_TopLevelDefinitions);
710 IO.enumCase(Val&: Value, Str: "AllDefinitions", ConstVal: FormatStyle::RTBS_AllDefinitions);
711 }
712};
713
714template <>
715struct ScalarEnumerationTraits<FormatStyle::SeparateDefinitionStyle> {
716 static void enumeration(IO &IO, FormatStyle::SeparateDefinitionStyle &Value) {
717 IO.enumCase(Val&: Value, Str: "Leave", ConstVal: FormatStyle::SDS_Leave);
718 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::SDS_Always);
719 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::SDS_Never);
720 }
721};
722
723template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> {
724 static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) {
725 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::SBS_Never);
726 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::SBS_Never);
727 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::SBS_Always);
728 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::SBS_Always);
729 IO.enumCase(Val&: Value, Str: "Empty", ConstVal: FormatStyle::SBS_Empty);
730 }
731};
732
733template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
734 static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
735 IO.enumCase(Val&: Value, Str: "None", ConstVal: FormatStyle::SFS_None);
736 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::SFS_None);
737 IO.enumCase(Val&: Value, Str: "All", ConstVal: FormatStyle::SFS_All);
738 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::SFS_All);
739 IO.enumCase(Val&: Value, Str: "Inline", ConstVal: FormatStyle::SFS_Inline);
740 IO.enumCase(Val&: Value, Str: "InlineOnly", ConstVal: FormatStyle::SFS_InlineOnly);
741 IO.enumCase(Val&: Value, Str: "Empty", ConstVal: FormatStyle::SFS_Empty);
742 }
743};
744
745template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> {
746 static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) {
747 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::SIS_Never);
748 IO.enumCase(Val&: Value, Str: "WithoutElse", ConstVal: FormatStyle::SIS_WithoutElse);
749 IO.enumCase(Val&: Value, Str: "OnlyFirstIf", ConstVal: FormatStyle::SIS_OnlyFirstIf);
750 IO.enumCase(Val&: Value, Str: "AllIfsAndElse", ConstVal: FormatStyle::SIS_AllIfsAndElse);
751
752 // For backward compatibility.
753 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::SIS_OnlyFirstIf);
754 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::SIS_Never);
755 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::SIS_WithoutElse);
756 }
757};
758
759template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> {
760 static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) {
761 IO.enumCase(Val&: Value, Str: "None", ConstVal: FormatStyle::SLS_None);
762 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::SLS_None);
763 IO.enumCase(Val&: Value, Str: "Empty", ConstVal: FormatStyle::SLS_Empty);
764 IO.enumCase(Val&: Value, Str: "Inline", ConstVal: FormatStyle::SLS_Inline);
765 IO.enumCase(Val&: Value, Str: "All", ConstVal: FormatStyle::SLS_All);
766 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::SLS_All);
767 }
768};
769
770template <> struct MappingTraits<FormatStyle::SortIncludesOptions> {
771 static void enumInput(IO &IO, FormatStyle::SortIncludesOptions &Value) {
772 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::SortIncludesOptions({}));
773 IO.enumCase(Val&: Value, Str: "CaseInsensitive",
774 ConstVal: FormatStyle::SortIncludesOptions({/*Enabled=*/true,
775 /*IgnoreCase=*/true,
776 /*IgnoreExtension=*/false}));
777 IO.enumCase(Val&: Value, Str: "CaseSensitive",
778 ConstVal: FormatStyle::SortIncludesOptions({/*Enabled=*/true,
779 /*IgnoreCase=*/false,
780 /*IgnoreExtension=*/false}));
781
782 // For backward compatibility.
783 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::SortIncludesOptions({}));
784 IO.enumCase(Val&: Value, Str: "true",
785 ConstVal: FormatStyle::SortIncludesOptions({/*Enabled=*/true,
786 /*IgnoreCase=*/false,
787 /*IgnoreExtension=*/false}));
788 }
789
790 static void mapping(IO &IO, FormatStyle::SortIncludesOptions &Value) {
791 IO.mapOptional(Key: "Enabled", Val&: Value.Enabled);
792 IO.mapOptional(Key: "IgnoreCase", Val&: Value.IgnoreCase);
793 IO.mapOptional(Key: "IgnoreExtension", Val&: Value.IgnoreExtension);
794 }
795};
796
797template <>
798struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> {
799 static void enumeration(IO &IO,
800 FormatStyle::SortJavaStaticImportOptions &Value) {
801 IO.enumCase(Val&: Value, Str: "Before", ConstVal: FormatStyle::SJSIO_Before);
802 IO.enumCase(Val&: Value, Str: "After", ConstVal: FormatStyle::SJSIO_After);
803 }
804};
805
806template <>
807struct ScalarEnumerationTraits<FormatStyle::SortUsingDeclarationsOptions> {
808 static void enumeration(IO &IO,
809 FormatStyle::SortUsingDeclarationsOptions &Value) {
810 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::SUD_Never);
811 IO.enumCase(Val&: Value, Str: "Lexicographic", ConstVal: FormatStyle::SUD_Lexicographic);
812 IO.enumCase(Val&: Value, Str: "LexicographicNumeric",
813 ConstVal: FormatStyle::SUD_LexicographicNumeric);
814
815 // For backward compatibility.
816 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::SUD_Never);
817 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::SUD_LexicographicNumeric);
818 }
819};
820
821template <>
822struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> {
823 static void
824 enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value) {
825 IO.enumCase(Val&: Value, Str: "Default", ConstVal: FormatStyle::SAPQ_Default);
826 IO.enumCase(Val&: Value, Str: "Before", ConstVal: FormatStyle::SAPQ_Before);
827 IO.enumCase(Val&: Value, Str: "After", ConstVal: FormatStyle::SAPQ_After);
828 IO.enumCase(Val&: Value, Str: "Both", ConstVal: FormatStyle::SAPQ_Both);
829 }
830};
831
832template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> {
833 static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) {
834 IO.mapOptional(Key: "AfterControlStatements", Val&: Spacing.AfterControlStatements);
835 IO.mapOptional(Key: "AfterForeachMacros", Val&: Spacing.AfterForeachMacros);
836 IO.mapOptional(Key: "AfterFunctionDefinitionName",
837 Val&: Spacing.AfterFunctionDefinitionName);
838 IO.mapOptional(Key: "AfterFunctionDeclarationName",
839 Val&: Spacing.AfterFunctionDeclarationName);
840 IO.mapOptional(Key: "AfterIfMacros", Val&: Spacing.AfterIfMacros);
841 IO.mapOptional(Key: "AfterNot", Val&: Spacing.AfterNot);
842 IO.mapOptional(Key: "AfterOverloadedOperator", Val&: Spacing.AfterOverloadedOperator);
843 IO.mapOptional(Key: "AfterPlacementOperator", Val&: Spacing.AfterPlacementOperator);
844 IO.mapOptional(Key: "AfterRequiresInClause", Val&: Spacing.AfterRequiresInClause);
845 IO.mapOptional(Key: "AfterRequiresInExpression",
846 Val&: Spacing.AfterRequiresInExpression);
847 IO.mapOptional(Key: "BeforeNonEmptyParentheses",
848 Val&: Spacing.BeforeNonEmptyParentheses);
849 }
850};
851
852template <>
853struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> {
854 static void enumeration(IO &IO, FormatStyle::SpaceBeforeParensStyle &Value) {
855 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::SBPO_Never);
856 IO.enumCase(Val&: Value, Str: "ControlStatements",
857 ConstVal: FormatStyle::SBPO_ControlStatements);
858 IO.enumCase(Val&: Value, Str: "ControlStatementsExceptControlMacros",
859 ConstVal: FormatStyle::SBPO_ControlStatementsExceptControlMacros);
860 IO.enumCase(Val&: Value, Str: "NonEmptyParentheses",
861 ConstVal: FormatStyle::SBPO_NonEmptyParentheses);
862 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::SBPO_Always);
863 IO.enumCase(Val&: Value, Str: "Custom", ConstVal: FormatStyle::SBPO_Custom);
864
865 // For backward compatibility.
866 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::SBPO_Never);
867 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::SBPO_ControlStatements);
868 IO.enumCase(Val&: Value, Str: "ControlStatementsExceptForEachMacros",
869 ConstVal: FormatStyle::SBPO_ControlStatementsExceptControlMacros);
870 }
871};
872
873template <>
874struct ScalarEnumerationTraits<FormatStyle::SpaceInEmptyBracesStyle> {
875 static void enumeration(IO &IO, FormatStyle::SpaceInEmptyBracesStyle &Value) {
876 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::SIEB_Always);
877 IO.enumCase(Val&: Value, Str: "Block", ConstVal: FormatStyle::SIEB_Block);
878 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::SIEB_Never);
879 }
880};
881
882template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> {
883 static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value) {
884 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::SIAS_Never);
885 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::SIAS_Always);
886 IO.enumCase(Val&: Value, Str: "Leave", ConstVal: FormatStyle::SIAS_Leave);
887
888 // For backward compatibility.
889 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::SIAS_Never);
890 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::SIAS_Always);
891 }
892};
893
894template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {
895 static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
896 // Transform the maximum to signed, to parse "-1" correctly
897 int signedMaximum = static_cast<int>(Space.Maximum);
898 IO.mapOptional(Key: "Minimum", Val&: Space.Minimum);
899 IO.mapOptional(Key: "Maximum", Val&: signedMaximum);
900 Space.Maximum = static_cast<unsigned>(signedMaximum);
901
902 if (Space.Maximum < std::numeric_limits<unsigned>::max())
903 Space.Minimum = std::min(a: Space.Minimum, b: Space.Maximum);
904 }
905};
906
907template <> struct MappingTraits<FormatStyle::SpacesInParensCustom> {
908 static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) {
909 IO.mapOptional(Key: "ExceptDoubleParentheses", Val&: Spaces.ExceptDoubleParentheses);
910 IO.mapOptional(Key: "InCStyleCasts", Val&: Spaces.InCStyleCasts);
911 IO.mapOptional(Key: "InConditionalStatements", Val&: Spaces.InConditionalStatements);
912 IO.mapOptional(Key: "InEmptyParentheses", Val&: Spaces.InEmptyParentheses);
913 IO.mapOptional(Key: "Other", Val&: Spaces.Other);
914 }
915};
916
917template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInParensStyle> {
918 static void enumeration(IO &IO, FormatStyle::SpacesInParensStyle &Value) {
919 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::SIPO_Never);
920 IO.enumCase(Val&: Value, Str: "Custom", ConstVal: FormatStyle::SIPO_Custom);
921 }
922};
923
924template <> struct ScalarEnumerationTraits<FormatStyle::TrailingCommaStyle> {
925 static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) {
926 IO.enumCase(Val&: Value, Str: "None", ConstVal: FormatStyle::TCS_None);
927 IO.enumCase(Val&: Value, Str: "Wrapped", ConstVal: FormatStyle::TCS_Wrapped);
928 }
929};
930
931template <>
932struct ScalarEnumerationTraits<FormatStyle::TrailingCommentsAlignmentKinds> {
933 static void enumeration(IO &IO,
934 FormatStyle::TrailingCommentsAlignmentKinds &Value) {
935 IO.enumCase(Val&: Value, Str: "Leave", ConstVal: FormatStyle::TCAS_Leave);
936 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::TCAS_Always);
937 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::TCAS_Never);
938 }
939};
940
941template <> struct MappingTraits<FormatStyle::TrailingCommentsAlignmentStyle> {
942 static void enumInput(IO &IO,
943 FormatStyle::TrailingCommentsAlignmentStyle &Value) {
944 IO.enumCase(Val&: Value, Str: "Leave",
945 ConstVal: FormatStyle::TrailingCommentsAlignmentStyle(
946 {.Kind: FormatStyle::TCAS_Leave, .OverEmptyLines: 0, .AlignPPAndNotPP: true}));
947
948 IO.enumCase(Val&: Value, Str: "Always",
949 ConstVal: FormatStyle::TrailingCommentsAlignmentStyle(
950 {.Kind: FormatStyle::TCAS_Always, .OverEmptyLines: 0, .AlignPPAndNotPP: true}));
951
952 IO.enumCase(Val&: Value, Str: "Never",
953 ConstVal: FormatStyle::TrailingCommentsAlignmentStyle(
954 {.Kind: FormatStyle::TCAS_Never, .OverEmptyLines: 0, .AlignPPAndNotPP: true}));
955
956 // For backwards compatibility
957 IO.enumCase(Val&: Value, Str: "true",
958 ConstVal: FormatStyle::TrailingCommentsAlignmentStyle(
959 {.Kind: FormatStyle::TCAS_Always, .OverEmptyLines: 0, .AlignPPAndNotPP: true}));
960 IO.enumCase(Val&: Value, Str: "false",
961 ConstVal: FormatStyle::TrailingCommentsAlignmentStyle(
962 {.Kind: FormatStyle::TCAS_Never, .OverEmptyLines: 0, .AlignPPAndNotPP: true}));
963 }
964
965 static void mapping(IO &IO,
966 FormatStyle::TrailingCommentsAlignmentStyle &Value) {
967 IO.mapOptional(Key: "AlignPPAndNotPP", Val&: Value.AlignPPAndNotPP);
968 IO.mapOptional(Key: "Kind", Val&: Value.Kind);
969 IO.mapOptional(Key: "OverEmptyLines", Val&: Value.OverEmptyLines);
970 }
971};
972
973template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
974 static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {
975 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::UT_Never);
976 IO.enumCase(Val&: Value, Str: "false", ConstVal: FormatStyle::UT_Never);
977 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::UT_Always);
978 IO.enumCase(Val&: Value, Str: "true", ConstVal: FormatStyle::UT_Always);
979 IO.enumCase(Val&: Value, Str: "ForIndentation", ConstVal: FormatStyle::UT_ForIndentation);
980 IO.enumCase(Val&: Value, Str: "ForContinuationAndIndentation",
981 ConstVal: FormatStyle::UT_ForContinuationAndIndentation);
982 IO.enumCase(Val&: Value, Str: "AlignWithSpaces", ConstVal: FormatStyle::UT_AlignWithSpaces);
983 }
984};
985
986template <>
987struct ScalarEnumerationTraits<
988 FormatStyle::WrapNamespaceBodyWithEmptyLinesStyle> {
989 static void
990 enumeration(IO &IO,
991 FormatStyle::WrapNamespaceBodyWithEmptyLinesStyle &Value) {
992 IO.enumCase(Val&: Value, Str: "Never", ConstVal: FormatStyle::WNBWELS_Never);
993 IO.enumCase(Val&: Value, Str: "Always", ConstVal: FormatStyle::WNBWELS_Always);
994 IO.enumCase(Val&: Value, Str: "Leave", ConstVal: FormatStyle::WNBWELS_Leave);
995 }
996};
997
998template <> struct MappingTraits<FormatStyle> {
999 static void mapping(IO &IO, FormatStyle &Style) {
1000 // When reading, read the language first, we need it for getPredefinedStyle.
1001 IO.mapOptional(Key: "Language", Val&: Style.Language);
1002
1003 StringRef BasedOnStyle;
1004 if (IO.outputting()) {
1005 StringRef Styles[] = {"LLVM", "Google", "Chromium", "Mozilla",
1006 "WebKit", "GNU", "Microsoft", "clang-format"};
1007 for (StringRef StyleName : Styles) {
1008 FormatStyle PredefinedStyle;
1009 if (getPredefinedStyle(Name: StyleName, Language: Style.Language, Style: &PredefinedStyle) &&
1010 Style == PredefinedStyle) {
1011 BasedOnStyle = StyleName;
1012 break;
1013 }
1014 }
1015 } else {
1016 IO.mapOptional(Key: "BasedOnStyle", Val&: BasedOnStyle);
1017 if (!BasedOnStyle.empty()) {
1018 FormatStyle::LanguageKind OldLanguage = Style.Language;
1019 FormatStyle::LanguageKind Language =
1020 ((FormatStyle *)IO.getContext())->Language;
1021 if (!getPredefinedStyle(Name: BasedOnStyle, Language, Style: &Style)) {
1022 IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle));
1023 return;
1024 }
1025 Style.Language = OldLanguage;
1026 }
1027 }
1028
1029 // Initialize some variables used in the parsing. The using logic is at the
1030 // end.
1031
1032 // For backward compatibility:
1033 // The default value of ConstructorInitializerAllOnOneLineOrOnePerLine was
1034 // false unless BasedOnStyle was Google or Chromium whereas that of
1035 // AllowAllConstructorInitializersOnNextLine was always true, so the
1036 // equivalent default value of PackConstructorInitializers is PCIS_NextLine
1037 // for Google/Chromium or PCIS_BinPack otherwise. If the deprecated options
1038 // had a non-default value while PackConstructorInitializers has a default
1039 // value, set the latter to an equivalent non-default value if needed.
1040 const bool IsGoogleOrChromium = BasedOnStyle.equals_insensitive(RHS: "google") ||
1041 BasedOnStyle.equals_insensitive(RHS: "chromium");
1042 bool OnCurrentLine = IsGoogleOrChromium;
1043 bool OnNextLine = true;
1044
1045 bool BreakBeforeInheritanceComma = false;
1046 bool BreakConstructorInitializersBeforeComma = false;
1047
1048 bool DeriveLineEnding = true;
1049 bool UseCRLF = false;
1050
1051 bool SpaceInEmptyBlock = false;
1052 bool SpaceInEmptyParentheses = false;
1053 bool SpacesInConditionalStatement = false;
1054 bool SpacesInCStyleCastParentheses = false;
1055 bool SpacesInParentheses = false;
1056
1057 if (IO.outputting()) {
1058 IO.mapOptional(Key: "AlignAfterOpenBracket", Val&: Style.AlignAfterOpenBracket);
1059 } else {
1060 // For backward compatibility.
1061 BracketAlignmentStyle LocalBAS = BAS_Align;
1062 if (IsGoogleOrChromium) {
1063 FormatStyle::LanguageKind Language = Style.Language;
1064 if (Language == FormatStyle::LK_None)
1065 Language = ((FormatStyle *)IO.getContext())->Language;
1066 if (Language == FormatStyle::LK_JavaScript)
1067 LocalBAS = BAS_AlwaysBreak;
1068 else if (Language == FormatStyle::LK_Java)
1069 LocalBAS = BAS_DontAlign;
1070 } else if (BasedOnStyle.equals_insensitive(RHS: "webkit")) {
1071 LocalBAS = BAS_DontAlign;
1072 }
1073 IO.mapOptional(Key: "AlignAfterOpenBracket", Val&: LocalBAS);
1074 Style.BreakAfterOpenBracketBracedList = false;
1075 Style.BreakAfterOpenBracketFunction = false;
1076 Style.BreakAfterOpenBracketIf = false;
1077 Style.BreakAfterOpenBracketLoop = false;
1078 Style.BreakAfterOpenBracketSwitch = false;
1079 Style.BreakBeforeCloseBracketBracedList = false;
1080 Style.BreakBeforeCloseBracketFunction = false;
1081 Style.BreakBeforeCloseBracketIf = false;
1082 Style.BreakBeforeCloseBracketLoop = false;
1083 Style.BreakBeforeCloseBracketSwitch = false;
1084
1085 switch (LocalBAS) {
1086 case BAS_DontAlign:
1087 Style.AlignAfterOpenBracket = false;
1088 break;
1089 case BAS_BlockIndent:
1090 Style.BreakBeforeCloseBracketBracedList = true;
1091 Style.BreakBeforeCloseBracketFunction = true;
1092 Style.BreakBeforeCloseBracketIf = true;
1093 [[fallthrough]];
1094 case BAS_AlwaysBreak:
1095 Style.BreakAfterOpenBracketBracedList = true;
1096 Style.BreakAfterOpenBracketFunction = true;
1097 Style.BreakAfterOpenBracketIf = true;
1098 [[fallthrough]];
1099 case BAS_Align:
1100 Style.AlignAfterOpenBracket = true;
1101 break;
1102 }
1103 }
1104
1105 // For backward compatibility.
1106 if (!IO.outputting()) {
1107 IO.mapOptional(Key: "AlignEscapedNewlinesLeft", Val&: Style.AlignEscapedNewlines);
1108 IO.mapOptional(Key: "AllowAllConstructorInitializersOnNextLine", Val&: OnNextLine);
1109 IO.mapOptional(Key: "AlwaysBreakAfterReturnType", Val&: Style.BreakAfterReturnType);
1110 IO.mapOptional(Key: "AlwaysBreakTemplateDeclarations",
1111 Val&: Style.BreakTemplateDeclarations);
1112 IO.mapOptional(Key: "BreakBeforeInheritanceComma",
1113 Val&: BreakBeforeInheritanceComma);
1114 IO.mapOptional(Key: "BreakConstructorInitializersBeforeComma",
1115 Val&: BreakConstructorInitializersBeforeComma);
1116 IO.mapOptional(Key: "ConstructorInitializerAllOnOneLineOrOnePerLine",
1117 Val&: OnCurrentLine);
1118 IO.mapOptional(Key: "DeriveLineEnding", Val&: DeriveLineEnding);
1119 IO.mapOptional(Key: "DerivePointerBinding", Val&: Style.DerivePointerAlignment);
1120 IO.mapOptional(Key: "KeepEmptyLinesAtEOF", Val&: Style.KeepEmptyLines.AtEndOfFile);
1121 IO.mapOptional(Key: "KeepEmptyLinesAtTheStartOfBlocks",
1122 Val&: Style.KeepEmptyLines.AtStartOfBlock);
1123 IO.mapOptional(Key: "IndentFunctionDeclarationAfterType",
1124 Val&: Style.IndentWrappedFunctionNames);
1125 IO.mapOptional(Key: "IndentRequires", Val&: Style.IndentRequiresClause);
1126 IO.mapOptional(Key: "PointerBindsToType", Val&: Style.PointerAlignment);
1127 IO.mapOptional(Key: "SpaceAfterControlStatementKeyword",
1128 Val&: Style.SpaceBeforeParens);
1129 IO.mapOptional(Key: "SpaceInEmptyBlock", Val&: SpaceInEmptyBlock);
1130 IO.mapOptional(Key: "SpaceInEmptyParentheses", Val&: SpaceInEmptyParentheses);
1131 IO.mapOptional(Key: "SpacesInConditionalStatement",
1132 Val&: SpacesInConditionalStatement);
1133 IO.mapOptional(Key: "SpacesInCStyleCastParentheses",
1134 Val&: SpacesInCStyleCastParentheses);
1135 IO.mapOptional(Key: "SpacesInParentheses", Val&: SpacesInParentheses);
1136 IO.mapOptional(Key: "UseCRLF", Val&: UseCRLF);
1137 }
1138
1139 IO.mapOptional(Key: "AccessModifierOffset", Val&: Style.AccessModifierOffset);
1140 IO.mapOptional(Key: "AlignArrayOfStructures", Val&: Style.AlignArrayOfStructures);
1141 IO.mapOptional(Key: "AlignConsecutiveAssignments",
1142 Val&: Style.AlignConsecutiveAssignments);
1143 IO.mapOptional(Key: "AlignConsecutiveBitFields",
1144 Val&: Style.AlignConsecutiveBitFields);
1145 IO.mapOptional(Key: "AlignConsecutiveDeclarations",
1146 Val&: Style.AlignConsecutiveDeclarations);
1147 IO.mapOptional(Key: "AlignConsecutiveMacros", Val&: Style.AlignConsecutiveMacros);
1148 IO.mapOptional(Key: "AlignConsecutiveShortCaseStatements",
1149 Val&: Style.AlignConsecutiveShortCaseStatements);
1150 IO.mapOptional(Key: "AlignConsecutiveTableGenBreakingDAGArgColons",
1151 Val&: Style.AlignConsecutiveTableGenBreakingDAGArgColons);
1152 IO.mapOptional(Key: "AlignConsecutiveTableGenCondOperatorColons",
1153 Val&: Style.AlignConsecutiveTableGenCondOperatorColons);
1154 IO.mapOptional(Key: "AlignConsecutiveTableGenDefinitionColons",
1155 Val&: Style.AlignConsecutiveTableGenDefinitionColons);
1156 IO.mapOptional(Key: "AlignEscapedNewlines", Val&: Style.AlignEscapedNewlines);
1157 IO.mapOptional(Key: "AlignOperands", Val&: Style.AlignOperands);
1158 IO.mapOptional(Key: "AlignTrailingComments", Val&: Style.AlignTrailingComments);
1159 IO.mapOptional(Key: "AllowAllArgumentsOnNextLine",
1160 Val&: Style.AllowAllArgumentsOnNextLine);
1161 IO.mapOptional(Key: "AllowAllParametersOfDeclarationOnNextLine",
1162 Val&: Style.AllowAllParametersOfDeclarationOnNextLine);
1163 IO.mapOptional(Key: "AllowBreakBeforeNoexceptSpecifier",
1164 Val&: Style.AllowBreakBeforeNoexceptSpecifier);
1165 IO.mapOptional(Key: "AllowBreakBeforeQtProperty",
1166 Val&: Style.AllowBreakBeforeQtProperty);
1167 IO.mapOptional(Key: "AllowShortBlocksOnASingleLine",
1168 Val&: Style.AllowShortBlocksOnASingleLine);
1169 IO.mapOptional(Key: "AllowShortCaseExpressionOnASingleLine",
1170 Val&: Style.AllowShortCaseExpressionOnASingleLine);
1171 IO.mapOptional(Key: "AllowShortCaseLabelsOnASingleLine",
1172 Val&: Style.AllowShortCaseLabelsOnASingleLine);
1173 IO.mapOptional(Key: "AllowShortCompoundRequirementOnASingleLine",
1174 Val&: Style.AllowShortCompoundRequirementOnASingleLine);
1175 IO.mapOptional(Key: "AllowShortEnumsOnASingleLine",
1176 Val&: Style.AllowShortEnumsOnASingleLine);
1177 IO.mapOptional(Key: "AllowShortFunctionsOnASingleLine",
1178 Val&: Style.AllowShortFunctionsOnASingleLine);
1179 IO.mapOptional(Key: "AllowShortIfStatementsOnASingleLine",
1180 Val&: Style.AllowShortIfStatementsOnASingleLine);
1181 IO.mapOptional(Key: "AllowShortLambdasOnASingleLine",
1182 Val&: Style.AllowShortLambdasOnASingleLine);
1183 IO.mapOptional(Key: "AllowShortLoopsOnASingleLine",
1184 Val&: Style.AllowShortLoopsOnASingleLine);
1185 IO.mapOptional(Key: "AllowShortNamespacesOnASingleLine",
1186 Val&: Style.AllowShortNamespacesOnASingleLine);
1187 IO.mapOptional(Key: "AlwaysBreakAfterDefinitionReturnType",
1188 Val&: Style.AlwaysBreakAfterDefinitionReturnType);
1189 IO.mapOptional(Key: "AlwaysBreakBeforeMultilineStrings",
1190 Val&: Style.AlwaysBreakBeforeMultilineStrings);
1191 IO.mapOptional(Key: "AttributeMacros", Val&: Style.AttributeMacros);
1192 IO.mapOptional(Key: "BinPackArguments", Val&: Style.BinPackArguments);
1193 IO.mapOptional(Key: "BinPackLongBracedList", Val&: Style.BinPackLongBracedList);
1194 IO.mapOptional(Key: "BinPackParameters", Val&: Style.BinPackParameters);
1195 IO.mapOptional(Key: "BitFieldColonSpacing", Val&: Style.BitFieldColonSpacing);
1196 IO.mapOptional(Key: "BracedInitializerIndentWidth",
1197 Val&: Style.BracedInitializerIndentWidth);
1198 IO.mapOptional(Key: "BraceWrapping", Val&: Style.BraceWrapping);
1199 IO.mapOptional(Key: "BreakAdjacentStringLiterals",
1200 Val&: Style.BreakAdjacentStringLiterals);
1201 IO.mapOptional(Key: "BreakAfterAttributes", Val&: Style.BreakAfterAttributes);
1202 IO.mapOptional(Key: "BreakAfterJavaFieldAnnotations",
1203 Val&: Style.BreakAfterJavaFieldAnnotations);
1204 IO.mapOptional(Key: "BreakAfterOpenBracketBracedList",
1205 Val&: Style.BreakAfterOpenBracketBracedList);
1206 IO.mapOptional(Key: "BreakAfterOpenBracketFunction",
1207 Val&: Style.BreakAfterOpenBracketFunction);
1208 IO.mapOptional(Key: "BreakAfterOpenBracketIf", Val&: Style.BreakAfterOpenBracketIf);
1209 IO.mapOptional(Key: "BreakAfterOpenBracketLoop",
1210 Val&: Style.BreakAfterOpenBracketLoop);
1211 IO.mapOptional(Key: "BreakAfterOpenBracketSwitch",
1212 Val&: Style.BreakAfterOpenBracketSwitch);
1213 IO.mapOptional(Key: "BreakAfterReturnType", Val&: Style.BreakAfterReturnType);
1214 IO.mapOptional(Key: "BreakArrays", Val&: Style.BreakArrays);
1215 IO.mapOptional(Key: "BreakBeforeBinaryOperators",
1216 Val&: Style.BreakBeforeBinaryOperators);
1217 IO.mapOptional(Key: "BreakBeforeCloseBracketBracedList",
1218 Val&: Style.BreakBeforeCloseBracketBracedList);
1219 IO.mapOptional(Key: "BreakBeforeCloseBracketFunction",
1220 Val&: Style.BreakBeforeCloseBracketFunction);
1221 IO.mapOptional(Key: "BreakBeforeCloseBracketIf",
1222 Val&: Style.BreakBeforeCloseBracketIf);
1223 IO.mapOptional(Key: "BreakBeforeCloseBracketLoop",
1224 Val&: Style.BreakBeforeCloseBracketLoop);
1225 IO.mapOptional(Key: "BreakBeforeCloseBracketSwitch",
1226 Val&: Style.BreakBeforeCloseBracketSwitch);
1227 IO.mapOptional(Key: "BreakBeforeConceptDeclarations",
1228 Val&: Style.BreakBeforeConceptDeclarations);
1229 IO.mapOptional(Key: "BreakBeforeBraces", Val&: Style.BreakBeforeBraces);
1230 IO.mapOptional(Key: "BreakBeforeInlineASMColon",
1231 Val&: Style.BreakBeforeInlineASMColon);
1232 IO.mapOptional(Key: "BreakBeforeTemplateCloser",
1233 Val&: Style.BreakBeforeTemplateCloser);
1234 IO.mapOptional(Key: "BreakBeforeTernaryOperators",
1235 Val&: Style.BreakBeforeTernaryOperators);
1236 IO.mapOptional(Key: "BreakBinaryOperations", Val&: Style.BreakBinaryOperations);
1237 IO.mapOptional(Key: "BreakConstructorInitializers",
1238 Val&: Style.BreakConstructorInitializers);
1239 IO.mapOptional(Key: "BreakFunctionDefinitionParameters",
1240 Val&: Style.BreakFunctionDefinitionParameters);
1241 IO.mapOptional(Key: "BreakInheritanceList", Val&: Style.BreakInheritanceList);
1242 IO.mapOptional(Key: "BreakStringLiterals", Val&: Style.BreakStringLiterals);
1243 IO.mapOptional(Key: "BreakTemplateDeclarations",
1244 Val&: Style.BreakTemplateDeclarations);
1245 IO.mapOptional(Key: "ColumnLimit", Val&: Style.ColumnLimit);
1246 IO.mapOptional(Key: "CommentPragmas", Val&: Style.CommentPragmas);
1247 IO.mapOptional(Key: "CompactNamespaces", Val&: Style.CompactNamespaces);
1248 IO.mapOptional(Key: "ConstructorInitializerIndentWidth",
1249 Val&: Style.ConstructorInitializerIndentWidth);
1250 IO.mapOptional(Key: "ContinuationIndentWidth", Val&: Style.ContinuationIndentWidth);
1251 IO.mapOptional(Key: "Cpp11BracedListStyle", Val&: Style.Cpp11BracedListStyle);
1252 IO.mapOptional(Key: "DerivePointerAlignment", Val&: Style.DerivePointerAlignment);
1253 IO.mapOptional(Key: "DisableFormat", Val&: Style.DisableFormat);
1254 IO.mapOptional(Key: "EmptyLineAfterAccessModifier",
1255 Val&: Style.EmptyLineAfterAccessModifier);
1256 IO.mapOptional(Key: "EmptyLineBeforeAccessModifier",
1257 Val&: Style.EmptyLineBeforeAccessModifier);
1258 IO.mapOptional(Key: "EnumTrailingComma", Val&: Style.EnumTrailingComma);
1259 IO.mapOptional(Key: "ExperimentalAutoDetectBinPacking",
1260 Val&: Style.ExperimentalAutoDetectBinPacking);
1261 IO.mapOptional(Key: "FixNamespaceComments", Val&: Style.FixNamespaceComments);
1262 IO.mapOptional(Key: "ForEachMacros", Val&: Style.ForEachMacros);
1263 IO.mapOptional(Key: "IfMacros", Val&: Style.IfMacros);
1264 IO.mapOptional(Key: "IncludeBlocks", Val&: Style.IncludeStyle.IncludeBlocks);
1265 IO.mapOptional(Key: "IncludeCategories", Val&: Style.IncludeStyle.IncludeCategories);
1266 IO.mapOptional(Key: "IncludeIsMainRegex", Val&: Style.IncludeStyle.IncludeIsMainRegex);
1267 IO.mapOptional(Key: "IncludeIsMainSourceRegex",
1268 Val&: Style.IncludeStyle.IncludeIsMainSourceRegex);
1269 IO.mapOptional(Key: "IndentAccessModifiers", Val&: Style.IndentAccessModifiers);
1270 IO.mapOptional(Key: "IndentCaseBlocks", Val&: Style.IndentCaseBlocks);
1271 IO.mapOptional(Key: "IndentCaseLabels", Val&: Style.IndentCaseLabels);
1272 IO.mapOptional(Key: "IndentExportBlock", Val&: Style.IndentExportBlock);
1273 IO.mapOptional(Key: "IndentExternBlock", Val&: Style.IndentExternBlock);
1274 IO.mapOptional(Key: "IndentGotoLabels", Val&: Style.IndentGotoLabels);
1275 IO.mapOptional(Key: "IndentPPDirectives", Val&: Style.IndentPPDirectives);
1276 IO.mapOptional(Key: "IndentRequiresClause", Val&: Style.IndentRequiresClause);
1277 IO.mapOptional(Key: "IndentWidth", Val&: Style.IndentWidth);
1278 IO.mapOptional(Key: "IndentWrappedFunctionNames",
1279 Val&: Style.IndentWrappedFunctionNames);
1280 IO.mapOptional(Key: "InsertBraces", Val&: Style.InsertBraces);
1281 IO.mapOptional(Key: "InsertNewlineAtEOF", Val&: Style.InsertNewlineAtEOF);
1282 IO.mapOptional(Key: "InsertTrailingCommas", Val&: Style.InsertTrailingCommas);
1283 IO.mapOptional(Key: "IntegerLiteralSeparator", Val&: Style.IntegerLiteralSeparator);
1284 IO.mapOptional(Key: "JavaImportGroups", Val&: Style.JavaImportGroups);
1285 IO.mapOptional(Key: "JavaScriptQuotes", Val&: Style.JavaScriptQuotes);
1286 IO.mapOptional(Key: "JavaScriptWrapImports", Val&: Style.JavaScriptWrapImports);
1287 IO.mapOptional(Key: "KeepEmptyLines", Val&: Style.KeepEmptyLines);
1288 IO.mapOptional(Key: "KeepFormFeed", Val&: Style.KeepFormFeed);
1289 IO.mapOptional(Key: "LambdaBodyIndentation", Val&: Style.LambdaBodyIndentation);
1290 IO.mapOptional(Key: "LineEnding", Val&: Style.LineEnding);
1291 IO.mapOptional(Key: "MacroBlockBegin", Val&: Style.MacroBlockBegin);
1292 IO.mapOptional(Key: "MacroBlockEnd", Val&: Style.MacroBlockEnd);
1293 IO.mapOptional(Key: "Macros", Val&: Style.Macros);
1294 IO.mapOptional(Key: "MacrosSkippedByRemoveParentheses",
1295 Val&: Style.MacrosSkippedByRemoveParentheses);
1296 IO.mapOptional(Key: "MainIncludeChar", Val&: Style.IncludeStyle.MainIncludeChar);
1297 IO.mapOptional(Key: "MaxEmptyLinesToKeep", Val&: Style.MaxEmptyLinesToKeep);
1298 IO.mapOptional(Key: "NamespaceIndentation", Val&: Style.NamespaceIndentation);
1299 IO.mapOptional(Key: "NamespaceMacros", Val&: Style.NamespaceMacros);
1300 IO.mapOptional(Key: "NumericLiteralCase", Val&: Style.NumericLiteralCase);
1301 IO.mapOptional(Key: "ObjCBinPackProtocolList", Val&: Style.ObjCBinPackProtocolList);
1302 IO.mapOptional(Key: "ObjCBlockIndentWidth", Val&: Style.ObjCBlockIndentWidth);
1303 IO.mapOptional(Key: "ObjCBreakBeforeNestedBlockParam",
1304 Val&: Style.ObjCBreakBeforeNestedBlockParam);
1305 IO.mapOptional(Key: "ObjCPropertyAttributeOrder",
1306 Val&: Style.ObjCPropertyAttributeOrder);
1307 IO.mapOptional(Key: "ObjCSpaceAfterMethodDeclarationPrefix",
1308 Val&: Style.ObjCSpaceAfterMethodDeclarationPrefix);
1309 IO.mapOptional(Key: "ObjCSpaceAfterProperty", Val&: Style.ObjCSpaceAfterProperty);
1310 IO.mapOptional(Key: "ObjCSpaceBeforeProtocolList",
1311 Val&: Style.ObjCSpaceBeforeProtocolList);
1312 IO.mapOptional(Key: "OneLineFormatOffRegex", Val&: Style.OneLineFormatOffRegex);
1313 IO.mapOptional(Key: "PackConstructorInitializers",
1314 Val&: Style.PackConstructorInitializers);
1315 IO.mapOptional(Key: "PenaltyBreakAssignment", Val&: Style.PenaltyBreakAssignment);
1316 IO.mapOptional(Key: "PenaltyBreakBeforeFirstCallParameter",
1317 Val&: Style.PenaltyBreakBeforeFirstCallParameter);
1318 IO.mapOptional(Key: "PenaltyBreakBeforeMemberAccess",
1319 Val&: Style.PenaltyBreakBeforeMemberAccess);
1320 IO.mapOptional(Key: "PenaltyBreakComment", Val&: Style.PenaltyBreakComment);
1321 IO.mapOptional(Key: "PenaltyBreakFirstLessLess",
1322 Val&: Style.PenaltyBreakFirstLessLess);
1323 IO.mapOptional(Key: "PenaltyBreakOpenParenthesis",
1324 Val&: Style.PenaltyBreakOpenParenthesis);
1325 IO.mapOptional(Key: "PenaltyBreakScopeResolution",
1326 Val&: Style.PenaltyBreakScopeResolution);
1327 IO.mapOptional(Key: "PenaltyBreakString", Val&: Style.PenaltyBreakString);
1328 IO.mapOptional(Key: "PenaltyBreakTemplateDeclaration",
1329 Val&: Style.PenaltyBreakTemplateDeclaration);
1330 IO.mapOptional(Key: "PenaltyExcessCharacter", Val&: Style.PenaltyExcessCharacter);
1331 IO.mapOptional(Key: "PenaltyIndentedWhitespace",
1332 Val&: Style.PenaltyIndentedWhitespace);
1333 IO.mapOptional(Key: "PenaltyReturnTypeOnItsOwnLine",
1334 Val&: Style.PenaltyReturnTypeOnItsOwnLine);
1335 IO.mapOptional(Key: "PointerAlignment", Val&: Style.PointerAlignment);
1336 IO.mapOptional(Key: "PPIndentWidth", Val&: Style.PPIndentWidth);
1337 IO.mapOptional(Key: "QualifierAlignment", Val&: Style.QualifierAlignment);
1338 // Default Order for Left/Right based Qualifier alignment.
1339 if (Style.QualifierAlignment == FormatStyle::QAS_Right)
1340 Style.QualifierOrder = {"type", "const", "volatile"};
1341 else if (Style.QualifierAlignment == FormatStyle::QAS_Left)
1342 Style.QualifierOrder = {"const", "volatile", "type"};
1343 else if (Style.QualifierAlignment == FormatStyle::QAS_Custom)
1344 IO.mapOptional(Key: "QualifierOrder", Val&: Style.QualifierOrder);
1345 IO.mapOptional(Key: "RawStringFormats", Val&: Style.RawStringFormats);
1346 IO.mapOptional(Key: "ReferenceAlignment", Val&: Style.ReferenceAlignment);
1347 IO.mapOptional(Key: "ReflowComments", Val&: Style.ReflowComments);
1348 IO.mapOptional(Key: "RemoveBracesLLVM", Val&: Style.RemoveBracesLLVM);
1349 IO.mapOptional(Key: "RemoveEmptyLinesInUnwrappedLines",
1350 Val&: Style.RemoveEmptyLinesInUnwrappedLines);
1351 IO.mapOptional(Key: "RemoveParentheses", Val&: Style.RemoveParentheses);
1352 IO.mapOptional(Key: "RemoveSemicolon", Val&: Style.RemoveSemicolon);
1353 IO.mapOptional(Key: "RequiresClausePosition", Val&: Style.RequiresClausePosition);
1354 IO.mapOptional(Key: "RequiresExpressionIndentation",
1355 Val&: Style.RequiresExpressionIndentation);
1356 IO.mapOptional(Key: "SeparateDefinitionBlocks", Val&: Style.SeparateDefinitionBlocks);
1357 IO.mapOptional(Key: "ShortNamespaceLines", Val&: Style.ShortNamespaceLines);
1358 IO.mapOptional(Key: "SkipMacroDefinitionBody", Val&: Style.SkipMacroDefinitionBody);
1359 IO.mapOptional(Key: "SortIncludes", Val&: Style.SortIncludes);
1360 IO.mapOptional(Key: "SortJavaStaticImport", Val&: Style.SortJavaStaticImport);
1361 IO.mapOptional(Key: "SortUsingDeclarations", Val&: Style.SortUsingDeclarations);
1362 IO.mapOptional(Key: "SpaceAfterCStyleCast", Val&: Style.SpaceAfterCStyleCast);
1363 IO.mapOptional(Key: "SpaceAfterLogicalNot", Val&: Style.SpaceAfterLogicalNot);
1364 IO.mapOptional(Key: "SpaceAfterOperatorKeyword",
1365 Val&: Style.SpaceAfterOperatorKeyword);
1366 IO.mapOptional(Key: "SpaceAfterTemplateKeyword",
1367 Val&: Style.SpaceAfterTemplateKeyword);
1368 IO.mapOptional(Key: "SpaceAroundPointerQualifiers",
1369 Val&: Style.SpaceAroundPointerQualifiers);
1370 IO.mapOptional(Key: "SpaceBeforeAssignmentOperators",
1371 Val&: Style.SpaceBeforeAssignmentOperators);
1372 IO.mapOptional(Key: "SpaceBeforeCaseColon", Val&: Style.SpaceBeforeCaseColon);
1373 IO.mapOptional(Key: "SpaceBeforeCpp11BracedList",
1374 Val&: Style.SpaceBeforeCpp11BracedList);
1375 IO.mapOptional(Key: "SpaceBeforeCtorInitializerColon",
1376 Val&: Style.SpaceBeforeCtorInitializerColon);
1377 IO.mapOptional(Key: "SpaceBeforeInheritanceColon",
1378 Val&: Style.SpaceBeforeInheritanceColon);
1379 IO.mapOptional(Key: "SpaceBeforeJsonColon", Val&: Style.SpaceBeforeJsonColon);
1380 IO.mapOptional(Key: "SpaceBeforeParens", Val&: Style.SpaceBeforeParens);
1381 IO.mapOptional(Key: "SpaceBeforeParensOptions", Val&: Style.SpaceBeforeParensOptions);
1382 IO.mapOptional(Key: "SpaceBeforeRangeBasedForLoopColon",
1383 Val&: Style.SpaceBeforeRangeBasedForLoopColon);
1384 IO.mapOptional(Key: "SpaceBeforeSquareBrackets",
1385 Val&: Style.SpaceBeforeSquareBrackets);
1386 IO.mapOptional(Key: "SpaceInEmptyBraces", Val&: Style.SpaceInEmptyBraces);
1387 IO.mapOptional(Key: "SpacesBeforeTrailingComments",
1388 Val&: Style.SpacesBeforeTrailingComments);
1389 IO.mapOptional(Key: "SpacesInAngles", Val&: Style.SpacesInAngles);
1390 IO.mapOptional(Key: "SpacesInContainerLiterals",
1391 Val&: Style.SpacesInContainerLiterals);
1392 IO.mapOptional(Key: "SpacesInLineCommentPrefix",
1393 Val&: Style.SpacesInLineCommentPrefix);
1394 IO.mapOptional(Key: "SpacesInParens", Val&: Style.SpacesInParens);
1395 IO.mapOptional(Key: "SpacesInParensOptions", Val&: Style.SpacesInParensOptions);
1396 IO.mapOptional(Key: "SpacesInSquareBrackets", Val&: Style.SpacesInSquareBrackets);
1397 IO.mapOptional(Key: "Standard", Val&: Style.Standard);
1398 IO.mapOptional(Key: "StatementAttributeLikeMacros",
1399 Val&: Style.StatementAttributeLikeMacros);
1400 IO.mapOptional(Key: "StatementMacros", Val&: Style.StatementMacros);
1401 IO.mapOptional(Key: "TableGenBreakingDAGArgOperators",
1402 Val&: Style.TableGenBreakingDAGArgOperators);
1403 IO.mapOptional(Key: "TableGenBreakInsideDAGArg",
1404 Val&: Style.TableGenBreakInsideDAGArg);
1405 IO.mapOptional(Key: "TabWidth", Val&: Style.TabWidth);
1406 IO.mapOptional(Key: "TemplateNames", Val&: Style.TemplateNames);
1407 IO.mapOptional(Key: "TypeNames", Val&: Style.TypeNames);
1408 IO.mapOptional(Key: "TypenameMacros", Val&: Style.TypenameMacros);
1409 IO.mapOptional(Key: "UseTab", Val&: Style.UseTab);
1410 IO.mapOptional(Key: "VariableTemplates", Val&: Style.VariableTemplates);
1411 IO.mapOptional(Key: "VerilogBreakBetweenInstancePorts",
1412 Val&: Style.VerilogBreakBetweenInstancePorts);
1413 IO.mapOptional(Key: "WhitespaceSensitiveMacros",
1414 Val&: Style.WhitespaceSensitiveMacros);
1415 IO.mapOptional(Key: "WrapNamespaceBodyWithEmptyLines",
1416 Val&: Style.WrapNamespaceBodyWithEmptyLines);
1417
1418 // If AlwaysBreakAfterDefinitionReturnType was specified but
1419 // BreakAfterReturnType was not, initialize the latter from the former for
1420 // backwards compatibility.
1421 if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&
1422 Style.BreakAfterReturnType == FormatStyle::RTBS_None) {
1423 if (Style.AlwaysBreakAfterDefinitionReturnType ==
1424 FormatStyle::DRTBS_All) {
1425 Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
1426 } else if (Style.AlwaysBreakAfterDefinitionReturnType ==
1427 FormatStyle::DRTBS_TopLevel) {
1428 Style.BreakAfterReturnType = FormatStyle::RTBS_TopLevelDefinitions;
1429 }
1430 }
1431
1432 // If BreakBeforeInheritanceComma was specified but BreakInheritance was
1433 // not, initialize the latter from the former for backwards compatibility.
1434 if (BreakBeforeInheritanceComma &&
1435 Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) {
1436 Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
1437 }
1438
1439 // If BreakConstructorInitializersBeforeComma was specified but
1440 // BreakConstructorInitializers was not, initialize the latter from the
1441 // former for backwards compatibility.
1442 if (BreakConstructorInitializersBeforeComma &&
1443 Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon) {
1444 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
1445 }
1446
1447 if (!IsGoogleOrChromium) {
1448 if (Style.PackConstructorInitializers == FormatStyle::PCIS_BinPack &&
1449 OnCurrentLine) {
1450 Style.PackConstructorInitializers = OnNextLine
1451 ? FormatStyle::PCIS_NextLine
1452 : FormatStyle::PCIS_CurrentLine;
1453 }
1454 } else if (Style.PackConstructorInitializers ==
1455 FormatStyle::PCIS_NextLine) {
1456 if (!OnCurrentLine)
1457 Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
1458 else if (!OnNextLine)
1459 Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine;
1460 }
1461
1462 if (Style.LineEnding == FormatStyle::LE_DeriveLF) {
1463 if (!DeriveLineEnding)
1464 Style.LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF;
1465 else if (UseCRLF)
1466 Style.LineEnding = FormatStyle::LE_DeriveCRLF;
1467 }
1468
1469 // If SpaceInEmptyBlock was specified but SpaceInEmptyBraces was not,
1470 // initialize the latter from the former for backward compatibility.
1471 if (SpaceInEmptyBlock &&
1472 Style.SpaceInEmptyBraces == FormatStyle::SIEB_Never) {
1473 Style.SpaceInEmptyBraces = FormatStyle::SIEB_Block;
1474 }
1475
1476 if (Style.SpacesInParens != FormatStyle::SIPO_Custom &&
1477 (SpacesInParentheses || SpaceInEmptyParentheses ||
1478 SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) {
1479 if (SpacesInParentheses) {
1480 // For backward compatibility.
1481 Style.SpacesInParensOptions.ExceptDoubleParentheses = false;
1482 Style.SpacesInParensOptions.InConditionalStatements = true;
1483 Style.SpacesInParensOptions.InCStyleCasts =
1484 SpacesInCStyleCastParentheses;
1485 Style.SpacesInParensOptions.InEmptyParentheses =
1486 SpaceInEmptyParentheses;
1487 Style.SpacesInParensOptions.Other = true;
1488 } else {
1489 Style.SpacesInParensOptions = {};
1490 Style.SpacesInParensOptions.InConditionalStatements =
1491 SpacesInConditionalStatement;
1492 Style.SpacesInParensOptions.InCStyleCasts =
1493 SpacesInCStyleCastParentheses;
1494 Style.SpacesInParensOptions.InEmptyParentheses =
1495 SpaceInEmptyParentheses;
1496 }
1497 Style.SpacesInParens = FormatStyle::SIPO_Custom;
1498 }
1499 }
1500};
1501
1502// Allows to read vector<FormatStyle> while keeping default values.
1503// IO.getContext() should contain a pointer to the FormatStyle structure, that
1504// will be used to get default values for missing keys.
1505// If the first element has no Language specified, it will be treated as the
1506// default one for the following elements.
1507template <> struct DocumentListTraits<std::vector<FormatStyle>> {
1508 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
1509 return Seq.size();
1510 }
1511 static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq,
1512 size_t Index) {
1513 if (Index >= Seq.size()) {
1514 assert(Index == Seq.size());
1515 FormatStyle Template;
1516 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
1517 Template = Seq[0];
1518 } else {
1519 Template = *((const FormatStyle *)IO.getContext());
1520 Template.Language = FormatStyle::LK_None;
1521 }
1522 Seq.resize(new_size: Index + 1, x: Template);
1523 }
1524 return Seq[Index];
1525 }
1526};
1527} // namespace yaml
1528} // namespace llvm
1529
1530namespace clang {
1531namespace format {
1532
1533const std::error_category &getParseCategory() {
1534 static const ParseErrorCategory C{};
1535 return C;
1536}
1537std::error_code make_error_code(ParseError e) {
1538 return std::error_code(static_cast<int>(e), getParseCategory());
1539}
1540
1541inline llvm::Error make_string_error(const Twine &Message) {
1542 return llvm::make_error<llvm::StringError>(Args: Message,
1543 Args: llvm::inconvertibleErrorCode());
1544}
1545
1546const char *ParseErrorCategory::name() const noexcept {
1547 return "clang-format.parse_error";
1548}
1549
1550std::string ParseErrorCategory::message(int EV) const {
1551 switch (static_cast<ParseError>(EV)) {
1552 case ParseError::Success:
1553 return "Success";
1554 case ParseError::Error:
1555 return "Invalid argument";
1556 case ParseError::Unsuitable:
1557 return "Unsuitable";
1558 case ParseError::BinPackTrailingCommaConflict:
1559 return "trailing comma insertion cannot be used with bin packing";
1560 case ParseError::InvalidQualifierSpecified:
1561 return "Invalid qualifier specified in QualifierOrder";
1562 case ParseError::DuplicateQualifierSpecified:
1563 return "Duplicate qualifier specified in QualifierOrder";
1564 case ParseError::MissingQualifierType:
1565 return "Missing type in QualifierOrder";
1566 case ParseError::MissingQualifierOrder:
1567 return "Missing QualifierOrder";
1568 }
1569 llvm_unreachable("unexpected parse error");
1570}
1571
1572static void expandPresetsBraceWrapping(FormatStyle &Expanded) {
1573 if (Expanded.BreakBeforeBraces == FormatStyle::BS_Custom)
1574 return;
1575 Expanded.BraceWrapping = {/*AfterCaseLabel=*/false,
1576 /*AfterClass=*/false,
1577 /*AfterControlStatement=*/FormatStyle::BWACS_Never,
1578 /*AfterEnum=*/false,
1579 /*AfterFunction=*/false,
1580 /*AfterNamespace=*/false,
1581 /*AfterObjCDeclaration=*/false,
1582 /*AfterStruct=*/false,
1583 /*AfterUnion=*/false,
1584 /*AfterExternBlock=*/false,
1585 /*BeforeCatch=*/false,
1586 /*BeforeElse=*/false,
1587 /*BeforeLambdaBody=*/false,
1588 /*BeforeWhile=*/false,
1589 /*IndentBraces=*/false,
1590 /*SplitEmptyFunction=*/true,
1591 /*SplitEmptyRecord=*/true,
1592 /*SplitEmptyNamespace=*/true};
1593 switch (Expanded.BreakBeforeBraces) {
1594 case FormatStyle::BS_Linux:
1595 Expanded.BraceWrapping.AfterClass = true;
1596 Expanded.BraceWrapping.AfterFunction = true;
1597 Expanded.BraceWrapping.AfterNamespace = true;
1598 break;
1599 case FormatStyle::BS_Mozilla:
1600 Expanded.BraceWrapping.AfterClass = true;
1601 Expanded.BraceWrapping.AfterEnum = true;
1602 Expanded.BraceWrapping.AfterFunction = true;
1603 Expanded.BraceWrapping.AfterStruct = true;
1604 Expanded.BraceWrapping.AfterUnion = true;
1605 Expanded.BraceWrapping.AfterExternBlock = true;
1606 Expanded.BraceWrapping.SplitEmptyFunction = true;
1607 Expanded.BraceWrapping.SplitEmptyRecord = false;
1608 break;
1609 case FormatStyle::BS_Stroustrup:
1610 Expanded.BraceWrapping.AfterFunction = true;
1611 Expanded.BraceWrapping.BeforeCatch = true;
1612 Expanded.BraceWrapping.BeforeElse = true;
1613 break;
1614 case FormatStyle::BS_Allman:
1615 Expanded.BraceWrapping.AfterCaseLabel = true;
1616 Expanded.BraceWrapping.AfterClass = true;
1617 Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
1618 Expanded.BraceWrapping.AfterEnum = true;
1619 Expanded.BraceWrapping.AfterFunction = true;
1620 Expanded.BraceWrapping.AfterNamespace = true;
1621 Expanded.BraceWrapping.AfterObjCDeclaration = true;
1622 Expanded.BraceWrapping.AfterStruct = true;
1623 Expanded.BraceWrapping.AfterUnion = true;
1624 Expanded.BraceWrapping.AfterExternBlock = true;
1625 Expanded.BraceWrapping.BeforeCatch = true;
1626 Expanded.BraceWrapping.BeforeElse = true;
1627 Expanded.BraceWrapping.BeforeLambdaBody = true;
1628 break;
1629 case FormatStyle::BS_Whitesmiths:
1630 Expanded.BraceWrapping.AfterCaseLabel = true;
1631 Expanded.BraceWrapping.AfterClass = true;
1632 Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
1633 Expanded.BraceWrapping.AfterEnum = true;
1634 Expanded.BraceWrapping.AfterFunction = true;
1635 Expanded.BraceWrapping.AfterNamespace = true;
1636 Expanded.BraceWrapping.AfterObjCDeclaration = true;
1637 Expanded.BraceWrapping.AfterStruct = true;
1638 Expanded.BraceWrapping.AfterExternBlock = true;
1639 Expanded.BraceWrapping.BeforeCatch = true;
1640 Expanded.BraceWrapping.BeforeElse = true;
1641 Expanded.BraceWrapping.BeforeLambdaBody = true;
1642 break;
1643 case FormatStyle::BS_GNU:
1644 Expanded.BraceWrapping = {
1645 /*AfterCaseLabel=*/true,
1646 /*AfterClass=*/true,
1647 /*AfterControlStatement=*/FormatStyle::BWACS_Always,
1648 /*AfterEnum=*/true,
1649 /*AfterFunction=*/true,
1650 /*AfterNamespace=*/true,
1651 /*AfterObjCDeclaration=*/true,
1652 /*AfterStruct=*/true,
1653 /*AfterUnion=*/true,
1654 /*AfterExternBlock=*/true,
1655 /*BeforeCatch=*/true,
1656 /*BeforeElse=*/true,
1657 /*BeforeLambdaBody=*/true,
1658 /*BeforeWhile=*/true,
1659 /*IndentBraces=*/true,
1660 /*SplitEmptyFunction=*/true,
1661 /*SplitEmptyRecord=*/true,
1662 /*SplitEmptyNamespace=*/true};
1663 break;
1664 case FormatStyle::BS_WebKit:
1665 Expanded.BraceWrapping.AfterFunction = true;
1666 break;
1667 default:
1668 break;
1669 }
1670}
1671
1672static void expandPresetsSpaceBeforeParens(FormatStyle &Expanded) {
1673 if (Expanded.SpaceBeforeParens == FormatStyle::SBPO_Custom)
1674 return;
1675 // Reset all flags
1676 Expanded.SpaceBeforeParensOptions = {};
1677 Expanded.SpaceBeforeParensOptions.AfterPlacementOperator = true;
1678
1679 switch (Expanded.SpaceBeforeParens) {
1680 case FormatStyle::SBPO_ControlStatements:
1681 Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;
1682 Expanded.SpaceBeforeParensOptions.AfterForeachMacros = true;
1683 Expanded.SpaceBeforeParensOptions.AfterIfMacros = true;
1684 break;
1685 case FormatStyle::SBPO_ControlStatementsExceptControlMacros:
1686 Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;
1687 break;
1688 case FormatStyle::SBPO_NonEmptyParentheses:
1689 Expanded.SpaceBeforeParensOptions.BeforeNonEmptyParentheses = true;
1690 break;
1691 default:
1692 break;
1693 }
1694}
1695
1696static void expandPresetsSpacesInParens(FormatStyle &Expanded) {
1697 if (Expanded.SpacesInParens == FormatStyle::SIPO_Custom)
1698 return;
1699 assert(Expanded.SpacesInParens == FormatStyle::SIPO_Never);
1700 // Reset all flags
1701 Expanded.SpacesInParensOptions = {};
1702}
1703
1704FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
1705 FormatStyle LLVMStyle;
1706 LLVMStyle.AccessModifierOffset = -2;
1707 LLVMStyle.AlignAfterOpenBracket = true;
1708 LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;
1709 LLVMStyle.AlignConsecutiveAssignments = {};
1710 LLVMStyle.AlignConsecutiveAssignments.PadOperators = true;
1711 LLVMStyle.AlignConsecutiveBitFields = {};
1712 LLVMStyle.AlignConsecutiveDeclarations = {};
1713 LLVMStyle.AlignConsecutiveDeclarations.AlignFunctionDeclarations = true;
1714 LLVMStyle.AlignConsecutiveMacros = {};
1715 LLVMStyle.AlignConsecutiveShortCaseStatements = {};
1716 LLVMStyle.AlignConsecutiveTableGenBreakingDAGArgColons = {};
1717 LLVMStyle.AlignConsecutiveTableGenCondOperatorColons = {};
1718 LLVMStyle.AlignConsecutiveTableGenDefinitionColons = {};
1719 LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
1720 LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
1721 LLVMStyle.AlignTrailingComments = {};
1722 LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always;
1723 LLVMStyle.AlignTrailingComments.OverEmptyLines = 0;
1724 LLVMStyle.AlignTrailingComments.AlignPPAndNotPP = true;
1725 LLVMStyle.AllowAllArgumentsOnNextLine = true;
1726 LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
1727 LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;
1728 LLVMStyle.AllowBreakBeforeQtProperty = false;
1729 LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
1730 LLVMStyle.AllowShortCaseExpressionOnASingleLine = true;
1731 LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
1732 LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true;
1733 LLVMStyle.AllowShortEnumsOnASingleLine = true;
1734 LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
1735 LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
1736 LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
1737 LLVMStyle.AllowShortLoopsOnASingleLine = false;
1738 LLVMStyle.AllowShortNamespacesOnASingleLine = false;
1739 LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
1740 LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
1741 LLVMStyle.AttributeMacros.push_back(x: "__capability");
1742 LLVMStyle.BinPackArguments = true;
1743 LLVMStyle.BinPackLongBracedList = true;
1744 LLVMStyle.BinPackParameters = FormatStyle::BPPS_BinPack;
1745 LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;
1746 LLVMStyle.BracedInitializerIndentWidth = -1;
1747 LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false,
1748 /*AfterClass=*/false,
1749 /*AfterControlStatement=*/FormatStyle::BWACS_Never,
1750 /*AfterEnum=*/false,
1751 /*AfterFunction=*/false,
1752 /*AfterNamespace=*/false,
1753 /*AfterObjCDeclaration=*/false,
1754 /*AfterStruct=*/false,
1755 /*AfterUnion=*/false,
1756 /*AfterExternBlock=*/false,
1757 /*BeforeCatch=*/false,
1758 /*BeforeElse=*/false,
1759 /*BeforeLambdaBody=*/false,
1760 /*BeforeWhile=*/false,
1761 /*IndentBraces=*/false,
1762 /*SplitEmptyFunction=*/true,
1763 /*SplitEmptyRecord=*/true,
1764 /*SplitEmptyNamespace=*/true};
1765 LLVMStyle.BreakAdjacentStringLiterals = true;
1766 LLVMStyle.BreakAfterAttributes = FormatStyle::ABS_Leave;
1767 LLVMStyle.BreakAfterJavaFieldAnnotations = false;
1768 LLVMStyle.BreakAfterOpenBracketBracedList = false;
1769 LLVMStyle.BreakAfterOpenBracketFunction = false;
1770 LLVMStyle.BreakAfterOpenBracketIf = false;
1771 LLVMStyle.BreakAfterOpenBracketLoop = false;
1772 LLVMStyle.BreakAfterOpenBracketSwitch = false;
1773 LLVMStyle.BreakAfterReturnType = FormatStyle::RTBS_None;
1774 LLVMStyle.BreakArrays = true;
1775 LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
1776 LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
1777 LLVMStyle.BreakBeforeCloseBracketBracedList = false;
1778 LLVMStyle.BreakBeforeCloseBracketFunction = false;
1779 LLVMStyle.BreakBeforeCloseBracketIf = false;
1780 LLVMStyle.BreakBeforeCloseBracketLoop = false;
1781 LLVMStyle.BreakBeforeCloseBracketSwitch = false;
1782 LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always;
1783 LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline;
1784 LLVMStyle.BreakBeforeTemplateCloser = false;
1785 LLVMStyle.BreakBeforeTernaryOperators = true;
1786 LLVMStyle.BreakBinaryOperations = {.Default: FormatStyle::BBO_Never, .PerOperator: {}};
1787 LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
1788 LLVMStyle.BreakFunctionDefinitionParameters = false;
1789 LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
1790 LLVMStyle.BreakStringLiterals = true;
1791 LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
1792 LLVMStyle.ColumnLimit = 80;
1793 LLVMStyle.CommentPragmas = "^ IWYU pragma:";
1794 LLVMStyle.CompactNamespaces = false;
1795 LLVMStyle.ConstructorInitializerIndentWidth = 4;
1796 LLVMStyle.ContinuationIndentWidth = 4;
1797 LLVMStyle.Cpp11BracedListStyle = FormatStyle::BLS_AlignFirstComment;
1798 LLVMStyle.DerivePointerAlignment = false;
1799 LLVMStyle.DisableFormat = false;
1800 LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never;
1801 LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock;
1802 LLVMStyle.EnumTrailingComma = FormatStyle::ETC_Leave;
1803 LLVMStyle.ExperimentalAutoDetectBinPacking = false;
1804 LLVMStyle.FixNamespaceComments = true;
1805 LLVMStyle.ForEachMacros.push_back(x: "foreach");
1806 LLVMStyle.ForEachMacros.push_back(x: "Q_FOREACH");
1807 LLVMStyle.ForEachMacros.push_back(x: "BOOST_FOREACH");
1808 LLVMStyle.IfMacros.push_back(x: "KJ_IF_MAYBE");
1809 LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
1810 LLVMStyle.IncludeStyle.IncludeCategories = {
1811 {.Regex: "^\"(llvm|llvm-c|clang|clang-c)/", .Priority: 2, .SortPriority: 0, .RegexIsCaseSensitive: false},
1812 {.Regex: "^(<|\"(gtest|gmock|isl|json)/)", .Priority: 3, .SortPriority: 0, .RegexIsCaseSensitive: false},
1813 {.Regex: ".*", .Priority: 1, .SortPriority: 0, .RegexIsCaseSensitive: false}};
1814 LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
1815 LLVMStyle.IncludeStyle.MainIncludeChar = tooling::IncludeStyle::MICD_Quote;
1816 LLVMStyle.IndentAccessModifiers = false;
1817 LLVMStyle.IndentCaseBlocks = false;
1818 LLVMStyle.IndentCaseLabels = false;
1819 LLVMStyle.IndentExportBlock = true;
1820 LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
1821 LLVMStyle.IndentGotoLabels = true;
1822 LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
1823 LLVMStyle.IndentRequiresClause = true;
1824 LLVMStyle.IndentWidth = 2;
1825 LLVMStyle.IndentWrappedFunctionNames = false;
1826 LLVMStyle.InheritsParentConfig = false;
1827 LLVMStyle.InsertBraces = false;
1828 LLVMStyle.InsertNewlineAtEOF = false;
1829 LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
1830 LLVMStyle.IntegerLiteralSeparator = {};
1831 LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
1832 LLVMStyle.JavaScriptWrapImports = true;
1833 LLVMStyle.KeepEmptyLines = {
1834 /*AtEndOfFile=*/false,
1835 /*AtStartOfBlock=*/true,
1836 /*AtStartOfFile=*/true,
1837 };
1838 LLVMStyle.KeepFormFeed = false;
1839 LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature;
1840 LLVMStyle.Language = Language;
1841 LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF;
1842 LLVMStyle.MaxEmptyLinesToKeep = 1;
1843 LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
1844 LLVMStyle.NumericLiteralCase = {/*ExponentLetter=*/FormatStyle::NLCS_Leave,
1845 /*HexDigit=*/FormatStyle::NLCS_Leave,
1846 /*Prefix=*/FormatStyle::NLCS_Leave,
1847 /*Suffix=*/FormatStyle::NLCS_Leave};
1848 LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto;
1849 LLVMStyle.ObjCBlockIndentWidth = 2;
1850 LLVMStyle.ObjCBreakBeforeNestedBlockParam = true;
1851 LLVMStyle.ObjCSpaceAfterMethodDeclarationPrefix = true;
1852 LLVMStyle.ObjCSpaceAfterProperty = false;
1853 LLVMStyle.ObjCSpaceBeforeProtocolList = true;
1854 LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
1855 LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
1856 LLVMStyle.PPIndentWidth = -1;
1857 LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
1858 LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer;
1859 LLVMStyle.ReflowComments = FormatStyle::RCS_Always;
1860 LLVMStyle.RemoveBracesLLVM = false;
1861 LLVMStyle.RemoveEmptyLinesInUnwrappedLines = false;
1862 LLVMStyle.RemoveParentheses = FormatStyle::RPS_Leave;
1863 LLVMStyle.RemoveSemicolon = false;
1864 LLVMStyle.RequiresClausePosition = FormatStyle::RCPS_OwnLine;
1865 LLVMStyle.RequiresExpressionIndentation = FormatStyle::REI_OuterScope;
1866 LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
1867 LLVMStyle.ShortNamespaceLines = 1;
1868 LLVMStyle.SkipMacroDefinitionBody = false;
1869 LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false,
1870 /*IgnoreExtension=*/false};
1871 LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
1872 LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;
1873 LLVMStyle.SpaceAfterCStyleCast = false;
1874 LLVMStyle.SpaceAfterLogicalNot = false;
1875 LLVMStyle.SpaceAfterOperatorKeyword = false;
1876 LLVMStyle.SpaceAfterTemplateKeyword = true;
1877 LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
1878 LLVMStyle.SpaceBeforeAssignmentOperators = true;
1879 LLVMStyle.SpaceBeforeCaseColon = false;
1880 LLVMStyle.SpaceBeforeCpp11BracedList = false;
1881 LLVMStyle.SpaceBeforeCtorInitializerColon = true;
1882 LLVMStyle.SpaceBeforeInheritanceColon = true;
1883 LLVMStyle.SpaceBeforeJsonColon = false;
1884 LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
1885 LLVMStyle.SpaceBeforeParensOptions = {};
1886 LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true;
1887 LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true;
1888 LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true;
1889 LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
1890 LLVMStyle.SpaceBeforeSquareBrackets = false;
1891 LLVMStyle.SpaceInEmptyBraces = FormatStyle::SIEB_Never;
1892 LLVMStyle.SpacesBeforeTrailingComments = 1;
1893 LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never;
1894 LLVMStyle.SpacesInContainerLiterals = true;
1895 LLVMStyle.SpacesInLineCommentPrefix = {
1896 /*Minimum=*/1, /*Maximum=*/std::numeric_limits<unsigned>::max()};
1897 LLVMStyle.SpacesInParens = FormatStyle::SIPO_Never;
1898 LLVMStyle.SpacesInSquareBrackets = false;
1899 LLVMStyle.Standard = FormatStyle::LS_Latest;
1900 LLVMStyle.StatementAttributeLikeMacros.push_back(x: "Q_EMIT");
1901 LLVMStyle.StatementMacros.push_back(x: "Q_UNUSED");
1902 LLVMStyle.StatementMacros.push_back(x: "QT_REQUIRE_VERSION");
1903 LLVMStyle.TableGenBreakingDAGArgOperators = {};
1904 LLVMStyle.TableGenBreakInsideDAGArg = FormatStyle::DAS_DontBreak;
1905 LLVMStyle.TabWidth = 8;
1906 LLVMStyle.UseTab = FormatStyle::UT_Never;
1907 LLVMStyle.VerilogBreakBetweenInstancePorts = true;
1908 LLVMStyle.WhitespaceSensitiveMacros.push_back(x: "BOOST_PP_STRINGIZE");
1909 LLVMStyle.WhitespaceSensitiveMacros.push_back(x: "CF_SWIFT_NAME");
1910 LLVMStyle.WhitespaceSensitiveMacros.push_back(x: "NS_SWIFT_NAME");
1911 LLVMStyle.WhitespaceSensitiveMacros.push_back(x: "PP_STRINGIZE");
1912 LLVMStyle.WhitespaceSensitiveMacros.push_back(x: "STRINGIZE");
1913 LLVMStyle.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Leave;
1914
1915 LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
1916 LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
1917 LLVMStyle.PenaltyBreakBeforeMemberAccess = 150;
1918 LLVMStyle.PenaltyBreakComment = 300;
1919 LLVMStyle.PenaltyBreakFirstLessLess = 120;
1920 LLVMStyle.PenaltyBreakOpenParenthesis = 0;
1921 LLVMStyle.PenaltyBreakScopeResolution = 500;
1922 LLVMStyle.PenaltyBreakString = 1000;
1923 LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;
1924 LLVMStyle.PenaltyExcessCharacter = 1'000'000;
1925 LLVMStyle.PenaltyIndentedWhitespace = 0;
1926 LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
1927
1928 // Defaults that differ when not C++.
1929 switch (Language) {
1930 case FormatStyle::LK_TableGen:
1931 LLVMStyle.SpacesInContainerLiterals = false;
1932 break;
1933 case FormatStyle::LK_Json:
1934 LLVMStyle.ColumnLimit = 0;
1935 break;
1936 case FormatStyle::LK_Verilog:
1937 LLVMStyle.IndentCaseLabels = true;
1938 LLVMStyle.SpacesInContainerLiterals = false;
1939 break;
1940 default:
1941 break;
1942 }
1943
1944 return LLVMStyle;
1945}
1946
1947FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
1948 if (Language == FormatStyle::LK_TextProto) {
1949 FormatStyle GoogleStyle = getGoogleStyle(Language: FormatStyle::LK_Proto);
1950 GoogleStyle.Language = FormatStyle::LK_TextProto;
1951
1952 return GoogleStyle;
1953 }
1954
1955 FormatStyle GoogleStyle = getLLVMStyle(Language);
1956
1957 GoogleStyle.AccessModifierOffset = -1;
1958 GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left;
1959 GoogleStyle.AllowShortIfStatementsOnASingleLine =
1960 FormatStyle::SIS_WithoutElse;
1961 GoogleStyle.AllowShortLoopsOnASingleLine = true;
1962 GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
1963 // Abseil aliases to clang's `_Nonnull`, `_Nullable` and `_Null_unspecified`.
1964 GoogleStyle.AttributeMacros.push_back(x: "absl_nonnull");
1965 GoogleStyle.AttributeMacros.push_back(x: "absl_nullable");
1966 GoogleStyle.AttributeMacros.push_back(x: "absl_nullability_unknown");
1967 GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
1968 GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
1969 GoogleStyle.IncludeStyle.IncludeCategories = {{.Regex: "^<ext/.*\\.h>", .Priority: 2, .SortPriority: 0, .RegexIsCaseSensitive: false},
1970 {.Regex: "^<.*\\.h>", .Priority: 1, .SortPriority: 0, .RegexIsCaseSensitive: false},
1971 {.Regex: "^<.*", .Priority: 2, .SortPriority: 0, .RegexIsCaseSensitive: false},
1972 {.Regex: ".*", .Priority: 3, .SortPriority: 0, .RegexIsCaseSensitive: false}};
1973 GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
1974 GoogleStyle.IndentCaseLabels = true;
1975 GoogleStyle.KeepEmptyLines.AtStartOfBlock = false;
1976
1977 GoogleStyle.Macros.push_back(x: "ASSIGN_OR_RETURN(a, b)=a = (b)");
1978 GoogleStyle.Macros.push_back(
1979 x: "ASSIGN_OR_RETURN(a, b, c)=a = (b); if (x) return c");
1980
1981 GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never;
1982 GoogleStyle.ObjCSpaceAfterProperty = false;
1983 GoogleStyle.ObjCSpaceBeforeProtocolList = true;
1984 GoogleStyle.PackConstructorInitializers = FormatStyle::PCIS_NextLine;
1985 GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;
1986 GoogleStyle.RawStringFormats = {
1987 {
1988 .Language: FormatStyle::LK_Cpp,
1989 /*Delimiters=*/
1990 {
1991 "cc",
1992 "CC",
1993 "cpp",
1994 "Cpp",
1995 "CPP",
1996 "c++",
1997 "C++",
1998 },
1999 /*EnclosingFunctionNames=*/
2000 .EnclosingFunctions: {},
2001 /*CanonicalDelimiter=*/"",
2002 /*BasedOnStyle=*/"google",
2003 },
2004 {
2005 .Language: FormatStyle::LK_TextProto,
2006 /*Delimiters=*/
2007 {
2008 "pb",
2009 "PB",
2010 "proto",
2011 "PROTO",
2012 },
2013 /*EnclosingFunctionNames=*/
2014 .EnclosingFunctions: {
2015 "EqualsProto",
2016 "EquivToProto",
2017 "PARSE_PARTIAL_TEXT_PROTO",
2018 "PARSE_TEST_PROTO",
2019 "PARSE_TEXT_PROTO",
2020 "ParseTextOrDie",
2021 "ParseTextProtoOrDie",
2022 "ParseTestProto",
2023 "ParsePartialTestProto",
2024 },
2025 /*CanonicalDelimiter=*/"pb",
2026 /*BasedOnStyle=*/"google",
2027 },
2028 };
2029
2030 GoogleStyle.SpacesBeforeTrailingComments = 2;
2031 GoogleStyle.Standard = FormatStyle::LS_Auto;
2032
2033 GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;
2034 GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
2035
2036 if (Language == FormatStyle::LK_Java) {
2037 GoogleStyle.AlignAfterOpenBracket = false;
2038 GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
2039 GoogleStyle.AlignTrailingComments = {};
2040 GoogleStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;
2041 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
2042 GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
2043 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
2044 GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
2045 GoogleStyle.ColumnLimit = 100;
2046 GoogleStyle.SpaceAfterCStyleCast = true;
2047 GoogleStyle.SpacesBeforeTrailingComments = 1;
2048 } else if (Language == FormatStyle::LK_JavaScript) {
2049 GoogleStyle.BreakAfterOpenBracketBracedList = true;
2050 GoogleStyle.BreakAfterOpenBracketFunction = true;
2051 GoogleStyle.BreakAfterOpenBracketIf = true;
2052 GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
2053 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
2054 // TODO: still under discussion whether to switch to SLS_All.
2055 GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
2056 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
2057 GoogleStyle.BreakBeforeTernaryOperators = false;
2058 // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is
2059 // commonly followed by overlong URLs.
2060 GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)";
2061 // TODO: enable once decided, in particular re disabling bin packing.
2062 // https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma
2063 // GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
2064 GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single;
2065 GoogleStyle.JavaScriptWrapImports = false;
2066 GoogleStyle.MaxEmptyLinesToKeep = 3;
2067 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
2068 GoogleStyle.SpacesInContainerLiterals = false;
2069 } else if (Language == FormatStyle::LK_Proto) {
2070 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
2071 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
2072 // This affects protocol buffer options specifications and text protos.
2073 // Text protos are currently mostly formatted inside C++ raw string literals
2074 // and often the current breaking behavior of string literals is not
2075 // beneficial there. Investigate turning this on once proper string reflow
2076 // has been implemented.
2077 GoogleStyle.BreakStringLiterals = false;
2078 GoogleStyle.Cpp11BracedListStyle = FormatStyle::BLS_Block;
2079 GoogleStyle.SpacesInContainerLiterals = false;
2080 } else if (Language == FormatStyle::LK_ObjC) {
2081 GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
2082 GoogleStyle.ColumnLimit = 100;
2083 GoogleStyle.DerivePointerAlignment = true;
2084 // "Regroup" doesn't work well for ObjC yet (main header heuristic,
2085 // relationship between ObjC standard library headers and other heades,
2086 // #imports, etc.)
2087 GoogleStyle.IncludeStyle.IncludeBlocks =
2088 tooling::IncludeStyle::IBS_Preserve;
2089 } else if (Language == FormatStyle::LK_CSharp) {
2090 GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
2091 GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
2092 GoogleStyle.BreakStringLiterals = false;
2093 GoogleStyle.ColumnLimit = 100;
2094 GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
2095 }
2096
2097 return GoogleStyle;
2098}
2099
2100FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
2101 FormatStyle ChromiumStyle = getGoogleStyle(Language);
2102
2103 // Disable include reordering across blocks in Chromium code.
2104 // - clang-format tries to detect that foo.h is the "main" header for
2105 // foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium
2106 // uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc,
2107 // _private.cc, _impl.cc etc) in different permutations
2108 // (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a
2109 // better default for Chromium code.
2110 // - The default for .cc and .mm files is different (r357695) for Google style
2111 // for the same reason. The plan is to unify this again once the main
2112 // header detection works for Google's ObjC code, but this hasn't happened
2113 // yet. Since Chromium has some ObjC code, switching Chromium is blocked
2114 // on that.
2115 // - Finally, "If include reordering is harmful, put things in different
2116 // blocks to prevent it" has been a recommendation for a long time that
2117 // people are used to. We'll need a dev education push to change this to
2118 // "If include reordering is harmful, put things in a different block and
2119 // _prepend that with a comment_ to prevent it" before changing behavior.
2120 ChromiumStyle.IncludeStyle.IncludeBlocks =
2121 tooling::IncludeStyle::IBS_Preserve;
2122
2123 if (Language == FormatStyle::LK_Java) {
2124 ChromiumStyle.AllowShortIfStatementsOnASingleLine =
2125 FormatStyle::SIS_WithoutElse;
2126 ChromiumStyle.BreakAfterJavaFieldAnnotations = true;
2127 ChromiumStyle.ContinuationIndentWidth = 8;
2128 ChromiumStyle.IndentWidth = 4;
2129 // See styleguide for import groups:
2130 // https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/java/java.md#Import-Order
2131 ChromiumStyle.JavaImportGroups = {
2132 "android",
2133 "androidx",
2134 "com",
2135 "dalvik",
2136 "junit",
2137 "org",
2138 "com.google.android.apps.chrome",
2139 "org.chromium",
2140 "java",
2141 "javax",
2142 };
2143 } else if (Language == FormatStyle::LK_JavaScript) {
2144 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
2145 ChromiumStyle.AllowShortLoopsOnASingleLine = false;
2146 } else {
2147 ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
2148 ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
2149 ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
2150 ChromiumStyle.AllowShortLoopsOnASingleLine = false;
2151 ChromiumStyle.BinPackParameters = FormatStyle::BPPS_OnePerLine;
2152 ChromiumStyle.DerivePointerAlignment = false;
2153 if (Language == FormatStyle::LK_ObjC)
2154 ChromiumStyle.ColumnLimit = 80;
2155 }
2156 return ChromiumStyle;
2157}
2158
2159FormatStyle getMozillaStyle() {
2160 FormatStyle MozillaStyle = getLLVMStyle();
2161 MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
2162 MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
2163 MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
2164 FormatStyle::DRTBS_TopLevel;
2165 MozillaStyle.BinPackArguments = false;
2166 MozillaStyle.BinPackParameters = FormatStyle::BPPS_OnePerLine;
2167 MozillaStyle.BreakAfterReturnType = FormatStyle::RTBS_TopLevel;
2168 MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
2169 MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
2170 MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
2171 MozillaStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
2172 MozillaStyle.ConstructorInitializerIndentWidth = 2;
2173 MozillaStyle.ContinuationIndentWidth = 2;
2174 MozillaStyle.Cpp11BracedListStyle = FormatStyle::BLS_Block;
2175 MozillaStyle.FixNamespaceComments = false;
2176 MozillaStyle.IndentCaseLabels = true;
2177 MozillaStyle.ObjCSpaceAfterProperty = true;
2178 MozillaStyle.ObjCSpaceBeforeProtocolList = false;
2179 MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
2180 MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
2181 MozillaStyle.SpaceAfterTemplateKeyword = false;
2182 return MozillaStyle;
2183}
2184
2185FormatStyle getWebKitStyle() {
2186 FormatStyle Style = getLLVMStyle();
2187 Style.AccessModifierOffset = -4;
2188 Style.AlignAfterOpenBracket = false;
2189 Style.AlignOperands = FormatStyle::OAS_DontAlign;
2190 Style.AlignTrailingComments = {};
2191 Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;
2192 Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;
2193 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
2194 Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
2195 Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
2196 Style.ColumnLimit = 0;
2197 Style.Cpp11BracedListStyle = FormatStyle::BLS_Block;
2198 Style.FixNamespaceComments = false;
2199 Style.IndentWidth = 4;
2200 Style.NamespaceIndentation = FormatStyle::NI_Inner;
2201 Style.ObjCBlockIndentWidth = 4;
2202 Style.ObjCSpaceAfterProperty = true;
2203 Style.PointerAlignment = FormatStyle::PAS_Left;
2204 Style.SpaceBeforeCpp11BracedList = true;
2205 Style.SpaceInEmptyBraces = FormatStyle::SIEB_Always;
2206 return Style;
2207}
2208
2209FormatStyle getGNUStyle() {
2210 FormatStyle Style = getLLVMStyle();
2211 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
2212 Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
2213 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
2214 Style.BreakBeforeBraces = FormatStyle::BS_GNU;
2215 Style.BreakBeforeTernaryOperators = true;
2216 Style.ColumnLimit = 79;
2217 Style.Cpp11BracedListStyle = FormatStyle::BLS_Block;
2218 Style.FixNamespaceComments = false;
2219 Style.KeepFormFeed = true;
2220 Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
2221 return Style;
2222}
2223
2224FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) {
2225 FormatStyle Style = getLLVMStyle(Language);
2226 Style.ColumnLimit = 120;
2227 Style.TabWidth = 4;
2228 Style.IndentWidth = 4;
2229 Style.UseTab = FormatStyle::UT_Never;
2230 Style.BreakBeforeBraces = FormatStyle::BS_Custom;
2231 Style.BraceWrapping.AfterClass = true;
2232 Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
2233 Style.BraceWrapping.AfterEnum = true;
2234 Style.BraceWrapping.AfterFunction = true;
2235 Style.BraceWrapping.AfterNamespace = true;
2236 Style.BraceWrapping.AfterObjCDeclaration = true;
2237 Style.BraceWrapping.AfterStruct = true;
2238 Style.BraceWrapping.AfterExternBlock = true;
2239 Style.BraceWrapping.BeforeCatch = true;
2240 Style.BraceWrapping.BeforeElse = true;
2241 Style.BraceWrapping.BeforeWhile = false;
2242 Style.PenaltyReturnTypeOnItsOwnLine = 1000;
2243 Style.AllowShortEnumsOnASingleLine = false;
2244 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
2245 Style.AllowShortCaseLabelsOnASingleLine = false;
2246 Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
2247 Style.AllowShortLoopsOnASingleLine = false;
2248 Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
2249 Style.BreakAfterReturnType = FormatStyle::RTBS_None;
2250 return Style;
2251}
2252
2253FormatStyle getClangFormatStyle() {
2254 FormatStyle Style = getLLVMStyle();
2255 Style.InsertBraces = true;
2256 Style.InsertNewlineAtEOF = true;
2257 Style.IntegerLiteralSeparator.Decimal = 3;
2258 Style.IntegerLiteralSeparator.DecimalMinDigitsInsert = 5;
2259 Style.LineEnding = FormatStyle::LE_LF;
2260 Style.RemoveBracesLLVM = true;
2261 Style.RemoveEmptyLinesInUnwrappedLines = true;
2262 Style.RemoveParentheses = FormatStyle::RPS_ReturnStatement;
2263 Style.RemoveSemicolon = true;
2264 return Style;
2265}
2266
2267FormatStyle getNoStyle() {
2268 FormatStyle NoStyle = getLLVMStyle();
2269 NoStyle.DisableFormat = true;
2270 NoStyle.SortIncludes = {};
2271 NoStyle.SortUsingDeclarations = FormatStyle::SUD_Never;
2272 return NoStyle;
2273}
2274
2275bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
2276 FormatStyle *Style) {
2277 if (Name.equals_insensitive(RHS: "llvm"))
2278 *Style = getLLVMStyle(Language);
2279 else if (Name.equals_insensitive(RHS: "chromium"))
2280 *Style = getChromiumStyle(Language);
2281 else if (Name.equals_insensitive(RHS: "mozilla"))
2282 *Style = getMozillaStyle();
2283 else if (Name.equals_insensitive(RHS: "google"))
2284 *Style = getGoogleStyle(Language);
2285 else if (Name.equals_insensitive(RHS: "webkit"))
2286 *Style = getWebKitStyle();
2287 else if (Name.equals_insensitive(RHS: "gnu"))
2288 *Style = getGNUStyle();
2289 else if (Name.equals_insensitive(RHS: "microsoft"))
2290 *Style = getMicrosoftStyle(Language);
2291 else if (Name.equals_insensitive(RHS: "clang-format"))
2292 *Style = getClangFormatStyle();
2293 else if (Name.equals_insensitive(RHS: "none"))
2294 *Style = getNoStyle();
2295 else if (Name.equals_insensitive(RHS: "inheritparentconfig"))
2296 Style->InheritsParentConfig = true;
2297 else
2298 return false;
2299
2300 Style->Language = Language;
2301 return true;
2302}
2303
2304ParseError validateQualifierOrder(FormatStyle *Style) {
2305 // If its empty then it means don't do anything.
2306 if (Style->QualifierOrder.empty())
2307 return ParseError::MissingQualifierOrder;
2308
2309 // Ensure the list contains only currently valid qualifiers.
2310 for (const auto &Qualifier : Style->QualifierOrder) {
2311 if (Qualifier == "type")
2312 continue;
2313 auto token =
2314 LeftRightQualifierAlignmentFixer::getTokenFromQualifier(Qualifier);
2315 if (token == tok::identifier)
2316 return ParseError::InvalidQualifierSpecified;
2317 }
2318
2319 // Ensure the list is unique (no duplicates).
2320 std::set<std::string> UniqueQualifiers(Style->QualifierOrder.begin(),
2321 Style->QualifierOrder.end());
2322 if (Style->QualifierOrder.size() != UniqueQualifiers.size()) {
2323 LLVM_DEBUG(llvm::dbgs()
2324 << "Duplicate Qualifiers " << Style->QualifierOrder.size()
2325 << " vs " << UniqueQualifiers.size() << "\n");
2326 return ParseError::DuplicateQualifierSpecified;
2327 }
2328
2329 // Ensure the list has 'type' in it.
2330 if (!llvm::is_contained(Range&: Style->QualifierOrder, Element: "type"))
2331 return ParseError::MissingQualifierType;
2332
2333 return ParseError::Success;
2334}
2335
2336std::error_code parseConfiguration(llvm::MemoryBufferRef Config,
2337 FormatStyle *Style, bool AllowUnknownOptions,
2338 llvm::SourceMgr::DiagHandlerTy DiagHandler,
2339 void *DiagHandlerCtxt, bool IsDotHFile) {
2340 assert(Style);
2341 FormatStyle::LanguageKind Language = Style->Language;
2342 assert(Language != FormatStyle::LK_None);
2343 if (Config.getBuffer().trim().empty())
2344 return make_error_code(e: ParseError::Success);
2345 Style->StyleSet.Clear();
2346 std::vector<FormatStyle> Styles;
2347 llvm::yaml::Input Input(Config, /*Ctxt=*/nullptr, DiagHandler,
2348 DiagHandlerCtxt);
2349 // DocumentListTraits<vector<FormatStyle>> uses the context to get default
2350 // values for the fields, keys for which are missing from the configuration.
2351 // Mapping also uses the context to get the language to find the correct
2352 // base style.
2353 Input.setContext(Style);
2354 Input.setAllowUnknownKeys(AllowUnknownOptions);
2355 Input >> Styles;
2356 if (Input.error())
2357 return Input.error();
2358 if (Styles.empty())
2359 return make_error_code(e: ParseError::Success);
2360
2361 const auto StyleCount = Styles.size();
2362
2363 // Start from the second style as (only) the first one may be the default.
2364 for (unsigned I = 1; I < StyleCount; ++I) {
2365 const auto Lang = Styles[I].Language;
2366 if (Lang == FormatStyle::LK_None)
2367 return make_error_code(e: ParseError::Error);
2368 // Ensure that each language is configured at most once.
2369 for (unsigned J = 0; J < I; ++J) {
2370 if (Lang == Styles[J].Language) {
2371 LLVM_DEBUG(llvm::dbgs()
2372 << "Duplicate languages in the config file on positions "
2373 << J << " and " << I << '\n');
2374 return make_error_code(e: ParseError::Error);
2375 }
2376 }
2377 }
2378
2379 int LanguagePos = -1; // Position of the style for Language.
2380 int CppPos = -1; // Position of the style for C++.
2381 int CPos = -1; // Position of the style for C.
2382
2383 // Search Styles for Language and store the positions of C++ and C styles in
2384 // case Language is not found.
2385 for (unsigned I = 0; I < StyleCount; ++I) {
2386 const auto Lang = Styles[I].Language;
2387 if (Lang == Language) {
2388 LanguagePos = I;
2389 break;
2390 }
2391 if (Lang == FormatStyle::LK_Cpp)
2392 CppPos = I;
2393 else if (Lang == FormatStyle::LK_C)
2394 CPos = I;
2395 }
2396
2397 // If Language is not found, use the default style if there is one. Otherwise,
2398 // use the C style for C++ .h files and for backward compatibility, the C++
2399 // style for .c files.
2400 if (LanguagePos < 0) {
2401 if (Styles[0].Language == FormatStyle::LK_None) // Default style.
2402 LanguagePos = 0;
2403 else if (IsDotHFile && Language == FormatStyle::LK_Cpp)
2404 LanguagePos = CPos;
2405 else if (!IsDotHFile && Language == FormatStyle::LK_C)
2406 LanguagePos = CppPos;
2407 if (LanguagePos < 0)
2408 return make_error_code(e: ParseError::Unsuitable);
2409 }
2410
2411 for (const auto &S : llvm::reverse(C: llvm::drop_begin(RangeOrContainer&: Styles)))
2412 Style->StyleSet.Add(Style: S);
2413
2414 *Style = Styles[LanguagePos];
2415
2416 if (LanguagePos == 0) {
2417 if (Style->Language == FormatStyle::LK_None) // Default style.
2418 Style->Language = Language;
2419 Style->StyleSet.Add(Style: *Style);
2420 }
2421
2422 if (Style->InsertTrailingCommas != FormatStyle::TCS_None &&
2423 Style->BinPackArguments) {
2424 // See comment on FormatStyle::TSC_Wrapped.
2425 return make_error_code(e: ParseError::BinPackTrailingCommaConflict);
2426 }
2427 if (Style->QualifierAlignment != FormatStyle::QAS_Leave)
2428 return make_error_code(e: validateQualifierOrder(Style));
2429 return make_error_code(e: ParseError::Success);
2430}
2431
2432std::string configurationAsText(const FormatStyle &Style) {
2433 std::string Text;
2434 llvm::raw_string_ostream Stream(Text);
2435 llvm::yaml::Output Output(Stream);
2436 // We use the same mapping method for input and output, so we need a non-const
2437 // reference here.
2438 FormatStyle NonConstStyle = Style;
2439 expandPresetsBraceWrapping(Expanded&: NonConstStyle);
2440 expandPresetsSpaceBeforeParens(Expanded&: NonConstStyle);
2441 expandPresetsSpacesInParens(Expanded&: NonConstStyle);
2442 Output << NonConstStyle;
2443
2444 return Stream.str();
2445}
2446
2447std::optional<FormatStyle>
2448FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {
2449 if (!Styles)
2450 return std::nullopt;
2451 auto It = Styles->find(x: Language);
2452 if (It == Styles->end())
2453 return std::nullopt;
2454 FormatStyle Style = It->second;
2455 Style.StyleSet = *this;
2456 return Style;
2457}
2458
2459void FormatStyle::FormatStyleSet::Add(FormatStyle Style) {
2460 assert(Style.Language != LK_None &&
2461 "Cannot add a style for LK_None to a StyleSet");
2462 assert(
2463 !Style.StyleSet.Styles &&
2464 "Cannot add a style associated with an existing StyleSet to a StyleSet");
2465 if (!Styles)
2466 Styles = std::make_shared<MapType>();
2467 (*Styles)[Style.Language] = std::move(Style);
2468}
2469
2470void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); }
2471
2472std::optional<FormatStyle>
2473FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {
2474 return StyleSet.Get(Language);
2475}
2476
2477namespace {
2478
2479void replaceToken(const FormatToken &Token, FormatToken *Next,
2480 const SourceManager &SourceMgr, tooling::Replacements &Result,
2481 StringRef Text = "") {
2482 const auto &Tok = Token.Tok;
2483 SourceLocation Start;
2484 if (Next && Next->NewlinesBefore == 0 && Next->isNot(Kind: tok::eof)) {
2485 Start = Tok.getLocation();
2486 Next->WhitespaceRange = Token.WhitespaceRange;
2487 } else {
2488 Start = Token.WhitespaceRange.getBegin();
2489 }
2490 const auto &Range = CharSourceRange::getCharRange(B: Start, E: Tok.getEndLoc());
2491 cantFail(Err: Result.add(R: tooling::Replacement(SourceMgr, Range, Text)));
2492}
2493
2494class ParensRemover : public TokenAnalyzer {
2495public:
2496 ParensRemover(const Environment &Env, const FormatStyle &Style)
2497 : TokenAnalyzer(Env, Style) {}
2498
2499 std::pair<tooling::Replacements, unsigned>
2500 analyze(TokenAnnotator &Annotator,
2501 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2502 FormatTokenLexer &Tokens) override {
2503 AffectedRangeMgr.computeAffectedLines(Lines&: AnnotatedLines);
2504 tooling::Replacements Result;
2505 removeParens(Lines&: AnnotatedLines, Result);
2506 return {Result, 0};
2507 }
2508
2509private:
2510 void removeParens(SmallVectorImpl<AnnotatedLine *> &Lines,
2511 tooling::Replacements &Result) {
2512 const auto &SourceMgr = Env.getSourceManager();
2513 for (auto *Line : Lines) {
2514 if (!Line->Children.empty())
2515 removeParens(Lines&: Line->Children, Result);
2516 if (!Line->Affected)
2517 continue;
2518 for (const auto *Token = Line->First; Token && !Token->Finalized;
2519 Token = Token->Next) {
2520 if (Token->Optional && Token->isOneOf(K1: tok::l_paren, K2: tok::r_paren))
2521 replaceToken(Token: *Token, Next: Token->Next, SourceMgr, Result, Text: " ");
2522 }
2523 }
2524 }
2525};
2526
2527class BracesInserter : public TokenAnalyzer {
2528public:
2529 BracesInserter(const Environment &Env, const FormatStyle &Style)
2530 : TokenAnalyzer(Env, Style) {}
2531
2532 std::pair<tooling::Replacements, unsigned>
2533 analyze(TokenAnnotator &Annotator,
2534 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2535 FormatTokenLexer &Tokens) override {
2536 AffectedRangeMgr.computeAffectedLines(Lines&: AnnotatedLines);
2537 tooling::Replacements Result;
2538 insertBraces(Lines&: AnnotatedLines, Result);
2539 return {Result, 0};
2540 }
2541
2542private:
2543 void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2544 tooling::Replacements &Result) {
2545 const auto &SourceMgr = Env.getSourceManager();
2546 int OpeningBraceSurplus = 0;
2547 for (AnnotatedLine *Line : Lines) {
2548 if (!Line->Children.empty())
2549 insertBraces(Lines&: Line->Children, Result);
2550 if (!Line->Affected && OpeningBraceSurplus == 0)
2551 continue;
2552 for (FormatToken *Token = Line->First; Token && !Token->Finalized;
2553 Token = Token->Next) {
2554 int BraceCount = Token->BraceCount;
2555 if (BraceCount == 0)
2556 continue;
2557 std::string Brace;
2558 if (BraceCount < 0) {
2559 assert(BraceCount == -1);
2560 if (!Line->Affected)
2561 break;
2562 Brace = Token->is(Kind: tok::comment) ? "\n{" : "{";
2563 ++OpeningBraceSurplus;
2564 } else {
2565 if (OpeningBraceSurplus == 0)
2566 break;
2567 if (OpeningBraceSurplus < BraceCount)
2568 BraceCount = OpeningBraceSurplus;
2569 Brace = '\n' + std::string(BraceCount, '}');
2570 OpeningBraceSurplus -= BraceCount;
2571 }
2572 Token->BraceCount = 0;
2573 const auto Start = Token->Tok.getEndLoc();
2574 cantFail(Err: Result.add(R: tooling::Replacement(SourceMgr, Start, 0, Brace)));
2575 }
2576 }
2577 assert(OpeningBraceSurplus == 0);
2578 }
2579};
2580
2581class BracesRemover : public TokenAnalyzer {
2582public:
2583 BracesRemover(const Environment &Env, const FormatStyle &Style)
2584 : TokenAnalyzer(Env, Style) {}
2585
2586 std::pair<tooling::Replacements, unsigned>
2587 analyze(TokenAnnotator &Annotator,
2588 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2589 FormatTokenLexer &Tokens) override {
2590 AffectedRangeMgr.computeAffectedLines(Lines&: AnnotatedLines);
2591 tooling::Replacements Result;
2592 removeBraces(Lines&: AnnotatedLines, Result);
2593 return {Result, 0};
2594 }
2595
2596private:
2597 void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
2598 tooling::Replacements &Result) {
2599 const auto &SourceMgr = Env.getSourceManager();
2600 const auto *End = Lines.end();
2601 for (const auto *I = Lines.begin(); I != End; ++I) {
2602 const auto &Line = *I;
2603 if (!Line->Children.empty())
2604 removeBraces(Lines&: Line->Children, Result);
2605 if (!Line->Affected)
2606 continue;
2607 const auto *NextLine = I + 1 == End ? nullptr : I[1];
2608 for (const auto *Token = Line->First; Token && !Token->Finalized;
2609 Token = Token->Next) {
2610 if (!Token->Optional || Token->isNoneOf(Ks: tok::l_brace, Ks: tok::r_brace))
2611 continue;
2612 auto *Next = Token->Next;
2613 assert(Next || Token == Line->Last);
2614 if (!Next && NextLine)
2615 Next = NextLine->First;
2616 replaceToken(Token: *Token, Next, SourceMgr, Result);
2617 }
2618 }
2619 }
2620};
2621
2622class SemiRemover : public TokenAnalyzer {
2623public:
2624 SemiRemover(const Environment &Env, const FormatStyle &Style)
2625 : TokenAnalyzer(Env, Style) {}
2626
2627 std::pair<tooling::Replacements, unsigned>
2628 analyze(TokenAnnotator &Annotator,
2629 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2630 FormatTokenLexer &Tokens) override {
2631 AffectedRangeMgr.computeAffectedLines(Lines&: AnnotatedLines);
2632 tooling::Replacements Result;
2633 removeSemi(Annotator, Lines&: AnnotatedLines, Result);
2634 return {Result, 0};
2635 }
2636
2637private:
2638 void removeSemi(TokenAnnotator &Annotator,
2639 SmallVectorImpl<AnnotatedLine *> &Lines,
2640 tooling::Replacements &Result) {
2641 auto PrecededByFunctionRBrace = [](const FormatToken &Tok) {
2642 const auto *Prev = Tok.Previous;
2643 if (!Prev || Prev->isNot(Kind: tok::r_brace))
2644 return false;
2645 const auto *LBrace = Prev->MatchingParen;
2646 return LBrace && LBrace->is(TT: TT_FunctionLBrace);
2647 };
2648 const auto &SourceMgr = Env.getSourceManager();
2649 const auto *End = Lines.end();
2650 for (const auto *I = Lines.begin(); I != End; ++I) {
2651 const auto &Line = *I;
2652 if (!Line->Children.empty())
2653 removeSemi(Annotator, Lines&: Line->Children, Result);
2654 if (!Line->Affected)
2655 continue;
2656 Annotator.calculateFormattingInformation(Line&: *Line);
2657 const auto *NextLine = I + 1 == End ? nullptr : I[1];
2658 for (const auto *Token = Line->First; Token && !Token->Finalized;
2659 Token = Token->Next) {
2660 if (Token->isNot(Kind: tok::semi) ||
2661 (!Token->Optional && !PrecededByFunctionRBrace(*Token))) {
2662 continue;
2663 }
2664 auto *Next = Token->Next;
2665 assert(Next || Token == Line->Last);
2666 if (!Next && NextLine)
2667 Next = NextLine->First;
2668 replaceToken(Token: *Token, Next, SourceMgr, Result);
2669 }
2670 }
2671 }
2672};
2673
2674class EnumTrailingCommaEditor : public TokenAnalyzer {
2675public:
2676 EnumTrailingCommaEditor(const Environment &Env, const FormatStyle &Style)
2677 : TokenAnalyzer(Env, Style) {}
2678
2679 std::pair<tooling::Replacements, unsigned>
2680 analyze(TokenAnnotator &Annotator,
2681 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2682 FormatTokenLexer &Tokens) override {
2683 AffectedRangeMgr.computeAffectedLines(Lines&: AnnotatedLines);
2684 tooling::Replacements Result;
2685 editEnumTrailingComma(Lines&: AnnotatedLines, Result);
2686 return {Result, 0};
2687 }
2688
2689private:
2690 void editEnumTrailingComma(SmallVectorImpl<AnnotatedLine *> &Lines,
2691 tooling::Replacements &Result) {
2692 bool InEnumBraces = false;
2693 const FormatToken *BeforeRBrace = nullptr;
2694 const auto &SourceMgr = Env.getSourceManager();
2695 for (auto *Line : Lines) {
2696 if (!Line->Children.empty())
2697 editEnumTrailingComma(Lines&: Line->Children, Result);
2698 for (const auto *Token = Line->First; Token && !Token->Finalized;
2699 Token = Token->Next) {
2700 if (Token->isNot(Kind: TT_EnumRBrace)) {
2701 if (Token->is(TT: TT_EnumLBrace))
2702 InEnumBraces = true;
2703 else if (InEnumBraces && Token->isNot(Kind: tok::comment))
2704 BeforeRBrace = Line->Affected ? Token : nullptr;
2705 continue;
2706 }
2707 InEnumBraces = false;
2708 if (!BeforeRBrace) // Empty braces or Line not affected.
2709 continue;
2710 if (BeforeRBrace->is(Kind: tok::comma)) {
2711 if (Style.EnumTrailingComma == FormatStyle::ETC_Remove)
2712 replaceToken(Token: *BeforeRBrace, Next: BeforeRBrace->Next, SourceMgr, Result);
2713 } else if (Style.EnumTrailingComma == FormatStyle::ETC_Insert) {
2714 cantFail(Err: Result.add(R: tooling::Replacement(
2715 SourceMgr, BeforeRBrace->Tok.getEndLoc(), 0, ",")));
2716 }
2717 BeforeRBrace = nullptr;
2718 }
2719 }
2720 }
2721};
2722
2723class JavaScriptRequoter : public TokenAnalyzer {
2724public:
2725 JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)
2726 : TokenAnalyzer(Env, Style) {}
2727
2728 std::pair<tooling::Replacements, unsigned>
2729 analyze(TokenAnnotator &Annotator,
2730 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2731 FormatTokenLexer &Tokens) override {
2732 AffectedRangeMgr.computeAffectedLines(Lines&: AnnotatedLines);
2733 tooling::Replacements Result;
2734 requoteJSStringLiteral(Lines&: AnnotatedLines, Result);
2735 return {Result, 0};
2736 }
2737
2738private:
2739 // Replaces double/single-quoted string literal as appropriate, re-escaping
2740 // the contents in the process.
2741 void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
2742 tooling::Replacements &Result) {
2743 for (AnnotatedLine *Line : Lines) {
2744 requoteJSStringLiteral(Lines&: Line->Children, Result);
2745 if (!Line->Affected)
2746 continue;
2747 for (FormatToken *FormatTok = Line->First; FormatTok;
2748 FormatTok = FormatTok->Next) {
2749 StringRef Input = FormatTok->TokenText;
2750 if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
2751 // NB: testing for not starting with a double quote to avoid
2752 // breaking `template strings`.
2753 (Style.JavaScriptQuotes == FormatStyle::JSQS_Single &&
2754 !Input.starts_with(Prefix: "\"")) ||
2755 (Style.JavaScriptQuotes == FormatStyle::JSQS_Double &&
2756 !Input.starts_with(Prefix: "\'"))) {
2757 continue;
2758 }
2759
2760 // Change start and end quote.
2761 bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single;
2762 SourceLocation Start = FormatTok->Tok.getLocation();
2763 auto Replace = [&](SourceLocation Start, unsigned Length,
2764 StringRef ReplacementText) {
2765 auto Err = Result.add(R: tooling::Replacement(
2766 Env.getSourceManager(), Start, Length, ReplacementText));
2767 // FIXME: handle error. For now, print error message and skip the
2768 // replacement for release version.
2769 if (Err) {
2770 llvm::errs() << toString(E: std::move(Err)) << "\n";
2771 assert(false);
2772 }
2773 };
2774 Replace(Start, 1, IsSingle ? "'" : "\"");
2775 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(Offset: -1), 1,
2776 IsSingle ? "'" : "\"");
2777
2778 // Escape internal quotes.
2779 bool Escaped = false;
2780 for (size_t i = 1; i < Input.size() - 1; i++) {
2781 switch (Input[i]) {
2782 case '\\':
2783 if (!Escaped && i + 1 < Input.size() &&
2784 ((IsSingle && Input[i + 1] == '"') ||
2785 (!IsSingle && Input[i + 1] == '\''))) {
2786 // Remove this \, it's escaping a " or ' that no longer needs
2787 // escaping
2788 Replace(Start.getLocWithOffset(Offset: i), 1, "");
2789 continue;
2790 }
2791 Escaped = !Escaped;
2792 break;
2793 case '\"':
2794 case '\'':
2795 if (!Escaped && IsSingle == (Input[i] == '\'')) {
2796 // Escape the quote.
2797 Replace(Start.getLocWithOffset(Offset: i), 0, "\\");
2798 }
2799 Escaped = false;
2800 break;
2801 default:
2802 Escaped = false;
2803 break;
2804 }
2805 }
2806 }
2807 }
2808 }
2809};
2810
2811class Formatter : public TokenAnalyzer {
2812public:
2813 Formatter(const Environment &Env, const FormatStyle &Style,
2814 FormattingAttemptStatus *Status)
2815 : TokenAnalyzer(Env, Style), Status(Status) {}
2816
2817 std::pair<tooling::Replacements, unsigned>
2818 analyze(TokenAnnotator &Annotator,
2819 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2820 FormatTokenLexer &Tokens) override {
2821 tooling::Replacements Result;
2822 deriveLocalStyle(AnnotatedLines);
2823 AffectedRangeMgr.computeAffectedLines(Lines&: AnnotatedLines);
2824 for (AnnotatedLine *Line : AnnotatedLines)
2825 Annotator.calculateFormattingInformation(Line&: *Line);
2826 Annotator.setCommentLineLevels(AnnotatedLines);
2827
2828 WhitespaceManager Whitespaces(
2829 Env.getSourceManager(), Style,
2830 Style.LineEnding > FormatStyle::LE_CRLF
2831 ? WhitespaceManager::inputUsesCRLF(
2832 Text: Env.getSourceManager().getBufferData(FID: Env.getFileID()),
2833 DefaultToCRLF: Style.LineEnding == FormatStyle::LE_DeriveCRLF)
2834 : Style.LineEnding == FormatStyle::LE_CRLF);
2835 ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
2836 Env.getSourceManager(), Whitespaces, Encoding,
2837 BinPackInconclusiveFunctions);
2838 unsigned Penalty =
2839 UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,
2840 Tokens.getKeywords(), Env.getSourceManager(),
2841 Status)
2842 .format(Lines: AnnotatedLines, /*DryRun=*/false,
2843 /*AdditionalIndent=*/0,
2844 /*FixBadIndentation=*/false,
2845 /*FirstStartColumn=*/Env.getFirstStartColumn(),
2846 /*NextStartColumn=*/Env.getNextStartColumn(),
2847 /*LastStartColumn=*/Env.getLastStartColumn());
2848 for (const auto &R : Whitespaces.generateReplacements())
2849 if (Result.add(R))
2850 return std::make_pair(x&: Result, y: 0);
2851 return std::make_pair(x&: Result, y&: Penalty);
2852 }
2853
2854private:
2855 bool
2856 hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) {
2857 for (const AnnotatedLine *Line : Lines) {
2858 if (hasCpp03IncompatibleFormat(Lines: Line->Children))
2859 return true;
2860 for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {
2861 if (!Tok->hasWhitespaceBefore()) {
2862 if (Tok->is(Kind: tok::coloncolon) && Tok->Previous->is(TT: TT_TemplateOpener))
2863 return true;
2864 if (Tok->is(TT: TT_TemplateCloser) &&
2865 Tok->Previous->is(TT: TT_TemplateCloser)) {
2866 return true;
2867 }
2868 }
2869 }
2870 }
2871 return false;
2872 }
2873
2874 int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) {
2875 int AlignmentDiff = 0;
2876
2877 for (const AnnotatedLine *Line : Lines) {
2878 AlignmentDiff += countVariableAlignments(Lines: Line->Children);
2879
2880 for (const auto *Tok = Line->getFirstNonComment(); Tok; Tok = Tok->Next) {
2881 if (Tok->isNot(Kind: TT_PointerOrReference))
2882 continue;
2883
2884 const auto *Prev = Tok->Previous;
2885 const bool PrecededByName = Prev && Prev->Tok.getIdentifierInfo();
2886 const bool SpaceBefore = Tok->hasWhitespaceBefore();
2887
2888 // e.g. `int **`, `int*&`, etc.
2889 while (Tok->Next && Tok->Next->is(TT: TT_PointerOrReference))
2890 Tok = Tok->Next;
2891
2892 const auto *Next = Tok->Next;
2893 const bool FollowedByName = Next && Next->Tok.getIdentifierInfo();
2894 const bool SpaceAfter = Next && Next->hasWhitespaceBefore();
2895
2896 if ((!PrecededByName && !FollowedByName) ||
2897 // e.g. `int * i` or `int*i`
2898 (PrecededByName && FollowedByName && SpaceBefore == SpaceAfter)) {
2899 continue;
2900 }
2901
2902 if ((PrecededByName && SpaceBefore) ||
2903 (FollowedByName && !SpaceAfter)) {
2904 // Right alignment.
2905 ++AlignmentDiff;
2906 } else if ((PrecededByName && !SpaceBefore) ||
2907 (FollowedByName && SpaceAfter)) {
2908 // Left alignment.
2909 --AlignmentDiff;
2910 }
2911 }
2912 }
2913
2914 return AlignmentDiff;
2915 }
2916
2917 void
2918 deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2919 bool HasBinPackedFunction = false;
2920 bool HasOnePerLineFunction = false;
2921 for (AnnotatedLine *Line : AnnotatedLines) {
2922 if (!Line->First->Next)
2923 continue;
2924 FormatToken *Tok = Line->First->Next;
2925 while (Tok->Next) {
2926 if (Tok->is(PPK: PPK_BinPacked))
2927 HasBinPackedFunction = true;
2928 if (Tok->is(PPK: PPK_OnePerLine))
2929 HasOnePerLineFunction = true;
2930
2931 Tok = Tok->Next;
2932 }
2933 }
2934 if (Style.DerivePointerAlignment) {
2935 const auto NetRightCount = countVariableAlignments(Lines: AnnotatedLines);
2936 if (NetRightCount > 0)
2937 Style.PointerAlignment = FormatStyle::PAS_Right;
2938 else if (NetRightCount < 0)
2939 Style.PointerAlignment = FormatStyle::PAS_Left;
2940 Style.ReferenceAlignment = FormatStyle::RAS_Pointer;
2941 }
2942 if (Style.Standard == FormatStyle::LS_Auto) {
2943 Style.Standard = hasCpp03IncompatibleFormat(Lines: AnnotatedLines)
2944 ? FormatStyle::LS_Latest
2945 : FormatStyle::LS_Cpp03;
2946 }
2947 BinPackInconclusiveFunctions =
2948 HasBinPackedFunction || !HasOnePerLineFunction;
2949 }
2950
2951 bool BinPackInconclusiveFunctions;
2952 FormattingAttemptStatus *Status;
2953};
2954
2955/// TrailingCommaInserter inserts trailing commas into container literals.
2956/// E.g.:
2957/// const x = [
2958/// 1,
2959/// ];
2960/// TrailingCommaInserter runs after formatting. To avoid causing a required
2961/// reformatting (and thus reflow), it never inserts a comma that'd exceed the
2962/// ColumnLimit.
2963///
2964/// Because trailing commas disable binpacking of arrays, TrailingCommaInserter
2965/// is conceptually incompatible with bin packing.
2966class TrailingCommaInserter : public TokenAnalyzer {
2967public:
2968 TrailingCommaInserter(const Environment &Env, const FormatStyle &Style)
2969 : TokenAnalyzer(Env, Style) {}
2970
2971 std::pair<tooling::Replacements, unsigned>
2972 analyze(TokenAnnotator &Annotator,
2973 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2974 FormatTokenLexer &Tokens) override {
2975 AffectedRangeMgr.computeAffectedLines(Lines&: AnnotatedLines);
2976 tooling::Replacements Result;
2977 insertTrailingCommas(Lines&: AnnotatedLines, Result);
2978 return {Result, 0};
2979 }
2980
2981private:
2982 /// Inserts trailing commas in [] and {} initializers if they wrap over
2983 /// multiple lines.
2984 void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,
2985 tooling::Replacements &Result) {
2986 for (AnnotatedLine *Line : Lines) {
2987 insertTrailingCommas(Lines&: Line->Children, Result);
2988 if (!Line->Affected)
2989 continue;
2990 for (FormatToken *FormatTok = Line->First; FormatTok;
2991 FormatTok = FormatTok->Next) {
2992 if (FormatTok->NewlinesBefore == 0)
2993 continue;
2994 FormatToken *Matching = FormatTok->MatchingParen;
2995 if (!Matching || !FormatTok->getPreviousNonComment())
2996 continue;
2997 if (!(FormatTok->is(Kind: tok::r_square) &&
2998 Matching->is(TT: TT_ArrayInitializerLSquare)) &&
2999 !(FormatTok->is(Kind: tok::r_brace) && Matching->is(TT: TT_DictLiteral))) {
3000 continue;
3001 }
3002 FormatToken *Prev = FormatTok->getPreviousNonComment();
3003 if (Prev->is(Kind: tok::comma) || Prev->is(Kind: tok::semi))
3004 continue;
3005 // getEndLoc is not reliably set during re-lexing, use text length
3006 // instead.
3007 SourceLocation Start =
3008 Prev->Tok.getLocation().getLocWithOffset(Offset: Prev->TokenText.size());
3009 // If inserting a comma would push the code over the column limit, skip
3010 // this location - it'd introduce an unstable formatting due to the
3011 // required reflow.
3012 unsigned ColumnNumber =
3013 Env.getSourceManager().getSpellingColumnNumber(Loc: Start);
3014 if (ColumnNumber > Style.ColumnLimit)
3015 continue;
3016 // Comma insertions cannot conflict with each other, and this pass has a
3017 // clean set of Replacements, so the operation below cannot fail.
3018 cantFail(Err: Result.add(
3019 R: tooling::Replacement(Env.getSourceManager(), Start, 0, ",")));
3020 }
3021 }
3022 }
3023};
3024
3025// This class clean up the erroneous/redundant code around the given ranges in
3026// file.
3027class Cleaner : public TokenAnalyzer {
3028public:
3029 Cleaner(const Environment &Env, const FormatStyle &Style)
3030 : TokenAnalyzer(Env, Style),
3031 DeletedTokens(FormatTokenLess(Env.getSourceManager())) {}
3032
3033 // FIXME: eliminate unused parameters.
3034 std::pair<tooling::Replacements, unsigned>
3035 analyze(TokenAnnotator &Annotator,
3036 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
3037 FormatTokenLexer &Tokens) override {
3038 // FIXME: in the current implementation the granularity of affected range
3039 // is an annotated line. However, this is not sufficient. Furthermore,
3040 // redundant code introduced by replacements does not necessarily
3041 // intercept with ranges of replacements that result in the redundancy.
3042 // To determine if some redundant code is actually introduced by
3043 // replacements(e.g. deletions), we need to come up with a more
3044 // sophisticated way of computing affected ranges.
3045 AffectedRangeMgr.computeAffectedLines(Lines&: AnnotatedLines);
3046
3047 checkEmptyNamespace(AnnotatedLines);
3048
3049 for (auto *Line : AnnotatedLines)
3050 cleanupLine(Line);
3051
3052 return {generateFixes(), 0};
3053 }
3054
3055private:
3056 void cleanupLine(AnnotatedLine *Line) {
3057 for (auto *Child : Line->Children)
3058 cleanupLine(Line: Child);
3059
3060 if (Line->Affected) {
3061 cleanupRight(Start: Line->First, LK: tok::comma, RK: tok::comma);
3062 cleanupRight(Start: Line->First, LK: TT_CtorInitializerColon, RK: tok::comma);
3063 cleanupRight(Start: Line->First, LK: tok::l_paren, RK: tok::comma);
3064 cleanupLeft(Start: Line->First, LK: tok::comma, RK: tok::r_paren);
3065 cleanupLeft(Start: Line->First, LK: TT_CtorInitializerComma, RK: tok::l_brace);
3066 cleanupLeft(Start: Line->First, LK: TT_CtorInitializerColon, RK: tok::l_brace);
3067 cleanupLeft(Start: Line->First, LK: TT_CtorInitializerColon, RK: tok::equal);
3068 }
3069 }
3070
3071 bool containsOnlyComments(const AnnotatedLine &Line) {
3072 for (FormatToken *Tok = Line.First; Tok; Tok = Tok->Next)
3073 if (Tok->isNot(Kind: tok::comment))
3074 return false;
3075 return true;
3076 }
3077
3078 // Iterate through all lines and remove any empty (nested) namespaces.
3079 void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
3080 std::set<unsigned> DeletedLines;
3081 for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
3082 auto &Line = *AnnotatedLines[i];
3083 if (Line.startsWithNamespace())
3084 checkEmptyNamespace(AnnotatedLines, CurrentLine: i, NewLine&: i, DeletedLines);
3085 }
3086
3087 for (auto Line : DeletedLines) {
3088 FormatToken *Tok = AnnotatedLines[Line]->First;
3089 while (Tok) {
3090 deleteToken(Tok);
3091 Tok = Tok->Next;
3092 }
3093 }
3094 }
3095
3096 // The function checks if the namespace, which starts from \p CurrentLine, and
3097 // its nested namespaces are empty and delete them if they are empty. It also
3098 // sets \p NewLine to the last line checked.
3099 // Returns true if the current namespace is empty.
3100 bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
3101 unsigned CurrentLine, unsigned &NewLine,
3102 std::set<unsigned> &DeletedLines) {
3103 unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
3104 if (Style.BraceWrapping.AfterNamespace) {
3105 // If the left brace is in a new line, we should consume it first so that
3106 // it does not make the namespace non-empty.
3107 // FIXME: error handling if there is no left brace.
3108 if (!AnnotatedLines[++CurrentLine]->startsWith(Tokens: tok::l_brace)) {
3109 NewLine = CurrentLine;
3110 return false;
3111 }
3112 } else if (!AnnotatedLines[CurrentLine]->endsWith(Tokens: tok::l_brace)) {
3113 return false;
3114 }
3115 while (++CurrentLine < End) {
3116 if (AnnotatedLines[CurrentLine]->startsWith(Tokens: tok::r_brace))
3117 break;
3118
3119 if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
3120 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
3121 DeletedLines)) {
3122 return false;
3123 }
3124 CurrentLine = NewLine;
3125 continue;
3126 }
3127
3128 if (containsOnlyComments(Line: *AnnotatedLines[CurrentLine]))
3129 continue;
3130
3131 // If there is anything other than comments or nested namespaces in the
3132 // current namespace, the namespace cannot be empty.
3133 NewLine = CurrentLine;
3134 return false;
3135 }
3136
3137 NewLine = CurrentLine;
3138 if (CurrentLine >= End)
3139 return false;
3140
3141 // Check if the empty namespace is actually affected by changed ranges.
3142 if (!AffectedRangeMgr.affectsCharSourceRange(Range: CharSourceRange::getCharRange(
3143 B: AnnotatedLines[InitLine]->First->Tok.getLocation(),
3144 E: AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) {
3145 return false;
3146 }
3147
3148 for (unsigned i = InitLine; i <= CurrentLine; ++i)
3149 DeletedLines.insert(x: i);
3150
3151 return true;
3152 }
3153
3154 // Checks pairs {start, start->next},..., {end->previous, end} and deletes one
3155 // of the token in the pair if the left token has \p LK token kind and the
3156 // right token has \p RK token kind. If \p DeleteLeft is true, the left token
3157 // is deleted on match; otherwise, the right token is deleted.
3158 template <typename LeftKind, typename RightKind>
3159 void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
3160 bool DeleteLeft) {
3161 auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {
3162 for (auto *Res = Tok.Next; Res; Res = Res->Next) {
3163 if (Res->isNot(Kind: tok::comment) &&
3164 DeletedTokens.find(x: Res) == DeletedTokens.end()) {
3165 return Res;
3166 }
3167 }
3168 return nullptr;
3169 };
3170 for (auto *Left = Start; Left;) {
3171 auto *Right = NextNotDeleted(*Left);
3172 if (!Right)
3173 break;
3174 if (Left->is(LK) && Right->is(RK)) {
3175 deleteToken(Tok: DeleteLeft ? Left : Right);
3176 for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
3177 deleteToken(Tok);
3178 // If the right token is deleted, we should keep the left token
3179 // unchanged and pair it with the new right token.
3180 if (!DeleteLeft)
3181 continue;
3182 }
3183 Left = Right;
3184 }
3185 }
3186
3187 template <typename LeftKind, typename RightKind>
3188 void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
3189 cleanupPair(Start, LK, RK, /*DeleteLeft=*/true);
3190 }
3191
3192 template <typename LeftKind, typename RightKind>
3193 void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
3194 cleanupPair(Start, LK, RK, /*DeleteLeft=*/false);
3195 }
3196
3197 // Delete the given token.
3198 inline void deleteToken(FormatToken *Tok) {
3199 if (Tok)
3200 DeletedTokens.insert(x: Tok);
3201 }
3202
3203 tooling::Replacements generateFixes() {
3204 tooling::Replacements Fixes;
3205 SmallVector<FormatToken *> Tokens;
3206 std::copy(first: DeletedTokens.begin(), last: DeletedTokens.end(),
3207 result: std::back_inserter(x&: Tokens));
3208
3209 // Merge multiple continuous token deletions into one big deletion so that
3210 // the number of replacements can be reduced. This makes computing affected
3211 // ranges more efficient when we run reformat on the changed code.
3212 unsigned Idx = 0;
3213 while (Idx < Tokens.size()) {
3214 unsigned St = Idx, End = Idx;
3215 while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1])
3216 ++End;
3217 auto SR = CharSourceRange::getCharRange(B: Tokens[St]->Tok.getLocation(),
3218 E: Tokens[End]->Tok.getEndLoc());
3219 auto Err =
3220 Fixes.add(R: tooling::Replacement(Env.getSourceManager(), SR, ""));
3221 // FIXME: better error handling. for now just print error message and skip
3222 // for the release version.
3223 if (Err) {
3224 llvm::errs() << toString(E: std::move(Err)) << "\n";
3225 assert(false && "Fixes must not conflict!");
3226 }
3227 Idx = End + 1;
3228 }
3229
3230 return Fixes;
3231 }
3232
3233 // Class for less-than inequality comparason for the set `RedundantTokens`.
3234 // We store tokens in the order they appear in the translation unit so that
3235 // we do not need to sort them in `generateFixes()`.
3236 struct FormatTokenLess {
3237 FormatTokenLess(const SourceManager &SM) : SM(SM) {}
3238
3239 bool operator()(const FormatToken *LHS, const FormatToken *RHS) const {
3240 return SM.isBeforeInTranslationUnit(LHS: LHS->Tok.getLocation(),
3241 RHS: RHS->Tok.getLocation());
3242 }
3243 const SourceManager &SM;
3244 };
3245
3246 // Tokens to be deleted.
3247 std::set<FormatToken *, FormatTokenLess> DeletedTokens;
3248};
3249
3250class ObjCHeaderStyleGuesser : public TokenAnalyzer {
3251public:
3252 ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style)
3253 : TokenAnalyzer(Env, Style), IsObjC(false) {}
3254
3255 std::pair<tooling::Replacements, unsigned>
3256 analyze(TokenAnnotator &Annotator,
3257 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
3258 FormatTokenLexer &Tokens) override {
3259 assert(Style.Language == FormatStyle::LK_Cpp);
3260 IsObjC = guessIsObjC(SourceManager: Env.getSourceManager(), AnnotatedLines,
3261 Keywords: Tokens.getKeywords());
3262 tooling::Replacements Result;
3263 return {Result, 0};
3264 }
3265
3266 bool isObjC() { return IsObjC; }
3267
3268private:
3269 static bool
3270 guessIsObjC(const SourceManager &SourceManager,
3271 const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
3272 const AdditionalKeywords &Keywords) {
3273 // Keep this array sorted, since we are binary searching over it.
3274 static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
3275 "CGFloat",
3276 "CGPoint",
3277 "CGPointMake",
3278 "CGPointZero",
3279 "CGRect",
3280 "CGRectEdge",
3281 "CGRectInfinite",
3282 "CGRectMake",
3283 "CGRectNull",
3284 "CGRectZero",
3285 "CGSize",
3286 "CGSizeMake",
3287 "CGVector",
3288 "CGVectorMake",
3289 "FOUNDATION_EXPORT", // This is an alias for FOUNDATION_EXTERN.
3290 "FOUNDATION_EXTERN",
3291 "NSAffineTransform",
3292 "NSArray",
3293 "NSAttributedString",
3294 "NSBlockOperation",
3295 "NSBundle",
3296 "NSCache",
3297 "NSCalendar",
3298 "NSCharacterSet",
3299 "NSCountedSet",
3300 "NSData",
3301 "NSDataDetector",
3302 "NSDecimal",
3303 "NSDecimalNumber",
3304 "NSDictionary",
3305 "NSEdgeInsets",
3306 "NSError",
3307 "NSErrorDomain",
3308 "NSHashTable",
3309 "NSIndexPath",
3310 "NSIndexSet",
3311 "NSInteger",
3312 "NSInvocationOperation",
3313 "NSLocale",
3314 "NSMapTable",
3315 "NSMutableArray",
3316 "NSMutableAttributedString",
3317 "NSMutableCharacterSet",
3318 "NSMutableData",
3319 "NSMutableDictionary",
3320 "NSMutableIndexSet",
3321 "NSMutableOrderedSet",
3322 "NSMutableSet",
3323 "NSMutableString",
3324 "NSNumber",
3325 "NSNumberFormatter",
3326 "NSObject",
3327 "NSOperation",
3328 "NSOperationQueue",
3329 "NSOperationQueuePriority",
3330 "NSOrderedSet",
3331 "NSPoint",
3332 "NSPointerArray",
3333 "NSQualityOfService",
3334 "NSRange",
3335 "NSRect",
3336 "NSRegularExpression",
3337 "NSSet",
3338 "NSSize",
3339 "NSString",
3340 "NSTimeZone",
3341 "NSUInteger",
3342 "NSURL",
3343 "NSURLComponents",
3344 "NSURLQueryItem",
3345 "NSUUID",
3346 "NSValue",
3347 "NS_ASSUME_NONNULL_BEGIN",
3348 "UIImage",
3349 "UIView",
3350 };
3351 assert(llvm::is_sorted(FoundationIdentifiers));
3352
3353 for (auto *Line : AnnotatedLines) {
3354 if (Line->First && (Line->First->TokenText.starts_with(Prefix: "#") ||
3355 Line->First->TokenText == "__pragma" ||
3356 Line->First->TokenText == "_Pragma")) {
3357 continue;
3358 }
3359 for (const FormatToken *FormatTok = Line->First; FormatTok;
3360 FormatTok = FormatTok->Next) {
3361 if ((FormatTok->Previous && FormatTok->Previous->is(Kind: tok::at) &&
3362 (FormatTok->isNot(Kind: tok::objc_not_keyword) ||
3363 FormatTok->isOneOf(K1: tok::numeric_constant, K2: tok::l_square,
3364 Ks: tok::l_brace))) ||
3365 (FormatTok->Tok.isAnyIdentifier() &&
3366 llvm::binary_search(Range: FoundationIdentifiers,
3367 Value: FormatTok->TokenText)) ||
3368 FormatTok->is(TT: TT_ObjCStringLiteral) ||
3369 FormatTok->isOneOf(K1: Keywords.kw_NS_CLOSED_ENUM, K2: Keywords.kw_NS_ENUM,
3370 Ks: Keywords.kw_NS_ERROR_ENUM,
3371 Ks: Keywords.kw_NS_OPTIONS, Ks: TT_ObjCBlockLBrace,
3372 Ks: TT_ObjCBlockLParen, Ks: TT_ObjCDecl, Ks: TT_ObjCForIn,
3373 Ks: TT_ObjCMethodExpr, Ks: TT_ObjCMethodSpecifier,
3374 Ks: TT_ObjCProperty, Ks: TT_ObjCSelector)) {
3375 LLVM_DEBUG(llvm::dbgs()
3376 << "Detected ObjC at location "
3377 << FormatTok->Tok.getLocation().printToString(
3378 SourceManager)
3379 << " token: " << FormatTok->TokenText << " token type: "
3380 << getTokenTypeName(FormatTok->getType()) << "\n");
3381 return true;
3382 }
3383 }
3384 if (guessIsObjC(SourceManager, AnnotatedLines: Line->Children, Keywords))
3385 return true;
3386 }
3387 return false;
3388 }
3389
3390 bool IsObjC;
3391};
3392
3393struct IncludeDirective {
3394 StringRef Filename;
3395 StringRef Text;
3396 unsigned Offset;
3397 int Category;
3398 int Priority;
3399};
3400
3401struct JavaImportDirective {
3402 StringRef Identifier;
3403 StringRef Text;
3404 unsigned Offset;
3405 SmallVector<StringRef> AssociatedCommentLines;
3406 bool IsStatic;
3407};
3408
3409} // end anonymous namespace
3410
3411// Determines whether 'Ranges' intersects with ('Start', 'End').
3412static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start,
3413 unsigned End) {
3414 for (const auto &Range : Ranges) {
3415 if (Range.getOffset() < End &&
3416 Range.getOffset() + Range.getLength() > Start) {
3417 return true;
3418 }
3419 }
3420 return false;
3421}
3422
3423// Returns a pair (Index, OffsetToEOL) describing the position of the cursor
3424// before sorting/deduplicating. Index is the index of the include under the
3425// cursor in the original set of includes. If this include has duplicates, it is
3426// the index of the first of the duplicates as the others are going to be
3427// removed. OffsetToEOL describes the cursor's position relative to the end of
3428// its current line.
3429// If `Cursor` is not on any #include, `Index` will be
3430// std::numeric_limits<unsigned>::max().
3431static std::pair<unsigned, unsigned>
3432FindCursorIndex(const ArrayRef<IncludeDirective> &Includes,
3433 const ArrayRef<unsigned> &Indices, unsigned Cursor) {
3434 unsigned CursorIndex = std::numeric_limits<unsigned>::max();
3435 unsigned OffsetToEOL = 0;
3436 for (int i = 0, e = Includes.size(); i != e; ++i) {
3437 unsigned Start = Includes[Indices[i]].Offset;
3438 unsigned End = Start + Includes[Indices[i]].Text.size();
3439 if (!(Cursor >= Start && Cursor < End))
3440 continue;
3441 CursorIndex = Indices[i];
3442 OffsetToEOL = End - Cursor;
3443 // Put the cursor on the only remaining #include among the duplicate
3444 // #includes.
3445 while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text)
3446 CursorIndex = i;
3447 break;
3448 }
3449 return std::make_pair(x&: CursorIndex, y&: OffsetToEOL);
3450}
3451
3452// Replace all "\r\n" with "\n".
3453std::string replaceCRLF(const std::string &Code) {
3454 std::string NewCode;
3455 size_t Pos = 0, LastPos = 0;
3456
3457 do {
3458 Pos = Code.find(s: "\r\n", pos: LastPos);
3459 if (Pos == LastPos) {
3460 ++LastPos;
3461 continue;
3462 }
3463 if (Pos == std::string::npos) {
3464 NewCode += Code.substr(pos: LastPos);
3465 break;
3466 }
3467 NewCode += Code.substr(pos: LastPos, n: Pos - LastPos) + "\n";
3468 LastPos = Pos + 2;
3469 } while (Pos != std::string::npos);
3470
3471 return NewCode;
3472}
3473
3474// Sorts and deduplicate a block of includes given by 'Includes' alphabetically
3475// adding the necessary replacement to 'Replaces'. 'Includes' must be in strict
3476// source order.
3477// #include directives with the same text will be deduplicated, and only the
3478// first #include in the duplicate #includes remains. If the `Cursor` is
3479// provided and put on a deleted #include, it will be moved to the remaining
3480// #include in the duplicate #includes.
3481static void sortCppIncludes(const FormatStyle &Style,
3482 const ArrayRef<IncludeDirective> &Includes,
3483 ArrayRef<tooling::Range> Ranges, StringRef FileName,
3484 StringRef Code, tooling::Replacements &Replaces,
3485 unsigned *Cursor) {
3486 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
3487 const unsigned IncludesBeginOffset = Includes.front().Offset;
3488 const unsigned IncludesEndOffset =
3489 Includes.back().Offset + Includes.back().Text.size();
3490 const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
3491 if (!affectsRange(Ranges, Start: IncludesBeginOffset, End: IncludesEndOffset))
3492 return;
3493 SmallVector<unsigned, 16> Indices =
3494 llvm::to_vector<16>(Range: llvm::seq<unsigned>(Begin: 0, End: Includes.size()));
3495
3496 if (Style.SortIncludes.Enabled) {
3497 stable_sort(Range&: Indices, C: [&](unsigned LHSI, unsigned RHSI) {
3498 SmallString<128> LHSStem, RHSStem;
3499 if (Style.SortIncludes.IgnoreExtension) {
3500 LHSStem = Includes[LHSI].Filename;
3501 RHSStem = Includes[RHSI].Filename;
3502 llvm::sys::path::replace_extension(path&: LHSStem, extension: "");
3503 llvm::sys::path::replace_extension(path&: RHSStem, extension: "");
3504 }
3505 std::string LHSStemLower, RHSStemLower;
3506 std::string LHSFilenameLower, RHSFilenameLower;
3507 if (Style.SortIncludes.IgnoreCase) {
3508 LHSStemLower = LHSStem.str().lower();
3509 RHSStemLower = RHSStem.str().lower();
3510 LHSFilenameLower = Includes[LHSI].Filename.lower();
3511 RHSFilenameLower = Includes[RHSI].Filename.lower();
3512 }
3513 return std::tie(args: Includes[LHSI].Priority, args&: LHSStemLower, args&: LHSStem,
3514 args&: LHSFilenameLower, args: Includes[LHSI].Filename) <
3515 std::tie(args: Includes[RHSI].Priority, args&: RHSStemLower, args&: RHSStem,
3516 args&: RHSFilenameLower, args: Includes[RHSI].Filename);
3517 });
3518 }
3519
3520 // The index of the include on which the cursor will be put after
3521 // sorting/deduplicating.
3522 unsigned CursorIndex;
3523 // The offset from cursor to the end of line.
3524 unsigned CursorToEOLOffset;
3525 if (Cursor) {
3526 std::tie(args&: CursorIndex, args&: CursorToEOLOffset) =
3527 FindCursorIndex(Includes, Indices, Cursor: *Cursor);
3528 }
3529
3530 // Deduplicate #includes.
3531 Indices.erase(CS: llvm::unique(R&: Indices,
3532 P: [&](unsigned LHSI, unsigned RHSI) {
3533 return Includes[LHSI].Text.trim() ==
3534 Includes[RHSI].Text.trim();
3535 }),
3536 CE: Indices.end());
3537
3538 int CurrentCategory = Includes.front().Category;
3539
3540 // If the #includes are out of order, we generate a single replacement fixing
3541 // the entire block. Otherwise, no replacement is generated.
3542 // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not
3543 // enough as additional newlines might be added or removed across #include
3544 // blocks. This we handle below by generating the updated #include blocks and
3545 // comparing it to the original.
3546 if (Indices.size() == Includes.size() && is_sorted(Range&: Indices) &&
3547 Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) {
3548 return;
3549 }
3550
3551 const auto OldCursor = Cursor ? *Cursor : 0;
3552 std::string result;
3553 for (unsigned Index : Indices) {
3554 if (!result.empty()) {
3555 result += "\n";
3556 if (Style.IncludeStyle.IncludeBlocks ==
3557 tooling::IncludeStyle::IBS_Regroup &&
3558 CurrentCategory != Includes[Index].Category) {
3559 result += "\n";
3560 }
3561 }
3562 result += Includes[Index].Text;
3563 if (Cursor && CursorIndex == Index)
3564 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
3565 CurrentCategory = Includes[Index].Category;
3566 }
3567
3568 if (Cursor && *Cursor >= IncludesEndOffset)
3569 *Cursor += result.size() - IncludesBlockSize;
3570
3571 // If the #includes are out of order, we generate a single replacement fixing
3572 // the entire range of blocks. Otherwise, no replacement is generated.
3573 if (replaceCRLF(Code: result) == replaceCRLF(Code: std::string(Code.substr(
3574 Start: IncludesBeginOffset, N: IncludesBlockSize)))) {
3575 if (Cursor)
3576 *Cursor = OldCursor;
3577 return;
3578 }
3579
3580 auto Err = Replaces.add(R: tooling::Replacement(
3581 FileName, Includes.front().Offset, IncludesBlockSize, result));
3582 // FIXME: better error handling. For now, just skip the replacement for the
3583 // release version.
3584 if (Err) {
3585 llvm::errs() << toString(E: std::move(Err)) << "\n";
3586 assert(false);
3587 }
3588}
3589
3590tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
3591 ArrayRef<tooling::Range> Ranges,
3592 StringRef FileName,
3593 tooling::Replacements &Replaces,
3594 unsigned *Cursor) {
3595 unsigned Prev = llvm::StringSwitch<size_t>(Code)
3596 .StartsWith(S: "\xEF\xBB\xBF", Value: 3) // UTF-8 BOM
3597 .Default(Value: 0);
3598 unsigned SearchFrom = 0;
3599 SmallVector<StringRef, 4> Matches;
3600 SmallVector<IncludeDirective, 16> IncludesInBlock;
3601
3602 // In compiled files, consider the first #include to be the main #include of
3603 // the file if it is not a system #include. This ensures that the header
3604 // doesn't have hidden dependencies
3605 // (http://llvm.org/docs/CodingStandards.html#include-style).
3606 //
3607 // FIXME: Do some validation, e.g. edit distance of the base name, to fix
3608 // cases where the first #include is unlikely to be the main header.
3609 tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
3610 bool FirstIncludeBlock = true;
3611 bool MainIncludeFound = false;
3612 bool FormattingOff = false;
3613
3614 // '[' must be the first and '-' the last character inside [...].
3615 llvm::Regex RawStringRegex(
3616 "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\(");
3617 SmallVector<StringRef, 2> RawStringMatches;
3618 std::string RawStringTermination = ")\"";
3619
3620 for (const auto Size = Code.size(); SearchFrom < Size;) {
3621 size_t Pos = SearchFrom;
3622 if (Code[SearchFrom] != '\n') {
3623 do { // Search for the first newline while skipping line splices.
3624 ++Pos;
3625 Pos = Code.find(C: '\n', From: Pos);
3626 } while (Pos != StringRef::npos && Code[Pos - 1] == '\\');
3627 }
3628
3629 StringRef Line =
3630 Code.substr(Start: Prev, N: (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3631
3632 StringRef Trimmed = Line.trim();
3633
3634 // #includes inside raw string literals need to be ignored.
3635 // or we will sort the contents of the string.
3636 // Skip past until we think we are at the rawstring literal close.
3637 if (RawStringRegex.match(String: Trimmed, Matches: &RawStringMatches)) {
3638 std::string CharSequence = RawStringMatches[1].str();
3639 RawStringTermination = ")" + CharSequence + "\"";
3640 FormattingOff = true;
3641 }
3642
3643 if (Trimmed.contains(Other: RawStringTermination))
3644 FormattingOff = false;
3645
3646 bool IsBlockComment = false;
3647
3648 if (isClangFormatOff(Comment: Trimmed)) {
3649 FormattingOff = true;
3650 } else if (isClangFormatOn(Comment: Trimmed)) {
3651 FormattingOff = false;
3652 } else if (Trimmed.starts_with(Prefix: "/*")) {
3653 IsBlockComment = true;
3654 Pos = Code.find(Str: "*/", From: SearchFrom + 2);
3655 }
3656
3657 const bool EmptyLineSkipped =
3658 Trimmed.empty() &&
3659 (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge ||
3660 Style.IncludeStyle.IncludeBlocks ==
3661 tooling::IncludeStyle::IBS_Regroup);
3662
3663 bool MergeWithNextLine = Trimmed.ends_with(Suffix: "\\");
3664 if (!FormattingOff && !MergeWithNextLine) {
3665 if (!IsBlockComment &&
3666 tooling::HeaderIncludes::IncludeRegex.match(String: Trimmed, Matches: &Matches)) {
3667 StringRef IncludeName = Matches[2];
3668 if (Trimmed.contains(Other: "/*") && !Trimmed.contains(Other: "*/")) {
3669 // #include with a start of a block comment, but without the end.
3670 // Need to keep all the lines until the end of the comment together.
3671 // FIXME: This is somehow simplified check that probably does not work
3672 // correctly if there are multiple comments on a line.
3673 Pos = Code.find(Str: "*/", From: SearchFrom);
3674 Line = Code.substr(
3675 Start: Prev, N: (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev);
3676 }
3677 int Category = Categories.getIncludePriority(
3678 IncludeName,
3679 /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock);
3680 int Priority = Categories.getSortIncludePriority(
3681 IncludeName, CheckMainHeader: !MainIncludeFound && FirstIncludeBlock);
3682 if (Category == 0)
3683 MainIncludeFound = true;
3684 IncludesInBlock.push_back(
3685 Elt: {.Filename: IncludeName, .Text: Line, .Offset: Prev, .Category: Category, .Priority: Priority});
3686 } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
3687 sortCppIncludes(Style, Includes: IncludesInBlock, Ranges, FileName, Code,
3688 Replaces, Cursor);
3689 IncludesInBlock.clear();
3690 if (Trimmed.starts_with(Prefix: "#pragma hdrstop")) // Precompiled headers.
3691 FirstIncludeBlock = true;
3692 else
3693 FirstIncludeBlock = false;
3694 }
3695 }
3696 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3697 break;
3698
3699 if (!MergeWithNextLine)
3700 Prev = Pos + 1;
3701 SearchFrom = Pos + 1;
3702 }
3703 if (!IncludesInBlock.empty()) {
3704 sortCppIncludes(Style, Includes: IncludesInBlock, Ranges, FileName, Code, Replaces,
3705 Cursor);
3706 }
3707 return Replaces;
3708}
3709
3710// Returns group number to use as a first order sort on imports. Gives
3711// std::numeric_limits<unsigned>::max() if the import does not match any given
3712// groups.
3713static unsigned findJavaImportGroup(const FormatStyle &Style,
3714 StringRef ImportIdentifier) {
3715 unsigned LongestMatchIndex = std::numeric_limits<unsigned>::max();
3716 unsigned LongestMatchLength = 0;
3717 for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) {
3718 const std::string &GroupPrefix = Style.JavaImportGroups[I];
3719 if (ImportIdentifier.starts_with(Prefix: GroupPrefix) &&
3720 GroupPrefix.length() > LongestMatchLength) {
3721 LongestMatchIndex = I;
3722 LongestMatchLength = GroupPrefix.length();
3723 }
3724 }
3725 return LongestMatchIndex;
3726}
3727
3728// Sorts and deduplicates a block of includes given by 'Imports' based on
3729// JavaImportGroups, then adding the necessary replacement to 'Replaces'.
3730// Import declarations with the same text will be deduplicated. Between each
3731// import group, a newline is inserted, and within each import group, a
3732// lexicographic sort based on ASCII value is performed.
3733static void sortJavaImports(const FormatStyle &Style,
3734 const ArrayRef<JavaImportDirective> &Imports,
3735 ArrayRef<tooling::Range> Ranges, StringRef FileName,
3736 StringRef Code, tooling::Replacements &Replaces) {
3737 unsigned ImportsBeginOffset = Imports.front().Offset;
3738 unsigned ImportsEndOffset =
3739 Imports.back().Offset + Imports.back().Text.size();
3740 unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;
3741 if (!affectsRange(Ranges, Start: ImportsBeginOffset, End: ImportsEndOffset))
3742 return;
3743
3744 SmallVector<unsigned, 16> Indices =
3745 llvm::to_vector<16>(Range: llvm::seq<unsigned>(Begin: 0, End: Imports.size()));
3746 SmallVector<unsigned, 16> JavaImportGroups;
3747 JavaImportGroups.reserve(N: Imports.size());
3748 for (const JavaImportDirective &Import : Imports)
3749 JavaImportGroups.push_back(Elt: findJavaImportGroup(Style, ImportIdentifier: Import.Identifier));
3750
3751 bool StaticImportAfterNormalImport =
3752 Style.SortJavaStaticImport == FormatStyle::SJSIO_After;
3753 sort(C&: Indices, Comp: [&](unsigned LHSI, unsigned RHSI) {
3754 // Negating IsStatic to push static imports above non-static imports.
3755 return std::make_tuple(args: !Imports[LHSI].IsStatic ^
3756 StaticImportAfterNormalImport,
3757 args&: JavaImportGroups[LHSI], args: Imports[LHSI].Identifier) <
3758 std::make_tuple(args: !Imports[RHSI].IsStatic ^
3759 StaticImportAfterNormalImport,
3760 args&: JavaImportGroups[RHSI], args: Imports[RHSI].Identifier);
3761 });
3762
3763 // Deduplicate imports.
3764 Indices.erase(CS: llvm::unique(R&: Indices,
3765 P: [&](unsigned LHSI, unsigned RHSI) {
3766 return Imports[LHSI].Text == Imports[RHSI].Text;
3767 }),
3768 CE: Indices.end());
3769
3770 bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
3771 unsigned CurrentImportGroup = JavaImportGroups[Indices.front()];
3772
3773 std::string result;
3774 for (unsigned Index : Indices) {
3775 if (!result.empty()) {
3776 result += "\n";
3777 if (CurrentIsStatic != Imports[Index].IsStatic ||
3778 CurrentImportGroup != JavaImportGroups[Index]) {
3779 result += "\n";
3780 }
3781 }
3782 for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) {
3783 result += CommentLine;
3784 result += "\n";
3785 }
3786 result += Imports[Index].Text;
3787 CurrentIsStatic = Imports[Index].IsStatic;
3788 CurrentImportGroup = JavaImportGroups[Index];
3789 }
3790
3791 // If the imports are out of order, we generate a single replacement fixing
3792 // the entire block. Otherwise, no replacement is generated.
3793 if (replaceCRLF(Code: result) == replaceCRLF(Code: std::string(Code.substr(
3794 Start: Imports.front().Offset, N: ImportsBlockSize)))) {
3795 return;
3796 }
3797
3798 auto Err = Replaces.add(R: tooling::Replacement(FileName, Imports.front().Offset,
3799 ImportsBlockSize, result));
3800 // FIXME: better error handling. For now, just skip the replacement for the
3801 // release version.
3802 if (Err) {
3803 llvm::errs() << toString(E: std::move(Err)) << "\n";
3804 assert(false);
3805 }
3806}
3807
3808namespace {
3809
3810const char JavaImportRegexPattern[] =
3811 "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;";
3812
3813} // anonymous namespace
3814
3815tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code,
3816 ArrayRef<tooling::Range> Ranges,
3817 StringRef FileName,
3818 tooling::Replacements &Replaces) {
3819 unsigned Prev = 0;
3820 unsigned SearchFrom = 0;
3821 llvm::Regex ImportRegex(JavaImportRegexPattern);
3822 SmallVector<StringRef, 4> Matches;
3823 SmallVector<JavaImportDirective, 16> ImportsInBlock;
3824 SmallVector<StringRef> AssociatedCommentLines;
3825
3826 bool FormattingOff = false;
3827
3828 for (;;) {
3829 auto Pos = Code.find(C: '\n', From: SearchFrom);
3830 StringRef Line =
3831 Code.substr(Start: Prev, N: (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
3832
3833 StringRef Trimmed = Line.trim();
3834 if (isClangFormatOff(Comment: Trimmed))
3835 FormattingOff = true;
3836 else if (isClangFormatOn(Comment: Trimmed))
3837 FormattingOff = false;
3838
3839 if (ImportRegex.match(String: Line, Matches: &Matches)) {
3840 if (FormattingOff) {
3841 // If at least one import line has formatting turned off, turn off
3842 // formatting entirely.
3843 return Replaces;
3844 }
3845 StringRef Static = Matches[1];
3846 StringRef Identifier = Matches[2];
3847 bool IsStatic = false;
3848 if (Static.contains(Other: "static"))
3849 IsStatic = true;
3850 ImportsInBlock.push_back(
3851 Elt: {.Identifier: Identifier, .Text: Line, .Offset: Prev, .AssociatedCommentLines: AssociatedCommentLines, .IsStatic: IsStatic});
3852 AssociatedCommentLines.clear();
3853 } else if (!Trimmed.empty() && !ImportsInBlock.empty()) {
3854 // Associating comments within the imports with the nearest import below
3855 AssociatedCommentLines.push_back(Elt: Line);
3856 }
3857 Prev = Pos + 1;
3858 if (Pos == StringRef::npos || Pos + 1 == Code.size())
3859 break;
3860 SearchFrom = Pos + 1;
3861 }
3862 if (!ImportsInBlock.empty())
3863 sortJavaImports(Style, Imports: ImportsInBlock, Ranges, FileName, Code, Replaces);
3864 return Replaces;
3865}
3866
3867bool isMpegTS(StringRef Code) {
3868 // MPEG transport streams use the ".ts" file extension. clang-format should
3869 // not attempt to format those. MPEG TS' frame format starts with 0x47 every
3870 // 189 bytes - detect that and return.
3871 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
3872}
3873
3874bool isLikelyXml(StringRef Code) { return Code.ltrim().starts_with(Prefix: "<"); }
3875
3876tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
3877 ArrayRef<tooling::Range> Ranges,
3878 StringRef FileName, unsigned *Cursor) {
3879 tooling::Replacements Replaces;
3880 if (!Style.SortIncludes.Enabled || Style.DisableFormat)
3881 return Replaces;
3882 if (isLikelyXml(Code))
3883 return Replaces;
3884 if (Style.isJavaScript()) {
3885 if (isMpegTS(Code))
3886 return Replaces;
3887 return sortJavaScriptImports(Style, Code, Ranges, FileName);
3888 }
3889 if (Style.isJava())
3890 return sortJavaImports(Style, Code, Ranges, FileName, Replaces);
3891 if (Style.isCpp())
3892 sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor);
3893 return Replaces;
3894}
3895
3896template <typename T>
3897static Expected<tooling::Replacements>
3898processReplacements(T ProcessFunc, StringRef Code,
3899 const tooling::Replacements &Replaces,
3900 const FormatStyle &Style) {
3901 if (Replaces.empty())
3902 return tooling::Replacements();
3903
3904 auto NewCode = applyAllReplacements(Code, Replaces);
3905 if (!NewCode)
3906 return NewCode.takeError();
3907 std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();
3908 StringRef FileName = Replaces.begin()->getFilePath();
3909
3910 tooling::Replacements FormatReplaces =
3911 ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
3912
3913 return Replaces.merge(Replaces: FormatReplaces);
3914}
3915
3916Expected<tooling::Replacements>
3917formatReplacements(StringRef Code, const tooling::Replacements &Replaces,
3918 const FormatStyle &Style) {
3919 // We need to use lambda function here since there are two versions of
3920 // `sortIncludes`.
3921 auto SortIncludes = [](const FormatStyle &Style, StringRef Code,
3922 std::vector<tooling::Range> Ranges,
3923 StringRef FileName) -> tooling::Replacements {
3924 return sortIncludes(Style, Code, Ranges, FileName);
3925 };
3926 auto SortedReplaces =
3927 processReplacements(ProcessFunc: SortIncludes, Code, Replaces, Style);
3928 if (!SortedReplaces)
3929 return SortedReplaces.takeError();
3930
3931 // We need to use lambda function here since there are two versions of
3932 // `reformat`.
3933 auto Reformat = [](const FormatStyle &Style, StringRef Code,
3934 std::vector<tooling::Range> Ranges,
3935 StringRef FileName) -> tooling::Replacements {
3936 return reformat(Style, Code, Ranges, FileName);
3937 };
3938 return processReplacements(ProcessFunc: Reformat, Code, Replaces: *SortedReplaces, Style);
3939}
3940
3941namespace {
3942
3943inline bool isHeaderInsertion(const tooling::Replacement &Replace) {
3944 return Replace.getOffset() == std::numeric_limits<unsigned>::max() &&
3945 Replace.getLength() == 0 &&
3946 tooling::HeaderIncludes::IncludeRegex.match(
3947 String: Replace.getReplacementText());
3948}
3949
3950inline bool isHeaderDeletion(const tooling::Replacement &Replace) {
3951 return Replace.getOffset() == std::numeric_limits<unsigned>::max() &&
3952 Replace.getLength() == 1;
3953}
3954
3955// FIXME: insert empty lines between newly created blocks.
3956tooling::Replacements
3957fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
3958 const FormatStyle &Style) {
3959 if (!Style.isCpp())
3960 return Replaces;
3961
3962 tooling::Replacements HeaderInsertions;
3963 std::set<StringRef> HeadersToDelete;
3964 tooling::Replacements Result;
3965 for (const auto &R : Replaces) {
3966 if (isHeaderInsertion(Replace: R)) {
3967 // Replacements from \p Replaces must be conflict-free already, so we can
3968 // simply consume the error.
3969 consumeError(Err: HeaderInsertions.add(R));
3970 } else if (isHeaderDeletion(Replace: R)) {
3971 HeadersToDelete.insert(x: R.getReplacementText());
3972 } else if (R.getOffset() == std::numeric_limits<unsigned>::max()) {
3973 llvm::errs() << "Insertions other than header #include insertion are "
3974 "not supported! "
3975 << R.getReplacementText() << "\n";
3976 } else {
3977 consumeError(Err: Result.add(R));
3978 }
3979 }
3980 if (HeaderInsertions.empty() && HeadersToDelete.empty())
3981 return Replaces;
3982
3983 StringRef FileName = Replaces.begin()->getFilePath();
3984 tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle);
3985
3986 for (const auto &Header : HeadersToDelete) {
3987 tooling::Replacements Replaces =
3988 Includes.remove(Header: Header.trim(Chars: "\"<>"), IsAngled: Header.starts_with(Prefix: "<"));
3989 for (const auto &R : Replaces) {
3990 auto Err = Result.add(R);
3991 if (Err) {
3992 // Ignore the deletion on conflict.
3993 llvm::errs() << "Failed to add header deletion replacement for "
3994 << Header << ": " << toString(E: std::move(Err)) << "\n";
3995 }
3996 }
3997 }
3998
3999 SmallVector<StringRef, 4> Matches;
4000 for (const auto &R : HeaderInsertions) {
4001 auto IncludeDirective = R.getReplacementText();
4002 bool Matched =
4003 tooling::HeaderIncludes::IncludeRegex.match(String: IncludeDirective, Matches: &Matches);
4004 assert(Matched && "Header insertion replacement must have replacement text "
4005 "'#include ...'");
4006 (void)Matched;
4007 auto IncludeName = Matches[2];
4008 auto Replace =
4009 Includes.insert(Header: IncludeName.trim(Chars: "\"<>"), IsAngled: IncludeName.starts_with(Prefix: "<"),
4010 Directive: tooling::IncludeDirective::Include);
4011 if (Replace) {
4012 auto Err = Result.add(R: *Replace);
4013 if (Err) {
4014 consumeError(Err: std::move(Err));
4015 unsigned NewOffset =
4016 Result.getShiftedCodePosition(Position: Replace->getOffset());
4017 auto Shifted = tooling::Replacement(FileName, NewOffset, 0,
4018 Replace->getReplacementText());
4019 Result = Result.merge(Replaces: tooling::Replacements(Shifted));
4020 }
4021 }
4022 }
4023 return Result;
4024}
4025
4026} // anonymous namespace
4027
4028Expected<tooling::Replacements>
4029cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
4030 const FormatStyle &Style) {
4031 // We need to use lambda function here since there are two versions of
4032 // `cleanup`.
4033 auto Cleanup = [](const FormatStyle &Style, StringRef Code,
4034 ArrayRef<tooling::Range> Ranges,
4035 StringRef FileName) -> tooling::Replacements {
4036 return cleanup(Style, Code, Ranges, FileName);
4037 };
4038 // Make header insertion replacements insert new headers into correct blocks.
4039 tooling::Replacements NewReplaces =
4040 fixCppIncludeInsertions(Code, Replaces, Style);
4041 return cantFail(ValOrErr: processReplacements(ProcessFunc: Cleanup, Code, Replaces: NewReplaces, Style));
4042}
4043
4044namespace internal {
4045std::pair<tooling::Replacements, unsigned>
4046reformat(const FormatStyle &Style, StringRef Code,
4047 ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,
4048 unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,
4049 FormattingAttemptStatus *Status) {
4050 FormatStyle Expanded = Style;
4051 expandPresetsBraceWrapping(Expanded);
4052 expandPresetsSpaceBeforeParens(Expanded);
4053 expandPresetsSpacesInParens(Expanded);
4054 Expanded.InsertBraces = false;
4055 Expanded.RemoveBracesLLVM = false;
4056 Expanded.RemoveParentheses = FormatStyle::RPS_Leave;
4057 Expanded.RemoveSemicolon = false;
4058 switch (Expanded.RequiresClausePosition) {
4059 case FormatStyle::RCPS_SingleLine:
4060 case FormatStyle::RCPS_WithPreceding:
4061 Expanded.IndentRequiresClause = false;
4062 break;
4063 default:
4064 break;
4065 }
4066
4067 if (Expanded.DisableFormat)
4068 return {tooling::Replacements(), 0};
4069 if (isLikelyXml(Code))
4070 return {tooling::Replacements(), 0};
4071 if (Expanded.isJavaScript() && isMpegTS(Code))
4072 return {tooling::Replacements(), 0};
4073
4074 // JSON only needs the formatting passing.
4075 if (Style.isJson()) {
4076 std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
4077 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
4078 NextStartColumn, LastStartColumn);
4079 if (!Env)
4080 return {};
4081 // Perform the actual formatting pass.
4082 tooling::Replacements Replaces =
4083 Formatter(*Env, Style, Status).process().first;
4084 // add a replacement to remove the "x = " from the result.
4085 if (Code.starts_with(Prefix: "x = ")) {
4086 Replaces = Replaces.merge(
4087 Replaces: tooling::Replacements(tooling::Replacement(FileName, 0, 4, "")));
4088 }
4089 // apply the reformatting changes and the removal of "x = ".
4090 if (applyAllReplacements(Code, Replaces))
4091 return {Replaces, 0};
4092 return {tooling::Replacements(), 0};
4093 }
4094
4095 auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
4096 NextStartColumn, LastStartColumn);
4097 if (!Env)
4098 return {};
4099
4100 typedef std::function<std::pair<tooling::Replacements, unsigned>(
4101 const Environment &)>
4102 AnalyzerPass;
4103
4104 SmallVector<AnalyzerPass, 16> Passes;
4105
4106 Passes.emplace_back(Args: [&](const Environment &Env) {
4107 return IntegerLiteralSeparatorFixer().process(Env, Style: Expanded);
4108 });
4109
4110 Passes.emplace_back(Args: [&](const Environment &Env) {
4111 return NumericLiteralCaseFixer().process(Env, Style: Expanded);
4112 });
4113
4114 if (Style.isCpp()) {
4115 if (Style.QualifierAlignment != FormatStyle::QAS_Leave)
4116 addQualifierAlignmentFixerPasses(Style: Expanded, Passes);
4117
4118 if (Style.RemoveParentheses != FormatStyle::RPS_Leave) {
4119 FormatStyle S = Expanded;
4120 S.RemoveParentheses = Style.RemoveParentheses;
4121 Passes.emplace_back(Args: [&, S = std::move(S)](const Environment &Env) {
4122 return ParensRemover(Env, S).process(/*SkipAnnotation=*/true);
4123 });
4124 }
4125
4126 if (Style.InsertBraces) {
4127 FormatStyle S = Expanded;
4128 S.InsertBraces = true;
4129 Passes.emplace_back(Args: [&, S = std::move(S)](const Environment &Env) {
4130 return BracesInserter(Env, S).process(/*SkipAnnotation=*/true);
4131 });
4132 }
4133
4134 if (Style.RemoveBracesLLVM) {
4135 FormatStyle S = Expanded;
4136 S.RemoveBracesLLVM = true;
4137 Passes.emplace_back(Args: [&, S = std::move(S)](const Environment &Env) {
4138 return BracesRemover(Env, S).process(/*SkipAnnotation=*/true);
4139 });
4140 }
4141
4142 if (Style.RemoveSemicolon) {
4143 FormatStyle S = Expanded;
4144 S.RemoveSemicolon = true;
4145 Passes.emplace_back(Args: [&, S = std::move(S)](const Environment &Env) {
4146 return SemiRemover(Env, S).process();
4147 });
4148 }
4149
4150 if (Style.EnumTrailingComma != FormatStyle::ETC_Leave) {
4151 Passes.emplace_back(Args: [&](const Environment &Env) {
4152 return EnumTrailingCommaEditor(Env, Expanded)
4153 .process(/*SkipAnnotation=*/true);
4154 });
4155 }
4156
4157 if (Style.FixNamespaceComments) {
4158 Passes.emplace_back(Args: [&](const Environment &Env) {
4159 return NamespaceEndCommentsFixer(Env, Expanded).process();
4160 });
4161 }
4162
4163 if (Style.SortUsingDeclarations != FormatStyle::SUD_Never) {
4164 Passes.emplace_back(Args: [&](const Environment &Env) {
4165 return UsingDeclarationsSorter(Env, Expanded).process();
4166 });
4167 }
4168 }
4169
4170 if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) {
4171 Passes.emplace_back(Args: [&](const Environment &Env) {
4172 return DefinitionBlockSeparator(Env, Expanded).process();
4173 });
4174 }
4175
4176 if (Style.Language == FormatStyle::LK_ObjC &&
4177 !Style.ObjCPropertyAttributeOrder.empty()) {
4178 Passes.emplace_back(Args: [&](const Environment &Env) {
4179 return ObjCPropertyAttributeOrderFixer(Env, Expanded).process();
4180 });
4181 }
4182
4183 if (Style.isJavaScript() &&
4184 Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) {
4185 Passes.emplace_back(Args: [&](const Environment &Env) {
4186 return JavaScriptRequoter(Env, Expanded).process(/*SkipAnnotation=*/true);
4187 });
4188 }
4189
4190 Passes.emplace_back(Args: [&](const Environment &Env) {
4191 return Formatter(Env, Expanded, Status).process();
4192 });
4193
4194 if (Style.isJavaScript() &&
4195 Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) {
4196 Passes.emplace_back(Args: [&](const Environment &Env) {
4197 return TrailingCommaInserter(Env, Expanded).process();
4198 });
4199 }
4200
4201 std::optional<std::string> CurrentCode;
4202 tooling::Replacements Fixes;
4203 unsigned Penalty = 0;
4204 for (size_t I = 0, E = Passes.size(); I < E; ++I) {
4205 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
4206 auto NewCode = applyAllReplacements(
4207 Code: CurrentCode ? StringRef(*CurrentCode) : Code, Replaces: PassFixes.first);
4208 if (NewCode) {
4209 Fixes = Fixes.merge(Replaces: PassFixes.first);
4210 Penalty += PassFixes.second;
4211 if (I + 1 < E) {
4212 CurrentCode = std::move(*NewCode);
4213 Env = Environment::make(
4214 Code: *CurrentCode, FileName,
4215 Ranges: tooling::calculateRangesAfterReplacements(Replaces: Fixes, Ranges),
4216 FirstStartColumn, NextStartColumn, LastStartColumn);
4217 if (!Env)
4218 return {};
4219 }
4220 }
4221 }
4222
4223 if (Style.QualifierAlignment != FormatStyle::QAS_Leave) {
4224 // Don't make replacements that replace nothing. QualifierAlignment can
4225 // produce them if one of its early passes changes e.g. `const volatile` to
4226 // `volatile const` and then a later pass changes it back again.
4227 tooling::Replacements NonNoOpFixes;
4228 for (const tooling::Replacement &Fix : Fixes) {
4229 StringRef OriginalCode = Code.substr(Start: Fix.getOffset(), N: Fix.getLength());
4230 if (OriginalCode != Fix.getReplacementText()) {
4231 auto Err = NonNoOpFixes.add(R: Fix);
4232 if (Err) {
4233 llvm::errs() << "Error adding replacements : "
4234 << toString(E: std::move(Err)) << "\n";
4235 }
4236 }
4237 }
4238 Fixes = std::move(NonNoOpFixes);
4239 }
4240
4241 return {Fixes, Penalty};
4242}
4243} // namespace internal
4244
4245tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
4246 ArrayRef<tooling::Range> Ranges,
4247 StringRef FileName,
4248 FormattingAttemptStatus *Status) {
4249 return internal::reformat(Style, Code, Ranges,
4250 /*FirstStartColumn=*/0,
4251 /*NextStartColumn=*/0,
4252 /*LastStartColumn=*/0, FileName, Status)
4253 .first;
4254}
4255
4256tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
4257 ArrayRef<tooling::Range> Ranges,
4258 StringRef FileName) {
4259 // cleanups only apply to C++ (they mostly concern ctor commas etc.)
4260 if (Style.Language != FormatStyle::LK_Cpp)
4261 return tooling::Replacements();
4262 auto Env = Environment::make(Code, FileName, Ranges);
4263 if (!Env)
4264 return {};
4265 return Cleaner(*Env, Style).process().first;
4266}
4267
4268tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
4269 ArrayRef<tooling::Range> Ranges,
4270 StringRef FileName, bool *IncompleteFormat) {
4271 FormattingAttemptStatus Status;
4272 auto Result = reformat(Style, Code, Ranges, FileName, Status: &Status);
4273 if (!Status.FormatComplete)
4274 *IncompleteFormat = true;
4275 return Result;
4276}
4277
4278tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,
4279 StringRef Code,
4280 ArrayRef<tooling::Range> Ranges,
4281 StringRef FileName) {
4282 auto Env = Environment::make(Code, FileName, Ranges);
4283 if (!Env)
4284 return {};
4285 return NamespaceEndCommentsFixer(*Env, Style).process().first;
4286}
4287
4288tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
4289 StringRef Code,
4290 ArrayRef<tooling::Range> Ranges,
4291 StringRef FileName) {
4292 auto Env = Environment::make(Code, FileName, Ranges);
4293 if (!Env)
4294 return {};
4295 return UsingDeclarationsSorter(*Env, Style).process().first;
4296}
4297
4298LangOptions getFormattingLangOpts(const FormatStyle &Style) {
4299 LangOptions LangOpts;
4300
4301 auto LexingStd = Style.Standard;
4302 if (LexingStd == FormatStyle::LS_Auto || LexingStd == FormatStyle::LS_Latest)
4303 LexingStd = FormatStyle::LS_Cpp20;
4304
4305 const bool SinceCpp11 = LexingStd >= FormatStyle::LS_Cpp11;
4306 const bool SinceCpp20 = LexingStd >= FormatStyle::LS_Cpp20;
4307
4308 switch (Style.Language) {
4309 case FormatStyle::LK_C:
4310 LangOpts.C11 = 1;
4311 LangOpts.C23 = 1;
4312 break;
4313 case FormatStyle::LK_Cpp:
4314 case FormatStyle::LK_ObjC:
4315 LangOpts.CXXOperatorNames = 1;
4316 LangOpts.CPlusPlus11 = SinceCpp11;
4317 LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14;
4318 LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17;
4319 LangOpts.CPlusPlus20 = SinceCpp20;
4320 [[fallthrough]];
4321 default:
4322 LangOpts.CPlusPlus = 1;
4323 }
4324
4325 LangOpts.Char8 = SinceCpp20;
4326 // Turning on digraphs in standards before C++0x is error-prone, because e.g.
4327 // the sequence "<::" will be unconditionally treated as "[:".
4328 // Cf. Lexer::LexTokenInternal.
4329 LangOpts.Digraphs = SinceCpp11;
4330
4331 LangOpts.LineComment = 1;
4332 LangOpts.Bool = 1;
4333 LangOpts.ObjC = 1;
4334 LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally.
4335 LangOpts.DeclSpecKeyword = 1; // To get __declspec.
4336 LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict.
4337
4338 return LangOpts;
4339}
4340
4341const char *StyleOptionHelpDescription =
4342 "Set coding style. <string> can be:\n"
4343 "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"
4344 " Mozilla, WebKit.\n"
4345 "2. 'file' to load style configuration from a\n"
4346 " .clang-format file in one of the parent directories\n"
4347 " of the source file (for stdin, see --assume-filename).\n"
4348 " If no .clang-format file is found, falls back to\n"
4349 " --fallback-style.\n"
4350 " --style=file is the default.\n"
4351 "3. 'file:<format_file_path>' to explicitly specify\n"
4352 " the configuration file.\n"
4353 "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n"
4354 " --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
4355
4356static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
4357 if (FileName.ends_with(Suffix: ".c"))
4358 return FormatStyle::LK_C;
4359 if (FileName.ends_with(Suffix: ".java"))
4360 return FormatStyle::LK_Java;
4361 if (FileName.ends_with_insensitive(Suffix: ".js") ||
4362 FileName.ends_with_insensitive(Suffix: ".mjs") ||
4363 FileName.ends_with_insensitive(Suffix: ".cjs") ||
4364 FileName.ends_with_insensitive(Suffix: ".ts")) {
4365 return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript.
4366 }
4367 if (FileName.ends_with(Suffix: ".m") || FileName.ends_with(Suffix: ".mm"))
4368 return FormatStyle::LK_ObjC;
4369 if (FileName.ends_with_insensitive(Suffix: ".proto") ||
4370 FileName.ends_with_insensitive(Suffix: ".protodevel")) {
4371 return FormatStyle::LK_Proto;
4372 }
4373 // txtpb is the canonical extension, and textproto is the legacy canonical
4374 // extension
4375 // https://protobuf.dev/reference/protobuf/textformat-spec/#text-format-files
4376 if (FileName.ends_with_insensitive(Suffix: ".txtpb") ||
4377 FileName.ends_with_insensitive(Suffix: ".textpb") ||
4378 FileName.ends_with_insensitive(Suffix: ".pb.txt") ||
4379 FileName.ends_with_insensitive(Suffix: ".textproto") ||
4380 FileName.ends_with_insensitive(Suffix: ".asciipb")) {
4381 return FormatStyle::LK_TextProto;
4382 }
4383 if (FileName.ends_with_insensitive(Suffix: ".td"))
4384 return FormatStyle::LK_TableGen;
4385 if (FileName.ends_with_insensitive(Suffix: ".cs"))
4386 return FormatStyle::LK_CSharp;
4387 if (FileName.ends_with_insensitive(Suffix: ".json") ||
4388 FileName.ends_with_insensitive(Suffix: ".ipynb")) {
4389 return FormatStyle::LK_Json;
4390 }
4391 if (FileName.ends_with_insensitive(Suffix: ".sv") ||
4392 FileName.ends_with_insensitive(Suffix: ".svh") ||
4393 FileName.ends_with_insensitive(Suffix: ".v") ||
4394 FileName.ends_with_insensitive(Suffix: ".vh")) {
4395 return FormatStyle::LK_Verilog;
4396 }
4397 return FormatStyle::LK_Cpp;
4398}
4399
4400static FormatStyle::LanguageKind getLanguageByComment(const Environment &Env) {
4401 const auto ID = Env.getFileID();
4402 const auto &SourceMgr = Env.getSourceManager();
4403
4404 LangOptions LangOpts;
4405 LangOpts.CPlusPlus = 1;
4406 LangOpts.LineComment = 1;
4407
4408 Lexer Lex(ID, SourceMgr.getBufferOrFake(FID: ID), SourceMgr, LangOpts);
4409 Lex.SetCommentRetentionState(true);
4410
4411 for (Token Tok; !Lex.LexFromRawLexer(Result&: Tok) && Tok.is(K: tok::comment);) {
4412 auto Text = StringRef(SourceMgr.getCharacterData(SL: Tok.getLocation()),
4413 Tok.getLength());
4414 if (!Text.consume_front(Prefix: "// clang-format Language:"))
4415 continue;
4416
4417 Text = Text.trim();
4418 if (Text == "C")
4419 return FormatStyle::LK_C;
4420 if (Text == "Cpp")
4421 return FormatStyle::LK_Cpp;
4422 if (Text == "ObjC")
4423 return FormatStyle::LK_ObjC;
4424 }
4425
4426 return FormatStyle::LK_None;
4427}
4428
4429FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {
4430 const auto GuessedLanguage = getLanguageByFileName(FileName);
4431 if (GuessedLanguage == FormatStyle::LK_Cpp) {
4432 auto Extension = llvm::sys::path::extension(path: FileName);
4433 // If there's no file extension (or it's .h), we need to check the contents
4434 // of the code to see if it contains Objective-C.
4435 if (!Code.empty() && (Extension.empty() || Extension == ".h")) {
4436 auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName;
4437 Environment Env(Code, NonEmptyFileName, /*Ranges=*/{});
4438 if (const auto Language = getLanguageByComment(Env);
4439 Language != FormatStyle::LK_None) {
4440 return Language;
4441 }
4442 ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle());
4443 Guesser.process();
4444 if (Guesser.isObjC())
4445 return FormatStyle::LK_ObjC;
4446 }
4447 }
4448 return GuessedLanguage;
4449}
4450
4451// Update StyleOptionHelpDescription above when changing this.
4452const char *DefaultFormatStyle = "file";
4453
4454const char *DefaultFallbackStyle = "LLVM";
4455
4456llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
4457loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS,
4458 FormatStyle *Style, bool AllowUnknownOptions,
4459 llvm::SourceMgr::DiagHandlerTy DiagHandler,
4460 bool IsDotHFile) {
4461 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
4462 FS->getBufferForFile(Name: ConfigFile.str());
4463 if (auto EC = Text.getError())
4464 return EC;
4465 if (auto EC = parseConfiguration(Config: *Text.get(), Style, AllowUnknownOptions,
4466 DiagHandler, /*DiagHandlerCtx=*/DiagHandlerCtxt: nullptr,
4467 IsDotHFile)) {
4468 return EC;
4469 }
4470 return Text;
4471}
4472
4473Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
4474 StringRef FallbackStyleName, StringRef Code,
4475 llvm::vfs::FileSystem *FS,
4476 bool AllowUnknownOptions,
4477 llvm::SourceMgr::DiagHandlerTy DiagHandler) {
4478 FormatStyle Style = getLLVMStyle(Language: guessLanguage(FileName, Code));
4479 FormatStyle FallbackStyle = getNoStyle();
4480 if (!getPredefinedStyle(Name: FallbackStyleName, Language: Style.Language, Style: &FallbackStyle))
4481 return make_string_error(Message: "Invalid fallback style: " + FallbackStyleName);
4482
4483 SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1> ChildFormatTextToApply;
4484
4485 if (StyleName.starts_with(Prefix: "{")) {
4486 // Parse YAML/JSON style from the command line.
4487 StringRef Source = "<command-line>";
4488 if (std::error_code ec =
4489 parseConfiguration(Config: llvm::MemoryBufferRef(StyleName, Source), Style: &Style,
4490 AllowUnknownOptions, DiagHandler)) {
4491 return make_string_error(Message: "Error parsing -style: " + ec.message());
4492 }
4493
4494 if (!Style.InheritsParentConfig)
4495 return Style;
4496
4497 ChildFormatTextToApply.emplace_back(
4498 Args: llvm::MemoryBuffer::getMemBuffer(InputData: StyleName, BufferName: Source, RequiresNullTerminator: false));
4499 }
4500
4501 if (!FS)
4502 FS = llvm::vfs::getRealFileSystem().get();
4503 assert(FS);
4504
4505 const bool IsDotHFile = FileName.ends_with(Suffix: ".h");
4506
4507 // User provided clang-format file using -style=file:path/to/format/file.
4508 if (!Style.InheritsParentConfig &&
4509 StyleName.starts_with_insensitive(Prefix: "file:")) {
4510 auto ConfigFile = StyleName.substr(Start: 5);
4511 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
4512 loadAndParseConfigFile(ConfigFile, FS, Style: &Style, AllowUnknownOptions,
4513 DiagHandler, IsDotHFile);
4514 if (auto EC = Text.getError()) {
4515 return make_string_error(Message: "Error reading " + ConfigFile + ": " +
4516 EC.message());
4517 }
4518
4519 LLVM_DEBUG(llvm::dbgs()
4520 << "Using configuration file " << ConfigFile << "\n");
4521
4522 if (!Style.InheritsParentConfig)
4523 return Style;
4524
4525 // Search for parent configs starting from the parent directory of
4526 // ConfigFile.
4527 FileName = ConfigFile;
4528 ChildFormatTextToApply.emplace_back(Args: std::move(*Text));
4529 }
4530
4531 // If the style inherits the parent configuration it is a command line
4532 // configuration, which wants to inherit, so we have to skip the check of the
4533 // StyleName.
4534 if (!Style.InheritsParentConfig && !StyleName.equals_insensitive(RHS: "file")) {
4535 if (!getPredefinedStyle(Name: StyleName, Language: Style.Language, Style: &Style))
4536 return make_string_error(Message: "Invalid value for -style");
4537 if (!Style.InheritsParentConfig)
4538 return Style;
4539 }
4540
4541 SmallString<128> Path(FileName);
4542 if (std::error_code EC = FS->makeAbsolute(Path))
4543 return make_string_error(Message: EC.message());
4544
4545 // Reset possible inheritance
4546 Style.InheritsParentConfig = false;
4547
4548 auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {};
4549
4550 auto applyChildFormatTexts = [&](FormatStyle *Style) {
4551 for (const auto &MemBuf : llvm::reverse(C&: ChildFormatTextToApply)) {
4552 auto EC =
4553 parseConfiguration(Config: *MemBuf, Style, AllowUnknownOptions,
4554 DiagHandler: DiagHandler ? DiagHandler : dropDiagnosticHandler);
4555 // It was already correctly parsed.
4556 assert(!EC);
4557 static_cast<void>(EC);
4558 }
4559 };
4560
4561 // Look for .clang-format/_clang-format file in the file's parent directories.
4562 SmallVector<std::string, 2> FilesToLookFor;
4563 FilesToLookFor.push_back(Elt: ".clang-format");
4564 FilesToLookFor.push_back(Elt: "_clang-format");
4565
4566 SmallString<128> UnsuitableConfigFiles;
4567 for (StringRef Directory = Path; !Directory.empty();
4568 Directory = llvm::sys::path::parent_path(path: Directory)) {
4569 auto Status = FS->status(Path: Directory);
4570 if (!Status ||
4571 Status->getType() != llvm::sys::fs::file_type::directory_file) {
4572 continue;
4573 }
4574
4575 for (const auto &F : FilesToLookFor) {
4576 SmallString<128> ConfigFile(Directory);
4577
4578 llvm::sys::path::append(path&: ConfigFile, a: F);
4579 LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
4580
4581 Status = FS->status(Path: ConfigFile);
4582 if (!Status ||
4583 Status->getType() != llvm::sys::fs::file_type::regular_file) {
4584 continue;
4585 }
4586
4587 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
4588 loadAndParseConfigFile(ConfigFile, FS, Style: &Style, AllowUnknownOptions,
4589 DiagHandler, IsDotHFile);
4590 if (auto EC = Text.getError()) {
4591 if (EC != ParseError::Unsuitable) {
4592 return make_string_error(Message: "Error reading " + ConfigFile + ": " +
4593 EC.message());
4594 }
4595 if (!UnsuitableConfigFiles.empty())
4596 UnsuitableConfigFiles.append(RHS: ", ");
4597 UnsuitableConfigFiles.append(RHS: ConfigFile);
4598 continue;
4599 }
4600
4601 LLVM_DEBUG(llvm::dbgs()
4602 << "Using configuration file " << ConfigFile << "\n");
4603
4604 if (!Style.InheritsParentConfig) {
4605 if (!ChildFormatTextToApply.empty()) {
4606 LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n");
4607 applyChildFormatTexts(&Style);
4608 }
4609 return Style;
4610 }
4611
4612 LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n");
4613
4614 // Reset inheritance of style
4615 Style.InheritsParentConfig = false;
4616
4617 ChildFormatTextToApply.emplace_back(Args: std::move(*Text));
4618
4619 // Breaking out of the inner loop, since we don't want to parse
4620 // .clang-format AND _clang-format, if both exist. Then we continue the
4621 // outer loop (parent directories) in search for the parent
4622 // configuration.
4623 break;
4624 }
4625 }
4626
4627 if (!UnsuitableConfigFiles.empty()) {
4628 return make_string_error(Message: "Configuration file(s) do(es) not support " +
4629 getLanguageName(Language: Style.Language) + ": " +
4630 UnsuitableConfigFiles);
4631 }
4632
4633 if (!ChildFormatTextToApply.empty()) {
4634 LLVM_DEBUG(llvm::dbgs()
4635 << "Applying child configurations on fallback style\n");
4636 applyChildFormatTexts(&FallbackStyle);
4637 }
4638
4639 return FallbackStyle;
4640}
4641
4642static bool isClangFormatOnOff(StringRef Comment, bool On) {
4643 if (Comment == (On ? "/* clang-format on */" : "/* clang-format off */"))
4644 return true;
4645
4646 static const char ClangFormatOn[] = "// clang-format on";
4647 static const char ClangFormatOff[] = "// clang-format off";
4648 const unsigned Size = (On ? sizeof ClangFormatOn : sizeof ClangFormatOff) - 1;
4649
4650 return Comment.starts_with(Prefix: On ? ClangFormatOn : ClangFormatOff) &&
4651 (Comment.size() == Size || Comment[Size] == ':');
4652}
4653
4654bool isClangFormatOn(StringRef Comment) {
4655 return isClangFormatOnOff(Comment, /*On=*/true);
4656}
4657
4658bool isClangFormatOff(StringRef Comment) {
4659 return isClangFormatOnOff(Comment, /*On=*/false);
4660}
4661
4662} // namespace format
4663} // namespace clang
4664