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