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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181326 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index 3bb90d9..92435fe 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -3909,5 +3909,113 @@
                "}");
 }
 
+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