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