Coverage Report

Created: 2021-01-26 06:56

/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 "FormatInternal.h"
20
#include "FormatTokenLexer.h"
21
#include "NamespaceEndCommentsFixer.h"
22
#include "SortJavaScriptImports.h"
23
#include "TokenAnalyzer.h"
24
#include "TokenAnnotator.h"
25
#include "UnwrappedLineFormatter.h"
26
#include "UnwrappedLineParser.h"
27
#include "UsingDeclarationsSorter.h"
28
#include "WhitespaceManager.h"
29
#include "clang/Basic/Diagnostic.h"
30
#include "clang/Basic/DiagnosticOptions.h"
31
#include "clang/Basic/SourceManager.h"
32
#include "clang/Lex/Lexer.h"
33
#include "clang/Tooling/Inclusions/HeaderIncludes.h"
34
#include "llvm/ADT/STLExtras.h"
35
#include "llvm/ADT/StringRef.h"
36
#include "llvm/Support/Allocator.h"
37
#include "llvm/Support/Debug.h"
38
#include "llvm/Support/Path.h"
39
#include "llvm/Support/Regex.h"
40
#include "llvm/Support/VirtualFileSystem.h"
41
#include "llvm/Support/YAMLTraits.h"
42
#include <algorithm>
43
#include <memory>
44
#include <mutex>
45
#include <string>
46
#include <unordered_map>
47
48
#define DEBUG_TYPE "format-formatter"
49
50
using clang::format::FormatStyle;
51
52
LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat)
53
54
namespace llvm {
55
namespace yaml {
56
template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
57
28
  static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
58
28
    IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
59
28
    IO.enumCase(Value, "Java", FormatStyle::LK_Java);
60
28
    IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
61
28
    IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);
62
28
    IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
63
28
    IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);
64
28
    IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto);
65
28
    IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp);
66
28
  }
67
};
68
69
template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
70
18
  static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
71
18
    IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03);
72
18
    IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias
73
18
    IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias
74
75
18
    IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11);
76
18
    IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias
77
78
18
    IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14);
79
18
    IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17);
80
18
    IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20);
81
82
18
    IO.enumCase(Value, "Latest", FormatStyle::LS_Latest);
83
18
    IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias
84
18
    IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);
85
18
  }
86
};
87
88
template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
89
14
  static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {
90
14
    IO.enumCase(Value, "Never", FormatStyle::UT_Never);
91
14
    IO.enumCase(Value, "false", FormatStyle::UT_Never);
92
14
    IO.enumCase(Value, "Always", FormatStyle::UT_Always);
93
14
    IO.enumCase(Value, "true", FormatStyle::UT_Always);
94
14
    IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation);
95
14
    IO.enumCase(Value, "ForContinuationAndIndentation",
96
14
                FormatStyle::UT_ForContinuationAndIndentation);
97
14
    IO.enumCase(Value, "AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);
98
14
  }
99
};
100
101
template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {
102
7
  static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) {
103
7
    IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave);
104
7
    IO.enumCase(Value, "Single", FormatStyle::JSQS_Single);
105
7
    IO.enumCase(Value, "Double", FormatStyle::JSQS_Double);
106
7
  }
107
};
108
109
template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> {
110
12
  static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) {
111
12
    IO.enumCase(Value, "Never", FormatStyle::SBS_Never);
112
12
    IO.enumCase(Value, "false", FormatStyle::SBS_Never);
113
12
    IO.enumCase(Value, "Always", FormatStyle::SBS_Always);
114
12
    IO.enumCase(Value, "true", FormatStyle::SBS_Always);
115
12
    IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty);
116
12
  }
117
};
118
119
template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
120
13
  static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
121
13
    IO.enumCase(Value, "None", FormatStyle::SFS_None);
122
13
    IO.enumCase(Value, "false", FormatStyle::SFS_None);
123
13
    IO.enumCase(Value, "All", FormatStyle::SFS_All);
124
13
    IO.enumCase(Value, "true", FormatStyle::SFS_All);
125
13
    IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
126
13
    IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly);
127
13
    IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);
128
13
  }
129
};
130
131
template <> struct ScalarEnumerationTraits<FormatStyle::AlignConsecutiveStyle> {
132
52
  static void enumeration(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
133
52
    IO.enumCase(Value, "None", FormatStyle::ACS_None);
134
52
    IO.enumCase(Value, "Consecutive", FormatStyle::ACS_Consecutive);
135
52
    IO.enumCase(Value, "AcrossEmptyLines", FormatStyle::ACS_AcrossEmptyLines);
136
52
    IO.enumCase(Value, "AcrossComments", FormatStyle::ACS_AcrossComments);
137
52
    IO.enumCase(Value, "AcrossEmptyLinesAndComments",
138
52
                FormatStyle::ACS_AcrossEmptyLinesAndComments);
139
140
    // For backward compability.
141
52
    IO.enumCase(Value, "true", FormatStyle::ACS_Consecutive);
142
52
    IO.enumCase(Value, "false", FormatStyle::ACS_None);
143
52
  }
144
};
145
146
template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> {
147
12
  static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) {
148
12
    IO.enumCase(Value, "Never", FormatStyle::SIS_Never);
149
12
    IO.enumCase(Value, "Always", FormatStyle::SIS_Always);
150
12
    IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse);
151
152
    // For backward compatibility.
153
12
    IO.enumCase(Value, "false", FormatStyle::SIS_Never);
154
12
    IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse);
155
12
  }
156
};
157
158
template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> {
159
7
  static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) {
160
7
    IO.enumCase(Value, "None", FormatStyle::SLS_None);
161
7
    IO.enumCase(Value, "false", FormatStyle::SLS_None);
162
7
    IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty);
163
7
    IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline);
164
7
    IO.enumCase(Value, "All", FormatStyle::SLS_All);
165
7
    IO.enumCase(Value, "true", FormatStyle::SLS_All);
166
7
  }
167
};
168
169
template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {
170
7
  static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) {
171
7
    IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto);
172
7
    IO.enumCase(Value, "Always", FormatStyle::BPS_Always);
173
7
    IO.enumCase(Value, "Never", FormatStyle::BPS_Never);
174
7
  }
175
};
176
177
template <> struct ScalarEnumerationTraits<FormatStyle::TrailingCommaStyle> {
178
8
  static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) {
179
8
    IO.enumCase(Value, "None", FormatStyle::TCS_None);
180
8
    IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped);
181
8
  }
182
};
183
184
template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> {
185
12
  static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {
186
12
    IO.enumCase(Value, "All", FormatStyle::BOS_All);
187
12
    IO.enumCase(Value, "true", FormatStyle::BOS_All);
188
12
    IO.enumCase(Value, "None", FormatStyle::BOS_None);
189
12
    IO.enumCase(Value, "false", FormatStyle::BOS_None);
190
12
    IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment);
191
12
  }
192
};
193
194
template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
195
18
  static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {
196
18
    IO.enumCase(Value, "Attach", FormatStyle::BS_Attach);
197
18
    IO.enumCase(Value, "Linux", FormatStyle::BS_Linux);
198
18
    IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla);
199
18
    IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);
200
18
    IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
201
18
    IO.enumCase(Value, "Whitesmiths", FormatStyle::BS_Whitesmiths);
202
18
    IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
203
18
    IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit);
204
18
    IO.enumCase(Value, "Custom", FormatStyle::BS_Custom);
205
18
  }
206
};
207
208
template <>
209
struct ScalarEnumerationTraits<
210
    FormatStyle::BraceWrappingAfterControlStatementStyle> {
211
  static void
212
  enumeration(IO &IO,
213
12
              FormatStyle::BraceWrappingAfterControlStatementStyle &Value) {
214
12
    IO.enumCase(Value, "Never", FormatStyle::BWACS_Never);
215
12
    IO.enumCase(Value, "MultiLine", FormatStyle::BWACS_MultiLine);
216
12
    IO.enumCase(Value, "Always", FormatStyle::BWACS_Always);
217
218
    // For backward compatibility.
219
12
    IO.enumCase(Value, "false", FormatStyle::BWACS_Never);
220
12
    IO.enumCase(Value, "true", FormatStyle::BWACS_Always);
221
12
  }
222
};
223
224
template <>
225
struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
226
  static void
227
10
  enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
228
10
    IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon);
229
10
    IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma);
230
10
    IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon);
231
10
  }
232
};
233
234
template <>
235
struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {
236
  static void enumeration(IO &IO,
237
10
                          FormatStyle::BreakInheritanceListStyle &Value) {
238
10
    IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon);
239
10
    IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma);
240
10
    IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon);
241
10
  }
242
};
243
244
template <>
245
struct ScalarEnumerationTraits<
246
    FormatStyle::EmptyLineBeforeAccessModifierStyle> {
247
  static void
248
13
  enumeration(IO &IO, FormatStyle::EmptyLineBeforeAccessModifierStyle &Value) {
249
13
    IO.enumCase(Value, "Never", FormatStyle::ELBAMS_Never);
250
13
    IO.enumCase(Value, "Leave", FormatStyle::ELBAMS_Leave);
251
13
    IO.enumCase(Value, "LogicalBlock", FormatStyle::ELBAMS_LogicalBlock);
252
13
    IO.enumCase(Value, "Always", FormatStyle::ELBAMS_Always);
253
13
  }
254
};
255
256
template <>
257
struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
258
7
  static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
259
7
    IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
260
7
    IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);
261
7
    IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash);
262
7
  }
263
};
264
265
template <>
266
struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> {
267
12
  static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value) {
268
12
    IO.enumCase(Value, "AfterExternBlock", FormatStyle::IEBS_AfterExternBlock);
269
12
    IO.enumCase(Value, "Indent", FormatStyle::IEBS_Indent);
270
12
    IO.enumCase(Value, "NoIndent", FormatStyle::IEBS_NoIndent);
271
12
    IO.enumCase(Value, "true", FormatStyle::IEBS_Indent);
272
12
    IO.enumCase(Value, "false", FormatStyle::IEBS_NoIndent);
273
12
  }
274
};
275
276
template <>
277
struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
278
12
  static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
279
12
    IO.enumCase(Value, "None", FormatStyle::RTBS_None);
280
12
    IO.enumCase(Value, "All", FormatStyle::RTBS_All);
281
12
    IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel);
282
12
    IO.enumCase(Value, "TopLevelDefinitions",
283
12
                FormatStyle::RTBS_TopLevelDefinitions);
284
12
    IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions);
285
12
  }
286
};
287
288
template <>
289
struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
290
  static void enumeration(IO &IO,
291
21
                          FormatStyle::BreakTemplateDeclarationsStyle &Value) {
292
21
    IO.enumCase(Value, "No", FormatStyle::BTDS_No);
293
21
    IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);
294
21
    IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);
295
296
    // For backward compatibility.
297
21
    IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine);
298
21
    IO.enumCase(Value, "true", FormatStyle::BTDS_Yes);
299
21
  }
300
};
301
302
template <>
303
struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
304
  static void
305
10
  enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
306
10
    IO.enumCase(Value, "None", FormatStyle::DRTBS_None);
307
10
    IO.enumCase(Value, "All", FormatStyle::DRTBS_All);
308
10
    IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel);
309
310
    // For backward compatibility.
311
10
    IO.enumCase(Value, "false", FormatStyle::DRTBS_None);
312
10
    IO.enumCase(Value, "true", FormatStyle::DRTBS_All);
313
10
  }
314
};
315
316
template <>
317
struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
318
  static void enumeration(IO &IO,
319
10
                          FormatStyle::NamespaceIndentationKind &Value) {
320
10
    IO.enumCase(Value, "None", FormatStyle::NI_None);
321
10
    IO.enumCase(Value, "Inner", FormatStyle::NI_Inner);
322
10
    IO.enumCase(Value, "All", FormatStyle::NI_All);
323
10
  }
324
};
325
326
template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> {
327
12
  static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) {
328
12
    IO.enumCase(Value, "Align", FormatStyle::BAS_Align);
329
12
    IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign);
330
12
    IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak);
331
332
    // For backward compatibility.
333
12
    IO.enumCase(Value, "true", FormatStyle::BAS_Align);
334
12
    IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign);
335
12
  }
336
};
337
338
template <>
339
struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
340
  static void enumeration(IO &IO,
341
12
                          FormatStyle::EscapedNewlineAlignmentStyle &Value) {
342
12
    IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign);
343
12
    IO.enumCase(Value, "Left", FormatStyle::ENAS_Left);
344
12
    IO.enumCase(Value, "Right", FormatStyle::ENAS_Right);
345
346
    // For backward compatibility.
347
12
    IO.enumCase(Value, "true", FormatStyle::ENAS_Left);
348
12
    IO.enumCase(Value, "false", FormatStyle::ENAS_Right);
349
12
  }
350
};
351
352
template <> struct ScalarEnumerationTraits<FormatStyle::OperandAlignmentStyle> {
353
12
  static void enumeration(IO &IO, FormatStyle::OperandAlignmentStyle &Value) {
354
12
    IO.enumCase(Value, "DontAlign", FormatStyle::OAS_DontAlign);
355
12
    IO.enumCase(Value, "Align", FormatStyle::OAS_Align);
356
12
    IO.enumCase(Value, "AlignAfterOperator",
357
12
                FormatStyle::OAS_AlignAfterOperator);
358
359
    // For backward compatibility.
360
12
    IO.enumCase(Value, "true", FormatStyle::OAS_Align);
361
12
    IO.enumCase(Value, "false", FormatStyle::OAS_DontAlign);
362
12
  }
363
};
364
365
template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
366
15
  static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {
367
15
    IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
368
15
    IO.enumCase(Value, "Left", FormatStyle::PAS_Left);
369
15
    IO.enumCase(Value, "Right", FormatStyle::PAS_Right);
370
371
    // For backward compatibility.
372
15
    IO.enumCase(Value, "true", FormatStyle::PAS_Left);
373
15
    IO.enumCase(Value, "false", FormatStyle::PAS_Right);
374
15
  }
375
};
376
377
template <>
378
struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> {
379
  static void
380
11
  enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value) {
381
11
    IO.enumCase(Value, "Default", FormatStyle::SAPQ_Default);
382
11
    IO.enumCase(Value, "Before", FormatStyle::SAPQ_Before);
383
11
    IO.enumCase(Value, "After", FormatStyle::SAPQ_After);
384
11
    IO.enumCase(Value, "Both", FormatStyle::SAPQ_Both);
385
11
  }
386
};
387
388
template <>
389
struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
390
  static void enumeration(IO &IO,
391
13
                          FormatStyle::SpaceBeforeParensOptions &Value) {
392
13
    IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
393
13
    IO.enumCase(Value, "ControlStatements",
394
13
                FormatStyle::SBPO_ControlStatements);
395
13
    IO.enumCase(Value, "ControlStatementsExceptForEachMacros",
396
13
                FormatStyle::SBPO_ControlStatementsExceptForEachMacros);
397
13
    IO.enumCase(Value, "NonEmptyParentheses",
398
13
                FormatStyle::SBPO_NonEmptyParentheses);
399
13
    IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
400
401
    // For backward compatibility.
402
13
    IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
403
13
    IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);
404
13
  }
405
};
406
407
template <>
408
struct ScalarEnumerationTraits<FormatStyle::BitFieldColonSpacingStyle> {
409
  static void enumeration(IO &IO,
410
11
                          FormatStyle::BitFieldColonSpacingStyle &Value) {
411
11
    IO.enumCase(Value, "Both", FormatStyle::BFCS_Both);
412
11
    IO.enumCase(Value, "None", FormatStyle::BFCS_None);
413
11
    IO.enumCase(Value, "Before", FormatStyle::BFCS_Before);
414
11
    IO.enumCase(Value, "After", FormatStyle::BFCS_After);
415
11
  }
416
};
417
418
template <>
419
struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> {
420
  static void enumeration(IO &IO,
421
9
                          FormatStyle::SortJavaStaticImportOptions &Value) {
422
9
    IO.enumCase(Value, "Before", FormatStyle::SJSIO_Before);
423
9
    IO.enumCase(Value, "After", FormatStyle::SJSIO_After);
424
9
  }
425
};
426
427
template <> struct MappingTraits<FormatStyle> {
428
408
  static void mapping(IO &IO, FormatStyle &Style) {
429
    // When reading, read the language first, we need it for getPredefinedStyle.
430
408
    IO.mapOptional("Language", Style.Language);
431
432
408
    if (IO.outputting()) {
433
6
      StringRef StylesArray[] = {"LLVM",   "Google", "Chromium", "Mozilla",
434
6
                                 "WebKit", "GNU",    "Microsoft"};
435
6
      ArrayRef<StringRef> Styles(StylesArray);
436
34
      for (size_t i = 0, e = Styles.size(); i < e; 
++i28
) {
437
30
        StringRef StyleName(Styles[i]);
438
30
        FormatStyle PredefinedStyle;
439
30
        if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) &&
440
30
            Style == PredefinedStyle) {
441
2
          IO.mapOptional("# BasedOnStyle", StyleName);
442
2
          break;
443
2
        }
444
30
      }
445
402
    } else {
446
402
      StringRef BasedOnStyle;
447
402
      IO.mapOptional("BasedOnStyle", BasedOnStyle);
448
402
      if (!BasedOnStyle.empty()) {
449
41
        FormatStyle::LanguageKind OldLanguage = Style.Language;
450
41
        FormatStyle::LanguageKind Language =
451
41
            ((FormatStyle *)IO.getContext())->Language;
452
41
        if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
453
1
          IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle));
454
1
          return;
455
1
        }
456
40
        Style.Language = OldLanguage;
457
40
      }
458
402
    }
459
460
    // For backward compatibility.
461
407
    if (!IO.outputting()) {
462
401
      IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines);
463
401
      IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
464
401
      IO.mapOptional("IndentFunctionDeclarationAfterType",
465
401
                     Style.IndentWrappedFunctionNames);
466
401
      IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
467
401
      IO.mapOptional("SpaceAfterControlStatementKeyword",
468
401
                     Style.SpaceBeforeParens);
