Coverage Report

Created: 2020-09-19 12:23

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