xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Format/Format.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===--- Format.cpp - Format C++ code -------------------------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg ///
97330f729Sjoerg /// \file
107330f729Sjoerg /// This file implements functions declared in Format.h. This will be
117330f729Sjoerg /// split into separate files as we go.
127330f729Sjoerg ///
137330f729Sjoerg //===----------------------------------------------------------------------===//
147330f729Sjoerg 
157330f729Sjoerg #include "clang/Format/Format.h"
167330f729Sjoerg #include "AffectedRangeManager.h"
17*e038c9c4Sjoerg #include "BreakableToken.h"
187330f729Sjoerg #include "ContinuationIndenter.h"
197330f729Sjoerg #include "FormatInternal.h"
207330f729Sjoerg #include "FormatTokenLexer.h"
217330f729Sjoerg #include "NamespaceEndCommentsFixer.h"
227330f729Sjoerg #include "SortJavaScriptImports.h"
237330f729Sjoerg #include "TokenAnalyzer.h"
247330f729Sjoerg #include "TokenAnnotator.h"
257330f729Sjoerg #include "UnwrappedLineFormatter.h"
267330f729Sjoerg #include "UnwrappedLineParser.h"
277330f729Sjoerg #include "UsingDeclarationsSorter.h"
287330f729Sjoerg #include "WhitespaceManager.h"
297330f729Sjoerg #include "clang/Basic/Diagnostic.h"
307330f729Sjoerg #include "clang/Basic/DiagnosticOptions.h"
317330f729Sjoerg #include "clang/Basic/SourceManager.h"
327330f729Sjoerg #include "clang/Lex/Lexer.h"
337330f729Sjoerg #include "clang/Tooling/Inclusions/HeaderIncludes.h"
347330f729Sjoerg #include "llvm/ADT/STLExtras.h"
357330f729Sjoerg #include "llvm/ADT/StringRef.h"
367330f729Sjoerg #include "llvm/Support/Allocator.h"
377330f729Sjoerg #include "llvm/Support/Debug.h"
387330f729Sjoerg #include "llvm/Support/Path.h"
397330f729Sjoerg #include "llvm/Support/Regex.h"
407330f729Sjoerg #include "llvm/Support/VirtualFileSystem.h"
417330f729Sjoerg #include "llvm/Support/YAMLTraits.h"
427330f729Sjoerg #include <algorithm>
437330f729Sjoerg #include <memory>
447330f729Sjoerg #include <mutex>
457330f729Sjoerg #include <string>
467330f729Sjoerg #include <unordered_map>
477330f729Sjoerg 
487330f729Sjoerg #define DEBUG_TYPE "format-formatter"
497330f729Sjoerg 
507330f729Sjoerg using clang::format::FormatStyle;
517330f729Sjoerg 
527330f729Sjoerg LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat)
537330f729Sjoerg 
547330f729Sjoerg namespace llvm {
557330f729Sjoerg namespace yaml {
567330f729Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
enumerationllvm::yaml::ScalarEnumerationTraits577330f729Sjoerg   static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
587330f729Sjoerg     IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
597330f729Sjoerg     IO.enumCase(Value, "Java", FormatStyle::LK_Java);
607330f729Sjoerg     IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
617330f729Sjoerg     IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);
627330f729Sjoerg     IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
637330f729Sjoerg     IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);
647330f729Sjoerg     IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto);
657330f729Sjoerg     IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp);
667330f729Sjoerg   }
677330f729Sjoerg };
687330f729Sjoerg 
697330f729Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
enumerationllvm::yaml::ScalarEnumerationTraits707330f729Sjoerg   static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
717330f729Sjoerg     IO.enumCase(Value, "c++03", FormatStyle::LS_Cpp03);
727330f729Sjoerg     IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03); // Legacy alias
737330f729Sjoerg     IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03); // Legacy alias
747330f729Sjoerg 
757330f729Sjoerg     IO.enumCase(Value, "c++11", FormatStyle::LS_Cpp11);
767330f729Sjoerg     IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11); // Legacy alias
777330f729Sjoerg 
787330f729Sjoerg     IO.enumCase(Value, "c++14", FormatStyle::LS_Cpp14);
797330f729Sjoerg     IO.enumCase(Value, "c++17", FormatStyle::LS_Cpp17);
807330f729Sjoerg     IO.enumCase(Value, "c++20", FormatStyle::LS_Cpp20);
817330f729Sjoerg 
827330f729Sjoerg     IO.enumCase(Value, "Latest", FormatStyle::LS_Latest);
837330f729Sjoerg     IO.enumCase(Value, "Cpp11", FormatStyle::LS_Latest); // Legacy alias
847330f729Sjoerg     IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);
857330f729Sjoerg   }
867330f729Sjoerg };
877330f729Sjoerg 
887330f729Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits897330f729Sjoerg   static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {
907330f729Sjoerg     IO.enumCase(Value, "Never", FormatStyle::UT_Never);
917330f729Sjoerg     IO.enumCase(Value, "false", FormatStyle::UT_Never);
927330f729Sjoerg     IO.enumCase(Value, "Always", FormatStyle::UT_Always);
937330f729Sjoerg     IO.enumCase(Value, "true", FormatStyle::UT_Always);
947330f729Sjoerg     IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation);
957330f729Sjoerg     IO.enumCase(Value, "ForContinuationAndIndentation",
967330f729Sjoerg                 FormatStyle::UT_ForContinuationAndIndentation);
97*e038c9c4Sjoerg     IO.enumCase(Value, "AlignWithSpaces", FormatStyle::UT_AlignWithSpaces);
987330f729Sjoerg   }
997330f729Sjoerg };
1007330f729Sjoerg 
1017330f729Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits1027330f729Sjoerg   static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) {
1037330f729Sjoerg     IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave);
1047330f729Sjoerg     IO.enumCase(Value, "Single", FormatStyle::JSQS_Single);
1057330f729Sjoerg     IO.enumCase(Value, "Double", FormatStyle::JSQS_Double);
1067330f729Sjoerg   }
1077330f729Sjoerg };
1087330f729Sjoerg 
1097330f729Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::ShortBlockStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits1107330f729Sjoerg   static void enumeration(IO &IO, FormatStyle::ShortBlockStyle &Value) {
1117330f729Sjoerg     IO.enumCase(Value, "Never", FormatStyle::SBS_Never);
1127330f729Sjoerg     IO.enumCase(Value, "false", FormatStyle::SBS_Never);
1137330f729Sjoerg     IO.enumCase(Value, "Always", FormatStyle::SBS_Always);
1147330f729Sjoerg     IO.enumCase(Value, "true", FormatStyle::SBS_Always);
1157330f729Sjoerg     IO.enumCase(Value, "Empty", FormatStyle::SBS_Empty);
1167330f729Sjoerg   }
1177330f729Sjoerg };
1187330f729Sjoerg 
1197330f729Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits1207330f729Sjoerg   static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
1217330f729Sjoerg     IO.enumCase(Value, "None", FormatStyle::SFS_None);
1227330f729Sjoerg     IO.enumCase(Value, "false", FormatStyle::SFS_None);
1237330f729Sjoerg     IO.enumCase(Value, "All", FormatStyle::SFS_All);
1247330f729Sjoerg     IO.enumCase(Value, "true", FormatStyle::SFS_All);
1257330f729Sjoerg     IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
1267330f729Sjoerg     IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly);
1277330f729Sjoerg     IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);
1287330f729Sjoerg   }
1297330f729Sjoerg };
1307330f729Sjoerg 
131*e038c9c4Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::AlignConsecutiveStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits132*e038c9c4Sjoerg   static void enumeration(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
133*e038c9c4Sjoerg     IO.enumCase(Value, "None", FormatStyle::ACS_None);
134*e038c9c4Sjoerg     IO.enumCase(Value, "Consecutive", FormatStyle::ACS_Consecutive);
135*e038c9c4Sjoerg     IO.enumCase(Value, "AcrossEmptyLines", FormatStyle::ACS_AcrossEmptyLines);
136*e038c9c4Sjoerg     IO.enumCase(Value, "AcrossComments", FormatStyle::ACS_AcrossComments);
137*e038c9c4Sjoerg     IO.enumCase(Value, "AcrossEmptyLinesAndComments",
138*e038c9c4Sjoerg                 FormatStyle::ACS_AcrossEmptyLinesAndComments);
139*e038c9c4Sjoerg 
140*e038c9c4Sjoerg     // For backward compability.
141*e038c9c4Sjoerg     IO.enumCase(Value, "true", FormatStyle::ACS_Consecutive);
142*e038c9c4Sjoerg     IO.enumCase(Value, "false", FormatStyle::ACS_None);
143*e038c9c4Sjoerg   }
144*e038c9c4Sjoerg };
145*e038c9c4Sjoerg 
1467330f729Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits1477330f729Sjoerg   static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) {
1487330f729Sjoerg     IO.enumCase(Value, "Never", FormatStyle::SIS_Never);
1497330f729Sjoerg     IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse);
150*e038c9c4Sjoerg     IO.enumCase(Value, "OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf);
151*e038c9c4Sjoerg     IO.enumCase(Value, "AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse);
1527330f729Sjoerg 
1537330f729Sjoerg     // For backward compatibility.
154*e038c9c4Sjoerg     IO.enumCase(Value, "Always", FormatStyle::SIS_OnlyFirstIf);
1557330f729Sjoerg     IO.enumCase(Value, "false", FormatStyle::SIS_Never);
1567330f729Sjoerg     IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse);
1577330f729Sjoerg   }
1587330f729Sjoerg };
1597330f729Sjoerg 
1607330f729Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::ShortLambdaStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits1617330f729Sjoerg   static void enumeration(IO &IO, FormatStyle::ShortLambdaStyle &Value) {
1627330f729Sjoerg     IO.enumCase(Value, "None", FormatStyle::SLS_None);
1637330f729Sjoerg     IO.enumCase(Value, "false", FormatStyle::SLS_None);
1647330f729Sjoerg     IO.enumCase(Value, "Empty", FormatStyle::SLS_Empty);
1657330f729Sjoerg     IO.enumCase(Value, "Inline", FormatStyle::SLS_Inline);
1667330f729Sjoerg     IO.enumCase(Value, "All", FormatStyle::SLS_All);
1677330f729Sjoerg     IO.enumCase(Value, "true", FormatStyle::SLS_All);
1687330f729Sjoerg   }
1697330f729Sjoerg };
1707330f729Sjoerg 
1717330f729Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits1727330f729Sjoerg   static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) {
1737330f729Sjoerg     IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto);
1747330f729Sjoerg     IO.enumCase(Value, "Always", FormatStyle::BPS_Always);
1757330f729Sjoerg     IO.enumCase(Value, "Never", FormatStyle::BPS_Never);
1767330f729Sjoerg   }
1777330f729Sjoerg };
1787330f729Sjoerg 
179*e038c9c4Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::TrailingCommaStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits180*e038c9c4Sjoerg   static void enumeration(IO &IO, FormatStyle::TrailingCommaStyle &Value) {
181*e038c9c4Sjoerg     IO.enumCase(Value, "None", FormatStyle::TCS_None);
182*e038c9c4Sjoerg     IO.enumCase(Value, "Wrapped", FormatStyle::TCS_Wrapped);
183*e038c9c4Sjoerg   }
184*e038c9c4Sjoerg };
185*e038c9c4Sjoerg 
1867330f729Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits1877330f729Sjoerg   static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {
1887330f729Sjoerg     IO.enumCase(Value, "All", FormatStyle::BOS_All);
1897330f729Sjoerg     IO.enumCase(Value, "true", FormatStyle::BOS_All);
1907330f729Sjoerg     IO.enumCase(Value, "None", FormatStyle::BOS_None);
1917330f729Sjoerg     IO.enumCase(Value, "false", FormatStyle::BOS_None);
1927330f729Sjoerg     IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment);
1937330f729Sjoerg   }
1947330f729Sjoerg };
1957330f729Sjoerg 
1967330f729Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits1977330f729Sjoerg   static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {
1987330f729Sjoerg     IO.enumCase(Value, "Attach", FormatStyle::BS_Attach);
1997330f729Sjoerg     IO.enumCase(Value, "Linux", FormatStyle::BS_Linux);
2007330f729Sjoerg     IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla);
2017330f729Sjoerg     IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);
2027330f729Sjoerg     IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
2037330f729Sjoerg     IO.enumCase(Value, "Whitesmiths", FormatStyle::BS_Whitesmiths);
2047330f729Sjoerg     IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
2057330f729Sjoerg     IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit);
2067330f729Sjoerg     IO.enumCase(Value, "Custom", FormatStyle::BS_Custom);
2077330f729Sjoerg   }
2087330f729Sjoerg };
2097330f729Sjoerg 
2107330f729Sjoerg template <>
2117330f729Sjoerg struct ScalarEnumerationTraits<
2127330f729Sjoerg     FormatStyle::BraceWrappingAfterControlStatementStyle> {
2137330f729Sjoerg   static void
enumerationllvm::yaml::ScalarEnumerationTraits2147330f729Sjoerg   enumeration(IO &IO,
2157330f729Sjoerg               FormatStyle::BraceWrappingAfterControlStatementStyle &Value) {
2167330f729Sjoerg     IO.enumCase(Value, "Never", FormatStyle::BWACS_Never);
2177330f729Sjoerg     IO.enumCase(Value, "MultiLine", FormatStyle::BWACS_MultiLine);
2187330f729Sjoerg     IO.enumCase(Value, "Always", FormatStyle::BWACS_Always);
219*e038c9c4Sjoerg 
220*e038c9c4Sjoerg     // For backward compatibility.
221*e038c9c4Sjoerg     IO.enumCase(Value, "false", FormatStyle::BWACS_Never);
222*e038c9c4Sjoerg     IO.enumCase(Value, "true", FormatStyle::BWACS_Always);
2237330f729Sjoerg   }
2247330f729Sjoerg };
2257330f729Sjoerg 
2267330f729Sjoerg template <>
2277330f729Sjoerg struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
2287330f729Sjoerg   static void
enumerationllvm::yaml::ScalarEnumerationTraits2297330f729Sjoerg   enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
2307330f729Sjoerg     IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon);
2317330f729Sjoerg     IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma);
2327330f729Sjoerg     IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon);
2337330f729Sjoerg   }
2347330f729Sjoerg };
2357330f729Sjoerg 
2367330f729Sjoerg template <>
2377330f729Sjoerg struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits2387330f729Sjoerg   static void enumeration(IO &IO,
2397330f729Sjoerg                           FormatStyle::BreakInheritanceListStyle &Value) {
2407330f729Sjoerg     IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon);
2417330f729Sjoerg     IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma);
2427330f729Sjoerg     IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon);
2437330f729Sjoerg   }
2447330f729Sjoerg };
2457330f729Sjoerg 
2467330f729Sjoerg template <>
247*e038c9c4Sjoerg struct ScalarEnumerationTraits<FormatStyle::EmptyLineAfterAccessModifierStyle> {
248*e038c9c4Sjoerg   static void
enumerationllvm::yaml::ScalarEnumerationTraits249*e038c9c4Sjoerg   enumeration(IO &IO, FormatStyle::EmptyLineAfterAccessModifierStyle &Value) {
250*e038c9c4Sjoerg     IO.enumCase(Value, "Never", FormatStyle::ELAAMS_Never);
251*e038c9c4Sjoerg     IO.enumCase(Value, "Leave", FormatStyle::ELAAMS_Leave);
252*e038c9c4Sjoerg     IO.enumCase(Value, "Always", FormatStyle::ELAAMS_Always);
253*e038c9c4Sjoerg   }
254*e038c9c4Sjoerg };
255*e038c9c4Sjoerg 
256*e038c9c4Sjoerg template <>
257*e038c9c4Sjoerg struct ScalarEnumerationTraits<
258*e038c9c4Sjoerg     FormatStyle::EmptyLineBeforeAccessModifierStyle> {
259*e038c9c4Sjoerg   static void
enumerationllvm::yaml::ScalarEnumerationTraits260*e038c9c4Sjoerg   enumeration(IO &IO, FormatStyle::EmptyLineBeforeAccessModifierStyle &Value) {
261*e038c9c4Sjoerg     IO.enumCase(Value, "Never", FormatStyle::ELBAMS_Never);
262*e038c9c4Sjoerg     IO.enumCase(Value, "Leave", FormatStyle::ELBAMS_Leave);
263*e038c9c4Sjoerg     IO.enumCase(Value, "LogicalBlock", FormatStyle::ELBAMS_LogicalBlock);
264*e038c9c4Sjoerg     IO.enumCase(Value, "Always", FormatStyle::ELBAMS_Always);
265*e038c9c4Sjoerg   }
266*e038c9c4Sjoerg };
267*e038c9c4Sjoerg 
268*e038c9c4Sjoerg template <>
2697330f729Sjoerg struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits2707330f729Sjoerg   static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
2717330f729Sjoerg     IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
2727330f729Sjoerg     IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);
2737330f729Sjoerg     IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash);
2747330f729Sjoerg   }
2757330f729Sjoerg };
2767330f729Sjoerg 
2777330f729Sjoerg template <>
278*e038c9c4Sjoerg struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits279*e038c9c4Sjoerg   static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value) {
280*e038c9c4Sjoerg     IO.enumCase(Value, "AfterExternBlock", FormatStyle::IEBS_AfterExternBlock);
281*e038c9c4Sjoerg     IO.enumCase(Value, "Indent", FormatStyle::IEBS_Indent);
282*e038c9c4Sjoerg     IO.enumCase(Value, "NoIndent", FormatStyle::IEBS_NoIndent);
283*e038c9c4Sjoerg     IO.enumCase(Value, "true", FormatStyle::IEBS_Indent);
284*e038c9c4Sjoerg     IO.enumCase(Value, "false", FormatStyle::IEBS_NoIndent);
285*e038c9c4Sjoerg   }
286*e038c9c4Sjoerg };
287*e038c9c4Sjoerg 
288*e038c9c4Sjoerg template <>
2897330f729Sjoerg struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits2907330f729Sjoerg   static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
2917330f729Sjoerg     IO.enumCase(Value, "None", FormatStyle::RTBS_None);
2927330f729Sjoerg     IO.enumCase(Value, "All", FormatStyle::RTBS_All);
2937330f729Sjoerg     IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel);
2947330f729Sjoerg     IO.enumCase(Value, "TopLevelDefinitions",
2957330f729Sjoerg                 FormatStyle::RTBS_TopLevelDefinitions);
2967330f729Sjoerg     IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions);
2977330f729Sjoerg   }
2987330f729Sjoerg };
2997330f729Sjoerg 
3007330f729Sjoerg template <>
3017330f729Sjoerg struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits3027330f729Sjoerg   static void enumeration(IO &IO,
3037330f729Sjoerg                           FormatStyle::BreakTemplateDeclarationsStyle &Value) {
3047330f729Sjoerg     IO.enumCase(Value, "No", FormatStyle::BTDS_No);
3057330f729Sjoerg     IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);
3067330f729Sjoerg     IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);
3077330f729Sjoerg 
3087330f729Sjoerg     // For backward compatibility.
3097330f729Sjoerg     IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine);
3107330f729Sjoerg     IO.enumCase(Value, "true", FormatStyle::BTDS_Yes);
3117330f729Sjoerg   }
3127330f729Sjoerg };
3137330f729Sjoerg 
3147330f729Sjoerg template <>
3157330f729Sjoerg struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
3167330f729Sjoerg   static void
enumerationllvm::yaml::ScalarEnumerationTraits3177330f729Sjoerg   enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
3187330f729Sjoerg     IO.enumCase(Value, "None", FormatStyle::DRTBS_None);
3197330f729Sjoerg     IO.enumCase(Value, "All", FormatStyle::DRTBS_All);
3207330f729Sjoerg     IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel);
3217330f729Sjoerg 
3227330f729Sjoerg     // For backward compatibility.
3237330f729Sjoerg     IO.enumCase(Value, "false", FormatStyle::DRTBS_None);
3247330f729Sjoerg     IO.enumCase(Value, "true", FormatStyle::DRTBS_All);
3257330f729Sjoerg   }
3267330f729Sjoerg };
3277330f729Sjoerg 
3287330f729Sjoerg template <>
3297330f729Sjoerg struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
enumerationllvm::yaml::ScalarEnumerationTraits3307330f729Sjoerg   static void enumeration(IO &IO,
3317330f729Sjoerg                           FormatStyle::NamespaceIndentationKind &Value) {
3327330f729Sjoerg     IO.enumCase(Value, "None", FormatStyle::NI_None);
3337330f729Sjoerg     IO.enumCase(Value, "Inner", FormatStyle::NI_Inner);
3347330f729Sjoerg     IO.enumCase(Value, "All", FormatStyle::NI_All);
3357330f729Sjoerg   }
3367330f729Sjoerg };
3377330f729Sjoerg 
3387330f729Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits3397330f729Sjoerg   static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) {
3407330f729Sjoerg     IO.enumCase(Value, "Align", FormatStyle::BAS_Align);
3417330f729Sjoerg     IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign);
3427330f729Sjoerg     IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak);
3437330f729Sjoerg 
3447330f729Sjoerg     // For backward compatibility.
3457330f729Sjoerg     IO.enumCase(Value, "true", FormatStyle::BAS_Align);
3467330f729Sjoerg     IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign);
3477330f729Sjoerg   }
3487330f729Sjoerg };
3497330f729Sjoerg 
3507330f729Sjoerg template <>
3517330f729Sjoerg struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits3527330f729Sjoerg   static void enumeration(IO &IO,
3537330f729Sjoerg                           FormatStyle::EscapedNewlineAlignmentStyle &Value) {
3547330f729Sjoerg     IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign);
3557330f729Sjoerg     IO.enumCase(Value, "Left", FormatStyle::ENAS_Left);
3567330f729Sjoerg     IO.enumCase(Value, "Right", FormatStyle::ENAS_Right);
3577330f729Sjoerg 
3587330f729Sjoerg     // For backward compatibility.
3597330f729Sjoerg     IO.enumCase(Value, "true", FormatStyle::ENAS_Left);
3607330f729Sjoerg     IO.enumCase(Value, "false", FormatStyle::ENAS_Right);
3617330f729Sjoerg   }
3627330f729Sjoerg };
3637330f729Sjoerg 
364*e038c9c4Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::OperandAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits365*e038c9c4Sjoerg   static void enumeration(IO &IO, FormatStyle::OperandAlignmentStyle &Value) {
366*e038c9c4Sjoerg     IO.enumCase(Value, "DontAlign", FormatStyle::OAS_DontAlign);
367*e038c9c4Sjoerg     IO.enumCase(Value, "Align", FormatStyle::OAS_Align);
368*e038c9c4Sjoerg     IO.enumCase(Value, "AlignAfterOperator",
369*e038c9c4Sjoerg                 FormatStyle::OAS_AlignAfterOperator);
370*e038c9c4Sjoerg 
371*e038c9c4Sjoerg     // For backward compatibility.
372*e038c9c4Sjoerg     IO.enumCase(Value, "true", FormatStyle::OAS_Align);
373*e038c9c4Sjoerg     IO.enumCase(Value, "false", FormatStyle::OAS_DontAlign);
374*e038c9c4Sjoerg   }
375*e038c9c4Sjoerg };
376*e038c9c4Sjoerg 
3777330f729Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits3787330f729Sjoerg   static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {
3797330f729Sjoerg     IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
3807330f729Sjoerg     IO.enumCase(Value, "Left", FormatStyle::PAS_Left);
3817330f729Sjoerg     IO.enumCase(Value, "Right", FormatStyle::PAS_Right);
3827330f729Sjoerg 
3837330f729Sjoerg     // For backward compatibility.
3847330f729Sjoerg     IO.enumCase(Value, "true", FormatStyle::PAS_Left);
3857330f729Sjoerg     IO.enumCase(Value, "false", FormatStyle::PAS_Right);
3867330f729Sjoerg   }
3877330f729Sjoerg };
3887330f729Sjoerg 
3897330f729Sjoerg template <>
390*e038c9c4Sjoerg struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> {
391*e038c9c4Sjoerg   static void
enumerationllvm::yaml::ScalarEnumerationTraits392*e038c9c4Sjoerg   enumeration(IO &IO, FormatStyle::SpaceAroundPointerQualifiersStyle &Value) {
393*e038c9c4Sjoerg     IO.enumCase(Value, "Default", FormatStyle::SAPQ_Default);
394*e038c9c4Sjoerg     IO.enumCase(Value, "Before", FormatStyle::SAPQ_Before);
395*e038c9c4Sjoerg     IO.enumCase(Value, "After", FormatStyle::SAPQ_After);
396*e038c9c4Sjoerg     IO.enumCase(Value, "Both", FormatStyle::SAPQ_Both);
397*e038c9c4Sjoerg   }
398*e038c9c4Sjoerg };
399*e038c9c4Sjoerg 
400*e038c9c4Sjoerg template <>
4017330f729Sjoerg struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
enumerationllvm::yaml::ScalarEnumerationTraits4027330f729Sjoerg   static void enumeration(IO &IO,
4037330f729Sjoerg                           FormatStyle::SpaceBeforeParensOptions &Value) {
4047330f729Sjoerg     IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
4057330f729Sjoerg     IO.enumCase(Value, "ControlStatements",
4067330f729Sjoerg                 FormatStyle::SBPO_ControlStatements);
407*e038c9c4Sjoerg     IO.enumCase(Value, "ControlStatementsExceptForEachMacros",
408*e038c9c4Sjoerg                 FormatStyle::SBPO_ControlStatementsExceptForEachMacros);
4097330f729Sjoerg     IO.enumCase(Value, "NonEmptyParentheses",
4107330f729Sjoerg                 FormatStyle::SBPO_NonEmptyParentheses);
4117330f729Sjoerg     IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
4127330f729Sjoerg 
4137330f729Sjoerg     // For backward compatibility.
4147330f729Sjoerg     IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
4157330f729Sjoerg     IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);
4167330f729Sjoerg   }
4177330f729Sjoerg };
4187330f729Sjoerg 
419*e038c9c4Sjoerg template <>
420*e038c9c4Sjoerg struct ScalarEnumerationTraits<FormatStyle::BitFieldColonSpacingStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits421*e038c9c4Sjoerg   static void enumeration(IO &IO,
422*e038c9c4Sjoerg                           FormatStyle::BitFieldColonSpacingStyle &Value) {
423*e038c9c4Sjoerg     IO.enumCase(Value, "Both", FormatStyle::BFCS_Both);
424*e038c9c4Sjoerg     IO.enumCase(Value, "None", FormatStyle::BFCS_None);
425*e038c9c4Sjoerg     IO.enumCase(Value, "Before", FormatStyle::BFCS_Before);
426*e038c9c4Sjoerg     IO.enumCase(Value, "After", FormatStyle::BFCS_After);
427*e038c9c4Sjoerg   }
428*e038c9c4Sjoerg };
429*e038c9c4Sjoerg 
430*e038c9c4Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::SortIncludesOptions> {
enumerationllvm::yaml::ScalarEnumerationTraits431*e038c9c4Sjoerg   static void enumeration(IO &IO, FormatStyle::SortIncludesOptions &Value) {
432*e038c9c4Sjoerg     IO.enumCase(Value, "Never", FormatStyle::SI_Never);
433*e038c9c4Sjoerg     IO.enumCase(Value, "CaseInsensitive", FormatStyle::SI_CaseInsensitive);
434*e038c9c4Sjoerg     IO.enumCase(Value, "CaseSensitive", FormatStyle::SI_CaseSensitive);
435*e038c9c4Sjoerg 
436*e038c9c4Sjoerg     // For backward compatibility.
437*e038c9c4Sjoerg     IO.enumCase(Value, "false", FormatStyle::SI_Never);
438*e038c9c4Sjoerg     IO.enumCase(Value, "true", FormatStyle::SI_CaseSensitive);
439*e038c9c4Sjoerg   }
440*e038c9c4Sjoerg };
441*e038c9c4Sjoerg 
442*e038c9c4Sjoerg template <>
443*e038c9c4Sjoerg struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> {
enumerationllvm::yaml::ScalarEnumerationTraits444*e038c9c4Sjoerg   static void enumeration(IO &IO,
445*e038c9c4Sjoerg                           FormatStyle::SortJavaStaticImportOptions &Value) {
446*e038c9c4Sjoerg     IO.enumCase(Value, "Before", FormatStyle::SJSIO_Before);
447*e038c9c4Sjoerg     IO.enumCase(Value, "After", FormatStyle::SJSIO_After);
448*e038c9c4Sjoerg   }
449*e038c9c4Sjoerg };
450*e038c9c4Sjoerg 
451*e038c9c4Sjoerg template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> {
enumerationllvm::yaml::ScalarEnumerationTraits452*e038c9c4Sjoerg   static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value) {
453*e038c9c4Sjoerg     IO.enumCase(Value, "Never", FormatStyle::SIAS_Never);
454*e038c9c4Sjoerg     IO.enumCase(Value, "Always", FormatStyle::SIAS_Always);
455*e038c9c4Sjoerg     IO.enumCase(Value, "Leave", FormatStyle::SIAS_Leave);
456*e038c9c4Sjoerg 
457*e038c9c4Sjoerg     // For backward compatibility.
458*e038c9c4Sjoerg     IO.enumCase(Value, "false", FormatStyle::SIAS_Never);
459*e038c9c4Sjoerg     IO.enumCase(Value, "true", FormatStyle::SIAS_Always);
460*e038c9c4Sjoerg   }
461*e038c9c4Sjoerg };
462*e038c9c4Sjoerg 
4637330f729Sjoerg template <> struct MappingTraits<FormatStyle> {
mappingllvm::yaml::MappingTraits4647330f729Sjoerg   static void mapping(IO &IO, FormatStyle &Style) {
4657330f729Sjoerg     // When reading, read the language first, we need it for getPredefinedStyle.
4667330f729Sjoerg     IO.mapOptional("Language", Style.Language);
4677330f729Sjoerg 
4687330f729Sjoerg     if (IO.outputting()) {
4697330f729Sjoerg       StringRef StylesArray[] = {"LLVM",   "Google", "Chromium", "Mozilla",
4707330f729Sjoerg                                  "WebKit", "GNU",    "Microsoft"};
4717330f729Sjoerg       ArrayRef<StringRef> Styles(StylesArray);
4727330f729Sjoerg       for (size_t i = 0, e = Styles.size(); i < e; ++i) {
4737330f729Sjoerg         StringRef StyleName(Styles[i]);
4747330f729Sjoerg         FormatStyle PredefinedStyle;
4757330f729Sjoerg         if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) &&
4767330f729Sjoerg             Style == PredefinedStyle) {
4777330f729Sjoerg           IO.mapOptional("# BasedOnStyle", StyleName);
4787330f729Sjoerg           break;
4797330f729Sjoerg         }
4807330f729Sjoerg       }
4817330f729Sjoerg     } else {
4827330f729Sjoerg       StringRef BasedOnStyle;
4837330f729Sjoerg       IO.mapOptional("BasedOnStyle", BasedOnStyle);
4847330f729Sjoerg       if (!BasedOnStyle.empty()) {
4857330f729Sjoerg         FormatStyle::LanguageKind OldLanguage = Style.Language;
4867330f729Sjoerg         FormatStyle::LanguageKind Language =
4877330f729Sjoerg             ((FormatStyle *)IO.getContext())->Language;
4887330f729Sjoerg         if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
4897330f729Sjoerg           IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle));
4907330f729Sjoerg           return;
4917330f729Sjoerg         }
4927330f729Sjoerg         Style.Language = OldLanguage;
4937330f729Sjoerg       }
4947330f729Sjoerg     }
4957330f729Sjoerg 
4967330f729Sjoerg     // For backward compatibility.
4977330f729Sjoerg     if (!IO.outputting()) {
4987330f729Sjoerg       IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines);
4997330f729Sjoerg       IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
5007330f729Sjoerg       IO.mapOptional("IndentFunctionDeclarationAfterType",
5017330f729Sjoerg                      Style.IndentWrappedFunctionNames);
5027330f729Sjoerg       IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
5037330f729Sjoerg       IO.mapOptional("SpaceAfterControlStatementKeyword",
5047330f729Sjoerg                      Style.SpaceBeforeParens);
5057330f729Sjoerg     }
5067330f729Sjoerg 
5077330f729Sjoerg     IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
5087330f729Sjoerg     IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
5097330f729Sjoerg     IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);
5107330f729Sjoerg     IO.mapOptional("AlignConsecutiveAssignments",
5117330f729Sjoerg                    Style.AlignConsecutiveAssignments);
512*e038c9c4Sjoerg     IO.mapOptional("AlignConsecutiveBitFields",
513*e038c9c4Sjoerg                    Style.AlignConsecutiveBitFields);
5147330f729Sjoerg     IO.mapOptional("AlignConsecutiveDeclarations",
5157330f729Sjoerg                    Style.AlignConsecutiveDeclarations);
5167330f729Sjoerg     IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines);
5177330f729Sjoerg     IO.mapOptional("AlignOperands", Style.AlignOperands);
5187330f729Sjoerg     IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
5197330f729Sjoerg     IO.mapOptional("AllowAllArgumentsOnNextLine",
5207330f729Sjoerg                    Style.AllowAllArgumentsOnNextLine);
5217330f729Sjoerg     IO.mapOptional("AllowAllConstructorInitializersOnNextLine",
5227330f729Sjoerg                    Style.AllowAllConstructorInitializersOnNextLine);
5237330f729Sjoerg     IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
5247330f729Sjoerg                    Style.AllowAllParametersOfDeclarationOnNextLine);
525*e038c9c4Sjoerg     IO.mapOptional("AllowShortEnumsOnASingleLine",
526*e038c9c4Sjoerg                    Style.AllowShortEnumsOnASingleLine);
5277330f729Sjoerg     IO.mapOptional("AllowShortBlocksOnASingleLine",
5287330f729Sjoerg                    Style.AllowShortBlocksOnASingleLine);
5297330f729Sjoerg     IO.mapOptional("AllowShortCaseLabelsOnASingleLine",
5307330f729Sjoerg                    Style.AllowShortCaseLabelsOnASingleLine);
5317330f729Sjoerg     IO.mapOptional("AllowShortFunctionsOnASingleLine",
5327330f729Sjoerg                    Style.AllowShortFunctionsOnASingleLine);
5337330f729Sjoerg     IO.mapOptional("AllowShortLambdasOnASingleLine",
5347330f729Sjoerg                    Style.AllowShortLambdasOnASingleLine);
5357330f729Sjoerg     IO.mapOptional("AllowShortIfStatementsOnASingleLine",
5367330f729Sjoerg                    Style.AllowShortIfStatementsOnASingleLine);
5377330f729Sjoerg     IO.mapOptional("AllowShortLoopsOnASingleLine",
5387330f729Sjoerg                    Style.AllowShortLoopsOnASingleLine);
5397330f729Sjoerg     IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",
5407330f729Sjoerg                    Style.AlwaysBreakAfterDefinitionReturnType);
5417330f729Sjoerg     IO.mapOptional("AlwaysBreakAfterReturnType",
5427330f729Sjoerg                    Style.AlwaysBreakAfterReturnType);
5437330f729Sjoerg 
5447330f729Sjoerg     // If AlwaysBreakAfterDefinitionReturnType was specified but
5457330f729Sjoerg     // AlwaysBreakAfterReturnType was not, initialize the latter from the
5467330f729Sjoerg     // former for backwards compatibility.
5477330f729Sjoerg     if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&
5487330f729Sjoerg         Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) {
5497330f729Sjoerg       if (Style.AlwaysBreakAfterDefinitionReturnType == FormatStyle::DRTBS_All)
5507330f729Sjoerg         Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
5517330f729Sjoerg       else if (Style.AlwaysBreakAfterDefinitionReturnType ==
5527330f729Sjoerg                FormatStyle::DRTBS_TopLevel)
5537330f729Sjoerg         Style.AlwaysBreakAfterReturnType =
5547330f729Sjoerg             FormatStyle::RTBS_TopLevelDefinitions;
5557330f729Sjoerg     }
5567330f729Sjoerg 
5577330f729Sjoerg     IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
5587330f729Sjoerg                    Style.AlwaysBreakBeforeMultilineStrings);
5597330f729Sjoerg     IO.mapOptional("AlwaysBreakTemplateDeclarations",
5607330f729Sjoerg                    Style.AlwaysBreakTemplateDeclarations);
561*e038c9c4Sjoerg     IO.mapOptional("AttributeMacros", Style.AttributeMacros);
5627330f729Sjoerg     IO.mapOptional("BinPackArguments", Style.BinPackArguments);
5637330f729Sjoerg     IO.mapOptional("BinPackParameters", Style.BinPackParameters);
5647330f729Sjoerg     IO.mapOptional("BraceWrapping", Style.BraceWrapping);
5657330f729Sjoerg     IO.mapOptional("BreakBeforeBinaryOperators",
5667330f729Sjoerg                    Style.BreakBeforeBinaryOperators);
567*e038c9c4Sjoerg     IO.mapOptional("BreakBeforeConceptDeclarations",
568*e038c9c4Sjoerg                    Style.BreakBeforeConceptDeclarations);
5697330f729Sjoerg     IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
5707330f729Sjoerg 
5717330f729Sjoerg     bool BreakBeforeInheritanceComma = false;
5727330f729Sjoerg     IO.mapOptional("BreakBeforeInheritanceComma", BreakBeforeInheritanceComma);
5737330f729Sjoerg     IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList);
5747330f729Sjoerg     // If BreakBeforeInheritanceComma was specified but
5757330f729Sjoerg     // BreakInheritance was not, initialize the latter from the
5767330f729Sjoerg     // former for backwards compatibility.
5777330f729Sjoerg     if (BreakBeforeInheritanceComma &&
5787330f729Sjoerg         Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon)
5797330f729Sjoerg       Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
5807330f729Sjoerg 
5817330f729Sjoerg     IO.mapOptional("BreakBeforeTernaryOperators",
5827330f729Sjoerg                    Style.BreakBeforeTernaryOperators);
5837330f729Sjoerg 
5847330f729Sjoerg     bool BreakConstructorInitializersBeforeComma = false;
5857330f729Sjoerg     IO.mapOptional("BreakConstructorInitializersBeforeComma",
5867330f729Sjoerg                    BreakConstructorInitializersBeforeComma);
5877330f729Sjoerg     IO.mapOptional("BreakConstructorInitializers",
5887330f729Sjoerg                    Style.BreakConstructorInitializers);
5897330f729Sjoerg     // If BreakConstructorInitializersBeforeComma was specified but
5907330f729Sjoerg     // BreakConstructorInitializers was not, initialize the latter from the
5917330f729Sjoerg     // former for backwards compatibility.
5927330f729Sjoerg     if (BreakConstructorInitializersBeforeComma &&
5937330f729Sjoerg         Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon)
5947330f729Sjoerg       Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
5957330f729Sjoerg 
5967330f729Sjoerg     IO.mapOptional("BreakAfterJavaFieldAnnotations",
5977330f729Sjoerg                    Style.BreakAfterJavaFieldAnnotations);
5987330f729Sjoerg     IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
5997330f729Sjoerg     IO.mapOptional("ColumnLimit", Style.ColumnLimit);
6007330f729Sjoerg     IO.mapOptional("CommentPragmas", Style.CommentPragmas);
6017330f729Sjoerg     IO.mapOptional("CompactNamespaces", Style.CompactNamespaces);
6027330f729Sjoerg     IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
6037330f729Sjoerg                    Style.ConstructorInitializerAllOnOneLineOrOnePerLine);
6047330f729Sjoerg     IO.mapOptional("ConstructorInitializerIndentWidth",
6057330f729Sjoerg                    Style.ConstructorInitializerIndentWidth);
6067330f729Sjoerg     IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
6077330f729Sjoerg     IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
608*e038c9c4Sjoerg     IO.mapOptional("DeriveLineEnding", Style.DeriveLineEnding);
6097330f729Sjoerg     IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
6107330f729Sjoerg     IO.mapOptional("DisableFormat", Style.DisableFormat);
611*e038c9c4Sjoerg     IO.mapOptional("EmptyLineAfterAccessModifier",
612*e038c9c4Sjoerg                    Style.EmptyLineAfterAccessModifier);
613*e038c9c4Sjoerg     IO.mapOptional("EmptyLineBeforeAccessModifier",
614*e038c9c4Sjoerg                    Style.EmptyLineBeforeAccessModifier);
6157330f729Sjoerg     IO.mapOptional("ExperimentalAutoDetectBinPacking",
6167330f729Sjoerg                    Style.ExperimentalAutoDetectBinPacking);
6177330f729Sjoerg     IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
6187330f729Sjoerg     IO.mapOptional("ForEachMacros", Style.ForEachMacros);
619*e038c9c4Sjoerg     IO.mapOptional("StatementAttributeLikeMacros",
620*e038c9c4Sjoerg                    Style.StatementAttributeLikeMacros);
6217330f729Sjoerg     IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
6227330f729Sjoerg     IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
6237330f729Sjoerg     IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
624*e038c9c4Sjoerg     IO.mapOptional("IncludeIsMainSourceRegex",
625*e038c9c4Sjoerg                    Style.IncludeStyle.IncludeIsMainSourceRegex);
626*e038c9c4Sjoerg     IO.mapOptional("IndentAccessModifiers", Style.IndentAccessModifiers);
6277330f729Sjoerg     IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
628*e038c9c4Sjoerg     IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks);
6297330f729Sjoerg     IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels);
6307330f729Sjoerg     IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
631*e038c9c4Sjoerg     IO.mapOptional("IndentExternBlock", Style.IndentExternBlock);
632*e038c9c4Sjoerg     IO.mapOptional("IndentRequires", Style.IndentRequires);
6337330f729Sjoerg     IO.mapOptional("IndentWidth", Style.IndentWidth);
6347330f729Sjoerg     IO.mapOptional("IndentWrappedFunctionNames",
6357330f729Sjoerg                    Style.IndentWrappedFunctionNames);
636*e038c9c4Sjoerg     IO.mapOptional("InsertTrailingCommas", Style.InsertTrailingCommas);
6377330f729Sjoerg     IO.mapOptional("JavaImportGroups", Style.JavaImportGroups);
6387330f729Sjoerg     IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);
6397330f729Sjoerg     IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
6407330f729Sjoerg     IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
6417330f729Sjoerg                    Style.KeepEmptyLinesAtTheStartOfBlocks);
6427330f729Sjoerg     IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
6437330f729Sjoerg     IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);
6447330f729Sjoerg     IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
6457330f729Sjoerg     IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
6467330f729Sjoerg     IO.mapOptional("NamespaceMacros", Style.NamespaceMacros);
6477330f729Sjoerg     IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList);
6487330f729Sjoerg     IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);
649*e038c9c4Sjoerg     IO.mapOptional("ObjCBreakBeforeNestedBlockParam",
650*e038c9c4Sjoerg                    Style.ObjCBreakBeforeNestedBlockParam);
6517330f729Sjoerg     IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
6527330f729Sjoerg     IO.mapOptional("ObjCSpaceBeforeProtocolList",
6537330f729Sjoerg                    Style.ObjCSpaceBeforeProtocolList);
6547330f729Sjoerg     IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment);
6557330f729Sjoerg     IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",
6567330f729Sjoerg                    Style.PenaltyBreakBeforeFirstCallParameter);
6577330f729Sjoerg     IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
6587330f729Sjoerg     IO.mapOptional("PenaltyBreakFirstLessLess",
6597330f729Sjoerg                    Style.PenaltyBreakFirstLessLess);
6607330f729Sjoerg     IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
6617330f729Sjoerg     IO.mapOptional("PenaltyBreakTemplateDeclaration",
6627330f729Sjoerg                    Style.PenaltyBreakTemplateDeclaration);
6637330f729Sjoerg     IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
6647330f729Sjoerg     IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
6657330f729Sjoerg                    Style.PenaltyReturnTypeOnItsOwnLine);
666*e038c9c4Sjoerg     IO.mapOptional("PenaltyIndentedWhitespace",
667*e038c9c4Sjoerg                    Style.PenaltyIndentedWhitespace);
6687330f729Sjoerg     IO.mapOptional("PointerAlignment", Style.PointerAlignment);
6697330f729Sjoerg     IO.mapOptional("RawStringFormats", Style.RawStringFormats);
6707330f729Sjoerg     IO.mapOptional("ReflowComments", Style.ReflowComments);
671*e038c9c4Sjoerg     IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines);
6727330f729Sjoerg     IO.mapOptional("SortIncludes", Style.SortIncludes);
673*e038c9c4Sjoerg     IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport);
6747330f729Sjoerg     IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);
6757330f729Sjoerg     IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
6767330f729Sjoerg     IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot);
6777330f729Sjoerg     IO.mapOptional("SpaceAfterTemplateKeyword",
6787330f729Sjoerg                    Style.SpaceAfterTemplateKeyword);
6797330f729Sjoerg     IO.mapOptional("SpaceBeforeAssignmentOperators",
6807330f729Sjoerg                    Style.SpaceBeforeAssignmentOperators);
681*e038c9c4Sjoerg     IO.mapOptional("SpaceBeforeCaseColon", Style.SpaceBeforeCaseColon);
6827330f729Sjoerg     IO.mapOptional("SpaceBeforeCpp11BracedList",
6837330f729Sjoerg                    Style.SpaceBeforeCpp11BracedList);
6847330f729Sjoerg     IO.mapOptional("SpaceBeforeCtorInitializerColon",
6857330f729Sjoerg                    Style.SpaceBeforeCtorInitializerColon);
6867330f729Sjoerg     IO.mapOptional("SpaceBeforeInheritanceColon",
6877330f729Sjoerg                    Style.SpaceBeforeInheritanceColon);
6887330f729Sjoerg     IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
689*e038c9c4Sjoerg     IO.mapOptional("SpaceAroundPointerQualifiers",
690*e038c9c4Sjoerg                    Style.SpaceAroundPointerQualifiers);
6917330f729Sjoerg     IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
6927330f729Sjoerg                    Style.SpaceBeforeRangeBasedForLoopColon);
6937330f729Sjoerg     IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock);
6947330f729Sjoerg     IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
6957330f729Sjoerg     IO.mapOptional("SpacesBeforeTrailingComments",
6967330f729Sjoerg                    Style.SpacesBeforeTrailingComments);
6977330f729Sjoerg     IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
698*e038c9c4Sjoerg     IO.mapOptional("SpacesInConditionalStatement",
699*e038c9c4Sjoerg                    Style.SpacesInConditionalStatement);
7007330f729Sjoerg     IO.mapOptional("SpacesInContainerLiterals",
7017330f729Sjoerg                    Style.SpacesInContainerLiterals);
7027330f729Sjoerg     IO.mapOptional("SpacesInCStyleCastParentheses",
7037330f729Sjoerg                    Style.SpacesInCStyleCastParentheses);
704*e038c9c4Sjoerg     IO.mapOptional("SpacesInLineCommentPrefix",
705*e038c9c4Sjoerg                    Style.SpacesInLineCommentPrefix);
7067330f729Sjoerg     IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
7077330f729Sjoerg     IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
708*e038c9c4Sjoerg     IO.mapOptional("SpaceBeforeSquareBrackets",
709*e038c9c4Sjoerg                    Style.SpaceBeforeSquareBrackets);
710*e038c9c4Sjoerg     IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing);
7117330f729Sjoerg     IO.mapOptional("Standard", Style.Standard);
7127330f729Sjoerg     IO.mapOptional("StatementMacros", Style.StatementMacros);
7137330f729Sjoerg     IO.mapOptional("TabWidth", Style.TabWidth);
7147330f729Sjoerg     IO.mapOptional("TypenameMacros", Style.TypenameMacros);
715*e038c9c4Sjoerg     IO.mapOptional("UseCRLF", Style.UseCRLF);
7167330f729Sjoerg     IO.mapOptional("UseTab", Style.UseTab);
717*e038c9c4Sjoerg     IO.mapOptional("WhitespaceSensitiveMacros",
718*e038c9c4Sjoerg                    Style.WhitespaceSensitiveMacros);
7197330f729Sjoerg   }
7207330f729Sjoerg };
7217330f729Sjoerg 
7227330f729Sjoerg template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
mappingllvm::yaml::MappingTraits7237330f729Sjoerg   static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
7247330f729Sjoerg     IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel);
7257330f729Sjoerg     IO.mapOptional("AfterClass", Wrapping.AfterClass);
7267330f729Sjoerg     IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement);
7277330f729Sjoerg     IO.mapOptional("AfterEnum", Wrapping.AfterEnum);
7287330f729Sjoerg     IO.mapOptional("AfterFunction", Wrapping.AfterFunction);
7297330f729Sjoerg     IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace);
7307330f729Sjoerg     IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
7317330f729Sjoerg     IO.mapOptional("AfterStruct", Wrapping.AfterStruct);
7327330f729Sjoerg     IO.mapOptional("AfterUnion", Wrapping.AfterUnion);
7337330f729Sjoerg     IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
7347330f729Sjoerg     IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
7357330f729Sjoerg     IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
736*e038c9c4Sjoerg     IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody);
737*e038c9c4Sjoerg     IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile);
7387330f729Sjoerg     IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
7397330f729Sjoerg     IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);
7407330f729Sjoerg     IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);
7417330f729Sjoerg     IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
7427330f729Sjoerg   }
7437330f729Sjoerg };
7447330f729Sjoerg 
7457330f729Sjoerg template <> struct MappingTraits<FormatStyle::RawStringFormat> {
mappingllvm::yaml::MappingTraits7467330f729Sjoerg   static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
7477330f729Sjoerg     IO.mapOptional("Language", Format.Language);
7487330f729Sjoerg     IO.mapOptional("Delimiters", Format.Delimiters);
7497330f729Sjoerg     IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);
7507330f729Sjoerg     IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter);
7517330f729Sjoerg     IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);
7527330f729Sjoerg   }
7537330f729Sjoerg };
7547330f729Sjoerg 
755*e038c9c4Sjoerg template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {
mappingllvm::yaml::MappingTraits756*e038c9c4Sjoerg   static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
757*e038c9c4Sjoerg     // Transform the maximum to signed, to parse "-1" correctly
758*e038c9c4Sjoerg     int signedMaximum = static_cast<int>(Space.Maximum);
759*e038c9c4Sjoerg     IO.mapOptional("Minimum", Space.Minimum);
760*e038c9c4Sjoerg     IO.mapOptional("Maximum", signedMaximum);
761*e038c9c4Sjoerg     Space.Maximum = static_cast<unsigned>(signedMaximum);
762*e038c9c4Sjoerg 
763*e038c9c4Sjoerg     if (Space.Maximum != -1u) {
764*e038c9c4Sjoerg       Space.Minimum = std::min(Space.Minimum, Space.Maximum);
765*e038c9c4Sjoerg     }
766*e038c9c4Sjoerg   }
767*e038c9c4Sjoerg };
768*e038c9c4Sjoerg 
7697330f729Sjoerg // Allows to read vector<FormatStyle> while keeping default values.
7707330f729Sjoerg // IO.getContext() should contain a pointer to the FormatStyle structure, that
7717330f729Sjoerg // will be used to get default values for missing keys.
7727330f729Sjoerg // If the first element has no Language specified, it will be treated as the
7737330f729Sjoerg // default one for the following elements.
7747330f729Sjoerg template <> struct DocumentListTraits<std::vector<FormatStyle>> {
sizellvm::yaml::DocumentListTraits7757330f729Sjoerg   static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
7767330f729Sjoerg     return Seq.size();
7777330f729Sjoerg   }
elementllvm::yaml::DocumentListTraits7787330f729Sjoerg   static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq,
7797330f729Sjoerg                               size_t Index) {
7807330f729Sjoerg     if (Index >= Seq.size()) {
7817330f729Sjoerg       assert(Index == Seq.size());
7827330f729Sjoerg       FormatStyle Template;
7837330f729Sjoerg       if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
7847330f729Sjoerg         Template = Seq[0];
7857330f729Sjoerg       } else {
7867330f729Sjoerg         Template = *((const FormatStyle *)IO.getContext());
7877330f729Sjoerg         Template.Language = FormatStyle::LK_None;
7887330f729Sjoerg       }
7897330f729Sjoerg       Seq.resize(Index + 1, Template);
7907330f729Sjoerg     }
7917330f729Sjoerg     return Seq[Index];
7927330f729Sjoerg   }
7937330f729Sjoerg };
7947330f729Sjoerg } // namespace yaml
7957330f729Sjoerg } // namespace llvm
7967330f729Sjoerg 
7977330f729Sjoerg namespace clang {
7987330f729Sjoerg namespace format {
7997330f729Sjoerg 
getParseCategory()8007330f729Sjoerg const std::error_category &getParseCategory() {
8017330f729Sjoerg   static const ParseErrorCategory C{};
8027330f729Sjoerg   return C;
8037330f729Sjoerg }
make_error_code(ParseError e)8047330f729Sjoerg std::error_code make_error_code(ParseError e) {
8057330f729Sjoerg   return std::error_code(static_cast<int>(e), getParseCategory());
8067330f729Sjoerg }
8077330f729Sjoerg 
make_string_error(const llvm::Twine & Message)8087330f729Sjoerg inline llvm::Error make_string_error(const llvm::Twine &Message) {
8097330f729Sjoerg   return llvm::make_error<llvm::StringError>(Message,
8107330f729Sjoerg                                              llvm::inconvertibleErrorCode());
8117330f729Sjoerg }
8127330f729Sjoerg 
name() const8137330f729Sjoerg const char *ParseErrorCategory::name() const noexcept {
8147330f729Sjoerg   return "clang-format.parse_error";
8157330f729Sjoerg }
8167330f729Sjoerg 
message(int EV) const8177330f729Sjoerg std::string ParseErrorCategory::message(int EV) const {
8187330f729Sjoerg   switch (static_cast<ParseError>(EV)) {
8197330f729Sjoerg   case ParseError::Success:
8207330f729Sjoerg     return "Success";
8217330f729Sjoerg   case ParseError::Error:
8227330f729Sjoerg     return "Invalid argument";
8237330f729Sjoerg   case ParseError::Unsuitable:
8247330f729Sjoerg     return "Unsuitable";
825*e038c9c4Sjoerg   case ParseError::BinPackTrailingCommaConflict:
826*e038c9c4Sjoerg     return "trailing comma insertion cannot be used with bin packing";
8277330f729Sjoerg   }
8287330f729Sjoerg   llvm_unreachable("unexpected parse error");
8297330f729Sjoerg }
8307330f729Sjoerg 
expandPresets(const FormatStyle & Style)8317330f729Sjoerg static FormatStyle expandPresets(const FormatStyle &Style) {
8327330f729Sjoerg   if (Style.BreakBeforeBraces == FormatStyle::BS_Custom)
8337330f729Sjoerg     return Style;
8347330f729Sjoerg   FormatStyle Expanded = Style;
835*e038c9c4Sjoerg   Expanded.BraceWrapping = {/*AfterCaseLabel=*/false,
836*e038c9c4Sjoerg                             /*AfterClass=*/false,
837*e038c9c4Sjoerg                             /*AfterControlStatement=*/FormatStyle::BWACS_Never,
838*e038c9c4Sjoerg                             /*AfterEnum=*/false,
839*e038c9c4Sjoerg                             /*AfterFunction=*/false,
840*e038c9c4Sjoerg                             /*AfterNamespace=*/false,
841*e038c9c4Sjoerg                             /*AfterObjCDeclaration=*/false,
842*e038c9c4Sjoerg                             /*AfterStruct=*/false,
843*e038c9c4Sjoerg                             /*AfterUnion=*/false,
844*e038c9c4Sjoerg                             /*AfterExternBlock=*/false,
845*e038c9c4Sjoerg                             /*BeforeCatch=*/false,
846*e038c9c4Sjoerg                             /*BeforeElse=*/false,
847*e038c9c4Sjoerg                             /*BeforeLambdaBody=*/false,
848*e038c9c4Sjoerg                             /*BeforeWhile=*/false,
849*e038c9c4Sjoerg                             /*IndentBraces=*/false,
850*e038c9c4Sjoerg                             /*SplitEmptyFunction=*/true,
851*e038c9c4Sjoerg                             /*SplitEmptyRecord=*/true,
852*e038c9c4Sjoerg                             /*SplitEmptyNamespace=*/true};
8537330f729Sjoerg   switch (Style.BreakBeforeBraces) {
8547330f729Sjoerg   case FormatStyle::BS_Linux:
8557330f729Sjoerg     Expanded.BraceWrapping.AfterClass = true;
8567330f729Sjoerg     Expanded.BraceWrapping.AfterFunction = true;
8577330f729Sjoerg     Expanded.BraceWrapping.AfterNamespace = true;
8587330f729Sjoerg     break;
8597330f729Sjoerg   case FormatStyle::BS_Mozilla:
8607330f729Sjoerg     Expanded.BraceWrapping.AfterClass = true;
8617330f729Sjoerg     Expanded.BraceWrapping.AfterEnum = true;
8627330f729Sjoerg     Expanded.BraceWrapping.AfterFunction = true;
8637330f729Sjoerg     Expanded.BraceWrapping.AfterStruct = true;
8647330f729Sjoerg     Expanded.BraceWrapping.AfterUnion = true;
8657330f729Sjoerg     Expanded.BraceWrapping.AfterExternBlock = true;
866*e038c9c4Sjoerg     Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
8677330f729Sjoerg     Expanded.BraceWrapping.SplitEmptyFunction = true;
8687330f729Sjoerg     Expanded.BraceWrapping.SplitEmptyRecord = false;
8697330f729Sjoerg     break;
8707330f729Sjoerg   case FormatStyle::BS_Stroustrup:
8717330f729Sjoerg     Expanded.BraceWrapping.AfterFunction = true;
8727330f729Sjoerg     Expanded.BraceWrapping.BeforeCatch = true;
8737330f729Sjoerg     Expanded.BraceWrapping.BeforeElse = true;
8747330f729Sjoerg     break;
8757330f729Sjoerg   case FormatStyle::BS_Allman:
8767330f729Sjoerg     Expanded.BraceWrapping.AfterCaseLabel = true;
8777330f729Sjoerg     Expanded.BraceWrapping.AfterClass = true;
8787330f729Sjoerg     Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
8797330f729Sjoerg     Expanded.BraceWrapping.AfterEnum = true;
8807330f729Sjoerg     Expanded.BraceWrapping.AfterFunction = true;
8817330f729Sjoerg     Expanded.BraceWrapping.AfterNamespace = true;
8827330f729Sjoerg     Expanded.BraceWrapping.AfterObjCDeclaration = true;
8837330f729Sjoerg     Expanded.BraceWrapping.AfterStruct = true;
8847330f729Sjoerg     Expanded.BraceWrapping.AfterUnion = true;
8857330f729Sjoerg     Expanded.BraceWrapping.AfterExternBlock = true;
886*e038c9c4Sjoerg     Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
8877330f729Sjoerg     Expanded.BraceWrapping.BeforeCatch = true;
8887330f729Sjoerg     Expanded.BraceWrapping.BeforeElse = true;
889*e038c9c4Sjoerg     Expanded.BraceWrapping.BeforeLambdaBody = true;
8907330f729Sjoerg     break;
8917330f729Sjoerg   case FormatStyle::BS_Whitesmiths:
8927330f729Sjoerg     Expanded.BraceWrapping.AfterCaseLabel = true;
8937330f729Sjoerg     Expanded.BraceWrapping.AfterClass = true;
8947330f729Sjoerg     Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
8957330f729Sjoerg     Expanded.BraceWrapping.AfterEnum = true;
8967330f729Sjoerg     Expanded.BraceWrapping.AfterFunction = true;
8977330f729Sjoerg     Expanded.BraceWrapping.AfterNamespace = true;
8987330f729Sjoerg     Expanded.BraceWrapping.AfterObjCDeclaration = true;
8997330f729Sjoerg     Expanded.BraceWrapping.AfterStruct = true;
9007330f729Sjoerg     Expanded.BraceWrapping.AfterExternBlock = true;
901*e038c9c4Sjoerg     Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
9027330f729Sjoerg     Expanded.BraceWrapping.BeforeCatch = true;
9037330f729Sjoerg     Expanded.BraceWrapping.BeforeElse = true;
904*e038c9c4Sjoerg     Expanded.BraceWrapping.BeforeLambdaBody = true;
9057330f729Sjoerg     break;
9067330f729Sjoerg   case FormatStyle::BS_GNU:
907*e038c9c4Sjoerg     Expanded.BraceWrapping = {
908*e038c9c4Sjoerg         /*AfterCaseLabel=*/true,
909*e038c9c4Sjoerg         /*AfterClass=*/true,
910*e038c9c4Sjoerg         /*AfterControlStatement=*/FormatStyle::BWACS_Always,
911*e038c9c4Sjoerg         /*AfterEnum=*/true,
912*e038c9c4Sjoerg         /*AfterFunction=*/true,
913*e038c9c4Sjoerg         /*AfterNamespace=*/true,
914*e038c9c4Sjoerg         /*AfterObjCDeclaration=*/true,
915*e038c9c4Sjoerg         /*AfterStruct=*/true,
916*e038c9c4Sjoerg         /*AfterUnion=*/true,
917*e038c9c4Sjoerg         /*AfterExternBlock=*/true,
918*e038c9c4Sjoerg         /*BeforeCatch=*/true,
919*e038c9c4Sjoerg         /*BeforeElse=*/true,
920*e038c9c4Sjoerg         /*BeforeLambdaBody=*/false,
921*e038c9c4Sjoerg         /*BeforeWhile=*/true,
922*e038c9c4Sjoerg         /*IndentBraces=*/true,
923*e038c9c4Sjoerg         /*SplitEmptyFunction=*/true,
924*e038c9c4Sjoerg         /*SplitEmptyRecord=*/true,
925*e038c9c4Sjoerg         /*SplitEmptyNamespace=*/true};
926*e038c9c4Sjoerg     Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
9277330f729Sjoerg     break;
9287330f729Sjoerg   case FormatStyle::BS_WebKit:
9297330f729Sjoerg     Expanded.BraceWrapping.AfterFunction = true;
9307330f729Sjoerg     break;
9317330f729Sjoerg   default:
9327330f729Sjoerg     break;
9337330f729Sjoerg   }
9347330f729Sjoerg   return Expanded;
9357330f729Sjoerg }
9367330f729Sjoerg 
getLLVMStyle(FormatStyle::LanguageKind Language)9377330f729Sjoerg FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
9387330f729Sjoerg   FormatStyle LLVMStyle;
939*e038c9c4Sjoerg   LLVMStyle.InheritsParentConfig = false;
9407330f729Sjoerg   LLVMStyle.Language = Language;
9417330f729Sjoerg   LLVMStyle.AccessModifierOffset = -2;
9427330f729Sjoerg   LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
9437330f729Sjoerg   LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
944*e038c9c4Sjoerg   LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
9457330f729Sjoerg   LLVMStyle.AlignTrailingComments = true;
946*e038c9c4Sjoerg   LLVMStyle.AlignConsecutiveAssignments = FormatStyle::ACS_None;
947*e038c9c4Sjoerg   LLVMStyle.AlignConsecutiveBitFields = FormatStyle::ACS_None;
948*e038c9c4Sjoerg   LLVMStyle.AlignConsecutiveDeclarations = FormatStyle::ACS_None;
949*e038c9c4Sjoerg   LLVMStyle.AlignConsecutiveMacros = FormatStyle::ACS_None;
9507330f729Sjoerg   LLVMStyle.AllowAllArgumentsOnNextLine = true;
9517330f729Sjoerg   LLVMStyle.AllowAllConstructorInitializersOnNextLine = true;
9527330f729Sjoerg   LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
953*e038c9c4Sjoerg   LLVMStyle.AllowShortEnumsOnASingleLine = true;
9547330f729Sjoerg   LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
9557330f729Sjoerg   LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
9567330f729Sjoerg   LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
9577330f729Sjoerg   LLVMStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
9587330f729Sjoerg   LLVMStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_All;
9597330f729Sjoerg   LLVMStyle.AllowShortLoopsOnASingleLine = false;
9607330f729Sjoerg   LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
9617330f729Sjoerg   LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
9627330f729Sjoerg   LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
9637330f729Sjoerg   LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
964*e038c9c4Sjoerg   LLVMStyle.AttributeMacros.push_back("__capability");
9657330f729Sjoerg   LLVMStyle.BinPackArguments = true;
9667330f729Sjoerg   LLVMStyle.BinPackParameters = true;
9677330f729Sjoerg   LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
968*e038c9c4Sjoerg   LLVMStyle.BreakBeforeConceptDeclarations = true;
9697330f729Sjoerg   LLVMStyle.BreakBeforeTernaryOperators = true;
9707330f729Sjoerg   LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
971*e038c9c4Sjoerg   LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false,
972*e038c9c4Sjoerg                              /*AfterClass=*/false,
973*e038c9c4Sjoerg                              /*AfterControlStatement=*/FormatStyle::BWACS_Never,
974*e038c9c4Sjoerg                              /*AfterEnum=*/false,
975*e038c9c4Sjoerg                              /*AfterFunction=*/false,
976*e038c9c4Sjoerg                              /*AfterNamespace=*/false,
977*e038c9c4Sjoerg                              /*AfterObjCDeclaration=*/false,
978*e038c9c4Sjoerg                              /*AfterStruct=*/false,
979*e038c9c4Sjoerg                              /*AfterUnion=*/false,
980*e038c9c4Sjoerg                              /*AfterExternBlock=*/false,
981*e038c9c4Sjoerg                              /*BeforeCatch=*/false,
982*e038c9c4Sjoerg                              /*BeforeElse=*/false,
983*e038c9c4Sjoerg                              /*BeforeLambdaBody=*/false,
984*e038c9c4Sjoerg                              /*BeforeWhile=*/false,
985*e038c9c4Sjoerg                              /*IndentBraces=*/false,
986*e038c9c4Sjoerg                              /*SplitEmptyFunction=*/true,
987*e038c9c4Sjoerg                              /*SplitEmptyRecord=*/true,
988*e038c9c4Sjoerg                              /*SplitEmptyNamespace=*/true};
989*e038c9c4Sjoerg   LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
9907330f729Sjoerg   LLVMStyle.BreakAfterJavaFieldAnnotations = false;
9917330f729Sjoerg   LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
9927330f729Sjoerg   LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
9937330f729Sjoerg   LLVMStyle.BreakStringLiterals = true;
9947330f729Sjoerg   LLVMStyle.ColumnLimit = 80;
9957330f729Sjoerg   LLVMStyle.CommentPragmas = "^ IWYU pragma:";
9967330f729Sjoerg   LLVMStyle.CompactNamespaces = false;
9977330f729Sjoerg   LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false;
9987330f729Sjoerg   LLVMStyle.ConstructorInitializerIndentWidth = 4;
9997330f729Sjoerg   LLVMStyle.ContinuationIndentWidth = 4;
10007330f729Sjoerg   LLVMStyle.Cpp11BracedListStyle = true;
1001*e038c9c4Sjoerg   LLVMStyle.DeriveLineEnding = true;
10027330f729Sjoerg   LLVMStyle.DerivePointerAlignment = false;
1003*e038c9c4Sjoerg   LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never;
1004*e038c9c4Sjoerg   LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock;
10057330f729Sjoerg   LLVMStyle.ExperimentalAutoDetectBinPacking = false;
10067330f729Sjoerg   LLVMStyle.FixNamespaceComments = true;
10077330f729Sjoerg   LLVMStyle.ForEachMacros.push_back("foreach");
10087330f729Sjoerg   LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
10097330f729Sjoerg   LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
10107330f729Sjoerg   LLVMStyle.IncludeStyle.IncludeCategories = {
1011*e038c9c4Sjoerg       {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false},
1012*e038c9c4Sjoerg       {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},
1013*e038c9c4Sjoerg       {".*", 1, 0, false}};
10147330f729Sjoerg   LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
10157330f729Sjoerg   LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
1016*e038c9c4Sjoerg   LLVMStyle.IndentAccessModifiers = false;
10177330f729Sjoerg   LLVMStyle.IndentCaseLabels = false;
1018*e038c9c4Sjoerg   LLVMStyle.IndentCaseBlocks = false;
10197330f729Sjoerg   LLVMStyle.IndentGotoLabels = true;
10207330f729Sjoerg   LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
1021*e038c9c4Sjoerg   LLVMStyle.IndentRequires = false;
10227330f729Sjoerg   LLVMStyle.IndentWrappedFunctionNames = false;
10237330f729Sjoerg   LLVMStyle.IndentWidth = 2;
1024*e038c9c4Sjoerg   LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
10257330f729Sjoerg   LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
10267330f729Sjoerg   LLVMStyle.JavaScriptWrapImports = true;
10277330f729Sjoerg   LLVMStyle.TabWidth = 8;
10287330f729Sjoerg   LLVMStyle.MaxEmptyLinesToKeep = 1;
10297330f729Sjoerg   LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
10307330f729Sjoerg   LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
10317330f729Sjoerg   LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto;
10327330f729Sjoerg   LLVMStyle.ObjCBlockIndentWidth = 2;
1033*e038c9c4Sjoerg   LLVMStyle.ObjCBreakBeforeNestedBlockParam = true;
10347330f729Sjoerg   LLVMStyle.ObjCSpaceAfterProperty = false;
10357330f729Sjoerg   LLVMStyle.ObjCSpaceBeforeProtocolList = true;
10367330f729Sjoerg   LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
1037*e038c9c4Sjoerg   LLVMStyle.ShortNamespaceLines = 1;
10387330f729Sjoerg   LLVMStyle.SpacesBeforeTrailingComments = 1;
10397330f729Sjoerg   LLVMStyle.Standard = FormatStyle::LS_Latest;
1040*e038c9c4Sjoerg   LLVMStyle.UseCRLF = false;
10417330f729Sjoerg   LLVMStyle.UseTab = FormatStyle::UT_Never;
10427330f729Sjoerg   LLVMStyle.ReflowComments = true;
10437330f729Sjoerg   LLVMStyle.SpacesInParentheses = false;
10447330f729Sjoerg   LLVMStyle.SpacesInSquareBrackets = false;
10457330f729Sjoerg   LLVMStyle.SpaceInEmptyBlock = false;
10467330f729Sjoerg   LLVMStyle.SpaceInEmptyParentheses = false;
10477330f729Sjoerg   LLVMStyle.SpacesInContainerLiterals = true;
10487330f729Sjoerg   LLVMStyle.SpacesInCStyleCastParentheses = false;
1049*e038c9c4Sjoerg   LLVMStyle.SpacesInLineCommentPrefix = {/*Minimum=*/1, /*Maximum=*/-1u};
10507330f729Sjoerg   LLVMStyle.SpaceAfterCStyleCast = false;
10517330f729Sjoerg   LLVMStyle.SpaceAfterLogicalNot = false;
10527330f729Sjoerg   LLVMStyle.SpaceAfterTemplateKeyword = true;
1053*e038c9c4Sjoerg   LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
1054*e038c9c4Sjoerg   LLVMStyle.SpaceBeforeCaseColon = false;
10557330f729Sjoerg   LLVMStyle.SpaceBeforeCtorInitializerColon = true;
10567330f729Sjoerg   LLVMStyle.SpaceBeforeInheritanceColon = true;
10577330f729Sjoerg   LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
10587330f729Sjoerg   LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
10597330f729Sjoerg   LLVMStyle.SpaceBeforeAssignmentOperators = true;
10607330f729Sjoerg   LLVMStyle.SpaceBeforeCpp11BracedList = false;
1061*e038c9c4Sjoerg   LLVMStyle.SpaceBeforeSquareBrackets = false;
1062*e038c9c4Sjoerg   LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;
1063*e038c9c4Sjoerg   LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never;
1064*e038c9c4Sjoerg   LLVMStyle.SpacesInConditionalStatement = false;
10657330f729Sjoerg 
10667330f729Sjoerg   LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
10677330f729Sjoerg   LLVMStyle.PenaltyBreakComment = 300;
10687330f729Sjoerg   LLVMStyle.PenaltyBreakFirstLessLess = 120;
10697330f729Sjoerg   LLVMStyle.PenaltyBreakString = 1000;
10707330f729Sjoerg   LLVMStyle.PenaltyExcessCharacter = 1000000;
10717330f729Sjoerg   LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
10727330f729Sjoerg   LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
10737330f729Sjoerg   LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;
1074*e038c9c4Sjoerg   LLVMStyle.PenaltyIndentedWhitespace = 0;
10757330f729Sjoerg 
10767330f729Sjoerg   LLVMStyle.DisableFormat = false;
1077*e038c9c4Sjoerg   LLVMStyle.SortIncludes = FormatStyle::SI_CaseSensitive;
1078*e038c9c4Sjoerg   LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
10797330f729Sjoerg   LLVMStyle.SortUsingDeclarations = true;
1080*e038c9c4Sjoerg   LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");
10817330f729Sjoerg   LLVMStyle.StatementMacros.push_back("Q_UNUSED");
10827330f729Sjoerg   LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION");
1083*e038c9c4Sjoerg   LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE");
1084*e038c9c4Sjoerg   LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE");
1085*e038c9c4Sjoerg   LLVMStyle.WhitespaceSensitiveMacros.push_back("BOOST_PP_STRINGIZE");
1086*e038c9c4Sjoerg   LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME");
1087*e038c9c4Sjoerg   LLVMStyle.WhitespaceSensitiveMacros.push_back("CF_SWIFT_NAME");
10887330f729Sjoerg 
10897330f729Sjoerg   // Defaults that differ when not C++.
10907330f729Sjoerg   if (Language == FormatStyle::LK_TableGen) {
10917330f729Sjoerg     LLVMStyle.SpacesInContainerLiterals = false;
10927330f729Sjoerg   }
10937330f729Sjoerg 
10947330f729Sjoerg   return LLVMStyle;
10957330f729Sjoerg }
10967330f729Sjoerg 
getGoogleStyle(FormatStyle::LanguageKind Language)10977330f729Sjoerg FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
10987330f729Sjoerg   if (Language == FormatStyle::LK_TextProto) {
10997330f729Sjoerg     FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto);
11007330f729Sjoerg     GoogleStyle.Language = FormatStyle::LK_TextProto;
11017330f729Sjoerg 
11027330f729Sjoerg     return GoogleStyle;
11037330f729Sjoerg   }
11047330f729Sjoerg 
11057330f729Sjoerg   FormatStyle GoogleStyle = getLLVMStyle(Language);
11067330f729Sjoerg 
11077330f729Sjoerg   GoogleStyle.AccessModifierOffset = -1;
11087330f729Sjoerg   GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left;
11097330f729Sjoerg   GoogleStyle.AllowShortIfStatementsOnASingleLine =
11107330f729Sjoerg       FormatStyle::SIS_WithoutElse;
11117330f729Sjoerg   GoogleStyle.AllowShortLoopsOnASingleLine = true;
11127330f729Sjoerg   GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
11137330f729Sjoerg   GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
11147330f729Sjoerg   GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
11157330f729Sjoerg   GoogleStyle.DerivePointerAlignment = true;
1116*e038c9c4Sjoerg   GoogleStyle.IncludeStyle.IncludeCategories = {{"^<ext/.*\\.h>", 2, 0, false},
1117*e038c9c4Sjoerg                                                 {"^<.*\\.h>", 1, 0, false},
1118*e038c9c4Sjoerg                                                 {"^<.*", 2, 0, false},
1119*e038c9c4Sjoerg                                                 {".*", 3, 0, false}};
11207330f729Sjoerg   GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
11217330f729Sjoerg   GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
11227330f729Sjoerg   GoogleStyle.IndentCaseLabels = true;
11237330f729Sjoerg   GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
11247330f729Sjoerg   GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never;
11257330f729Sjoerg   GoogleStyle.ObjCSpaceAfterProperty = false;
11267330f729Sjoerg   GoogleStyle.ObjCSpaceBeforeProtocolList = true;
11277330f729Sjoerg   GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;
11287330f729Sjoerg   GoogleStyle.RawStringFormats = {
11297330f729Sjoerg       {
11307330f729Sjoerg           FormatStyle::LK_Cpp,
11317330f729Sjoerg           /*Delimiters=*/
11327330f729Sjoerg           {
11337330f729Sjoerg               "cc",
11347330f729Sjoerg               "CC",
11357330f729Sjoerg               "cpp",
11367330f729Sjoerg               "Cpp",
11377330f729Sjoerg               "CPP",
11387330f729Sjoerg               "c++",
11397330f729Sjoerg               "C++",
11407330f729Sjoerg           },
11417330f729Sjoerg           /*EnclosingFunctionNames=*/
11427330f729Sjoerg           {},
11437330f729Sjoerg           /*CanonicalDelimiter=*/"",
11447330f729Sjoerg           /*BasedOnStyle=*/"google",
11457330f729Sjoerg       },
11467330f729Sjoerg       {
11477330f729Sjoerg           FormatStyle::LK_TextProto,
11487330f729Sjoerg           /*Delimiters=*/
11497330f729Sjoerg           {
11507330f729Sjoerg               "pb",
11517330f729Sjoerg               "PB",
11527330f729Sjoerg               "proto",
11537330f729Sjoerg               "PROTO",
11547330f729Sjoerg           },
11557330f729Sjoerg           /*EnclosingFunctionNames=*/
11567330f729Sjoerg           {
11577330f729Sjoerg               "EqualsProto",
11587330f729Sjoerg               "EquivToProto",
11597330f729Sjoerg               "PARSE_PARTIAL_TEXT_PROTO",
11607330f729Sjoerg               "PARSE_TEST_PROTO",
11617330f729Sjoerg               "PARSE_TEXT_PROTO",
11627330f729Sjoerg               "ParseTextOrDie",
11637330f729Sjoerg               "ParseTextProtoOrDie",
1164*e038c9c4Sjoerg               "ParseTestProto",
1165*e038c9c4Sjoerg               "ParsePartialTestProto",
11667330f729Sjoerg           },
1167*e038c9c4Sjoerg           /*CanonicalDelimiter=*/"pb",
11687330f729Sjoerg           /*BasedOnStyle=*/"google",
11697330f729Sjoerg       },
11707330f729Sjoerg   };
11717330f729Sjoerg   GoogleStyle.SpacesBeforeTrailingComments = 2;
11727330f729Sjoerg   GoogleStyle.Standard = FormatStyle::LS_Auto;
11737330f729Sjoerg 
11747330f729Sjoerg   GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
11757330f729Sjoerg   GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;
11767330f729Sjoerg 
11777330f729Sjoerg   if (Language == FormatStyle::LK_Java) {
11787330f729Sjoerg     GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
1179*e038c9c4Sjoerg     GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
11807330f729Sjoerg     GoogleStyle.AlignTrailingComments = false;
11817330f729Sjoerg     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
11827330f729Sjoerg     GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
11837330f729Sjoerg     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
11847330f729Sjoerg     GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
11857330f729Sjoerg     GoogleStyle.ColumnLimit = 100;
11867330f729Sjoerg     GoogleStyle.SpaceAfterCStyleCast = true;
11877330f729Sjoerg     GoogleStyle.SpacesBeforeTrailingComments = 1;
11887330f729Sjoerg   } else if (Language == FormatStyle::LK_JavaScript) {
11897330f729Sjoerg     GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
1190*e038c9c4Sjoerg     GoogleStyle.AlignOperands = FormatStyle::OAS_DontAlign;
11917330f729Sjoerg     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
1192*e038c9c4Sjoerg     // TODO: still under discussion whether to switch to SLS_All.
1193*e038c9c4Sjoerg     GoogleStyle.AllowShortLambdasOnASingleLine = FormatStyle::SLS_Empty;
11947330f729Sjoerg     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
11957330f729Sjoerg     GoogleStyle.BreakBeforeTernaryOperators = false;
1196*e038c9c4Sjoerg     // taze:, triple slash directives (`/// <...`), tslint:, and @see, which is
1197*e038c9c4Sjoerg     // commonly followed by overlong URLs.
1198*e038c9c4Sjoerg     GoogleStyle.CommentPragmas = "(taze:|^/[ \t]*<|tslint:|@see)";
1199*e038c9c4Sjoerg     // TODO: enable once decided, in particular re disabling bin packing.
1200*e038c9c4Sjoerg     // https://google.github.io/styleguide/jsguide.html#features-arrays-trailing-comma
1201*e038c9c4Sjoerg     // GoogleStyle.InsertTrailingCommas = FormatStyle::TCS_Wrapped;
12027330f729Sjoerg     GoogleStyle.MaxEmptyLinesToKeep = 3;
12037330f729Sjoerg     GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
12047330f729Sjoerg     GoogleStyle.SpacesInContainerLiterals = false;
12057330f729Sjoerg     GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single;
12067330f729Sjoerg     GoogleStyle.JavaScriptWrapImports = false;
12077330f729Sjoerg   } else if (Language == FormatStyle::LK_Proto) {
12087330f729Sjoerg     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
12097330f729Sjoerg     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
12107330f729Sjoerg     GoogleStyle.SpacesInContainerLiterals = false;
12117330f729Sjoerg     GoogleStyle.Cpp11BracedListStyle = false;
12127330f729Sjoerg     // This affects protocol buffer options specifications and text protos.
12137330f729Sjoerg     // Text protos are currently mostly formatted inside C++ raw string literals
12147330f729Sjoerg     // and often the current breaking behavior of string literals is not
12157330f729Sjoerg     // beneficial there. Investigate turning this on once proper string reflow
12167330f729Sjoerg     // has been implemented.
12177330f729Sjoerg     GoogleStyle.BreakStringLiterals = false;
12187330f729Sjoerg   } else if (Language == FormatStyle::LK_ObjC) {
12197330f729Sjoerg     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
12207330f729Sjoerg     GoogleStyle.ColumnLimit = 100;
12217330f729Sjoerg     // "Regroup" doesn't work well for ObjC yet (main header heuristic,
12227330f729Sjoerg     // relationship between ObjC standard library headers and other heades,
12237330f729Sjoerg     // #imports, etc.)
12247330f729Sjoerg     GoogleStyle.IncludeStyle.IncludeBlocks =
12257330f729Sjoerg         tooling::IncludeStyle::IBS_Preserve;
1226*e038c9c4Sjoerg   } else if (Language == FormatStyle::LK_CSharp) {
1227*e038c9c4Sjoerg     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
1228*e038c9c4Sjoerg     GoogleStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
1229*e038c9c4Sjoerg     GoogleStyle.BreakStringLiterals = false;
1230*e038c9c4Sjoerg     GoogleStyle.ColumnLimit = 100;
1231*e038c9c4Sjoerg     GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
12327330f729Sjoerg   }
12337330f729Sjoerg 
12347330f729Sjoerg   return GoogleStyle;
12357330f729Sjoerg }
12367330f729Sjoerg 
getChromiumStyle(FormatStyle::LanguageKind Language)12377330f729Sjoerg FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
12387330f729Sjoerg   FormatStyle ChromiumStyle = getGoogleStyle(Language);
12397330f729Sjoerg 
12407330f729Sjoerg   // Disable include reordering across blocks in Chromium code.
12417330f729Sjoerg   // - clang-format tries to detect that foo.h is the "main" header for
12427330f729Sjoerg   //   foo.cc and foo_unittest.cc via IncludeIsMainRegex. However, Chromium
12437330f729Sjoerg   //   uses many other suffices (_win.cc, _mac.mm, _posix.cc, _browsertest.cc,
12447330f729Sjoerg   //   _private.cc, _impl.cc etc) in different permutations
12457330f729Sjoerg   //   (_win_browsertest.cc) so disable this until IncludeIsMainRegex has a
12467330f729Sjoerg   //   better default for Chromium code.
12477330f729Sjoerg   // - The default for .cc and .mm files is different (r357695) for Google style
12487330f729Sjoerg   //   for the same reason. The plan is to unify this again once the main
12497330f729Sjoerg   //   header detection works for Google's ObjC code, but this hasn't happened
12507330f729Sjoerg   //   yet. Since Chromium has some ObjC code, switching Chromium is blocked
12517330f729Sjoerg   //   on that.
12527330f729Sjoerg   // - Finally, "If include reordering is harmful, put things in different
12537330f729Sjoerg   //   blocks to prevent it" has been a recommendation for a long time that
12547330f729Sjoerg   //   people are used to. We'll need a dev education push to change this to
12557330f729Sjoerg   //   "If include reordering is harmful, put things in a different block and
12567330f729Sjoerg   //   _prepend that with a comment_ to prevent it" before changing behavior.
12577330f729Sjoerg   ChromiumStyle.IncludeStyle.IncludeBlocks =
12587330f729Sjoerg       tooling::IncludeStyle::IBS_Preserve;
12597330f729Sjoerg 
12607330f729Sjoerg   if (Language == FormatStyle::LK_Java) {
12617330f729Sjoerg     ChromiumStyle.AllowShortIfStatementsOnASingleLine =
12627330f729Sjoerg         FormatStyle::SIS_WithoutElse;
12637330f729Sjoerg     ChromiumStyle.BreakAfterJavaFieldAnnotations = true;
12647330f729Sjoerg     ChromiumStyle.ContinuationIndentWidth = 8;
12657330f729Sjoerg     ChromiumStyle.IndentWidth = 4;
12667330f729Sjoerg     // See styleguide for import groups:
12677330f729Sjoerg     // https://chromium.googlesource.com/chromium/src/+/master/styleguide/java/java.md#Import-Order
12687330f729Sjoerg     ChromiumStyle.JavaImportGroups = {
12697330f729Sjoerg         "android",
12707330f729Sjoerg         "androidx",
12717330f729Sjoerg         "com",
12727330f729Sjoerg         "dalvik",
12737330f729Sjoerg         "junit",
12747330f729Sjoerg         "org",
12757330f729Sjoerg         "com.google.android.apps.chrome",
12767330f729Sjoerg         "org.chromium",
12777330f729Sjoerg         "java",
12787330f729Sjoerg         "javax",
12797330f729Sjoerg     };
1280*e038c9c4Sjoerg     ChromiumStyle.SortIncludes = FormatStyle::SI_CaseSensitive;
12817330f729Sjoerg   } else if (Language == FormatStyle::LK_JavaScript) {
12827330f729Sjoerg     ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
12837330f729Sjoerg     ChromiumStyle.AllowShortLoopsOnASingleLine = false;
12847330f729Sjoerg   } else {
12857330f729Sjoerg     ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
12867330f729Sjoerg     ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
12877330f729Sjoerg     ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
12887330f729Sjoerg     ChromiumStyle.AllowShortLoopsOnASingleLine = false;
12897330f729Sjoerg     ChromiumStyle.BinPackParameters = false;
12907330f729Sjoerg     ChromiumStyle.DerivePointerAlignment = false;
12917330f729Sjoerg     if (Language == FormatStyle::LK_ObjC)
12927330f729Sjoerg       ChromiumStyle.ColumnLimit = 80;
12937330f729Sjoerg   }
12947330f729Sjoerg   return ChromiumStyle;
12957330f729Sjoerg }
12967330f729Sjoerg 
getMozillaStyle()12977330f729Sjoerg FormatStyle getMozillaStyle() {
12987330f729Sjoerg   FormatStyle MozillaStyle = getLLVMStyle();
12997330f729Sjoerg   MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
13007330f729Sjoerg   MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
13017330f729Sjoerg   MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel;
13027330f729Sjoerg   MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
13037330f729Sjoerg       FormatStyle::DRTBS_TopLevel;
13047330f729Sjoerg   MozillaStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
13057330f729Sjoerg   MozillaStyle.BinPackParameters = false;
13067330f729Sjoerg   MozillaStyle.BinPackArguments = false;
13077330f729Sjoerg   MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
13087330f729Sjoerg   MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
13097330f729Sjoerg   MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
13107330f729Sjoerg   MozillaStyle.ConstructorInitializerIndentWidth = 2;
13117330f729Sjoerg   MozillaStyle.ContinuationIndentWidth = 2;
13127330f729Sjoerg   MozillaStyle.Cpp11BracedListStyle = false;
13137330f729Sjoerg   MozillaStyle.FixNamespaceComments = false;
13147330f729Sjoerg   MozillaStyle.IndentCaseLabels = true;
13157330f729Sjoerg   MozillaStyle.ObjCSpaceAfterProperty = true;
13167330f729Sjoerg   MozillaStyle.ObjCSpaceBeforeProtocolList = false;
13177330f729Sjoerg   MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
13187330f729Sjoerg   MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
13197330f729Sjoerg   MozillaStyle.SpaceAfterTemplateKeyword = false;
13207330f729Sjoerg   return MozillaStyle;
13217330f729Sjoerg }
13227330f729Sjoerg 
getWebKitStyle()13237330f729Sjoerg FormatStyle getWebKitStyle() {
13247330f729Sjoerg   FormatStyle Style = getLLVMStyle();
13257330f729Sjoerg   Style.AccessModifierOffset = -4;
13267330f729Sjoerg   Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
1327*e038c9c4Sjoerg   Style.AlignOperands = FormatStyle::OAS_DontAlign;
13287330f729Sjoerg   Style.AlignTrailingComments = false;
13297330f729Sjoerg   Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;
13307330f729Sjoerg   Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
13317330f729Sjoerg   Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
13327330f729Sjoerg   Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
13337330f729Sjoerg   Style.Cpp11BracedListStyle = false;
13347330f729Sjoerg   Style.ColumnLimit = 0;
13357330f729Sjoerg   Style.FixNamespaceComments = false;
13367330f729Sjoerg   Style.IndentWidth = 4;
13377330f729Sjoerg   Style.NamespaceIndentation = FormatStyle::NI_Inner;
13387330f729Sjoerg   Style.ObjCBlockIndentWidth = 4;
13397330f729Sjoerg   Style.ObjCSpaceAfterProperty = true;
13407330f729Sjoerg   Style.PointerAlignment = FormatStyle::PAS_Left;
13417330f729Sjoerg   Style.SpaceBeforeCpp11BracedList = true;
13427330f729Sjoerg   Style.SpaceInEmptyBlock = true;
13437330f729Sjoerg   return Style;
13447330f729Sjoerg }
13457330f729Sjoerg 
getGNUStyle()13467330f729Sjoerg FormatStyle getGNUStyle() {
13477330f729Sjoerg   FormatStyle Style = getLLVMStyle();
13487330f729Sjoerg   Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
13497330f729Sjoerg   Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
13507330f729Sjoerg   Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
13517330f729Sjoerg   Style.BreakBeforeBraces = FormatStyle::BS_GNU;
13527330f729Sjoerg   Style.BreakBeforeTernaryOperators = true;
13537330f729Sjoerg   Style.Cpp11BracedListStyle = false;
13547330f729Sjoerg   Style.ColumnLimit = 79;
13557330f729Sjoerg   Style.FixNamespaceComments = false;
13567330f729Sjoerg   Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
13577330f729Sjoerg   Style.Standard = FormatStyle::LS_Cpp03;
13587330f729Sjoerg   return Style;
13597330f729Sjoerg }
13607330f729Sjoerg 
getMicrosoftStyle(FormatStyle::LanguageKind Language)13617330f729Sjoerg FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) {
13627330f729Sjoerg   FormatStyle Style = getLLVMStyle(Language);
13637330f729Sjoerg   Style.ColumnLimit = 120;
13647330f729Sjoerg   Style.TabWidth = 4;
13657330f729Sjoerg   Style.IndentWidth = 4;
13667330f729Sjoerg   Style.UseTab = FormatStyle::UT_Never;
13677330f729Sjoerg   Style.BreakBeforeBraces = FormatStyle::BS_Custom;
13687330f729Sjoerg   Style.BraceWrapping.AfterClass = true;
13697330f729Sjoerg   Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always;
13707330f729Sjoerg   Style.BraceWrapping.AfterEnum = true;
13717330f729Sjoerg   Style.BraceWrapping.AfterFunction = true;
13727330f729Sjoerg   Style.BraceWrapping.AfterNamespace = true;
13737330f729Sjoerg   Style.BraceWrapping.AfterObjCDeclaration = true;
13747330f729Sjoerg   Style.BraceWrapping.AfterStruct = true;
13757330f729Sjoerg   Style.BraceWrapping.AfterExternBlock = true;
1376*e038c9c4Sjoerg   Style.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
13777330f729Sjoerg   Style.BraceWrapping.BeforeCatch = true;
13787330f729Sjoerg   Style.BraceWrapping.BeforeElse = true;
1379*e038c9c4Sjoerg   Style.BraceWrapping.BeforeWhile = false;
13807330f729Sjoerg   Style.PenaltyReturnTypeOnItsOwnLine = 1000;
1381*e038c9c4Sjoerg   Style.AllowShortEnumsOnASingleLine = false;
13827330f729Sjoerg   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
13837330f729Sjoerg   Style.AllowShortCaseLabelsOnASingleLine = false;
13847330f729Sjoerg   Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
13857330f729Sjoerg   Style.AllowShortLoopsOnASingleLine = false;
13867330f729Sjoerg   Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
13877330f729Sjoerg   Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
13887330f729Sjoerg   return Style;
13897330f729Sjoerg }
13907330f729Sjoerg 
getNoStyle()13917330f729Sjoerg FormatStyle getNoStyle() {
13927330f729Sjoerg   FormatStyle NoStyle = getLLVMStyle();
13937330f729Sjoerg   NoStyle.DisableFormat = true;
1394*e038c9c4Sjoerg   NoStyle.SortIncludes = FormatStyle::SI_Never;
13957330f729Sjoerg   NoStyle.SortUsingDeclarations = false;
13967330f729Sjoerg   return NoStyle;
13977330f729Sjoerg }
13987330f729Sjoerg 
getPredefinedStyle(StringRef Name,FormatStyle::LanguageKind Language,FormatStyle * Style)13997330f729Sjoerg bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
14007330f729Sjoerg                         FormatStyle *Style) {
14017330f729Sjoerg   if (Name.equals_lower("llvm")) {
14027330f729Sjoerg     *Style = getLLVMStyle(Language);
14037330f729Sjoerg   } else if (Name.equals_lower("chromium")) {
14047330f729Sjoerg     *Style = getChromiumStyle(Language);
14057330f729Sjoerg   } else if (Name.equals_lower("mozilla")) {
14067330f729Sjoerg     *Style = getMozillaStyle();
14077330f729Sjoerg   } else if (Name.equals_lower("google")) {
14087330f729Sjoerg     *Style = getGoogleStyle(Language);
14097330f729Sjoerg   } else if (Name.equals_lower("webkit")) {
14107330f729Sjoerg     *Style = getWebKitStyle();
14117330f729Sjoerg   } else if (Name.equals_lower("gnu")) {
14127330f729Sjoerg     *Style = getGNUStyle();
14137330f729Sjoerg   } else if (Name.equals_lower("microsoft")) {
14147330f729Sjoerg     *Style = getMicrosoftStyle(Language);
14157330f729Sjoerg   } else if (Name.equals_lower("none")) {
14167330f729Sjoerg     *Style = getNoStyle();
1417*e038c9c4Sjoerg   } else if (Name.equals_lower("inheritparentconfig")) {
1418*e038c9c4Sjoerg     Style->InheritsParentConfig = true;
14197330f729Sjoerg   } else {
14207330f729Sjoerg     return false;
14217330f729Sjoerg   }
14227330f729Sjoerg 
14237330f729Sjoerg   Style->Language = Language;
14247330f729Sjoerg   return true;
14257330f729Sjoerg }
14267330f729Sjoerg 
parseConfiguration(llvm::MemoryBufferRef Config,FormatStyle * Style,bool AllowUnknownOptions,llvm::SourceMgr::DiagHandlerTy DiagHandler,void * DiagHandlerCtxt)1427*e038c9c4Sjoerg std::error_code parseConfiguration(llvm::MemoryBufferRef Config,
1428*e038c9c4Sjoerg                                    FormatStyle *Style, bool AllowUnknownOptions,
1429*e038c9c4Sjoerg                                    llvm::SourceMgr::DiagHandlerTy DiagHandler,
1430*e038c9c4Sjoerg                                    void *DiagHandlerCtxt) {
14317330f729Sjoerg   assert(Style);
14327330f729Sjoerg   FormatStyle::LanguageKind Language = Style->Language;
14337330f729Sjoerg   assert(Language != FormatStyle::LK_None);
1434*e038c9c4Sjoerg   if (Config.getBuffer().trim().empty())
14357330f729Sjoerg     return make_error_code(ParseError::Error);
14367330f729Sjoerg   Style->StyleSet.Clear();
14377330f729Sjoerg   std::vector<FormatStyle> Styles;
1438*e038c9c4Sjoerg   llvm::yaml::Input Input(Config, /*Ctxt=*/nullptr, DiagHandler,
1439*e038c9c4Sjoerg                           DiagHandlerCtxt);
14407330f729Sjoerg   // DocumentListTraits<vector<FormatStyle>> uses the context to get default
14417330f729Sjoerg   // values for the fields, keys for which are missing from the configuration.
14427330f729Sjoerg   // Mapping also uses the context to get the language to find the correct
14437330f729Sjoerg   // base style.
14447330f729Sjoerg   Input.setContext(Style);
1445*e038c9c4Sjoerg   Input.setAllowUnknownKeys(AllowUnknownOptions);
14467330f729Sjoerg   Input >> Styles;
14477330f729Sjoerg   if (Input.error())
14487330f729Sjoerg     return Input.error();
14497330f729Sjoerg 
14507330f729Sjoerg   for (unsigned i = 0; i < Styles.size(); ++i) {
14517330f729Sjoerg     // Ensures that only the first configuration can skip the Language option.
14527330f729Sjoerg     if (Styles[i].Language == FormatStyle::LK_None && i != 0)
14537330f729Sjoerg       return make_error_code(ParseError::Error);
14547330f729Sjoerg     // Ensure that each language is configured at most once.
14557330f729Sjoerg     for (unsigned j = 0; j < i; ++j) {
14567330f729Sjoerg       if (Styles[i].Language == Styles[j].Language) {
14577330f729Sjoerg         LLVM_DEBUG(llvm::dbgs()
14587330f729Sjoerg                    << "Duplicate languages in the config file on positions "
14597330f729Sjoerg                    << j << " and " << i << "\n");
14607330f729Sjoerg         return make_error_code(ParseError::Error);
14617330f729Sjoerg       }
14627330f729Sjoerg     }
14637330f729Sjoerg   }
14647330f729Sjoerg   // Look for a suitable configuration starting from the end, so we can
14657330f729Sjoerg   // find the configuration for the specific language first, and the default
14667330f729Sjoerg   // configuration (which can only be at slot 0) after it.
14677330f729Sjoerg   FormatStyle::FormatStyleSet StyleSet;
14687330f729Sjoerg   bool LanguageFound = false;
14697330f729Sjoerg   for (int i = Styles.size() - 1; i >= 0; --i) {
14707330f729Sjoerg     if (Styles[i].Language != FormatStyle::LK_None)
14717330f729Sjoerg       StyleSet.Add(Styles[i]);
14727330f729Sjoerg     if (Styles[i].Language == Language)
14737330f729Sjoerg       LanguageFound = true;
14747330f729Sjoerg   }
14757330f729Sjoerg   if (!LanguageFound) {
14767330f729Sjoerg     if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None)
14777330f729Sjoerg       return make_error_code(ParseError::Unsuitable);
14787330f729Sjoerg     FormatStyle DefaultStyle = Styles[0];
14797330f729Sjoerg     DefaultStyle.Language = Language;
14807330f729Sjoerg     StyleSet.Add(std::move(DefaultStyle));
14817330f729Sjoerg   }
14827330f729Sjoerg   *Style = *StyleSet.Get(Language);
1483*e038c9c4Sjoerg   if (Style->InsertTrailingCommas != FormatStyle::TCS_None &&
1484*e038c9c4Sjoerg       Style->BinPackArguments) {
1485*e038c9c4Sjoerg     // See comment on FormatStyle::TSC_Wrapped.
1486*e038c9c4Sjoerg     return make_error_code(ParseError::BinPackTrailingCommaConflict);
1487*e038c9c4Sjoerg   }
14887330f729Sjoerg   return make_error_code(ParseError::Success);
14897330f729Sjoerg }
14907330f729Sjoerg 
configurationAsText(const FormatStyle & Style)14917330f729Sjoerg std::string configurationAsText(const FormatStyle &Style) {
14927330f729Sjoerg   std::string Text;
14937330f729Sjoerg   llvm::raw_string_ostream Stream(Text);
14947330f729Sjoerg   llvm::yaml::Output Output(Stream);
14957330f729Sjoerg   // We use the same mapping method for input and output, so we need a non-const
14967330f729Sjoerg   // reference here.
14977330f729Sjoerg   FormatStyle NonConstStyle = expandPresets(Style);
14987330f729Sjoerg   Output << NonConstStyle;
14997330f729Sjoerg   return Stream.str();
15007330f729Sjoerg }
15017330f729Sjoerg 
15027330f729Sjoerg llvm::Optional<FormatStyle>
Get(FormatStyle::LanguageKind Language) const15037330f729Sjoerg FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {
15047330f729Sjoerg   if (!Styles)
15057330f729Sjoerg     return None;
15067330f729Sjoerg   auto It = Styles->find(Language);
15077330f729Sjoerg   if (It == Styles->end())
15087330f729Sjoerg     return None;
15097330f729Sjoerg   FormatStyle Style = It->second;
15107330f729Sjoerg   Style.StyleSet = *this;
15117330f729Sjoerg   return Style;
15127330f729Sjoerg }
15137330f729Sjoerg 
Add(FormatStyle Style)15147330f729Sjoerg void FormatStyle::FormatStyleSet::Add(FormatStyle Style) {
15157330f729Sjoerg   assert(Style.Language != LK_None &&
15167330f729Sjoerg          "Cannot add a style for LK_None to a StyleSet");
15177330f729Sjoerg   assert(
15187330f729Sjoerg       !Style.StyleSet.Styles &&
15197330f729Sjoerg       "Cannot add a style associated with an existing StyleSet to a StyleSet");
15207330f729Sjoerg   if (!Styles)
15217330f729Sjoerg     Styles = std::make_shared<MapType>();
15227330f729Sjoerg   (*Styles)[Style.Language] = std::move(Style);
15237330f729Sjoerg }
15247330f729Sjoerg 
Clear()15257330f729Sjoerg void FormatStyle::FormatStyleSet::Clear() { Styles.reset(); }
15267330f729Sjoerg 
15277330f729Sjoerg llvm::Optional<FormatStyle>
GetLanguageStyle(FormatStyle::LanguageKind Language) const15287330f729Sjoerg FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {
15297330f729Sjoerg   return StyleSet.Get(Language);
15307330f729Sjoerg }
15317330f729Sjoerg 
15327330f729Sjoerg namespace {
15337330f729Sjoerg 
15347330f729Sjoerg class JavaScriptRequoter : public TokenAnalyzer {
15357330f729Sjoerg public:
JavaScriptRequoter(const Environment & Env,const FormatStyle & Style)15367330f729Sjoerg   JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)
15377330f729Sjoerg       : TokenAnalyzer(Env, Style) {}
15387330f729Sjoerg 
15397330f729Sjoerg   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)15407330f729Sjoerg   analyze(TokenAnnotator &Annotator,
15417330f729Sjoerg           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
15427330f729Sjoerg           FormatTokenLexer &Tokens) override {
15437330f729Sjoerg     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
15447330f729Sjoerg     tooling::Replacements Result;
15457330f729Sjoerg     requoteJSStringLiteral(AnnotatedLines, Result);
15467330f729Sjoerg     return {Result, 0};
15477330f729Sjoerg   }
15487330f729Sjoerg 
15497330f729Sjoerg private:
15507330f729Sjoerg   // Replaces double/single-quoted string literal as appropriate, re-escaping
15517330f729Sjoerg   // the contents in the process.
requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine * > & Lines,tooling::Replacements & Result)15527330f729Sjoerg   void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
15537330f729Sjoerg                               tooling::Replacements &Result) {
15547330f729Sjoerg     for (AnnotatedLine *Line : Lines) {
15557330f729Sjoerg       requoteJSStringLiteral(Line->Children, Result);
15567330f729Sjoerg       if (!Line->Affected)
15577330f729Sjoerg         continue;
15587330f729Sjoerg       for (FormatToken *FormatTok = Line->First; FormatTok;
15597330f729Sjoerg            FormatTok = FormatTok->Next) {
15607330f729Sjoerg         StringRef Input = FormatTok->TokenText;
15617330f729Sjoerg         if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
15627330f729Sjoerg             // NB: testing for not starting with a double quote to avoid
15637330f729Sjoerg             // breaking `template strings`.
15647330f729Sjoerg             (Style.JavaScriptQuotes == FormatStyle::JSQS_Single &&
15657330f729Sjoerg              !Input.startswith("\"")) ||
15667330f729Sjoerg             (Style.JavaScriptQuotes == FormatStyle::JSQS_Double &&
15677330f729Sjoerg              !Input.startswith("\'")))
15687330f729Sjoerg           continue;
15697330f729Sjoerg 
15707330f729Sjoerg         // Change start and end quote.
15717330f729Sjoerg         bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single;
15727330f729Sjoerg         SourceLocation Start = FormatTok->Tok.getLocation();
15737330f729Sjoerg         auto Replace = [&](SourceLocation Start, unsigned Length,
15747330f729Sjoerg                            StringRef ReplacementText) {
15757330f729Sjoerg           auto Err = Result.add(tooling::Replacement(
15767330f729Sjoerg               Env.getSourceManager(), Start, Length, ReplacementText));
15777330f729Sjoerg           // FIXME: handle error. For now, print error message and skip the
15787330f729Sjoerg           // replacement for release version.
15797330f729Sjoerg           if (Err) {
15807330f729Sjoerg             llvm::errs() << llvm::toString(std::move(Err)) << "\n";
15817330f729Sjoerg             assert(false);
15827330f729Sjoerg           }
15837330f729Sjoerg         };
15847330f729Sjoerg         Replace(Start, 1, IsSingle ? "'" : "\"");
15857330f729Sjoerg         Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
15867330f729Sjoerg                 IsSingle ? "'" : "\"");
15877330f729Sjoerg 
15887330f729Sjoerg         // Escape internal quotes.
15897330f729Sjoerg         bool Escaped = false;
15907330f729Sjoerg         for (size_t i = 1; i < Input.size() - 1; i++) {
15917330f729Sjoerg           switch (Input[i]) {
15927330f729Sjoerg           case '\\':
15937330f729Sjoerg             if (!Escaped && i + 1 < Input.size() &&
15947330f729Sjoerg                 ((IsSingle && Input[i + 1] == '"') ||
15957330f729Sjoerg                  (!IsSingle && Input[i + 1] == '\''))) {
15967330f729Sjoerg               // Remove this \, it's escaping a " or ' that no longer needs
15977330f729Sjoerg               // escaping
15987330f729Sjoerg               Replace(Start.getLocWithOffset(i), 1, "");
15997330f729Sjoerg               continue;
16007330f729Sjoerg             }
16017330f729Sjoerg             Escaped = !Escaped;
16027330f729Sjoerg             break;
16037330f729Sjoerg           case '\"':
16047330f729Sjoerg           case '\'':
16057330f729Sjoerg             if (!Escaped && IsSingle == (Input[i] == '\'')) {
16067330f729Sjoerg               // Escape the quote.
16077330f729Sjoerg               Replace(Start.getLocWithOffset(i), 0, "\\");
16087330f729Sjoerg             }
16097330f729Sjoerg             Escaped = false;
16107330f729Sjoerg             break;
16117330f729Sjoerg           default:
16127330f729Sjoerg             Escaped = false;
16137330f729Sjoerg             break;
16147330f729Sjoerg           }
16157330f729Sjoerg         }
16167330f729Sjoerg       }
16177330f729Sjoerg     }
16187330f729Sjoerg   }
16197330f729Sjoerg };
16207330f729Sjoerg 
16217330f729Sjoerg class Formatter : public TokenAnalyzer {
16227330f729Sjoerg public:
Formatter(const Environment & Env,const FormatStyle & Style,FormattingAttemptStatus * Status)16237330f729Sjoerg   Formatter(const Environment &Env, const FormatStyle &Style,
16247330f729Sjoerg             FormattingAttemptStatus *Status)
16257330f729Sjoerg       : TokenAnalyzer(Env, Style), Status(Status) {}
16267330f729Sjoerg 
16277330f729Sjoerg   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)16287330f729Sjoerg   analyze(TokenAnnotator &Annotator,
16297330f729Sjoerg           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
16307330f729Sjoerg           FormatTokenLexer &Tokens) override {
16317330f729Sjoerg     tooling::Replacements Result;
16327330f729Sjoerg     deriveLocalStyle(AnnotatedLines);
16337330f729Sjoerg     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
16347330f729Sjoerg     for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
16357330f729Sjoerg       Annotator.calculateFormattingInformation(*AnnotatedLines[i]);
16367330f729Sjoerg     }
16377330f729Sjoerg     Annotator.setCommentLineLevels(AnnotatedLines);
16387330f729Sjoerg 
16397330f729Sjoerg     WhitespaceManager Whitespaces(
16407330f729Sjoerg         Env.getSourceManager(), Style,
1641*e038c9c4Sjoerg         Style.DeriveLineEnding
1642*e038c9c4Sjoerg             ? inputUsesCRLF(
1643*e038c9c4Sjoerg                   Env.getSourceManager().getBufferData(Env.getFileID()),
1644*e038c9c4Sjoerg                   Style.UseCRLF)
1645*e038c9c4Sjoerg             : Style.UseCRLF);
16467330f729Sjoerg     ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
16477330f729Sjoerg                                   Env.getSourceManager(), Whitespaces, Encoding,
16487330f729Sjoerg                                   BinPackInconclusiveFunctions);
16497330f729Sjoerg     unsigned Penalty =
16507330f729Sjoerg         UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,
16517330f729Sjoerg                                Tokens.getKeywords(), Env.getSourceManager(),
16527330f729Sjoerg                                Status)
16537330f729Sjoerg             .format(AnnotatedLines, /*DryRun=*/false,
16547330f729Sjoerg                     /*AdditionalIndent=*/0,
16557330f729Sjoerg                     /*FixBadIndentation=*/false,
16567330f729Sjoerg                     /*FirstStartColumn=*/Env.getFirstStartColumn(),
16577330f729Sjoerg                     /*NextStartColumn=*/Env.getNextStartColumn(),
16587330f729Sjoerg                     /*LastStartColumn=*/Env.getLastStartColumn());
16597330f729Sjoerg     for (const auto &R : Whitespaces.generateReplacements())
16607330f729Sjoerg       if (Result.add(R))
16617330f729Sjoerg         return std::make_pair(Result, 0);
16627330f729Sjoerg     return std::make_pair(Result, Penalty);
16637330f729Sjoerg   }
16647330f729Sjoerg 
16657330f729Sjoerg private:
inputUsesCRLF(StringRef Text,bool DefaultToCRLF)1666*e038c9c4Sjoerg   static bool inputUsesCRLF(StringRef Text, bool DefaultToCRLF) {
1667*e038c9c4Sjoerg     size_t LF = Text.count('\n');
1668*e038c9c4Sjoerg     size_t CR = Text.count('\r') * 2;
1669*e038c9c4Sjoerg     return LF == CR ? DefaultToCRLF : CR > LF;
16707330f729Sjoerg   }
16717330f729Sjoerg 
16727330f729Sjoerg   bool
hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine * > & Lines)16737330f729Sjoerg   hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) {
16747330f729Sjoerg     for (const AnnotatedLine *Line : Lines) {
16757330f729Sjoerg       if (hasCpp03IncompatibleFormat(Line->Children))
16767330f729Sjoerg         return true;
16777330f729Sjoerg       for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {
16787330f729Sjoerg         if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) {
16797330f729Sjoerg           if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
16807330f729Sjoerg             return true;
16817330f729Sjoerg           if (Tok->is(TT_TemplateCloser) &&
16827330f729Sjoerg               Tok->Previous->is(TT_TemplateCloser))
16837330f729Sjoerg             return true;
16847330f729Sjoerg         }
16857330f729Sjoerg       }
16867330f729Sjoerg     }
16877330f729Sjoerg     return false;
16887330f729Sjoerg   }
16897330f729Sjoerg 
countVariableAlignments(const SmallVectorImpl<AnnotatedLine * > & Lines)16907330f729Sjoerg   int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) {
16917330f729Sjoerg     int AlignmentDiff = 0;
16927330f729Sjoerg     for (const AnnotatedLine *Line : Lines) {
16937330f729Sjoerg       AlignmentDiff += countVariableAlignments(Line->Children);
16947330f729Sjoerg       for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {
16957330f729Sjoerg         if (!Tok->is(TT_PointerOrReference))
16967330f729Sjoerg           continue;
16977330f729Sjoerg         bool SpaceBefore =
16987330f729Sjoerg             Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd();
16997330f729Sjoerg         bool SpaceAfter = Tok->Next->WhitespaceRange.getBegin() !=
17007330f729Sjoerg                           Tok->Next->WhitespaceRange.getEnd();
17017330f729Sjoerg         if (SpaceBefore && !SpaceAfter)
17027330f729Sjoerg           ++AlignmentDiff;
17037330f729Sjoerg         if (!SpaceBefore && SpaceAfter)
17047330f729Sjoerg           --AlignmentDiff;
17057330f729Sjoerg       }
17067330f729Sjoerg     }
17077330f729Sjoerg     return AlignmentDiff;
17087330f729Sjoerg   }
17097330f729Sjoerg 
17107330f729Sjoerg   void
deriveLocalStyle(const SmallVectorImpl<AnnotatedLine * > & AnnotatedLines)17117330f729Sjoerg   deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
17127330f729Sjoerg     bool HasBinPackedFunction = false;
17137330f729Sjoerg     bool HasOnePerLineFunction = false;
17147330f729Sjoerg     for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
17157330f729Sjoerg       if (!AnnotatedLines[i]->First->Next)
17167330f729Sjoerg         continue;
17177330f729Sjoerg       FormatToken *Tok = AnnotatedLines[i]->First->Next;
17187330f729Sjoerg       while (Tok->Next) {
1719*e038c9c4Sjoerg         if (Tok->is(PPK_BinPacked))
17207330f729Sjoerg           HasBinPackedFunction = true;
1721*e038c9c4Sjoerg         if (Tok->is(PPK_OnePerLine))
17227330f729Sjoerg           HasOnePerLineFunction = true;
17237330f729Sjoerg 
17247330f729Sjoerg         Tok = Tok->Next;
17257330f729Sjoerg       }
17267330f729Sjoerg     }
17277330f729Sjoerg     if (Style.DerivePointerAlignment)
17287330f729Sjoerg       Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0
17297330f729Sjoerg                                    ? FormatStyle::PAS_Left
17307330f729Sjoerg                                    : FormatStyle::PAS_Right;
17317330f729Sjoerg     if (Style.Standard == FormatStyle::LS_Auto)
17327330f729Sjoerg       Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
17337330f729Sjoerg                            ? FormatStyle::LS_Latest
17347330f729Sjoerg                            : FormatStyle::LS_Cpp03;
17357330f729Sjoerg     BinPackInconclusiveFunctions =
17367330f729Sjoerg         HasBinPackedFunction || !HasOnePerLineFunction;
17377330f729Sjoerg   }
17387330f729Sjoerg 
17397330f729Sjoerg   bool BinPackInconclusiveFunctions;
17407330f729Sjoerg   FormattingAttemptStatus *Status;
17417330f729Sjoerg };
17427330f729Sjoerg 
1743*e038c9c4Sjoerg /// TrailingCommaInserter inserts trailing commas into container literals.
1744*e038c9c4Sjoerg /// E.g.:
1745*e038c9c4Sjoerg ///     const x = [
1746*e038c9c4Sjoerg ///       1,
1747*e038c9c4Sjoerg ///     ];
1748*e038c9c4Sjoerg /// TrailingCommaInserter runs after formatting. To avoid causing a required
1749*e038c9c4Sjoerg /// reformatting (and thus reflow), it never inserts a comma that'd exceed the
1750*e038c9c4Sjoerg /// ColumnLimit.
1751*e038c9c4Sjoerg ///
1752*e038c9c4Sjoerg /// Because trailing commas disable binpacking of arrays, TrailingCommaInserter
1753*e038c9c4Sjoerg /// is conceptually incompatible with bin packing.
1754*e038c9c4Sjoerg class TrailingCommaInserter : public TokenAnalyzer {
1755*e038c9c4Sjoerg public:
TrailingCommaInserter(const Environment & Env,const FormatStyle & Style)1756*e038c9c4Sjoerg   TrailingCommaInserter(const Environment &Env, const FormatStyle &Style)
1757*e038c9c4Sjoerg       : TokenAnalyzer(Env, Style) {}
1758*e038c9c4Sjoerg 
1759*e038c9c4Sjoerg   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)1760*e038c9c4Sjoerg   analyze(TokenAnnotator &Annotator,
1761*e038c9c4Sjoerg           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1762*e038c9c4Sjoerg           FormatTokenLexer &Tokens) override {
1763*e038c9c4Sjoerg     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
1764*e038c9c4Sjoerg     tooling::Replacements Result;
1765*e038c9c4Sjoerg     insertTrailingCommas(AnnotatedLines, Result);
1766*e038c9c4Sjoerg     return {Result, 0};
1767*e038c9c4Sjoerg   }
1768*e038c9c4Sjoerg 
1769*e038c9c4Sjoerg private:
1770*e038c9c4Sjoerg   /// Inserts trailing commas in [] and {} initializers if they wrap over
1771*e038c9c4Sjoerg   /// multiple lines.
insertTrailingCommas(SmallVectorImpl<AnnotatedLine * > & Lines,tooling::Replacements & Result)1772*e038c9c4Sjoerg   void insertTrailingCommas(SmallVectorImpl<AnnotatedLine *> &Lines,
1773*e038c9c4Sjoerg                             tooling::Replacements &Result) {
1774*e038c9c4Sjoerg     for (AnnotatedLine *Line : Lines) {
1775*e038c9c4Sjoerg       insertTrailingCommas(Line->Children, Result);
1776*e038c9c4Sjoerg       if (!Line->Affected)
1777*e038c9c4Sjoerg         continue;
1778*e038c9c4Sjoerg       for (FormatToken *FormatTok = Line->First; FormatTok;
1779*e038c9c4Sjoerg            FormatTok = FormatTok->Next) {
1780*e038c9c4Sjoerg         if (FormatTok->NewlinesBefore == 0)
1781*e038c9c4Sjoerg           continue;
1782*e038c9c4Sjoerg         FormatToken *Matching = FormatTok->MatchingParen;
1783*e038c9c4Sjoerg         if (!Matching || !FormatTok->getPreviousNonComment())
1784*e038c9c4Sjoerg           continue;
1785*e038c9c4Sjoerg         if (!(FormatTok->is(tok::r_square) &&
1786*e038c9c4Sjoerg               Matching->is(TT_ArrayInitializerLSquare)) &&
1787*e038c9c4Sjoerg             !(FormatTok->is(tok::r_brace) && Matching->is(TT_DictLiteral)))
1788*e038c9c4Sjoerg           continue;
1789*e038c9c4Sjoerg         FormatToken *Prev = FormatTok->getPreviousNonComment();
1790*e038c9c4Sjoerg         if (Prev->is(tok::comma) || Prev->is(tok::semi))
1791*e038c9c4Sjoerg           continue;
1792*e038c9c4Sjoerg         // getEndLoc is not reliably set during re-lexing, use text length
1793*e038c9c4Sjoerg         // instead.
1794*e038c9c4Sjoerg         SourceLocation Start =
1795*e038c9c4Sjoerg             Prev->Tok.getLocation().getLocWithOffset(Prev->TokenText.size());
1796*e038c9c4Sjoerg         // If inserting a comma would push the code over the column limit, skip
1797*e038c9c4Sjoerg         // this location - it'd introduce an unstable formatting due to the
1798*e038c9c4Sjoerg         // required reflow.
1799*e038c9c4Sjoerg         unsigned ColumnNumber =
1800*e038c9c4Sjoerg             Env.getSourceManager().getSpellingColumnNumber(Start);
1801*e038c9c4Sjoerg         if (ColumnNumber > Style.ColumnLimit)
1802*e038c9c4Sjoerg           continue;
1803*e038c9c4Sjoerg         // Comma insertions cannot conflict with each other, and this pass has a
1804*e038c9c4Sjoerg         // clean set of Replacements, so the operation below cannot fail.
1805*e038c9c4Sjoerg         cantFail(Result.add(
1806*e038c9c4Sjoerg             tooling::Replacement(Env.getSourceManager(), Start, 0, ",")));
1807*e038c9c4Sjoerg       }
1808*e038c9c4Sjoerg     }
1809*e038c9c4Sjoerg   }
1810*e038c9c4Sjoerg };
1811*e038c9c4Sjoerg 
18127330f729Sjoerg // This class clean up the erroneous/redundant code around the given ranges in
18137330f729Sjoerg // file.
18147330f729Sjoerg class Cleaner : public TokenAnalyzer {
18157330f729Sjoerg public:
Cleaner(const Environment & Env,const FormatStyle & Style)18167330f729Sjoerg   Cleaner(const Environment &Env, const FormatStyle &Style)
18177330f729Sjoerg       : TokenAnalyzer(Env, Style),
18187330f729Sjoerg         DeletedTokens(FormatTokenLess(Env.getSourceManager())) {}
18197330f729Sjoerg 
18207330f729Sjoerg   // FIXME: eliminate unused parameters.
18217330f729Sjoerg   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)18227330f729Sjoerg   analyze(TokenAnnotator &Annotator,
18237330f729Sjoerg           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
18247330f729Sjoerg           FormatTokenLexer &Tokens) override {
18257330f729Sjoerg     // FIXME: in the current implementation the granularity of affected range
18267330f729Sjoerg     // is an annotated line. However, this is not sufficient. Furthermore,
18277330f729Sjoerg     // redundant code introduced by replacements does not necessarily
18287330f729Sjoerg     // intercept with ranges of replacements that result in the redundancy.
18297330f729Sjoerg     // To determine if some redundant code is actually introduced by
18307330f729Sjoerg     // replacements(e.g. deletions), we need to come up with a more
18317330f729Sjoerg     // sophisticated way of computing affected ranges.
18327330f729Sjoerg     AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
18337330f729Sjoerg 
18347330f729Sjoerg     checkEmptyNamespace(AnnotatedLines);
18357330f729Sjoerg 
18367330f729Sjoerg     for (auto *Line : AnnotatedLines)
18377330f729Sjoerg       cleanupLine(Line);
18387330f729Sjoerg 
18397330f729Sjoerg     return {generateFixes(), 0};
18407330f729Sjoerg   }
18417330f729Sjoerg 
18427330f729Sjoerg private:
cleanupLine(AnnotatedLine * Line)18437330f729Sjoerg   void cleanupLine(AnnotatedLine *Line) {
18447330f729Sjoerg     for (auto *Child : Line->Children) {
18457330f729Sjoerg       cleanupLine(Child);
18467330f729Sjoerg     }
18477330f729Sjoerg 
18487330f729Sjoerg     if (Line->Affected) {
18497330f729Sjoerg       cleanupRight(Line->First, tok::comma, tok::comma);
18507330f729Sjoerg       cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
18517330f729Sjoerg       cleanupRight(Line->First, tok::l_paren, tok::comma);
18527330f729Sjoerg       cleanupLeft(Line->First, tok::comma, tok::r_paren);
18537330f729Sjoerg       cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
18547330f729Sjoerg       cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
18557330f729Sjoerg       cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
18567330f729Sjoerg     }
18577330f729Sjoerg   }
18587330f729Sjoerg 
containsOnlyComments(const AnnotatedLine & Line)18597330f729Sjoerg   bool containsOnlyComments(const AnnotatedLine &Line) {
18607330f729Sjoerg     for (FormatToken *Tok = Line.First; Tok != nullptr; Tok = Tok->Next) {
18617330f729Sjoerg       if (Tok->isNot(tok::comment))
18627330f729Sjoerg         return false;
18637330f729Sjoerg     }
18647330f729Sjoerg     return true;
18657330f729Sjoerg   }
18667330f729Sjoerg 
18677330f729Sjoerg   // Iterate through all lines and remove any empty (nested) namespaces.
checkEmptyNamespace(SmallVectorImpl<AnnotatedLine * > & AnnotatedLines)18687330f729Sjoerg   void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
18697330f729Sjoerg     std::set<unsigned> DeletedLines;
18707330f729Sjoerg     for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
18717330f729Sjoerg       auto &Line = *AnnotatedLines[i];
18727330f729Sjoerg       if (Line.startsWithNamespace()) {
18737330f729Sjoerg         checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
18747330f729Sjoerg       }
18757330f729Sjoerg     }
18767330f729Sjoerg 
18777330f729Sjoerg     for (auto Line : DeletedLines) {
18787330f729Sjoerg       FormatToken *Tok = AnnotatedLines[Line]->First;
18797330f729Sjoerg       while (Tok) {
18807330f729Sjoerg         deleteToken(Tok);
18817330f729Sjoerg         Tok = Tok->Next;
18827330f729Sjoerg       }
18837330f729Sjoerg     }
18847330f729Sjoerg   }
18857330f729Sjoerg 
18867330f729Sjoerg   // The function checks if the namespace, which starts from \p CurrentLine, and
18877330f729Sjoerg   // its nested namespaces are empty and delete them if they are empty. It also
18887330f729Sjoerg   // sets \p NewLine to the last line checked.
18897330f729Sjoerg   // Returns true if the current namespace is empty.
checkEmptyNamespace(SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,unsigned CurrentLine,unsigned & NewLine,std::set<unsigned> & DeletedLines)18907330f729Sjoerg   bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
18917330f729Sjoerg                            unsigned CurrentLine, unsigned &NewLine,
18927330f729Sjoerg                            std::set<unsigned> &DeletedLines) {
18937330f729Sjoerg     unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
18947330f729Sjoerg     if (Style.BraceWrapping.AfterNamespace) {
18957330f729Sjoerg       // If the left brace is in a new line, we should consume it first so that
18967330f729Sjoerg       // it does not make the namespace non-empty.
18977330f729Sjoerg       // FIXME: error handling if there is no left brace.
18987330f729Sjoerg       if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
18997330f729Sjoerg         NewLine = CurrentLine;
19007330f729Sjoerg         return false;
19017330f729Sjoerg       }
19027330f729Sjoerg     } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
19037330f729Sjoerg       return false;
19047330f729Sjoerg     }
19057330f729Sjoerg     while (++CurrentLine < End) {
19067330f729Sjoerg       if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
19077330f729Sjoerg         break;
19087330f729Sjoerg 
19097330f729Sjoerg       if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
19107330f729Sjoerg         if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
19117330f729Sjoerg                                  DeletedLines))
19127330f729Sjoerg           return false;
19137330f729Sjoerg         CurrentLine = NewLine;
19147330f729Sjoerg         continue;
19157330f729Sjoerg       }
19167330f729Sjoerg 
19177330f729Sjoerg       if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
19187330f729Sjoerg         continue;
19197330f729Sjoerg 
19207330f729Sjoerg       // If there is anything other than comments or nested namespaces in the
19217330f729Sjoerg       // current namespace, the namespace cannot be empty.
19227330f729Sjoerg       NewLine = CurrentLine;
19237330f729Sjoerg       return false;
19247330f729Sjoerg     }
19257330f729Sjoerg 
19267330f729Sjoerg     NewLine = CurrentLine;
19277330f729Sjoerg     if (CurrentLine >= End)
19287330f729Sjoerg       return false;
19297330f729Sjoerg 
19307330f729Sjoerg     // Check if the empty namespace is actually affected by changed ranges.
19317330f729Sjoerg     if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
19327330f729Sjoerg             AnnotatedLines[InitLine]->First->Tok.getLocation(),
19337330f729Sjoerg             AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc())))
19347330f729Sjoerg       return false;
19357330f729Sjoerg 
19367330f729Sjoerg     for (unsigned i = InitLine; i <= CurrentLine; ++i) {
19377330f729Sjoerg       DeletedLines.insert(i);
19387330f729Sjoerg     }
19397330f729Sjoerg 
19407330f729Sjoerg     return true;
19417330f729Sjoerg   }
19427330f729Sjoerg 
19437330f729Sjoerg   // Checks pairs {start, start->next},..., {end->previous, end} and deletes one
19447330f729Sjoerg   // of the token in the pair if the left token has \p LK token kind and the
19457330f729Sjoerg   // right token has \p RK token kind. If \p DeleteLeft is true, the left token
19467330f729Sjoerg   // is deleted on match; otherwise, the right token is deleted.
19477330f729Sjoerg   template <typename LeftKind, typename RightKind>
cleanupPair(FormatToken * Start,LeftKind LK,RightKind RK,bool DeleteLeft)19487330f729Sjoerg   void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
19497330f729Sjoerg                    bool DeleteLeft) {
19507330f729Sjoerg     auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {
19517330f729Sjoerg       for (auto *Res = Tok.Next; Res; Res = Res->Next)
19527330f729Sjoerg         if (!Res->is(tok::comment) &&
19537330f729Sjoerg             DeletedTokens.find(Res) == DeletedTokens.end())
19547330f729Sjoerg           return Res;
19557330f729Sjoerg       return nullptr;
19567330f729Sjoerg     };
19577330f729Sjoerg     for (auto *Left = Start; Left;) {
19587330f729Sjoerg       auto *Right = NextNotDeleted(*Left);
19597330f729Sjoerg       if (!Right)
19607330f729Sjoerg         break;
19617330f729Sjoerg       if (Left->is(LK) && Right->is(RK)) {
19627330f729Sjoerg         deleteToken(DeleteLeft ? Left : Right);
19637330f729Sjoerg         for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
19647330f729Sjoerg           deleteToken(Tok);
19657330f729Sjoerg         // If the right token is deleted, we should keep the left token
19667330f729Sjoerg         // unchanged and pair it with the new right token.
19677330f729Sjoerg         if (!DeleteLeft)
19687330f729Sjoerg           continue;
19697330f729Sjoerg       }
19707330f729Sjoerg       Left = Right;
19717330f729Sjoerg     }
19727330f729Sjoerg   }
19737330f729Sjoerg 
19747330f729Sjoerg   template <typename LeftKind, typename RightKind>
cleanupLeft(FormatToken * Start,LeftKind LK,RightKind RK)19757330f729Sjoerg   void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
19767330f729Sjoerg     cleanupPair(Start, LK, RK, /*DeleteLeft=*/true);
19777330f729Sjoerg   }
19787330f729Sjoerg 
19797330f729Sjoerg   template <typename LeftKind, typename RightKind>
cleanupRight(FormatToken * Start,LeftKind LK,RightKind RK)19807330f729Sjoerg   void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
19817330f729Sjoerg     cleanupPair(Start, LK, RK, /*DeleteLeft=*/false);
19827330f729Sjoerg   }
19837330f729Sjoerg 
19847330f729Sjoerg   // Delete the given token.
deleteToken(FormatToken * Tok)19857330f729Sjoerg   inline void deleteToken(FormatToken *Tok) {
19867330f729Sjoerg     if (Tok)
19877330f729Sjoerg       DeletedTokens.insert(Tok);
19887330f729Sjoerg   }
19897330f729Sjoerg 
generateFixes()19907330f729Sjoerg   tooling::Replacements generateFixes() {
19917330f729Sjoerg     tooling::Replacements Fixes;
19927330f729Sjoerg     std::vector<FormatToken *> Tokens;
19937330f729Sjoerg     std::copy(DeletedTokens.begin(), DeletedTokens.end(),
19947330f729Sjoerg               std::back_inserter(Tokens));
19957330f729Sjoerg 
19967330f729Sjoerg     // Merge multiple continuous token deletions into one big deletion so that
19977330f729Sjoerg     // the number of replacements can be reduced. This makes computing affected
19987330f729Sjoerg     // ranges more efficient when we run reformat on the changed code.
19997330f729Sjoerg     unsigned Idx = 0;
20007330f729Sjoerg     while (Idx < Tokens.size()) {
20017330f729Sjoerg       unsigned St = Idx, End = Idx;
20027330f729Sjoerg       while ((End + 1) < Tokens.size() &&
20037330f729Sjoerg              Tokens[End]->Next == Tokens[End + 1]) {
20047330f729Sjoerg         End++;
20057330f729Sjoerg       }
20067330f729Sjoerg       auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
20077330f729Sjoerg                                               Tokens[End]->Tok.getEndLoc());
20087330f729Sjoerg       auto Err =
20097330f729Sjoerg           Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, ""));
20107330f729Sjoerg       // FIXME: better error handling. for now just print error message and skip
20117330f729Sjoerg       // for the release version.
20127330f729Sjoerg       if (Err) {
20137330f729Sjoerg         llvm::errs() << llvm::toString(std::move(Err)) << "\n";
20147330f729Sjoerg         assert(false && "Fixes must not conflict!");
20157330f729Sjoerg       }
20167330f729Sjoerg       Idx = End + 1;
20177330f729Sjoerg     }
20187330f729Sjoerg 
20197330f729Sjoerg     return Fixes;
20207330f729Sjoerg   }
20217330f729Sjoerg 
20227330f729Sjoerg   // Class for less-than inequality comparason for the set `RedundantTokens`.
20237330f729Sjoerg   // We store tokens in the order they appear in the translation unit so that
20247330f729Sjoerg   // we do not need to sort them in `generateFixes()`.
20257330f729Sjoerg   struct FormatTokenLess {
FormatTokenLessclang::format::__anon5a72e2a60111::Cleaner::FormatTokenLess20267330f729Sjoerg     FormatTokenLess(const SourceManager &SM) : SM(SM) {}
20277330f729Sjoerg 
operator ()clang::format::__anon5a72e2a60111::Cleaner::FormatTokenLess20287330f729Sjoerg     bool operator()(const FormatToken *LHS, const FormatToken *RHS) const {
20297330f729Sjoerg       return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
20307330f729Sjoerg                                           RHS->Tok.getLocation());
20317330f729Sjoerg     }
20327330f729Sjoerg     const SourceManager &SM;
20337330f729Sjoerg   };
20347330f729Sjoerg 
20357330f729Sjoerg   // Tokens to be deleted.
20367330f729Sjoerg   std::set<FormatToken *, FormatTokenLess> DeletedTokens;
20377330f729Sjoerg };
20387330f729Sjoerg 
20397330f729Sjoerg class ObjCHeaderStyleGuesser : public TokenAnalyzer {
20407330f729Sjoerg public:
ObjCHeaderStyleGuesser(const Environment & Env,const FormatStyle & Style)20417330f729Sjoerg   ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style)
20427330f729Sjoerg       : TokenAnalyzer(Env, Style), IsObjC(false) {}
20437330f729Sjoerg 
20447330f729Sjoerg   std::pair<tooling::Replacements, unsigned>
analyze(TokenAnnotator & Annotator,SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,FormatTokenLexer & Tokens)20457330f729Sjoerg   analyze(TokenAnnotator &Annotator,
20467330f729Sjoerg           SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
20477330f729Sjoerg           FormatTokenLexer &Tokens) override {
20487330f729Sjoerg     assert(Style.Language == FormatStyle::LK_Cpp);
20497330f729Sjoerg     IsObjC = guessIsObjC(Env.getSourceManager(), AnnotatedLines,
20507330f729Sjoerg                          Tokens.getKeywords());
20517330f729Sjoerg     tooling::Replacements Result;
20527330f729Sjoerg     return {Result, 0};
20537330f729Sjoerg   }
20547330f729Sjoerg 
isObjC()20557330f729Sjoerg   bool isObjC() { return IsObjC; }
20567330f729Sjoerg 
20577330f729Sjoerg private:
20587330f729Sjoerg   static bool
guessIsObjC(const SourceManager & SourceManager,const SmallVectorImpl<AnnotatedLine * > & AnnotatedLines,const AdditionalKeywords & Keywords)20597330f729Sjoerg   guessIsObjC(const SourceManager &SourceManager,
20607330f729Sjoerg               const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
20617330f729Sjoerg               const AdditionalKeywords &Keywords) {
20627330f729Sjoerg     // Keep this array sorted, since we are binary searching over it.
20637330f729Sjoerg     static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
20647330f729Sjoerg         "CGFloat",
20657330f729Sjoerg         "CGPoint",
20667330f729Sjoerg         "CGPointMake",
20677330f729Sjoerg         "CGPointZero",
20687330f729Sjoerg         "CGRect",
20697330f729Sjoerg         "CGRectEdge",
20707330f729Sjoerg         "CGRectInfinite",
20717330f729Sjoerg         "CGRectMake",
20727330f729Sjoerg         "CGRectNull",
20737330f729Sjoerg         "CGRectZero",
20747330f729Sjoerg         "CGSize",
20757330f729Sjoerg         "CGSizeMake",
20767330f729Sjoerg         "CGVector",
20777330f729Sjoerg         "CGVectorMake",
20787330f729Sjoerg         "NSAffineTransform",
20797330f729Sjoerg         "NSArray",
20807330f729Sjoerg         "NSAttributedString",
20817330f729Sjoerg         "NSBlockOperation",
20827330f729Sjoerg         "NSBundle",
20837330f729Sjoerg         "NSCache",
20847330f729Sjoerg         "NSCalendar",
20857330f729Sjoerg         "NSCharacterSet",
20867330f729Sjoerg         "NSCountedSet",
20877330f729Sjoerg         "NSData",
20887330f729Sjoerg         "NSDataDetector",
20897330f729Sjoerg         "NSDecimal",
20907330f729Sjoerg         "NSDecimalNumber",
20917330f729Sjoerg         "NSDictionary",
20927330f729Sjoerg         "NSEdgeInsets",
20937330f729Sjoerg         "NSHashTable",
20947330f729Sjoerg         "NSIndexPath",
20957330f729Sjoerg         "NSIndexSet",
20967330f729Sjoerg         "NSInteger",
20977330f729Sjoerg         "NSInvocationOperation",
20987330f729Sjoerg         "NSLocale",
20997330f729Sjoerg         "NSMapTable",
21007330f729Sjoerg         "NSMutableArray",
21017330f729Sjoerg         "NSMutableAttributedString",
21027330f729Sjoerg         "NSMutableCharacterSet",
21037330f729Sjoerg         "NSMutableData",
21047330f729Sjoerg         "NSMutableDictionary",
21057330f729Sjoerg         "NSMutableIndexSet",
21067330f729Sjoerg         "NSMutableOrderedSet",
21077330f729Sjoerg         "NSMutableSet",
21087330f729Sjoerg         "NSMutableString",
21097330f729Sjoerg         "NSNumber",
21107330f729Sjoerg         "NSNumberFormatter",
21117330f729Sjoerg         "NSObject",
21127330f729Sjoerg         "NSOperation",
21137330f729Sjoerg         "NSOperationQueue",
21147330f729Sjoerg         "NSOperationQueuePriority",
21157330f729Sjoerg         "NSOrderedSet",
21167330f729Sjoerg         "NSPoint",
21177330f729Sjoerg         "NSPointerArray",
21187330f729Sjoerg         "NSQualityOfService",
21197330f729Sjoerg         "NSRange",
21207330f729Sjoerg         "NSRect",
21217330f729Sjoerg         "NSRegularExpression",
21227330f729Sjoerg         "NSSet",
21237330f729Sjoerg         "NSSize",
21247330f729Sjoerg         "NSString",
21257330f729Sjoerg         "NSTimeZone",
21267330f729Sjoerg         "NSUInteger",
21277330f729Sjoerg         "NSURL",
21287330f729Sjoerg         "NSURLComponents",
21297330f729Sjoerg         "NSURLQueryItem",
21307330f729Sjoerg         "NSUUID",
21317330f729Sjoerg         "NSValue",
21327330f729Sjoerg         "UIImage",
21337330f729Sjoerg         "UIView",
21347330f729Sjoerg     };
21357330f729Sjoerg 
21367330f729Sjoerg     for (auto Line : AnnotatedLines) {
2137*e038c9c4Sjoerg       if (Line->First && (Line->First->TokenText.startswith("#") ||
2138*e038c9c4Sjoerg                           Line->First->TokenText == "__pragma" ||
2139*e038c9c4Sjoerg                           Line->First->TokenText == "_Pragma"))
2140*e038c9c4Sjoerg         continue;
21417330f729Sjoerg       for (const FormatToken *FormatTok = Line->First; FormatTok;
21427330f729Sjoerg            FormatTok = FormatTok->Next) {
21437330f729Sjoerg         if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
21447330f729Sjoerg              (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
21457330f729Sjoerg               FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
21467330f729Sjoerg                                  tok::l_brace))) ||
21477330f729Sjoerg             (FormatTok->Tok.isAnyIdentifier() &&
21487330f729Sjoerg              std::binary_search(std::begin(FoundationIdentifiers),
21497330f729Sjoerg                                 std::end(FoundationIdentifiers),
21507330f729Sjoerg                                 FormatTok->TokenText)) ||
21517330f729Sjoerg             FormatTok->is(TT_ObjCStringLiteral) ||
21527330f729Sjoerg             FormatTok->isOneOf(Keywords.kw_NS_CLOSED_ENUM, Keywords.kw_NS_ENUM,
21537330f729Sjoerg                                Keywords.kw_NS_OPTIONS, TT_ObjCBlockLBrace,
21547330f729Sjoerg                                TT_ObjCBlockLParen, TT_ObjCDecl, TT_ObjCForIn,
21557330f729Sjoerg                                TT_ObjCMethodExpr, TT_ObjCMethodSpecifier,
21567330f729Sjoerg                                TT_ObjCProperty)) {
21577330f729Sjoerg           LLVM_DEBUG(llvm::dbgs()
21587330f729Sjoerg                      << "Detected ObjC at location "
21597330f729Sjoerg                      << FormatTok->Tok.getLocation().printToString(
21607330f729Sjoerg                             SourceManager)
21617330f729Sjoerg                      << " token: " << FormatTok->TokenText << " token type: "
2162*e038c9c4Sjoerg                      << getTokenTypeName(FormatTok->getType()) << "\n");
21637330f729Sjoerg           return true;
21647330f729Sjoerg         }
21657330f729Sjoerg         if (guessIsObjC(SourceManager, Line->Children, Keywords))
21667330f729Sjoerg           return true;
21677330f729Sjoerg       }
21687330f729Sjoerg     }
21697330f729Sjoerg     return false;
21707330f729Sjoerg   }
21717330f729Sjoerg 
21727330f729Sjoerg   bool IsObjC;
21737330f729Sjoerg };
21747330f729Sjoerg 
21757330f729Sjoerg struct IncludeDirective {
21767330f729Sjoerg   StringRef Filename;
21777330f729Sjoerg   StringRef Text;
21787330f729Sjoerg   unsigned Offset;
21797330f729Sjoerg   int Category;
21807330f729Sjoerg   int Priority;
21817330f729Sjoerg };
21827330f729Sjoerg 
21837330f729Sjoerg struct JavaImportDirective {
21847330f729Sjoerg   StringRef Identifier;
21857330f729Sjoerg   StringRef Text;
21867330f729Sjoerg   unsigned Offset;
21877330f729Sjoerg   std::vector<StringRef> AssociatedCommentLines;
21887330f729Sjoerg   bool IsStatic;
21897330f729Sjoerg };
21907330f729Sjoerg 
21917330f729Sjoerg } // end anonymous namespace
21927330f729Sjoerg 
21937330f729Sjoerg // Determines whether 'Ranges' intersects with ('Start', 'End').
affectsRange(ArrayRef<tooling::Range> Ranges,unsigned Start,unsigned End)21947330f729Sjoerg static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start,
21957330f729Sjoerg                          unsigned End) {
21967330f729Sjoerg   for (auto Range : Ranges) {
21977330f729Sjoerg     if (Range.getOffset() < End &&
21987330f729Sjoerg         Range.getOffset() + Range.getLength() > Start)
21997330f729Sjoerg       return true;
22007330f729Sjoerg   }
22017330f729Sjoerg   return false;
22027330f729Sjoerg }
22037330f729Sjoerg 
22047330f729Sjoerg // Returns a pair (Index, OffsetToEOL) describing the position of the cursor
22057330f729Sjoerg // before sorting/deduplicating. Index is the index of the include under the
22067330f729Sjoerg // cursor in the original set of includes. If this include has duplicates, it is
22077330f729Sjoerg // the index of the first of the duplicates as the others are going to be
22087330f729Sjoerg // removed. OffsetToEOL describes the cursor's position relative to the end of
22097330f729Sjoerg // its current line.
22107330f729Sjoerg // If `Cursor` is not on any #include, `Index` will be UINT_MAX.
22117330f729Sjoerg static std::pair<unsigned, unsigned>
FindCursorIndex(const SmallVectorImpl<IncludeDirective> & Includes,const SmallVectorImpl<unsigned> & Indices,unsigned Cursor)22127330f729Sjoerg FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes,
22137330f729Sjoerg                 const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) {
22147330f729Sjoerg   unsigned CursorIndex = UINT_MAX;
22157330f729Sjoerg   unsigned OffsetToEOL = 0;
22167330f729Sjoerg   for (int i = 0, e = Includes.size(); i != e; ++i) {
22177330f729Sjoerg     unsigned Start = Includes[Indices[i]].Offset;
22187330f729Sjoerg     unsigned End = Start + Includes[Indices[i]].Text.size();
22197330f729Sjoerg     if (!(Cursor >= Start && Cursor < End))
22207330f729Sjoerg       continue;
22217330f729Sjoerg     CursorIndex = Indices[i];
22227330f729Sjoerg     OffsetToEOL = End - Cursor;
22237330f729Sjoerg     // Put the cursor on the only remaining #include among the duplicate
22247330f729Sjoerg     // #includes.
22257330f729Sjoerg     while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text)
22267330f729Sjoerg       CursorIndex = i;
22277330f729Sjoerg     break;
22287330f729Sjoerg   }
22297330f729Sjoerg   return std::make_pair(CursorIndex, OffsetToEOL);
22307330f729Sjoerg }
22317330f729Sjoerg 
22327330f729Sjoerg // Replace all "\r\n" with "\n".
replaceCRLF(const std::string & Code)22337330f729Sjoerg std::string replaceCRLF(const std::string &Code) {
22347330f729Sjoerg   std::string NewCode;
22357330f729Sjoerg   size_t Pos = 0, LastPos = 0;
22367330f729Sjoerg 
22377330f729Sjoerg   do {
22387330f729Sjoerg     Pos = Code.find("\r\n", LastPos);
22397330f729Sjoerg     if (Pos == LastPos) {
22407330f729Sjoerg       LastPos++;
22417330f729Sjoerg       continue;
22427330f729Sjoerg     }
22437330f729Sjoerg     if (Pos == std::string::npos) {
22447330f729Sjoerg       NewCode += Code.substr(LastPos);
22457330f729Sjoerg       break;
22467330f729Sjoerg     }
22477330f729Sjoerg     NewCode += Code.substr(LastPos, Pos - LastPos) + "\n";
22487330f729Sjoerg     LastPos = Pos + 2;
22497330f729Sjoerg   } while (Pos != std::string::npos);
22507330f729Sjoerg 
22517330f729Sjoerg   return NewCode;
22527330f729Sjoerg }
22537330f729Sjoerg 
22547330f729Sjoerg // Sorts and deduplicate a block of includes given by 'Includes' alphabetically
22557330f729Sjoerg // adding the necessary replacement to 'Replaces'. 'Includes' must be in strict
22567330f729Sjoerg // source order.
22577330f729Sjoerg // #include directives with the same text will be deduplicated, and only the
22587330f729Sjoerg // first #include in the duplicate #includes remains. If the `Cursor` is
22597330f729Sjoerg // provided and put on a deleted #include, it will be moved to the remaining
22607330f729Sjoerg // #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)22617330f729Sjoerg static void sortCppIncludes(const FormatStyle &Style,
22627330f729Sjoerg                             const SmallVectorImpl<IncludeDirective> &Includes,
22637330f729Sjoerg                             ArrayRef<tooling::Range> Ranges, StringRef FileName,
22647330f729Sjoerg                             StringRef Code, tooling::Replacements &Replaces,
22657330f729Sjoerg                             unsigned *Cursor) {
22667330f729Sjoerg   tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
22677330f729Sjoerg   unsigned IncludesBeginOffset = Includes.front().Offset;
22687330f729Sjoerg   unsigned IncludesEndOffset =
22697330f729Sjoerg       Includes.back().Offset + Includes.back().Text.size();
22707330f729Sjoerg   unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
22717330f729Sjoerg   if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
22727330f729Sjoerg     return;
22737330f729Sjoerg   SmallVector<unsigned, 16> Indices;
22747330f729Sjoerg   for (unsigned i = 0, e = Includes.size(); i != e; ++i) {
22757330f729Sjoerg     Indices.push_back(i);
22767330f729Sjoerg   }
2277*e038c9c4Sjoerg 
2278*e038c9c4Sjoerg   if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) {
2279*e038c9c4Sjoerg     llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
2280*e038c9c4Sjoerg       const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
2281*e038c9c4Sjoerg       const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
2282*e038c9c4Sjoerg       return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
2283*e038c9c4Sjoerg                       Includes[LHSI].Filename) <
2284*e038c9c4Sjoerg              std::tie(Includes[RHSI].Priority, RHSFilenameLower,
2285*e038c9c4Sjoerg                       Includes[RHSI].Filename);
2286*e038c9c4Sjoerg     });
2287*e038c9c4Sjoerg   } else {
22887330f729Sjoerg     llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
22897330f729Sjoerg       return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
22907330f729Sjoerg              std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
22917330f729Sjoerg     });
2292*e038c9c4Sjoerg   }
2293*e038c9c4Sjoerg 
22947330f729Sjoerg   // The index of the include on which the cursor will be put after
22957330f729Sjoerg   // sorting/deduplicating.
22967330f729Sjoerg   unsigned CursorIndex;
22977330f729Sjoerg   // The offset from cursor to the end of line.
22987330f729Sjoerg   unsigned CursorToEOLOffset;
22997330f729Sjoerg   if (Cursor)
23007330f729Sjoerg     std::tie(CursorIndex, CursorToEOLOffset) =
23017330f729Sjoerg         FindCursorIndex(Includes, Indices, *Cursor);
23027330f729Sjoerg 
23037330f729Sjoerg   // Deduplicate #includes.
23047330f729Sjoerg   Indices.erase(std::unique(Indices.begin(), Indices.end(),
23057330f729Sjoerg                             [&](unsigned LHSI, unsigned RHSI) {
2306*e038c9c4Sjoerg                               return Includes[LHSI].Text.trim() ==
2307*e038c9c4Sjoerg                                      Includes[RHSI].Text.trim();
23087330f729Sjoerg                             }),
23097330f729Sjoerg                 Indices.end());
23107330f729Sjoerg 
23117330f729Sjoerg   int CurrentCategory = Includes.front().Category;
23127330f729Sjoerg 
23137330f729Sjoerg   // If the #includes are out of order, we generate a single replacement fixing
23147330f729Sjoerg   // the entire block. Otherwise, no replacement is generated.
23157330f729Sjoerg   // In case Style.IncldueStyle.IncludeBlocks != IBS_Preserve, this check is not
23167330f729Sjoerg   // enough as additional newlines might be added or removed across #include
23177330f729Sjoerg   // blocks. This we handle below by generating the updated #imclude blocks and
23187330f729Sjoerg   // comparing it to the original.
2319*e038c9c4Sjoerg   if (Indices.size() == Includes.size() && llvm::is_sorted(Indices) &&
23207330f729Sjoerg       Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve)
23217330f729Sjoerg     return;
23227330f729Sjoerg 
23237330f729Sjoerg   std::string result;
23247330f729Sjoerg   for (unsigned Index : Indices) {
23257330f729Sjoerg     if (!result.empty()) {
23267330f729Sjoerg       result += "\n";
23277330f729Sjoerg       if (Style.IncludeStyle.IncludeBlocks ==
23287330f729Sjoerg               tooling::IncludeStyle::IBS_Regroup &&
23297330f729Sjoerg           CurrentCategory != Includes[Index].Category)
23307330f729Sjoerg         result += "\n";
23317330f729Sjoerg     }
23327330f729Sjoerg     result += Includes[Index].Text;
23337330f729Sjoerg     if (Cursor && CursorIndex == Index)
23347330f729Sjoerg       *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
23357330f729Sjoerg     CurrentCategory = Includes[Index].Category;
23367330f729Sjoerg   }
23377330f729Sjoerg 
23387330f729Sjoerg   // If the #includes are out of order, we generate a single replacement fixing
23397330f729Sjoerg   // the entire range of blocks. Otherwise, no replacement is generated.
2340*e038c9c4Sjoerg   if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
2341*e038c9c4Sjoerg                                  IncludesBeginOffset, IncludesBlockSize))))
23427330f729Sjoerg     return;
23437330f729Sjoerg 
23447330f729Sjoerg   auto Err = Replaces.add(tooling::Replacement(
23457330f729Sjoerg       FileName, Includes.front().Offset, IncludesBlockSize, result));
23467330f729Sjoerg   // FIXME: better error handling. For now, just skip the replacement for the
23477330f729Sjoerg   // release version.
23487330f729Sjoerg   if (Err) {
23497330f729Sjoerg     llvm::errs() << llvm::toString(std::move(Err)) << "\n";
23507330f729Sjoerg     assert(false);
23517330f729Sjoerg   }
23527330f729Sjoerg }
23537330f729Sjoerg 
23547330f729Sjoerg namespace {
23557330f729Sjoerg 
23567330f729Sjoerg const char CppIncludeRegexPattern[] =
23577330f729Sjoerg     R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))";
23587330f729Sjoerg 
23597330f729Sjoerg } // anonymous namespace
23607330f729Sjoerg 
sortCppIncludes(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName,tooling::Replacements & Replaces,unsigned * Cursor)23617330f729Sjoerg tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
23627330f729Sjoerg                                       ArrayRef<tooling::Range> Ranges,
23637330f729Sjoerg                                       StringRef FileName,
23647330f729Sjoerg                                       tooling::Replacements &Replaces,
23657330f729Sjoerg                                       unsigned *Cursor) {
2366*e038c9c4Sjoerg   unsigned Prev = llvm::StringSwitch<size_t>(Code)
2367*e038c9c4Sjoerg                       .StartsWith("\xEF\xBB\xBF", 3) // UTF-8 BOM
2368*e038c9c4Sjoerg                       .Default(0);
23697330f729Sjoerg   unsigned SearchFrom = 0;
23707330f729Sjoerg   llvm::Regex IncludeRegex(CppIncludeRegexPattern);
23717330f729Sjoerg   SmallVector<StringRef, 4> Matches;
23727330f729Sjoerg   SmallVector<IncludeDirective, 16> IncludesInBlock;
23737330f729Sjoerg 
23747330f729Sjoerg   // In compiled files, consider the first #include to be the main #include of
23757330f729Sjoerg   // the file if it is not a system #include. This ensures that the header
23767330f729Sjoerg   // doesn't have hidden dependencies
23777330f729Sjoerg   // (http://llvm.org/docs/CodingStandards.html#include-style).
23787330f729Sjoerg   //
23797330f729Sjoerg   // FIXME: Do some sanity checking, e.g. edit distance of the base name, to fix
23807330f729Sjoerg   // cases where the first #include is unlikely to be the main header.
23817330f729Sjoerg   tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
23827330f729Sjoerg   bool FirstIncludeBlock = true;
23837330f729Sjoerg   bool MainIncludeFound = false;
23847330f729Sjoerg   bool FormattingOff = false;
23857330f729Sjoerg 
23867330f729Sjoerg   for (;;) {
23877330f729Sjoerg     auto Pos = Code.find('\n', SearchFrom);
23887330f729Sjoerg     StringRef Line =
23897330f729Sjoerg         Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
23907330f729Sjoerg 
23917330f729Sjoerg     StringRef Trimmed = Line.trim();
23927330f729Sjoerg     if (Trimmed == "// clang-format off" || Trimmed == "/* clang-format off */")
23937330f729Sjoerg       FormattingOff = true;
23947330f729Sjoerg     else if (Trimmed == "// clang-format on" ||
23957330f729Sjoerg              Trimmed == "/* clang-format on */")
23967330f729Sjoerg       FormattingOff = false;
23977330f729Sjoerg 
23987330f729Sjoerg     const bool EmptyLineSkipped =
23997330f729Sjoerg         Trimmed.empty() &&
24007330f729Sjoerg         (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge ||
24017330f729Sjoerg          Style.IncludeStyle.IncludeBlocks ==
24027330f729Sjoerg              tooling::IncludeStyle::IBS_Regroup);
24037330f729Sjoerg 
2404*e038c9c4Sjoerg     bool MergeWithNextLine = Trimmed.endswith("\\");
2405*e038c9c4Sjoerg     if (!FormattingOff && !MergeWithNextLine) {
24067330f729Sjoerg       if (IncludeRegex.match(Line, &Matches)) {
24077330f729Sjoerg         StringRef IncludeName = Matches[2];
24087330f729Sjoerg         int Category = Categories.getIncludePriority(
24097330f729Sjoerg             IncludeName,
24107330f729Sjoerg             /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock);
24117330f729Sjoerg         int Priority = Categories.getSortIncludePriority(
24127330f729Sjoerg             IncludeName, !MainIncludeFound && FirstIncludeBlock);
24137330f729Sjoerg         if (Category == 0)
24147330f729Sjoerg           MainIncludeFound = true;
24157330f729Sjoerg         IncludesInBlock.push_back(
24167330f729Sjoerg             {IncludeName, Line, Prev, Category, Priority});
24177330f729Sjoerg       } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
24187330f729Sjoerg         sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code,
24197330f729Sjoerg                         Replaces, Cursor);
24207330f729Sjoerg         IncludesInBlock.clear();
2421*e038c9c4Sjoerg         if (Trimmed.startswith("#pragma hdrstop")) // Precompiled headers.
2422*e038c9c4Sjoerg           FirstIncludeBlock = true;
2423*e038c9c4Sjoerg         else
24247330f729Sjoerg           FirstIncludeBlock = false;
24257330f729Sjoerg       }
24267330f729Sjoerg     }
24277330f729Sjoerg     if (Pos == StringRef::npos || Pos + 1 == Code.size())
24287330f729Sjoerg       break;
2429*e038c9c4Sjoerg 
2430*e038c9c4Sjoerg     if (!MergeWithNextLine)
2431*e038c9c4Sjoerg       Prev = Pos + 1;
24327330f729Sjoerg     SearchFrom = Pos + 1;
24337330f729Sjoerg   }
24347330f729Sjoerg   if (!IncludesInBlock.empty()) {
24357330f729Sjoerg     sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Code, Replaces,
24367330f729Sjoerg                     Cursor);
24377330f729Sjoerg   }
24387330f729Sjoerg   return Replaces;
24397330f729Sjoerg }
24407330f729Sjoerg 
24417330f729Sjoerg // Returns group number to use as a first order sort on imports. Gives UINT_MAX
24427330f729Sjoerg // if the import does not match any given groups.
findJavaImportGroup(const FormatStyle & Style,StringRef ImportIdentifier)24437330f729Sjoerg static unsigned findJavaImportGroup(const FormatStyle &Style,
24447330f729Sjoerg                                     StringRef ImportIdentifier) {
24457330f729Sjoerg   unsigned LongestMatchIndex = UINT_MAX;
24467330f729Sjoerg   unsigned LongestMatchLength = 0;
24477330f729Sjoerg   for (unsigned I = 0; I < Style.JavaImportGroups.size(); I++) {
24487330f729Sjoerg     std::string GroupPrefix = Style.JavaImportGroups[I];
24497330f729Sjoerg     if (ImportIdentifier.startswith(GroupPrefix) &&
24507330f729Sjoerg         GroupPrefix.length() > LongestMatchLength) {
24517330f729Sjoerg       LongestMatchIndex = I;
24527330f729Sjoerg       LongestMatchLength = GroupPrefix.length();
24537330f729Sjoerg     }
24547330f729Sjoerg   }
24557330f729Sjoerg   return LongestMatchIndex;
24567330f729Sjoerg }
24577330f729Sjoerg 
24587330f729Sjoerg // Sorts and deduplicates a block of includes given by 'Imports' based on
24597330f729Sjoerg // JavaImportGroups, then adding the necessary replacement to 'Replaces'.
24607330f729Sjoerg // Import declarations with the same text will be deduplicated. Between each
24617330f729Sjoerg // import group, a newline is inserted, and within each import group, a
24627330f729Sjoerg // 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)24637330f729Sjoerg static void sortJavaImports(const FormatStyle &Style,
24647330f729Sjoerg                             const SmallVectorImpl<JavaImportDirective> &Imports,
24657330f729Sjoerg                             ArrayRef<tooling::Range> Ranges, StringRef FileName,
24667330f729Sjoerg                             StringRef Code, tooling::Replacements &Replaces) {
24677330f729Sjoerg   unsigned ImportsBeginOffset = Imports.front().Offset;
24687330f729Sjoerg   unsigned ImportsEndOffset =
24697330f729Sjoerg       Imports.back().Offset + Imports.back().Text.size();
24707330f729Sjoerg   unsigned ImportsBlockSize = ImportsEndOffset - ImportsBeginOffset;
24717330f729Sjoerg   if (!affectsRange(Ranges, ImportsBeginOffset, ImportsEndOffset))
24727330f729Sjoerg     return;
24737330f729Sjoerg   SmallVector<unsigned, 16> Indices;
24747330f729Sjoerg   SmallVector<unsigned, 16> JavaImportGroups;
24757330f729Sjoerg   for (unsigned i = 0, e = Imports.size(); i != e; ++i) {
24767330f729Sjoerg     Indices.push_back(i);
24777330f729Sjoerg     JavaImportGroups.push_back(
24787330f729Sjoerg         findJavaImportGroup(Style, Imports[i].Identifier));
24797330f729Sjoerg   }
2480*e038c9c4Sjoerg   bool StaticImportAfterNormalImport =
2481*e038c9c4Sjoerg       Style.SortJavaStaticImport == FormatStyle::SJSIO_After;
24827330f729Sjoerg   llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
24837330f729Sjoerg     // Negating IsStatic to push static imports above non-static imports.
2484*e038c9c4Sjoerg     return std::make_tuple(!Imports[LHSI].IsStatic ^
2485*e038c9c4Sjoerg                                StaticImportAfterNormalImport,
2486*e038c9c4Sjoerg                            JavaImportGroups[LHSI], Imports[LHSI].Identifier) <
2487*e038c9c4Sjoerg            std::make_tuple(!Imports[RHSI].IsStatic ^
2488*e038c9c4Sjoerg                                StaticImportAfterNormalImport,
2489*e038c9c4Sjoerg                            JavaImportGroups[RHSI], Imports[RHSI].Identifier);
24907330f729Sjoerg   });
24917330f729Sjoerg 
24927330f729Sjoerg   // Deduplicate imports.
24937330f729Sjoerg   Indices.erase(std::unique(Indices.begin(), Indices.end(),
24947330f729Sjoerg                             [&](unsigned LHSI, unsigned RHSI) {
24957330f729Sjoerg                               return Imports[LHSI].Text == Imports[RHSI].Text;
24967330f729Sjoerg                             }),
24977330f729Sjoerg                 Indices.end());
24987330f729Sjoerg 
24997330f729Sjoerg   bool CurrentIsStatic = Imports[Indices.front()].IsStatic;
25007330f729Sjoerg   unsigned CurrentImportGroup = JavaImportGroups[Indices.front()];
25017330f729Sjoerg 
25027330f729Sjoerg   std::string result;
25037330f729Sjoerg   for (unsigned Index : Indices) {
25047330f729Sjoerg     if (!result.empty()) {
25057330f729Sjoerg       result += "\n";
25067330f729Sjoerg       if (CurrentIsStatic != Imports[Index].IsStatic ||
25077330f729Sjoerg           CurrentImportGroup != JavaImportGroups[Index])
25087330f729Sjoerg         result += "\n";
25097330f729Sjoerg     }
25107330f729Sjoerg     for (StringRef CommentLine : Imports[Index].AssociatedCommentLines) {
25117330f729Sjoerg       result += CommentLine;
25127330f729Sjoerg       result += "\n";
25137330f729Sjoerg     }
25147330f729Sjoerg     result += Imports[Index].Text;
25157330f729Sjoerg     CurrentIsStatic = Imports[Index].IsStatic;
25167330f729Sjoerg     CurrentImportGroup = JavaImportGroups[Index];
25177330f729Sjoerg   }
25187330f729Sjoerg 
25197330f729Sjoerg   // If the imports are out of order, we generate a single replacement fixing
25207330f729Sjoerg   // the entire block. Otherwise, no replacement is generated.
2521*e038c9c4Sjoerg   if (replaceCRLF(result) == replaceCRLF(std::string(Code.substr(
2522*e038c9c4Sjoerg                                  Imports.front().Offset, ImportsBlockSize))))
25237330f729Sjoerg     return;
25247330f729Sjoerg 
25257330f729Sjoerg   auto Err = Replaces.add(tooling::Replacement(FileName, Imports.front().Offset,
25267330f729Sjoerg                                                ImportsBlockSize, result));
25277330f729Sjoerg   // FIXME: better error handling. For now, just skip the replacement for the
25287330f729Sjoerg   // release version.
25297330f729Sjoerg   if (Err) {
25307330f729Sjoerg     llvm::errs() << llvm::toString(std::move(Err)) << "\n";
25317330f729Sjoerg     assert(false);
25327330f729Sjoerg   }
25337330f729Sjoerg }
25347330f729Sjoerg 
25357330f729Sjoerg namespace {
25367330f729Sjoerg 
25377330f729Sjoerg const char JavaImportRegexPattern[] =
25387330f729Sjoerg     "^[\t ]*import[\t ]+(static[\t ]*)?([^\t ]*)[\t ]*;";
25397330f729Sjoerg 
25407330f729Sjoerg } // anonymous namespace
25417330f729Sjoerg 
sortJavaImports(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName,tooling::Replacements & Replaces)25427330f729Sjoerg tooling::Replacements sortJavaImports(const FormatStyle &Style, StringRef Code,
25437330f729Sjoerg                                       ArrayRef<tooling::Range> Ranges,
25447330f729Sjoerg                                       StringRef FileName,
25457330f729Sjoerg                                       tooling::Replacements &Replaces) {
25467330f729Sjoerg   unsigned Prev = 0;
25477330f729Sjoerg   unsigned SearchFrom = 0;
25487330f729Sjoerg   llvm::Regex ImportRegex(JavaImportRegexPattern);
25497330f729Sjoerg   SmallVector<StringRef, 4> Matches;
25507330f729Sjoerg   SmallVector<JavaImportDirective, 16> ImportsInBlock;
25517330f729Sjoerg   std::vector<StringRef> AssociatedCommentLines;
25527330f729Sjoerg 
25537330f729Sjoerg   bool FormattingOff = false;
25547330f729Sjoerg 
25557330f729Sjoerg   for (;;) {
25567330f729Sjoerg     auto Pos = Code.find('\n', SearchFrom);
25577330f729Sjoerg     StringRef Line =
25587330f729Sjoerg         Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
25597330f729Sjoerg 
25607330f729Sjoerg     StringRef Trimmed = Line.trim();
25617330f729Sjoerg     if (Trimmed == "// clang-format off")
25627330f729Sjoerg       FormattingOff = true;
25637330f729Sjoerg     else if (Trimmed == "// clang-format on")
25647330f729Sjoerg       FormattingOff = false;
25657330f729Sjoerg 
25667330f729Sjoerg     if (ImportRegex.match(Line, &Matches)) {
25677330f729Sjoerg       if (FormattingOff) {
25687330f729Sjoerg         // If at least one import line has formatting turned off, turn off
25697330f729Sjoerg         // formatting entirely.
25707330f729Sjoerg         return Replaces;
25717330f729Sjoerg       }
25727330f729Sjoerg       StringRef Static = Matches[1];
25737330f729Sjoerg       StringRef Identifier = Matches[2];
25747330f729Sjoerg       bool IsStatic = false;
25757330f729Sjoerg       if (Static.contains("static")) {
25767330f729Sjoerg         IsStatic = true;
25777330f729Sjoerg       }
25787330f729Sjoerg       ImportsInBlock.push_back(
25797330f729Sjoerg           {Identifier, Line, Prev, AssociatedCommentLines, IsStatic});
25807330f729Sjoerg       AssociatedCommentLines.clear();
25817330f729Sjoerg     } else if (Trimmed.size() > 0 && !ImportsInBlock.empty()) {
25827330f729Sjoerg       // Associating comments within the imports with the nearest import below
25837330f729Sjoerg       AssociatedCommentLines.push_back(Line);
25847330f729Sjoerg     }
25857330f729Sjoerg     Prev = Pos + 1;
25867330f729Sjoerg     if (Pos == StringRef::npos || Pos + 1 == Code.size())
25877330f729Sjoerg       break;
25887330f729Sjoerg     SearchFrom = Pos + 1;
25897330f729Sjoerg   }
25907330f729Sjoerg   if (!ImportsInBlock.empty())
25917330f729Sjoerg     sortJavaImports(Style, ImportsInBlock, Ranges, FileName, Code, Replaces);
25927330f729Sjoerg   return Replaces;
25937330f729Sjoerg }
25947330f729Sjoerg 
isMpegTS(StringRef Code)25957330f729Sjoerg bool isMpegTS(StringRef Code) {
25967330f729Sjoerg   // MPEG transport streams use the ".ts" file extension. clang-format should
25977330f729Sjoerg   // not attempt to format those. MPEG TS' frame format starts with 0x47 every
25987330f729Sjoerg   // 189 bytes - detect that and return.
25997330f729Sjoerg   return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
26007330f729Sjoerg }
26017330f729Sjoerg 
isLikelyXml(StringRef Code)26027330f729Sjoerg bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); }
26037330f729Sjoerg 
sortIncludes(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName,unsigned * Cursor)26047330f729Sjoerg tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
26057330f729Sjoerg                                    ArrayRef<tooling::Range> Ranges,
26067330f729Sjoerg                                    StringRef FileName, unsigned *Cursor) {
26077330f729Sjoerg   tooling::Replacements Replaces;
2608*e038c9c4Sjoerg   if (!Style.SortIncludes || Style.DisableFormat)
26097330f729Sjoerg     return Replaces;
26107330f729Sjoerg   if (isLikelyXml(Code))
26117330f729Sjoerg     return Replaces;
26127330f729Sjoerg   if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript &&
26137330f729Sjoerg       isMpegTS(Code))
26147330f729Sjoerg     return Replaces;
26157330f729Sjoerg   if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript)
26167330f729Sjoerg     return sortJavaScriptImports(Style, Code, Ranges, FileName);
26177330f729Sjoerg   if (Style.Language == FormatStyle::LanguageKind::LK_Java)
26187330f729Sjoerg     return sortJavaImports(Style, Code, Ranges, FileName, Replaces);
26197330f729Sjoerg   sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor);
26207330f729Sjoerg   return Replaces;
26217330f729Sjoerg }
26227330f729Sjoerg 
26237330f729Sjoerg template <typename T>
26247330f729Sjoerg static llvm::Expected<tooling::Replacements>
processReplacements(T ProcessFunc,StringRef Code,const tooling::Replacements & Replaces,const FormatStyle & Style)26257330f729Sjoerg processReplacements(T ProcessFunc, StringRef Code,
26267330f729Sjoerg                     const tooling::Replacements &Replaces,
26277330f729Sjoerg                     const FormatStyle &Style) {
26287330f729Sjoerg   if (Replaces.empty())
26297330f729Sjoerg     return tooling::Replacements();
26307330f729Sjoerg 
26317330f729Sjoerg   auto NewCode = applyAllReplacements(Code, Replaces);
26327330f729Sjoerg   if (!NewCode)
26337330f729Sjoerg     return NewCode.takeError();
26347330f729Sjoerg   std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();
26357330f729Sjoerg   StringRef FileName = Replaces.begin()->getFilePath();
26367330f729Sjoerg 
26377330f729Sjoerg   tooling::Replacements FormatReplaces =
26387330f729Sjoerg       ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
26397330f729Sjoerg 
26407330f729Sjoerg   return Replaces.merge(FormatReplaces);
26417330f729Sjoerg }
26427330f729Sjoerg 
26437330f729Sjoerg llvm::Expected<tooling::Replacements>
formatReplacements(StringRef Code,const tooling::Replacements & Replaces,const FormatStyle & Style)26447330f729Sjoerg formatReplacements(StringRef Code, const tooling::Replacements &Replaces,
26457330f729Sjoerg                    const FormatStyle &Style) {
26467330f729Sjoerg   // We need to use lambda function here since there are two versions of
26477330f729Sjoerg   // `sortIncludes`.
26487330f729Sjoerg   auto SortIncludes = [](const FormatStyle &Style, StringRef Code,
26497330f729Sjoerg                          std::vector<tooling::Range> Ranges,
26507330f729Sjoerg                          StringRef FileName) -> tooling::Replacements {
26517330f729Sjoerg     return sortIncludes(Style, Code, Ranges, FileName);
26527330f729Sjoerg   };
26537330f729Sjoerg   auto SortedReplaces =
26547330f729Sjoerg       processReplacements(SortIncludes, Code, Replaces, Style);
26557330f729Sjoerg   if (!SortedReplaces)
26567330f729Sjoerg     return SortedReplaces.takeError();
26577330f729Sjoerg 
26587330f729Sjoerg   // We need to use lambda function here since there are two versions of
26597330f729Sjoerg   // `reformat`.
26607330f729Sjoerg   auto Reformat = [](const FormatStyle &Style, StringRef Code,
26617330f729Sjoerg                      std::vector<tooling::Range> Ranges,
26627330f729Sjoerg                      StringRef FileName) -> tooling::Replacements {
26637330f729Sjoerg     return reformat(Style, Code, Ranges, FileName);
26647330f729Sjoerg   };
26657330f729Sjoerg   return processReplacements(Reformat, Code, *SortedReplaces, Style);
26667330f729Sjoerg }
26677330f729Sjoerg 
26687330f729Sjoerg namespace {
26697330f729Sjoerg 
isHeaderInsertion(const tooling::Replacement & Replace)26707330f729Sjoerg inline bool isHeaderInsertion(const tooling::Replacement &Replace) {
26717330f729Sjoerg   return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 &&
26727330f729Sjoerg          llvm::Regex(CppIncludeRegexPattern)
26737330f729Sjoerg              .match(Replace.getReplacementText());
26747330f729Sjoerg }
26757330f729Sjoerg 
isHeaderDeletion(const tooling::Replacement & Replace)26767330f729Sjoerg inline bool isHeaderDeletion(const tooling::Replacement &Replace) {
26777330f729Sjoerg   return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1;
26787330f729Sjoerg }
26797330f729Sjoerg 
26807330f729Sjoerg // FIXME: insert empty lines between newly created blocks.
26817330f729Sjoerg tooling::Replacements
fixCppIncludeInsertions(StringRef Code,const tooling::Replacements & Replaces,const FormatStyle & Style)26827330f729Sjoerg fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
26837330f729Sjoerg                         const FormatStyle &Style) {
26847330f729Sjoerg   if (!Style.isCpp())
26857330f729Sjoerg     return Replaces;
26867330f729Sjoerg 
26877330f729Sjoerg   tooling::Replacements HeaderInsertions;
26887330f729Sjoerg   std::set<llvm::StringRef> HeadersToDelete;
26897330f729Sjoerg   tooling::Replacements Result;
26907330f729Sjoerg   for (const auto &R : Replaces) {
26917330f729Sjoerg     if (isHeaderInsertion(R)) {
26927330f729Sjoerg       // Replacements from \p Replaces must be conflict-free already, so we can
26937330f729Sjoerg       // simply consume the error.
26947330f729Sjoerg       llvm::consumeError(HeaderInsertions.add(R));
26957330f729Sjoerg     } else if (isHeaderDeletion(R)) {
26967330f729Sjoerg       HeadersToDelete.insert(R.getReplacementText());
26977330f729Sjoerg     } else if (R.getOffset() == UINT_MAX) {
26987330f729Sjoerg       llvm::errs() << "Insertions other than header #include insertion are "
26997330f729Sjoerg                       "not supported! "
27007330f729Sjoerg                    << R.getReplacementText() << "\n";
27017330f729Sjoerg     } else {
27027330f729Sjoerg       llvm::consumeError(Result.add(R));
27037330f729Sjoerg     }
27047330f729Sjoerg   }
27057330f729Sjoerg   if (HeaderInsertions.empty() && HeadersToDelete.empty())
27067330f729Sjoerg     return Replaces;
27077330f729Sjoerg 
27087330f729Sjoerg   StringRef FileName = Replaces.begin()->getFilePath();
27097330f729Sjoerg   tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle);
27107330f729Sjoerg 
27117330f729Sjoerg   for (const auto &Header : HeadersToDelete) {
27127330f729Sjoerg     tooling::Replacements Replaces =
27137330f729Sjoerg         Includes.remove(Header.trim("\"<>"), Header.startswith("<"));
27147330f729Sjoerg     for (const auto &R : Replaces) {
27157330f729Sjoerg       auto Err = Result.add(R);
27167330f729Sjoerg       if (Err) {
27177330f729Sjoerg         // Ignore the deletion on conflict.
27187330f729Sjoerg         llvm::errs() << "Failed to add header deletion replacement for "
27197330f729Sjoerg                      << Header << ": " << llvm::toString(std::move(Err))
27207330f729Sjoerg                      << "\n";
27217330f729Sjoerg       }
27227330f729Sjoerg     }
27237330f729Sjoerg   }
27247330f729Sjoerg 
27257330f729Sjoerg   llvm::Regex IncludeRegex = llvm::Regex(CppIncludeRegexPattern);
27267330f729Sjoerg   llvm::SmallVector<StringRef, 4> Matches;
27277330f729Sjoerg   for (const auto &R : HeaderInsertions) {
27287330f729Sjoerg     auto IncludeDirective = R.getReplacementText();
27297330f729Sjoerg     bool Matched = IncludeRegex.match(IncludeDirective, &Matches);
27307330f729Sjoerg     assert(Matched && "Header insertion replacement must have replacement text "
27317330f729Sjoerg                       "'#include ...'");
27327330f729Sjoerg     (void)Matched;
27337330f729Sjoerg     auto IncludeName = Matches[2];
27347330f729Sjoerg     auto Replace =
27357330f729Sjoerg         Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<"));
27367330f729Sjoerg     if (Replace) {
27377330f729Sjoerg       auto Err = Result.add(*Replace);
27387330f729Sjoerg       if (Err) {
27397330f729Sjoerg         llvm::consumeError(std::move(Err));
27407330f729Sjoerg         unsigned NewOffset =
27417330f729Sjoerg             Result.getShiftedCodePosition(Replace->getOffset());
27427330f729Sjoerg         auto Shifted = tooling::Replacement(FileName, NewOffset, 0,
27437330f729Sjoerg                                             Replace->getReplacementText());
27447330f729Sjoerg         Result = Result.merge(tooling::Replacements(Shifted));
27457330f729Sjoerg       }
27467330f729Sjoerg     }
27477330f729Sjoerg   }
27487330f729Sjoerg   return Result;
27497330f729Sjoerg }
27507330f729Sjoerg 
27517330f729Sjoerg } // anonymous namespace
27527330f729Sjoerg 
27537330f729Sjoerg llvm::Expected<tooling::Replacements>
cleanupAroundReplacements(StringRef Code,const tooling::Replacements & Replaces,const FormatStyle & Style)27547330f729Sjoerg cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
27557330f729Sjoerg                           const FormatStyle &Style) {
27567330f729Sjoerg   // We need to use lambda function here since there are two versions of
27577330f729Sjoerg   // `cleanup`.
27587330f729Sjoerg   auto Cleanup = [](const FormatStyle &Style, StringRef Code,
27597330f729Sjoerg                     std::vector<tooling::Range> Ranges,
27607330f729Sjoerg                     StringRef FileName) -> tooling::Replacements {
27617330f729Sjoerg     return cleanup(Style, Code, Ranges, FileName);
27627330f729Sjoerg   };
27637330f729Sjoerg   // Make header insertion replacements insert new headers into correct blocks.
27647330f729Sjoerg   tooling::Replacements NewReplaces =
27657330f729Sjoerg       fixCppIncludeInsertions(Code, Replaces, Style);
27667330f729Sjoerg   return processReplacements(Cleanup, Code, NewReplaces, Style);
27677330f729Sjoerg }
27687330f729Sjoerg 
27697330f729Sjoerg namespace internal {
27707330f729Sjoerg 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)27717330f729Sjoerg reformat(const FormatStyle &Style, StringRef Code,
27727330f729Sjoerg          ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,
27737330f729Sjoerg          unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,
27747330f729Sjoerg          FormattingAttemptStatus *Status) {
27757330f729Sjoerg   FormatStyle Expanded = expandPresets(Style);
27767330f729Sjoerg   if (Expanded.DisableFormat)
27777330f729Sjoerg     return {tooling::Replacements(), 0};
27787330f729Sjoerg   if (isLikelyXml(Code))
27797330f729Sjoerg     return {tooling::Replacements(), 0};
27807330f729Sjoerg   if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code))
27817330f729Sjoerg     return {tooling::Replacements(), 0};
27827330f729Sjoerg 
27837330f729Sjoerg   typedef std::function<std::pair<tooling::Replacements, unsigned>(
27847330f729Sjoerg       const Environment &)>
27857330f729Sjoerg       AnalyzerPass;
27867330f729Sjoerg   SmallVector<AnalyzerPass, 4> Passes;
27877330f729Sjoerg 
27887330f729Sjoerg   if (Style.Language == FormatStyle::LK_Cpp) {
27897330f729Sjoerg     if (Style.FixNamespaceComments)
27907330f729Sjoerg       Passes.emplace_back([&](const Environment &Env) {
27917330f729Sjoerg         return NamespaceEndCommentsFixer(Env, Expanded).process();
27927330f729Sjoerg       });
27937330f729Sjoerg 
27947330f729Sjoerg     if (Style.SortUsingDeclarations)
27957330f729Sjoerg       Passes.emplace_back([&](const Environment &Env) {
27967330f729Sjoerg         return UsingDeclarationsSorter(Env, Expanded).process();
27977330f729Sjoerg       });
27987330f729Sjoerg   }
27997330f729Sjoerg 
28007330f729Sjoerg   if (Style.Language == FormatStyle::LK_JavaScript &&
28017330f729Sjoerg       Style.JavaScriptQuotes != FormatStyle::JSQS_Leave)
28027330f729Sjoerg     Passes.emplace_back([&](const Environment &Env) {
28037330f729Sjoerg       return JavaScriptRequoter(Env, Expanded).process();
28047330f729Sjoerg     });
28057330f729Sjoerg 
28067330f729Sjoerg   Passes.emplace_back([&](const Environment &Env) {
28077330f729Sjoerg     return Formatter(Env, Expanded, Status).process();
28087330f729Sjoerg   });
28097330f729Sjoerg 
2810*e038c9c4Sjoerg   if (Style.Language == FormatStyle::LK_JavaScript &&
2811*e038c9c4Sjoerg       Style.InsertTrailingCommas == FormatStyle::TCS_Wrapped)
2812*e038c9c4Sjoerg     Passes.emplace_back([&](const Environment &Env) {
2813*e038c9c4Sjoerg       return TrailingCommaInserter(Env, Expanded).process();
2814*e038c9c4Sjoerg     });
2815*e038c9c4Sjoerg 
28167330f729Sjoerg   auto Env =
28177330f729Sjoerg       std::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn,
28187330f729Sjoerg                                     NextStartColumn, LastStartColumn);
28197330f729Sjoerg   llvm::Optional<std::string> CurrentCode = None;
28207330f729Sjoerg   tooling::Replacements Fixes;
28217330f729Sjoerg   unsigned Penalty = 0;
28227330f729Sjoerg   for (size_t I = 0, E = Passes.size(); I < E; ++I) {
28237330f729Sjoerg     std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
28247330f729Sjoerg     auto NewCode = applyAllReplacements(
28257330f729Sjoerg         CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
28267330f729Sjoerg     if (NewCode) {
28277330f729Sjoerg       Fixes = Fixes.merge(PassFixes.first);
28287330f729Sjoerg       Penalty += PassFixes.second;
28297330f729Sjoerg       if (I + 1 < E) {
28307330f729Sjoerg         CurrentCode = std::move(*NewCode);
28317330f729Sjoerg         Env = std::make_unique<Environment>(
28327330f729Sjoerg             *CurrentCode, FileName,
28337330f729Sjoerg             tooling::calculateRangesAfterReplacements(Fixes, Ranges),
28347330f729Sjoerg             FirstStartColumn, NextStartColumn, LastStartColumn);
28357330f729Sjoerg       }
28367330f729Sjoerg     }
28377330f729Sjoerg   }
28387330f729Sjoerg 
28397330f729Sjoerg   return {Fixes, Penalty};
28407330f729Sjoerg }
28417330f729Sjoerg } // namespace internal
28427330f729Sjoerg 
reformat(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName,FormattingAttemptStatus * Status)28437330f729Sjoerg tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
28447330f729Sjoerg                                ArrayRef<tooling::Range> Ranges,
28457330f729Sjoerg                                StringRef FileName,
28467330f729Sjoerg                                FormattingAttemptStatus *Status) {
28477330f729Sjoerg   return internal::reformat(Style, Code, Ranges,
28487330f729Sjoerg                             /*FirstStartColumn=*/0,
28497330f729Sjoerg                             /*NextStartColumn=*/0,
28507330f729Sjoerg                             /*LastStartColumn=*/0, FileName, Status)
28517330f729Sjoerg       .first;
28527330f729Sjoerg }
28537330f729Sjoerg 
cleanup(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName)28547330f729Sjoerg tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
28557330f729Sjoerg                               ArrayRef<tooling::Range> Ranges,
28567330f729Sjoerg                               StringRef FileName) {
28577330f729Sjoerg   // cleanups only apply to C++ (they mostly concern ctor commas etc.)
28587330f729Sjoerg   if (Style.Language != FormatStyle::LK_Cpp)
28597330f729Sjoerg     return tooling::Replacements();
28607330f729Sjoerg   return Cleaner(Environment(Code, FileName, Ranges), Style).process().first;
28617330f729Sjoerg }
28627330f729Sjoerg 
reformat(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName,bool * IncompleteFormat)28637330f729Sjoerg tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
28647330f729Sjoerg                                ArrayRef<tooling::Range> Ranges,
28657330f729Sjoerg                                StringRef FileName, bool *IncompleteFormat) {
28667330f729Sjoerg   FormattingAttemptStatus Status;
28677330f729Sjoerg   auto Result = reformat(Style, Code, Ranges, FileName, &Status);
28687330f729Sjoerg   if (!Status.FormatComplete)
28697330f729Sjoerg     *IncompleteFormat = true;
28707330f729Sjoerg   return Result;
28717330f729Sjoerg }
28727330f729Sjoerg 
fixNamespaceEndComments(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName)28737330f729Sjoerg tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,
28747330f729Sjoerg                                               StringRef Code,
28757330f729Sjoerg                                               ArrayRef<tooling::Range> Ranges,
28767330f729Sjoerg                                               StringRef FileName) {
28777330f729Sjoerg   return NamespaceEndCommentsFixer(Environment(Code, FileName, Ranges), Style)
28787330f729Sjoerg       .process()
28797330f729Sjoerg       .first;
28807330f729Sjoerg }
28817330f729Sjoerg 
sortUsingDeclarations(const FormatStyle & Style,StringRef Code,ArrayRef<tooling::Range> Ranges,StringRef FileName)28827330f729Sjoerg tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
28837330f729Sjoerg                                             StringRef Code,
28847330f729Sjoerg                                             ArrayRef<tooling::Range> Ranges,
28857330f729Sjoerg                                             StringRef FileName) {
28867330f729Sjoerg   return UsingDeclarationsSorter(Environment(Code, FileName, Ranges), Style)
28877330f729Sjoerg       .process()
28887330f729Sjoerg       .first;
28897330f729Sjoerg }
28907330f729Sjoerg 
getFormattingLangOpts(const FormatStyle & Style)28917330f729Sjoerg LangOptions getFormattingLangOpts(const FormatStyle &Style) {
28927330f729Sjoerg   LangOptions LangOpts;
28937330f729Sjoerg 
28947330f729Sjoerg   FormatStyle::LanguageStandard LexingStd = Style.Standard;
28957330f729Sjoerg   if (LexingStd == FormatStyle::LS_Auto)
28967330f729Sjoerg     LexingStd = FormatStyle::LS_Latest;
28977330f729Sjoerg   if (LexingStd == FormatStyle::LS_Latest)
28987330f729Sjoerg     LexingStd = FormatStyle::LS_Cpp20;
28997330f729Sjoerg   LangOpts.CPlusPlus = 1;
29007330f729Sjoerg   LangOpts.CPlusPlus11 = LexingStd >= FormatStyle::LS_Cpp11;
29017330f729Sjoerg   LangOpts.CPlusPlus14 = LexingStd >= FormatStyle::LS_Cpp14;
29027330f729Sjoerg   LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17;
2903*e038c9c4Sjoerg   LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20;
2904*e038c9c4Sjoerg   LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20;
29057330f729Sjoerg 
29067330f729Sjoerg   LangOpts.LineComment = 1;
29077330f729Sjoerg   bool AlternativeOperators = Style.isCpp();
29087330f729Sjoerg   LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
29097330f729Sjoerg   LangOpts.Bool = 1;
29107330f729Sjoerg   LangOpts.ObjC = 1;
29117330f729Sjoerg   LangOpts.MicrosoftExt = 1;    // To get kw___try, kw___finally.
29127330f729Sjoerg   LangOpts.DeclSpecKeyword = 1; // To get __declspec.
2913*e038c9c4Sjoerg   LangOpts.C99 = 1; // To get kw_restrict for non-underscore-prefixed restrict.
29147330f729Sjoerg   return LangOpts;
29157330f729Sjoerg }
29167330f729Sjoerg 
29177330f729Sjoerg const char *StyleOptionHelpDescription =
29187330f729Sjoerg     "Coding style, currently supports:\n"
2919*e038c9c4Sjoerg     "  LLVM, GNU, Google, Chromium, Microsoft, Mozilla, WebKit.\n"
29207330f729Sjoerg     "Use -style=file to load style configuration from\n"
29217330f729Sjoerg     ".clang-format file located in one of the parent\n"
29227330f729Sjoerg     "directories of the source file (or current\n"
29237330f729Sjoerg     "directory for stdin).\n"
29247330f729Sjoerg     "Use -style=\"{key: value, ...}\" to set specific\n"
29257330f729Sjoerg     "parameters, e.g.:\n"
29267330f729Sjoerg     "  -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
29277330f729Sjoerg 
getLanguageByFileName(StringRef FileName)29287330f729Sjoerg static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
29297330f729Sjoerg   if (FileName.endswith(".java"))
29307330f729Sjoerg     return FormatStyle::LK_Java;
29317330f729Sjoerg   if (FileName.endswith_lower(".js") || FileName.endswith_lower(".mjs") ||
29327330f729Sjoerg       FileName.endswith_lower(".ts"))
29337330f729Sjoerg     return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript.
29347330f729Sjoerg   if (FileName.endswith(".m") || FileName.endswith(".mm"))
29357330f729Sjoerg     return FormatStyle::LK_ObjC;
29367330f729Sjoerg   if (FileName.endswith_lower(".proto") ||
29377330f729Sjoerg       FileName.endswith_lower(".protodevel"))
29387330f729Sjoerg     return FormatStyle::LK_Proto;
29397330f729Sjoerg   if (FileName.endswith_lower(".textpb") ||
29407330f729Sjoerg       FileName.endswith_lower(".pb.txt") ||
29417330f729Sjoerg       FileName.endswith_lower(".textproto") ||
29427330f729Sjoerg       FileName.endswith_lower(".asciipb"))
29437330f729Sjoerg     return FormatStyle::LK_TextProto;
29447330f729Sjoerg   if (FileName.endswith_lower(".td"))
29457330f729Sjoerg     return FormatStyle::LK_TableGen;
29467330f729Sjoerg   if (FileName.endswith_lower(".cs"))
29477330f729Sjoerg     return FormatStyle::LK_CSharp;
29487330f729Sjoerg   return FormatStyle::LK_Cpp;
29497330f729Sjoerg }
29507330f729Sjoerg 
guessLanguage(StringRef FileName,StringRef Code)29517330f729Sjoerg FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {
29527330f729Sjoerg   const auto GuessedLanguage = getLanguageByFileName(FileName);
29537330f729Sjoerg   if (GuessedLanguage == FormatStyle::LK_Cpp) {
29547330f729Sjoerg     auto Extension = llvm::sys::path::extension(FileName);
29557330f729Sjoerg     // If there's no file extension (or it's .h), we need to check the contents
29567330f729Sjoerg     // of the code to see if it contains Objective-C.
29577330f729Sjoerg     if (Extension.empty() || Extension == ".h") {
29587330f729Sjoerg       auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName;
29597330f729Sjoerg       Environment Env(Code, NonEmptyFileName, /*Ranges=*/{});
29607330f729Sjoerg       ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle());
29617330f729Sjoerg       Guesser.process();
29627330f729Sjoerg       if (Guesser.isObjC())
29637330f729Sjoerg         return FormatStyle::LK_ObjC;
29647330f729Sjoerg     }
29657330f729Sjoerg   }
29667330f729Sjoerg   return GuessedLanguage;
29677330f729Sjoerg }
29687330f729Sjoerg 
29697330f729Sjoerg const char *DefaultFormatStyle = "file";
29707330f729Sjoerg 
29717330f729Sjoerg const char *DefaultFallbackStyle = "LLVM";
29727330f729Sjoerg 
getStyle(StringRef StyleName,StringRef FileName,StringRef FallbackStyleName,StringRef Code,llvm::vfs::FileSystem * FS,bool AllowUnknownOptions)29737330f729Sjoerg llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
29747330f729Sjoerg                                      StringRef FallbackStyleName,
2975*e038c9c4Sjoerg                                      StringRef Code, llvm::vfs::FileSystem *FS,
2976*e038c9c4Sjoerg                                      bool AllowUnknownOptions) {
29777330f729Sjoerg   if (!FS) {
29787330f729Sjoerg     FS = llvm::vfs::getRealFileSystem().get();
29797330f729Sjoerg   }
29807330f729Sjoerg   FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code));
29817330f729Sjoerg 
29827330f729Sjoerg   FormatStyle FallbackStyle = getNoStyle();
29837330f729Sjoerg   if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))
29847330f729Sjoerg     return make_string_error("Invalid fallback style \"" + FallbackStyleName);
29857330f729Sjoerg 
2986*e038c9c4Sjoerg   llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1>
2987*e038c9c4Sjoerg       ChildFormatTextToApply;
2988*e038c9c4Sjoerg 
29897330f729Sjoerg   if (StyleName.startswith("{")) {
29907330f729Sjoerg     // Parse YAML/JSON style from the command line.
2991*e038c9c4Sjoerg     StringRef Source = "<command-line>";
2992*e038c9c4Sjoerg     if (std::error_code ec =
2993*e038c9c4Sjoerg             parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style,
2994*e038c9c4Sjoerg                                AllowUnknownOptions))
29957330f729Sjoerg       return make_string_error("Error parsing -style: " + ec.message());
2996*e038c9c4Sjoerg     if (Style.InheritsParentConfig)
2997*e038c9c4Sjoerg       ChildFormatTextToApply.emplace_back(
2998*e038c9c4Sjoerg           llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false));
2999*e038c9c4Sjoerg     else
30007330f729Sjoerg       return Style;
30017330f729Sjoerg   }
30027330f729Sjoerg 
3003*e038c9c4Sjoerg   // If the style inherits the parent configuration it is a command line
3004*e038c9c4Sjoerg   // configuration, which wants to inherit, so we have to skip the check of the
3005*e038c9c4Sjoerg   // StyleName.
3006*e038c9c4Sjoerg   if (!Style.InheritsParentConfig && !StyleName.equals_lower("file")) {
30077330f729Sjoerg     if (!getPredefinedStyle(StyleName, Style.Language, &Style))
30087330f729Sjoerg       return make_string_error("Invalid value for -style");
3009*e038c9c4Sjoerg     if (!Style.InheritsParentConfig)
30107330f729Sjoerg       return Style;
30117330f729Sjoerg   }
30127330f729Sjoerg 
3013*e038c9c4Sjoerg   // Reset possible inheritance
3014*e038c9c4Sjoerg   Style.InheritsParentConfig = false;
3015*e038c9c4Sjoerg 
30167330f729Sjoerg   // Look for .clang-format/_clang-format file in the file's parent directories.
30177330f729Sjoerg   SmallString<128> UnsuitableConfigFiles;
30187330f729Sjoerg   SmallString<128> Path(FileName);
30197330f729Sjoerg   if (std::error_code EC = FS->makeAbsolute(Path))
30207330f729Sjoerg     return make_string_error(EC.message());
30217330f729Sjoerg 
3022*e038c9c4Sjoerg   llvm::SmallVector<std::string, 2> FilesToLookFor;
3023*e038c9c4Sjoerg   FilesToLookFor.push_back(".clang-format");
3024*e038c9c4Sjoerg   FilesToLookFor.push_back("_clang-format");
3025*e038c9c4Sjoerg 
3026*e038c9c4Sjoerg   auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {};
3027*e038c9c4Sjoerg 
30287330f729Sjoerg   for (StringRef Directory = Path; !Directory.empty();
30297330f729Sjoerg        Directory = llvm::sys::path::parent_path(Directory)) {
30307330f729Sjoerg 
30317330f729Sjoerg     auto Status = FS->status(Directory);
30327330f729Sjoerg     if (!Status ||
30337330f729Sjoerg         Status->getType() != llvm::sys::fs::file_type::directory_file) {
30347330f729Sjoerg       continue;
30357330f729Sjoerg     }
30367330f729Sjoerg 
3037*e038c9c4Sjoerg     for (const auto &F : FilesToLookFor) {
30387330f729Sjoerg       SmallString<128> ConfigFile(Directory);
30397330f729Sjoerg 
3040*e038c9c4Sjoerg       llvm::sys::path::append(ConfigFile, F);
30417330f729Sjoerg       LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
30427330f729Sjoerg 
30437330f729Sjoerg       Status = FS->status(ConfigFile.str());
30447330f729Sjoerg 
3045*e038c9c4Sjoerg       if (Status &&
3046*e038c9c4Sjoerg           (Status->getType() == llvm::sys::fs::file_type::regular_file)) {
30477330f729Sjoerg         llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
30487330f729Sjoerg             FS->getBufferForFile(ConfigFile.str());
30497330f729Sjoerg         if (std::error_code EC = Text.getError())
30507330f729Sjoerg           return make_string_error(EC.message());
30517330f729Sjoerg         if (std::error_code ec =
3052*e038c9c4Sjoerg                 parseConfiguration(*Text.get(), &Style, AllowUnknownOptions)) {
30537330f729Sjoerg           if (ec == ParseError::Unsuitable) {
30547330f729Sjoerg             if (!UnsuitableConfigFiles.empty())
30557330f729Sjoerg               UnsuitableConfigFiles.append(", ");
30567330f729Sjoerg             UnsuitableConfigFiles.append(ConfigFile);
30577330f729Sjoerg             continue;
30587330f729Sjoerg           }
30597330f729Sjoerg           return make_string_error("Error reading " + ConfigFile + ": " +
30607330f729Sjoerg                                    ec.message());
30617330f729Sjoerg         }
30627330f729Sjoerg         LLVM_DEBUG(llvm::dbgs()
30637330f729Sjoerg                    << "Using configuration file " << ConfigFile << "\n");
3064*e038c9c4Sjoerg 
3065*e038c9c4Sjoerg         if (!Style.InheritsParentConfig) {
3066*e038c9c4Sjoerg           if (ChildFormatTextToApply.empty())
30677330f729Sjoerg             return Style;
3068*e038c9c4Sjoerg 
3069*e038c9c4Sjoerg           LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n");
3070*e038c9c4Sjoerg 
3071*e038c9c4Sjoerg           for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) {
3072*e038c9c4Sjoerg             auto Ec = parseConfiguration(*MemBuf, &Style, AllowUnknownOptions,
3073*e038c9c4Sjoerg                                          dropDiagnosticHandler);
3074*e038c9c4Sjoerg             // It was already correctly parsed.
3075*e038c9c4Sjoerg             assert(!Ec);
3076*e038c9c4Sjoerg             static_cast<void>(Ec);
3077*e038c9c4Sjoerg           }
3078*e038c9c4Sjoerg 
3079*e038c9c4Sjoerg           return Style;
3080*e038c9c4Sjoerg         }
3081*e038c9c4Sjoerg 
3082*e038c9c4Sjoerg         LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n");
3083*e038c9c4Sjoerg 
3084*e038c9c4Sjoerg         // Reset inheritance of style
3085*e038c9c4Sjoerg         Style.InheritsParentConfig = false;
3086*e038c9c4Sjoerg 
3087*e038c9c4Sjoerg         ChildFormatTextToApply.emplace_back(std::move(*Text));
3088*e038c9c4Sjoerg 
3089*e038c9c4Sjoerg         // Breaking out of the inner loop, since we don't want to parse
3090*e038c9c4Sjoerg         // .clang-format AND _clang-format, if both exist. Then we continue the
3091*e038c9c4Sjoerg         // inner loop (parent directories) in search for the parent
3092*e038c9c4Sjoerg         // configuration.
3093*e038c9c4Sjoerg         break;
3094*e038c9c4Sjoerg       }
30957330f729Sjoerg     }
30967330f729Sjoerg   }
30977330f729Sjoerg   if (!UnsuitableConfigFiles.empty())
30987330f729Sjoerg     return make_string_error("Configuration file(s) do(es) not support " +
30997330f729Sjoerg                              getLanguageName(Style.Language) + ": " +
31007330f729Sjoerg                              UnsuitableConfigFiles);
3101*e038c9c4Sjoerg 
3102*e038c9c4Sjoerg   if (!ChildFormatTextToApply.empty()) {
3103*e038c9c4Sjoerg     assert(ChildFormatTextToApply.size() == 1);
3104*e038c9c4Sjoerg 
3105*e038c9c4Sjoerg     LLVM_DEBUG(llvm::dbgs()
3106*e038c9c4Sjoerg                << "Applying child configuration on fallback style\n");
3107*e038c9c4Sjoerg 
3108*e038c9c4Sjoerg     auto Ec =
3109*e038c9c4Sjoerg         parseConfiguration(*ChildFormatTextToApply.front(), &FallbackStyle,
3110*e038c9c4Sjoerg                            AllowUnknownOptions, dropDiagnosticHandler);
3111*e038c9c4Sjoerg     // It was already correctly parsed.
3112*e038c9c4Sjoerg     assert(!Ec);
3113*e038c9c4Sjoerg     static_cast<void>(Ec);
3114*e038c9c4Sjoerg   }
3115*e038c9c4Sjoerg 
31167330f729Sjoerg   return FallbackStyle;
31177330f729Sjoerg }
31187330f729Sjoerg 
31197330f729Sjoerg } // namespace format
31207330f729Sjoerg } // namespace clang
3121