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

source code of clang/lib/Format/Format.cpp