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