Coverage Report

Created: 2024-01-17 10:31

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