469
401
    }
470
471
407
    IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
472
407
    IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
473
407
    IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);
474
407
    IO.mapOptional("AlignConsecutiveAssignments",
475
407
                   Style.AlignConsecutiveAssignments);
476
407
    IO.mapOptional("AlignConsecutiveBitFields",
477
407
                   Style.AlignConsecutiveBitFields);
478
407
    IO.mapOptional("AlignConsecutiveDeclarations",
479
407
                   Style.AlignConsecutiveDeclarations);
480
407
    IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines);
481
407
    IO.mapOptional("AlignOperands", Style.AlignOperands);
482
407
    IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
483
407
    IO.mapOptional("AllowAllArgumentsOnNextLine",
484
407
                   Style.AllowAllArgumentsOnNextLine);
485
407
    IO.mapOptional("AllowAllConstructorInitializersOnNextLine",
486
407
                   Style.AllowAllConstructorInitializersOnNextLine);
487
407
    IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
488
407
                   Style.AllowAllParametersOfDeclarationOnNextLine);
489
407
    IO.mapOptional("AllowShortEnumsOnASingleLine",
490
407
                   Style.AllowShortEnumsOnASingleLine);
491
407
    IO.mapOptional("AllowShortBlocksOnASingleLine",
492
407
                   Style.AllowShortBlocksOnASingleLine);
493
407
    IO.mapOptional("AllowShortCaseLabelsOnASingleLine",
494
407
                   Style.AllowShortCaseLabelsOnASingleLine);
495
407
    IO.mapOptional("AllowShortFunctionsOnASingleLine",
496
407
                   Style.AllowShortFunctionsOnASingleLine);
497
407
    IO.mapOptional("AllowShortLambdasOnASingleLine",
498
407
                   Style.AllowShortLambdasOnASingleLine);
499
407
    IO.mapOptional("AllowShortIfStatementsOnASingleLine",
500
407
                   Style.AllowShortIfStatementsOnASingleLine);
501
407
    IO.mapOptional("AllowShortLoopsOnASingleLine",
502
407
                   Style.AllowShortLoopsOnASingleLine);
503
407
    IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",
504
407
                   Style.AlwaysBreakAfterDefinitionReturnType);
505
407
    IO.mapOptional("AlwaysBreakAfterReturnType",
506
407
                   Style.AlwaysBreakAfterReturnType);
507
508
    // If AlwaysBreakAfterDefinitionReturnType was specified but
509
    // AlwaysBreakAfterReturnType was not, initialize the latter from the
510
    // former for backwards compatibility.
511
407
    if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&
512
23
        Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) {
513
0
      if (Style.AlwaysBreakAfterDefinitionReturnType == FormatStyle::DRTBS_All)
514
0
        Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
515
0
      else if (Style.AlwaysBreakAfterDefinitionReturnType ==
516
0
               FormatStyle::DRTBS_TopLevel)
517
0
        Style.AlwaysBreakAfterReturnType =
518
0
            FormatStyle::RTBS_TopLevelDefinitions;
519
0
    }
520
521
407
    IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
522
407
                   Style.AlwaysBreakBeforeMultilineStrings);
523
407
    IO.mapOptional("AlwaysBreakTemplateDeclarations",
524
407
                   Style.AlwaysBreakTemplateDeclarations);
525
407
    IO.mapOptional("AttributeMacros", Style.AttributeMacros);
526
407
    IO.mapOptional("BinPackArguments", Style.BinPackArguments);
527
407
    IO.mapOptional("BinPackParameters", Style.BinPackParameters);
528
407
    IO.mapOptional("BraceWrapping", Style.BraceWrapping);
529
407
    IO.mapOptional("BreakBeforeBinaryOperators",
530
407
                   Style.BreakBeforeBinaryOperators);
531
407
    IO.mapOptional("BreakBeforeConceptDeclarations",
532
407
                   Style.BreakBeforeConceptDeclarations);
533
407
    IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
534
535
407
    bool BreakBeforeInheritanceComma = false;
536
407
    IO.mapOptional("BreakBeforeInheritanceComma", BreakBeforeInheritanceComma);
537
407
    IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList);
538
    // If BreakBeforeInheritanceComma was specified but
539
    // BreakInheritance was not, initialize the latter from the
540
    // former for backwards compatibility.
541
407
    if (BreakBeforeInheritanceComma &&
542
1
        Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon)
543
1
      Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
544
545
407
    IO.mapOptional("BreakBeforeTernaryOperators",
546
407
                   Style.BreakBeforeTernaryOperators);
547
548
407
    bool BreakConstructorInitializersBeforeComma = false;
549
407
    IO.mapOptional("BreakConstructorInitializersBeforeComma",
550
407
                   BreakConstructorInitializersBeforeComma);
551
407
    IO.mapOptional("BreakConstructorInitializers",
552
407
                   Style.BreakConstructorInitializers);
553
    // If BreakConstructorInitializersBeforeComma was specified but
554
    // BreakConstructorInitializers was not, initialize the latter from the
555
    // former for backwards compatibility.
556
407
    if (BreakConstructorInitializersBeforeComma &&
557
1
        Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon)
558
1
      Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
559
560
407
    IO.mapOptional("BreakAfterJavaFieldAnnotations",
561
407
                   Style.BreakAfterJavaFieldAnnotations);
562
407
    IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
563
407
    IO.mapOptional("ColumnLimit", Style.ColumnLimit);
564
407
    IO.mapOptional("CommentPragmas", Style.CommentPragmas);
565
407
    IO.mapOptional("CompactNamespaces", Style.CompactNamespaces);
566
407
    IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
567
407
                   Style.ConstructorInitializerAllOnOneLineOrOnePerLine);
568
407
    IO.mapOptional("ConstructorInitializerIndentWidth",
569
407
                   Style.ConstructorInitializerIndentWidth);
570
407
    IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
571
407
    IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
572
407
    IO.mapOptional("DeriveLineEnding", Style.DeriveLineEnding);
573
407
    IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
574
407
    IO.mapOptional("DisableFormat", Style.DisableFormat);
575
407
    IO.mapOptional("EmptyLineBeforeAccessModifier",
576
407
                   Style.EmptyLineBeforeAccessModifier);
577
407
    IO.mapOptional("ExperimentalAutoDetectBinPacking",
578
407
                   Style.ExperimentalAutoDetectBinPacking);
579
407
    IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
580
407
    IO.mapOptional("ForEachMacros", Style.ForEachMacros);
581
407
    IO.mapOptional("StatementAttributeLikeMacros",
582
407
                   Style.StatementAttributeLikeMacros);
583
407
    IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
584
407
    IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
585
407
    IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
586
407
    IO.mapOptional("IncludeIsMainSourceRegex",
587
407
                   Style.IncludeStyle.IncludeIsMainSourceRegex);
588
407
    IO.mapOptional("IncludeSortAlphabetically",
589
407
                   Style.IncludeStyle.IncludeSortAlphabetically);
590
407
    IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
591
407
    IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks);
592
407
    IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels);
593
407
    IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
594
407
    IO.mapOptional("IndentExternBlock", Style.IndentExternBlock);
595
407
    IO.mapOptional("IndentRequires", Style.IndentRequires);
596
407
    IO.mapOptional("IndentWidth", Style.IndentWidth);
597
407
    IO.mapOptional("IndentWrappedFunctionNames",
598
407
                   Style.IndentWrappedFunctionNames);
599
407
    IO.mapOptional("InsertTrailingCommas", Style.InsertTrailingCommas);
600
407
    IO.mapOptional("JavaImportGroups", Style.JavaImportGroups);
601
407
    IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);
602
407
    IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
603
407
    IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
604
407
                   Style.KeepEmptyLinesAtTheStartOfBlocks);
605
407
    IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
606
407
    IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);
607
407
    IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
608
407
    IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
609
407
    IO.mapOptional("NamespaceMacros", Style.NamespaceMacros);
610
407
    IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList);
611
407
    IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);
612
407
    IO.mapOptional("ObjCBreakBeforeNestedBlockParam",
613
407
                   Style.ObjCBreakBeforeNestedBlockParam);
614
407
    IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
615
407
    IO.mapOptional("ObjCSpaceBeforeProtocolList",
616
407
                   Style.ObjCSpaceBeforeProtocolList);
617
407
    IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment);
618
407
    IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",
619
407
                   Style.PenaltyBreakBeforeFirstCallParameter);
620
407
    IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
621
407
    IO.mapOptional("PenaltyBreakFirstLessLess",
622
407
                   Style.PenaltyBreakFirstLessLess);
623
407
    IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
624
407
    IO.mapOptional("PenaltyBreakTemplateDeclaration",
625
407
                   Style.PenaltyBreakTemplateDeclaration);
626
407
    IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
627
407
    IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
628
407
                   Style.PenaltyReturnTypeOnItsOwnLine);
629
407
    IO.mapOptional("PenaltyIndentedWhitespace",
630
407
                   Style.PenaltyIndentedWhitespace);
631
407
    IO.mapOptional("PointerAlignment", Style.PointerAlignment);
632
407
    IO.mapOptional("RawStringFormats", Style.RawStringFormats);
633
407
    IO.mapOptional("ReflowComments", Style.ReflowComments);
634
407
    IO.mapOptional("SortIncludes", Style.SortIncludes);
635
407
    IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport);
636
407
    IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);
637
407
    IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
638
407
    IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot);
639
407
    IO.mapOptional("SpaceAfterTemplateKeyword",
640
407
                   Style.SpaceAfterTemplateKeyword);
641
407
    IO.mapOptional("SpaceBeforeAssignmentOperators",
642
407
                   Style.SpaceBeforeAssignmentOperators);
643
407
    IO.mapOptional("SpaceBeforeCaseColon", Style.SpaceBeforeCaseColon);
644
407
    IO.mapOptional("SpaceBeforeCpp11BracedList",
645
407
                   Style.SpaceBeforeCpp11BracedList);
646
407
    IO.mapOptional("SpaceBeforeCtorInitializerColon",
647
407
                   Style.SpaceBeforeCtorInitializerColon);
648
407
    IO.mapOptional("SpaceBeforeInheritanceColon",
649
407
                   Style.SpaceBeforeInheritanceColon);
650
407
    IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
651
407
    IO.mapOptional("SpaceAroundPointerQualifiers",
652
407
                   Style.SpaceAroundPointerQualifiers);
653
407
    IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
654
407
                   Style.SpaceBeforeRangeBasedForLoopColon);
655
407
    IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock);
656
407
    IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
657
407
    IO.mapOptional("SpacesBeforeTrailingComments",
658
407
                   Style.SpacesBeforeTrailingComments);
659
407
    IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
660
407
    IO.mapOptional("SpacesInConditionalStatement",
661
407
                   Style.SpacesInConditionalStatement);
662
407
    IO.mapOptional("SpacesInContainerLiterals",
663
407
                   Style.SpacesInContainerLiterals);
664
407
    IO.mapOptional("SpacesInCStyleCastParentheses",
665
407
                   Style.SpacesInCStyleCastParentheses);
666
407
    IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
667
407
    IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
668
407
    IO.mapOptional("SpaceBeforeSquareBrackets",
669
407
                   Style.SpaceBeforeSquareBrackets);
670
407
    IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing);
671
407
    IO.mapOptional("Standard", Style.Standard);
672
407
    IO.mapOptional("StatementMacros", Style.StatementMacros);
673
407
    IO.mapOptional("TabWidth", Style.TabWidth);
674
407
    IO.mapOptional("TypenameMacros", Style.TypenameMacros);
675
407
    IO.mapOptional("UseCRLF", Style.UseCRLF);
676
407
    IO.mapOptional("UseTab", Style.UseTab);
677
407
    IO.mapOptional("WhitespaceSensitiveMacros",
678
407
                   Style.WhitespaceSensitiveMacros);
679
407
  }
680
};
681
682
template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
683
46
  static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
684
46
    IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel);
685
46
    IO.mapOptional("AfterClass", Wrapping.AfterClass);
686
46
    IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement);
687
46
    IO.mapOptional("AfterEnum", Wrapping.AfterEnum);
688
46
    IO.mapOptional("AfterFunction", Wrapping.AfterFunction);
689
46
    IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace);
690
46
    IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
691
46
    IO.mapOptional("AfterStruct", Wrapping.AfterStruct);
692
46
    IO.mapOptional("AfterUnion", Wrapping.AfterUnion);
693
46
    IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
694
46
    IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
695
46
    IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
696
46
    IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody);
697
46
    IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile);
698
46
    IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
699
46
    IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);
700
46
    IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);
701
46
    IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
702
46
  }
703
};
704
705
template <> struct MappingTraits<FormatStyle::RawStringFormat> {
706
2
  static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
707
2
    IO.mapOptional("Language", Format.Language);
708
2
    IO.mapOptional("Delimiters", Format.Delimiters);
709
2
    IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);
710
2
    IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter);
711
2
    IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);
712
2
  }
713
};
714
715
// Allows to read vector<FormatStyle> while keeping default values.
716
// IO.getContext() should contain a pointer to the FormatStyle structure, that
717
// will be used to get default values for missing keys.
718
// If the first element has no Language specified, it will be treated as the
719
// default one for the following elements.
720
template <> struct DocumentListTraits<std::vector<FormatStyle>> {
721
0
  static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
722
0
    return Seq.size();
723
0
  }
724
  static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq,
725
402
                              size_t Index) {
726
402
    if (Index >= Seq.size()) {
727
402
      assert(Index == Seq.size());
728
402
      FormatStyle Template;
729
402
      if (!Seq.empty() && 
Seq[0].Language == FormatStyle::LK_None9
) {
730
5
        Template = Seq[0];
731
397
      } else {
732
397
        Template = *((const FormatStyle *)IO.getContext());
733
397
        Template.Language = FormatStyle::LK_None;
734
397
      }
735
402
      Seq.resize(Index + 1, Template);
736
402
    }
737
402
    return Seq[Index];
738
402
  }
