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