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