739
};
740
} // namespace yaml
741
} // namespace llvm
742
743
namespace clang {
744
namespace format {
745
746
396
const std::error_category &getParseCategory() {
747
396
  static const ParseErrorCategory C{};
748
396
  return C;
749
396
}
750
396
std::error_code make_error_code(ParseError e) {
751
396
  return std::error_code(static_cast<int>(e), getParseCategory());
752
396
}
753
754
8
inline llvm::Error make_string_error(const llvm::Twine &Message) {
755
8
  return llvm::make_error<llvm::StringError>(Message,
756
8
                                             llvm::inconvertibleErrorCode());
757
8
}
758
759
0
const char *ParseErrorCategory::name() const noexcept {
760
0
  return "clang-format.parse_error";
761
0
}
762
763
1
std::string ParseErrorCategory::message(int EV) const {
764
1
  switch (static_cast<ParseError>(EV)) {
765
0
  case ParseError::Success:
766
0
    return "Success";
767
1
  case ParseError::Error:
768
1
    return "Invalid argument";
769
0
  case ParseError::Unsuitable:
770
0
    return "Unsuitable";
771
0
  case ParseError::BinPackTrailingCommaConflict:
772
0
    return "trailing comma insertion cannot be used with bin packing";
773
0
  }
774
0
  llvm_unreachable("unexpected parse error");
775
0
}
776
777
16.9k
static FormatStyle expandPresets(const FormatStyle &Style) {
778
16.9k
  if (Style.BreakBeforeBraces == FormatStyle::BS_Custom)
779
710
    return Style;
780
16.2k
  FormatStyle Expanded = Style;
781
16.2k
  Expanded.BraceWrapping = {/*AfterCaseLabel=*/false,
782
16.2k
                            /*AfterClass=*/false,
783
16.2k
                            /*AfterControlStatement=*/FormatStyle::BWACS_Never,
784
16.2k
                            /*AfterEnum=*/false,
785
16.2k
                            /*AfterFunction=*/false,
786
16.2k
                            /*AfterNamespace=*/false,
787
16.2k
                            /*AfterObjCDeclaration=*/false,
788
16.2k
                            /*AfterStruct=*/false,
789
16.2k
                            /*AfterUnion=*/false,
790
16.2k
                            /*AfterExternBlock=*/false,
791
16.2k
                            /*BeforeCatch=*/false,
792
16.2k
                            /*BeforeElse=*/false,
793
16.2k
                            /*BeforeLambdaBody=*/false,
794
16.2k
                            /*BeforeWhile=*/false,
795
16.2k
                            /*IndentBraces=*/false,
796
16.2k
                            /*SplitEmptyFunction=*/true,
797
16.2k
                            /*SplitEmptyRecord=*/true,
798
16.2k
                            /*SplitEmptyNamespace=*/true};
799
16.2k
  switch (Style.BreakBeforeBraces) {
800
9
  case FormatStyle::BS_Linux:
801
9
    Expanded.BraceWrapping.AfterClass = true;
802
9
    Expanded.BraceWrapping.AfterFunction = true;
803
9
    Expanded.BraceWrapping.AfterNamespace = true;
804
9
    break;
805
17
  case FormatStyle::BS_Mozilla:
806
17
    Expanded.BraceWrapping.AfterClass = true;
807
17
    Expanded.BraceWrapping.AfterEnum = true;
808
17
    Expanded.BraceWrapping.AfterFunction = true;
809
17
    Expanded.BraceWrapping.AfterStruct = true;
810
17
    Expanded.BraceWrapping.AfterUnion = true;
811
17
    Expanded.BraceWrapping.AfterExternBlock = true;
812
17
    Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
813
17
    Expanded.BraceWrapping.SplitEmptyFunction = true;
814
17
    Expanded.BraceWrapping.SplitEmptyRecord = false;
815
17
    break;
816
48
  case FormatStyle::BS_Stroustrup:
817
48
    Expanded.BraceWrapping.AfterFunction = true;
818
48
    Expanded.BraceWrapping.BeforeCatch = true;
819
48
    Expanded.BraceWrapping.BeforeElse = true;
820
48
    break;
821
110
  case FormatStyle::BS_Allman:
822
110
    Expanded.BraceWrapping.AfterCaseLabel = true;
823
110
    Expanded.BraceWrapping.AfterClass = true;
824
110
    Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
825
110
    Expanded.BraceWrapping.AfterEnum = true;
826
110
    Expanded.BraceWrapping.AfterFunction = true;
827
110
    Expanded.BraceWrapping.AfterNamespace = true;
828
110
    Expanded.BraceWrapping.AfterObjCDeclaration = true;
829
110
    Expanded.BraceWrapping.AfterStruct = true;
830
110
    Expanded.BraceWrapping.AfterUnion = true;
831
110
    Expanded.BraceWrapping.AfterExternBlock = true;
832
110
    Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
833
110
    Expanded.BraceWrapping.BeforeCatch = true;
834
110
    Expanded.BraceWrapping.BeforeElse = true;
835
110
    Expanded.BraceWrapping.BeforeLambdaBody = true;
836
110
    break;
837
75
  case FormatStyle::BS_Whitesmiths:
838
75
    Expanded.BraceWrapping.AfterCaseLabel = true;
839
75
    Expanded.BraceWrapping.AfterClass = true;
840
75
    Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
841
75
    Expanded.BraceWrapping.AfterEnum = true;
842
75
    Expanded.BraceWrapping.AfterFunction = true;
843
75
    Expanded.BraceWrapping.AfterNamespace = true;
844
75
    Expanded.BraceWrapping.AfterObjCDeclaration = true;
845
75
    Expanded.BraceWrapping.AfterStruct = true;
846
75
    Expanded.BraceWrapping.AfterExternBlock = true;
847
75
    Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
848
75
    Expanded.BraceWrapping.BeforeCatch = true;
849
75
    Expanded.BraceWrapping.BeforeElse = true;
850
75
    Expanded.BraceWrapping.BeforeLambdaBody = true;
851
75
    break;
852
48
  case FormatStyle::BS_GNU:
853
48
    Expanded.BraceWrapping = {
854
48
        /*AfterCaseLabel=*/true,
855
48
        /*AfterClass=*/true,
856
48
        /*AfterControlStatement=*/FormatStyle::BWACS_Always,
857
48
        /*AfterEnum=*/true,
858
48
        /*AfterFunction=*/true,
859
48
        /*AfterNamespace=*/true,
860
48
        /*AfterObjCDeclaration=*/true,
861
48
        /*AfterStruct=*/true,
862
48
        /*AfterUnion=*/true,
863
48
        /*AfterExternBlock=*/true,
864
48
        /*BeforeCatch=*/true,
865
48
        /*BeforeElse=*/true,
866
48
        /*BeforeLambdaBody=*/false,
867
48
        /*BeforeWhile=*/true,
868
48
        /*IndentBraces=*/true,
869
48
        /*SplitEmptyFunction=*/true,
870
48
        /*SplitEmptyRecord=*/true,
871
48
        /*SplitEmptyNamespace=*/true};
872
48
    Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
873
48
    break;
874
64
  case FormatStyle::BS_WebKit:
875
64
    Expanded.BraceWrapping.AfterFunction = true;
876
64
    break;
877
15.8k
  default:
878
15.8k
    break;
879
16.2k
  }
880
16.2k
  return Expanded;
881
16.2k
}
882
883
15.1k
FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
884
15.1k
  FormatStyle LLVMStyle;
885
15.1k
  LLVMStyle.Language = Language;
886
15.1k
  LLVMStyle.AccessModifierOffset = -2;
887
15.1k
  LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
888
15.1k
  LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
889
15.1k
  LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
890
15.1k
  LLVMStyle.AlignTrailingComments = true;
891
15.1k
  LLVMStyle.AlignConsecutiveAssignments = FormatStyle::ACS_None;
892
15.1k
  LLVMStyle.AlignConsecutiveBitFields = FormatStyle::ACS_None;
893
15.1k
  LLVMStyle.AlignConsecutiveDeclarations = FormatStyle::ACS_None;
894
15.1k
  LLVMStyle.AlignConsecutiveMacros = FormatStyle::ACS_None;
895
15.1k
  LLVMStyle.AllowAllArgumentsOnNextLine = true;
896
15.1k
  LLVMStyle.AllowAllConstructorInitializersOnNextLine = true;
897
15.1k
  LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
898
15.1k
  LLVMStyle.AllowShortEnumsOnASingleLine = true;
899
15.1k
  LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
900
15.1k
  LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
901
15.1k
  LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
902
15.1k
  LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
903
15.1k
  LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
904
15.1k
  LLVMStyle.AllowShortLoopsOnASingleLine = false;
905
15.1k
  LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
906
15.1k
  LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
907
15.1k
  LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
908
15.1k
  LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
909
15.1k
  LLVMStyle.AttributeMacros.push_back("__capability");
910
15.1k
  LLVMStyle.BinPackArguments = true;
911
15.1k
  LLVMStyle.BinPackParameters = true;
912
15.1k
  LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
913
15.1k
  LLVMStyle.BreakBeforeConceptDeclarations = true;
914
15.1k
  LLVMStyle.BreakBeforeTernaryOperators = true;
915
15.1k
  LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
916
15.1k
  LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false,
917
15.1k
                             /*AfterClass=*/false,
918
15.1k
                             /*AfterControlStatement=*/FormatStyle::BWACS_Never,
919
15.1k
                             /*AfterEnum=*/false,
920
15.1k
                             /*AfterFunction=*/false,
921
15.1k
                             /*AfterNamespace=*/false,
922
15.1k
                             /*AfterObjCDeclaration=*/false,
923
15.1k
                             /*AfterStruct=*/false,
924
15.1k
                             /*AfterUnion=*/false,
925
15.1k
                             /*AfterExternBlock=*/false,
926
15.1k
                             /*BeforeCatch=*/false,
927
15.1k
                             /*BeforeElse=*/false,
928
15.1k
                             /*BeforeLambdaBody=*/false,
929
15.1k
                             /*BeforeWhile=*/false,
930
15.1k
                             /*IndentBraces=*/false,
931
15.1k
                             /*SplitEmptyFunction=*/true,
932
15.1k
                             /*SplitEmptyRecord=*/true,
933
15.1k
                             /*SplitEmptyNamespace=*/true};
934
15.1k
  LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
935
15.1k
  LLVMStyle.BreakAfterJavaFieldAnnotations = false;
936
15.1k
  LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
937
15.1k
  LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
938
15.1k
  LLVMStyle.BreakStringLiterals = true;
939
15.1k
  LLVMStyle.ColumnLimit = 80;
940
15.1k
  LLVMStyle.CommentPragmas = "^ IWYU pragma:";
941
15.1k
  LLVMStyle.CompactNamespaces = false;
942
15.1k
  LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false;
943
15.1k
  LLVMStyle.ConstructorInitializerIndentWidth = 4;
944
15.1k
  LLVMStyle.ContinuationIndentWidth = 4;
945
15.1k
  LLVMStyle.Cpp11BracedListStyle = true;
946
15.1k
  LLVMStyle.DeriveLineEnding = true;
947
15.1k
  LLVMStyle.DerivePointerAlignment = false;
948
15.1k
  LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock;
949
15.1k
  LLVMStyle.ExperimentalAutoDetectBinPacking = false;
950
15.1k
  LLVMStyle.FixNamespaceComments = true;
951
15.1k
  LLVMStyle.ForEachMacros.push_back("foreach");
952
15.1k
  LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
953
15.1k
  LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
954
15.1k
  LLVMStyle.IncludeStyle.IncludeCategories = {
955
15.1k
      {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false},
956
15.1k
      {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},
957
15.1k
      {".*", 1, 0, false}};
958
15.1k
  LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
959
15.1k
  LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
960
15.1k
  LLVMStyle.IncludeStyle.IncludeSortAlphabetically = false;
961
15.1k
  LLVMStyle.IndentCaseLabels = false;
962
15.1k
  LLVMStyle.IndentCaseBlocks = false;
963
15.1k
  LLVMStyle.IndentGotoLabels = true;
964
15.1k
  LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
965
15.1k
  LLVMStyle.IndentRequires = false;
966
15.1k
  LLVMStyle.IndentWrappedFunctionNames = false;
967
15.1k
  LLVMStyle.IndentWidth = 2;
968
15.1k
  LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
969
15.1k
  LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
970
15.1k
  LLVMStyle.JavaScriptWrapImports = true;
971
15.1k
  LLVMStyle.TabWidth = 8;
972
15.1k
  LLVMStyle.MaxEmptyLinesToKeep = 1;
973
15.1k
  LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
974
15.1k
  LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
975
15.1k
  LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto;
976
15.1k
  LLVMStyle.ObjCBlockIndentWidth = 2;
977
15.1k
  LLVMStyle.ObjCBreakBeforeNestedBlockParam = true;
978
15.1k
  LLVMStyle.ObjCSpaceAfterProperty = false;
979
15.1k
  LLVMStyle.ObjCSpaceBeforeProtocolList = true;
980
15.1k
  LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
981
15.1k
  LLVMStyle.SpacesBeforeTrailingComments = 1;
982
15.1k
  LLVMStyle.Standard = FormatStyle::LS_Latest;
983
15.1k
  LLVMStyle.UseCRLF = false;
984
15.1k
  LLVMStyle.UseTab = FormatStyle::UT_Never;
985
15.1k
  LLVMStyle.ReflowComments = true;
986
15.1k
  LLVMStyle.SpacesInParentheses = false;
987
15.1k
  LLVMStyle.SpacesInSquareBrackets = false;
988
15.1k
  LLVMStyle.SpaceInEmptyBlock = false;
989
15.1k
  LLVMStyle.SpaceInEmptyParentheses = false;
990
15.1k
  LLVMStyle.SpacesInContainerLiterals = true;
991
15.1k
  LLVMStyle.SpacesInCStyleCastParentheses = false;
992
15.1k
  LLVMStyle.SpaceAfterCStyleCast = false;
993
15.1k
  LLVMStyle.SpaceAfterLogicalNot = false;
994
15.1k
  LLVMStyle.SpaceAfterTemplateKeyword = true;
995
15.1k
  LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
996
15.1k
  LLVMStyle.SpaceBeforeCaseColon = false;
997
15.1k
  LLVMStyle.SpaceBeforeCtorInitializerColon = true;
998
15.1k
  LLVMStyle.SpaceBeforeInheritanceColon = true;
999
15.1k
  LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
1000
15.1k
  LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
1001
15.1k
  LLVMStyle.SpaceBeforeAssignmentOperators = true;
1002
15.1k
  LLVMStyle.SpaceBeforeCpp11BracedList = false;
1003
15.1k
  LLVMStyle.SpaceBeforeSquareBrackets = false;
1004
15.1k
  LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;
1005
15.1k
  LLVMStyle.SpacesInAngles = false;
1006
15.1k
  LLVMStyle.SpacesInConditionalStatement = false;
1007
1008
15.1k
  LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
1009
15.1k
  LLVMStyle.PenaltyBreakComment = 300;
1010
15.1k
  LLVMStyle.PenaltyBreakFirstLessLess = 120;
1011
15.1k
  LLVMStyle.PenaltyBreakString = 1000;
1012
15.1k
  LLVMStyle.PenaltyExcessCharacter = 1000000;
1013
15.1k
  LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
1014
15.1k
  LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
1015
15.1k
  LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;
1016
15.1k
  LLVMStyle.PenaltyIndentedWhitespace = 0;
1017
1018
15.1k
  LLVMStyle.DisableFormat = false;
1019
15.1k
  LLVMStyle.SortIncludes = true;
1020
15.1k
  LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
1021
15.1k
  LLVMStyle.SortUsingDeclarations = true;
1022
15.1k
  LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");
1023
15.1k
  LLVMStyle.StatementMacros.push_back("Q_UNUSED");
1024
15.1k
  LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");
1025
15.1k
  LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE");
1026
15.1k
  LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE");
1027
15.1k
  LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE");
1028
15.1k
  LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME");
1029
15.1k
  LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME");
1030
1031
  // Defaults that differ when not C++.
1032
15.1k
  if (Language == FormatStyle::LK_TableGen) {
1033
7
    LLVMStyle.SpacesInContainerLiterals = false;
1034
7
  }
1035
1036
15.1k
  return LLVMStyle;
1037
15.1k
}
1038
1039
11.5k
FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
1040
11.5k
  if (Language == FormatStyle::LK_TextProto) {
1041
3.52k
    FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto);
1042
3.52k
    GoogleStyle.Language = FormatStyle::LK_TextProto;
1043
1044
3.52k
    return GoogleStyle;
1045
3.52k
  }
1046
1047
8.06k
  FormatStyle GoogleStyle = getLLVMStyle(Language);
1048
1049
8.06k
  GoogleStyle.AccessModifierOffset = -1;
1050
8.06k
  GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left;
1051
8.06k
  GoogleStyle.AllowShortIfStatementsOnASingleLine =
1052
8.06k
      FormatStyle::SIS_WithoutElse;
1053
8.06k
  GoogleStyle.AllowShortLoopsOnASingleLine = true;
1054
8.06k
  GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
1055
8.06k
  GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
1056
8.06k
  GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
1057
8.06k
  GoogleStyle.DerivePointerAlignment = true;
1058
8.06k
  GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false},
1059
8.06k
                                                {"^<.*\\.h>", 1, 0, false},
1060
8.06k
                                                {"^<.*", 2, 0, false},
1061
8.06k
                                                {".*", 3, 0, false}};
1062
8.06k
  GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
1063
8.06k
  GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
1064
8.06k
  GoogleStyle.IndentCaseLabels = true;
1065
8.06k
  GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
1066
8.06k
  GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never;
1067
8.06k
  GoogleStyle.ObjCSpaceAfterProperty = false;
1068
8.06k
  GoogleStyle.ObjCSpaceBeforeProtocolList = true;
1069
8.06k
  GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;
1070
8.06k
  GoogleStyle.RawStringFormats = {
1071
8.06k
      {
1072
8.06k
          FormatStyle::LK_Cpp,
1073
          /*Delimiters=*/
1074
8.06k
          {
1075
8.06k
              "cc",
1076
8.06k
              "CC",
1077
8.06k
              "cpp",
1078
8.06k
              "Cpp",
1079
8.06k
              "CPP",
1080
8.06k
              "c++",
1081
8.06k
              "C++",
1082
8.06k
          },
1083
          /*EnclosingFunctionNames=*/
1084
8.06k
          {},
1085
8.06k
          /*CanonicalDelimiter=*/"",
1086
8.06k
          /*BasedOnStyle=*/"google",
1087
8.06k
      },
1088
8.06k
      {
1089
8.06k
          FormatStyle::LK_TextProto,
1090
          /*Delimiters=*/
1091
8.06k
          {
1092
8.06k
              "pb",
1093
8.06k
              "PB",
1094
8.06k
              "proto",
1095
8.06k
              "PROTO",
1096
8.06k
          },
1097
          /*EnclosingFunctionNames=*/
1098
8.06k
          {
1099
8.06k
              "EqualsProto",
1100
8.06k
              "EquivToProto",
1101
8.06k
              "PARSE_PARTIAL_TEXT_PROTO",
1102
8.06k
              "PARSE_TEST_PROTO",
1103
8.06k
              "PARSE_TEXT_PROTO",
1104
8.06k
              "ParseTextOrDie",
1105
8.06k
              "ParseTextProtoOrDie",
1106
8.06k
              "ParseTestProto",
1107
8.06k
              "ParsePartialTestProto",
1108
8.06k
          },
1109
8.06k
          /*CanonicalDelimiter=*/"",
1110
8.06k
          /*BasedOnStyle=*/"google",
1111
8.06k
      },
1112
8.06k
  };
1113
8.06k
  GoogleStyle.SpacesBeforeTrailingComments = 2;
1114
8.06k
  GoogleStyle.Standard = FormatStyle::LS_Auto;
1115
1116
8.06k
  GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
1117
8.06k
  GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;
1118
1119
8.06k
  if (Language == FormatStyle::LK_Java) {
1120
147
    GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
1121
147
    GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
1122
147
    GoogleStyle.AlignTrailingComments = false;
1123
147
    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
1124
147
    GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
1125
147
    GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
1126
147
    GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
1127
147
    GoogleStyle.ColumnLimit = 100;
1128
147
    GoogleStyle.SpaceAfterCStyleCast = true;
1129
147
    GoogleStyle.SpacesBeforeTrailingComments = 1;
1130
7.92k
  } else if (Language == FormatStyle::LK_JavaScript) {
1131
679
    GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
1132
679
    GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
1133
679
    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
1134
    // TODO: still under discussion whether to switch to SLS_All.
1135
679
    GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
1136
679
    GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
1137
679
    GoogleStyle.BreakBeforeTernaryOperators = false;
1138
    // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is
1139
    // commonly followed by overlong URLs.
1140
679
    GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)";
1141
    // TODO: enable once decided, in particular re disabling bin packing.
1142
    // https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma
1143
    // GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
1144
679
    GoogleStyle.MaxEmptyLinesToKeep = 3;
1145
679
    GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
1146
679
    GoogleStyle.SpacesInContainerLiterals = false;
1147
679
    GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single;
1148
679
    GoogleStyle.JavaScriptWrapImports = false;
1149
7.24k
  } else if (Language == FormatStyle::LK_Proto) {
1150
3.69k
    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
1151
3.69k
    GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
1152
3.69k
    GoogleStyle.SpacesInContainerLiterals = false;
1153
3.69k
    GoogleStyle.Cpp11BracedListStyle = false;
1154
    // This affects protocol buffer options specifications and text protos.
1155
    // Text protos are currently mostly formatted inside C++ raw string literals
1156
    // and often the current breaking behavior of string literals is not
1157
    // beneficial there. Investigate turning this on once proper string reflow
1158
    // has been implemented.
1159
3.69k
    GoogleStyle.BreakStringLiterals = false;
1160
3.55k
  } else if (Language == FormatStyle::LK_ObjC) {
1161
14
    GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
1162
14
    GoogleStyle.ColumnLimit = 100;
1163
    // "Regroup" doesn't work well for ObjC yet (main header heuristic,
1164
    // relationship between ObjC standard library headers and other heades,
1165
    // #imports, etc.)
1166
14
    GoogleStyle.IncludeStyle.IncludeBlocks =
1167
14
        tooling::IncludeStyle::IBS_Preserve;
1168
3.53k
  } else if (Language == FormatStyle::LK_CSharp) {
1169
18
    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
1170
18
    GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
1171
18
    GoogleStyle.BreakStringLiterals = false;
1172
18
    GoogleStyle.ColumnLimit = 100;
1173
18
    GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
1174
18
  }
