xref: /freebsd-src/contrib/llvm-project/clang/lib/Format/Format.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- Format.cpp - Format C++ code -------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This file implements functions declared in Format.h. This will be
110b57cec5SDimitry Andric /// split into separate files as we go.
120b57cec5SDimitry Andric ///
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "clang/Format/Format.h"
1604eeddc0SDimitry Andric #include "DefinitionBlockSeparator.h"
17bdd1243dSDimitry Andric #include "IntegerLiteralSeparatorFixer.h"
180b57cec5SDimitry Andric #include "NamespaceEndCommentsFixer.h"
195f757f3fSDimitry Andric #include "ObjCPropertyAttributeOrderFixer.h"
20349cc55cSDimitry Andric #include "QualifierAlignmentFixer.h"
210b57cec5SDimitry Andric #include "SortJavaScriptImports.h"
220b57cec5SDimitry Andric #include "UnwrappedLineFormatter.h"
230b57cec5SDimitry Andric #include "UsingDeclarationsSorter.h"
240b57cec5SDimitry Andric #include "clang/Tooling/Inclusions/HeaderIncludes.h"
2581ad6265SDimitry Andric #include "llvm/ADT/Sequence.h"
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric #define DEBUG_TYPE "format-formatter"
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric using clang::format::FormatStyle;
300b57cec5SDimitry Andric 
31*0fca6ea1SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(FormatStyle::RawStringFormat)
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric namespace llvm {
340b57cec5SDimitry Andric namespace yaml {
355f757f3fSDimitry Andric template <>
365f757f3fSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BreakBeforeNoexceptSpecifierStyle> {
375f757f3fSDimitry Andric   static void
385f757f3fSDimitry Andric   enumeration(IO &IO, FormatStyle::BreakBeforeNoexceptSpecifierStyle &Value) {
395f757f3fSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::BBNSS_Never);
405f757f3fSDimitry Andric     IO.enumCase(Value, "OnlyWithParen", FormatStyle::BBNSS_OnlyWithParen);
415f757f3fSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::BBNSS_Always);
425f757f3fSDimitry Andric   }
435f757f3fSDimitry Andric };
445f757f3fSDimitry Andric 
4581ad6265SDimitry Andric template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {
4681ad6265SDimitry Andric   static void enumInput(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
4781ad6265SDimitry Andric     IO.enumCase(Value, "None",
4881ad6265SDimitry Andric                 FormatStyle::AlignConsecutiveStyle(
4981ad6265SDimitry Andric                     {/*Enabled=*/false, /*AcrossEmptyLines=*/false,
5081ad6265SDimitry Andric                      /*AcrossComments=*/false, /*AlignCompound=*/false,
51297eecfbSDimitry Andric                      /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
5281ad6265SDimitry Andric     IO.enumCase(Value, "Consecutive",
5381ad6265SDimitry Andric                 FormatStyle::AlignConsecutiveStyle(
5481ad6265SDimitry Andric                     {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
5581ad6265SDimitry Andric                      /*AcrossComments=*/false, /*AlignCompound=*/false,
56297eecfbSDimitry Andric                      /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
5781ad6265SDimitry Andric     IO.enumCase(Value, "AcrossEmptyLines",
5881ad6265SDimitry Andric                 FormatStyle::AlignConsecutiveStyle(
5981ad6265SDimitry Andric                     {/*Enabled=*/true, /*AcrossEmptyLines=*/true,
6081ad6265SDimitry Andric                      /*AcrossComments=*/false, /*AlignCompound=*/false,
61297eecfbSDimitry Andric                      /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
6281ad6265SDimitry Andric     IO.enumCase(Value, "AcrossComments",
63297eecfbSDimitry Andric                 FormatStyle::AlignConsecutiveStyle(
64297eecfbSDimitry Andric                     {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
65297eecfbSDimitry Andric                      /*AcrossComments=*/true, /*AlignCompound=*/false,
66297eecfbSDimitry Andric                      /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
67e8d8bef9SDimitry Andric     IO.enumCase(Value, "AcrossEmptyLinesAndComments",
68297eecfbSDimitry Andric                 FormatStyle::AlignConsecutiveStyle(
69297eecfbSDimitry Andric                     {/*Enabled=*/true, /*AcrossEmptyLines=*/true,
70297eecfbSDimitry Andric                      /*AcrossComments=*/true, /*AlignCompound=*/false,
71297eecfbSDimitry Andric                      /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
72e8d8bef9SDimitry Andric 
73349cc55cSDimitry Andric     // For backward compatibility.
7481ad6265SDimitry Andric     IO.enumCase(Value, "true",
7581ad6265SDimitry Andric                 FormatStyle::AlignConsecutiveStyle(
7681ad6265SDimitry Andric                     {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
7781ad6265SDimitry Andric                      /*AcrossComments=*/false, /*AlignCompound=*/false,
78297eecfbSDimitry Andric                      /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
7981ad6265SDimitry Andric     IO.enumCase(Value, "false",
8081ad6265SDimitry Andric                 FormatStyle::AlignConsecutiveStyle(
8181ad6265SDimitry Andric                     {/*Enabled=*/false, /*AcrossEmptyLines=*/false,
8281ad6265SDimitry Andric                      /*AcrossComments=*/false, /*AlignCompound=*/false,
83297eecfbSDimitry Andric                      /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
8481ad6265SDimitry Andric   }
8581ad6265SDimitry Andric 
8681ad6265SDimitry Andric   static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
8781ad6265SDimitry Andric     IO.mapOptional("Enabled", Value.Enabled);
8881ad6265SDimitry Andric     IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);
8981ad6265SDimitry Andric     IO.mapOptional("AcrossComments", Value.AcrossComments);
9081ad6265SDimitry Andric     IO.mapOptional("AlignCompound", Value.AlignCompound);
91297eecfbSDimitry Andric     IO.mapOptional("AlignFunctionPointers", Value.AlignFunctionPointers);
9281ad6265SDimitry Andric     IO.mapOptional("PadOperators", Value.PadOperators);
93e8d8bef9SDimitry Andric   }
94e8d8bef9SDimitry Andric };
95e8d8bef9SDimitry Andric 
96fe6060f1SDimitry Andric template <>
9706c3fb27SDimitry Andric struct MappingTraits<FormatStyle::ShortCaseStatementsAlignmentStyle> {
9806c3fb27SDimitry Andric   static void mapping(IO &IO,
9906c3fb27SDimitry Andric                       FormatStyle::ShortCaseStatementsAlignmentStyle &Value) {
10006c3fb27SDimitry Andric     IO.mapOptional("Enabled", Value.Enabled);
10106c3fb27SDimitry Andric     IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);
10206c3fb27SDimitry Andric     IO.mapOptional("AcrossComments", Value.AcrossComments);
103*0fca6ea1SDimitry Andric     IO.mapOptional("AlignCaseArrows", Value.AlignCaseArrows);
10406c3fb27SDimitry Andric     IO.mapOptional("AlignCaseColons", Value.AlignCaseColons);
10506c3fb27SDimitry Andric   }
10606c3fb27SDimitry Andric };
10706c3fb27SDimitry Andric 
10806c3fb27SDimitry Andric template <>
109bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::AttributeBreakingStyle> {
110bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::AttributeBreakingStyle &Value) {
111bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::ABS_Always);
112bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::ABS_Leave);
113bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::ABS_Never);
114bdd1243dSDimitry Andric   }
115bdd1243dSDimitry Andric };
116bdd1243dSDimitry Andric 
117bdd1243dSDimitry Andric template <>
118fe6060f1SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::ArrayInitializerAlignmentStyle> {
119fe6060f1SDimitry Andric   static void enumeration(IO &IO,
120fe6060f1SDimitry Andric                           FormatStyle::ArrayInitializerAlignmentStyle &Value) {
121fe6060f1SDimitry Andric     IO.enumCase(Value, "None", FormatStyle::AIAS_None);
122fe6060f1SDimitry Andric     IO.enumCase(Value, "Left", FormatStyle::AIAS_Left);
123fe6060f1SDimitry Andric     IO.enumCase(Value, "Right", FormatStyle::AIAS_Right);
124fe6060f1SDimitry Andric   }
125fe6060f1SDimitry Andric };
126fe6060f1SDimitry Andric 
127bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> {
128bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {
129bdd1243dSDimitry Andric     IO.enumCase(Value, "All", FormatStyle::BOS_All);
130bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::BOS_All);
131bdd1243dSDimitry Andric     IO.enumCase(Value, "None", FormatStyle::BOS_None);
132bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::BOS_None);
133bdd1243dSDimitry Andric     IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment);
1340b57cec5SDimitry Andric   }
1350b57cec5SDimitry Andric };
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {
1380b57cec5SDimitry Andric   static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) {
1390b57cec5SDimitry Andric     IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto);
1400b57cec5SDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::BPS_Always);
1410b57cec5SDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::BPS_Never);
1420b57cec5SDimitry Andric   }
1430b57cec5SDimitry Andric };
1440b57cec5SDimitry Andric 
145bdd1243dSDimitry Andric template <>
146bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BitFieldColonSpacingStyle> {
147bdd1243dSDimitry Andric   static void enumeration(IO &IO,
148bdd1243dSDimitry Andric                           FormatStyle::BitFieldColonSpacingStyle &Value) {
149bdd1243dSDimitry Andric     IO.enumCase(Value, "Both", FormatStyle::BFCS_Both);
150bdd1243dSDimitry Andric     IO.enumCase(Value, "None", FormatStyle::BFCS_None);
151bdd1243dSDimitry Andric     IO.enumCase(Value, "Before", FormatStyle::BFCS_Before);
152bdd1243dSDimitry Andric     IO.enumCase(Value, "After", FormatStyle::BFCS_After);
1530b57cec5SDimitry Andric   }
1540b57cec5SDimitry Andric };
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
1570b57cec5SDimitry Andric   static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {
1580b57cec5SDimitry Andric     IO.enumCase(Value, "Attach", FormatStyle::BS_Attach);
1590b57cec5SDimitry Andric     IO.enumCase(Value, "Linux", FormatStyle::BS_Linux);
1600b57cec5SDimitry Andric     IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla);
1610b57cec5SDimitry Andric     IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);
1620b57cec5SDimitry Andric     IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
163a7dea167SDimitry Andric     IO.enumCase(Value, "Whitesmiths", FormatStyle::BS_Whitesmiths);
1640b57cec5SDimitry Andric     IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
1650b57cec5SDimitry Andric     IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit);
1660b57cec5SDimitry Andric     IO.enumCase(Value, "Custom", FormatStyle::BS_Custom);
1670b57cec5SDimitry Andric   }
1680b57cec5SDimitry Andric };
1690b57cec5SDimitry Andric 
170bdd1243dSDimitry Andric template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
171bdd1243dSDimitry Andric   static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
172bdd1243dSDimitry Andric     IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel);
173bdd1243dSDimitry Andric     IO.mapOptional("AfterClass", Wrapping.AfterClass);
174bdd1243dSDimitry Andric     IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement);
175bdd1243dSDimitry Andric     IO.mapOptional("AfterEnum", Wrapping.AfterEnum);
176bdd1243dSDimitry Andric     IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
177bdd1243dSDimitry Andric     IO.mapOptional("AfterFunction", Wrapping.AfterFunction);
178bdd1243dSDimitry Andric     IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace);
179bdd1243dSDimitry Andric     IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
180bdd1243dSDimitry Andric     IO.mapOptional("AfterStruct", Wrapping.AfterStruct);
181bdd1243dSDimitry Andric     IO.mapOptional("AfterUnion", Wrapping.AfterUnion);
182bdd1243dSDimitry Andric     IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
183bdd1243dSDimitry Andric     IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
184bdd1243dSDimitry Andric     IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody);
185bdd1243dSDimitry Andric     IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile);
186bdd1243dSDimitry Andric     IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
187bdd1243dSDimitry Andric     IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);
188bdd1243dSDimitry Andric     IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);
189bdd1243dSDimitry Andric     IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
190bdd1243dSDimitry Andric   }
191bdd1243dSDimitry Andric };
192bdd1243dSDimitry Andric 
193bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> {
194bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) {
195bdd1243dSDimitry Andric     IO.enumCase(Value, "Align", FormatStyle::BAS_Align);
196bdd1243dSDimitry Andric     IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign);
197bdd1243dSDimitry Andric     IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak);
198bdd1243dSDimitry Andric     IO.enumCase(Value, "BlockIndent", FormatStyle::BAS_BlockIndent);
199bdd1243dSDimitry Andric 
200bdd1243dSDimitry Andric     // For backward compatibility.
201bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::BAS_Align);
202bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign);
203bdd1243dSDimitry Andric   }
204bdd1243dSDimitry Andric };
205bdd1243dSDimitry Andric 
2060b57cec5SDimitry Andric template <>
207a7dea167SDimitry Andric struct ScalarEnumerationTraits<
208a7dea167SDimitry Andric     FormatStyle::BraceWrappingAfterControlStatementStyle> {
209a7dea167SDimitry Andric   static void
210a7dea167SDimitry Andric   enumeration(IO &IO,
211a7dea167SDimitry Andric               FormatStyle::BraceWrappingAfterControlStatementStyle &Value) {
212a7dea167SDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::BWACS_Never);
213a7dea167SDimitry Andric     IO.enumCase(Value, "MultiLine", FormatStyle::BWACS_MultiLine);
214a7dea167SDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::BWACS_Always);
2155ffd83dbSDimitry Andric 
2165ffd83dbSDimitry Andric     // For backward compatibility.
2175ffd83dbSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::BWACS_Never);
2185ffd83dbSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::BWACS_Always);
219a7dea167SDimitry Andric   }
220a7dea167SDimitry Andric };
221a7dea167SDimitry Andric 
222a7dea167SDimitry Andric template <>
22381ad6265SDimitry Andric struct ScalarEnumerationTraits<
22481ad6265SDimitry Andric     FormatStyle::BreakBeforeConceptDeclarationsStyle> {
22581ad6265SDimitry Andric   static void
22681ad6265SDimitry Andric   enumeration(IO &IO, FormatStyle::BreakBeforeConceptDeclarationsStyle &Value) {
22781ad6265SDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::BBCDS_Never);
22881ad6265SDimitry Andric     IO.enumCase(Value, "Allowed", FormatStyle::BBCDS_Allowed);
22981ad6265SDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::BBCDS_Always);
23081ad6265SDimitry Andric 
23181ad6265SDimitry Andric     // For backward compatibility.
23281ad6265SDimitry Andric     IO.enumCase(Value, "true", FormatStyle::BBCDS_Always);
23381ad6265SDimitry Andric     IO.enumCase(Value, "false", FormatStyle::BBCDS_Allowed);
23481ad6265SDimitry Andric   }
23581ad6265SDimitry Andric };
23681ad6265SDimitry Andric 
23781ad6265SDimitry Andric template <>
238bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BreakBeforeInlineASMColonStyle> {
239bdd1243dSDimitry Andric   static void enumeration(IO &IO,
240bdd1243dSDimitry Andric                           FormatStyle::BreakBeforeInlineASMColonStyle &Value) {
241bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::BBIAS_Never);
242bdd1243dSDimitry Andric     IO.enumCase(Value, "OnlyMultiline", FormatStyle::BBIAS_OnlyMultiline);
243bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::BBIAS_Always);
244bdd1243dSDimitry Andric   }
245bdd1243dSDimitry Andric };
2465f757f3fSDimitry Andric 
247bdd1243dSDimitry Andric template <>
2480b57cec5SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
2490b57cec5SDimitry Andric   static void
2500b57cec5SDimitry Andric   enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
2510b57cec5SDimitry Andric     IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon);
2520b57cec5SDimitry Andric     IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma);
2530b57cec5SDimitry Andric     IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon);
2540b57cec5SDimitry Andric   }
2550b57cec5SDimitry Andric };
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric template <>
2580b57cec5SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {
2590b57cec5SDimitry Andric   static void enumeration(IO &IO,
2600b57cec5SDimitry Andric                           FormatStyle::BreakInheritanceListStyle &Value) {
2610b57cec5SDimitry Andric     IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon);
2620b57cec5SDimitry Andric     IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma);
2630b57cec5SDimitry Andric     IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon);
264fe6060f1SDimitry Andric     IO.enumCase(Value, "AfterComma", FormatStyle::BILS_AfterComma);
265fe6060f1SDimitry Andric   }
266fe6060f1SDimitry Andric };
267fe6060f1SDimitry Andric 
268fe6060f1SDimitry Andric template <>
2690b57cec5SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
2700b57cec5SDimitry Andric   static void enumeration(IO &IO,
2710b57cec5SDimitry Andric                           FormatStyle::BreakTemplateDeclarationsStyle &Value) {
272*0fca6ea1SDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::BTDS_Leave);
2730b57cec5SDimitry Andric     IO.enumCase(Value, "No", FormatStyle::BTDS_No);
2740b57cec5SDimitry Andric     IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);
2750b57cec5SDimitry Andric     IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric     // For backward compatibility.
2780b57cec5SDimitry Andric     IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine);
2790b57cec5SDimitry Andric     IO.enumCase(Value, "true", FormatStyle::BTDS_Yes);
2800b57cec5SDimitry Andric   }
2810b57cec5SDimitry Andric };
2820b57cec5SDimitry Andric 
283*0fca6ea1SDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::DAGArgStyle> {
284*0fca6ea1SDimitry Andric   static void enumeration(IO &IO, FormatStyle::DAGArgStyle &Value) {
285*0fca6ea1SDimitry Andric     IO.enumCase(Value, "DontBreak", FormatStyle::DAS_DontBreak);
286*0fca6ea1SDimitry Andric     IO.enumCase(Value, "BreakElements", FormatStyle::DAS_BreakElements);
287*0fca6ea1SDimitry Andric     IO.enumCase(Value, "BreakAll", FormatStyle::DAS_BreakAll);
288*0fca6ea1SDimitry Andric   }
289*0fca6ea1SDimitry Andric };
290*0fca6ea1SDimitry Andric 
2910b57cec5SDimitry Andric template <>
2920b57cec5SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
2930b57cec5SDimitry Andric   static void
2940b57cec5SDimitry Andric   enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
2950b57cec5SDimitry Andric     IO.enumCase(Value, "None", FormatStyle::DRTBS_None);
2960b57cec5SDimitry Andric     IO.enumCase(Value, "All", FormatStyle::DRTBS_All);
2970b57cec5SDimitry Andric     IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel);
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric     // For backward compatibility.
3000b57cec5SDimitry Andric     IO.enumCase(Value, "false", FormatStyle::DRTBS_None);
3010b57cec5SDimitry Andric     IO.enumCase(Value, "true", FormatStyle::DRTBS_All);
3020b57cec5SDimitry Andric   }
3030b57cec5SDimitry Andric };
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric template <>
3060b57cec5SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
3070b57cec5SDimitry Andric   static void enumeration(IO &IO,
3080b57cec5SDimitry Andric                           FormatStyle::EscapedNewlineAlignmentStyle &Value) {
3090b57cec5SDimitry Andric     IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign);
3100b57cec5SDimitry Andric     IO.enumCase(Value, "Left", FormatStyle::ENAS_Left);
311*0fca6ea1SDimitry Andric     IO.enumCase(Value, "LeftWithLastLine", FormatStyle::ENAS_LeftWithLastLine);
3120b57cec5SDimitry Andric     IO.enumCase(Value, "Right", FormatStyle::ENAS_Right);
3130b57cec5SDimitry Andric 
3140b57cec5SDimitry Andric     // For backward compatibility.
3150b57cec5SDimitry Andric     IO.enumCase(Value, "true", FormatStyle::ENAS_Left);
3160b57cec5SDimitry Andric     IO.enumCase(Value, "false", FormatStyle::ENAS_Right);
3170b57cec5SDimitry Andric   }
3180b57cec5SDimitry Andric };
3190b57cec5SDimitry Andric 
320bdd1243dSDimitry Andric template <>
321bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::EmptyLineAfterAccessModifierStyle> {
322bdd1243dSDimitry Andric   static void
323bdd1243dSDimitry Andric   enumeration(IO &IO, FormatStyle::EmptyLineAfterAccessModifierStyle &Value) {
324bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::ELAAMS_Never);
325bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::ELAAMS_Leave);
326bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::ELAAMS_Always);
327bdd1243dSDimitry Andric   }
328bdd1243dSDimitry Andric };
329bdd1243dSDimitry Andric 
330bdd1243dSDimitry Andric template <>
331bdd1243dSDimitry Andric struct ScalarEnumerationTraits<
332bdd1243dSDimitry Andric     FormatStyle::EmptyLineBeforeAccessModifierStyle> {
333bdd1243dSDimitry Andric   static void
334bdd1243dSDimitry Andric   enumeration(IO &IO, FormatStyle::EmptyLineBeforeAccessModifierStyle &Value) {
335bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::ELBAMS_Never);
336bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::ELBAMS_Leave);
337bdd1243dSDimitry Andric     IO.enumCase(Value, "LogicalBlock", FormatStyle::ELBAMS_LogicalBlock);
338bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::ELBAMS_Always);
339bdd1243dSDimitry Andric   }
340bdd1243dSDimitry Andric };
341bdd1243dSDimitry Andric 
342bdd1243dSDimitry Andric template <>
343bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> {
344bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value) {
345bdd1243dSDimitry Andric     IO.enumCase(Value, "AfterExternBlock", FormatStyle::IEBS_AfterExternBlock);
346bdd1243dSDimitry Andric     IO.enumCase(Value, "Indent", FormatStyle::IEBS_Indent);
347bdd1243dSDimitry Andric     IO.enumCase(Value, "NoIndent", FormatStyle::IEBS_NoIndent);
348bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::IEBS_Indent);
349bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::IEBS_NoIndent);
350bdd1243dSDimitry Andric   }
351bdd1243dSDimitry Andric };
352bdd1243dSDimitry Andric 
353bdd1243dSDimitry Andric template <> struct MappingTraits<FormatStyle::IntegerLiteralSeparatorStyle> {
354bdd1243dSDimitry Andric   static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &Base) {
355bdd1243dSDimitry Andric     IO.mapOptional("Binary", Base.Binary);
3561ac55f4cSDimitry Andric     IO.mapOptional("BinaryMinDigits", Base.BinaryMinDigits);
357bdd1243dSDimitry Andric     IO.mapOptional("Decimal", Base.Decimal);
3581ac55f4cSDimitry Andric     IO.mapOptional("DecimalMinDigits", Base.DecimalMinDigits);
359bdd1243dSDimitry Andric     IO.mapOptional("Hex", Base.Hex);
3601ac55f4cSDimitry Andric     IO.mapOptional("HexMinDigits", Base.HexMinDigits);
361bdd1243dSDimitry Andric   }
362bdd1243dSDimitry Andric };
363bdd1243dSDimitry Andric 
364bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {
365bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) {
366bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave);
367bdd1243dSDimitry Andric     IO.enumCase(Value, "Single", FormatStyle::JSQS_Single);
368bdd1243dSDimitry Andric     IO.enumCase(Value, "Double", FormatStyle::JSQS_Double);
369bdd1243dSDimitry Andric   }
370bdd1243dSDimitry Andric };
371bdd1243dSDimitry Andric 
372*0fca6ea1SDimitry Andric template <> struct MappingTraits<FormatStyle::KeepEmptyLinesStyle> {
373*0fca6ea1SDimitry Andric   static void mapping(IO &IO, FormatStyle::KeepEmptyLinesStyle &Value) {
374*0fca6ea1SDimitry Andric     IO.mapOptional("AtEndOfFile", Value.AtEndOfFile);
375*0fca6ea1SDimitry Andric     IO.mapOptional("AtStartOfBlock", Value.AtStartOfBlock);
376*0fca6ea1SDimitry Andric     IO.mapOptional("AtStartOfFile", Value.AtStartOfFile);
377*0fca6ea1SDimitry Andric   }
378*0fca6ea1SDimitry Andric };
379*0fca6ea1SDimitry Andric 
380bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
381bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
382bdd1243dSDimitry Andric     IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
383bdd1243dSDimitry Andric     IO.enumCase(Value, "Java", FormatStyle::LK_Java);
384bdd1243dSDimitry Andric     IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
385bdd1243dSDimitry Andric     IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);
386bdd1243dSDimitry Andric     IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
387bdd1243dSDimitry Andric     IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);
388bdd1243dSDimitry Andric     IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto);
389bdd1243dSDimitry Andric     IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp);
390bdd1243dSDimitry Andric     IO.enumCase(Value, "Json", FormatStyle::LK_Json);
39106c3fb27SDimitry Andric     IO.enumCase(Value, "Verilog", FormatStyle::LK_Verilog);
392bdd1243dSDimitry Andric   }
393bdd1243dSDimitry Andric };
394bdd1243dSDimitry Andric 
395bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
396bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
397bdd1243dSDimitry Andric     IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03);
398bdd1243dSDimitry Andric     IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias
399bdd1243dSDimitry Andric     IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias
400bdd1243dSDimitry Andric 
401bdd1243dSDimitry Andric     IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11);
402bdd1243dSDimitry Andric     IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias
403bdd1243dSDimitry Andric 
404bdd1243dSDimitry Andric     IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14);
405bdd1243dSDimitry Andric     IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17);
406bdd1243dSDimitry Andric     IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20);
407bdd1243dSDimitry Andric 
408bdd1243dSDimitry Andric     IO.enumCase(Value, "Latest", FormatStyle::LS_Latest);
409bdd1243dSDimitry Andric     IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias
410bdd1243dSDimitry Andric     IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);
411bdd1243dSDimitry Andric   }
412bdd1243dSDimitry Andric };
413bdd1243dSDimitry Andric 
414bdd1243dSDimitry Andric template <>
415bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::LambdaBodyIndentationKind> {
416bdd1243dSDimitry Andric   static void enumeration(IO &IO,
417bdd1243dSDimitry Andric                           FormatStyle::LambdaBodyIndentationKind &Value) {
418bdd1243dSDimitry Andric     IO.enumCase(Value, "Signature", FormatStyle::LBI_Signature);
419bdd1243dSDimitry Andric     IO.enumCase(Value, "OuterScope", FormatStyle::LBI_OuterScope);
420bdd1243dSDimitry Andric   }
421bdd1243dSDimitry Andric };
422bdd1243dSDimitry Andric 
423bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::LineEndingStyle> {
424bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::LineEndingStyle &Value) {
425bdd1243dSDimitry Andric     IO.enumCase(Value, "LF", FormatStyle::LE_LF);
426bdd1243dSDimitry Andric     IO.enumCase(Value, "CRLF", FormatStyle::LE_CRLF);
427bdd1243dSDimitry Andric     IO.enumCase(Value, "DeriveLF", FormatStyle::LE_DeriveLF);
428bdd1243dSDimitry Andric     IO.enumCase(Value, "DeriveCRLF", FormatStyle::LE_DeriveCRLF);
429bdd1243dSDimitry Andric   }
430bdd1243dSDimitry Andric };
431bdd1243dSDimitry Andric 
432bdd1243dSDimitry Andric template <>
433bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
434bdd1243dSDimitry Andric   static void enumeration(IO &IO,
435bdd1243dSDimitry Andric                           FormatStyle::NamespaceIndentationKind &Value) {
436bdd1243dSDimitry Andric     IO.enumCase(Value, "None", FormatStyle::NI_None);
437bdd1243dSDimitry Andric     IO.enumCase(Value, "Inner", FormatStyle::NI_Inner);
438bdd1243dSDimitry Andric     IO.enumCase(Value, "All", FormatStyle::NI_All);
439bdd1243dSDimitry Andric   }
440bdd1243dSDimitry Andric };
441bdd1243dSDimitry Andric 
4425ffd83dbSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::OperandAlignmentStyle> {
4435ffd83dbSDimitry Andric   static void enumeration(IO &IO, FormatStyle::OperandAlignmentStyle &Value) {
4445ffd83dbSDimitry Andric     IO.enumCase(Value, "DontAlign", FormatStyle::OAS_DontAlign);
4455ffd83dbSDimitry Andric     IO.enumCase(Value, "Align", FormatStyle::OAS_Align);
4465ffd83dbSDimitry Andric     IO.enumCase(Value, "AlignAfterOperator",
4475ffd83dbSDimitry Andric                 FormatStyle::OAS_AlignAfterOperator);
4485ffd83dbSDimitry Andric 
4495ffd83dbSDimitry Andric     // For backward compatibility.
4505ffd83dbSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::OAS_Align);
4515ffd83dbSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::OAS_DontAlign);
4525ffd83dbSDimitry Andric   }
4535ffd83dbSDimitry Andric };
4545ffd83dbSDimitry Andric 
455bdd1243dSDimitry Andric template <>
456bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::PackConstructorInitializersStyle> {
457bdd1243dSDimitry Andric   static void
458bdd1243dSDimitry Andric   enumeration(IO &IO, FormatStyle::PackConstructorInitializersStyle &Value) {
459bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::PCIS_Never);
460bdd1243dSDimitry Andric     IO.enumCase(Value, "BinPack", FormatStyle::PCIS_BinPack);
461bdd1243dSDimitry Andric     IO.enumCase(Value, "CurrentLine", FormatStyle::PCIS_CurrentLine);
462bdd1243dSDimitry Andric     IO.enumCase(Value, "NextLine", FormatStyle::PCIS_NextLine);
46306c3fb27SDimitry Andric     IO.enumCase(Value, "NextLineOnly", FormatStyle::PCIS_NextLineOnly);
464bdd1243dSDimitry Andric   }
465bdd1243dSDimitry Andric };
466bdd1243dSDimitry Andric 
4670b57cec5SDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
4680b57cec5SDimitry Andric   static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {
4690b57cec5SDimitry Andric     IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
4700b57cec5SDimitry Andric     IO.enumCase(Value, "Left", FormatStyle::PAS_Left);
4710b57cec5SDimitry Andric     IO.enumCase(Value, "Right", FormatStyle::PAS_Right);
4720b57cec5SDimitry Andric 
4730b57cec5SDimitry Andric     // For backward compatibility.
4740b57cec5SDimitry Andric     IO.enumCase(Value, "true", FormatStyle::PAS_Left);
4750b57cec5SDimitry Andric     IO.enumCase(Value, "false", FormatStyle::PAS_Right);
4760b57cec5SDimitry Andric   }
4770b57cec5SDimitry Andric };
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric template <>
480bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
481bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
482bdd1243dSDimitry Andric     IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
483bdd1243dSDimitry Andric     IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);
484bdd1243dSDimitry Andric     IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash);
48504eeddc0SDimitry Andric   }
48604eeddc0SDimitry Andric };
48704eeddc0SDimitry Andric 
48804eeddc0SDimitry Andric template <>
489bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::QualifierAlignmentStyle> {
490bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::QualifierAlignmentStyle &Value) {
491bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::QAS_Leave);
492bdd1243dSDimitry Andric     IO.enumCase(Value, "Left", FormatStyle::QAS_Left);
493bdd1243dSDimitry Andric     IO.enumCase(Value, "Right", FormatStyle::QAS_Right);
494bdd1243dSDimitry Andric     IO.enumCase(Value, "Custom", FormatStyle::QAS_Custom);
495bdd1243dSDimitry Andric   }
496bdd1243dSDimitry Andric };
497bdd1243dSDimitry Andric 
498bdd1243dSDimitry Andric template <> struct MappingTraits<FormatStyle::RawStringFormat> {
499bdd1243dSDimitry Andric   static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
500bdd1243dSDimitry Andric     IO.mapOptional("Language", Format.Language);
501bdd1243dSDimitry Andric     IO.mapOptional("Delimiters", Format.Delimiters);
502bdd1243dSDimitry Andric     IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);
503bdd1243dSDimitry Andric     IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter);
504bdd1243dSDimitry Andric     IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);
505e8d8bef9SDimitry Andric   }
506e8d8bef9SDimitry Andric };
507e8d8bef9SDimitry Andric 
508e8d8bef9SDimitry Andric template <>
509fe6060f1SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> {
510fe6060f1SDimitry Andric   static void enumeration(IO &IO, FormatStyle::ReferenceAlignmentStyle &Value) {
511fe6060f1SDimitry Andric     IO.enumCase(Value, "Pointer", FormatStyle::RAS_Pointer);
512fe6060f1SDimitry Andric     IO.enumCase(Value, "Middle", FormatStyle::RAS_Middle);
513fe6060f1SDimitry Andric     IO.enumCase(Value, "Left", FormatStyle::RAS_Left);
514fe6060f1SDimitry Andric     IO.enumCase(Value, "Right", FormatStyle::RAS_Right);
515fe6060f1SDimitry Andric   }
516fe6060f1SDimitry Andric };
517fe6060f1SDimitry Andric 
518fe6060f1SDimitry Andric template <>
51906c3fb27SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::RemoveParenthesesStyle> {
52006c3fb27SDimitry Andric   static void enumeration(IO &IO, FormatStyle::RemoveParenthesesStyle &Value) {
52106c3fb27SDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::RPS_Leave);
52206c3fb27SDimitry Andric     IO.enumCase(Value, "MultipleParentheses",
52306c3fb27SDimitry Andric                 FormatStyle::RPS_MultipleParentheses);
52406c3fb27SDimitry Andric     IO.enumCase(Value, "ReturnStatement", FormatStyle::RPS_ReturnStatement);
52506c3fb27SDimitry Andric   }
52606c3fb27SDimitry Andric };
52706c3fb27SDimitry Andric 
52806c3fb27SDimitry Andric template <>
52981ad6265SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::RequiresClausePositionStyle> {
53081ad6265SDimitry Andric   static void enumeration(IO &IO,
53181ad6265SDimitry Andric                           FormatStyle::RequiresClausePositionStyle &Value) {
53281ad6265SDimitry Andric     IO.enumCase(Value, "OwnLine", FormatStyle::RCPS_OwnLine);
53381ad6265SDimitry Andric     IO.enumCase(Value, "WithPreceding", FormatStyle::RCPS_WithPreceding);
53481ad6265SDimitry Andric     IO.enumCase(Value, "WithFollowing", FormatStyle::RCPS_WithFollowing);
53581ad6265SDimitry Andric     IO.enumCase(Value, "SingleLine", FormatStyle::RCPS_SingleLine);
53681ad6265SDimitry Andric   }
53781ad6265SDimitry Andric };
53881ad6265SDimitry Andric 
53981ad6265SDimitry Andric template <>
540bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::RequiresExpressionIndentationKind> {
541bdd1243dSDimitry Andric   static void
542bdd1243dSDimitry Andric   enumeration(IO &IO, FormatStyle::RequiresExpressionIndentationKind &Value) {
543bdd1243dSDimitry Andric     IO.enumCase(Value, "Keyword", FormatStyle::REI_Keyword);
544bdd1243dSDimitry Andric     IO.enumCase(Value, "OuterScope", FormatStyle::REI_OuterScope);
5450b57cec5SDimitry Andric   }
5460b57cec5SDimitry Andric };
5470b57cec5SDimitry Andric 
548e8d8bef9SDimitry Andric template <>
549bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
550bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
551bdd1243dSDimitry Andric     IO.enumCase(Value, "None", FormatStyle::RTBS_None);
552*0fca6ea1SDimitry Andric     IO.enumCase(Value, "Automatic", FormatStyle::RTBS_Automatic);
553*0fca6ea1SDimitry Andric     IO.enumCase(Value, "ExceptShortType", FormatStyle::RTBS_ExceptShortType);
554bdd1243dSDimitry Andric     IO.enumCase(Value, "All", FormatStyle::RTBS_All);
555bdd1243dSDimitry Andric     IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel);
556bdd1243dSDimitry Andric     IO.enumCase(Value, "TopLevelDefinitions",
557bdd1243dSDimitry Andric                 FormatStyle::RTBS_TopLevelDefinitions);
558bdd1243dSDimitry Andric     IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions);
559bdd1243dSDimitry Andric   }
560bdd1243dSDimitry Andric };
561bdd1243dSDimitry Andric 
562bdd1243dSDimitry Andric template <>
563bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::SeparateDefinitionStyle> {
564bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::SeparateDefinitionStyle &Value) {
565bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::SDS_Leave);
566bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::SDS_Always);
567bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::SDS_Never);
568bdd1243dSDimitry Andric   }
569bdd1243dSDimitry Andric };
570bdd1243dSDimitry Andric 
571bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> {
572bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) {
573bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::SBS_Never);
574bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::SBS_Never);
575bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::SBS_Always);
576bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::SBS_Always);
577bdd1243dSDimitry Andric     IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty);
578bdd1243dSDimitry Andric   }
579bdd1243dSDimitry Andric };
580bdd1243dSDimitry Andric 
581bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
582bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
583bdd1243dSDimitry Andric     IO.enumCase(Value, "None", FormatStyle::SFS_None);
584bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::SFS_None);
585bdd1243dSDimitry Andric     IO.enumCase(Value, "All", FormatStyle::SFS_All);
586bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::SFS_All);
587bdd1243dSDimitry Andric     IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
588bdd1243dSDimitry Andric     IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly);
589bdd1243dSDimitry Andric     IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);
590bdd1243dSDimitry Andric   }
591bdd1243dSDimitry Andric };
592bdd1243dSDimitry Andric 
593bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> {
594bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) {
595bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::SIS_Never);
596bdd1243dSDimitry Andric     IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse);
597bdd1243dSDimitry Andric     IO.enumCase(Value, "OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf);
598bdd1243dSDimitry Andric     IO.enumCase(Value, "AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse);
599bdd1243dSDimitry Andric 
600bdd1243dSDimitry Andric     // For backward compatibility.
601bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::SIS_OnlyFirstIf);
602bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::SIS_Never);
603bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse);
604bdd1243dSDimitry Andric   }
605bdd1243dSDimitry Andric };
606bdd1243dSDimitry Andric 
607bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> {
608bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) {
609bdd1243dSDimitry Andric     IO.enumCase(Value, "None", FormatStyle::SLS_None);
610bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::SLS_None);
611bdd1243dSDimitry Andric     IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty);
612bdd1243dSDimitry Andric     IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline);
613bdd1243dSDimitry Andric     IO.enumCase(Value, "All", FormatStyle::SLS_All);
614bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::SLS_All);
615e8d8bef9SDimitry Andric   }
616e8d8bef9SDimitry Andric };
617e8d8bef9SDimitry Andric 
618fe6060f1SDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::SortIncludesOptions> {
619fe6060f1SDimitry Andric   static void enumeration(IO &IO, FormatStyle::SortIncludesOptions &Value) {
620fe6060f1SDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::SI_Never);
621fe6060f1SDimitry Andric     IO.enumCase(Value, "CaseInsensitive", FormatStyle::SI_CaseInsensitive);
622fe6060f1SDimitry Andric     IO.enumCase(Value, "CaseSensitive", FormatStyle::SI_CaseSensitive);
623fe6060f1SDimitry Andric 
624fe6060f1SDimitry Andric     // For backward compatibility.
625fe6060f1SDimitry Andric     IO.enumCase(Value, "false", FormatStyle::SI_Never);
626fe6060f1SDimitry Andric     IO.enumCase(Value, "true", FormatStyle::SI_CaseSensitive);
627fe6060f1SDimitry Andric   }
628fe6060f1SDimitry Andric };
629fe6060f1SDimitry Andric 
630e8d8bef9SDimitry Andric template <>
631e8d8bef9SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> {
632e8d8bef9SDimitry Andric   static void enumeration(IO &IO,
633e8d8bef9SDimitry Andric                           FormatStyle::SortJavaStaticImportOptions &Value) {
634e8d8bef9SDimitry Andric     IO.enumCase(Value, "Before", FormatStyle::SJSIO_Before);
635e8d8bef9SDimitry Andric     IO.enumCase(Value, "After", FormatStyle::SJSIO_After);
636e8d8bef9SDimitry Andric   }
637e8d8bef9SDimitry Andric };
638e8d8bef9SDimitry Andric 
639bdd1243dSDimitry Andric template <>
640bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::SortUsingDeclarationsOptions> {
641bdd1243dSDimitry Andric   static void enumeration(IO &IO,
642bdd1243dSDimitry Andric                           FormatStyle::SortUsingDeclarationsOptions &Value) {
643bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::SUD_Never);
644bdd1243dSDimitry Andric     IO.enumCase(Value, "Lexicographic", FormatStyle::SUD_Lexicographic);
645bdd1243dSDimitry Andric     IO.enumCase(Value, "LexicographicNumeric",
646bdd1243dSDimitry Andric                 FormatStyle::SUD_LexicographicNumeric);
647fe6060f1SDimitry Andric 
648fe6060f1SDimitry Andric     // For backward compatibility.
649bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::SUD_Never);
650bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::SUD_LexicographicNumeric);
651fe6060f1SDimitry Andric   }
652fe6060f1SDimitry Andric };
653fe6060f1SDimitry Andric 
654bdd1243dSDimitry Andric template <>
655bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> {
656bdd1243dSDimitry Andric   static void
657bdd1243dSDimitry Andric   enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value) {
658bdd1243dSDimitry Andric     IO.enumCase(Value, "Default", FormatStyle::SAPQ_Default);
659bdd1243dSDimitry Andric     IO.enumCase(Value, "Before", FormatStyle::SAPQ_Before);
660bdd1243dSDimitry Andric     IO.enumCase(Value, "After", FormatStyle::SAPQ_After);
661bdd1243dSDimitry Andric     IO.enumCase(Value, "Both", FormatStyle::SAPQ_Both);
6620b57cec5SDimitry Andric   }
6630b57cec5SDimitry Andric };
6640b57cec5SDimitry Andric 
665349cc55cSDimitry Andric template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> {
666349cc55cSDimitry Andric   static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) {
667349cc55cSDimitry Andric     IO.mapOptional("AfterControlStatements", Spacing.AfterControlStatements);
668349cc55cSDimitry Andric     IO.mapOptional("AfterForeachMacros", Spacing.AfterForeachMacros);
669349cc55cSDimitry Andric     IO.mapOptional("AfterFunctionDefinitionName",
670349cc55cSDimitry Andric                    Spacing.AfterFunctionDefinitionName);
671349cc55cSDimitry Andric     IO.mapOptional("AfterFunctionDeclarationName",
672349cc55cSDimitry Andric                    Spacing.AfterFunctionDeclarationName);
673349cc55cSDimitry Andric     IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros);
67404eeddc0SDimitry Andric     IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
6755f757f3fSDimitry Andric     IO.mapOptional("AfterPlacementOperator", Spacing.AfterPlacementOperator);
67681ad6265SDimitry Andric     IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause);
67781ad6265SDimitry Andric     IO.mapOptional("AfterRequiresInExpression",
67881ad6265SDimitry Andric                    Spacing.AfterRequiresInExpression);
679349cc55cSDimitry Andric     IO.mapOptional("BeforeNonEmptyParentheses",
680349cc55cSDimitry Andric                    Spacing.BeforeNonEmptyParentheses);
681349cc55cSDimitry Andric   }
682349cc55cSDimitry Andric };
683349cc55cSDimitry Andric 
684bdd1243dSDimitry Andric template <>
685bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> {
686bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::SpaceBeforeParensStyle &Value) {
687bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
688bdd1243dSDimitry Andric     IO.enumCase(Value, "ControlStatements",
689bdd1243dSDimitry Andric                 FormatStyle::SBPO_ControlStatements);
690bdd1243dSDimitry Andric     IO.enumCase(Value, "ControlStatementsExceptControlMacros",
691bdd1243dSDimitry Andric                 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
692bdd1243dSDimitry Andric     IO.enumCase(Value, "NonEmptyParentheses",
693bdd1243dSDimitry Andric                 FormatStyle::SBPO_NonEmptyParentheses);
694bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
695bdd1243dSDimitry Andric     IO.enumCase(Value, "Custom", FormatStyle::SBPO_Custom);
696bdd1243dSDimitry Andric 
697bdd1243dSDimitry Andric     // For backward compatibility.
698bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
699bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);
700bdd1243dSDimitry Andric     IO.enumCase(Value, "ControlStatementsExceptForEachMacros",
701bdd1243dSDimitry Andric                 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
702bdd1243dSDimitry Andric   }
703bdd1243dSDimitry Andric };
704bdd1243dSDimitry Andric 
705bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> {
706bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value) {
707bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::SIAS_Never);
708bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::SIAS_Always);
709bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::SIAS_Leave);
710bdd1243dSDimitry Andric 
711bdd1243dSDimitry Andric     // For backward compatibility.
712bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::SIAS_Never);
713bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::SIAS_Always);
7140b57cec5SDimitry Andric   }
7150b57cec5SDimitry Andric };
7160b57cec5SDimitry Andric 
717fe6060f1SDimitry Andric template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {
718fe6060f1SDimitry Andric   static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
719fe6060f1SDimitry Andric     // Transform the maximum to signed, to parse "-1" correctly
720fe6060f1SDimitry Andric     int signedMaximum = static_cast<int>(Space.Maximum);
721fe6060f1SDimitry Andric     IO.mapOptional("Minimum", Space.Minimum);
722fe6060f1SDimitry Andric     IO.mapOptional("Maximum", signedMaximum);
723fe6060f1SDimitry Andric     Space.Maximum = static_cast<unsigned>(signedMaximum);
724fe6060f1SDimitry Andric 
72581ad6265SDimitry Andric     if (Space.Maximum != -1u)
726fe6060f1SDimitry Andric       Space.Minimum = std::min(Space.Minimum, Space.Maximum);
727fe6060f1SDimitry Andric   }
728fe6060f1SDimitry Andric };
729fe6060f1SDimitry Andric 
73006c3fb27SDimitry Andric template <> struct MappingTraits<FormatStyle::SpacesInParensCustom> {
73106c3fb27SDimitry Andric   static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) {
732*0fca6ea1SDimitry Andric     IO.mapOptional("ExceptDoubleParentheses", Spaces.ExceptDoubleParentheses);
73306c3fb27SDimitry Andric     IO.mapOptional("InCStyleCasts", Spaces.InCStyleCasts);
73406c3fb27SDimitry Andric     IO.mapOptional("InConditionalStatements", Spaces.InConditionalStatements);
73506c3fb27SDimitry Andric     IO.mapOptional("InEmptyParentheses", Spaces.InEmptyParentheses);
73606c3fb27SDimitry Andric     IO.mapOptional("Other", Spaces.Other);
73706c3fb27SDimitry Andric   }
73806c3fb27SDimitry Andric };
73906c3fb27SDimitry Andric 
74006c3fb27SDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInParensStyle> {
74106c3fb27SDimitry Andric   static void enumeration(IO &IO, FormatStyle::SpacesInParensStyle &Value) {
74206c3fb27SDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::SIPO_Never);
74306c3fb27SDimitry Andric     IO.enumCase(Value, "Custom", FormatStyle::SIPO_Custom);
74406c3fb27SDimitry Andric   }
74506c3fb27SDimitry Andric };
74606c3fb27SDimitry Andric 
747bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::TrailingCommaStyle> {
748bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) {
749bdd1243dSDimitry Andric     IO.enumCase(Value, "None", FormatStyle::TCS_None);
750bdd1243dSDimitry Andric     IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped);
751bdd1243dSDimitry Andric   }
752bdd1243dSDimitry Andric };
753bdd1243dSDimitry Andric 
754bdd1243dSDimitry Andric template <>
755bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::TrailingCommentsAlignmentKinds> {
756bdd1243dSDimitry Andric   static void enumeration(IO &IO,
757bdd1243dSDimitry Andric                           FormatStyle::TrailingCommentsAlignmentKinds &Value) {
758bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::TCAS_Leave);
759bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::TCAS_Always);
760bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::TCAS_Never);
761bdd1243dSDimitry Andric   }
762bdd1243dSDimitry Andric };
763bdd1243dSDimitry Andric 
764bdd1243dSDimitry Andric template <> struct MappingTraits<FormatStyle::TrailingCommentsAlignmentStyle> {
765bdd1243dSDimitry Andric   static void enumInput(IO &IO,
766bdd1243dSDimitry Andric                         FormatStyle::TrailingCommentsAlignmentStyle &Value) {
767bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave",
768bdd1243dSDimitry Andric                 FormatStyle::TrailingCommentsAlignmentStyle(
7699e7101a8SDimitry Andric                     {FormatStyle::TCAS_Leave, 0}));
770bdd1243dSDimitry Andric 
771bdd1243dSDimitry Andric     IO.enumCase(Value, "Always",
772bdd1243dSDimitry Andric                 FormatStyle::TrailingCommentsAlignmentStyle(
7739e7101a8SDimitry Andric                     {FormatStyle::TCAS_Always, 0}));
774bdd1243dSDimitry Andric 
775bdd1243dSDimitry Andric     IO.enumCase(Value, "Never",
776bdd1243dSDimitry Andric                 FormatStyle::TrailingCommentsAlignmentStyle(
7779e7101a8SDimitry Andric                     {FormatStyle::TCAS_Never, 0}));
778bdd1243dSDimitry Andric 
779bdd1243dSDimitry Andric     // For backwards compatibility
780bdd1243dSDimitry Andric     IO.enumCase(Value, "true",
781bdd1243dSDimitry Andric                 FormatStyle::TrailingCommentsAlignmentStyle(
7829e7101a8SDimitry Andric                     {FormatStyle::TCAS_Always, 0}));
783bdd1243dSDimitry Andric     IO.enumCase(Value, "false",
784bdd1243dSDimitry Andric                 FormatStyle::TrailingCommentsAlignmentStyle(
7859e7101a8SDimitry Andric                     {FormatStyle::TCAS_Never, 0}));
786bdd1243dSDimitry Andric   }
787bdd1243dSDimitry Andric 
788bdd1243dSDimitry Andric   static void mapping(IO &IO,
789bdd1243dSDimitry Andric                       FormatStyle::TrailingCommentsAlignmentStyle &Value) {
790bdd1243dSDimitry Andric     IO.mapOptional("Kind", Value.Kind);
791bdd1243dSDimitry Andric     IO.mapOptional("OverEmptyLines", Value.OverEmptyLines);
792bdd1243dSDimitry Andric   }
793bdd1243dSDimitry Andric };
794bdd1243dSDimitry Andric 
795bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
796bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {
797bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::UT_Never);
798bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::UT_Never);
799bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::UT_Always);
800bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::UT_Always);
801bdd1243dSDimitry Andric     IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation);
802bdd1243dSDimitry Andric     IO.enumCase(Value, "ForContinuationAndIndentation",
803bdd1243dSDimitry Andric                 FormatStyle::UT_ForContinuationAndIndentation);
804bdd1243dSDimitry Andric     IO.enumCase(Value, "AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);
805bdd1243dSDimitry Andric   }
806bdd1243dSDimitry Andric };
807bdd1243dSDimitry Andric 
808bdd1243dSDimitry Andric template <> struct MappingTraits<FormatStyle> {
809bdd1243dSDimitry Andric   static void mapping(IO &IO, FormatStyle &Style) {
810bdd1243dSDimitry Andric     // When reading, read the language first, we need it for getPredefinedStyle.
811bdd1243dSDimitry Andric     IO.mapOptional("Language", Style.Language);
812bdd1243dSDimitry Andric 
813bdd1243dSDimitry Andric     StringRef BasedOnStyle;
814bdd1243dSDimitry Andric     if (IO.outputting()) {
815bdd1243dSDimitry Andric       StringRef Styles[] = {"LLVM",   "Google", "Chromium",  "Mozilla",
8165f757f3fSDimitry Andric                             "WebKit", "GNU",    "Microsoft", "clang-format"};
817bdd1243dSDimitry Andric       for (StringRef StyleName : Styles) {
818bdd1243dSDimitry Andric         FormatStyle PredefinedStyle;
819bdd1243dSDimitry Andric         if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) &&
820bdd1243dSDimitry Andric             Style == PredefinedStyle) {
821bdd1243dSDimitry Andric           BasedOnStyle = StyleName;
822bdd1243dSDimitry Andric           break;
823bdd1243dSDimitry Andric         }
824bdd1243dSDimitry Andric       }
825bdd1243dSDimitry Andric     } else {
826bdd1243dSDimitry Andric       IO.mapOptional("BasedOnStyle", BasedOnStyle);
827bdd1243dSDimitry Andric       if (!BasedOnStyle.empty()) {
828bdd1243dSDimitry Andric         FormatStyle::LanguageKind OldLanguage = Style.Language;
829bdd1243dSDimitry Andric         FormatStyle::LanguageKind Language =
830bdd1243dSDimitry Andric             ((FormatStyle *)IO.getContext())->Language;
831bdd1243dSDimitry Andric         if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
832bdd1243dSDimitry Andric           IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle));
833bdd1243dSDimitry Andric           return;
834bdd1243dSDimitry Andric         }
835bdd1243dSDimitry Andric         Style.Language = OldLanguage;
836bdd1243dSDimitry Andric       }
837bdd1243dSDimitry Andric     }
838bdd1243dSDimitry Andric 
839bdd1243dSDimitry Andric     // Initialize some variables used in the parsing. The using logic is at the
840bdd1243dSDimitry Andric     // end.
841bdd1243dSDimitry Andric 
842bdd1243dSDimitry Andric     // For backward compatibility:
843bdd1243dSDimitry Andric     // The default value of ConstructorInitializerAllOnOneLineOrOnePerLine was
844bdd1243dSDimitry Andric     // false unless BasedOnStyle was Google or Chromium whereas that of
845bdd1243dSDimitry Andric     // AllowAllConstructorInitializersOnNextLine was always true, so the
846bdd1243dSDimitry Andric     // equivalent default value of PackConstructorInitializers is PCIS_NextLine
847bdd1243dSDimitry Andric     // for Google/Chromium or PCIS_BinPack otherwise. If the deprecated options
848bdd1243dSDimitry Andric     // had a non-default value while PackConstructorInitializers has a default
849bdd1243dSDimitry Andric     // value, set the latter to an equivalent non-default value if needed.
850bdd1243dSDimitry Andric     const bool IsGoogleOrChromium = BasedOnStyle.equals_insensitive("google") ||
851bdd1243dSDimitry Andric                                     BasedOnStyle.equals_insensitive("chromium");
852bdd1243dSDimitry Andric     bool OnCurrentLine = IsGoogleOrChromium;
853bdd1243dSDimitry Andric     bool OnNextLine = true;
854bdd1243dSDimitry Andric 
855bdd1243dSDimitry Andric     bool BreakBeforeInheritanceComma = false;
856bdd1243dSDimitry Andric     bool BreakConstructorInitializersBeforeComma = false;
857bdd1243dSDimitry Andric 
858bdd1243dSDimitry Andric     bool DeriveLineEnding = true;
859bdd1243dSDimitry Andric     bool UseCRLF = false;
860bdd1243dSDimitry Andric 
86106c3fb27SDimitry Andric     bool SpaceInEmptyParentheses = false;
86206c3fb27SDimitry Andric     bool SpacesInConditionalStatement = false;
86306c3fb27SDimitry Andric     bool SpacesInCStyleCastParentheses = false;
86406c3fb27SDimitry Andric     bool SpacesInParentheses = false;
86506c3fb27SDimitry Andric 
866bdd1243dSDimitry Andric     // For backward compatibility.
867bdd1243dSDimitry Andric     if (!IO.outputting()) {
868bdd1243dSDimitry Andric       IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines);
869bdd1243dSDimitry Andric       IO.mapOptional("AllowAllConstructorInitializersOnNextLine", OnNextLine);
870*0fca6ea1SDimitry Andric       IO.mapOptional("AlwaysBreakAfterReturnType", Style.BreakAfterReturnType);
871*0fca6ea1SDimitry Andric       IO.mapOptional("AlwaysBreakTemplateDeclarations",
872*0fca6ea1SDimitry Andric                      Style.BreakTemplateDeclarations);
873bdd1243dSDimitry Andric       IO.mapOptional("BreakBeforeInheritanceComma",
874bdd1243dSDimitry Andric                      BreakBeforeInheritanceComma);
875bdd1243dSDimitry Andric       IO.mapOptional("BreakConstructorInitializersBeforeComma",
876bdd1243dSDimitry Andric                      BreakConstructorInitializersBeforeComma);
877bdd1243dSDimitry Andric       IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
878bdd1243dSDimitry Andric                      OnCurrentLine);
879bdd1243dSDimitry Andric       IO.mapOptional("DeriveLineEnding", DeriveLineEnding);
880bdd1243dSDimitry Andric       IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
881*0fca6ea1SDimitry Andric       IO.mapOptional("KeepEmptyLinesAtEOF", Style.KeepEmptyLines.AtEndOfFile);
882*0fca6ea1SDimitry Andric       IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
883*0fca6ea1SDimitry Andric                      Style.KeepEmptyLines.AtStartOfBlock);
884bdd1243dSDimitry Andric       IO.mapOptional("IndentFunctionDeclarationAfterType",
885bdd1243dSDimitry Andric                      Style.IndentWrappedFunctionNames);
886bdd1243dSDimitry Andric       IO.mapOptional("IndentRequires", Style.IndentRequiresClause);
887bdd1243dSDimitry Andric       IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
888bdd1243dSDimitry Andric       IO.mapOptional("SpaceAfterControlStatementKeyword",
889bdd1243dSDimitry Andric                      Style.SpaceBeforeParens);
89006c3fb27SDimitry Andric       IO.mapOptional("SpaceInEmptyParentheses", SpaceInEmptyParentheses);
89106c3fb27SDimitry Andric       IO.mapOptional("SpacesInConditionalStatement",
89206c3fb27SDimitry Andric                      SpacesInConditionalStatement);
89306c3fb27SDimitry Andric       IO.mapOptional("SpacesInCStyleCastParentheses",
89406c3fb27SDimitry Andric                      SpacesInCStyleCastParentheses);
89506c3fb27SDimitry Andric       IO.mapOptional("SpacesInParentheses", SpacesInParentheses);
896bdd1243dSDimitry Andric       IO.mapOptional("UseCRLF", UseCRLF);
897bdd1243dSDimitry Andric     }
898bdd1243dSDimitry Andric 
899bdd1243dSDimitry Andric     IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
900bdd1243dSDimitry Andric     IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
901bdd1243dSDimitry Andric     IO.mapOptional("AlignArrayOfStructures", Style.AlignArrayOfStructures);
902bdd1243dSDimitry Andric     IO.mapOptional("AlignConsecutiveAssignments",
903bdd1243dSDimitry Andric                    Style.AlignConsecutiveAssignments);
904bdd1243dSDimitry Andric     IO.mapOptional("AlignConsecutiveBitFields",
905bdd1243dSDimitry Andric                    Style.AlignConsecutiveBitFields);
906bdd1243dSDimitry Andric     IO.mapOptional("AlignConsecutiveDeclarations",
907bdd1243dSDimitry Andric                    Style.AlignConsecutiveDeclarations);
908bdd1243dSDimitry Andric     IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);
90906c3fb27SDimitry Andric     IO.mapOptional("AlignConsecutiveShortCaseStatements",
91006c3fb27SDimitry Andric                    Style.AlignConsecutiveShortCaseStatements);
911*0fca6ea1SDimitry Andric     IO.mapOptional("AlignConsecutiveTableGenBreakingDAGArgColons",
912*0fca6ea1SDimitry Andric                    Style.AlignConsecutiveTableGenBreakingDAGArgColons);
913*0fca6ea1SDimitry Andric     IO.mapOptional("AlignConsecutiveTableGenCondOperatorColons",
914*0fca6ea1SDimitry Andric                    Style.AlignConsecutiveTableGenCondOperatorColons);
915*0fca6ea1SDimitry Andric     IO.mapOptional("AlignConsecutiveTableGenDefinitionColons",
916*0fca6ea1SDimitry Andric                    Style.AlignConsecutiveTableGenDefinitionColons);
917bdd1243dSDimitry Andric     IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines);
918bdd1243dSDimitry Andric     IO.mapOptional("AlignOperands", Style.AlignOperands);
919bdd1243dSDimitry Andric     IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
920bdd1243dSDimitry Andric     IO.mapOptional("AllowAllArgumentsOnNextLine",
921bdd1243dSDimitry Andric                    Style.AllowAllArgumentsOnNextLine);
922bdd1243dSDimitry Andric     IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
923bdd1243dSDimitry Andric                    Style.AllowAllParametersOfDeclarationOnNextLine);
9245f757f3fSDimitry Andric     IO.mapOptional("AllowBreakBeforeNoexceptSpecifier",
9255f757f3fSDimitry Andric                    Style.AllowBreakBeforeNoexceptSpecifier);
926bdd1243dSDimitry Andric     IO.mapOptional("AllowShortBlocksOnASingleLine",
927bdd1243dSDimitry Andric                    Style.AllowShortBlocksOnASingleLine);
928*0fca6ea1SDimitry Andric     IO.mapOptional("AllowShortCaseExpressionOnASingleLine",
929*0fca6ea1SDimitry Andric                    Style.AllowShortCaseExpressionOnASingleLine);
930bdd1243dSDimitry Andric     IO.mapOptional("AllowShortCaseLabelsOnASingleLine",
931bdd1243dSDimitry Andric                    Style.AllowShortCaseLabelsOnASingleLine);
9325f757f3fSDimitry Andric     IO.mapOptional("AllowShortCompoundRequirementOnASingleLine",
9335f757f3fSDimitry Andric                    Style.AllowShortCompoundRequirementOnASingleLine);
934bdd1243dSDimitry Andric     IO.mapOptional("AllowShortEnumsOnASingleLine",
935bdd1243dSDimitry Andric                    Style.AllowShortEnumsOnASingleLine);
936bdd1243dSDimitry Andric     IO.mapOptional("AllowShortFunctionsOnASingleLine",
937bdd1243dSDimitry Andric                    Style.AllowShortFunctionsOnASingleLine);
938bdd1243dSDimitry Andric     IO.mapOptional("AllowShortIfStatementsOnASingleLine",
939bdd1243dSDimitry Andric                    Style.AllowShortIfStatementsOnASingleLine);
940bdd1243dSDimitry Andric     IO.mapOptional("AllowShortLambdasOnASingleLine",
941bdd1243dSDimitry Andric                    Style.AllowShortLambdasOnASingleLine);
942bdd1243dSDimitry Andric     IO.mapOptional("AllowShortLoopsOnASingleLine",
943bdd1243dSDimitry Andric                    Style.AllowShortLoopsOnASingleLine);
944bdd1243dSDimitry Andric     IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",
945bdd1243dSDimitry Andric                    Style.AlwaysBreakAfterDefinitionReturnType);
946bdd1243dSDimitry Andric     IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
947bdd1243dSDimitry Andric                    Style.AlwaysBreakBeforeMultilineStrings);
948bdd1243dSDimitry Andric     IO.mapOptional("AttributeMacros", Style.AttributeMacros);
949bdd1243dSDimitry Andric     IO.mapOptional("BinPackArguments", Style.BinPackArguments);
950bdd1243dSDimitry Andric     IO.mapOptional("BinPackParameters", Style.BinPackParameters);
951bdd1243dSDimitry Andric     IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing);
95206c3fb27SDimitry Andric     IO.mapOptional("BracedInitializerIndentWidth",
95306c3fb27SDimitry Andric                    Style.BracedInitializerIndentWidth);
954bdd1243dSDimitry Andric     IO.mapOptional("BraceWrapping", Style.BraceWrapping);
9555f757f3fSDimitry Andric     IO.mapOptional("BreakAdjacentStringLiterals",
9565f757f3fSDimitry Andric                    Style.BreakAdjacentStringLiterals);
957bdd1243dSDimitry Andric     IO.mapOptional("BreakAfterAttributes", Style.BreakAfterAttributes);
958bdd1243dSDimitry Andric     IO.mapOptional("BreakAfterJavaFieldAnnotations",
959bdd1243dSDimitry Andric                    Style.BreakAfterJavaFieldAnnotations);
960*0fca6ea1SDimitry Andric     IO.mapOptional("BreakAfterReturnType", Style.BreakAfterReturnType);
961bdd1243dSDimitry Andric     IO.mapOptional("BreakArrays", Style.BreakArrays);
962bdd1243dSDimitry Andric     IO.mapOptional("BreakBeforeBinaryOperators",
963bdd1243dSDimitry Andric                    Style.BreakBeforeBinaryOperators);
964bdd1243dSDimitry Andric     IO.mapOptional("BreakBeforeConceptDeclarations",
965bdd1243dSDimitry Andric                    Style.BreakBeforeConceptDeclarations);
966bdd1243dSDimitry Andric     IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
967bdd1243dSDimitry Andric     IO.mapOptional("BreakBeforeInlineASMColon",
968bdd1243dSDimitry Andric                    Style.BreakBeforeInlineASMColon);
969bdd1243dSDimitry Andric     IO.mapOptional("BreakBeforeTernaryOperators",
970bdd1243dSDimitry Andric                    Style.BreakBeforeTernaryOperators);
971bdd1243dSDimitry Andric     IO.mapOptional("BreakConstructorInitializers",
972bdd1243dSDimitry Andric                    Style.BreakConstructorInitializers);
973*0fca6ea1SDimitry Andric     IO.mapOptional("BreakFunctionDefinitionParameters",
974*0fca6ea1SDimitry Andric                    Style.BreakFunctionDefinitionParameters);
975bdd1243dSDimitry Andric     IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList);
976bdd1243dSDimitry Andric     IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
977*0fca6ea1SDimitry Andric     IO.mapOptional("BreakTemplateDeclarations",
978*0fca6ea1SDimitry Andric                    Style.BreakTemplateDeclarations);
979bdd1243dSDimitry Andric     IO.mapOptional("ColumnLimit", Style.ColumnLimit);
980bdd1243dSDimitry Andric     IO.mapOptional("CommentPragmas", Style.CommentPragmas);
981bdd1243dSDimitry Andric     IO.mapOptional("CompactNamespaces", Style.CompactNamespaces);
982bdd1243dSDimitry Andric     IO.mapOptional("ConstructorInitializerIndentWidth",
983bdd1243dSDimitry Andric                    Style.ConstructorInitializerIndentWidth);
984bdd1243dSDimitry Andric     IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
985bdd1243dSDimitry Andric     IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
986bdd1243dSDimitry Andric     IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
987bdd1243dSDimitry Andric     IO.mapOptional("DisableFormat", Style.DisableFormat);
988bdd1243dSDimitry Andric     IO.mapOptional("EmptyLineAfterAccessModifier",
989bdd1243dSDimitry Andric                    Style.EmptyLineAfterAccessModifier);
990bdd1243dSDimitry Andric     IO.mapOptional("EmptyLineBeforeAccessModifier",
991bdd1243dSDimitry Andric                    Style.EmptyLineBeforeAccessModifier);
992bdd1243dSDimitry Andric     IO.mapOptional("ExperimentalAutoDetectBinPacking",
993bdd1243dSDimitry Andric                    Style.ExperimentalAutoDetectBinPacking);
994bdd1243dSDimitry Andric     IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
995bdd1243dSDimitry Andric     IO.mapOptional("ForEachMacros", Style.ForEachMacros);
996bdd1243dSDimitry Andric     IO.mapOptional("IfMacros", Style.IfMacros);
997bdd1243dSDimitry Andric     IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
998bdd1243dSDimitry Andric     IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
999bdd1243dSDimitry Andric     IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
1000bdd1243dSDimitry Andric     IO.mapOptional("IncludeIsMainSourceRegex",
1001bdd1243dSDimitry Andric                    Style.IncludeStyle.IncludeIsMainSourceRegex);
1002bdd1243dSDimitry Andric     IO.mapOptional("IndentAccessModifiers", Style.IndentAccessModifiers);
1003bdd1243dSDimitry Andric     IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks);
1004bdd1243dSDimitry Andric     IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
1005bdd1243dSDimitry Andric     IO.mapOptional("IndentExternBlock", Style.IndentExternBlock);
1006bdd1243dSDimitry Andric     IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels);
1007bdd1243dSDimitry Andric     IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
1008bdd1243dSDimitry Andric     IO.mapOptional("IndentRequiresClause", Style.IndentRequiresClause);
1009bdd1243dSDimitry Andric     IO.mapOptional("IndentWidth", Style.IndentWidth);
1010bdd1243dSDimitry Andric     IO.mapOptional("IndentWrappedFunctionNames",
1011bdd1243dSDimitry Andric                    Style.IndentWrappedFunctionNames);
1012bdd1243dSDimitry Andric     IO.mapOptional("InsertBraces", Style.InsertBraces);
1013bdd1243dSDimitry Andric     IO.mapOptional("InsertNewlineAtEOF", Style.InsertNewlineAtEOF);
1014bdd1243dSDimitry Andric     IO.mapOptional("InsertTrailingCommas", Style.InsertTrailingCommas);
1015bdd1243dSDimitry Andric     IO.mapOptional("IntegerLiteralSeparator", Style.IntegerLiteralSeparator);
1016bdd1243dSDimitry Andric     IO.mapOptional("JavaImportGroups", Style.JavaImportGroups);
1017bdd1243dSDimitry Andric     IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);
1018bdd1243dSDimitry Andric     IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
1019*0fca6ea1SDimitry Andric     IO.mapOptional("KeepEmptyLines", Style.KeepEmptyLines);
1020bdd1243dSDimitry Andric     IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation);
1021bdd1243dSDimitry Andric     IO.mapOptional("LineEnding", Style.LineEnding);
1022bdd1243dSDimitry Andric     IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
1023bdd1243dSDimitry Andric     IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);
10245f757f3fSDimitry Andric     IO.mapOptional("Macros", Style.Macros);
1025*0fca6ea1SDimitry Andric     IO.mapOptional("MainIncludeChar", Style.IncludeStyle.MainIncludeChar);
1026bdd1243dSDimitry Andric     IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
1027bdd1243dSDimitry Andric     IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
1028bdd1243dSDimitry Andric     IO.mapOptional("NamespaceMacros", Style.NamespaceMacros);
1029bdd1243dSDimitry Andric     IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList);
1030bdd1243dSDimitry Andric     IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);
1031bdd1243dSDimitry Andric     IO.mapOptional("ObjCBreakBeforeNestedBlockParam",
1032bdd1243dSDimitry Andric                    Style.ObjCBreakBeforeNestedBlockParam);
10335f757f3fSDimitry Andric     IO.mapOptional("ObjCPropertyAttributeOrder",
10345f757f3fSDimitry Andric                    Style.ObjCPropertyAttributeOrder);
1035bdd1243dSDimitry Andric     IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
1036bdd1243dSDimitry Andric     IO.mapOptional("ObjCSpaceBeforeProtocolList",
1037bdd1243dSDimitry Andric                    Style.ObjCSpaceBeforeProtocolList);
1038bdd1243dSDimitry Andric     IO.mapOptional("PackConstructorInitializers",
1039bdd1243dSDimitry Andric                    Style.PackConstructorInitializers);
1040bdd1243dSDimitry Andric     IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment);
1041bdd1243dSDimitry Andric     IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",
1042bdd1243dSDimitry Andric                    Style.PenaltyBreakBeforeFirstCallParameter);
1043bdd1243dSDimitry Andric     IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
1044bdd1243dSDimitry Andric     IO.mapOptional("PenaltyBreakFirstLessLess",
1045bdd1243dSDimitry Andric                    Style.PenaltyBreakFirstLessLess);
1046bdd1243dSDimitry Andric     IO.mapOptional("PenaltyBreakOpenParenthesis",
1047bdd1243dSDimitry Andric                    Style.PenaltyBreakOpenParenthesis);
10487a6dacacSDimitry Andric     IO.mapOptional("PenaltyBreakScopeResolution",
10497a6dacacSDimitry Andric                    Style.PenaltyBreakScopeResolution);
1050bdd1243dSDimitry Andric     IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
1051bdd1243dSDimitry Andric     IO.mapOptional("PenaltyBreakTemplateDeclaration",
1052bdd1243dSDimitry Andric                    Style.PenaltyBreakTemplateDeclaration);
1053bdd1243dSDimitry Andric     IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
1054bdd1243dSDimitry Andric     IO.mapOptional("PenaltyIndentedWhitespace",
1055bdd1243dSDimitry Andric                    Style.PenaltyIndentedWhitespace);
1056bdd1243dSDimitry Andric     IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
1057bdd1243dSDimitry Andric                    Style.PenaltyReturnTypeOnItsOwnLine);
1058bdd1243dSDimitry Andric     IO.mapOptional("PointerAlignment", Style.PointerAlignment);
1059bdd1243dSDimitry Andric     IO.mapOptional("PPIndentWidth", Style.PPIndentWidth);
1060bdd1243dSDimitry Andric     IO.mapOptional("QualifierAlignment", Style.QualifierAlignment);
1061bdd1243dSDimitry Andric     // Default Order for Left/Right based Qualifier alignment.
1062bdd1243dSDimitry Andric     if (Style.QualifierAlignment == FormatStyle::QAS_Right)
1063bdd1243dSDimitry Andric       Style.QualifierOrder = {"type", "const", "volatile"};
1064bdd1243dSDimitry Andric     else if (Style.QualifierAlignment == FormatStyle::QAS_Left)
1065bdd1243dSDimitry Andric       Style.QualifierOrder = {"const", "volatile", "type"};
1066bdd1243dSDimitry Andric     else if (Style.QualifierAlignment == FormatStyle::QAS_Custom)
1067bdd1243dSDimitry Andric       IO.mapOptional("QualifierOrder", Style.QualifierOrder);
1068bdd1243dSDimitry Andric     IO.mapOptional("RawStringFormats", Style.RawStringFormats);
1069bdd1243dSDimitry Andric     IO.mapOptional("ReferenceAlignment", Style.ReferenceAlignment);
1070bdd1243dSDimitry Andric     IO.mapOptional("ReflowComments", Style.ReflowComments);
1071bdd1243dSDimitry Andric     IO.mapOptional("RemoveBracesLLVM", Style.RemoveBracesLLVM);
107206c3fb27SDimitry Andric     IO.mapOptional("RemoveParentheses", Style.RemoveParentheses);
1073bdd1243dSDimitry Andric     IO.mapOptional("RemoveSemicolon", Style.RemoveSemicolon);
1074bdd1243dSDimitry Andric     IO.mapOptional("RequiresClausePosition", Style.RequiresClausePosition);
1075bdd1243dSDimitry Andric     IO.mapOptional("RequiresExpressionIndentation",
1076bdd1243dSDimitry Andric                    Style.RequiresExpressionIndentation);
1077bdd1243dSDimitry Andric     IO.mapOptional("SeparateDefinitionBlocks", Style.SeparateDefinitionBlocks);
1078bdd1243dSDimitry Andric     IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines);
10797a6dacacSDimitry Andric     IO.mapOptional("SkipMacroDefinitionBody", Style.SkipMacroDefinitionBody);
1080bdd1243dSDimitry Andric     IO.mapOptional("SortIncludes", Style.SortIncludes);
1081bdd1243dSDimitry Andric     IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport);
1082bdd1243dSDimitry Andric     IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);
1083bdd1243dSDimitry Andric     IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
1084bdd1243dSDimitry Andric     IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot);
1085bdd1243dSDimitry Andric     IO.mapOptional("SpaceAfterTemplateKeyword",
1086bdd1243dSDimitry Andric                    Style.SpaceAfterTemplateKeyword);
1087bdd1243dSDimitry Andric     IO.mapOptional("SpaceAroundPointerQualifiers",
1088bdd1243dSDimitry Andric                    Style.SpaceAroundPointerQualifiers);
1089bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeAssignmentOperators",
1090bdd1243dSDimitry Andric                    Style.SpaceBeforeAssignmentOperators);
1091bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeCaseColon", Style.SpaceBeforeCaseColon);
1092bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeCpp11BracedList",
1093bdd1243dSDimitry Andric                    Style.SpaceBeforeCpp11BracedList);
1094bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeCtorInitializerColon",
1095bdd1243dSDimitry Andric                    Style.SpaceBeforeCtorInitializerColon);
1096bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeInheritanceColon",
1097bdd1243dSDimitry Andric                    Style.SpaceBeforeInheritanceColon);
109806c3fb27SDimitry Andric     IO.mapOptional("SpaceBeforeJsonColon", Style.SpaceBeforeJsonColon);
1099bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
1100bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions);
1101bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
1102bdd1243dSDimitry Andric                    Style.SpaceBeforeRangeBasedForLoopColon);
1103bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeSquareBrackets",
1104bdd1243dSDimitry Andric                    Style.SpaceBeforeSquareBrackets);
1105bdd1243dSDimitry Andric     IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock);
1106bdd1243dSDimitry Andric     IO.mapOptional("SpacesBeforeTrailingComments",
1107bdd1243dSDimitry Andric                    Style.SpacesBeforeTrailingComments);
1108bdd1243dSDimitry Andric     IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
1109bdd1243dSDimitry Andric     IO.mapOptional("SpacesInContainerLiterals",
1110bdd1243dSDimitry Andric                    Style.SpacesInContainerLiterals);
1111bdd1243dSDimitry Andric     IO.mapOptional("SpacesInLineCommentPrefix",
1112bdd1243dSDimitry Andric                    Style.SpacesInLineCommentPrefix);
111306c3fb27SDimitry Andric     IO.mapOptional("SpacesInParens", Style.SpacesInParens);
111406c3fb27SDimitry Andric     IO.mapOptional("SpacesInParensOptions", Style.SpacesInParensOptions);
1115bdd1243dSDimitry Andric     IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
1116bdd1243dSDimitry Andric     IO.mapOptional("Standard", Style.Standard);
1117bdd1243dSDimitry Andric     IO.mapOptional("StatementAttributeLikeMacros",
1118bdd1243dSDimitry Andric                    Style.StatementAttributeLikeMacros);
1119bdd1243dSDimitry Andric     IO.mapOptional("StatementMacros", Style.StatementMacros);
1120*0fca6ea1SDimitry Andric     IO.mapOptional("TableGenBreakingDAGArgOperators",
1121*0fca6ea1SDimitry Andric                    Style.TableGenBreakingDAGArgOperators);
1122*0fca6ea1SDimitry Andric     IO.mapOptional("TableGenBreakInsideDAGArg",
1123*0fca6ea1SDimitry Andric                    Style.TableGenBreakInsideDAGArg);
1124bdd1243dSDimitry Andric     IO.mapOptional("TabWidth", Style.TabWidth);
112506c3fb27SDimitry Andric     IO.mapOptional("TypeNames", Style.TypeNames);
1126bdd1243dSDimitry Andric     IO.mapOptional("TypenameMacros", Style.TypenameMacros);
1127bdd1243dSDimitry Andric     IO.mapOptional("UseTab", Style.UseTab);
112806c3fb27SDimitry Andric     IO.mapOptional("VerilogBreakBetweenInstancePorts",
112906c3fb27SDimitry Andric                    Style.VerilogBreakBetweenInstancePorts);
1130bdd1243dSDimitry Andric     IO.mapOptional("WhitespaceSensitiveMacros",
1131bdd1243dSDimitry Andric                    Style.WhitespaceSensitiveMacros);
1132bdd1243dSDimitry Andric 
1133bdd1243dSDimitry Andric     // If AlwaysBreakAfterDefinitionReturnType was specified but
1134*0fca6ea1SDimitry Andric     // BreakAfterReturnType was not, initialize the latter from the former for
1135*0fca6ea1SDimitry Andric     // backwards compatibility.
1136bdd1243dSDimitry Andric     if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&
1137*0fca6ea1SDimitry Andric         Style.BreakAfterReturnType == FormatStyle::RTBS_None) {
1138bdd1243dSDimitry Andric       if (Style.AlwaysBreakAfterDefinitionReturnType ==
1139bdd1243dSDimitry Andric           FormatStyle::DRTBS_All) {
1140*0fca6ea1SDimitry Andric         Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
1141bdd1243dSDimitry Andric       } else if (Style.AlwaysBreakAfterDefinitionReturnType ==
1142bdd1243dSDimitry Andric                  FormatStyle::DRTBS_TopLevel) {
1143*0fca6ea1SDimitry Andric         Style.BreakAfterReturnType = FormatStyle::RTBS_TopLevelDefinitions;
1144bdd1243dSDimitry Andric       }
1145bdd1243dSDimitry Andric     }
1146bdd1243dSDimitry Andric 
1147bdd1243dSDimitry Andric     // If BreakBeforeInheritanceComma was specified but BreakInheritance was
1148bdd1243dSDimitry Andric     // not, initialize the latter from the former for backwards compatibility.
1149bdd1243dSDimitry Andric     if (BreakBeforeInheritanceComma &&
1150bdd1243dSDimitry Andric         Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) {
1151bdd1243dSDimitry Andric       Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
1152bdd1243dSDimitry Andric     }
1153bdd1243dSDimitry Andric 
1154bdd1243dSDimitry Andric     // If BreakConstructorInitializersBeforeComma was specified but
1155bdd1243dSDimitry Andric     // BreakConstructorInitializers was not, initialize the latter from the
1156bdd1243dSDimitry Andric     // former for backwards compatibility.
1157bdd1243dSDimitry Andric     if (BreakConstructorInitializersBeforeComma &&
1158bdd1243dSDimitry Andric         Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon) {
1159bdd1243dSDimitry Andric       Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
1160bdd1243dSDimitry Andric     }
1161bdd1243dSDimitry Andric 
1162bdd1243dSDimitry Andric     if (!IsGoogleOrChromium) {
1163bdd1243dSDimitry Andric       if (Style.PackConstructorInitializers == FormatStyle::PCIS_BinPack &&
1164bdd1243dSDimitry Andric           OnCurrentLine) {
1165bdd1243dSDimitry Andric         Style.PackConstructorInitializers = OnNextLine
1166bdd1243dSDimitry Andric                                                 ? FormatStyle::PCIS_NextLine
1167bdd1243dSDimitry Andric                                                 : FormatStyle::PCIS_CurrentLine;
1168bdd1243dSDimitry Andric       }
1169bdd1243dSDimitry Andric     } else if (Style.PackConstructorInitializers ==
1170bdd1243dSDimitry Andric                FormatStyle::PCIS_NextLine) {
1171bdd1243dSDimitry Andric       if (!OnCurrentLine)
1172bdd1243dSDimitry Andric         Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
1173bdd1243dSDimitry Andric       else if (!OnNextLine)
1174bdd1243dSDimitry Andric         Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine;
1175bdd1243dSDimitry Andric     }
1176bdd1243dSDimitry Andric 
1177bdd1243dSDimitry Andric     if (Style.LineEnding == FormatStyle::LE_DeriveLF) {
1178bdd1243dSDimitry Andric       if (!DeriveLineEnding)
1179bdd1243dSDimitry Andric         Style.LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF;
1180bdd1243dSDimitry Andric       else if (UseCRLF)
1181bdd1243dSDimitry Andric         Style.LineEnding = FormatStyle::LE_DeriveCRLF;
1182bdd1243dSDimitry Andric     }
118306c3fb27SDimitry Andric 
118406c3fb27SDimitry Andric     if (Style.SpacesInParens != FormatStyle::SIPO_Custom &&
118506c3fb27SDimitry Andric         (SpacesInParentheses || SpaceInEmptyParentheses ||
118606c3fb27SDimitry Andric          SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) {
118706c3fb27SDimitry Andric       if (SpacesInParentheses) {
1188*0fca6ea1SDimitry Andric         // For backward compatibility.
1189*0fca6ea1SDimitry Andric         Style.SpacesInParensOptions.ExceptDoubleParentheses = false;
119006c3fb27SDimitry Andric         Style.SpacesInParensOptions.InConditionalStatements = true;
119106c3fb27SDimitry Andric         Style.SpacesInParensOptions.InCStyleCasts =
119206c3fb27SDimitry Andric             SpacesInCStyleCastParentheses;
119306c3fb27SDimitry Andric         Style.SpacesInParensOptions.InEmptyParentheses =
119406c3fb27SDimitry Andric             SpaceInEmptyParentheses;
119506c3fb27SDimitry Andric         Style.SpacesInParensOptions.Other = true;
119606c3fb27SDimitry Andric       } else {
119706c3fb27SDimitry Andric         Style.SpacesInParensOptions = {};
119806c3fb27SDimitry Andric         Style.SpacesInParensOptions.InConditionalStatements =
119906c3fb27SDimitry Andric             SpacesInConditionalStatement;
120006c3fb27SDimitry Andric         Style.SpacesInParensOptions.InCStyleCasts =
120106c3fb27SDimitry Andric             SpacesInCStyleCastParentheses;
120206c3fb27SDimitry Andric         Style.SpacesInParensOptions.InEmptyParentheses =
120306c3fb27SDimitry Andric             SpaceInEmptyParentheses;
120406c3fb27SDimitry Andric       }
120506c3fb27SDimitry Andric       Style.SpacesInParens = FormatStyle::SIPO_Custom;
120606c3fb27SDimitry Andric     }
1207bdd1243dSDimitry Andric   }
1208bdd1243dSDimitry Andric };
1209bdd1243dSDimitry Andric 
12100b57cec5SDimitry Andric // Allows to read vector<FormatStyle> while keeping default values.
12110b57cec5SDimitry Andric // IO.getContext() should contain a pointer to the FormatStyle structure, that
12120b57cec5SDimitry Andric // will be used to get default values for missing keys.
12130b57cec5SDimitry Andric // If the first element has no Language specified, it will be treated as the
12140b57cec5SDimitry Andric // default one for the following elements.
12150b57cec5SDimitry Andric template <> struct DocumentListTraits<std::vector<FormatStyle>> {
12160b57cec5SDimitry Andric   static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
12170b57cec5SDimitry Andric     return Seq.size();
12180b57cec5SDimitry Andric   }
12190b57cec5SDimitry Andric   static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq,
12200b57cec5SDimitry Andric                               size_t Index) {
12210b57cec5SDimitry Andric     if (Index >= Seq.size()) {
12220b57cec5SDimitry Andric       assert(Index == Seq.size());
12230b57cec5SDimitry Andric       FormatStyle Template;
12240b57cec5SDimitry Andric       if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
12250b57cec5SDimitry Andric         Template = Seq[0];
12260b57cec5SDimitry Andric       } else {
12270b57cec5SDimitry Andric         Template = *((const FormatStyle *)IO.getContext());
12280b57cec5SDimitry Andric         Template.Language = FormatStyle::LK_None;
12290b57cec5SDimitry Andric       }
12300b57cec5SDimitry Andric       Seq.resize(Index + 1, Template);
12310b57cec5SDimitry Andric     }
12320b57cec5SDimitry Andric     return Seq[Index];
12330b57cec5SDimitry Andric   }
12340b57cec5SDimitry Andric };
12350b57cec5SDimitry Andric } // namespace yaml
12360b57cec5SDimitry Andric } // namespace llvm
12370b57cec5SDimitry Andric 
12380b57cec5SDimitry Andric namespace clang {
12390b57cec5SDimitry Andric namespace format {
12400b57cec5SDimitry Andric 
12410b57cec5SDimitry Andric const std::error_category &getParseCategory() {
12420b57cec5SDimitry Andric   static const ParseErrorCategory C{};
12430b57cec5SDimitry Andric   return C;
12440b57cec5SDimitry Andric }
12450b57cec5SDimitry Andric std::error_code make_error_code(ParseError e) {
12460b57cec5SDimitry Andric   return std::error_code(static_cast<int>(e), getParseCategory());
12470b57cec5SDimitry Andric }
12480b57cec5SDimitry Andric 
1249*0fca6ea1SDimitry Andric inline llvm::Error make_string_error(const Twine &Message) {
12500b57cec5SDimitry Andric   return llvm::make_error<llvm::StringError>(Message,
12510b57cec5SDimitry Andric                                              llvm::inconvertibleErrorCode());
12520b57cec5SDimitry Andric }
12530b57cec5SDimitry Andric 
12540b57cec5SDimitry Andric const char *ParseErrorCategory::name() const noexcept {
12550b57cec5SDimitry Andric   return "clang-format.parse_error";
12560b57cec5SDimitry Andric }
12570b57cec5SDimitry Andric 
12580b57cec5SDimitry Andric std::string ParseErrorCategory::message(int EV) const {
12590b57cec5SDimitry Andric   switch (static_cast<ParseError>(EV)) {
12600b57cec5SDimitry Andric   case ParseError::Success:
12610b57cec5SDimitry Andric     return "Success";
12620b57cec5SDimitry Andric   case ParseError::Error:
12630b57cec5SDimitry Andric     return "Invalid argument";
12640b57cec5SDimitry Andric   case ParseError::Unsuitable:
12650b57cec5SDimitry Andric     return "Unsuitable";
12665ffd83dbSDimitry Andric   case ParseError::BinPackTrailingCommaConflict:
12675ffd83dbSDimitry Andric     return "trailing comma insertion cannot be used with bin packing";
1268349cc55cSDimitry Andric   case ParseError::InvalidQualifierSpecified:
1269349cc55cSDimitry Andric     return "Invalid qualifier specified in QualifierOrder";
1270349cc55cSDimitry Andric   case ParseError::DuplicateQualifierSpecified:
127181ad6265SDimitry Andric     return "Duplicate qualifier specified in QualifierOrder";
1272349cc55cSDimitry Andric   case ParseError::MissingQualifierType:
127381ad6265SDimitry Andric     return "Missing type in QualifierOrder";
1274349cc55cSDimitry Andric   case ParseError::MissingQualifierOrder:
127581ad6265SDimitry Andric     return "Missing QualifierOrder";
12760b57cec5SDimitry Andric   }
12770b57cec5SDimitry Andric   llvm_unreachable("unexpected parse error");
12780b57cec5SDimitry Andric }
12790b57cec5SDimitry Andric 
1280349cc55cSDimitry Andric static void expandPresetsBraceWrapping(FormatStyle &Expanded) {
1281349cc55cSDimitry Andric   if (Expanded.BreakBeforeBraces == FormatStyle::BS_Custom)
1282349cc55cSDimitry Andric     return;
12835ffd83dbSDimitry Andric   Expanded.BraceWrapping = {/*AfterCaseLabel=*/false,
12845ffd83dbSDimitry Andric                             /*AfterClass=*/false,
12855ffd83dbSDimitry Andric                             /*AfterControlStatement=*/FormatStyle::BWACS_Never,
12865ffd83dbSDimitry Andric                             /*AfterEnum=*/false,
12875ffd83dbSDimitry Andric                             /*AfterFunction=*/false,
12885ffd83dbSDimitry Andric                             /*AfterNamespace=*/false,
12895ffd83dbSDimitry Andric                             /*AfterObjCDeclaration=*/false,
12905ffd83dbSDimitry Andric                             /*AfterStruct=*/false,
12915ffd83dbSDimitry Andric                             /*AfterUnion=*/false,
12925ffd83dbSDimitry Andric                             /*AfterExternBlock=*/false,
12935ffd83dbSDimitry Andric                             /*BeforeCatch=*/false,
12945ffd83dbSDimitry Andric                             /*BeforeElse=*/false,
12955ffd83dbSDimitry Andric                             /*BeforeLambdaBody=*/false,
12965ffd83dbSDimitry Andric                             /*BeforeWhile=*/false,
12975ffd83dbSDimitry Andric                             /*IndentBraces=*/false,
12985ffd83dbSDimitry Andric                             /*SplitEmptyFunction=*/true,
12995ffd83dbSDimitry Andric                             /*SplitEmptyRecord=*/true,
13005ffd83dbSDimitry Andric                             /*SplitEmptyNamespace=*/true};
1301349cc55cSDimitry Andric   switch (Expanded.BreakBeforeBraces) {
13020b57cec5SDimitry Andric   case FormatStyle::BS_Linux:
13030b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterClass = true;
13040b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterFunction = true;
13050b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterNamespace = true;
13060b57cec5SDimitry Andric     break;
13070b57cec5SDimitry Andric   case FormatStyle::BS_Mozilla:
13080b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterClass = true;
13090b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterEnum = true;
13100b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterFunction = true;
13110b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterStruct = true;
13120b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterUnion = true;
13130b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterExternBlock = true;
13140b57cec5SDimitry Andric     Expanded.BraceWrapping.SplitEmptyFunction = true;
13150b57cec5SDimitry Andric     Expanded.BraceWrapping.SplitEmptyRecord = false;
13160b57cec5SDimitry Andric     break;
13170b57cec5SDimitry Andric   case FormatStyle::BS_Stroustrup:
13180b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterFunction = true;
13190b57cec5SDimitry Andric     Expanded.BraceWrapping.BeforeCatch = true;
13200b57cec5SDimitry Andric     Expanded.BraceWrapping.BeforeElse = true;
13210b57cec5SDimitry Andric     break;
13220b57cec5SDimitry Andric   case FormatStyle::BS_Allman:
13230b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterCaseLabel = true;
13240b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterClass = true;
1325a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
1326a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterEnum = true;
1327a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterFunction = true;
1328a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterNamespace = true;
1329a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterObjCDeclaration = true;
1330a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterStruct = true;
1331a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterUnion = true;
1332a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterExternBlock = true;
1333a7dea167SDimitry Andric     Expanded.BraceWrapping.BeforeCatch = true;
1334a7dea167SDimitry Andric     Expanded.BraceWrapping.BeforeElse = true;
1335e8d8bef9SDimitry Andric     Expanded.BraceWrapping.BeforeLambdaBody = true;
1336a7dea167SDimitry Andric     break;
1337a7dea167SDimitry Andric   case FormatStyle::BS_Whitesmiths:
1338a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterCaseLabel = true;
1339a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterClass = true;
1340a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
13410b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterEnum = true;
13420b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterFunction = true;
13430b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterNamespace = true;
13440b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterObjCDeclaration = true;
13450b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterStruct = true;
13460b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterExternBlock = true;
13470b57cec5SDimitry Andric     Expanded.BraceWrapping.BeforeCatch = true;
13480b57cec5SDimitry Andric     Expanded.BraceWrapping.BeforeElse = true;
13495ffd83dbSDimitry Andric     Expanded.BraceWrapping.BeforeLambdaBody = true;
13500b57cec5SDimitry Andric     break;
13510b57cec5SDimitry Andric   case FormatStyle::BS_GNU:
13525ffd83dbSDimitry Andric     Expanded.BraceWrapping = {
13535ffd83dbSDimitry Andric         /*AfterCaseLabel=*/true,
13545ffd83dbSDimitry Andric         /*AfterClass=*/true,
13555ffd83dbSDimitry Andric         /*AfterControlStatement=*/FormatStyle::BWACS_Always,
13565ffd83dbSDimitry Andric         /*AfterEnum=*/true,
13575ffd83dbSDimitry Andric         /*AfterFunction=*/true,
13585ffd83dbSDimitry Andric         /*AfterNamespace=*/true,
13595ffd83dbSDimitry Andric         /*AfterObjCDeclaration=*/true,
13605ffd83dbSDimitry Andric         /*AfterStruct=*/true,
13615ffd83dbSDimitry Andric         /*AfterUnion=*/true,
13625ffd83dbSDimitry Andric         /*AfterExternBlock=*/true,
13635ffd83dbSDimitry Andric         /*BeforeCatch=*/true,
13645ffd83dbSDimitry Andric         /*BeforeElse=*/true,
13655ffd83dbSDimitry Andric         /*BeforeLambdaBody=*/false,
13665ffd83dbSDimitry Andric         /*BeforeWhile=*/true,
13675ffd83dbSDimitry Andric         /*IndentBraces=*/true,
13685ffd83dbSDimitry Andric         /*SplitEmptyFunction=*/true,
13695ffd83dbSDimitry Andric         /*SplitEmptyRecord=*/true,
13705ffd83dbSDimitry Andric         /*SplitEmptyNamespace=*/true};
13710b57cec5SDimitry Andric     break;
13720b57cec5SDimitry Andric   case FormatStyle::BS_WebKit:
13730b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterFunction = true;
13740b57cec5SDimitry Andric     break;
13750b57cec5SDimitry Andric   default:
13760b57cec5SDimitry Andric     break;
13770b57cec5SDimitry Andric   }
1378349cc55cSDimitry Andric }
1379349cc55cSDimitry Andric 
1380349cc55cSDimitry Andric static void expandPresetsSpaceBeforeParens(FormatStyle &Expanded) {
1381349cc55cSDimitry Andric   if (Expanded.SpaceBeforeParens == FormatStyle::SBPO_Custom)
1382349cc55cSDimitry Andric     return;
1383349cc55cSDimitry Andric   // Reset all flags
1384349cc55cSDimitry Andric   Expanded.SpaceBeforeParensOptions = {};
1385b3edf446SDimitry Andric   Expanded.SpaceBeforeParensOptions.AfterPlacementOperator = true;
1386349cc55cSDimitry Andric 
1387349cc55cSDimitry Andric   switch (Expanded.SpaceBeforeParens) {
1388349cc55cSDimitry Andric   case FormatStyle::SBPO_ControlStatements:
1389349cc55cSDimitry Andric     Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;
1390349cc55cSDimitry Andric     Expanded.SpaceBeforeParensOptions.AfterForeachMacros = true;
1391349cc55cSDimitry Andric     Expanded.SpaceBeforeParensOptions.AfterIfMacros = true;
1392349cc55cSDimitry Andric     break;
1393349cc55cSDimitry Andric   case FormatStyle::SBPO_ControlStatementsExceptControlMacros:
1394349cc55cSDimitry Andric     Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;
1395349cc55cSDimitry Andric     break;
1396349cc55cSDimitry Andric   case FormatStyle::SBPO_NonEmptyParentheses:
1397349cc55cSDimitry Andric     Expanded.SpaceBeforeParensOptions.BeforeNonEmptyParentheses = true;
1398349cc55cSDimitry Andric     break;
1399349cc55cSDimitry Andric   default:
1400349cc55cSDimitry Andric     break;
1401349cc55cSDimitry Andric   }
14020b57cec5SDimitry Andric }
14030b57cec5SDimitry Andric 
140406c3fb27SDimitry Andric static void expandPresetsSpacesInParens(FormatStyle &Expanded) {
140506c3fb27SDimitry Andric   if (Expanded.SpacesInParens == FormatStyle::SIPO_Custom)
140606c3fb27SDimitry Andric     return;
140706c3fb27SDimitry Andric   assert(Expanded.SpacesInParens == FormatStyle::SIPO_Never);
140806c3fb27SDimitry Andric   // Reset all flags
140906c3fb27SDimitry Andric   Expanded.SpacesInParensOptions = {};
141006c3fb27SDimitry Andric }
141106c3fb27SDimitry Andric 
14120b57cec5SDimitry Andric FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
14130b57cec5SDimitry Andric   FormatStyle LLVMStyle;
14140b57cec5SDimitry Andric   LLVMStyle.AccessModifierOffset = -2;
14150b57cec5SDimitry Andric   LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
1416fe6060f1SDimitry Andric   LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;
141781ad6265SDimitry Andric   LLVMStyle.AlignConsecutiveAssignments = {};
141881ad6265SDimitry Andric   LLVMStyle.AlignConsecutiveAssignments.AcrossComments = false;
1419*0fca6ea1SDimitry Andric   LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false;
142081ad6265SDimitry Andric   LLVMStyle.AlignConsecutiveAssignments.AlignCompound = false;
1421297eecfbSDimitry Andric   LLVMStyle.AlignConsecutiveAssignments.AlignFunctionPointers = false;
1422*0fca6ea1SDimitry Andric   LLVMStyle.AlignConsecutiveAssignments.Enabled = false;
142381ad6265SDimitry Andric   LLVMStyle.AlignConsecutiveAssignments.PadOperators = true;
142481ad6265SDimitry Andric   LLVMStyle.AlignConsecutiveBitFields = {};
142581ad6265SDimitry Andric   LLVMStyle.AlignConsecutiveDeclarations = {};
142681ad6265SDimitry Andric   LLVMStyle.AlignConsecutiveMacros = {};
142706c3fb27SDimitry Andric   LLVMStyle.AlignConsecutiveShortCaseStatements = {};
1428*0fca6ea1SDimitry Andric   LLVMStyle.AlignConsecutiveTableGenBreakingDAGArgColons = {};
1429*0fca6ea1SDimitry Andric   LLVMStyle.AlignConsecutiveTableGenCondOperatorColons = {};
1430*0fca6ea1SDimitry Andric   LLVMStyle.AlignConsecutiveTableGenDefinitionColons = {};
1431*0fca6ea1SDimitry Andric   LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
1432*0fca6ea1SDimitry Andric   LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
1433bdd1243dSDimitry Andric   LLVMStyle.AlignTrailingComments = {};
1434bdd1243dSDimitry Andric   LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always;
1435bdd1243dSDimitry Andric   LLVMStyle.AlignTrailingComments.OverEmptyLines = 0;
14360b57cec5SDimitry Andric   LLVMStyle.AllowAllArgumentsOnNextLine = true;
14370b57cec5SDimitry Andric   LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
1438*0fca6ea1SDimitry Andric   LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;
1439a7dea167SDimitry Andric   LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
1440*0fca6ea1SDimitry Andric   LLVMStyle.AllowShortCaseExpressionOnASingleLine = true;
14410b57cec5SDimitry Andric   LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
14425f757f3fSDimitry Andric   LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true;
1443bdd1243dSDimitry Andric   LLVMStyle.AllowShortEnumsOnASingleLine = true;
1444bdd1243dSDimitry Andric   LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
14450b57cec5SDimitry Andric   LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
14460b57cec5SDimitry Andric   LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
14470b57cec5SDimitry Andric   LLVMStyle.AllowShortLoopsOnASingleLine = false;
14480b57cec5SDimitry Andric   LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
14490b57cec5SDimitry Andric   LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
1450e8d8bef9SDimitry Andric   LLVMStyle.AttributeMacros.push_back("__capability");
14510b57cec5SDimitry Andric   LLVMStyle.BinPackArguments = true;
14520b57cec5SDimitry Andric   LLVMStyle.BinPackParameters = true;
1453*0fca6ea1SDimitry Andric   LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;
145406c3fb27SDimitry Andric   LLVMStyle.BracedInitializerIndentWidth = std::nullopt;
14555ffd83dbSDimitry Andric   LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false,
14565ffd83dbSDimitry Andric                              /*AfterClass=*/false,
14575ffd83dbSDimitry Andric                              /*AfterControlStatement=*/FormatStyle::BWACS_Never,
14585ffd83dbSDimitry Andric                              /*AfterEnum=*/false,
14595ffd83dbSDimitry Andric                              /*AfterFunction=*/false,
14605ffd83dbSDimitry Andric                              /*AfterNamespace=*/false,
14615ffd83dbSDimitry Andric                              /*AfterObjCDeclaration=*/false,
14625ffd83dbSDimitry Andric                              /*AfterStruct=*/false,
14635ffd83dbSDimitry Andric                              /*AfterUnion=*/false,
14645ffd83dbSDimitry Andric                              /*AfterExternBlock=*/false,
14655ffd83dbSDimitry Andric                              /*BeforeCatch=*/false,
14665ffd83dbSDimitry Andric                              /*BeforeElse=*/false,
14675ffd83dbSDimitry Andric                              /*BeforeLambdaBody=*/false,
14685ffd83dbSDimitry Andric                              /*BeforeWhile=*/false,
14695ffd83dbSDimitry Andric                              /*IndentBraces=*/false,
14705ffd83dbSDimitry Andric                              /*SplitEmptyFunction=*/true,
14715ffd83dbSDimitry Andric                              /*SplitEmptyRecord=*/true,
14725ffd83dbSDimitry Andric                              /*SplitEmptyNamespace=*/true};
14735f757f3fSDimitry Andric   LLVMStyle.BreakAdjacentStringLiterals = true;
14745f757f3fSDimitry Andric   LLVMStyle.BreakAfterAttributes = FormatStyle::ABS_Leave;
14750b57cec5SDimitry Andric   LLVMStyle.BreakAfterJavaFieldAnnotations = false;
1476*0fca6ea1SDimitry Andric   LLVMStyle.BreakAfterReturnType = FormatStyle::RTBS_None;
1477bdd1243dSDimitry Andric   LLVMStyle.BreakArrays = true;
1478bdd1243dSDimitry Andric   LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
1479bdd1243dSDimitry Andric   LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
1480bdd1243dSDimitry Andric   LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always;
1481bdd1243dSDimitry Andric   LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline;
1482bdd1243dSDimitry Andric   LLVMStyle.BreakBeforeTernaryOperators = true;
14830b57cec5SDimitry Andric   LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
1484*0fca6ea1SDimitry Andric   LLVMStyle.BreakFunctionDefinitionParameters = false;
14850b57cec5SDimitry Andric   LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
14860b57cec5SDimitry Andric   LLVMStyle.BreakStringLiterals = true;
1487*0fca6ea1SDimitry Andric   LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
14880b57cec5SDimitry Andric   LLVMStyle.ColumnLimit = 80;
14890b57cec5SDimitry Andric   LLVMStyle.CommentPragmas = "^ IWYU pragma:";
14900b57cec5SDimitry Andric   LLVMStyle.CompactNamespaces = false;
14910b57cec5SDimitry Andric   LLVMStyle.ConstructorInitializerIndentWidth = 4;
14920b57cec5SDimitry Andric   LLVMStyle.ContinuationIndentWidth = 4;
14930b57cec5SDimitry Andric   LLVMStyle.Cpp11BracedListStyle = true;
14940b57cec5SDimitry Andric   LLVMStyle.DerivePointerAlignment = false;
1495bdd1243dSDimitry Andric   LLVMStyle.DisableFormat = false;
1496fe6060f1SDimitry Andric   LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never;
1497e8d8bef9SDimitry Andric   LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock;
14980b57cec5SDimitry Andric   LLVMStyle.ExperimentalAutoDetectBinPacking = false;
14990b57cec5SDimitry Andric   LLVMStyle.FixNamespaceComments = true;
15000b57cec5SDimitry Andric   LLVMStyle.ForEachMacros.push_back("foreach");
15010b57cec5SDimitry Andric   LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
15020b57cec5SDimitry Andric   LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
1503fe6060f1SDimitry Andric   LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE");
1504*0fca6ea1SDimitry Andric   LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
15050b57cec5SDimitry Andric   LLVMStyle.IncludeStyle.IncludeCategories = {
1506e8d8bef9SDimitry Andric       {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false},
1507e8d8bef9SDimitry Andric       {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},
1508e8d8bef9SDimitry Andric       {".*", 1, 0, false}};
15090b57cec5SDimitry Andric   LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
1510*0fca6ea1SDimitry Andric   LLVMStyle.IncludeStyle.MainIncludeChar = tooling::IncludeStyle::MICD_Quote;
1511fe6060f1SDimitry Andric   LLVMStyle.IndentAccessModifiers = false;
15125ffd83dbSDimitry Andric   LLVMStyle.IndentCaseBlocks = false;
1513*0fca6ea1SDimitry Andric   LLVMStyle.IndentCaseLabels = false;
1514bdd1243dSDimitry Andric   LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
1515a7dea167SDimitry Andric   LLVMStyle.IndentGotoLabels = true;
15160b57cec5SDimitry Andric   LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
151781ad6265SDimitry Andric   LLVMStyle.IndentRequiresClause = true;
15180b57cec5SDimitry Andric   LLVMStyle.IndentWidth = 2;
1519bdd1243dSDimitry Andric   LLVMStyle.IndentWrappedFunctionNames = false;
1520*0fca6ea1SDimitry Andric   LLVMStyle.InheritsParentConfig = false;
152181ad6265SDimitry Andric   LLVMStyle.InsertBraces = false;
1522bdd1243dSDimitry Andric   LLVMStyle.InsertNewlineAtEOF = false;
15235ffd83dbSDimitry Andric   LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
15241ac55f4cSDimitry Andric   LLVMStyle.IntegerLiteralSeparator = {
15251ac55f4cSDimitry Andric       /*Binary=*/0,  /*BinaryMinDigits=*/0,
15261ac55f4cSDimitry Andric       /*Decimal=*/0, /*DecimalMinDigits=*/0,
15271ac55f4cSDimitry Andric       /*Hex=*/0,     /*HexMinDigits=*/0};
15280b57cec5SDimitry Andric   LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
15290b57cec5SDimitry Andric   LLVMStyle.JavaScriptWrapImports = true;
1530*0fca6ea1SDimitry Andric   LLVMStyle.KeepEmptyLines = {
1531*0fca6ea1SDimitry Andric       /*AtEndOfFile=*/false,
1532*0fca6ea1SDimitry Andric       /*AtStartOfBlock=*/true,
1533*0fca6ea1SDimitry Andric       /*AtStartOfFile=*/true,
1534*0fca6ea1SDimitry Andric   };
1535bdd1243dSDimitry Andric   LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature;
1536*0fca6ea1SDimitry Andric   LLVMStyle.Language = Language;
1537bdd1243dSDimitry Andric   LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF;
1538bdd1243dSDimitry Andric   LLVMStyle.MaxEmptyLinesToKeep = 1;
15390b57cec5SDimitry Andric   LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
15400b57cec5SDimitry Andric   LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto;
15410b57cec5SDimitry Andric   LLVMStyle.ObjCBlockIndentWidth = 2;
15425ffd83dbSDimitry Andric   LLVMStyle.ObjCBreakBeforeNestedBlockParam = true;
15430b57cec5SDimitry Andric   LLVMStyle.ObjCSpaceAfterProperty = false;
15440b57cec5SDimitry Andric   LLVMStyle.ObjCSpaceBeforeProtocolList = true;
1545bdd1243dSDimitry Andric   LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
15460b57cec5SDimitry Andric   LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
1547bdd1243dSDimitry Andric   LLVMStyle.PPIndentWidth = -1;
1548bdd1243dSDimitry Andric   LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
1549fe6060f1SDimitry Andric   LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer;
15500b57cec5SDimitry Andric   LLVMStyle.ReflowComments = true;
155104eeddc0SDimitry Andric   LLVMStyle.RemoveBracesLLVM = false;
155206c3fb27SDimitry Andric   LLVMStyle.RemoveParentheses = FormatStyle::RPS_Leave;
1553bdd1243dSDimitry Andric   LLVMStyle.RemoveSemicolon = false;
1554bdd1243dSDimitry Andric   LLVMStyle.RequiresClausePosition = FormatStyle::RCPS_OwnLine;
1555bdd1243dSDimitry Andric   LLVMStyle.RequiresExpressionIndentation = FormatStyle::REI_OuterScope;
1556bdd1243dSDimitry Andric   LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
1557bdd1243dSDimitry Andric   LLVMStyle.ShortNamespaceLines = 1;
15587a6dacacSDimitry Andric   LLVMStyle.SkipMacroDefinitionBody = false;
1559bdd1243dSDimitry Andric   LLVMStyle.SortIncludes = FormatStyle::SI_CaseSensitive;
1560bdd1243dSDimitry Andric   LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
1561bdd1243dSDimitry Andric   LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;
15620b57cec5SDimitry Andric   LLVMStyle.SpaceAfterCStyleCast = false;
15630b57cec5SDimitry Andric   LLVMStyle.SpaceAfterLogicalNot = false;
15640b57cec5SDimitry Andric   LLVMStyle.SpaceAfterTemplateKeyword = true;
1565e8d8bef9SDimitry Andric   LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
1566*0fca6ea1SDimitry Andric   LLVMStyle.SpaceBeforeAssignmentOperators = true;
1567e8d8bef9SDimitry Andric   LLVMStyle.SpaceBeforeCaseColon = false;
1568*0fca6ea1SDimitry Andric   LLVMStyle.SpaceBeforeCpp11BracedList = false;
15690b57cec5SDimitry Andric   LLVMStyle.SpaceBeforeCtorInitializerColon = true;
15700b57cec5SDimitry Andric   LLVMStyle.SpaceBeforeInheritanceColon = true;
157106c3fb27SDimitry Andric   LLVMStyle.SpaceBeforeJsonColon = false;
15720b57cec5SDimitry Andric   LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
157381ad6265SDimitry Andric   LLVMStyle.SpaceBeforeParensOptions = {};
1574349cc55cSDimitry Andric   LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true;
1575349cc55cSDimitry Andric   LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true;
1576349cc55cSDimitry Andric   LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true;
15770b57cec5SDimitry Andric   LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
1578480093f4SDimitry Andric   LLVMStyle.SpaceBeforeSquareBrackets = false;
1579bdd1243dSDimitry Andric   LLVMStyle.SpaceInEmptyBlock = false;
1580bdd1243dSDimitry Andric   LLVMStyle.SpacesBeforeTrailingComments = 1;
1581fe6060f1SDimitry Andric   LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never;
1582bdd1243dSDimitry Andric   LLVMStyle.SpacesInContainerLiterals = true;
1583bdd1243dSDimitry Andric   LLVMStyle.SpacesInLineCommentPrefix = {/*Minimum=*/1, /*Maximum=*/-1u};
158406c3fb27SDimitry Andric   LLVMStyle.SpacesInParens = FormatStyle::SIPO_Never;
1585bdd1243dSDimitry Andric   LLVMStyle.SpacesInSquareBrackets = false;
1586bdd1243dSDimitry Andric   LLVMStyle.Standard = FormatStyle::LS_Latest;
1587bdd1243dSDimitry Andric   LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");
1588bdd1243dSDimitry Andric   LLVMStyle.StatementMacros.push_back("Q_UNUSED");
1589bdd1243dSDimitry Andric   LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");
1590*0fca6ea1SDimitry Andric   LLVMStyle.TableGenBreakingDAGArgOperators = {};
1591*0fca6ea1SDimitry Andric   LLVMStyle.TableGenBreakInsideDAGArg = FormatStyle::DAS_DontBreak;
1592bdd1243dSDimitry Andric   LLVMStyle.TabWidth = 8;
1593bdd1243dSDimitry Andric   LLVMStyle.UseTab = FormatStyle::UT_Never;
159406c3fb27SDimitry Andric   LLVMStyle.VerilogBreakBetweenInstancePorts = true;
1595bdd1243dSDimitry Andric   LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE");
1596bdd1243dSDimitry Andric   LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME");
1597bdd1243dSDimitry Andric   LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME");
1598bdd1243dSDimitry Andric   LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE");
1599bdd1243dSDimitry Andric   LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE");
16000b57cec5SDimitry Andric 
16010b57cec5SDimitry Andric   LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
1602*0fca6ea1SDimitry Andric   LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
16030b57cec5SDimitry Andric   LLVMStyle.PenaltyBreakComment = 300;
16040b57cec5SDimitry Andric   LLVMStyle.PenaltyBreakFirstLessLess = 120;
160504eeddc0SDimitry Andric   LLVMStyle.PenaltyBreakOpenParenthesis = 0;
16067a6dacacSDimitry Andric   LLVMStyle.PenaltyBreakScopeResolution = 500;
1607*0fca6ea1SDimitry Andric   LLVMStyle.PenaltyBreakString = 1000;
16080b57cec5SDimitry Andric   LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;
1609*0fca6ea1SDimitry Andric   LLVMStyle.PenaltyExcessCharacter = 1'000'000;
1610e8d8bef9SDimitry Andric   LLVMStyle.PenaltyIndentedWhitespace = 0;
1611*0fca6ea1SDimitry Andric   LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
16120b57cec5SDimitry Andric 
16130b57cec5SDimitry Andric   // Defaults that differ when not C++.
1614bdd1243dSDimitry Andric   switch (Language) {
1615bdd1243dSDimitry Andric   case FormatStyle::LK_TableGen:
16160b57cec5SDimitry Andric     LLVMStyle.SpacesInContainerLiterals = false;
1617bdd1243dSDimitry Andric     break;
1618bdd1243dSDimitry Andric   case FormatStyle::LK_Json:
1619fe6060f1SDimitry Andric     LLVMStyle.ColumnLimit = 0;
1620bdd1243dSDimitry Andric     break;
1621bdd1243dSDimitry Andric   case FormatStyle::LK_Verilog:
1622bdd1243dSDimitry Andric     LLVMStyle.IndentCaseLabels = true;
162306c3fb27SDimitry Andric     LLVMStyle.SpacesInContainerLiterals = false;
1624bdd1243dSDimitry Andric     break;
1625bdd1243dSDimitry Andric   default:
1626bdd1243dSDimitry Andric     break;
1627bdd1243dSDimitry Andric   }
16280b57cec5SDimitry Andric 
16290b57cec5SDimitry Andric   return LLVMStyle;
16300b57cec5SDimitry Andric }
16310b57cec5SDimitry Andric 
16320b57cec5SDimitry Andric FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
16330b57cec5SDimitry Andric   if (Language == FormatStyle::LK_TextProto) {
16340b57cec5SDimitry Andric     FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto);
16350b57cec5SDimitry Andric     GoogleStyle.Language = FormatStyle::LK_TextProto;
16360b57cec5SDimitry Andric 
16370b57cec5SDimitry Andric     return GoogleStyle;
16380b57cec5SDimitry Andric   }
16390b57cec5SDimitry Andric 
16400b57cec5SDimitry Andric   FormatStyle GoogleStyle = getLLVMStyle(Language);
16410b57cec5SDimitry Andric 
16420b57cec5SDimitry Andric   GoogleStyle.AccessModifierOffset = -1;
16430b57cec5SDimitry Andric   GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left;
16440b57cec5SDimitry Andric   GoogleStyle.AllowShortIfStatementsOnASingleLine =
16450b57cec5SDimitry Andric       FormatStyle::SIS_WithoutElse;
16460b57cec5SDimitry Andric   GoogleStyle.AllowShortLoopsOnASingleLine = true;
16470b57cec5SDimitry Andric   GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
1648*0fca6ea1SDimitry Andric   GoogleStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
16490b57cec5SDimitry Andric   GoogleStyle.DerivePointerAlignment = true;
1650*0fca6ea1SDimitry Andric   GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
1651e8d8bef9SDimitry Andric   GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false},
1652e8d8bef9SDimitry Andric                                                 {"^<.*\\.h>", 1, 0, false},
1653e8d8bef9SDimitry Andric                                                 {"^<.*", 2, 0, false},
1654e8d8bef9SDimitry Andric                                                 {".*", 3, 0, false}};
16550b57cec5SDimitry Andric   GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
16560b57cec5SDimitry Andric   GoogleStyle.IndentCaseLabels = true;
1657*0fca6ea1SDimitry Andric   GoogleStyle.KeepEmptyLines.AtStartOfBlock = false;
16580b57cec5SDimitry Andric   GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never;
16590b57cec5SDimitry Andric   GoogleStyle.ObjCSpaceAfterProperty = false;
16600b57cec5SDimitry Andric   GoogleStyle.ObjCSpaceBeforeProtocolList = true;
1661349cc55cSDimitry Andric   GoogleStyle.PackConstructorInitializers = FormatStyle::PCIS_NextLine;
16620b57cec5SDimitry Andric   GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;
16630b57cec5SDimitry Andric   GoogleStyle.RawStringFormats = {
16640b57cec5SDimitry Andric       {
16650b57cec5SDimitry Andric           FormatStyle::LK_Cpp,
16660b57cec5SDimitry Andric           /*Delimiters=*/
16670b57cec5SDimitry Andric           {
16680b57cec5SDimitry Andric               "cc",
16690b57cec5SDimitry Andric               "CC",
16700b57cec5SDimitry Andric               "cpp",
16710b57cec5SDimitry Andric               "Cpp",
16720b57cec5SDimitry Andric               "CPP",
16730b57cec5SDimitry Andric               "c++",
16740b57cec5SDimitry Andric               "C++",
16750b57cec5SDimitry Andric           },
16760b57cec5SDimitry Andric           /*EnclosingFunctionNames=*/
16770b57cec5SDimitry Andric           {},
16780b57cec5SDimitry Andric           /*CanonicalDelimiter=*/"",
16790b57cec5SDimitry Andric           /*BasedOnStyle=*/"google",
16800b57cec5SDimitry Andric       },
16810b57cec5SDimitry Andric       {
16820b57cec5SDimitry Andric           FormatStyle::LK_TextProto,
16830b57cec5SDimitry Andric           /*Delimiters=*/
16840b57cec5SDimitry Andric           {
16850b57cec5SDimitry Andric               "pb",
16860b57cec5SDimitry Andric               "PB",
16870b57cec5SDimitry Andric               "proto",
16880b57cec5SDimitry Andric               "PROTO",
16890b57cec5SDimitry Andric           },
16900b57cec5SDimitry Andric           /*EnclosingFunctionNames=*/
16910b57cec5SDimitry Andric           {
16920b57cec5SDimitry Andric               "EqualsProto",
16930b57cec5SDimitry Andric               "EquivToProto",
16940b57cec5SDimitry Andric               "PARSE_PARTIAL_TEXT_PROTO",
16950b57cec5SDimitry Andric               "PARSE_TEST_PROTO",
16960b57cec5SDimitry Andric               "PARSE_TEXT_PROTO",
16970b57cec5SDimitry Andric               "ParseTextOrDie",
16980b57cec5SDimitry Andric               "ParseTextProtoOrDie",
16995ffd83dbSDimitry Andric               "ParseTestProto",
17005ffd83dbSDimitry Andric               "ParsePartialTestProto",
17010b57cec5SDimitry Andric           },
1702fe6060f1SDimitry Andric           /*CanonicalDelimiter=*/"pb",
17030b57cec5SDimitry Andric           /*BasedOnStyle=*/"google",
17040b57cec5SDimitry Andric       },
17050b57cec5SDimitry Andric   };
1706cb14a3feSDimitry Andric 
17070b57cec5SDimitry Andric   GoogleStyle.SpacesBeforeTrailingComments = 2;
17080b57cec5SDimitry Andric   GoogleStyle.Standard = FormatStyle::LS_Auto;
17090b57cec5SDimitry Andric 
17100b57cec5SDimitry Andric   GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;
1711*0fca6ea1SDimitry Andric   GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
17120b57cec5SDimitry Andric 
17130b57cec5SDimitry Andric   if (Language == FormatStyle::LK_Java) {
17140b57cec5SDimitry Andric     GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
17155ffd83dbSDimitry Andric     GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
1716bdd1243dSDimitry Andric     GoogleStyle.AlignTrailingComments = {};
1717bdd1243dSDimitry Andric     GoogleStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;
17180b57cec5SDimitry Andric     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
17190b57cec5SDimitry Andric     GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
17200b57cec5SDimitry Andric     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
17210b57cec5SDimitry Andric     GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
17220b57cec5SDimitry Andric     GoogleStyle.ColumnLimit = 100;
17230b57cec5SDimitry Andric     GoogleStyle.SpaceAfterCStyleCast = true;
17240b57cec5SDimitry Andric     GoogleStyle.SpacesBeforeTrailingComments = 1;
17250b57cec5SDimitry Andric   } else if (Language == FormatStyle::LK_JavaScript) {
17260b57cec5SDimitry Andric     GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
17275ffd83dbSDimitry Andric     GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
17280b57cec5SDimitry Andric     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
17295ffd83dbSDimitry Andric     // TODO: still under discussion whether to switch to SLS_All.
17305ffd83dbSDimitry Andric     GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
17310b57cec5SDimitry Andric     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
17320b57cec5SDimitry Andric     GoogleStyle.BreakBeforeTernaryOperators = false;
17335ffd83dbSDimitry Andric     // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is
17345ffd83dbSDimitry Andric     // commonly followed by overlong URLs.
17355ffd83dbSDimitry Andric     GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)";
17365ffd83dbSDimitry Andric     // TODO: enable once decided, in particular re disabling bin packing.
17375ffd83dbSDimitry Andric     // https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma
17385ffd83dbSDimitry Andric     // GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
1739*0fca6ea1SDimitry Andric     GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single;
1740*0fca6ea1SDimitry Andric     GoogleStyle.JavaScriptWrapImports = false;
17410b57cec5SDimitry Andric     GoogleStyle.MaxEmptyLinesToKeep = 3;
17420b57cec5SDimitry Andric     GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
17430b57cec5SDimitry Andric     GoogleStyle.SpacesInContainerLiterals = false;
17440b57cec5SDimitry Andric   } else if (Language == FormatStyle::LK_Proto) {
17450b57cec5SDimitry Andric     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
17460b57cec5SDimitry Andric     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
17470b57cec5SDimitry Andric     // This affects protocol buffer options specifications and text protos.
17480b57cec5SDimitry Andric     // Text protos are currently mostly formatted inside C++ raw string literals
17490b57cec5SDimitry Andric     // and often the current breaking behavior of string literals is not
17500b57cec5SDimitry Andric     // beneficial there. Investigate turning this on once proper string reflow
17510b57cec5SDimitry Andric     // has been implemented.
17520b57cec5SDimitry Andric     GoogleStyle.BreakStringLiterals = false;
1753*0fca6ea1SDimitry Andric     GoogleStyle.Cpp11BracedListStyle = false;
1754*0fca6ea1SDimitry Andric     GoogleStyle.SpacesInContainerLiterals = false;
17550b57cec5SDimitry Andric   } else if (Language == FormatStyle::LK_ObjC) {
17560b57cec5SDimitry Andric     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
17570b57cec5SDimitry Andric     GoogleStyle.ColumnLimit = 100;
17580b57cec5SDimitry Andric     // "Regroup" doesn't work well for ObjC yet (main header heuristic,
17590b57cec5SDimitry Andric     // relationship between ObjC standard library headers and other heades,
17600b57cec5SDimitry Andric     // #imports, etc.)
17610b57cec5SDimitry Andric     GoogleStyle.IncludeStyle.IncludeBlocks =
17620b57cec5SDimitry Andric         tooling::IncludeStyle::IBS_Preserve;
17635ffd83dbSDimitry Andric   } else if (Language == FormatStyle::LK_CSharp) {
17645ffd83dbSDimitry Andric     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
17655ffd83dbSDimitry Andric     GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
17665ffd83dbSDimitry Andric     GoogleStyle.BreakStringLiterals = false;
17675ffd83dbSDimitry Andric     GoogleStyle.ColumnLimit = 100;
17685ffd83dbSDimitry Andric     GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
17690b57cec5SDimitry Andric   }
17700b57cec5SDimitry Andric 
17710b57cec5SDimitry Andric   return GoogleStyle;
17720b57cec5SDimitry Andric }
17730b57cec5SDimitry Andric 
17740b57cec5SDimitry Andric FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
17750b57cec5SDimitry Andric   FormatStyle ChromiumStyle = getGoogleStyle(Language);
1776a7dea167SDimitry Andric 
1777a7dea167SDimitry Andric   // Disable include reordering across blocks in Chromium code.
1778a7dea167SDimitry Andric   // - clang-format tries to detect that foo.h is the "main" header for
1779a7dea167SDimitry Andric   //   foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium
1780a7dea167SDimitry Andric   //   uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc,
1781a7dea167SDimitry Andric   //   _private.cc, _impl.cc etc) in different permutations
1782a7dea167SDimitry Andric   //   (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a
1783a7dea167SDimitry Andric   //   better default for Chromium code.
1784a7dea167SDimitry Andric   // - The default for .cc and .mm files is different (r357695) for Google style
1785a7dea167SDimitry Andric   //   for the same reason. The plan is to unify this again once the main
1786a7dea167SDimitry Andric   //   header detection works for Google's ObjC code, but this hasn't happened
1787a7dea167SDimitry Andric   //   yet. Since Chromium has some ObjC code, switching Chromium is blocked
1788a7dea167SDimitry Andric   //   on that.
1789a7dea167SDimitry Andric   // - Finally, "If include reordering is harmful, put things in different
1790a7dea167SDimitry Andric   //   blocks to prevent it" has been a recommendation for a long time that
1791a7dea167SDimitry Andric   //   people are used to. We'll need a dev education push to change this to
1792a7dea167SDimitry Andric   //   "If include reordering is harmful, put things in a different block and
1793a7dea167SDimitry Andric   //   _prepend that with a comment_ to prevent it" before changing behavior.
1794a7dea167SDimitry Andric   ChromiumStyle.IncludeStyle.IncludeBlocks =
1795a7dea167SDimitry Andric       tooling::IncludeStyle::IBS_Preserve;
1796a7dea167SDimitry Andric 
17970b57cec5SDimitry Andric   if (Language == FormatStyle::LK_Java) {
17980b57cec5SDimitry Andric     ChromiumStyle.AllowShortIfStatementsOnASingleLine =
17990b57cec5SDimitry Andric         FormatStyle::SIS_WithoutElse;
18000b57cec5SDimitry Andric     ChromiumStyle.BreakAfterJavaFieldAnnotations = true;
18010b57cec5SDimitry Andric     ChromiumStyle.ContinuationIndentWidth = 8;
18020b57cec5SDimitry Andric     ChromiumStyle.IndentWidth = 4;
18030b57cec5SDimitry Andric     // See styleguide for import groups:
1804349cc55cSDimitry Andric     // https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/java/java.md#Import-Order
18050b57cec5SDimitry Andric     ChromiumStyle.JavaImportGroups = {
18060b57cec5SDimitry Andric         "android",
18070b57cec5SDimitry Andric         "androidx",
18080b57cec5SDimitry Andric         "com",
18090b57cec5SDimitry Andric         "dalvik",
18100b57cec5SDimitry Andric         "junit",
18110b57cec5SDimitry Andric         "org",
18120b57cec5SDimitry Andric         "com.google.android.apps.chrome",
18130b57cec5SDimitry Andric         "org.chromium",
18140b57cec5SDimitry Andric         "java",
18150b57cec5SDimitry Andric         "javax",
18160b57cec5SDimitry Andric     };
1817fe6060f1SDimitry Andric     ChromiumStyle.SortIncludes = FormatStyle::SI_CaseSensitive;
18180b57cec5SDimitry Andric   } else if (Language == FormatStyle::LK_JavaScript) {
18190b57cec5SDimitry Andric     ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
18200b57cec5SDimitry Andric     ChromiumStyle.AllowShortLoopsOnASingleLine = false;
18210b57cec5SDimitry Andric   } else {
18220b57cec5SDimitry Andric     ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
18230b57cec5SDimitry Andric     ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
18240b57cec5SDimitry Andric     ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
18250b57cec5SDimitry Andric     ChromiumStyle.AllowShortLoopsOnASingleLine = false;
18260b57cec5SDimitry Andric     ChromiumStyle.BinPackParameters = false;
18270b57cec5SDimitry Andric     ChromiumStyle.DerivePointerAlignment = false;
18280b57cec5SDimitry Andric     if (Language == FormatStyle::LK_ObjC)
18290b57cec5SDimitry Andric       ChromiumStyle.ColumnLimit = 80;
18300b57cec5SDimitry Andric   }
18310b57cec5SDimitry Andric   return ChromiumStyle;
18320b57cec5SDimitry Andric }
18330b57cec5SDimitry Andric 
18340b57cec5SDimitry Andric FormatStyle getMozillaStyle() {
18350b57cec5SDimitry Andric   FormatStyle MozillaStyle = getLLVMStyle();
18360b57cec5SDimitry Andric   MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
18370b57cec5SDimitry Andric   MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
18380b57cec5SDimitry Andric   MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
18390b57cec5SDimitry Andric       FormatStyle::DRTBS_TopLevel;
18400b57cec5SDimitry Andric   MozillaStyle.BinPackArguments = false;
1841*0fca6ea1SDimitry Andric   MozillaStyle.BinPackParameters = false;
1842*0fca6ea1SDimitry Andric   MozillaStyle.BreakAfterReturnType = FormatStyle::RTBS_TopLevel;
18430b57cec5SDimitry Andric   MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
18440b57cec5SDimitry Andric   MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
18450b57cec5SDimitry Andric   MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
1846*0fca6ea1SDimitry Andric   MozillaStyle.BreakTemplateDeclarations = FormatStyle::BTDS_Yes;
18470b57cec5SDimitry Andric   MozillaStyle.ConstructorInitializerIndentWidth = 2;
18480b57cec5SDimitry Andric   MozillaStyle.ContinuationIndentWidth = 2;
18490b57cec5SDimitry Andric   MozillaStyle.Cpp11BracedListStyle = false;
18500b57cec5SDimitry Andric   MozillaStyle.FixNamespaceComments = false;
18510b57cec5SDimitry Andric   MozillaStyle.IndentCaseLabels = true;
18520b57cec5SDimitry Andric   MozillaStyle.ObjCSpaceAfterProperty = true;
18530b57cec5SDimitry Andric   MozillaStyle.ObjCSpaceBeforeProtocolList = false;
18540b57cec5SDimitry Andric   MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
18550b57cec5SDimitry Andric   MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
18560b57cec5SDimitry Andric   MozillaStyle.SpaceAfterTemplateKeyword = false;
18570b57cec5SDimitry Andric   return MozillaStyle;
18580b57cec5SDimitry Andric }
18590b57cec5SDimitry Andric 
18600b57cec5SDimitry Andric FormatStyle getWebKitStyle() {
18610b57cec5SDimitry Andric   FormatStyle Style = getLLVMStyle();
18620b57cec5SDimitry Andric   Style.AccessModifierOffset = -4;
18630b57cec5SDimitry Andric   Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
18645ffd83dbSDimitry Andric   Style.AlignOperands = FormatStyle::OAS_DontAlign;
1865bdd1243dSDimitry Andric   Style.AlignTrailingComments = {};
1866bdd1243dSDimitry Andric   Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;
1867a7dea167SDimitry Andric   Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;
18680b57cec5SDimitry Andric   Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
18690b57cec5SDimitry Andric   Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
18700b57cec5SDimitry Andric   Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
18710b57cec5SDimitry Andric   Style.ColumnLimit = 0;
1872*0fca6ea1SDimitry Andric   Style.Cpp11BracedListStyle = false;
18730b57cec5SDimitry Andric   Style.FixNamespaceComments = false;
18740b57cec5SDimitry Andric   Style.IndentWidth = 4;
18750b57cec5SDimitry Andric   Style.NamespaceIndentation = FormatStyle::NI_Inner;
18760b57cec5SDimitry Andric   Style.ObjCBlockIndentWidth = 4;
18770b57cec5SDimitry Andric   Style.ObjCSpaceAfterProperty = true;
18780b57cec5SDimitry Andric   Style.PointerAlignment = FormatStyle::PAS_Left;
18790b57cec5SDimitry Andric   Style.SpaceBeforeCpp11BracedList = true;
1880a7dea167SDimitry Andric   Style.SpaceInEmptyBlock = true;
18810b57cec5SDimitry Andric   return Style;
18820b57cec5SDimitry Andric }
18830b57cec5SDimitry Andric 
18840b57cec5SDimitry Andric FormatStyle getGNUStyle() {
18850b57cec5SDimitry Andric   FormatStyle Style = getLLVMStyle();
18860b57cec5SDimitry Andric   Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
1887*0fca6ea1SDimitry Andric   Style.BreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
18880b57cec5SDimitry Andric   Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
18890b57cec5SDimitry Andric   Style.BreakBeforeBraces = FormatStyle::BS_GNU;
18900b57cec5SDimitry Andric   Style.BreakBeforeTernaryOperators = true;
18910b57cec5SDimitry Andric   Style.ColumnLimit = 79;
1892*0fca6ea1SDimitry Andric   Style.Cpp11BracedListStyle = false;
18930b57cec5SDimitry Andric   Style.FixNamespaceComments = false;
18940b57cec5SDimitry Andric   Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
18950b57cec5SDimitry Andric   Style.Standard = FormatStyle::LS_Cpp03;
18960b57cec5SDimitry Andric   return Style;
18970b57cec5SDimitry Andric }
18980b57cec5SDimitry Andric 
18990b57cec5SDimitry Andric FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) {
1900a7dea167SDimitry Andric   FormatStyle Style = getLLVMStyle(Language);
19010b57cec5SDimitry Andric   Style.ColumnLimit = 120;
19020b57cec5SDimitry Andric   Style.TabWidth = 4;
19030b57cec5SDimitry Andric   Style.IndentWidth = 4;
19040b57cec5SDimitry Andric   Style.UseTab = FormatStyle::UT_Never;
19050b57cec5SDimitry Andric   Style.BreakBeforeBraces = FormatStyle::BS_Custom;
19060b57cec5SDimitry Andric   Style.BraceWrapping.AfterClass = true;
1907a7dea167SDimitry Andric   Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
19080b57cec5SDimitry Andric   Style.BraceWrapping.AfterEnum = true;
19090b57cec5SDimitry Andric   Style.BraceWrapping.AfterFunction = true;
19100b57cec5SDimitry Andric   Style.BraceWrapping.AfterNamespace = true;
19110b57cec5SDimitry Andric   Style.BraceWrapping.AfterObjCDeclaration = true;
19120b57cec5SDimitry Andric   Style.BraceWrapping.AfterStruct = true;
19130b57cec5SDimitry Andric   Style.BraceWrapping.AfterExternBlock = true;
19140b57cec5SDimitry Andric   Style.BraceWrapping.BeforeCatch = true;
19150b57cec5SDimitry Andric   Style.BraceWrapping.BeforeElse = true;
19165ffd83dbSDimitry Andric   Style.BraceWrapping.BeforeWhile = false;
19170b57cec5SDimitry Andric   Style.PenaltyReturnTypeOnItsOwnLine = 1000;
19185ffd83dbSDimitry Andric   Style.AllowShortEnumsOnASingleLine = false;
19190b57cec5SDimitry Andric   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
19200b57cec5SDimitry Andric   Style.AllowShortCaseLabelsOnASingleLine = false;
19210b57cec5SDimitry Andric   Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
19220b57cec5SDimitry Andric   Style.AllowShortLoopsOnASingleLine = false;
1923a7dea167SDimitry Andric   Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
1924*0fca6ea1SDimitry Andric   Style.BreakAfterReturnType = FormatStyle::RTBS_None;
19250b57cec5SDimitry Andric   return Style;
19260b57cec5SDimitry Andric }
19270b57cec5SDimitry Andric 
19285f757f3fSDimitry Andric FormatStyle getClangFormatStyle() {
19295f757f3fSDimitry Andric   FormatStyle Style = getLLVMStyle();
19305f757f3fSDimitry Andric   Style.InsertBraces = true;
19315f757f3fSDimitry Andric   Style.InsertNewlineAtEOF = true;
1932*0fca6ea1SDimitry Andric   Style.IntegerLiteralSeparator.Decimal = 3;
1933*0fca6ea1SDimitry Andric   Style.IntegerLiteralSeparator.DecimalMinDigits = 5;
19345f757f3fSDimitry Andric   Style.LineEnding = FormatStyle::LE_LF;
19355f757f3fSDimitry Andric   Style.RemoveBracesLLVM = true;
19365f757f3fSDimitry Andric   Style.RemoveParentheses = FormatStyle::RPS_ReturnStatement;
1937*0fca6ea1SDimitry Andric   Style.RemoveSemicolon = true;
19385f757f3fSDimitry Andric   return Style;
19395f757f3fSDimitry Andric }
19405f757f3fSDimitry Andric 
19410b57cec5SDimitry Andric FormatStyle getNoStyle() {
19420b57cec5SDimitry Andric   FormatStyle NoStyle = getLLVMStyle();
19430b57cec5SDimitry Andric   NoStyle.DisableFormat = true;
1944fe6060f1SDimitry Andric   NoStyle.SortIncludes = FormatStyle::SI_Never;
1945bdd1243dSDimitry Andric   NoStyle.SortUsingDeclarations = FormatStyle::SUD_Never;
19460b57cec5SDimitry Andric   return NoStyle;
19470b57cec5SDimitry Andric }
19480b57cec5SDimitry Andric 
19490b57cec5SDimitry Andric bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
19500b57cec5SDimitry Andric                         FormatStyle *Style) {
195181ad6265SDimitry Andric   if (Name.equals_insensitive("llvm"))
19520b57cec5SDimitry Andric     *Style = getLLVMStyle(Language);
195381ad6265SDimitry Andric   else if (Name.equals_insensitive("chromium"))
19540b57cec5SDimitry Andric     *Style = getChromiumStyle(Language);
195581ad6265SDimitry Andric   else if (Name.equals_insensitive("mozilla"))
19560b57cec5SDimitry Andric     *Style = getMozillaStyle();
195781ad6265SDimitry Andric   else if (Name.equals_insensitive("google"))
19580b57cec5SDimitry Andric     *Style = getGoogleStyle(Language);
195981ad6265SDimitry Andric   else if (Name.equals_insensitive("webkit"))
19600b57cec5SDimitry Andric     *Style = getWebKitStyle();
196181ad6265SDimitry Andric   else if (Name.equals_insensitive("gnu"))
19620b57cec5SDimitry Andric     *Style = getGNUStyle();
196381ad6265SDimitry Andric   else if (Name.equals_insensitive("microsoft"))
19640b57cec5SDimitry Andric     *Style = getMicrosoftStyle(Language);
19655f757f3fSDimitry Andric   else if (Name.equals_insensitive("clang-format"))
19665f757f3fSDimitry Andric     *Style = getClangFormatStyle();
196781ad6265SDimitry Andric   else if (Name.equals_insensitive("none"))
19680b57cec5SDimitry Andric     *Style = getNoStyle();
196981ad6265SDimitry Andric   else if (Name.equals_insensitive("inheritparentconfig"))
1970fe6060f1SDimitry Andric     Style->InheritsParentConfig = true;
197181ad6265SDimitry Andric   else
19720b57cec5SDimitry Andric     return false;
19730b57cec5SDimitry Andric 
19740b57cec5SDimitry Andric   Style->Language = Language;
19750b57cec5SDimitry Andric   return true;
19760b57cec5SDimitry Andric }
19770b57cec5SDimitry Andric 
1978349cc55cSDimitry Andric ParseError validateQualifierOrder(FormatStyle *Style) {
1979349cc55cSDimitry Andric   // If its empty then it means don't do anything.
1980349cc55cSDimitry Andric   if (Style->QualifierOrder.empty())
1981349cc55cSDimitry Andric     return ParseError::MissingQualifierOrder;
1982349cc55cSDimitry Andric 
1983349cc55cSDimitry Andric   // Ensure the list contains only currently valid qualifiers.
1984349cc55cSDimitry Andric   for (const auto &Qualifier : Style->QualifierOrder) {
1985349cc55cSDimitry Andric     if (Qualifier == "type")
1986349cc55cSDimitry Andric       continue;
1987349cc55cSDimitry Andric     auto token =
1988349cc55cSDimitry Andric         LeftRightQualifierAlignmentFixer::getTokenFromQualifier(Qualifier);
1989349cc55cSDimitry Andric     if (token == tok::identifier)
1990349cc55cSDimitry Andric       return ParseError::InvalidQualifierSpecified;
1991349cc55cSDimitry Andric   }
199281ad6265SDimitry Andric 
199381ad6265SDimitry Andric   // Ensure the list is unique (no duplicates).
1994349cc55cSDimitry Andric   std::set<std::string> UniqueQualifiers(Style->QualifierOrder.begin(),
1995349cc55cSDimitry Andric                                          Style->QualifierOrder.end());
1996349cc55cSDimitry Andric   if (Style->QualifierOrder.size() != UniqueQualifiers.size()) {
1997349cc55cSDimitry Andric     LLVM_DEBUG(llvm::dbgs()
1998349cc55cSDimitry Andric                << "Duplicate Qualifiers " << Style->QualifierOrder.size()
1999349cc55cSDimitry Andric                << " vs " << UniqueQualifiers.size() << "\n");
2000349cc55cSDimitry Andric     return ParseError::DuplicateQualifierSpecified;
2001349cc55cSDimitry Andric   }
2002349cc55cSDimitry Andric 
200381ad6265SDimitry Andric   // Ensure the list has 'type' in it.
2004bdd1243dSDimitry Andric   if (!llvm::is_contained(Style->QualifierOrder, "type"))
2005349cc55cSDimitry Andric     return ParseError::MissingQualifierType;
200681ad6265SDimitry Andric 
2007349cc55cSDimitry Andric   return ParseError::Success;
2008349cc55cSDimitry Andric }
2009349cc55cSDimitry Andric 
2010e8d8bef9SDimitry Andric std::error_code parseConfiguration(llvm::MemoryBufferRef Config,
2011fe6060f1SDimitry Andric                                    FormatStyle *Style, bool AllowUnknownOptions,
2012fe6060f1SDimitry Andric                                    llvm::SourceMgr::DiagHandlerTy DiagHandler,
2013fe6060f1SDimitry Andric                                    void *DiagHandlerCtxt) {
20140b57cec5SDimitry Andric   assert(Style);
20150b57cec5SDimitry Andric   FormatStyle::LanguageKind Language = Style->Language;
20160b57cec5SDimitry Andric   assert(Language != FormatStyle::LK_None);
2017e8d8bef9SDimitry Andric   if (Config.getBuffer().trim().empty())
201881ad6265SDimitry Andric     return make_error_code(ParseError::Success);
20190b57cec5SDimitry Andric   Style->StyleSet.Clear();
20200b57cec5SDimitry Andric   std::vector<FormatStyle> Styles;
2021fe6060f1SDimitry Andric   llvm::yaml::Input Input(Config, /*Ctxt=*/nullptr, DiagHandler,
2022fe6060f1SDimitry Andric                           DiagHandlerCtxt);
20230b57cec5SDimitry Andric   // DocumentListTraits<vector<FormatStyle>> uses the context to get default
20240b57cec5SDimitry Andric   // values for the fields, keys for which are missing from the configuration.
20250b57cec5SDimitry Andric   // Mapping also uses the context to get the language to find the correct
20260b57cec5SDimitry Andric   // base style.
20270b57cec5SDimitry Andric   Input.setContext(Style);
2028e8d8bef9SDimitry Andric   Input.setAllowUnknownKeys(AllowUnknownOptions);
20290b57cec5SDimitry Andric   Input >> Styles;
20300b57cec5SDimitry Andric   if (Input.error())
20310b57cec5SDimitry Andric     return Input.error();
20320b57cec5SDimitry Andric 
20330b57cec5SDimitry Andric   for (unsigned i = 0; i < Styles.size(); ++i) {
20340b57cec5SDimitry Andric     // Ensures that only the first configuration can skip the Language option.
20350b57cec5SDimitry Andric     if (Styles[i].Language == FormatStyle::LK_None && i != 0)
20360b57cec5SDimitry Andric       return make_error_code(ParseError::Error);
20370b57cec5SDimitry Andric     // Ensure that each language is configured at most once.
20380b57cec5SDimitry Andric     for (unsigned j = 0; j < i; ++j) {
20390b57cec5SDimitry Andric       if (Styles[i].Language == Styles[j].Language) {
20400b57cec5SDimitry Andric         LLVM_DEBUG(llvm::dbgs()
20410b57cec5SDimitry Andric                    << "Duplicate languages in the config file on positions "
20420b57cec5SDimitry Andric                    << j << " and " << i << "\n");
20430b57cec5SDimitry Andric         return make_error_code(ParseError::Error);
20440b57cec5SDimitry Andric       }
20450b57cec5SDimitry Andric     }
20460b57cec5SDimitry Andric   }
20470b57cec5SDimitry Andric   // Look for a suitable configuration starting from the end, so we can
20480b57cec5SDimitry Andric   // find the configuration for the specific language first, and the default
20490b57cec5SDimitry Andric   // configuration (which can only be at slot 0) after it.
20500b57cec5SDimitry Andric   FormatStyle::FormatStyleSet StyleSet;
20510b57cec5SDimitry Andric   bool LanguageFound = false;
20521fd87a68SDimitry Andric   for (const FormatStyle &Style : llvm::reverse(Styles)) {
20531fd87a68SDimitry Andric     if (Style.Language != FormatStyle::LK_None)
20541fd87a68SDimitry Andric       StyleSet.Add(Style);
20551fd87a68SDimitry Andric     if (Style.Language == Language)
20560b57cec5SDimitry Andric       LanguageFound = true;
20570b57cec5SDimitry Andric   }
20580b57cec5SDimitry Andric   if (!LanguageFound) {
20590b57cec5SDimitry Andric     if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None)
20600b57cec5SDimitry Andric       return make_error_code(ParseError::Unsuitable);
20610b57cec5SDimitry Andric     FormatStyle DefaultStyle = Styles[0];
20620b57cec5SDimitry Andric     DefaultStyle.Language = Language;
20630b57cec5SDimitry Andric     StyleSet.Add(std::move(DefaultStyle));
20640b57cec5SDimitry Andric   }
20650b57cec5SDimitry Andric   *Style = *StyleSet.Get(Language);
20665ffd83dbSDimitry Andric   if (Style->InsertTrailingCommas != FormatStyle::TCS_None &&
20675ffd83dbSDimitry Andric       Style->BinPackArguments) {
20685ffd83dbSDimitry Andric     // See comment on FormatStyle::TSC_Wrapped.
20695ffd83dbSDimitry Andric     return make_error_code(ParseError::BinPackTrailingCommaConflict);
20705ffd83dbSDimitry Andric   }
2071349cc55cSDimitry Andric   if (Style->QualifierAlignment != FormatStyle::QAS_Leave)
2072349cc55cSDimitry Andric     return make_error_code(validateQualifierOrder(Style));
20730b57cec5SDimitry Andric   return make_error_code(ParseError::Success);
20740b57cec5SDimitry Andric }
20750b57cec5SDimitry Andric 
20760b57cec5SDimitry Andric std::string configurationAsText(const FormatStyle &Style) {
20770b57cec5SDimitry Andric   std::string Text;
20780b57cec5SDimitry Andric   llvm::raw_string_ostream Stream(Text);
20790b57cec5SDimitry Andric   llvm::yaml::Output Output(Stream);
20800b57cec5SDimitry Andric   // We use the same mapping method for input and output, so we need a non-const
20810b57cec5SDimitry Andric   // reference here.
2082349cc55cSDimitry Andric   FormatStyle NonConstStyle = Style;
2083349cc55cSDimitry Andric   expandPresetsBraceWrapping(NonConstStyle);
2084349cc55cSDimitry Andric   expandPresetsSpaceBeforeParens(NonConstStyle);
208506c3fb27SDimitry Andric   expandPresetsSpacesInParens(NonConstStyle);
20860b57cec5SDimitry Andric   Output << NonConstStyle;
2087349cc55cSDimitry Andric 
20880b57cec5SDimitry Andric   return Stream.str();
20890b57cec5SDimitry Andric }
20900b57cec5SDimitry Andric 
2091bdd1243dSDimitry Andric std::optional<FormatStyle>
20920b57cec5SDimitry Andric FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {
20930b57cec5SDimitry Andric   if (!Styles)
2094bdd1243dSDimitry Andric     return std::nullopt;
20950b57cec5SDimitry Andric   auto It = Styles->find(Language);
20960b57cec5SDimitry Andric   if (It == Styles->end())
2097bdd1243dSDimitry Andric     return std::nullopt;
20980b57cec5SDimitry Andric   FormatStyle Style = It->second;
20990b57cec5SDimitry Andric   Style.StyleSet = *this;
21000b57cec5SDimitry Andric   return Style;
21010b57cec5SDimitry Andric }
21020b57cec5SDimitry Andric 
21030b57cec5SDimitry Andric void FormatStyle::FormatStyleSet::Add(FormatStyle Style) {
21040b57cec5SDimitry Andric   assert(Style.Language != LK_None &&
21050b57cec5SDimitry Andric          "Cannot add a style for LK_None to a StyleSet");
21060b57cec5SDimitry Andric   assert(
21070b57cec5SDimitry Andric       !Style.StyleSet.Styles &&
21080b57cec5SDimitry Andric       "Cannot add a style associated with an existing StyleSet to a StyleSet");
21090b57cec5SDimitry Andric   if (!Styles)
21100b57cec5SDimitry Andric     Styles = std::make_shared<MapType>();
21110b57cec5SDimitry Andric   (*Styles)[Style.Language] = std::move(Style);
21120b57cec5SDimitry Andric }
21130b57cec5SDimitry Andric 
21140b57cec5SDimitry Andric void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); }
21150b57cec5SDimitry Andric 
2116bdd1243dSDimitry Andric std::optional<FormatStyle>
21170b57cec5SDimitry Andric FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {
21180b57cec5SDimitry Andric   return StyleSet.Get(Language);
21190b57cec5SDimitry Andric }
21200b57cec5SDimitry Andric 
21210b57cec5SDimitry Andric namespace {
21220b57cec5SDimitry Andric 
212306c3fb27SDimitry Andric class ParensRemover : public TokenAnalyzer {
212406c3fb27SDimitry Andric public:
212506c3fb27SDimitry Andric   ParensRemover(const Environment &Env, const FormatStyle &Style)
212606c3fb27SDimitry Andric       : TokenAnalyzer(Env, Style) {}
212706c3fb27SDimitry Andric 
212806c3fb27SDimitry Andric   std::pair<tooling::Replacements, unsigned>
212906c3fb27SDimitry Andric   analyze(TokenAnnotator &Annotator,
213006c3fb27SDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
213106c3fb27SDimitry Andric           FormatTokenLexer &Tokens) override {
213206c3fb27SDimitry Andric     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
213306c3fb27SDimitry Andric     tooling::Replacements Result;
213406c3fb27SDimitry Andric     removeParens(AnnotatedLines, Result);
213506c3fb27SDimitry Andric     return {Result, 0};
213606c3fb27SDimitry Andric   }
213706c3fb27SDimitry Andric 
213806c3fb27SDimitry Andric private:
213906c3fb27SDimitry Andric   void removeParens(SmallVectorImpl<AnnotatedLine *> &Lines,
214006c3fb27SDimitry Andric                     tooling::Replacements &Result) {
214106c3fb27SDimitry Andric     const auto &SourceMgr = Env.getSourceManager();
214206c3fb27SDimitry Andric     for (auto *Line : Lines) {
214306c3fb27SDimitry Andric       removeParens(Line->Children, Result);
214406c3fb27SDimitry Andric       if (!Line->Affected)
214506c3fb27SDimitry Andric         continue;
214606c3fb27SDimitry Andric       for (const auto *Token = Line->First; Token && !Token->Finalized;
214706c3fb27SDimitry Andric            Token = Token->Next) {
214806c3fb27SDimitry Andric         if (!Token->Optional || !Token->isOneOf(tok::l_paren, tok::r_paren))
214906c3fb27SDimitry Andric           continue;
215006c3fb27SDimitry Andric         auto *Next = Token->Next;
215106c3fb27SDimitry Andric         assert(Next && Next->isNot(tok::eof));
215206c3fb27SDimitry Andric         SourceLocation Start;
215306c3fb27SDimitry Andric         if (Next->NewlinesBefore == 0) {
215406c3fb27SDimitry Andric           Start = Token->Tok.getLocation();
215506c3fb27SDimitry Andric           Next->WhitespaceRange = Token->WhitespaceRange;
215606c3fb27SDimitry Andric         } else {
215706c3fb27SDimitry Andric           Start = Token->WhitespaceRange.getBegin();
215806c3fb27SDimitry Andric         }
215906c3fb27SDimitry Andric         const auto &Range =
216006c3fb27SDimitry Andric             CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
216106c3fb27SDimitry Andric         cantFail(Result.add(tooling::Replacement(SourceMgr, Range, " ")));
216206c3fb27SDimitry Andric       }
216306c3fb27SDimitry Andric     }
216406c3fb27SDimitry Andric   }
216506c3fb27SDimitry Andric };
216606c3fb27SDimitry Andric 
216781ad6265SDimitry Andric class BracesInserter : public TokenAnalyzer {
216881ad6265SDimitry Andric public:
216981ad6265SDimitry Andric   BracesInserter(const Environment &Env, const FormatStyle &Style)
2170bdd1243dSDimitry Andric       : TokenAnalyzer(Env, Style) {}
217181ad6265SDimitry Andric 
217281ad6265SDimitry Andric   std::pair<tooling::Replacements, unsigned>
217381ad6265SDimitry Andric   analyze(TokenAnnotator &Annotator,
217481ad6265SDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
217581ad6265SDimitry Andric           FormatTokenLexer &Tokens) override {
217681ad6265SDimitry Andric     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
217781ad6265SDimitry Andric     tooling::Replacements Result;
217881ad6265SDimitry Andric     insertBraces(AnnotatedLines, Result);
217981ad6265SDimitry Andric     return {Result, 0};
218081ad6265SDimitry Andric   }
218181ad6265SDimitry Andric 
218281ad6265SDimitry Andric private:
218381ad6265SDimitry Andric   void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
218481ad6265SDimitry Andric                     tooling::Replacements &Result) {
218581ad6265SDimitry Andric     const auto &SourceMgr = Env.getSourceManager();
2186bdd1243dSDimitry Andric     int OpeningBraceSurplus = 0;
218781ad6265SDimitry Andric     for (AnnotatedLine *Line : Lines) {
218881ad6265SDimitry Andric       insertBraces(Line->Children, Result);
2189bdd1243dSDimitry Andric       if (!Line->Affected && OpeningBraceSurplus == 0)
219081ad6265SDimitry Andric         continue;
219181ad6265SDimitry Andric       for (FormatToken *Token = Line->First; Token && !Token->Finalized;
219281ad6265SDimitry Andric            Token = Token->Next) {
2193bdd1243dSDimitry Andric         int BraceCount = Token->BraceCount;
2194bdd1243dSDimitry Andric         if (BraceCount == 0)
219581ad6265SDimitry Andric           continue;
219681ad6265SDimitry Andric         std::string Brace;
2197bdd1243dSDimitry Andric         if (BraceCount < 0) {
2198bdd1243dSDimitry Andric           assert(BraceCount == -1);
2199bdd1243dSDimitry Andric           if (!Line->Affected)
2200bdd1243dSDimitry Andric             break;
2201bdd1243dSDimitry Andric           Brace = Token->is(tok::comment) ? "\n{" : "{";
2202bdd1243dSDimitry Andric           ++OpeningBraceSurplus;
220381ad6265SDimitry Andric         } else {
2204bdd1243dSDimitry Andric           if (OpeningBraceSurplus == 0)
2205bdd1243dSDimitry Andric             break;
2206bdd1243dSDimitry Andric           if (OpeningBraceSurplus < BraceCount)
2207bdd1243dSDimitry Andric             BraceCount = OpeningBraceSurplus;
2208bdd1243dSDimitry Andric           Brace = '\n' + std::string(BraceCount, '}');
2209bdd1243dSDimitry Andric           OpeningBraceSurplus -= BraceCount;
221081ad6265SDimitry Andric         }
221181ad6265SDimitry Andric         Token->BraceCount = 0;
221281ad6265SDimitry Andric         const auto Start = Token->Tok.getEndLoc();
221381ad6265SDimitry Andric         cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0, Brace)));
221481ad6265SDimitry Andric       }
221581ad6265SDimitry Andric     }
2216bdd1243dSDimitry Andric     assert(OpeningBraceSurplus == 0);
221781ad6265SDimitry Andric   }
221881ad6265SDimitry Andric };
221981ad6265SDimitry Andric 
222004eeddc0SDimitry Andric class BracesRemover : public TokenAnalyzer {
222104eeddc0SDimitry Andric public:
222204eeddc0SDimitry Andric   BracesRemover(const Environment &Env, const FormatStyle &Style)
2223bdd1243dSDimitry Andric       : TokenAnalyzer(Env, Style) {}
222404eeddc0SDimitry Andric 
222504eeddc0SDimitry Andric   std::pair<tooling::Replacements, unsigned>
222604eeddc0SDimitry Andric   analyze(TokenAnnotator &Annotator,
222704eeddc0SDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
222804eeddc0SDimitry Andric           FormatTokenLexer &Tokens) override {
222904eeddc0SDimitry Andric     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
223004eeddc0SDimitry Andric     tooling::Replacements Result;
223104eeddc0SDimitry Andric     removeBraces(AnnotatedLines, Result);
223204eeddc0SDimitry Andric     return {Result, 0};
223304eeddc0SDimitry Andric   }
223404eeddc0SDimitry Andric 
223504eeddc0SDimitry Andric private:
223604eeddc0SDimitry Andric   void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
223704eeddc0SDimitry Andric                     tooling::Replacements &Result) {
223804eeddc0SDimitry Andric     const auto &SourceMgr = Env.getSourceManager();
2239bdd1243dSDimitry Andric     const auto End = Lines.end();
2240bdd1243dSDimitry Andric     for (auto I = Lines.begin(); I != End; ++I) {
2241bdd1243dSDimitry Andric       const auto Line = *I;
224204eeddc0SDimitry Andric       removeBraces(Line->Children, Result);
2243bdd1243dSDimitry Andric       if (!Line->Affected)
2244bdd1243dSDimitry Andric         continue;
2245bdd1243dSDimitry Andric       const auto NextLine = I + 1 == End ? nullptr : I[1];
2246bdd1243dSDimitry Andric       for (auto Token = Line->First; Token && !Token->Finalized;
224781ad6265SDimitry Andric            Token = Token->Next) {
224804eeddc0SDimitry Andric         if (!Token->Optional)
224904eeddc0SDimitry Andric           continue;
2250bdd1243dSDimitry Andric         if (!Token->isOneOf(tok::l_brace, tok::r_brace))
2251bdd1243dSDimitry Andric           continue;
2252bdd1243dSDimitry Andric         auto Next = Token->Next;
2253fcaf7f86SDimitry Andric         assert(Next || Token == Line->Last);
2254bdd1243dSDimitry Andric         if (!Next && NextLine)
2255bdd1243dSDimitry Andric           Next = NextLine->First;
2256bdd1243dSDimitry Andric         SourceLocation Start;
2257bdd1243dSDimitry Andric         if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2258bdd1243dSDimitry Andric           Start = Token->Tok.getLocation();
2259bdd1243dSDimitry Andric           Next->WhitespaceRange = Token->WhitespaceRange;
2260bdd1243dSDimitry Andric         } else {
2261bdd1243dSDimitry Andric           Start = Token->WhitespaceRange.getBegin();
2262bdd1243dSDimitry Andric         }
226304eeddc0SDimitry Andric         const auto Range =
226404eeddc0SDimitry Andric             CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
226504eeddc0SDimitry Andric         cantFail(Result.add(tooling::Replacement(SourceMgr, Range, "")));
226604eeddc0SDimitry Andric       }
226704eeddc0SDimitry Andric     }
2268bdd1243dSDimitry Andric   }
2269bdd1243dSDimitry Andric };
2270bdd1243dSDimitry Andric 
2271bdd1243dSDimitry Andric class SemiRemover : public TokenAnalyzer {
2272bdd1243dSDimitry Andric public:
2273bdd1243dSDimitry Andric   SemiRemover(const Environment &Env, const FormatStyle &Style)
2274bdd1243dSDimitry Andric       : TokenAnalyzer(Env, Style) {}
2275bdd1243dSDimitry Andric 
2276bdd1243dSDimitry Andric   std::pair<tooling::Replacements, unsigned>
2277bdd1243dSDimitry Andric   analyze(TokenAnnotator &Annotator,
2278bdd1243dSDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2279bdd1243dSDimitry Andric           FormatTokenLexer &Tokens) override {
2280bdd1243dSDimitry Andric     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2281bdd1243dSDimitry Andric     tooling::Replacements Result;
2282*0fca6ea1SDimitry Andric     removeSemi(Annotator, AnnotatedLines, Result);
2283bdd1243dSDimitry Andric     return {Result, 0};
2284bdd1243dSDimitry Andric   }
2285bdd1243dSDimitry Andric 
2286bdd1243dSDimitry Andric private:
2287*0fca6ea1SDimitry Andric   void removeSemi(TokenAnnotator &Annotator,
2288*0fca6ea1SDimitry Andric                   SmallVectorImpl<AnnotatedLine *> &Lines,
2289bdd1243dSDimitry Andric                   tooling::Replacements &Result) {
2290*0fca6ea1SDimitry Andric     auto PrecededByFunctionRBrace = [](const FormatToken &Tok) {
2291*0fca6ea1SDimitry Andric       const auto *Prev = Tok.Previous;
2292*0fca6ea1SDimitry Andric       if (!Prev || Prev->isNot(tok::r_brace))
2293*0fca6ea1SDimitry Andric         return false;
2294*0fca6ea1SDimitry Andric       const auto *LBrace = Prev->MatchingParen;
2295*0fca6ea1SDimitry Andric       return LBrace && LBrace->is(TT_FunctionLBrace);
2296*0fca6ea1SDimitry Andric     };
2297bdd1243dSDimitry Andric     const auto &SourceMgr = Env.getSourceManager();
2298bdd1243dSDimitry Andric     const auto End = Lines.end();
2299bdd1243dSDimitry Andric     for (auto I = Lines.begin(); I != End; ++I) {
2300bdd1243dSDimitry Andric       const auto Line = *I;
2301*0fca6ea1SDimitry Andric       removeSemi(Annotator, Line->Children, Result);
2302bdd1243dSDimitry Andric       if (!Line->Affected)
2303bdd1243dSDimitry Andric         continue;
2304*0fca6ea1SDimitry Andric       Annotator.calculateFormattingInformation(*Line);
2305bdd1243dSDimitry Andric       const auto NextLine = I + 1 == End ? nullptr : I[1];
2306bdd1243dSDimitry Andric       for (auto Token = Line->First; Token && !Token->Finalized;
2307bdd1243dSDimitry Andric            Token = Token->Next) {
2308*0fca6ea1SDimitry Andric         if (Token->isNot(tok::semi) ||
2309*0fca6ea1SDimitry Andric             (!Token->Optional && !PrecededByFunctionRBrace(*Token))) {
2310bdd1243dSDimitry Andric           continue;
2311*0fca6ea1SDimitry Andric         }
2312bdd1243dSDimitry Andric         auto Next = Token->Next;
2313bdd1243dSDimitry Andric         assert(Next || Token == Line->Last);
2314bdd1243dSDimitry Andric         if (!Next && NextLine)
2315bdd1243dSDimitry Andric           Next = NextLine->First;
2316bdd1243dSDimitry Andric         SourceLocation Start;
2317bdd1243dSDimitry Andric         if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2318bdd1243dSDimitry Andric           Start = Token->Tok.getLocation();
2319bdd1243dSDimitry Andric           Next->WhitespaceRange = Token->WhitespaceRange;
2320bdd1243dSDimitry Andric         } else {
2321bdd1243dSDimitry Andric           Start = Token->WhitespaceRange.getBegin();
2322bdd1243dSDimitry Andric         }
2323bdd1243dSDimitry Andric         const auto Range =
2324bdd1243dSDimitry Andric             CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2325bdd1243dSDimitry Andric         cantFail(Result.add(tooling::Replacement(SourceMgr, Range, "")));
2326bdd1243dSDimitry Andric       }
2327fcaf7f86SDimitry Andric     }
232804eeddc0SDimitry Andric   }
232904eeddc0SDimitry Andric };
233004eeddc0SDimitry Andric 
23310b57cec5SDimitry Andric class JavaScriptRequoter : public TokenAnalyzer {
23320b57cec5SDimitry Andric public:
23330b57cec5SDimitry Andric   JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)
23340b57cec5SDimitry Andric       : TokenAnalyzer(Env, Style) {}
23350b57cec5SDimitry Andric 
23360b57cec5SDimitry Andric   std::pair<tooling::Replacements, unsigned>
23370b57cec5SDimitry Andric   analyze(TokenAnnotator &Annotator,
23380b57cec5SDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
23390b57cec5SDimitry Andric           FormatTokenLexer &Tokens) override {
23400b57cec5SDimitry Andric     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
23410b57cec5SDimitry Andric     tooling::Replacements Result;
23420b57cec5SDimitry Andric     requoteJSStringLiteral(AnnotatedLines, Result);
23430b57cec5SDimitry Andric     return {Result, 0};
23440b57cec5SDimitry Andric   }
23450b57cec5SDimitry Andric 
23460b57cec5SDimitry Andric private:
23470b57cec5SDimitry Andric   // Replaces double/single-quoted string literal as appropriate, re-escaping
23480b57cec5SDimitry Andric   // the contents in the process.
23490b57cec5SDimitry Andric   void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
23500b57cec5SDimitry Andric                               tooling::Replacements &Result) {
23510b57cec5SDimitry Andric     for (AnnotatedLine *Line : Lines) {
23520b57cec5SDimitry Andric       requoteJSStringLiteral(Line->Children, Result);
23530b57cec5SDimitry Andric       if (!Line->Affected)
23540b57cec5SDimitry Andric         continue;
23550b57cec5SDimitry Andric       for (FormatToken *FormatTok = Line->First; FormatTok;
23560b57cec5SDimitry Andric            FormatTok = FormatTok->Next) {
23570b57cec5SDimitry Andric         StringRef Input = FormatTok->TokenText;
23580b57cec5SDimitry Andric         if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
23590b57cec5SDimitry Andric             // NB: testing for not starting with a double quote to avoid
23600b57cec5SDimitry Andric             // breaking `template strings`.
23610b57cec5SDimitry Andric             (Style.JavaScriptQuotes == FormatStyle::JSQS_Single &&
23625f757f3fSDimitry Andric              !Input.starts_with("\"")) ||
23630b57cec5SDimitry Andric             (Style.JavaScriptQuotes == FormatStyle::JSQS_Double &&
23645f757f3fSDimitry Andric              !Input.starts_with("\'"))) {
23650b57cec5SDimitry Andric           continue;
236681ad6265SDimitry Andric         }
23670b57cec5SDimitry Andric 
23680b57cec5SDimitry Andric         // Change start and end quote.
23690b57cec5SDimitry Andric         bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single;
23700b57cec5SDimitry Andric         SourceLocation Start = FormatTok->Tok.getLocation();
23710b57cec5SDimitry Andric         auto Replace = [&](SourceLocation Start, unsigned Length,
23720b57cec5SDimitry Andric                            StringRef ReplacementText) {
23730b57cec5SDimitry Andric           auto Err = Result.add(tooling::Replacement(
23740b57cec5SDimitry Andric               Env.getSourceManager(), Start, Length, ReplacementText));
23750b57cec5SDimitry Andric           // FIXME: handle error. For now, print error message and skip the
23760b57cec5SDimitry Andric           // replacement for release version.
23770b57cec5SDimitry Andric           if (Err) {
2378*0fca6ea1SDimitry Andric             llvm::errs() << toString(std::move(Err)) << "\n";
23790b57cec5SDimitry Andric             assert(false);
23800b57cec5SDimitry Andric           }
23810b57cec5SDimitry Andric         };
23820b57cec5SDimitry Andric         Replace(Start, 1, IsSingle ? "'" : "\"");
23830b57cec5SDimitry Andric         Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
23840b57cec5SDimitry Andric                 IsSingle ? "'" : "\"");
23850b57cec5SDimitry Andric 
23860b57cec5SDimitry Andric         // Escape internal quotes.
23870b57cec5SDimitry Andric         bool Escaped = false;
23880b57cec5SDimitry Andric         for (size_t i = 1; i < Input.size() - 1; i++) {
23890b57cec5SDimitry Andric           switch (Input[i]) {
23900b57cec5SDimitry Andric           case '\\':
23910b57cec5SDimitry Andric             if (!Escaped && i + 1 < Input.size() &&
23920b57cec5SDimitry Andric                 ((IsSingle && Input[i + 1] == '"') ||
23930b57cec5SDimitry Andric                  (!IsSingle && Input[i + 1] == '\''))) {
23940b57cec5SDimitry Andric               // Remove this \, it's escaping a " or ' that no longer needs
23950b57cec5SDimitry Andric               // escaping
23960b57cec5SDimitry Andric               Replace(Start.getLocWithOffset(i), 1, "");
23970b57cec5SDimitry Andric               continue;
23980b57cec5SDimitry Andric             }
23990b57cec5SDimitry Andric             Escaped = !Escaped;
24000b57cec5SDimitry Andric             break;
24010b57cec5SDimitry Andric           case '\"':
24020b57cec5SDimitry Andric           case '\'':
24030b57cec5SDimitry Andric             if (!Escaped && IsSingle == (Input[i] == '\'')) {
24040b57cec5SDimitry Andric               // Escape the quote.
24050b57cec5SDimitry Andric               Replace(Start.getLocWithOffset(i), 0, "\\");
24060b57cec5SDimitry Andric             }
24070b57cec5SDimitry Andric             Escaped = false;
24080b57cec5SDimitry Andric             break;
24090b57cec5SDimitry Andric           default:
24100b57cec5SDimitry Andric             Escaped = false;
24110b57cec5SDimitry Andric             break;
24120b57cec5SDimitry Andric           }
24130b57cec5SDimitry Andric         }
24140b57cec5SDimitry Andric       }
24150b57cec5SDimitry Andric     }
24160b57cec5SDimitry Andric   }
24170b57cec5SDimitry Andric };
24180b57cec5SDimitry Andric 
24190b57cec5SDimitry Andric class Formatter : public TokenAnalyzer {
24200b57cec5SDimitry Andric public:
24210b57cec5SDimitry Andric   Formatter(const Environment &Env, const FormatStyle &Style,
24220b57cec5SDimitry Andric             FormattingAttemptStatus *Status)
24230b57cec5SDimitry Andric       : TokenAnalyzer(Env, Style), Status(Status) {}
24240b57cec5SDimitry Andric 
24250b57cec5SDimitry Andric   std::pair<tooling::Replacements, unsigned>
24260b57cec5SDimitry Andric   analyze(TokenAnnotator &Annotator,
24270b57cec5SDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
24280b57cec5SDimitry Andric           FormatTokenLexer &Tokens) override {
24290b57cec5SDimitry Andric     tooling::Replacements Result;
24300b57cec5SDimitry Andric     deriveLocalStyle(AnnotatedLines);
24310b57cec5SDimitry Andric     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
24321fd87a68SDimitry Andric     for (AnnotatedLine *Line : AnnotatedLines)
24331fd87a68SDimitry Andric       Annotator.calculateFormattingInformation(*Line);
24340b57cec5SDimitry Andric     Annotator.setCommentLineLevels(AnnotatedLines);
24350b57cec5SDimitry Andric 
24360b57cec5SDimitry Andric     WhitespaceManager Whitespaces(
24370b57cec5SDimitry Andric         Env.getSourceManager(), Style,
2438bdd1243dSDimitry Andric         Style.LineEnding > FormatStyle::LE_CRLF
243904eeddc0SDimitry Andric             ? WhitespaceManager::inputUsesCRLF(
2440480093f4SDimitry Andric                   Env.getSourceManager().getBufferData(Env.getFileID()),
2441bdd1243dSDimitry Andric                   Style.LineEnding == FormatStyle::LE_DeriveCRLF)
2442bdd1243dSDimitry Andric             : Style.LineEnding == FormatStyle::LE_CRLF);
24430b57cec5SDimitry Andric     ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
24440b57cec5SDimitry Andric                                   Env.getSourceManager(), Whitespaces, Encoding,
24450b57cec5SDimitry Andric                                   BinPackInconclusiveFunctions);
24460b57cec5SDimitry Andric     unsigned Penalty =
24470b57cec5SDimitry Andric         UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,
24480b57cec5SDimitry Andric                                Tokens.getKeywords(), Env.getSourceManager(),
24490b57cec5SDimitry Andric                                Status)
24500b57cec5SDimitry Andric             .format(AnnotatedLines, /*DryRun=*/false,
24510b57cec5SDimitry Andric                     /*AdditionalIndent=*/0,
24520b57cec5SDimitry Andric                     /*FixBadIndentation=*/false,
24530b57cec5SDimitry Andric                     /*FirstStartColumn=*/Env.getFirstStartColumn(),
24540b57cec5SDimitry Andric                     /*NextStartColumn=*/Env.getNextStartColumn(),
24550b57cec5SDimitry Andric                     /*LastStartColumn=*/Env.getLastStartColumn());
24560b57cec5SDimitry Andric     for (const auto &R : Whitespaces.generateReplacements())
24570b57cec5SDimitry Andric       if (Result.add(R))
24580b57cec5SDimitry Andric         return std::make_pair(Result, 0);
24590b57cec5SDimitry Andric     return std::make_pair(Result, Penalty);
24600b57cec5SDimitry Andric   }
24610b57cec5SDimitry Andric 
24620b57cec5SDimitry Andric private:
24630b57cec5SDimitry Andric   bool
24640b57cec5SDimitry Andric   hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) {
24650b57cec5SDimitry Andric     for (const AnnotatedLine *Line : Lines) {
24660b57cec5SDimitry Andric       if (hasCpp03IncompatibleFormat(Line->Children))
24670b57cec5SDimitry Andric         return true;
24680b57cec5SDimitry Andric       for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {
246904eeddc0SDimitry Andric         if (!Tok->hasWhitespaceBefore()) {
24700b57cec5SDimitry Andric           if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
24710b57cec5SDimitry Andric             return true;
24720b57cec5SDimitry Andric           if (Tok->is(TT_TemplateCloser) &&
247381ad6265SDimitry Andric               Tok->Previous->is(TT_TemplateCloser)) {
24740b57cec5SDimitry Andric             return true;
24750b57cec5SDimitry Andric           }
24760b57cec5SDimitry Andric         }
24770b57cec5SDimitry Andric       }
247881ad6265SDimitry Andric     }
24790b57cec5SDimitry Andric     return false;
24800b57cec5SDimitry Andric   }
24810b57cec5SDimitry Andric 
24820b57cec5SDimitry Andric   int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) {
24830b57cec5SDimitry Andric     int AlignmentDiff = 0;
24840b57cec5SDimitry Andric     for (const AnnotatedLine *Line : Lines) {
24850b57cec5SDimitry Andric       AlignmentDiff += countVariableAlignments(Line->Children);
24860b57cec5SDimitry Andric       for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {
24875f757f3fSDimitry Andric         if (Tok->isNot(TT_PointerOrReference))
24880b57cec5SDimitry Andric           continue;
248981ad6265SDimitry Andric         // Don't treat space in `void foo() &&` as evidence.
249081ad6265SDimitry Andric         if (const auto *Prev = Tok->getPreviousNonComment()) {
249181ad6265SDimitry Andric           if (Prev->is(tok::r_paren) && Prev->MatchingParen) {
249281ad6265SDimitry Andric             if (const auto *Func =
249381ad6265SDimitry Andric                     Prev->MatchingParen->getPreviousNonComment()) {
249481ad6265SDimitry Andric               if (Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName,
249581ad6265SDimitry Andric                                 TT_OverloadedOperator)) {
249681ad6265SDimitry Andric                 continue;
249781ad6265SDimitry Andric               }
249881ad6265SDimitry Andric             }
249981ad6265SDimitry Andric           }
250081ad6265SDimitry Andric         }
250104eeddc0SDimitry Andric         bool SpaceBefore = Tok->hasWhitespaceBefore();
250204eeddc0SDimitry Andric         bool SpaceAfter = Tok->Next->hasWhitespaceBefore();
25030b57cec5SDimitry Andric         if (SpaceBefore && !SpaceAfter)
25040b57cec5SDimitry Andric           ++AlignmentDiff;
25050b57cec5SDimitry Andric         if (!SpaceBefore && SpaceAfter)
25060b57cec5SDimitry Andric           --AlignmentDiff;
25070b57cec5SDimitry Andric       }
25080b57cec5SDimitry Andric     }
25090b57cec5SDimitry Andric     return AlignmentDiff;
25100b57cec5SDimitry Andric   }
25110b57cec5SDimitry Andric 
25120b57cec5SDimitry Andric   void
25130b57cec5SDimitry Andric   deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
25140b57cec5SDimitry Andric     bool HasBinPackedFunction = false;
25150b57cec5SDimitry Andric     bool HasOnePerLineFunction = false;
25161fd87a68SDimitry Andric     for (AnnotatedLine *Line : AnnotatedLines) {
25171fd87a68SDimitry Andric       if (!Line->First->Next)
25180b57cec5SDimitry Andric         continue;
25191fd87a68SDimitry Andric       FormatToken *Tok = Line->First->Next;
25200b57cec5SDimitry Andric       while (Tok->Next) {
2521e8d8bef9SDimitry Andric         if (Tok->is(PPK_BinPacked))
25220b57cec5SDimitry Andric           HasBinPackedFunction = true;
2523e8d8bef9SDimitry Andric         if (Tok->is(PPK_OnePerLine))
25240b57cec5SDimitry Andric           HasOnePerLineFunction = true;
25250b57cec5SDimitry Andric 
25260b57cec5SDimitry Andric         Tok = Tok->Next;
25270b57cec5SDimitry Andric       }
25280b57cec5SDimitry Andric     }
2529fe6060f1SDimitry Andric     if (Style.DerivePointerAlignment) {
2530bdd1243dSDimitry Andric       const auto NetRightCount = countVariableAlignments(AnnotatedLines);
2531bdd1243dSDimitry Andric       if (NetRightCount > 0)
2532bdd1243dSDimitry Andric         Style.PointerAlignment = FormatStyle::PAS_Right;
2533bdd1243dSDimitry Andric       else if (NetRightCount < 0)
2534bdd1243dSDimitry Andric         Style.PointerAlignment = FormatStyle::PAS_Left;
2535fe6060f1SDimitry Andric       Style.ReferenceAlignment = FormatStyle::RAS_Pointer;
2536fe6060f1SDimitry Andric     }
253781ad6265SDimitry Andric     if (Style.Standard == FormatStyle::LS_Auto) {
25380b57cec5SDimitry Andric       Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
2539a7dea167SDimitry Andric                            ? FormatStyle::LS_Latest
25400b57cec5SDimitry Andric                            : FormatStyle::LS_Cpp03;
254181ad6265SDimitry Andric     }
25420b57cec5SDimitry Andric     BinPackInconclusiveFunctions =
25430b57cec5SDimitry Andric         HasBinPackedFunction || !HasOnePerLineFunction;
25440b57cec5SDimitry Andric   }
25450b57cec5SDimitry Andric 
25460b57cec5SDimitry Andric   bool BinPackInconclusiveFunctions;
25470b57cec5SDimitry Andric   FormattingAttemptStatus *Status;
25480b57cec5SDimitry Andric };
25490b57cec5SDimitry Andric 
25505ffd83dbSDimitry Andric /// TrailingCommaInserter inserts trailing commas into container literals.
25515ffd83dbSDimitry Andric /// E.g.:
25525ffd83dbSDimitry Andric ///     const x = [
25535ffd83dbSDimitry Andric ///       1,
25545ffd83dbSDimitry Andric ///     ];
25555ffd83dbSDimitry Andric /// TrailingCommaInserter runs after formatting. To avoid causing a required
25565ffd83dbSDimitry Andric /// reformatting (and thus reflow), it never inserts a comma that'd exceed the
25575ffd83dbSDimitry Andric /// ColumnLimit.
25585ffd83dbSDimitry Andric ///
25595ffd83dbSDimitry Andric /// Because trailing commas disable binpacking of arrays, TrailingCommaInserter
25605ffd83dbSDimitry Andric /// is conceptually incompatible with bin packing.
25615ffd83dbSDimitry Andric class TrailingCommaInserter : public TokenAnalyzer {
25625ffd83dbSDimitry Andric public:
25635ffd83dbSDimitry Andric   TrailingCommaInserter(const Environment &Env, const FormatStyle &Style)
25645ffd83dbSDimitry Andric       : TokenAnalyzer(Env, Style) {}
25655ffd83dbSDimitry Andric 
25665ffd83dbSDimitry Andric   std::pair<tooling::Replacements, unsigned>
25675ffd83dbSDimitry Andric   analyze(TokenAnnotator &Annotator,
25685ffd83dbSDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
25695ffd83dbSDimitry Andric           FormatTokenLexer &Tokens) override {
25705ffd83dbSDimitry Andric     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
25715ffd83dbSDimitry Andric     tooling::Replacements Result;
25725ffd83dbSDimitry Andric     insertTrailingCommas(AnnotatedLines, Result);
25735ffd83dbSDimitry Andric     return {Result, 0};
25745ffd83dbSDimitry Andric   }
25755ffd83dbSDimitry Andric 
25765ffd83dbSDimitry Andric private:
25775ffd83dbSDimitry Andric   /// Inserts trailing commas in [] and {} initializers if they wrap over
25785ffd83dbSDimitry Andric   /// multiple lines.
25795ffd83dbSDimitry Andric   void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,
25805ffd83dbSDimitry Andric                             tooling::Replacements &Result) {
25815ffd83dbSDimitry Andric     for (AnnotatedLine *Line : Lines) {
25825ffd83dbSDimitry Andric       insertTrailingCommas(Line->Children, Result);
25835ffd83dbSDimitry Andric       if (!Line->Affected)
25845ffd83dbSDimitry Andric         continue;
25855ffd83dbSDimitry Andric       for (FormatToken *FormatTok = Line->First; FormatTok;
25865ffd83dbSDimitry Andric            FormatTok = FormatTok->Next) {
25875ffd83dbSDimitry Andric         if (FormatTok->NewlinesBefore == 0)
25885ffd83dbSDimitry Andric           continue;
25895ffd83dbSDimitry Andric         FormatToken *Matching = FormatTok->MatchingParen;
25905ffd83dbSDimitry Andric         if (!Matching || !FormatTok->getPreviousNonComment())
25915ffd83dbSDimitry Andric           continue;
25925ffd83dbSDimitry Andric         if (!(FormatTok->is(tok::r_square) &&
25935ffd83dbSDimitry Andric               Matching->is(TT_ArrayInitializerLSquare)) &&
259481ad6265SDimitry Andric             !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) {
25955ffd83dbSDimitry Andric           continue;
259681ad6265SDimitry Andric         }
25975ffd83dbSDimitry Andric         FormatToken *Prev = FormatTok->getPreviousNonComment();
25985ffd83dbSDimitry Andric         if (Prev->is(tok::comma) || Prev->is(tok::semi))
25995ffd83dbSDimitry Andric           continue;
26005ffd83dbSDimitry Andric         // getEndLoc is not reliably set during re-lexing, use text length
26015ffd83dbSDimitry Andric         // instead.
26025ffd83dbSDimitry Andric         SourceLocation Start =
26035ffd83dbSDimitry Andric             Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size());
26045ffd83dbSDimitry Andric         // If inserting a comma would push the code over the column limit, skip
26055ffd83dbSDimitry Andric         // this location - it'd introduce an unstable formatting due to the
26065ffd83dbSDimitry Andric         // required reflow.
26075ffd83dbSDimitry Andric         unsigned ColumnNumber =
26085ffd83dbSDimitry Andric             Env.getSourceManager().getSpellingColumnNumber(Start);
26095ffd83dbSDimitry Andric         if (ColumnNumber > Style.ColumnLimit)
26105ffd83dbSDimitry Andric           continue;
26115ffd83dbSDimitry Andric         // Comma insertions cannot conflict with each other, and this pass has a
26125ffd83dbSDimitry Andric         // clean set of Replacements, so the operation below cannot fail.
26135ffd83dbSDimitry Andric         cantFail(Result.add(
26145ffd83dbSDimitry Andric             tooling::Replacement(Env.getSourceManager(), Start, 0, ",")));
26155ffd83dbSDimitry Andric       }
26165ffd83dbSDimitry Andric     }
26175ffd83dbSDimitry Andric   }
26185ffd83dbSDimitry Andric };
26195ffd83dbSDimitry Andric 
26200b57cec5SDimitry Andric // This class clean up the erroneous/redundant code around the given ranges in
26210b57cec5SDimitry Andric // file.
26220b57cec5SDimitry Andric class Cleaner : public TokenAnalyzer {
26230b57cec5SDimitry Andric public:
26240b57cec5SDimitry Andric   Cleaner(const Environment &Env, const FormatStyle &Style)
26250b57cec5SDimitry Andric       : TokenAnalyzer(Env, Style),
26260b57cec5SDimitry Andric         DeletedTokens(FormatTokenLess(Env.getSourceManager())) {}
26270b57cec5SDimitry Andric 
26280b57cec5SDimitry Andric   // FIXME: eliminate unused parameters.
26290b57cec5SDimitry Andric   std::pair<tooling::Replacements, unsigned>
26300b57cec5SDimitry Andric   analyze(TokenAnnotator &Annotator,
26310b57cec5SDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
26320b57cec5SDimitry Andric           FormatTokenLexer &Tokens) override {
26330b57cec5SDimitry Andric     // FIXME: in the current implementation the granularity of affected range
26340b57cec5SDimitry Andric     // is an annotated line. However, this is not sufficient. Furthermore,
26350b57cec5SDimitry Andric     // redundant code introduced by replacements does not necessarily
26360b57cec5SDimitry Andric     // intercept with ranges of replacements that result in the redundancy.
26370b57cec5SDimitry Andric     // To determine if some redundant code is actually introduced by
26380b57cec5SDimitry Andric     // replacements(e.g. deletions), we need to come up with a more
26390b57cec5SDimitry Andric     // sophisticated way of computing affected ranges.
26400b57cec5SDimitry Andric     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
26410b57cec5SDimitry Andric 
26420b57cec5SDimitry Andric     checkEmptyNamespace(AnnotatedLines);
26430b57cec5SDimitry Andric 
2644a7dea167SDimitry Andric     for (auto *Line : AnnotatedLines)
2645a7dea167SDimitry Andric       cleanupLine(Line);
2646a7dea167SDimitry Andric 
2647a7dea167SDimitry Andric     return {generateFixes(), 0};
2648a7dea167SDimitry Andric   }
2649a7dea167SDimitry Andric 
2650a7dea167SDimitry Andric private:
2651a7dea167SDimitry Andric   void cleanupLine(AnnotatedLine *Line) {
265281ad6265SDimitry Andric     for (auto *Child : Line->Children)
2653a7dea167SDimitry Andric       cleanupLine(Child);
2654a7dea167SDimitry Andric 
26550b57cec5SDimitry Andric     if (Line->Affected) {
26560b57cec5SDimitry Andric       cleanupRight(Line->First, tok::comma, tok::comma);
26570b57cec5SDimitry Andric       cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
26580b57cec5SDimitry Andric       cleanupRight(Line->First, tok::l_paren, tok::comma);
26590b57cec5SDimitry Andric       cleanupLeft(Line->First, tok::comma, tok::r_paren);
26600b57cec5SDimitry Andric       cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
26610b57cec5SDimitry Andric       cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
26620b57cec5SDimitry Andric       cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
26630b57cec5SDimitry Andric     }
26640b57cec5SDimitry Andric   }
26650b57cec5SDimitry Andric 
26660b57cec5SDimitry Andric   bool containsOnlyComments(const AnnotatedLine &Line) {
266706c3fb27SDimitry Andric     for (FormatToken *Tok = Line.First; Tok; Tok = Tok->Next)
26680b57cec5SDimitry Andric       if (Tok->isNot(tok::comment))
26690b57cec5SDimitry Andric         return false;
26700b57cec5SDimitry Andric     return true;
26710b57cec5SDimitry Andric   }
26720b57cec5SDimitry Andric 
26730b57cec5SDimitry Andric   // Iterate through all lines and remove any empty (nested) namespaces.
26740b57cec5SDimitry Andric   void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
26750b57cec5SDimitry Andric     std::set<unsigned> DeletedLines;
26760b57cec5SDimitry Andric     for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
26770b57cec5SDimitry Andric       auto &Line = *AnnotatedLines[i];
267881ad6265SDimitry Andric       if (Line.startsWithNamespace())
26790b57cec5SDimitry Andric         checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
26800b57cec5SDimitry Andric     }
26810b57cec5SDimitry Andric 
26820b57cec5SDimitry Andric     for (auto Line : DeletedLines) {
26830b57cec5SDimitry Andric       FormatToken *Tok = AnnotatedLines[Line]->First;
26840b57cec5SDimitry Andric       while (Tok) {
26850b57cec5SDimitry Andric         deleteToken(Tok);
26860b57cec5SDimitry Andric         Tok = Tok->Next;
26870b57cec5SDimitry Andric       }
26880b57cec5SDimitry Andric     }
26890b57cec5SDimitry Andric   }
26900b57cec5SDimitry Andric 
26910b57cec5SDimitry Andric   // The function checks if the namespace, which starts from \p CurrentLine, and
26920b57cec5SDimitry Andric   // its nested namespaces are empty and delete them if they are empty. It also
26930b57cec5SDimitry Andric   // sets \p NewLine to the last line checked.
26940b57cec5SDimitry Andric   // Returns true if the current namespace is empty.
26950b57cec5SDimitry Andric   bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
26960b57cec5SDimitry Andric                            unsigned CurrentLine, unsigned &NewLine,
26970b57cec5SDimitry Andric                            std::set<unsigned> &DeletedLines) {
26980b57cec5SDimitry Andric     unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
26990b57cec5SDimitry Andric     if (Style.BraceWrapping.AfterNamespace) {
27000b57cec5SDimitry Andric       // If the left brace is in a new line, we should consume it first so that
27010b57cec5SDimitry Andric       // it does not make the namespace non-empty.
27020b57cec5SDimitry Andric       // FIXME: error handling if there is no left brace.
27030b57cec5SDimitry Andric       if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
27040b57cec5SDimitry Andric         NewLine = CurrentLine;
27050b57cec5SDimitry Andric         return false;
27060b57cec5SDimitry Andric       }
27070b57cec5SDimitry Andric     } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
27080b57cec5SDimitry Andric       return false;
27090b57cec5SDimitry Andric     }
27100b57cec5SDimitry Andric     while (++CurrentLine < End) {
27110b57cec5SDimitry Andric       if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
27120b57cec5SDimitry Andric         break;
27130b57cec5SDimitry Andric 
27140b57cec5SDimitry Andric       if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
27150b57cec5SDimitry Andric         if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
271681ad6265SDimitry Andric                                  DeletedLines)) {
27170b57cec5SDimitry Andric           return false;
271881ad6265SDimitry Andric         }
27190b57cec5SDimitry Andric         CurrentLine = NewLine;
27200b57cec5SDimitry Andric         continue;
27210b57cec5SDimitry Andric       }
27220b57cec5SDimitry Andric 
27230b57cec5SDimitry Andric       if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
27240b57cec5SDimitry Andric         continue;
27250b57cec5SDimitry Andric 
27260b57cec5SDimitry Andric       // If there is anything other than comments or nested namespaces in the
27270b57cec5SDimitry Andric       // current namespace, the namespace cannot be empty.
27280b57cec5SDimitry Andric       NewLine = CurrentLine;
27290b57cec5SDimitry Andric       return false;
27300b57cec5SDimitry Andric     }
27310b57cec5SDimitry Andric 
27320b57cec5SDimitry Andric     NewLine = CurrentLine;
27330b57cec5SDimitry Andric     if (CurrentLine >= End)
27340b57cec5SDimitry Andric       return false;
27350b57cec5SDimitry Andric 
27360b57cec5SDimitry Andric     // Check if the empty namespace is actually affected by changed ranges.
27370b57cec5SDimitry Andric     if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
27380b57cec5SDimitry Andric             AnnotatedLines[InitLine]->First->Tok.getLocation(),
273981ad6265SDimitry Andric             AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) {
27400b57cec5SDimitry Andric       return false;
27410b57cec5SDimitry Andric     }
27420b57cec5SDimitry Andric 
274381ad6265SDimitry Andric     for (unsigned i = InitLine; i <= CurrentLine; ++i)
274481ad6265SDimitry Andric       DeletedLines.insert(i);
274581ad6265SDimitry Andric 
27460b57cec5SDimitry Andric     return true;
27470b57cec5SDimitry Andric   }
27480b57cec5SDimitry Andric 
27490b57cec5SDimitry Andric   // Checks pairs {start, start->next},..., {end->previous, end} and deletes one
27500b57cec5SDimitry Andric   // of the token in the pair if the left token has \p LK token kind and the
27510b57cec5SDimitry Andric   // right token has \p RK token kind. If \p DeleteLeft is true, the left token
27520b57cec5SDimitry Andric   // is deleted on match; otherwise, the right token is deleted.
27530b57cec5SDimitry Andric   template <typename LeftKind, typename RightKind>
27540b57cec5SDimitry Andric   void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
27550b57cec5SDimitry Andric                    bool DeleteLeft) {
27560b57cec5SDimitry Andric     auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {
275781ad6265SDimitry Andric       for (auto *Res = Tok.Next; Res; Res = Res->Next) {
27585f757f3fSDimitry Andric         if (Res->isNot(tok::comment) &&
275981ad6265SDimitry Andric             DeletedTokens.find(Res) == DeletedTokens.end()) {
27600b57cec5SDimitry Andric           return Res;
276181ad6265SDimitry Andric         }
276281ad6265SDimitry Andric       }
27630b57cec5SDimitry Andric       return nullptr;
27640b57cec5SDimitry Andric     };
27650b57cec5SDimitry Andric     for (auto *Left = Start; Left;) {
27660b57cec5SDimitry Andric       auto *Right = NextNotDeleted(*Left);
27670b57cec5SDimitry Andric       if (!Right)
27680b57cec5SDimitry Andric         break;
27690b57cec5SDimitry Andric       if (Left->is(LK) && Right->is(RK)) {
27700b57cec5SDimitry Andric         deleteToken(DeleteLeft ? Left : Right);
27710b57cec5SDimitry Andric         for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
27720b57cec5SDimitry Andric           deleteToken(Tok);
27730b57cec5SDimitry Andric         // If the right token is deleted, we should keep the left token
27740b57cec5SDimitry Andric         // unchanged and pair it with the new right token.
27750b57cec5SDimitry Andric         if (!DeleteLeft)
27760b57cec5SDimitry Andric           continue;
27770b57cec5SDimitry Andric       }
27780b57cec5SDimitry Andric       Left = Right;
27790b57cec5SDimitry Andric     }
27800b57cec5SDimitry Andric   }
27810b57cec5SDimitry Andric 
27820b57cec5SDimitry Andric   template <typename LeftKind, typename RightKind>
27830b57cec5SDimitry Andric   void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
27840b57cec5SDimitry Andric     cleanupPair(Start, LK, RK, /*DeleteLeft=*/true);
27850b57cec5SDimitry Andric   }
27860b57cec5SDimitry Andric 
27870b57cec5SDimitry Andric   template <typename LeftKind, typename RightKind>
27880b57cec5SDimitry Andric   void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
27890b57cec5SDimitry Andric     cleanupPair(Start, LK, RK, /*DeleteLeft=*/false);
27900b57cec5SDimitry Andric   }
27910b57cec5SDimitry Andric 
27920b57cec5SDimitry Andric   // Delete the given token.
27930b57cec5SDimitry Andric   inline void deleteToken(FormatToken *Tok) {
27940b57cec5SDimitry Andric     if (Tok)
27950b57cec5SDimitry Andric       DeletedTokens.insert(Tok);
27960b57cec5SDimitry Andric   }
27970b57cec5SDimitry Andric 
27980b57cec5SDimitry Andric   tooling::Replacements generateFixes() {
27990b57cec5SDimitry Andric     tooling::Replacements Fixes;
2800753f127fSDimitry Andric     SmallVector<FormatToken *> Tokens;
28010b57cec5SDimitry Andric     std::copy(DeletedTokens.begin(), DeletedTokens.end(),
28020b57cec5SDimitry Andric               std::back_inserter(Tokens));
28030b57cec5SDimitry Andric 
28040b57cec5SDimitry Andric     // Merge multiple continuous token deletions into one big deletion so that
28050b57cec5SDimitry Andric     // the number of replacements can be reduced. This makes computing affected
28060b57cec5SDimitry Andric     // ranges more efficient when we run reformat on the changed code.
28070b57cec5SDimitry Andric     unsigned Idx = 0;
28080b57cec5SDimitry Andric     while (Idx < Tokens.size()) {
28090b57cec5SDimitry Andric       unsigned St = Idx, End = Idx;
281081ad6265SDimitry Andric       while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1])
281104eeddc0SDimitry Andric         ++End;
28120b57cec5SDimitry Andric       auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
28130b57cec5SDimitry Andric                                               Tokens[End]->Tok.getEndLoc());
28140b57cec5SDimitry Andric       auto Err =
28150b57cec5SDimitry Andric           Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, ""));
28160b57cec5SDimitry Andric       // FIXME: better error handling. for now just print error message and skip
28170b57cec5SDimitry Andric       // for the release version.
28180b57cec5SDimitry Andric       if (Err) {
2819*0fca6ea1SDimitry Andric         llvm::errs() << toString(std::move(Err)) << "\n";
28200b57cec5SDimitry Andric         assert(false && "Fixes must not conflict!");
28210b57cec5SDimitry Andric       }
28220b57cec5SDimitry Andric       Idx = End + 1;
28230b57cec5SDimitry Andric     }
28240b57cec5SDimitry Andric 
28250b57cec5SDimitry Andric     return Fixes;
28260b57cec5SDimitry Andric   }
28270b57cec5SDimitry Andric 
28280b57cec5SDimitry Andric   // Class for less-than inequality comparason for the set `RedundantTokens`.
28290b57cec5SDimitry Andric   // We store tokens in the order they appear in the translation unit so that
28300b57cec5SDimitry Andric   // we do not need to sort them in `generateFixes()`.
28310b57cec5SDimitry Andric   struct FormatTokenLess {
28320b57cec5SDimitry Andric     FormatTokenLess(const SourceManager &SM) : SM(SM) {}
28330b57cec5SDimitry Andric 
28340b57cec5SDimitry Andric     bool operator()(const FormatToken *LHS, const FormatToken *RHS) const {
28350b57cec5SDimitry Andric       return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
28360b57cec5SDimitry Andric                                           RHS->Tok.getLocation());
28370b57cec5SDimitry Andric     }
28380b57cec5SDimitry Andric     const SourceManager &SM;
28390b57cec5SDimitry Andric   };
28400b57cec5SDimitry Andric 
28410b57cec5SDimitry Andric   // Tokens to be deleted.
28420b57cec5SDimitry Andric   std::set<FormatToken *, FormatTokenLess> DeletedTokens;
28430b57cec5SDimitry Andric };
28440b57cec5SDimitry Andric 
28450b57cec5SDimitry Andric class ObjCHeaderStyleGuesser : public TokenAnalyzer {
28460b57cec5SDimitry Andric public:
28470b57cec5SDimitry Andric   ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style)
28480b57cec5SDimitry Andric       : TokenAnalyzer(Env, Style), IsObjC(false) {}
28490b57cec5SDimitry Andric 
28500b57cec5SDimitry Andric   std::pair<tooling::Replacements, unsigned>
28510b57cec5SDimitry Andric   analyze(TokenAnnotator &Annotator,
28520b57cec5SDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
28530b57cec5SDimitry Andric           FormatTokenLexer &Tokens) override {
28540b57cec5SDimitry Andric     assert(Style.Language == FormatStyle::LK_Cpp);
28550b57cec5SDimitry Andric     IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines,
28560b57cec5SDimitry Andric                          Tokens.getKeywords());
28570b57cec5SDimitry Andric     tooling::Replacements Result;
28580b57cec5SDimitry Andric     return {Result, 0};
28590b57cec5SDimitry Andric   }
28600b57cec5SDimitry Andric 
28610b57cec5SDimitry Andric   bool isObjC() { return IsObjC; }
28620b57cec5SDimitry Andric 
28630b57cec5SDimitry Andric private:
28640b57cec5SDimitry Andric   static bool
28650b57cec5SDimitry Andric   guessIsObjC(const SourceManager &SourceManager,
28660b57cec5SDimitry Andric               const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
28670b57cec5SDimitry Andric               const AdditionalKeywords &Keywords) {
28680b57cec5SDimitry Andric     // Keep this array sorted, since we are binary searching over it.
28690b57cec5SDimitry Andric     static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
28700b57cec5SDimitry Andric         "CGFloat",
28710b57cec5SDimitry Andric         "CGPoint",
28720b57cec5SDimitry Andric         "CGPointMake",
28730b57cec5SDimitry Andric         "CGPointZero",
28740b57cec5SDimitry Andric         "CGRect",
28750b57cec5SDimitry Andric         "CGRectEdge",
28760b57cec5SDimitry Andric         "CGRectInfinite",
28770b57cec5SDimitry Andric         "CGRectMake",
28780b57cec5SDimitry Andric         "CGRectNull",
28790b57cec5SDimitry Andric         "CGRectZero",
28800b57cec5SDimitry Andric         "CGSize",
28810b57cec5SDimitry Andric         "CGSizeMake",
28820b57cec5SDimitry Andric         "CGVector",
28830b57cec5SDimitry Andric         "CGVectorMake",
288406c3fb27SDimitry Andric         "FOUNDATION_EXPORT", // This is an alias for FOUNDATION_EXTERN.
288506c3fb27SDimitry Andric         "FOUNDATION_EXTERN",
28860b57cec5SDimitry Andric         "NSAffineTransform",
28870b57cec5SDimitry Andric         "NSArray",
28880b57cec5SDimitry Andric         "NSAttributedString",
28890b57cec5SDimitry Andric         "NSBlockOperation",
28900b57cec5SDimitry Andric         "NSBundle",
28910b57cec5SDimitry Andric         "NSCache",
28920b57cec5SDimitry Andric         "NSCalendar",
28930b57cec5SDimitry Andric         "NSCharacterSet",
28940b57cec5SDimitry Andric         "NSCountedSet",
28950b57cec5SDimitry Andric         "NSData",
28960b57cec5SDimitry Andric         "NSDataDetector",
28970b57cec5SDimitry Andric         "NSDecimal",
28980b57cec5SDimitry Andric         "NSDecimalNumber",
28990b57cec5SDimitry Andric         "NSDictionary",
29000b57cec5SDimitry Andric         "NSEdgeInsets",
290106c3fb27SDimitry Andric         "NSError",
290206c3fb27SDimitry Andric         "NSErrorDomain",
29030b57cec5SDimitry Andric         "NSHashTable",
29040b57cec5SDimitry Andric         "NSIndexPath",
29050b57cec5SDimitry Andric         "NSIndexSet",
29060b57cec5SDimitry Andric         "NSInteger",
29070b57cec5SDimitry Andric         "NSInvocationOperation",
29080b57cec5SDimitry Andric         "NSLocale",
29090b57cec5SDimitry Andric         "NSMapTable",
29100b57cec5SDimitry Andric         "NSMutableArray",
29110b57cec5SDimitry Andric         "NSMutableAttributedString",
29120b57cec5SDimitry Andric         "NSMutableCharacterSet",
29130b57cec5SDimitry Andric         "NSMutableData",
29140b57cec5SDimitry Andric         "NSMutableDictionary",
29150b57cec5SDimitry Andric         "NSMutableIndexSet",
29160b57cec5SDimitry Andric         "NSMutableOrderedSet",
29170b57cec5SDimitry Andric         "NSMutableSet",
29180b57cec5SDimitry Andric         "NSMutableString",
29190b57cec5SDimitry Andric         "NSNumber",
29200b57cec5SDimitry Andric         "NSNumberFormatter",
29210b57cec5SDimitry Andric         "NSObject",
29220b57cec5SDimitry Andric         "NSOperation",
29230b57cec5SDimitry Andric         "NSOperationQueue",
29240b57cec5SDimitry Andric         "NSOperationQueuePriority",
29250b57cec5SDimitry Andric         "NSOrderedSet",
29260b57cec5SDimitry Andric         "NSPoint",
29270b57cec5SDimitry Andric         "NSPointerArray",
29280b57cec5SDimitry Andric         "NSQualityOfService",
29290b57cec5SDimitry Andric         "NSRange",
29300b57cec5SDimitry Andric         "NSRect",
29310b57cec5SDimitry Andric         "NSRegularExpression",
29320b57cec5SDimitry Andric         "NSSet",
29330b57cec5SDimitry Andric         "NSSize",
29340b57cec5SDimitry Andric         "NSString",
29350b57cec5SDimitry Andric         "NSTimeZone",
29360b57cec5SDimitry Andric         "NSUInteger",
29370b57cec5SDimitry Andric         "NSURL",
29380b57cec5SDimitry Andric         "NSURLComponents",
29390b57cec5SDimitry Andric         "NSURLQueryItem",
29400b57cec5SDimitry Andric         "NSUUID",
29410b57cec5SDimitry Andric         "NSValue",
294206c3fb27SDimitry Andric         "NS_ASSUME_NONNULL_BEGIN",
29430b57cec5SDimitry Andric         "UIImage",
29440b57cec5SDimitry Andric         "UIView",
29450b57cec5SDimitry Andric     };
29460b57cec5SDimitry Andric 
2947bdd1243dSDimitry Andric     for (auto *Line : AnnotatedLines) {
29485f757f3fSDimitry Andric       if (Line->First && (Line->First->TokenText.starts_with("#") ||
2949e8d8bef9SDimitry Andric                           Line->First->TokenText == "__pragma" ||
295081ad6265SDimitry Andric                           Line->First->TokenText == "_Pragma")) {
2951e8d8bef9SDimitry Andric         continue;
295281ad6265SDimitry Andric       }
29530b57cec5SDimitry Andric       for (const FormatToken *FormatTok = Line->First; FormatTok;
29540b57cec5SDimitry Andric            FormatTok = FormatTok->Next) {
29550b57cec5SDimitry Andric         if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
29560b57cec5SDimitry Andric              (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
29570b57cec5SDimitry Andric               FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
29580b57cec5SDimitry Andric                                  tok::l_brace))) ||
29590b57cec5SDimitry Andric             (FormatTok->Tok.isAnyIdentifier() &&
29600b57cec5SDimitry Andric              std::binary_search(std::begin(FoundationIdentifiers),
29610b57cec5SDimitry Andric                                 std::end(FoundationIdentifiers),
29620b57cec5SDimitry Andric                                 FormatTok->TokenText)) ||
29630b57cec5SDimitry Andric             FormatTok->is(TT_ObjCStringLiteral) ||
2964a7dea167SDimitry Andric             FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,
296506c3fb27SDimitry Andric                                Keywords.kw_NS_ERROR_ENUM,
2966a7dea167SDimitry Andric                                Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,
2967a7dea167SDimitry Andric                                TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,
2968a7dea167SDimitry Andric                                TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,
2969a7dea167SDimitry Andric                                TT_ObjCProperty)) {
29700b57cec5SDimitry Andric           LLVM_DEBUG(llvm::dbgs()
29710b57cec5SDimitry Andric                      << "Detected ObjC at location "
29720b57cec5SDimitry Andric                      << FormatTok->Tok.getLocation().printToString(
29730b57cec5SDimitry Andric                             SourceManager)
29740b57cec5SDimitry Andric                      << " token: " << FormatTok->TokenText << " token type: "
29755ffd83dbSDimitry Andric                      << getTokenTypeName(FormatTok->getType()) << "\n");
29760b57cec5SDimitry Andric           return true;
29770b57cec5SDimitry Andric         }
2978*0fca6ea1SDimitry Andric       }
29790b57cec5SDimitry Andric       if (guessIsObjC(SourceManager, Line->Children, Keywords))
29800b57cec5SDimitry Andric         return true;
29810b57cec5SDimitry Andric     }
29820b57cec5SDimitry Andric     return false;
29830b57cec5SDimitry Andric   }
29840b57cec5SDimitry Andric 
29850b57cec5SDimitry Andric   bool IsObjC;
29860b57cec5SDimitry Andric };
29870b57cec5SDimitry Andric 
29880b57cec5SDimitry Andric struct IncludeDirective {
29890b57cec5SDimitry Andric   StringRef Filename;
29900b57cec5SDimitry Andric   StringRef Text;
29910b57cec5SDimitry Andric   unsigned Offset;
29920b57cec5SDimitry Andric   int Category;
2993a7dea167SDimitry Andric   int Priority;
29940b57cec5SDimitry Andric };
29950b57cec5SDimitry Andric 
29960b57cec5SDimitry Andric struct JavaImportDirective {
29970b57cec5SDimitry Andric   StringRef Identifier;
29980b57cec5SDimitry Andric   StringRef Text;
29990b57cec5SDimitry Andric   unsigned Offset;
3000753f127fSDimitry Andric   SmallVector<StringRef> AssociatedCommentLines;
30010b57cec5SDimitry Andric   bool IsStatic;
30020b57cec5SDimitry Andric };
30030b57cec5SDimitry Andric 
30040b57cec5SDimitry Andric } // end anonymous namespace
30050b57cec5SDimitry Andric 
30060b57cec5SDimitry Andric // Determines whether 'Ranges' intersects with ('Start', 'End').
30070b57cec5SDimitry Andric static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start,
30080b57cec5SDimitry Andric                          unsigned End) {
300906c3fb27SDimitry Andric   for (const auto &Range : Ranges) {
30100b57cec5SDimitry Andric     if (Range.getOffset() < End &&
301181ad6265SDimitry Andric         Range.getOffset() + Range.getLength() > Start) {
30120b57cec5SDimitry Andric       return true;
30130b57cec5SDimitry Andric     }
301481ad6265SDimitry Andric   }
30150b57cec5SDimitry Andric   return false;
30160b57cec5SDimitry Andric }
30170b57cec5SDimitry Andric 
30180b57cec5SDimitry Andric // Returns a pair (Index, OffsetToEOL) describing the position of the cursor
30190b57cec5SDimitry Andric // before sorting/deduplicating. Index is the index of the include under the
30200b57cec5SDimitry Andric // cursor in the original set of includes. If this include has duplicates, it is
30210b57cec5SDimitry Andric // the index of the first of the duplicates as the others are going to be
30220b57cec5SDimitry Andric // removed. OffsetToEOL describes the cursor's position relative to the end of
30230b57cec5SDimitry Andric // its current line.
30240b57cec5SDimitry Andric // If `Cursor` is not on any #include, `Index` will be UINT_MAX.
30250b57cec5SDimitry Andric static std::pair<unsigned, unsigned>
30260b57cec5SDimitry Andric FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes,
30270b57cec5SDimitry Andric                 const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) {
30280b57cec5SDimitry Andric   unsigned CursorIndex = UINT_MAX;
30290b57cec5SDimitry Andric   unsigned OffsetToEOL = 0;
30300b57cec5SDimitry Andric   for (int i = 0, e = Includes.size(); i != e; ++i) {
30310b57cec5SDimitry Andric     unsigned Start = Includes[Indices[i]].Offset;
30320b57cec5SDimitry Andric     unsigned End = Start + Includes[Indices[i]].Text.size();
30330b57cec5SDimitry Andric     if (!(Cursor >= Start && Cursor < End))
30340b57cec5SDimitry Andric       continue;
30350b57cec5SDimitry Andric     CursorIndex = Indices[i];
30360b57cec5SDimitry Andric     OffsetToEOL = End - Cursor;
30370b57cec5SDimitry Andric     // Put the cursor on the only remaining #include among the duplicate
30380b57cec5SDimitry Andric     // #includes.
30390b57cec5SDimitry Andric     while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text)
30400b57cec5SDimitry Andric       CursorIndex = i;
30410b57cec5SDimitry Andric     break;
30420b57cec5SDimitry Andric   }
30430b57cec5SDimitry Andric   return std::make_pair(CursorIndex, OffsetToEOL);
30440b57cec5SDimitry Andric }
30450b57cec5SDimitry Andric 
3046a7dea167SDimitry Andric // Replace all "\r\n" with "\n".
3047a7dea167SDimitry Andric std::string replaceCRLF(const std::string &Code) {
3048a7dea167SDimitry Andric   std::string NewCode;
3049a7dea167SDimitry Andric   size_t Pos = 0, LastPos = 0;
3050a7dea167SDimitry Andric 
3051a7dea167SDimitry Andric   do {
3052a7dea167SDimitry Andric     Pos = Code.find("\r\n", LastPos);
3053a7dea167SDimitry Andric     if (Pos == LastPos) {
305404eeddc0SDimitry Andric       ++LastPos;
3055a7dea167SDimitry Andric       continue;
3056a7dea167SDimitry Andric     }
3057a7dea167SDimitry Andric     if (Pos == std::string::npos) {
3058a7dea167SDimitry Andric       NewCode += Code.substr(LastPos);
3059a7dea167SDimitry Andric       break;
3060a7dea167SDimitry Andric     }
3061a7dea167SDimitry Andric     NewCode += Code.substr(LastPos, Pos - LastPos) + "\n";
3062a7dea167SDimitry Andric     LastPos = Pos + 2;
3063a7dea167SDimitry Andric   } while (Pos != std::string::npos);
3064a7dea167SDimitry Andric 
3065a7dea167SDimitry Andric   return NewCode;
3066a7dea167SDimitry Andric }
3067a7dea167SDimitry Andric 
30680b57cec5SDimitry Andric // Sorts and deduplicate a block of includes given by 'Includes' alphabetically
30690b57cec5SDimitry Andric // adding the necessary replacement to 'Replaces'. 'Includes' must be in strict
30700b57cec5SDimitry Andric // source order.
30710b57cec5SDimitry Andric // #include directives with the same text will be deduplicated, and only the
30720b57cec5SDimitry Andric // first #include in the duplicate #includes remains. If the `Cursor` is
30730b57cec5SDimitry Andric // provided and put on a deleted #include, it will be moved to the remaining
30740b57cec5SDimitry Andric // #include in the duplicate #includes.
30750b57cec5SDimitry Andric static void sortCppIncludes(const FormatStyle &Style,
30760b57cec5SDimitry Andric                             const SmallVectorImpl<IncludeDirective> &Includes,
30770b57cec5SDimitry Andric                             ArrayRef<tooling::Range> Ranges, StringRef FileName,
3078a7dea167SDimitry Andric                             StringRef Code, tooling::Replacements &Replaces,
3079a7dea167SDimitry Andric                             unsigned *Cursor) {
3080a7dea167SDimitry Andric   tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
308181ad6265SDimitry Andric   const unsigned IncludesBeginOffset = Includes.front().Offset;
308281ad6265SDimitry Andric   const unsigned IncludesEndOffset =
30830b57cec5SDimitry Andric       Includes.back().Offset + Includes.back().Text.size();
308481ad6265SDimitry Andric   const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
30850b57cec5SDimitry Andric   if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
30860b57cec5SDimitry Andric     return;
308781ad6265SDimitry Andric   SmallVector<unsigned, 16> Indices =
308881ad6265SDimitry Andric       llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size()));
3089fe6060f1SDimitry Andric 
3090fe6060f1SDimitry Andric   if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) {
3091*0fca6ea1SDimitry Andric     stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
3092fe6060f1SDimitry Andric       const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
3093fe6060f1SDimitry Andric       const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
3094fe6060f1SDimitry Andric       return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
3095fe6060f1SDimitry Andric                       Includes[LHSI].Filename) <
3096fe6060f1SDimitry Andric              std::tie(Includes[RHSI].Priority, RHSFilenameLower,
3097fe6060f1SDimitry Andric                       Includes[RHSI].Filename);
3098fe6060f1SDimitry Andric     });
3099fe6060f1SDimitry Andric   } else {
3100*0fca6ea1SDimitry Andric     stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
3101a7dea167SDimitry Andric       return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
3102a7dea167SDimitry Andric              std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
31030b57cec5SDimitry Andric     });
3104fe6060f1SDimitry Andric   }
3105fe6060f1SDimitry Andric 
31060b57cec5SDimitry Andric   // The index of the include on which the cursor will be put after
31070b57cec5SDimitry Andric   // sorting/deduplicating.
31080b57cec5SDimitry Andric   unsigned CursorIndex;
31090b57cec5SDimitry Andric   // The offset from cursor to the end of line.
31100b57cec5SDimitry Andric   unsigned CursorToEOLOffset;
311181ad6265SDimitry Andric   if (Cursor) {
31120b57cec5SDimitry Andric     std::tie(CursorIndex, CursorToEOLOffset) =
31130b57cec5SDimitry Andric         FindCursorIndex(Includes, Indices, *Cursor);
311481ad6265SDimitry Andric   }
31150b57cec5SDimitry Andric 
31160b57cec5SDimitry Andric   // Deduplicate #includes.
31170b57cec5SDimitry Andric   Indices.erase(std::unique(Indices.begin(), Indices.end(),
31180b57cec5SDimitry Andric                             [&](unsigned LHSI, unsigned RHSI) {
3119e8d8bef9SDimitry Andric                               return Includes[LHSI].Text.trim() ==
3120e8d8bef9SDimitry Andric                                      Includes[RHSI].Text.trim();
31210b57cec5SDimitry Andric                             }),
31220b57cec5SDimitry Andric                 Indices.end());
31230b57cec5SDimitry Andric 
31240b57cec5SDimitry Andric   int CurrentCategory = Includes.front().Category;
31250b57cec5SDimitry Andric 
31260b57cec5SDimitry Andric   // If the #includes are out of order, we generate a single replacement fixing
31270b57cec5SDimitry Andric   // the entire block. Otherwise, no replacement is generated.
31280b57cec5SDimitry Andric   // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not
31290b57cec5SDimitry Andric   // enough as additional newlines might be added or removed across #include
313081ad6265SDimitry Andric   // blocks. This we handle below by generating the updated #include blocks and
31310b57cec5SDimitry Andric   // comparing it to the original.
3132*0fca6ea1SDimitry Andric   if (Indices.size() == Includes.size() && is_sorted(Indices) &&
313381ad6265SDimitry Andric       Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) {
31340b57cec5SDimitry Andric     return;
313581ad6265SDimitry Andric   }
31360b57cec5SDimitry Andric 
3137*0fca6ea1SDimitry Andric   const auto OldCursor = Cursor ? *Cursor : 0;
31380b57cec5SDimitry Andric   std::string result;
31390b57cec5SDimitry Andric   for (unsigned Index : Indices) {
31400b57cec5SDimitry Andric     if (!result.empty()) {
31410b57cec5SDimitry Andric       result += "\n";
31420b57cec5SDimitry Andric       if (Style.IncludeStyle.IncludeBlocks ==
31430b57cec5SDimitry Andric               tooling::IncludeStyle::IBS_Regroup &&
314481ad6265SDimitry Andric           CurrentCategory != Includes[Index].Category) {
31450b57cec5SDimitry Andric         result += "\n";
31460b57cec5SDimitry Andric       }
314781ad6265SDimitry Andric     }
31480b57cec5SDimitry Andric     result += Includes[Index].Text;
31490b57cec5SDimitry Andric     if (Cursor && CursorIndex == Index)
31500b57cec5SDimitry Andric       *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
31510b57cec5SDimitry Andric     CurrentCategory = Includes[Index].Category;
31520b57cec5SDimitry Andric   }
31530b57cec5SDimitry Andric 
315481ad6265SDimitry Andric   if (Cursor && *Cursor >= IncludesEndOffset)
315581ad6265SDimitry Andric     *Cursor += result.size() - IncludesBlockSize;
315681ad6265SDimitry Andric 
31570b57cec5SDimitry Andric   // If the #includes are out of order, we generate a single replacement fixing
31580b57cec5SDimitry Andric   // the entire range of blocks. Otherwise, no replacement is generated.
31595ffd83dbSDimitry Andric   if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
316081ad6265SDimitry Andric                                  IncludesBeginOffset, IncludesBlockSize)))) {
3161*0fca6ea1SDimitry Andric     if (Cursor)
3162*0fca6ea1SDimitry Andric       *Cursor = OldCursor;
31630b57cec5SDimitry Andric     return;
316481ad6265SDimitry Andric   }
31650b57cec5SDimitry Andric 
31660b57cec5SDimitry Andric   auto Err = Replaces.add(tooling::Replacement(
31670b57cec5SDimitry Andric       FileName, Includes.front().Offset, IncludesBlockSize, result));
31680b57cec5SDimitry Andric   // FIXME: better error handling. For now, just skip the replacement for the
31690b57cec5SDimitry Andric   // release version.
31700b57cec5SDimitry Andric   if (Err) {
3171*0fca6ea1SDimitry Andric     llvm::errs() << toString(std::move(Err)) << "\n";
31720b57cec5SDimitry Andric     assert(false);
31730b57cec5SDimitry Andric   }
31740b57cec5SDimitry Andric }
31750b57cec5SDimitry Andric 
31760b57cec5SDimitry Andric tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
31770b57cec5SDimitry Andric                                       ArrayRef<tooling::Range> Ranges,
31780b57cec5SDimitry Andric                                       StringRef FileName,
31790b57cec5SDimitry Andric                                       tooling::Replacements &Replaces,
31800b57cec5SDimitry Andric                                       unsigned *Cursor) {
3181e8d8bef9SDimitry Andric   unsigned Prev = llvm::StringSwitch<size_t>(Code)
3182e8d8bef9SDimitry Andric                       .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM
3183e8d8bef9SDimitry Andric                       .Default(0);
31840b57cec5SDimitry Andric   unsigned SearchFrom = 0;
31850b57cec5SDimitry Andric   SmallVector<StringRef, 4> Matches;
31860b57cec5SDimitry Andric   SmallVector<IncludeDirective, 16> IncludesInBlock;
31870b57cec5SDimitry Andric 
31880b57cec5SDimitry Andric   // In compiled files, consider the first #include to be the main #include of
31890b57cec5SDimitry Andric   // the file if it is not a system #include. This ensures that the header
31900b57cec5SDimitry Andric   // doesn't have hidden dependencies
31910b57cec5SDimitry Andric   // (http://llvm.org/docs/CodingStandards.html#include-style).
31920b57cec5SDimitry Andric   //
31935e801ac6SDimitry Andric   // FIXME: Do some validation, e.g. edit distance of the base name, to fix
31940b57cec5SDimitry Andric   // cases where the first #include is unlikely to be the main header.
31950b57cec5SDimitry Andric   tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
31960b57cec5SDimitry Andric   bool FirstIncludeBlock = true;
31970b57cec5SDimitry Andric   bool MainIncludeFound = false;
31980b57cec5SDimitry Andric   bool FormattingOff = false;
31990b57cec5SDimitry Andric 
320004eeddc0SDimitry Andric   // '[' must be the first and '-' the last character inside [...].
32010eae32dcSDimitry Andric   llvm::Regex RawStringRegex(
320204eeddc0SDimitry Andric       "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\(");
32030eae32dcSDimitry Andric   SmallVector<StringRef, 2> RawStringMatches;
32040eae32dcSDimitry Andric   std::string RawStringTermination = ")\"";
32050eae32dcSDimitry Andric 
32060b57cec5SDimitry Andric   for (;;) {
32070b57cec5SDimitry Andric     auto Pos = Code.find('\n', SearchFrom);
32080b57cec5SDimitry Andric     StringRef Line =
32090b57cec5SDimitry Andric         Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
32100b57cec5SDimitry Andric 
32110b57cec5SDimitry Andric     StringRef Trimmed = Line.trim();
32120eae32dcSDimitry Andric 
32130eae32dcSDimitry Andric     // #includes inside raw string literals need to be ignored.
32140eae32dcSDimitry Andric     // or we will sort the contents of the string.
32150eae32dcSDimitry Andric     // Skip past until we think we are at the rawstring literal close.
32160eae32dcSDimitry Andric     if (RawStringRegex.match(Trimmed, &RawStringMatches)) {
32170eae32dcSDimitry Andric       std::string CharSequence = RawStringMatches[1].str();
32180eae32dcSDimitry Andric       RawStringTermination = ")" + CharSequence + "\"";
32190eae32dcSDimitry Andric       FormattingOff = true;
32200eae32dcSDimitry Andric     }
32210eae32dcSDimitry Andric 
322281ad6265SDimitry Andric     if (Trimmed.contains(RawStringTermination))
322381ad6265SDimitry Andric       FormattingOff = false;
322481ad6265SDimitry Andric 
3225*0fca6ea1SDimitry Andric     bool IsBlockComment = false;
3226*0fca6ea1SDimitry Andric 
3227*0fca6ea1SDimitry Andric     if (isClangFormatOff(Trimmed)) {
322881ad6265SDimitry Andric       FormattingOff = true;
3229*0fca6ea1SDimitry Andric     } else if (isClangFormatOn(Trimmed)) {
32300eae32dcSDimitry Andric       FormattingOff = false;
3231*0fca6ea1SDimitry Andric     } else if (Trimmed.starts_with("/*")) {
3232*0fca6ea1SDimitry Andric       IsBlockComment = true;
3233*0fca6ea1SDimitry Andric       Pos = Code.find("*/", SearchFrom + 2);
3234*0fca6ea1SDimitry Andric     }
32350eae32dcSDimitry Andric 
32360b57cec5SDimitry Andric     const bool EmptyLineSkipped =
32370b57cec5SDimitry Andric         Trimmed.empty() &&
32380b57cec5SDimitry Andric         (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge ||
32390b57cec5SDimitry Andric          Style.IncludeStyle.IncludeBlocks ==
32400b57cec5SDimitry Andric              tooling::IncludeStyle::IBS_Regroup);
32410b57cec5SDimitry Andric 
32425f757f3fSDimitry Andric     bool MergeWithNextLine = Trimmed.ends_with("\\");
3243e8d8bef9SDimitry Andric     if (!FormattingOff && !MergeWithNextLine) {
3244*0fca6ea1SDimitry Andric       if (!IsBlockComment &&
3245*0fca6ea1SDimitry Andric           tooling::HeaderIncludes::IncludeRegex.match(Trimmed, &Matches)) {
32460b57cec5SDimitry Andric         StringRef IncludeName = Matches[2];
3247*0fca6ea1SDimitry Andric         if (Trimmed.contains("/*") && !Trimmed.contains("*/")) {
32481fd87a68SDimitry Andric           // #include with a start of a block comment, but without the end.
32491fd87a68SDimitry Andric           // Need to keep all the lines until the end of the comment together.
32501fd87a68SDimitry Andric           // FIXME: This is somehow simplified check that probably does not work
32511fd87a68SDimitry Andric           // correctly if there are multiple comments on a line.
32521fd87a68SDimitry Andric           Pos = Code.find("*/", SearchFrom);
32531fd87a68SDimitry Andric           Line = Code.substr(
32541fd87a68SDimitry Andric               Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev);
32551fd87a68SDimitry Andric         }
32560b57cec5SDimitry Andric         int Category = Categories.getIncludePriority(
32570b57cec5SDimitry Andric             IncludeName,
32580b57cec5SDimitry Andric             /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock);
3259a7dea167SDimitry Andric         int Priority = Categories.getSortIncludePriority(
3260a7dea167SDimitry Andric             IncludeName, !MainIncludeFound && FirstIncludeBlock);
32610b57cec5SDimitry Andric         if (Category == 0)
32620b57cec5SDimitry Andric           MainIncludeFound = true;
3263a7dea167SDimitry Andric         IncludesInBlock.push_back(
3264a7dea167SDimitry Andric             {IncludeName, Line, Prev, Category, Priority});
32650b57cec5SDimitry Andric       } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
32660b57cec5SDimitry Andric         sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code,
32670b57cec5SDimitry Andric                         Replaces, Cursor);
32680b57cec5SDimitry Andric         IncludesInBlock.clear();
32695f757f3fSDimitry Andric         if (Trimmed.starts_with("#pragma hdrstop")) // Precompiled headers.
3270e8d8bef9SDimitry Andric           FirstIncludeBlock = true;
3271e8d8bef9SDimitry Andric         else
32720b57cec5SDimitry Andric           FirstIncludeBlock = false;
32730b57cec5SDimitry Andric       }
32740b57cec5SDimitry Andric     }
32750b57cec5SDimitry Andric     if (Pos == StringRef::npos || Pos + 1 == Code.size())
32760b57cec5SDimitry Andric       break;
3277e8d8bef9SDimitry Andric 
3278e8d8bef9SDimitry Andric     if (!MergeWithNextLine)
3279e8d8bef9SDimitry Andric       Prev = Pos + 1;
32800b57cec5SDimitry Andric     SearchFrom = Pos + 1;
32810b57cec5SDimitry Andric   }
32820b57cec5SDimitry Andric   if (!IncludesInBlock.empty()) {
32830b57cec5SDimitry Andric     sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces,
32840b57cec5SDimitry Andric                     Cursor);
32850b57cec5SDimitry Andric   }
32860b57cec5SDimitry Andric   return Replaces;
32870b57cec5SDimitry Andric }
32880b57cec5SDimitry Andric 
32890b57cec5SDimitry Andric // Returns group number to use as a first order sort on imports. Gives UINT_MAX
32900b57cec5SDimitry Andric // if the import does not match any given groups.
32910b57cec5SDimitry Andric static unsigned findJavaImportGroup(const FormatStyle &Style,
32920b57cec5SDimitry Andric                                     StringRef ImportIdentifier) {
32930b57cec5SDimitry Andric   unsigned LongestMatchIndex = UINT_MAX;
32940b57cec5SDimitry Andric   unsigned LongestMatchLength = 0;
32950b57cec5SDimitry Andric   for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) {
32961fd87a68SDimitry Andric     const std::string &GroupPrefix = Style.JavaImportGroups[I];
32975f757f3fSDimitry Andric     if (ImportIdentifier.starts_with(GroupPrefix) &&
32980b57cec5SDimitry Andric         GroupPrefix.length() > LongestMatchLength) {
32990b57cec5SDimitry Andric       LongestMatchIndex = I;
33000b57cec5SDimitry Andric       LongestMatchLength = GroupPrefix.length();
33010b57cec5SDimitry Andric     }
33020b57cec5SDimitry Andric   }
33030b57cec5SDimitry Andric   return LongestMatchIndex;
33040b57cec5SDimitry Andric }
33050b57cec5SDimitry Andric 
33060b57cec5SDimitry Andric // Sorts and deduplicates a block of includes given by 'Imports' based on
33070b57cec5SDimitry Andric // JavaImportGroups, then adding the necessary replacement to 'Replaces'.
33080b57cec5SDimitry Andric // Import declarations with the same text will be deduplicated. Between each
33090b57cec5SDimitry Andric // import group, a newline is inserted, and within each import group, a
33100b57cec5SDimitry Andric // lexicographic sort based on ASCII value is performed.
33110b57cec5SDimitry Andric static void sortJavaImports(const FormatStyle &Style,
33120b57cec5SDimitry Andric                             const SmallVectorImpl<JavaImportDirective> &Imports,
33130b57cec5SDimitry Andric                             ArrayRef<tooling::Range> Ranges, StringRef FileName,
33140b57cec5SDimitry Andric                             StringRef Code, tooling::Replacements &Replaces) {
33150b57cec5SDimitry Andric   unsigned ImportsBeginOffset = Imports.front().Offset;
33160b57cec5SDimitry Andric   unsigned ImportsEndOffset =
33170b57cec5SDimitry Andric       Imports.back().Offset + Imports.back().Text.size();
33180b57cec5SDimitry Andric   unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;
33190b57cec5SDimitry Andric   if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))
33200b57cec5SDimitry Andric     return;
33211fd87a68SDimitry Andric 
332281ad6265SDimitry Andric   SmallVector<unsigned, 16> Indices =
332381ad6265SDimitry Andric       llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size()));
33240b57cec5SDimitry Andric   SmallVector<unsigned, 16> JavaImportGroups;
33251fd87a68SDimitry Andric   JavaImportGroups.reserve(Imports.size());
33261fd87a68SDimitry Andric   for (const JavaImportDirective &Import : Imports)
33271fd87a68SDimitry Andric     JavaImportGroups.push_back(findJavaImportGroup(Style, Import.Identifier));
33281fd87a68SDimitry Andric 
3329e8d8bef9SDimitry Andric   bool StaticImportAfterNormalImport =
3330e8d8bef9SDimitry Andric       Style.SortJavaStaticImport == FormatStyle::SJSIO_After;
3331*0fca6ea1SDimitry Andric   sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
33320b57cec5SDimitry Andric     // Negating IsStatic to push static imports above non-static imports.
3333e8d8bef9SDimitry Andric     return std::make_tuple(!Imports[LHSI].IsStatic ^
3334e8d8bef9SDimitry Andric                                StaticImportAfterNormalImport,
3335e8d8bef9SDimitry Andric                            JavaImportGroups[LHSI], Imports[LHSI].Identifier) <
3336e8d8bef9SDimitry Andric            std::make_tuple(!Imports[RHSI].IsStatic ^
3337e8d8bef9SDimitry Andric                                StaticImportAfterNormalImport,
3338e8d8bef9SDimitry Andric                            JavaImportGroups[RHSI], Imports[RHSI].Identifier);
33390b57cec5SDimitry Andric   });
33400b57cec5SDimitry Andric 
33410b57cec5SDimitry Andric   // Deduplicate imports.
33420b57cec5SDimitry Andric   Indices.erase(std::unique(Indices.begin(), Indices.end(),
33430b57cec5SDimitry Andric                             [&](unsigned LHSI, unsigned RHSI) {
33440b57cec5SDimitry Andric                               return Imports[LHSI].Text == Imports[RHSI].Text;
33450b57cec5SDimitry Andric                             }),
33460b57cec5SDimitry Andric                 Indices.end());
33470b57cec5SDimitry Andric 
33480b57cec5SDimitry Andric   bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
33490b57cec5SDimitry Andric   unsigned CurrentImportGroup = JavaImportGroups[Indices.front()];
33500b57cec5SDimitry Andric 
33510b57cec5SDimitry Andric   std::string result;
33520b57cec5SDimitry Andric   for (unsigned Index : Indices) {
33530b57cec5SDimitry Andric     if (!result.empty()) {
33540b57cec5SDimitry Andric       result += "\n";
33550b57cec5SDimitry Andric       if (CurrentIsStatic != Imports[Index].IsStatic ||
335681ad6265SDimitry Andric           CurrentImportGroup != JavaImportGroups[Index]) {
33570b57cec5SDimitry Andric         result += "\n";
33580b57cec5SDimitry Andric       }
335981ad6265SDimitry Andric     }
33600b57cec5SDimitry Andric     for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) {
33610b57cec5SDimitry Andric       result += CommentLine;
33620b57cec5SDimitry Andric       result += "\n";
33630b57cec5SDimitry Andric     }
33640b57cec5SDimitry Andric     result += Imports[Index].Text;
33650b57cec5SDimitry Andric     CurrentIsStatic = Imports[Index].IsStatic;
33660b57cec5SDimitry Andric     CurrentImportGroup = JavaImportGroups[Index];
33670b57cec5SDimitry Andric   }
33680b57cec5SDimitry Andric 
33690b57cec5SDimitry Andric   // If the imports are out of order, we generate a single replacement fixing
33700b57cec5SDimitry Andric   // the entire block. Otherwise, no replacement is generated.
33715ffd83dbSDimitry Andric   if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
337281ad6265SDimitry Andric                                  Imports.front().Offset, ImportsBlockSize)))) {
33730b57cec5SDimitry Andric     return;
337481ad6265SDimitry Andric   }
33750b57cec5SDimitry Andric 
33760b57cec5SDimitry Andric   auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset,
33770b57cec5SDimitry Andric                                                ImportsBlockSize, result));
33780b57cec5SDimitry Andric   // FIXME: better error handling. For now, just skip the replacement for the
33790b57cec5SDimitry Andric   // release version.
33800b57cec5SDimitry Andric   if (Err) {
3381*0fca6ea1SDimitry Andric     llvm::errs() << toString(std::move(Err)) << "\n";
33820b57cec5SDimitry Andric     assert(false);
33830b57cec5SDimitry Andric   }
33840b57cec5SDimitry Andric }
33850b57cec5SDimitry Andric 
33860b57cec5SDimitry Andric namespace {
33870b57cec5SDimitry Andric 
33880b57cec5SDimitry Andric const char JavaImportRegexPattern[] =
33890b57cec5SDimitry Andric     "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;";
33900b57cec5SDimitry Andric 
33910b57cec5SDimitry Andric } // anonymous namespace
33920b57cec5SDimitry Andric 
33930b57cec5SDimitry Andric tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code,
33940b57cec5SDimitry Andric                                       ArrayRef<tooling::Range> Ranges,
33950b57cec5SDimitry Andric                                       StringRef FileName,
33960b57cec5SDimitry Andric                                       tooling::Replacements &Replaces) {
33970b57cec5SDimitry Andric   unsigned Prev = 0;
33980b57cec5SDimitry Andric   unsigned SearchFrom = 0;
33990b57cec5SDimitry Andric   llvm::Regex ImportRegex(JavaImportRegexPattern);
34000b57cec5SDimitry Andric   SmallVector<StringRef, 4> Matches;
34010b57cec5SDimitry Andric   SmallVector<JavaImportDirective, 16> ImportsInBlock;
3402753f127fSDimitry Andric   SmallVector<StringRef> AssociatedCommentLines;
34030b57cec5SDimitry Andric 
34040b57cec5SDimitry Andric   bool FormattingOff = false;
34050b57cec5SDimitry Andric 
34060b57cec5SDimitry Andric   for (;;) {
34070b57cec5SDimitry Andric     auto Pos = Code.find('\n', SearchFrom);
34080b57cec5SDimitry Andric     StringRef Line =
34090b57cec5SDimitry Andric         Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
34100b57cec5SDimitry Andric 
34110b57cec5SDimitry Andric     StringRef Trimmed = Line.trim();
341206c3fb27SDimitry Andric     if (isClangFormatOff(Trimmed))
34130b57cec5SDimitry Andric       FormattingOff = true;
341406c3fb27SDimitry Andric     else if (isClangFormatOn(Trimmed))
34150b57cec5SDimitry Andric       FormattingOff = false;
34160b57cec5SDimitry Andric 
34170b57cec5SDimitry Andric     if (ImportRegex.match(Line, &Matches)) {
34180b57cec5SDimitry Andric       if (FormattingOff) {
34190b57cec5SDimitry Andric         // If at least one import line has formatting turned off, turn off
34200b57cec5SDimitry Andric         // formatting entirely.
34210b57cec5SDimitry Andric         return Replaces;
34220b57cec5SDimitry Andric       }
34230b57cec5SDimitry Andric       StringRef Static = Matches[1];
34240b57cec5SDimitry Andric       StringRef Identifier = Matches[2];
34250b57cec5SDimitry Andric       bool IsStatic = false;
342681ad6265SDimitry Andric       if (Static.contains("static"))
34270b57cec5SDimitry Andric         IsStatic = true;
34280b57cec5SDimitry Andric       ImportsInBlock.push_back(
34290b57cec5SDimitry Andric           {Identifier, Line, Prev, AssociatedCommentLines, IsStatic});
34300b57cec5SDimitry Andric       AssociatedCommentLines.clear();
34310b57cec5SDimitry Andric     } else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) {
34320b57cec5SDimitry Andric       // Associating comments within the imports with the nearest import below
34330b57cec5SDimitry Andric       AssociatedCommentLines.push_back(Line);
34340b57cec5SDimitry Andric     }
34350b57cec5SDimitry Andric     Prev = Pos + 1;
34360b57cec5SDimitry Andric     if (Pos == StringRef::npos || Pos + 1 == Code.size())
34370b57cec5SDimitry Andric       break;
34380b57cec5SDimitry Andric     SearchFrom = Pos + 1;
34390b57cec5SDimitry Andric   }
34400b57cec5SDimitry Andric   if (!ImportsInBlock.empty())
34410b57cec5SDimitry Andric     sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces);
34420b57cec5SDimitry Andric   return Replaces;
34430b57cec5SDimitry Andric }
34440b57cec5SDimitry Andric 
34450b57cec5SDimitry Andric bool isMpegTS(StringRef Code) {
34460b57cec5SDimitry Andric   // MPEG transport streams use the ".ts" file extension. clang-format should
34470b57cec5SDimitry Andric   // not attempt to format those. MPEG TS' frame format starts with 0x47 every
34480b57cec5SDimitry Andric   // 189 bytes - detect that and return.
34490b57cec5SDimitry Andric   return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
34500b57cec5SDimitry Andric }
34510b57cec5SDimitry Andric 
34525f757f3fSDimitry Andric bool isLikelyXml(StringRef Code) { return Code.ltrim().starts_with("<"); }
34530b57cec5SDimitry Andric 
34540b57cec5SDimitry Andric tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
34550b57cec5SDimitry Andric                                    ArrayRef<tooling::Range> Ranges,
34560b57cec5SDimitry Andric                                    StringRef FileName, unsigned *Cursor) {
34570b57cec5SDimitry Andric   tooling::Replacements Replaces;
3458fe6060f1SDimitry Andric   if (!Style.SortIncludes || Style.DisableFormat)
34590b57cec5SDimitry Andric     return Replaces;
34600b57cec5SDimitry Andric   if (isLikelyXml(Code))
34610b57cec5SDimitry Andric     return Replaces;
34620b57cec5SDimitry Andric   if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript &&
346381ad6265SDimitry Andric       isMpegTS(Code)) {
34640b57cec5SDimitry Andric     return Replaces;
346581ad6265SDimitry Andric   }
34660b57cec5SDimitry Andric   if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript)
34670b57cec5SDimitry Andric     return sortJavaScriptImports(Style, Code, Ranges, FileName);
34680b57cec5SDimitry Andric   if (Style.Language == FormatStyle::LanguageKind::LK_Java)
34690b57cec5SDimitry Andric     return sortJavaImports(Style, Code, Ranges, FileName, Replaces);
34700b57cec5SDimitry Andric   sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor);
34710b57cec5SDimitry Andric   return Replaces;
34720b57cec5SDimitry Andric }
34730b57cec5SDimitry Andric 
34740b57cec5SDimitry Andric template <typename T>
3475*0fca6ea1SDimitry Andric static Expected<tooling::Replacements>
34760b57cec5SDimitry Andric processReplacements(T ProcessFunc, StringRef Code,
34770b57cec5SDimitry Andric                     const tooling::Replacements &Replaces,
34780b57cec5SDimitry Andric                     const FormatStyle &Style) {
34790b57cec5SDimitry Andric   if (Replaces.empty())
34800b57cec5SDimitry Andric     return tooling::Replacements();
34810b57cec5SDimitry Andric 
34820b57cec5SDimitry Andric   auto NewCode = applyAllReplacements(Code, Replaces);
34830b57cec5SDimitry Andric   if (!NewCode)
34840b57cec5SDimitry Andric     return NewCode.takeError();
34850b57cec5SDimitry Andric   std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();
34860b57cec5SDimitry Andric   StringRef FileName = Replaces.begin()->getFilePath();
34870b57cec5SDimitry Andric 
34880b57cec5SDimitry Andric   tooling::Replacements FormatReplaces =
34890b57cec5SDimitry Andric       ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
34900b57cec5SDimitry Andric 
34910b57cec5SDimitry Andric   return Replaces.merge(FormatReplaces);
34920b57cec5SDimitry Andric }
34930b57cec5SDimitry Andric 
3494*0fca6ea1SDimitry Andric Expected<tooling::Replacements>
34950b57cec5SDimitry Andric formatReplacements(StringRef Code, const tooling::Replacements &Replaces,
34960b57cec5SDimitry Andric                    const FormatStyle &Style) {
34970b57cec5SDimitry Andric   // We need to use lambda function here since there are two versions of
34980b57cec5SDimitry Andric   // `sortIncludes`.
34990b57cec5SDimitry Andric   auto SortIncludes = [](const FormatStyle &Style, StringRef Code,
35000b57cec5SDimitry Andric                          std::vector<tooling::Range> Ranges,
35010b57cec5SDimitry Andric                          StringRef FileName) -> tooling::Replacements {
35020b57cec5SDimitry Andric     return sortIncludes(Style, Code, Ranges, FileName);
35030b57cec5SDimitry Andric   };
35040b57cec5SDimitry Andric   auto SortedReplaces =
35050b57cec5SDimitry Andric       processReplacements(SortIncludes, Code, Replaces, Style);
35060b57cec5SDimitry Andric   if (!SortedReplaces)
35070b57cec5SDimitry Andric     return SortedReplaces.takeError();
35080b57cec5SDimitry Andric 
35090b57cec5SDimitry Andric   // We need to use lambda function here since there are two versions of
35100b57cec5SDimitry Andric   // `reformat`.
35110b57cec5SDimitry Andric   auto Reformat = [](const FormatStyle &Style, StringRef Code,
35120b57cec5SDimitry Andric                      std::vector<tooling::Range> Ranges,
35130b57cec5SDimitry Andric                      StringRef FileName) -> tooling::Replacements {
35140b57cec5SDimitry Andric     return reformat(Style, Code, Ranges, FileName);
35150b57cec5SDimitry Andric   };
35160b57cec5SDimitry Andric   return processReplacements(Reformat, Code, *SortedReplaces, Style);
35170b57cec5SDimitry Andric }
35180b57cec5SDimitry Andric 
35190b57cec5SDimitry Andric namespace {
35200b57cec5SDimitry Andric 
35210b57cec5SDimitry Andric inline bool isHeaderInsertion(const tooling::Replacement &Replace) {
35220b57cec5SDimitry Andric   return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 &&
3523bdd1243dSDimitry Andric          tooling::HeaderIncludes::IncludeRegex.match(
3524bdd1243dSDimitry Andric              Replace.getReplacementText());
35250b57cec5SDimitry Andric }
35260b57cec5SDimitry Andric 
35270b57cec5SDimitry Andric inline bool isHeaderDeletion(const tooling::Replacement &Replace) {
35280b57cec5SDimitry Andric   return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1;
35290b57cec5SDimitry Andric }
35300b57cec5SDimitry Andric 
35310b57cec5SDimitry Andric // FIXME: insert empty lines between newly created blocks.
35320b57cec5SDimitry Andric tooling::Replacements
35330b57cec5SDimitry Andric fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
35340b57cec5SDimitry Andric                         const FormatStyle &Style) {
35350b57cec5SDimitry Andric   if (!Style.isCpp())
35360b57cec5SDimitry Andric     return Replaces;
35370b57cec5SDimitry Andric 
35380b57cec5SDimitry Andric   tooling::Replacements HeaderInsertions;
3539*0fca6ea1SDimitry Andric   std::set<StringRef> HeadersToDelete;
35400b57cec5SDimitry Andric   tooling::Replacements Result;
35410b57cec5SDimitry Andric   for (const auto &R : Replaces) {
35420b57cec5SDimitry Andric     if (isHeaderInsertion(R)) {
35430b57cec5SDimitry Andric       // Replacements from \p Replaces must be conflict-free already, so we can
35440b57cec5SDimitry Andric       // simply consume the error.
3545*0fca6ea1SDimitry Andric       consumeError(HeaderInsertions.add(R));
35460b57cec5SDimitry Andric     } else if (isHeaderDeletion(R)) {
35470b57cec5SDimitry Andric       HeadersToDelete.insert(R.getReplacementText());
35480b57cec5SDimitry Andric     } else if (R.getOffset() == UINT_MAX) {
35490b57cec5SDimitry Andric       llvm::errs() << "Insertions other than header #include insertion are "
35500b57cec5SDimitry Andric                       "not supported! "
35510b57cec5SDimitry Andric                    << R.getReplacementText() << "\n";
35520b57cec5SDimitry Andric     } else {
3553*0fca6ea1SDimitry Andric       consumeError(Result.add(R));
35540b57cec5SDimitry Andric     }
35550b57cec5SDimitry Andric   }
35560b57cec5SDimitry Andric   if (HeaderInsertions.empty() && HeadersToDelete.empty())
35570b57cec5SDimitry Andric     return Replaces;
35580b57cec5SDimitry Andric 
35590b57cec5SDimitry Andric   StringRef FileName = Replaces.begin()->getFilePath();
35600b57cec5SDimitry Andric   tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle);
35610b57cec5SDimitry Andric 
35620b57cec5SDimitry Andric   for (const auto &Header : HeadersToDelete) {
35630b57cec5SDimitry Andric     tooling::Replacements Replaces =
35645f757f3fSDimitry Andric         Includes.remove(Header.trim("\"<>"), Header.starts_with("<"));
35650b57cec5SDimitry Andric     for (const auto &R : Replaces) {
35660b57cec5SDimitry Andric       auto Err = Result.add(R);
35670b57cec5SDimitry Andric       if (Err) {
35680b57cec5SDimitry Andric         // Ignore the deletion on conflict.
35690b57cec5SDimitry Andric         llvm::errs() << "Failed to add header deletion replacement for "
3570*0fca6ea1SDimitry Andric                      << Header << ": " << toString(std::move(Err)) << "\n";
35710b57cec5SDimitry Andric       }
35720b57cec5SDimitry Andric     }
35730b57cec5SDimitry Andric   }
35740b57cec5SDimitry Andric 
3575*0fca6ea1SDimitry Andric   SmallVector<StringRef, 4> Matches;
35760b57cec5SDimitry Andric   for (const auto &R : HeaderInsertions) {
35770b57cec5SDimitry Andric     auto IncludeDirective = R.getReplacementText();
3578bdd1243dSDimitry Andric     bool Matched =
3579bdd1243dSDimitry Andric         tooling::HeaderIncludes::IncludeRegex.match(IncludeDirective, &Matches);
35800b57cec5SDimitry Andric     assert(Matched && "Header insertion replacement must have replacement text "
35810b57cec5SDimitry Andric                       "'#include ...'");
35820b57cec5SDimitry Andric     (void)Matched;
35830b57cec5SDimitry Andric     auto IncludeName = Matches[2];
35840b57cec5SDimitry Andric     auto Replace =
35855f757f3fSDimitry Andric         Includes.insert(IncludeName.trim("\"<>"), IncludeName.starts_with("<"),
3586bdd1243dSDimitry Andric                         tooling::IncludeDirective::Include);
35870b57cec5SDimitry Andric     if (Replace) {
35880b57cec5SDimitry Andric       auto Err = Result.add(*Replace);
35890b57cec5SDimitry Andric       if (Err) {
3590*0fca6ea1SDimitry Andric         consumeError(std::move(Err));
35910b57cec5SDimitry Andric         unsigned NewOffset =
35920b57cec5SDimitry Andric             Result.getShiftedCodePosition(Replace->getOffset());
35930b57cec5SDimitry Andric         auto Shifted = tooling::Replacement(FileName, NewOffset, 0,
35940b57cec5SDimitry Andric                                             Replace->getReplacementText());
35950b57cec5SDimitry Andric         Result = Result.merge(tooling::Replacements(Shifted));
35960b57cec5SDimitry Andric       }
35970b57cec5SDimitry Andric     }
35980b57cec5SDimitry Andric   }
35990b57cec5SDimitry Andric   return Result;
36000b57cec5SDimitry Andric }
36010b57cec5SDimitry Andric 
36020b57cec5SDimitry Andric } // anonymous namespace
36030b57cec5SDimitry Andric 
3604*0fca6ea1SDimitry Andric Expected<tooling::Replacements>
36050b57cec5SDimitry Andric cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
36060b57cec5SDimitry Andric                           const FormatStyle &Style) {
36070b57cec5SDimitry Andric   // We need to use lambda function here since there are two versions of
36080b57cec5SDimitry Andric   // `cleanup`.
36090b57cec5SDimitry Andric   auto Cleanup = [](const FormatStyle &Style, StringRef Code,
3610*0fca6ea1SDimitry Andric                     ArrayRef<tooling::Range> Ranges,
36110b57cec5SDimitry Andric                     StringRef FileName) -> tooling::Replacements {
36120b57cec5SDimitry Andric     return cleanup(Style, Code, Ranges, FileName);
36130b57cec5SDimitry Andric   };
36140b57cec5SDimitry Andric   // Make header insertion replacements insert new headers into correct blocks.
36150b57cec5SDimitry Andric   tooling::Replacements NewReplaces =
36160b57cec5SDimitry Andric       fixCppIncludeInsertions(Code, Replaces, Style);
3617bdd1243dSDimitry Andric   return cantFail(processReplacements(Cleanup, Code, NewReplaces, Style));
36180b57cec5SDimitry Andric }
36190b57cec5SDimitry Andric 
36200b57cec5SDimitry Andric namespace internal {
36210b57cec5SDimitry Andric std::pair<tooling::Replacements, unsigned>
36220b57cec5SDimitry Andric reformat(const FormatStyle &Style, StringRef Code,
36230b57cec5SDimitry Andric          ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,
36240b57cec5SDimitry Andric          unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,
36250b57cec5SDimitry Andric          FormattingAttemptStatus *Status) {
3626349cc55cSDimitry Andric   FormatStyle Expanded = Style;
3627349cc55cSDimitry Andric   expandPresetsBraceWrapping(Expanded);
3628349cc55cSDimitry Andric   expandPresetsSpaceBeforeParens(Expanded);
362906c3fb27SDimitry Andric   expandPresetsSpacesInParens(Expanded);
3630bdd1243dSDimitry Andric   Expanded.InsertBraces = false;
3631bdd1243dSDimitry Andric   Expanded.RemoveBracesLLVM = false;
363206c3fb27SDimitry Andric   Expanded.RemoveParentheses = FormatStyle::RPS_Leave;
3633bdd1243dSDimitry Andric   Expanded.RemoveSemicolon = false;
363481ad6265SDimitry Andric   switch (Expanded.RequiresClausePosition) {
363581ad6265SDimitry Andric   case FormatStyle::RCPS_SingleLine:
363681ad6265SDimitry Andric   case FormatStyle::RCPS_WithPreceding:
363781ad6265SDimitry Andric     Expanded.IndentRequiresClause = false;
363881ad6265SDimitry Andric     break;
363981ad6265SDimitry Andric   default:
364081ad6265SDimitry Andric     break;
364181ad6265SDimitry Andric   }
364281ad6265SDimitry Andric 
36430b57cec5SDimitry Andric   if (Expanded.DisableFormat)
36440b57cec5SDimitry Andric     return {tooling::Replacements(), 0};
36450b57cec5SDimitry Andric   if (isLikelyXml(Code))
36460b57cec5SDimitry Andric     return {tooling::Replacements(), 0};
36470b57cec5SDimitry Andric   if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code))
36480b57cec5SDimitry Andric     return {tooling::Replacements(), 0};
36490b57cec5SDimitry Andric 
3650fe6060f1SDimitry Andric   // JSON only needs the formatting passing.
3651fe6060f1SDimitry Andric   if (Style.isJson()) {
3652fe6060f1SDimitry Andric     std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
36534824e7fdSDimitry Andric     auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
3654fe6060f1SDimitry Andric                                  NextStartColumn, LastStartColumn);
3655349cc55cSDimitry Andric     if (!Env)
3656349cc55cSDimitry Andric       return {};
3657fe6060f1SDimitry Andric     // Perform the actual formatting pass.
3658fe6060f1SDimitry Andric     tooling::Replacements Replaces =
3659fe6060f1SDimitry Andric         Formatter(*Env, Style, Status).process().first;
3660fe6060f1SDimitry Andric     // add a replacement to remove the "x = " from the result.
366106c3fb27SDimitry Andric     Replaces = Replaces.merge(
366206c3fb27SDimitry Andric         tooling::Replacements(tooling::Replacement(FileName, 0, 4, "")));
3663fe6060f1SDimitry Andric     // apply the reformatting changes and the removal of "x = ".
366481ad6265SDimitry Andric     if (applyAllReplacements(Code, Replaces))
3665fe6060f1SDimitry Andric       return {Replaces, 0};
3666fe6060f1SDimitry Andric     return {tooling::Replacements(), 0};
3667fe6060f1SDimitry Andric   }
3668fe6060f1SDimitry Andric 
3669bdd1243dSDimitry Andric   auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
3670bdd1243dSDimitry Andric                                NextStartColumn, LastStartColumn);
3671bdd1243dSDimitry Andric   if (!Env)
3672bdd1243dSDimitry Andric     return {};
3673bdd1243dSDimitry Andric 
36740b57cec5SDimitry Andric   typedef std::function<std::pair<tooling::Replacements, unsigned>(
36750b57cec5SDimitry Andric       const Environment &)>
36760b57cec5SDimitry Andric       AnalyzerPass;
367706c3fb27SDimitry Andric 
367806c3fb27SDimitry Andric   SmallVector<AnalyzerPass, 16> Passes;
36790b57cec5SDimitry Andric 
3680bdd1243dSDimitry Andric   Passes.emplace_back([&](const Environment &Env) {
3681bdd1243dSDimitry Andric     return IntegerLiteralSeparatorFixer().process(Env, Expanded);
3682bdd1243dSDimitry Andric   });
3683bdd1243dSDimitry Andric 
368481ad6265SDimitry Andric   if (Style.isCpp()) {
368506c3fb27SDimitry Andric     if (Style.QualifierAlignment != FormatStyle::QAS_Leave)
368606c3fb27SDimitry Andric       addQualifierAlignmentFixerPasses(Expanded, Passes);
368706c3fb27SDimitry Andric 
368806c3fb27SDimitry Andric     if (Style.RemoveParentheses != FormatStyle::RPS_Leave) {
368906c3fb27SDimitry Andric       FormatStyle S = Expanded;
369006c3fb27SDimitry Andric       S.RemoveParentheses = Style.RemoveParentheses;
369106c3fb27SDimitry Andric       Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
369206c3fb27SDimitry Andric         return ParensRemover(Env, S).process(/*SkipAnnotation=*/true);
3693349cc55cSDimitry Andric       });
3694349cc55cSDimitry Andric     }
3695349cc55cSDimitry Andric 
369681ad6265SDimitry Andric     if (Style.InsertBraces) {
3697bdd1243dSDimitry Andric       FormatStyle S = Expanded;
3698bdd1243dSDimitry Andric       S.InsertBraces = true;
369906c3fb27SDimitry Andric       Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
3700bdd1243dSDimitry Andric         return BracesInserter(Env, S).process(/*SkipAnnotation=*/true);
370181ad6265SDimitry Andric       });
370281ad6265SDimitry Andric     }
370381ad6265SDimitry Andric 
370481ad6265SDimitry Andric     if (Style.RemoveBracesLLVM) {
3705bdd1243dSDimitry Andric       FormatStyle S = Expanded;
3706bdd1243dSDimitry Andric       S.RemoveBracesLLVM = true;
370706c3fb27SDimitry Andric       Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
3708bdd1243dSDimitry Andric         return BracesRemover(Env, S).process(/*SkipAnnotation=*/true);
3709bdd1243dSDimitry Andric       });
3710bdd1243dSDimitry Andric     }
3711bdd1243dSDimitry Andric 
3712bdd1243dSDimitry Andric     if (Style.RemoveSemicolon) {
3713bdd1243dSDimitry Andric       FormatStyle S = Expanded;
3714bdd1243dSDimitry Andric       S.RemoveSemicolon = true;
371506c3fb27SDimitry Andric       Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
3716*0fca6ea1SDimitry Andric         return SemiRemover(Env, S).process();
371704eeddc0SDimitry Andric       });
371881ad6265SDimitry Andric     }
371904eeddc0SDimitry Andric 
372081ad6265SDimitry Andric     if (Style.FixNamespaceComments) {
37210b57cec5SDimitry Andric       Passes.emplace_back([&](const Environment &Env) {
37220b57cec5SDimitry Andric         return NamespaceEndCommentsFixer(Env, Expanded).process();
37230b57cec5SDimitry Andric       });
372481ad6265SDimitry Andric     }
37250b57cec5SDimitry Andric 
3726bdd1243dSDimitry Andric     if (Style.SortUsingDeclarations != FormatStyle::SUD_Never) {
37270b57cec5SDimitry Andric       Passes.emplace_back([&](const Environment &Env) {
37280b57cec5SDimitry Andric         return UsingDeclarationsSorter(Env, Expanded).process();
37290b57cec5SDimitry Andric       });
37300b57cec5SDimitry Andric     }
373181ad6265SDimitry Andric   }
37320b57cec5SDimitry Andric 
373381ad6265SDimitry Andric   if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) {
373404eeddc0SDimitry Andric     Passes.emplace_back([&](const Environment &Env) {
373504eeddc0SDimitry Andric       return DefinitionBlockSeparator(Env, Expanded).process();
373604eeddc0SDimitry Andric     });
373781ad6265SDimitry Andric   }
373804eeddc0SDimitry Andric 
37395f757f3fSDimitry Andric   if (Style.Language == FormatStyle::LK_ObjC &&
37405f757f3fSDimitry Andric       !Style.ObjCPropertyAttributeOrder.empty()) {
37415f757f3fSDimitry Andric     Passes.emplace_back([&](const Environment &Env) {
37425f757f3fSDimitry Andric       return ObjCPropertyAttributeOrderFixer(Env, Expanded).process();
37435f757f3fSDimitry Andric     });
37445f757f3fSDimitry Andric   }
37455f757f3fSDimitry Andric 
374681ad6265SDimitry Andric   if (Style.isJavaScript() &&
374781ad6265SDimitry Andric       Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) {
37480b57cec5SDimitry Andric     Passes.emplace_back([&](const Environment &Env) {
3749bdd1243dSDimitry Andric       return JavaScriptRequoter(Env, Expanded).process(/*SkipAnnotation=*/true);
37500b57cec5SDimitry Andric     });
375181ad6265SDimitry Andric   }
37520b57cec5SDimitry Andric 
37530b57cec5SDimitry Andric   Passes.emplace_back([&](const Environment &Env) {
37540b57cec5SDimitry Andric     return Formatter(Env, Expanded, Status).process();
37550b57cec5SDimitry Andric   });
37560b57cec5SDimitry Andric 
37570eae32dcSDimitry Andric   if (Style.isJavaScript() &&
375881ad6265SDimitry Andric       Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) {
37595ffd83dbSDimitry Andric     Passes.emplace_back([&](const Environment &Env) {
37605ffd83dbSDimitry Andric       return TrailingCommaInserter(Env, Expanded).process();
37615ffd83dbSDimitry Andric     });
376281ad6265SDimitry Andric   }
37635ffd83dbSDimitry Andric 
3764bdd1243dSDimitry Andric   std::optional<std::string> CurrentCode;
37650b57cec5SDimitry Andric   tooling::Replacements Fixes;
37660b57cec5SDimitry Andric   unsigned Penalty = 0;
37670b57cec5SDimitry Andric   for (size_t I = 0, E = Passes.size(); I < E; ++I) {
37680b57cec5SDimitry Andric     std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
37690b57cec5SDimitry Andric     auto NewCode = applyAllReplacements(
37700b57cec5SDimitry Andric         CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
37710b57cec5SDimitry Andric     if (NewCode) {
37720b57cec5SDimitry Andric       Fixes = Fixes.merge(PassFixes.first);
37730b57cec5SDimitry Andric       Penalty += PassFixes.second;
37740b57cec5SDimitry Andric       if (I + 1 < E) {
37750b57cec5SDimitry Andric         CurrentCode = std::move(*NewCode);
3776349cc55cSDimitry Andric         Env = Environment::make(
37770b57cec5SDimitry Andric             *CurrentCode, FileName,
37780b57cec5SDimitry Andric             tooling::calculateRangesAfterReplacements(Fixes, Ranges),
37790b57cec5SDimitry Andric             FirstStartColumn, NextStartColumn, LastStartColumn);
3780349cc55cSDimitry Andric         if (!Env)
3781349cc55cSDimitry Andric           return {};
37820b57cec5SDimitry Andric       }
37830b57cec5SDimitry Andric     }
37840b57cec5SDimitry Andric   }
37850b57cec5SDimitry Andric 
378606c3fb27SDimitry Andric   if (Style.QualifierAlignment != FormatStyle::QAS_Leave) {
378706c3fb27SDimitry Andric     // Don't make replacements that replace nothing. QualifierAlignment can
378806c3fb27SDimitry Andric     // produce them if one of its early passes changes e.g. `const volatile` to
378906c3fb27SDimitry Andric     // `volatile const` and then a later pass changes it back again.
379006c3fb27SDimitry Andric     tooling::Replacements NonNoOpFixes;
379106c3fb27SDimitry Andric     for (const tooling::Replacement &Fix : Fixes) {
379206c3fb27SDimitry Andric       StringRef OriginalCode = Code.substr(Fix.getOffset(), Fix.getLength());
3793*0fca6ea1SDimitry Andric       if (OriginalCode != Fix.getReplacementText()) {
379406c3fb27SDimitry Andric         auto Err = NonNoOpFixes.add(Fix);
379506c3fb27SDimitry Andric         if (Err) {
379606c3fb27SDimitry Andric           llvm::errs() << "Error adding replacements : "
3797*0fca6ea1SDimitry Andric                        << toString(std::move(Err)) << "\n";
379806c3fb27SDimitry Andric         }
379906c3fb27SDimitry Andric       }
380006c3fb27SDimitry Andric     }
380106c3fb27SDimitry Andric     Fixes = std::move(NonNoOpFixes);
380206c3fb27SDimitry Andric   }
380306c3fb27SDimitry Andric 
38040b57cec5SDimitry Andric   return {Fixes, Penalty};
38050b57cec5SDimitry Andric }
38060b57cec5SDimitry Andric } // namespace internal
38070b57cec5SDimitry Andric 
38080b57cec5SDimitry Andric tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
38090b57cec5SDimitry Andric                                ArrayRef<tooling::Range> Ranges,
38100b57cec5SDimitry Andric                                StringRef FileName,
38110b57cec5SDimitry Andric                                FormattingAttemptStatus *Status) {
38120b57cec5SDimitry Andric   return internal::reformat(Style, Code, Ranges,
38130b57cec5SDimitry Andric                             /*FirstStartColumn=*/0,
38140b57cec5SDimitry Andric                             /*NextStartColumn=*/0,
38150b57cec5SDimitry Andric                             /*LastStartColumn=*/0, FileName, Status)
38160b57cec5SDimitry Andric       .first;
38170b57cec5SDimitry Andric }
38180b57cec5SDimitry Andric 
38190b57cec5SDimitry Andric tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
38200b57cec5SDimitry Andric                               ArrayRef<tooling::Range> Ranges,
38210b57cec5SDimitry Andric                               StringRef FileName) {
38220b57cec5SDimitry Andric   // cleanups only apply to C++ (they mostly concern ctor commas etc.)
38230b57cec5SDimitry Andric   if (Style.Language != FormatStyle::LK_Cpp)
38240b57cec5SDimitry Andric     return tooling::Replacements();
3825349cc55cSDimitry Andric   auto Env = Environment::make(Code, FileName, Ranges);
3826349cc55cSDimitry Andric   if (!Env)
3827349cc55cSDimitry Andric     return {};
3828349cc55cSDimitry Andric   return Cleaner(*Env, Style).process().first;
38290b57cec5SDimitry Andric }
38300b57cec5SDimitry Andric 
38310b57cec5SDimitry Andric tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
38320b57cec5SDimitry Andric                                ArrayRef<tooling::Range> Ranges,
38330b57cec5SDimitry Andric                                StringRef FileName, bool *IncompleteFormat) {
38340b57cec5SDimitry Andric   FormattingAttemptStatus Status;
38350b57cec5SDimitry Andric   auto Result = reformat(Style, Code, Ranges, FileName, &Status);
38360b57cec5SDimitry Andric   if (!Status.FormatComplete)
38370b57cec5SDimitry Andric     *IncompleteFormat = true;
38380b57cec5SDimitry Andric   return Result;
38390b57cec5SDimitry Andric }
38400b57cec5SDimitry Andric 
38410b57cec5SDimitry Andric tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,
38420b57cec5SDimitry Andric                                               StringRef Code,
38430b57cec5SDimitry Andric                                               ArrayRef<tooling::Range> Ranges,
38440b57cec5SDimitry Andric                                               StringRef FileName) {
3845349cc55cSDimitry Andric   auto Env = Environment::make(Code, FileName, Ranges);
3846349cc55cSDimitry Andric   if (!Env)
3847349cc55cSDimitry Andric     return {};
38484824e7fdSDimitry Andric   return NamespaceEndCommentsFixer(*Env, Style).process().first;
38490b57cec5SDimitry Andric }
38500b57cec5SDimitry Andric 
38510b57cec5SDimitry Andric tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
38520b57cec5SDimitry Andric                                             StringRef Code,
38530b57cec5SDimitry Andric                                             ArrayRef<tooling::Range> Ranges,
38540b57cec5SDimitry Andric                                             StringRef FileName) {
3855349cc55cSDimitry Andric   auto Env = Environment::make(Code, FileName, Ranges);
3856349cc55cSDimitry Andric   if (!Env)
3857349cc55cSDimitry Andric     return {};
38584824e7fdSDimitry Andric   return UsingDeclarationsSorter(*Env, Style).process().first;
38590b57cec5SDimitry Andric }
38600b57cec5SDimitry Andric 
38610b57cec5SDimitry Andric LangOptions getFormattingLangOpts(const FormatStyle &Style) {
38620b57cec5SDimitry Andric   LangOptions LangOpts;
3863a7dea167SDimitry Andric 
3864a7dea167SDimitry Andric   FormatStyle::LanguageStandard LexingStd = Style.Standard;
3865a7dea167SDimitry Andric   if (LexingStd == FormatStyle::LS_Auto)
3866a7dea167SDimitry Andric     LexingStd = FormatStyle::LS_Latest;
3867a7dea167SDimitry Andric   if (LexingStd == FormatStyle::LS_Latest)
3868a7dea167SDimitry Andric     LexingStd = FormatStyle::LS_Cpp20;
38690b57cec5SDimitry Andric   LangOpts.CPlusPlus = 1;
3870a7dea167SDimitry Andric   LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11;
3871a7dea167SDimitry Andric   LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14;
3872a7dea167SDimitry Andric   LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17;
38735ffd83dbSDimitry Andric   LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20;
38745ffd83dbSDimitry Andric   LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20;
387581ad6265SDimitry Andric   // Turning on digraphs in standards before C++0x is error-prone, because e.g.
387681ad6265SDimitry Andric   // the sequence "<::" will be unconditionally treated as "[:".
387781ad6265SDimitry Andric   // Cf. Lexer::LexTokenInternal.
387881ad6265SDimitry Andric   LangOpts.Digraphs = LexingStd >= FormatStyle::LS_Cpp11;
3879a7dea167SDimitry Andric 
38800b57cec5SDimitry Andric   LangOpts.LineComment = 1;
3881*0fca6ea1SDimitry Andric   LangOpts.CXXOperatorNames = Style.isCpp();
38820b57cec5SDimitry Andric   LangOpts.Bool = 1;
38830b57cec5SDimitry Andric   LangOpts.ObjC = 1;
38840b57cec5SDimitry Andric   LangOpts.MicrosoftExt = 1;    // To get kw___try, kw___finally.
38850b57cec5SDimitry Andric   LangOpts.DeclSpecKeyword = 1; // To get __declspec.
3886e8d8bef9SDimitry Andric   LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict.
38870b57cec5SDimitry Andric   return LangOpts;
38880b57cec5SDimitry Andric }
38890b57cec5SDimitry Andric 
38900b57cec5SDimitry Andric const char *StyleOptionHelpDescription =
3891753f127fSDimitry Andric     "Set coding style. <string> can be:\n"
3892753f127fSDimitry Andric     "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"
3893753f127fSDimitry Andric     "   Mozilla, WebKit.\n"
3894753f127fSDimitry Andric     "2. 'file' to load style configuration from a\n"
3895753f127fSDimitry Andric     "   .clang-format file in one of the parent directories\n"
3896753f127fSDimitry Andric     "   of the source file (for stdin, see --assume-filename).\n"
3897753f127fSDimitry Andric     "   If no .clang-format file is found, falls back to\n"
3898753f127fSDimitry Andric     "   --fallback-style.\n"
3899753f127fSDimitry Andric     "   --style=file is the default.\n"
3900753f127fSDimitry Andric     "3. 'file:<format_file_path>' to explicitly specify\n"
390104eeddc0SDimitry Andric     "   the configuration file.\n"
3902753f127fSDimitry Andric     "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n"
3903753f127fSDimitry Andric     "   --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
39040b57cec5SDimitry Andric 
39050b57cec5SDimitry Andric static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
39065f757f3fSDimitry Andric   if (FileName.ends_with(".java"))
39070b57cec5SDimitry Andric     return FormatStyle::LK_Java;
390806c3fb27SDimitry Andric   if (FileName.ends_with_insensitive(".js") ||
390906c3fb27SDimitry Andric       FileName.ends_with_insensitive(".mjs") ||
391006c3fb27SDimitry Andric       FileName.ends_with_insensitive(".ts")) {
3911a7dea167SDimitry Andric     return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript.
391281ad6265SDimitry Andric   }
39135f757f3fSDimitry Andric   if (FileName.ends_with(".m") || FileName.ends_with(".mm"))
39140b57cec5SDimitry Andric     return FormatStyle::LK_ObjC;
391506c3fb27SDimitry Andric   if (FileName.ends_with_insensitive(".proto") ||
391606c3fb27SDimitry Andric       FileName.ends_with_insensitive(".protodevel")) {
39170b57cec5SDimitry Andric     return FormatStyle::LK_Proto;
391881ad6265SDimitry Andric   }
3919*0fca6ea1SDimitry Andric   // txtpb is the canonical extension, and textproto is the legacy canonical
3920*0fca6ea1SDimitry Andric   // extension
3921*0fca6ea1SDimitry Andric   // https://protobuf.dev/reference/protobuf/textformat-spec/#text-format-files
3922*0fca6ea1SDimitry Andric   if (FileName.ends_with_insensitive(".txtpb") ||
3923*0fca6ea1SDimitry Andric       FileName.ends_with_insensitive(".textpb") ||
392406c3fb27SDimitry Andric       FileName.ends_with_insensitive(".pb.txt") ||
392506c3fb27SDimitry Andric       FileName.ends_with_insensitive(".textproto") ||
392606c3fb27SDimitry Andric       FileName.ends_with_insensitive(".asciipb")) {
39270b57cec5SDimitry Andric     return FormatStyle::LK_TextProto;
392881ad6265SDimitry Andric   }
392906c3fb27SDimitry Andric   if (FileName.ends_with_insensitive(".td"))
39300b57cec5SDimitry Andric     return FormatStyle::LK_TableGen;
393106c3fb27SDimitry Andric   if (FileName.ends_with_insensitive(".cs"))
39320b57cec5SDimitry Andric     return FormatStyle::LK_CSharp;
393306c3fb27SDimitry Andric   if (FileName.ends_with_insensitive(".json"))
3934fe6060f1SDimitry Andric     return FormatStyle::LK_Json;
393506c3fb27SDimitry Andric   if (FileName.ends_with_insensitive(".sv") ||
393606c3fb27SDimitry Andric       FileName.ends_with_insensitive(".svh") ||
393706c3fb27SDimitry Andric       FileName.ends_with_insensitive(".v") ||
393806c3fb27SDimitry Andric       FileName.ends_with_insensitive(".vh")) {
393981ad6265SDimitry Andric     return FormatStyle::LK_Verilog;
394081ad6265SDimitry Andric   }
39410b57cec5SDimitry Andric   return FormatStyle::LK_Cpp;
39420b57cec5SDimitry Andric }
39430b57cec5SDimitry Andric 
39440b57cec5SDimitry Andric FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {
39450b57cec5SDimitry Andric   const auto GuessedLanguage = getLanguageByFileName(FileName);
39460b57cec5SDimitry Andric   if (GuessedLanguage == FormatStyle::LK_Cpp) {
39470b57cec5SDimitry Andric     auto Extension = llvm::sys::path::extension(FileName);
39480b57cec5SDimitry Andric     // If there's no file extension (or it's .h), we need to check the contents
39490b57cec5SDimitry Andric     // of the code to see if it contains Objective-C.
3950*0fca6ea1SDimitry Andric     if (!Code.empty() && (Extension.empty() || Extension == ".h")) {
39510b57cec5SDimitry Andric       auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName;
39520b57cec5SDimitry Andric       Environment Env(Code, NonEmptyFileName, /*Ranges=*/{});
39530b57cec5SDimitry Andric       ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle());
39540b57cec5SDimitry Andric       Guesser.process();
39550b57cec5SDimitry Andric       if (Guesser.isObjC())
39560b57cec5SDimitry Andric         return FormatStyle::LK_ObjC;
39570b57cec5SDimitry Andric     }
39580b57cec5SDimitry Andric   }
39590b57cec5SDimitry Andric   return GuessedLanguage;
39600b57cec5SDimitry Andric }
39610b57cec5SDimitry Andric 
3962753f127fSDimitry Andric // Update StyleOptionHelpDescription above when changing this.
39630b57cec5SDimitry Andric const char *DefaultFormatStyle = "file";
39640b57cec5SDimitry Andric 
39650b57cec5SDimitry Andric const char *DefaultFallbackStyle = "LLVM";
39660b57cec5SDimitry Andric 
396704eeddc0SDimitry Andric llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
396804eeddc0SDimitry Andric loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS,
3969*0fca6ea1SDimitry Andric                        FormatStyle *Style, bool AllowUnknownOptions,
3970*0fca6ea1SDimitry Andric                        llvm::SourceMgr::DiagHandlerTy DiagHandler) {
397104eeddc0SDimitry Andric   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
397204eeddc0SDimitry Andric       FS->getBufferForFile(ConfigFile.str());
397304eeddc0SDimitry Andric   if (auto EC = Text.getError())
397404eeddc0SDimitry Andric     return EC;
3975*0fca6ea1SDimitry Andric   if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions,
3976*0fca6ea1SDimitry Andric                                    DiagHandler)) {
397704eeddc0SDimitry Andric     return EC;
3978*0fca6ea1SDimitry Andric   }
397904eeddc0SDimitry Andric   return Text;
398004eeddc0SDimitry Andric }
398104eeddc0SDimitry Andric 
3982*0fca6ea1SDimitry Andric Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
3983*0fca6ea1SDimitry Andric                                StringRef FallbackStyleName, StringRef Code,
3984*0fca6ea1SDimitry Andric                                llvm::vfs::FileSystem *FS,
3985*0fca6ea1SDimitry Andric                                bool AllowUnknownOptions,
3986*0fca6ea1SDimitry Andric                                llvm::SourceMgr::DiagHandlerTy DiagHandler) {
39870b57cec5SDimitry Andric   FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code));
39880b57cec5SDimitry Andric   FormatStyle FallbackStyle = getNoStyle();
39890b57cec5SDimitry Andric   if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))
39905f757f3fSDimitry Andric     return make_string_error("Invalid fallback style: " + FallbackStyleName);
39910b57cec5SDimitry Andric 
3992*0fca6ea1SDimitry Andric   SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1> ChildFormatTextToApply;
3993fe6060f1SDimitry Andric 
39945f757f3fSDimitry Andric   if (StyleName.starts_with("{")) {
39950b57cec5SDimitry Andric     // Parse YAML/JSON style from the command line.
3996fe6060f1SDimitry Andric     StringRef Source = "<command-line>";
3997fe6060f1SDimitry Andric     if (std::error_code ec =
3998fe6060f1SDimitry Andric             parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style,
3999*0fca6ea1SDimitry Andric                                AllowUnknownOptions, DiagHandler)) {
40000b57cec5SDimitry Andric       return make_string_error("Error parsing -style: " + ec.message());
400181ad6265SDimitry Andric     }
40025f757f3fSDimitry Andric 
40035f757f3fSDimitry Andric     if (!Style.InheritsParentConfig)
40045f757f3fSDimitry Andric       return Style;
40055f757f3fSDimitry Andric 
4006fe6060f1SDimitry Andric     ChildFormatTextToApply.emplace_back(
4007fe6060f1SDimitry Andric         llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false));
40080b57cec5SDimitry Andric   }
40095f757f3fSDimitry Andric 
40105f757f3fSDimitry Andric   if (!FS)
40115f757f3fSDimitry Andric     FS = llvm::vfs::getRealFileSystem().get();
40125f757f3fSDimitry Andric   assert(FS);
40130b57cec5SDimitry Andric 
401404eeddc0SDimitry Andric   // User provided clang-format file using -style=file:path/to/format/file.
401504eeddc0SDimitry Andric   if (!Style.InheritsParentConfig &&
401606c3fb27SDimitry Andric       StyleName.starts_with_insensitive("file:")) {
401704eeddc0SDimitry Andric     auto ConfigFile = StyleName.substr(5);
401804eeddc0SDimitry Andric     llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
4019*0fca6ea1SDimitry Andric         loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions,
4020*0fca6ea1SDimitry Andric                                DiagHandler);
402181ad6265SDimitry Andric     if (auto EC = Text.getError()) {
402204eeddc0SDimitry Andric       return make_string_error("Error reading " + ConfigFile + ": " +
402304eeddc0SDimitry Andric                                EC.message());
402481ad6265SDimitry Andric     }
402504eeddc0SDimitry Andric 
402604eeddc0SDimitry Andric     LLVM_DEBUG(llvm::dbgs()
402704eeddc0SDimitry Andric                << "Using configuration file " << ConfigFile << "\n");
402804eeddc0SDimitry Andric 
402904eeddc0SDimitry Andric     if (!Style.InheritsParentConfig)
403004eeddc0SDimitry Andric       return Style;
403104eeddc0SDimitry Andric 
403204eeddc0SDimitry Andric     // Search for parent configs starting from the parent directory of
403304eeddc0SDimitry Andric     // ConfigFile.
403404eeddc0SDimitry Andric     FileName = ConfigFile;
403504eeddc0SDimitry Andric     ChildFormatTextToApply.emplace_back(std::move(*Text));
403604eeddc0SDimitry Andric   }
403704eeddc0SDimitry Andric 
4038fe6060f1SDimitry Andric   // If the style inherits the parent configuration it is a command line
4039fe6060f1SDimitry Andric   // configuration, which wants to inherit, so we have to skip the check of the
4040fe6060f1SDimitry Andric   // StyleName.
4041fe6060f1SDimitry Andric   if (!Style.InheritsParentConfig && !StyleName.equals_insensitive("file")) {
40420b57cec5SDimitry Andric     if (!getPredefinedStyle(StyleName, Style.Language, &Style))
40430b57cec5SDimitry Andric       return make_string_error("Invalid value for -style");
4044fe6060f1SDimitry Andric     if (!Style.InheritsParentConfig)
40450b57cec5SDimitry Andric       return Style;
40460b57cec5SDimitry Andric   }
40470b57cec5SDimitry Andric 
40480b57cec5SDimitry Andric   SmallString<128> Path(FileName);
40490b57cec5SDimitry Andric   if (std::error_code EC = FS->makeAbsolute(Path))
40500b57cec5SDimitry Andric     return make_string_error(EC.message());
40510b57cec5SDimitry Andric 
40525f757f3fSDimitry Andric   // Reset possible inheritance
40535f757f3fSDimitry Andric   Style.InheritsParentConfig = false;
4054480093f4SDimitry Andric 
4055fe6060f1SDimitry Andric   auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {};
4056fe6060f1SDimitry Andric 
405704eeddc0SDimitry Andric   auto applyChildFormatTexts = [&](FormatStyle *Style) {
405804eeddc0SDimitry Andric     for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) {
4059*0fca6ea1SDimitry Andric       auto EC =
4060*0fca6ea1SDimitry Andric           parseConfiguration(*MemBuf, Style, AllowUnknownOptions,
4061*0fca6ea1SDimitry Andric                              DiagHandler ? DiagHandler : dropDiagnosticHandler);
406204eeddc0SDimitry Andric       // It was already correctly parsed.
406304eeddc0SDimitry Andric       assert(!EC);
406404eeddc0SDimitry Andric       static_cast<void>(EC);
406504eeddc0SDimitry Andric     }
406604eeddc0SDimitry Andric   };
406704eeddc0SDimitry Andric 
40685f757f3fSDimitry Andric   // Look for .clang-format/_clang-format file in the file's parent directories.
4069*0fca6ea1SDimitry Andric   SmallVector<std::string, 2> FilesToLookFor;
40705f757f3fSDimitry Andric   FilesToLookFor.push_back(".clang-format");
40715f757f3fSDimitry Andric   FilesToLookFor.push_back("_clang-format");
40725f757f3fSDimitry Andric 
40735f757f3fSDimitry Andric   SmallString<128> UnsuitableConfigFiles;
40740b57cec5SDimitry Andric   for (StringRef Directory = Path; !Directory.empty();
40750b57cec5SDimitry Andric        Directory = llvm::sys::path::parent_path(Directory)) {
40760b57cec5SDimitry Andric     auto Status = FS->status(Directory);
40770b57cec5SDimitry Andric     if (!Status ||
40780b57cec5SDimitry Andric         Status->getType() != llvm::sys::fs::file_type::directory_file) {
40790b57cec5SDimitry Andric       continue;
40800b57cec5SDimitry Andric     }
40810b57cec5SDimitry Andric 
4082480093f4SDimitry Andric     for (const auto &F : FilesToLookFor) {
40830b57cec5SDimitry Andric       SmallString<128> ConfigFile(Directory);
40840b57cec5SDimitry Andric 
4085480093f4SDimitry Andric       llvm::sys::path::append(ConfigFile, F);
40860b57cec5SDimitry Andric       LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
40870b57cec5SDimitry Andric 
40885f757f3fSDimitry Andric       Status = FS->status(ConfigFile);
40895f757f3fSDimitry Andric       if (!Status ||
40905f757f3fSDimitry Andric           Status->getType() != llvm::sys::fs::file_type::regular_file) {
40915f757f3fSDimitry Andric         continue;
40925f757f3fSDimitry Andric       }
40930b57cec5SDimitry Andric 
40940b57cec5SDimitry Andric       llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
4095*0fca6ea1SDimitry Andric           loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions,
4096*0fca6ea1SDimitry Andric                                  DiagHandler);
409704eeddc0SDimitry Andric       if (auto EC = Text.getError()) {
40985f757f3fSDimitry Andric         if (EC != ParseError::Unsuitable) {
40995f757f3fSDimitry Andric           return make_string_error("Error reading " + ConfigFile + ": " +
41005f757f3fSDimitry Andric                                    EC.message());
41015f757f3fSDimitry Andric         }
41020b57cec5SDimitry Andric         if (!UnsuitableConfigFiles.empty())
41030b57cec5SDimitry Andric           UnsuitableConfigFiles.append(", ");
41040b57cec5SDimitry Andric         UnsuitableConfigFiles.append(ConfigFile);
41050b57cec5SDimitry Andric         continue;
41060b57cec5SDimitry Andric       }
41075f757f3fSDimitry Andric 
41080b57cec5SDimitry Andric       LLVM_DEBUG(llvm::dbgs()
41090b57cec5SDimitry Andric                  << "Using configuration file " << ConfigFile << "\n");
4110fe6060f1SDimitry Andric 
4111fe6060f1SDimitry Andric       if (!Style.InheritsParentConfig) {
41125f757f3fSDimitry Andric         if (!ChildFormatTextToApply.empty()) {
4113fe6060f1SDimitry Andric           LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n");
411404eeddc0SDimitry Andric           applyChildFormatTexts(&Style);
41155f757f3fSDimitry Andric         }
4116fe6060f1SDimitry Andric         return Style;
4117fe6060f1SDimitry Andric       }
4118fe6060f1SDimitry Andric 
4119fe6060f1SDimitry Andric       LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n");
4120fe6060f1SDimitry Andric 
4121fe6060f1SDimitry Andric       // Reset inheritance of style
4122fe6060f1SDimitry Andric       Style.InheritsParentConfig = false;
4123fe6060f1SDimitry Andric 
4124fe6060f1SDimitry Andric       ChildFormatTextToApply.emplace_back(std::move(*Text));
4125fe6060f1SDimitry Andric 
4126fe6060f1SDimitry Andric       // Breaking out of the inner loop, since we don't want to parse
4127fe6060f1SDimitry Andric       // .clang-format AND _clang-format, if both exist. Then we continue the
41285f757f3fSDimitry Andric       // outer loop (parent directories) in search for the parent
4129fe6060f1SDimitry Andric       // configuration.
4130fe6060f1SDimitry Andric       break;
41310b57cec5SDimitry Andric     }
41320b57cec5SDimitry Andric   }
41335f757f3fSDimitry Andric 
413481ad6265SDimitry Andric   if (!UnsuitableConfigFiles.empty()) {
41350b57cec5SDimitry Andric     return make_string_error("Configuration file(s) do(es) not support " +
41360b57cec5SDimitry Andric                              getLanguageName(Style.Language) + ": " +
41370b57cec5SDimitry Andric                              UnsuitableConfigFiles);
413881ad6265SDimitry Andric   }
4139fe6060f1SDimitry Andric 
4140fe6060f1SDimitry Andric   if (!ChildFormatTextToApply.empty()) {
4141fe6060f1SDimitry Andric     LLVM_DEBUG(llvm::dbgs()
414204eeddc0SDimitry Andric                << "Applying child configurations on fallback style\n");
414304eeddc0SDimitry Andric     applyChildFormatTexts(&FallbackStyle);
4144fe6060f1SDimitry Andric   }
4145fe6060f1SDimitry Andric 
41460b57cec5SDimitry Andric   return FallbackStyle;
41470b57cec5SDimitry Andric }
41480b57cec5SDimitry Andric 
414906c3fb27SDimitry Andric static bool isClangFormatOnOff(StringRef Comment, bool On) {
415006c3fb27SDimitry Andric   if (Comment == (On ? "/* clang-format on */" : "/* clang-format off */"))
415106c3fb27SDimitry Andric     return true;
415206c3fb27SDimitry Andric 
415306c3fb27SDimitry Andric   static const char ClangFormatOn[] = "// clang-format on";
415406c3fb27SDimitry Andric   static const char ClangFormatOff[] = "// clang-format off";
415506c3fb27SDimitry Andric   const unsigned Size = (On ? sizeof ClangFormatOn : sizeof ClangFormatOff) - 1;
415606c3fb27SDimitry Andric 
41575f757f3fSDimitry Andric   return Comment.starts_with(On ? ClangFormatOn : ClangFormatOff) &&
415806c3fb27SDimitry Andric          (Comment.size() == Size || Comment[Size] == ':');
415906c3fb27SDimitry Andric }
416006c3fb27SDimitry Andric 
416106c3fb27SDimitry Andric bool isClangFormatOn(StringRef Comment) {
416206c3fb27SDimitry Andric   return isClangFormatOnOff(Comment, /*On=*/true);
416306c3fb27SDimitry Andric }
416406c3fb27SDimitry Andric 
416506c3fb27SDimitry Andric bool isClangFormatOff(StringRef Comment) {
416606c3fb27SDimitry Andric   return isClangFormatOnOff(Comment, /*On=*/false);
416706c3fb27SDimitry Andric }
416806c3fb27SDimitry Andric 
41690b57cec5SDimitry Andric } // namespace format
41700b57cec5SDimitry Andric } // namespace clang
4171