r181326 - Config file support for clang-format, part 1.
Alexander Kornienko
alexfh at google.com
Tue May 7 08:32:15 PDT 2013
Author: alexfh
Date: Tue May 7 10:32:14 2013
New Revision: 181326
URL: http://llvm.org/viewvc/llvm-project?rev=181326&view=rev
Log:
Config file support for clang-format, part 1.
Summary:
Added parseConfiguration method, which reads FormatStyle from YAML
string. This supports all FormatStyle fields and an additional BasedOnStyle
field, which can be used to specify base style.
Reviewers: djasper, klimek
Reviewed By: djasper
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D754
Modified:
cfe/trunk/include/clang/Format/Format.h
cfe/trunk/lib/Format/Format.cpp
cfe/trunk/unittests/Format/FormatTest.cpp
Modified: cfe/trunk/include/clang/Format/Format.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Format/Format.h?rev=181326&r1=181325&r2=181326&view=diff
==============================================================================
--- cfe/trunk/include/clang/Format/Format.h (original)
+++ cfe/trunk/include/clang/Format/Format.h Tue May 7 10:32:14 2013
@@ -17,6 +17,7 @@
#include "clang/Frontend/FrontendAction.h"
#include "clang/Tooling/Refactoring.h"
+#include "llvm/Support/system_error.h"
namespace clang {
@@ -110,6 +111,18 @@ FormatStyle getChromiumStyle();
/// https://developer.mozilla.org/en-US/docs/Developer_Guide/Coding_Style.
FormatStyle getMozillaStyle();
+/// \brief Returns a predefined style by name.
+///
+/// Currently supported names: LLVM, Google, Chromium, Mozilla. Names are
+/// compared case-insensitively.
+FormatStyle getPredefinedStyle(StringRef Name);
+
+/// \brief Parse configuration from YAML-formatted text.
+llvm::error_code parseConfiguration(StringRef Text, FormatStyle *Style);
+
+/// \brief Gets configuration in a YAML string.
+std::string configurationAsText(const FormatStyle &Style);
+
/// \brief Reformats the given \p Ranges in the token stream coming out of
/// \c Lex.
///
Modified: cfe/trunk/lib/Format/Format.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=181326&r1=181325&r2=181326&view=diff
==============================================================================
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Tue May 7 10:32:14 2013
@@ -28,9 +28,59 @@
#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 {
@@ -98,6 +148,37 @@ FormatStyle getMozillaStyle() {
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) {
Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=181326&r1=181325&r2=181326&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Tue May 7 10:32:14 2013
@@ -3909,5 +3909,113 @@ TEST_F(FormatTest, DoNotCreateUnreasonab
"}");
}
+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
More information about the cfe-commits
mailing list