1175
1176
8.06k
  return GoogleStyle;
1177
8.06k
}
1178
1179
15
FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
1180
15
  FormatStyle ChromiumStyle = getGoogleStyle(Language);
1181
1182
  // Disable include reordering across blocks in Chromium code.
1183
  // - clang-format tries to detect that foo.h is the "main" header for
1184
  //   foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium
1185
  //   uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc,
1186
  //   _private.cc, _impl.cc etc) in different permutations
1187
  //   (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a
1188
  //   better default for Chromium code.
1189
  // - The default for .cc and .mm files is different (r357695) for Google style
1190
  //   for the same reason. The plan is to unify this again once the main
1191
  //   header detection works for Google's ObjC code, but this hasn't happened
1192
  //   yet. Since Chromium has some ObjC code, switching Chromium is blocked
1193
  //   on that.
1194
  // - Finally, "If include reordering is harmful, put things in different
1195
  //   blocks to prevent it" has been a recommendation for a long time that
1196
  //   people are used to. We'll need a dev education push to change this to
1197
  //   "If include reordering is harmful, put things in a different block and
1198
  //   _prepend that with a comment_ to prevent it" before changing behavior.
1199
15
  ChromiumStyle.IncludeStyle.IncludeBlocks =
1200
15
      tooling::IncludeStyle::IBS_Preserve;
1201
1202
15
  if (Language == FormatStyle::LK_Java) {
1203
2
    ChromiumStyle.AllowShortIfStatementsOnASingleLine =
1204
2
        FormatStyle::SIS_WithoutElse;
1205
2
    ChromiumStyle.BreakAfterJavaFieldAnnotations = true;
1206
2
    ChromiumStyle.ContinuationIndentWidth = 8;
1207
2
    ChromiumStyle.IndentWidth = 4;
1208
    // See styleguide for import groups:
1209
    // https://chromium.googlesource.com/chromium/src/+/master/styleguide/java/java.md#Import-Order
1210
2
    ChromiumStyle.JavaImportGroups = {
1211
2
        "android",
1212
2
        "androidx",
1213
2
        "com",
1214
2
        "dalvik",
1215
2
        "junit",
1216
2
        "org",
1217
2
        "com.google.android.apps.chrome",
1218
2
        "org.chromium",
1219
2
        "java",
1220
2
        "javax",
1221
2
    };
1222
2
    ChromiumStyle.SortIncludes = true;
1223
13
  } else if (Language == FormatStyle::LK_JavaScript) {
1224
1
    ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
1225
1
    ChromiumStyle.AllowShortLoopsOnASingleLine = false;
1226
12
  } else {
1227
12
    ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
1228
12
    ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
1229
12
    ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
1230
12
    ChromiumStyle.AllowShortLoopsOnASingleLine = false;
1231
12
    ChromiumStyle.BinPackParameters = false;
1232
12
    ChromiumStyle.DerivePointerAlignment = false;
1233
12
    if (Language == FormatStyle::LK_ObjC)
1234
2
      ChromiumStyle.ColumnLimit = 80;
1235
12
  }
1236
15
  return ChromiumStyle;
1237
15
}
1238
1239
12
FormatStyle getMozillaStyle() {
1240
12
  FormatStyle MozillaStyle = getLLVMStyle();
1241
12
  MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
1242
12
  MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
1243
12
  MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel;
1244
12
  MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
1245
12
      FormatStyle::DRTBS_TopLevel;
1246
12
  MozillaStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
1247
12
  MozillaStyle.BinPackParameters = false;
1248
12
  MozillaStyle.BinPackArguments = false;
1249
12
  MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
1250
12
  MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
1251
12
  MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
1252
12
  MozillaStyle.ConstructorInitializerIndentWidth = 2;
1253
12
  MozillaStyle.ContinuationIndentWidth = 2;
1254
12
  MozillaStyle.Cpp11BracedListStyle = false;
1255
12
  MozillaStyle.FixNamespaceComments = false;
1256
12
  MozillaStyle.IndentCaseLabels = true;
1257
12
  MozillaStyle.ObjCSpaceAfterProperty = true;
1258
12
  MozillaStyle.ObjCSpaceBeforeProtocolList = false;
1259
12
  MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
1260
12
  MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
1261
12
  MozillaStyle.SpaceAfterTemplateKeyword = false;
1262
12
  return MozillaStyle;
1263
12
}
1264
1265
12
FormatStyle getWebKitStyle() {
1266
12
  FormatStyle Style = getLLVMStyle();
1267
12
  Style.AccessModifierOffset = -4;
1268
12
  Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
1269
12
  Style.AlignOperands = FormatStyle::OAS_DontAlign;
1270
12
  Style.AlignTrailingComments = false;
1271
12
  Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;
1272
12
  Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
1273
12
  Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
1274
12
  Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
1275
12
  Style.Cpp11BracedListStyle = false;
1276
12
  Style.ColumnLimit = 0;
1277
12
  Style.FixNamespaceComments = false;
1278
12
  Style.IndentWidth = 4;
1279
12
  Style.NamespaceIndentation = FormatStyle::NI_Inner;
1280
12
  Style.ObjCBlockIndentWidth = 4;
1281
12
  Style.ObjCSpaceAfterProperty = true;
1282
12
  Style.PointerAlignment = FormatStyle::PAS_Left;
1283
12
  Style.SpaceBeforeCpp11BracedList = true;
1284
12
  Style.SpaceInEmptyBlock = true;
1285
12
  return Style;
1286
12
}
1287
1288
9
FormatStyle getGNUStyle() {
1289
9
  FormatStyle Style = getLLVMStyle();
1290
9
  Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
1291
9
  Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
1292
9
  Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
1293
9
  Style.BreakBeforeBraces = FormatStyle::BS_GNU;
1294
9
  Style.BreakBeforeTernaryOperators = true;
1295
9
  Style.Cpp11BracedListStyle = false;
1296
9
  Style.ColumnLimit = 79;
1297
9
  Style.FixNamespaceComments = false;
1298
9
  Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
1299
9
  Style.Standard = FormatStyle::LS_Cpp03;
1300
9
  return Style;
1301
9
}
1302
1303
51
FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) {
1304
51
  FormatStyle Style = getLLVMStyle(Language);
1305
51
  Style.ColumnLimit = 120;
1306
51
  Style.TabWidth = 4;
1307
51
  Style.IndentWidth = 4;
1308
51
  Style.UseTab = FormatStyle::UT_Never;
1309
51
  Style.BreakBeforeBraces = FormatStyle::BS_Custom;
1310
51
  Style.BraceWrapping.AfterClass = true;
1311
51
  Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
1312
51
  Style.BraceWrapping.AfterEnum = true;
1313
51
  Style.BraceWrapping.AfterFunction = true;
1314
51
  Style.BraceWrapping.AfterNamespace = true;
1315
51
  Style.BraceWrapping.AfterObjCDeclaration = true;
1316
51
  Style.BraceWrapping.AfterStruct = true;
1317
51
  Style.BraceWrapping.AfterExternBlock = true;
1318
51
  Style.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
1319
51
  Style.BraceWrapping.BeforeCatch = true;
1320
51
  Style.BraceWrapping.BeforeElse = true;
1321
51
  Style.BraceWrapping.BeforeWhile = false;
1322
51
  Style.PenaltyReturnTypeOnItsOwnLine = 1000;
1323
51
  Style.AllowShortEnumsOnASingleLine = false;
1324
51
  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
1325
51
  Style.AllowShortCaseLabelsOnASingleLine = false;
1326
51
  Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
1327
51
  Style.AllowShortLoopsOnASingleLine = false;
1328
51
  Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
1329
51
  Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
1330
51
  return Style;
1331
51
}
1332
1333
726
FormatStyle getNoStyle() {
1334
726
  FormatStyle NoStyle = getLLVMStyle();
1335
726
  NoStyle.DisableFormat = true;
1336
726
  NoStyle.SortIncludes = false;
1337
726
  NoStyle.SortUsingDeclarations = false;
1338
726
  return NoStyle;
1339
726
}
1340
1341
bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
1342
7.84k
                        FormatStyle *Style) {
1343
7.84k
  if (Name.equals_lower("llvm")) {
1344
1.07k
    *Style = getLLVMStyle(Language);
1345
6.77k
  } else if (Name.equals_lower("chromium")) {
1346
6
    *Style = getChromiumStyle(Language);
1347
6.76k
  } else if (Name.equals_lower("mozilla")) {
1348
7
    *Style = getMozillaStyle();
1349
6.76k
  } else if (Name.equals_lower("google")) {
1350
6.70k
    *Style = getGoogleStyle(Language);
1351
52
  } else if (Name.equals_lower("webkit")) {
1352
8
    *Style = getWebKitStyle();
1353
44
  } else if (Name.equals_lower("gnu")) {
1354
6
    *Style = getGNUStyle();
1355
38
  } else if (Name.equals_lower("microsoft")) {
1356
4
    *Style = getMicrosoftStyle(Language);
1357
34
  } else if (Name.equals_lower("none")) {
1358
29
    *Style = getNoStyle();
1359
5
  } else {
1360
5
    return false;
1361
5
  }
1362
1363
7.83k
  Style->Language = Language;
1364
7.83k
  return true;
1365
7.83k
}
1366
1367
std::error_code parseConfiguration(llvm::MemoryBufferRef Config,
1368
                                   FormatStyle *Style,
1369
394
                                   bool AllowUnknownOptions) {
1370
394
  assert(Style);
1371
394
  FormatStyle::LanguageKind Language = Style->Language;
1372
394
  assert(Language != FormatStyle::LK_None);
1373
394
  if (Config.getBuffer().trim().empty())
1374
1
    return make_error_code(ParseError::Error);
1375
393
  Style->StyleSet.Clear();
1376
393
  std::vector<FormatStyle> Styles;
1377
393
  llvm::yaml::Input Input(Config);
1378
  // DocumentListTraits<vector<FormatStyle>> uses the context to get default
1379
  // values for the fields, keys for which are missing from the configuration.
1380
  // Mapping also uses the context to get the language to find the correct
1381
  // base style.
1382
393
  Input.setContext(Style);
1383
393
  Input.setAllowUnknownKeys(AllowUnknownOptions);
1384
393
  Input >> Styles;
1385
393
  if (Input.error())
1386
5
    return Input.error();
1387
1388
783
  
for (unsigned i = 0; 388
i < Styles.size();
++i395
) {
1389
    // Ensures that only the first configuration can skip the Language option.
1390
397
    if (Styles[i].Language == FormatStyle::LK_None && 
i != 0377
)
1391
1
      return make_error_code(ParseError::Error);
1392
    // Ensure that each language is configured at most once.
1393
404
    
for (unsigned j = 0; 396
j < i;
++j8
) {
1394
9
      if (Styles[i].Language == Styles[j].Language) {
1395
1
        LLVM_DEBUG(llvm::dbgs()
1396
1
                   << "Duplicate languages in the config file on positions "
1397
1
                   << j << " and " << i << "\n");
1398
1
        return make_error_code(ParseError::Error);
1399
1
      }
1400
9
    }
1401
396
  }
1402
  // Look for a suitable configuration starting from the end, so we can
1403
  // find the configuration for the specific language first, and the default
1404
  // configuration (which can only be at slot 0) after it.
1405
386
  FormatStyle::FormatStyleSet StyleSet;
1406
386
  bool LanguageFound = false;
1407
779
  for (int i = Styles.size() - 1; i >= 0; 
--i393
) {
1408
393
    if (Styles[i].Language != FormatStyle::LK_None)
1409
17
      StyleSet.Add(Styles[i]);
1410
393
    if (Styles[i].Language == Language)
1411
11
      LanguageFound = true;
1412
393
  }
1413
386
  if (!LanguageFound) {
1414
375
    if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None)
1415
2
      return make_error_code(ParseError::Unsuitable);
1416
373
    FormatStyle DefaultStyle = Styles[0];
1417
373
    DefaultStyle.Language = Language;
1418
373
    StyleSet.Add(std::move(DefaultStyle));
1419
373
  }
1420
384
  *Style = *StyleSet.Get(Language);
1421
384
  if (Style->InsertTrailingCommas != FormatStyle::TCS_None &&
1422
1
      Style->BinPackArguments) {
1423
    // See comment on FormatStyle::TSC_Wrapped.
1424
1
    return make_error_code(ParseError::BinPackTrailingCommaConflict);
1425
1
  }
1426
383
  return make_error_code(ParseError::Success);
1427
383
}
1428
1429
6
std::string configurationAsText(const FormatStyle &Style) {
1430
6
  std::string Text;
1431
6
  llvm::raw_string_ostream Stream(Text);
1432
6
  llvm::yaml::Output Output(Stream);
1433
  // We use the same mapping method for input and output, so we need a non-const
1434
  // reference here.
1435
6
  FormatStyle NonConstStyle = expandPresets(Style);
1436
6
  Output << NonConstStyle;
1437
6
  return Stream.str();
1438
6
}
1439
1440
llvm::Optional<FormatStyle>
1441
7.07k
FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {
1442
7.07k
  if (!Styles)
1443
6.68k
    return None;
1444
393
  auto It = Styles->find(Language);
1445
393
  if (It == Styles->end())
1446
4
    return None;
1447
389
  FormatStyle Style = It->second;
1448
389
  Style.StyleSet = *this;
1449
389
  return Style;
1450
389
}
1451
1452
390
void FormatStyle::FormatStyleSet::Add(FormatStyle Style) {
1453
390
  assert(Style.Language != LK_None &&
1454
390
         "Cannot add a style for LK_None to a StyleSet");
1455
390
  assert(
1456
390
      !Style.StyleSet.Styles &&
1457
390
      "Cannot add a style associated with an existing StyleSet to a StyleSet");
1458
390
  if (!Styles)
1459
386
    Styles = std::make_shared<MapType>();
1460
390
  (*Styles)[Style.Language] = std::move(Style);
1461
390
}
1462
1463
393
void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); }
1464
1465
llvm::Optional<FormatStyle>
1466
6.69k
FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {
1467
6.69k
  return StyleSet.Get(Language);
1468
6.69k
}
1469
1470
namespace {
1471
1472
class JavaScriptRequoter : public TokenAnalyzer {
1473
public:
1474
  JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)
1475
1.38k
      : TokenAnalyzer(Env, Style) {}
1476
1477
  std::pair<tooling::Replacements, unsigned>
1478
  analyze(TokenAnnotator &Annotator,
1479
          SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1480
1.38k
          FormatTokenLexer &Tokens) override {
1481
1.38k
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
1482
1.38k
    tooling::Replacements Result;
1483
1.38k
    requoteJSStringLiteral(AnnotatedLines, Result);
1484
1.38k
    return {Result, 0};
1485
1.38k
  }
1486
1487
private:
1488
  // Replaces double/single-quoted string literal as appropriate, re-escaping
1489
  // the contents in the process.
1490
  void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
1491
5.21k
                              tooling::Replacements &Result) {
1492
3.83k
    for (AnnotatedLine *Line : Lines) {
1493
3.83k
      requoteJSStringLiteral(Line->Children, Result);
1494
3.83k
      if (!Line->Affected)
1495
21
        continue;
1496
20.5k
      
for (FormatToken *FormatTok = Line->First; 3.81k
FormatTok;
1497
16.7k
           FormatTok = FormatTok->Next) {
1498
16.7k
        StringRef Input = FormatTok->TokenText;
1499
16.7k
        if (FormatTok->Finalized || 
!FormatTok->isStringLiteral()16.6k
||
1500
            // NB: testing for not starting with a double quote to avoid
1501
            // breaking `template strings`.
1502
512
            (Style.JavaScriptQuotes == FormatStyle::JSQS_Single &&
1503
506
             !Input.startswith("\"")) ||
1504
17
            (Style.JavaScriptQuotes == FormatStyle::JSQS_Double &&
1505
6
             !Input.startswith("\'")))
1506
16.6k
          continue;
1507
1508
        // Change start and end quote.
1509
13
        bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single;
1510
13
        SourceLocation Start = FormatTok->Tok.getLocation();
1511
13
        auto Replace = [&](SourceLocation Start, unsigned Length,
1512
35
                           StringRef ReplacementText) {
1513
35
          auto Err = Result.add(tooling::Replacement(
1514
35
              Env.getSourceManager(), Start, Length, ReplacementText));
1515
          // FIXME: handle error. For now, print error message and skip the
1516
          // replacement for release version.
1517
35
          if (Err) {
1518
0
            llvm::errs() << llvm::toString(std::move(Err)) << "\n";
1519
0
            assert(false);
1520
0
          }
1521
35
        };
1522
11
        Replace(Start, 1, IsSingle ? "'" : 
"\""2
);
1523
13
        Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
1524
11
                IsSingle ? "'" : 
"\""2
);
1525
1526
        // Escape internal quotes.
1527
13
        bool Escaped = false;
1528
108
        for (size_t i = 1; i < Input.size() - 1; 
i++95
) {
1529
95
          switch (Input[i]) {
1530
4
          case '\\':
1531
4
            if (!Escaped && i + 1 < Input.size() &&
1532
4
                ((IsSingle && 
Input[i + 1] == '"'3
) ||
1533
3
                 
(2
!IsSingle2
&&
Input[i + 1] == '\''1
))) {
1534
              // Remove this \, it's escaping a " or ' that no longer needs
1535
              // escaping
1536
3
              Replace(Start.getLocWithOffset(i), 1, "");
1537
3
              continue;
1538
3
            }
1539
1
            Escaped = !Escaped;
1540
1
            break;
1541
2
          case '\"':
1542
10
          case '\'':
1543
10
            if (!Escaped && 
IsSingle == (Input[i] == '\'')9
) {
1544
              // Escape the quote.
1545
6
              Replace(Start.getLocWithOffset(i), 0, "\\");
1546
6
            }
1547
10
            Escaped = false;
1548
10
            break;
1549
81
          default:
1550
81
            Escaped = false;
1551
81
            break;
1552
95
          }
1553
95
        }
1554
13
      }
1555
3.81k
    }
