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