#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/YAMLTraits.h"
#include <queue>
#include <string>
+namespace llvm {
+namespace yaml {
+template <>
+struct ScalarEnumerationTraits<clang::format::FormatStyle::LanguageStandard> {
+ static void enumeration(IO &io,
+ clang::format::FormatStyle::LanguageStandard &value) {
+ io.enumCase(value, "C++03", clang::format::FormatStyle::LS_Cpp03);
+ io.enumCase(value, "C++11", clang::format::FormatStyle::LS_Cpp11);
+ io.enumCase(value, "Auto", clang::format::FormatStyle::LS_Auto);
+ }
+};
+
+template <> struct MappingTraits<clang::format::FormatStyle> {
+ static void mapping(llvm::yaml::IO &IO, clang::format::FormatStyle &Style) {
+ if (!IO.outputting()) {
+ StringRef BasedOnStyle;
+ IO.mapOptional("BasedOnStyle", BasedOnStyle);
+
+ if (!BasedOnStyle.empty())
+ Style = clang::format::getPredefinedStyle(BasedOnStyle);
+ }
+
+ IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
+ IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlinesLeft);
+ IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
+ Style.AllowAllParametersOfDeclarationOnNextLine);
+ IO.mapOptional("AllowShortIfStatementsOnASingleLine",
+ Style.AllowShortIfStatementsOnASingleLine);
+ IO.mapOptional("BinPackParameters", Style.BinPackParameters);
+ IO.mapOptional("ColumnLimit", Style.ColumnLimit);
+ IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
+ Style.ConstructorInitializerAllOnOneLineOrOnePerLine);
+ IO.mapOptional("DerivePointerBinding", Style.DerivePointerBinding);
+ IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
+ IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
+ IO.mapOptional("ObjCSpaceBeforeProtocolList",
+ Style.ObjCSpaceBeforeProtocolList);
+ IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
+ IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
+ Style.PenaltyReturnTypeOnItsOwnLine);
+ IO.mapOptional("PointerBindsToType", Style.PointerBindsToType);
+ IO.mapOptional("SpacesBeforeTrailingComments",
+ Style.SpacesBeforeTrailingComments);
+ IO.mapOptional("Standard", Style.Standard);
+ }
+};
+}
+}
+
namespace clang {
namespace format {
return MozillaStyle;
}
+FormatStyle getPredefinedStyle(StringRef Name) {
+ if (Name.equals_lower("llvm"))
+ return getLLVMStyle();
+ if (Name.equals_lower("chromium"))
+ return getChromiumStyle();
+ if (Name.equals_lower("mozilla"))
+ return getMozillaStyle();
+ if (Name.equals_lower("google"))
+ return getGoogleStyle();
+
+ llvm::errs() << "Unknown style " << Name << ", using Google style.\n";
+ return getGoogleStyle();
+}
+
+llvm::error_code parseConfiguration(StringRef Text, FormatStyle *Style) {
+ llvm::yaml::Input Input(Text);
+ Input >> *Style;
+ return Input.error();
+}
+
+std::string configurationAsText(const FormatStyle &Style) {
+ std::string Text;
+ llvm::raw_string_ostream Stream(Text);
+ llvm::yaml::Output Output(Stream);
+ // We use the same mapping method for input and output, so we need a non-const
+ // reference here.
+ FormatStyle NonConstStyle = Style;
+ Output << NonConstStyle;
+ return Text;
+}
+
// Returns the length of everything up to the first possible line break after
// the ), ], } or > matching \c Tok.
static unsigned getLengthToMatchingParen(const AnnotatedToken &Tok) {
"}");
}
+bool operator==(const FormatStyle &L, const FormatStyle &R) {
+ return L.AccessModifierOffset == R.AccessModifierOffset &&
+ L.AlignEscapedNewlinesLeft == R.AlignEscapedNewlinesLeft &&
+ L.AllowAllParametersOfDeclarationOnNextLine ==
+ R.AllowAllParametersOfDeclarationOnNextLine &&
+ L.AllowShortIfStatementsOnASingleLine ==
+ R.AllowShortIfStatementsOnASingleLine &&
+ L.BinPackParameters == R.BinPackParameters &&
+ L.ColumnLimit == R.ColumnLimit &&
+ L.ConstructorInitializerAllOnOneLineOrOnePerLine ==
+ R.ConstructorInitializerAllOnOneLineOrOnePerLine &&
+ L.DerivePointerBinding == R.DerivePointerBinding &&
+ L.IndentCaseLabels == R.IndentCaseLabels &&
+ L.MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep &&
+ L.ObjCSpaceBeforeProtocolList == R.ObjCSpaceBeforeProtocolList &&
+ L.PenaltyExcessCharacter == R.PenaltyExcessCharacter &&
+ L.PenaltyReturnTypeOnItsOwnLine == R.PenaltyReturnTypeOnItsOwnLine &&
+ L.PointerBindsToType == R.PointerBindsToType &&
+ L.SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments &&
+ L.Standard == R.Standard;
+}
+
+bool allStylesEqual(ArrayRef<FormatStyle> Styles) {
+ for (size_t i = 1; i < Styles.size(); ++i)
+ if (!(Styles[0] == Styles[i]))
+ return false;
+ return true;
+}
+
+TEST_F(FormatTest, GetsPredefinedStyleByName) {
+ FormatStyle LLVMStyles[] = { getLLVMStyle(), getPredefinedStyle("LLVM"),
+ getPredefinedStyle("llvm"),
+ getPredefinedStyle("lLvM") };
+ EXPECT_TRUE(allStylesEqual(LLVMStyles));
+
+ FormatStyle GoogleStyles[] = { getGoogleStyle(), getPredefinedStyle("Google"),
+ getPredefinedStyle("google"),
+ getPredefinedStyle("gOOgle") };
+ EXPECT_TRUE(allStylesEqual(GoogleStyles));
+
+ FormatStyle ChromiumStyles[] = { getChromiumStyle(),
+ getPredefinedStyle("Chromium"),
+ getPredefinedStyle("chromium"),
+ getPredefinedStyle("chROmiUM") };
+ EXPECT_TRUE(allStylesEqual(ChromiumStyles));
+
+ FormatStyle MozillaStyles[] = { getMozillaStyle(),
+ getPredefinedStyle("Mozilla"),
+ getPredefinedStyle("mozilla"),
+ getPredefinedStyle("moZilla") };
+ EXPECT_TRUE(allStylesEqual(MozillaStyles));
+}
+
+TEST_F(FormatTest, ParsesConfiguration) {
+ FormatStyle Style = {};
+#define CHECK_PARSE(TEXT, FIELD, VALUE) \
+ EXPECT_NE(VALUE, Style.FIELD); \
+ EXPECT_EQ(0, parseConfiguration(TEXT, &Style).value()); \
+ EXPECT_EQ(VALUE, Style.FIELD)
+
+#define CHECK_PARSE_BOOL(FIELD) \
+ Style.FIELD = false; \
+ EXPECT_EQ(0, parseConfiguration(#FIELD ": true", &Style).value()); \
+ EXPECT_EQ(true, Style.FIELD); \
+ EXPECT_EQ(0, parseConfiguration(#FIELD ": false", &Style).value()); \
+ EXPECT_EQ(false, Style.FIELD);
+
+ CHECK_PARSE_BOOL(AlignEscapedNewlinesLeft);
+ CHECK_PARSE_BOOL(AllowAllParametersOfDeclarationOnNextLine);
+ CHECK_PARSE_BOOL(AllowShortIfStatementsOnASingleLine);
+ CHECK_PARSE_BOOL(BinPackParameters);
+ CHECK_PARSE_BOOL(ConstructorInitializerAllOnOneLineOrOnePerLine);
+ CHECK_PARSE_BOOL(DerivePointerBinding);
+ CHECK_PARSE_BOOL(IndentCaseLabels);
+ CHECK_PARSE_BOOL(ObjCSpaceBeforeProtocolList);
+ CHECK_PARSE_BOOL(PointerBindsToType);
+
+ CHECK_PARSE("AccessModifierOffset: -1234", AccessModifierOffset, -1234);
+ CHECK_PARSE("ColumnLimit: 1234", ColumnLimit, 1234u);
+ CHECK_PARSE("MaxEmptyLinesToKeep: 1234", MaxEmptyLinesToKeep, 1234u);
+ CHECK_PARSE("PenaltyExcessCharacter: 1234", PenaltyExcessCharacter, 1234u);
+ CHECK_PARSE("PenaltyReturnTypeOnItsOwnLine: 1234",
+ PenaltyReturnTypeOnItsOwnLine, 1234u);
+ CHECK_PARSE("SpacesBeforeTrailingComments: 1234",
+ SpacesBeforeTrailingComments, 1234u);
+
+ Style.Standard = FormatStyle::LS_Auto;
+ CHECK_PARSE("Standard: C++03", Standard, FormatStyle::LS_Cpp03);
+ CHECK_PARSE("Standard: C++11", Standard, FormatStyle::LS_Cpp11);
+ CHECK_PARSE("Standard: Auto", Standard, FormatStyle::LS_Auto);
+
+ Style.ColumnLimit = 123;
+ FormatStyle BaseStyle = getLLVMStyle();
+ CHECK_PARSE("BasedOnStyle: LLVM", ColumnLimit, BaseStyle.ColumnLimit);
+ CHECK_PARSE("BasedOnStyle: LLVM\nColumnLimit: 1234", ColumnLimit, 1234u);
+
+#undef CHECK_PARSE
+#undef CHECK_PARSE_BOOL
+}
+
+TEST_F(FormatTest, ConfigurationRoundTripTest) {
+ FormatStyle Style = getLLVMStyle();
+ std::string YAML = configurationAsText(Style);
+ FormatStyle ParsedStyle = {};
+ EXPECT_EQ(0, parseConfiguration(YAML, &ParsedStyle).value());
+ EXPECT_EQ(Style, ParsedStyle);
+}
+
} // end namespace tooling
} // end namespace clang