1556
5.21k
  }
1557
};
1558
1559
class Formatter : public TokenAnalyzer {
1560
public:
1561
  Formatter(const Environment &Env, const FormatStyle &Style,
1562
            FormattingAttemptStatus *Status)
1563
16.9k
      : TokenAnalyzer(Env, Style), Status(Status) {}
1564
1565
  std::pair<tooling::Replacements, unsigned>
1566
  analyze(TokenAnnotator &Annotator,
1567
          SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1568
17.0k
          FormatTokenLexer &Tokens) override {
1569
17.0k
    tooling::Replacements Result;
1570
17.0k
    deriveLocalStyle(AnnotatedLines);
1571
17.0k
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
1572
79.7k
    for (unsigned i = 0, e = AnnotatedLines.size(); i != e; 
++i62.7k
) {
1573
62.7k
      Annotator.calculateFormattingInformation(*AnnotatedLines[i]);
1574
62.7k
    }
1575
17.0k
    Annotator.setCommentLineLevels(AnnotatedLines);
1576
1577
17.0k
    WhitespaceManager Whitespaces(
1578
17.0k
        Env.getSourceManager(), Style,
1579
17.0k
        Style.DeriveLineEnding
1580
17.0k
            ? inputUsesCRLF(
1581
17.0k
                  Env.getSourceManager().getBufferData(Env.getFileID()),
1582
17.0k
                  Style.UseCRLF)
1583
2
            : Style.UseCRLF);
1584
17.0k
    ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
1585
17.0k
                                  Env.getSourceManager(), Whitespaces, Encoding,
1586
17.0k
                                  BinPackInconclusiveFunctions);
1587
17.0k
    unsigned Penalty =
1588
17.0k
        UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,
1589
17.0k
                               Tokens.getKeywords(), Env.getSourceManager(),
1590
17.0k
                               Status)
1591
17.0k
            .format(AnnotatedLines, /*DryRun=*/false,
1592
17.0k
                    /*AdditionalIndent=*/0,
1593
17.0k
                    /*FixBadIndentation=*/false,
1594
17.0k
                    /*FirstStartColumn=*/Env.getFirstStartColumn(),
1595
17.0k
                    /*NextStartColumn=*/Env.getNextStartColumn(),
1596
17.0k
                    /*LastStartColumn=*/Env.getLastStartColumn());
1597
17.0k
    for (const auto &R : Whitespaces.generateReplacements())
1598
21.8k
      if (Result.add(R))
1599
0
        return std::make_pair(Result, 0);
1600
17.0k
    return std::make_pair(Result, Penalty);
1601
17.0k
  }
1602
1603
private:
1604
17.0k
  static bool inputUsesCRLF(StringRef Text, bool DefaultToCRLF) {
1605
17.0k
    size_t LF = Text.count('\n');
1606
17.0k
    size_t CR = Text.count('\r') * 2;
1607
10.6k
    return LF == CR ? DefaultToCRLF : 
CR > LF6.36k
;
1608
17.0k
  }
1609
1610
  bool
1611
12.4k
  hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) {
1612
9.17k
    for (const AnnotatedLine *Line : Lines) {
1613
9.17k
      if (hasCpp03IncompatibleFormat(Line->Children))
1614
1
        return true;
1615
46.1k
      
for (FormatToken *Tok = Line->First->Next; 9.17k
Tok;
Tok = Tok->Next36.9k
) {
1616
37.0k
        if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) {
1617
19.3k
          if (Tok->is(tok::coloncolon) && 
Tok->Previous->is(TT_TemplateOpener)107
)
1618
7
            return true;
1619
19.3k
          if (Tok->is(TT_TemplateCloser) &&
1620
384
              Tok->Previous->is(TT_TemplateCloser))
1621
30
            return true;
1622
19.3k
        }
1623
37.0k
      }
1624
9.17k
    }
1625
12.4k
    return false;
1626
12.4k
  }
1627
1628
12.3k
  int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) {
1629
12.3k
    int AlignmentDiff = 0;
1630
9.09k
    for (const AnnotatedLine *Line : Lines) {
1631
9.09k
      AlignmentDiff += countVariableAlignments(Line->Children);
1632
45.6k
      for (FormatToken *Tok = Line->First; Tok && Tok->Next; 
Tok = Tok->Next36.6k
) {
1633
36.6k
        if (!Tok->is(TT_PointerOrReference))
1634
36.3k
          continue;
1635
293
        bool SpaceBefore =
1636
293
            Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd();
1637
293
        bool SpaceAfter = Tok->Next->WhitespaceRange.getBegin() !=
1638
293
                          Tok->Next->WhitespaceRange.getEnd();
1639
293
        if (SpaceBefore && 
!SpaceAfter77
)
1640
63
          ++AlignmentDiff;
1641
293
        if (!SpaceBefore && 
SpaceAfter216
)
1642
99
          --AlignmentDiff;
1643
293
      }
1644
9.09k
    }
1645
12.3k
    return AlignmentDiff;
1646
12.3k
  }
1647
1648
  void
1649
17.0k
  deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
1650
17.0k
    bool HasBinPackedFunction = false;
1651
17.0k
    bool HasOnePerLineFunction = false;
1652
79.7k
    for (unsigned i = 0, e = AnnotatedLines.size(); i != e; 
++i62.7k
) {
1653
62.7k
      if (!AnnotatedLines[i]->First->Next)
1654
26.0k
        continue;
1655
36.6k
      FormatToken *Tok = AnnotatedLines[i]->First->Next;
1656
213k
      while (Tok->Next) {
1657
176k
        if (Tok->is(PPK_BinPacked))
1658
105
          HasBinPackedFunction = true;
1659
176k
        if (Tok->is(PPK_OnePerLine))
1660
488
          HasOnePerLineFunction = true;
1661
1662
176k
        Tok = Tok->Next;
1663
176k
      }
1664
36.6k
    }
1665
17.0k
    if (Style.DerivePointerAlignment)
1666
3.27k
      Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0
1667
3.23k
                                   ? FormatStyle::PAS_Left
1668
36
                                   : FormatStyle::PAS_Right;
1669
17.0k
    if (Style.Standard == FormatStyle::LS_Auto)
1670
3.31k
      Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
1671
37
                           ? FormatStyle::LS_Latest
1672
3.27k
                           : FormatStyle::LS_Cpp03;
1673
17.0k
    BinPackInconclusiveFunctions =
1674
17.0k
        HasBinPackedFunction || 
!HasOnePerLineFunction16.9k
;
1675
17.0k
  }
1676
1677
  bool BinPackInconclusiveFunctions;
1678
  FormattingAttemptStatus *Status;
1679
};
1680
1681
/// TrailingCommaInserter inserts trailing commas into container literals.
1682
/// E.g.:
1683
///     const x = [
1684
///       1,
1685
///     ];
1686
/// TrailingCommaInserter runs after formatting. To avoid causing a required
1687
/// reformatting (and thus reflow), it never inserts a comma that'd exceed the
1688
/// ColumnLimit.
1689
///
1690
/// Because trailing commas disable binpacking of arrays, TrailingCommaInserter
1691
/// is conceptually incompatible with bin packing.
1692
class TrailingCommaInserter : public TokenAnalyzer {
1693
public:
1694
  TrailingCommaInserter(const Environment &Env, const FormatStyle &Style)
1695
12
      : TokenAnalyzer(Env, Style) {}
1696
1697
  std::pair<tooling::Replacements, unsigned>
1698
  analyze(TokenAnnotator &Annotator,
1699
          SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1700
12
          FormatTokenLexer &Tokens) override {
1701
12
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
1702
12
    tooling::Replacements Result;
1703
12
    insertTrailingCommas(AnnotatedLines, Result);
1704
12
    return {Result, 0};
1705
12
  }
1706
1707
private:
1708
  /// Inserts trailing commas in [] and {} initializers if they wrap over
1709
  /// multiple lines.
1710
  void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,
1711
36
                            tooling::Replacements &Result) {
1712
24
    for (AnnotatedLine *Line : Lines) {
1713
24
      insertTrailingCommas(Line->Children, Result);
1714
24
      if (!Line->Affected)
1715
0
        continue;
1716
142
      
for (FormatToken *FormatTok = Line->First; 24
FormatTok;
1717
118
           FormatTok = FormatTok->Next) {
1718
118
        if (FormatTok->NewlinesBefore == 0)
1719
92
          continue;
1720
26
        FormatToken *Matching = FormatTok->MatchingParen;
1721
26
        if (!Matching || 
!FormatTok->getPreviousNonComment()12
)
1722
14
          continue;
1723
12
        if (!(FormatTok->is(tok::r_square) &&
1724
6
              Matching->is(TT_ArrayInitializerLSquare)) &&
1725
6
            !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral)))
1726
0
          continue;
1727
12
        FormatToken *Prev = FormatTok->getPreviousNonComment();
1728
12
        if (Prev->is(tok::comma) || 
Prev->is(tok::semi)8
)
1729
4
          continue;
1730
        // getEndLoc is not reliably set during re-lexing, use text length
1731
        // instead.
1732
8
        SourceLocation Start =
1733
8
            Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size());
1734
        // If inserting a comma would push the code over the column limit, skip
1735
        // this location - it'd introduce an unstable formatting due to the
1736
        // required reflow.
1737
8
        unsigned ColumnNumber =
1738
8
            Env.getSourceManager().getSpellingColumnNumber(Start);
1739
8
        if (ColumnNumber > Style.ColumnLimit)
1740
4
          continue;
1741
        // Comma insertions cannot conflict with each other, and this pass has a
1742
        // clean set of Replacements, so the operation below cannot fail.
1743
4
        cantFail(Result.add(
1744
4
            tooling::Replacement(Env.getSourceManager(), Start, 0, ",")));
1745
4
      }
1746
24
    }
1747
36
  }
1748
};
1749
1750
// This class clean up the erroneous/redundant code around the given ranges in
1751
// file.
1752
class Cleaner : public TokenAnalyzer {
1753
public:
1754
  Cleaner(const Environment &Env, const FormatStyle &Style)
1755
      : TokenAnalyzer(Env, Style),
1756
130
        DeletedTokens(FormatTokenLess(Env.getSourceManager())) {}
1757
1758
  // FIXME: eliminate unused parameters.
1759
  std::pair<tooling::Replacements, unsigned>
1760
  analyze(TokenAnnotator &Annotator,
1761
          SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1762
131
          FormatTokenLexer &Tokens) override {
1763
    // FIXME: in the current implementation the granularity of affected range
1764
    // is an annotated line. However, this is not sufficient. Furthermore,
1765
    // redundant code introduced by replacements does not necessarily
1766
    // intercept with ranges of replacements that result in the redundancy.
1767
    // To determine if some redundant code is actually introduced by
1768
    // replacements(e.g. deletions), we need to come up with a more
1769
    // sophisticated way of computing affected ranges.
1770
131
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
1771
1772
131
    checkEmptyNamespace(AnnotatedLines);
1773
1774
131
    for (auto *Line : AnnotatedLines)
1775
890
      cleanupLine(Line);
1776
1777
131
    return {generateFixes(), 0};
1778
131
  }
1779
1780
private:
1781
891
  void cleanupLine(AnnotatedLine *Line) {
1782
1
    for (auto *Child : Line->Children) {
1783
1
      cleanupLine(Child);
1784
1
    }
1785
1786
891
    if (Line->Affected) {
1787
458
      cleanupRight(Line->First, tok::comma, tok::comma);
1788
458
      cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
1789
458
      cleanupRight(Line->First, tok::l_paren, tok::comma);
1790
458
      cleanupLeft(Line->First, tok::comma, tok::r_paren);
1791
458
      cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
1792
458
      cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
1793
458
      cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
1794
458
    }
1795
891
  }
1796
1797
5
  bool containsOnlyComments(const AnnotatedLine &Line) {
1798
7
    for (FormatToken *Tok = Line.First; Tok != nullptr; 
Tok = Tok->Next2
) {
1799
5
      if (Tok->isNot(tok::comment))
1800
3
        return false;
1801
5
    }
1802
2
    return true;
1803
5
  }
1804
1805
  // Iterate through all lines and remove any empty (nested) namespaces.
1806
131
  void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
1807
131
    std::set<unsigned> DeletedLines;
1808
976
    for (unsigned i = 0, e = AnnotatedLines.size(); i != e; 
++i845
) {
1809
845
      auto &Line = *AnnotatedLines[i];
1810
845
      if (Line.startsWithNamespace()) {
1811
19
        checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
1812
19
      }
1813
845
    }
1814
1815
49
    for (auto Line : DeletedLines) {
1816
49
      FormatToken *Tok = AnnotatedLines[Line]->First;
1817
150
      while (Tok) {
1818
101
        deleteToken(Tok);
1819
101
        Tok = Tok->Next;
1820
101
      }
1821
49
    }
1822
131
  }
1823
1824
  // The function checks if the namespace, which starts from \p CurrentLine, and
1825
  // its nested namespaces are empty and delete them if they are empty. It also
1826
  // sets \p NewLine to the last line checked.
1827
  // Returns true if the current namespace is empty.
1828
  bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1829
                           unsigned CurrentLine, unsigned &NewLine,
1830
36
                           std::set<unsigned> &DeletedLines) {
1831
36
    unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
1832
36
    if (Style.BraceWrapping.AfterNamespace) {
1833
      // If the left brace is in a new line, we should consume it first so that
1834
      // it does not make the namespace non-empty.
1835
      // FIXME: error handling if there is no left brace.
1836
3
      if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
1837
0
        NewLine = CurrentLine;
1838
0
        return false;
1839
0
      }
1840
33
    } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
1841
3
      return false;
1842
3
    }
1843
45
    
while (33
++CurrentLine < End) {
1844
45
      if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
1845
23
        break;
1846
1847
22
      if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
1848
17
        if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
1849
17
                                 DeletedLines))
1850
7
          return false;
1851
10
        CurrentLine = NewLine;
1852
10
        continue;
1853
10
      }
1854
1855
5
      if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
1856
2
        continue;
1857
1858
      // If there is anything other than comments or nested namespaces in the
1859
      // current namespace, the namespace cannot be empty.
1860
3
      NewLine = CurrentLine;
1861
3
      return false;
1862
3
    }
1863
1864
23
    NewLine = CurrentLine;
1865
23
    if (CurrentLine >= End)
1866
0
      return false;
1867
1868
    // Check if the empty namespace is actually affected by changed ranges.
1869
23
    if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
1870
23
            AnnotatedLines[InitLine]->First->Tok.getLocation(),
1871
23
            AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc())))
1872
1
      return false;
1873
1874
90
    
for (unsigned i = InitLine; 22
i <= CurrentLine;
++i68
) {
1875
68
      DeletedLines.insert(i);
1876
68
    }
1877
1878
22
    return true;
1879
22
  }
1880
1881
  // Checks pairs {start, start->next},..., {end->previous, end} and deletes one
1882
  // of the token in the pair if the left token has \p LK token kind and the
1883
  // right token has \p RK token kind. If \p DeleteLeft is true, the left token
1884
  // is deleted on match; otherwise, the right token is deleted.
1885
  template <typename LeftKind, typename RightKind>
1886
  void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
1887
3.20k
                   bool DeleteLeft) {
1888
10.6k
    auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {
1889
11.3k
      for (auto *Res = Tok.Next; Res; 
Res = Res->Next702
)
1890
8.09k
        if (!Res->is(tok::comment) &&
1891
7.89k
            DeletedTokens.find(Res) == DeletedTokens.end())
1892
7.39k
          return Res;
1893
3.20k
      return nullptr;
1894
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
1888
4.58k
    auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {
1889
4.86k
      for (auto *Res = Tok.Next; Res; 
Res = Res->Next279
)
1890
3.48k
        if (!Res->is(tok::comment) &&
1891
3.40k
            DeletedTokens.find(Res) == DeletedTokens.end())
1892
3.20k
          return Res;
1893
1.37k
      return nullptr;
1894
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
1888
6.01k
    auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {
1889
6.44k
      for (auto *Res = Tok.Next; Res; 
Res = Res->Next423
)
1890
4.60k
        if (!Res->is(tok::comment) &&
1891
4.49k
            DeletedTokens.find(Res) == DeletedTokens.end())
1892
4.18k
          return Res;
1893
1.83k
      return nullptr;
1894
6.01k
    };
1895
10.6k
    for (auto *Left = Start; Left;) {
1896
10.6k
      auto *Right = NextNotDeleted(*Left);
1897
10.6k
      if (!Right)
1898
3.20k
        break;
1899
7.39k
      if (Left->is(LK) && 
Right->is(RK)315
) {
1900
42
        deleteToken(DeleteLeft ? 
Left27
: Right);
1901
110
        for (auto *Tok = Left->Next; Tok && Tok != Right; 
Tok = Tok->Next41
)
1902
41
          deleteToken(Tok);
1903
        // If the right token is deleted, we should keep the left token
1904
        // unchanged and pair it with the new right token.
1905
69
        if (!DeleteLeft)
1906
42
          continue;
1907
7.35k
      }
1908
7.35k
      Left = Right;
1909
7.35k
    }
1910
3.20k
  }
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
1887
1.37k
                   bool DeleteLeft) {
1888
1.37k
    auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {
1889
1.37k
      for (auto *Res = Tok.Next; Res; Res = Res->Next)
1890
1.37k
        if (!Res->is(tok::comment) &&
1891
1.37k
            DeletedTokens.find(Res) == DeletedTokens.end())
1892
1.37k
          return Res;
1893
1.37k
      return nullptr;
1894
1.37k
    };
1895
4.58k
    for (auto *Left = Start; Left;) {
1896
4.58k
      auto *Right = NextNotDeleted(*Left);
1897
4.58k
      if (!Right)
1898
1.37k
        break;
1899
3.20k
      if (Left->is(LK) && 
Right->is(RK)228
) {
1900
30
        deleteToken(DeleteLeft ? 
Left6
: Right);
1901
49
        for (auto *Tok = Left->Next; Tok && Tok != Right; 
Tok = Tok->Next13
)
1902
13
          deleteToken(Tok);
1903
        // If the right token is deleted, we should keep the left token
1904
        // unchanged and pair it with the new right token.
1905
36
        if (!DeleteLeft)
1906
30
          continue;
1907
3.17k
      }
1908
3.17k
      Left = Right;
1909
3.17k
    }
1910
1.37k
  }
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
1887
1.83k
                   bool DeleteLeft) {
1888
1.83k
    auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {
1889
1.83k
      for (auto *Res = Tok.Next; Res; Res = Res->Next)
1890
1.83k
        if (!Res->is(tok::comment) &&
1891
1.83k
            DeletedTokens.find(Res) == DeletedTokens.end())
1892
1.83k
          return Res;
1893
1.83k
      return nullptr;
1894
1.83k
    };
1895
6.01k
    for (auto *Left = Start; Left;) {
1896
6.01k
      auto *Right = NextNotDeleted(*Left);
1897
6.01k
      if (!Right)
1898
1.83k
        break;
1899
4.18k
      if (Left->is(LK) && 
Right->is(RK)87
) {
1900
21
        deleteToken(DeleteLeft ? Left : 
Right12
);
1901
61
        for (auto *Tok = Left->Next; Tok && Tok != Right; 
Tok = Tok->Next28
)
1902
28
          deleteToken(Tok);
1903
        // If the right token is deleted, we should keep the left token
1904
        // unchanged and pair it with the new right token.
1905
33
        if (!DeleteLeft)
1906
12
          continue;
1907
4.17k
      }
1908
4.17k
      Left = Right;
1909
4.17k
    }
1910
1.83k
  }
