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