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