1911
1912
  template <typename LeftKind, typename RightKind>
1913
1.83k
  void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
1914
1.83k
    cleanupPair(Start, LK, RK, /*DeleteLeft=*/true);
1915
1.83k
  }
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
1913
458
  void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
1914
458
    cleanupPair(Start, LK, RK, /*DeleteLeft=*/true);
1915
458
  }
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
1913
1.37k
  void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
1914
1.37k
    cleanupPair(Start, LK, RK, /*DeleteLeft=*/true);
1915
1.37k
  }
1916
1917
  template <typename LeftKind, typename RightKind>
1918
1.37k
  void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
1919
1.37k
    cleanupPair(Start, LK, RK, /*DeleteLeft=*/false);
1920
1.37k
  }
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
1918
916
  void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
1919
916
    cleanupPair(Start, LK, RK, /*DeleteLeft=*/false);
1920
916
  }
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
1918
458
  void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
1919
458
    cleanupPair(Start, LK, RK, /*DeleteLeft=*/false);
1920
458
  }
1921
1922
  // Delete the given token.
1923
211
  inline void deleteToken(FormatToken *Tok) {
1924
211
    if (Tok)
1925
211
      DeletedTokens.insert(Tok);
1926
211
  }
1927
1928
131
  tooling::Replacements generateFixes() {
1929
131
    tooling::Replacements Fixes;
1930
131
    std::vector<FormatToken *> Tokens;
1931
131
    std::copy(DeletedTokens.begin(), DeletedTokens.end(),
1932
131
              std::back_inserter(Tokens));
1933
1934
    // Merge multiple continuous token deletions into one big deletion so that
1935
    // the number of replacements can be reduced. This makes computing affected
1936
    // ranges more efficient when we run reformat on the changed code.
1937
131
    unsigned Idx = 0;
1938
224
    while (Idx < Tokens.size()) {
1939
93
      unsigned St = Idx, End = Idx;
1940
178
      while ((End + 1) < Tokens.size() &&
1941
145
             Tokens[End]->Next == Tokens[End + 1]) {
1942
85
        End++;
1943
85
      }
1944
93
      auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
1945
93
                                              Tokens[End]->Tok.getEndLoc());
1946
93
      auto Err =
1947
93
          Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, ""));
1948
      // FIXME: better error handling. for now just print error message and skip
1949
      // for the release version.
1950
93
      if (Err) {
1951
0
        llvm::errs() << llvm::toString(std::move(Err)) << "\n";
1952
0
        assert(false && "Fixes must not conflict!");
1953
0
      }
1954
93
      Idx = End + 1;
1955
93
    }
1956
1957
131
    return Fixes;
1958
131
  }
1959
1960
  // Class for less-than inequality comparason for the set `RedundantTokens`.
1961
  // We store tokens in the order they appear in the translation unit so that
1962
  // we do not need to sort them in `generateFixes()`.
1963
  struct FormatTokenLess {
1964
130
    FormatTokenLess(const SourceManager &SM) : SM(SM) {}
1965
1966
8.41k
    bool operator()(const FormatToken *LHS, const FormatToken *RHS) const {
1967
8.41k
      return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
1968
8.41k
                                          RHS->Tok.getLocation());
1969
8.41k
    }
1970
    const SourceManager &SM;
1971
  };
1972
1973
  // Tokens to be deleted.
1974
  std::set<FormatToken *, FormatTokenLess> DeletedTokens;
1975
};
1976
1977
class ObjCHeaderStyleGuesser : public TokenAnalyzer {
1978
public:
1979
  ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style)
1980
312
      : TokenAnalyzer(Env, Style), IsObjC(false) {}
1981
1982
  std::pair<tooling::Replacements, unsigned>
1983
  analyze(TokenAnnotator &Annotator,
1984
          SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1985
312
          FormatTokenLexer &Tokens) override {
1986
312
    assert(Style.Language == FormatStyle::LK_Cpp);
1987
312
    IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines,
1988
312
                         Tokens.getKeywords());
1989
312
    tooling::Replacements Result;
1990
312
    return {Result, 0};
1991
312
  }
1992
1993
312
  bool isObjC() { return IsObjC; }
1994
1995
private:
1996
  static bool
1997
  guessIsObjC(const SourceManager &SourceManager,
1998
              const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1999
1.39k
              const AdditionalKeywords &Keywords) {
2000
    // Keep this array sorted, since we are binary searching over it.
2001
1.39k
    static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
2002
1.39k
        "CGFloat",
2003
1.39k
        "CGPoint",
2004
1.39k
        "CGPointMake",
2005
1.39k
        "CGPointZero",
2006
1.39k
        "CGRect",
2007
1.39k
        "CGRectEdge",
2008
1.39k
        "CGRectInfinite",
2009
1.39k
        "CGRectMake",
2010
1.39k
        "CGRectNull",
2011
1.39k
        "CGRectZero",
2012
1.39k
        "CGSize",
2013
1.39k
        "CGSizeMake",
2014
1.39k
        "CGVector",
2015
1.39k
        "CGVectorMake",
2016
1.39k
        "NSAffineTransform",
2017
1.39k
        "NSArray",
2018
1.39k
        "NSAttributedString",
2019
1.39k
        "NSBlockOperation",
2020
1.39k
        "NSBundle",
2021
1.39k
        "NSCache",
2022
1.39k
        "NSCalendar",
2023
1.39k
        "NSCharacterSet",
2024
1.39k
        "NSCountedSet",
2025
1.39k
        "NSData",
2026
1.39k
        "NSDataDetector",
2027
1.39k
        "NSDecimal",
2028
1.39k
        "NSDecimalNumber",
2029
1.39k
        "NSDictionary",
2030
1.39k
        "NSEdgeInsets",
2031
1.39k
        "NSHashTable",
2032
1.39k
        "NSIndexPath",
2033
1.39k
        "NSIndexSet",
2034
1.39k
        "NSInteger",
2035
1.39k
        "NSInvocationOperation",
2036
1.39k
        "NSLocale",
2037
1.39k
        "NSMapTable",
2038
1.39k
        "NSMutableArray",
2039
1.39k
        "NSMutableAttributedString",
2040
1.39k
        "NSMutableCharacterSet",
2041
1.39k
        "NSMutableData",
2042
1.39k
        "NSMutableDictionary",
2043
1.39k
        "NSMutableIndexSet",
2044
1.39k
        "NSMutableOrderedSet",
2045
1.39k
        "NSMutableSet",
2046
1.39k
        "NSMutableString",
2047
1.39k
        "NSNumber",
2048
1.39k
        "NSNumberFormatter",
2049
1.39k
        "NSObject",
2050
1.39k
        "NSOperation",
2051
1.39k
        "NSOperationQueue",
2052
1.39k
        "NSOperationQueuePriority",
2053
1.39k
        "NSOrderedSet",
2054
1.39k
        "NSPoint",
2055
1.39k
        "NSPointerArray",
2056
1.39k
        "NSQualityOfService",
2057
1.39k
        "NSRange",
2058
1.39k
        "NSRect",
2059
1.39k
        "NSRegularExpression",
2060
1.39k
        "NSSet",
2061
1.39k
        "NSSize",
2062
1.39k
        "NSString",
2063
1.39k
        "NSTimeZone",
2064
1.39k
        "NSUInteger",
2065
1.39k
        "NSURL",
2066
1.39k
        "NSURLComponents",
2067
1.39k
        "NSURLQueryItem",
2068
1.39k
        "NSUUID",
2069
1.39k
        "NSValue",
2070
1.39k
        "UIImage",
2071
1.39k
        "UIView",
2072
1.39k
    };
2073
2074
493
    for (auto Line : AnnotatedLines) {
2075
493
      if (Line->First && (Line->First->TokenText.startswith("#") ||
2076
479
                          Line->First->TokenText == "__pragma" ||
2077
478
                          Line->First->TokenText == "_Pragma"))
2078
16
        continue;
2079
1.55k
      
for (const FormatToken *FormatTok = Line->First; 477
FormatTok;
2080
1.11k
           
FormatTok = FormatTok->Next1.08k
) {
2081
1.11k
        if ((FormatTok->Previous && 
FormatTok->Previous->is(tok::at)640
&&
2082
5
             (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
2083
2
              FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
2084
2
                                 tok::l_brace))) ||
2085
1.11k
            (FormatTok->Tok.isAnyIdentifier() &&
2086
207
             std::binary_search(std::begin(FoundationIdentifiers),
2087
207
                                std::end(FoundationIdentifiers),
2088
207
                                FormatTok->TokenText)) ||
2089
1.10k
            FormatTok->is(TT_ObjCStringLiteral) ||
2090
1.10k
            FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,
2091
1.10k
                               Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,
2092
1.10k
                               TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,
2093
1.10k
                               TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,
2094
34
                               TT_ObjCProperty)) {
2095
34
          LLVM_DEBUG(llvm::dbgs()
2096
34
                     << "Detected ObjC at location "
2097
34
                     << FormatTok->Tok.getLocation().printToString(
2098
34
                            SourceManager)
2099
34
                     << " token: " << FormatTok->TokenText << " token type: "
2100
34
                     << getTokenTypeName(FormatTok->getType()) << "\n");
2101
34
          return true;
2102
34
        }
2103
1.08k
        if (guessIsObjC(SourceManager, Line->Children, Keywords))
2104
3
          return true;
2105
1.08k
      }
2106
477
    }
2107
1.35k
    return false;
2108
1.39k
  }
2109
2110
  bool IsObjC;
2111
};
2112
2113
struct IncludeDirective {
2114
  StringRef Filename;
2115
  StringRef Text;
2116
  unsigned Offset;
2117
  int Category;
2118
  int Priority;
2119
};
2120
2121
struct JavaImportDirective {
2122
  StringRef Identifier;
2123
  StringRef Text;
2124
  unsigned Offset;
2125
  std::vector<StringRef> AssociatedCommentLines;
2126
  bool IsStatic;
2127
};
2128
2129
} // end anonymous namespace
2130
2131
// Determines whether 'Ranges' intersects with ('Start', 'End').
2132
static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start,
2133
383
                         unsigned End) {
2134
506
  for (auto Range : Ranges) {
2135
506
    if (Range.getOffset() < End &&
2136
133
        Range.getOffset() + Range.getLength() > Start)
2137
129
      return true;
2138
506
  }
2139
254
  return false;
2140
383
}
2141
2142
// Returns a pair (Index, OffsetToEOL) describing the position of the cursor
2143
// before sorting/deduplicating. Index is the index of the include under the
2144
// cursor in the original set of includes. If this include has duplicates, it is
2145
// the index of the first of the duplicates as the others are going to be
2146
// removed. OffsetToEOL describes the cursor's position relative to the end of
2147
// its current line.
2148
// If `Cursor` is not on any #include, `Index` will be UINT_MAX.
2149
static std::pair<unsigned, unsigned>
2150
FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes,
2151
17
                const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) {
2152
17
  unsigned CursorIndex = UINT_MAX;
2153
17
  unsigned OffsetToEOL = 0;
2154
46
  for (int i = 0, e = Includes.size(); i != e; 
++i29
) {
2155
43
    unsigned Start = Includes[Indices[i]].Offset;
2156
43
    unsigned End = Start + Includes[Indices[i]].Text.size();
2157
43
    if (!(Cursor >= Start && 
Cursor < End29
))
2158
29
      continue;
2159
14
    CursorIndex = Indices[i];
2160
14
    OffsetToEOL = End - Cursor;
2161
    // Put the cursor on the only remaining #include among the duplicate
2162
    // #includes.
2163
25
    while (--i >= 0 && 
Includes[CursorIndex].Text == Includes[Indices[i]].Text17
)
2164
11
      CursorIndex = i;
2165
14
    break;
2166
14
  }
2167
17
  return std::make_pair(CursorIndex, OffsetToEOL);
2168
17
}
2169
2170
// Replace all "\r\n" with "\n".
2171
234
std::string replaceCRLF(const std::string &Code) {
2172
234
  std::string NewCode;
2173
234
  size_t Pos = 0, LastPos = 0;
2174
2175
270
  do {
2176
270
    Pos = Code.find("\r\n", LastPos);
2177
270
    if (Pos == LastPos) {
2178
2
      LastPos++;
2179
2
      continue;
2180
2
    }
2181
268
    if (Pos == std::string::npos) {
2182
234
      NewCode += Code.substr(LastPos);
2183
234
      break;
2184
234
    }
2185
34
    NewCode += Code.substr(LastPos, Pos - LastPos) + "\n";
2186
34
    LastPos = Pos + 2;
2187
36
  } while (Pos != std::string::npos);
2188
2189
234
  return NewCode;
2190
234
}
2191
2192
// Sorts and deduplicate a block of includes given by 'Includes' alphabetically
2193
// adding the necessary replacement to 'Replaces'. 'Includes' must be in strict
2194
// source order.
2195
// #include directives with the same text will be deduplicated, and only the
2196
// first #include in the duplicate #includes remains. If the `Cursor` is
2197
// provided and put on a deleted #include, it will be moved to the remaining
2198
// #include in the duplicate #includes.
2199
static void sortCppIncludes(const FormatStyle &Style,
2200
                            const SmallVectorImpl<IncludeDirective> &Includes,
2201
                            ArrayRef<tooling::Range> Ranges, StringRef FileName,
2202
                            StringRef Code, tooling::Replacements &Replaces,
2203
361
                            unsigned *Cursor) {
2204
361
  tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
2205
361
  unsigned IncludesBeginOffset = Includes.front().Offset;
2206
361
  unsigned IncludesEndOffset =
2207
361
      Includes.back().Offset + Includes.back().Text.size();
2208
361
  unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
2209
361
  if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
2210
253
    return;
2211
108
  SmallVector<unsigned, 16> Indices;
2212
505
  for (unsigned i = 0, e = Includes.size(); i != e; 
++i397
) {
2213
397
    Indices.push_back(i);
2214
397
  }
2215
2216
108
  if (Style.IncludeStyle.IncludeSortAlphabetically) {
2217
36
    llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
2218
36
      const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
2219
36
      const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
2220
36
      return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
2221
36
                      Includes[LHSI].Filename) <
2222
36
             std::tie(Includes[RHSI].Priority, RHSFilenameLower,
2223
36
                      Includes[RHSI].Filename);
2224
36
    });
2225
106
  } else {
2226
424
    llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
2227
424
      return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
2228
424
             std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
2229
424
    });
2230
106
  }
2231
2232
  // The index of the include on which the cursor will be put after
2233
  // sorting/deduplicating.
2234
108
  unsigned CursorIndex;
2235
  // The offset from cursor to the end of line.
2236
108
  unsigned CursorToEOLOffset;
2237
108
  if (Cursor)
2238
17
    std::tie(CursorIndex, CursorToEOLOffset) =
2239
17
        FindCursorIndex(Includes, Indices, *Cursor);
2240
2241
  // Deduplicate #includes.
2242
108
  Indices.erase(std::unique(Indices.begin(), Indices.end(),
2243
289
                            [&](unsigned LHSI, unsigned RHSI) {
2244
289
                              return Includes[LHSI].Text.trim() ==
2245
289
                                     Includes[RHSI].Text.trim();
2246
289
                            }),
2247
108
                Indices.end());
2248
2249
108
  int CurrentCategory = Includes.front().Category;
2250
2251
  // If the #includes are out of order, we generate a single replacement fixing
2252
  // the entire block. Otherwise, no replacement is generated.
2253
  // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not
2254
  // enough as additional newlines might be added or removed across #include
2255
  // blocks. This we handle below by generating the updated #imclude blocks and
2256
  // comparing it to the original.
2257
108
  if (Indices.size() == Includes.size() && 
llvm::is_sorted(Indices)89
&&
2258
18
      Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve)
2259
12
    return;
2260
2261
96
  std::string result;
2262
321
  for (unsigned Index : Indices) {
2263
321
    if (!result.empty()) {
2264
225
      result += "\n";
2265
225
      if (Style.IncludeStyle.IncludeBlocks ==
2266
225
              tooling::IncludeStyle::IBS_Regroup &&
2267
70
          CurrentCategory != Includes[Index].Category)
2268
27
        result += "\n";
2269
225
    }
2270
321
    result += Includes[Index].Text;
2271
321
    if (Cursor && 
CursorIndex == Index47
)
2272
14
      *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
2273
321
    CurrentCategory = Includes[Index].Category;
2274
321
  }
