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