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