1f7935115SDaniel Jasper //===--- Format.cpp - Format C++ code -------------------------------------===//
2f7935115SDaniel Jasper //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f7935115SDaniel Jasper //
7f7935115SDaniel Jasper //===----------------------------------------------------------------------===//
8f7935115SDaniel Jasper ///
9f7935115SDaniel Jasper /// \file
109fc8faf9SAdrian Prantl /// This file implements functions declared in Format.h. This will be
11f7935115SDaniel Jasper /// split into separate files as we go.
12f7935115SDaniel Jasper ///
13f7935115SDaniel Jasper //===----------------------------------------------------------------------===//
14f7935115SDaniel Jasper 
1585c472dcSDaniel Jasper #include "clang/Format/Format.h"
164cfb88a9SEric Liu #include "AffectedRangeManager.h"
179520bf14SJonathan Coe #include "BreakableToken.h"
18de0328aeSDaniel Jasper #include "ContinuationIndenter.h"
196f6f88ffSksyx #include "DefinitionBlockSeparator.h"
209ad83fe7SKrasimir Georgiev #include "FormatInternal.h"
21acc3ce94SSam McCall #include "FormatToken.h"
22c4a0dd49SMartin Probst #include "FormatTokenLexer.h"
237cb267afSKrasimir Georgiev #include "NamespaceEndCommentsFixer.h"
24a44ab170Smydeveloperday #include "QualifierAlignmentFixer.h"
25c4a0dd49SMartin Probst #include "SortJavaScriptImports.h"
26c4a0dd49SMartin Probst #include "TokenAnalyzer.h"
277a6d09b3SDaniel Jasper #include "TokenAnnotator.h"
280df50938SDaniel Jasper #include "UnwrappedLineFormatter.h"
293a02247dSChandler Carruth #include "UnwrappedLineParser.h"
30b03877abSKrasimir Georgiev #include "UsingDeclarationsSorter.h"
31cb45bc18SAlexander Kornienko #include "WhitespaceManager.h"
32ec04c0dbSDaniel Jasper #include "clang/Basic/Diagnostic.h"
33f3ca2698SBenjamin Kramer #include "clang/Basic/DiagnosticOptions.h"
3444eb4f66SChandler Carruth #include "clang/Basic/SourceManager.h"
35f7935115SDaniel Jasper #include "clang/Lex/Lexer.h"
3644564ac7SEric Liu #include "clang/Tooling/Inclusions/HeaderIncludes.h"
37ffd6d04aSAlexander Kornienko #include "llvm/ADT/STLExtras.h"
3861f09bcfSMarek Kurdej #include "llvm/ADT/Sequence.h"
39e2e3e67cSBen Hamilton #include "llvm/ADT/StringRef.h"
402ef908e4SManuel Klimek #include "llvm/Support/Allocator.h"
4124998104SManuel Klimek #include "llvm/Support/Debug.h"
42d544aa79SEdwin Vane #include "llvm/Support/Path.h"
43b001a0baSBirunthan Mohanathas #include "llvm/Support/Regex.h"
44fc51490bSJonas Devlieghere #include "llvm/Support/VirtualFileSystem.h"
455553d0d4SChandler Carruth #include "llvm/Support/YAMLTraits.h"
46081f176aSMartin Probst #include <algorithm>
474cfb88a9SEric Liu #include <memory>
48bf4c41c7SEric Liu #include <mutex>
498b529711SDaniel Jasper #include <string>
50bf4c41c7SEric Liu #include <unordered_map>
518b529711SDaniel Jasper 
5210346667SChandler Carruth #define DEBUG_TYPE "format-formatter"
5310346667SChandler Carruth 
546d2c88eaSAlexander Kornienko using clang::format::FormatStyle;
556d2c88eaSAlexander Kornienko 
56057a942dSNAKAMURA Takumi LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat)
57e1e4319aSDaniel Jasper 
58d6538338SAlexander Kornienko namespace llvm {
59d6538338SAlexander Kornienko namespace yaml {
606d2c88eaSAlexander Kornienko template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
enumerationllvm::yaml::ScalarEnumerationTraits616d2c88eaSAlexander Kornienko   static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
626d2c88eaSAlexander Kornienko     IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
63c58c70e2SDaniel Jasper     IO.enumCase(Value, "Java", FormatStyle::LK_Java);
646d2c88eaSAlexander Kornienko     IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
6503a04fe9SDaniel Jasper     IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);
667052ce6dSDaniel Jasper     IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
67498f558fSDaniel Jasper     IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);
6826b144ccSKrasimir Georgiev     IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto);
69cbb726d0SPaul Hoad     IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp);
708b7881a0Smydeveloperday     IO.enumCase(Value, "Json", FormatStyle::LK_Json);
716d2c88eaSAlexander Kornienko   }
726d2c88eaSAlexander Kornienko };
736d2c88eaSAlexander Kornienko 
746d2c88eaSAlexander Kornienko template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
enumerationllvm::yaml::ScalarEnumerationTraits756d2c88eaSAlexander Kornienko   static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
76e5032567SSam McCall     IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03);
77e5032567SSam McCall     IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias
78e5032567SSam McCall     IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias
79e5032567SSam McCall 
80e5032567SSam McCall     IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11);
81e5032567SSam McCall     IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias
82e5032567SSam McCall 
83e5032567SSam McCall     IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14);
84e5032567SSam McCall     IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17);
85e5032567SSam McCall     IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20);
86e5032567SSam McCall 
87e5032567SSam McCall     IO.enumCase(Value, "Latest", FormatStyle::LS_Latest);
88e5032567SSam McCall     IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias
896d2c88eaSAlexander Kornienko     IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);
906d2c88eaSAlexander Kornienko   }
916d2c88eaSAlexander Kornienko };
926d2c88eaSAlexander Kornienko 
9364cf5ebaSVitali Lovich template <>
9464cf5ebaSVitali Lovich struct ScalarEnumerationTraits<FormatStyle::LambdaBodyIndentationKind> {
enumerationllvm::yaml::ScalarEnumerationTraits9564cf5ebaSVitali Lovich   static void enumeration(IO &IO,
9664cf5ebaSVitali Lovich                           FormatStyle::LambdaBodyIndentationKind &Value) {
9764cf5ebaSVitali Lovich     IO.enumCase(Value, "Signature", FormatStyle::LBI_Signature);
9864cf5ebaSVitali Lovich     IO.enumCase(Value, "OuterScope", FormatStyle::LBI_OuterScope);
9964cf5ebaSVitali Lovich   }
10064cf5ebaSVitali Lovich };
10164cf5ebaSVitali Lovich 
1026d2c88eaSAlexander Kornienko template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits1036d2c88eaSAlexander Kornienko   static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {
1046d2c88eaSAlexander Kornienko     IO.enumCase(Value, "Never", FormatStyle::UT_Never);
1056d2c88eaSAlexander Kornienko     IO.enumCase(Value, "false", FormatStyle::UT_Never);
1066d2c88eaSAlexander Kornienko     IO.enumCase(Value, "Always", FormatStyle::UT_Always);
1076d2c88eaSAlexander Kornienko     IO.enumCase(Value, "true", FormatStyle::UT_Always);
1086d2c88eaSAlexander Kornienko     IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation);
10951fe279fSMarianne Mailhot-Sarrasin     IO.enumCase(Value, "ForContinuationAndIndentation",
11051fe279fSMarianne Mailhot-Sarrasin                 FormatStyle::UT_ForContinuationAndIndentation);
111e8111502Smydeveloperday     IO.enumCase(Value, "AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);
1126d2c88eaSAlexander Kornienko   }
1136d2c88eaSAlexander Kornienko };
1146d2c88eaSAlexander Kornienko 
115abd1f574SDaniel Jasper template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits116abd1f574SDaniel Jasper   static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) {
117abd1f574SDaniel Jasper     IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave);
118abd1f574SDaniel Jasper     IO.enumCase(Value, "Single", FormatStyle::JSQS_Single);
119abd1f574SDaniel Jasper     IO.enumCase(Value, "Double", FormatStyle::JSQS_Double);
120abd1f574SDaniel Jasper   }
121abd1f574SDaniel Jasper };
122abd1f574SDaniel Jasper 
12310234da7SOwen Pan template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits12410234da7SOwen Pan   static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) {
12510234da7SOwen Pan     IO.enumCase(Value, "Never", FormatStyle::SBS_Never);
12610234da7SOwen Pan     IO.enumCase(Value, "false", FormatStyle::SBS_Never);
12710234da7SOwen Pan     IO.enumCase(Value, "Always", FormatStyle::SBS_Always);
12810234da7SOwen Pan     IO.enumCase(Value, "true", FormatStyle::SBS_Always);
12910234da7SOwen Pan     IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty);
13010234da7SOwen Pan   }
13110234da7SOwen Pan };
13210234da7SOwen Pan 
133a44ab170Smydeveloperday template <>
134a44ab170Smydeveloperday struct ScalarEnumerationTraits<FormatStyle::QualifierAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits135a44ab170Smydeveloperday   static void enumeration(IO &IO, FormatStyle::QualifierAlignmentStyle &Value) {
136a44ab170Smydeveloperday     IO.enumCase(Value, "Leave", FormatStyle::QAS_Leave);
137a44ab170Smydeveloperday     IO.enumCase(Value, "Left", FormatStyle::QAS_Left);
138a44ab170Smydeveloperday     IO.enumCase(Value, "Right", FormatStyle::QAS_Right);
139a44ab170Smydeveloperday     IO.enumCase(Value, "Custom", FormatStyle::QAS_Custom);
140a44ab170Smydeveloperday   }
141a44ab170Smydeveloperday };
142a44ab170Smydeveloperday 
143d74cf403SDaniel Jasper template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits144d74cf403SDaniel Jasper   static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
145d74cf403SDaniel Jasper     IO.enumCase(Value, "None", FormatStyle::SFS_None);
146d74cf403SDaniel Jasper     IO.enumCase(Value, "false", FormatStyle::SFS_None);
147d74cf403SDaniel Jasper     IO.enumCase(Value, "All", FormatStyle::SFS_All);
148d74cf403SDaniel Jasper     IO.enumCase(Value, "true", FormatStyle::SFS_All);
149d74cf403SDaniel Jasper     IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
150d3f0e3deSFrancois Ferrand     IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly);
1519e709351SDaniel Jasper     IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);
152d74cf403SDaniel Jasper   }
153d74cf403SDaniel Jasper };
154d74cf403SDaniel Jasper 
155c24b3db4Ssstwcw template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {
enumInputllvm::yaml::MappingTraits156c24b3db4Ssstwcw   static void enumInput(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
157c24b3db4Ssstwcw     IO.enumCase(Value, "None",
158c24b3db4Ssstwcw                 FormatStyle::AlignConsecutiveStyle(
159c24b3db4Ssstwcw                     {/*Enabled=*/false, /*AcrossEmptyLines=*/false,
160c24b3db4Ssstwcw                      /*AcrossComments=*/false, /*AlignCompound=*/false,
161c24b3db4Ssstwcw                      /*PadOperators=*/true}));
162c24b3db4Ssstwcw     IO.enumCase(Value, "Consecutive",
163c24b3db4Ssstwcw                 FormatStyle::AlignConsecutiveStyle(
164c24b3db4Ssstwcw                     {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
165c24b3db4Ssstwcw                      /*AcrossComments=*/false, /*AlignCompound=*/false,
166c24b3db4Ssstwcw                      /*PadOperators=*/true}));
167c24b3db4Ssstwcw     IO.enumCase(Value, "AcrossEmptyLines",
168c24b3db4Ssstwcw                 FormatStyle::AlignConsecutiveStyle(
169c24b3db4Ssstwcw                     {/*Enabled=*/true, /*AcrossEmptyLines=*/true,
170c24b3db4Ssstwcw                      /*AcrossComments=*/false, /*AlignCompound=*/false,
171c24b3db4Ssstwcw                      /*PadOperators=*/true}));
172c24b3db4Ssstwcw     IO.enumCase(Value, "AcrossComments",
173c24b3db4Ssstwcw                 FormatStyle::AlignConsecutiveStyle({/*Enabled=*/true,
174c24b3db4Ssstwcw                                                     /*AcrossEmptyLines=*/false,
175c24b3db4Ssstwcw                                                     /*AcrossComments=*/true,
176c24b3db4Ssstwcw                                                     /*AlignCompound=*/false,
177c24b3db4Ssstwcw                                                     /*PadOperators=*/true}));
17825631471SLukas Barth     IO.enumCase(Value, "AcrossEmptyLinesAndComments",
179c24b3db4Ssstwcw                 FormatStyle::AlignConsecutiveStyle({/*Enabled=*/true,
180c24b3db4Ssstwcw                                                     /*AcrossEmptyLines=*/true,
181c24b3db4Ssstwcw                                                     /*AcrossComments=*/true,
182c24b3db4Ssstwcw                                                     /*AlignCompound=*/false,
183c24b3db4Ssstwcw                                                     /*PadOperators=*/true}));
18425631471SLukas Barth 
185f1191705SNico Weber     // For backward compatibility.
186c24b3db4Ssstwcw     IO.enumCase(Value, "true",
187c24b3db4Ssstwcw                 FormatStyle::AlignConsecutiveStyle(
188c24b3db4Ssstwcw                     {/*Enabled=*/true, /*AcrossEmptyLines=*/false,
189c24b3db4Ssstwcw                      /*AcrossComments=*/false, /*AlignCompound=*/false,
190c24b3db4Ssstwcw                      /*PadOperators=*/true}));
191c24b3db4Ssstwcw     IO.enumCase(Value, "false",
192c24b3db4Ssstwcw                 FormatStyle::AlignConsecutiveStyle(
193c24b3db4Ssstwcw                     {/*Enabled=*/false, /*AcrossEmptyLines=*/false,
194c24b3db4Ssstwcw                      /*AcrossComments=*/false, /*AlignCompound=*/false,
195c24b3db4Ssstwcw                      /*PadOperators=*/true}));
196c24b3db4Ssstwcw   }
197c24b3db4Ssstwcw 
mappingllvm::yaml::MappingTraits198c24b3db4Ssstwcw   static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
199c24b3db4Ssstwcw     IO.mapOptional("Enabled", Value.Enabled);
200c24b3db4Ssstwcw     IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);
201c24b3db4Ssstwcw     IO.mapOptional("AcrossComments", Value.AcrossComments);
202c24b3db4Ssstwcw     IO.mapOptional("AlignCompound", Value.AlignCompound);
203c24b3db4Ssstwcw     IO.mapOptional("PadOperators", Value.PadOperators);
20425631471SLukas Barth   }
20525631471SLukas Barth };
20625631471SLukas Barth 
207673c5ba5SFred Grim template <>
208673c5ba5SFred Grim struct ScalarEnumerationTraits<FormatStyle::ArrayInitializerAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits209673c5ba5SFred Grim   static void enumeration(IO &IO,
210673c5ba5SFred Grim                           FormatStyle::ArrayInitializerAlignmentStyle &Value) {
211673c5ba5SFred Grim     IO.enumCase(Value, "None", FormatStyle::AIAS_None);
212673c5ba5SFred Grim     IO.enumCase(Value, "Left", FormatStyle::AIAS_Left);
213673c5ba5SFred Grim     IO.enumCase(Value, "Right", FormatStyle::AIAS_Right);
214673c5ba5SFred Grim   }
215673c5ba5SFred Grim };
216673c5ba5SFred Grim 
21715000a12SPaul Hoad template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits21815000a12SPaul Hoad   static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) {
21915000a12SPaul Hoad     IO.enumCase(Value, "Never", FormatStyle::SIS_Never);
22015000a12SPaul Hoad     IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse);
2218d93d7ffSMarek Kurdej     IO.enumCase(Value, "OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf);
2228d93d7ffSMarek Kurdej     IO.enumCase(Value, "AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse);
22315000a12SPaul Hoad 
22415000a12SPaul Hoad     // For backward compatibility.
2258d93d7ffSMarek Kurdej     IO.enumCase(Value, "Always", FormatStyle::SIS_OnlyFirstIf);
22615000a12SPaul Hoad     IO.enumCase(Value, "false", FormatStyle::SIS_Never);
22715000a12SPaul Hoad     IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse);
22815000a12SPaul Hoad   }
22915000a12SPaul Hoad };
23015000a12SPaul Hoad 
231a83e2dbbSRonald Wampler template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits232a83e2dbbSRonald Wampler   static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) {
233a83e2dbbSRonald Wampler     IO.enumCase(Value, "None", FormatStyle::SLS_None);
234a83e2dbbSRonald Wampler     IO.enumCase(Value, "false", FormatStyle::SLS_None);
235a83e2dbbSRonald Wampler     IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty);
236a83e2dbbSRonald Wampler     IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline);
237a83e2dbbSRonald Wampler     IO.enumCase(Value, "All", FormatStyle::SLS_All);
238a83e2dbbSRonald Wampler     IO.enumCase(Value, "true", FormatStyle::SLS_All);
239a83e2dbbSRonald Wampler   }
240a83e2dbbSRonald Wampler };
241a83e2dbbSRonald Wampler 
2424dc658caSBen Hamilton template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits2434dc658caSBen Hamilton   static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) {
2444dc658caSBen Hamilton     IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto);
2454dc658caSBen Hamilton     IO.enumCase(Value, "Always", FormatStyle::BPS_Always);
2464dc658caSBen Hamilton     IO.enumCase(Value, "Never", FormatStyle::BPS_Never);
2474dc658caSBen Hamilton   }
2484dc658caSBen Hamilton };
2494dc658caSBen Hamilton 
250a324fcf1SMartin Probst template <> struct ScalarEnumerationTraits<FormatStyle::TrailingCommaStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits251a324fcf1SMartin Probst   static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) {
252a324fcf1SMartin Probst     IO.enumCase(Value, "None", FormatStyle::TCS_None);
253a324fcf1SMartin Probst     IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped);
254a324fcf1SMartin Probst   }
255a324fcf1SMartin Probst };
256a324fcf1SMartin Probst 
257ac043c90SDaniel Jasper template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits258ac043c90SDaniel Jasper   static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {
259ac043c90SDaniel Jasper     IO.enumCase(Value, "All", FormatStyle::BOS_All);
260ac043c90SDaniel Jasper     IO.enumCase(Value, "true", FormatStyle::BOS_All);
261ac043c90SDaniel Jasper     IO.enumCase(Value, "None", FormatStyle::BOS_None);
262ac043c90SDaniel Jasper     IO.enumCase(Value, "false", FormatStyle::BOS_None);
263ac043c90SDaniel Jasper     IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment);
264ac043c90SDaniel Jasper   }
265ac043c90SDaniel Jasper };
266ac043c90SDaniel Jasper 
2676d2c88eaSAlexander Kornienko template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits2686d2c88eaSAlexander Kornienko   static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {
2696d2c88eaSAlexander Kornienko     IO.enumCase(Value, "Attach", FormatStyle::BS_Attach);
2706d2c88eaSAlexander Kornienko     IO.enumCase(Value, "Linux", FormatStyle::BS_Linux);
271305fa9c2SBirunthan Mohanathas     IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla);
2726d2c88eaSAlexander Kornienko     IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);
2736d2c88eaSAlexander Kornienko     IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
274a506ed25SPaul Hoad     IO.enumCase(Value, "Whitesmiths", FormatStyle::BS_Whitesmiths);
2753a33f029SAlexander Kornienko     IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
276291f64fdSRoman Kashitsyn     IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit);
277c1bc38edSDaniel Jasper     IO.enumCase(Value, "Custom", FormatStyle::BS_Custom);
2786d2c88eaSAlexander Kornienko   }
2796d2c88eaSAlexander Kornienko };
2806d2c88eaSAlexander Kornienko 
28189628f64SManuel Klimek template <>
282fb13e65aSPaul Hoad struct ScalarEnumerationTraits<
283fb13e65aSPaul Hoad     FormatStyle::BraceWrappingAfterControlStatementStyle> {
284fb13e65aSPaul Hoad   static void
enumerationllvm::yaml::ScalarEnumerationTraits285fb13e65aSPaul Hoad   enumeration(IO &IO,
286fb13e65aSPaul Hoad               FormatStyle::BraceWrappingAfterControlStatementStyle &Value) {
287fb13e65aSPaul Hoad     IO.enumCase(Value, "Never", FormatStyle::BWACS_Never);
288fb13e65aSPaul Hoad     IO.enumCase(Value, "MultiLine", FormatStyle::BWACS_MultiLine);
289fb13e65aSPaul Hoad     IO.enumCase(Value, "Always", FormatStyle::BWACS_Always);
29057332269Smydeveloperday 
29157332269Smydeveloperday     // For backward compatibility.
29257332269Smydeveloperday     IO.enumCase(Value, "false", FormatStyle::BWACS_Never);
29357332269Smydeveloperday     IO.enumCase(Value, "true", FormatStyle::BWACS_Always);
294fb13e65aSPaul Hoad   }
295fb13e65aSPaul Hoad };
296fb13e65aSPaul Hoad 
297fb13e65aSPaul Hoad template <>
2989aab0db1SBjörn Schäpers struct ScalarEnumerationTraits<
2999aab0db1SBjörn Schäpers     FormatStyle::BreakBeforeConceptDeclarationsStyle> {
3009aab0db1SBjörn Schäpers   static void
enumerationllvm::yaml::ScalarEnumerationTraits3019aab0db1SBjörn Schäpers   enumeration(IO &IO, FormatStyle::BreakBeforeConceptDeclarationsStyle &Value) {
3029aab0db1SBjörn Schäpers     IO.enumCase(Value, "Never", FormatStyle::BBCDS_Never);
3039aab0db1SBjörn Schäpers     IO.enumCase(Value, "Allowed", FormatStyle::BBCDS_Allowed);
3049aab0db1SBjörn Schäpers     IO.enumCase(Value, "Always", FormatStyle::BBCDS_Always);
3059aab0db1SBjörn Schäpers 
3069aab0db1SBjörn Schäpers     // For backward compatibility.
3079aab0db1SBjörn Schäpers     IO.enumCase(Value, "true", FormatStyle::BBCDS_Always);
3089aab0db1SBjörn Schäpers     IO.enumCase(Value, "false", FormatStyle::BBCDS_Allowed);
3099aab0db1SBjörn Schäpers   }
3109aab0db1SBjörn Schäpers };
3119aab0db1SBjörn Schäpers 
3129aab0db1SBjörn Schäpers template <>
31389628f64SManuel Klimek struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
31489628f64SManuel Klimek   static void
enumerationllvm::yaml::ScalarEnumerationTraits31589628f64SManuel Klimek   enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
316a6b6d51bSFrancois Ferrand     IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon);
317a6b6d51bSFrancois Ferrand     IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma);
318a6b6d51bSFrancois Ferrand     IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon);
319a6b6d51bSFrancois Ferrand   }
320a6b6d51bSFrancois Ferrand };
321a6b6d51bSFrancois Ferrand 
322c1bc38edSDaniel Jasper template <>
3236bb103f9SFrancois Ferrand struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits3245bcf99b4SPaul Hoad   static void enumeration(IO &IO,
3255bcf99b4SPaul Hoad                           FormatStyle::BreakInheritanceListStyle &Value) {
3266bb103f9SFrancois Ferrand     IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon);
3276bb103f9SFrancois Ferrand     IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma);
3286bb103f9SFrancois Ferrand     IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon);
32909b75f48SZhihao Yuan     IO.enumCase(Value, "AfterComma", FormatStyle::BILS_AfterComma);
3306bb103f9SFrancois Ferrand   }
3316bb103f9SFrancois Ferrand };
3326bb103f9SFrancois Ferrand 
3336bb103f9SFrancois Ferrand template <>
3348a780a2fSowenca struct ScalarEnumerationTraits<FormatStyle::PackConstructorInitializersStyle> {
3358a780a2fSowenca   static void
enumerationllvm::yaml::ScalarEnumerationTraits3368a780a2fSowenca   enumeration(IO &IO, FormatStyle::PackConstructorInitializersStyle &Value) {
3378a780a2fSowenca     IO.enumCase(Value, "Never", FormatStyle::PCIS_Never);
3388a780a2fSowenca     IO.enumCase(Value, "BinPack", FormatStyle::PCIS_BinPack);
3398a780a2fSowenca     IO.enumCase(Value, "CurrentLine", FormatStyle::PCIS_CurrentLine);
3408a780a2fSowenca     IO.enumCase(Value, "NextLine", FormatStyle::PCIS_NextLine);
3418a780a2fSowenca   }
3428a780a2fSowenca };
3438a780a2fSowenca 
3448a780a2fSowenca template <>
345dda978eeSMax Sagebaum struct ScalarEnumerationTraits<FormatStyle::EmptyLineAfterAccessModifierStyle> {
346dda978eeSMax Sagebaum   static void
enumerationllvm::yaml::ScalarEnumerationTraits347dda978eeSMax Sagebaum   enumeration(IO &IO, FormatStyle::EmptyLineAfterAccessModifierStyle &Value) {
348dda978eeSMax Sagebaum     IO.enumCase(Value, "Never", FormatStyle::ELAAMS_Never);
349dda978eeSMax Sagebaum     IO.enumCase(Value, "Leave", FormatStyle::ELAAMS_Leave);
350dda978eeSMax Sagebaum     IO.enumCase(Value, "Always", FormatStyle::ELAAMS_Always);
351dda978eeSMax Sagebaum   }
352dda978eeSMax Sagebaum };
353dda978eeSMax Sagebaum 
354dda978eeSMax Sagebaum template <>
35560bf5826SAlbertas Vyšniauskas struct ScalarEnumerationTraits<
35660bf5826SAlbertas Vyšniauskas     FormatStyle::EmptyLineBeforeAccessModifierStyle> {
35760bf5826SAlbertas Vyšniauskas   static void
enumerationllvm::yaml::ScalarEnumerationTraits35860bf5826SAlbertas Vyšniauskas   enumeration(IO &IO, FormatStyle::EmptyLineBeforeAccessModifierStyle &Value) {
35960bf5826SAlbertas Vyšniauskas     IO.enumCase(Value, "Never", FormatStyle::ELBAMS_Never);
36060bf5826SAlbertas Vyšniauskas     IO.enumCase(Value, "Leave", FormatStyle::ELBAMS_Leave);
36160bf5826SAlbertas Vyšniauskas     IO.enumCase(Value, "LogicalBlock", FormatStyle::ELBAMS_LogicalBlock);
36260bf5826SAlbertas Vyšniauskas     IO.enumCase(Value, "Always", FormatStyle::ELBAMS_Always);
36360bf5826SAlbertas Vyšniauskas   }
36460bf5826SAlbertas Vyšniauskas };
36560bf5826SAlbertas Vyšniauskas 
36660bf5826SAlbertas Vyšniauskas template <>
367ad47c907SKrasimir Georgiev struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits368ad47c907SKrasimir Georgiev   static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
369ad47c907SKrasimir Georgiev     IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
370ad47c907SKrasimir Georgiev     IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);
371701a0d7eSPaul Hoad     IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash);
372ad47c907SKrasimir Georgiev   }
373ad47c907SKrasimir Georgiev };
374ad47c907SKrasimir Georgiev 
375ad47c907SKrasimir Georgiev template <>
3766ef45b04Smydeveloperday struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits3776ef45b04Smydeveloperday   static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value) {
3786ef45b04Smydeveloperday     IO.enumCase(Value, "AfterExternBlock", FormatStyle::IEBS_AfterExternBlock);
3796ef45b04Smydeveloperday     IO.enumCase(Value, "Indent", FormatStyle::IEBS_Indent);
3806ef45b04Smydeveloperday     IO.enumCase(Value, "NoIndent", FormatStyle::IEBS_NoIndent);
3816ef45b04Smydeveloperday     IO.enumCase(Value, "true", FormatStyle::IEBS_Indent);
3826ef45b04Smydeveloperday     IO.enumCase(Value, "false", FormatStyle::IEBS_NoIndent);
3836ef45b04Smydeveloperday   }
3846ef45b04Smydeveloperday };
3856ef45b04Smydeveloperday 
3866ef45b04Smydeveloperday template <>
387448592eeSZachary Turner struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits388448592eeSZachary Turner   static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
389448592eeSZachary Turner     IO.enumCase(Value, "None", FormatStyle::RTBS_None);
390448592eeSZachary Turner     IO.enumCase(Value, "All", FormatStyle::RTBS_All);
391448592eeSZachary Turner     IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel);
392448592eeSZachary Turner     IO.enumCase(Value, "TopLevelDefinitions",
393448592eeSZachary Turner                 FormatStyle::RTBS_TopLevelDefinitions);
394448592eeSZachary Turner     IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions);
395448592eeSZachary Turner   }
396448592eeSZachary Turner };
397448592eeSZachary Turner 
398448592eeSZachary Turner template <>
39958e6fe5bSFrancois Ferrand struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits4005bcf99b4SPaul Hoad   static void enumeration(IO &IO,
4015bcf99b4SPaul Hoad                           FormatStyle::BreakTemplateDeclarationsStyle &Value) {
40258e6fe5bSFrancois Ferrand     IO.enumCase(Value, "No", FormatStyle::BTDS_No);
40358e6fe5bSFrancois Ferrand     IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);
40458e6fe5bSFrancois Ferrand     IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);
40558e6fe5bSFrancois Ferrand 
40658e6fe5bSFrancois Ferrand     // For backward compatibility.
40758e6fe5bSFrancois Ferrand     IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine);
40858e6fe5bSFrancois Ferrand     IO.enumCase(Value, "true", FormatStyle::BTDS_Yes);
40958e6fe5bSFrancois Ferrand   }
41058e6fe5bSFrancois Ferrand };
41158e6fe5bSFrancois Ferrand 
41258e6fe5bSFrancois Ferrand template <>
413c1bc38edSDaniel Jasper struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
414c1bc38edSDaniel Jasper   static void
enumerationllvm::yaml::ScalarEnumerationTraits415c1bc38edSDaniel Jasper   enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
416a0388a8aSBirunthan Mohanathas     IO.enumCase(Value, "None", FormatStyle::DRTBS_None);
417a0388a8aSBirunthan Mohanathas     IO.enumCase(Value, "All", FormatStyle::DRTBS_All);
418a0388a8aSBirunthan Mohanathas     IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel);
419a0388a8aSBirunthan Mohanathas 
420a0388a8aSBirunthan Mohanathas     // For backward compatibility.
421a0388a8aSBirunthan Mohanathas     IO.enumCase(Value, "false", FormatStyle::DRTBS_None);
422a0388a8aSBirunthan Mohanathas     IO.enumCase(Value, "true", FormatStyle::DRTBS_All);
423a0388a8aSBirunthan Mohanathas   }
424a0388a8aSBirunthan Mohanathas };
425a0388a8aSBirunthan Mohanathas 
426d6538338SAlexander Kornienko template <>
4276d2c88eaSAlexander Kornienko struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
enumerationllvm::yaml::ScalarEnumerationTraits428cabdd738SAlexander Kornienko   static void enumeration(IO &IO,
4296d2c88eaSAlexander Kornienko                           FormatStyle::NamespaceIndentationKind &Value) {
4306d2c88eaSAlexander Kornienko     IO.enumCase(Value, "None", FormatStyle::NI_None);
4316d2c88eaSAlexander Kornienko     IO.enumCase(Value, "Inner", FormatStyle::NI_Inner);
4326d2c88eaSAlexander Kornienko     IO.enumCase(Value, "All", FormatStyle::NI_All);
433cabdd738SAlexander Kornienko   }
434cabdd738SAlexander Kornienko };
435cabdd738SAlexander Kornienko 
4366501f7e8SDaniel Jasper template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits4376501f7e8SDaniel Jasper   static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) {
4386501f7e8SDaniel Jasper     IO.enumCase(Value, "Align", FormatStyle::BAS_Align);
4396501f7e8SDaniel Jasper     IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign);
4406501f7e8SDaniel Jasper     IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak);
441966f24e5SCameron Mulhern     IO.enumCase(Value, "BlockIndent", FormatStyle::BAS_BlockIndent);
4426501f7e8SDaniel Jasper 
4436501f7e8SDaniel Jasper     // For backward compatibility.
4446501f7e8SDaniel Jasper     IO.enumCase(Value, "true", FormatStyle::BAS_Align);
4456501f7e8SDaniel Jasper     IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign);
4466501f7e8SDaniel Jasper   }
4476501f7e8SDaniel Jasper };
4486501f7e8SDaniel Jasper 
44989628f64SManuel Klimek template <>
45089628f64SManuel Klimek struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits45189628f64SManuel Klimek   static void enumeration(IO &IO,
45289628f64SManuel Klimek                           FormatStyle::EscapedNewlineAlignmentStyle &Value) {
4537fdbb3feSDaniel Jasper     IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign);
4547fdbb3feSDaniel Jasper     IO.enumCase(Value, "Left", FormatStyle::ENAS_Left);
4557fdbb3feSDaniel Jasper     IO.enumCase(Value, "Right", FormatStyle::ENAS_Right);
4567fdbb3feSDaniel Jasper 
4577fdbb3feSDaniel Jasper     // For backward compatibility.
4587fdbb3feSDaniel Jasper     IO.enumCase(Value, "true", FormatStyle::ENAS_Left);
4597fdbb3feSDaniel Jasper     IO.enumCase(Value, "false", FormatStyle::ENAS_Right);
4607fdbb3feSDaniel Jasper   }
4617fdbb3feSDaniel Jasper };
4627fdbb3feSDaniel Jasper 
4630ee04e6eSFrancois Ferrand template <> struct ScalarEnumerationTraits<FormatStyle::OperandAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits4640ee04e6eSFrancois Ferrand   static void enumeration(IO &IO, FormatStyle::OperandAlignmentStyle &Value) {
4650ee04e6eSFrancois Ferrand     IO.enumCase(Value, "DontAlign", FormatStyle::OAS_DontAlign);
4660ee04e6eSFrancois Ferrand     IO.enumCase(Value, "Align", FormatStyle::OAS_Align);
4670ee04e6eSFrancois Ferrand     IO.enumCase(Value, "AlignAfterOperator",
4680ee04e6eSFrancois Ferrand                 FormatStyle::OAS_AlignAfterOperator);
4690ee04e6eSFrancois Ferrand 
4700ee04e6eSFrancois Ferrand     // For backward compatibility.
4710ee04e6eSFrancois Ferrand     IO.enumCase(Value, "true", FormatStyle::OAS_Align);
4720ee04e6eSFrancois Ferrand     IO.enumCase(Value, "false", FormatStyle::OAS_DontAlign);
4730ee04e6eSFrancois Ferrand   }
4740ee04e6eSFrancois Ferrand };
4750ee04e6eSFrancois Ferrand 
476fc275112SJacques Pienaar template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits477fc275112SJacques Pienaar   static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {
478553d4878SDaniel Jasper     IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
479553d4878SDaniel Jasper     IO.enumCase(Value, "Left", FormatStyle::PAS_Left);
480553d4878SDaniel Jasper     IO.enumCase(Value, "Right", FormatStyle::PAS_Right);
481553d4878SDaniel Jasper 
482958027b6SAlp Toker     // For backward compatibility.
483553d4878SDaniel Jasper     IO.enumCase(Value, "true", FormatStyle::PAS_Left);
484553d4878SDaniel Jasper     IO.enumCase(Value, "false", FormatStyle::PAS_Right);
485553d4878SDaniel Jasper   }
486553d4878SDaniel Jasper };
487553d4878SDaniel Jasper 
488553d4878SDaniel Jasper template <>
4896f6f88ffSksyx struct ScalarEnumerationTraits<FormatStyle::SeparateDefinitionStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits4906f6f88ffSksyx   static void enumeration(IO &IO, FormatStyle::SeparateDefinitionStyle &Value) {
4916f6f88ffSksyx     IO.enumCase(Value, "Leave", FormatStyle::SDS_Leave);
4926f6f88ffSksyx     IO.enumCase(Value, "Always", FormatStyle::SDS_Always);
4936f6f88ffSksyx     IO.enumCase(Value, "Never", FormatStyle::SDS_Never);
4946f6f88ffSksyx   }
4956f6f88ffSksyx };
4966f6f88ffSksyx 
4976f6f88ffSksyx template <>
4989e27f383SAlex Richardson struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> {
4999e27f383SAlex Richardson   static void
enumerationllvm::yaml::ScalarEnumerationTraits5009e27f383SAlex Richardson   enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value) {
5019e27f383SAlex Richardson     IO.enumCase(Value, "Default", FormatStyle::SAPQ_Default);
5029e27f383SAlex Richardson     IO.enumCase(Value, "Before", FormatStyle::SAPQ_Before);
5039e27f383SAlex Richardson     IO.enumCase(Value, "After", FormatStyle::SAPQ_After);
5049e27f383SAlex Richardson     IO.enumCase(Value, "Both", FormatStyle::SAPQ_Both);
5059e27f383SAlex Richardson   }
5069e27f383SAlex Richardson };
5079e27f383SAlex Richardson 
5089e27f383SAlex Richardson template <>
509a08fa8a5SSeraphime Kirkovski struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits510a08fa8a5SSeraphime Kirkovski   static void enumeration(IO &IO, FormatStyle::ReferenceAlignmentStyle &Value) {
511a08fa8a5SSeraphime Kirkovski     IO.enumCase(Value, "Pointer", FormatStyle::RAS_Pointer);
512a08fa8a5SSeraphime Kirkovski     IO.enumCase(Value, "Middle", FormatStyle::RAS_Middle);
513a08fa8a5SSeraphime Kirkovski     IO.enumCase(Value, "Left", FormatStyle::RAS_Left);
514a08fa8a5SSeraphime Kirkovski     IO.enumCase(Value, "Right", FormatStyle::RAS_Right);
515a08fa8a5SSeraphime Kirkovski   }
516a08fa8a5SSeraphime Kirkovski };
517a08fa8a5SSeraphime Kirkovski 
518a08fa8a5SSeraphime Kirkovski template <>
5199aab0db1SBjörn Schäpers struct ScalarEnumerationTraits<FormatStyle::RequiresClausePositionStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits5209aab0db1SBjörn Schäpers   static void enumeration(IO &IO,
5219aab0db1SBjörn Schäpers                           FormatStyle::RequiresClausePositionStyle &Value) {
5229aab0db1SBjörn Schäpers     IO.enumCase(Value, "OwnLine", FormatStyle::RCPS_OwnLine);
5239aab0db1SBjörn Schäpers     IO.enumCase(Value, "WithPreceding", FormatStyle::RCPS_WithPreceding);
5249aab0db1SBjörn Schäpers     IO.enumCase(Value, "WithFollowing", FormatStyle::RCPS_WithFollowing);
5259aab0db1SBjörn Schäpers     IO.enumCase(Value, "SingleLine", FormatStyle::RCPS_SingleLine);
5269aab0db1SBjörn Schäpers   }
5279aab0db1SBjörn Schäpers };
5289aab0db1SBjörn Schäpers 
5299aab0db1SBjörn Schäpers template <>
5306facafe7SC. Rayroud struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits5316facafe7SC. Rayroud   static void enumeration(IO &IO, FormatStyle::SpaceBeforeParensStyle &Value) {
5326d2c88eaSAlexander Kornienko     IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
533fdca83d4SAlexander Kornienko     IO.enumCase(Value, "ControlStatements",
5346d2c88eaSAlexander Kornienko                 FormatStyle::SBPO_ControlStatements);
535be9a87feSVitali Lovich     IO.enumCase(Value, "ControlStatementsExceptControlMacros",
536be9a87feSVitali Lovich                 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
53708a940d6SReuben Thomas     IO.enumCase(Value, "NonEmptyParentheses",
53808a940d6SReuben Thomas                 FormatStyle::SBPO_NonEmptyParentheses);
5396d2c88eaSAlexander Kornienko     IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
5406facafe7SC. Rayroud     IO.enumCase(Value, "Custom", FormatStyle::SBPO_Custom);
541fdca83d4SAlexander Kornienko 
542fdca83d4SAlexander Kornienko     // For backward compatibility.
5436d2c88eaSAlexander Kornienko     IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
5446d2c88eaSAlexander Kornienko     IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);
545be9a87feSVitali Lovich     IO.enumCase(Value, "ControlStatementsExceptForEachMacros",
546be9a87feSVitali Lovich                 FormatStyle::SBPO_ControlStatementsExceptControlMacros);
547fdca83d4SAlexander Kornienko   }
548fdca83d4SAlexander Kornienko };
549fdca83d4SAlexander Kornienko 
55052ab7aa0SAnders Waldenborg template <>
55152ab7aa0SAnders Waldenborg struct ScalarEnumerationTraits<FormatStyle::BitFieldColonSpacingStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits55252ab7aa0SAnders Waldenborg   static void enumeration(IO &IO,
55352ab7aa0SAnders Waldenborg                           FormatStyle::BitFieldColonSpacingStyle &Value) {
55452ab7aa0SAnders Waldenborg     IO.enumCase(Value, "Both", FormatStyle::BFCS_Both);
55552ab7aa0SAnders Waldenborg     IO.enumCase(Value, "None", FormatStyle::BFCS_None);
55652ab7aa0SAnders Waldenborg     IO.enumCase(Value, "Before", FormatStyle::BFCS_Before);
55752ab7aa0SAnders Waldenborg     IO.enumCase(Value, "After", FormatStyle::BFCS_After);
55852ab7aa0SAnders Waldenborg   }
55952ab7aa0SAnders Waldenborg };
56052ab7aa0SAnders Waldenborg 
561a8105b37SKent Sommer template <> struct ScalarEnumerationTraits<FormatStyle::SortIncludesOptions> {
enumerationllvm::yaml::ScalarEnumerationTraits562a8105b37SKent Sommer   static void enumeration(IO &IO, FormatStyle::SortIncludesOptions &Value) {
563a8105b37SKent Sommer     IO.enumCase(Value, "Never", FormatStyle::SI_Never);
564a8105b37SKent Sommer     IO.enumCase(Value, "CaseInsensitive", FormatStyle::SI_CaseInsensitive);
565a8105b37SKent Sommer     IO.enumCase(Value, "CaseSensitive", FormatStyle::SI_CaseSensitive);
566a8105b37SKent Sommer 
567a8105b37SKent Sommer     // For backward compatibility.
568a8105b37SKent Sommer     IO.enumCase(Value, "false", FormatStyle::SI_Never);
5697b02794fSBjörn Schäpers     IO.enumCase(Value, "true", FormatStyle::SI_CaseSensitive);
570a8105b37SKent Sommer   }
571a8105b37SKent Sommer };
572a8105b37SKent Sommer 
5732e7add81Smydeveloperday template <>
5742e7add81Smydeveloperday struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> {
enumerationllvm::yaml::ScalarEnumerationTraits5752e7add81Smydeveloperday   static void enumeration(IO &IO,
5762e7add81Smydeveloperday                           FormatStyle::SortJavaStaticImportOptions &Value) {
5772e7add81Smydeveloperday     IO.enumCase(Value, "Before", FormatStyle::SJSIO_Before);
5782e7add81Smydeveloperday     IO.enumCase(Value, "After", FormatStyle::SJSIO_After);
5792e7add81Smydeveloperday   }
5802e7add81Smydeveloperday };
5812e7add81Smydeveloperday 
5829363aa90SMarek Kurdej template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits5839363aa90SMarek Kurdej   static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value) {
5849363aa90SMarek Kurdej     IO.enumCase(Value, "Never", FormatStyle::SIAS_Never);
5859363aa90SMarek Kurdej     IO.enumCase(Value, "Always", FormatStyle::SIAS_Always);
5869363aa90SMarek Kurdej     IO.enumCase(Value, "Leave", FormatStyle::SIAS_Leave);
5879363aa90SMarek Kurdej 
5889363aa90SMarek Kurdej     // For backward compatibility.
5899363aa90SMarek Kurdej     IO.enumCase(Value, "false", FormatStyle::SIAS_Never);
5909363aa90SMarek Kurdej     IO.enumCase(Value, "true", FormatStyle::SIAS_Always);
5919363aa90SMarek Kurdej   }
5929363aa90SMarek Kurdej };
5939363aa90SMarek Kurdej 
5946d2c88eaSAlexander Kornienko template <> struct MappingTraits<FormatStyle> {
mappingllvm::yaml::MappingTraits595c1637f16SAlexander Kornienko   static void mapping(IO &IO, FormatStyle &Style) {
596c1637f16SAlexander Kornienko     // When reading, read the language first, we need it for getPredefinedStyle.
597c1637f16SAlexander Kornienko     IO.mapOptional("Language", Style.Language);
598c1637f16SAlexander Kornienko 
59949149677SAlexander Kornienko     if (IO.outputting()) {
600545317cbSMarek Kurdej       StringRef Styles[] = {"LLVM",   "Google", "Chromium", "Mozilla",
601cbb726d0SPaul Hoad                             "WebKit", "GNU",    "Microsoft"};
602545317cbSMarek Kurdej       for (StringRef StyleName : Styles) {
6036d2c88eaSAlexander Kornienko         FormatStyle PredefinedStyle;
604c1637f16SAlexander Kornienko         if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) &&
605006b5c89SAlexander Kornienko             Style == PredefinedStyle) {
60649149677SAlexander Kornienko           IO.mapOptional("# BasedOnStyle", StyleName);
60749149677SAlexander Kornienko           break;
60849149677SAlexander Kornienko         }
60949149677SAlexander Kornienko       }
61049149677SAlexander Kornienko     } else {
611d6538338SAlexander Kornienko       StringRef BasedOnStyle;
612d6538338SAlexander Kornienko       IO.mapOptional("BasedOnStyle", BasedOnStyle);
613cabdd738SAlexander Kornienko       if (!BasedOnStyle.empty()) {
614c1637f16SAlexander Kornienko         FormatStyle::LanguageKind OldLanguage = Style.Language;
615c1637f16SAlexander Kornienko         FormatStyle::LanguageKind Language =
616c1637f16SAlexander Kornienko             ((FormatStyle *)IO.getContext())->Language;
617c1637f16SAlexander Kornienko         if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
618006b5c89SAlexander Kornienko           IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle));
619006b5c89SAlexander Kornienko           return;
620006b5c89SAlexander Kornienko         }
621c1637f16SAlexander Kornienko         Style.Language = OldLanguage;
622cabdd738SAlexander Kornienko       }
623d6538338SAlexander Kornienko     }
624d6538338SAlexander Kornienko 
62550a6f915SBirunthan Mohanathas     // For backward compatibility.
62650a6f915SBirunthan Mohanathas     if (!IO.outputting()) {
6277fdbb3feSDaniel Jasper       IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines);
62850a6f915SBirunthan Mohanathas       IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
62950a6f915SBirunthan Mohanathas       IO.mapOptional("IndentFunctionDeclarationAfterType",
63050a6f915SBirunthan Mohanathas                      Style.IndentWrappedFunctionNames);
6319aab0db1SBjörn Schäpers       IO.mapOptional("IndentRequires", Style.IndentRequiresClause);
63250a6f915SBirunthan Mohanathas       IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
63350a6f915SBirunthan Mohanathas       IO.mapOptional("SpaceAfterControlStatementKeyword",
63450a6f915SBirunthan Mohanathas                      Style.SpaceBeforeParens);
63550a6f915SBirunthan Mohanathas     }
63650a6f915SBirunthan Mohanathas 
637d6538338SAlexander Kornienko     IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
6383aa9a6a1SDaniel Jasper     IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
639673c5ba5SFred Grim     IO.mapOptional("AlignArrayOfStructures", Style.AlignArrayOfStructures);
64035cfbd79SBirunthan Mohanathas     IO.mapOptional("AlignConsecutiveAssignments",
64135cfbd79SBirunthan Mohanathas                    Style.AlignConsecutiveAssignments);
642b99bf0e0Smydeveloperday     IO.mapOptional("AlignConsecutiveBitFields",
643b99bf0e0Smydeveloperday                    Style.AlignConsecutiveBitFields);
644e12597ccSDaniel Jasper     IO.mapOptional("AlignConsecutiveDeclarations",
645e12597ccSDaniel Jasper                    Style.AlignConsecutiveDeclarations);
646c24b3db4Ssstwcw     IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);
6477fdbb3feSDaniel Jasper     IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines);
6483219e43cSDaniel Jasper     IO.mapOptional("AlignOperands", Style.AlignOperands);
649552f4a7eSDaniel Jasper     IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
650c6deae45SPaul Hoad     IO.mapOptional("AllowAllArgumentsOnNextLine",
651c6deae45SPaul Hoad                    Style.AllowAllArgumentsOnNextLine);
652d6538338SAlexander Kornienko     IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
653d6538338SAlexander Kornienko                    Style.AllowAllParametersOfDeclarationOnNextLine);
654292058a5SAaron Smith     IO.mapOptional("AllowShortEnumsOnASingleLine",
655292058a5SAaron Smith                    Style.AllowShortEnumsOnASingleLine);
65617605d39SDaniel Jasper     IO.mapOptional("AllowShortBlocksOnASingleLine",
65717605d39SDaniel Jasper                    Style.AllowShortBlocksOnASingleLine);
658b87899b5SDaniel Jasper     IO.mapOptional("AllowShortCaseLabelsOnASingleLine",
659b87899b5SDaniel Jasper                    Style.AllowShortCaseLabelsOnASingleLine);
66035cfbd79SBirunthan Mohanathas     IO.mapOptional("AllowShortFunctionsOnASingleLine",
66135cfbd79SBirunthan Mohanathas                    Style.AllowShortFunctionsOnASingleLine);
662a83e2dbbSRonald Wampler     IO.mapOptional("AllowShortLambdasOnASingleLine",
663a83e2dbbSRonald Wampler                    Style.AllowShortLambdasOnASingleLine);
664d6538338SAlexander Kornienko     IO.mapOptional("AllowShortIfStatementsOnASingleLine",
665d6538338SAlexander Kornienko                    Style.AllowShortIfStatementsOnASingleLine);
6663a685df7SDaniel Jasper     IO.mapOptional("AllowShortLoopsOnASingleLine",
6673a685df7SDaniel Jasper                    Style.AllowShortLoopsOnASingleLine);
668ca4ea1ceSDaniel Jasper     IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",
669ca4ea1ceSDaniel Jasper                    Style.AlwaysBreakAfterDefinitionReturnType);
670448592eeSZachary Turner     IO.mapOptional("AlwaysBreakAfterReturnType",
671448592eeSZachary Turner                    Style.AlwaysBreakAfterReturnType);
672c6deae45SPaul Hoad 
673448592eeSZachary Turner     // If AlwaysBreakAfterDefinitionReturnType was specified but
674448592eeSZachary Turner     // AlwaysBreakAfterReturnType was not, initialize the latter from the
675448592eeSZachary Turner     // former for backwards compatibility.
676448592eeSZachary Turner     if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&
677448592eeSZachary Turner         Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) {
678bebf7bdfSowenca       if (Style.AlwaysBreakAfterDefinitionReturnType ==
679bebf7bdfSowenca           FormatStyle::DRTBS_All) {
680448592eeSZachary Turner         Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
681bebf7bdfSowenca       } else if (Style.AlwaysBreakAfterDefinitionReturnType ==
682bebf7bdfSowenca                  FormatStyle::DRTBS_TopLevel) {
683448592eeSZachary Turner         Style.AlwaysBreakAfterReturnType =
684448592eeSZachary Turner             FormatStyle::RTBS_TopLevelDefinitions;
685448592eeSZachary Turner       }
686bebf7bdfSowenca     }
687448592eeSZachary Turner 
68858611718SAlexander Kornienko     IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
68958611718SAlexander Kornienko                    Style.AlwaysBreakBeforeMultilineStrings);
69035cfbd79SBirunthan Mohanathas     IO.mapOptional("AlwaysBreakTemplateDeclarations",
69135cfbd79SBirunthan Mohanathas                    Style.AlwaysBreakTemplateDeclarations);
692e7bd058cSAlex Richardson     IO.mapOptional("AttributeMacros", Style.AttributeMacros);
69335cfbd79SBirunthan Mohanathas     IO.mapOptional("BinPackArguments", Style.BinPackArguments);
69435cfbd79SBirunthan Mohanathas     IO.mapOptional("BinPackParameters", Style.BinPackParameters);
695c1bc38edSDaniel Jasper     IO.mapOptional("BraceWrapping", Style.BraceWrapping);
696e33d4afaSDaniel Jasper     IO.mapOptional("BreakBeforeBinaryOperators",
697e33d4afaSDaniel Jasper                    Style.BreakBeforeBinaryOperators);
698840e651dSmydeveloperday     IO.mapOptional("BreakBeforeConceptDeclarations",
699840e651dSmydeveloperday                    Style.BreakBeforeConceptDeclarations);
70035cfbd79SBirunthan Mohanathas     IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
7016bb103f9SFrancois Ferrand 
7026bb103f9SFrancois Ferrand     bool BreakBeforeInheritanceComma = false;
7035bcf99b4SPaul Hoad     IO.mapOptional("BreakBeforeInheritanceComma", BreakBeforeInheritanceComma);
7045bcf99b4SPaul Hoad     IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList);
7056bb103f9SFrancois Ferrand     // If BreakBeforeInheritanceComma was specified but
7066bb103f9SFrancois Ferrand     // BreakInheritance was not, initialize the latter from the
7076bb103f9SFrancois Ferrand     // former for backwards compatibility.
7086bb103f9SFrancois Ferrand     if (BreakBeforeInheritanceComma &&
709bebf7bdfSowenca         Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon) {
7106bb103f9SFrancois Ferrand       Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
711bebf7bdfSowenca     }
7126bb103f9SFrancois Ferrand 
713165b29e2SDaniel Jasper     IO.mapOptional("BreakBeforeTernaryOperators",
714165b29e2SDaniel Jasper                    Style.BreakBeforeTernaryOperators);
715a6b6d51bSFrancois Ferrand 
716a6b6d51bSFrancois Ferrand     bool BreakConstructorInitializersBeforeComma = false;
717e33d4afaSDaniel Jasper     IO.mapOptional("BreakConstructorInitializersBeforeComma",
718a6b6d51bSFrancois Ferrand                    BreakConstructorInitializersBeforeComma);
719a6b6d51bSFrancois Ferrand     IO.mapOptional("BreakConstructorInitializers",
720a6b6d51bSFrancois Ferrand                    Style.BreakConstructorInitializers);
721a6b6d51bSFrancois Ferrand     // If BreakConstructorInitializersBeforeComma was specified but
722a6b6d51bSFrancois Ferrand     // BreakConstructorInitializers was not, initialize the latter from the
723a6b6d51bSFrancois Ferrand     // former for backwards compatibility.
724a6b6d51bSFrancois Ferrand     if (BreakConstructorInitializersBeforeComma &&
725bebf7bdfSowenca         Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon) {
726a6b6d51bSFrancois Ferrand       Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
727bebf7bdfSowenca     }
728a6b6d51bSFrancois Ferrand 
729e1a7b763SDaniel Jasper     IO.mapOptional("BreakAfterJavaFieldAnnotations",
730e1a7b763SDaniel Jasper                    Style.BreakAfterJavaFieldAnnotations);
731e1a7b763SDaniel Jasper     IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
732d6538338SAlexander Kornienko     IO.mapOptional("ColumnLimit", Style.ColumnLimit);
73335cfbd79SBirunthan Mohanathas     IO.mapOptional("CommentPragmas", Style.CommentPragmas);
734a44ab170Smydeveloperday     IO.mapOptional("QualifierAlignment", Style.QualifierAlignment);
735a44ab170Smydeveloperday 
736a44ab170Smydeveloperday     // Default Order for Left/Right based Qualifier alignment.
737d079995dSMarek Kurdej     if (Style.QualifierAlignment == FormatStyle::QAS_Right)
738a44ab170Smydeveloperday       Style.QualifierOrder = {"type", "const", "volatile"};
739d079995dSMarek Kurdej     else if (Style.QualifierAlignment == FormatStyle::QAS_Left)
740a44ab170Smydeveloperday       Style.QualifierOrder = {"const", "volatile", "type"};
741d079995dSMarek Kurdej     else if (Style.QualifierAlignment == FormatStyle::QAS_Custom)
742a44ab170Smydeveloperday       IO.mapOptional("QualifierOrder", Style.QualifierOrder);
743a44ab170Smydeveloperday 
744e56a829eSFrancois Ferrand     IO.mapOptional("CompactNamespaces", Style.CompactNamespaces);
74550d634b3SDaniel Jasper     IO.mapOptional("ConstructorInitializerIndentWidth",
74650d634b3SDaniel Jasper                    Style.ConstructorInitializerIndentWidth);
74735cfbd79SBirunthan Mohanathas     IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
74835cfbd79SBirunthan Mohanathas     IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
749358eaa3dSCameron Desrochers     IO.mapOptional("DeriveLineEnding", Style.DeriveLineEnding);
750553d4878SDaniel Jasper     IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
75135cfbd79SBirunthan Mohanathas     IO.mapOptional("DisableFormat", Style.DisableFormat);
752dda978eeSMax Sagebaum     IO.mapOptional("EmptyLineAfterAccessModifier",
753dda978eeSMax Sagebaum                    Style.EmptyLineAfterAccessModifier);
75460bf5826SAlbertas Vyšniauskas     IO.mapOptional("EmptyLineBeforeAccessModifier",
75560bf5826SAlbertas Vyšniauskas                    Style.EmptyLineBeforeAccessModifier);
756b10cbc45SDaniel Jasper     IO.mapOptional("ExperimentalAutoDetectBinPacking",
757b10cbc45SDaniel Jasper                    Style.ExperimentalAutoDetectBinPacking);
7588a780a2fSowenca 
7598a780a2fSowenca     IO.mapOptional("PackConstructorInitializers",
7608a780a2fSowenca                    Style.PackConstructorInitializers);
7614b1fde8aSowenca     // For backward compatibility:
7624b1fde8aSowenca     // The default value of ConstructorInitializerAllOnOneLineOrOnePerLine was
7634b1fde8aSowenca     // false unless BasedOnStyle was Google or Chromium whereas that of
7644b1fde8aSowenca     // AllowAllConstructorInitializersOnNextLine was always true, so the
7654b1fde8aSowenca     // equivalent default value of PackConstructorInitializers is PCIS_NextLine
7664b1fde8aSowenca     // for Google/Chromium or PCIS_BinPack otherwise. If the deprecated options
7674b1fde8aSowenca     // had a non-default value while PackConstructorInitializers has a default
7684b1fde8aSowenca     // value, set the latter to an equivalent non-default value if needed.
7698a780a2fSowenca     StringRef BasedOn;
7708a780a2fSowenca     IO.mapOptional("BasedOnStyle", BasedOn);
7718a780a2fSowenca     const bool IsGoogleOrChromium = BasedOn.equals_insensitive("google") ||
7728a780a2fSowenca                                     BasedOn.equals_insensitive("chromium");
7738a780a2fSowenca     bool OnCurrentLine = IsGoogleOrChromium;
774170a3c6fSowenca     bool OnNextLine = true;
7758a780a2fSowenca     IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
7768a780a2fSowenca                    OnCurrentLine);
7778a780a2fSowenca     IO.mapOptional("AllowAllConstructorInitializersOnNextLine", OnNextLine);
7784b1fde8aSowenca     if (!IsGoogleOrChromium) {
7794b1fde8aSowenca       if (Style.PackConstructorInitializers == FormatStyle::PCIS_BinPack &&
7808a780a2fSowenca           OnCurrentLine) {
7818a780a2fSowenca         Style.PackConstructorInitializers = OnNextLine
7828a780a2fSowenca                                                 ? FormatStyle::PCIS_NextLine
7838a780a2fSowenca                                                 : FormatStyle::PCIS_CurrentLine;
7848a780a2fSowenca       }
7854b1fde8aSowenca     } else if (Style.PackConstructorInitializers ==
7864b1fde8aSowenca                FormatStyle::PCIS_NextLine) {
7874b1fde8aSowenca       if (!OnCurrentLine)
7884b1fde8aSowenca         Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
7894b1fde8aSowenca       else if (!OnNextLine)
7904b1fde8aSowenca         Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine;
7914b1fde8aSowenca     }
7928a780a2fSowenca 
79332eaa864SKrasimir Georgiev     IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
79435cfbd79SBirunthan Mohanathas     IO.mapOptional("ForEachMacros", Style.ForEachMacros);
795be9a87feSVitali Lovich     IO.mapOptional("IfMacros", Style.IfMacros);
796be9a87feSVitali Lovich 
7979d92c027SEric Liu     IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
7989d92c027SEric Liu     IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
7999d92c027SEric Liu     IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
800335ac2ebSmydeveloperday     IO.mapOptional("IncludeIsMainSourceRegex",
801335ac2ebSmydeveloperday                    Style.IncludeStyle.IncludeIsMainSourceRegex);
8022a42c759SJakub Budiský     IO.mapOptional("IndentAccessModifiers", Style.IndentAccessModifiers);
803d6538338SAlexander Kornienko     IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
80414c04475Smydeveloperday     IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks);
8053867a2d5SPaul Hoad     IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels);
806ad47c907SKrasimir Georgiev     IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
8076ef45b04Smydeveloperday     IO.mapOptional("IndentExternBlock", Style.IndentExternBlock);
8089aab0db1SBjörn Schäpers     IO.mapOptional("IndentRequiresClause", Style.IndentRequiresClause);
80935cfbd79SBirunthan Mohanathas     IO.mapOptional("IndentWidth", Style.IndentWidth);
81035cfbd79SBirunthan Mohanathas     IO.mapOptional("IndentWrappedFunctionNames",
81135cfbd79SBirunthan Mohanathas                    Style.IndentWrappedFunctionNames);
81277e60bc4Sowenca     IO.mapOptional("InsertBraces", Style.InsertBraces);
813a324fcf1SMartin Probst     IO.mapOptional("InsertTrailingCommas", Style.InsertTrailingCommas);
8147e91b033SKrasimir Georgiev     IO.mapOptional("JavaImportGroups", Style.JavaImportGroups);
8150cd74ee8SMartin Probst     IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);
8160cd74ee8SMartin Probst     IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
817a26fc5c9SDaniel Jasper     IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
818a26fc5c9SDaniel Jasper                    Style.KeepEmptyLinesAtTheStartOfBlocks);
81964cf5ebaSVitali Lovich     IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation);
820b001a0baSBirunthan Mohanathas     IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
821b001a0baSBirunthan Mohanathas     IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);
82235cfbd79SBirunthan Mohanathas     IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
82365ee3472SDaniel Jasper     IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
824e8a301f8SFrancois Ferrand     IO.mapOptional("NamespaceMacros", Style.NamespaceMacros);
8254dc658caSBen Hamilton     IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList);
82650d634b3SDaniel Jasper     IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);
82770c98671Smydeveloperday     IO.mapOptional("ObjCBreakBeforeNestedBlockParam",
82870c98671Smydeveloperday                    Style.ObjCBreakBeforeNestedBlockParam);
829e9beea24SDaniel Jasper     IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
830d6538338SAlexander Kornienko     IO.mapOptional("ObjCSpaceBeforeProtocolList",
831d6538338SAlexander Kornienko                    Style.ObjCSpaceBeforeProtocolList);
83289628f64SManuel Klimek     IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment);
83333b909c5SDaniel Jasper     IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",
83433b909c5SDaniel Jasper                    Style.PenaltyBreakBeforeFirstCallParameter);
835dd7ece53SAlexander Kornienko     IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
8364e9678f7SDaniel Jasper     IO.mapOptional("PenaltyBreakFirstLessLess",
8374e9678f7SDaniel Jasper                    Style.PenaltyBreakFirstLessLess);
838cfe31807SG. Pery     IO.mapOptional("PenaltyBreakOpenParenthesis",
839cfe31807SG. Pery                    Style.PenaltyBreakOpenParenthesis);
84035cfbd79SBirunthan Mohanathas     IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
84158e6fe5bSFrancois Ferrand     IO.mapOptional("PenaltyBreakTemplateDeclaration",
84258e6fe5bSFrancois Ferrand                    Style.PenaltyBreakTemplateDeclaration);
843d6538338SAlexander Kornienko     IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
844d6538338SAlexander Kornienko     IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
845d6538338SAlexander Kornienko                    Style.PenaltyReturnTypeOnItsOwnLine);
8461e4d6d1cSMark Nauwelaerts     IO.mapOptional("PenaltyIndentedWhitespace",
8471e4d6d1cSMark Nauwelaerts                    Style.PenaltyIndentedWhitespace);
848553d4878SDaniel Jasper     IO.mapOptional("PointerAlignment", Style.PointerAlignment);
8496f605b8dSGerhard Gappmeier     IO.mapOptional("PPIndentWidth", Style.PPIndentWidth);
8509ad83fe7SKrasimir Georgiev     IO.mapOptional("RawStringFormats", Style.RawStringFormats);
851a08fa8a5SSeraphime Kirkovski     IO.mapOptional("ReferenceAlignment", Style.ReferenceAlignment);
852a0a5039dSDaniel Jasper     IO.mapOptional("ReflowComments", Style.ReflowComments);
853533fbae8SOwen Pan     IO.mapOptional("RemoveBracesLLVM", Style.RemoveBracesLLVM);
8549aab0db1SBjörn Schäpers     IO.mapOptional("RequiresClausePosition", Style.RequiresClausePosition);
8556f6f88ffSksyx     IO.mapOptional("SeparateDefinitionBlocks", Style.SeparateDefinitionBlocks);
8566ca52815SKrystian Kuzniarek     IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines);
857a0a5039dSDaniel Jasper     IO.mapOptional("SortIncludes", Style.SortIncludes);
8582e7add81Smydeveloperday     IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport);
859ac16a201SKrasimir Georgiev     IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);
860db986eb6SDaniel Jasper     IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
86191f60b44SReuben Thomas     IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot);
86289628f64SManuel Klimek     IO.mapOptional("SpaceAfterTemplateKeyword",
86389628f64SManuel Klimek                    Style.SpaceAfterTemplateKeyword);
864d94bff37SDaniel Jasper     IO.mapOptional("SpaceBeforeAssignmentOperators",
865d94bff37SDaniel Jasper                    Style.SpaceBeforeAssignmentOperators);
86647877c90SBjörn Schäpers     IO.mapOptional("SpaceBeforeCaseColon", Style.SpaceBeforeCaseColon);
867bfc34065SHans Wennborg     IO.mapOptional("SpaceBeforeCpp11BracedList",
868bfc34065SHans Wennborg                    Style.SpaceBeforeCpp11BracedList);
8692a9ea781SFrancois Ferrand     IO.mapOptional("SpaceBeforeCtorInitializerColon",
8702a9ea781SFrancois Ferrand                    Style.SpaceBeforeCtorInitializerColon);
8712a9ea781SFrancois Ferrand     IO.mapOptional("SpaceBeforeInheritanceColon",
8722a9ea781SFrancois Ferrand                    Style.SpaceBeforeInheritanceColon);
87335cfbd79SBirunthan Mohanathas     IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
8746facafe7SC. Rayroud     IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions);
8759e27f383SAlex Richardson     IO.mapOptional("SpaceAroundPointerQualifiers",
8769e27f383SAlex Richardson                    Style.SpaceAroundPointerQualifiers);
8772a9ea781SFrancois Ferrand     IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
8782a9ea781SFrancois Ferrand                    Style.SpaceBeforeRangeBasedForLoopColon);
879db4ad360SOwen Pan     IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock);
88035cfbd79SBirunthan Mohanathas     IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
88135cfbd79SBirunthan Mohanathas     IO.mapOptional("SpacesBeforeTrailingComments",
88235cfbd79SBirunthan Mohanathas                    Style.SpacesBeforeTrailingComments);
88335cfbd79SBirunthan Mohanathas     IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
88426748a32SMitchell Balan     IO.mapOptional("SpacesInConditionalStatement",
88526748a32SMitchell Balan                    Style.SpacesInConditionalStatement);
88635cfbd79SBirunthan Mohanathas     IO.mapOptional("SpacesInContainerLiterals",
88735cfbd79SBirunthan Mohanathas                    Style.SpacesInContainerLiterals);
88835cfbd79SBirunthan Mohanathas     IO.mapOptional("SpacesInCStyleCastParentheses",
88935cfbd79SBirunthan Mohanathas                    Style.SpacesInCStyleCastParentheses);
890772eb24eSBjörn Schäpers     IO.mapOptional("SpacesInLineCommentPrefix",
891772eb24eSBjörn Schäpers                    Style.SpacesInLineCommentPrefix);
89235cfbd79SBirunthan Mohanathas     IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
89335cfbd79SBirunthan Mohanathas     IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
894a4a7c125Smydeveloperday     IO.mapOptional("SpaceBeforeSquareBrackets",
895a4a7c125Smydeveloperday                    Style.SpaceBeforeSquareBrackets);
89652ab7aa0SAnders Waldenborg     IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing);
89735cfbd79SBirunthan Mohanathas     IO.mapOptional("Standard", Style.Standard);
8989ef66ed4SBjörn Schäpers     IO.mapOptional("StatementAttributeLikeMacros",
8999ef66ed4SBjörn Schäpers                    Style.StatementAttributeLikeMacros);
9006f40e21aSFrancois Ferrand     IO.mapOptional("StatementMacros", Style.StatementMacros);
90135cfbd79SBirunthan Mohanathas     IO.mapOptional("TabWidth", Style.TabWidth);
902c5227a1fSFrancois Ferrand     IO.mapOptional("TypenameMacros", Style.TypenameMacros);
903358eaa3dSCameron Desrochers     IO.mapOptional("UseCRLF", Style.UseCRLF);
90435cfbd79SBirunthan Mohanathas     IO.mapOptional("UseTab", Style.UseTab);
9050c332a77SJake Merdich     IO.mapOptional("WhitespaceSensitiveMacros",
9060c332a77SJake Merdich                    Style.WhitespaceSensitiveMacros);
907d6538338SAlexander Kornienko   }
908d6538338SAlexander Kornienko };
909cabdd738SAlexander Kornienko 
910c1bc38edSDaniel Jasper template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
mappingllvm::yaml::MappingTraits911c1bc38edSDaniel Jasper   static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
912806d5741SOwen Pan     IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel);
913c1bc38edSDaniel Jasper     IO.mapOptional("AfterClass", Wrapping.AfterClass);
914c1bc38edSDaniel Jasper     IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement);
915c1bc38edSDaniel Jasper     IO.mapOptional("AfterEnum", Wrapping.AfterEnum);
916c1bc38edSDaniel Jasper     IO.mapOptional("AfterFunction", Wrapping.AfterFunction);
917c1bc38edSDaniel Jasper     IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace);
918c1bc38edSDaniel Jasper     IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
919c1bc38edSDaniel Jasper     IO.mapOptional("AfterStruct", Wrapping.AfterStruct);
920c1bc38edSDaniel Jasper     IO.mapOptional("AfterUnion", Wrapping.AfterUnion);
921d6ce937fSKrasimir Georgiev     IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
922c1bc38edSDaniel Jasper     IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
923c1bc38edSDaniel Jasper     IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
924fa0118e6SWawha     IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody);
925807ab2cdSmydeveloperday     IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile);
926c1bc38edSDaniel Jasper     IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
927ad72256dSFrancois Ferrand     IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);
928ad72256dSFrancois Ferrand     IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);
929ad72256dSFrancois Ferrand     IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
930c1bc38edSDaniel Jasper   }
931c1bc38edSDaniel Jasper };
932c1bc38edSDaniel Jasper 
9336facafe7SC. Rayroud template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> {
mappingllvm::yaml::MappingTraits9346facafe7SC. Rayroud   static void mapping(IO &IO, FormatStyle::SpaceBeforeParensCustom &Spacing) {
9356facafe7SC. Rayroud     IO.mapOptional("AfterControlStatements", Spacing.AfterControlStatements);
9366facafe7SC. Rayroud     IO.mapOptional("AfterForeachMacros", Spacing.AfterForeachMacros);
9376facafe7SC. Rayroud     IO.mapOptional("AfterFunctionDefinitionName",
9386facafe7SC. Rayroud                    Spacing.AfterFunctionDefinitionName);
9396facafe7SC. Rayroud     IO.mapOptional("AfterFunctionDeclarationName",
9406facafe7SC. Rayroud                    Spacing.AfterFunctionDeclarationName);
9416facafe7SC. Rayroud     IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros);
942da6b0d0bSRajat Bajpai     IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
943b786a4aeSBjörn Schäpers     IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause);
944b786a4aeSBjörn Schäpers     IO.mapOptional("AfterRequiresInExpression",
945b786a4aeSBjörn Schäpers                    Spacing.AfterRequiresInExpression);
9466facafe7SC. Rayroud     IO.mapOptional("BeforeNonEmptyParentheses",
9476facafe7SC. Rayroud                    Spacing.BeforeNonEmptyParentheses);
9486facafe7SC. Rayroud   }
9496facafe7SC. Rayroud };
9506facafe7SC. Rayroud 
9519ad83fe7SKrasimir Georgiev template <> struct MappingTraits<FormatStyle::RawStringFormat> {
mappingllvm::yaml::MappingTraits9529ad83fe7SKrasimir Georgiev   static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
9539ad83fe7SKrasimir Georgiev     IO.mapOptional("Language", Format.Language);
9544527f13aSKrasimir Georgiev     IO.mapOptional("Delimiters", Format.Delimiters);
9552537e220SKrasimir Georgiev     IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);
956412ed095SKrasimir Georgiev     IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter);
9579ad83fe7SKrasimir Georgiev     IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);
9589ad83fe7SKrasimir Georgiev   }
9599ad83fe7SKrasimir Georgiev };
9609ad83fe7SKrasimir Georgiev 
961772eb24eSBjörn Schäpers template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {
mappingllvm::yaml::MappingTraits962772eb24eSBjörn Schäpers   static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
963772eb24eSBjörn Schäpers     // Transform the maximum to signed, to parse "-1" correctly
964772eb24eSBjörn Schäpers     int signedMaximum = static_cast<int>(Space.Maximum);
965772eb24eSBjörn Schäpers     IO.mapOptional("Minimum", Space.Minimum);
966772eb24eSBjörn Schäpers     IO.mapOptional("Maximum", signedMaximum);
967772eb24eSBjörn Schäpers     Space.Maximum = static_cast<unsigned>(signedMaximum);
968772eb24eSBjörn Schäpers 
969d079995dSMarek Kurdej     if (Space.Maximum != -1u)
970772eb24eSBjörn Schäpers       Space.Minimum = std::min(Space.Minimum, Space.Maximum);
971772eb24eSBjörn Schäpers   }
972772eb24eSBjörn Schäpers };
973772eb24eSBjörn Schäpers 
974cabdd738SAlexander Kornienko // Allows to read vector<FormatStyle> while keeping default values.
975c1637f16SAlexander Kornienko // IO.getContext() should contain a pointer to the FormatStyle structure, that
976c1637f16SAlexander Kornienko // will be used to get default values for missing keys.
977c1637f16SAlexander Kornienko // If the first element has no Language specified, it will be treated as the
978c1637f16SAlexander Kornienko // default one for the following elements.
9796d2c88eaSAlexander Kornienko template <> struct DocumentListTraits<std::vector<FormatStyle>> {
sizellvm::yaml::DocumentListTraits980c1637f16SAlexander Kornienko   static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
981c1637f16SAlexander Kornienko     return Seq.size();
982cabdd738SAlexander Kornienko   }
elementllvm::yaml::DocumentListTraits983c1637f16SAlexander Kornienko   static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq,
9846d2c88eaSAlexander Kornienko                               size_t Index) {
985c1637f16SAlexander Kornienko     if (Index >= Seq.size()) {
986c1637f16SAlexander Kornienko       assert(Index == Seq.size());
9876d2c88eaSAlexander Kornienko       FormatStyle Template;
9881696bb65SKrasimir Georgiev       if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
989cabdd738SAlexander Kornienko         Template = Seq[0];
990c1637f16SAlexander Kornienko       } else {
991c1637f16SAlexander Kornienko         Template = *((const FormatStyle *)IO.getContext());
9926d2c88eaSAlexander Kornienko         Template.Language = FormatStyle::LK_None;
993cabdd738SAlexander Kornienko       }
994c1637f16SAlexander Kornienko       Seq.resize(Index + 1, Template);
995cabdd738SAlexander Kornienko     }
996c1637f16SAlexander Kornienko     return Seq[Index];
997cabdd738SAlexander Kornienko   }
998cabdd738SAlexander Kornienko };
999d89ae9d3SDaniel Jasper } // namespace yaml
1000d89ae9d3SDaniel Jasper } // namespace llvm
1001d6538338SAlexander Kornienko 
1002f7935115SDaniel Jasper namespace clang {
1003f7935115SDaniel Jasper namespace format {
1004f7935115SDaniel Jasper 
getParseCategory()10056d0d89b4SRafael Espindola const std::error_category &getParseCategory() {
1006f76861c2SBenjamin Kramer   static const ParseErrorCategory C{};
1007d0136707SRafael Espindola   return C;
1008d0136707SRafael Espindola }
make_error_code(ParseError e)1009d0136707SRafael Espindola std::error_code make_error_code(ParseError e) {
10106d0d89b4SRafael Espindola   return std::error_code(static_cast<int>(e), getParseCategory());
1011d0136707SRafael Espindola }
1012d0136707SRafael Espindola 
make_string_error(const llvm::Twine & Message)10133adfb6a3SAntonio Maiorano inline llvm::Error make_string_error(const llvm::Twine &Message) {
10143adfb6a3SAntonio Maiorano   return llvm::make_error<llvm::StringError>(Message,
10153adfb6a3SAntonio Maiorano                                              llvm::inconvertibleErrorCode());
10163adfb6a3SAntonio Maiorano }
10173adfb6a3SAntonio Maiorano 
name() const10186432d45fSReid Kleckner const char *ParseErrorCategory::name() const noexcept {
1019d0136707SRafael Espindola   return "clang-format.parse_error";
1020d0136707SRafael Espindola }
1021d0136707SRafael Espindola 
message(int EV) const1022d0136707SRafael Espindola std::string ParseErrorCategory::message(int EV) const {
1023d0136707SRafael Espindola   switch (static_cast<ParseError>(EV)) {
1024d0136707SRafael Espindola   case ParseError::Success:
1025d0136707SRafael Espindola     return "Success";
1026d0136707SRafael Espindola   case ParseError::Error:
1027d0136707SRafael Espindola     return "Invalid argument";
1028d0136707SRafael Espindola   case ParseError::Unsuitable:
1029d0136707SRafael Espindola     return "Unsuitable";
1030a324fcf1SMartin Probst   case ParseError::BinPackTrailingCommaConflict:
1031a324fcf1SMartin Probst     return "trailing comma insertion cannot be used with bin packing";
1032a44ab170Smydeveloperday   case ParseError::InvalidQualifierSpecified:
1033a44ab170Smydeveloperday     return "Invalid qualifier specified in QualifierOrder";
1034a44ab170Smydeveloperday   case ParseError::DuplicateQualifierSpecified:
1035aacc110bSKrystian Kuzniarek     return "Duplicate qualifier specified in QualifierOrder";
1036a44ab170Smydeveloperday   case ParseError::MissingQualifierType:
1037aacc110bSKrystian Kuzniarek     return "Missing type in QualifierOrder";
1038a44ab170Smydeveloperday   case ParseError::MissingQualifierOrder:
1039aacc110bSKrystian Kuzniarek     return "Missing QualifierOrder";
1040d0136707SRafael Espindola   }
1041fbfbaf6aSSaleem Abdulrasool   llvm_unreachable("unexpected parse error");
1042d0136707SRafael Espindola }
1043d0136707SRafael Espindola 
expandPresetsBraceWrapping(FormatStyle & Expanded)10446facafe7SC. Rayroud static void expandPresetsBraceWrapping(FormatStyle &Expanded) {
10456facafe7SC. Rayroud   if (Expanded.BreakBeforeBraces == FormatStyle::BS_Custom)
10466facafe7SC. Rayroud     return;
1047807ab2cdSmydeveloperday   Expanded.BraceWrapping = {/*AfterCaseLabel=*/false,
1048807ab2cdSmydeveloperday                             /*AfterClass=*/false,
1049807ab2cdSmydeveloperday                             /*AfterControlStatement=*/FormatStyle::BWACS_Never,
1050807ab2cdSmydeveloperday                             /*AfterEnum=*/false,
1051807ab2cdSmydeveloperday                             /*AfterFunction=*/false,
1052807ab2cdSmydeveloperday                             /*AfterNamespace=*/false,
1053807ab2cdSmydeveloperday                             /*AfterObjCDeclaration=*/false,
1054807ab2cdSmydeveloperday                             /*AfterStruct=*/false,
1055807ab2cdSmydeveloperday                             /*AfterUnion=*/false,
1056807ab2cdSmydeveloperday                             /*AfterExternBlock=*/false,
1057807ab2cdSmydeveloperday                             /*BeforeCatch=*/false,
1058807ab2cdSmydeveloperday                             /*BeforeElse=*/false,
1059807ab2cdSmydeveloperday                             /*BeforeLambdaBody=*/false,
1060807ab2cdSmydeveloperday                             /*BeforeWhile=*/false,
1061807ab2cdSmydeveloperday                             /*IndentBraces=*/false,
1062807ab2cdSmydeveloperday                             /*SplitEmptyFunction=*/true,
1063807ab2cdSmydeveloperday                             /*SplitEmptyRecord=*/true,
1064807ab2cdSmydeveloperday                             /*SplitEmptyNamespace=*/true};
10656facafe7SC. Rayroud   switch (Expanded.BreakBeforeBraces) {
1066c1bc38edSDaniel Jasper   case FormatStyle::BS_Linux:
1067c1bc38edSDaniel Jasper     Expanded.BraceWrapping.AfterClass = true;
1068c1bc38edSDaniel Jasper     Expanded.BraceWrapping.AfterFunction = true;
1069c1bc38edSDaniel Jasper     Expanded.BraceWrapping.AfterNamespace = true;
1070c1bc38edSDaniel Jasper     break;
1071c1bc38edSDaniel Jasper   case FormatStyle::BS_Mozilla:
1072c1bc38edSDaniel Jasper     Expanded.BraceWrapping.AfterClass = true;
1073c1bc38edSDaniel Jasper     Expanded.BraceWrapping.AfterEnum = true;
1074c1bc38edSDaniel Jasper     Expanded.BraceWrapping.AfterFunction = true;
1075c1bc38edSDaniel Jasper     Expanded.BraceWrapping.AfterStruct = true;
1076c1bc38edSDaniel Jasper     Expanded.BraceWrapping.AfterUnion = true;
1077d6ce937fSKrasimir Georgiev     Expanded.BraceWrapping.AfterExternBlock = true;
10786ef45b04Smydeveloperday     Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
107982c9a0ecSSylvestre Ledru     Expanded.BraceWrapping.SplitEmptyFunction = true;
1080ad72256dSFrancois Ferrand     Expanded.BraceWrapping.SplitEmptyRecord = false;
1081c1bc38edSDaniel Jasper     break;
1082c1bc38edSDaniel Jasper   case FormatStyle::BS_Stroustrup:
1083c1bc38edSDaniel Jasper     Expanded.BraceWrapping.AfterFunction = true;
1084c1bc38edSDaniel Jasper     Expanded.BraceWrapping.BeforeCatch = true;
1085c1bc38edSDaniel Jasper     Expanded.BraceWrapping.BeforeElse = true;
1086c1bc38edSDaniel Jasper     break;
1087c1bc38edSDaniel Jasper   case FormatStyle::BS_Allman:
1088806d5741SOwen Pan     Expanded.BraceWrapping.AfterCaseLabel = true;
1089c1bc38edSDaniel Jasper     Expanded.BraceWrapping.AfterClass = true;
1090fb13e65aSPaul Hoad     Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
1091c1bc38edSDaniel Jasper     Expanded.BraceWrapping.AfterEnum = true;
1092c1bc38edSDaniel Jasper     Expanded.BraceWrapping.AfterFunction = true;
1093c1bc38edSDaniel Jasper     Expanded.BraceWrapping.AfterNamespace = true;
1094c1bc38edSDaniel Jasper     Expanded.BraceWrapping.AfterObjCDeclaration = true;
1095c1bc38edSDaniel Jasper     Expanded.BraceWrapping.AfterStruct = true;
10969131e925SOwen Pan     Expanded.BraceWrapping.AfterUnion = true;
1097d6ce937fSKrasimir Georgiev     Expanded.BraceWrapping.AfterExternBlock = true;
10986ef45b04Smydeveloperday     Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
1099c1bc38edSDaniel Jasper     Expanded.BraceWrapping.BeforeCatch = true;
1100c1bc38edSDaniel Jasper     Expanded.BraceWrapping.BeforeElse = true;
1101cbdde495SBjörn Schäpers     Expanded.BraceWrapping.BeforeLambdaBody = true;
1102c1bc38edSDaniel Jasper     break;
1103a506ed25SPaul Hoad   case FormatStyle::BS_Whitesmiths:
1104a506ed25SPaul Hoad     Expanded.BraceWrapping.AfterCaseLabel = true;
1105a506ed25SPaul Hoad     Expanded.BraceWrapping.AfterClass = true;
1106fb13e65aSPaul Hoad     Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
1107a506ed25SPaul Hoad     Expanded.BraceWrapping.AfterEnum = true;
1108a506ed25SPaul Hoad     Expanded.BraceWrapping.AfterFunction = true;
1109a506ed25SPaul Hoad     Expanded.BraceWrapping.AfterNamespace = true;
1110a506ed25SPaul Hoad     Expanded.BraceWrapping.AfterObjCDeclaration = true;
1111a506ed25SPaul Hoad     Expanded.BraceWrapping.AfterStruct = true;
1112a506ed25SPaul Hoad     Expanded.BraceWrapping.AfterExternBlock = true;
11136ef45b04Smydeveloperday     Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
1114a506ed25SPaul Hoad     Expanded.BraceWrapping.BeforeCatch = true;
1115a506ed25SPaul Hoad     Expanded.BraceWrapping.BeforeElse = true;
1116fa0118e6SWawha     Expanded.BraceWrapping.BeforeLambdaBody = true;
1117a506ed25SPaul Hoad     break;
1118c1bc38edSDaniel Jasper   case FormatStyle::BS_GNU:
1119807ab2cdSmydeveloperday     Expanded.BraceWrapping = {
1120807ab2cdSmydeveloperday         /*AfterCaseLabel=*/true,
1121807ab2cdSmydeveloperday         /*AfterClass=*/true,
1122807ab2cdSmydeveloperday         /*AfterControlStatement=*/FormatStyle::BWACS_Always,
1123807ab2cdSmydeveloperday         /*AfterEnum=*/true,
1124807ab2cdSmydeveloperday         /*AfterFunction=*/true,
1125807ab2cdSmydeveloperday         /*AfterNamespace=*/true,
1126807ab2cdSmydeveloperday         /*AfterObjCDeclaration=*/true,
1127807ab2cdSmydeveloperday         /*AfterStruct=*/true,
1128807ab2cdSmydeveloperday         /*AfterUnion=*/true,
1129807ab2cdSmydeveloperday         /*AfterExternBlock=*/true,
1130807ab2cdSmydeveloperday         /*BeforeCatch=*/true,
1131807ab2cdSmydeveloperday         /*BeforeElse=*/true,
1132807ab2cdSmydeveloperday         /*BeforeLambdaBody=*/false,
1133807ab2cdSmydeveloperday         /*BeforeWhile=*/true,
1134807ab2cdSmydeveloperday         /*IndentBraces=*/true,
1135807ab2cdSmydeveloperday         /*SplitEmptyFunction=*/true,
1136807ab2cdSmydeveloperday         /*SplitEmptyRecord=*/true,
1137807ab2cdSmydeveloperday         /*SplitEmptyNamespace=*/true};
11386ef45b04Smydeveloperday     Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
1139c1bc38edSDaniel Jasper     break;
1140c1bc38edSDaniel Jasper   case FormatStyle::BS_WebKit:
1141c1bc38edSDaniel Jasper     Expanded.BraceWrapping.AfterFunction = true;
1142c1bc38edSDaniel Jasper     break;
1143c1bc38edSDaniel Jasper   default:
1144c1bc38edSDaniel Jasper     break;
1145c1bc38edSDaniel Jasper   }
11466facafe7SC. Rayroud }
11476facafe7SC. Rayroud 
expandPresetsSpaceBeforeParens(FormatStyle & Expanded)11486facafe7SC. Rayroud static void expandPresetsSpaceBeforeParens(FormatStyle &Expanded) {
11496facafe7SC. Rayroud   if (Expanded.SpaceBeforeParens == FormatStyle::SBPO_Custom)
11506facafe7SC. Rayroud     return;
11516facafe7SC. Rayroud   // Reset all flags
11526facafe7SC. Rayroud   Expanded.SpaceBeforeParensOptions = {};
11536facafe7SC. Rayroud 
11546facafe7SC. Rayroud   switch (Expanded.SpaceBeforeParens) {
11556facafe7SC. Rayroud   case FormatStyle::SBPO_Never:
11566facafe7SC. Rayroud     break;
11576facafe7SC. Rayroud   case FormatStyle::SBPO_ControlStatements:
11586facafe7SC. Rayroud     Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;
11596facafe7SC. Rayroud     Expanded.SpaceBeforeParensOptions.AfterForeachMacros = true;
11606facafe7SC. Rayroud     Expanded.SpaceBeforeParensOptions.AfterIfMacros = true;
11616facafe7SC. Rayroud     break;
11626facafe7SC. Rayroud   case FormatStyle::SBPO_ControlStatementsExceptControlMacros:
11636facafe7SC. Rayroud     Expanded.SpaceBeforeParensOptions.AfterControlStatements = true;
11646facafe7SC. Rayroud     break;
11656facafe7SC. Rayroud   case FormatStyle::SBPO_NonEmptyParentheses:
11666facafe7SC. Rayroud     Expanded.SpaceBeforeParensOptions.BeforeNonEmptyParentheses = true;
11676facafe7SC. Rayroud     break;
11686facafe7SC. Rayroud   case FormatStyle::SBPO_Always:
11696facafe7SC. Rayroud     break;
11706facafe7SC. Rayroud   default:
11716facafe7SC. Rayroud     break;
11726facafe7SC. Rayroud   }
1173c1bc38edSDaniel Jasper }
1174c1bc38edSDaniel Jasper 
getLLVMStyle(FormatStyle::LanguageKind Language)11758bd97e75SJordan Rupprecht FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
1176f7935115SDaniel Jasper   FormatStyle LLVMStyle;
117725f753c5SBjörn Schäpers   LLVMStyle.InheritsParentConfig = false;
11788bd97e75SJordan Rupprecht   LLVMStyle.Language = Language;
1179f7935115SDaniel Jasper   LLVMStyle.AccessModifierOffset = -2;
11807fdbb3feSDaniel Jasper   LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
11816501f7e8SDaniel Jasper   LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
1182673c5ba5SFred Grim   LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;
11830ee04e6eSFrancois Ferrand   LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
1184552f4a7eSDaniel Jasper   LLVMStyle.AlignTrailingComments = true;
1185c24b3db4Ssstwcw   LLVMStyle.AlignConsecutiveAssignments = {};
1186c24b3db4Ssstwcw   LLVMStyle.AlignConsecutiveAssignments.Enabled = false;
1187c24b3db4Ssstwcw   LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false;
1188c24b3db4Ssstwcw   LLVMStyle.AlignConsecutiveAssignments.AcrossComments = false;
1189c24b3db4Ssstwcw   LLVMStyle.AlignConsecutiveAssignments.AlignCompound = false;
1190c24b3db4Ssstwcw   LLVMStyle.AlignConsecutiveAssignments.PadOperators = true;
1191c24b3db4Ssstwcw   LLVMStyle.AlignConsecutiveBitFields = {};
1192c24b3db4Ssstwcw   LLVMStyle.AlignConsecutiveDeclarations = {};
1193c24b3db4Ssstwcw   LLVMStyle.AlignConsecutiveMacros = {};
1194c6deae45SPaul Hoad   LLVMStyle.AllowAllArgumentsOnNextLine = true;
1195f7db433eSDaniel Jasper   LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
1196292058a5SAaron Smith   LLVMStyle.AllowShortEnumsOnASingleLine = true;
1197d74cf403SDaniel Jasper   LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
119810234da7SOwen Pan   LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
1199b87899b5SDaniel Jasper   LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
120015000a12SPaul Hoad   LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
1201a83e2dbbSRonald Wampler   LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
12023a685df7SDaniel Jasper   LLVMStyle.AllowShortLoopsOnASingleLine = false;
1203448592eeSZachary Turner   LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
1204a0388a8aSBirunthan Mohanathas   LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
120558611718SAlexander Kornienko   LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
120658e6fe5bSFrancois Ferrand   LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
1207e7bd058cSAlex Richardson   LLVMStyle.AttributeMacros.push_back("__capability");
120818210d7dSDaniel Jasper   LLVMStyle.BinPackArguments = true;
1209e56a829eSFrancois Ferrand   LLVMStyle.BinPackParameters = true;
1210ac043c90SDaniel Jasper   LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
12119aab0db1SBjörn Schäpers   LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always;
1212165b29e2SDaniel Jasper   LLVMStyle.BreakBeforeTernaryOperators = true;
1213e33d4afaSDaniel Jasper   LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
1214807ab2cdSmydeveloperday   LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false,
1215807ab2cdSmydeveloperday                              /*AfterClass=*/false,
1216807ab2cdSmydeveloperday                              /*AfterControlStatement=*/FormatStyle::BWACS_Never,
1217807ab2cdSmydeveloperday                              /*AfterEnum=*/false,
1218807ab2cdSmydeveloperday                              /*AfterFunction=*/false,
1219807ab2cdSmydeveloperday                              /*AfterNamespace=*/false,
1220807ab2cdSmydeveloperday                              /*AfterObjCDeclaration=*/false,
1221807ab2cdSmydeveloperday                              /*AfterStruct=*/false,
1222807ab2cdSmydeveloperday                              /*AfterUnion=*/false,
1223807ab2cdSmydeveloperday                              /*AfterExternBlock=*/false,
1224807ab2cdSmydeveloperday                              /*BeforeCatch=*/false,
1225807ab2cdSmydeveloperday                              /*BeforeElse=*/false,
1226807ab2cdSmydeveloperday                              /*BeforeLambdaBody=*/false,
1227807ab2cdSmydeveloperday                              /*BeforeWhile=*/false,
1228807ab2cdSmydeveloperday                              /*IndentBraces=*/false,
1229807ab2cdSmydeveloperday                              /*SplitEmptyFunction=*/true,
1230807ab2cdSmydeveloperday                              /*SplitEmptyRecord=*/true,
1231807ab2cdSmydeveloperday                              /*SplitEmptyNamespace=*/true};
12326ef45b04Smydeveloperday   LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
12332cd92f1cSNico Weber   LLVMStyle.BreakAfterJavaFieldAnnotations = false;
1234a6b6d51bSFrancois Ferrand   LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
12356bb103f9SFrancois Ferrand   LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
1236e1a7b763SDaniel Jasper   LLVMStyle.BreakStringLiterals = true;
1237c860266eSAlexander Kornienko   LLVMStyle.ColumnLimit = 80;
1238e1e4319aSDaniel Jasper   LLVMStyle.CommentPragmas = "^ IWYU pragma:";
1239e56a829eSFrancois Ferrand   LLVMStyle.CompactNamespaces = false;
1240cdaffa45SDaniel Jasper   LLVMStyle.ConstructorInitializerIndentWidth = 4;
1241e1e4319aSDaniel Jasper   LLVMStyle.ContinuationIndentWidth = 4;
1242f8b7266dSChandler Carruth   LLVMStyle.Cpp11BracedListStyle = true;
1243a44ab170Smydeveloperday 
1244a44ab170Smydeveloperday   // Off by default Qualifier ordering
1245a44ab170Smydeveloperday   LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave;
1246a44ab170Smydeveloperday 
1247358eaa3dSCameron Desrochers   LLVMStyle.DeriveLineEnding = true;
1248553d4878SDaniel Jasper   LLVMStyle.DerivePointerAlignment = false;
1249dda978eeSMax Sagebaum   LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never;
125060bf5826SAlbertas Vyšniauskas   LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock;
1251b10cbc45SDaniel Jasper   LLVMStyle.ExperimentalAutoDetectBinPacking = false;
12528a780a2fSowenca   LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack;
125332eaa864SKrasimir Georgiev   LLVMStyle.FixNamespaceComments = true;
1254e1e4319aSDaniel Jasper   LLVMStyle.ForEachMacros.push_back("foreach");
1255e1e4319aSDaniel Jasper   LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
1256e1e4319aSDaniel Jasper   LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
1257be9a87feSVitali Lovich   LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE");
12589d92c027SEric Liu   LLVMStyle.IncludeStyle.IncludeCategories = {
12598668eae2Smydeveloperday       {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false},
12608668eae2Smydeveloperday       {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},
12618668eae2Smydeveloperday       {".*", 1, 0, false}};
12629d92c027SEric Liu   LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
12639d92c027SEric Liu   LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
12642a42c759SJakub Budiský   LLVMStyle.IndentAccessModifiers = false;
1265c860266eSAlexander Kornienko   LLVMStyle.IndentCaseLabels = false;
126614c04475Smydeveloperday   LLVMStyle.IndentCaseBlocks = false;
12673867a2d5SPaul Hoad   LLVMStyle.IndentGotoLabels = true;
1268ad47c907SKrasimir Georgiev   LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
12699aab0db1SBjörn Schäpers   LLVMStyle.IndentRequiresClause = true;
1270c75e1effSDaniel Jasper   LLVMStyle.IndentWrappedFunctionNames = false;
1271e33d4afaSDaniel Jasper   LLVMStyle.IndentWidth = 2;
12726f605b8dSGerhard Gappmeier   LLVMStyle.PPIndentWidth = -1;
127377e60bc4Sowenca   LLVMStyle.InsertBraces = false;
1274a324fcf1SMartin Probst   LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
1275fb2342d2SMartin Probst   LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
1276fb2342d2SMartin Probst   LLVMStyle.JavaScriptWrapImports = true;
1277ebb43caaSAlexander Kornienko   LLVMStyle.TabWidth = 8;
127864cf5ebaSVitali Lovich   LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature;
1279c860266eSAlexander Kornienko   LLVMStyle.MaxEmptyLinesToKeep = 1;
1280a26fc5c9SDaniel Jasper   LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
128165ee3472SDaniel Jasper   LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
12824dc658caSBen Hamilton   LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto;
128350d634b3SDaniel Jasper   LLVMStyle.ObjCBlockIndentWidth = 2;
128470c98671Smydeveloperday   LLVMStyle.ObjCBreakBeforeNestedBlockParam = true;
1285e9beea24SDaniel Jasper   LLVMStyle.ObjCSpaceAfterProperty = false;
1286a608775bSNico Weber   LLVMStyle.ObjCSpaceBeforeProtocolList = true;
1287553d4878SDaniel Jasper   LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
1288a08fa8a5SSeraphime Kirkovski   LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer;
12899aab0db1SBjörn Schäpers   LLVMStyle.RequiresClausePosition = FormatStyle::RCPS_OwnLine;
12906f6f88ffSksyx   LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
12916ca52815SKrystian Kuzniarek   LLVMStyle.ShortNamespaceLines = 1;
1292c860266eSAlexander Kornienko   LLVMStyle.SpacesBeforeTrailingComments = 1;
1293e5032567SSam McCall   LLVMStyle.Standard = FormatStyle::LS_Latest;
1294358eaa3dSCameron Desrochers   LLVMStyle.UseCRLF = false;
12953c3d09c8SAlexander Kornienko   LLVMStyle.UseTab = FormatStyle::UT_Never;
1296a0a5039dSDaniel Jasper   LLVMStyle.ReflowComments = true;
1297533fbae8SOwen Pan   LLVMStyle.RemoveBracesLLVM = false;
1298b55acad9SDaniel Jasper   LLVMStyle.SpacesInParentheses = false;
1299ad981f88SDaniel Jasper   LLVMStyle.SpacesInSquareBrackets = false;
1300db4ad360SOwen Pan   LLVMStyle.SpaceInEmptyBlock = false;
1301b55acad9SDaniel Jasper   LLVMStyle.SpaceInEmptyParentheses = false;
1302b2e10a54SDaniel Jasper   LLVMStyle.SpacesInContainerLiterals = true;
1303b55acad9SDaniel Jasper   LLVMStyle.SpacesInCStyleCastParentheses = false;
1304772eb24eSBjörn Schäpers   LLVMStyle.SpacesInLineCommentPrefix = {/*Minimum=*/1, /*Maximum=*/-1u};
1305db986eb6SDaniel Jasper   LLVMStyle.SpaceAfterCStyleCast = false;
130691f60b44SReuben Thomas   LLVMStyle.SpaceAfterLogicalNot = false;
130783bbd573SSylvestre Ledru   LLVMStyle.SpaceAfterTemplateKeyword = true;
13089e27f383SAlex Richardson   LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
130947877c90SBjörn Schäpers   LLVMStyle.SpaceBeforeCaseColon = false;
13102a9ea781SFrancois Ferrand   LLVMStyle.SpaceBeforeCtorInitializerColon = true;
13112a9ea781SFrancois Ferrand   LLVMStyle.SpaceBeforeInheritanceColon = true;
1312fdca83d4SAlexander Kornienko   LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
1313b786a4aeSBjörn Schäpers   LLVMStyle.SpaceBeforeParensOptions = {};
13146facafe7SC. Rayroud   LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true;
13156facafe7SC. Rayroud   LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true;
13166facafe7SC. Rayroud   LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true;
13172a9ea781SFrancois Ferrand   LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
1318d94bff37SDaniel Jasper   LLVMStyle.SpaceBeforeAssignmentOperators = true;
1319bfc34065SHans Wennborg   LLVMStyle.SpaceBeforeCpp11BracedList = false;
1320a4a7c125Smydeveloperday   LLVMStyle.SpaceBeforeSquareBrackets = false;
132152ab7aa0SAnders Waldenborg   LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;
13229363aa90SMarek Kurdej   LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never;
132326748a32SMitchell Balan   LLVMStyle.SpacesInConditionalStatement = false;
13244e9678f7SDaniel Jasper 
13259976efa8SFrancois Ferrand   LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
132619a541efSDaniel Jasper   LLVMStyle.PenaltyBreakComment = 300;
1327fe7a57faSAlexander Kornienko   LLVMStyle.PenaltyBreakFirstLessLess = 120;
1328fe7a57faSAlexander Kornienko   LLVMStyle.PenaltyBreakString = 1000;
1329fe7a57faSAlexander Kornienko   LLVMStyle.PenaltyExcessCharacter = 1000000;
13304e9678f7SDaniel Jasper   LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
133133b909c5SDaniel Jasper   LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
1332cfe31807SG. Pery   LLVMStyle.PenaltyBreakOpenParenthesis = 0;
133358e6fe5bSFrancois Ferrand   LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;
13341e4d6d1cSMark Nauwelaerts   LLVMStyle.PenaltyIndentedWhitespace = 0;
13354e9678f7SDaniel Jasper 
1336c64b09acSDaniel Jasper   LLVMStyle.DisableFormat = false;
13377b02794fSBjörn Schäpers   LLVMStyle.SortIncludes = FormatStyle::SI_CaseSensitive;
13382e7add81Smydeveloperday   LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
1339ac16a201SKrasimir Georgiev   LLVMStyle.SortUsingDeclarations = true;
1340bcc1dee6SBjörn Schäpers   LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");
13416f40e21aSFrancois Ferrand   LLVMStyle.StatementMacros.push_back("Q_UNUSED");
13426f40e21aSFrancois Ferrand   LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");
13430c332a77SJake Merdich   LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE");
13440c332a77SJake Merdich   LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE");
13450c332a77SJake Merdich   LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE");
1346e7b4feeaSBen Hamilton   LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME");
1347e7b4feeaSBen Hamilton   LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME");
1348c64b09acSDaniel Jasper 
13497f514164SJordan Rupprecht   // Defaults that differ when not C++.
1350d079995dSMarek Kurdej   if (Language == FormatStyle::LK_TableGen)
13517f514164SJordan Rupprecht     LLVMStyle.SpacesInContainerLiterals = false;
1352d079995dSMarek Kurdej   if (LLVMStyle.isJson())
13538b7881a0Smydeveloperday     LLVMStyle.ColumnLimit = 0;
13547f514164SJordan Rupprecht 
1355f7935115SDaniel Jasper   return LLVMStyle;
1356f7935115SDaniel Jasper }
1357f7935115SDaniel Jasper 
getGoogleStyle(FormatStyle::LanguageKind Language)1358514ecc8cSNico Weber FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
135926b144ccSKrasimir Georgiev   if (Language == FormatStyle::LK_TextProto) {
136026b144ccSKrasimir Georgiev     FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto);
136126b144ccSKrasimir Georgiev     GoogleStyle.Language = FormatStyle::LK_TextProto;
1362eda222e7SKrasimir Georgiev 
136326b144ccSKrasimir Georgiev     return GoogleStyle;
136426b144ccSKrasimir Georgiev   }
136526b144ccSKrasimir Georgiev 
13668bd97e75SJordan Rupprecht   FormatStyle GoogleStyle = getLLVMStyle(Language);
1367514ecc8cSNico Weber 
1368f7935115SDaniel Jasper   GoogleStyle.AccessModifierOffset = -1;
13697fdbb3feSDaniel Jasper   GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left;
137015000a12SPaul Hoad   GoogleStyle.AllowShortIfStatementsOnASingleLine =
137115000a12SPaul Hoad       FormatStyle::SIS_WithoutElse;
13723a685df7SDaniel Jasper   GoogleStyle.AllowShortLoopsOnASingleLine = true;
137358611718SAlexander Kornienko   GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
137458e6fe5bSFrancois Ferrand   GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
1375553d4878SDaniel Jasper   GoogleStyle.DerivePointerAlignment = true;
13768668eae2Smydeveloperday   GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false},
13778668eae2Smydeveloperday                                                 {"^<.*\\.h>", 1, 0, false},
13788668eae2Smydeveloperday                                                 {"^<.*", 2, 0, false},
13798668eae2Smydeveloperday                                                 {".*", 3, 0, false}};
13809d92c027SEric Liu   GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
13810f4d5f85SEric Liu   GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
1382c860266eSAlexander Kornienko   GoogleStyle.IndentCaseLabels = true;
1383a26fc5c9SDaniel Jasper   GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
13843a47fddfSBen Hamilton   GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never;
1385e9beea24SDaniel Jasper   GoogleStyle.ObjCSpaceAfterProperty = false;
1386f84f118eSBen Hamilton   GoogleStyle.ObjCSpaceBeforeProtocolList = true;
13878a780a2fSowenca   GoogleStyle.PackConstructorInitializers = FormatStyle::PCIS_NextLine;
1388553d4878SDaniel Jasper   GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;
13895559cc3bSKrasimir Georgiev   GoogleStyle.RawStringFormats = {
13905559cc3bSKrasimir Georgiev       {
13915559cc3bSKrasimir Georgiev           FormatStyle::LK_Cpp,
13925559cc3bSKrasimir Georgiev           /*Delimiters=*/
13935559cc3bSKrasimir Georgiev           {
13945559cc3bSKrasimir Georgiev               "cc",
13955559cc3bSKrasimir Georgiev               "CC",
13965559cc3bSKrasimir Georgiev               "cpp",
13975559cc3bSKrasimir Georgiev               "Cpp",
13985559cc3bSKrasimir Georgiev               "CPP",
13995559cc3bSKrasimir Georgiev               "c++",
14005559cc3bSKrasimir Georgiev               "C++",
14015559cc3bSKrasimir Georgiev           },
14025559cc3bSKrasimir Georgiev           /*EnclosingFunctionNames=*/
14035559cc3bSKrasimir Georgiev           {},
14045559cc3bSKrasimir Georgiev           /*CanonicalDelimiter=*/"",
14055559cc3bSKrasimir Georgiev           /*BasedOnStyle=*/"google",
14065559cc3bSKrasimir Georgiev       },
14075559cc3bSKrasimir Georgiev       {
14084527f13aSKrasimir Georgiev           FormatStyle::LK_TextProto,
14094527f13aSKrasimir Georgiev           /*Delimiters=*/
14104527f13aSKrasimir Georgiev           {
14114527f13aSKrasimir Georgiev               "pb",
14124527f13aSKrasimir Georgiev               "PB",
14132fac8d94SKrasimir Georgiev               "proto",
14142fac8d94SKrasimir Georgiev               "PROTO",
14154527f13aSKrasimir Georgiev           },
14162537e220SKrasimir Georgiev           /*EnclosingFunctionNames=*/
141742948e3cSKrasimir Georgiev           {
141842948e3cSKrasimir Georgiev               "EqualsProto",
141961f46f22SKrasimir Georgiev               "EquivToProto",
1420ce0b8d69SKrasimir Georgiev               "PARSE_PARTIAL_TEXT_PROTO",
142161f46f22SKrasimir Georgiev               "PARSE_TEST_PROTO",
142261f46f22SKrasimir Georgiev               "PARSE_TEXT_PROTO",
142361f46f22SKrasimir Georgiev               "ParseTextOrDie",
1424ce0b8d69SKrasimir Georgiev               "ParseTextProtoOrDie",
1425f1ef237dSSam McCall               "ParseTestProto",
1426f1ef237dSSam McCall               "ParsePartialTestProto",
142742948e3cSKrasimir Georgiev           },
1428587859d9SKrasimir Georgiev           /*CanonicalDelimiter=*/"pb",
14294527f13aSKrasimir Georgiev           /*BasedOnStyle=*/"google",
14305559cc3bSKrasimir Georgiev       },
14315559cc3bSKrasimir Georgiev   };
1432c860266eSAlexander Kornienko   GoogleStyle.SpacesBeforeTrailingComments = 2;
1433c860266eSAlexander Kornienko   GoogleStyle.Standard = FormatStyle::LS_Auto;
14344e9678f7SDaniel Jasper 
14354e9678f7SDaniel Jasper   GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
143633b909c5SDaniel Jasper   GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;
14374e9678f7SDaniel Jasper 
1438c58c70e2SDaniel Jasper   if (Language == FormatStyle::LK_Java) {
14396501f7e8SDaniel Jasper     GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
14400ee04e6eSFrancois Ferrand     GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
1441fd4ed184SDaniel Jasper     GoogleStyle.AlignTrailingComments = false;
14429e709351SDaniel Jasper     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
144315000a12SPaul Hoad     GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
14441cd3c71cSDaniel Jasper     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
1445c58c70e2SDaniel Jasper     GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
1446c58c70e2SDaniel Jasper     GoogleStyle.ColumnLimit = 100;
1447c58c70e2SDaniel Jasper     GoogleStyle.SpaceAfterCStyleCast = true;
144861d81973SDaniel Jasper     GoogleStyle.SpacesBeforeTrailingComments = 1;
1449c58c70e2SDaniel Jasper   } else if (Language == FormatStyle::LK_JavaScript) {
14506501f7e8SDaniel Jasper     GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
14510ee04e6eSFrancois Ferrand     GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
145228d8a5abSDaniel Jasper     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
145302656f29SMartin Probst     // TODO: still under discussion whether to switch to SLS_All.
145402656f29SMartin Probst     GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
14556501f7e8SDaniel Jasper     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
1456e551bb70SDaniel Jasper     GoogleStyle.BreakBeforeTernaryOperators = false;
14579835cf15SMartin Probst     // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is
14589835cf15SMartin Probst     // commonly followed by overlong URLs.
14599835cf15SMartin Probst     GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)";
1460a324fcf1SMartin Probst     // TODO: enable once decided, in particular re disabling bin packing.
1461a324fcf1SMartin Probst     // https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma
1462a324fcf1SMartin Probst     // GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
14638f83a907SDaniel Jasper     GoogleStyle.MaxEmptyLinesToKeep = 3;
1464ece8c0c6SMartin Probst     GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
1465514ecc8cSNico Weber     GoogleStyle.SpacesInContainerLiterals = false;
1466abd1f574SDaniel Jasper     GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single;
14670cd74ee8SMartin Probst     GoogleStyle.JavaScriptWrapImports = false;
1468514ecc8cSNico Weber   } else if (Language == FormatStyle::LK_Proto) {
146967e6521aSDaniel Jasper     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
14709c95dfe6SDaniel Jasper     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
1471783bac6bSDaniel Jasper     GoogleStyle.SpacesInContainerLiterals = false;
1472c2091808SKrasimir Georgiev     GoogleStyle.Cpp11BracedListStyle = false;
1473374e6de8SKrasimir Georgiev     // This affects protocol buffer options specifications and text protos.
1474374e6de8SKrasimir Georgiev     // Text protos are currently mostly formatted inside C++ raw string literals
1475374e6de8SKrasimir Georgiev     // and often the current breaking behavior of string literals is not
1476374e6de8SKrasimir Georgiev     // beneficial there. Investigate turning this on once proper string reflow
1477374e6de8SKrasimir Georgiev     // has been implemented.
1478374e6de8SKrasimir Georgiev     GoogleStyle.BreakStringLiterals = false;
147903a04fe9SDaniel Jasper   } else if (Language == FormatStyle::LK_ObjC) {
14801ab722edSBen Hamilton     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
148103a04fe9SDaniel Jasper     GoogleStyle.ColumnLimit = 100;
148200e7ae9fSKrasimir Georgiev     // "Regroup" doesn't work well for ObjC yet (main header heuristic,
148300e7ae9fSKrasimir Georgiev     // relationship between ObjC standard library headers and other heades,
148400e7ae9fSKrasimir Georgiev     // #imports, etc.)
148500e7ae9fSKrasimir Georgiev     GoogleStyle.IncludeStyle.IncludeBlocks =
148600e7ae9fSKrasimir Georgiev         tooling::IncludeStyle::IBS_Preserve;
14879520bf14SJonathan Coe   } else if (Language == FormatStyle::LK_CSharp) {
14889520bf14SJonathan Coe     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
14899520bf14SJonathan Coe     GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
14909520bf14SJonathan Coe     GoogleStyle.BreakStringLiterals = false;
14919520bf14SJonathan Coe     GoogleStyle.ColumnLimit = 100;
14929520bf14SJonathan Coe     GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
1493514ecc8cSNico Weber   }
1494514ecc8cSNico Weber 
1495f7935115SDaniel Jasper   return GoogleStyle;
1496f7935115SDaniel Jasper }
1497f7935115SDaniel Jasper 
getChromiumStyle(FormatStyle::LanguageKind Language)1498514ecc8cSNico Weber FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
1499514ecc8cSNico Weber   FormatStyle ChromiumStyle = getGoogleStyle(Language);
1500b55dea4eSNico Weber 
1501b55dea4eSNico Weber   // Disable include reordering across blocks in Chromium code.
1502b55dea4eSNico Weber   // - clang-format tries to detect that foo.h is the "main" header for
1503b55dea4eSNico Weber   //   foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium
1504b55dea4eSNico Weber   //   uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc,
1505b55dea4eSNico Weber   //   _private.cc, _impl.cc etc) in different permutations
1506b55dea4eSNico Weber   //   (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a
1507b55dea4eSNico Weber   //   better default for Chromium code.
1508b55dea4eSNico Weber   // - The default for .cc and .mm files is different (r357695) for Google style
1509b55dea4eSNico Weber   //   for the same reason. The plan is to unify this again once the main
1510b55dea4eSNico Weber   //   header detection works for Google's ObjC code, but this hasn't happened
1511b55dea4eSNico Weber   //   yet. Since Chromium has some ObjC code, switching Chromium is blocked
1512b55dea4eSNico Weber   //   on that.
1513b55dea4eSNico Weber   // - Finally, "If include reordering is harmful, put things in different
1514b55dea4eSNico Weber   //   blocks to prevent it" has been a recommendation for a long time that
1515b55dea4eSNico Weber   //   people are used to. We'll need a dev education push to change this to
1516b55dea4eSNico Weber   //   "If include reordering is harmful, put things in a different block and
1517b55dea4eSNico Weber   //   _prepend that with a comment_ to prevent it" before changing behavior.
1518b55dea4eSNico Weber   ChromiumStyle.IncludeStyle.IncludeBlocks =
1519b55dea4eSNico Weber       tooling::IncludeStyle::IBS_Preserve;
1520b55dea4eSNico Weber 
1521450425c9SNico Weber   if (Language == FormatStyle::LK_Java) {
152215000a12SPaul Hoad     ChromiumStyle.AllowShortIfStatementsOnASingleLine =
152315000a12SPaul Hoad         FormatStyle::SIS_WithoutElse;
15242cd92f1cSNico Weber     ChromiumStyle.BreakAfterJavaFieldAnnotations = true;
1525450425c9SNico Weber     ChromiumStyle.ContinuationIndentWidth = 8;
15262cd92f1cSNico Weber     ChromiumStyle.IndentWidth = 4;
15277e91b033SKrasimir Georgiev     // See styleguide for import groups:
1528c71fbdd8SQuinn Pham     // https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/java/java.md#Import-Order
15297e91b033SKrasimir Georgiev     ChromiumStyle.JavaImportGroups = {
1530ffff4921SNico Weber         "android",
1531ffff4921SNico Weber         "androidx",
1532ffff4921SNico Weber         "com",
1533ffff4921SNico Weber         "dalvik",
1534ffff4921SNico Weber         "junit",
1535ffff4921SNico Weber         "org",
1536ffff4921SNico Weber         "com.google.android.apps.chrome",
1537ffff4921SNico Weber         "org.chromium",
1538ffff4921SNico Weber         "java",
1539ffff4921SNico Weber         "javax",
15407e91b033SKrasimir Georgiev     };
15417b02794fSBjörn Schäpers     ChromiumStyle.SortIncludes = FormatStyle::SI_CaseSensitive;
1542ea649697SNico Weber   } else if (Language == FormatStyle::LK_JavaScript) {
154315000a12SPaul Hoad     ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
1544ea649697SNico Weber     ChromiumStyle.AllowShortLoopsOnASingleLine = false;
1545450425c9SNico Weber   } else {
1546f7db433eSDaniel Jasper     ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
1547d74cf403SDaniel Jasper     ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
154815000a12SPaul Hoad     ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
15493a685df7SDaniel Jasper     ChromiumStyle.AllowShortLoopsOnASingleLine = false;
15502cf17bfcSDaniel Jasper     ChromiumStyle.BinPackParameters = false;
1551553d4878SDaniel Jasper     ChromiumStyle.DerivePointerAlignment = false;
15529e2bc306SNico Weber     if (Language == FormatStyle::LK_ObjC)
15539e2bc306SNico Weber       ChromiumStyle.ColumnLimit = 80;
1554450425c9SNico Weber   }
15551b750eddSDaniel Jasper   return ChromiumStyle;
15561b750eddSDaniel Jasper }
15571b750eddSDaniel Jasper 
getMozillaStyle()1558c860266eSAlexander Kornienko FormatStyle getMozillaStyle() {
1559c860266eSAlexander Kornienko   FormatStyle MozillaStyle = getLLVMStyle();
1560c860266eSAlexander Kornienko   MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
1561a081002bSBirunthan Mohanathas   MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
156289628f64SManuel Klimek   MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel;
1563a0388a8aSBirunthan Mohanathas   MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
1564a0388a8aSBirunthan Mohanathas       FormatStyle::DRTBS_TopLevel;
156558e6fe5bSFrancois Ferrand   MozillaStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
1566dcb038d4SSylvestre Ledru   MozillaStyle.BinPackParameters = false;
1567dcb038d4SSylvestre Ledru   MozillaStyle.BinPackArguments = false;
1568305fa9c2SBirunthan Mohanathas   MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
1569a6b6d51bSFrancois Ferrand   MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
15706bb103f9SFrancois Ferrand   MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
1571a081002bSBirunthan Mohanathas   MozillaStyle.ConstructorInitializerIndentWidth = 2;
1572a081002bSBirunthan Mohanathas   MozillaStyle.ContinuationIndentWidth = 2;
1573f8b7266dSChandler Carruth   MozillaStyle.Cpp11BracedListStyle = false;
157432eaa864SKrasimir Georgiev   MozillaStyle.FixNamespaceComments = false;
1575c860266eSAlexander Kornienko   MozillaStyle.IndentCaseLabels = true;
1576e9beea24SDaniel Jasper   MozillaStyle.ObjCSpaceAfterProperty = true;
1577c860266eSAlexander Kornienko   MozillaStyle.ObjCSpaceBeforeProtocolList = false;
1578c860266eSAlexander Kornienko   MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
1579553d4878SDaniel Jasper   MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
158083bbd573SSylvestre Ledru   MozillaStyle.SpaceAfterTemplateKeyword = false;
1581c860266eSAlexander Kornienko   return MozillaStyle;
1582c860266eSAlexander Kornienko }
1583c860266eSAlexander Kornienko 
getWebKitStyle()1584ffefb3d1SDaniel Jasper FormatStyle getWebKitStyle() {
1585ffefb3d1SDaniel Jasper   FormatStyle Style = getLLVMStyle();
158665ee3472SDaniel Jasper   Style.AccessModifierOffset = -4;
15876501f7e8SDaniel Jasper   Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
15880ee04e6eSFrancois Ferrand   Style.AlignOperands = FormatStyle::OAS_DontAlign;
1589552f4a7eSDaniel Jasper   Style.AlignTrailingComments = false;
159010234da7SOwen Pan   Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;
1591ac043c90SDaniel Jasper   Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
1592291f64fdSRoman Kashitsyn   Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
1593a6b6d51bSFrancois Ferrand   Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
1594f8b7266dSChandler Carruth   Style.Cpp11BracedListStyle = false;
159565ee3472SDaniel Jasper   Style.ColumnLimit = 0;
159632eaa864SKrasimir Georgiev   Style.FixNamespaceComments = false;
1597e33d4afaSDaniel Jasper   Style.IndentWidth = 4;
159865ee3472SDaniel Jasper   Style.NamespaceIndentation = FormatStyle::NI_Inner;
159950d634b3SDaniel Jasper   Style.ObjCBlockIndentWidth = 4;
1600e9beea24SDaniel Jasper   Style.ObjCSpaceAfterProperty = true;
1601553d4878SDaniel Jasper   Style.PointerAlignment = FormatStyle::PAS_Left;
1602bfc34065SHans Wennborg   Style.SpaceBeforeCpp11BracedList = true;
1603db4ad360SOwen Pan   Style.SpaceInEmptyBlock = true;
1604ffefb3d1SDaniel Jasper   return Style;
1605ffefb3d1SDaniel Jasper }
1606ffefb3d1SDaniel Jasper 
getGNUStyle()1607fe7a57faSAlexander Kornienko FormatStyle getGNUStyle() {
1608fe7a57faSAlexander Kornienko   FormatStyle Style = getLLVMStyle();
1609a0388a8aSBirunthan Mohanathas   Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
1610448592eeSZachary Turner   Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
1611ac043c90SDaniel Jasper   Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
16123a33f029SAlexander Kornienko   Style.BreakBeforeBraces = FormatStyle::BS_GNU;
1613fe7a57faSAlexander Kornienko   Style.BreakBeforeTernaryOperators = true;
1614f8b7266dSChandler Carruth   Style.Cpp11BracedListStyle = false;
1615fe7a57faSAlexander Kornienko   Style.ColumnLimit = 79;
161632eaa864SKrasimir Georgiev   Style.FixNamespaceComments = false;
1617fe7a57faSAlexander Kornienko   Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
1618f8b7266dSChandler Carruth   Style.Standard = FormatStyle::LS_Cpp03;
1619fe7a57faSAlexander Kornienko   return Style;
1620fe7a57faSAlexander Kornienko }
1621fe7a57faSAlexander Kornienko 
getMicrosoftStyle(FormatStyle::LanguageKind Language)1622cbb726d0SPaul Hoad FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) {
1623a2f963bbSPaul Hoad   FormatStyle Style = getLLVMStyle(Language);
1624cbb726d0SPaul Hoad   Style.ColumnLimit = 120;
1625cbb726d0SPaul Hoad   Style.TabWidth = 4;
1626cbb726d0SPaul Hoad   Style.IndentWidth = 4;
1627cbb726d0SPaul Hoad   Style.UseTab = FormatStyle::UT_Never;
1628cbb726d0SPaul Hoad   Style.BreakBeforeBraces = FormatStyle::BS_Custom;
1629cbb726d0SPaul Hoad   Style.BraceWrapping.AfterClass = true;
1630fb13e65aSPaul Hoad   Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
1631cbb726d0SPaul Hoad   Style.BraceWrapping.AfterEnum = true;
1632cbb726d0SPaul Hoad   Style.BraceWrapping.AfterFunction = true;
1633cbb726d0SPaul Hoad   Style.BraceWrapping.AfterNamespace = true;
1634cbb726d0SPaul Hoad   Style.BraceWrapping.AfterObjCDeclaration = true;
1635cbb726d0SPaul Hoad   Style.BraceWrapping.AfterStruct = true;
1636cbb726d0SPaul Hoad   Style.BraceWrapping.AfterExternBlock = true;
16376ef45b04Smydeveloperday   Style.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
1638cbb726d0SPaul Hoad   Style.BraceWrapping.BeforeCatch = true;
1639cbb726d0SPaul Hoad   Style.BraceWrapping.BeforeElse = true;
1640807ab2cdSmydeveloperday   Style.BraceWrapping.BeforeWhile = false;
1641cbb726d0SPaul Hoad   Style.PenaltyReturnTypeOnItsOwnLine = 1000;
1642292058a5SAaron Smith   Style.AllowShortEnumsOnASingleLine = false;
1643cbb726d0SPaul Hoad   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
1644cbb726d0SPaul Hoad   Style.AllowShortCaseLabelsOnASingleLine = false;
1645cbb726d0SPaul Hoad   Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
1646cbb726d0SPaul Hoad   Style.AllowShortLoopsOnASingleLine = false;
1647a2f963bbSPaul Hoad   Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
1648a2f963bbSPaul Hoad   Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
1649cbb726d0SPaul Hoad   return Style;
1650cbb726d0SPaul Hoad }
1651cbb726d0SPaul Hoad 
getNoStyle()1652c64b09acSDaniel Jasper FormatStyle getNoStyle() {
1653c64b09acSDaniel Jasper   FormatStyle NoStyle = getLLVMStyle();
1654c64b09acSDaniel Jasper   NoStyle.DisableFormat = true;
1655a8105b37SKent Sommer   NoStyle.SortIncludes = FormatStyle::SI_Never;
1656ac16a201SKrasimir Georgiev   NoStyle.SortUsingDeclarations = false;
1657c64b09acSDaniel Jasper   return NoStyle;
1658c64b09acSDaniel Jasper }
1659c64b09acSDaniel Jasper 
getPredefinedStyle(StringRef Name,FormatStyle::LanguageKind Language,FormatStyle * Style)1660c1637f16SAlexander Kornienko bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
1661c1637f16SAlexander Kornienko                         FormatStyle *Style) {
1662d079995dSMarek Kurdej   if (Name.equals_insensitive("llvm"))
166355881d5dSJordan Rupprecht     *Style = getLLVMStyle(Language);
1664d079995dSMarek Kurdej   else if (Name.equals_insensitive("chromium"))
1665514ecc8cSNico Weber     *Style = getChromiumStyle(Language);
1666d079995dSMarek Kurdej   else if (Name.equals_insensitive("mozilla"))
1667006b5c89SAlexander Kornienko     *Style = getMozillaStyle();
1668d079995dSMarek Kurdej   else if (Name.equals_insensitive("google"))
1669514ecc8cSNico Weber     *Style = getGoogleStyle(Language);
1670d079995dSMarek Kurdej   else if (Name.equals_insensitive("webkit"))
1671ffefb3d1SDaniel Jasper     *Style = getWebKitStyle();
1672d079995dSMarek Kurdej   else if (Name.equals_insensitive("gnu"))
1673fe7a57faSAlexander Kornienko     *Style = getGNUStyle();
1674d079995dSMarek Kurdej   else if (Name.equals_insensitive("microsoft"))
1675cbb726d0SPaul Hoad     *Style = getMicrosoftStyle(Language);
1676d079995dSMarek Kurdej   else if (Name.equals_insensitive("none"))
1677c64b09acSDaniel Jasper     *Style = getNoStyle();
1678d079995dSMarek Kurdej   else if (Name.equals_insensitive("inheritparentconfig"))
167925f753c5SBjörn Schäpers     Style->InheritsParentConfig = true;
1680d079995dSMarek Kurdej   else
1681006b5c89SAlexander Kornienko     return false;
1682d6538338SAlexander Kornienko 
1683c1637f16SAlexander Kornienko   Style->Language = Language;
1684006b5c89SAlexander Kornienko   return true;
1685d6538338SAlexander Kornienko }
1686d6538338SAlexander Kornienko 
validateQualifierOrder(FormatStyle * Style)1687a44ab170Smydeveloperday ParseError validateQualifierOrder(FormatStyle *Style) {
1688a44ab170Smydeveloperday   // If its empty then it means don't do anything.
1689a44ab170Smydeveloperday   if (Style->QualifierOrder.empty())
1690a44ab170Smydeveloperday     return ParseError::MissingQualifierOrder;
1691a44ab170Smydeveloperday 
1692a44ab170Smydeveloperday   // Ensure the list contains only currently valid qualifiers.
1693a44ab170Smydeveloperday   for (const auto &Qualifier : Style->QualifierOrder) {
1694a44ab170Smydeveloperday     if (Qualifier == "type")
1695a44ab170Smydeveloperday       continue;
1696a44ab170Smydeveloperday     auto token =
1697a44ab170Smydeveloperday         LeftRightQualifierAlignmentFixer::getTokenFromQualifier(Qualifier);
1698a44ab170Smydeveloperday     if (token == tok::identifier)
1699a44ab170Smydeveloperday       return ParseError::InvalidQualifierSpecified;
1700a44ab170Smydeveloperday   }
1701aacc110bSKrystian Kuzniarek 
1702aacc110bSKrystian Kuzniarek   // Ensure the list is unique (no duplicates).
1703a44ab170Smydeveloperday   std::set<std::string> UniqueQualifiers(Style->QualifierOrder.begin(),
1704a44ab170Smydeveloperday                                          Style->QualifierOrder.end());
1705a44ab170Smydeveloperday   if (Style->QualifierOrder.size() != UniqueQualifiers.size()) {
1706a44ab170Smydeveloperday     LLVM_DEBUG(llvm::dbgs()
1707a44ab170Smydeveloperday                << "Duplicate Qualifiers " << Style->QualifierOrder.size()
1708a44ab170Smydeveloperday                << " vs " << UniqueQualifiers.size() << "\n");
1709a44ab170Smydeveloperday     return ParseError::DuplicateQualifierSpecified;
1710a44ab170Smydeveloperday   }
1711a44ab170Smydeveloperday 
171277e60bc4Sowenca   // Ensure the list has 'type' in it.
1713a44ab170Smydeveloperday   auto type = std::find(Style->QualifierOrder.begin(),
1714a44ab170Smydeveloperday                         Style->QualifierOrder.end(), "type");
1715a44ab170Smydeveloperday   if (type == Style->QualifierOrder.end())
1716a44ab170Smydeveloperday     return ParseError::MissingQualifierType;
1717aacc110bSKrystian Kuzniarek 
1718a44ab170Smydeveloperday   return ParseError::Success;
1719a44ab170Smydeveloperday }
1720a44ab170Smydeveloperday 
parseConfiguration(llvm::MemoryBufferRef Config,FormatStyle * Style,bool AllowUnknownOptions,llvm::SourceMgr::DiagHandlerTy DiagHandler,void * DiagHandlerCtxt)1721eb9483b2SNathan James std::error_code parseConfiguration(llvm::MemoryBufferRef Config,
1722e7309404SBjörn Schäpers                                    FormatStyle *Style, bool AllowUnknownOptions,
1723e7309404SBjörn Schäpers                                    llvm::SourceMgr::DiagHandlerTy DiagHandler,
1724e7309404SBjörn Schäpers                                    void *DiagHandlerCtxt) {
1725cabdd738SAlexander Kornienko   assert(Style);
1726c1637f16SAlexander Kornienko   FormatStyle::LanguageKind Language = Style->Language;
1727c1637f16SAlexander Kornienko   assert(Language != FormatStyle::LK_None);
1728eb9483b2SNathan James   if (Config.getBuffer().trim().empty())
17290cb9c6eaSowenca     return make_error_code(ParseError::Success);
173054076fe1SKrasimir Georgiev   Style->StyleSet.Clear();
1731cabdd738SAlexander Kornienko   std::vector<FormatStyle> Styles;
1732e7309404SBjörn Schäpers   llvm::yaml::Input Input(Config, /*Ctxt=*/nullptr, DiagHandler,
1733e7309404SBjörn Schäpers                           DiagHandlerCtxt);
1734c1637f16SAlexander Kornienko   // DocumentListTraits<vector<FormatStyle>> uses the context to get default
1735c1637f16SAlexander Kornienko   // values for the fields, keys for which are missing from the configuration.
1736c1637f16SAlexander Kornienko   // Mapping also uses the context to get the language to find the correct
1737c1637f16SAlexander Kornienko   // base style.
1738c1637f16SAlexander Kornienko   Input.setContext(Style);
1739f64903fdSJoachim Meyer   Input.setAllowUnknownKeys(AllowUnknownOptions);
1740cabdd738SAlexander Kornienko   Input >> Styles;
1741cabdd738SAlexander Kornienko   if (Input.error())
1742d6538338SAlexander Kornienko     return Input.error();
1743cabdd738SAlexander Kornienko 
1744c1637f16SAlexander Kornienko   for (unsigned i = 0; i < Styles.size(); ++i) {
1745cabdd738SAlexander Kornienko     // Ensures that only the first configuration can skip the Language option.
1746c1637f16SAlexander Kornienko     if (Styles[i].Language == FormatStyle::LK_None && i != 0)
1747d0136707SRafael Espindola       return make_error_code(ParseError::Error);
1748cabdd738SAlexander Kornienko     // Ensure that each language is configured at most once.
1749c1637f16SAlexander Kornienko     for (unsigned j = 0; j < i; ++j) {
1750c1637f16SAlexander Kornienko       if (Styles[i].Language == Styles[j].Language) {
17513538b39eSNicola Zaghen         LLVM_DEBUG(llvm::dbgs()
17523538b39eSNicola Zaghen                    << "Duplicate languages in the config file on positions "
17533538b39eSNicola Zaghen                    << j << " and " << i << "\n");
1754d0136707SRafael Espindola         return make_error_code(ParseError::Error);
1755cabdd738SAlexander Kornienko       }
1756cabdd738SAlexander Kornienko     }
1757c1637f16SAlexander Kornienko   }
1758cabdd738SAlexander Kornienko   // Look for a suitable configuration starting from the end, so we can
1759cabdd738SAlexander Kornienko   // find the configuration for the specific language first, and the default
1760c1637f16SAlexander Kornienko   // configuration (which can only be at slot 0) after it.
176154076fe1SKrasimir Georgiev   FormatStyle::FormatStyleSet StyleSet;
176254076fe1SKrasimir Georgiev   bool LanguageFound = false;
1763545317cbSMarek Kurdej   for (const FormatStyle &Style : llvm::reverse(Styles)) {
1764545317cbSMarek Kurdej     if (Style.Language != FormatStyle::LK_None)
1765545317cbSMarek Kurdej       StyleSet.Add(Style);
1766545317cbSMarek Kurdej     if (Style.Language == Language)
176754076fe1SKrasimir Georgiev       LanguageFound = true;
1768cabdd738SAlexander Kornienko   }
176954076fe1SKrasimir Georgiev   if (!LanguageFound) {
177054076fe1SKrasimir Georgiev     if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None)
1771d0136707SRafael Espindola       return make_error_code(ParseError::Unsuitable);
177254076fe1SKrasimir Georgiev     FormatStyle DefaultStyle = Styles[0];
177354076fe1SKrasimir Georgiev     DefaultStyle.Language = Language;
177454076fe1SKrasimir Georgiev     StyleSet.Add(std::move(DefaultStyle));
177554076fe1SKrasimir Georgiev   }
177654076fe1SKrasimir Georgiev   *Style = *StyleSet.Get(Language);
1777a324fcf1SMartin Probst   if (Style->InsertTrailingCommas != FormatStyle::TCS_None &&
1778a324fcf1SMartin Probst       Style->BinPackArguments) {
1779a324fcf1SMartin Probst     // See comment on FormatStyle::TSC_Wrapped.
1780a324fcf1SMartin Probst     return make_error_code(ParseError::BinPackTrailingCommaConflict);
1781a324fcf1SMartin Probst   }
1782a44ab170Smydeveloperday   if (Style->QualifierAlignment != FormatStyle::QAS_Leave)
1783a44ab170Smydeveloperday     return make_error_code(validateQualifierOrder(Style));
178454076fe1SKrasimir Georgiev   return make_error_code(ParseError::Success);
1785d6538338SAlexander Kornienko }
1786d6538338SAlexander Kornienko 
configurationAsText(const FormatStyle & Style)1787d6538338SAlexander Kornienko std::string configurationAsText(const FormatStyle &Style) {
1788d6538338SAlexander Kornienko   std::string Text;
1789d6538338SAlexander Kornienko   llvm::raw_string_ostream Stream(Text);
1790d6538338SAlexander Kornienko   llvm::yaml::Output Output(Stream);
1791d6538338SAlexander Kornienko   // We use the same mapping method for input and output, so we need a non-const
1792d6538338SAlexander Kornienko   // reference here.
17936facafe7SC. Rayroud   FormatStyle NonConstStyle = Style;
17946facafe7SC. Rayroud   expandPresetsBraceWrapping(NonConstStyle);
17956facafe7SC. Rayroud   expandPresetsSpaceBeforeParens(NonConstStyle);
1796d6538338SAlexander Kornienko   Output << NonConstStyle;
17976facafe7SC. Rayroud 
17989a38ec26SAlexander Kornienko   return Stream.str();
1799d6538338SAlexander Kornienko }
1800d6538338SAlexander Kornienko 
180154076fe1SKrasimir Georgiev llvm::Optional<FormatStyle>
Get(FormatStyle::LanguageKind Language) const180254076fe1SKrasimir Georgiev FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {
180354076fe1SKrasimir Georgiev   if (!Styles)
180454076fe1SKrasimir Georgiev     return None;
180554076fe1SKrasimir Georgiev   auto It = Styles->find(Language);
180654076fe1SKrasimir Georgiev   if (It == Styles->end())
180754076fe1SKrasimir Georgiev     return None;
180854076fe1SKrasimir Georgiev   FormatStyle Style = It->second;
180954076fe1SKrasimir Georgiev   Style.StyleSet = *this;
181054076fe1SKrasimir Georgiev   return Style;
181154076fe1SKrasimir Georgiev }
181254076fe1SKrasimir Georgiev 
Add(FormatStyle Style)181354076fe1SKrasimir Georgiev void FormatStyle::FormatStyleSet::Add(FormatStyle Style) {
181454076fe1SKrasimir Georgiev   assert(Style.Language != LK_None &&
181554076fe1SKrasimir Georgiev          "Cannot add a style for LK_None to a StyleSet");
181654076fe1SKrasimir Georgiev   assert(
181754076fe1SKrasimir Georgiev       !Style.StyleSet.Styles &&
181854076fe1SKrasimir Georgiev       "Cannot add a style associated with an existing StyleSet to a StyleSet");
181954076fe1SKrasimir Georgiev   if (!Styles)
182054076fe1SKrasimir Georgiev     Styles = std::make_shared<MapType>();
182154076fe1SKrasimir Georgiev   (*Styles)[Style.Language] = std::move(Style);
182254076fe1SKrasimir Georgiev }
182354076fe1SKrasimir Georgiev 
Clear()18245bcf99b4SPaul Hoad void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); }
182554076fe1SKrasimir Georgiev 
182654076fe1SKrasimir Georgiev llvm::Optional<FormatStyle>
GetLanguageStyle(FormatStyle::LanguageKind Language) const182754076fe1SKrasimir Georgiev FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {
182854076fe1SKrasimir Georgiev   return StyleSet.Get(Language);
182954076fe1SKrasimir Georgiev }
183054076fe1SKrasimir Georgiev 
1831af35e852SCraig Topper namespace {
1832af35e852SCraig Topper 
183377e60bc4Sowenca class BracesInserter : public TokenAnalyzer {
183477e60bc4Sowenca public:
BracesInserter(const Environment & Env,const FormatStyle & Style)183577e60bc4Sowenca   BracesInserter(const Environment &Env, const FormatStyle &Style)
183607b3446dSowenca       : TokenAnalyzer(Env, Style) {
183707b3446dSowenca     this->Style.RemoveBracesLLVM = false;
183807b3446dSowenca   }
183977e60bc4Sowenca 
184077e60bc4Sowenca   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)184177e60bc4Sowenca   analyze(TokenAnnotator &Annotator,
184277e60bc4Sowenca           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
184377e60bc4Sowenca           FormatTokenLexer &Tokens) override {
184477e60bc4Sowenca     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
184577e60bc4Sowenca     tooling::Replacements Result;
184677e60bc4Sowenca     insertBraces(AnnotatedLines, Result);
184777e60bc4Sowenca     return {Result, 0};
184877e60bc4Sowenca   }
184977e60bc4Sowenca 
185077e60bc4Sowenca private:
insertBraces(SmallVectorImpl<AnnotatedLine * > & Lines,tooling::Replacements & Result)185177e60bc4Sowenca   void insertBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
185277e60bc4Sowenca                     tooling::Replacements &Result) {
185377e60bc4Sowenca     const auto &SourceMgr = Env.getSourceManager();
185477e60bc4Sowenca     for (AnnotatedLine *Line : Lines) {
185577e60bc4Sowenca       insertBraces(Line->Children, Result);
185677e60bc4Sowenca       if (!Line->Affected)
185777e60bc4Sowenca         continue;
185877e60bc4Sowenca       for (FormatToken *Token = Line->First; Token && !Token->Finalized;
185977e60bc4Sowenca            Token = Token->Next) {
186077e60bc4Sowenca         if (Token->BraceCount == 0)
186177e60bc4Sowenca           continue;
186277e60bc4Sowenca         std::string Brace;
186377e60bc4Sowenca         if (Token->BraceCount < 0) {
186477e60bc4Sowenca           assert(Token->BraceCount == -1);
186577e60bc4Sowenca           Brace = '{';
186677e60bc4Sowenca         } else {
1867c05da55bSowenca           Brace = '\n' + std::string(Token->BraceCount, '}');
186877e60bc4Sowenca         }
186977e60bc4Sowenca         Token->BraceCount = 0;
187077e60bc4Sowenca         const auto Start = Token->Tok.getEndLoc();
187177e60bc4Sowenca         cantFail(Result.add(tooling::Replacement(SourceMgr, Start, 0, Brace)));
187277e60bc4Sowenca       }
187377e60bc4Sowenca     }
187477e60bc4Sowenca   }
187577e60bc4Sowenca };
187677e60bc4Sowenca 
18779f616a46Sowenca class BracesRemover : public TokenAnalyzer {
18789f616a46Sowenca public:
BracesRemover(const Environment & Env,const FormatStyle & Style)18799f616a46Sowenca   BracesRemover(const Environment &Env, const FormatStyle &Style)
188007b3446dSowenca       : TokenAnalyzer(Env, Style) {
188107b3446dSowenca     this->Style.InsertBraces = false;
188207b3446dSowenca   }
18839f616a46Sowenca 
18849f616a46Sowenca   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)18859f616a46Sowenca   analyze(TokenAnnotator &Annotator,
18869f616a46Sowenca           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
18879f616a46Sowenca           FormatTokenLexer &Tokens) override {
18889f616a46Sowenca     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
18899f616a46Sowenca     tooling::Replacements Result;
18909f616a46Sowenca     removeBraces(AnnotatedLines, Result);
18919f616a46Sowenca     return {Result, 0};
18929f616a46Sowenca   }
18939f616a46Sowenca 
18949f616a46Sowenca private:
removeBraces(SmallVectorImpl<AnnotatedLine * > & Lines,tooling::Replacements & Result)18959f616a46Sowenca   void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
18969f616a46Sowenca                     tooling::Replacements &Result) {
18979f616a46Sowenca     const auto &SourceMgr = Env.getSourceManager();
1898*6ab73071Sowenca     bool EndsWithComment = false;
18999f616a46Sowenca     for (AnnotatedLine *Line : Lines) {
19009f616a46Sowenca       removeBraces(Line->Children, Result);
1901*6ab73071Sowenca       if (Line->Affected) {
19029f616a46Sowenca         for (FormatToken *Token = Line->First; Token && !Token->Finalized;
19039f616a46Sowenca              Token = Token->Next) {
19049f616a46Sowenca           if (!Token->Optional)
19059f616a46Sowenca             continue;
19069f616a46Sowenca           assert(Token->isOneOf(tok::l_brace, tok::r_brace));
1907*6ab73071Sowenca           assert(Token->Previous || Token == Line->First);
1908*6ab73071Sowenca           const FormatToken *Next = Token->Next;
1909*6ab73071Sowenca           assert(Next || Token == Line->Last);
19109f616a46Sowenca           const auto Start =
1911*6ab73071Sowenca               (!Token->Previous && EndsWithComment) ||
1912*6ab73071Sowenca                       (Next && !(Next->isOneOf(tok::kw_else, tok::comment) &&
1913*6ab73071Sowenca                                  Next->NewlinesBefore > 0))
1914*6ab73071Sowenca                   ? Token->Tok.getLocation()
1915*6ab73071Sowenca                   : Token->WhitespaceRange.getBegin();
19169f616a46Sowenca           const auto Range =
19179f616a46Sowenca               CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
19189f616a46Sowenca           cantFail(Result.add(tooling::Replacement(SourceMgr, Range, "")));
19199f616a46Sowenca         }
19209f616a46Sowenca       }
1921*6ab73071Sowenca       assert(Line->Last);
1922*6ab73071Sowenca       EndsWithComment = Line->Last->is(tok::comment);
1923*6ab73071Sowenca     }
19249f616a46Sowenca   }
19259f616a46Sowenca };
19269f616a46Sowenca 
1927496c1999SDaniel Jasper class JavaScriptRequoter : public TokenAnalyzer {
19284cfb88a9SEric Liu public:
JavaScriptRequoter(const Environment & Env,const FormatStyle & Style)1929496c1999SDaniel Jasper   JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)
1930496c1999SDaniel Jasper       : TokenAnalyzer(Env, Style) {}
19314cfb88a9SEric Liu 
19329ad83fe7SKrasimir Georgiev   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)19334cfb88a9SEric Liu   analyze(TokenAnnotator &Annotator,
19344cfb88a9SEric Liu           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1935a9855afeSMartin Probst           FormatTokenLexer &Tokens) override {
19360dddcf78SManuel Klimek     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
1937496c1999SDaniel Jasper     tooling::Replacements Result;
1938496c1999SDaniel Jasper     requoteJSStringLiteral(AnnotatedLines, Result);
19399ad83fe7SKrasimir Georgiev     return {Result, 0};
194062b85b96SAlexander Kornienko   }
194162b85b96SAlexander Kornienko 
194262b85b96SAlexander Kornienko private:
1943496c1999SDaniel Jasper   // Replaces double/single-quoted string literal as appropriate, re-escaping
1944496c1999SDaniel Jasper   // the contents in the process.
requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine * > & Lines,tooling::Replacements & Result)194597439926SDaniel Jasper   void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
194697439926SDaniel Jasper                               tooling::Replacements &Result) {
194797439926SDaniel Jasper     for (AnnotatedLine *Line : Lines) {
194897439926SDaniel Jasper       requoteJSStringLiteral(Line->Children, Result);
194997439926SDaniel Jasper       if (!Line->Affected)
195097439926SDaniel Jasper         continue;
195197439926SDaniel Jasper       for (FormatToken *FormatTok = Line->First; FormatTok;
195297439926SDaniel Jasper            FormatTok = FormatTok->Next) {
195397439926SDaniel Jasper         StringRef Input = FormatTok->TokenText;
1954a166979eSMartin Probst         if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
195597439926SDaniel Jasper             // NB: testing for not starting with a double quote to avoid
1956496c1999SDaniel Jasper             // breaking `template strings`.
1957635423e6SEric Liu             (Style.JavaScriptQuotes == FormatStyle::JSQS_Single &&
195897439926SDaniel Jasper              !Input.startswith("\"")) ||
1959635423e6SEric Liu             (Style.JavaScriptQuotes == FormatStyle::JSQS_Double &&
1960bebf7bdfSowenca              !Input.startswith("\'"))) {
196197439926SDaniel Jasper           continue;
1962bebf7bdfSowenca         }
196397439926SDaniel Jasper 
196497439926SDaniel Jasper         // Change start and end quote.
1965635423e6SEric Liu         bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single;
196697439926SDaniel Jasper         SourceLocation Start = FormatTok->Tok.getLocation();
196797439926SDaniel Jasper         auto Replace = [&](SourceLocation Start, unsigned Length,
196897439926SDaniel Jasper                            StringRef ReplacementText) {
196940ef2fb3SEric Liu           auto Err = Result.add(tooling::Replacement(
197040ef2fb3SEric Liu               Env.getSourceManager(), Start, Length, ReplacementText));
197140ef2fb3SEric Liu           // FIXME: handle error. For now, print error message and skip the
197240ef2fb3SEric Liu           // replacement for release version.
19731ec383c7SPiotr Padlewski           if (Err) {
197440ef2fb3SEric Liu             llvm::errs() << llvm::toString(std::move(Err)) << "\n";
19751ec383c7SPiotr Padlewski             assert(false);
19761ec383c7SPiotr Padlewski           }
197797439926SDaniel Jasper         };
197897439926SDaniel Jasper         Replace(Start, 1, IsSingle ? "'" : "\"");
197997439926SDaniel Jasper         Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
198097439926SDaniel Jasper                 IsSingle ? "'" : "\"");
198197439926SDaniel Jasper 
198297439926SDaniel Jasper         // Escape internal quotes.
198397439926SDaniel Jasper         bool Escaped = false;
198497439926SDaniel Jasper         for (size_t i = 1; i < Input.size() - 1; i++) {
198597439926SDaniel Jasper           switch (Input[i]) {
198697439926SDaniel Jasper           case '\\':
198797439926SDaniel Jasper             if (!Escaped && i + 1 < Input.size() &&
198897439926SDaniel Jasper                 ((IsSingle && Input[i + 1] == '"') ||
198997439926SDaniel Jasper                  (!IsSingle && Input[i + 1] == '\''))) {
199097439926SDaniel Jasper               // Remove this \, it's escaping a " or ' that no longer needs
199197439926SDaniel Jasper               // escaping
199297439926SDaniel Jasper               Replace(Start.getLocWithOffset(i), 1, "");
199397439926SDaniel Jasper               continue;
199497439926SDaniel Jasper             }
199597439926SDaniel Jasper             Escaped = !Escaped;
199697439926SDaniel Jasper             break;
199797439926SDaniel Jasper           case '\"':
199897439926SDaniel Jasper           case '\'':
199997439926SDaniel Jasper             if (!Escaped && IsSingle == (Input[i] == '\'')) {
200097439926SDaniel Jasper               // Escape the quote.
200197439926SDaniel Jasper               Replace(Start.getLocWithOffset(i), 0, "\\");
200297439926SDaniel Jasper             }
200397439926SDaniel Jasper             Escaped = false;
200497439926SDaniel Jasper             break;
200597439926SDaniel Jasper           default:
200697439926SDaniel Jasper             Escaped = false;
200797439926SDaniel Jasper             break;
200897439926SDaniel Jasper           }
200997439926SDaniel Jasper         }
2010496c1999SDaniel Jasper       }
2011496c1999SDaniel Jasper     }
2012496c1999SDaniel Jasper   }
2013496c1999SDaniel Jasper };
201497439926SDaniel Jasper 
2015496c1999SDaniel Jasper class Formatter : public TokenAnalyzer {
2016496c1999SDaniel Jasper public:
Formatter(const Environment & Env,const FormatStyle & Style,FormattingAttemptStatus * Status)2017496c1999SDaniel Jasper   Formatter(const Environment &Env, const FormatStyle &Style,
2018bcda54b6SKrasimir Georgiev             FormattingAttemptStatus *Status)
2019bcda54b6SKrasimir Georgiev       : TokenAnalyzer(Env, Style), Status(Status) {}
2020496c1999SDaniel Jasper 
20219ad83fe7SKrasimir Georgiev   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)2022496c1999SDaniel Jasper   analyze(TokenAnnotator &Annotator,
2023496c1999SDaniel Jasper           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2024496c1999SDaniel Jasper           FormatTokenLexer &Tokens) override {
2025496c1999SDaniel Jasper     tooling::Replacements Result;
2026496c1999SDaniel Jasper     deriveLocalStyle(AnnotatedLines);
20270dddcf78SManuel Klimek     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2028545317cbSMarek Kurdej     for (AnnotatedLine *Line : AnnotatedLines)
2029545317cbSMarek Kurdej       Annotator.calculateFormattingInformation(*Line);
2030496c1999SDaniel Jasper     Annotator.setCommentLineLevels(AnnotatedLines);
2031496c1999SDaniel Jasper 
2032496c1999SDaniel Jasper     WhitespaceManager Whitespaces(
2033496c1999SDaniel Jasper         Env.getSourceManager(), Style,
2034a4a7c125Smydeveloperday         Style.DeriveLineEnding
20356f6f88ffSksyx             ? WhitespaceManager::inputUsesCRLF(
2036a4a7c125Smydeveloperday                   Env.getSourceManager().getBufferData(Env.getFileID()),
2037a4a7c125Smydeveloperday                   Style.UseCRLF)
2038a4a7c125Smydeveloperday             : Style.UseCRLF);
2039496c1999SDaniel Jasper     ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
2040496c1999SDaniel Jasper                                   Env.getSourceManager(), Whitespaces, Encoding,
2041496c1999SDaniel Jasper                                   BinPackInconclusiveFunctions);
20429ad83fe7SKrasimir Georgiev     unsigned Penalty =
20439ad83fe7SKrasimir Georgiev         UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,
20449ad83fe7SKrasimir Georgiev                                Tokens.getKeywords(), Env.getSourceManager(),
20459ad83fe7SKrasimir Georgiev                                Status)
20469ad83fe7SKrasimir Georgiev             .format(AnnotatedLines, /*DryRun=*/false,
20479ad83fe7SKrasimir Georgiev                     /*AdditionalIndent=*/0,
20489ad83fe7SKrasimir Georgiev                     /*FixBadIndentation=*/false,
20499ad83fe7SKrasimir Georgiev                     /*FirstStartColumn=*/Env.getFirstStartColumn(),
20509ad83fe7SKrasimir Georgiev                     /*NextStartColumn=*/Env.getNextStartColumn(),
20519ad83fe7SKrasimir Georgiev                     /*LastStartColumn=*/Env.getLastStartColumn());
2052496c1999SDaniel Jasper     for (const auto &R : Whitespaces.generateReplacements())
2053496c1999SDaniel Jasper       if (Result.add(R))
2054e56e9a4fSKrasimir Georgiev         return std::make_pair(Result, 0);
2055e56e9a4fSKrasimir Georgiev     return std::make_pair(Result, Penalty);
205697439926SDaniel Jasper   }
2057496c1999SDaniel Jasper 
2058496c1999SDaniel Jasper private:
2059352f0df4SDaniel Jasper   bool
hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine * > & Lines)2060352f0df4SDaniel Jasper   hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) {
2061352f0df4SDaniel Jasper     for (const AnnotatedLine *Line : Lines) {
2062352f0df4SDaniel Jasper       if (hasCpp03IncompatibleFormat(Line->Children))
2063352f0df4SDaniel Jasper         return true;
2064352f0df4SDaniel Jasper       for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {
206582452be5SMarek Kurdej         if (!Tok->hasWhitespaceBefore()) {
2066352f0df4SDaniel Jasper           if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
2067352f0df4SDaniel Jasper             return true;
2068352f0df4SDaniel Jasper           if (Tok->is(TT_TemplateCloser) &&
2069bebf7bdfSowenca               Tok->Previous->is(TT_TemplateCloser)) {
2070352f0df4SDaniel Jasper             return true;
2071352f0df4SDaniel Jasper           }
2072352f0df4SDaniel Jasper         }
2073352f0df4SDaniel Jasper       }
2074bebf7bdfSowenca     }
2075352f0df4SDaniel Jasper     return false;
2076352f0df4SDaniel Jasper   }
2077352f0df4SDaniel Jasper 
countVariableAlignments(const SmallVectorImpl<AnnotatedLine * > & Lines)2078352f0df4SDaniel Jasper   int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) {
2079352f0df4SDaniel Jasper     int AlignmentDiff = 0;
2080352f0df4SDaniel Jasper     for (const AnnotatedLine *Line : Lines) {
2081352f0df4SDaniel Jasper       AlignmentDiff += countVariableAlignments(Line->Children);
2082352f0df4SDaniel Jasper       for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {
2083352f0df4SDaniel Jasper         if (!Tok->is(TT_PointerOrReference))
2084352f0df4SDaniel Jasper           continue;
2085acc3ce94SSam McCall         // Don't treat space in `void foo() &&` as evidence.
2086acc3ce94SSam McCall         if (const auto *Prev = Tok->getPreviousNonComment()) {
2087bebf7bdfSowenca           if (Prev->is(tok::r_paren) && Prev->MatchingParen) {
2088bebf7bdfSowenca             if (const auto *Func =
2089bebf7bdfSowenca                     Prev->MatchingParen->getPreviousNonComment()) {
2090acc3ce94SSam McCall               if (Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName,
2091bebf7bdfSowenca                                 TT_OverloadedOperator)) {
2092acc3ce94SSam McCall                 continue;
2093acc3ce94SSam McCall               }
2094bebf7bdfSowenca             }
2095bebf7bdfSowenca           }
2096bebf7bdfSowenca         }
209782452be5SMarek Kurdej         bool SpaceBefore = Tok->hasWhitespaceBefore();
209882452be5SMarek Kurdej         bool SpaceAfter = Tok->Next->hasWhitespaceBefore();
2099352f0df4SDaniel Jasper         if (SpaceBefore && !SpaceAfter)
2100352f0df4SDaniel Jasper           ++AlignmentDiff;
2101352f0df4SDaniel Jasper         if (!SpaceBefore && SpaceAfter)
2102352f0df4SDaniel Jasper           --AlignmentDiff;
2103352f0df4SDaniel Jasper       }
2104352f0df4SDaniel Jasper     }
2105352f0df4SDaniel Jasper     return AlignmentDiff;
2106352f0df4SDaniel Jasper   }
2107352f0df4SDaniel Jasper 
210871814b44SManuel Klimek   void
deriveLocalStyle(const SmallVectorImpl<AnnotatedLine * > & AnnotatedLines)210971814b44SManuel Klimek   deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
2110b10cbc45SDaniel Jasper     bool HasBinPackedFunction = false;
2111b10cbc45SDaniel Jasper     bool HasOnePerLineFunction = false;
2112545317cbSMarek Kurdej     for (AnnotatedLine *Line : AnnotatedLines) {
2113545317cbSMarek Kurdej       if (!Line->First->Next)
21147fce3ab0SDaniel Jasper         continue;
2115545317cbSMarek Kurdej       FormatToken *Tok = Line->First->Next;
21166e6310ecSManuel Klimek       while (Tok->Next) {
2117f5acd11dSBruno Ricci         if (Tok->is(PPK_BinPacked))
2118b10cbc45SDaniel Jasper           HasBinPackedFunction = true;
2119f5acd11dSBruno Ricci         if (Tok->is(PPK_OnePerLine))
2120b10cbc45SDaniel Jasper           HasOnePerLineFunction = true;
2121b10cbc45SDaniel Jasper 
21226e6310ecSManuel Klimek         Tok = Tok->Next;
21237fce3ab0SDaniel Jasper       }
21247fce3ab0SDaniel Jasper     }
2125a08fa8a5SSeraphime Kirkovski     if (Style.DerivePointerAlignment) {
2126635423e6SEric Liu       Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0
2127635423e6SEric Liu                                    ? FormatStyle::PAS_Left
2128352f0df4SDaniel Jasper                                    : FormatStyle::PAS_Right;
2129a08fa8a5SSeraphime Kirkovski       Style.ReferenceAlignment = FormatStyle::RAS_Pointer;
2130a08fa8a5SSeraphime Kirkovski     }
2131bebf7bdfSowenca     if (Style.Standard == FormatStyle::LS_Auto) {
2132635423e6SEric Liu       Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
2133e5032567SSam McCall                            ? FormatStyle::LS_Latest
21347fce3ab0SDaniel Jasper                            : FormatStyle::LS_Cpp03;
2135bebf7bdfSowenca     }
2136b10cbc45SDaniel Jasper     BinPackInconclusiveFunctions =
2137b10cbc45SDaniel Jasper         HasBinPackedFunction || !HasOnePerLineFunction;
21387fce3ab0SDaniel Jasper   }
21397fce3ab0SDaniel Jasper 
2140b10cbc45SDaniel Jasper   bool BinPackInconclusiveFunctions;
2141bcda54b6SKrasimir Georgiev   FormattingAttemptStatus *Status;
21424cfb88a9SEric Liu };
21434cfb88a9SEric Liu 
2144a324fcf1SMartin Probst /// TrailingCommaInserter inserts trailing commas into container literals.
2145a324fcf1SMartin Probst /// E.g.:
2146a324fcf1SMartin Probst ///     const x = [
2147a324fcf1SMartin Probst ///       1,
2148a324fcf1SMartin Probst ///     ];
2149a324fcf1SMartin Probst /// TrailingCommaInserter runs after formatting. To avoid causing a required
2150a324fcf1SMartin Probst /// reformatting (and thus reflow), it never inserts a comma that'd exceed the
2151a324fcf1SMartin Probst /// ColumnLimit.
2152a324fcf1SMartin Probst ///
2153a324fcf1SMartin Probst /// Because trailing commas disable binpacking of arrays, TrailingCommaInserter
2154a324fcf1SMartin Probst /// is conceptually incompatible with bin packing.
2155a324fcf1SMartin Probst class TrailingCommaInserter : public TokenAnalyzer {
2156a324fcf1SMartin Probst public:
TrailingCommaInserter(const Environment & Env,const FormatStyle & Style)2157a324fcf1SMartin Probst   TrailingCommaInserter(const Environment &Env, const FormatStyle &Style)
2158a324fcf1SMartin Probst       : TokenAnalyzer(Env, Style) {}
2159a324fcf1SMartin Probst 
2160a324fcf1SMartin Probst   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)2161a324fcf1SMartin Probst   analyze(TokenAnnotator &Annotator,
2162a324fcf1SMartin Probst           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2163a324fcf1SMartin Probst           FormatTokenLexer &Tokens) override {
2164a324fcf1SMartin Probst     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
2165a324fcf1SMartin Probst     tooling::Replacements Result;
2166a324fcf1SMartin Probst     insertTrailingCommas(AnnotatedLines, Result);
2167a324fcf1SMartin Probst     return {Result, 0};
2168a324fcf1SMartin Probst   }
2169a324fcf1SMartin Probst 
2170a324fcf1SMartin Probst private:
2171a324fcf1SMartin Probst   /// Inserts trailing commas in [] and {} initializers if they wrap over
2172a324fcf1SMartin Probst   /// multiple lines.
insertTrailingCommas(SmallVectorImpl<AnnotatedLine * > & Lines,tooling::Replacements & Result)2173a324fcf1SMartin Probst   void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,
2174a324fcf1SMartin Probst                             tooling::Replacements &Result) {
2175a324fcf1SMartin Probst     for (AnnotatedLine *Line : Lines) {
2176a324fcf1SMartin Probst       insertTrailingCommas(Line->Children, Result);
2177a324fcf1SMartin Probst       if (!Line->Affected)
2178a324fcf1SMartin Probst         continue;
2179a324fcf1SMartin Probst       for (FormatToken *FormatTok = Line->First; FormatTok;
2180a324fcf1SMartin Probst            FormatTok = FormatTok->Next) {
2181a324fcf1SMartin Probst         if (FormatTok->NewlinesBefore == 0)
2182a324fcf1SMartin Probst           continue;
2183a324fcf1SMartin Probst         FormatToken *Matching = FormatTok->MatchingParen;
2184a324fcf1SMartin Probst         if (!Matching || !FormatTok->getPreviousNonComment())
2185a324fcf1SMartin Probst           continue;
2186a324fcf1SMartin Probst         if (!(FormatTok->is(tok::r_square) &&
2187a324fcf1SMartin Probst               Matching->is(TT_ArrayInitializerLSquare)) &&
2188bebf7bdfSowenca             !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral))) {
2189a324fcf1SMartin Probst           continue;
2190bebf7bdfSowenca         }
2191a324fcf1SMartin Probst         FormatToken *Prev = FormatTok->getPreviousNonComment();
2192a324fcf1SMartin Probst         if (Prev->is(tok::comma) || Prev->is(tok::semi))
2193a324fcf1SMartin Probst           continue;
2194a324fcf1SMartin Probst         // getEndLoc is not reliably set during re-lexing, use text length
2195a324fcf1SMartin Probst         // instead.
2196a324fcf1SMartin Probst         SourceLocation Start =
2197a324fcf1SMartin Probst             Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size());
2198a324fcf1SMartin Probst         // If inserting a comma would push the code over the column limit, skip
2199a324fcf1SMartin Probst         // this location - it'd introduce an unstable formatting due to the
2200a324fcf1SMartin Probst         // required reflow.
2201a324fcf1SMartin Probst         unsigned ColumnNumber =
2202a324fcf1SMartin Probst             Env.getSourceManager().getSpellingColumnNumber(Start);
2203a324fcf1SMartin Probst         if (ColumnNumber > Style.ColumnLimit)
2204a324fcf1SMartin Probst           continue;
2205a324fcf1SMartin Probst         // Comma insertions cannot conflict with each other, and this pass has a
2206a324fcf1SMartin Probst         // clean set of Replacements, so the operation below cannot fail.
2207a324fcf1SMartin Probst         cantFail(Result.add(
2208a324fcf1SMartin Probst             tooling::Replacement(Env.getSourceManager(), Start, 0, ",")));
2209a324fcf1SMartin Probst       }
2210a324fcf1SMartin Probst     }
2211a324fcf1SMartin Probst   }
2212a324fcf1SMartin Probst };
2213a324fcf1SMartin Probst 
22144cfb88a9SEric Liu // This class clean up the erroneous/redundant code around the given ranges in
22154cfb88a9SEric Liu // file.
22164cfb88a9SEric Liu class Cleaner : public TokenAnalyzer {
22174cfb88a9SEric Liu public:
Cleaner(const Environment & Env,const FormatStyle & Style)2218635423e6SEric Liu   Cleaner(const Environment &Env, const FormatStyle &Style)
2219635423e6SEric Liu       : TokenAnalyzer(Env, Style),
22204cfb88a9SEric Liu         DeletedTokens(FormatTokenLess(Env.getSourceManager())) {}
22214cfb88a9SEric Liu 
22224cfb88a9SEric Liu   // FIXME: eliminate unused parameters.
22239ad83fe7SKrasimir Georgiev   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)22244cfb88a9SEric Liu   analyze(TokenAnnotator &Annotator,
22254cfb88a9SEric Liu           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2226a9855afeSMartin Probst           FormatTokenLexer &Tokens) override {
22274cfb88a9SEric Liu     // FIXME: in the current implementation the granularity of affected range
22284cfb88a9SEric Liu     // is an annotated line. However, this is not sufficient. Furthermore,
22294cfb88a9SEric Liu     // redundant code introduced by replacements does not necessarily
22304cfb88a9SEric Liu     // intercept with ranges of replacements that result in the redundancy.
22314cfb88a9SEric Liu     // To determine if some redundant code is actually introduced by
22324cfb88a9SEric Liu     // replacements(e.g. deletions), we need to come up with a more
22334cfb88a9SEric Liu     // sophisticated way of computing affected ranges.
22340dddcf78SManuel Klimek     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
22354cfb88a9SEric Liu 
22364cfb88a9SEric Liu     checkEmptyNamespace(AnnotatedLines);
22374cfb88a9SEric Liu 
223845b6ca5cSYitzhak Mandelbaum     for (auto *Line : AnnotatedLines)
223945b6ca5cSYitzhak Mandelbaum       cleanupLine(Line);
224045b6ca5cSYitzhak Mandelbaum 
224145b6ca5cSYitzhak Mandelbaum     return {generateFixes(), 0};
224245b6ca5cSYitzhak Mandelbaum   }
224345b6ca5cSYitzhak Mandelbaum 
224445b6ca5cSYitzhak Mandelbaum private:
cleanupLine(AnnotatedLine * Line)224545b6ca5cSYitzhak Mandelbaum   void cleanupLine(AnnotatedLine *Line) {
2246630c7360SMarek Kurdej     for (auto *Child : Line->Children)
224745b6ca5cSYitzhak Mandelbaum       cleanupLine(Child);
224845b6ca5cSYitzhak Mandelbaum 
2249ce5e4bc7SEric Liu     if (Line->Affected) {
2250ce5e4bc7SEric Liu       cleanupRight(Line->First, tok::comma, tok::comma);
2251ce5e4bc7SEric Liu       cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
22522574d15cSEric Liu       cleanupRight(Line->First, tok::l_paren, tok::comma);
22532574d15cSEric Liu       cleanupLeft(Line->First, tok::comma, tok::r_paren);
2254ce5e4bc7SEric Liu       cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
2255ce5e4bc7SEric Liu       cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
22565d8cdb83SMalcolm Parsons       cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
2257ce5e4bc7SEric Liu     }
2258ce5e4bc7SEric Liu   }
2259ce5e4bc7SEric Liu 
containsOnlyComments(const AnnotatedLine & Line)22604cfb88a9SEric Liu   bool containsOnlyComments(const AnnotatedLine &Line) {
2261d079995dSMarek Kurdej     for (FormatToken *Tok = Line.First; Tok != nullptr; Tok = Tok->Next)
22624cfb88a9SEric Liu       if (Tok->isNot(tok::comment))
22634cfb88a9SEric Liu         return false;
22644cfb88a9SEric Liu     return true;
22654cfb88a9SEric Liu   }
22664cfb88a9SEric Liu 
22674cfb88a9SEric Liu   // Iterate through all lines and remove any empty (nested) namespaces.
checkEmptyNamespace(SmallVectorImpl<AnnotatedLine * > & AnnotatedLines)22684cfb88a9SEric Liu   void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
22697956c400SEric Liu     std::set<unsigned> DeletedLines;
22704cfb88a9SEric Liu     for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
22714cfb88a9SEric Liu       auto &Line = *AnnotatedLines[i];
2272630c7360SMarek Kurdej       if (Line.startsWithNamespace())
22737956c400SEric Liu         checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
22744cfb88a9SEric Liu     }
22754cfb88a9SEric Liu 
22764cfb88a9SEric Liu     for (auto Line : DeletedLines) {
22774cfb88a9SEric Liu       FormatToken *Tok = AnnotatedLines[Line]->First;
22784cfb88a9SEric Liu       while (Tok) {
22794cfb88a9SEric Liu         deleteToken(Tok);
22804cfb88a9SEric Liu         Tok = Tok->Next;
22814cfb88a9SEric Liu       }
22824cfb88a9SEric Liu     }
22834cfb88a9SEric Liu   }
22844cfb88a9SEric Liu 
22854cfb88a9SEric Liu   // The function checks if the namespace, which starts from \p CurrentLine, and
22864cfb88a9SEric Liu   // its nested namespaces are empty and delete them if they are empty. It also
22874cfb88a9SEric Liu   // sets \p NewLine to the last line checked.
22884cfb88a9SEric Liu   // Returns true if the current namespace is empty.
checkEmptyNamespace(SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,unsigned CurrentLine,unsigned & NewLine,std::set<unsigned> & DeletedLines)22894cfb88a9SEric Liu   bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
22907956c400SEric Liu                            unsigned CurrentLine, unsigned &NewLine,
22917956c400SEric Liu                            std::set<unsigned> &DeletedLines) {
22924cfb88a9SEric Liu     unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
2293635423e6SEric Liu     if (Style.BraceWrapping.AfterNamespace) {
22944cfb88a9SEric Liu       // If the left brace is in a new line, we should consume it first so that
22954cfb88a9SEric Liu       // it does not make the namespace non-empty.
22964cfb88a9SEric Liu       // FIXME: error handling if there is no left brace.
22974cfb88a9SEric Liu       if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
22984cfb88a9SEric Liu         NewLine = CurrentLine;
22994cfb88a9SEric Liu         return false;
23004cfb88a9SEric Liu       }
23014cfb88a9SEric Liu     } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
23024cfb88a9SEric Liu       return false;
23034cfb88a9SEric Liu     }
23044cfb88a9SEric Liu     while (++CurrentLine < End) {
23054cfb88a9SEric Liu       if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
23064cfb88a9SEric Liu         break;
23074cfb88a9SEric Liu 
23086f3778c3SSam McCall       if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
23097956c400SEric Liu         if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
2310bebf7bdfSowenca                                  DeletedLines)) {
23114cfb88a9SEric Liu           return false;
2312bebf7bdfSowenca         }
23134cfb88a9SEric Liu         CurrentLine = NewLine;
23144cfb88a9SEric Liu         continue;
23154cfb88a9SEric Liu       }
23164cfb88a9SEric Liu 
23174cfb88a9SEric Liu       if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
23184cfb88a9SEric Liu         continue;
23194cfb88a9SEric Liu 
23204cfb88a9SEric Liu       // If there is anything other than comments or nested namespaces in the
23214cfb88a9SEric Liu       // current namespace, the namespace cannot be empty.
23224cfb88a9SEric Liu       NewLine = CurrentLine;
23234cfb88a9SEric Liu       return false;
23244cfb88a9SEric Liu     }
23254cfb88a9SEric Liu 
23264cfb88a9SEric Liu     NewLine = CurrentLine;
23274cfb88a9SEric Liu     if (CurrentLine >= End)
23284cfb88a9SEric Liu       return false;
23294cfb88a9SEric Liu 
23304cfb88a9SEric Liu     // Check if the empty namespace is actually affected by changed ranges.
23314cfb88a9SEric Liu     if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
23324cfb88a9SEric Liu             AnnotatedLines[InitLine]->First->Tok.getLocation(),
2333bebf7bdfSowenca             AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc()))) {
23344cfb88a9SEric Liu       return false;
2335bebf7bdfSowenca     }
23364cfb88a9SEric Liu 
2337630c7360SMarek Kurdej     for (unsigned i = InitLine; i <= CurrentLine; ++i)
23384cfb88a9SEric Liu       DeletedLines.insert(i);
23394cfb88a9SEric Liu 
23404cfb88a9SEric Liu     return true;
23414cfb88a9SEric Liu   }
23424cfb88a9SEric Liu 
2343ce5e4bc7SEric Liu   // Checks pairs {start, start->next},..., {end->previous, end} and deletes one
2344ce5e4bc7SEric Liu   // of the token in the pair if the left token has \p LK token kind and the
2345ce5e4bc7SEric Liu   // right token has \p RK token kind. If \p DeleteLeft is true, the left token
2346ce5e4bc7SEric Liu   // is deleted on match; otherwise, the right token is deleted.
2347ce5e4bc7SEric Liu   template <typename LeftKind, typename RightKind>
cleanupPair(FormatToken * Start,LeftKind LK,RightKind RK,bool DeleteLeft)2348ce5e4bc7SEric Liu   void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
2349ce5e4bc7SEric Liu                    bool DeleteLeft) {
2350ce5e4bc7SEric Liu     auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {
2351bebf7bdfSowenca       for (auto *Res = Tok.Next; Res; Res = Res->Next) {
2352ce5e4bc7SEric Liu         if (!Res->is(tok::comment) &&
2353bebf7bdfSowenca             DeletedTokens.find(Res) == DeletedTokens.end()) {
2354ce5e4bc7SEric Liu           return Res;
2355bebf7bdfSowenca         }
2356bebf7bdfSowenca       }
2357ce5e4bc7SEric Liu       return nullptr;
2358ce5e4bc7SEric Liu     };
2359ce5e4bc7SEric Liu     for (auto *Left = Start; Left;) {
2360ce5e4bc7SEric Liu       auto *Right = NextNotDeleted(*Left);
2361ce5e4bc7SEric Liu       if (!Right)
2362ce5e4bc7SEric Liu         break;
2363ce5e4bc7SEric Liu       if (Left->is(LK) && Right->is(RK)) {
2364ce5e4bc7SEric Liu         deleteToken(DeleteLeft ? Left : Right);
236501426ff8SEric Liu         for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
236601426ff8SEric Liu           deleteToken(Tok);
2367ce5e4bc7SEric Liu         // If the right token is deleted, we should keep the left token
2368ce5e4bc7SEric Liu         // unchanged and pair it with the new right token.
2369ce5e4bc7SEric Liu         if (!DeleteLeft)
2370ce5e4bc7SEric Liu           continue;
2371ce5e4bc7SEric Liu       }
2372ce5e4bc7SEric Liu       Left = Right;
2373ce5e4bc7SEric Liu     }
2374ce5e4bc7SEric Liu   }
2375ce5e4bc7SEric Liu 
2376ce5e4bc7SEric Liu   template <typename LeftKind, typename RightKind>
cleanupLeft(FormatToken * Start,LeftKind LK,RightKind RK)2377ce5e4bc7SEric Liu   void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
2378ce5e4bc7SEric Liu     cleanupPair(Start, LK, RK, /*DeleteLeft=*/true);
2379ce5e4bc7SEric Liu   }
2380ce5e4bc7SEric Liu 
2381ce5e4bc7SEric Liu   template <typename LeftKind, typename RightKind>
cleanupRight(FormatToken * Start,LeftKind LK,RightKind RK)2382ce5e4bc7SEric Liu   void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
2383ce5e4bc7SEric Liu     cleanupPair(Start, LK, RK, /*DeleteLeft=*/false);
2384ce5e4bc7SEric Liu   }
2385ce5e4bc7SEric Liu 
23864cfb88a9SEric Liu   // Delete the given token.
deleteToken(FormatToken * Tok)23874cfb88a9SEric Liu   inline void deleteToken(FormatToken *Tok) {
23884cfb88a9SEric Liu     if (Tok)
23894cfb88a9SEric Liu       DeletedTokens.insert(Tok);
23904cfb88a9SEric Liu   }
23914cfb88a9SEric Liu 
generateFixes()23924cfb88a9SEric Liu   tooling::Replacements generateFixes() {
23934cfb88a9SEric Liu     tooling::Replacements Fixes;
239436229fa3Sowenca     SmallVector<FormatToken *> Tokens;
23954cfb88a9SEric Liu     std::copy(DeletedTokens.begin(), DeletedTokens.end(),
23964cfb88a9SEric Liu               std::back_inserter(Tokens));
23974cfb88a9SEric Liu 
23984cfb88a9SEric Liu     // Merge multiple continuous token deletions into one big deletion so that
23994cfb88a9SEric Liu     // the number of replacements can be reduced. This makes computing affected
24004cfb88a9SEric Liu     // ranges more efficient when we run reformat on the changed code.
24014cfb88a9SEric Liu     unsigned Idx = 0;
24024cfb88a9SEric Liu     while (Idx < Tokens.size()) {
24034cfb88a9SEric Liu       unsigned St = Idx, End = Idx;
2404d079995dSMarek Kurdej       while ((End + 1) < Tokens.size() && Tokens[End]->Next == Tokens[End + 1])
2405359b4e6cSMarek Kurdej         ++End;
24064cfb88a9SEric Liu       auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
24074cfb88a9SEric Liu                                               Tokens[End]->Tok.getEndLoc());
240840ef2fb3SEric Liu       auto Err =
240940ef2fb3SEric Liu           Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, ""));
241040ef2fb3SEric Liu       // FIXME: better error handling. for now just print error message and skip
241140ef2fb3SEric Liu       // for the release version.
24121ec383c7SPiotr Padlewski       if (Err) {
241340ef2fb3SEric Liu         llvm::errs() << llvm::toString(std::move(Err)) << "\n";
24141ec383c7SPiotr Padlewski         assert(false && "Fixes must not conflict!");
24151ec383c7SPiotr Padlewski       }
24164cfb88a9SEric Liu       Idx = End + 1;
24174cfb88a9SEric Liu     }
24184cfb88a9SEric Liu 
24194cfb88a9SEric Liu     return Fixes;
24204cfb88a9SEric Liu   }
24214cfb88a9SEric Liu 
24224cfb88a9SEric Liu   // Class for less-than inequality comparason for the set `RedundantTokens`.
24234cfb88a9SEric Liu   // We store tokens in the order they appear in the translation unit so that
24244cfb88a9SEric Liu   // we do not need to sort them in `generateFixes()`.
24254cfb88a9SEric Liu   struct FormatTokenLess {
FormatTokenLessclang::format::__anon8802244b0111::Cleaner::FormatTokenLess2426635423e6SEric Liu     FormatTokenLess(const SourceManager &SM) : SM(SM) {}
24274cfb88a9SEric Liu 
operator ()clang::format::__anon8802244b0111::Cleaner::FormatTokenLess24282874ac3eSEric Liu     bool operator()(const FormatToken *LHS, const FormatToken *RHS) const {
24294cfb88a9SEric Liu       return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
24304cfb88a9SEric Liu                                           RHS->Tok.getLocation());
24314cfb88a9SEric Liu     }
2432635423e6SEric Liu     const SourceManager &SM;
24334cfb88a9SEric Liu   };
24344cfb88a9SEric Liu 
24354cfb88a9SEric Liu   // Tokens to be deleted.
24364cfb88a9SEric Liu   std::set<FormatToken *, FormatTokenLess> DeletedTokens;
2437f7935115SDaniel Jasper };
2438f7935115SDaniel Jasper 
2439e2e3e67cSBen Hamilton class ObjCHeaderStyleGuesser : public TokenAnalyzer {
2440e2e3e67cSBen Hamilton public:
ObjCHeaderStyleGuesser(const Environment & Env,const FormatStyle & Style)2441e2e3e67cSBen Hamilton   ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style)
2442e2e3e67cSBen Hamilton       : TokenAnalyzer(Env, Style), IsObjC(false) {}
2443e2e3e67cSBen Hamilton 
2444e2e3e67cSBen Hamilton   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)2445e2e3e67cSBen Hamilton   analyze(TokenAnnotator &Annotator,
2446e2e3e67cSBen Hamilton           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2447e2e3e67cSBen Hamilton           FormatTokenLexer &Tokens) override {
2448e2e3e67cSBen Hamilton     assert(Style.Language == FormatStyle::LK_Cpp);
24490675e87eSBen Hamilton     IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines,
24500675e87eSBen Hamilton                          Tokens.getKeywords());
2451e2e3e67cSBen Hamilton     tooling::Replacements Result;
2452e2e3e67cSBen Hamilton     return {Result, 0};
2453e2e3e67cSBen Hamilton   }
2454e2e3e67cSBen Hamilton 
isObjC()2455e2e3e67cSBen Hamilton   bool isObjC() { return IsObjC; }
2456e2e3e67cSBen Hamilton 
2457e2e3e67cSBen Hamilton private:
24580675e87eSBen Hamilton   static bool
guessIsObjC(const SourceManager & SourceManager,const SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,const AdditionalKeywords & Keywords)24590675e87eSBen Hamilton   guessIsObjC(const SourceManager &SourceManager,
24600675e87eSBen Hamilton               const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
2461e2e3e67cSBen Hamilton               const AdditionalKeywords &Keywords) {
24628e21678dSKrasimir Georgiev     // Keep this array sorted, since we are binary searching over it.
24638e21678dSKrasimir Georgiev     static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
2464e2e3e67cSBen Hamilton         "CGFloat",
246519c782d5SBen Hamilton         "CGPoint",
246619c782d5SBen Hamilton         "CGPointMake",
246719c782d5SBen Hamilton         "CGPointZero",
246819c782d5SBen Hamilton         "CGRect",
246919c782d5SBen Hamilton         "CGRectEdge",
247019c782d5SBen Hamilton         "CGRectInfinite",
247119c782d5SBen Hamilton         "CGRectMake",
247219c782d5SBen Hamilton         "CGRectNull",
247319c782d5SBen Hamilton         "CGRectZero",
247419c782d5SBen Hamilton         "CGSize",
247519c782d5SBen Hamilton         "CGSizeMake",
247619c782d5SBen Hamilton         "CGVector",
247719c782d5SBen Hamilton         "CGVectorMake",
2478e2e3e67cSBen Hamilton         "NSAffineTransform",
2479e2e3e67cSBen Hamilton         "NSArray",
2480e2e3e67cSBen Hamilton         "NSAttributedString",
2481b1a7919eSBen Hamilton         "NSBlockOperation",
2482ce4f0af3SJacek Olesiak         "NSBundle",
2483e2e3e67cSBen Hamilton         "NSCache",
2484ce4f0af3SJacek Olesiak         "NSCalendar",
2485e2e3e67cSBen Hamilton         "NSCharacterSet",
2486e2e3e67cSBen Hamilton         "NSCountedSet",
2487e2e3e67cSBen Hamilton         "NSData",
2488e2e3e67cSBen Hamilton         "NSDataDetector",
2489e2e3e67cSBen Hamilton         "NSDecimal",
2490e2e3e67cSBen Hamilton         "NSDecimalNumber",
2491e2e3e67cSBen Hamilton         "NSDictionary",
2492e2e3e67cSBen Hamilton         "NSEdgeInsets",
2493e2e3e67cSBen Hamilton         "NSHashTable",
2494e2e3e67cSBen Hamilton         "NSIndexPath",
2495e2e3e67cSBen Hamilton         "NSIndexSet",
2496e2e3e67cSBen Hamilton         "NSInteger",
2497b1a7919eSBen Hamilton         "NSInvocationOperation",
2498e2e3e67cSBen Hamilton         "NSLocale",
2499e2e3e67cSBen Hamilton         "NSMapTable",
2500e2e3e67cSBen Hamilton         "NSMutableArray",
2501e2e3e67cSBen Hamilton         "NSMutableAttributedString",
2502e2e3e67cSBen Hamilton         "NSMutableCharacterSet",
2503e2e3e67cSBen Hamilton         "NSMutableData",
2504e2e3e67cSBen Hamilton         "NSMutableDictionary",
2505e2e3e67cSBen Hamilton         "NSMutableIndexSet",
2506e2e3e67cSBen Hamilton         "NSMutableOrderedSet",
2507e2e3e67cSBen Hamilton         "NSMutableSet",
2508e2e3e67cSBen Hamilton         "NSMutableString",
2509e2e3e67cSBen Hamilton         "NSNumber",
2510e2e3e67cSBen Hamilton         "NSNumberFormatter",
2511ce4f0af3SJacek Olesiak         "NSObject",
2512b1a7919eSBen Hamilton         "NSOperation",
2513b1a7919eSBen Hamilton         "NSOperationQueue",
2514b1a7919eSBen Hamilton         "NSOperationQueuePriority",
2515e2e3e67cSBen Hamilton         "NSOrderedSet",
2516e2e3e67cSBen Hamilton         "NSPoint",
2517e2e3e67cSBen Hamilton         "NSPointerArray",
2518b1a7919eSBen Hamilton         "NSQualityOfService",
2519e2e3e67cSBen Hamilton         "NSRange",
2520e2e3e67cSBen Hamilton         "NSRect",
2521e2e3e67cSBen Hamilton         "NSRegularExpression",
2522e2e3e67cSBen Hamilton         "NSSet",
2523e2e3e67cSBen Hamilton         "NSSize",
2524e2e3e67cSBen Hamilton         "NSString",
2525ce4f0af3SJacek Olesiak         "NSTimeZone",
2526e2e3e67cSBen Hamilton         "NSUInteger",
2527e2e3e67cSBen Hamilton         "NSURL",
2528e2e3e67cSBen Hamilton         "NSURLComponents",
2529e2e3e67cSBen Hamilton         "NSURLQueryItem",
2530e2e3e67cSBen Hamilton         "NSUUID",
2531ce4f0af3SJacek Olesiak         "NSValue",
253219c782d5SBen Hamilton         "UIImage",
253319c782d5SBen Hamilton         "UIView",
2534e2e3e67cSBen Hamilton     };
2535e2e3e67cSBen Hamilton 
2536ea7a27b8SBen Hamilton     for (auto Line : AnnotatedLines) {
25377b2d62fdSmydeveloperday       if (Line->First && (Line->First->TokenText.startswith("#") ||
25387b2d62fdSmydeveloperday                           Line->First->TokenText == "__pragma" ||
2539bebf7bdfSowenca                           Line->First->TokenText == "_Pragma")) {
25407b2d62fdSmydeveloperday         continue;
2541bebf7bdfSowenca       }
2542ea7a27b8SBen Hamilton       for (const FormatToken *FormatTok = Line->First; FormatTok;
2543e2e3e67cSBen Hamilton            FormatTok = FormatTok->Next) {
2544ce4f0af3SJacek Olesiak         if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
2545b1a7919eSBen Hamilton              (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
2546e2e3e67cSBen Hamilton               FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
2547e2e3e67cSBen Hamilton                                  tok::l_brace))) ||
2548e2e3e67cSBen Hamilton             (FormatTok->Tok.isAnyIdentifier() &&
25498e21678dSKrasimir Georgiev              std::binary_search(std::begin(FoundationIdentifiers),
25508e21678dSKrasimir Georgiev                                 std::end(FoundationIdentifiers),
25518e21678dSKrasimir Georgiev                                 FormatTok->TokenText)) ||
2552e2e3e67cSBen Hamilton             FormatTok->is(TT_ObjCStringLiteral) ||
2553d9212ef7SBen Hamilton             FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,
2554d9212ef7SBen Hamilton                                Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,
2555d9212ef7SBen Hamilton                                TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,
2556d9212ef7SBen Hamilton                                TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,
2557d9212ef7SBen Hamilton                                TT_ObjCProperty)) {
25580675e87eSBen Hamilton           LLVM_DEBUG(llvm::dbgs()
25590675e87eSBen Hamilton                      << "Detected ObjC at location "
25600675e87eSBen Hamilton                      << FormatTok->Tok.getLocation().printToString(
25610675e87eSBen Hamilton                             SourceManager)
25620675e87eSBen Hamilton                      << " token: " << FormatTok->TokenText << " token type: "
256353cc90f7SManuel Klimek                      << getTokenTypeName(FormatTok->getType()) << "\n");
2564e2e3e67cSBen Hamilton           return true;
2565e2e3e67cSBen Hamilton         }
25660675e87eSBen Hamilton         if (guessIsObjC(SourceManager, Line->Children, Keywords))
25676432afe5SBen Hamilton           return true;
25686432afe5SBen Hamilton       }
2569e2e3e67cSBen Hamilton     }
2570e2e3e67cSBen Hamilton     return false;
2571e2e3e67cSBen Hamilton   }
2572e2e3e67cSBen Hamilton 
2573e2e3e67cSBen Hamilton   bool IsObjC;
2574e2e3e67cSBen Hamilton };
2575e2e3e67cSBen Hamilton 
2576d89ae9d3SDaniel Jasper struct IncludeDirective {
2577d89ae9d3SDaniel Jasper   StringRef Filename;
2578d89ae9d3SDaniel Jasper   StringRef Text;
2579d89ae9d3SDaniel Jasper   unsigned Offset;
2580d2629dc8SDaniel Jasper   int Category;
258152e44b14SPaul Hoad   int Priority;
2582d89ae9d3SDaniel Jasper };
2583d89ae9d3SDaniel Jasper 
25847e91b033SKrasimir Georgiev struct JavaImportDirective {
25857e91b033SKrasimir Georgiev   StringRef Identifier;
25867e91b033SKrasimir Georgiev   StringRef Text;
25877e91b033SKrasimir Georgiev   unsigned Offset;
258836229fa3Sowenca   SmallVector<StringRef> AssociatedCommentLines;
25897e91b033SKrasimir Georgiev   bool IsStatic;
25907e91b033SKrasimir Georgiev };
25917e91b033SKrasimir Georgiev 
2592af35e852SCraig Topper } // end anonymous namespace
2593af35e852SCraig Topper 
2594d89ae9d3SDaniel Jasper // Determines whether 'Ranges' intersects with ('Start', 'End').
affectsRange(ArrayRef<tooling::Range> Ranges,unsigned Start,unsigned End)2595d89ae9d3SDaniel Jasper static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start,
2596d89ae9d3SDaniel Jasper                          unsigned End) {
2597bebf7bdfSowenca   for (auto Range : Ranges) {
2598d89ae9d3SDaniel Jasper     if (Range.getOffset() < End &&
2599bebf7bdfSowenca         Range.getOffset() + Range.getLength() > Start) {
2600d89ae9d3SDaniel Jasper       return true;
2601bebf7bdfSowenca     }
2602bebf7bdfSowenca   }
2603d89ae9d3SDaniel Jasper   return false;
2604d89ae9d3SDaniel Jasper }
2605d89ae9d3SDaniel Jasper 
2606a992afe8SEric Liu // Returns a pair (Index, OffsetToEOL) describing the position of the cursor
2607a992afe8SEric Liu // before sorting/deduplicating. Index is the index of the include under the
2608a992afe8SEric Liu // cursor in the original set of includes. If this include has duplicates, it is
2609a992afe8SEric Liu // the index of the first of the duplicates as the others are going to be
2610a992afe8SEric Liu // removed. OffsetToEOL describes the cursor's position relative to the end of
2611a992afe8SEric Liu // its current line.
2612a992afe8SEric Liu // If `Cursor` is not on any #include, `Index` will be UINT_MAX.
2613a992afe8SEric Liu static std::pair<unsigned, unsigned>
FindCursorIndex(const SmallVectorImpl<IncludeDirective> & Includes,const SmallVectorImpl<unsigned> & Indices,unsigned Cursor)2614a992afe8SEric Liu FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes,
2615a992afe8SEric Liu                 const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) {
2616a992afe8SEric Liu   unsigned CursorIndex = UINT_MAX;
2617a992afe8SEric Liu   unsigned OffsetToEOL = 0;
2618a992afe8SEric Liu   for (int i = 0, e = Includes.size(); i != e; ++i) {
2619a992afe8SEric Liu     unsigned Start = Includes[Indices[i]].Offset;
2620a992afe8SEric Liu     unsigned End = Start + Includes[Indices[i]].Text.size();
2621a992afe8SEric Liu     if (!(Cursor >= Start && Cursor < End))
2622a992afe8SEric Liu       continue;
2623a992afe8SEric Liu     CursorIndex = Indices[i];
2624a992afe8SEric Liu     OffsetToEOL = End - Cursor;
2625a992afe8SEric Liu     // Put the cursor on the only remaining #include among the duplicate
2626a992afe8SEric Liu     // #includes.
2627a992afe8SEric Liu     while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text)
2628a992afe8SEric Liu       CursorIndex = i;
2629a992afe8SEric Liu     break;
2630a992afe8SEric Liu   }
2631a992afe8SEric Liu   return std::make_pair(CursorIndex, OffsetToEOL);
2632a992afe8SEric Liu }
2633a992afe8SEric Liu 
263460365021SPaul Hoad // Replace all "\r\n" with "\n".
replaceCRLF(const std::string & Code)263560365021SPaul Hoad std::string replaceCRLF(const std::string &Code) {
263660365021SPaul Hoad   std::string NewCode;
263760365021SPaul Hoad   size_t Pos = 0, LastPos = 0;
263860365021SPaul Hoad 
263960365021SPaul Hoad   do {
264060365021SPaul Hoad     Pos = Code.find("\r\n", LastPos);
264160365021SPaul Hoad     if (Pos == LastPos) {
2642359b4e6cSMarek Kurdej       ++LastPos;
264360365021SPaul Hoad       continue;
264460365021SPaul Hoad     }
264560365021SPaul Hoad     if (Pos == std::string::npos) {
264660365021SPaul Hoad       NewCode += Code.substr(LastPos);
264760365021SPaul Hoad       break;
264860365021SPaul Hoad     }
264960365021SPaul Hoad     NewCode += Code.substr(LastPos, Pos - LastPos) + "\n";
265060365021SPaul Hoad     LastPos = Pos + 2;
265160365021SPaul Hoad   } while (Pos != std::string::npos);
265260365021SPaul Hoad 
265360365021SPaul Hoad   return NewCode;
265460365021SPaul Hoad }
265560365021SPaul Hoad 
2656a992afe8SEric Liu // Sorts and deduplicate a block of includes given by 'Includes' alphabetically
2657a992afe8SEric Liu // adding the necessary replacement to 'Replaces'. 'Includes' must be in strict
2658a992afe8SEric Liu // source order.
2659a992afe8SEric Liu // #include directives with the same text will be deduplicated, and only the
2660a992afe8SEric Liu // first #include in the duplicate #includes remains. If the `Cursor` is
2661a992afe8SEric Liu // provided and put on a deleted #include, it will be moved to the remaining
2662a992afe8SEric Liu // #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)2663c4a0dd49SMartin Probst static void sortCppIncludes(const FormatStyle &Style,
2664d89ae9d3SDaniel Jasper                             const SmallVectorImpl<IncludeDirective> &Includes,
2665d89ae9d3SDaniel Jasper                             ArrayRef<tooling::Range> Ranges, StringRef FileName,
2666ff9f4b54SNico Weber                             StringRef Code, tooling::Replacements &Replaces,
2667ff9f4b54SNico Weber                             unsigned *Cursor) {
266852e44b14SPaul Hoad   tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
2669db57acffSowenca   const unsigned IncludesBeginOffset = Includes.front().Offset;
2670db57acffSowenca   const unsigned IncludesEndOffset =
2671d6a00780SDaniel Jasper       Includes.back().Offset + Includes.back().Text.size();
2672db57acffSowenca   const unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
2673d6a00780SDaniel Jasper   if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
2674d89ae9d3SDaniel Jasper     return;
267561f09bcfSMarek Kurdej   SmallVector<unsigned, 16> Indices =
267661f09bcfSMarek Kurdej       llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size()));
2677a8105b37SKent Sommer 
2678bebf7bdfSowenca   if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) {
2679a8105b37SKent Sommer     llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
2680a8105b37SKent Sommer       const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
2681a8105b37SKent Sommer       const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
2682a8105b37SKent Sommer       return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
2683a8105b37SKent Sommer                       Includes[LHSI].Filename) <
2684a8105b37SKent Sommer              std::tie(Includes[RHSI].Priority, RHSFilenameLower,
2685a8105b37SKent Sommer                       Includes[RHSI].Filename);
2686a8105b37SKent Sommer     });
2687bebf7bdfSowenca   } else {
2688899d1392SFangrui Song     llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
268952e44b14SPaul Hoad       return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
269052e44b14SPaul Hoad              std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
2691d89ae9d3SDaniel Jasper     });
2692bebf7bdfSowenca   }
2693a8105b37SKent Sommer 
2694a992afe8SEric Liu   // The index of the include on which the cursor will be put after
2695a992afe8SEric Liu   // sorting/deduplicating.
2696a992afe8SEric Liu   unsigned CursorIndex;
2697a992afe8SEric Liu   // The offset from cursor to the end of line.
2698a992afe8SEric Liu   unsigned CursorToEOLOffset;
2699bebf7bdfSowenca   if (Cursor) {
2700a992afe8SEric Liu     std::tie(CursorIndex, CursorToEOLOffset) =
2701a992afe8SEric Liu         FindCursorIndex(Includes, Indices, *Cursor);
2702bebf7bdfSowenca   }
2703a992afe8SEric Liu 
2704a992afe8SEric Liu   // Deduplicate #includes.
2705a992afe8SEric Liu   Indices.erase(std::unique(Indices.begin(), Indices.end(),
2706a992afe8SEric Liu                             [&](unsigned LHSI, unsigned RHSI) {
2707fe21c86eSMarek Kurdej                               return Includes[LHSI].Text.trim() ==
2708fe21c86eSMarek Kurdej                                      Includes[RHSI].Text.trim();
2709a992afe8SEric Liu                             }),
2710a992afe8SEric Liu                 Indices.end());
2711d89ae9d3SDaniel Jasper 
27124c2c9c36SKrasimir Georgiev   int CurrentCategory = Includes.front().Category;
27134c2c9c36SKrasimir Georgiev 
2714d89ae9d3SDaniel Jasper   // If the #includes are out of order, we generate a single replacement fixing
2715d89ae9d3SDaniel Jasper   // the entire block. Otherwise, no replacement is generated.
2716925bb20cSKrasimir Georgiev   // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not
2717925bb20cSKrasimir Georgiev   // enough as additional newlines might be added or removed across #include
2718db57acffSowenca   // blocks. This we handle below by generating the updated #include blocks and
2719925bb20cSKrasimir Georgiev   // comparing it to the original.
27201647ff6eSGeorgii Rymar   if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) &&
2721bebf7bdfSowenca       Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve) {
2722d89ae9d3SDaniel Jasper     return;
2723bebf7bdfSowenca   }
2724d89ae9d3SDaniel Jasper 
2725b68aabf7SDaniel Jasper   std::string result;
2726b68aabf7SDaniel Jasper   for (unsigned Index : Indices) {
27274c2c9c36SKrasimir Georgiev     if (!result.empty()) {
2728d89ae9d3SDaniel Jasper       result += "\n";
27299d92c027SEric Liu       if (Style.IncludeStyle.IncludeBlocks ==
27309d92c027SEric Liu               tooling::IncludeStyle::IBS_Regroup &&
2731bebf7bdfSowenca           CurrentCategory != Includes[Index].Category) {
27324c2c9c36SKrasimir Georgiev         result += "\n";
27334c2c9c36SKrasimir Georgiev       }
2734bebf7bdfSowenca     }
2735b68aabf7SDaniel Jasper     result += Includes[Index].Text;
2736a992afe8SEric Liu     if (Cursor && CursorIndex == Index)
2737a992afe8SEric Liu       *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
27384c2c9c36SKrasimir Georgiev     CurrentCategory = Includes[Index].Category;
2739b68aabf7SDaniel Jasper   }
2740d89ae9d3SDaniel Jasper 
2741db57acffSowenca   if (Cursor && *Cursor >= IncludesEndOffset)
2742db57acffSowenca     *Cursor += result.size() - IncludesBlockSize;
2743db57acffSowenca 
2744925bb20cSKrasimir Georgiev   // If the #includes are out of order, we generate a single replacement fixing
2745925bb20cSKrasimir Georgiev   // the entire range of blocks. Otherwise, no replacement is generated.
2746adcd0268SBenjamin Kramer   if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
2747bebf7bdfSowenca                                  IncludesBeginOffset, IncludesBlockSize)))) {
2748925bb20cSKrasimir Georgiev     return;
2749bebf7bdfSowenca   }
2750925bb20cSKrasimir Georgiev 
275140ef2fb3SEric Liu   auto Err = Replaces.add(tooling::Replacement(
2752a992afe8SEric Liu       FileName, Includes.front().Offset, IncludesBlockSize, result));
275340ef2fb3SEric Liu   // FIXME: better error handling. For now, just skip the replacement for the
275440ef2fb3SEric Liu   // release version.
27551ec383c7SPiotr Padlewski   if (Err) {
275640ef2fb3SEric Liu     llvm::errs() << llvm::toString(std::move(Err)) << "\n";
27571ec383c7SPiotr Padlewski     assert(false);
27581ec383c7SPiotr Padlewski   }
2759d89ae9d3SDaniel Jasper }
2760d89ae9d3SDaniel Jasper 
2761e8cc7490SKrasimir Georgiev namespace {
2762e8cc7490SKrasimir Georgiev 
2763e8cc7490SKrasimir Georgiev const char CppIncludeRegexPattern[] =
2764e8cc7490SKrasimir Georgiev     R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))";
2765e8cc7490SKrasimir Georgiev 
2766e8cc7490SKrasimir Georgiev } // anonymous namespace
2767e8cc7490SKrasimir Georgiev 
sortCppIncludes(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName,tooling::Replacements & Replaces,unsigned * Cursor)2768c4a0dd49SMartin Probst tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
2769d89ae9d3SDaniel Jasper                                       ArrayRef<tooling::Range> Ranges,
2770c4a0dd49SMartin Probst                                       StringRef FileName,
2771c4a0dd49SMartin Probst                                       tooling::Replacements &Replaces,
2772c4a0dd49SMartin Probst                                       unsigned *Cursor) {
2773ee27c767SRafał Jelonek   unsigned Prev = llvm::StringSwitch<size_t>(Code)
2774ee27c767SRafał Jelonek                       .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM
2775ee27c767SRafał Jelonek                       .Default(0);
2776d89ae9d3SDaniel Jasper   unsigned SearchFrom = 0;
2777e8cc7490SKrasimir Georgiev   llvm::Regex IncludeRegex(CppIncludeRegexPattern);
2778d89ae9d3SDaniel Jasper   SmallVector<StringRef, 4> Matches;
2779d89ae9d3SDaniel Jasper   SmallVector<IncludeDirective, 16> IncludesInBlock;
278085c472dcSDaniel Jasper 
278185c472dcSDaniel Jasper   // In compiled files, consider the first #include to be the main #include of
278285c472dcSDaniel Jasper   // the file if it is not a system #include. This ensures that the header
278385c472dcSDaniel Jasper   // doesn't have hidden dependencies
278485c472dcSDaniel Jasper   // (http://llvm.org/docs/CodingStandards.html#include-style).
278585c472dcSDaniel Jasper   //
2786d8e5a0c4SZarko Todorovski   // FIXME: Do some validation, e.g. edit distance of the base name, to fix
278785c472dcSDaniel Jasper   // cases where the first #include is unlikely to be the main header.
27887129e63bSEric Liu   tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
278932d75fa2SDaniel Jasper   bool FirstIncludeBlock = true;
2790a252f5d5SDaniel Jasper   bool MainIncludeFound = false;
27919b8c7c72SDaniel Jasper   bool FormattingOff = false;
27929b8c7c72SDaniel Jasper 
279346db0301SMarek Kurdej   // '[' must be the first and '-' the last character inside [...].
279405bea533Smydeveloperday   llvm::Regex RawStringRegex(
279546db0301SMarek Kurdej       "R\"([][A-Za-z0-9_{}#<>%:;.?*+/^&\\$|~!=,'-]*)\\(");
279605bea533Smydeveloperday   SmallVector<StringRef, 2> RawStringMatches;
279705bea533Smydeveloperday   std::string RawStringTermination = ")\"";
279805bea533Smydeveloperday 
2799d89ae9d3SDaniel Jasper   for (;;) {
2800d89ae9d3SDaniel Jasper     auto Pos = Code.find('\n', SearchFrom);
2801d89ae9d3SDaniel Jasper     StringRef Line =
2802d89ae9d3SDaniel Jasper         Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
28039b8c7c72SDaniel Jasper 
28049b8c7c72SDaniel Jasper     StringRef Trimmed = Line.trim();
280505bea533Smydeveloperday 
280605bea533Smydeveloperday     // #includes inside raw string literals need to be ignored.
280705bea533Smydeveloperday     // or we will sort the contents of the string.
280805bea533Smydeveloperday     // Skip past until we think we are at the rawstring literal close.
280905bea533Smydeveloperday     if (RawStringRegex.match(Trimmed, &RawStringMatches)) {
281005bea533Smydeveloperday       std::string CharSequence = RawStringMatches[1].str();
281105bea533Smydeveloperday       RawStringTermination = ")" + CharSequence + "\"";
281205bea533Smydeveloperday       FormattingOff = true;
281305bea533Smydeveloperday     }
281405bea533Smydeveloperday 
2815d079995dSMarek Kurdej     if (Trimmed.contains(RawStringTermination))
281605bea533Smydeveloperday       FormattingOff = false;
281705bea533Smydeveloperday 
2818bebf7bdfSowenca     if (Trimmed == "// clang-format off" ||
2819bebf7bdfSowenca         Trimmed == "/* clang-format off */") {
28209b8c7c72SDaniel Jasper       FormattingOff = true;
2821bebf7bdfSowenca     } else if (Trimmed == "// clang-format on" ||
2822bebf7bdfSowenca                Trimmed == "/* clang-format on */") {
28239b8c7c72SDaniel Jasper       FormattingOff = false;
2824bebf7bdfSowenca     }
28259b8c7c72SDaniel Jasper 
28264c2c9c36SKrasimir Georgiev     const bool EmptyLineSkipped =
28279d92c027SEric Liu         Trimmed.empty() &&
28289d92c027SEric Liu         (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge ||
28299d92c027SEric Liu          Style.IncludeStyle.IncludeBlocks ==
28309d92c027SEric Liu              tooling::IncludeStyle::IBS_Regroup);
28314c2c9c36SKrasimir Georgiev 
28327473940bSRafał Jelonek     bool MergeWithNextLine = Trimmed.endswith("\\");
28337473940bSRafał Jelonek     if (!FormattingOff && !MergeWithNextLine) {
2834d89ae9d3SDaniel Jasper       if (IncludeRegex.match(Line, &Matches)) {
2835e8cc7490SKrasimir Georgiev         StringRef IncludeName = Matches[2];
283695bf0a9eSMarek Kurdej         if (Line.contains("/*") && !Line.contains("*/")) {
283795bf0a9eSMarek Kurdej           // #include with a start of a block comment, but without the end.
283895bf0a9eSMarek Kurdej           // Need to keep all the lines until the end of the comment together.
283995bf0a9eSMarek Kurdej           // FIXME: This is somehow simplified check that probably does not work
284095bf0a9eSMarek Kurdej           // correctly if there are multiple comments on a line.
284195bf0a9eSMarek Kurdej           Pos = Code.find("*/", SearchFrom);
284295bf0a9eSMarek Kurdej           Line = Code.substr(
284395bf0a9eSMarek Kurdej               Prev, (Pos != StringRef::npos ? Pos + 2 : Code.size()) - Prev);
284495bf0a9eSMarek Kurdej         }
2845659afd55SEric Liu         int Category = Categories.getIncludePriority(
2846659afd55SEric Liu             IncludeName,
2847659afd55SEric Liu             /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock);
2848e8cc7490SKrasimir Georgiev         int Priority = Categories.getSortIncludePriority(
2849e8cc7490SKrasimir Georgiev             IncludeName, !MainIncludeFound && FirstIncludeBlock);
2850659afd55SEric Liu         if (Category == 0)
2851a252f5d5SDaniel Jasper           MainIncludeFound = true;
285252e44b14SPaul Hoad         IncludesInBlock.push_back(
285352e44b14SPaul Hoad             {IncludeName, Line, Prev, Category, Priority});
28544c2c9c36SKrasimir Georgiev       } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
2855925bb20cSKrasimir Georgiev         sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code,
2856925bb20cSKrasimir Georgiev                         Replaces, Cursor);
2857d89ae9d3SDaniel Jasper         IncludesInBlock.clear();
285889878e8cSRafał Jelonek         if (Trimmed.startswith("#pragma hdrstop")) // Precompiled headers.
285989878e8cSRafał Jelonek           FirstIncludeBlock = true;
286089878e8cSRafał Jelonek         else
286132d75fa2SDaniel Jasper           FirstIncludeBlock = false;
2862d89ae9d3SDaniel Jasper       }
2863d89ae9d3SDaniel Jasper     }
2864d89ae9d3SDaniel Jasper     if (Pos == StringRef::npos || Pos + 1 == Code.size())
2865d89ae9d3SDaniel Jasper       break;
28667473940bSRafał Jelonek 
28677473940bSRafał Jelonek     if (!MergeWithNextLine)
28687473940bSRafał Jelonek       Prev = Pos + 1;
2869d89ae9d3SDaniel Jasper     SearchFrom = Pos + 1;
2870d89ae9d3SDaniel Jasper   }
2871925bb20cSKrasimir Georgiev   if (!IncludesInBlock.empty()) {
2872925bb20cSKrasimir Georgiev     sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces,
2873925bb20cSKrasimir Georgiev                     Cursor);
2874925bb20cSKrasimir Georgiev   }
2875c4a0dd49SMartin Probst   return Replaces;
2876c4a0dd49SMartin Probst }
2877c4a0dd49SMartin Probst 
28787e91b033SKrasimir Georgiev // Returns group number to use as a first order sort on imports. Gives UINT_MAX
28797e91b033SKrasimir Georgiev // if the import does not match any given groups.
findJavaImportGroup(const FormatStyle & Style,StringRef ImportIdentifier)28807e91b033SKrasimir Georgiev static unsigned findJavaImportGroup(const FormatStyle &Style,
28817e91b033SKrasimir Georgiev                                     StringRef ImportIdentifier) {
28827e91b033SKrasimir Georgiev   unsigned LongestMatchIndex = UINT_MAX;
28837e91b033SKrasimir Georgiev   unsigned LongestMatchLength = 0;
28847e91b033SKrasimir Georgiev   for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) {
2885545317cbSMarek Kurdej     const std::string &GroupPrefix = Style.JavaImportGroups[I];
28867e91b033SKrasimir Georgiev     if (ImportIdentifier.startswith(GroupPrefix) &&
28877e91b033SKrasimir Georgiev         GroupPrefix.length() > LongestMatchLength) {
28887e91b033SKrasimir Georgiev       LongestMatchIndex = I;
28897e91b033SKrasimir Georgiev       LongestMatchLength = GroupPrefix.length();
28907e91b033SKrasimir Georgiev     }
28917e91b033SKrasimir Georgiev   }
28927e91b033SKrasimir Georgiev   return LongestMatchIndex;
28937e91b033SKrasimir Georgiev }
28947e91b033SKrasimir Georgiev 
28957e91b033SKrasimir Georgiev // Sorts and deduplicates a block of includes given by 'Imports' based on
28967e91b033SKrasimir Georgiev // JavaImportGroups, then adding the necessary replacement to 'Replaces'.
28977e91b033SKrasimir Georgiev // Import declarations with the same text will be deduplicated. Between each
28987e91b033SKrasimir Georgiev // import group, a newline is inserted, and within each import group, a
28997e91b033SKrasimir Georgiev // 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)29007e91b033SKrasimir Georgiev static void sortJavaImports(const FormatStyle &Style,
29017e91b033SKrasimir Georgiev                             const SmallVectorImpl<JavaImportDirective> &Imports,
29027e91b033SKrasimir Georgiev                             ArrayRef<tooling::Range> Ranges, StringRef FileName,
29035bcf99b4SPaul Hoad                             StringRef Code, tooling::Replacements &Replaces) {
29047e91b033SKrasimir Georgiev   unsigned ImportsBeginOffset = Imports.front().Offset;
29057e91b033SKrasimir Georgiev   unsigned ImportsEndOffset =
29067e91b033SKrasimir Georgiev       Imports.back().Offset + Imports.back().Text.size();
29077e91b033SKrasimir Georgiev   unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;
29087e91b033SKrasimir Georgiev   if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))
29097e91b033SKrasimir Georgiev     return;
2910af8f1dbbSMarek Kurdej 
291161f09bcfSMarek Kurdej   SmallVector<unsigned, 16> Indices =
291261f09bcfSMarek Kurdej       llvm::to_vector<16>(llvm::seq<unsigned>(0, Imports.size()));
29137e91b033SKrasimir Georgiev   SmallVector<unsigned, 16> JavaImportGroups;
2914af8f1dbbSMarek Kurdej   JavaImportGroups.reserve(Imports.size());
2915af8f1dbbSMarek Kurdej   for (const JavaImportDirective &Import : Imports)
2916af8f1dbbSMarek Kurdej     JavaImportGroups.push_back(findJavaImportGroup(Style, Import.Identifier));
2917af8f1dbbSMarek Kurdej 
29182e7add81Smydeveloperday   bool StaticImportAfterNormalImport =
29192e7add81Smydeveloperday       Style.SortJavaStaticImport == FormatStyle::SJSIO_After;
2920d36da8a0SMandeep Singh Grang   llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
29217e91b033SKrasimir Georgiev     // Negating IsStatic to push static imports above non-static imports.
29222e7add81Smydeveloperday     return std::make_tuple(!Imports[LHSI].IsStatic ^
29232e7add81Smydeveloperday                                StaticImportAfterNormalImport,
29242e7add81Smydeveloperday                            JavaImportGroups[LHSI], Imports[LHSI].Identifier) <
29252e7add81Smydeveloperday            std::make_tuple(!Imports[RHSI].IsStatic ^
29262e7add81Smydeveloperday                                StaticImportAfterNormalImport,
29272e7add81Smydeveloperday                            JavaImportGroups[RHSI], Imports[RHSI].Identifier);
29287e91b033SKrasimir Georgiev   });
29297e91b033SKrasimir Georgiev 
29307e91b033SKrasimir Georgiev   // Deduplicate imports.
29317e91b033SKrasimir Georgiev   Indices.erase(std::unique(Indices.begin(), Indices.end(),
29327e91b033SKrasimir Georgiev                             [&](unsigned LHSI, unsigned RHSI) {
29337e91b033SKrasimir Georgiev                               return Imports[LHSI].Text == Imports[RHSI].Text;
29347e91b033SKrasimir Georgiev                             }),
29357e91b033SKrasimir Georgiev                 Indices.end());
29367e91b033SKrasimir Georgiev 
29377e91b033SKrasimir Georgiev   bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
29387e91b033SKrasimir Georgiev   unsigned CurrentImportGroup = JavaImportGroups[Indices.front()];
29397e91b033SKrasimir Georgiev 
29407e91b033SKrasimir Georgiev   std::string result;
29417e91b033SKrasimir Georgiev   for (unsigned Index : Indices) {
29427e91b033SKrasimir Georgiev     if (!result.empty()) {
29437e91b033SKrasimir Georgiev       result += "\n";
29447e91b033SKrasimir Georgiev       if (CurrentIsStatic != Imports[Index].IsStatic ||
2945bebf7bdfSowenca           CurrentImportGroup != JavaImportGroups[Index]) {
29467e91b033SKrasimir Georgiev         result += "\n";
29477e91b033SKrasimir Georgiev       }
2948bebf7bdfSowenca     }
29497e91b033SKrasimir Georgiev     for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) {
29507e91b033SKrasimir Georgiev       result += CommentLine;
29517e91b033SKrasimir Georgiev       result += "\n";
29527e91b033SKrasimir Georgiev     }
29537e91b033SKrasimir Georgiev     result += Imports[Index].Text;
29547e91b033SKrasimir Georgiev     CurrentIsStatic = Imports[Index].IsStatic;
29557e91b033SKrasimir Georgiev     CurrentImportGroup = JavaImportGroups[Index];
29567e91b033SKrasimir Georgiev   }
29577e91b033SKrasimir Georgiev 
2958777bb825SKrasimir Georgiev   // If the imports are out of order, we generate a single replacement fixing
2959777bb825SKrasimir Georgiev   // the entire block. Otherwise, no replacement is generated.
2960adcd0268SBenjamin Kramer   if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
2961bebf7bdfSowenca                                  Imports.front().Offset, ImportsBlockSize)))) {
2962777bb825SKrasimir Georgiev     return;
2963bebf7bdfSowenca   }
2964777bb825SKrasimir Georgiev 
29657e91b033SKrasimir Georgiev   auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset,
29667e91b033SKrasimir Georgiev                                                ImportsBlockSize, result));
29677e91b033SKrasimir Georgiev   // FIXME: better error handling. For now, just skip the replacement for the
29687e91b033SKrasimir Georgiev   // release version.
29697e91b033SKrasimir Georgiev   if (Err) {
29707e91b033SKrasimir Georgiev     llvm::errs() << llvm::toString(std::move(Err)) << "\n";
29717e91b033SKrasimir Georgiev     assert(false);
29727e91b033SKrasimir Georgiev   }
29737e91b033SKrasimir Georgiev }
29747e91b033SKrasimir Georgiev 
29757e91b033SKrasimir Georgiev namespace {
29767e91b033SKrasimir Georgiev 
29777e91b033SKrasimir Georgiev const char JavaImportRegexPattern[] =
297888335c21SPaul Hoad     "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;";
29797e91b033SKrasimir Georgiev 
29807e91b033SKrasimir Georgiev } // anonymous namespace
29817e91b033SKrasimir Georgiev 
sortJavaImports(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName,tooling::Replacements & Replaces)29827e91b033SKrasimir Georgiev tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code,
29837e91b033SKrasimir Georgiev                                       ArrayRef<tooling::Range> Ranges,
29847e91b033SKrasimir Georgiev                                       StringRef FileName,
29857e91b033SKrasimir Georgiev                                       tooling::Replacements &Replaces) {
29867e91b033SKrasimir Georgiev   unsigned Prev = 0;
29877e91b033SKrasimir Georgiev   unsigned SearchFrom = 0;
29887e91b033SKrasimir Georgiev   llvm::Regex ImportRegex(JavaImportRegexPattern);
29897e91b033SKrasimir Georgiev   SmallVector<StringRef, 4> Matches;
29907e91b033SKrasimir Georgiev   SmallVector<JavaImportDirective, 16> ImportsInBlock;
299136229fa3Sowenca   SmallVector<StringRef> AssociatedCommentLines;
29927e91b033SKrasimir Georgiev 
29937e91b033SKrasimir Georgiev   bool FormattingOff = false;
29947e91b033SKrasimir Georgiev 
29957e91b033SKrasimir Georgiev   for (;;) {
29967e91b033SKrasimir Georgiev     auto Pos = Code.find('\n', SearchFrom);
29977e91b033SKrasimir Georgiev     StringRef Line =
29987e91b033SKrasimir Georgiev         Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
29997e91b033SKrasimir Georgiev 
30007e91b033SKrasimir Georgiev     StringRef Trimmed = Line.trim();
30017e91b033SKrasimir Georgiev     if (Trimmed == "// clang-format off")
30027e91b033SKrasimir Georgiev       FormattingOff = true;
30037e91b033SKrasimir Georgiev     else if (Trimmed == "// clang-format on")
30047e91b033SKrasimir Georgiev       FormattingOff = false;
30057e91b033SKrasimir Georgiev 
30067e91b033SKrasimir Georgiev     if (ImportRegex.match(Line, &Matches)) {
30077e91b033SKrasimir Georgiev       if (FormattingOff) {
30087e91b033SKrasimir Georgiev         // If at least one import line has formatting turned off, turn off
30097e91b033SKrasimir Georgiev         // formatting entirely.
30107e91b033SKrasimir Georgiev         return Replaces;
30117e91b033SKrasimir Georgiev       }
30127e91b033SKrasimir Georgiev       StringRef Static = Matches[1];
30137e91b033SKrasimir Georgiev       StringRef Identifier = Matches[2];
30147e91b033SKrasimir Georgiev       bool IsStatic = false;
3015d079995dSMarek Kurdej       if (Static.contains("static"))
30167e91b033SKrasimir Georgiev         IsStatic = true;
30175bcf99b4SPaul Hoad       ImportsInBlock.push_back(
30185bcf99b4SPaul Hoad           {Identifier, Line, Prev, AssociatedCommentLines, IsStatic});
30197e91b033SKrasimir Georgiev       AssociatedCommentLines.clear();
30207e91b033SKrasimir Georgiev     } else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) {
30217e91b033SKrasimir Georgiev       // Associating comments within the imports with the nearest import below
30227e91b033SKrasimir Georgiev       AssociatedCommentLines.push_back(Line);
30237e91b033SKrasimir Georgiev     }
30247e91b033SKrasimir Georgiev     Prev = Pos + 1;
30257e91b033SKrasimir Georgiev     if (Pos == StringRef::npos || Pos + 1 == Code.size())
30267e91b033SKrasimir Georgiev       break;
30277e91b033SKrasimir Georgiev     SearchFrom = Pos + 1;
30287e91b033SKrasimir Georgiev   }
30297e91b033SKrasimir Georgiev   if (!ImportsInBlock.empty())
3030777bb825SKrasimir Georgiev     sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces);
30317e91b033SKrasimir Georgiev   return Replaces;
30327e91b033SKrasimir Georgiev }
30337e91b033SKrasimir Georgiev 
isMpegTS(StringRef Code)3034fa37b18fSMartin Probst bool isMpegTS(StringRef Code) {
3035fa37b18fSMartin Probst   // MPEG transport streams use the ".ts" file extension. clang-format should
3036fa37b18fSMartin Probst   // not attempt to format those. MPEG TS' frame format starts with 0x47 every
3037fa37b18fSMartin Probst   // 189 bytes - detect that and return.
3038fa37b18fSMartin Probst   return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
3039fa37b18fSMartin Probst }
3040fa37b18fSMartin Probst 
isLikelyXml(StringRef Code)304189628f64SManuel Klimek bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); }
3042a2e7d0deSKrasimir Georgiev 
sortIncludes(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName,unsigned * Cursor)3043c4a0dd49SMartin Probst tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
3044c4a0dd49SMartin Probst                                    ArrayRef<tooling::Range> Ranges,
3045c4a0dd49SMartin Probst                                    StringRef FileName, unsigned *Cursor) {
3046c4a0dd49SMartin Probst   tooling::Replacements Replaces;
304761dc0f2bSNathan James   if (!Style.SortIncludes || Style.DisableFormat)
3048c4a0dd49SMartin Probst     return Replaces;
304986873030SKrasimir Georgiev   if (isLikelyXml(Code))
305086873030SKrasimir Georgiev     return Replaces;
305186873030SKrasimir Georgiev   if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript &&
3052bebf7bdfSowenca       isMpegTS(Code)) {
3053fa37b18fSMartin Probst     return Replaces;
3054bebf7bdfSowenca   }
3055c4a0dd49SMartin Probst   if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript)
3056c4a0dd49SMartin Probst     return sortJavaScriptImports(Style, Code, Ranges, FileName);
30577e91b033SKrasimir Georgiev   if (Style.Language == FormatStyle::LanguageKind::LK_Java)
30587e91b033SKrasimir Georgiev     return sortJavaImports(Style, Code, Ranges, FileName, Replaces);
3059c4a0dd49SMartin Probst   sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor);
3060d89ae9d3SDaniel Jasper   return Replaces;
3061d89ae9d3SDaniel Jasper }
3062d89ae9d3SDaniel Jasper 
30634cfb88a9SEric Liu template <typename T>
30644f8d9943SEric Liu static llvm::Expected<tooling::Replacements>
processReplacements(T ProcessFunc,StringRef Code,const tooling::Replacements & Replaces,const FormatStyle & Style)30654cfb88a9SEric Liu processReplacements(T ProcessFunc, StringRef Code,
3066b12e5a5cSManuel Klimek                     const tooling::Replacements &Replaces,
3067b12e5a5cSManuel Klimek                     const FormatStyle &Style) {
3068b12e5a5cSManuel Klimek   if (Replaces.empty())
3069b12e5a5cSManuel Klimek     return tooling::Replacements();
3070b12e5a5cSManuel Klimek 
30714f8d9943SEric Liu   auto NewCode = applyAllReplacements(Code, Replaces);
30724f8d9943SEric Liu   if (!NewCode)
30734f8d9943SEric Liu     return NewCode.takeError();
307440ef2fb3SEric Liu   std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();
3075b12e5a5cSManuel Klimek   StringRef FileName = Replaces.begin()->getFilePath();
30764cfb88a9SEric Liu 
3077b12e5a5cSManuel Klimek   tooling::Replacements FormatReplaces =
30784f8d9943SEric Liu       ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
3079b12e5a5cSManuel Klimek 
308040ef2fb3SEric Liu   return Replaces.merge(FormatReplaces);
3081b12e5a5cSManuel Klimek }
3082b12e5a5cSManuel Klimek 
30834f8d9943SEric Liu llvm::Expected<tooling::Replacements>
formatReplacements(StringRef Code,const tooling::Replacements & Replaces,const FormatStyle & Style)30844f8d9943SEric Liu formatReplacements(StringRef Code, const tooling::Replacements &Replaces,
30854cfb88a9SEric Liu                    const FormatStyle &Style) {
30864cfb88a9SEric Liu   // We need to use lambda function here since there are two versions of
3087baf58c23SEric Liu   // `sortIncludes`.
3088baf58c23SEric Liu   auto SortIncludes = [](const FormatStyle &Style, StringRef Code,
3089baf58c23SEric Liu                          std::vector<tooling::Range> Ranges,
3090baf58c23SEric Liu                          StringRef FileName) -> tooling::Replacements {
3091baf58c23SEric Liu     return sortIncludes(Style, Code, Ranges, FileName);
3092baf58c23SEric Liu   };
30934f8d9943SEric Liu   auto SortedReplaces =
3094baf58c23SEric Liu       processReplacements(SortIncludes, Code, Replaces, Style);
30954f8d9943SEric Liu   if (!SortedReplaces)
30964f8d9943SEric Liu     return SortedReplaces.takeError();
3097baf58c23SEric Liu 
3098baf58c23SEric Liu   // We need to use lambda function here since there are two versions of
30994cfb88a9SEric Liu   // `reformat`.
31004cfb88a9SEric Liu   auto Reformat = [](const FormatStyle &Style, StringRef Code,
31014cfb88a9SEric Liu                      std::vector<tooling::Range> Ranges,
31024cfb88a9SEric Liu                      StringRef FileName) -> tooling::Replacements {
31034cfb88a9SEric Liu     return reformat(Style, Code, Ranges, FileName);
31044cfb88a9SEric Liu   };
31054f8d9943SEric Liu   return processReplacements(Reformat, Code, *SortedReplaces, Style);
31064cfb88a9SEric Liu }
31074cfb88a9SEric Liu 
3108659afd55SEric Liu namespace {
3109659afd55SEric Liu 
isHeaderInsertion(const tooling::Replacement & Replace)3110659afd55SEric Liu inline bool isHeaderInsertion(const tooling::Replacement &Replace) {
3111c0d3a801SEric Liu   return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 &&
3112e8cc7490SKrasimir Georgiev          llvm::Regex(CppIncludeRegexPattern)
3113e8cc7490SKrasimir Georgiev              .match(Replace.getReplacementText());
3114659afd55SEric Liu }
3115659afd55SEric Liu 
isHeaderDeletion(const tooling::Replacement & Replace)3116c0d3a801SEric Liu inline bool isHeaderDeletion(const tooling::Replacement &Replace) {
3117c0d3a801SEric Liu   return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1;
3118c0d3a801SEric Liu }
3119c0d3a801SEric Liu 
3120659afd55SEric Liu // FIXME: insert empty lines between newly created blocks.
3121e8cc7490SKrasimir Georgiev tooling::Replacements
fixCppIncludeInsertions(StringRef Code,const tooling::Replacements & Replaces,const FormatStyle & Style)3122659afd55SEric Liu fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
3123659afd55SEric Liu                         const FormatStyle &Style) {
31241dbc2105SDaniel Jasper   if (!Style.isCpp())
3125659afd55SEric Liu     return Replaces;
3126659afd55SEric Liu 
3127659afd55SEric Liu   tooling::Replacements HeaderInsertions;
3128c0d3a801SEric Liu   std::set<llvm::StringRef> HeadersToDelete;
312940ef2fb3SEric Liu   tooling::Replacements Result;
3130659afd55SEric Liu   for (const auto &R : Replaces) {
313140ef2fb3SEric Liu     if (isHeaderInsertion(R)) {
313240ef2fb3SEric Liu       // Replacements from \p Replaces must be conflict-free already, so we can
313340ef2fb3SEric Liu       // simply consume the error.
313440ef2fb3SEric Liu       llvm::consumeError(HeaderInsertions.add(R));
3135c0d3a801SEric Liu     } else if (isHeaderDeletion(R)) {
3136c0d3a801SEric Liu       HeadersToDelete.insert(R.getReplacementText());
313740ef2fb3SEric Liu     } else if (R.getOffset() == UINT_MAX) {
3138659afd55SEric Liu       llvm::errs() << "Insertions other than header #include insertion are "
3139659afd55SEric Liu                       "not supported! "
3140659afd55SEric Liu                    << R.getReplacementText() << "\n";
314140ef2fb3SEric Liu     } else {
314240ef2fb3SEric Liu       llvm::consumeError(Result.add(R));
314340ef2fb3SEric Liu     }
3144659afd55SEric Liu   }
3145c0d3a801SEric Liu   if (HeaderInsertions.empty() && HeadersToDelete.empty())
3146659afd55SEric Liu     return Replaces;
3147659afd55SEric Liu 
3148659afd55SEric Liu   StringRef FileName = Replaces.begin()->getFilePath();
31497129e63bSEric Liu   tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle);
3150659afd55SEric Liu 
3151bf4c41c7SEric Liu   for (const auto &Header : HeadersToDelete) {
3152bf4c41c7SEric Liu     tooling::Replacements Replaces =
3153e8cc7490SKrasimir Georgiev         Includes.remove(Header.trim("\"<>"), Header.startswith("<"));
3154bf4c41c7SEric Liu     for (const auto &R : Replaces) {
3155bf4c41c7SEric Liu       auto Err = Result.add(R);
3156c0d3a801SEric Liu       if (Err) {
3157c0d3a801SEric Liu         // Ignore the deletion on conflict.
3158c0d3a801SEric Liu         llvm::errs() << "Failed to add header deletion replacement for "
3159bf4c41c7SEric Liu                      << Header << ": " << llvm::toString(std::move(Err))
3160c0d3a801SEric Liu                      << "\n";
3161c0d3a801SEric Liu       }
3162c0d3a801SEric Liu     }
3163659afd55SEric Liu   }
3164659afd55SEric Liu 
3165e8cc7490SKrasimir Georgiev   llvm::Regex IncludeRegex = llvm::Regex(CppIncludeRegexPattern);
3166bf4c41c7SEric Liu   llvm::SmallVector<StringRef, 4> Matches;
3167659afd55SEric Liu   for (const auto &R : HeaderInsertions) {
3168659afd55SEric Liu     auto IncludeDirective = R.getReplacementText();
3169659afd55SEric Liu     bool Matched = IncludeRegex.match(IncludeDirective, &Matches);
3170659afd55SEric Liu     assert(Matched && "Header insertion replacement must have replacement text "
3171659afd55SEric Liu                       "'#include ...'");
31721cb7ee13SBenjamin Kramer     (void)Matched;
3173e8cc7490SKrasimir Georgiev     auto IncludeName = Matches[2];
3174e8cc7490SKrasimir Georgiev     auto Replace =
3175e8cc7490SKrasimir Georgiev         Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<"));
3176bf4c41c7SEric Liu     if (Replace) {
3177bf4c41c7SEric Liu       auto Err = Result.add(*Replace);
317840ef2fb3SEric Liu       if (Err) {
317940ef2fb3SEric Liu         llvm::consumeError(std::move(Err));
31805bcf99b4SPaul Hoad         unsigned NewOffset =
31815bcf99b4SPaul Hoad             Result.getShiftedCodePosition(Replace->getOffset());
3182bf4c41c7SEric Liu         auto Shifted = tooling::Replacement(FileName, NewOffset, 0,
3183bf4c41c7SEric Liu                                             Replace->getReplacementText());
3184bf4c41c7SEric Liu         Result = Result.merge(tooling::Replacements(Shifted));
3185bf4c41c7SEric Liu       }
318640ef2fb3SEric Liu     }
3187659afd55SEric Liu   }
3188659afd55SEric Liu   return Result;
3189659afd55SEric Liu }
3190659afd55SEric Liu 
3191659afd55SEric Liu } // anonymous namespace
3192659afd55SEric Liu 
31934f8d9943SEric Liu llvm::Expected<tooling::Replacements>
cleanupAroundReplacements(StringRef Code,const tooling::Replacements & Replaces,const FormatStyle & Style)31944cfb88a9SEric Liu cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
31954cfb88a9SEric Liu                           const FormatStyle &Style) {
31964cfb88a9SEric Liu   // We need to use lambda function here since there are two versions of
31974cfb88a9SEric Liu   // `cleanup`.
31984cfb88a9SEric Liu   auto Cleanup = [](const FormatStyle &Style, StringRef Code,
31994cfb88a9SEric Liu                     std::vector<tooling::Range> Ranges,
32004cfb88a9SEric Liu                     StringRef FileName) -> tooling::Replacements {
32014cfb88a9SEric Liu     return cleanup(Style, Code, Ranges, FileName);
32024cfb88a9SEric Liu   };
3203659afd55SEric Liu   // Make header insertion replacements insert new headers into correct blocks.
3204659afd55SEric Liu   tooling::Replacements NewReplaces =
3205659afd55SEric Liu       fixCppIncludeInsertions(Code, Replaces, Style);
3206659afd55SEric Liu   return processReplacements(Cleanup, Code, NewReplaces, Style);
32074cfb88a9SEric Liu }
32084cfb88a9SEric Liu 
32099ad83fe7SKrasimir Georgiev namespace internal {
32109ad83fe7SKrasimir Georgiev 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)32119ad83fe7SKrasimir Georgiev reformat(const FormatStyle &Style, StringRef Code,
32129ad83fe7SKrasimir Georgiev          ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,
32139ad83fe7SKrasimir Georgiev          unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,
3214bcda54b6SKrasimir Georgiev          FormattingAttemptStatus *Status) {
32156facafe7SC. Rayroud   FormatStyle Expanded = Style;
32166facafe7SC. Rayroud   expandPresetsBraceWrapping(Expanded);
32176facafe7SC. Rayroud   expandPresetsSpaceBeforeParens(Expanded);
32189aab0db1SBjörn Schäpers   switch (Expanded.RequiresClausePosition) {
32199aab0db1SBjörn Schäpers   case FormatStyle::RCPS_SingleLine:
32209aab0db1SBjörn Schäpers   case FormatStyle::RCPS_WithPreceding:
32219aab0db1SBjörn Schäpers     Expanded.IndentRequiresClause = false;
32229aab0db1SBjörn Schäpers     break;
32239aab0db1SBjörn Schäpers   default:
32249aab0db1SBjörn Schäpers     break;
32259aab0db1SBjörn Schäpers   }
32269aab0db1SBjörn Schäpers 
32274cfb88a9SEric Liu   if (Expanded.DisableFormat)
32289ad83fe7SKrasimir Georgiev     return {tooling::Replacements(), 0};
322986873030SKrasimir Georgiev   if (isLikelyXml(Code))
32309ad83fe7SKrasimir Georgiev     return {tooling::Replacements(), 0};
323186873030SKrasimir Georgiev   if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code))
32329ad83fe7SKrasimir Georgiev     return {tooling::Replacements(), 0};
3233496c1999SDaniel Jasper 
32348b7881a0Smydeveloperday   // JSON only needs the formatting passing.
32358b7881a0Smydeveloperday   if (Style.isJson()) {
32368b7881a0Smydeveloperday     std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
323793fc9161Smydeveloperday     auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
32388b7881a0Smydeveloperday                                  NextStartColumn, LastStartColumn);
3239c2271926SManuel Klimek     if (!Env)
3240c2271926SManuel Klimek       return {};
32418b7881a0Smydeveloperday     // Perform the actual formatting pass.
32428b7881a0Smydeveloperday     tooling::Replacements Replaces =
32438b7881a0Smydeveloperday         Formatter(*Env, Style, Status).process().first;
32448b7881a0Smydeveloperday     // add a replacement to remove the "x = " from the result.
32458b7881a0Smydeveloperday     if (!Replaces.add(tooling::Replacement(FileName, 0, 4, ""))) {
32468b7881a0Smydeveloperday       // apply the reformatting changes and the removal of "x = ".
3247d079995dSMarek Kurdej       if (applyAllReplacements(Code, Replaces))
32488b7881a0Smydeveloperday         return {Replaces, 0};
32498b7881a0Smydeveloperday     }
32508b7881a0Smydeveloperday     return {tooling::Replacements(), 0};
32518b7881a0Smydeveloperday   }
32528b7881a0Smydeveloperday 
32539ad83fe7SKrasimir Georgiev   typedef std::function<std::pair<tooling::Replacements, unsigned>(
32549ad83fe7SKrasimir Georgiev       const Environment &)>
3255ac16a201SKrasimir Georgiev       AnalyzerPass;
32569f616a46Sowenca   SmallVector<AnalyzerPass, 8> Passes;
325732eaa864SKrasimir Georgiev 
32589f616a46Sowenca   if (Style.isCpp()) {
32599f616a46Sowenca     if (Style.QualifierAlignment != FormatStyle::QAS_Leave) {
3260a44ab170Smydeveloperday       Passes.emplace_back([&](const Environment &Env) {
3261a44ab170Smydeveloperday         return QualifierAlignmentFixer(Env, Expanded, Code, Ranges,
3262a44ab170Smydeveloperday                                        FirstStartColumn, NextStartColumn,
3263a44ab170Smydeveloperday                                        LastStartColumn, FileName)
3264a44ab170Smydeveloperday             .process();
3265a44ab170Smydeveloperday       });
3266a44ab170Smydeveloperday     }
3267a44ab170Smydeveloperday 
3268bebf7bdfSowenca     if (Style.InsertBraces) {
326977e60bc4Sowenca       Passes.emplace_back([&](const Environment &Env) {
327077e60bc4Sowenca         return BracesInserter(Env, Expanded).process();
327177e60bc4Sowenca       });
3272bebf7bdfSowenca     }
327377e60bc4Sowenca 
3274bebf7bdfSowenca     if (Style.RemoveBracesLLVM) {
3275533fbae8SOwen Pan       Passes.emplace_back([&](const Environment &Env) {
3276533fbae8SOwen Pan         return BracesRemover(Env, Expanded).process();
3277533fbae8SOwen Pan       });
3278bebf7bdfSowenca     }
3279533fbae8SOwen Pan 
3280bebf7bdfSowenca     if (Style.FixNamespaceComments) {
3281ac16a201SKrasimir Georgiev       Passes.emplace_back([&](const Environment &Env) {
3282ac16a201SKrasimir Georgiev         return NamespaceEndCommentsFixer(Env, Expanded).process();
3283ac16a201SKrasimir Georgiev       });
3284bebf7bdfSowenca     }
3285ac16a201SKrasimir Georgiev 
3286bebf7bdfSowenca     if (Style.SortUsingDeclarations) {
3287ac16a201SKrasimir Georgiev       Passes.emplace_back([&](const Environment &Env) {
3288ac16a201SKrasimir Georgiev         return UsingDeclarationsSorter(Env, Expanded).process();
3289ac16a201SKrasimir Georgiev       });
329032eaa864SKrasimir Georgiev     }
3291bebf7bdfSowenca   }
329232eaa864SKrasimir Georgiev 
3293bebf7bdfSowenca   if (Style.SeparateDefinitionBlocks != FormatStyle::SDS_Leave) {
32946f6f88ffSksyx     Passes.emplace_back([&](const Environment &Env) {
32956f6f88ffSksyx       return DefinitionBlockSeparator(Env, Expanded).process();
32966f6f88ffSksyx     });
3297bebf7bdfSowenca   }
32986f6f88ffSksyx 
3299bebf7bdfSowenca   if (Style.isJavaScript() &&
3300bebf7bdfSowenca       Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) {
3301ac16a201SKrasimir Georgiev     Passes.emplace_back([&](const Environment &Env) {
3302ac16a201SKrasimir Georgiev       return JavaScriptRequoter(Env, Expanded).process();
3303ac16a201SKrasimir Georgiev     });
3304bebf7bdfSowenca   }
3305ac16a201SKrasimir Georgiev 
3306ac16a201SKrasimir Georgiev   Passes.emplace_back([&](const Environment &Env) {
3307ac16a201SKrasimir Georgiev     return Formatter(Env, Expanded, Status).process();
3308ac16a201SKrasimir Georgiev   });
3309ac16a201SKrasimir Georgiev 
3310142e79b8Smydeveloperday   if (Style.isJavaScript() &&
3311bebf7bdfSowenca       Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped) {
3312a324fcf1SMartin Probst     Passes.emplace_back([&](const Environment &Env) {
3313a324fcf1SMartin Probst       return TrailingCommaInserter(Env, Expanded).process();
3314a324fcf1SMartin Probst     });
3315bebf7bdfSowenca   }
3316a324fcf1SMartin Probst 
3317c2271926SManuel Klimek   auto Env = Environment::make(Code, FileName, Ranges, FirstStartColumn,
33182e538089SEric Liu                                NextStartColumn, LastStartColumn);
3319c2271926SManuel Klimek   if (!Env)
3320c2271926SManuel Klimek     return {};
3321ac16a201SKrasimir Georgiev   llvm::Optional<std::string> CurrentCode = None;
3322ac16a201SKrasimir Georgiev   tooling::Replacements Fixes;
33239ad83fe7SKrasimir Georgiev   unsigned Penalty = 0;
3324ac16a201SKrasimir Georgiev   for (size_t I = 0, E = Passes.size(); I < E; ++I) {
33259ad83fe7SKrasimir Georgiev     std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
3326ac16a201SKrasimir Georgiev     auto NewCode = applyAllReplacements(
33279ad83fe7SKrasimir Georgiev         CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
3328ac16a201SKrasimir Georgiev     if (NewCode) {
33299ad83fe7SKrasimir Georgiev       Fixes = Fixes.merge(PassFixes.first);
33309ad83fe7SKrasimir Georgiev       Penalty += PassFixes.second;
3331ac16a201SKrasimir Georgiev       if (I + 1 < E) {
3332ac16a201SKrasimir Georgiev         CurrentCode = std::move(*NewCode);
3333c2271926SManuel Klimek         Env = Environment::make(
3334ac16a201SKrasimir Georgiev             *CurrentCode, FileName,
33359ad83fe7SKrasimir Georgiev             tooling::calculateRangesAfterReplacements(Fixes, Ranges),
33369ad83fe7SKrasimir Georgiev             FirstStartColumn, NextStartColumn, LastStartColumn);
3337c2271926SManuel Klimek         if (!Env)
3338c2271926SManuel Klimek           return {};
3339ac16a201SKrasimir Georgiev       }
3340ac16a201SKrasimir Georgiev     }
3341496c1999SDaniel Jasper   }
3342496c1999SDaniel Jasper 
33439ad83fe7SKrasimir Georgiev   return {Fixes, Penalty};
33449ad83fe7SKrasimir Georgiev }
33459ad83fe7SKrasimir Georgiev } // namespace internal
33469ad83fe7SKrasimir Georgiev 
reformat(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName,FormattingAttemptStatus * Status)33479ad83fe7SKrasimir Georgiev tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
33489ad83fe7SKrasimir Georgiev                                ArrayRef<tooling::Range> Ranges,
33499ad83fe7SKrasimir Georgiev                                StringRef FileName,
33509ad83fe7SKrasimir Georgiev                                FormattingAttemptStatus *Status) {
33519ad83fe7SKrasimir Georgiev   return internal::reformat(Style, Code, Ranges,
33529ad83fe7SKrasimir Georgiev                             /*FirstStartColumn=*/0,
33539ad83fe7SKrasimir Georgiev                             /*NextStartColumn=*/0,
33549ad83fe7SKrasimir Georgiev                             /*LastStartColumn=*/0, FileName, Status)
33559ad83fe7SKrasimir Georgiev       .first;
3356ec04c0dbSDaniel Jasper }
33574cfb88a9SEric Liu 
cleanup(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName)33584cfb88a9SEric Liu tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
33594cfb88a9SEric Liu                               ArrayRef<tooling::Range> Ranges,
33604cfb88a9SEric Liu                               StringRef FileName) {
3361816a9668SMartin Probst   // cleanups only apply to C++ (they mostly concern ctor commas etc.)
3362816a9668SMartin Probst   if (Style.Language != FormatStyle::LK_Cpp)
3363816a9668SMartin Probst     return tooling::Replacements();
3364c2271926SManuel Klimek   auto Env = Environment::make(Code, FileName, Ranges);
3365c2271926SManuel Klimek   if (!Env)
3366c2271926SManuel Klimek     return {};
3367c2271926SManuel Klimek   return Cleaner(*Env, Style).process().first;
3368ec04c0dbSDaniel Jasper }
3369ec04c0dbSDaniel Jasper 
reformat(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName,bool * IncompleteFormat)3370bcda54b6SKrasimir Georgiev tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
3371bcda54b6SKrasimir Georgiev                                ArrayRef<tooling::Range> Ranges,
3372bcda54b6SKrasimir Georgiev                                StringRef FileName, bool *IncompleteFormat) {
3373bcda54b6SKrasimir Georgiev   FormattingAttemptStatus Status;
3374bcda54b6SKrasimir Georgiev   auto Result = reformat(Style, Code, Ranges, FileName, &Status);
3375bcda54b6SKrasimir Georgiev   if (!Status.FormatComplete)
3376bcda54b6SKrasimir Georgiev     *IncompleteFormat = true;
3377bcda54b6SKrasimir Georgiev   return Result;
3378bcda54b6SKrasimir Georgiev }
3379bcda54b6SKrasimir Georgiev 
fixNamespaceEndComments(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName)33807cb267afSKrasimir Georgiev tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,
33817cb267afSKrasimir Georgiev                                               StringRef Code,
33827cb267afSKrasimir Georgiev                                               ArrayRef<tooling::Range> Ranges,
33837cb267afSKrasimir Georgiev                                               StringRef FileName) {
3384c2271926SManuel Klimek   auto Env = Environment::make(Code, FileName, Ranges);
3385c2271926SManuel Klimek   if (!Env)
3386c2271926SManuel Klimek     return {};
338793fc9161Smydeveloperday   return NamespaceEndCommentsFixer(*Env, Style).process().first;
33887cb267afSKrasimir Georgiev }
33897cb267afSKrasimir Georgiev 
separateDefinitionBlocks(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName)33906f6f88ffSksyx tooling::Replacements separateDefinitionBlocks(const FormatStyle &Style,
33916f6f88ffSksyx                                                StringRef Code,
33926f6f88ffSksyx                                                ArrayRef<tooling::Range> Ranges,
33936f6f88ffSksyx                                                StringRef FileName) {
33946f6f88ffSksyx   auto Env = Environment::make(Code, FileName, Ranges);
33956f6f88ffSksyx   if (!Env)
33966f6f88ffSksyx     return {};
33976f6f88ffSksyx   return DefinitionBlockSeparator(*Env, Style).process().first;
33986f6f88ffSksyx }
33996f6f88ffSksyx 
sortUsingDeclarations(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName)3400b03877abSKrasimir Georgiev tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
3401b03877abSKrasimir Georgiev                                             StringRef Code,
3402b03877abSKrasimir Georgiev                                             ArrayRef<tooling::Range> Ranges,
3403b03877abSKrasimir Georgiev                                             StringRef FileName) {
3404c2271926SManuel Klimek   auto Env = Environment::make(Code, FileName, Ranges);
3405c2271926SManuel Klimek   if (!Env)
3406c2271926SManuel Klimek     return {};
340793fc9161Smydeveloperday   return UsingDeclarationsSorter(*Env, Style).process().first;
3408b03877abSKrasimir Georgiev }
3409b03877abSKrasimir Georgiev 
getFormattingLangOpts(const FormatStyle & Style)34104db69bd5SDaniel Jasper LangOptions getFormattingLangOpts(const FormatStyle &Style) {
3411c1fa2813SDaniel Jasper   LangOptions LangOpts;
3412e5032567SSam McCall 
3413e5032567SSam McCall   FormatStyle::LanguageStandard LexingStd = Style.Standard;
3414e5032567SSam McCall   if (LexingStd == FormatStyle::LS_Auto)
3415e5032567SSam McCall     LexingStd = FormatStyle::LS_Latest;
3416e5032567SSam McCall   if (LexingStd == FormatStyle::LS_Latest)
3417e5032567SSam McCall     LexingStd = FormatStyle::LS_Cpp20;
3418c1fa2813SDaniel Jasper   LangOpts.CPlusPlus = 1;
34195a43ba8aSFangrui Song   LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11;
3420e5032567SSam McCall   LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14;
3421e5032567SSam McCall   LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17;
34226a308943SAaron Ballman   LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20;
342320df6038SRichard Smith   LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20;
3424bc40b76bSMarek Kurdej   // Turning on digraphs in standards before C++0x is error-prone, because e.g.
3425bc40b76bSMarek Kurdej   // the sequence "<::" will be unconditionally treated as "[:".
3426bc40b76bSMarek Kurdej   // Cf. Lexer::LexTokenInternal.
3427bc40b76bSMarek Kurdej   LangOpts.Digraphs = LexingStd >= FormatStyle::LS_Cpp11;
3428e5032567SSam McCall 
342955213652SDaniel Jasper   LangOpts.LineComment = 1;
34301dbc2105SDaniel Jasper   bool AlternativeOperators = Style.isCpp();
343130a2406eSDaniel Jasper   LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
3432c1fa2813SDaniel Jasper   LangOpts.Bool = 1;
3433fa98390bSErik Pilkington   LangOpts.ObjC = 1;
3434fac2371bSNico Weber   LangOpts.MicrosoftExt = 1;    // To get kw___try, kw___finally.
3435d170c4b5SSaleem Abdulrasool   LangOpts.DeclSpecKeyword = 1; // To get __declspec.
34364f103695SAlex Richardson   LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict.
3437c1fa2813SDaniel Jasper   return LangOpts;
3438c1fa2813SDaniel Jasper }
3439c1fa2813SDaniel Jasper 
3440d544aa79SEdwin Vane const char *StyleOptionHelpDescription =
3441b1f0efc0SNico Weber     "Set coding style. <string> can be:\n"
3442b1f0efc0SNico Weber     "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"
3443b1f0efc0SNico Weber     "   Mozilla, WebKit.\n"
3444b1f0efc0SNico Weber     "2. 'file' to load style configuration from a\n"
3445b1f0efc0SNico Weber     "   .clang-format file in one of the parent directories\n"
3446b1f0efc0SNico Weber     "   of the source file (for stdin, see --assume-filename).\n"
3447b1f0efc0SNico Weber     "   If no .clang-format file is found, falls back to\n"
3448b1f0efc0SNico Weber     "   --fallback-style.\n"
3449b1f0efc0SNico Weber     "   --style=file is the default.\n"
3450b1f0efc0SNico Weber     "3. 'file:<format_file_path>' to explicitly specify\n"
3451b9e173fcSZhao Wei Liew     "   the configuration file.\n"
3452b1f0efc0SNico Weber     "4. \"{key: value, ...}\" to set specific parameters, e.g.:\n"
3453b1f0efc0SNico Weber     "   --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
3454d544aa79SEdwin Vane 
getLanguageByFileName(StringRef FileName)3455c1637f16SAlexander Kornienko static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
3456498f558fSDaniel Jasper   if (FileName.endswith(".java"))
3457c58c70e2SDaniel Jasper     return FormatStyle::LK_Java;
3458e5c7c171SMartin Storsjö   if (FileName.endswith_insensitive(".js") ||
3459e5c7c171SMartin Storsjö       FileName.endswith_insensitive(".mjs") ||
3460bebf7bdfSowenca       FileName.endswith_insensitive(".ts")) {
34618798c8deSFangrui Song     return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript.
3462bebf7bdfSowenca   }
346303a04fe9SDaniel Jasper   if (FileName.endswith(".m") || FileName.endswith(".mm"))
346403a04fe9SDaniel Jasper     return FormatStyle::LK_ObjC;
3465e5c7c171SMartin Storsjö   if (FileName.endswith_insensitive(".proto") ||
3466bebf7bdfSowenca       FileName.endswith_insensitive(".protodevel")) {
34677052ce6dSDaniel Jasper     return FormatStyle::LK_Proto;
3468bebf7bdfSowenca   }
3469e5c7c171SMartin Storsjö   if (FileName.endswith_insensitive(".textpb") ||
3470e5c7c171SMartin Storsjö       FileName.endswith_insensitive(".pb.txt") ||
3471e5c7c171SMartin Storsjö       FileName.endswith_insensitive(".textproto") ||
3472bebf7bdfSowenca       FileName.endswith_insensitive(".asciipb")) {
34736649665dSKrasimir Georgiev     return FormatStyle::LK_TextProto;
3474bebf7bdfSowenca   }
3475e5c7c171SMartin Storsjö   if (FileName.endswith_insensitive(".td"))
3476498f558fSDaniel Jasper     return FormatStyle::LK_TableGen;
3477e5c7c171SMartin Storsjö   if (FileName.endswith_insensitive(".cs"))
3478cbb726d0SPaul Hoad     return FormatStyle::LK_CSharp;
34798b7881a0Smydeveloperday   if (FileName.endswith_insensitive(".json"))
34808b7881a0Smydeveloperday     return FormatStyle::LK_Json;
34819ed2e68cSsstwcw   if (FileName.endswith_insensitive(".sv") ||
34829ed2e68cSsstwcw       FileName.endswith_insensitive(".svh") ||
34839ed2e68cSsstwcw       FileName.endswith_insensitive(".v") ||
34849ed2e68cSsstwcw       FileName.endswith_insensitive(".vh")) {
34859ed2e68cSsstwcw     return FormatStyle::LK_Verilog;
34869ed2e68cSsstwcw   }
3487c1637f16SAlexander Kornienko   return FormatStyle::LK_Cpp;
3488cabdd738SAlexander Kornienko }
3489cabdd738SAlexander Kornienko 
guessLanguage(StringRef FileName,StringRef Code)34903b345c36SBen Hamilton FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {
34916e066350SBen Hamilton   const auto GuessedLanguage = getLanguageByFileName(FileName);
34926e066350SBen Hamilton   if (GuessedLanguage == FormatStyle::LK_Cpp) {
349307e58365SBen Hamilton     auto Extension = llvm::sys::path::extension(FileName);
34943b345c36SBen Hamilton     // If there's no file extension (or it's .h), we need to check the contents
34953b345c36SBen Hamilton     // of the code to see if it contains Objective-C.
349607e58365SBen Hamilton     if (Extension.empty() || Extension == ".h") {
349707e58365SBen Hamilton       auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName;
34982e538089SEric Liu       Environment Env(Code, NonEmptyFileName, /*Ranges=*/{});
34992e538089SEric Liu       ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle());
35003b345c36SBen Hamilton       Guesser.process();
35016e066350SBen Hamilton       if (Guesser.isObjC())
35026e066350SBen Hamilton         return FormatStyle::LK_ObjC;
35033b345c36SBen Hamilton     }
35043b345c36SBen Hamilton   }
35056e066350SBen Hamilton   return GuessedLanguage;
35063b345c36SBen Hamilton }
35073b345c36SBen Hamilton 
3508b1f0efc0SNico Weber // Update StyleOptionHelpDescription above when changing this.
3509b4adc911SEric Liu const char *DefaultFormatStyle = "file";
3510b4adc911SEric Liu 
3511b4adc911SEric Liu const char *DefaultFallbackStyle = "LLVM";
3512b4adc911SEric Liu 
3513b9e173fcSZhao Wei Liew llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
loadAndParseConfigFile(StringRef ConfigFile,llvm::vfs::FileSystem * FS,FormatStyle * Style,bool AllowUnknownOptions)3514b9e173fcSZhao Wei Liew loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS,
3515b9e173fcSZhao Wei Liew                        FormatStyle *Style, bool AllowUnknownOptions) {
3516b9e173fcSZhao Wei Liew   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
3517b9e173fcSZhao Wei Liew       FS->getBufferForFile(ConfigFile.str());
3518b9e173fcSZhao Wei Liew   if (auto EC = Text.getError())
3519b9e173fcSZhao Wei Liew     return EC;
3520b9e173fcSZhao Wei Liew   if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions))
3521b9e173fcSZhao Wei Liew     return EC;
3522b9e173fcSZhao Wei Liew   return Text;
3523b9e173fcSZhao Wei Liew }
3524b9e173fcSZhao Wei Liew 
getStyle(StringRef StyleName,StringRef FileName,StringRef FallbackStyleName,StringRef Code,llvm::vfs::FileSystem * FS,bool AllowUnknownOptions)35253adfb6a3SAntonio Maiorano llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
35267eb7507aSAntonio Maiorano                                      StringRef FallbackStyleName,
3527f64903fdSJoachim Meyer                                      StringRef Code, llvm::vfs::FileSystem *FS,
3528f64903fdSJoachim Meyer                                      bool AllowUnknownOptions) {
3529d079995dSMarek Kurdej   if (!FS)
3530fc51490bSJonas Devlieghere     FS = llvm::vfs::getRealFileSystem().get();
35318bd97e75SJordan Rupprecht   FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code));
353203a04fe9SDaniel Jasper 
35337eb7507aSAntonio Maiorano   FormatStyle FallbackStyle = getNoStyle();
35347eb7507aSAntonio Maiorano   if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))
35357eb7507aSAntonio Maiorano     return make_string_error("Invalid fallback style \"" + FallbackStyleName);
3536d544aa79SEdwin Vane 
353725f753c5SBjörn Schäpers   llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1>
353825f753c5SBjörn Schäpers       ChildFormatTextToApply;
353925f753c5SBjörn Schäpers 
3540d544aa79SEdwin Vane   if (StyleName.startswith("{")) {
3541d544aa79SEdwin Vane     // Parse YAML/JSON style from the command line.
354225f753c5SBjörn Schäpers     StringRef Source = "<command-line>";
354325f753c5SBjörn Schäpers     if (std::error_code ec =
354425f753c5SBjörn Schäpers             parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style,
3545bebf7bdfSowenca                                AllowUnknownOptions)) {
35463adfb6a3SAntonio Maiorano       return make_string_error("Error parsing -style: " + ec.message());
3547bebf7bdfSowenca     }
3548bebf7bdfSowenca     if (Style.InheritsParentConfig) {
354925f753c5SBjörn Schäpers       ChildFormatTextToApply.emplace_back(
355025f753c5SBjörn Schäpers           llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false));
3551bebf7bdfSowenca     } else {
3552d544aa79SEdwin Vane       return Style;
3553d544aa79SEdwin Vane     }
3554bebf7bdfSowenca   }
3555d544aa79SEdwin Vane 
3556b9e173fcSZhao Wei Liew   // User provided clang-format file using -style=file:path/to/format/file.
3557b9e173fcSZhao Wei Liew   if (!Style.InheritsParentConfig &&
3558b9e173fcSZhao Wei Liew       StyleName.startswith_insensitive("file:")) {
3559b9e173fcSZhao Wei Liew     auto ConfigFile = StyleName.substr(5);
3560b9e173fcSZhao Wei Liew     llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
3561b9e173fcSZhao Wei Liew         loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions);
3562bebf7bdfSowenca     if (auto EC = Text.getError()) {
3563b9e173fcSZhao Wei Liew       return make_string_error("Error reading " + ConfigFile + ": " +
3564b9e173fcSZhao Wei Liew                                EC.message());
3565bebf7bdfSowenca     }
3566b9e173fcSZhao Wei Liew 
3567b9e173fcSZhao Wei Liew     LLVM_DEBUG(llvm::dbgs()
3568b9e173fcSZhao Wei Liew                << "Using configuration file " << ConfigFile << "\n");
3569b9e173fcSZhao Wei Liew 
3570b9e173fcSZhao Wei Liew     if (!Style.InheritsParentConfig)
3571b9e173fcSZhao Wei Liew       return Style;
3572b9e173fcSZhao Wei Liew 
3573b9e173fcSZhao Wei Liew     // Search for parent configs starting from the parent directory of
3574b9e173fcSZhao Wei Liew     // ConfigFile.
3575b9e173fcSZhao Wei Liew     FileName = ConfigFile;
3576b9e173fcSZhao Wei Liew     ChildFormatTextToApply.emplace_back(std::move(*Text));
3577b9e173fcSZhao Wei Liew   }
3578b9e173fcSZhao Wei Liew 
357925f753c5SBjörn Schäpers   // If the style inherits the parent configuration it is a command line
358025f753c5SBjörn Schäpers   // configuration, which wants to inherit, so we have to skip the check of the
358125f753c5SBjörn Schäpers   // StyleName.
3582e5c7c171SMartin Storsjö   if (!Style.InheritsParentConfig && !StyleName.equals_insensitive("file")) {
3583c1637f16SAlexander Kornienko     if (!getPredefinedStyle(StyleName, Style.Language, &Style))
35843adfb6a3SAntonio Maiorano       return make_string_error("Invalid value for -style");
358525f753c5SBjörn Schäpers     if (!Style.InheritsParentConfig)
3586d544aa79SEdwin Vane       return Style;
3587d544aa79SEdwin Vane   }
3588d544aa79SEdwin Vane 
358925f753c5SBjörn Schäpers   // Reset possible inheritance
359025f753c5SBjörn Schäpers   Style.InheritsParentConfig = false;
359125f753c5SBjörn Schäpers 
3592c1637f16SAlexander Kornienko   // Look for .clang-format/_clang-format file in the file's parent directories.
3593cabdd738SAlexander Kornienko   SmallString<128> UnsuitableConfigFiles;
3594d544aa79SEdwin Vane   SmallString<128> Path(FileName);
35953adfb6a3SAntonio Maiorano   if (std::error_code EC = FS->makeAbsolute(Path))
35963adfb6a3SAntonio Maiorano     return make_string_error(EC.message());
359734c03764SAntonio Maiorano 
3598c5c487f0SMitchell Balan   llvm::SmallVector<std::string, 2> FilesToLookFor;
359986825dbeSAnders Waldenborg   FilesToLookFor.push_back(".clang-format");
360086825dbeSAnders Waldenborg   FilesToLookFor.push_back("_clang-format");
360186825dbeSAnders Waldenborg 
3602e7309404SBjörn Schäpers   auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {};
3603e7309404SBjörn Schäpers 
36040090cd4eSZhao Wei Liew   auto applyChildFormatTexts = [&](FormatStyle *Style) {
36050090cd4eSZhao Wei Liew     for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) {
36060090cd4eSZhao Wei Liew       auto EC = parseConfiguration(*MemBuf, Style, AllowUnknownOptions,
36070090cd4eSZhao Wei Liew                                    dropDiagnosticHandler);
36080090cd4eSZhao Wei Liew       // It was already correctly parsed.
36090090cd4eSZhao Wei Liew       assert(!EC);
36100090cd4eSZhao Wei Liew       static_cast<void>(EC);
36110090cd4eSZhao Wei Liew     }
36120090cd4eSZhao Wei Liew   };
36130090cd4eSZhao Wei Liew 
3614e2e0387fSAlexander Kornienko   for (StringRef Directory = Path; !Directory.empty();
3615d544aa79SEdwin Vane        Directory = llvm::sys::path::parent_path(Directory)) {
3616547d8791SEric Liu 
3617547d8791SEric Liu     auto Status = FS->status(Directory);
3618547d8791SEric Liu     if (!Status ||
3619bebf7bdfSowenca         Status->getType() != llvm::sys::fs::file_type::directory_file) {
3620d544aa79SEdwin Vane       continue;
3621bebf7bdfSowenca     }
3622547d8791SEric Liu 
362386825dbeSAnders Waldenborg     for (const auto &F : FilesToLookFor) {
3624d544aa79SEdwin Vane       SmallString<128> ConfigFile(Directory);
3625d544aa79SEdwin Vane 
362686825dbeSAnders Waldenborg       llvm::sys::path::append(ConfigFile, F);
36273538b39eSNicola Zaghen       LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
3628c5c487f0SMitchell Balan 
3629547d8791SEric Liu       Status = FS->status(ConfigFile.str());
3630c5c487f0SMitchell Balan 
363186825dbeSAnders Waldenborg       if (Status &&
363286825dbeSAnders Waldenborg           (Status->getType() == llvm::sys::fs::file_type::regular_file)) {
3633c5c487f0SMitchell Balan         llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
3634b9e173fcSZhao Wei Liew             loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions);
3635b9e173fcSZhao Wei Liew         if (auto EC = Text.getError()) {
3636b9e173fcSZhao Wei Liew           if (EC == ParseError::Unsuitable) {
3637cabdd738SAlexander Kornienko             if (!UnsuitableConfigFiles.empty())
3638cabdd738SAlexander Kornienko               UnsuitableConfigFiles.append(", ");
3639cabdd738SAlexander Kornienko             UnsuitableConfigFiles.append(ConfigFile);
3640bc4ae449SAlexander Kornienko             continue;
3641bc4ae449SAlexander Kornienko           }
3642c5c487f0SMitchell Balan           return make_string_error("Error reading " + ConfigFile + ": " +
3643b9e173fcSZhao Wei Liew                                    EC.message());
3644d544aa79SEdwin Vane         }
3645c5c487f0SMitchell Balan         LLVM_DEBUG(llvm::dbgs()
3646c5c487f0SMitchell Balan                    << "Using configuration file " << ConfigFile << "\n");
364725f753c5SBjörn Schäpers 
364825f753c5SBjörn Schäpers         if (!Style.InheritsParentConfig) {
364925f753c5SBjörn Schäpers           if (ChildFormatTextToApply.empty())
3650c5c487f0SMitchell Balan             return Style;
365125f753c5SBjörn Schäpers 
365225f753c5SBjörn Schäpers           LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n");
36530090cd4eSZhao Wei Liew           applyChildFormatTexts(&Style);
365425f753c5SBjörn Schäpers 
365525f753c5SBjörn Schäpers           return Style;
365625f753c5SBjörn Schäpers         }
365725f753c5SBjörn Schäpers 
365825f753c5SBjörn Schäpers         LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n");
365925f753c5SBjörn Schäpers 
366025f753c5SBjörn Schäpers         // Reset inheritance of style
366125f753c5SBjörn Schäpers         Style.InheritsParentConfig = false;
366225f753c5SBjörn Schäpers 
366325f753c5SBjörn Schäpers         ChildFormatTextToApply.emplace_back(std::move(*Text));
366425f753c5SBjörn Schäpers 
366525f753c5SBjörn Schäpers         // Breaking out of the inner loop, since we don't want to parse
366625f753c5SBjörn Schäpers         // .clang-format AND _clang-format, if both exist. Then we continue the
366725f753c5SBjörn Schäpers         // inner loop (parent directories) in search for the parent
366825f753c5SBjörn Schäpers         // configuration.
366925f753c5SBjörn Schäpers         break;
3670d544aa79SEdwin Vane       }
3671d544aa79SEdwin Vane     }
367286825dbeSAnders Waldenborg   }
3673bebf7bdfSowenca   if (!UnsuitableConfigFiles.empty()) {
36743adfb6a3SAntonio Maiorano     return make_string_error("Configuration file(s) do(es) not support " +
36753adfb6a3SAntonio Maiorano                              getLanguageName(Style.Language) + ": " +
36763adfb6a3SAntonio Maiorano                              UnsuitableConfigFiles);
3677bebf7bdfSowenca   }
367825f753c5SBjörn Schäpers 
367925f753c5SBjörn Schäpers   if (!ChildFormatTextToApply.empty()) {
368025f753c5SBjörn Schäpers     LLVM_DEBUG(llvm::dbgs()
36810090cd4eSZhao Wei Liew                << "Applying child configurations on fallback style\n");
36820090cd4eSZhao Wei Liew     applyChildFormatTexts(&FallbackStyle);
368325f753c5SBjörn Schäpers   }
368425f753c5SBjörn Schäpers 
36857eb7507aSAntonio Maiorano   return FallbackStyle;
3686d544aa79SEdwin Vane }
3687d544aa79SEdwin Vane 
3688f7935115SDaniel Jasper } // namespace format
3689f7935115SDaniel Jasper } // namespace clang
3690