2275
2276
  // If the #includes are out of order, we generate a single replacement fixing
2277
  // the entire range of blocks. Otherwise, no replacement is generated.
2278
96
  if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
2279
96
                                 IncludesBeginOffset, IncludesBlockSize))))
2280
6
    return;
2281
2282
90
  auto Err = Replaces.add(tooling::Replacement(
2283
90
      FileName, Includes.front().Offset, IncludesBlockSize, result));
2284
  // FIXME: better error handling. For now, just skip the replacement for the
2285
  // release version.
2286
90
  if (Err) {
2287
0
    llvm::errs() << llvm::toString(std::move(Err)) << "\n";
2288
0
    assert(false);
2289
0
  }
2290
90
}
2291
2292
namespace {
2293
2294
const char CppIncludeRegexPattern[] =
2295
    R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))";
2296
2297
} // anonymous namespace
2298
2299
tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
2300
                                      ArrayRef<tooling::Range> Ranges,
2301
                                      StringRef FileName,
2302
                                      tooling::Replacements &Replaces,
2303
632
                                      unsigned *Cursor) {
2304
632
  unsigned Prev = llvm::StringSwitch<size_t>(Code)
2305
632
                      .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM
2306
632
                      .Default(0);
2307
632
  unsigned SearchFrom = 0;
2308
632
  llvm::Regex IncludeRegex(CppIncludeRegexPattern);
2309
632
  SmallVector<StringRef, 4> Matches;
2310
632
  SmallVector<IncludeDirective, 16> IncludesInBlock;
2311
2312
  // In compiled files, consider the first #include to be the main #include of
2313
  // the file if it is not a system #include. This ensures that the header
2314
  // doesn't have hidden dependencies
2315
  // (http://llvm.org/docs/CodingStandards.html#include-style).
2316
  //
2317
  // FIXME: Do some sanity checking, e.g. edit distance of the base name, to fix
2318
  // cases where the first #include is unlikely to be the main header.
2319
632
  tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
2320
632
  bool FirstIncludeBlock = true;
2321
632
  bool MainIncludeFound = false;
2322
632
  bool FormattingOff = false;
2323
2324
8.04k
  for (;;) {
2325
8.04k
    auto Pos = Code.find('\n', SearchFrom);
2326
8.04k
    StringRef Line =
2327
7.53k
        Code.substr(Prev, (Pos != StringRef::npos ? Pos : 
Code.size()510
) - Prev);
2328
2329
8.04k
    StringRef Trimmed = Line.trim();
2330
8.04k
    if (Trimmed == "// clang-format off" || 
Trimmed == "/* clang-format off */"8.03k
)
2331
3
      FormattingOff = true;
2332
8.03k
    else if (Trimmed == "// clang-format on" ||
2333
8.03k
             Trimmed == "/* clang-format on */")
2334
3
      FormattingOff = false;
2335
2336
8.04k
    const bool EmptyLineSkipped =
2337
8.04k
        Trimmed.empty() &&
2338
758
        (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge ||
2339
746
         Style.IncludeStyle.IncludeBlocks ==
2340
746
             tooling::IncludeStyle::IBS_Regroup);
2341
2342
8.04k
    bool MergeWithNextLine = Trimmed.endswith("\\");
2343
8.04k
    if (!FormattingOff && 
!MergeWithNextLine8.03k
) {
2344
8.02k
      if (IncludeRegex.match(Line, &Matches)) {
2345
650
        StringRef IncludeName = Matches[2];
2346
650
        int Category = Categories.getIncludePriority(
2347
650
            IncludeName,
2348
650
            /*CheckMainHeader=*/!MainIncludeFound && 
FirstIncludeBlock620
);
2349
650
        int Priority = Categories.getSortIncludePriority(
2350
650
            IncludeName, !MainIncludeFound && 
FirstIncludeBlock620
);
2351
650
        if (Category == 0)
2352
23
          MainIncludeFound = true;
2353
650
        IncludesInBlock.push_back(
2354
650
            {IncludeName, Line, Prev, Category, Priority});
2355
7.37k
      } else if (!IncludesInBlock.empty() && 
!EmptyLineSkipped300
) {
2356
279
        sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code,
2357
279
                        Replaces, Cursor);
2358
279
        IncludesInBlock.clear();
2359
279
        if (Trimmed.startswith("#pragma hdrstop")) // Precompiled headers.
2360
2
          FirstIncludeBlock = true;
2361
277
        else
2362
277
          FirstIncludeBlock = false;
2363
279
      }
2364
8.02k
    }
2365
8.04k
    if (Pos == StringRef::npos || 
Pos + 1 == Code.size()7.53k
)
2366
632
      break;
2367
2368
7.40k
    if (!MergeWithNextLine)
2369
7.40k
      Prev = Pos + 1;
2370
7.40k
    SearchFrom = Pos + 1;
2371
7.40k
  }
2372
632
  if (!IncludesInBlock.empty()) {
2373
82
    sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces,
2374
82
                    Cursor);
2375
82
  }
2376
632
  return Replaces;
2377
632
}
2378
2379
// Returns group number to use as a first order sort on imports. Gives UINT_MAX
2380
// if the import does not match any given groups.
2381
static unsigned findJavaImportGroup(const FormatStyle &Style,
2382
70
                                    StringRef ImportIdentifier) {
2383
70
  unsigned LongestMatchIndex = UINT_MAX;
2384
70
  unsigned LongestMatchLength = 0;
2385
280
  for (unsigned I = 0; I < Style.JavaImportGroups.size(); 
I++210
) {
2386
210
    std::string GroupPrefix = Style.JavaImportGroups[I];
2387
210
    if (ImportIdentifier.startswith(GroupPrefix) &&
2388
80
        GroupPrefix.length() > LongestMatchLength) {
2389
67
      LongestMatchIndex = I;
2390
67
      LongestMatchLength = GroupPrefix.length();
2391
67
    }
2392
210
  }
2393
70
  return LongestMatchIndex;
2394
70
}
2395
2396
// Sorts and deduplicates a block of includes given by 'Imports' based on
2397
// JavaImportGroups, then adding the necessary replacement to 'Replaces'.
2398
// Import declarations with the same text will be deduplicated. Between each
2399
// import group, a newline is inserted, and within each import group, a
2400
// lexicographic sort based on ASCII value is performed.
2401
static void sortJavaImports(const FormatStyle &Style,
2402
                            const SmallVectorImpl<JavaImportDirective> &Imports,
2403
                            ArrayRef<tooling::Range> Ranges, StringRef FileName,
2404
22
                            StringRef Code, tooling::Replacements &Replaces) {
2405
22
  unsigned ImportsBeginOffset = Imports.front().Offset;
2406
22
  unsigned ImportsEndOffset =
2407
22
      Imports.back().Offset + Imports.back().Text.size();
2408
22
  unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;
2409
22
  if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))
2410
1
    return;
2411
21
  SmallVector<unsigned, 16> Indices;
2412
21
  SmallVector<unsigned, 16> JavaImportGroups;
2413
91
  for (unsigned i = 0, e = Imports.size(); i != e; 
++i70
) {
2414
70
    Indices.push_back(i);
2415
70
    JavaImportGroups.push_back(
2416
70
        findJavaImportGroup(Style, Imports[i].Identifier));
2417
70
  }
2418
21
  bool StaticImportAfterNormalImport =
2419
21
      Style.SortJavaStaticImport == FormatStyle::SJSIO_After;
2420
74
  llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
2421
    // Negating IsStatic to push static imports above non-static imports.
2422
74
    return std::make_tuple(!Imports[LHSI].IsStatic ^
2423
74
                               StaticImportAfterNormalImport,
2424
74
                           JavaImportGroups[LHSI], Imports[LHSI].Identifier) <
2425
74
           std::make_tuple(!Imports[RHSI].IsStatic ^
2426
74
                               StaticImportAfterNormalImport,
2427
74
                           JavaImportGroups[RHSI], Imports[RHSI].Identifier);
2428
74
  });
2429
2430
  // Deduplicate imports.
2431
21
  Indices.erase(std::unique(Indices.begin(), Indices.end(),
2432
49
                            [&](unsigned LHSI, unsigned RHSI) {
2433
49
                              return Imports[LHSI].Text == Imports[RHSI].Text;
2434
49
                            }),
2435
21
                Indices.end());
2436
2437
21
  bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
2438
21
  unsigned CurrentImportGroup = JavaImportGroups[Indices.front()];
2439
2440
21
  std::string result;
2441
69
  for (unsigned Index : Indices) {
2442
69
    if (!result.empty()) {
2443
48
      result += "\n";
2444
48
      if (CurrentIsStatic != Imports[Index].IsStatic ||
2445
42
          CurrentImportGroup != JavaImportGroups[Index])
2446
26
        result += "\n";
2447
48
    }
2448
5
    for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) {
2449
5
      result += CommentLine;
2450
5
      result += "\n";
2451
5
    }
2452
69
    result += Imports[Index].Text;
2453
69
    CurrentIsStatic = Imports[Index].IsStatic;
2454
69
    CurrentImportGroup = JavaImportGroups[Index];
2455
69
  }
2456
2457
  // If the imports are out of order, we generate a single replacement fixing
2458
  // the entire block. Otherwise, no replacement is generated.
2459
21
  if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
2460
21
                                 Imports.front().Offset, ImportsBlockSize))))
2461
4
    return;
2462
2463
17
  auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset,
2464
17
                                               ImportsBlockSize, result));
2465
  // FIXME: better error handling. For now, just skip the replacement for the
2466
  // release version.
2467
17
  if (Err) {
2468
0
    llvm::errs() << llvm::toString(std::move(Err)) << "\n";
2469
0
    assert(false);
2470
0
  }
2471
17
}
2472
2473
namespace {
2474
2475
const char JavaImportRegexPattern[] =
2476
    "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;";
2477
2478
} // anonymous namespace
2479
2480
tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code,
2481
                                      ArrayRef<tooling::Range> Ranges,
2482
                                      StringRef FileName,
2483
24
                                      tooling::Replacements &Replaces) {
2484
24
  unsigned Prev = 0;
2485
24
  unsigned SearchFrom = 0;
2486
24
  llvm::Regex ImportRegex(JavaImportRegexPattern);
2487
24
  SmallVector<StringRef, 4> Matches;
2488
24
  SmallVector<JavaImportDirective, 16> ImportsInBlock;
2489
24
  std::vector<StringRef> AssociatedCommentLines;
2490
2491
24
  bool FormattingOff = false;
2492
2493
101
  for (;;) {
2494
101
    auto Pos = Code.find('\n', SearchFrom);
2495
101
    StringRef Line =
2496
100
        Code.substr(Prev, (Pos != StringRef::npos ? Pos : 
Code.size()1
) - Prev);
2497
2498
101
    StringRef Trimmed = Line.trim();
2499
101
    if (Trimmed == "// clang-format off")
2500
3
      FormattingOff = true;
2501
98
    else if (Trimmed == "// clang-format on")
2502
1
      FormattingOff = false;
2503
2504
101
    if (ImportRegex.match(Line, &Matches)) {
2505
74
      if (FormattingOff) {
2506
        // If at least one import line has formatting turned off, turn off
2507
        // formatting entirely.
2508
2
        return Replaces;
2509
2
      }
2510
72
      StringRef Static = Matches[1];
2511
72
      StringRef Identifier = Matches[2];
2512
72
      bool IsStatic = false;
2513
72
      if (Static.contains("static")) {
2514
15
        IsStatic = true;
2515
15
      }
2516
72
      ImportsInBlock.push_back(
2517
72
          {Identifier, Line, Prev, AssociatedCommentLines, IsStatic});
2518
72
      AssociatedCommentLines.clear();
2519
27
    } else if (Trimmed.size() > 0 && 
!ImportsInBlock.empty()22
) {
2520
      // Associating comments within the imports with the nearest import below
2521
17
      AssociatedCommentLines.push_back(Line);
2522
17
    }
2523
99
    Prev = Pos + 1;
2524
99
    if (Pos == StringRef::npos || 
Pos + 1 == Code.size()98
)
2525
22
      break;
2526
77
    SearchFrom = Pos + 1;
2527
77
  }
2528
22
  if (!ImportsInBlock.empty())
2529
22
    sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces);
2530
22
  return Replaces;
2531
24
}
2532
2533
1.41k
bool isMpegTS(StringRef Code) {
2534
  // MPEG transport streams use the ".ts" file extension. clang-format should
2535
  // not attempt to format those. MPEG TS' frame format starts with 0x47 every
2536
  // 189 bytes - detect that and return.
2537
1.41k
  return Code.size() > 188 && 
Code[0] == 0x477
&&
Code[188] == 0x472
;
2538
1.41k
}
2539
2540
17.6k
bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); }
2541
2542
tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
2543
                                   ArrayRef<tooling::Range> Ranges,
2544
778
                                   StringRef FileName, unsigned *Cursor) {
2545
778
  tooling::Replacements Replaces;
2546
778
  if (!Style.SortIncludes)
2547
95
    return Replaces;
2548
683
  if (isLikelyXml(Code))
2549
1
    return Replaces;
2550
682
  if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript &&
2551
26
      isMpegTS(Code))
2552
0
    return Replaces;
2553
682
  if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript)
2554
26
    return sortJavaScriptImports(Style, Code, Ranges, FileName);
2555
656
  if (Style.Language == FormatStyle::LanguageKind::LK_Java)
2556
24
    return sortJavaImports(Style, Code, Ranges, FileName, Replaces);
2557
632
  sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor);
2558
632
  return Replaces;
2559
632
}
2560
2561
template <typename T>
2562
static llvm::Expected<tooling::Replacements>
2563
processReplacements(T ProcessFunc, StringRef Code,
2564
                    const tooling::Replacements &Replaces,
2565
1.18k
                    const FormatStyle &Style) {
2566
1.18k
  if (Replaces.empty())
2567
114
    return tooling::Replacements();
2568
2569
1.07k
  auto NewCode = applyAllReplacements(Code, Replaces);
2570
1.07k
  if (!NewCode)
2571
0
    return NewCode.takeError();
2572
1.07k
  std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();
2573
1.07k
  StringRef FileName = Replaces.begin()->getFilePath();
2574
2575
1.07k
  tooling::Replacements FormatReplaces =
2576
1.07k
      ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
2577
2578
1.07k
  return Replaces.merge(FormatReplaces);
2579
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
2565
487
                    const FormatStyle &Style) {
2566
487
  if (Replaces.empty())
2567
0
    return tooling::Replacements();
2568
2569
487
  auto NewCode = applyAllReplacements(Code, Replaces);
2570
487
  if (!NewCode)
2571
0
    return NewCode.takeError();
2572
487
  std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();
2573
487
  StringRef FileName = Replaces.begin()->getFilePath();
2574
2575
487
  tooling::Replacements FormatReplaces =
2576
487
      ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
2577
2578
487
  return Replaces.merge(FormatReplaces);
2579
487
}
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
2565
487
                    const FormatStyle &Style) {
2566
487
  if (Replaces.empty())
2567
0
    return tooling::Replacements();
2568
2569
487
  auto NewCode = applyAllReplacements(Code, Replaces);
2570
487
  if (!NewCode)
2571
0
    return NewCode.takeError();
2572
487
  std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();
2573
487
  StringRef FileName = Replaces.begin()->getFilePath();
2574
2575
487
  tooling::Replacements FormatReplaces =
2576
487
      ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
2577
2578
487
  return Replaces.merge(FormatReplaces);
2579
487
}
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
2565
210
                    const FormatStyle &Style) {
2566
210
  if (Replaces.empty())
2567
114
    return tooling::Replacements();
2568
2569
96
  auto NewCode = applyAllReplacements(Code, Replaces);
2570
96
  if (!NewCode)
2571
0
    return NewCode.takeError();
2572
96
  std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();
2573
96
  StringRef FileName = Replaces.begin()->getFilePath();
2574
2575
96
  tooling::Replacements FormatReplaces =
2576
96
      ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
2577
2578
96
  return Replaces.merge(FormatReplaces);
2579
96
}
2580
2581
llvm::Expected<tooling::Replacements>
2582
formatReplacements(StringRef Code, const tooling::Replacements &Replaces,
2583
487
                   const FormatStyle &Style) {
2584
  // We need to use lambda function here since there are two versions of
2585
  // `sortIncludes`.
2586
487
  auto SortIncludes = [](const FormatStyle &Style, StringRef Code,
2587
487
                         std::vector<tooling::Range> Ranges,
2588
487
                         StringRef FileName) -> tooling::Replacements {
2589
487
    return sortIncludes(Style, Code, Ranges, FileName);
2590
487
  };
2591
487
  auto SortedReplaces =
2592
487
      processReplacements(SortIncludes, Code, Replaces, Style);
2593
487
  if (!SortedReplaces)
2594
0
    return SortedReplaces.takeError();
2595
2596
  // We need to use lambda function here since there are two versions of
2597
  // `reformat`.
2598
487
  auto Reformat = [](const FormatStyle &Style, StringRef Code,
2599
487
                     std::vector<tooling::Range> Ranges,
2600
487
                     StringRef FileName) -> tooling::Replacements {
2601
487
    return reformat(Style, Code, Ranges, FileName);
2602
487
  };
2603
487
  return processReplacements(Reformat, Code, *SortedReplaces, Style);
2604
487
}
2605
2606
namespace {
2607
2608
198
inline bool isHeaderInsertion(const tooling::Replacement &Replace) {
2609
198
  return Replace.getOffset() == UINT_MAX && 
Replace.getLength() == 042
&&
2610
36
         llvm::Regex(CppIncludeRegexPattern)
2611
36
             .match(Replace.getReplacementText());
2612
198
}
2613
2614
162
inline bool isHeaderDeletion(const tooling::Replacement &Replace) {
2615
162
  return Replace.getOffset() == UINT_MAX && 
Replace.getLength() == 16
;
2616
162
}
2617
2618
// FIXME: insert empty lines between newly created blocks.
2619
tooling::Replacements
2620
fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
2621
210
                        const FormatStyle &Style) {
2622
210
  if (!Style.isCpp())
2623
0
    return Replaces;
2624
2625
210
  tooling::Replacements HeaderInsertions;
2626
210
  std::set<llvm::StringRef> HeadersToDelete;
2627
210
  tooling::Replacements Result;
2628
198
  for (const auto &R : Replaces) {
2629
198
    if (isHeaderInsertion(R)) {
2630
      // Replacements from \p Replaces must be conflict-free already, so we can
2631
      // simply consume the error.
2632
36
      llvm::consumeError(HeaderInsertions.add(R));
2633
162
    } else if (isHeaderDeletion(R)) {
2634
6
      HeadersToDelete.insert(R.getReplacementText());
2635
156
    } else if (R.getOffset() == UINT_MAX) {
2636
0
      llvm::errs() << "Insertions other than header #include insertion are "
2637
0
                      "not supported! "
2638
0
                   << R.getReplacementText() << "\n";
2639
156
    } else {
2640
156
      llvm::consumeError(Result.add(R));
2641
156
    }
2642
198
  }
2643
210
  if (HeaderInsertions.empty() && 
HeadersToDelete.empty()196
)
2644
192
    return Replaces;
2645
2646
18
  StringRef FileName = Replaces.begin()->getFilePath();
2647
18
  tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle);
