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"
160b57cec5SDimitry Andric #include "AffectedRangeManager.h"
175ffd83dbSDimitry Andric #include "BreakableToken.h"
180b57cec5SDimitry Andric #include "ContinuationIndenter.h"
1904eeddc0SDimitry Andric #include "DefinitionBlockSeparator.h"
200b57cec5SDimitry Andric #include "FormatInternal.h"
2181ad6265SDimitry Andric #include "FormatToken.h"
220b57cec5SDimitry Andric #include "FormatTokenLexer.h"
23bdd1243dSDimitry Andric #include "IntegerLiteralSeparatorFixer.h"
240b57cec5SDimitry Andric #include "NamespaceEndCommentsFixer.h"
255f757f3fSDimitry Andric #include "ObjCPropertyAttributeOrderFixer.h"
26349cc55cSDimitry Andric #include "QualifierAlignmentFixer.h"
270b57cec5SDimitry Andric #include "SortJavaScriptImports.h"
280b57cec5SDimitry Andric #include "TokenAnalyzer.h"
290b57cec5SDimitry Andric #include "TokenAnnotator.h"
300b57cec5SDimitry Andric #include "UnwrappedLineFormatter.h"
310b57cec5SDimitry Andric #include "UnwrappedLineParser.h"
320b57cec5SDimitry Andric #include "UsingDeclarationsSorter.h"
330b57cec5SDimitry Andric #include "WhitespaceManager.h"
340b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h"
350b57cec5SDimitry Andric #include "clang/Basic/DiagnosticOptions.h"
360b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
370b57cec5SDimitry Andric #include "clang/Lex/Lexer.h"
380b57cec5SDimitry Andric #include "clang/Tooling/Inclusions/HeaderIncludes.h"
390b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
4081ad6265SDimitry Andric #include "llvm/ADT/Sequence.h"
410b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
420b57cec5SDimitry Andric #include "llvm/Support/Allocator.h"
430b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
440b57cec5SDimitry Andric #include "llvm/Support/Path.h"
450b57cec5SDimitry Andric #include "llvm/Support/Regex.h"
460b57cec5SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
470b57cec5SDimitry Andric #include "llvm/Support/YAMLTraits.h"
480b57cec5SDimitry Andric #include <algorithm>
490b57cec5SDimitry Andric #include <memory>
500b57cec5SDimitry Andric #include <mutex>
51bdd1243dSDimitry Andric #include <optional>
520b57cec5SDimitry Andric #include <string>
530b57cec5SDimitry Andric #include <unordered_map>
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric #define DEBUG_TYPE "format-formatter"
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric using clang::format::FormatStyle;
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat)
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric namespace llvm {
620b57cec5SDimitry Andric namespace yaml {
635f757f3fSDimitry Andric template <>
645f757f3fSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BreakBeforeNoexceptSpecifierStyle> {
655f757f3fSDimitry Andric   static void
enumerationllvm::yaml::ScalarEnumerationTraits665f757f3fSDimitry Andric   enumeration(IO &IO, FormatStyle::BreakBeforeNoexceptSpecifierStyle &Value) {
675f757f3fSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::BBNSS_Never);
685f757f3fSDimitry Andric     IO.enumCase(Value, "OnlyWithParen", FormatStyle::BBNSS_OnlyWithParen);
695f757f3fSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::BBNSS_Always);
705f757f3fSDimitry Andric   }
715f757f3fSDimitry Andric };
725f757f3fSDimitry Andric 
7381ad6265SDimitry Andric template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {
enumInputllvm::yaml::MappingTraits7481ad6265SDimitry Andric   static void enumInput(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
7581ad6265SDimitry Andric     IO.enumCase(Value, "None",
7681ad6265SDimitry Andric                 FormatStyle::AlignConsecutiveStyle(
7781ad6265SDimitry Andric                     {/*Enabled=*/false, /*AcrossEmptyLines=*/false,
7881ad6265SDimitry Andric                      /*AcrossComments=*/false, /*AlignCompound=*/false,
79297eecfbSDimitry Andric                      /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
8081ad6265SDimitry Andric     IO.enumCase(Value, "Consecutive",
8181ad6265SDimitry Andric                 FormatStyle::AlignConsecutiveStyle(
8281ad6265SDimitry Andric                     {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
8381ad6265SDimitry Andric                      /*AcrossComments=*/false, /*AlignCompound=*/false,
84297eecfbSDimitry Andric                      /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
8581ad6265SDimitry Andric     IO.enumCase(Value, "AcrossEmptyLines",
8681ad6265SDimitry Andric                 FormatStyle::AlignConsecutiveStyle(
8781ad6265SDimitry Andric                     {/*Enabled=*/true, /*AcrossEmptyLines=*/true,
8881ad6265SDimitry Andric                      /*AcrossComments=*/false, /*AlignCompound=*/false,
89297eecfbSDimitry Andric                      /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
9081ad6265SDimitry Andric     IO.enumCase(Value, "AcrossComments",
91297eecfbSDimitry Andric                 FormatStyle::AlignConsecutiveStyle(
92297eecfbSDimitry Andric                     {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
93297eecfbSDimitry Andric                      /*AcrossComments=*/true, /*AlignCompound=*/false,
94297eecfbSDimitry Andric                      /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
95e8d8bef9SDimitry Andric     IO.enumCase(Value, "AcrossEmptyLinesAndComments",
96297eecfbSDimitry Andric                 FormatStyle::AlignConsecutiveStyle(
97297eecfbSDimitry Andric                     {/*Enabled=*/true, /*AcrossEmptyLines=*/true,
98297eecfbSDimitry Andric                      /*AcrossComments=*/true, /*AlignCompound=*/false,
99297eecfbSDimitry Andric                      /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
100e8d8bef9SDimitry Andric 
101349cc55cSDimitry Andric     // For backward compatibility.
10281ad6265SDimitry Andric     IO.enumCase(Value, "true",
10381ad6265SDimitry Andric                 FormatStyle::AlignConsecutiveStyle(
10481ad6265SDimitry Andric                     {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
10581ad6265SDimitry Andric                      /*AcrossComments=*/false, /*AlignCompound=*/false,
106297eecfbSDimitry Andric                      /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
10781ad6265SDimitry Andric     IO.enumCase(Value, "false",
10881ad6265SDimitry Andric                 FormatStyle::AlignConsecutiveStyle(
10981ad6265SDimitry Andric                     {/*Enabled=*/false, /*AcrossEmptyLines=*/false,
11081ad6265SDimitry Andric                      /*AcrossComments=*/false, /*AlignCompound=*/false,
111297eecfbSDimitry Andric                      /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
11281ad6265SDimitry Andric   }
11381ad6265SDimitry Andric 
mappingllvm::yaml::MappingTraits11481ad6265SDimitry Andric   static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
11581ad6265SDimitry Andric     IO.mapOptional("Enabled", Value.Enabled);
11681ad6265SDimitry Andric     IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);
11781ad6265SDimitry Andric     IO.mapOptional("AcrossComments", Value.AcrossComments);
11881ad6265SDimitry Andric     IO.mapOptional("AlignCompound", Value.AlignCompound);
119297eecfbSDimitry Andric     IO.mapOptional("AlignFunctionPointers", Value.AlignFunctionPointers);
12081ad6265SDimitry Andric     IO.mapOptional("PadOperators", Value.PadOperators);
121e8d8bef9SDimitry Andric   }
122e8d8bef9SDimitry Andric };
123e8d8bef9SDimitry Andric 
124fe6060f1SDimitry Andric template <>
12506c3fb27SDimitry Andric struct MappingTraits<FormatStyle::ShortCaseStatementsAlignmentStyle> {
mappingllvm::yaml::MappingTraits12606c3fb27SDimitry Andric   static void mapping(IO &IO,
12706c3fb27SDimitry Andric                       FormatStyle::ShortCaseStatementsAlignmentStyle &Value) {
12806c3fb27SDimitry Andric     IO.mapOptional("Enabled", Value.Enabled);
12906c3fb27SDimitry Andric     IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);
13006c3fb27SDimitry Andric     IO.mapOptional("AcrossComments", Value.AcrossComments);
13106c3fb27SDimitry Andric     IO.mapOptional("AlignCaseColons", Value.AlignCaseColons);
13206c3fb27SDimitry Andric   }
13306c3fb27SDimitry Andric };
13406c3fb27SDimitry Andric 
13506c3fb27SDimitry Andric template <>
136bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::AttributeBreakingStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits137bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::AttributeBreakingStyle &Value) {
138bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::ABS_Always);
139bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::ABS_Leave);
140bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::ABS_Never);
141bdd1243dSDimitry Andric   }
142bdd1243dSDimitry Andric };
143bdd1243dSDimitry Andric 
144bdd1243dSDimitry Andric template <>
145fe6060f1SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::ArrayInitializerAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits146fe6060f1SDimitry Andric   static void enumeration(IO &IO,
147fe6060f1SDimitry Andric                           FormatStyle::ArrayInitializerAlignmentStyle &Value) {
148fe6060f1SDimitry Andric     IO.enumCase(Value, "None", FormatStyle::AIAS_None);
149fe6060f1SDimitry Andric     IO.enumCase(Value, "Left", FormatStyle::AIAS_Left);
150fe6060f1SDimitry Andric     IO.enumCase(Value, "Right", FormatStyle::AIAS_Right);
151fe6060f1SDimitry Andric   }
152fe6060f1SDimitry Andric };
153fe6060f1SDimitry Andric 
154bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits155bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {
156bdd1243dSDimitry Andric     IO.enumCase(Value, "All", FormatStyle::BOS_All);
157bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::BOS_All);
158bdd1243dSDimitry Andric     IO.enumCase(Value, "None", FormatStyle::BOS_None);
159bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::BOS_None);
160bdd1243dSDimitry Andric     IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment);
1610b57cec5SDimitry Andric   }
1620b57cec5SDimitry Andric };
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits1650b57cec5SDimitry Andric   static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) {
1660b57cec5SDimitry Andric     IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto);
1670b57cec5SDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::BPS_Always);
1680b57cec5SDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::BPS_Never);
1690b57cec5SDimitry Andric   }
1700b57cec5SDimitry Andric };
1710b57cec5SDimitry Andric 
172bdd1243dSDimitry Andric template <>
173bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BitFieldColonSpacingStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits174bdd1243dSDimitry Andric   static void enumeration(IO &IO,
175bdd1243dSDimitry Andric                           FormatStyle::BitFieldColonSpacingStyle &Value) {
176bdd1243dSDimitry Andric     IO.enumCase(Value, "Both", FormatStyle::BFCS_Both);
177bdd1243dSDimitry Andric     IO.enumCase(Value, "None", FormatStyle::BFCS_None);
178bdd1243dSDimitry Andric     IO.enumCase(Value, "Before", FormatStyle::BFCS_Before);
179bdd1243dSDimitry Andric     IO.enumCase(Value, "After", FormatStyle::BFCS_After);
1800b57cec5SDimitry Andric   }
1810b57cec5SDimitry Andric };
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits1840b57cec5SDimitry Andric   static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {
1850b57cec5SDimitry Andric     IO.enumCase(Value, "Attach", FormatStyle::BS_Attach);
1860b57cec5SDimitry Andric     IO.enumCase(Value, "Linux", FormatStyle::BS_Linux);
1870b57cec5SDimitry Andric     IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla);
1880b57cec5SDimitry Andric     IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);
1890b57cec5SDimitry Andric     IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
190a7dea167SDimitry Andric     IO.enumCase(Value, "Whitesmiths", FormatStyle::BS_Whitesmiths);
1910b57cec5SDimitry Andric     IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
1920b57cec5SDimitry Andric     IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit);
1930b57cec5SDimitry Andric     IO.enumCase(Value, "Custom", FormatStyle::BS_Custom);
1940b57cec5SDimitry Andric   }
1950b57cec5SDimitry Andric };
1960b57cec5SDimitry Andric 
197bdd1243dSDimitry Andric template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
mappingllvm::yaml::MappingTraits198bdd1243dSDimitry Andric   static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
199bdd1243dSDimitry Andric     IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel);
200bdd1243dSDimitry Andric     IO.mapOptional("AfterClass", Wrapping.AfterClass);
201bdd1243dSDimitry Andric     IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement);
202bdd1243dSDimitry Andric     IO.mapOptional("AfterEnum", Wrapping.AfterEnum);
203bdd1243dSDimitry Andric     IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
204bdd1243dSDimitry Andric     IO.mapOptional("AfterFunction", Wrapping.AfterFunction);
205bdd1243dSDimitry Andric     IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace);
206bdd1243dSDimitry Andric     IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
207bdd1243dSDimitry Andric     IO.mapOptional("AfterStruct", Wrapping.AfterStruct);
208bdd1243dSDimitry Andric     IO.mapOptional("AfterUnion", Wrapping.AfterUnion);
209bdd1243dSDimitry Andric     IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
210bdd1243dSDimitry Andric     IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
211bdd1243dSDimitry Andric     IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody);
212bdd1243dSDimitry Andric     IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile);
213bdd1243dSDimitry Andric     IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
214bdd1243dSDimitry Andric     IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);
215bdd1243dSDimitry Andric     IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);
216bdd1243dSDimitry Andric     IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
217bdd1243dSDimitry Andric   }
218bdd1243dSDimitry Andric };
219bdd1243dSDimitry Andric 
220bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits221bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) {
222bdd1243dSDimitry Andric     IO.enumCase(Value, "Align", FormatStyle::BAS_Align);
223bdd1243dSDimitry Andric     IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign);
224bdd1243dSDimitry Andric     IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak);
225bdd1243dSDimitry Andric     IO.enumCase(Value, "BlockIndent", FormatStyle::BAS_BlockIndent);
226bdd1243dSDimitry Andric 
227bdd1243dSDimitry Andric     // For backward compatibility.
228bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::BAS_Align);
229bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign);
230bdd1243dSDimitry Andric   }
231bdd1243dSDimitry Andric };
232bdd1243dSDimitry Andric 
2330b57cec5SDimitry Andric template <>
234a7dea167SDimitry Andric struct ScalarEnumerationTraits<
235a7dea167SDimitry Andric     FormatStyle::BraceWrappingAfterControlStatementStyle> {
236a7dea167SDimitry Andric   static void
enumerationllvm::yaml::ScalarEnumerationTraits237a7dea167SDimitry Andric   enumeration(IO &IO,
238a7dea167SDimitry Andric               FormatStyle::BraceWrappingAfterControlStatementStyle &Value) {
239a7dea167SDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::BWACS_Never);
240a7dea167SDimitry Andric     IO.enumCase(Value, "MultiLine", FormatStyle::BWACS_MultiLine);
241a7dea167SDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::BWACS_Always);
2425ffd83dbSDimitry Andric 
2435ffd83dbSDimitry Andric     // For backward compatibility.
2445ffd83dbSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::BWACS_Never);
2455ffd83dbSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::BWACS_Always);
246a7dea167SDimitry Andric   }
247a7dea167SDimitry Andric };
248a7dea167SDimitry Andric 
249a7dea167SDimitry Andric template <>
25081ad6265SDimitry Andric struct ScalarEnumerationTraits<
25181ad6265SDimitry Andric     FormatStyle::BreakBeforeConceptDeclarationsStyle> {
25281ad6265SDimitry Andric   static void
enumerationllvm::yaml::ScalarEnumerationTraits25381ad6265SDimitry Andric   enumeration(IO &IO, FormatStyle::BreakBeforeConceptDeclarationsStyle &Value) {
25481ad6265SDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::BBCDS_Never);
25581ad6265SDimitry Andric     IO.enumCase(Value, "Allowed", FormatStyle::BBCDS_Allowed);
25681ad6265SDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::BBCDS_Always);
25781ad6265SDimitry Andric 
25881ad6265SDimitry Andric     // For backward compatibility.
25981ad6265SDimitry Andric     IO.enumCase(Value, "true", FormatStyle::BBCDS_Always);
26081ad6265SDimitry Andric     IO.enumCase(Value, "false", FormatStyle::BBCDS_Allowed);
26181ad6265SDimitry Andric   }
26281ad6265SDimitry Andric };
26381ad6265SDimitry Andric 
26481ad6265SDimitry Andric template <>
265bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BreakBeforeInlineASMColonStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits266bdd1243dSDimitry Andric   static void enumeration(IO &IO,
267bdd1243dSDimitry Andric                           FormatStyle::BreakBeforeInlineASMColonStyle &Value) {
268bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::BBIAS_Never);
269bdd1243dSDimitry Andric     IO.enumCase(Value, "OnlyMultiline", FormatStyle::BBIAS_OnlyMultiline);
270bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::BBIAS_Always);
271bdd1243dSDimitry Andric   }
272bdd1243dSDimitry Andric };
2735f757f3fSDimitry Andric 
274bdd1243dSDimitry Andric template <>
2750b57cec5SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
2760b57cec5SDimitry Andric   static void
enumerationllvm::yaml::ScalarEnumerationTraits2770b57cec5SDimitry Andric   enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
2780b57cec5SDimitry Andric     IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon);
2790b57cec5SDimitry Andric     IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma);
2800b57cec5SDimitry Andric     IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon);
2810b57cec5SDimitry Andric   }
2820b57cec5SDimitry Andric };
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric template <>
2850b57cec5SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits2860b57cec5SDimitry Andric   static void enumeration(IO &IO,
2870b57cec5SDimitry Andric                           FormatStyle::BreakInheritanceListStyle &Value) {
2880b57cec5SDimitry Andric     IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon);
2890b57cec5SDimitry Andric     IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma);
2900b57cec5SDimitry Andric     IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon);
291fe6060f1SDimitry Andric     IO.enumCase(Value, "AfterComma", FormatStyle::BILS_AfterComma);
292fe6060f1SDimitry Andric   }
293fe6060f1SDimitry Andric };
294fe6060f1SDimitry Andric 
295fe6060f1SDimitry Andric template <>
2960b57cec5SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits2970b57cec5SDimitry Andric   static void enumeration(IO &IO,
2980b57cec5SDimitry Andric                           FormatStyle::BreakTemplateDeclarationsStyle &Value) {
2990b57cec5SDimitry Andric     IO.enumCase(Value, "No", FormatStyle::BTDS_No);
3000b57cec5SDimitry Andric     IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);
3010b57cec5SDimitry Andric     IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric     // For backward compatibility.
3040b57cec5SDimitry Andric     IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine);
3050b57cec5SDimitry Andric     IO.enumCase(Value, "true", FormatStyle::BTDS_Yes);
3060b57cec5SDimitry Andric   }
3070b57cec5SDimitry Andric };
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric template <>
3100b57cec5SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
3110b57cec5SDimitry Andric   static void
enumerationllvm::yaml::ScalarEnumerationTraits3120b57cec5SDimitry Andric   enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
3130b57cec5SDimitry Andric     IO.enumCase(Value, "None", FormatStyle::DRTBS_None);
3140b57cec5SDimitry Andric     IO.enumCase(Value, "All", FormatStyle::DRTBS_All);
3150b57cec5SDimitry Andric     IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel);
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric     // For backward compatibility.
3180b57cec5SDimitry Andric     IO.enumCase(Value, "false", FormatStyle::DRTBS_None);
3190b57cec5SDimitry Andric     IO.enumCase(Value, "true", FormatStyle::DRTBS_All);
3200b57cec5SDimitry Andric   }
3210b57cec5SDimitry Andric };
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric template <>
3240b57cec5SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits3250b57cec5SDimitry Andric   static void enumeration(IO &IO,
3260b57cec5SDimitry Andric                           FormatStyle::EscapedNewlineAlignmentStyle &Value) {
3270b57cec5SDimitry Andric     IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign);
3280b57cec5SDimitry Andric     IO.enumCase(Value, "Left", FormatStyle::ENAS_Left);
3290b57cec5SDimitry Andric     IO.enumCase(Value, "Right", FormatStyle::ENAS_Right);
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric     // For backward compatibility.
3320b57cec5SDimitry Andric     IO.enumCase(Value, "true", FormatStyle::ENAS_Left);
3330b57cec5SDimitry Andric     IO.enumCase(Value, "false", FormatStyle::ENAS_Right);
3340b57cec5SDimitry Andric   }
3350b57cec5SDimitry Andric };
3360b57cec5SDimitry Andric 
337bdd1243dSDimitry Andric template <>
338bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::EmptyLineAfterAccessModifierStyle> {
339bdd1243dSDimitry Andric   static void
enumerationllvm::yaml::ScalarEnumerationTraits340bdd1243dSDimitry Andric   enumeration(IO &IO, FormatStyle::EmptyLineAfterAccessModifierStyle &Value) {
341bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::ELAAMS_Never);
342bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::ELAAMS_Leave);
343bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::ELAAMS_Always);
344bdd1243dSDimitry Andric   }
345bdd1243dSDimitry Andric };
346bdd1243dSDimitry Andric 
347bdd1243dSDimitry Andric template <>
348bdd1243dSDimitry Andric struct ScalarEnumerationTraits<
349bdd1243dSDimitry Andric     FormatStyle::EmptyLineBeforeAccessModifierStyle> {
350bdd1243dSDimitry Andric   static void
enumerationllvm::yaml::ScalarEnumerationTraits351bdd1243dSDimitry Andric   enumeration(IO &IO, FormatStyle::EmptyLineBeforeAccessModifierStyle &Value) {
352bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::ELBAMS_Never);
353bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::ELBAMS_Leave);
354bdd1243dSDimitry Andric     IO.enumCase(Value, "LogicalBlock", FormatStyle::ELBAMS_LogicalBlock);
355bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::ELBAMS_Always);
356bdd1243dSDimitry Andric   }
357bdd1243dSDimitry Andric };
358bdd1243dSDimitry Andric 
359bdd1243dSDimitry Andric template <>
360bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits361bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value) {
362bdd1243dSDimitry Andric     IO.enumCase(Value, "AfterExternBlock", FormatStyle::IEBS_AfterExternBlock);
363bdd1243dSDimitry Andric     IO.enumCase(Value, "Indent", FormatStyle::IEBS_Indent);
364bdd1243dSDimitry Andric     IO.enumCase(Value, "NoIndent", FormatStyle::IEBS_NoIndent);
365bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::IEBS_Indent);
366bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::IEBS_NoIndent);
367bdd1243dSDimitry Andric   }
368bdd1243dSDimitry Andric };
369bdd1243dSDimitry Andric 
370bdd1243dSDimitry Andric template <> struct MappingTraits<FormatStyle::IntegerLiteralSeparatorStyle> {
mappingllvm::yaml::MappingTraits371bdd1243dSDimitry Andric   static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &Base) {
372bdd1243dSDimitry Andric     IO.mapOptional("Binary", Base.Binary);
3731ac55f4cSDimitry Andric     IO.mapOptional("BinaryMinDigits", Base.BinaryMinDigits);
374bdd1243dSDimitry Andric     IO.mapOptional("Decimal", Base.Decimal);
3751ac55f4cSDimitry Andric     IO.mapOptional("DecimalMinDigits", Base.DecimalMinDigits);
376bdd1243dSDimitry Andric     IO.mapOptional("Hex", Base.Hex);
3771ac55f4cSDimitry Andric     IO.mapOptional("HexMinDigits", Base.HexMinDigits);
378bdd1243dSDimitry Andric   }
379bdd1243dSDimitry Andric };
380bdd1243dSDimitry Andric 
381bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits382bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) {
383bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave);
384bdd1243dSDimitry Andric     IO.enumCase(Value, "Single", FormatStyle::JSQS_Single);
385bdd1243dSDimitry Andric     IO.enumCase(Value, "Double", FormatStyle::JSQS_Double);
386bdd1243dSDimitry Andric   }
387bdd1243dSDimitry Andric };
388bdd1243dSDimitry Andric 
389bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
enumerationllvm::yaml::ScalarEnumerationTraits390bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
391bdd1243dSDimitry Andric     IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
392bdd1243dSDimitry Andric     IO.enumCase(Value, "Java", FormatStyle::LK_Java);
393bdd1243dSDimitry Andric     IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
394bdd1243dSDimitry Andric     IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);
395bdd1243dSDimitry Andric     IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
396bdd1243dSDimitry Andric     IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);
397bdd1243dSDimitry Andric     IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto);
398bdd1243dSDimitry Andric     IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp);
399bdd1243dSDimitry Andric     IO.enumCase(Value, "Json", FormatStyle::LK_Json);
40006c3fb27SDimitry Andric     IO.enumCase(Value, "Verilog", FormatStyle::LK_Verilog);
401bdd1243dSDimitry Andric   }
402bdd1243dSDimitry Andric };
403bdd1243dSDimitry Andric 
404bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
enumerationllvm::yaml::ScalarEnumerationTraits405bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
406bdd1243dSDimitry Andric     IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03);
407bdd1243dSDimitry Andric     IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias
408bdd1243dSDimitry Andric     IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias
409bdd1243dSDimitry Andric 
410bdd1243dSDimitry Andric     IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11);
411bdd1243dSDimitry Andric     IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias
412bdd1243dSDimitry Andric 
413bdd1243dSDimitry Andric     IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14);
414bdd1243dSDimitry Andric     IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17);
415bdd1243dSDimitry Andric     IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20);
416bdd1243dSDimitry Andric 
417bdd1243dSDimitry Andric     IO.enumCase(Value, "Latest", FormatStyle::LS_Latest);
418bdd1243dSDimitry Andric     IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias
419bdd1243dSDimitry Andric     IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);
420bdd1243dSDimitry Andric   }
421bdd1243dSDimitry Andric };
422bdd1243dSDimitry Andric 
423bdd1243dSDimitry Andric template <>
424bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::LambdaBodyIndentationKind> {
enumerationllvm::yaml::ScalarEnumerationTraits425bdd1243dSDimitry Andric   static void enumeration(IO &IO,
426bdd1243dSDimitry Andric                           FormatStyle::LambdaBodyIndentationKind &Value) {
427bdd1243dSDimitry Andric     IO.enumCase(Value, "Signature", FormatStyle::LBI_Signature);
428bdd1243dSDimitry Andric     IO.enumCase(Value, "OuterScope", FormatStyle::LBI_OuterScope);
429bdd1243dSDimitry Andric   }
430bdd1243dSDimitry Andric };
431bdd1243dSDimitry Andric 
432bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::LineEndingStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits433bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::LineEndingStyle &Value) {
434bdd1243dSDimitry Andric     IO.enumCase(Value, "LF", FormatStyle::LE_LF);
435bdd1243dSDimitry Andric     IO.enumCase(Value, "CRLF", FormatStyle::LE_CRLF);
436bdd1243dSDimitry Andric     IO.enumCase(Value, "DeriveLF", FormatStyle::LE_DeriveLF);
437bdd1243dSDimitry Andric     IO.enumCase(Value, "DeriveCRLF", FormatStyle::LE_DeriveCRLF);
438bdd1243dSDimitry Andric   }
439bdd1243dSDimitry Andric };
440bdd1243dSDimitry Andric 
441bdd1243dSDimitry Andric template <>
442bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
enumerationllvm::yaml::ScalarEnumerationTraits443bdd1243dSDimitry Andric   static void enumeration(IO &IO,
444bdd1243dSDimitry Andric                           FormatStyle::NamespaceIndentationKind &Value) {
445bdd1243dSDimitry Andric     IO.enumCase(Value, "None", FormatStyle::NI_None);
446bdd1243dSDimitry Andric     IO.enumCase(Value, "Inner", FormatStyle::NI_Inner);
447bdd1243dSDimitry Andric     IO.enumCase(Value, "All", FormatStyle::NI_All);
448bdd1243dSDimitry Andric   }
449bdd1243dSDimitry Andric };
450bdd1243dSDimitry Andric 
4515ffd83dbSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::OperandAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits4525ffd83dbSDimitry Andric   static void enumeration(IO &IO, FormatStyle::OperandAlignmentStyle &Value) {
4535ffd83dbSDimitry Andric     IO.enumCase(Value, "DontAlign", FormatStyle::OAS_DontAlign);
4545ffd83dbSDimitry Andric     IO.enumCase(Value, "Align", FormatStyle::OAS_Align);
4555ffd83dbSDimitry Andric     IO.enumCase(Value, "AlignAfterOperator",
4565ffd83dbSDimitry Andric                 FormatStyle::OAS_AlignAfterOperator);
4575ffd83dbSDimitry Andric 
4585ffd83dbSDimitry Andric     // For backward compatibility.
4595ffd83dbSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::OAS_Align);
4605ffd83dbSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::OAS_DontAlign);
4615ffd83dbSDimitry Andric   }
4625ffd83dbSDimitry Andric };
4635ffd83dbSDimitry Andric 
464bdd1243dSDimitry Andric template <>
465bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::PackConstructorInitializersStyle> {
466bdd1243dSDimitry Andric   static void
enumerationllvm::yaml::ScalarEnumerationTraits467bdd1243dSDimitry Andric   enumeration(IO &IO, FormatStyle::PackConstructorInitializersStyle &Value) {
468bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::PCIS_Never);
469bdd1243dSDimitry Andric     IO.enumCase(Value, "BinPack", FormatStyle::PCIS_BinPack);
470bdd1243dSDimitry Andric     IO.enumCase(Value, "CurrentLine", FormatStyle::PCIS_CurrentLine);
471bdd1243dSDimitry Andric     IO.enumCase(Value, "NextLine", FormatStyle::PCIS_NextLine);
47206c3fb27SDimitry Andric     IO.enumCase(Value, "NextLineOnly", FormatStyle::PCIS_NextLineOnly);
473bdd1243dSDimitry Andric   }
474bdd1243dSDimitry Andric };
475bdd1243dSDimitry Andric 
4760b57cec5SDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits4770b57cec5SDimitry Andric   static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {
4780b57cec5SDimitry Andric     IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
4790b57cec5SDimitry Andric     IO.enumCase(Value, "Left", FormatStyle::PAS_Left);
4800b57cec5SDimitry Andric     IO.enumCase(Value, "Right", FormatStyle::PAS_Right);
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric     // For backward compatibility.
4830b57cec5SDimitry Andric     IO.enumCase(Value, "true", FormatStyle::PAS_Left);
4840b57cec5SDimitry Andric     IO.enumCase(Value, "false", FormatStyle::PAS_Right);
4850b57cec5SDimitry Andric   }
4860b57cec5SDimitry Andric };
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric template <>
489bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits490bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
491bdd1243dSDimitry Andric     IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
492bdd1243dSDimitry Andric     IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);
493bdd1243dSDimitry Andric     IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash);
49404eeddc0SDimitry Andric   }
49504eeddc0SDimitry Andric };
49604eeddc0SDimitry Andric 
49704eeddc0SDimitry Andric template <>
498bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::QualifierAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits499bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::QualifierAlignmentStyle &Value) {
500bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::QAS_Leave);
501bdd1243dSDimitry Andric     IO.enumCase(Value, "Left", FormatStyle::QAS_Left);
502bdd1243dSDimitry Andric     IO.enumCase(Value, "Right", FormatStyle::QAS_Right);
503bdd1243dSDimitry Andric     IO.enumCase(Value, "Custom", FormatStyle::QAS_Custom);
504bdd1243dSDimitry Andric   }
505bdd1243dSDimitry Andric };
506bdd1243dSDimitry Andric 
507bdd1243dSDimitry Andric template <> struct MappingTraits<FormatStyle::RawStringFormat> {
mappingllvm::yaml::MappingTraits508bdd1243dSDimitry Andric   static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
509bdd1243dSDimitry Andric     IO.mapOptional("Language", Format.Language);
510bdd1243dSDimitry Andric     IO.mapOptional("Delimiters", Format.Delimiters);
511bdd1243dSDimitry Andric     IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);
512bdd1243dSDimitry Andric     IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter);
513bdd1243dSDimitry Andric     IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);
514e8d8bef9SDimitry Andric   }
515e8d8bef9SDimitry Andric };
516e8d8bef9SDimitry Andric 
517e8d8bef9SDimitry Andric template <>
518fe6060f1SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits519fe6060f1SDimitry Andric   static void enumeration(IO &IO, FormatStyle::ReferenceAlignmentStyle &Value) {
520fe6060f1SDimitry Andric     IO.enumCase(Value, "Pointer", FormatStyle::RAS_Pointer);
521fe6060f1SDimitry Andric     IO.enumCase(Value, "Middle", FormatStyle::RAS_Middle);
522fe6060f1SDimitry Andric     IO.enumCase(Value, "Left", FormatStyle::RAS_Left);
523fe6060f1SDimitry Andric     IO.enumCase(Value, "Right", FormatStyle::RAS_Right);
524fe6060f1SDimitry Andric   }
525fe6060f1SDimitry Andric };
526fe6060f1SDimitry Andric 
527fe6060f1SDimitry Andric template <>
52806c3fb27SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::RemoveParenthesesStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits52906c3fb27SDimitry Andric   static void enumeration(IO &IO, FormatStyle::RemoveParenthesesStyle &Value) {
53006c3fb27SDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::RPS_Leave);
53106c3fb27SDimitry Andric     IO.enumCase(Value, "MultipleParentheses",
53206c3fb27SDimitry Andric                 FormatStyle::RPS_MultipleParentheses);
53306c3fb27SDimitry Andric     IO.enumCase(Value, "ReturnStatement", FormatStyle::RPS_ReturnStatement);
53406c3fb27SDimitry Andric   }
53506c3fb27SDimitry Andric };
53606c3fb27SDimitry Andric 
53706c3fb27SDimitry Andric template <>
53881ad6265SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::RequiresClausePositionStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits53981ad6265SDimitry Andric   static void enumeration(IO &IO,
54081ad6265SDimitry Andric                           FormatStyle::RequiresClausePositionStyle &Value) {
54181ad6265SDimitry Andric     IO.enumCase(Value, "OwnLine", FormatStyle::RCPS_OwnLine);
54281ad6265SDimitry Andric     IO.enumCase(Value, "WithPreceding", FormatStyle::RCPS_WithPreceding);
54381ad6265SDimitry Andric     IO.enumCase(Value, "WithFollowing", FormatStyle::RCPS_WithFollowing);
54481ad6265SDimitry Andric     IO.enumCase(Value, "SingleLine", FormatStyle::RCPS_SingleLine);
54581ad6265SDimitry Andric   }
54681ad6265SDimitry Andric };
54781ad6265SDimitry Andric 
54881ad6265SDimitry Andric template <>
549bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::RequiresExpressionIndentationKind> {
550bdd1243dSDimitry Andric   static void
enumerationllvm::yaml::ScalarEnumerationTraits551bdd1243dSDimitry Andric   enumeration(IO &IO, FormatStyle::RequiresExpressionIndentationKind &Value) {
552bdd1243dSDimitry Andric     IO.enumCase(Value, "Keyword", FormatStyle::REI_Keyword);
553bdd1243dSDimitry Andric     IO.enumCase(Value, "OuterScope", FormatStyle::REI_OuterScope);
5540b57cec5SDimitry Andric   }
5550b57cec5SDimitry Andric };
5560b57cec5SDimitry Andric 
557e8d8bef9SDimitry Andric template <>
558bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits559bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
560bdd1243dSDimitry Andric     IO.enumCase(Value, "None", FormatStyle::RTBS_None);
561bdd1243dSDimitry Andric     IO.enumCase(Value, "All", FormatStyle::RTBS_All);
562bdd1243dSDimitry Andric     IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel);
563bdd1243dSDimitry Andric     IO.enumCase(Value, "TopLevelDefinitions",
564bdd1243dSDimitry Andric                 FormatStyle::RTBS_TopLevelDefinitions);
565bdd1243dSDimitry Andric     IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions);
566bdd1243dSDimitry Andric   }
567bdd1243dSDimitry Andric };
568bdd1243dSDimitry Andric 
569bdd1243dSDimitry Andric template <>
570bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::SeparateDefinitionStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits571bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::SeparateDefinitionStyle &Value) {
572bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::SDS_Leave);
573bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::SDS_Always);
574bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::SDS_Never);
575bdd1243dSDimitry Andric   }
576bdd1243dSDimitry Andric };
577bdd1243dSDimitry Andric 
578bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits579bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) {
580bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::SBS_Never);
581bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::SBS_Never);
582bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::SBS_Always);
583bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::SBS_Always);
584bdd1243dSDimitry Andric     IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty);
585bdd1243dSDimitry Andric   }
586bdd1243dSDimitry Andric };
587bdd1243dSDimitry Andric 
588bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits589bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
590bdd1243dSDimitry Andric     IO.enumCase(Value, "None", FormatStyle::SFS_None);
591bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::SFS_None);
592bdd1243dSDimitry Andric     IO.enumCase(Value, "All", FormatStyle::SFS_All);
593bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::SFS_All);
594bdd1243dSDimitry Andric     IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
595bdd1243dSDimitry Andric     IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly);
596bdd1243dSDimitry Andric     IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);
597bdd1243dSDimitry Andric   }
598bdd1243dSDimitry Andric };
599bdd1243dSDimitry Andric 
600bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits601bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) {
602bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::SIS_Never);
603bdd1243dSDimitry Andric     IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse);
604bdd1243dSDimitry Andric     IO.enumCase(Value, "OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf);
605bdd1243dSDimitry Andric     IO.enumCase(Value, "AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse);
606bdd1243dSDimitry Andric 
607bdd1243dSDimitry Andric     // For backward compatibility.
608bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::SIS_OnlyFirstIf);
609bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::SIS_Never);
610bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse);
611bdd1243dSDimitry Andric   }
612bdd1243dSDimitry Andric };
613bdd1243dSDimitry Andric 
614bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits615bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) {
616bdd1243dSDimitry Andric     IO.enumCase(Value, "None", FormatStyle::SLS_None);
617bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::SLS_None);
618bdd1243dSDimitry Andric     IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty);
619bdd1243dSDimitry Andric     IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline);
620bdd1243dSDimitry Andric     IO.enumCase(Value, "All", FormatStyle::SLS_All);
621bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::SLS_All);
622e8d8bef9SDimitry Andric   }
623e8d8bef9SDimitry Andric };
624e8d8bef9SDimitry Andric 
625fe6060f1SDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::SortIncludesOptions> {
enumerationllvm::yaml::ScalarEnumerationTraits626fe6060f1SDimitry Andric   static void enumeration(IO &IO, FormatStyle::SortIncludesOptions &Value) {
627fe6060f1SDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::SI_Never);
628fe6060f1SDimitry Andric     IO.enumCase(Value, "CaseInsensitive", FormatStyle::SI_CaseInsensitive);
629fe6060f1SDimitry Andric     IO.enumCase(Value, "CaseSensitive", FormatStyle::SI_CaseSensitive);
630fe6060f1SDimitry Andric 
631fe6060f1SDimitry Andric     // For backward compatibility.
632fe6060f1SDimitry Andric     IO.enumCase(Value, "false", FormatStyle::SI_Never);
633fe6060f1SDimitry Andric     IO.enumCase(Value, "true", FormatStyle::SI_CaseSensitive);
634fe6060f1SDimitry Andric   }
635fe6060f1SDimitry Andric };
636fe6060f1SDimitry Andric 
637e8d8bef9SDimitry Andric template <>
638e8d8bef9SDimitry Andric struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> {
enumerationllvm::yaml::ScalarEnumerationTraits639e8d8bef9SDimitry Andric   static void enumeration(IO &IO,
640e8d8bef9SDimitry Andric                           FormatStyle::SortJavaStaticImportOptions &Value) {
641e8d8bef9SDimitry Andric     IO.enumCase(Value, "Before", FormatStyle::SJSIO_Before);
642e8d8bef9SDimitry Andric     IO.enumCase(Value, "After", FormatStyle::SJSIO_After);
643e8d8bef9SDimitry Andric   }
644e8d8bef9SDimitry Andric };
645e8d8bef9SDimitry Andric 
646bdd1243dSDimitry Andric template <>
647bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::SortUsingDeclarationsOptions> {
enumerationllvm::yaml::ScalarEnumerationTraits648bdd1243dSDimitry Andric   static void enumeration(IO &IO,
649bdd1243dSDimitry Andric                           FormatStyle::SortUsingDeclarationsOptions &Value) {
650bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::SUD_Never);
651bdd1243dSDimitry Andric     IO.enumCase(Value, "Lexicographic", FormatStyle::SUD_Lexicographic);
652bdd1243dSDimitry Andric     IO.enumCase(Value, "LexicographicNumeric",
653bdd1243dSDimitry Andric                 FormatStyle::SUD_LexicographicNumeric);
654fe6060f1SDimitry Andric 
655fe6060f1SDimitry Andric     // For backward compatibility.
656bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::SUD_Never);
657bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::SUD_LexicographicNumeric);
658fe6060f1SDimitry Andric   }
659fe6060f1SDimitry Andric };
660fe6060f1SDimitry Andric 
661bdd1243dSDimitry Andric template <>
662bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> {
663bdd1243dSDimitry Andric   static void
enumerationllvm::yaml::ScalarEnumerationTraits664bdd1243dSDimitry Andric   enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value) {
665bdd1243dSDimitry Andric     IO.enumCase(Value, "Default", FormatStyle::SAPQ_Default);
666bdd1243dSDimitry Andric     IO.enumCase(Value, "Before", FormatStyle::SAPQ_Before);
667bdd1243dSDimitry Andric     IO.enumCase(Value, "After", FormatStyle::SAPQ_After);
668bdd1243dSDimitry Andric     IO.enumCase(Value, "Both", FormatStyle::SAPQ_Both);
6690b57cec5SDimitry Andric   }
6700b57cec5SDimitry Andric };
6710b57cec5SDimitry Andric 
672349cc55cSDimitry Andric template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> {
mappingllvm::yaml::MappingTraits673349cc55cSDimitry Andric   static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) {
674349cc55cSDimitry Andric     IO.mapOptional("AfterControlStatements", Spacing.AfterControlStatements);
675349cc55cSDimitry Andric     IO.mapOptional("AfterForeachMacros", Spacing.AfterForeachMacros);
676349cc55cSDimitry Andric     IO.mapOptional("AfterFunctionDefinitionName",
677349cc55cSDimitry Andric                    Spacing.AfterFunctionDefinitionName);
678349cc55cSDimitry Andric     IO.mapOptional("AfterFunctionDeclarationName",
679349cc55cSDimitry Andric                    Spacing.AfterFunctionDeclarationName);
680349cc55cSDimitry Andric     IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros);
68104eeddc0SDimitry Andric     IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
6825f757f3fSDimitry Andric     IO.mapOptional("AfterPlacementOperator", Spacing.AfterPlacementOperator);
68381ad6265SDimitry Andric     IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause);
68481ad6265SDimitry Andric     IO.mapOptional("AfterRequiresInExpression",
68581ad6265SDimitry Andric                    Spacing.AfterRequiresInExpression);
686349cc55cSDimitry Andric     IO.mapOptional("BeforeNonEmptyParentheses",
687349cc55cSDimitry Andric                    Spacing.BeforeNonEmptyParentheses);
688349cc55cSDimitry Andric   }
689349cc55cSDimitry Andric };
690349cc55cSDimitry Andric 
691bdd1243dSDimitry Andric template <>
692bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits693bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::SpaceBeforeParensStyle &Value) {
694bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
695bdd1243dSDimitry Andric     IO.enumCase(Value, "ControlStatements",
696bdd1243dSDimitry Andric                 FormatStyle::SBPO_ControlStatements);
697bdd1243dSDimitry Andric     IO.enumCase(Value, "ControlStatementsExceptControlMacros",
698bdd1243dSDimitry Andric                 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
699bdd1243dSDimitry Andric     IO.enumCase(Value, "NonEmptyParentheses",
700bdd1243dSDimitry Andric                 FormatStyle::SBPO_NonEmptyParentheses);
701bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
702bdd1243dSDimitry Andric     IO.enumCase(Value, "Custom", FormatStyle::SBPO_Custom);
703bdd1243dSDimitry Andric 
704bdd1243dSDimitry Andric     // For backward compatibility.
705bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
706bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);
707bdd1243dSDimitry Andric     IO.enumCase(Value, "ControlStatementsExceptForEachMacros",
708bdd1243dSDimitry Andric                 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
709bdd1243dSDimitry Andric   }
710bdd1243dSDimitry Andric };
711bdd1243dSDimitry Andric 
712bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits713bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value) {
714bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::SIAS_Never);
715bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::SIAS_Always);
716bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::SIAS_Leave);
717bdd1243dSDimitry Andric 
718bdd1243dSDimitry Andric     // For backward compatibility.
719bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::SIAS_Never);
720bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::SIAS_Always);
7210b57cec5SDimitry Andric   }
7220b57cec5SDimitry Andric };
7230b57cec5SDimitry Andric 
724fe6060f1SDimitry Andric template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {
mappingllvm::yaml::MappingTraits725fe6060f1SDimitry Andric   static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
726fe6060f1SDimitry Andric     // Transform the maximum to signed, to parse "-1" correctly
727fe6060f1SDimitry Andric     int signedMaximum = static_cast<int>(Space.Maximum);
728fe6060f1SDimitry Andric     IO.mapOptional("Minimum", Space.Minimum);
729fe6060f1SDimitry Andric     IO.mapOptional("Maximum", signedMaximum);
730fe6060f1SDimitry Andric     Space.Maximum = static_cast<unsigned>(signedMaximum);
731fe6060f1SDimitry Andric 
73281ad6265SDimitry Andric     if (Space.Maximum != -1u)
733fe6060f1SDimitry Andric       Space.Minimum = std::min(Space.Minimum, Space.Maximum);
734fe6060f1SDimitry Andric   }
735fe6060f1SDimitry Andric };
736fe6060f1SDimitry Andric 
73706c3fb27SDimitry Andric template <> struct MappingTraits<FormatStyle::SpacesInParensCustom> {
mappingllvm::yaml::MappingTraits73806c3fb27SDimitry Andric   static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) {
73906c3fb27SDimitry Andric     IO.mapOptional("InCStyleCasts", Spaces.InCStyleCasts);
74006c3fb27SDimitry Andric     IO.mapOptional("InConditionalStatements", Spaces.InConditionalStatements);
74106c3fb27SDimitry Andric     IO.mapOptional("InEmptyParentheses", Spaces.InEmptyParentheses);
74206c3fb27SDimitry Andric     IO.mapOptional("Other", Spaces.Other);
74306c3fb27SDimitry Andric   }
74406c3fb27SDimitry Andric };
74506c3fb27SDimitry Andric 
74606c3fb27SDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInParensStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits74706c3fb27SDimitry Andric   static void enumeration(IO &IO, FormatStyle::SpacesInParensStyle &Value) {
74806c3fb27SDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::SIPO_Never);
74906c3fb27SDimitry Andric     IO.enumCase(Value, "Custom", FormatStyle::SIPO_Custom);
75006c3fb27SDimitry Andric   }
75106c3fb27SDimitry Andric };
75206c3fb27SDimitry Andric 
753bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::TrailingCommaStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits754bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) {
755bdd1243dSDimitry Andric     IO.enumCase(Value, "None", FormatStyle::TCS_None);
756bdd1243dSDimitry Andric     IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped);
757bdd1243dSDimitry Andric   }
758bdd1243dSDimitry Andric };
759bdd1243dSDimitry Andric 
760bdd1243dSDimitry Andric template <>
761bdd1243dSDimitry Andric struct ScalarEnumerationTraits<FormatStyle::TrailingCommentsAlignmentKinds> {
enumerationllvm::yaml::ScalarEnumerationTraits762bdd1243dSDimitry Andric   static void enumeration(IO &IO,
763bdd1243dSDimitry Andric                           FormatStyle::TrailingCommentsAlignmentKinds &Value) {
764bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave", FormatStyle::TCAS_Leave);
765bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::TCAS_Always);
766bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::TCAS_Never);
767bdd1243dSDimitry Andric   }
768bdd1243dSDimitry Andric };
769bdd1243dSDimitry Andric 
770bdd1243dSDimitry Andric template <> struct MappingTraits<FormatStyle::TrailingCommentsAlignmentStyle> {
enumInputllvm::yaml::MappingTraits771bdd1243dSDimitry Andric   static void enumInput(IO &IO,
772bdd1243dSDimitry Andric                         FormatStyle::TrailingCommentsAlignmentStyle &Value) {
773bdd1243dSDimitry Andric     IO.enumCase(Value, "Leave",
774bdd1243dSDimitry Andric                 FormatStyle::TrailingCommentsAlignmentStyle(
7759e7101a8SDimitry Andric                     {FormatStyle::TCAS_Leave, 0}));
776bdd1243dSDimitry Andric 
777bdd1243dSDimitry Andric     IO.enumCase(Value, "Always",
778bdd1243dSDimitry Andric                 FormatStyle::TrailingCommentsAlignmentStyle(
7799e7101a8SDimitry Andric                     {FormatStyle::TCAS_Always, 0}));
780bdd1243dSDimitry Andric 
781bdd1243dSDimitry Andric     IO.enumCase(Value, "Never",
782bdd1243dSDimitry Andric                 FormatStyle::TrailingCommentsAlignmentStyle(
7839e7101a8SDimitry Andric                     {FormatStyle::TCAS_Never, 0}));
784bdd1243dSDimitry Andric 
785bdd1243dSDimitry Andric     // For backwards compatibility
786bdd1243dSDimitry Andric     IO.enumCase(Value, "true",
787bdd1243dSDimitry Andric                 FormatStyle::TrailingCommentsAlignmentStyle(
7889e7101a8SDimitry Andric                     {FormatStyle::TCAS_Always, 0}));
789bdd1243dSDimitry Andric     IO.enumCase(Value, "false",
790bdd1243dSDimitry Andric                 FormatStyle::TrailingCommentsAlignmentStyle(
7919e7101a8SDimitry Andric                     {FormatStyle::TCAS_Never, 0}));
792bdd1243dSDimitry Andric   }
793bdd1243dSDimitry Andric 
mappingllvm::yaml::MappingTraits794bdd1243dSDimitry Andric   static void mapping(IO &IO,
795bdd1243dSDimitry Andric                       FormatStyle::TrailingCommentsAlignmentStyle &Value) {
796bdd1243dSDimitry Andric     IO.mapOptional("Kind", Value.Kind);
797bdd1243dSDimitry Andric     IO.mapOptional("OverEmptyLines", Value.OverEmptyLines);
798bdd1243dSDimitry Andric   }
799bdd1243dSDimitry Andric };
800bdd1243dSDimitry Andric 
801bdd1243dSDimitry Andric template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits802bdd1243dSDimitry Andric   static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {
803bdd1243dSDimitry Andric     IO.enumCase(Value, "Never", FormatStyle::UT_Never);
804bdd1243dSDimitry Andric     IO.enumCase(Value, "false", FormatStyle::UT_Never);
805bdd1243dSDimitry Andric     IO.enumCase(Value, "Always", FormatStyle::UT_Always);
806bdd1243dSDimitry Andric     IO.enumCase(Value, "true", FormatStyle::UT_Always);
807bdd1243dSDimitry Andric     IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation);
808bdd1243dSDimitry Andric     IO.enumCase(Value, "ForContinuationAndIndentation",
809bdd1243dSDimitry Andric                 FormatStyle::UT_ForContinuationAndIndentation);
810bdd1243dSDimitry Andric     IO.enumCase(Value, "AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);
811bdd1243dSDimitry Andric   }
812bdd1243dSDimitry Andric };
813bdd1243dSDimitry Andric 
814bdd1243dSDimitry Andric template <> struct MappingTraits<FormatStyle> {
mappingllvm::yaml::MappingTraits815bdd1243dSDimitry Andric   static void mapping(IO &IO, FormatStyle &Style) {
816bdd1243dSDimitry Andric     // When reading, read the language first, we need it for getPredefinedStyle.
817bdd1243dSDimitry Andric     IO.mapOptional("Language", Style.Language);
818bdd1243dSDimitry Andric 
819bdd1243dSDimitry Andric     StringRef BasedOnStyle;
820bdd1243dSDimitry Andric     if (IO.outputting()) {
821bdd1243dSDimitry Andric       StringRef Styles[] = {"LLVM",   "Google", "Chromium",  "Mozilla",
8225f757f3fSDimitry Andric                             "WebKit", "GNU",    "Microsoft", "clang-format"};
823bdd1243dSDimitry Andric       for (StringRef StyleName : Styles) {
824bdd1243dSDimitry Andric         FormatStyle PredefinedStyle;
825bdd1243dSDimitry Andric         if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) &&
826bdd1243dSDimitry Andric             Style == PredefinedStyle) {
827bdd1243dSDimitry Andric           IO.mapOptional("# BasedOnStyle", StyleName);
828bdd1243dSDimitry Andric           BasedOnStyle = StyleName;
829bdd1243dSDimitry Andric           break;
830bdd1243dSDimitry Andric         }
831bdd1243dSDimitry Andric       }
832bdd1243dSDimitry Andric     } else {
833bdd1243dSDimitry Andric       IO.mapOptional("BasedOnStyle", BasedOnStyle);
834bdd1243dSDimitry Andric       if (!BasedOnStyle.empty()) {
835bdd1243dSDimitry Andric         FormatStyle::LanguageKind OldLanguage = Style.Language;
836bdd1243dSDimitry Andric         FormatStyle::LanguageKind Language =
837bdd1243dSDimitry Andric             ((FormatStyle *)IO.getContext())->Language;
838bdd1243dSDimitry Andric         if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
839bdd1243dSDimitry Andric           IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle));
840bdd1243dSDimitry Andric           return;
841bdd1243dSDimitry Andric         }
842bdd1243dSDimitry Andric         Style.Language = OldLanguage;
843bdd1243dSDimitry Andric       }
844bdd1243dSDimitry Andric     }
845bdd1243dSDimitry Andric 
846bdd1243dSDimitry Andric     // Initialize some variables used in the parsing. The using logic is at the
847bdd1243dSDimitry Andric     // end.
848bdd1243dSDimitry Andric 
849bdd1243dSDimitry Andric     // For backward compatibility:
850bdd1243dSDimitry Andric     // The default value of ConstructorInitializerAllOnOneLineOrOnePerLine was
851bdd1243dSDimitry Andric     // false unless BasedOnStyle was Google or Chromium whereas that of
852bdd1243dSDimitry Andric     // AllowAllConstructorInitializersOnNextLine was always true, so the
853bdd1243dSDimitry Andric     // equivalent default value of PackConstructorInitializers is PCIS_NextLine
854bdd1243dSDimitry Andric     // for Google/Chromium or PCIS_BinPack otherwise. If the deprecated options
855bdd1243dSDimitry Andric     // had a non-default value while PackConstructorInitializers has a default
856bdd1243dSDimitry Andric     // value, set the latter to an equivalent non-default value if needed.
857bdd1243dSDimitry Andric     const bool IsGoogleOrChromium = BasedOnStyle.equals_insensitive("google") ||
858bdd1243dSDimitry Andric                                     BasedOnStyle.equals_insensitive("chromium");
859bdd1243dSDimitry Andric     bool OnCurrentLine = IsGoogleOrChromium;
860bdd1243dSDimitry Andric     bool OnNextLine = true;
861bdd1243dSDimitry Andric 
862bdd1243dSDimitry Andric     bool BreakBeforeInheritanceComma = false;
863bdd1243dSDimitry Andric     bool BreakConstructorInitializersBeforeComma = false;
864bdd1243dSDimitry Andric 
865bdd1243dSDimitry Andric     bool DeriveLineEnding = true;
866bdd1243dSDimitry Andric     bool UseCRLF = false;
867bdd1243dSDimitry Andric 
86806c3fb27SDimitry Andric     bool SpaceInEmptyParentheses = false;
86906c3fb27SDimitry Andric     bool SpacesInConditionalStatement = false;
87006c3fb27SDimitry Andric     bool SpacesInCStyleCastParentheses = false;
87106c3fb27SDimitry Andric     bool SpacesInParentheses = false;
87206c3fb27SDimitry Andric 
873bdd1243dSDimitry Andric     // For backward compatibility.
874bdd1243dSDimitry Andric     if (!IO.outputting()) {
875bdd1243dSDimitry Andric       IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines);
876bdd1243dSDimitry Andric       IO.mapOptional("AllowAllConstructorInitializersOnNextLine", OnNextLine);
877bdd1243dSDimitry Andric       IO.mapOptional("BreakBeforeInheritanceComma",
878bdd1243dSDimitry Andric                      BreakBeforeInheritanceComma);
879bdd1243dSDimitry Andric       IO.mapOptional("BreakConstructorInitializersBeforeComma",
880bdd1243dSDimitry Andric                      BreakConstructorInitializersBeforeComma);
881bdd1243dSDimitry Andric       IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
882bdd1243dSDimitry Andric                      OnCurrentLine);
883bdd1243dSDimitry Andric       IO.mapOptional("DeriveLineEnding", DeriveLineEnding);
884bdd1243dSDimitry Andric       IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
885bdd1243dSDimitry Andric       IO.mapOptional("IndentFunctionDeclarationAfterType",
886bdd1243dSDimitry Andric                      Style.IndentWrappedFunctionNames);
887bdd1243dSDimitry Andric       IO.mapOptional("IndentRequires", Style.IndentRequiresClause);
888bdd1243dSDimitry Andric       IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
889bdd1243dSDimitry Andric       IO.mapOptional("SpaceAfterControlStatementKeyword",
890bdd1243dSDimitry Andric                      Style.SpaceBeforeParens);
89106c3fb27SDimitry Andric       IO.mapOptional("SpaceInEmptyParentheses", SpaceInEmptyParentheses);
89206c3fb27SDimitry Andric       IO.mapOptional("SpacesInConditionalStatement",
89306c3fb27SDimitry Andric                      SpacesInConditionalStatement);
89406c3fb27SDimitry Andric       IO.mapOptional("SpacesInCStyleCastParentheses",
89506c3fb27SDimitry Andric                      SpacesInCStyleCastParentheses);
89606c3fb27SDimitry Andric       IO.mapOptional("SpacesInParentheses", SpacesInParentheses);
897bdd1243dSDimitry Andric       IO.mapOptional("UseCRLF", UseCRLF);
898bdd1243dSDimitry Andric     }
899bdd1243dSDimitry Andric 
900bdd1243dSDimitry Andric     IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
901bdd1243dSDimitry Andric     IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
902bdd1243dSDimitry Andric     IO.mapOptional("AlignArrayOfStructures", Style.AlignArrayOfStructures);
903bdd1243dSDimitry Andric     IO.mapOptional("AlignConsecutiveAssignments",
904bdd1243dSDimitry Andric                    Style.AlignConsecutiveAssignments);
905bdd1243dSDimitry Andric     IO.mapOptional("AlignConsecutiveBitFields",
906bdd1243dSDimitry Andric                    Style.AlignConsecutiveBitFields);
907bdd1243dSDimitry Andric     IO.mapOptional("AlignConsecutiveDeclarations",
908bdd1243dSDimitry Andric                    Style.AlignConsecutiveDeclarations);
909bdd1243dSDimitry Andric     IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);
91006c3fb27SDimitry Andric     IO.mapOptional("AlignConsecutiveShortCaseStatements",
91106c3fb27SDimitry Andric                    Style.AlignConsecutiveShortCaseStatements);
912bdd1243dSDimitry Andric     IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines);
913bdd1243dSDimitry Andric     IO.mapOptional("AlignOperands", Style.AlignOperands);
914bdd1243dSDimitry Andric     IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
915bdd1243dSDimitry Andric     IO.mapOptional("AllowAllArgumentsOnNextLine",
916bdd1243dSDimitry Andric                    Style.AllowAllArgumentsOnNextLine);
917bdd1243dSDimitry Andric     IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
918bdd1243dSDimitry Andric                    Style.AllowAllParametersOfDeclarationOnNextLine);
9195f757f3fSDimitry Andric     IO.mapOptional("AllowBreakBeforeNoexceptSpecifier",
9205f757f3fSDimitry Andric                    Style.AllowBreakBeforeNoexceptSpecifier);
921bdd1243dSDimitry Andric     IO.mapOptional("AllowShortBlocksOnASingleLine",
922bdd1243dSDimitry Andric                    Style.AllowShortBlocksOnASingleLine);
923bdd1243dSDimitry Andric     IO.mapOptional("AllowShortCaseLabelsOnASingleLine",
924bdd1243dSDimitry Andric                    Style.AllowShortCaseLabelsOnASingleLine);
9255f757f3fSDimitry Andric     IO.mapOptional("AllowShortCompoundRequirementOnASingleLine",
9265f757f3fSDimitry Andric                    Style.AllowShortCompoundRequirementOnASingleLine);
927bdd1243dSDimitry Andric     IO.mapOptional("AllowShortEnumsOnASingleLine",
928bdd1243dSDimitry Andric                    Style.AllowShortEnumsOnASingleLine);
929bdd1243dSDimitry Andric     IO.mapOptional("AllowShortFunctionsOnASingleLine",
930bdd1243dSDimitry Andric                    Style.AllowShortFunctionsOnASingleLine);
931bdd1243dSDimitry Andric     IO.mapOptional("AllowShortIfStatementsOnASingleLine",
932bdd1243dSDimitry Andric                    Style.AllowShortIfStatementsOnASingleLine);
933bdd1243dSDimitry Andric     IO.mapOptional("AllowShortLambdasOnASingleLine",
934bdd1243dSDimitry Andric                    Style.AllowShortLambdasOnASingleLine);
935bdd1243dSDimitry Andric     IO.mapOptional("AllowShortLoopsOnASingleLine",
936bdd1243dSDimitry Andric                    Style.AllowShortLoopsOnASingleLine);
937bdd1243dSDimitry Andric     IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",
938bdd1243dSDimitry Andric                    Style.AlwaysBreakAfterDefinitionReturnType);
939bdd1243dSDimitry Andric     IO.mapOptional("AlwaysBreakAfterReturnType",
940bdd1243dSDimitry Andric                    Style.AlwaysBreakAfterReturnType);
941bdd1243dSDimitry Andric     IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
942bdd1243dSDimitry Andric                    Style.AlwaysBreakBeforeMultilineStrings);
943bdd1243dSDimitry Andric     IO.mapOptional("AlwaysBreakTemplateDeclarations",
944bdd1243dSDimitry Andric                    Style.AlwaysBreakTemplateDeclarations);
945bdd1243dSDimitry Andric     IO.mapOptional("AttributeMacros", Style.AttributeMacros);
946bdd1243dSDimitry Andric     IO.mapOptional("BinPackArguments", Style.BinPackArguments);
947bdd1243dSDimitry Andric     IO.mapOptional("BinPackParameters", Style.BinPackParameters);
948bdd1243dSDimitry Andric     IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing);
94906c3fb27SDimitry Andric     IO.mapOptional("BracedInitializerIndentWidth",
95006c3fb27SDimitry Andric                    Style.BracedInitializerIndentWidth);
951bdd1243dSDimitry Andric     IO.mapOptional("BraceWrapping", Style.BraceWrapping);
9525f757f3fSDimitry Andric     IO.mapOptional("BreakAdjacentStringLiterals",
9535f757f3fSDimitry Andric                    Style.BreakAdjacentStringLiterals);
954bdd1243dSDimitry Andric     IO.mapOptional("BreakAfterAttributes", Style.BreakAfterAttributes);
955bdd1243dSDimitry Andric     IO.mapOptional("BreakAfterJavaFieldAnnotations",
956bdd1243dSDimitry Andric                    Style.BreakAfterJavaFieldAnnotations);
957bdd1243dSDimitry Andric     IO.mapOptional("BreakArrays", Style.BreakArrays);
958bdd1243dSDimitry Andric     IO.mapOptional("BreakBeforeBinaryOperators",
959bdd1243dSDimitry Andric                    Style.BreakBeforeBinaryOperators);
960bdd1243dSDimitry Andric     IO.mapOptional("BreakBeforeConceptDeclarations",
961bdd1243dSDimitry Andric                    Style.BreakBeforeConceptDeclarations);
962bdd1243dSDimitry Andric     IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
963bdd1243dSDimitry Andric     IO.mapOptional("BreakBeforeInlineASMColon",
964bdd1243dSDimitry Andric                    Style.BreakBeforeInlineASMColon);
965bdd1243dSDimitry Andric     IO.mapOptional("BreakBeforeTernaryOperators",
966bdd1243dSDimitry Andric                    Style.BreakBeforeTernaryOperators);
967bdd1243dSDimitry Andric     IO.mapOptional("BreakConstructorInitializers",
968bdd1243dSDimitry Andric                    Style.BreakConstructorInitializers);
969bdd1243dSDimitry Andric     IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList);
970bdd1243dSDimitry Andric     IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
971bdd1243dSDimitry Andric     IO.mapOptional("ColumnLimit", Style.ColumnLimit);
972bdd1243dSDimitry Andric     IO.mapOptional("CommentPragmas", Style.CommentPragmas);
973bdd1243dSDimitry Andric     IO.mapOptional("CompactNamespaces", Style.CompactNamespaces);
974bdd1243dSDimitry Andric     IO.mapOptional("ConstructorInitializerIndentWidth",
975bdd1243dSDimitry Andric                    Style.ConstructorInitializerIndentWidth);
976bdd1243dSDimitry Andric     IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
977bdd1243dSDimitry Andric     IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
978bdd1243dSDimitry Andric     IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
979bdd1243dSDimitry Andric     IO.mapOptional("DisableFormat", Style.DisableFormat);
980bdd1243dSDimitry Andric     IO.mapOptional("EmptyLineAfterAccessModifier",
981bdd1243dSDimitry Andric                    Style.EmptyLineAfterAccessModifier);
982bdd1243dSDimitry Andric     IO.mapOptional("EmptyLineBeforeAccessModifier",
983bdd1243dSDimitry Andric                    Style.EmptyLineBeforeAccessModifier);
984bdd1243dSDimitry Andric     IO.mapOptional("ExperimentalAutoDetectBinPacking",
985bdd1243dSDimitry Andric                    Style.ExperimentalAutoDetectBinPacking);
986bdd1243dSDimitry Andric     IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
987bdd1243dSDimitry Andric     IO.mapOptional("ForEachMacros", Style.ForEachMacros);
988bdd1243dSDimitry Andric     IO.mapOptional("IfMacros", Style.IfMacros);
989bdd1243dSDimitry Andric     IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
990bdd1243dSDimitry Andric     IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
991bdd1243dSDimitry Andric     IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
992bdd1243dSDimitry Andric     IO.mapOptional("IncludeIsMainSourceRegex",
993bdd1243dSDimitry Andric                    Style.IncludeStyle.IncludeIsMainSourceRegex);
994bdd1243dSDimitry Andric     IO.mapOptional("IndentAccessModifiers", Style.IndentAccessModifiers);
995bdd1243dSDimitry Andric     IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks);
996bdd1243dSDimitry Andric     IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
997bdd1243dSDimitry Andric     IO.mapOptional("IndentExternBlock", Style.IndentExternBlock);
998bdd1243dSDimitry Andric     IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels);
999bdd1243dSDimitry Andric     IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
1000bdd1243dSDimitry Andric     IO.mapOptional("IndentRequiresClause", Style.IndentRequiresClause);
1001bdd1243dSDimitry Andric     IO.mapOptional("IndentWidth", Style.IndentWidth);
1002bdd1243dSDimitry Andric     IO.mapOptional("IndentWrappedFunctionNames",
1003bdd1243dSDimitry Andric                    Style.IndentWrappedFunctionNames);
1004bdd1243dSDimitry Andric     IO.mapOptional("InsertBraces", Style.InsertBraces);
1005bdd1243dSDimitry Andric     IO.mapOptional("InsertNewlineAtEOF", Style.InsertNewlineAtEOF);
1006bdd1243dSDimitry Andric     IO.mapOptional("InsertTrailingCommas", Style.InsertTrailingCommas);
1007bdd1243dSDimitry Andric     IO.mapOptional("IntegerLiteralSeparator", Style.IntegerLiteralSeparator);
1008bdd1243dSDimitry Andric     IO.mapOptional("JavaImportGroups", Style.JavaImportGroups);
1009bdd1243dSDimitry Andric     IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);
1010bdd1243dSDimitry Andric     IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
1011bdd1243dSDimitry Andric     IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
1012bdd1243dSDimitry Andric                    Style.KeepEmptyLinesAtTheStartOfBlocks);
101306c3fb27SDimitry Andric     IO.mapOptional("KeepEmptyLinesAtEOF", Style.KeepEmptyLinesAtEOF);
1014bdd1243dSDimitry Andric     IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation);
1015bdd1243dSDimitry Andric     IO.mapOptional("LineEnding", Style.LineEnding);
1016bdd1243dSDimitry Andric     IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
1017bdd1243dSDimitry Andric     IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);
10185f757f3fSDimitry Andric     IO.mapOptional("Macros", Style.Macros);
1019bdd1243dSDimitry Andric     IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
1020bdd1243dSDimitry Andric     IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
1021bdd1243dSDimitry Andric     IO.mapOptional("NamespaceMacros", Style.NamespaceMacros);
1022bdd1243dSDimitry Andric     IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList);
1023bdd1243dSDimitry Andric     IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);
1024bdd1243dSDimitry Andric     IO.mapOptional("ObjCBreakBeforeNestedBlockParam",
1025bdd1243dSDimitry Andric                    Style.ObjCBreakBeforeNestedBlockParam);
10265f757f3fSDimitry Andric     IO.mapOptional("ObjCPropertyAttributeOrder",
10275f757f3fSDimitry Andric                    Style.ObjCPropertyAttributeOrder);
1028bdd1243dSDimitry Andric     IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
1029bdd1243dSDimitry Andric     IO.mapOptional("ObjCSpaceBeforeProtocolList",
1030bdd1243dSDimitry Andric                    Style.ObjCSpaceBeforeProtocolList);
1031bdd1243dSDimitry Andric     IO.mapOptional("PackConstructorInitializers",
1032bdd1243dSDimitry Andric                    Style.PackConstructorInitializers);
1033bdd1243dSDimitry Andric     IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment);
1034bdd1243dSDimitry Andric     IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",
1035bdd1243dSDimitry Andric                    Style.PenaltyBreakBeforeFirstCallParameter);
1036bdd1243dSDimitry Andric     IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
1037bdd1243dSDimitry Andric     IO.mapOptional("PenaltyBreakFirstLessLess",
1038bdd1243dSDimitry Andric                    Style.PenaltyBreakFirstLessLess);
1039bdd1243dSDimitry Andric     IO.mapOptional("PenaltyBreakOpenParenthesis",
1040bdd1243dSDimitry Andric                    Style.PenaltyBreakOpenParenthesis);
10417a6dacacSDimitry Andric     IO.mapOptional("PenaltyBreakScopeResolution",
10427a6dacacSDimitry Andric                    Style.PenaltyBreakScopeResolution);
1043bdd1243dSDimitry Andric     IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
1044bdd1243dSDimitry Andric     IO.mapOptional("PenaltyBreakTemplateDeclaration",
1045bdd1243dSDimitry Andric                    Style.PenaltyBreakTemplateDeclaration);
1046bdd1243dSDimitry Andric     IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
1047bdd1243dSDimitry Andric     IO.mapOptional("PenaltyIndentedWhitespace",
1048bdd1243dSDimitry Andric                    Style.PenaltyIndentedWhitespace);
1049bdd1243dSDimitry Andric     IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
1050bdd1243dSDimitry Andric                    Style.PenaltyReturnTypeOnItsOwnLine);
1051bdd1243dSDimitry Andric     IO.mapOptional("PointerAlignment", Style.PointerAlignment);
1052bdd1243dSDimitry Andric     IO.mapOptional("PPIndentWidth", Style.PPIndentWidth);
1053bdd1243dSDimitry Andric     IO.mapOptional("QualifierAlignment", Style.QualifierAlignment);
1054bdd1243dSDimitry Andric     // Default Order for Left/Right based Qualifier alignment.
1055bdd1243dSDimitry Andric     if (Style.QualifierAlignment == FormatStyle::QAS_Right)
1056bdd1243dSDimitry Andric       Style.QualifierOrder = {"type", "const", "volatile"};
1057bdd1243dSDimitry Andric     else if (Style.QualifierAlignment == FormatStyle::QAS_Left)
1058bdd1243dSDimitry Andric       Style.QualifierOrder = {"const", "volatile", "type"};
1059bdd1243dSDimitry Andric     else if (Style.QualifierAlignment == FormatStyle::QAS_Custom)
1060bdd1243dSDimitry Andric       IO.mapOptional("QualifierOrder", Style.QualifierOrder);
1061bdd1243dSDimitry Andric     IO.mapOptional("RawStringFormats", Style.RawStringFormats);
1062bdd1243dSDimitry Andric     IO.mapOptional("ReferenceAlignment", Style.ReferenceAlignment);
1063bdd1243dSDimitry Andric     IO.mapOptional("ReflowComments", Style.ReflowComments);
1064bdd1243dSDimitry Andric     IO.mapOptional("RemoveBracesLLVM", Style.RemoveBracesLLVM);
106506c3fb27SDimitry Andric     IO.mapOptional("RemoveParentheses", Style.RemoveParentheses);
1066bdd1243dSDimitry Andric     IO.mapOptional("RemoveSemicolon", Style.RemoveSemicolon);
1067bdd1243dSDimitry Andric     IO.mapOptional("RequiresClausePosition", Style.RequiresClausePosition);
1068bdd1243dSDimitry Andric     IO.mapOptional("RequiresExpressionIndentation",
1069bdd1243dSDimitry Andric                    Style.RequiresExpressionIndentation);
1070bdd1243dSDimitry Andric     IO.mapOptional("SeparateDefinitionBlocks", Style.SeparateDefinitionBlocks);
1071bdd1243dSDimitry Andric     IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines);
10727a6dacacSDimitry Andric     IO.mapOptional("SkipMacroDefinitionBody", Style.SkipMacroDefinitionBody);
1073bdd1243dSDimitry Andric     IO.mapOptional("SortIncludes", Style.SortIncludes);
1074bdd1243dSDimitry Andric     IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport);
1075bdd1243dSDimitry Andric     IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);
1076bdd1243dSDimitry Andric     IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
1077bdd1243dSDimitry Andric     IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot);
1078bdd1243dSDimitry Andric     IO.mapOptional("SpaceAfterTemplateKeyword",
1079bdd1243dSDimitry Andric                    Style.SpaceAfterTemplateKeyword);
1080bdd1243dSDimitry Andric     IO.mapOptional("SpaceAroundPointerQualifiers",
1081bdd1243dSDimitry Andric                    Style.SpaceAroundPointerQualifiers);
1082bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeAssignmentOperators",
1083bdd1243dSDimitry Andric                    Style.SpaceBeforeAssignmentOperators);
1084bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeCaseColon", Style.SpaceBeforeCaseColon);
1085bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeCpp11BracedList",
1086bdd1243dSDimitry Andric                    Style.SpaceBeforeCpp11BracedList);
1087bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeCtorInitializerColon",
1088bdd1243dSDimitry Andric                    Style.SpaceBeforeCtorInitializerColon);
1089bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeInheritanceColon",
1090bdd1243dSDimitry Andric                    Style.SpaceBeforeInheritanceColon);
109106c3fb27SDimitry Andric     IO.mapOptional("SpaceBeforeJsonColon", Style.SpaceBeforeJsonColon);
1092bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
1093bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions);
1094bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
1095bdd1243dSDimitry Andric                    Style.SpaceBeforeRangeBasedForLoopColon);
1096bdd1243dSDimitry Andric     IO.mapOptional("SpaceBeforeSquareBrackets",
1097bdd1243dSDimitry Andric                    Style.SpaceBeforeSquareBrackets);
1098bdd1243dSDimitry Andric     IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock);
1099bdd1243dSDimitry Andric     IO.mapOptional("SpacesBeforeTrailingComments",
1100bdd1243dSDimitry Andric                    Style.SpacesBeforeTrailingComments);
1101bdd1243dSDimitry Andric     IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
1102bdd1243dSDimitry Andric     IO.mapOptional("SpacesInContainerLiterals",
1103bdd1243dSDimitry Andric                    Style.SpacesInContainerLiterals);
1104bdd1243dSDimitry Andric     IO.mapOptional("SpacesInLineCommentPrefix",
1105bdd1243dSDimitry Andric                    Style.SpacesInLineCommentPrefix);
110606c3fb27SDimitry Andric     IO.mapOptional("SpacesInParens", Style.SpacesInParens);
110706c3fb27SDimitry Andric     IO.mapOptional("SpacesInParensOptions", Style.SpacesInParensOptions);
1108bdd1243dSDimitry Andric     IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
1109bdd1243dSDimitry Andric     IO.mapOptional("Standard", Style.Standard);
1110bdd1243dSDimitry Andric     IO.mapOptional("StatementAttributeLikeMacros",
1111bdd1243dSDimitry Andric                    Style.StatementAttributeLikeMacros);
1112bdd1243dSDimitry Andric     IO.mapOptional("StatementMacros", Style.StatementMacros);
1113bdd1243dSDimitry Andric     IO.mapOptional("TabWidth", Style.TabWidth);
111406c3fb27SDimitry Andric     IO.mapOptional("TypeNames", Style.TypeNames);
1115bdd1243dSDimitry Andric     IO.mapOptional("TypenameMacros", Style.TypenameMacros);
1116bdd1243dSDimitry Andric     IO.mapOptional("UseTab", Style.UseTab);
111706c3fb27SDimitry Andric     IO.mapOptional("VerilogBreakBetweenInstancePorts",
111806c3fb27SDimitry Andric                    Style.VerilogBreakBetweenInstancePorts);
1119bdd1243dSDimitry Andric     IO.mapOptional("WhitespaceSensitiveMacros",
1120bdd1243dSDimitry Andric                    Style.WhitespaceSensitiveMacros);
1121bdd1243dSDimitry Andric 
1122bdd1243dSDimitry Andric     // If AlwaysBreakAfterDefinitionReturnType was specified but
1123bdd1243dSDimitry Andric     // AlwaysBreakAfterReturnType was not, initialize the latter from the
1124bdd1243dSDimitry Andric     // former for backwards compatibility.
1125bdd1243dSDimitry Andric     if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&
1126bdd1243dSDimitry Andric         Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) {
1127bdd1243dSDimitry Andric       if (Style.AlwaysBreakAfterDefinitionReturnType ==
1128bdd1243dSDimitry Andric           FormatStyle::DRTBS_All) {
1129bdd1243dSDimitry Andric         Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
1130bdd1243dSDimitry Andric       } else if (Style.AlwaysBreakAfterDefinitionReturnType ==
1131bdd1243dSDimitry Andric                  FormatStyle::DRTBS_TopLevel) {
1132bdd1243dSDimitry Andric         Style.AlwaysBreakAfterReturnType =
1133bdd1243dSDimitry Andric             FormatStyle::RTBS_TopLevelDefinitions;
1134bdd1243dSDimitry Andric       }
1135bdd1243dSDimitry Andric     }
1136bdd1243dSDimitry Andric 
1137bdd1243dSDimitry Andric     // If BreakBeforeInheritanceComma was specified but BreakInheritance was
1138bdd1243dSDimitry Andric     // not, initialize the latter from the former for backwards compatibility.
1139bdd1243dSDimitry Andric     if (BreakBeforeInheritanceComma &&
1140bdd1243dSDimitry Andric         Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) {
1141bdd1243dSDimitry Andric       Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
1142bdd1243dSDimitry Andric     }
1143bdd1243dSDimitry Andric 
1144bdd1243dSDimitry Andric     // If BreakConstructorInitializersBeforeComma was specified but
1145bdd1243dSDimitry Andric     // BreakConstructorInitializers was not, initialize the latter from the
1146bdd1243dSDimitry Andric     // former for backwards compatibility.
1147bdd1243dSDimitry Andric     if (BreakConstructorInitializersBeforeComma &&
1148bdd1243dSDimitry Andric         Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon) {
1149bdd1243dSDimitry Andric       Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
1150bdd1243dSDimitry Andric     }
1151bdd1243dSDimitry Andric 
1152bdd1243dSDimitry Andric     if (!IsGoogleOrChromium) {
1153bdd1243dSDimitry Andric       if (Style.PackConstructorInitializers == FormatStyle::PCIS_BinPack &&
1154bdd1243dSDimitry Andric           OnCurrentLine) {
1155bdd1243dSDimitry Andric         Style.PackConstructorInitializers = OnNextLine
1156bdd1243dSDimitry Andric                                                 ? FormatStyle::PCIS_NextLine
1157bdd1243dSDimitry Andric                                                 : FormatStyle::PCIS_CurrentLine;
1158bdd1243dSDimitry Andric       }
1159bdd1243dSDimitry Andric     } else if (Style.PackConstructorInitializers ==
1160bdd1243dSDimitry Andric                FormatStyle::PCIS_NextLine) {
1161bdd1243dSDimitry Andric       if (!OnCurrentLine)
1162bdd1243dSDimitry Andric         Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
1163bdd1243dSDimitry Andric       else if (!OnNextLine)
1164bdd1243dSDimitry Andric         Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine;
1165bdd1243dSDimitry Andric     }
1166bdd1243dSDimitry Andric 
1167bdd1243dSDimitry Andric     if (Style.LineEnding == FormatStyle::LE_DeriveLF) {
1168bdd1243dSDimitry Andric       if (!DeriveLineEnding)
1169bdd1243dSDimitry Andric         Style.LineEnding = UseCRLF ? FormatStyle::LE_CRLF : FormatStyle::LE_LF;
1170bdd1243dSDimitry Andric       else if (UseCRLF)
1171bdd1243dSDimitry Andric         Style.LineEnding = FormatStyle::LE_DeriveCRLF;
1172bdd1243dSDimitry Andric     }
117306c3fb27SDimitry Andric 
117406c3fb27SDimitry Andric     if (Style.SpacesInParens != FormatStyle::SIPO_Custom &&
117506c3fb27SDimitry Andric         (SpacesInParentheses || SpaceInEmptyParentheses ||
117606c3fb27SDimitry Andric          SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) {
117706c3fb27SDimitry Andric       if (SpacesInParentheses) {
117806c3fb27SDimitry Andric         // set all options except InCStyleCasts and InEmptyParentheses
117906c3fb27SDimitry Andric         // to true for backward compatibility.
118006c3fb27SDimitry Andric         Style.SpacesInParensOptions.InConditionalStatements = true;
118106c3fb27SDimitry Andric         Style.SpacesInParensOptions.InCStyleCasts =
118206c3fb27SDimitry Andric             SpacesInCStyleCastParentheses;
118306c3fb27SDimitry Andric         Style.SpacesInParensOptions.InEmptyParentheses =
118406c3fb27SDimitry Andric             SpaceInEmptyParentheses;
118506c3fb27SDimitry Andric         Style.SpacesInParensOptions.Other = true;
118606c3fb27SDimitry Andric       } else {
118706c3fb27SDimitry Andric         Style.SpacesInParensOptions = {};
118806c3fb27SDimitry Andric         Style.SpacesInParensOptions.InConditionalStatements =
118906c3fb27SDimitry Andric             SpacesInConditionalStatement;
119006c3fb27SDimitry Andric         Style.SpacesInParensOptions.InCStyleCasts =
119106c3fb27SDimitry Andric             SpacesInCStyleCastParentheses;
119206c3fb27SDimitry Andric         Style.SpacesInParensOptions.InEmptyParentheses =
119306c3fb27SDimitry Andric             SpaceInEmptyParentheses;
119406c3fb27SDimitry Andric       }
119506c3fb27SDimitry Andric       Style.SpacesInParens = FormatStyle::SIPO_Custom;
119606c3fb27SDimitry Andric     }
1197bdd1243dSDimitry Andric   }
1198bdd1243dSDimitry Andric };
1199bdd1243dSDimitry Andric 
12000b57cec5SDimitry Andric // Allows to read vector<FormatStyle> while keeping default values.
12010b57cec5SDimitry Andric // IO.getContext() should contain a pointer to the FormatStyle structure, that
12020b57cec5SDimitry Andric // will be used to get default values for missing keys.
12030b57cec5SDimitry Andric // If the first element has no Language specified, it will be treated as the
12040b57cec5SDimitry Andric // default one for the following elements.
12050b57cec5SDimitry Andric template <> struct DocumentListTraits<std::vector<FormatStyle>> {
sizellvm::yaml::DocumentListTraits12060b57cec5SDimitry Andric   static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
12070b57cec5SDimitry Andric     return Seq.size();
12080b57cec5SDimitry Andric   }
elementllvm::yaml::DocumentListTraits12090b57cec5SDimitry Andric   static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq,
12100b57cec5SDimitry Andric                               size_t Index) {
12110b57cec5SDimitry Andric     if (Index >= Seq.size()) {
12120b57cec5SDimitry Andric       assert(Index == Seq.size());
12130b57cec5SDimitry Andric       FormatStyle Template;
12140b57cec5SDimitry Andric       if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
12150b57cec5SDimitry Andric         Template = Seq[0];
12160b57cec5SDimitry Andric       } else {
12170b57cec5SDimitry Andric         Template = *((const FormatStyle *)IO.getContext());
12180b57cec5SDimitry Andric         Template.Language = FormatStyle::LK_None;
12190b57cec5SDimitry Andric       }
12200b57cec5SDimitry Andric       Seq.resize(Index + 1, Template);
12210b57cec5SDimitry Andric     }
12220b57cec5SDimitry Andric     return Seq[Index];
12230b57cec5SDimitry Andric   }
12240b57cec5SDimitry Andric };
12250b57cec5SDimitry Andric } // namespace yaml
12260b57cec5SDimitry Andric } // namespace llvm
12270b57cec5SDimitry Andric 
12280b57cec5SDimitry Andric namespace clang {
12290b57cec5SDimitry Andric namespace format {
12300b57cec5SDimitry Andric 
getParseCategory()12310b57cec5SDimitry Andric const std::error_category &getParseCategory() {
12320b57cec5SDimitry Andric   static const ParseErrorCategory C{};
12330b57cec5SDimitry Andric   return C;
12340b57cec5SDimitry Andric }
make_error_code(ParseError e)12350b57cec5SDimitry Andric std::error_code make_error_code(ParseError e) {
12360b57cec5SDimitry Andric   return std::error_code(static_cast<int>(e), getParseCategory());
12370b57cec5SDimitry Andric }
12380b57cec5SDimitry Andric 
make_string_error(const llvm::Twine & Message)12390b57cec5SDimitry Andric inline llvm::Error make_string_error(const llvm::Twine &Message) {
12400b57cec5SDimitry Andric   return llvm::make_error<llvm::StringError>(Message,
12410b57cec5SDimitry Andric                                              llvm::inconvertibleErrorCode());
12420b57cec5SDimitry Andric }
12430b57cec5SDimitry Andric 
name() const12440b57cec5SDimitry Andric const char *ParseErrorCategory::name() const noexcept {
12450b57cec5SDimitry Andric   return "clang-format.parse_error";
12460b57cec5SDimitry Andric }
12470b57cec5SDimitry Andric 
message(int EV) const12480b57cec5SDimitry Andric std::string ParseErrorCategory::message(int EV) const {
12490b57cec5SDimitry Andric   switch (static_cast<ParseError>(EV)) {
12500b57cec5SDimitry Andric   case ParseError::Success:
12510b57cec5SDimitry Andric     return "Success";
12520b57cec5SDimitry Andric   case ParseError::Error:
12530b57cec5SDimitry Andric     return "Invalid argument";
12540b57cec5SDimitry Andric   case ParseError::Unsuitable:
12550b57cec5SDimitry Andric     return "Unsuitable";
12565ffd83dbSDimitry Andric   case ParseError::BinPackTrailingCommaConflict:
12575ffd83dbSDimitry Andric     return "trailing comma insertion cannot be used with bin packing";
1258349cc55cSDimitry Andric   case ParseError::InvalidQualifierSpecified:
1259349cc55cSDimitry Andric     return "Invalid qualifier specified in QualifierOrder";
1260349cc55cSDimitry Andric   case ParseError::DuplicateQualifierSpecified:
126181ad6265SDimitry Andric     return "Duplicate qualifier specified in QualifierOrder";
1262349cc55cSDimitry Andric   case ParseError::MissingQualifierType:
126381ad6265SDimitry Andric     return "Missing type in QualifierOrder";
1264349cc55cSDimitry Andric   case ParseError::MissingQualifierOrder:
126581ad6265SDimitry Andric     return "Missing QualifierOrder";
12660b57cec5SDimitry Andric   }
12670b57cec5SDimitry Andric   llvm_unreachable("unexpected parse error");
12680b57cec5SDimitry Andric }
12690b57cec5SDimitry Andric 
expandPresetsBraceWrapping(FormatStyle & Expanded)1270349cc55cSDimitry Andric static void expandPresetsBraceWrapping(FormatStyle &Expanded) {
1271349cc55cSDimitry Andric   if (Expanded.BreakBeforeBraces == FormatStyle::BS_Custom)
1272349cc55cSDimitry Andric     return;
12735ffd83dbSDimitry Andric   Expanded.BraceWrapping = {/*AfterCaseLabel=*/false,
12745ffd83dbSDimitry Andric                             /*AfterClass=*/false,
12755ffd83dbSDimitry Andric                             /*AfterControlStatement=*/FormatStyle::BWACS_Never,
12765ffd83dbSDimitry Andric                             /*AfterEnum=*/false,
12775ffd83dbSDimitry Andric                             /*AfterFunction=*/false,
12785ffd83dbSDimitry Andric                             /*AfterNamespace=*/false,
12795ffd83dbSDimitry Andric                             /*AfterObjCDeclaration=*/false,
12805ffd83dbSDimitry Andric                             /*AfterStruct=*/false,
12815ffd83dbSDimitry Andric                             /*AfterUnion=*/false,
12825ffd83dbSDimitry Andric                             /*AfterExternBlock=*/false,
12835ffd83dbSDimitry Andric                             /*BeforeCatch=*/false,
12845ffd83dbSDimitry Andric                             /*BeforeElse=*/false,
12855ffd83dbSDimitry Andric                             /*BeforeLambdaBody=*/false,
12865ffd83dbSDimitry Andric                             /*BeforeWhile=*/false,
12875ffd83dbSDimitry Andric                             /*IndentBraces=*/false,
12885ffd83dbSDimitry Andric                             /*SplitEmptyFunction=*/true,
12895ffd83dbSDimitry Andric                             /*SplitEmptyRecord=*/true,
12905ffd83dbSDimitry Andric                             /*SplitEmptyNamespace=*/true};
1291349cc55cSDimitry Andric   switch (Expanded.BreakBeforeBraces) {
12920b57cec5SDimitry Andric   case FormatStyle::BS_Linux:
12930b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterClass = true;
12940b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterFunction = true;
12950b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterNamespace = true;
12960b57cec5SDimitry Andric     break;
12970b57cec5SDimitry Andric   case FormatStyle::BS_Mozilla:
12980b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterClass = true;
12990b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterEnum = true;
13000b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterFunction = true;
13010b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterStruct = true;
13020b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterUnion = true;
13030b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterExternBlock = true;
13040b57cec5SDimitry Andric     Expanded.BraceWrapping.SplitEmptyFunction = true;
13050b57cec5SDimitry Andric     Expanded.BraceWrapping.SplitEmptyRecord = false;
13060b57cec5SDimitry Andric     break;
13070b57cec5SDimitry Andric   case FormatStyle::BS_Stroustrup:
13080b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterFunction = true;
13090b57cec5SDimitry Andric     Expanded.BraceWrapping.BeforeCatch = true;
13100b57cec5SDimitry Andric     Expanded.BraceWrapping.BeforeElse = true;
13110b57cec5SDimitry Andric     break;
13120b57cec5SDimitry Andric   case FormatStyle::BS_Allman:
13130b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterCaseLabel = true;
13140b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterClass = true;
1315a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
1316a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterEnum = true;
1317a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterFunction = true;
1318a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterNamespace = true;
1319a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterObjCDeclaration = true;
1320a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterStruct = true;
1321a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterUnion = true;
1322a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterExternBlock = true;
1323a7dea167SDimitry Andric     Expanded.BraceWrapping.BeforeCatch = true;
1324a7dea167SDimitry Andric     Expanded.BraceWrapping.BeforeElse = true;
1325e8d8bef9SDimitry Andric     Expanded.BraceWrapping.BeforeLambdaBody = true;
1326a7dea167SDimitry Andric     break;
1327a7dea167SDimitry Andric   case FormatStyle::BS_Whitesmiths:
1328a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterCaseLabel = true;
1329a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterClass = true;
1330a7dea167SDimitry Andric     Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
13310b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterEnum = true;
13320b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterFunction = true;
13330b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterNamespace = true;
13340b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterObjCDeclaration = true;
13350b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterStruct = true;
13360b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterExternBlock = true;
13370b57cec5SDimitry Andric     Expanded.BraceWrapping.BeforeCatch = true;
13380b57cec5SDimitry Andric     Expanded.BraceWrapping.BeforeElse = true;
13395ffd83dbSDimitry Andric     Expanded.BraceWrapping.BeforeLambdaBody = true;
13400b57cec5SDimitry Andric     break;
13410b57cec5SDimitry Andric   case FormatStyle::BS_GNU:
13425ffd83dbSDimitry Andric     Expanded.BraceWrapping = {
13435ffd83dbSDimitry Andric         /*AfterCaseLabel=*/true,
13445ffd83dbSDimitry Andric         /*AfterClass=*/true,
13455ffd83dbSDimitry Andric         /*AfterControlStatement=*/FormatStyle::BWACS_Always,
13465ffd83dbSDimitry Andric         /*AfterEnum=*/true,
13475ffd83dbSDimitry Andric         /*AfterFunction=*/true,
13485ffd83dbSDimitry Andric         /*AfterNamespace=*/true,
13495ffd83dbSDimitry Andric         /*AfterObjCDeclaration=*/true,
13505ffd83dbSDimitry Andric         /*AfterStruct=*/true,
13515ffd83dbSDimitry Andric         /*AfterUnion=*/true,
13525ffd83dbSDimitry Andric         /*AfterExternBlock=*/true,
13535ffd83dbSDimitry Andric         /*BeforeCatch=*/true,
13545ffd83dbSDimitry Andric         /*BeforeElse=*/true,
13555ffd83dbSDimitry Andric         /*BeforeLambdaBody=*/false,
13565ffd83dbSDimitry Andric         /*BeforeWhile=*/true,
13575ffd83dbSDimitry Andric         /*IndentBraces=*/true,
13585ffd83dbSDimitry Andric         /*SplitEmptyFunction=*/true,
13595ffd83dbSDimitry Andric         /*SplitEmptyRecord=*/true,
13605ffd83dbSDimitry Andric         /*SplitEmptyNamespace=*/true};
13610b57cec5SDimitry Andric     break;
13620b57cec5SDimitry Andric   case FormatStyle::BS_WebKit:
13630b57cec5SDimitry Andric     Expanded.BraceWrapping.AfterFunction = true;
13640b57cec5SDimitry Andric     break;
13650b57cec5SDimitry Andric   default:
13660b57cec5SDimitry Andric     break;
13670b57cec5SDimitry Andric   }
1368349cc55cSDimitry Andric }
1369349cc55cSDimitry Andric 
expandPresetsSpaceBeforeParens(FormatStyle & Expanded)1370349cc55cSDimitry Andric static void expandPresetsSpaceBeforeParens(FormatStyle &Expanded) {
1371349cc55cSDimitry Andric   if (Expanded.SpaceBeforeParens == FormatStyle::SBPO_Custom)
1372349cc55cSDimitry Andric     return;
1373349cc55cSDimitry Andric   // Reset all flags
1374349cc55cSDimitry Andric   Expanded.SpaceBeforeParensOptions = {};
1375b3edf446SDimitry Andric   Expanded.SpaceBeforeParensOptions.AfterPlacementOperator = true;
1376349cc55cSDimitry Andric 
1377349cc55cSDimitry Andric   switch (Expanded.SpaceBeforeParens) {
1378349cc55cSDimitry Andric   case FormatStyle::SBPO_ControlStatements:
1379349cc55cSDimitry Andric     Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;
1380349cc55cSDimitry Andric     Expanded.SpaceBeforeParensOptions.AfterForeachMacros = true;
1381349cc55cSDimitry Andric     Expanded.SpaceBeforeParensOptions.AfterIfMacros = true;
1382349cc55cSDimitry Andric     break;
1383349cc55cSDimitry Andric   case FormatStyle::SBPO_ControlStatementsExceptControlMacros:
1384349cc55cSDimitry Andric     Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;
1385349cc55cSDimitry Andric     break;
1386349cc55cSDimitry Andric   case FormatStyle::SBPO_NonEmptyParentheses:
1387349cc55cSDimitry Andric     Expanded.SpaceBeforeParensOptions.BeforeNonEmptyParentheses = true;
1388349cc55cSDimitry Andric     break;
1389349cc55cSDimitry Andric   default:
1390349cc55cSDimitry Andric     break;
1391349cc55cSDimitry Andric   }
13920b57cec5SDimitry Andric }
13930b57cec5SDimitry Andric 
expandPresetsSpacesInParens(FormatStyle & Expanded)139406c3fb27SDimitry Andric static void expandPresetsSpacesInParens(FormatStyle &Expanded) {
139506c3fb27SDimitry Andric   if (Expanded.SpacesInParens == FormatStyle::SIPO_Custom)
139606c3fb27SDimitry Andric     return;
139706c3fb27SDimitry Andric   assert(Expanded.SpacesInParens == FormatStyle::SIPO_Never);
139806c3fb27SDimitry Andric   // Reset all flags
139906c3fb27SDimitry Andric   Expanded.SpacesInParensOptions = {};
140006c3fb27SDimitry Andric }
140106c3fb27SDimitry Andric 
getLLVMStyle(FormatStyle::LanguageKind Language)14020b57cec5SDimitry Andric FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
14030b57cec5SDimitry Andric   FormatStyle LLVMStyle;
1404fe6060f1SDimitry Andric   LLVMStyle.InheritsParentConfig = false;
14050b57cec5SDimitry Andric   LLVMStyle.Language = Language;
14060b57cec5SDimitry Andric   LLVMStyle.AccessModifierOffset = -2;
14070b57cec5SDimitry Andric   LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
14080b57cec5SDimitry Andric   LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
1409fe6060f1SDimitry Andric   LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;
14105ffd83dbSDimitry Andric   LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
141181ad6265SDimitry Andric   LLVMStyle.AlignConsecutiveAssignments = {};
141281ad6265SDimitry Andric   LLVMStyle.AlignConsecutiveAssignments.Enabled = false;
141381ad6265SDimitry Andric   LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false;
141481ad6265SDimitry Andric   LLVMStyle.AlignConsecutiveAssignments.AcrossComments = false;
141581ad6265SDimitry Andric   LLVMStyle.AlignConsecutiveAssignments.AlignCompound = false;
1416297eecfbSDimitry Andric   LLVMStyle.AlignConsecutiveAssignments.AlignFunctionPointers = false;
141781ad6265SDimitry Andric   LLVMStyle.AlignConsecutiveAssignments.PadOperators = true;
141881ad6265SDimitry Andric   LLVMStyle.AlignConsecutiveBitFields = {};
141981ad6265SDimitry Andric   LLVMStyle.AlignConsecutiveDeclarations = {};
142081ad6265SDimitry Andric   LLVMStyle.AlignConsecutiveMacros = {};
142106c3fb27SDimitry Andric   LLVMStyle.AlignConsecutiveShortCaseStatements = {};
1422bdd1243dSDimitry Andric   LLVMStyle.AlignTrailingComments = {};
1423bdd1243dSDimitry Andric   LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always;
1424bdd1243dSDimitry Andric   LLVMStyle.AlignTrailingComments.OverEmptyLines = 0;
14250b57cec5SDimitry Andric   LLVMStyle.AllowAllArgumentsOnNextLine = true;
14260b57cec5SDimitry Andric   LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
1427a7dea167SDimitry Andric   LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
14280b57cec5SDimitry Andric   LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
14295f757f3fSDimitry Andric   LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true;
1430bdd1243dSDimitry Andric   LLVMStyle.AllowShortEnumsOnASingleLine = true;
1431bdd1243dSDimitry Andric   LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
14320b57cec5SDimitry Andric   LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
14330b57cec5SDimitry Andric   LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
14340b57cec5SDimitry Andric   LLVMStyle.AllowShortLoopsOnASingleLine = false;
14350b57cec5SDimitry Andric   LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
14360b57cec5SDimitry Andric   LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
14370b57cec5SDimitry Andric   LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
14380b57cec5SDimitry Andric   LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
1439e8d8bef9SDimitry Andric   LLVMStyle.AttributeMacros.push_back("__capability");
1440bdd1243dSDimitry Andric   LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;
14410b57cec5SDimitry Andric   LLVMStyle.BinPackArguments = true;
14420b57cec5SDimitry Andric   LLVMStyle.BinPackParameters = true;
144306c3fb27SDimitry Andric   LLVMStyle.BracedInitializerIndentWidth = std::nullopt;
14445ffd83dbSDimitry Andric   LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false,
14455ffd83dbSDimitry Andric                              /*AfterClass=*/false,
14465ffd83dbSDimitry Andric                              /*AfterControlStatement=*/FormatStyle::BWACS_Never,
14475ffd83dbSDimitry Andric                              /*AfterEnum=*/false,
14485ffd83dbSDimitry Andric                              /*AfterFunction=*/false,
14495ffd83dbSDimitry Andric                              /*AfterNamespace=*/false,
14505ffd83dbSDimitry Andric                              /*AfterObjCDeclaration=*/false,
14515ffd83dbSDimitry Andric                              /*AfterStruct=*/false,
14525ffd83dbSDimitry Andric                              /*AfterUnion=*/false,
14535ffd83dbSDimitry Andric                              /*AfterExternBlock=*/false,
14545ffd83dbSDimitry Andric                              /*BeforeCatch=*/false,
14555ffd83dbSDimitry Andric                              /*BeforeElse=*/false,
14565ffd83dbSDimitry Andric                              /*BeforeLambdaBody=*/false,
14575ffd83dbSDimitry Andric                              /*BeforeWhile=*/false,
14585ffd83dbSDimitry Andric                              /*IndentBraces=*/false,
14595ffd83dbSDimitry Andric                              /*SplitEmptyFunction=*/true,
14605ffd83dbSDimitry Andric                              /*SplitEmptyRecord=*/true,
14615ffd83dbSDimitry Andric                              /*SplitEmptyNamespace=*/true};
14625f757f3fSDimitry Andric   LLVMStyle.BreakAdjacentStringLiterals = true;
14635f757f3fSDimitry Andric   LLVMStyle.BreakAfterAttributes = FormatStyle::ABS_Leave;
14640b57cec5SDimitry Andric   LLVMStyle.BreakAfterJavaFieldAnnotations = false;
1465bdd1243dSDimitry Andric   LLVMStyle.BreakArrays = true;
1466bdd1243dSDimitry Andric   LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
1467bdd1243dSDimitry Andric   LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
1468bdd1243dSDimitry Andric   LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always;
1469bdd1243dSDimitry Andric   LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline;
14705f757f3fSDimitry Andric   LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;
1471bdd1243dSDimitry Andric   LLVMStyle.BreakBeforeTernaryOperators = true;
14720b57cec5SDimitry Andric   LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
14730b57cec5SDimitry Andric   LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
14740b57cec5SDimitry Andric   LLVMStyle.BreakStringLiterals = true;
14750b57cec5SDimitry Andric   LLVMStyle.ColumnLimit = 80;
14760b57cec5SDimitry Andric   LLVMStyle.CommentPragmas = "^ IWYU pragma:";
14770b57cec5SDimitry Andric   LLVMStyle.CompactNamespaces = false;
14780b57cec5SDimitry Andric   LLVMStyle.ConstructorInitializerIndentWidth = 4;
14790b57cec5SDimitry Andric   LLVMStyle.ContinuationIndentWidth = 4;
14800b57cec5SDimitry Andric   LLVMStyle.Cpp11BracedListStyle = true;
14810b57cec5SDimitry Andric   LLVMStyle.DerivePointerAlignment = false;
1482bdd1243dSDimitry Andric   LLVMStyle.DisableFormat = false;
1483fe6060f1SDimitry Andric   LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never;
1484e8d8bef9SDimitry Andric   LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock;
14850b57cec5SDimitry Andric   LLVMStyle.ExperimentalAutoDetectBinPacking = false;
14860b57cec5SDimitry Andric   LLVMStyle.FixNamespaceComments = true;
14870b57cec5SDimitry Andric   LLVMStyle.ForEachMacros.push_back("foreach");
14880b57cec5SDimitry Andric   LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
14890b57cec5SDimitry Andric   LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
1490fe6060f1SDimitry Andric   LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE");
14910b57cec5SDimitry Andric   LLVMStyle.IncludeStyle.IncludeCategories = {
1492e8d8bef9SDimitry Andric       {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false},
1493e8d8bef9SDimitry Andric       {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},
1494e8d8bef9SDimitry Andric       {".*", 1, 0, false}};
14950b57cec5SDimitry Andric   LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
14960b57cec5SDimitry Andric   LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
1497fe6060f1SDimitry Andric   LLVMStyle.IndentAccessModifiers = false;
14980b57cec5SDimitry Andric   LLVMStyle.IndentCaseLabels = false;
14995ffd83dbSDimitry Andric   LLVMStyle.IndentCaseBlocks = false;
1500bdd1243dSDimitry Andric   LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
1501a7dea167SDimitry Andric   LLVMStyle.IndentGotoLabels = true;
15020b57cec5SDimitry Andric   LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
150381ad6265SDimitry Andric   LLVMStyle.IndentRequiresClause = true;
15040b57cec5SDimitry Andric   LLVMStyle.IndentWidth = 2;
1505bdd1243dSDimitry Andric   LLVMStyle.IndentWrappedFunctionNames = false;
150681ad6265SDimitry Andric   LLVMStyle.InsertBraces = false;
1507bdd1243dSDimitry Andric   LLVMStyle.InsertNewlineAtEOF = false;
15085ffd83dbSDimitry Andric   LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
15091ac55f4cSDimitry Andric   LLVMStyle.IntegerLiteralSeparator = {
15101ac55f4cSDimitry Andric       /*Binary=*/0,  /*BinaryMinDigits=*/0,
15111ac55f4cSDimitry Andric       /*Decimal=*/0, /*DecimalMinDigits=*/0,
15121ac55f4cSDimitry Andric       /*Hex=*/0,     /*HexMinDigits=*/0};
15130b57cec5SDimitry Andric   LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
15140b57cec5SDimitry Andric   LLVMStyle.JavaScriptWrapImports = true;
151506c3fb27SDimitry Andric   LLVMStyle.KeepEmptyLinesAtEOF = false;
15160b57cec5SDimitry Andric   LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
1517bdd1243dSDimitry Andric   LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature;
1518bdd1243dSDimitry Andric   LLVMStyle.LineEnding = FormatStyle::LE_DeriveLF;
1519bdd1243dSDimitry Andric   LLVMStyle.MaxEmptyLinesToKeep = 1;
15200b57cec5SDimitry Andric   LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
15210b57cec5SDimitry Andric   LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto;
15220b57cec5SDimitry Andric   LLVMStyle.ObjCBlockIndentWidth = 2;
15235ffd83dbSDimitry Andric   LLVMStyle.ObjCBreakBeforeNestedBlockParam = true;
15240b57cec5SDimitry Andric   LLVMStyle.ObjCSpaceAfterProperty = false;
15250b57cec5SDimitry Andric   LLVMStyle.ObjCSpaceBeforeProtocolList = true;
1526bdd1243dSDimitry Andric   LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
15270b57cec5SDimitry Andric   LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
1528bdd1243dSDimitry Andric   LLVMStyle.PPIndentWidth = -1;
1529bdd1243dSDimitry Andric   LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
1530fe6060f1SDimitry Andric   LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer;
15310b57cec5SDimitry Andric   LLVMStyle.ReflowComments = true;
153204eeddc0SDimitry Andric   LLVMStyle.RemoveBracesLLVM = false;
153306c3fb27SDimitry Andric   LLVMStyle.RemoveParentheses = FormatStyle::RPS_Leave;
1534bdd1243dSDimitry Andric   LLVMStyle.RemoveSemicolon = false;
1535bdd1243dSDimitry Andric   LLVMStyle.RequiresClausePosition = FormatStyle::RCPS_OwnLine;
1536bdd1243dSDimitry Andric   LLVMStyle.RequiresExpressionIndentation = FormatStyle::REI_OuterScope;
1537bdd1243dSDimitry Andric   LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
1538bdd1243dSDimitry Andric   LLVMStyle.ShortNamespaceLines = 1;
15397a6dacacSDimitry Andric   LLVMStyle.SkipMacroDefinitionBody = false;
1540bdd1243dSDimitry Andric   LLVMStyle.SortIncludes = FormatStyle::SI_CaseSensitive;
1541bdd1243dSDimitry Andric   LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
1542bdd1243dSDimitry Andric   LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;
15430b57cec5SDimitry Andric   LLVMStyle.SpaceAfterCStyleCast = false;
15440b57cec5SDimitry Andric   LLVMStyle.SpaceAfterLogicalNot = false;
15450b57cec5SDimitry Andric   LLVMStyle.SpaceAfterTemplateKeyword = true;
1546e8d8bef9SDimitry Andric   LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
1547e8d8bef9SDimitry Andric   LLVMStyle.SpaceBeforeCaseColon = false;
15480b57cec5SDimitry Andric   LLVMStyle.SpaceBeforeCtorInitializerColon = true;
15490b57cec5SDimitry Andric   LLVMStyle.SpaceBeforeInheritanceColon = true;
155006c3fb27SDimitry Andric   LLVMStyle.SpaceBeforeJsonColon = false;
15510b57cec5SDimitry Andric   LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
155281ad6265SDimitry Andric   LLVMStyle.SpaceBeforeParensOptions = {};
1553349cc55cSDimitry Andric   LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true;
1554349cc55cSDimitry Andric   LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true;
1555349cc55cSDimitry Andric   LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true;
15560b57cec5SDimitry Andric   LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
15570b57cec5SDimitry Andric   LLVMStyle.SpaceBeforeAssignmentOperators = true;
15580b57cec5SDimitry Andric   LLVMStyle.SpaceBeforeCpp11BracedList = false;
1559480093f4SDimitry Andric   LLVMStyle.SpaceBeforeSquareBrackets = false;
1560bdd1243dSDimitry Andric   LLVMStyle.SpaceInEmptyBlock = false;
1561bdd1243dSDimitry Andric   LLVMStyle.SpacesBeforeTrailingComments = 1;
1562fe6060f1SDimitry Andric   LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never;
1563bdd1243dSDimitry Andric   LLVMStyle.SpacesInContainerLiterals = true;
1564bdd1243dSDimitry Andric   LLVMStyle.SpacesInLineCommentPrefix = {/*Minimum=*/1, /*Maximum=*/-1u};
156506c3fb27SDimitry Andric   LLVMStyle.SpacesInParens = FormatStyle::SIPO_Never;
1566bdd1243dSDimitry Andric   LLVMStyle.SpacesInSquareBrackets = false;
1567bdd1243dSDimitry Andric   LLVMStyle.Standard = FormatStyle::LS_Latest;
1568bdd1243dSDimitry Andric   LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");
1569bdd1243dSDimitry Andric   LLVMStyle.StatementMacros.push_back("Q_UNUSED");
1570bdd1243dSDimitry Andric   LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");
1571bdd1243dSDimitry Andric   LLVMStyle.TabWidth = 8;
1572bdd1243dSDimitry Andric   LLVMStyle.UseTab = FormatStyle::UT_Never;
157306c3fb27SDimitry Andric   LLVMStyle.VerilogBreakBetweenInstancePorts = true;
1574bdd1243dSDimitry Andric   LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE");
1575bdd1243dSDimitry Andric   LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME");
1576bdd1243dSDimitry Andric   LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME");
1577bdd1243dSDimitry Andric   LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE");
1578bdd1243dSDimitry Andric   LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE");
15790b57cec5SDimitry Andric 
15800b57cec5SDimitry Andric   LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
15810b57cec5SDimitry Andric   LLVMStyle.PenaltyBreakComment = 300;
15820b57cec5SDimitry Andric   LLVMStyle.PenaltyBreakFirstLessLess = 120;
15830b57cec5SDimitry Andric   LLVMStyle.PenaltyBreakString = 1000;
15840b57cec5SDimitry Andric   LLVMStyle.PenaltyExcessCharacter = 1000000;
15850b57cec5SDimitry Andric   LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
15860b57cec5SDimitry Andric   LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
158704eeddc0SDimitry Andric   LLVMStyle.PenaltyBreakOpenParenthesis = 0;
15887a6dacacSDimitry Andric   LLVMStyle.PenaltyBreakScopeResolution = 500;
15890b57cec5SDimitry Andric   LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;
1590e8d8bef9SDimitry Andric   LLVMStyle.PenaltyIndentedWhitespace = 0;
15910b57cec5SDimitry Andric 
15920b57cec5SDimitry Andric   // Defaults that differ when not C++.
1593bdd1243dSDimitry Andric   switch (Language) {
1594bdd1243dSDimitry Andric   case FormatStyle::LK_TableGen:
15950b57cec5SDimitry Andric     LLVMStyle.SpacesInContainerLiterals = false;
1596bdd1243dSDimitry Andric     break;
1597bdd1243dSDimitry Andric   case FormatStyle::LK_Json:
1598fe6060f1SDimitry Andric     LLVMStyle.ColumnLimit = 0;
1599bdd1243dSDimitry Andric     break;
1600bdd1243dSDimitry Andric   case FormatStyle::LK_Verilog:
1601bdd1243dSDimitry Andric     LLVMStyle.IndentCaseLabels = true;
160206c3fb27SDimitry Andric     LLVMStyle.SpacesInContainerLiterals = false;
1603bdd1243dSDimitry Andric     break;
1604bdd1243dSDimitry Andric   default:
1605bdd1243dSDimitry Andric     break;
1606bdd1243dSDimitry Andric   }
16070b57cec5SDimitry Andric 
16080b57cec5SDimitry Andric   return LLVMStyle;
16090b57cec5SDimitry Andric }
16100b57cec5SDimitry Andric 
getGoogleStyle(FormatStyle::LanguageKind Language)16110b57cec5SDimitry Andric FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
16120b57cec5SDimitry Andric   if (Language == FormatStyle::LK_TextProto) {
16130b57cec5SDimitry Andric     FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto);
16140b57cec5SDimitry Andric     GoogleStyle.Language = FormatStyle::LK_TextProto;
16150b57cec5SDimitry Andric 
16160b57cec5SDimitry Andric     return GoogleStyle;
16170b57cec5SDimitry Andric   }
16180b57cec5SDimitry Andric 
16190b57cec5SDimitry Andric   FormatStyle GoogleStyle = getLLVMStyle(Language);
16200b57cec5SDimitry Andric 
16210b57cec5SDimitry Andric   GoogleStyle.AccessModifierOffset = -1;
16220b57cec5SDimitry Andric   GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left;
16230b57cec5SDimitry Andric   GoogleStyle.AllowShortIfStatementsOnASingleLine =
16240b57cec5SDimitry Andric       FormatStyle::SIS_WithoutElse;
16250b57cec5SDimitry Andric   GoogleStyle.AllowShortLoopsOnASingleLine = true;
16260b57cec5SDimitry Andric   GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
16270b57cec5SDimitry Andric   GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
16280b57cec5SDimitry Andric   GoogleStyle.DerivePointerAlignment = true;
1629e8d8bef9SDimitry Andric   GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false},
1630e8d8bef9SDimitry Andric                                                 {"^<.*\\.h>", 1, 0, false},
1631e8d8bef9SDimitry Andric                                                 {"^<.*", 2, 0, false},
1632e8d8bef9SDimitry Andric                                                 {".*", 3, 0, false}};
16330b57cec5SDimitry Andric   GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
16340b57cec5SDimitry Andric   GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
16350b57cec5SDimitry Andric   GoogleStyle.IndentCaseLabels = true;
16360b57cec5SDimitry Andric   GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
16370b57cec5SDimitry Andric   GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never;
16380b57cec5SDimitry Andric   GoogleStyle.ObjCSpaceAfterProperty = false;
16390b57cec5SDimitry Andric   GoogleStyle.ObjCSpaceBeforeProtocolList = true;
1640349cc55cSDimitry Andric   GoogleStyle.PackConstructorInitializers = FormatStyle::PCIS_NextLine;
16410b57cec5SDimitry Andric   GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;
16420b57cec5SDimitry Andric   GoogleStyle.RawStringFormats = {
16430b57cec5SDimitry Andric       {
16440b57cec5SDimitry Andric           FormatStyle::LK_Cpp,
16450b57cec5SDimitry Andric           /*Delimiters=*/
16460b57cec5SDimitry Andric           {
16470b57cec5SDimitry Andric               "cc",
16480b57cec5SDimitry Andric               "CC",
16490b57cec5SDimitry Andric               "cpp",
16500b57cec5SDimitry Andric               "Cpp",
16510b57cec5SDimitry Andric               "CPP",
16520b57cec5SDimitry Andric               "c++",
16530b57cec5SDimitry Andric               "C++",
16540b57cec5SDimitry Andric           },
16550b57cec5SDimitry Andric           /*EnclosingFunctionNames=*/
16560b57cec5SDimitry Andric           {},
16570b57cec5SDimitry Andric           /*CanonicalDelimiter=*/"",
16580b57cec5SDimitry Andric           /*BasedOnStyle=*/"google",
16590b57cec5SDimitry Andric       },
16600b57cec5SDimitry Andric       {
16610b57cec5SDimitry Andric           FormatStyle::LK_TextProto,
16620b57cec5SDimitry Andric           /*Delimiters=*/
16630b57cec5SDimitry Andric           {
16640b57cec5SDimitry Andric               "pb",
16650b57cec5SDimitry Andric               "PB",
16660b57cec5SDimitry Andric               "proto",
16670b57cec5SDimitry Andric               "PROTO",
16680b57cec5SDimitry Andric           },
16690b57cec5SDimitry Andric           /*EnclosingFunctionNames=*/
16700b57cec5SDimitry Andric           {
16710b57cec5SDimitry Andric               "EqualsProto",
16720b57cec5SDimitry Andric               "EquivToProto",
16730b57cec5SDimitry Andric               "PARSE_PARTIAL_TEXT_PROTO",
16740b57cec5SDimitry Andric               "PARSE_TEST_PROTO",
16750b57cec5SDimitry Andric               "PARSE_TEXT_PROTO",
16760b57cec5SDimitry Andric               "ParseTextOrDie",
16770b57cec5SDimitry Andric               "ParseTextProtoOrDie",
16785ffd83dbSDimitry Andric               "ParseTestProto",
16795ffd83dbSDimitry Andric               "ParsePartialTestProto",
16800b57cec5SDimitry Andric           },
1681fe6060f1SDimitry Andric           /*CanonicalDelimiter=*/"pb",
16820b57cec5SDimitry Andric           /*BasedOnStyle=*/"google",
16830b57cec5SDimitry Andric       },
16840b57cec5SDimitry Andric   };
1685cb14a3feSDimitry Andric 
16860b57cec5SDimitry Andric   GoogleStyle.SpacesBeforeTrailingComments = 2;
16870b57cec5SDimitry Andric   GoogleStyle.Standard = FormatStyle::LS_Auto;
16880b57cec5SDimitry Andric 
16890b57cec5SDimitry Andric   GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
16900b57cec5SDimitry Andric   GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;
16910b57cec5SDimitry Andric 
16920b57cec5SDimitry Andric   if (Language == FormatStyle::LK_Java) {
16930b57cec5SDimitry Andric     GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
16945ffd83dbSDimitry Andric     GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
1695bdd1243dSDimitry Andric     GoogleStyle.AlignTrailingComments = {};
1696bdd1243dSDimitry Andric     GoogleStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;
16970b57cec5SDimitry Andric     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
16980b57cec5SDimitry Andric     GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
16990b57cec5SDimitry Andric     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
17000b57cec5SDimitry Andric     GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
17010b57cec5SDimitry Andric     GoogleStyle.ColumnLimit = 100;
17020b57cec5SDimitry Andric     GoogleStyle.SpaceAfterCStyleCast = true;
17030b57cec5SDimitry Andric     GoogleStyle.SpacesBeforeTrailingComments = 1;
17040b57cec5SDimitry Andric   } else if (Language == FormatStyle::LK_JavaScript) {
17050b57cec5SDimitry Andric     GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
17065ffd83dbSDimitry Andric     GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
17070b57cec5SDimitry Andric     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
17085ffd83dbSDimitry Andric     // TODO: still under discussion whether to switch to SLS_All.
17095ffd83dbSDimitry Andric     GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
17100b57cec5SDimitry Andric     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
17110b57cec5SDimitry Andric     GoogleStyle.BreakBeforeTernaryOperators = false;
17125ffd83dbSDimitry Andric     // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is
17135ffd83dbSDimitry Andric     // commonly followed by overlong URLs.
17145ffd83dbSDimitry Andric     GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)";
17155ffd83dbSDimitry Andric     // TODO: enable once decided, in particular re disabling bin packing.
17165ffd83dbSDimitry Andric     // https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma
17175ffd83dbSDimitry Andric     // GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
17180b57cec5SDimitry Andric     GoogleStyle.MaxEmptyLinesToKeep = 3;
17190b57cec5SDimitry Andric     GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
17200b57cec5SDimitry Andric     GoogleStyle.SpacesInContainerLiterals = false;
17210b57cec5SDimitry Andric     GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single;
17220b57cec5SDimitry Andric     GoogleStyle.JavaScriptWrapImports = false;
17230b57cec5SDimitry Andric   } else if (Language == FormatStyle::LK_Proto) {
17240b57cec5SDimitry Andric     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
17250b57cec5SDimitry Andric     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
17260b57cec5SDimitry Andric     GoogleStyle.SpacesInContainerLiterals = false;
17270b57cec5SDimitry Andric     GoogleStyle.Cpp11BracedListStyle = false;
17280b57cec5SDimitry Andric     // This affects protocol buffer options specifications and text protos.
17290b57cec5SDimitry Andric     // Text protos are currently mostly formatted inside C++ raw string literals
17300b57cec5SDimitry Andric     // and often the current breaking behavior of string literals is not
17310b57cec5SDimitry Andric     // beneficial there. Investigate turning this on once proper string reflow
17320b57cec5SDimitry Andric     // has been implemented.
17330b57cec5SDimitry Andric     GoogleStyle.BreakStringLiterals = false;
17340b57cec5SDimitry Andric   } else if (Language == FormatStyle::LK_ObjC) {
17350b57cec5SDimitry Andric     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
17360b57cec5SDimitry Andric     GoogleStyle.ColumnLimit = 100;
17370b57cec5SDimitry Andric     // "Regroup" doesn't work well for ObjC yet (main header heuristic,
17380b57cec5SDimitry Andric     // relationship between ObjC standard library headers and other heades,
17390b57cec5SDimitry Andric     // #imports, etc.)
17400b57cec5SDimitry Andric     GoogleStyle.IncludeStyle.IncludeBlocks =
17410b57cec5SDimitry Andric         tooling::IncludeStyle::IBS_Preserve;
17425ffd83dbSDimitry Andric   } else if (Language == FormatStyle::LK_CSharp) {
17435ffd83dbSDimitry Andric     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
17445ffd83dbSDimitry Andric     GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
17455ffd83dbSDimitry Andric     GoogleStyle.BreakStringLiterals = false;
17465ffd83dbSDimitry Andric     GoogleStyle.ColumnLimit = 100;
17475ffd83dbSDimitry Andric     GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
17480b57cec5SDimitry Andric   }
17490b57cec5SDimitry Andric 
17500b57cec5SDimitry Andric   return GoogleStyle;
17510b57cec5SDimitry Andric }
17520b57cec5SDimitry Andric 
getChromiumStyle(FormatStyle::LanguageKind Language)17530b57cec5SDimitry Andric FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
17540b57cec5SDimitry Andric   FormatStyle ChromiumStyle = getGoogleStyle(Language);
1755a7dea167SDimitry Andric 
1756a7dea167SDimitry Andric   // Disable include reordering across blocks in Chromium code.
1757a7dea167SDimitry Andric   // - clang-format tries to detect that foo.h is the "main" header for
1758a7dea167SDimitry Andric   //   foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium
1759a7dea167SDimitry Andric   //   uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc,
1760a7dea167SDimitry Andric   //   _private.cc, _impl.cc etc) in different permutations
1761a7dea167SDimitry Andric   //   (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a
1762a7dea167SDimitry Andric   //   better default for Chromium code.
1763a7dea167SDimitry Andric   // - The default for .cc and .mm files is different (r357695) for Google style
1764a7dea167SDimitry Andric   //   for the same reason. The plan is to unify this again once the main
1765a7dea167SDimitry Andric   //   header detection works for Google's ObjC code, but this hasn't happened
1766a7dea167SDimitry Andric   //   yet. Since Chromium has some ObjC code, switching Chromium is blocked
1767a7dea167SDimitry Andric   //   on that.
1768a7dea167SDimitry Andric   // - Finally, "If include reordering is harmful, put things in different
1769a7dea167SDimitry Andric   //   blocks to prevent it" has been a recommendation for a long time that
1770a7dea167SDimitry Andric   //   people are used to. We'll need a dev education push to change this to
1771a7dea167SDimitry Andric   //   "If include reordering is harmful, put things in a different block and
1772a7dea167SDimitry Andric   //   _prepend that with a comment_ to prevent it" before changing behavior.
1773a7dea167SDimitry Andric   ChromiumStyle.IncludeStyle.IncludeBlocks =
1774a7dea167SDimitry Andric       tooling::IncludeStyle::IBS_Preserve;
1775a7dea167SDimitry Andric 
17760b57cec5SDimitry Andric   if (Language == FormatStyle::LK_Java) {
17770b57cec5SDimitry Andric     ChromiumStyle.AllowShortIfStatementsOnASingleLine =
17780b57cec5SDimitry Andric         FormatStyle::SIS_WithoutElse;
17790b57cec5SDimitry Andric     ChromiumStyle.BreakAfterJavaFieldAnnotations = true;
17800b57cec5SDimitry Andric     ChromiumStyle.ContinuationIndentWidth = 8;
17810b57cec5SDimitry Andric     ChromiumStyle.IndentWidth = 4;
17820b57cec5SDimitry Andric     // See styleguide for import groups:
1783349cc55cSDimitry Andric     // https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/java/java.md#Import-Order
17840b57cec5SDimitry Andric     ChromiumStyle.JavaImportGroups = {
17850b57cec5SDimitry Andric         "android",
17860b57cec5SDimitry Andric         "androidx",
17870b57cec5SDimitry Andric         "com",
17880b57cec5SDimitry Andric         "dalvik",
17890b57cec5SDimitry Andric         "junit",
17900b57cec5SDimitry Andric         "org",
17910b57cec5SDimitry Andric         "com.google.android.apps.chrome",
17920b57cec5SDimitry Andric         "org.chromium",
17930b57cec5SDimitry Andric         "java",
17940b57cec5SDimitry Andric         "javax",
17950b57cec5SDimitry Andric     };
1796fe6060f1SDimitry Andric     ChromiumStyle.SortIncludes = FormatStyle::SI_CaseSensitive;
17970b57cec5SDimitry Andric   } else if (Language == FormatStyle::LK_JavaScript) {
17980b57cec5SDimitry Andric     ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
17990b57cec5SDimitry Andric     ChromiumStyle.AllowShortLoopsOnASingleLine = false;
18000b57cec5SDimitry Andric   } else {
18010b57cec5SDimitry Andric     ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
18020b57cec5SDimitry Andric     ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
18030b57cec5SDimitry Andric     ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
18040b57cec5SDimitry Andric     ChromiumStyle.AllowShortLoopsOnASingleLine = false;
18050b57cec5SDimitry Andric     ChromiumStyle.BinPackParameters = false;
18060b57cec5SDimitry Andric     ChromiumStyle.DerivePointerAlignment = false;
18070b57cec5SDimitry Andric     if (Language == FormatStyle::LK_ObjC)
18080b57cec5SDimitry Andric       ChromiumStyle.ColumnLimit = 80;
18090b57cec5SDimitry Andric   }
18100b57cec5SDimitry Andric   return ChromiumStyle;
18110b57cec5SDimitry Andric }
18120b57cec5SDimitry Andric 
getMozillaStyle()18130b57cec5SDimitry Andric FormatStyle getMozillaStyle() {
18140b57cec5SDimitry Andric   FormatStyle MozillaStyle = getLLVMStyle();
18150b57cec5SDimitry Andric   MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
18160b57cec5SDimitry Andric   MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
18170b57cec5SDimitry Andric   MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel;
18180b57cec5SDimitry Andric   MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
18190b57cec5SDimitry Andric       FormatStyle::DRTBS_TopLevel;
18200b57cec5SDimitry Andric   MozillaStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
18210b57cec5SDimitry Andric   MozillaStyle.BinPackParameters = false;
18220b57cec5SDimitry Andric   MozillaStyle.BinPackArguments = false;
18230b57cec5SDimitry Andric   MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
18240b57cec5SDimitry Andric   MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
18250b57cec5SDimitry Andric   MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
18260b57cec5SDimitry Andric   MozillaStyle.ConstructorInitializerIndentWidth = 2;
18270b57cec5SDimitry Andric   MozillaStyle.ContinuationIndentWidth = 2;
18280b57cec5SDimitry Andric   MozillaStyle.Cpp11BracedListStyle = false;
18290b57cec5SDimitry Andric   MozillaStyle.FixNamespaceComments = false;
18300b57cec5SDimitry Andric   MozillaStyle.IndentCaseLabels = true;
18310b57cec5SDimitry Andric   MozillaStyle.ObjCSpaceAfterProperty = true;
18320b57cec5SDimitry Andric   MozillaStyle.ObjCSpaceBeforeProtocolList = false;
18330b57cec5SDimitry Andric   MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
18340b57cec5SDimitry Andric   MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
18350b57cec5SDimitry Andric   MozillaStyle.SpaceAfterTemplateKeyword = false;
18360b57cec5SDimitry Andric   return MozillaStyle;
18370b57cec5SDimitry Andric }
18380b57cec5SDimitry Andric 
getWebKitStyle()18390b57cec5SDimitry Andric FormatStyle getWebKitStyle() {
18400b57cec5SDimitry Andric   FormatStyle Style = getLLVMStyle();
18410b57cec5SDimitry Andric   Style.AccessModifierOffset = -4;
18420b57cec5SDimitry Andric   Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
18435ffd83dbSDimitry Andric   Style.AlignOperands = FormatStyle::OAS_DontAlign;
1844bdd1243dSDimitry Andric   Style.AlignTrailingComments = {};
1845bdd1243dSDimitry Andric   Style.AlignTrailingComments.Kind = FormatStyle::TCAS_Never;
1846a7dea167SDimitry Andric   Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;
18470b57cec5SDimitry Andric   Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
18480b57cec5SDimitry Andric   Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
18490b57cec5SDimitry Andric   Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
18500b57cec5SDimitry Andric   Style.Cpp11BracedListStyle = false;
18510b57cec5SDimitry Andric   Style.ColumnLimit = 0;
18520b57cec5SDimitry Andric   Style.FixNamespaceComments = false;
18530b57cec5SDimitry Andric   Style.IndentWidth = 4;
18540b57cec5SDimitry Andric   Style.NamespaceIndentation = FormatStyle::NI_Inner;
18550b57cec5SDimitry Andric   Style.ObjCBlockIndentWidth = 4;
18560b57cec5SDimitry Andric   Style.ObjCSpaceAfterProperty = true;
18570b57cec5SDimitry Andric   Style.PointerAlignment = FormatStyle::PAS_Left;
18580b57cec5SDimitry Andric   Style.SpaceBeforeCpp11BracedList = true;
1859a7dea167SDimitry Andric   Style.SpaceInEmptyBlock = true;
18600b57cec5SDimitry Andric   return Style;
18610b57cec5SDimitry Andric }
18620b57cec5SDimitry Andric 
getGNUStyle()18630b57cec5SDimitry Andric FormatStyle getGNUStyle() {
18640b57cec5SDimitry Andric   FormatStyle Style = getLLVMStyle();
18650b57cec5SDimitry Andric   Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
18660b57cec5SDimitry Andric   Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
18670b57cec5SDimitry Andric   Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
18680b57cec5SDimitry Andric   Style.BreakBeforeBraces = FormatStyle::BS_GNU;
18690b57cec5SDimitry Andric   Style.BreakBeforeTernaryOperators = true;
18700b57cec5SDimitry Andric   Style.Cpp11BracedListStyle = false;
18710b57cec5SDimitry Andric   Style.ColumnLimit = 79;
18720b57cec5SDimitry Andric   Style.FixNamespaceComments = false;
18730b57cec5SDimitry Andric   Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
18740b57cec5SDimitry Andric   Style.Standard = FormatStyle::LS_Cpp03;
18750b57cec5SDimitry Andric   return Style;
18760b57cec5SDimitry Andric }
18770b57cec5SDimitry Andric 
getMicrosoftStyle(FormatStyle::LanguageKind Language)18780b57cec5SDimitry Andric FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) {
1879a7dea167SDimitry Andric   FormatStyle Style = getLLVMStyle(Language);
18800b57cec5SDimitry Andric   Style.ColumnLimit = 120;
18810b57cec5SDimitry Andric   Style.TabWidth = 4;
18820b57cec5SDimitry Andric   Style.IndentWidth = 4;
18830b57cec5SDimitry Andric   Style.UseTab = FormatStyle::UT_Never;
18840b57cec5SDimitry Andric   Style.BreakBeforeBraces = FormatStyle::BS_Custom;
18850b57cec5SDimitry Andric   Style.BraceWrapping.AfterClass = true;
1886a7dea167SDimitry Andric   Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
18870b57cec5SDimitry Andric   Style.BraceWrapping.AfterEnum = true;
18880b57cec5SDimitry Andric   Style.BraceWrapping.AfterFunction = true;
18890b57cec5SDimitry Andric   Style.BraceWrapping.AfterNamespace = true;
18900b57cec5SDimitry Andric   Style.BraceWrapping.AfterObjCDeclaration = true;
18910b57cec5SDimitry Andric   Style.BraceWrapping.AfterStruct = true;
18920b57cec5SDimitry Andric   Style.BraceWrapping.AfterExternBlock = true;
18930b57cec5SDimitry Andric   Style.BraceWrapping.BeforeCatch = true;
18940b57cec5SDimitry Andric   Style.BraceWrapping.BeforeElse = true;
18955ffd83dbSDimitry Andric   Style.BraceWrapping.BeforeWhile = false;
18960b57cec5SDimitry Andric   Style.PenaltyReturnTypeOnItsOwnLine = 1000;
18975ffd83dbSDimitry Andric   Style.AllowShortEnumsOnASingleLine = false;
18980b57cec5SDimitry Andric   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
18990b57cec5SDimitry Andric   Style.AllowShortCaseLabelsOnASingleLine = false;
19000b57cec5SDimitry Andric   Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
19010b57cec5SDimitry Andric   Style.AllowShortLoopsOnASingleLine = false;
1902a7dea167SDimitry Andric   Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
1903a7dea167SDimitry Andric   Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
19040b57cec5SDimitry Andric   return Style;
19050b57cec5SDimitry Andric }
19060b57cec5SDimitry Andric 
getClangFormatStyle()19075f757f3fSDimitry Andric FormatStyle getClangFormatStyle() {
19085f757f3fSDimitry Andric   FormatStyle Style = getLLVMStyle();
19095f757f3fSDimitry Andric   Style.InsertBraces = true;
19105f757f3fSDimitry Andric   Style.InsertNewlineAtEOF = true;
19115f757f3fSDimitry Andric   Style.LineEnding = FormatStyle::LE_LF;
19125f757f3fSDimitry Andric   Style.RemoveBracesLLVM = true;
19135f757f3fSDimitry Andric   Style.RemoveParentheses = FormatStyle::RPS_ReturnStatement;
19145f757f3fSDimitry Andric   return Style;
19155f757f3fSDimitry Andric }
19165f757f3fSDimitry Andric 
getNoStyle()19170b57cec5SDimitry Andric FormatStyle getNoStyle() {
19180b57cec5SDimitry Andric   FormatStyle NoStyle = getLLVMStyle();
19190b57cec5SDimitry Andric   NoStyle.DisableFormat = true;
1920fe6060f1SDimitry Andric   NoStyle.SortIncludes = FormatStyle::SI_Never;
1921bdd1243dSDimitry Andric   NoStyle.SortUsingDeclarations = FormatStyle::SUD_Never;
19220b57cec5SDimitry Andric   return NoStyle;
19230b57cec5SDimitry Andric }
19240b57cec5SDimitry Andric 
getPredefinedStyle(StringRef Name,FormatStyle::LanguageKind Language,FormatStyle * Style)19250b57cec5SDimitry Andric bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
19260b57cec5SDimitry Andric                         FormatStyle *Style) {
192781ad6265SDimitry Andric   if (Name.equals_insensitive("llvm"))
19280b57cec5SDimitry Andric     *Style = getLLVMStyle(Language);
192981ad6265SDimitry Andric   else if (Name.equals_insensitive("chromium"))
19300b57cec5SDimitry Andric     *Style = getChromiumStyle(Language);
193181ad6265SDimitry Andric   else if (Name.equals_insensitive("mozilla"))
19320b57cec5SDimitry Andric     *Style = getMozillaStyle();
193381ad6265SDimitry Andric   else if (Name.equals_insensitive("google"))
19340b57cec5SDimitry Andric     *Style = getGoogleStyle(Language);
193581ad6265SDimitry Andric   else if (Name.equals_insensitive("webkit"))
19360b57cec5SDimitry Andric     *Style = getWebKitStyle();
193781ad6265SDimitry Andric   else if (Name.equals_insensitive("gnu"))
19380b57cec5SDimitry Andric     *Style = getGNUStyle();
193981ad6265SDimitry Andric   else if (Name.equals_insensitive("microsoft"))
19400b57cec5SDimitry Andric     *Style = getMicrosoftStyle(Language);
19415f757f3fSDimitry Andric   else if (Name.equals_insensitive("clang-format"))
19425f757f3fSDimitry Andric     *Style = getClangFormatStyle();
194381ad6265SDimitry Andric   else if (Name.equals_insensitive("none"))
19440b57cec5SDimitry Andric     *Style = getNoStyle();
194581ad6265SDimitry Andric   else if (Name.equals_insensitive("inheritparentconfig"))
1946fe6060f1SDimitry Andric     Style->InheritsParentConfig = true;
194781ad6265SDimitry Andric   else
19480b57cec5SDimitry Andric     return false;
19490b57cec5SDimitry Andric 
19500b57cec5SDimitry Andric   Style->Language = Language;
19510b57cec5SDimitry Andric   return true;
19520b57cec5SDimitry Andric }
19530b57cec5SDimitry Andric 
validateQualifierOrder(FormatStyle * Style)1954349cc55cSDimitry Andric ParseError validateQualifierOrder(FormatStyle *Style) {
1955349cc55cSDimitry Andric   // If its empty then it means don't do anything.
1956349cc55cSDimitry Andric   if (Style->QualifierOrder.empty())
1957349cc55cSDimitry Andric     return ParseError::MissingQualifierOrder;
1958349cc55cSDimitry Andric 
1959349cc55cSDimitry Andric   // Ensure the list contains only currently valid qualifiers.
1960349cc55cSDimitry Andric   for (const auto &Qualifier : Style->QualifierOrder) {
1961349cc55cSDimitry Andric     if (Qualifier == "type")
1962349cc55cSDimitry Andric       continue;
1963349cc55cSDimitry Andric     auto token =
1964349cc55cSDimitry Andric         LeftRightQualifierAlignmentFixer::getTokenFromQualifier(Qualifier);
1965349cc55cSDimitry Andric     if (token == tok::identifier)
1966349cc55cSDimitry Andric       return ParseError::InvalidQualifierSpecified;
1967349cc55cSDimitry Andric   }
196881ad6265SDimitry Andric 
196981ad6265SDimitry Andric   // Ensure the list is unique (no duplicates).
1970349cc55cSDimitry Andric   std::set<std::string> UniqueQualifiers(Style->QualifierOrder.begin(),
1971349cc55cSDimitry Andric                                          Style->QualifierOrder.end());
1972349cc55cSDimitry Andric   if (Style->QualifierOrder.size() != UniqueQualifiers.size()) {
1973349cc55cSDimitry Andric     LLVM_DEBUG(llvm::dbgs()
1974349cc55cSDimitry Andric                << "Duplicate Qualifiers " << Style->QualifierOrder.size()
1975349cc55cSDimitry Andric                << " vs " << UniqueQualifiers.size() << "\n");
1976349cc55cSDimitry Andric     return ParseError::DuplicateQualifierSpecified;
1977349cc55cSDimitry Andric   }
1978349cc55cSDimitry Andric 
197981ad6265SDimitry Andric   // Ensure the list has 'type' in it.
1980bdd1243dSDimitry Andric   if (!llvm::is_contained(Style->QualifierOrder, "type"))
1981349cc55cSDimitry Andric     return ParseError::MissingQualifierType;
198281ad6265SDimitry Andric 
1983349cc55cSDimitry Andric   return ParseError::Success;
1984349cc55cSDimitry Andric }
1985349cc55cSDimitry Andric 
parseConfiguration(llvm::MemoryBufferRef Config,FormatStyle * Style,bool AllowUnknownOptions,llvm::SourceMgr::DiagHandlerTy DiagHandler,void * DiagHandlerCtxt)1986e8d8bef9SDimitry Andric std::error_code parseConfiguration(llvm::MemoryBufferRef Config,
1987fe6060f1SDimitry Andric                                    FormatStyle *Style, bool AllowUnknownOptions,
1988fe6060f1SDimitry Andric                                    llvm::SourceMgr::DiagHandlerTy DiagHandler,
1989fe6060f1SDimitry Andric                                    void *DiagHandlerCtxt) {
19900b57cec5SDimitry Andric   assert(Style);
19910b57cec5SDimitry Andric   FormatStyle::LanguageKind Language = Style->Language;
19920b57cec5SDimitry Andric   assert(Language != FormatStyle::LK_None);
1993e8d8bef9SDimitry Andric   if (Config.getBuffer().trim().empty())
199481ad6265SDimitry Andric     return make_error_code(ParseError::Success);
19950b57cec5SDimitry Andric   Style->StyleSet.Clear();
19960b57cec5SDimitry Andric   std::vector<FormatStyle> Styles;
1997fe6060f1SDimitry Andric   llvm::yaml::Input Input(Config, /*Ctxt=*/nullptr, DiagHandler,
1998fe6060f1SDimitry Andric                           DiagHandlerCtxt);
19990b57cec5SDimitry Andric   // DocumentListTraits<vector<FormatStyle>> uses the context to get default
20000b57cec5SDimitry Andric   // values for the fields, keys for which are missing from the configuration.
20010b57cec5SDimitry Andric   // Mapping also uses the context to get the language to find the correct
20020b57cec5SDimitry Andric   // base style.
20030b57cec5SDimitry Andric   Input.setContext(Style);
2004e8d8bef9SDimitry Andric   Input.setAllowUnknownKeys(AllowUnknownOptions);
20050b57cec5SDimitry Andric   Input >> Styles;
20060b57cec5SDimitry Andric   if (Input.error())
20070b57cec5SDimitry Andric     return Input.error();
20080b57cec5SDimitry Andric 
20090b57cec5SDimitry Andric   for (unsigned i = 0; i < Styles.size(); ++i) {
20100b57cec5SDimitry Andric     // Ensures that only the first configuration can skip the Language option.
20110b57cec5SDimitry Andric     if (Styles[i].Language == FormatStyle::LK_None && i != 0)
20120b57cec5SDimitry Andric       return make_error_code(ParseError::Error);
20130b57cec5SDimitry Andric     // Ensure that each language is configured at most once.
20140b57cec5SDimitry Andric     for (unsigned j = 0; j < i; ++j) {
20150b57cec5SDimitry Andric       if (Styles[i].Language == Styles[j].Language) {
20160b57cec5SDimitry Andric         LLVM_DEBUG(llvm::dbgs()
20170b57cec5SDimitry Andric                    << "Duplicate languages in the config file on positions "
20180b57cec5SDimitry Andric                    << j << " and " << i << "\n");
20190b57cec5SDimitry Andric         return make_error_code(ParseError::Error);
20200b57cec5SDimitry Andric       }
20210b57cec5SDimitry Andric     }
20220b57cec5SDimitry Andric   }
20230b57cec5SDimitry Andric   // Look for a suitable configuration starting from the end, so we can
20240b57cec5SDimitry Andric   // find the configuration for the specific language first, and the default
20250b57cec5SDimitry Andric   // configuration (which can only be at slot 0) after it.
20260b57cec5SDimitry Andric   FormatStyle::FormatStyleSet StyleSet;
20270b57cec5SDimitry Andric   bool LanguageFound = false;
20281fd87a68SDimitry Andric   for (const FormatStyle &Style : llvm::reverse(Styles)) {
20291fd87a68SDimitry Andric     if (Style.Language != FormatStyle::LK_None)
20301fd87a68SDimitry Andric       StyleSet.Add(Style);
20311fd87a68SDimitry Andric     if (Style.Language == Language)
20320b57cec5SDimitry Andric       LanguageFound = true;
20330b57cec5SDimitry Andric   }
20340b57cec5SDimitry Andric   if (!LanguageFound) {
20350b57cec5SDimitry Andric     if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None)
20360b57cec5SDimitry Andric       return make_error_code(ParseError::Unsuitable);
20370b57cec5SDimitry Andric     FormatStyle DefaultStyle = Styles[0];
20380b57cec5SDimitry Andric     DefaultStyle.Language = Language;
20390b57cec5SDimitry Andric     StyleSet.Add(std::move(DefaultStyle));
20400b57cec5SDimitry Andric   }
20410b57cec5SDimitry Andric   *Style = *StyleSet.Get(Language);
20425ffd83dbSDimitry Andric   if (Style->InsertTrailingCommas != FormatStyle::TCS_None &&
20435ffd83dbSDimitry Andric       Style->BinPackArguments) {
20445ffd83dbSDimitry Andric     // See comment on FormatStyle::TSC_Wrapped.
20455ffd83dbSDimitry Andric     return make_error_code(ParseError::BinPackTrailingCommaConflict);
20465ffd83dbSDimitry Andric   }
2047349cc55cSDimitry Andric   if (Style->QualifierAlignment != FormatStyle::QAS_Leave)
2048349cc55cSDimitry Andric     return make_error_code(validateQualifierOrder(Style));
20490b57cec5SDimitry Andric   return make_error_code(ParseError::Success);
20500b57cec5SDimitry Andric }
20510b57cec5SDimitry Andric 
configurationAsText(const FormatStyle & Style)20520b57cec5SDimitry Andric std::string configurationAsText(const FormatStyle &Style) {
20530b57cec5SDimitry Andric   std::string Text;
20540b57cec5SDimitry Andric   llvm::raw_string_ostream Stream(Text);
20550b57cec5SDimitry Andric   llvm::yaml::Output Output(Stream);
20560b57cec5SDimitry Andric   // We use the same mapping method for input and output, so we need a non-const
20570b57cec5SDimitry Andric   // reference here.
2058349cc55cSDimitry Andric   FormatStyle NonConstStyle = Style;
2059349cc55cSDimitry Andric   expandPresetsBraceWrapping(NonConstStyle);
2060349cc55cSDimitry Andric   expandPresetsSpaceBeforeParens(NonConstStyle);
206106c3fb27SDimitry Andric   expandPresetsSpacesInParens(NonConstStyle);
20620b57cec5SDimitry Andric   Output << NonConstStyle;
2063349cc55cSDimitry Andric 
20640b57cec5SDimitry Andric   return Stream.str();
20650b57cec5SDimitry Andric }
20660b57cec5SDimitry Andric 
2067bdd1243dSDimitry Andric std::optional<FormatStyle>
Get(FormatStyle::LanguageKind Language) const20680b57cec5SDimitry Andric FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {
20690b57cec5SDimitry Andric   if (!Styles)
2070bdd1243dSDimitry Andric     return std::nullopt;
20710b57cec5SDimitry Andric   auto It = Styles->find(Language);
20720b57cec5SDimitry Andric   if (It == Styles->end())
2073bdd1243dSDimitry Andric     return std::nullopt;
20740b57cec5SDimitry Andric   FormatStyle Style = It->second;
20750b57cec5SDimitry Andric   Style.StyleSet = *this;
20760b57cec5SDimitry Andric   return Style;
20770b57cec5SDimitry Andric }
20780b57cec5SDimitry Andric 
Add(FormatStyle Style)20790b57cec5SDimitry Andric void FormatStyle::FormatStyleSet::Add(FormatStyle Style) {
20800b57cec5SDimitry Andric   assert(Style.Language != LK_None &&
20810b57cec5SDimitry Andric          "Cannot add a style for LK_None to a StyleSet");
20820b57cec5SDimitry Andric   assert(
20830b57cec5SDimitry Andric       !Style.StyleSet.Styles &&
20840b57cec5SDimitry Andric       "Cannot add a style associated with an existing StyleSet to a StyleSet");
20850b57cec5SDimitry Andric   if (!Styles)
20860b57cec5SDimitry Andric     Styles = std::make_shared<MapType>();
20870b57cec5SDimitry Andric   (*Styles)[Style.Language] = std::move(Style);
20880b57cec5SDimitry Andric }
20890b57cec5SDimitry Andric 
Clear()20900b57cec5SDimitry Andric void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); }
20910b57cec5SDimitry Andric 
2092bdd1243dSDimitry Andric std::optional<FormatStyle>
GetLanguageStyle(FormatStyle::LanguageKind Language) const20930b57cec5SDimitry Andric FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {
20940b57cec5SDimitry Andric   return StyleSet.Get(Language);
20950b57cec5SDimitry Andric }
20960b57cec5SDimitry Andric 
20970b57cec5SDimitry Andric namespace {
20980b57cec5SDimitry Andric 
209906c3fb27SDimitry Andric class ParensRemover : public TokenAnalyzer {
210006c3fb27SDimitry Andric public:
ParensRemover(const Environment & Env,const FormatStyle & Style)210106c3fb27SDimitry Andric   ParensRemover(const Environment &Env, const FormatStyle &Style)
210206c3fb27SDimitry Andric       : TokenAnalyzer(Env, Style) {}
210306c3fb27SDimitry Andric 
210406c3fb27SDimitry Andric   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)210506c3fb27SDimitry Andric   analyze(TokenAnnotator &Annotator,
210606c3fb27SDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
210706c3fb27SDimitry Andric           FormatTokenLexer &Tokens) override {
210806c3fb27SDimitry Andric     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
210906c3fb27SDimitry Andric     tooling::Replacements Result;
211006c3fb27SDimitry Andric     removeParens(AnnotatedLines, Result);
211106c3fb27SDimitry Andric     return {Result, 0};
211206c3fb27SDimitry Andric   }
211306c3fb27SDimitry Andric 
211406c3fb27SDimitry Andric private:
removeParens(SmallVectorImpl<AnnotatedLine * > & Lines,tooling::Replacements & Result)211506c3fb27SDimitry Andric   void removeParens(SmallVectorImpl<AnnotatedLine *> &Lines,
211606c3fb27SDimitry Andric                     tooling::Replacements &Result) {
211706c3fb27SDimitry Andric     const auto &SourceMgr = Env.getSourceManager();
211806c3fb27SDimitry Andric     for (auto *Line : Lines) {
211906c3fb27SDimitry Andric       removeParens(Line->Children, Result);
212006c3fb27SDimitry Andric       if (!Line->Affected)
212106c3fb27SDimitry Andric         continue;
212206c3fb27SDimitry Andric       for (const auto *Token = Line->First; Token && !Token->Finalized;
212306c3fb27SDimitry Andric            Token = Token->Next) {
212406c3fb27SDimitry Andric         if (!Token->Optional || !Token->isOneOf(tok::l_paren, tok::r_paren))
212506c3fb27SDimitry Andric           continue;
212606c3fb27SDimitry Andric         auto *Next = Token->Next;
212706c3fb27SDimitry Andric         assert(Next && Next->isNot(tok::eof));
212806c3fb27SDimitry Andric         SourceLocation Start;
212906c3fb27SDimitry Andric         if (Next->NewlinesBefore == 0) {
213006c3fb27SDimitry Andric           Start = Token->Tok.getLocation();
213106c3fb27SDimitry Andric           Next->WhitespaceRange = Token->WhitespaceRange;
213206c3fb27SDimitry Andric         } else {
213306c3fb27SDimitry Andric           Start = Token->WhitespaceRange.getBegin();
213406c3fb27SDimitry Andric         }
213506c3fb27SDimitry Andric         const auto &Range =
213606c3fb27SDimitry Andric             CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
213706c3fb27SDimitry Andric         cantFail(Result.add(tooling::Replacement(SourceMgr, Range, " ")));
213806c3fb27SDimitry Andric       }
213906c3fb27SDimitry Andric     }
214006c3fb27SDimitry Andric   }
214106c3fb27SDimitry Andric };
214206c3fb27SDimitry Andric 
214381ad6265SDimitry Andric class BracesInserter : public TokenAnalyzer {
214481ad6265SDimitry Andric public:
BracesInserter(const Environment & Env,const FormatStyle & Style)214581ad6265SDimitry Andric   BracesInserter(const Environment &Env, const FormatStyle &Style)
2146bdd1243dSDimitry Andric       : TokenAnalyzer(Env, Style) {}
214781ad6265SDimitry Andric 
214881ad6265SDimitry Andric   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)214981ad6265SDimitry Andric   analyze(TokenAnnotator &Annotator,
215081ad6265SDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
215181ad6265SDimitry Andric           FormatTokenLexer &Tokens) override {
215281ad6265SDimitry Andric     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
215381ad6265SDimitry Andric     tooling::Replacements Result;
215481ad6265SDimitry Andric     insertBraces(AnnotatedLines, Result);
215581ad6265SDimitry Andric     return {Result, 0};
215681ad6265SDimitry Andric   }
215781ad6265SDimitry Andric 
215881ad6265SDimitry Andric private:
insertBraces(SmallVectorImpl<AnnotatedLine * > & Lines,tooling::Replacements & Result)215981ad6265SDimitry Andric   void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
216081ad6265SDimitry Andric                     tooling::Replacements &Result) {
216181ad6265SDimitry Andric     const auto &SourceMgr = Env.getSourceManager();
2162bdd1243dSDimitry Andric     int OpeningBraceSurplus = 0;
216381ad6265SDimitry Andric     for (AnnotatedLine *Line : Lines) {
216481ad6265SDimitry Andric       insertBraces(Line->Children, Result);
2165bdd1243dSDimitry Andric       if (!Line->Affected && OpeningBraceSurplus == 0)
216681ad6265SDimitry Andric         continue;
216781ad6265SDimitry Andric       for (FormatToken *Token = Line->First; Token && !Token->Finalized;
216881ad6265SDimitry Andric            Token = Token->Next) {
2169bdd1243dSDimitry Andric         int BraceCount = Token->BraceCount;
2170bdd1243dSDimitry Andric         if (BraceCount == 0)
217181ad6265SDimitry Andric           continue;
217281ad6265SDimitry Andric         std::string Brace;
2173bdd1243dSDimitry Andric         if (BraceCount < 0) {
2174bdd1243dSDimitry Andric           assert(BraceCount == -1);
2175bdd1243dSDimitry Andric           if (!Line->Affected)
2176bdd1243dSDimitry Andric             break;
2177bdd1243dSDimitry Andric           Brace = Token->is(tok::comment) ? "\n{" : "{";
2178bdd1243dSDimitry Andric           ++OpeningBraceSurplus;
217981ad6265SDimitry Andric         } else {
2180bdd1243dSDimitry Andric           if (OpeningBraceSurplus == 0)
2181bdd1243dSDimitry Andric             break;
2182bdd1243dSDimitry Andric           if (OpeningBraceSurplus < BraceCount)
2183bdd1243dSDimitry Andric             BraceCount = OpeningBraceSurplus;
2184bdd1243dSDimitry Andric           Brace = '\n' + std::string(BraceCount, '}');
2185bdd1243dSDimitry Andric           OpeningBraceSurplus -= BraceCount;
218681ad6265SDimitry Andric         }
218781ad6265SDimitry Andric         Token->BraceCount = 0;
218881ad6265SDimitry Andric         const auto Start = Token->Tok.getEndLoc();
218981ad6265SDimitry Andric         cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0, Brace)));
219081ad6265SDimitry Andric       }
219181ad6265SDimitry Andric     }
2192bdd1243dSDimitry Andric     assert(OpeningBraceSurplus == 0);
219381ad6265SDimitry Andric   }
219481ad6265SDimitry Andric };
219581ad6265SDimitry Andric 
219604eeddc0SDimitry Andric class BracesRemover : public TokenAnalyzer {
219704eeddc0SDimitry Andric public:
BracesRemover(const Environment & Env,const FormatStyle & Style)219804eeddc0SDimitry Andric   BracesRemover(const Environment &Env, const FormatStyle &Style)
2199bdd1243dSDimitry Andric       : TokenAnalyzer(Env, Style) {}
220004eeddc0SDimitry Andric 
220104eeddc0SDimitry Andric   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)220204eeddc0SDimitry Andric   analyze(TokenAnnotator &Annotator,
220304eeddc0SDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
220404eeddc0SDimitry Andric           FormatTokenLexer &Tokens) override {
220504eeddc0SDimitry Andric     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
220604eeddc0SDimitry Andric     tooling::Replacements Result;
220704eeddc0SDimitry Andric     removeBraces(AnnotatedLines, Result);
220804eeddc0SDimitry Andric     return {Result, 0};
220904eeddc0SDimitry Andric   }
221004eeddc0SDimitry Andric 
221104eeddc0SDimitry Andric private:
removeBraces(SmallVectorImpl<AnnotatedLine * > & Lines,tooling::Replacements & Result)221204eeddc0SDimitry Andric   void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
221304eeddc0SDimitry Andric                     tooling::Replacements &Result) {
221404eeddc0SDimitry Andric     const auto &SourceMgr = Env.getSourceManager();
2215bdd1243dSDimitry Andric     const auto End = Lines.end();
2216bdd1243dSDimitry Andric     for (auto I = Lines.begin(); I != End; ++I) {
2217bdd1243dSDimitry Andric       const auto Line = *I;
221804eeddc0SDimitry Andric       removeBraces(Line->Children, Result);
2219bdd1243dSDimitry Andric       if (!Line->Affected)
2220bdd1243dSDimitry Andric         continue;
2221bdd1243dSDimitry Andric       const auto NextLine = I + 1 == End ? nullptr : I[1];
2222bdd1243dSDimitry Andric       for (auto Token = Line->First; Token && !Token->Finalized;
222381ad6265SDimitry Andric            Token = Token->Next) {
222404eeddc0SDimitry Andric         if (!Token->Optional)
222504eeddc0SDimitry Andric           continue;
2226bdd1243dSDimitry Andric         if (!Token->isOneOf(tok::l_brace, tok::r_brace))
2227bdd1243dSDimitry Andric           continue;
2228bdd1243dSDimitry Andric         auto Next = Token->Next;
2229fcaf7f86SDimitry Andric         assert(Next || Token == Line->Last);
2230bdd1243dSDimitry Andric         if (!Next && NextLine)
2231bdd1243dSDimitry Andric           Next = NextLine->First;
2232bdd1243dSDimitry Andric         SourceLocation Start;
2233bdd1243dSDimitry Andric         if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2234bdd1243dSDimitry Andric           Start = Token->Tok.getLocation();
2235bdd1243dSDimitry Andric           Next->WhitespaceRange = Token->WhitespaceRange;
2236bdd1243dSDimitry Andric         } else {
2237bdd1243dSDimitry Andric           Start = Token->WhitespaceRange.getBegin();
2238bdd1243dSDimitry Andric         }
223904eeddc0SDimitry Andric         const auto Range =
224004eeddc0SDimitry Andric             CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
224104eeddc0SDimitry Andric         cantFail(Result.add(tooling::Replacement(SourceMgr, Range, "")));
224204eeddc0SDimitry Andric       }
224304eeddc0SDimitry Andric     }
2244bdd1243dSDimitry Andric   }
2245bdd1243dSDimitry Andric };
2246bdd1243dSDimitry Andric 
2247bdd1243dSDimitry Andric class SemiRemover : public TokenAnalyzer {
2248bdd1243dSDimitry Andric public:
SemiRemover(const Environment & Env,const FormatStyle & Style)2249bdd1243dSDimitry Andric   SemiRemover(const Environment &Env, const FormatStyle &Style)
2250bdd1243dSDimitry Andric       : TokenAnalyzer(Env, Style) {}
2251bdd1243dSDimitry Andric 
2252bdd1243dSDimitry Andric   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)2253bdd1243dSDimitry Andric   analyze(TokenAnnotator &Annotator,
2254bdd1243dSDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2255bdd1243dSDimitry Andric           FormatTokenLexer &Tokens) override {
2256bdd1243dSDimitry Andric     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2257bdd1243dSDimitry Andric     tooling::Replacements Result;
2258bdd1243dSDimitry Andric     removeSemi(AnnotatedLines, Result);
2259bdd1243dSDimitry Andric     return {Result, 0};
2260bdd1243dSDimitry Andric   }
2261bdd1243dSDimitry Andric 
2262bdd1243dSDimitry Andric private:
removeSemi(SmallVectorImpl<AnnotatedLine * > & Lines,tooling::Replacements & Result)2263bdd1243dSDimitry Andric   void removeSemi(SmallVectorImpl<AnnotatedLine *> &Lines,
2264bdd1243dSDimitry Andric                   tooling::Replacements &Result) {
2265bdd1243dSDimitry Andric     const auto &SourceMgr = Env.getSourceManager();
2266bdd1243dSDimitry Andric     const auto End = Lines.end();
2267bdd1243dSDimitry Andric     for (auto I = Lines.begin(); I != End; ++I) {
2268bdd1243dSDimitry Andric       const auto Line = *I;
2269bdd1243dSDimitry Andric       removeSemi(Line->Children, Result);
2270bdd1243dSDimitry Andric       if (!Line->Affected)
2271bdd1243dSDimitry Andric         continue;
2272bdd1243dSDimitry Andric       const auto NextLine = I + 1 == End ? nullptr : I[1];
2273bdd1243dSDimitry Andric       for (auto Token = Line->First; Token && !Token->Finalized;
2274bdd1243dSDimitry Andric            Token = Token->Next) {
2275bdd1243dSDimitry Andric         if (!Token->Optional)
2276bdd1243dSDimitry Andric           continue;
2277bdd1243dSDimitry Andric         if (Token->isNot(tok::semi))
2278bdd1243dSDimitry Andric           continue;
2279bdd1243dSDimitry Andric         auto Next = Token->Next;
2280bdd1243dSDimitry Andric         assert(Next || Token == Line->Last);
2281bdd1243dSDimitry Andric         if (!Next && NextLine)
2282bdd1243dSDimitry Andric           Next = NextLine->First;
2283bdd1243dSDimitry Andric         SourceLocation Start;
2284bdd1243dSDimitry Andric         if (Next && Next->NewlinesBefore == 0 && Next->isNot(tok::eof)) {
2285bdd1243dSDimitry Andric           Start = Token->Tok.getLocation();
2286bdd1243dSDimitry Andric           Next->WhitespaceRange = Token->WhitespaceRange;
2287bdd1243dSDimitry Andric         } else {
2288bdd1243dSDimitry Andric           Start = Token->WhitespaceRange.getBegin();
2289bdd1243dSDimitry Andric         }
2290bdd1243dSDimitry Andric         const auto Range =
2291bdd1243dSDimitry Andric             CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
2292bdd1243dSDimitry Andric         cantFail(Result.add(tooling::Replacement(SourceMgr, Range, "")));
2293bdd1243dSDimitry Andric       }
2294fcaf7f86SDimitry Andric     }
229504eeddc0SDimitry Andric   }
229604eeddc0SDimitry Andric };
229704eeddc0SDimitry Andric 
22980b57cec5SDimitry Andric class JavaScriptRequoter : public TokenAnalyzer {
22990b57cec5SDimitry Andric public:
JavaScriptRequoter(const Environment & Env,const FormatStyle & Style)23000b57cec5SDimitry Andric   JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)
23010b57cec5SDimitry Andric       : TokenAnalyzer(Env, Style) {}
23020b57cec5SDimitry Andric 
23030b57cec5SDimitry Andric   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)23040b57cec5SDimitry Andric   analyze(TokenAnnotator &Annotator,
23050b57cec5SDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
23060b57cec5SDimitry Andric           FormatTokenLexer &Tokens) override {
23070b57cec5SDimitry Andric     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
23080b57cec5SDimitry Andric     tooling::Replacements Result;
23090b57cec5SDimitry Andric     requoteJSStringLiteral(AnnotatedLines, Result);
23100b57cec5SDimitry Andric     return {Result, 0};
23110b57cec5SDimitry Andric   }
23120b57cec5SDimitry Andric 
23130b57cec5SDimitry Andric private:
23140b57cec5SDimitry Andric   // Replaces double/single-quoted string literal as appropriate, re-escaping
23150b57cec5SDimitry Andric   // the contents in the process.
requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine * > & Lines,tooling::Replacements & Result)23160b57cec5SDimitry Andric   void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
23170b57cec5SDimitry Andric                               tooling::Replacements &Result) {
23180b57cec5SDimitry Andric     for (AnnotatedLine *Line : Lines) {
23190b57cec5SDimitry Andric       requoteJSStringLiteral(Line->Children, Result);
23200b57cec5SDimitry Andric       if (!Line->Affected)
23210b57cec5SDimitry Andric         continue;
23220b57cec5SDimitry Andric       for (FormatToken *FormatTok = Line->First; FormatTok;
23230b57cec5SDimitry Andric            FormatTok = FormatTok->Next) {
23240b57cec5SDimitry Andric         StringRef Input = FormatTok->TokenText;
23250b57cec5SDimitry Andric         if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
23260b57cec5SDimitry Andric             // NB: testing for not starting with a double quote to avoid
23270b57cec5SDimitry Andric             // breaking `template strings`.
23280b57cec5SDimitry Andric             (Style.JavaScriptQuotes == FormatStyle::JSQS_Single &&
23295f757f3fSDimitry Andric              !Input.starts_with("\"")) ||
23300b57cec5SDimitry Andric             (Style.JavaScriptQuotes == FormatStyle::JSQS_Double &&
23315f757f3fSDimitry Andric              !Input.starts_with("\'"))) {
23320b57cec5SDimitry Andric           continue;
233381ad6265SDimitry Andric         }
23340b57cec5SDimitry Andric 
23350b57cec5SDimitry Andric         // Change start and end quote.
23360b57cec5SDimitry Andric         bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single;
23370b57cec5SDimitry Andric         SourceLocation Start = FormatTok->Tok.getLocation();
23380b57cec5SDimitry Andric         auto Replace = [&](SourceLocation Start, unsigned Length,
23390b57cec5SDimitry Andric                            StringRef ReplacementText) {
23400b57cec5SDimitry Andric           auto Err = Result.add(tooling::Replacement(
23410b57cec5SDimitry Andric               Env.getSourceManager(), Start, Length, ReplacementText));
23420b57cec5SDimitry Andric           // FIXME: handle error. For now, print error message and skip the
23430b57cec5SDimitry Andric           // replacement for release version.
23440b57cec5SDimitry Andric           if (Err) {
23450b57cec5SDimitry Andric             llvm::errs() << llvm::toString(std::move(Err)) << "\n";
23460b57cec5SDimitry Andric             assert(false);
23470b57cec5SDimitry Andric           }
23480b57cec5SDimitry Andric         };
23490b57cec5SDimitry Andric         Replace(Start, 1, IsSingle ? "'" : "\"");
23500b57cec5SDimitry Andric         Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
23510b57cec5SDimitry Andric                 IsSingle ? "'" : "\"");
23520b57cec5SDimitry Andric 
23530b57cec5SDimitry Andric         // Escape internal quotes.
23540b57cec5SDimitry Andric         bool Escaped = false;
23550b57cec5SDimitry Andric         for (size_t i = 1; i < Input.size() - 1; i++) {
23560b57cec5SDimitry Andric           switch (Input[i]) {
23570b57cec5SDimitry Andric           case '\\':
23580b57cec5SDimitry Andric             if (!Escaped && i + 1 < Input.size() &&
23590b57cec5SDimitry Andric                 ((IsSingle && Input[i + 1] == '"') ||
23600b57cec5SDimitry Andric                  (!IsSingle && Input[i + 1] == '\''))) {
23610b57cec5SDimitry Andric               // Remove this \, it's escaping a " or ' that no longer needs
23620b57cec5SDimitry Andric               // escaping
23630b57cec5SDimitry Andric               Replace(Start.getLocWithOffset(i), 1, "");
23640b57cec5SDimitry Andric               continue;
23650b57cec5SDimitry Andric             }
23660b57cec5SDimitry Andric             Escaped = !Escaped;
23670b57cec5SDimitry Andric             break;
23680b57cec5SDimitry Andric           case '\"':
23690b57cec5SDimitry Andric           case '\'':
23700b57cec5SDimitry Andric             if (!Escaped && IsSingle == (Input[i] == '\'')) {
23710b57cec5SDimitry Andric               // Escape the quote.
23720b57cec5SDimitry Andric               Replace(Start.getLocWithOffset(i), 0, "\\");
23730b57cec5SDimitry Andric             }
23740b57cec5SDimitry Andric             Escaped = false;
23750b57cec5SDimitry Andric             break;
23760b57cec5SDimitry Andric           default:
23770b57cec5SDimitry Andric             Escaped = false;
23780b57cec5SDimitry Andric             break;
23790b57cec5SDimitry Andric           }
23800b57cec5SDimitry Andric         }
23810b57cec5SDimitry Andric       }
23820b57cec5SDimitry Andric     }
23830b57cec5SDimitry Andric   }
23840b57cec5SDimitry Andric };
23850b57cec5SDimitry Andric 
23860b57cec5SDimitry Andric class Formatter : public TokenAnalyzer {
23870b57cec5SDimitry Andric public:
Formatter(const Environment & Env,const FormatStyle & Style,FormattingAttemptStatus * Status)23880b57cec5SDimitry Andric   Formatter(const Environment &Env, const FormatStyle &Style,
23890b57cec5SDimitry Andric             FormattingAttemptStatus *Status)
23900b57cec5SDimitry Andric       : TokenAnalyzer(Env, Style), Status(Status) {}
23910b57cec5SDimitry Andric 
23920b57cec5SDimitry Andric   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)23930b57cec5SDimitry Andric   analyze(TokenAnnotator &Annotator,
23940b57cec5SDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
23950b57cec5SDimitry Andric           FormatTokenLexer &Tokens) override {
23960b57cec5SDimitry Andric     tooling::Replacements Result;
23970b57cec5SDimitry Andric     deriveLocalStyle(AnnotatedLines);
23980b57cec5SDimitry Andric     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
23991fd87a68SDimitry Andric     for (AnnotatedLine *Line : AnnotatedLines)
24001fd87a68SDimitry Andric       Annotator.calculateFormattingInformation(*Line);
24010b57cec5SDimitry Andric     Annotator.setCommentLineLevels(AnnotatedLines);
24020b57cec5SDimitry Andric 
24030b57cec5SDimitry Andric     WhitespaceManager Whitespaces(
24040b57cec5SDimitry Andric         Env.getSourceManager(), Style,
2405bdd1243dSDimitry Andric         Style.LineEnding > FormatStyle::LE_CRLF
240604eeddc0SDimitry Andric             ? WhitespaceManager::inputUsesCRLF(
2407480093f4SDimitry Andric                   Env.getSourceManager().getBufferData(Env.getFileID()),
2408bdd1243dSDimitry Andric                   Style.LineEnding == FormatStyle::LE_DeriveCRLF)
2409bdd1243dSDimitry Andric             : Style.LineEnding == FormatStyle::LE_CRLF);
24100b57cec5SDimitry Andric     ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
24110b57cec5SDimitry Andric                                   Env.getSourceManager(), Whitespaces, Encoding,
24120b57cec5SDimitry Andric                                   BinPackInconclusiveFunctions);
24130b57cec5SDimitry Andric     unsigned Penalty =
24140b57cec5SDimitry Andric         UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,
24150b57cec5SDimitry Andric                                Tokens.getKeywords(), Env.getSourceManager(),
24160b57cec5SDimitry Andric                                Status)
24170b57cec5SDimitry Andric             .format(AnnotatedLines, /*DryRun=*/false,
24180b57cec5SDimitry Andric                     /*AdditionalIndent=*/0,
24190b57cec5SDimitry Andric                     /*FixBadIndentation=*/false,
24200b57cec5SDimitry Andric                     /*FirstStartColumn=*/Env.getFirstStartColumn(),
24210b57cec5SDimitry Andric                     /*NextStartColumn=*/Env.getNextStartColumn(),
24220b57cec5SDimitry Andric                     /*LastStartColumn=*/Env.getLastStartColumn());
24230b57cec5SDimitry Andric     for (const auto &R : Whitespaces.generateReplacements())
24240b57cec5SDimitry Andric       if (Result.add(R))
24250b57cec5SDimitry Andric         return std::make_pair(Result, 0);
24260b57cec5SDimitry Andric     return std::make_pair(Result, Penalty);
24270b57cec5SDimitry Andric   }
24280b57cec5SDimitry Andric 
24290b57cec5SDimitry Andric private:
24300b57cec5SDimitry Andric   bool
hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine * > & Lines)24310b57cec5SDimitry Andric   hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) {
24320b57cec5SDimitry Andric     for (const AnnotatedLine *Line : Lines) {
24330b57cec5SDimitry Andric       if (hasCpp03IncompatibleFormat(Line->Children))
24340b57cec5SDimitry Andric         return true;
24350b57cec5SDimitry Andric       for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {
243604eeddc0SDimitry Andric         if (!Tok->hasWhitespaceBefore()) {
24370b57cec5SDimitry Andric           if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
24380b57cec5SDimitry Andric             return true;
24390b57cec5SDimitry Andric           if (Tok->is(TT_TemplateCloser) &&
244081ad6265SDimitry Andric               Tok->Previous->is(TT_TemplateCloser)) {
24410b57cec5SDimitry Andric             return true;
24420b57cec5SDimitry Andric           }
24430b57cec5SDimitry Andric         }
24440b57cec5SDimitry Andric       }
244581ad6265SDimitry Andric     }
24460b57cec5SDimitry Andric     return false;
24470b57cec5SDimitry Andric   }
24480b57cec5SDimitry Andric 
countVariableAlignments(const SmallVectorImpl<AnnotatedLine * > & Lines)24490b57cec5SDimitry Andric   int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) {
24500b57cec5SDimitry Andric     int AlignmentDiff = 0;
24510b57cec5SDimitry Andric     for (const AnnotatedLine *Line : Lines) {
24520b57cec5SDimitry Andric       AlignmentDiff += countVariableAlignments(Line->Children);
24530b57cec5SDimitry Andric       for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {
24545f757f3fSDimitry Andric         if (Tok->isNot(TT_PointerOrReference))
24550b57cec5SDimitry Andric           continue;
245681ad6265SDimitry Andric         // Don't treat space in `void foo() &&` as evidence.
245781ad6265SDimitry Andric         if (const auto *Prev = Tok->getPreviousNonComment()) {
245881ad6265SDimitry Andric           if (Prev->is(tok::r_paren) && Prev->MatchingParen) {
245981ad6265SDimitry Andric             if (const auto *Func =
246081ad6265SDimitry Andric                     Prev->MatchingParen->getPreviousNonComment()) {
246181ad6265SDimitry Andric               if (Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName,
246281ad6265SDimitry Andric                                 TT_OverloadedOperator)) {
246381ad6265SDimitry Andric                 continue;
246481ad6265SDimitry Andric               }
246581ad6265SDimitry Andric             }
246681ad6265SDimitry Andric           }
246781ad6265SDimitry Andric         }
246804eeddc0SDimitry Andric         bool SpaceBefore = Tok->hasWhitespaceBefore();
246904eeddc0SDimitry Andric         bool SpaceAfter = Tok->Next->hasWhitespaceBefore();
24700b57cec5SDimitry Andric         if (SpaceBefore && !SpaceAfter)
24710b57cec5SDimitry Andric           ++AlignmentDiff;
24720b57cec5SDimitry Andric         if (!SpaceBefore && SpaceAfter)
24730b57cec5SDimitry Andric           --AlignmentDiff;
24740b57cec5SDimitry Andric       }
24750b57cec5SDimitry Andric     }
24760b57cec5SDimitry Andric     return AlignmentDiff;
24770b57cec5SDimitry Andric   }
24780b57cec5SDimitry Andric 
24790b57cec5SDimitry Andric   void
deriveLocalStyle(const SmallVectorImpl<AnnotatedLine * > & AnnotatedLines)24800b57cec5SDimitry Andric   deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
24810b57cec5SDimitry Andric     bool HasBinPackedFunction = false;
24820b57cec5SDimitry Andric     bool HasOnePerLineFunction = false;
24831fd87a68SDimitry Andric     for (AnnotatedLine *Line : AnnotatedLines) {
24841fd87a68SDimitry Andric       if (!Line->First->Next)
24850b57cec5SDimitry Andric         continue;
24861fd87a68SDimitry Andric       FormatToken *Tok = Line->First->Next;
24870b57cec5SDimitry Andric       while (Tok->Next) {
2488e8d8bef9SDimitry Andric         if (Tok->is(PPK_BinPacked))
24890b57cec5SDimitry Andric           HasBinPackedFunction = true;
2490e8d8bef9SDimitry Andric         if (Tok->is(PPK_OnePerLine))
24910b57cec5SDimitry Andric           HasOnePerLineFunction = true;
24920b57cec5SDimitry Andric 
24930b57cec5SDimitry Andric         Tok = Tok->Next;
24940b57cec5SDimitry Andric       }
24950b57cec5SDimitry Andric     }
2496fe6060f1SDimitry Andric     if (Style.DerivePointerAlignment) {
2497bdd1243dSDimitry Andric       const auto NetRightCount = countVariableAlignments(AnnotatedLines);
2498bdd1243dSDimitry Andric       if (NetRightCount > 0)
2499bdd1243dSDimitry Andric         Style.PointerAlignment = FormatStyle::PAS_Right;
2500bdd1243dSDimitry Andric       else if (NetRightCount < 0)
2501bdd1243dSDimitry Andric         Style.PointerAlignment = FormatStyle::PAS_Left;
2502fe6060f1SDimitry Andric       Style.ReferenceAlignment = FormatStyle::RAS_Pointer;
2503fe6060f1SDimitry Andric     }
250481ad6265SDimitry Andric     if (Style.Standard == FormatStyle::LS_Auto) {
25050b57cec5SDimitry Andric       Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
2506a7dea167SDimitry Andric                            ? FormatStyle::LS_Latest
25070b57cec5SDimitry Andric                            : FormatStyle::LS_Cpp03;
250881ad6265SDimitry Andric     }
25090b57cec5SDimitry Andric     BinPackInconclusiveFunctions =
25100b57cec5SDimitry Andric         HasBinPackedFunction || !HasOnePerLineFunction;
25110b57cec5SDimitry Andric   }
25120b57cec5SDimitry Andric 
25130b57cec5SDimitry Andric   bool BinPackInconclusiveFunctions;
25140b57cec5SDimitry Andric   FormattingAttemptStatus *Status;
25150b57cec5SDimitry Andric };
25160b57cec5SDimitry Andric 
25175ffd83dbSDimitry Andric /// TrailingCommaInserter inserts trailing commas into container literals.
25185ffd83dbSDimitry Andric /// E.g.:
25195ffd83dbSDimitry Andric ///     const x = [
25205ffd83dbSDimitry Andric ///       1,
25215ffd83dbSDimitry Andric ///     ];
25225ffd83dbSDimitry Andric /// TrailingCommaInserter runs after formatting. To avoid causing a required
25235ffd83dbSDimitry Andric /// reformatting (and thus reflow), it never inserts a comma that'd exceed the
25245ffd83dbSDimitry Andric /// ColumnLimit.
25255ffd83dbSDimitry Andric ///
25265ffd83dbSDimitry Andric /// Because trailing commas disable binpacking of arrays, TrailingCommaInserter
25275ffd83dbSDimitry Andric /// is conceptually incompatible with bin packing.
25285ffd83dbSDimitry Andric class TrailingCommaInserter : public TokenAnalyzer {
25295ffd83dbSDimitry Andric public:
TrailingCommaInserter(const Environment & Env,const FormatStyle & Style)25305ffd83dbSDimitry Andric   TrailingCommaInserter(const Environment &Env, const FormatStyle &Style)
25315ffd83dbSDimitry Andric       : TokenAnalyzer(Env, Style) {}
25325ffd83dbSDimitry Andric 
25335ffd83dbSDimitry Andric   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)25345ffd83dbSDimitry Andric   analyze(TokenAnnotator &Annotator,
25355ffd83dbSDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
25365ffd83dbSDimitry Andric           FormatTokenLexer &Tokens) override {
25375ffd83dbSDimitry Andric     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
25385ffd83dbSDimitry Andric     tooling::Replacements Result;
25395ffd83dbSDimitry Andric     insertTrailingCommas(AnnotatedLines, Result);
25405ffd83dbSDimitry Andric     return {Result, 0};
25415ffd83dbSDimitry Andric   }
25425ffd83dbSDimitry Andric 
25435ffd83dbSDimitry Andric private:
25445ffd83dbSDimitry Andric   /// Inserts trailing commas in [] and {} initializers if they wrap over
25455ffd83dbSDimitry Andric   /// multiple lines.
insertTrailingCommas(SmallVectorImpl<AnnotatedLine * > & Lines,tooling::Replacements & Result)25465ffd83dbSDimitry Andric   void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,
25475ffd83dbSDimitry Andric                             tooling::Replacements &Result) {
25485ffd83dbSDimitry Andric     for (AnnotatedLine *Line : Lines) {
25495ffd83dbSDimitry Andric       insertTrailingCommas(Line->Children, Result);
25505ffd83dbSDimitry Andric       if (!Line->Affected)
25515ffd83dbSDimitry Andric         continue;
25525ffd83dbSDimitry Andric       for (FormatToken *FormatTok = Line->First; FormatTok;
25535ffd83dbSDimitry Andric            FormatTok = FormatTok->Next) {
25545ffd83dbSDimitry Andric         if (FormatTok->NewlinesBefore == 0)
25555ffd83dbSDimitry Andric           continue;
25565ffd83dbSDimitry Andric         FormatToken *Matching = FormatTok->MatchingParen;
25575ffd83dbSDimitry Andric         if (!Matching || !FormatTok->getPreviousNonComment())
25585ffd83dbSDimitry Andric           continue;
25595ffd83dbSDimitry Andric         if (!(FormatTok->is(tok::r_square) &&
25605ffd83dbSDimitry Andric               Matching->is(TT_ArrayInitializerLSquare)) &&
256181ad6265SDimitry Andric             !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) {
25625ffd83dbSDimitry Andric           continue;
256381ad6265SDimitry Andric         }
25645ffd83dbSDimitry Andric         FormatToken *Prev = FormatTok->getPreviousNonComment();
25655ffd83dbSDimitry Andric         if (Prev->is(tok::comma) || Prev->is(tok::semi))
25665ffd83dbSDimitry Andric           continue;
25675ffd83dbSDimitry Andric         // getEndLoc is not reliably set during re-lexing, use text length
25685ffd83dbSDimitry Andric         // instead.
25695ffd83dbSDimitry Andric         SourceLocation Start =
25705ffd83dbSDimitry Andric             Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size());
25715ffd83dbSDimitry Andric         // If inserting a comma would push the code over the column limit, skip
25725ffd83dbSDimitry Andric         // this location - it'd introduce an unstable formatting due to the
25735ffd83dbSDimitry Andric         // required reflow.
25745ffd83dbSDimitry Andric         unsigned ColumnNumber =
25755ffd83dbSDimitry Andric             Env.getSourceManager().getSpellingColumnNumber(Start);
25765ffd83dbSDimitry Andric         if (ColumnNumber > Style.ColumnLimit)
25775ffd83dbSDimitry Andric           continue;
25785ffd83dbSDimitry Andric         // Comma insertions cannot conflict with each other, and this pass has a
25795ffd83dbSDimitry Andric         // clean set of Replacements, so the operation below cannot fail.
25805ffd83dbSDimitry Andric         cantFail(Result.add(
25815ffd83dbSDimitry Andric             tooling::Replacement(Env.getSourceManager(), Start, 0, ",")));
25825ffd83dbSDimitry Andric       }
25835ffd83dbSDimitry Andric     }
25845ffd83dbSDimitry Andric   }
25855ffd83dbSDimitry Andric };
25865ffd83dbSDimitry Andric 
25870b57cec5SDimitry Andric // This class clean up the erroneous/redundant code around the given ranges in
25880b57cec5SDimitry Andric // file.
25890b57cec5SDimitry Andric class Cleaner : public TokenAnalyzer {
25900b57cec5SDimitry Andric public:
Cleaner(const Environment & Env,const FormatStyle & Style)25910b57cec5SDimitry Andric   Cleaner(const Environment &Env, const FormatStyle &Style)
25920b57cec5SDimitry Andric       : TokenAnalyzer(Env, Style),
25930b57cec5SDimitry Andric         DeletedTokens(FormatTokenLess(Env.getSourceManager())) {}
25940b57cec5SDimitry Andric 
25950b57cec5SDimitry Andric   // FIXME: eliminate unused parameters.
25960b57cec5SDimitry Andric   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)25970b57cec5SDimitry Andric   analyze(TokenAnnotator &Annotator,
25980b57cec5SDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
25990b57cec5SDimitry Andric           FormatTokenLexer &Tokens) override {
26000b57cec5SDimitry Andric     // FIXME: in the current implementation the granularity of affected range
26010b57cec5SDimitry Andric     // is an annotated line. However, this is not sufficient. Furthermore,
26020b57cec5SDimitry Andric     // redundant code introduced by replacements does not necessarily
26030b57cec5SDimitry Andric     // intercept with ranges of replacements that result in the redundancy.
26040b57cec5SDimitry Andric     // To determine if some redundant code is actually introduced by
26050b57cec5SDimitry Andric     // replacements(e.g. deletions), we need to come up with a more
26060b57cec5SDimitry Andric     // sophisticated way of computing affected ranges.
26070b57cec5SDimitry Andric     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
26080b57cec5SDimitry Andric 
26090b57cec5SDimitry Andric     checkEmptyNamespace(AnnotatedLines);
26100b57cec5SDimitry Andric 
2611a7dea167SDimitry Andric     for (auto *Line : AnnotatedLines)
2612a7dea167SDimitry Andric       cleanupLine(Line);
2613a7dea167SDimitry Andric 
2614a7dea167SDimitry Andric     return {generateFixes(), 0};
2615a7dea167SDimitry Andric   }
2616a7dea167SDimitry Andric 
2617a7dea167SDimitry Andric private:
cleanupLine(AnnotatedLine * Line)2618a7dea167SDimitry Andric   void cleanupLine(AnnotatedLine *Line) {
261981ad6265SDimitry Andric     for (auto *Child : Line->Children)
2620a7dea167SDimitry Andric       cleanupLine(Child);
2621a7dea167SDimitry Andric 
26220b57cec5SDimitry Andric     if (Line->Affected) {
26230b57cec5SDimitry Andric       cleanupRight(Line->First, tok::comma, tok::comma);
26240b57cec5SDimitry Andric       cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
26250b57cec5SDimitry Andric       cleanupRight(Line->First, tok::l_paren, tok::comma);
26260b57cec5SDimitry Andric       cleanupLeft(Line->First, tok::comma, tok::r_paren);
26270b57cec5SDimitry Andric       cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
26280b57cec5SDimitry Andric       cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
26290b57cec5SDimitry Andric       cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
26300b57cec5SDimitry Andric     }
26310b57cec5SDimitry Andric   }
26320b57cec5SDimitry Andric 
containsOnlyComments(const AnnotatedLine & Line)26330b57cec5SDimitry Andric   bool containsOnlyComments(const AnnotatedLine &Line) {
263406c3fb27SDimitry Andric     for (FormatToken *Tok = Line.First; Tok; Tok = Tok->Next)
26350b57cec5SDimitry Andric       if (Tok->isNot(tok::comment))
26360b57cec5SDimitry Andric         return false;
26370b57cec5SDimitry Andric     return true;
26380b57cec5SDimitry Andric   }
26390b57cec5SDimitry Andric 
26400b57cec5SDimitry Andric   // Iterate through all lines and remove any empty (nested) namespaces.
checkEmptyNamespace(SmallVectorImpl<AnnotatedLine * > & AnnotatedLines)26410b57cec5SDimitry Andric   void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
26420b57cec5SDimitry Andric     std::set<unsigned> DeletedLines;
26430b57cec5SDimitry Andric     for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
26440b57cec5SDimitry Andric       auto &Line = *AnnotatedLines[i];
264581ad6265SDimitry Andric       if (Line.startsWithNamespace())
26460b57cec5SDimitry Andric         checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
26470b57cec5SDimitry Andric     }
26480b57cec5SDimitry Andric 
26490b57cec5SDimitry Andric     for (auto Line : DeletedLines) {
26500b57cec5SDimitry Andric       FormatToken *Tok = AnnotatedLines[Line]->First;
26510b57cec5SDimitry Andric       while (Tok) {
26520b57cec5SDimitry Andric         deleteToken(Tok);
26530b57cec5SDimitry Andric         Tok = Tok->Next;
26540b57cec5SDimitry Andric       }
26550b57cec5SDimitry Andric     }
26560b57cec5SDimitry Andric   }
26570b57cec5SDimitry Andric 
26580b57cec5SDimitry Andric   // The function checks if the namespace, which starts from \p CurrentLine, and
26590b57cec5SDimitry Andric   // its nested namespaces are empty and delete them if they are empty. It also
26600b57cec5SDimitry Andric   // sets \p NewLine to the last line checked.
26610b57cec5SDimitry Andric   // Returns true if the current namespace is empty.
checkEmptyNamespace(SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,unsigned CurrentLine,unsigned & NewLine,std::set<unsigned> & DeletedLines)26620b57cec5SDimitry Andric   bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
26630b57cec5SDimitry Andric                            unsigned CurrentLine, unsigned &NewLine,
26640b57cec5SDimitry Andric                            std::set<unsigned> &DeletedLines) {
26650b57cec5SDimitry Andric     unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
26660b57cec5SDimitry Andric     if (Style.BraceWrapping.AfterNamespace) {
26670b57cec5SDimitry Andric       // If the left brace is in a new line, we should consume it first so that
26680b57cec5SDimitry Andric       // it does not make the namespace non-empty.
26690b57cec5SDimitry Andric       // FIXME: error handling if there is no left brace.
26700b57cec5SDimitry Andric       if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
26710b57cec5SDimitry Andric         NewLine = CurrentLine;
26720b57cec5SDimitry Andric         return false;
26730b57cec5SDimitry Andric       }
26740b57cec5SDimitry Andric     } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
26750b57cec5SDimitry Andric       return false;
26760b57cec5SDimitry Andric     }
26770b57cec5SDimitry Andric     while (++CurrentLine < End) {
26780b57cec5SDimitry Andric       if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
26790b57cec5SDimitry Andric         break;
26800b57cec5SDimitry Andric 
26810b57cec5SDimitry Andric       if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
26820b57cec5SDimitry Andric         if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
268381ad6265SDimitry Andric                                  DeletedLines)) {
26840b57cec5SDimitry Andric           return false;
268581ad6265SDimitry Andric         }
26860b57cec5SDimitry Andric         CurrentLine = NewLine;
26870b57cec5SDimitry Andric         continue;
26880b57cec5SDimitry Andric       }
26890b57cec5SDimitry Andric 
26900b57cec5SDimitry Andric       if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
26910b57cec5SDimitry Andric         continue;
26920b57cec5SDimitry Andric 
26930b57cec5SDimitry Andric       // If there is anything other than comments or nested namespaces in the
26940b57cec5SDimitry Andric       // current namespace, the namespace cannot be empty.
26950b57cec5SDimitry Andric       NewLine = CurrentLine;
26960b57cec5SDimitry Andric       return false;
26970b57cec5SDimitry Andric     }
26980b57cec5SDimitry Andric 
26990b57cec5SDimitry Andric     NewLine = CurrentLine;
27000b57cec5SDimitry Andric     if (CurrentLine >= End)
27010b57cec5SDimitry Andric       return false;
27020b57cec5SDimitry Andric 
27030b57cec5SDimitry Andric     // Check if the empty namespace is actually affected by changed ranges.
27040b57cec5SDimitry Andric     if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
27050b57cec5SDimitry Andric             AnnotatedLines[InitLine]->First->Tok.getLocation(),
270681ad6265SDimitry Andric             AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) {
27070b57cec5SDimitry Andric       return false;
27080b57cec5SDimitry Andric     }
27090b57cec5SDimitry Andric 
271081ad6265SDimitry Andric     for (unsigned i = InitLine; i <= CurrentLine; ++i)
271181ad6265SDimitry Andric       DeletedLines.insert(i);
271281ad6265SDimitry Andric 
27130b57cec5SDimitry Andric     return true;
27140b57cec5SDimitry Andric   }
27150b57cec5SDimitry Andric 
27160b57cec5SDimitry Andric   // Checks pairs {start, start->next},..., {end->previous, end} and deletes one
27170b57cec5SDimitry Andric   // of the token in the pair if the left token has \p LK token kind and the
27180b57cec5SDimitry Andric   // right token has \p RK token kind. If \p DeleteLeft is true, the left token
27190b57cec5SDimitry Andric   // is deleted on match; otherwise, the right token is deleted.
27200b57cec5SDimitry Andric   template <typename LeftKind, typename RightKind>
cleanupPair(FormatToken * Start,LeftKind LK,RightKind RK,bool DeleteLeft)27210b57cec5SDimitry Andric   void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
27220b57cec5SDimitry Andric                    bool DeleteLeft) {
27230b57cec5SDimitry Andric     auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {
272481ad6265SDimitry Andric       for (auto *Res = Tok.Next; Res; Res = Res->Next) {
27255f757f3fSDimitry Andric         if (Res->isNot(tok::comment) &&
272681ad6265SDimitry Andric             DeletedTokens.find(Res) == DeletedTokens.end()) {
27270b57cec5SDimitry Andric           return Res;
272881ad6265SDimitry Andric         }
272981ad6265SDimitry Andric       }
27300b57cec5SDimitry Andric       return nullptr;
27310b57cec5SDimitry Andric     };
27320b57cec5SDimitry Andric     for (auto *Left = Start; Left;) {
27330b57cec5SDimitry Andric       auto *Right = NextNotDeleted(*Left);
27340b57cec5SDimitry Andric       if (!Right)
27350b57cec5SDimitry Andric         break;
27360b57cec5SDimitry Andric       if (Left->is(LK) && Right->is(RK)) {
27370b57cec5SDimitry Andric         deleteToken(DeleteLeft ? Left : Right);
27380b57cec5SDimitry Andric         for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
27390b57cec5SDimitry Andric           deleteToken(Tok);
27400b57cec5SDimitry Andric         // If the right token is deleted, we should keep the left token
27410b57cec5SDimitry Andric         // unchanged and pair it with the new right token.
27420b57cec5SDimitry Andric         if (!DeleteLeft)
27430b57cec5SDimitry Andric           continue;
27440b57cec5SDimitry Andric       }
27450b57cec5SDimitry Andric       Left = Right;
27460b57cec5SDimitry Andric     }
27470b57cec5SDimitry Andric   }
27480b57cec5SDimitry Andric 
27490b57cec5SDimitry Andric   template <typename LeftKind, typename RightKind>
cleanupLeft(FormatToken * Start,LeftKind LK,RightKind RK)27500b57cec5SDimitry Andric   void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
27510b57cec5SDimitry Andric     cleanupPair(Start, LK, RK, /*DeleteLeft=*/true);
27520b57cec5SDimitry Andric   }
27530b57cec5SDimitry Andric 
27540b57cec5SDimitry Andric   template <typename LeftKind, typename RightKind>
cleanupRight(FormatToken * Start,LeftKind LK,RightKind RK)27550b57cec5SDimitry Andric   void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
27560b57cec5SDimitry Andric     cleanupPair(Start, LK, RK, /*DeleteLeft=*/false);
27570b57cec5SDimitry Andric   }
27580b57cec5SDimitry Andric 
27590b57cec5SDimitry Andric   // Delete the given token.
deleteToken(FormatToken * Tok)27600b57cec5SDimitry Andric   inline void deleteToken(FormatToken *Tok) {
27610b57cec5SDimitry Andric     if (Tok)
27620b57cec5SDimitry Andric       DeletedTokens.insert(Tok);
27630b57cec5SDimitry Andric   }
27640b57cec5SDimitry Andric 
generateFixes()27650b57cec5SDimitry Andric   tooling::Replacements generateFixes() {
27660b57cec5SDimitry Andric     tooling::Replacements Fixes;
2767753f127fSDimitry Andric     SmallVector<FormatToken *> Tokens;
27680b57cec5SDimitry Andric     std::copy(DeletedTokens.begin(), DeletedTokens.end(),
27690b57cec5SDimitry Andric               std::back_inserter(Tokens));
27700b57cec5SDimitry Andric 
27710b57cec5SDimitry Andric     // Merge multiple continuous token deletions into one big deletion so that
27720b57cec5SDimitry Andric     // the number of replacements can be reduced. This makes computing affected
27730b57cec5SDimitry Andric     // ranges more efficient when we run reformat on the changed code.
27740b57cec5SDimitry Andric     unsigned Idx = 0;
27750b57cec5SDimitry Andric     while (Idx < Tokens.size()) {
27760b57cec5SDimitry Andric       unsigned St = Idx, End = Idx;
277781ad6265SDimitry Andric       while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1])
277804eeddc0SDimitry Andric         ++End;
27790b57cec5SDimitry Andric       auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
27800b57cec5SDimitry Andric                                               Tokens[End]->Tok.getEndLoc());
27810b57cec5SDimitry Andric       auto Err =
27820b57cec5SDimitry Andric           Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, ""));
27830b57cec5SDimitry Andric       // FIXME: better error handling. for now just print error message and skip
27840b57cec5SDimitry Andric       // for the release version.
27850b57cec5SDimitry Andric       if (Err) {
27860b57cec5SDimitry Andric         llvm::errs() << llvm::toString(std::move(Err)) << "\n";
27870b57cec5SDimitry Andric         assert(false && "Fixes must not conflict!");
27880b57cec5SDimitry Andric       }
27890b57cec5SDimitry Andric       Idx = End + 1;
27900b57cec5SDimitry Andric     }
27910b57cec5SDimitry Andric 
27920b57cec5SDimitry Andric     return Fixes;
27930b57cec5SDimitry Andric   }
27940b57cec5SDimitry Andric 
27950b57cec5SDimitry Andric   // Class for less-than inequality comparason for the set `RedundantTokens`.
27960b57cec5SDimitry Andric   // We store tokens in the order they appear in the translation unit so that
27970b57cec5SDimitry Andric   // we do not need to sort them in `generateFixes()`.
27980b57cec5SDimitry Andric   struct FormatTokenLess {
FormatTokenLessclang::format::__anondf462be30111::Cleaner::FormatTokenLess27990b57cec5SDimitry Andric     FormatTokenLess(const SourceManager &SM) : SM(SM) {}
28000b57cec5SDimitry Andric 
operator ()clang::format::__anondf462be30111::Cleaner::FormatTokenLess28010b57cec5SDimitry Andric     bool operator()(const FormatToken *LHS, const FormatToken *RHS) const {
28020b57cec5SDimitry Andric       return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
28030b57cec5SDimitry Andric                                           RHS->Tok.getLocation());
28040b57cec5SDimitry Andric     }
28050b57cec5SDimitry Andric     const SourceManager &SM;
28060b57cec5SDimitry Andric   };
28070b57cec5SDimitry Andric 
28080b57cec5SDimitry Andric   // Tokens to be deleted.
28090b57cec5SDimitry Andric   std::set<FormatToken *, FormatTokenLess> DeletedTokens;
28100b57cec5SDimitry Andric };
28110b57cec5SDimitry Andric 
28120b57cec5SDimitry Andric class ObjCHeaderStyleGuesser : public TokenAnalyzer {
28130b57cec5SDimitry Andric public:
ObjCHeaderStyleGuesser(const Environment & Env,const FormatStyle & Style)28140b57cec5SDimitry Andric   ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style)
28150b57cec5SDimitry Andric       : TokenAnalyzer(Env, Style), IsObjC(false) {}
28160b57cec5SDimitry Andric 
28170b57cec5SDimitry Andric   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)28180b57cec5SDimitry Andric   analyze(TokenAnnotator &Annotator,
28190b57cec5SDimitry Andric           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
28200b57cec5SDimitry Andric           FormatTokenLexer &Tokens) override {
28210b57cec5SDimitry Andric     assert(Style.Language == FormatStyle::LK_Cpp);
28220b57cec5SDimitry Andric     IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines,
28230b57cec5SDimitry Andric                          Tokens.getKeywords());
28240b57cec5SDimitry Andric     tooling::Replacements Result;
28250b57cec5SDimitry Andric     return {Result, 0};
28260b57cec5SDimitry Andric   }
28270b57cec5SDimitry Andric 
isObjC()28280b57cec5SDimitry Andric   bool isObjC() { return IsObjC; }
28290b57cec5SDimitry Andric 
28300b57cec5SDimitry Andric private:
28310b57cec5SDimitry Andric   static bool
guessIsObjC(const SourceManager & SourceManager,const SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,const AdditionalKeywords & Keywords)28320b57cec5SDimitry Andric   guessIsObjC(const SourceManager &SourceManager,
28330b57cec5SDimitry Andric               const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
28340b57cec5SDimitry Andric               const AdditionalKeywords &Keywords) {
28350b57cec5SDimitry Andric     // Keep this array sorted, since we are binary searching over it.
28360b57cec5SDimitry Andric     static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
28370b57cec5SDimitry Andric         "CGFloat",
28380b57cec5SDimitry Andric         "CGPoint",
28390b57cec5SDimitry Andric         "CGPointMake",
28400b57cec5SDimitry Andric         "CGPointZero",
28410b57cec5SDimitry Andric         "CGRect",
28420b57cec5SDimitry Andric         "CGRectEdge",
28430b57cec5SDimitry Andric         "CGRectInfinite",
28440b57cec5SDimitry Andric         "CGRectMake",
28450b57cec5SDimitry Andric         "CGRectNull",
28460b57cec5SDimitry Andric         "CGRectZero",
28470b57cec5SDimitry Andric         "CGSize",
28480b57cec5SDimitry Andric         "CGSizeMake",
28490b57cec5SDimitry Andric         "CGVector",
28500b57cec5SDimitry Andric         "CGVectorMake",
285106c3fb27SDimitry Andric         "FOUNDATION_EXPORT", // This is an alias for FOUNDATION_EXTERN.
285206c3fb27SDimitry Andric         "FOUNDATION_EXTERN",
28530b57cec5SDimitry Andric         "NSAffineTransform",
28540b57cec5SDimitry Andric         "NSArray",
28550b57cec5SDimitry Andric         "NSAttributedString",
28560b57cec5SDimitry Andric         "NSBlockOperation",
28570b57cec5SDimitry Andric         "NSBundle",
28580b57cec5SDimitry Andric         "NSCache",
28590b57cec5SDimitry Andric         "NSCalendar",
28600b57cec5SDimitry Andric         "NSCharacterSet",
28610b57cec5SDimitry Andric         "NSCountedSet",
28620b57cec5SDimitry Andric         "NSData",
28630b57cec5SDimitry Andric         "NSDataDetector",
28640b57cec5SDimitry Andric         "NSDecimal",
28650b57cec5SDimitry Andric         "NSDecimalNumber",
28660b57cec5SDimitry Andric         "NSDictionary",
28670b57cec5SDimitry Andric         "NSEdgeInsets",
286806c3fb27SDimitry Andric         "NSError",
286906c3fb27SDimitry Andric         "NSErrorDomain",
28700b57cec5SDimitry Andric         "NSHashTable",
28710b57cec5SDimitry Andric         "NSIndexPath",
28720b57cec5SDimitry Andric         "NSIndexSet",
28730b57cec5SDimitry Andric         "NSInteger",
28740b57cec5SDimitry Andric         "NSInvocationOperation",
28750b57cec5SDimitry Andric         "NSLocale",
28760b57cec5SDimitry Andric         "NSMapTable",
28770b57cec5SDimitry Andric         "NSMutableArray",
28780b57cec5SDimitry Andric         "NSMutableAttributedString",
28790b57cec5SDimitry Andric         "NSMutableCharacterSet",
28800b57cec5SDimitry Andric         "NSMutableData",
28810b57cec5SDimitry Andric         "NSMutableDictionary",
28820b57cec5SDimitry Andric         "NSMutableIndexSet",
28830b57cec5SDimitry Andric         "NSMutableOrderedSet",
28840b57cec5SDimitry Andric         "NSMutableSet",
28850b57cec5SDimitry Andric         "NSMutableString",
28860b57cec5SDimitry Andric         "NSNumber",
28870b57cec5SDimitry Andric         "NSNumberFormatter",
28880b57cec5SDimitry Andric         "NSObject",
28890b57cec5SDimitry Andric         "NSOperation",
28900b57cec5SDimitry Andric         "NSOperationQueue",
28910b57cec5SDimitry Andric         "NSOperationQueuePriority",
28920b57cec5SDimitry Andric         "NSOrderedSet",
28930b57cec5SDimitry Andric         "NSPoint",
28940b57cec5SDimitry Andric         "NSPointerArray",
28950b57cec5SDimitry Andric         "NSQualityOfService",
28960b57cec5SDimitry Andric         "NSRange",
28970b57cec5SDimitry Andric         "NSRect",
28980b57cec5SDimitry Andric         "NSRegularExpression",
28990b57cec5SDimitry Andric         "NSSet",
29000b57cec5SDimitry Andric         "NSSize",
29010b57cec5SDimitry Andric         "NSString",
29020b57cec5SDimitry Andric         "NSTimeZone",
29030b57cec5SDimitry Andric         "NSUInteger",
29040b57cec5SDimitry Andric         "NSURL",
29050b57cec5SDimitry Andric         "NSURLComponents",
29060b57cec5SDimitry Andric         "NSURLQueryItem",
29070b57cec5SDimitry Andric         "NSUUID",
29080b57cec5SDimitry Andric         "NSValue",
290906c3fb27SDimitry Andric         "NS_ASSUME_NONNULL_BEGIN",
29100b57cec5SDimitry Andric         "UIImage",
29110b57cec5SDimitry Andric         "UIView",
29120b57cec5SDimitry Andric     };
29130b57cec5SDimitry Andric 
2914bdd1243dSDimitry Andric     for (auto *Line : AnnotatedLines) {
29155f757f3fSDimitry Andric       if (Line->First && (Line->First->TokenText.starts_with("#") ||
2916e8d8bef9SDimitry Andric                           Line->First->TokenText == "__pragma" ||
291781ad6265SDimitry Andric                           Line->First->TokenText == "_Pragma")) {
2918e8d8bef9SDimitry Andric         continue;
291981ad6265SDimitry Andric       }
29200b57cec5SDimitry Andric       for (const FormatToken *FormatTok = Line->First; FormatTok;
29210b57cec5SDimitry Andric            FormatTok = FormatTok->Next) {
29220b57cec5SDimitry Andric         if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
29230b57cec5SDimitry Andric              (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
29240b57cec5SDimitry Andric               FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
29250b57cec5SDimitry Andric                                  tok::l_brace))) ||
29260b57cec5SDimitry Andric             (FormatTok->Tok.isAnyIdentifier() &&
29270b57cec5SDimitry Andric              std::binary_search(std::begin(FoundationIdentifiers),
29280b57cec5SDimitry Andric                                 std::end(FoundationIdentifiers),
29290b57cec5SDimitry Andric                                 FormatTok->TokenText)) ||
29300b57cec5SDimitry Andric             FormatTok->is(TT_ObjCStringLiteral) ||
2931a7dea167SDimitry Andric             FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,
293206c3fb27SDimitry Andric                                Keywords.kw_NS_ERROR_ENUM,
2933a7dea167SDimitry Andric                                Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,
2934a7dea167SDimitry Andric                                TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,
2935a7dea167SDimitry Andric                                TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,
2936a7dea167SDimitry Andric                                TT_ObjCProperty)) {
29370b57cec5SDimitry Andric           LLVM_DEBUG(llvm::dbgs()
29380b57cec5SDimitry Andric                      << "Detected ObjC at location "
29390b57cec5SDimitry Andric                      << FormatTok->Tok.getLocation().printToString(
29400b57cec5SDimitry Andric                             SourceManager)
29410b57cec5SDimitry Andric                      << " token: " << FormatTok->TokenText << " token type: "
29425ffd83dbSDimitry Andric                      << getTokenTypeName(FormatTok->getType()) << "\n");
29430b57cec5SDimitry Andric           return true;
29440b57cec5SDimitry Andric         }
29450b57cec5SDimitry Andric         if (guessIsObjC(SourceManager, Line->Children, Keywords))
29460b57cec5SDimitry Andric           return true;
29470b57cec5SDimitry Andric       }
29480b57cec5SDimitry Andric     }
29490b57cec5SDimitry Andric     return false;
29500b57cec5SDimitry Andric   }
29510b57cec5SDimitry Andric 
29520b57cec5SDimitry Andric   bool IsObjC;
29530b57cec5SDimitry Andric };
29540b57cec5SDimitry Andric 
29550b57cec5SDimitry Andric struct IncludeDirective {
29560b57cec5SDimitry Andric   StringRef Filename;
29570b57cec5SDimitry Andric   StringRef Text;
29580b57cec5SDimitry Andric   unsigned Offset;
29590b57cec5SDimitry Andric   int Category;
2960a7dea167SDimitry Andric   int Priority;
29610b57cec5SDimitry Andric };
29620b57cec5SDimitry Andric 
29630b57cec5SDimitry Andric struct JavaImportDirective {
29640b57cec5SDimitry Andric   StringRef Identifier;
29650b57cec5SDimitry Andric   StringRef Text;
29660b57cec5SDimitry Andric   unsigned Offset;
2967753f127fSDimitry Andric   SmallVector<StringRef> AssociatedCommentLines;
29680b57cec5SDimitry Andric   bool IsStatic;
29690b57cec5SDimitry Andric };
29700b57cec5SDimitry Andric 
29710b57cec5SDimitry Andric } // end anonymous namespace
29720b57cec5SDimitry Andric 
29730b57cec5SDimitry Andric // Determines whether 'Ranges' intersects with ('Start', 'End').
affectsRange(ArrayRef<tooling::Range> Ranges,unsigned Start,unsigned End)29740b57cec5SDimitry Andric static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start,
29750b57cec5SDimitry Andric                          unsigned End) {
297606c3fb27SDimitry Andric   for (const auto &Range : Ranges) {
29770b57cec5SDimitry Andric     if (Range.getOffset() < End &&
297881ad6265SDimitry Andric         Range.getOffset() + Range.getLength() > Start) {
29790b57cec5SDimitry Andric       return true;
29800b57cec5SDimitry Andric     }
298181ad6265SDimitry Andric   }
29820b57cec5SDimitry Andric   return false;
29830b57cec5SDimitry Andric }
29840b57cec5SDimitry Andric 
29850b57cec5SDimitry Andric // Returns a pair (Index, OffsetToEOL) describing the position of the cursor
29860b57cec5SDimitry Andric // before sorting/deduplicating. Index is the index of the include under the
29870b57cec5SDimitry Andric // cursor in the original set of includes. If this include has duplicates, it is
29880b57cec5SDimitry Andric // the index of the first of the duplicates as the others are going to be
29890b57cec5SDimitry Andric // removed. OffsetToEOL describes the cursor's position relative to the end of
29900b57cec5SDimitry Andric // its current line.
29910b57cec5SDimitry Andric // If `Cursor` is not on any #include, `Index` will be UINT_MAX.
29920b57cec5SDimitry Andric static std::pair<unsigned, unsigned>
FindCursorIndex(const SmallVectorImpl<IncludeDirective> & Includes,const SmallVectorImpl<unsigned> & Indices,unsigned Cursor)29930b57cec5SDimitry Andric FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes,
29940b57cec5SDimitry Andric                 const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) {
29950b57cec5SDimitry Andric   unsigned CursorIndex = UINT_MAX;
29960b57cec5SDimitry Andric   unsigned OffsetToEOL = 0;
29970b57cec5SDimitry Andric   for (int i = 0, e = Includes.size(); i != e; ++i) {
29980b57cec5SDimitry Andric     unsigned Start = Includes[Indices[i]].Offset;
29990b57cec5SDimitry Andric     unsigned End = Start + Includes[Indices[i]].Text.size();
30000b57cec5SDimitry Andric     if (!(Cursor >= Start && Cursor < End))
30010b57cec5SDimitry Andric       continue;
30020b57cec5SDimitry Andric     CursorIndex = Indices[i];
30030b57cec5SDimitry Andric     OffsetToEOL = End - Cursor;
30040b57cec5SDimitry Andric     // Put the cursor on the only remaining #include among the duplicate
30050b57cec5SDimitry Andric     // #includes.
30060b57cec5SDimitry Andric     while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text)
30070b57cec5SDimitry Andric       CursorIndex = i;
30080b57cec5SDimitry Andric     break;
30090b57cec5SDimitry Andric   }
30100b57cec5SDimitry Andric   return std::make_pair(CursorIndex, OffsetToEOL);
30110b57cec5SDimitry Andric }
30120b57cec5SDimitry Andric 
3013a7dea167SDimitry Andric // Replace all "\r\n" with "\n".
replaceCRLF(const std::string & Code)3014a7dea167SDimitry Andric std::string replaceCRLF(const std::string &Code) {
3015a7dea167SDimitry Andric   std::string NewCode;
3016a7dea167SDimitry Andric   size_t Pos = 0, LastPos = 0;
3017a7dea167SDimitry Andric 
3018a7dea167SDimitry Andric   do {
3019a7dea167SDimitry Andric     Pos = Code.find("\r\n", LastPos);
3020a7dea167SDimitry Andric     if (Pos == LastPos) {
302104eeddc0SDimitry Andric       ++LastPos;
3022a7dea167SDimitry Andric       continue;
3023a7dea167SDimitry Andric     }
3024a7dea167SDimitry Andric     if (Pos == std::string::npos) {
3025a7dea167SDimitry Andric       NewCode += Code.substr(LastPos);
3026a7dea167SDimitry Andric       break;
3027a7dea167SDimitry Andric     }
3028a7dea167SDimitry Andric     NewCode += Code.substr(LastPos, Pos - LastPos) + "\n";
3029a7dea167SDimitry Andric     LastPos = Pos + 2;
3030a7dea167SDimitry Andric   } while (Pos != std::string::npos);
3031a7dea167SDimitry Andric 
3032a7dea167SDimitry Andric   return NewCode;
3033a7dea167SDimitry Andric }
3034a7dea167SDimitry Andric 
30350b57cec5SDimitry Andric // Sorts and deduplicate a block of includes given by 'Includes' alphabetically
30360b57cec5SDimitry Andric // adding the necessary replacement to 'Replaces'. 'Includes' must be in strict
30370b57cec5SDimitry Andric // source order.
30380b57cec5SDimitry Andric // #include directives with the same text will be deduplicated, and only the
30390b57cec5SDimitry Andric // first #include in the duplicate #includes remains. If the `Cursor` is
30400b57cec5SDimitry Andric // provided and put on a deleted #include, it will be moved to the remaining
30410b57cec5SDimitry Andric // #include in the duplicate #includes.
sortCppIncludes(const FormatStyle & Style,const SmallVectorImpl<IncludeDirective> & Includes,ArrayRef<tooling::Range> Ranges,StringRef FileName,StringRef Code,tooling::Replacements & Replaces,unsigned * Cursor)30420b57cec5SDimitry Andric static void sortCppIncludes(const FormatStyle &Style,
30430b57cec5SDimitry Andric                             const SmallVectorImpl<IncludeDirective> &Includes,
30440b57cec5SDimitry Andric                             ArrayRef<tooling::Range> Ranges, StringRef FileName,
3045a7dea167SDimitry Andric                             StringRef Code, tooling::Replacements &Replaces,
3046a7dea167SDimitry Andric                             unsigned *Cursor) {
3047a7dea167SDimitry Andric   tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
304881ad6265SDimitry Andric   const unsigned IncludesBeginOffset = Includes.front().Offset;
304981ad6265SDimitry Andric   const unsigned IncludesEndOffset =
30500b57cec5SDimitry Andric       Includes.back().Offset + Includes.back().Text.size();
305181ad6265SDimitry Andric   const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
30520b57cec5SDimitry Andric   if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
30530b57cec5SDimitry Andric     return;
305481ad6265SDimitry Andric   SmallVector<unsigned, 16> Indices =
305581ad6265SDimitry Andric       llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size()));
3056fe6060f1SDimitry Andric 
3057fe6060f1SDimitry Andric   if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) {
3058fe6060f1SDimitry Andric     llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
3059fe6060f1SDimitry Andric       const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
3060fe6060f1SDimitry Andric       const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
3061fe6060f1SDimitry Andric       return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
3062fe6060f1SDimitry Andric                       Includes[LHSI].Filename) <
3063fe6060f1SDimitry Andric              std::tie(Includes[RHSI].Priority, RHSFilenameLower,
3064fe6060f1SDimitry Andric                       Includes[RHSI].Filename);
3065fe6060f1SDimitry Andric     });
3066fe6060f1SDimitry Andric   } else {
30670b57cec5SDimitry Andric     llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
3068a7dea167SDimitry Andric       return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
3069a7dea167SDimitry Andric              std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
30700b57cec5SDimitry Andric     });
3071fe6060f1SDimitry Andric   }
3072fe6060f1SDimitry Andric 
30730b57cec5SDimitry Andric   // The index of the include on which the cursor will be put after
30740b57cec5SDimitry Andric   // sorting/deduplicating.
30750b57cec5SDimitry Andric   unsigned CursorIndex;
30760b57cec5SDimitry Andric   // The offset from cursor to the end of line.
30770b57cec5SDimitry Andric   unsigned CursorToEOLOffset;
307881ad6265SDimitry Andric   if (Cursor) {
30790b57cec5SDimitry Andric     std::tie(CursorIndex, CursorToEOLOffset) =
30800b57cec5SDimitry Andric         FindCursorIndex(Includes, Indices, *Cursor);
308181ad6265SDimitry Andric   }
30820b57cec5SDimitry Andric 
30830b57cec5SDimitry Andric   // Deduplicate #includes.
30840b57cec5SDimitry Andric   Indices.erase(std::unique(Indices.begin(), Indices.end(),
30850b57cec5SDimitry Andric                             [&](unsigned LHSI, unsigned RHSI) {
3086e8d8bef9SDimitry Andric                               return Includes[LHSI].Text.trim() ==
3087e8d8bef9SDimitry Andric                                      Includes[RHSI].Text.trim();
30880b57cec5SDimitry Andric                             }),
30890b57cec5SDimitry Andric                 Indices.end());
30900b57cec5SDimitry Andric 
30910b57cec5SDimitry Andric   int CurrentCategory = Includes.front().Category;
30920b57cec5SDimitry Andric 
30930b57cec5SDimitry Andric   // If the #includes are out of order, we generate a single replacement fixing
30940b57cec5SDimitry Andric   // the entire block. Otherwise, no replacement is generated.
30950b57cec5SDimitry Andric   // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not
30960b57cec5SDimitry Andric   // enough as additional newlines might be added or removed across #include
309781ad6265SDimitry Andric   // blocks. This we handle below by generating the updated #include blocks and
30980b57cec5SDimitry Andric   // comparing it to the original.
30995ffd83dbSDimitry Andric   if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) &&
310081ad6265SDimitry Andric       Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) {
31010b57cec5SDimitry Andric     return;
310281ad6265SDimitry Andric   }
31030b57cec5SDimitry Andric 
31040b57cec5SDimitry Andric   std::string result;
31050b57cec5SDimitry Andric   for (unsigned Index : Indices) {
31060b57cec5SDimitry Andric     if (!result.empty()) {
31070b57cec5SDimitry Andric       result += "\n";
31080b57cec5SDimitry Andric       if (Style.IncludeStyle.IncludeBlocks ==
31090b57cec5SDimitry Andric               tooling::IncludeStyle::IBS_Regroup &&
311081ad6265SDimitry Andric           CurrentCategory != Includes[Index].Category) {
31110b57cec5SDimitry Andric         result += "\n";
31120b57cec5SDimitry Andric       }
311381ad6265SDimitry Andric     }
31140b57cec5SDimitry Andric     result += Includes[Index].Text;
31150b57cec5SDimitry Andric     if (Cursor && CursorIndex == Index)
31160b57cec5SDimitry Andric       *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
31170b57cec5SDimitry Andric     CurrentCategory = Includes[Index].Category;
31180b57cec5SDimitry Andric   }
31190b57cec5SDimitry Andric 
312081ad6265SDimitry Andric   if (Cursor && *Cursor >= IncludesEndOffset)
312181ad6265SDimitry Andric     *Cursor += result.size() - IncludesBlockSize;
312281ad6265SDimitry Andric 
31230b57cec5SDimitry Andric   // If the #includes are out of order, we generate a single replacement fixing
31240b57cec5SDimitry Andric   // the entire range of blocks. Otherwise, no replacement is generated.
31255ffd83dbSDimitry Andric   if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
312681ad6265SDimitry Andric                                  IncludesBeginOffset, IncludesBlockSize)))) {
31270b57cec5SDimitry Andric     return;
312881ad6265SDimitry Andric   }
31290b57cec5SDimitry Andric 
31300b57cec5SDimitry Andric   auto Err = Replaces.add(tooling::Replacement(
31310b57cec5SDimitry Andric       FileName, Includes.front().Offset, IncludesBlockSize, result));
31320b57cec5SDimitry Andric   // FIXME: better error handling. For now, just skip the replacement for the
31330b57cec5SDimitry Andric   // release version.
31340b57cec5SDimitry Andric   if (Err) {
31350b57cec5SDimitry Andric     llvm::errs() << llvm::toString(std::move(Err)) << "\n";
31360b57cec5SDimitry Andric     assert(false);
31370b57cec5SDimitry Andric   }
31380b57cec5SDimitry Andric }
31390b57cec5SDimitry Andric 
sortCppIncludes(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName,tooling::Replacements & Replaces,unsigned * Cursor)31400b57cec5SDimitry Andric tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
31410b57cec5SDimitry Andric                                       ArrayRef<tooling::Range> Ranges,
31420b57cec5SDimitry Andric                                       StringRef FileName,
31430b57cec5SDimitry Andric                                       tooling::Replacements &Replaces,
31440b57cec5SDimitry Andric                                       unsigned *Cursor) {
3145e8d8bef9SDimitry Andric   unsigned Prev = llvm::StringSwitch<size_t>(Code)
3146e8d8bef9SDimitry Andric                       .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM
3147e8d8bef9SDimitry Andric                       .Default(0);
31480b57cec5SDimitry Andric   unsigned SearchFrom = 0;
31490b57cec5SDimitry Andric   SmallVector<StringRef, 4> Matches;
31500b57cec5SDimitry Andric   SmallVector<IncludeDirective, 16> IncludesInBlock;
31510b57cec5SDimitry Andric 
31520b57cec5SDimitry Andric   // In compiled files, consider the first #include to be the main #include of
31530b57cec5SDimitry Andric   // the file if it is not a system #include. This ensures that the header
31540b57cec5SDimitry Andric   // doesn't have hidden dependencies
31550b57cec5SDimitry Andric   // (http://llvm.org/docs/CodingStandards.html#include-style).
31560b57cec5SDimitry Andric   //
31575e801ac6SDimitry Andric   // FIXME: Do some validation, e.g. edit distance of the base name, to fix
31580b57cec5SDimitry Andric   // cases where the first #include is unlikely to be the main header.
31590b57cec5SDimitry Andric   tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
31600b57cec5SDimitry Andric   bool FirstIncludeBlock = true;
31610b57cec5SDimitry Andric   bool MainIncludeFound = false;
31620b57cec5SDimitry Andric   bool FormattingOff = false;
31630b57cec5SDimitry Andric 
316404eeddc0SDimitry Andric   // '[' must be the first and '-' the last character inside [...].
31650eae32dcSDimitry Andric   llvm::Regex RawStringRegex(
316604eeddc0SDimitry Andric       "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\(");
31670eae32dcSDimitry Andric   SmallVector<StringRef, 2> RawStringMatches;
31680eae32dcSDimitry Andric   std::string RawStringTermination = ")\"";
31690eae32dcSDimitry Andric 
31700b57cec5SDimitry Andric   for (;;) {
31710b57cec5SDimitry Andric     auto Pos = Code.find('\n', SearchFrom);
31720b57cec5SDimitry Andric     StringRef Line =
31730b57cec5SDimitry Andric         Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
31740b57cec5SDimitry Andric 
31750b57cec5SDimitry Andric     StringRef Trimmed = Line.trim();
31760eae32dcSDimitry Andric 
31770eae32dcSDimitry Andric     // #includes inside raw string literals need to be ignored.
31780eae32dcSDimitry Andric     // or we will sort the contents of the string.
31790eae32dcSDimitry Andric     // Skip past until we think we are at the rawstring literal close.
31800eae32dcSDimitry Andric     if (RawStringRegex.match(Trimmed, &RawStringMatches)) {
31810eae32dcSDimitry Andric       std::string CharSequence = RawStringMatches[1].str();
31820eae32dcSDimitry Andric       RawStringTermination = ")" + CharSequence + "\"";
31830eae32dcSDimitry Andric       FormattingOff = true;
31840eae32dcSDimitry Andric     }
31850eae32dcSDimitry Andric 
318681ad6265SDimitry Andric     if (Trimmed.contains(RawStringTermination))
318781ad6265SDimitry Andric       FormattingOff = false;
318881ad6265SDimitry Andric 
318906c3fb27SDimitry Andric     if (isClangFormatOff(Trimmed))
319081ad6265SDimitry Andric       FormattingOff = true;
319106c3fb27SDimitry Andric     else if (isClangFormatOn(Trimmed))
31920eae32dcSDimitry Andric       FormattingOff = false;
31930eae32dcSDimitry Andric 
31940b57cec5SDimitry Andric     const bool EmptyLineSkipped =
31950b57cec5SDimitry Andric         Trimmed.empty() &&
31960b57cec5SDimitry Andric         (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge ||
31970b57cec5SDimitry Andric          Style.IncludeStyle.IncludeBlocks ==
31980b57cec5SDimitry Andric              tooling::IncludeStyle::IBS_Regroup);
31990b57cec5SDimitry Andric 
32005f757f3fSDimitry Andric     bool MergeWithNextLine = Trimmed.ends_with("\\");
3201e8d8bef9SDimitry Andric     if (!FormattingOff && !MergeWithNextLine) {
3202bdd1243dSDimitry Andric       if (tooling::HeaderIncludes::IncludeRegex.match(Line, &Matches)) {
32030b57cec5SDimitry Andric         StringRef IncludeName = Matches[2];
32041fd87a68SDimitry Andric         if (Line.contains("/*") && !Line.contains("*/")) {
32051fd87a68SDimitry Andric           // #include with a start of a block comment, but without the end.
32061fd87a68SDimitry Andric           // Need to keep all the lines until the end of the comment together.
32071fd87a68SDimitry Andric           // FIXME: This is somehow simplified check that probably does not work
32081fd87a68SDimitry Andric           // correctly if there are multiple comments on a line.
32091fd87a68SDimitry Andric           Pos = Code.find("*/", SearchFrom);
32101fd87a68SDimitry Andric           Line = Code.substr(
32111fd87a68SDimitry Andric               Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev);
32121fd87a68SDimitry Andric         }
32130b57cec5SDimitry Andric         int Category = Categories.getIncludePriority(
32140b57cec5SDimitry Andric             IncludeName,
32150b57cec5SDimitry Andric             /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock);
3216a7dea167SDimitry Andric         int Priority = Categories.getSortIncludePriority(
3217a7dea167SDimitry Andric             IncludeName, !MainIncludeFound && FirstIncludeBlock);
32180b57cec5SDimitry Andric         if (Category == 0)
32190b57cec5SDimitry Andric           MainIncludeFound = true;
3220a7dea167SDimitry Andric         IncludesInBlock.push_back(
3221a7dea167SDimitry Andric             {IncludeName, Line, Prev, Category, Priority});
32220b57cec5SDimitry Andric       } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
32230b57cec5SDimitry Andric         sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code,
32240b57cec5SDimitry Andric                         Replaces, Cursor);
32250b57cec5SDimitry Andric         IncludesInBlock.clear();
32265f757f3fSDimitry Andric         if (Trimmed.starts_with("#pragma hdrstop")) // Precompiled headers.
3227e8d8bef9SDimitry Andric           FirstIncludeBlock = true;
3228e8d8bef9SDimitry Andric         else
32290b57cec5SDimitry Andric           FirstIncludeBlock = false;
32300b57cec5SDimitry Andric       }
32310b57cec5SDimitry Andric     }
32320b57cec5SDimitry Andric     if (Pos == StringRef::npos || Pos + 1 == Code.size())
32330b57cec5SDimitry Andric       break;
3234e8d8bef9SDimitry Andric 
3235e8d8bef9SDimitry Andric     if (!MergeWithNextLine)
3236e8d8bef9SDimitry Andric       Prev = Pos + 1;
32370b57cec5SDimitry Andric     SearchFrom = Pos + 1;
32380b57cec5SDimitry Andric   }
32390b57cec5SDimitry Andric   if (!IncludesInBlock.empty()) {
32400b57cec5SDimitry Andric     sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces,
32410b57cec5SDimitry Andric                     Cursor);
32420b57cec5SDimitry Andric   }
32430b57cec5SDimitry Andric   return Replaces;
32440b57cec5SDimitry Andric }
32450b57cec5SDimitry Andric 
32460b57cec5SDimitry Andric // Returns group number to use as a first order sort on imports. Gives UINT_MAX
32470b57cec5SDimitry Andric // if the import does not match any given groups.
findJavaImportGroup(const FormatStyle & Style,StringRef ImportIdentifier)32480b57cec5SDimitry Andric static unsigned findJavaImportGroup(const FormatStyle &Style,
32490b57cec5SDimitry Andric                                     StringRef ImportIdentifier) {
32500b57cec5SDimitry Andric   unsigned LongestMatchIndex = UINT_MAX;
32510b57cec5SDimitry Andric   unsigned LongestMatchLength = 0;
32520b57cec5SDimitry Andric   for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) {
32531fd87a68SDimitry Andric     const std::string &GroupPrefix = Style.JavaImportGroups[I];
32545f757f3fSDimitry Andric     if (ImportIdentifier.starts_with(GroupPrefix) &&
32550b57cec5SDimitry Andric         GroupPrefix.length() > LongestMatchLength) {
32560b57cec5SDimitry Andric       LongestMatchIndex = I;
32570b57cec5SDimitry Andric       LongestMatchLength = GroupPrefix.length();
32580b57cec5SDimitry Andric     }
32590b57cec5SDimitry Andric   }
32600b57cec5SDimitry Andric   return LongestMatchIndex;
32610b57cec5SDimitry Andric }
32620b57cec5SDimitry Andric 
32630b57cec5SDimitry Andric // Sorts and deduplicates a block of includes given by 'Imports' based on
32640b57cec5SDimitry Andric // JavaImportGroups, then adding the necessary replacement to 'Replaces'.
32650b57cec5SDimitry Andric // Import declarations with the same text will be deduplicated. Between each
32660b57cec5SDimitry Andric // import group, a newline is inserted, and within each import group, a
32670b57cec5SDimitry Andric // lexicographic sort based on ASCII value is performed.
sortJavaImports(const FormatStyle & Style,const SmallVectorImpl<JavaImportDirective> & Imports,ArrayRef<tooling::Range> Ranges,StringRef FileName,StringRef Code,tooling::Replacements & Replaces)32680b57cec5SDimitry Andric static void sortJavaImports(const FormatStyle &Style,
32690b57cec5SDimitry Andric                             const SmallVectorImpl<JavaImportDirective> &Imports,
32700b57cec5SDimitry Andric                             ArrayRef<tooling::Range> Ranges, StringRef FileName,
32710b57cec5SDimitry Andric                             StringRef Code, tooling::Replacements &Replaces) {
32720b57cec5SDimitry Andric   unsigned ImportsBeginOffset = Imports.front().Offset;
32730b57cec5SDimitry Andric   unsigned ImportsEndOffset =
32740b57cec5SDimitry Andric       Imports.back().Offset + Imports.back().Text.size();
32750b57cec5SDimitry Andric   unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;
32760b57cec5SDimitry Andric   if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))
32770b57cec5SDimitry Andric     return;
32781fd87a68SDimitry Andric 
327981ad6265SDimitry Andric   SmallVector<unsigned, 16> Indices =
328081ad6265SDimitry Andric       llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size()));
32810b57cec5SDimitry Andric   SmallVector<unsigned, 16> JavaImportGroups;
32821fd87a68SDimitry Andric   JavaImportGroups.reserve(Imports.size());
32831fd87a68SDimitry Andric   for (const JavaImportDirective &Import : Imports)
32841fd87a68SDimitry Andric     JavaImportGroups.push_back(findJavaImportGroup(Style, Import.Identifier));
32851fd87a68SDimitry Andric 
3286e8d8bef9SDimitry Andric   bool StaticImportAfterNormalImport =
3287e8d8bef9SDimitry Andric       Style.SortJavaStaticImport == FormatStyle::SJSIO_After;
32880b57cec5SDimitry Andric   llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
32890b57cec5SDimitry Andric     // Negating IsStatic to push static imports above non-static imports.
3290e8d8bef9SDimitry Andric     return std::make_tuple(!Imports[LHSI].IsStatic ^
3291e8d8bef9SDimitry Andric                                StaticImportAfterNormalImport,
3292e8d8bef9SDimitry Andric                            JavaImportGroups[LHSI], Imports[LHSI].Identifier) <
3293e8d8bef9SDimitry Andric            std::make_tuple(!Imports[RHSI].IsStatic ^
3294e8d8bef9SDimitry Andric                                StaticImportAfterNormalImport,
3295e8d8bef9SDimitry Andric                            JavaImportGroups[RHSI], Imports[RHSI].Identifier);
32960b57cec5SDimitry Andric   });
32970b57cec5SDimitry Andric 
32980b57cec5SDimitry Andric   // Deduplicate imports.
32990b57cec5SDimitry Andric   Indices.erase(std::unique(Indices.begin(), Indices.end(),
33000b57cec5SDimitry Andric                             [&](unsigned LHSI, unsigned RHSI) {
33010b57cec5SDimitry Andric                               return Imports[LHSI].Text == Imports[RHSI].Text;
33020b57cec5SDimitry Andric                             }),
33030b57cec5SDimitry Andric                 Indices.end());
33040b57cec5SDimitry Andric 
33050b57cec5SDimitry Andric   bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
33060b57cec5SDimitry Andric   unsigned CurrentImportGroup = JavaImportGroups[Indices.front()];
33070b57cec5SDimitry Andric 
33080b57cec5SDimitry Andric   std::string result;
33090b57cec5SDimitry Andric   for (unsigned Index : Indices) {
33100b57cec5SDimitry Andric     if (!result.empty()) {
33110b57cec5SDimitry Andric       result += "\n";
33120b57cec5SDimitry Andric       if (CurrentIsStatic != Imports[Index].IsStatic ||
331381ad6265SDimitry Andric           CurrentImportGroup != JavaImportGroups[Index]) {
33140b57cec5SDimitry Andric         result += "\n";
33150b57cec5SDimitry Andric       }
331681ad6265SDimitry Andric     }
33170b57cec5SDimitry Andric     for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) {
33180b57cec5SDimitry Andric       result += CommentLine;
33190b57cec5SDimitry Andric       result += "\n";
33200b57cec5SDimitry Andric     }
33210b57cec5SDimitry Andric     result += Imports[Index].Text;
33220b57cec5SDimitry Andric     CurrentIsStatic = Imports[Index].IsStatic;
33230b57cec5SDimitry Andric     CurrentImportGroup = JavaImportGroups[Index];
33240b57cec5SDimitry Andric   }
33250b57cec5SDimitry Andric 
33260b57cec5SDimitry Andric   // If the imports are out of order, we generate a single replacement fixing
33270b57cec5SDimitry Andric   // the entire block. Otherwise, no replacement is generated.
33285ffd83dbSDimitry Andric   if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
332981ad6265SDimitry Andric                                  Imports.front().Offset, ImportsBlockSize)))) {
33300b57cec5SDimitry Andric     return;
333181ad6265SDimitry Andric   }
33320b57cec5SDimitry Andric 
33330b57cec5SDimitry Andric   auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset,
33340b57cec5SDimitry Andric                                                ImportsBlockSize, result));
33350b57cec5SDimitry Andric   // FIXME: better error handling. For now, just skip the replacement for the
33360b57cec5SDimitry Andric   // release version.
33370b57cec5SDimitry Andric   if (Err) {
33380b57cec5SDimitry Andric     llvm::errs() << llvm::toString(std::move(Err)) << "\n";
33390b57cec5SDimitry Andric     assert(false);
33400b57cec5SDimitry Andric   }
33410b57cec5SDimitry Andric }
33420b57cec5SDimitry Andric 
33430b57cec5SDimitry Andric namespace {
33440b57cec5SDimitry Andric 
33450b57cec5SDimitry Andric const char JavaImportRegexPattern[] =
33460b57cec5SDimitry Andric     "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;";
33470b57cec5SDimitry Andric 
33480b57cec5SDimitry Andric } // anonymous namespace
33490b57cec5SDimitry Andric 
sortJavaImports(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName,tooling::Replacements & Replaces)33500b57cec5SDimitry Andric tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code,
33510b57cec5SDimitry Andric                                       ArrayRef<tooling::Range> Ranges,
33520b57cec5SDimitry Andric                                       StringRef FileName,
33530b57cec5SDimitry Andric                                       tooling::Replacements &Replaces) {
33540b57cec5SDimitry Andric   unsigned Prev = 0;
33550b57cec5SDimitry Andric   unsigned SearchFrom = 0;
33560b57cec5SDimitry Andric   llvm::Regex ImportRegex(JavaImportRegexPattern);
33570b57cec5SDimitry Andric   SmallVector<StringRef, 4> Matches;
33580b57cec5SDimitry Andric   SmallVector<JavaImportDirective, 16> ImportsInBlock;
3359753f127fSDimitry Andric   SmallVector<StringRef> AssociatedCommentLines;
33600b57cec5SDimitry Andric 
33610b57cec5SDimitry Andric   bool FormattingOff = false;
33620b57cec5SDimitry Andric 
33630b57cec5SDimitry Andric   for (;;) {
33640b57cec5SDimitry Andric     auto Pos = Code.find('\n', SearchFrom);
33650b57cec5SDimitry Andric     StringRef Line =
33660b57cec5SDimitry Andric         Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
33670b57cec5SDimitry Andric 
33680b57cec5SDimitry Andric     StringRef Trimmed = Line.trim();
336906c3fb27SDimitry Andric     if (isClangFormatOff(Trimmed))
33700b57cec5SDimitry Andric       FormattingOff = true;
337106c3fb27SDimitry Andric     else if (isClangFormatOn(Trimmed))
33720b57cec5SDimitry Andric       FormattingOff = false;
33730b57cec5SDimitry Andric 
33740b57cec5SDimitry Andric     if (ImportRegex.match(Line, &Matches)) {
33750b57cec5SDimitry Andric       if (FormattingOff) {
33760b57cec5SDimitry Andric         // If at least one import line has formatting turned off, turn off
33770b57cec5SDimitry Andric         // formatting entirely.
33780b57cec5SDimitry Andric         return Replaces;
33790b57cec5SDimitry Andric       }
33800b57cec5SDimitry Andric       StringRef Static = Matches[1];
33810b57cec5SDimitry Andric       StringRef Identifier = Matches[2];
33820b57cec5SDimitry Andric       bool IsStatic = false;
338381ad6265SDimitry Andric       if (Static.contains("static"))
33840b57cec5SDimitry Andric         IsStatic = true;
33850b57cec5SDimitry Andric       ImportsInBlock.push_back(
33860b57cec5SDimitry Andric           {Identifier, Line, Prev, AssociatedCommentLines, IsStatic});
33870b57cec5SDimitry Andric       AssociatedCommentLines.clear();
33880b57cec5SDimitry Andric     } else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) {
33890b57cec5SDimitry Andric       // Associating comments within the imports with the nearest import below
33900b57cec5SDimitry Andric       AssociatedCommentLines.push_back(Line);
33910b57cec5SDimitry Andric     }
33920b57cec5SDimitry Andric     Prev = Pos + 1;
33930b57cec5SDimitry Andric     if (Pos == StringRef::npos || Pos + 1 == Code.size())
33940b57cec5SDimitry Andric       break;
33950b57cec5SDimitry Andric     SearchFrom = Pos + 1;
33960b57cec5SDimitry Andric   }
33970b57cec5SDimitry Andric   if (!ImportsInBlock.empty())
33980b57cec5SDimitry Andric     sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces);
33990b57cec5SDimitry Andric   return Replaces;
34000b57cec5SDimitry Andric }
34010b57cec5SDimitry Andric 
isMpegTS(StringRef Code)34020b57cec5SDimitry Andric bool isMpegTS(StringRef Code) {
34030b57cec5SDimitry Andric   // MPEG transport streams use the ".ts" file extension. clang-format should
34040b57cec5SDimitry Andric   // not attempt to format those. MPEG TS' frame format starts with 0x47 every
34050b57cec5SDimitry Andric   // 189 bytes - detect that and return.
34060b57cec5SDimitry Andric   return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
34070b57cec5SDimitry Andric }
34080b57cec5SDimitry Andric 
isLikelyXml(StringRef Code)34095f757f3fSDimitry Andric bool isLikelyXml(StringRef Code) { return Code.ltrim().starts_with("<"); }
34100b57cec5SDimitry Andric 
sortIncludes(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName,unsigned * Cursor)34110b57cec5SDimitry Andric tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
34120b57cec5SDimitry Andric                                    ArrayRef<tooling::Range> Ranges,
34130b57cec5SDimitry Andric                                    StringRef FileName, unsigned *Cursor) {
34140b57cec5SDimitry Andric   tooling::Replacements Replaces;
3415fe6060f1SDimitry Andric   if (!Style.SortIncludes || Style.DisableFormat)
34160b57cec5SDimitry Andric     return Replaces;
34170b57cec5SDimitry Andric   if (isLikelyXml(Code))
34180b57cec5SDimitry Andric     return Replaces;
34190b57cec5SDimitry Andric   if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript &&
342081ad6265SDimitry Andric       isMpegTS(Code)) {
34210b57cec5SDimitry Andric     return Replaces;
342281ad6265SDimitry Andric   }
34230b57cec5SDimitry Andric   if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript)
34240b57cec5SDimitry Andric     return sortJavaScriptImports(Style, Code, Ranges, FileName);
34250b57cec5SDimitry Andric   if (Style.Language == FormatStyle::LanguageKind::LK_Java)
34260b57cec5SDimitry Andric     return sortJavaImports(Style, Code, Ranges, FileName, Replaces);
34270b57cec5SDimitry Andric   sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor);
34280b57cec5SDimitry Andric   return Replaces;
34290b57cec5SDimitry Andric }
34300b57cec5SDimitry Andric 
34310b57cec5SDimitry Andric template <typename T>
34320b57cec5SDimitry Andric static llvm::Expected<tooling::Replacements>
processReplacements(T ProcessFunc,StringRef Code,const tooling::Replacements & Replaces,const FormatStyle & Style)34330b57cec5SDimitry Andric processReplacements(T ProcessFunc, StringRef Code,
34340b57cec5SDimitry Andric                     const tooling::Replacements &Replaces,
34350b57cec5SDimitry Andric                     const FormatStyle &Style) {
34360b57cec5SDimitry Andric   if (Replaces.empty())
34370b57cec5SDimitry Andric     return tooling::Replacements();
34380b57cec5SDimitry Andric 
34390b57cec5SDimitry Andric   auto NewCode = applyAllReplacements(Code, Replaces);
34400b57cec5SDimitry Andric   if (!NewCode)
34410b57cec5SDimitry Andric     return NewCode.takeError();
34420b57cec5SDimitry Andric   std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();
34430b57cec5SDimitry Andric   StringRef FileName = Replaces.begin()->getFilePath();
34440b57cec5SDimitry Andric 
34450b57cec5SDimitry Andric   tooling::Replacements FormatReplaces =
34460b57cec5SDimitry Andric       ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
34470b57cec5SDimitry Andric 
34480b57cec5SDimitry Andric   return Replaces.merge(FormatReplaces);
34490b57cec5SDimitry Andric }
34500b57cec5SDimitry Andric 
34510b57cec5SDimitry Andric llvm::Expected<tooling::Replacements>
formatReplacements(StringRef Code,const tooling::Replacements & Replaces,const FormatStyle & Style)34520b57cec5SDimitry Andric formatReplacements(StringRef Code, const tooling::Replacements &Replaces,
34530b57cec5SDimitry Andric                    const FormatStyle &Style) {
34540b57cec5SDimitry Andric   // We need to use lambda function here since there are two versions of
34550b57cec5SDimitry Andric   // `sortIncludes`.
34560b57cec5SDimitry Andric   auto SortIncludes = [](const FormatStyle &Style, StringRef Code,
34570b57cec5SDimitry Andric                          std::vector<tooling::Range> Ranges,
34580b57cec5SDimitry Andric                          StringRef FileName) -> tooling::Replacements {
34590b57cec5SDimitry Andric     return sortIncludes(Style, Code, Ranges, FileName);
34600b57cec5SDimitry Andric   };
34610b57cec5SDimitry Andric   auto SortedReplaces =
34620b57cec5SDimitry Andric       processReplacements(SortIncludes, Code, Replaces, Style);
34630b57cec5SDimitry Andric   if (!SortedReplaces)
34640b57cec5SDimitry Andric     return SortedReplaces.takeError();
34650b57cec5SDimitry Andric 
34660b57cec5SDimitry Andric   // We need to use lambda function here since there are two versions of
34670b57cec5SDimitry Andric   // `reformat`.
34680b57cec5SDimitry Andric   auto Reformat = [](const FormatStyle &Style, StringRef Code,
34690b57cec5SDimitry Andric                      std::vector<tooling::Range> Ranges,
34700b57cec5SDimitry Andric                      StringRef FileName) -> tooling::Replacements {
34710b57cec5SDimitry Andric     return reformat(Style, Code, Ranges, FileName);
34720b57cec5SDimitry Andric   };
34730b57cec5SDimitry Andric   return processReplacements(Reformat, Code, *SortedReplaces, Style);
34740b57cec5SDimitry Andric }
34750b57cec5SDimitry Andric 
34760b57cec5SDimitry Andric namespace {
34770b57cec5SDimitry Andric 
isHeaderInsertion(const tooling::Replacement & Replace)34780b57cec5SDimitry Andric inline bool isHeaderInsertion(const tooling::Replacement &Replace) {
34790b57cec5SDimitry Andric   return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 &&
3480bdd1243dSDimitry Andric          tooling::HeaderIncludes::IncludeRegex.match(
3481bdd1243dSDimitry Andric              Replace.getReplacementText());
34820b57cec5SDimitry Andric }
34830b57cec5SDimitry Andric 
isHeaderDeletion(const tooling::Replacement & Replace)34840b57cec5SDimitry Andric inline bool isHeaderDeletion(const tooling::Replacement &Replace) {
34850b57cec5SDimitry Andric   return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1;
34860b57cec5SDimitry Andric }
34870b57cec5SDimitry Andric 
34880b57cec5SDimitry Andric // FIXME: insert empty lines between newly created blocks.
34890b57cec5SDimitry Andric tooling::Replacements
fixCppIncludeInsertions(StringRef Code,const tooling::Replacements & Replaces,const FormatStyle & Style)34900b57cec5SDimitry Andric fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
34910b57cec5SDimitry Andric                         const FormatStyle &Style) {
34920b57cec5SDimitry Andric   if (!Style.isCpp())
34930b57cec5SDimitry Andric     return Replaces;
34940b57cec5SDimitry Andric 
34950b57cec5SDimitry Andric   tooling::Replacements HeaderInsertions;
34960b57cec5SDimitry Andric   std::set<llvm::StringRef> HeadersToDelete;
34970b57cec5SDimitry Andric   tooling::Replacements Result;
34980b57cec5SDimitry Andric   for (const auto &R : Replaces) {
34990b57cec5SDimitry Andric     if (isHeaderInsertion(R)) {
35000b57cec5SDimitry Andric       // Replacements from \p Replaces must be conflict-free already, so we can
35010b57cec5SDimitry Andric       // simply consume the error.
35020b57cec5SDimitry Andric       llvm::consumeError(HeaderInsertions.add(R));
35030b57cec5SDimitry Andric     } else if (isHeaderDeletion(R)) {
35040b57cec5SDimitry Andric       HeadersToDelete.insert(R.getReplacementText());
35050b57cec5SDimitry Andric     } else if (R.getOffset() == UINT_MAX) {
35060b57cec5SDimitry Andric       llvm::errs() << "Insertions other than header #include insertion are "
35070b57cec5SDimitry Andric                       "not supported! "
35080b57cec5SDimitry Andric                    << R.getReplacementText() << "\n";
35090b57cec5SDimitry Andric     } else {
35100b57cec5SDimitry Andric       llvm::consumeError(Result.add(R));
35110b57cec5SDimitry Andric     }
35120b57cec5SDimitry Andric   }
35130b57cec5SDimitry Andric   if (HeaderInsertions.empty() && HeadersToDelete.empty())
35140b57cec5SDimitry Andric     return Replaces;
35150b57cec5SDimitry Andric 
35160b57cec5SDimitry Andric   StringRef FileName = Replaces.begin()->getFilePath();
35170b57cec5SDimitry Andric   tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle);
35180b57cec5SDimitry Andric 
35190b57cec5SDimitry Andric   for (const auto &Header : HeadersToDelete) {
35200b57cec5SDimitry Andric     tooling::Replacements Replaces =
35215f757f3fSDimitry Andric         Includes.remove(Header.trim("\"<>"), Header.starts_with("<"));
35220b57cec5SDimitry Andric     for (const auto &R : Replaces) {
35230b57cec5SDimitry Andric       auto Err = Result.add(R);
35240b57cec5SDimitry Andric       if (Err) {
35250b57cec5SDimitry Andric         // Ignore the deletion on conflict.
35260b57cec5SDimitry Andric         llvm::errs() << "Failed to add header deletion replacement for "
35270b57cec5SDimitry Andric                      << Header << ": " << llvm::toString(std::move(Err))
35280b57cec5SDimitry Andric                      << "\n";
35290b57cec5SDimitry Andric       }
35300b57cec5SDimitry Andric     }
35310b57cec5SDimitry Andric   }
35320b57cec5SDimitry Andric 
35330b57cec5SDimitry Andric   llvm::SmallVector<StringRef, 4> Matches;
35340b57cec5SDimitry Andric   for (const auto &R : HeaderInsertions) {
35350b57cec5SDimitry Andric     auto IncludeDirective = R.getReplacementText();
3536bdd1243dSDimitry Andric     bool Matched =
3537bdd1243dSDimitry Andric         tooling::HeaderIncludes::IncludeRegex.match(IncludeDirective, &Matches);
35380b57cec5SDimitry Andric     assert(Matched && "Header insertion replacement must have replacement text "
35390b57cec5SDimitry Andric                       "'#include ...'");
35400b57cec5SDimitry Andric     (void)Matched;
35410b57cec5SDimitry Andric     auto IncludeName = Matches[2];
35420b57cec5SDimitry Andric     auto Replace =
35435f757f3fSDimitry Andric         Includes.insert(IncludeName.trim("\"<>"), IncludeName.starts_with("<"),
3544bdd1243dSDimitry Andric                         tooling::IncludeDirective::Include);
35450b57cec5SDimitry Andric     if (Replace) {
35460b57cec5SDimitry Andric       auto Err = Result.add(*Replace);
35470b57cec5SDimitry Andric       if (Err) {
35480b57cec5SDimitry Andric         llvm::consumeError(std::move(Err));
35490b57cec5SDimitry Andric         unsigned NewOffset =
35500b57cec5SDimitry Andric             Result.getShiftedCodePosition(Replace->getOffset());
35510b57cec5SDimitry Andric         auto Shifted = tooling::Replacement(FileName, NewOffset, 0,
35520b57cec5SDimitry Andric                                             Replace->getReplacementText());
35530b57cec5SDimitry Andric         Result = Result.merge(tooling::Replacements(Shifted));
35540b57cec5SDimitry Andric       }
35550b57cec5SDimitry Andric     }
35560b57cec5SDimitry Andric   }
35570b57cec5SDimitry Andric   return Result;
35580b57cec5SDimitry Andric }
35590b57cec5SDimitry Andric 
35600b57cec5SDimitry Andric } // anonymous namespace
35610b57cec5SDimitry Andric 
35620b57cec5SDimitry Andric llvm::Expected<tooling::Replacements>
cleanupAroundReplacements(StringRef Code,const tooling::Replacements & Replaces,const FormatStyle & Style)35630b57cec5SDimitry Andric cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
35640b57cec5SDimitry Andric                           const FormatStyle &Style) {
35650b57cec5SDimitry Andric   // We need to use lambda function here since there are two versions of
35660b57cec5SDimitry Andric   // `cleanup`.
35670b57cec5SDimitry Andric   auto Cleanup = [](const FormatStyle &Style, StringRef Code,
35680b57cec5SDimitry Andric                     std::vector<tooling::Range> Ranges,
35690b57cec5SDimitry Andric                     StringRef FileName) -> tooling::Replacements {
35700b57cec5SDimitry Andric     return cleanup(Style, Code, Ranges, FileName);
35710b57cec5SDimitry Andric   };
35720b57cec5SDimitry Andric   // Make header insertion replacements insert new headers into correct blocks.
35730b57cec5SDimitry Andric   tooling::Replacements NewReplaces =
35740b57cec5SDimitry Andric       fixCppIncludeInsertions(Code, Replaces, Style);
3575bdd1243dSDimitry Andric   return cantFail(processReplacements(Cleanup, Code, NewReplaces, Style));
35760b57cec5SDimitry Andric }
35770b57cec5SDimitry Andric 
35780b57cec5SDimitry Andric namespace internal {
35790b57cec5SDimitry Andric std::pair<tooling::Replacements, unsigned>
reformat(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,unsigned FirstStartColumn,unsigned NextStartColumn,unsigned LastStartColumn,StringRef FileName,FormattingAttemptStatus * Status)35800b57cec5SDimitry Andric reformat(const FormatStyle &Style, StringRef Code,
35810b57cec5SDimitry Andric          ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,
35820b57cec5SDimitry Andric          unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,
35830b57cec5SDimitry Andric          FormattingAttemptStatus *Status) {
3584349cc55cSDimitry Andric   FormatStyle Expanded = Style;
3585349cc55cSDimitry Andric   expandPresetsBraceWrapping(Expanded);
3586349cc55cSDimitry Andric   expandPresetsSpaceBeforeParens(Expanded);
358706c3fb27SDimitry Andric   expandPresetsSpacesInParens(Expanded);
3588bdd1243dSDimitry Andric   Expanded.InsertBraces = false;
3589bdd1243dSDimitry Andric   Expanded.RemoveBracesLLVM = false;
359006c3fb27SDimitry Andric   Expanded.RemoveParentheses = FormatStyle::RPS_Leave;
3591bdd1243dSDimitry Andric   Expanded.RemoveSemicolon = false;
359281ad6265SDimitry Andric   switch (Expanded.RequiresClausePosition) {
359381ad6265SDimitry Andric   case FormatStyle::RCPS_SingleLine:
359481ad6265SDimitry Andric   case FormatStyle::RCPS_WithPreceding:
359581ad6265SDimitry Andric     Expanded.IndentRequiresClause = false;
359681ad6265SDimitry Andric     break;
359781ad6265SDimitry Andric   default:
359881ad6265SDimitry Andric     break;
359981ad6265SDimitry Andric   }
360081ad6265SDimitry Andric 
36010b57cec5SDimitry Andric   if (Expanded.DisableFormat)
36020b57cec5SDimitry Andric     return {tooling::Replacements(), 0};
36030b57cec5SDimitry Andric   if (isLikelyXml(Code))
36040b57cec5SDimitry Andric     return {tooling::Replacements(), 0};
36050b57cec5SDimitry Andric   if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code))
36060b57cec5SDimitry Andric     return {tooling::Replacements(), 0};
36070b57cec5SDimitry Andric 
3608fe6060f1SDimitry Andric   // JSON only needs the formatting passing.
3609fe6060f1SDimitry Andric   if (Style.isJson()) {
3610fe6060f1SDimitry Andric     std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
36114824e7fdSDimitry Andric     auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
3612fe6060f1SDimitry Andric                                  NextStartColumn, LastStartColumn);
3613349cc55cSDimitry Andric     if (!Env)
3614349cc55cSDimitry Andric       return {};
3615fe6060f1SDimitry Andric     // Perform the actual formatting pass.
3616fe6060f1SDimitry Andric     tooling::Replacements Replaces =
3617fe6060f1SDimitry Andric         Formatter(*Env, Style, Status).process().first;
3618fe6060f1SDimitry Andric     // add a replacement to remove the "x = " from the result.
361906c3fb27SDimitry Andric     Replaces = Replaces.merge(
362006c3fb27SDimitry Andric         tooling::Replacements(tooling::Replacement(FileName, 0, 4, "")));
3621fe6060f1SDimitry Andric     // apply the reformatting changes and the removal of "x = ".
362281ad6265SDimitry Andric     if (applyAllReplacements(Code, Replaces))
3623fe6060f1SDimitry Andric       return {Replaces, 0};
3624fe6060f1SDimitry Andric     return {tooling::Replacements(), 0};
3625fe6060f1SDimitry Andric   }
3626fe6060f1SDimitry Andric 
3627bdd1243dSDimitry Andric   auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
3628bdd1243dSDimitry Andric                                NextStartColumn, LastStartColumn);
3629bdd1243dSDimitry Andric   if (!Env)
3630bdd1243dSDimitry Andric     return {};
3631bdd1243dSDimitry Andric 
36320b57cec5SDimitry Andric   typedef std::function<std::pair<tooling::Replacements, unsigned>(
36330b57cec5SDimitry Andric       const Environment &)>
36340b57cec5SDimitry Andric       AnalyzerPass;
363506c3fb27SDimitry Andric 
363606c3fb27SDimitry Andric   SmallVector<AnalyzerPass, 16> Passes;
36370b57cec5SDimitry Andric 
3638bdd1243dSDimitry Andric   Passes.emplace_back([&](const Environment &Env) {
3639bdd1243dSDimitry Andric     return IntegerLiteralSeparatorFixer().process(Env, Expanded);
3640bdd1243dSDimitry Andric   });
3641bdd1243dSDimitry Andric 
364281ad6265SDimitry Andric   if (Style.isCpp()) {
364306c3fb27SDimitry Andric     if (Style.QualifierAlignment != FormatStyle::QAS_Leave)
364406c3fb27SDimitry Andric       addQualifierAlignmentFixerPasses(Expanded, Passes);
364506c3fb27SDimitry Andric 
364606c3fb27SDimitry Andric     if (Style.RemoveParentheses != FormatStyle::RPS_Leave) {
364706c3fb27SDimitry Andric       FormatStyle S = Expanded;
364806c3fb27SDimitry Andric       S.RemoveParentheses = Style.RemoveParentheses;
364906c3fb27SDimitry Andric       Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
365006c3fb27SDimitry Andric         return ParensRemover(Env, S).process(/*SkipAnnotation=*/true);
3651349cc55cSDimitry Andric       });
3652349cc55cSDimitry Andric     }
3653349cc55cSDimitry Andric 
365481ad6265SDimitry Andric     if (Style.InsertBraces) {
3655bdd1243dSDimitry Andric       FormatStyle S = Expanded;
3656bdd1243dSDimitry Andric       S.InsertBraces = true;
365706c3fb27SDimitry Andric       Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
3658bdd1243dSDimitry Andric         return BracesInserter(Env, S).process(/*SkipAnnotation=*/true);
365981ad6265SDimitry Andric       });
366081ad6265SDimitry Andric     }
366181ad6265SDimitry Andric 
366281ad6265SDimitry Andric     if (Style.RemoveBracesLLVM) {
3663bdd1243dSDimitry Andric       FormatStyle S = Expanded;
3664bdd1243dSDimitry Andric       S.RemoveBracesLLVM = true;
366506c3fb27SDimitry Andric       Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
3666bdd1243dSDimitry Andric         return BracesRemover(Env, S).process(/*SkipAnnotation=*/true);
3667bdd1243dSDimitry Andric       });
3668bdd1243dSDimitry Andric     }
3669bdd1243dSDimitry Andric 
3670bdd1243dSDimitry Andric     if (Style.RemoveSemicolon) {
3671bdd1243dSDimitry Andric       FormatStyle S = Expanded;
3672bdd1243dSDimitry Andric       S.RemoveSemicolon = true;
367306c3fb27SDimitry Andric       Passes.emplace_back([&, S = std::move(S)](const Environment &Env) {
3674bdd1243dSDimitry Andric         return SemiRemover(Env, S).process(/*SkipAnnotation=*/true);
367504eeddc0SDimitry Andric       });
367681ad6265SDimitry Andric     }
367704eeddc0SDimitry Andric 
367881ad6265SDimitry Andric     if (Style.FixNamespaceComments) {
36790b57cec5SDimitry Andric       Passes.emplace_back([&](const Environment &Env) {
36800b57cec5SDimitry Andric         return NamespaceEndCommentsFixer(Env, Expanded).process();
36810b57cec5SDimitry Andric       });
368281ad6265SDimitry Andric     }
36830b57cec5SDimitry Andric 
3684bdd1243dSDimitry Andric     if (Style.SortUsingDeclarations != FormatStyle::SUD_Never) {
36850b57cec5SDimitry Andric       Passes.emplace_back([&](const Environment &Env) {
36860b57cec5SDimitry Andric         return UsingDeclarationsSorter(Env, Expanded).process();
36870b57cec5SDimitry Andric       });
36880b57cec5SDimitry Andric     }
368981ad6265SDimitry Andric   }
36900b57cec5SDimitry Andric 
369181ad6265SDimitry Andric   if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) {
369204eeddc0SDimitry Andric     Passes.emplace_back([&](const Environment &Env) {
369304eeddc0SDimitry Andric       return DefinitionBlockSeparator(Env, Expanded).process();
369404eeddc0SDimitry Andric     });
369581ad6265SDimitry Andric   }
369604eeddc0SDimitry Andric 
36975f757f3fSDimitry Andric   if (Style.Language == FormatStyle::LK_ObjC &&
36985f757f3fSDimitry Andric       !Style.ObjCPropertyAttributeOrder.empty()) {
36995f757f3fSDimitry Andric     Passes.emplace_back([&](const Environment &Env) {
37005f757f3fSDimitry Andric       return ObjCPropertyAttributeOrderFixer(Env, Expanded).process();
37015f757f3fSDimitry Andric     });
37025f757f3fSDimitry Andric   }
37035f757f3fSDimitry Andric 
370481ad6265SDimitry Andric   if (Style.isJavaScript() &&
370581ad6265SDimitry Andric       Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) {
37060b57cec5SDimitry Andric     Passes.emplace_back([&](const Environment &Env) {
3707bdd1243dSDimitry Andric       return JavaScriptRequoter(Env, Expanded).process(/*SkipAnnotation=*/true);
37080b57cec5SDimitry Andric     });
370981ad6265SDimitry Andric   }
37100b57cec5SDimitry Andric 
37110b57cec5SDimitry Andric   Passes.emplace_back([&](const Environment &Env) {
37120b57cec5SDimitry Andric     return Formatter(Env, Expanded, Status).process();
37130b57cec5SDimitry Andric   });
37140b57cec5SDimitry Andric 
37150eae32dcSDimitry Andric   if (Style.isJavaScript() &&
371681ad6265SDimitry Andric       Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) {
37175ffd83dbSDimitry Andric     Passes.emplace_back([&](const Environment &Env) {
37185ffd83dbSDimitry Andric       return TrailingCommaInserter(Env, Expanded).process();
37195ffd83dbSDimitry Andric     });
372081ad6265SDimitry Andric   }
37215ffd83dbSDimitry Andric 
3722bdd1243dSDimitry Andric   std::optional<std::string> CurrentCode;
37230b57cec5SDimitry Andric   tooling::Replacements Fixes;
37240b57cec5SDimitry Andric   unsigned Penalty = 0;
37250b57cec5SDimitry Andric   for (size_t I = 0, E = Passes.size(); I < E; ++I) {
37260b57cec5SDimitry Andric     std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
37270b57cec5SDimitry Andric     auto NewCode = applyAllReplacements(
37280b57cec5SDimitry Andric         CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
37290b57cec5SDimitry Andric     if (NewCode) {
37300b57cec5SDimitry Andric       Fixes = Fixes.merge(PassFixes.first);
37310b57cec5SDimitry Andric       Penalty += PassFixes.second;
37320b57cec5SDimitry Andric       if (I + 1 < E) {
37330b57cec5SDimitry Andric         CurrentCode = std::move(*NewCode);
3734349cc55cSDimitry Andric         Env = Environment::make(
37350b57cec5SDimitry Andric             *CurrentCode, FileName,
37360b57cec5SDimitry Andric             tooling::calculateRangesAfterReplacements(Fixes, Ranges),
37370b57cec5SDimitry Andric             FirstStartColumn, NextStartColumn, LastStartColumn);
3738349cc55cSDimitry Andric         if (!Env)
3739349cc55cSDimitry Andric           return {};
37400b57cec5SDimitry Andric       }
37410b57cec5SDimitry Andric     }
37420b57cec5SDimitry Andric   }
37430b57cec5SDimitry Andric 
374406c3fb27SDimitry Andric   if (Style.QualifierAlignment != FormatStyle::QAS_Leave) {
374506c3fb27SDimitry Andric     // Don't make replacements that replace nothing. QualifierAlignment can
374606c3fb27SDimitry Andric     // produce them if one of its early passes changes e.g. `const volatile` to
374706c3fb27SDimitry Andric     // `volatile const` and then a later pass changes it back again.
374806c3fb27SDimitry Andric     tooling::Replacements NonNoOpFixes;
374906c3fb27SDimitry Andric     for (const tooling::Replacement &Fix : Fixes) {
375006c3fb27SDimitry Andric       StringRef OriginalCode = Code.substr(Fix.getOffset(), Fix.getLength());
375106c3fb27SDimitry Andric       if (!OriginalCode.equals(Fix.getReplacementText())) {
375206c3fb27SDimitry Andric         auto Err = NonNoOpFixes.add(Fix);
375306c3fb27SDimitry Andric         if (Err) {
375406c3fb27SDimitry Andric           llvm::errs() << "Error adding replacements : "
375506c3fb27SDimitry Andric                        << llvm::toString(std::move(Err)) << "\n";
375606c3fb27SDimitry Andric         }
375706c3fb27SDimitry Andric       }
375806c3fb27SDimitry Andric     }
375906c3fb27SDimitry Andric     Fixes = std::move(NonNoOpFixes);
376006c3fb27SDimitry Andric   }
376106c3fb27SDimitry Andric 
37620b57cec5SDimitry Andric   return {Fixes, Penalty};
37630b57cec5SDimitry Andric }
37640b57cec5SDimitry Andric } // namespace internal
37650b57cec5SDimitry Andric 
reformat(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName,FormattingAttemptStatus * Status)37660b57cec5SDimitry Andric tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
37670b57cec5SDimitry Andric                                ArrayRef<tooling::Range> Ranges,
37680b57cec5SDimitry Andric                                StringRef FileName,
37690b57cec5SDimitry Andric                                FormattingAttemptStatus *Status) {
37700b57cec5SDimitry Andric   return internal::reformat(Style, Code, Ranges,
37710b57cec5SDimitry Andric                             /*FirstStartColumn=*/0,
37720b57cec5SDimitry Andric                             /*NextStartColumn=*/0,
37730b57cec5SDimitry Andric                             /*LastStartColumn=*/0, FileName, Status)
37740b57cec5SDimitry Andric       .first;
37750b57cec5SDimitry Andric }
37760b57cec5SDimitry Andric 
cleanup(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName)37770b57cec5SDimitry Andric tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
37780b57cec5SDimitry Andric                               ArrayRef<tooling::Range> Ranges,
37790b57cec5SDimitry Andric                               StringRef FileName) {
37800b57cec5SDimitry Andric   // cleanups only apply to C++ (they mostly concern ctor commas etc.)
37810b57cec5SDimitry Andric   if (Style.Language != FormatStyle::LK_Cpp)
37820b57cec5SDimitry Andric     return tooling::Replacements();
3783349cc55cSDimitry Andric   auto Env = Environment::make(Code, FileName, Ranges);
3784349cc55cSDimitry Andric   if (!Env)
3785349cc55cSDimitry Andric     return {};
3786349cc55cSDimitry Andric   return Cleaner(*Env, Style).process().first;
37870b57cec5SDimitry Andric }
37880b57cec5SDimitry Andric 
reformat(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName,bool * IncompleteFormat)37890b57cec5SDimitry Andric tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
37900b57cec5SDimitry Andric                                ArrayRef<tooling::Range> Ranges,
37910b57cec5SDimitry Andric                                StringRef FileName, bool *IncompleteFormat) {
37920b57cec5SDimitry Andric   FormattingAttemptStatus Status;
37930b57cec5SDimitry Andric   auto Result = reformat(Style, Code, Ranges, FileName, &Status);
37940b57cec5SDimitry Andric   if (!Status.FormatComplete)
37950b57cec5SDimitry Andric     *IncompleteFormat = true;
37960b57cec5SDimitry Andric   return Result;
37970b57cec5SDimitry Andric }
37980b57cec5SDimitry Andric 
fixNamespaceEndComments(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName)37990b57cec5SDimitry Andric tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,
38000b57cec5SDimitry Andric                                               StringRef Code,
38010b57cec5SDimitry Andric                                               ArrayRef<tooling::Range> Ranges,
38020b57cec5SDimitry Andric                                               StringRef FileName) {
3803349cc55cSDimitry Andric   auto Env = Environment::make(Code, FileName, Ranges);
3804349cc55cSDimitry Andric   if (!Env)
3805349cc55cSDimitry Andric     return {};
38064824e7fdSDimitry Andric   return NamespaceEndCommentsFixer(*Env, Style).process().first;
38070b57cec5SDimitry Andric }
38080b57cec5SDimitry Andric 
sortUsingDeclarations(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName)38090b57cec5SDimitry Andric tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
38100b57cec5SDimitry Andric                                             StringRef Code,
38110b57cec5SDimitry Andric                                             ArrayRef<tooling::Range> Ranges,
38120b57cec5SDimitry Andric                                             StringRef FileName) {
3813349cc55cSDimitry Andric   auto Env = Environment::make(Code, FileName, Ranges);
3814349cc55cSDimitry Andric   if (!Env)
3815349cc55cSDimitry Andric     return {};
38164824e7fdSDimitry Andric   return UsingDeclarationsSorter(*Env, Style).process().first;
38170b57cec5SDimitry Andric }
38180b57cec5SDimitry Andric 
getFormattingLangOpts(const FormatStyle & Style)38190b57cec5SDimitry Andric LangOptions getFormattingLangOpts(const FormatStyle &Style) {
38200b57cec5SDimitry Andric   LangOptions LangOpts;
3821a7dea167SDimitry Andric 
3822a7dea167SDimitry Andric   FormatStyle::LanguageStandard LexingStd = Style.Standard;
3823a7dea167SDimitry Andric   if (LexingStd == FormatStyle::LS_Auto)
3824a7dea167SDimitry Andric     LexingStd = FormatStyle::LS_Latest;
3825a7dea167SDimitry Andric   if (LexingStd == FormatStyle::LS_Latest)
3826a7dea167SDimitry Andric     LexingStd = FormatStyle::LS_Cpp20;
38270b57cec5SDimitry Andric   LangOpts.CPlusPlus = 1;
3828a7dea167SDimitry Andric   LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11;
3829a7dea167SDimitry Andric   LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14;
3830a7dea167SDimitry Andric   LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17;
38315ffd83dbSDimitry Andric   LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20;
38325ffd83dbSDimitry Andric   LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20;
383381ad6265SDimitry Andric   // Turning on digraphs in standards before C++0x is error-prone, because e.g.
383481ad6265SDimitry Andric   // the sequence "<::" will be unconditionally treated as "[:".
383581ad6265SDimitry Andric   // Cf. Lexer::LexTokenInternal.
383681ad6265SDimitry Andric   LangOpts.Digraphs = LexingStd >= FormatStyle::LS_Cpp11;
3837a7dea167SDimitry Andric 
38380b57cec5SDimitry Andric   LangOpts.LineComment = 1;
38390b57cec5SDimitry Andric   bool AlternativeOperators = Style.isCpp();
38400b57cec5SDimitry Andric   LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
38410b57cec5SDimitry Andric   LangOpts.Bool = 1;
38420b57cec5SDimitry Andric   LangOpts.ObjC = 1;
38430b57cec5SDimitry Andric   LangOpts.MicrosoftExt = 1;    // To get kw___try, kw___finally.
38440b57cec5SDimitry Andric   LangOpts.DeclSpecKeyword = 1; // To get __declspec.
3845e8d8bef9SDimitry Andric   LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict.
38460b57cec5SDimitry Andric   return LangOpts;
38470b57cec5SDimitry Andric }
38480b57cec5SDimitry Andric 
38490b57cec5SDimitry Andric const char *StyleOptionHelpDescription =
3850753f127fSDimitry Andric     "Set coding style. <string> can be:\n"
3851753f127fSDimitry Andric     "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"
3852753f127fSDimitry Andric     "   Mozilla, WebKit.\n"
3853753f127fSDimitry Andric     "2. 'file' to load style configuration from a\n"
3854753f127fSDimitry Andric     "   .clang-format file in one of the parent directories\n"
3855753f127fSDimitry Andric     "   of the source file (for stdin, see --assume-filename).\n"
3856753f127fSDimitry Andric     "   If no .clang-format file is found, falls back to\n"
3857753f127fSDimitry Andric     "   --fallback-style.\n"
3858753f127fSDimitry Andric     "   --style=file is the default.\n"
3859753f127fSDimitry Andric     "3. 'file:<format_file_path>' to explicitly specify\n"
386004eeddc0SDimitry Andric     "   the configuration file.\n"
3861753f127fSDimitry Andric     "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n"
3862753f127fSDimitry Andric     "   --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
38630b57cec5SDimitry Andric 
getLanguageByFileName(StringRef FileName)38640b57cec5SDimitry Andric static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
38655f757f3fSDimitry Andric   if (FileName.ends_with(".java"))
38660b57cec5SDimitry Andric     return FormatStyle::LK_Java;
386706c3fb27SDimitry Andric   if (FileName.ends_with_insensitive(".js") ||
386806c3fb27SDimitry Andric       FileName.ends_with_insensitive(".mjs") ||
386906c3fb27SDimitry Andric       FileName.ends_with_insensitive(".ts")) {
3870a7dea167SDimitry Andric     return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript.
387181ad6265SDimitry Andric   }
38725f757f3fSDimitry Andric   if (FileName.ends_with(".m") || FileName.ends_with(".mm"))
38730b57cec5SDimitry Andric     return FormatStyle::LK_ObjC;
387406c3fb27SDimitry Andric   if (FileName.ends_with_insensitive(".proto") ||
387506c3fb27SDimitry Andric       FileName.ends_with_insensitive(".protodevel")) {
38760b57cec5SDimitry Andric     return FormatStyle::LK_Proto;
387781ad6265SDimitry Andric   }
387806c3fb27SDimitry Andric   if (FileName.ends_with_insensitive(".textpb") ||
387906c3fb27SDimitry Andric       FileName.ends_with_insensitive(".pb.txt") ||
388006c3fb27SDimitry Andric       FileName.ends_with_insensitive(".textproto") ||
388106c3fb27SDimitry Andric       FileName.ends_with_insensitive(".asciipb")) {
38820b57cec5SDimitry Andric     return FormatStyle::LK_TextProto;
388381ad6265SDimitry Andric   }
388406c3fb27SDimitry Andric   if (FileName.ends_with_insensitive(".td"))
38850b57cec5SDimitry Andric     return FormatStyle::LK_TableGen;
388606c3fb27SDimitry Andric   if (FileName.ends_with_insensitive(".cs"))
38870b57cec5SDimitry Andric     return FormatStyle::LK_CSharp;
388806c3fb27SDimitry Andric   if (FileName.ends_with_insensitive(".json"))
3889fe6060f1SDimitry Andric     return FormatStyle::LK_Json;
389006c3fb27SDimitry Andric   if (FileName.ends_with_insensitive(".sv") ||
389106c3fb27SDimitry Andric       FileName.ends_with_insensitive(".svh") ||
389206c3fb27SDimitry Andric       FileName.ends_with_insensitive(".v") ||
389306c3fb27SDimitry Andric       FileName.ends_with_insensitive(".vh")) {
389481ad6265SDimitry Andric     return FormatStyle::LK_Verilog;
389581ad6265SDimitry Andric   }
38960b57cec5SDimitry Andric   return FormatStyle::LK_Cpp;
38970b57cec5SDimitry Andric }
38980b57cec5SDimitry Andric 
guessLanguage(StringRef FileName,StringRef Code)38990b57cec5SDimitry Andric FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {
39000b57cec5SDimitry Andric   const auto GuessedLanguage = getLanguageByFileName(FileName);
39010b57cec5SDimitry Andric   if (GuessedLanguage == FormatStyle::LK_Cpp) {
39020b57cec5SDimitry Andric     auto Extension = llvm::sys::path::extension(FileName);
39030b57cec5SDimitry Andric     // If there's no file extension (or it's .h), we need to check the contents
39040b57cec5SDimitry Andric     // of the code to see if it contains Objective-C.
39050b57cec5SDimitry Andric     if (Extension.empty() || Extension == ".h") {
39060b57cec5SDimitry Andric       auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName;
39070b57cec5SDimitry Andric       Environment Env(Code, NonEmptyFileName, /*Ranges=*/{});
39080b57cec5SDimitry Andric       ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle());
39090b57cec5SDimitry Andric       Guesser.process();
39100b57cec5SDimitry Andric       if (Guesser.isObjC())
39110b57cec5SDimitry Andric         return FormatStyle::LK_ObjC;
39120b57cec5SDimitry Andric     }
39130b57cec5SDimitry Andric   }
39140b57cec5SDimitry Andric   return GuessedLanguage;
39150b57cec5SDimitry Andric }
39160b57cec5SDimitry Andric 
3917753f127fSDimitry Andric // Update StyleOptionHelpDescription above when changing this.
39180b57cec5SDimitry Andric const char *DefaultFormatStyle = "file";
39190b57cec5SDimitry Andric 
39200b57cec5SDimitry Andric const char *DefaultFallbackStyle = "LLVM";
39210b57cec5SDimitry Andric 
392204eeddc0SDimitry Andric llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
loadAndParseConfigFile(StringRef ConfigFile,llvm::vfs::FileSystem * FS,FormatStyle * Style,bool AllowUnknownOptions)392304eeddc0SDimitry Andric loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS,
392404eeddc0SDimitry Andric                        FormatStyle *Style, bool AllowUnknownOptions) {
392504eeddc0SDimitry Andric   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
392604eeddc0SDimitry Andric       FS->getBufferForFile(ConfigFile.str());
392704eeddc0SDimitry Andric   if (auto EC = Text.getError())
392804eeddc0SDimitry Andric     return EC;
392904eeddc0SDimitry Andric   if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions))
393004eeddc0SDimitry Andric     return EC;
393104eeddc0SDimitry Andric   return Text;
393204eeddc0SDimitry Andric }
393304eeddc0SDimitry Andric 
getStyle(StringRef StyleName,StringRef FileName,StringRef FallbackStyleName,StringRef Code,llvm::vfs::FileSystem * FS,bool AllowUnknownOptions)39340b57cec5SDimitry Andric llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
39350b57cec5SDimitry Andric                                      StringRef FallbackStyleName,
3936e8d8bef9SDimitry Andric                                      StringRef Code, llvm::vfs::FileSystem *FS,
3937e8d8bef9SDimitry Andric                                      bool AllowUnknownOptions) {
39380b57cec5SDimitry Andric   FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code));
39390b57cec5SDimitry Andric   FormatStyle FallbackStyle = getNoStyle();
39400b57cec5SDimitry Andric   if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))
39415f757f3fSDimitry Andric     return make_string_error("Invalid fallback style: " + FallbackStyleName);
39420b57cec5SDimitry Andric 
3943fe6060f1SDimitry Andric   llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1>
3944fe6060f1SDimitry Andric       ChildFormatTextToApply;
3945fe6060f1SDimitry Andric 
39465f757f3fSDimitry Andric   if (StyleName.starts_with("{")) {
39470b57cec5SDimitry Andric     // Parse YAML/JSON style from the command line.
3948fe6060f1SDimitry Andric     StringRef Source = "<command-line>";
3949fe6060f1SDimitry Andric     if (std::error_code ec =
3950fe6060f1SDimitry Andric             parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style,
395181ad6265SDimitry Andric                                AllowUnknownOptions)) {
39520b57cec5SDimitry Andric       return make_string_error("Error parsing -style: " + ec.message());
395381ad6265SDimitry Andric     }
39545f757f3fSDimitry Andric 
39555f757f3fSDimitry Andric     if (!Style.InheritsParentConfig)
39565f757f3fSDimitry Andric       return Style;
39575f757f3fSDimitry Andric 
3958fe6060f1SDimitry Andric     ChildFormatTextToApply.emplace_back(
3959fe6060f1SDimitry Andric         llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false));
39600b57cec5SDimitry Andric   }
39615f757f3fSDimitry Andric 
39625f757f3fSDimitry Andric   if (!FS)
39635f757f3fSDimitry Andric     FS = llvm::vfs::getRealFileSystem().get();
39645f757f3fSDimitry Andric   assert(FS);
39650b57cec5SDimitry Andric 
396604eeddc0SDimitry Andric   // User provided clang-format file using -style=file:path/to/format/file.
396704eeddc0SDimitry Andric   if (!Style.InheritsParentConfig &&
396806c3fb27SDimitry Andric       StyleName.starts_with_insensitive("file:")) {
396904eeddc0SDimitry Andric     auto ConfigFile = StyleName.substr(5);
397004eeddc0SDimitry Andric     llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
397104eeddc0SDimitry Andric         loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions);
397281ad6265SDimitry Andric     if (auto EC = Text.getError()) {
397304eeddc0SDimitry Andric       return make_string_error("Error reading " + ConfigFile + ": " +
397404eeddc0SDimitry Andric                                EC.message());
397581ad6265SDimitry Andric     }
397604eeddc0SDimitry Andric 
397704eeddc0SDimitry Andric     LLVM_DEBUG(llvm::dbgs()
397804eeddc0SDimitry Andric                << "Using configuration file " << ConfigFile << "\n");
397904eeddc0SDimitry Andric 
398004eeddc0SDimitry Andric     if (!Style.InheritsParentConfig)
398104eeddc0SDimitry Andric       return Style;
398204eeddc0SDimitry Andric 
398304eeddc0SDimitry Andric     // Search for parent configs starting from the parent directory of
398404eeddc0SDimitry Andric     // ConfigFile.
398504eeddc0SDimitry Andric     FileName = ConfigFile;
398604eeddc0SDimitry Andric     ChildFormatTextToApply.emplace_back(std::move(*Text));
398704eeddc0SDimitry Andric   }
398804eeddc0SDimitry Andric 
3989fe6060f1SDimitry Andric   // If the style inherits the parent configuration it is a command line
3990fe6060f1SDimitry Andric   // configuration, which wants to inherit, so we have to skip the check of the
3991fe6060f1SDimitry Andric   // StyleName.
3992fe6060f1SDimitry Andric   if (!Style.InheritsParentConfig && !StyleName.equals_insensitive("file")) {
39930b57cec5SDimitry Andric     if (!getPredefinedStyle(StyleName, Style.Language, &Style))
39940b57cec5SDimitry Andric       return make_string_error("Invalid value for -style");
3995fe6060f1SDimitry Andric     if (!Style.InheritsParentConfig)
39960b57cec5SDimitry Andric       return Style;
39970b57cec5SDimitry Andric   }
39980b57cec5SDimitry Andric 
39990b57cec5SDimitry Andric   SmallString<128> Path(FileName);
40000b57cec5SDimitry Andric   if (std::error_code EC = FS->makeAbsolute(Path))
40010b57cec5SDimitry Andric     return make_string_error(EC.message());
40020b57cec5SDimitry Andric 
40035f757f3fSDimitry Andric   // Reset possible inheritance
40045f757f3fSDimitry Andric   Style.InheritsParentConfig = false;
4005480093f4SDimitry Andric 
4006fe6060f1SDimitry Andric   auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {};
4007fe6060f1SDimitry Andric 
400804eeddc0SDimitry Andric   auto applyChildFormatTexts = [&](FormatStyle *Style) {
400904eeddc0SDimitry Andric     for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) {
401004eeddc0SDimitry Andric       auto EC = parseConfiguration(*MemBuf, Style, AllowUnknownOptions,
401104eeddc0SDimitry Andric                                    dropDiagnosticHandler);
401204eeddc0SDimitry Andric       // It was already correctly parsed.
401304eeddc0SDimitry Andric       assert(!EC);
401404eeddc0SDimitry Andric       static_cast<void>(EC);
401504eeddc0SDimitry Andric     }
401604eeddc0SDimitry Andric   };
401704eeddc0SDimitry Andric 
40185f757f3fSDimitry Andric   // Look for .clang-format/_clang-format file in the file's parent directories.
40195f757f3fSDimitry Andric   llvm::SmallVector<std::string, 2> FilesToLookFor;
40205f757f3fSDimitry Andric   FilesToLookFor.push_back(".clang-format");
40215f757f3fSDimitry Andric   FilesToLookFor.push_back("_clang-format");
40225f757f3fSDimitry Andric 
40235f757f3fSDimitry Andric   SmallString<128> UnsuitableConfigFiles;
40240b57cec5SDimitry Andric   for (StringRef Directory = Path; !Directory.empty();
40250b57cec5SDimitry Andric        Directory = llvm::sys::path::parent_path(Directory)) {
40260b57cec5SDimitry Andric     auto Status = FS->status(Directory);
40270b57cec5SDimitry Andric     if (!Status ||
40280b57cec5SDimitry Andric         Status->getType() != llvm::sys::fs::file_type::directory_file) {
40290b57cec5SDimitry Andric       continue;
40300b57cec5SDimitry Andric     }
40310b57cec5SDimitry Andric 
4032480093f4SDimitry Andric     for (const auto &F : FilesToLookFor) {
40330b57cec5SDimitry Andric       SmallString<128> ConfigFile(Directory);
40340b57cec5SDimitry Andric 
4035480093f4SDimitry Andric       llvm::sys::path::append(ConfigFile, F);
40360b57cec5SDimitry Andric       LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
40370b57cec5SDimitry Andric 
40385f757f3fSDimitry Andric       Status = FS->status(ConfigFile);
40395f757f3fSDimitry Andric       if (!Status ||
40405f757f3fSDimitry Andric           Status->getType() != llvm::sys::fs::file_type::regular_file) {
40415f757f3fSDimitry Andric         continue;
40425f757f3fSDimitry Andric       }
40430b57cec5SDimitry Andric 
40440b57cec5SDimitry Andric       llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
404504eeddc0SDimitry Andric           loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions);
404604eeddc0SDimitry Andric       if (auto EC = Text.getError()) {
40475f757f3fSDimitry Andric         if (EC != ParseError::Unsuitable) {
40485f757f3fSDimitry Andric           return make_string_error("Error reading " + ConfigFile + ": " +
40495f757f3fSDimitry Andric                                    EC.message());
40505f757f3fSDimitry Andric         }
40510b57cec5SDimitry Andric         if (!UnsuitableConfigFiles.empty())
40520b57cec5SDimitry Andric           UnsuitableConfigFiles.append(", ");
40530b57cec5SDimitry Andric         UnsuitableConfigFiles.append(ConfigFile);
40540b57cec5SDimitry Andric         continue;
40550b57cec5SDimitry Andric       }
40565f757f3fSDimitry Andric 
40570b57cec5SDimitry Andric       LLVM_DEBUG(llvm::dbgs()
40580b57cec5SDimitry Andric                  << "Using configuration file " << ConfigFile << "\n");
4059fe6060f1SDimitry Andric 
4060fe6060f1SDimitry Andric       if (!Style.InheritsParentConfig) {
40615f757f3fSDimitry Andric         if (!ChildFormatTextToApply.empty()) {
4062fe6060f1SDimitry Andric           LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n");
406304eeddc0SDimitry Andric           applyChildFormatTexts(&Style);
40645f757f3fSDimitry Andric         }
4065fe6060f1SDimitry Andric         return Style;
4066fe6060f1SDimitry Andric       }
4067fe6060f1SDimitry Andric 
4068fe6060f1SDimitry Andric       LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n");
4069fe6060f1SDimitry Andric 
4070fe6060f1SDimitry Andric       // Reset inheritance of style
4071fe6060f1SDimitry Andric       Style.InheritsParentConfig = false;
4072fe6060f1SDimitry Andric 
4073fe6060f1SDimitry Andric       ChildFormatTextToApply.emplace_back(std::move(*Text));
4074fe6060f1SDimitry Andric 
4075fe6060f1SDimitry Andric       // Breaking out of the inner loop, since we don't want to parse
4076fe6060f1SDimitry Andric       // .clang-format AND _clang-format, if both exist. Then we continue the
40775f757f3fSDimitry Andric       // outer loop (parent directories) in search for the parent
4078fe6060f1SDimitry Andric       // configuration.
4079fe6060f1SDimitry Andric       break;
40800b57cec5SDimitry Andric     }
40810b57cec5SDimitry Andric   }
40825f757f3fSDimitry Andric 
408381ad6265SDimitry Andric   if (!UnsuitableConfigFiles.empty()) {
40840b57cec5SDimitry Andric     return make_string_error("Configuration file(s) do(es) not support " +
40850b57cec5SDimitry Andric                              getLanguageName(Style.Language) + ": " +
40860b57cec5SDimitry Andric                              UnsuitableConfigFiles);
408781ad6265SDimitry Andric   }
4088fe6060f1SDimitry Andric 
4089fe6060f1SDimitry Andric   if (!ChildFormatTextToApply.empty()) {
4090fe6060f1SDimitry Andric     LLVM_DEBUG(llvm::dbgs()
409104eeddc0SDimitry Andric                << "Applying child configurations on fallback style\n");
409204eeddc0SDimitry Andric     applyChildFormatTexts(&FallbackStyle);
4093fe6060f1SDimitry Andric   }
4094fe6060f1SDimitry Andric 
40950b57cec5SDimitry Andric   return FallbackStyle;
40960b57cec5SDimitry Andric }
40970b57cec5SDimitry Andric 
isClangFormatOnOff(StringRef Comment,bool On)409806c3fb27SDimitry Andric static bool isClangFormatOnOff(StringRef Comment, bool On) {
409906c3fb27SDimitry Andric   if (Comment == (On ? "/* clang-format on */" : "/* clang-format off */"))
410006c3fb27SDimitry Andric     return true;
410106c3fb27SDimitry Andric 
410206c3fb27SDimitry Andric   static const char ClangFormatOn[] = "// clang-format on";
410306c3fb27SDimitry Andric   static const char ClangFormatOff[] = "// clang-format off";
410406c3fb27SDimitry Andric   const unsigned Size = (On ? sizeof ClangFormatOn : sizeof ClangFormatOff) - 1;
410506c3fb27SDimitry Andric 
41065f757f3fSDimitry Andric   return Comment.starts_with(On ? ClangFormatOn : ClangFormatOff) &&
410706c3fb27SDimitry Andric          (Comment.size() == Size || Comment[Size] == ':');
410806c3fb27SDimitry Andric }
410906c3fb27SDimitry Andric 
isClangFormatOn(StringRef Comment)411006c3fb27SDimitry Andric bool isClangFormatOn(StringRef Comment) {
411106c3fb27SDimitry Andric   return isClangFormatOnOff(Comment, /*On=*/true);
411206c3fb27SDimitry Andric }
411306c3fb27SDimitry Andric 
isClangFormatOff(StringRef Comment)411406c3fb27SDimitry Andric bool isClangFormatOff(StringRef Comment) {
411506c3fb27SDimitry Andric   return isClangFormatOnOff(Comment, /*On=*/false);
411606c3fb27SDimitry Andric }
411706c3fb27SDimitry Andric 
41180b57cec5SDimitry Andric } // namespace format
41190b57cec5SDimitry Andric } // namespace clang
4120