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