Coverage Report

Created: 2022-07-16 07:03

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