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