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