2648
2649
6
  for (const auto &Header : HeadersToDelete) {
2650
6
    tooling::Replacements Replaces =
2651
6
        Includes.remove(Header.trim("\"<>"), Header.startswith("<"));
2652
6
    for (const auto &R : Replaces) {
2653
6
      auto Err = Result.add(R);
2654
6
      if (Err) {
2655
        // Ignore the deletion on conflict.
2656
0
        llvm::errs() << "Failed to add header deletion replacement for "
2657
0
                     << Header << ": " << llvm::toString(std::move(Err))
2658
0
                     << "\n";
2659
0
      }
2660
6
    }
2661
6
  }
2662
2663
18
  llvm::Regex IncludeRegex = llvm::Regex(CppIncludeRegexPattern);
2664
18
  llvm::SmallVector<StringRef, 4> Matches;
2665
36
  for (const auto &R : HeaderInsertions) {
2666
36
    auto IncludeDirective = R.getReplacementText();
2667
36
    bool Matched = IncludeRegex.match(IncludeDirective, &Matches);
2668
36
    assert(Matched && "Header insertion replacement must have replacement text "
2669
36
                      "'#include ...'");
2670
36
    (void)Matched;
2671
36
    auto IncludeName = Matches[2];
2672
36
    auto Replace =
2673
36
        Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<"));
2674
36
    if (Replace) {
2675
35
      auto Err = Result.add(*Replace);
2676
35
      if (Err) {
2677
17
        llvm::consumeError(std::move(Err));
2678
17
        unsigned NewOffset =
2679
17
            Result.getShiftedCodePosition(Replace->getOffset());
2680
17
        auto Shifted = tooling::Replacement(FileName, NewOffset, 0,
2681
17
                                            Replace->getReplacementText());
2682
17
        Result = Result.merge(tooling::Replacements(Shifted));
2683
17
      }
2684
35
    }
2685
36
  }
2686
18
  return Result;
2687
18
}
2688
2689
} // anonymous namespace
2690
2691
llvm::Expected<tooling::Replacements>
2692
cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
2693
210
                          const FormatStyle &Style) {
2694
  // We need to use lambda function here since there are two versions of
2695
  // `cleanup`.
2696
210
  auto Cleanup = [](const FormatStyle &Style, StringRef Code,
2697
210
                    std::vector<tooling::Range> Ranges,
2698
96
                    StringRef FileName) -> tooling::Replacements {
2699
96
    return cleanup(Style, Code, Ranges, FileName);
2700
96
  };
2701
  // Make header insertion replacements insert new headers into correct blocks.
2702
210
  tooling::Replacements NewReplaces =
2703
210
      fixCppIncludeInsertions(Code, Replaces, Style);
2704
210
  return processReplacements(Cleanup, Code, NewReplaces, Style);
2705
210
}
2706
2707
namespace internal {
2708
std::pair<tooling::Replacements, unsigned>
2709
reformat(const FormatStyle &Style, StringRef Code,
2710
         ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,
2711
         unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,
2712
16.9k
         FormattingAttemptStatus *Status) {
2713
16.9k
  FormatStyle Expanded = expandPresets(Style);
2714
16.9k
  if (Expanded.DisableFormat)
2715
1
    return {tooling::Replacements(), 0};
2716
16.9k
  if (isLikelyXml(Code))
2717
15
    return {tooling::Replacements(), 0};
2718
16.9k
  if (Expanded.Language == FormatStyle::LK_JavaScript && 
isMpegTS(Code)1.39k
)
2719
2
    return {tooling::Replacements(), 0};
2720
2721
16.9k
  typedef std::function<std::pair<tooling::Replacements, unsigned>(
2722
16.9k
      const Environment &)>
2723
16.9k
      AnalyzerPass;
2724
16.9k
  SmallVector<AnalyzerPass, 4> Passes;
2725
2726
16.9k
  if (Style.Language == FormatStyle::LK_Cpp) {
2727
10.0k
    if (Style.FixNamespaceComments)
2728
9.00k
      Passes.emplace_back([&](const Environment &Env) {
2729
9.00k
        return NamespaceEndCommentsFixer(Env, Expanded).process();
2730
9.00k
      });
2731
2732
10.0k
    if (Style.SortUsingDeclarations)
2733
10.0k
      Passes.emplace_back([&](const Environment &Env) {
2734
10.0k
        return UsingDeclarationsSorter(Env, Expanded).process();
2735
10.0k
      });
2736
10.0k
  }
2737
2738
16.9k
  if (Style.Language == FormatStyle::LK_JavaScript &&
2739
1.38k
      Style.JavaScriptQuotes != FormatStyle::JSQS_Leave)
2740
1.38k
    Passes.emplace_back([&](const Environment &Env) {
2741
1.38k
      return JavaScriptRequoter(Env, Expanded).process();
2742
1.38k
    });
2743
2744
16.9k
  Passes.emplace_back([&](const Environment &Env) {
2745
16.9k
    return Formatter(Env, Expanded, Status).process();
2746
16.9k
  });
2747
2748
16.9k
  if (Style.Language == FormatStyle::LK_JavaScript &&
2749
1.38k
      Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped)
2750
12
    Passes.emplace_back([&](const Environment &Env) {
2751
12
      return TrailingCommaInserter(Env, Expanded).process();
2752
12
    });
2753
2754
16.9k
  auto Env =
2755
16.9k
      std::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn,
2756
16.9k
                                    NextStartColumn, LastStartColumn);
2757
16.9k
  llvm::Optional<std::string> CurrentCode = None;
2758
16.9k
  tooling::Replacements Fixes;
2759
16.9k
  unsigned Penalty = 0;
2760
54.3k
  for (size_t I = 0, E = Passes.size(); I < E; 
++I37.3k
) {
2761
37.3k
    std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
2762
37.3k
    auto NewCode = applyAllReplacements(
2763
20.4k
        CurrentCode ? StringRef(*CurrentCode) : 
Code16.9k
, PassFixes.first);
2764
37.3k
    if (NewCode) {
2765
37.3k
      Fixes = Fixes.merge(PassFixes.first);
2766
37.3k
      Penalty += PassFixes.second;
2767
37.3k
      if (I + 1 < E) {
2768
20.4k
        CurrentCode = std::move(*NewCode);
2769
20.4k
        Env = std::make_unique<Environment>(
2770
20.4k
            *CurrentCode, FileName,
2771
20.4k
            tooling::calculateRangesAfterReplacements(Fixes, Ranges),
2772
20.4k
            FirstStartColumn, NextStartColumn, LastStartColumn);
2773
20.4k
      }
2774
37.3k
    }
2775
37.3k
  }
2776
2777
16.9k
  return {Fixes, Penalty};
2778
16.9k
}
2779
} // namespace internal
2780
2781
tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
2782
                               ArrayRef<tooling::Range> Ranges,
2783
                               StringRef FileName,
2784
16.6k
                               FormattingAttemptStatus *Status) {
2785
16.6k
  return internal::reformat(Style, Code, Ranges,
2786
16.6k
                            /*FirstStartColumn=*/0,
2787
16.6k
                            /*NextStartColumn=*/0,
2788
16.6k
                            /*LastStartColumn=*/0, FileName, Status)
2789
16.6k
      .first;
2790
16.6k
}
2791
2792
tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
2793
                              ArrayRef<tooling::Range> Ranges,
2794
131
                              StringRef FileName) {
2795
  // cleanups only apply to C++ (they mostly concern ctor commas etc.)
2796
131
  if (Style.Language != FormatStyle::LK_Cpp)
2797
1
    return tooling::Replacements();
2798
130
  return Cleaner(Environment(Code, FileName, Ranges), Style).process().first;
2799
130
}
2800
2801
tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
2802
                               ArrayRef<tooling::Range> Ranges,
2803
0
                               StringRef FileName, bool *IncompleteFormat) {
2804
0
  FormattingAttemptStatus Status;
2805
0
  auto Result = reformat(Style, Code, Ranges, FileName, &Status);
2806
0
  if (!Status.FormatComplete)
2807
0
    *IncompleteFormat = true;
2808
0
  return Result;
2809
0
}
2810
2811
tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,
2812
                                              StringRef Code,
2813
                                              ArrayRef<tooling::Range> Ranges,
2814
118
                                              StringRef FileName) {
2815
118
  return NamespaceEndCommentsFixer(Environment(Code, FileName, Ranges), Style)
2816
118
      .process()
2817
118
      .first;
2818
118
}
2819
2820
tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
2821
                                            StringRef Code,
2822
                                            ArrayRef<tooling::Range> Ranges,
2823
35
                                            StringRef FileName) {
2824
35
  return UsingDeclarationsSorter(Environment(Code, FileName, Ranges), Style)
2825
35
      .process()
2826
35
      .first;
2827
35
}
2828
2829
76.7k
LangOptions getFormattingLangOpts(const FormatStyle &Style) {
2830
76.7k
  LangOptions LangOpts;
2831
2832
76.7k
  FormatStyle::LanguageStandard LexingStd = Style.Standard;
2833
76.7k
  if (LexingStd == FormatStyle::LS_Auto)
2834
11.7k
    LexingStd = FormatStyle::LS_Latest;
2835
76.7k
  if (LexingStd == FormatStyle::LS_Latest)
2836
76.6k
    LexingStd = FormatStyle::LS_Cpp20;
2837
76.7k
  LangOpts.CPlusPlus = 1;
2838
76.7k
  LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11;
2839
76.7k
  LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14;
2840
76.7k
  LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17;
2841
76.7k
  LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20;
2842
76.7k
  LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20;
2843
2844
76.7k
  LangOpts.LineComment = 1;
2845
76.7k
  bool AlternativeOperators = Style.isCpp();
2846
67.7k
  LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 
09.03k
;
2847
76.7k
  LangOpts.Bool = 1;
2848
76.7k
  LangOpts.ObjC = 1;
2849
76.7k
  LangOpts.MicrosoftExt = 1;    // To get kw___try, kw___finally.
2850
76.7k
  LangOpts.DeclSpecKeyword = 1; // To get __declspec.
2851
76.7k
  LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict.
2852
76.7k
  return LangOpts;
2853
76.7k
}
2854
2855
const char *StyleOptionHelpDescription =
2856
    "Coding style, currently supports:\n"
2857
    "  LLVM, GNU, Google, Chromium, Microsoft, Mozilla, WebKit.\n"
2858
    "Use -style=file to load style configuration from\n"
2859
    ".clang-format file located in one of the parent\n"
2860
    "directories of the source file (or current\n"
2861
    "directory for stdin).\n"
2862
    "Use -style=\"{key: value, ...}\" to set specific\n"
2863
    "parameters, e.g.:\n"
2864
    "  -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
2865
2866
611
static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
2867
611
  if (FileName.endswith(".java"))
2868
0
    return FormatStyle::LK_Java;
2869
611
  if (FileName.endswith_lower(".js") || 
FileName.endswith_lower(".mjs")610
||
2870
610
      FileName.endswith_lower(".ts"))
2871
1
    return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript.
2872
610
  if (FileName.endswith(".m") || 
FileName.endswith(".mm")609
)
2873
2
    return FormatStyle::LK_ObjC;
2874
608
  if (FileName.endswith_lower(".proto") ||
2875
608
      FileName.endswith_lower(".protodevel"))
2876
0
    return FormatStyle::LK_Proto;
2877
608
  if (FileName.endswith_lower(".textpb") ||
2878
608
      FileName.endswith_lower(".pb.txt") ||
2879
608
      FileName.endswith_lower(".textproto") ||
2880
608
      FileName.endswith_lower(".asciipb"))
2881
0
    return FormatStyle::LK_TextProto;
2882
608
  if (FileName.endswith_lower(".td"))
2883
1
    return FormatStyle::LK_TableGen;
2884
607
  if (FileName.endswith_lower(".cs"))
2885
0
    return FormatStyle::LK_CSharp;
2886
607
  return FormatStyle::LK_Cpp;
2887
607
}
2888
2889
611
FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {
2890
611
  const auto GuessedLanguage = getLanguageByFileName(FileName);
2891
611
  if (GuessedLanguage == FormatStyle::LK_Cpp) {
2892
607
    auto Extension = llvm::sys::path::extension(FileName);
2893
    // If there's no file extension (or it's .h), we need to check the contents
2894
    // of the code to see if it contains Objective-C.
2895
607
    if (Extension.empty() || 
Extension == ".h"594
) {
2896
311
      auto NonEmptyFileName = FileName.empty() ? 
"guess.h"1
: FileName;
2897
312
      Environment Env(Code, NonEmptyFileName, /*Ranges=*/{});
2898
312
      ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle());
2899
312
      Guesser.process();
2900
312
      if (Guesser.isObjC())
2901
34
        return FormatStyle::LK_ObjC;
2902
577
    }
2903
607
  }
2904
577
  return GuessedLanguage;
2905
577
}
2906
2907
const char *DefaultFormatStyle = "file";
2908
2909
const char *DefaultFallbackStyle = "LLVM";
2910
2911
llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
2912
                                     StringRef FallbackStyleName,
2913
                                     StringRef Code, llvm::vfs::FileSystem *FS,
2914
564
                                     bool AllowUnknownOptions) {
2915
564
  if (!FS) {
2916
551
    FS = llvm::vfs::getRealFileSystem().get();
2917
551
  }
2918
564
  FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code));
2919
2920
564
  FormatStyle FallbackStyle = getNoStyle();
2921
564
  if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))
2922
1
    return make_string_error("Invalid fallback style \"" + FallbackStyleName);
2923
2924
563
  if (StyleName.startswith("{")) {
2925
    // Parse YAML/JSON style from the command line.
2926
36
    if (std::error_code ec = parseConfiguration(
2927
4
            llvm::MemoryBufferRef(StyleName, "<command-line>"), &Style,
2928
4
            AllowUnknownOptions))
2929
4
      return make_string_error("Error parsing -style: " + ec.message());
2930
32
    return Style;
2931
32
  }
2932
2933
527
  if (!StyleName.equals_lower("file")) {
2934
505
    if (!getPredefinedStyle(StyleName, Style.Language, &Style))
2935
1
      return make_string_error("Invalid value for -style");
2936
504
    return Style;
2937
504
  }
2938
2939
  // Look for .clang-format/_clang-format file in the file's parent directories.
2940
22
  SmallString<128> UnsuitableConfigFiles;
2941
22
  SmallString<128> Path(FileName);
2942
22
  if (std::error_code EC = FS->makeAbsolute(Path))
2943
0
    return make_string_error(EC.message());
2944
2945
22
  llvm::SmallVector<std::string, 2> FilesToLookFor;
2946
22
  FilesToLookFor.push_back(".clang-format");
2947
22
  FilesToLookFor.push_back("_clang-format");
2948
2949
59
  for (StringRef Directory = Path; !Directory.empty();
2950
55
       
Directory = llvm::sys::path::parent_path(Directory)37
) {
2951
2952
55
    auto Status = FS->status(Directory);
2953
55
    if (!Status ||
2954
50
        Status->getType() != llvm::sys::fs::file_type::directory_file) {
2955
21
      continue;
2956
21
    }
2957
2958
52
    
for (const auto &F : FilesToLookFor)34
{
2959
52
      SmallString<128> ConfigFile(Directory);
2960
2961
52
      llvm::sys::path::append(ConfigFile, F);
2962
52
      LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
2963
2964
52
      Status = FS->status(ConfigFile.str());
2965
2966
52
      if (Status &&
2967
18
          (Status->getType() == llvm::sys::fs::file_type::regular_file)) {
2968
18
        llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
2969
18
            FS->getBufferForFile(ConfigFile.str());
2970
18
        if (std::error_code EC = Text.getError())
2971
0
          return make_string_error(EC.message());
2972
18
        if (std::error_code ec =
2973
2
                parseConfiguration(*Text.get(), &Style, AllowUnknownOptions)) {
2974
2
          if (ec == ParseError::Unsuitable) {
2975
0
            if (!UnsuitableConfigFiles.empty())
2976
0
              UnsuitableConfigFiles.append(", ");
2977
0
            UnsuitableConfigFiles.append(ConfigFile);
2978
0
            continue;
2979
0
          }
2980
2
          return make_string_error("Error reading " + ConfigFile + ": " +
2981
2
                                   ec.message());
2982
2
        }
2983
16
        LLVM_DEBUG(llvm::dbgs()
2984
16
                   << "Using configuration file " << ConfigFile << "\n");
2985
16
        return Style;
2986
16
      }
2987
52
    }
2988
34
  }
2989
4
  if (!UnsuitableConfigFiles.empty())
2990
0
    return make_string_error("Configuration file(s) do(es) not support " +
2991
0
                             getLanguageName(Style.Language) + ": " +
2992
0
                             UnsuitableConfigFiles);
2993
4
  return FallbackStyle;
2994
4
}
2995
2996
} // namespace format
2997
} // namespace clang