From 6bfd987f37e0d5af9b33c9f04228b19ec38bcc71 Mon Sep 17 00:00:00 2001
From: kdeyev <k.deyev@gmial.com>
Date: Sun, 17 Sep 2017 09:07:13 +0300
Subject: [PATCH] SpacesBeforeSquareBrackets and SpacesBeforeAngleBrackets
 options were added All FormatTest passed

---
 include/clang/Format/Format.h   | 19 ++++++++++++++-
 lib/Format/Format.cpp           | 21 +++++++++++------
 lib/Format/TokenAnnotator.cpp   |  7 ++++++
 unittests/Format/FormatTest.cpp | 51 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 90 insertions(+), 8 deletions(-)

diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h
index 302ced3f78..8eaa285674 100644
--- a/include/clang/Format/Format.h
+++ b/include/clang/Format/Format.h
@@ -1486,6 +1486,21 @@ struct FormatStyle {
   /// \endcode
   bool SpacesInSquareBrackets;
 
+  /// \brief If ``true``, a space will be inserted before ``[`` in array
+  /// subscripts. \code
+  ///    true:                                  false:
+  ///    int a [5];                    vs.     int a[5];
+  ///    std::unique_ptr<int[]> foo() {} // Won't be affected
+  /// \endcode
+  bool SpacesBeforeSquareBrackets;
+
+  /// \brief If \c true, a space will be inserted before '<' before template
+  /// definition. \code
+  ///    true:                                  false:
+  ///    std::unique_ptr <Foo>        vs.     std::unique_ptr<Foo>
+  /// \endcode
+  bool SpacesBeforeAngleBrackets;
+
   /// \brief Supported language standards.
   enum LanguageStandard {
     /// Use C++03-compatible syntax.
@@ -1603,6 +1618,8 @@ struct FormatStyle {
            SpacesInCStyleCastParentheses == R.SpacesInCStyleCastParentheses &&
            SpacesInParentheses == R.SpacesInParentheses &&
            SpacesInSquareBrackets == R.SpacesInSquareBrackets &&
+           SpacesBeforeSquareBrackets == R.SpacesBeforeSquareBrackets &&
+           SpacesBeforeAngleBrackets == R.SpacesBeforeAngleBrackets &&
            Standard == R.Standard && TabWidth == R.TabWidth &&
            UseTab == R.UseTab;
   }
@@ -1821,6 +1838,6 @@ inline StringRef getLanguageName(FormatStyle::LanguageKind Language) {
 namespace std {
 template <>
 struct is_error_code_enum<clang::format::ParseError> : std::true_type {};
-}
+} // namespace std
 
 #endif // LLVM_CLANG_FORMAT_FORMAT_H
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 8663faf9e1..0f078d842a 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -390,7 +390,8 @@ template <> struct MappingTraits<FormatStyle> {
     IO.mapOptional("SortIncludes", Style.SortIncludes);
     IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);
     IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
-    IO.mapOptional("SpaceAfterTemplateKeyword", Style.SpaceAfterTemplateKeyword);
+    IO.mapOptional("SpaceAfterTemplateKeyword",
+                   Style.SpaceAfterTemplateKeyword);
     IO.mapOptional("SpaceBeforeAssignmentOperators",
                    Style.SpaceBeforeAssignmentOperators);
     IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
@@ -404,6 +405,10 @@ template <> struct MappingTraits<FormatStyle> {
                    Style.SpacesInCStyleCastParentheses);
     IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
     IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
+    IO.mapOptional("SpacesBeforeSquareBrackets",
+                   Style.SpacesBeforeSquareBrackets);
+    IO.mapOptional("SpacesBeforeAngleBrackets",
+                   Style.SpacesBeforeAngleBrackets);
     IO.mapOptional("Standard", Style.Standard);
     IO.mapOptional("TabWidth", Style.TabWidth);
     IO.mapOptional("UseTab", Style.UseTab);
@@ -501,9 +506,9 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
   if (Style.BreakBeforeBraces == FormatStyle::BS_Custom)
     return Style;
   FormatStyle Expanded = Style;
-  Expanded.BraceWrapping = {false, false, false, false, false, false, 
-                            false, false, false, false, false, false, 
-                            true,  true,  true};
+  Expanded.BraceWrapping = {false, false, false, false, false,
+                            false, false, false, false, false,
+                            false, false, true,  true,  true};
   switch (Style.BreakBeforeBraces) {
   case FormatStyle::BS_Linux:
     Expanded.BraceWrapping.AfterClass = true;
@@ -576,9 +581,9 @@ FormatStyle getLLVMStyle() {
   LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
   LLVMStyle.BreakBeforeTernaryOperators = true;
   LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
-  LLVMStyle.BraceWrapping = {false, false, false, false, false, false, 
-                             false, false, false, false, false, false, 
-                             true,  true,  true};
+  LLVMStyle.BraceWrapping = {false, false, false, false, false,
+                             false, false, false, false, false,
+                             false, false, true,  true,  true};
   LLVMStyle.BreakAfterJavaFieldAnnotations = false;
   LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
   LLVMStyle.BreakBeforeInheritanceComma = false;
@@ -620,6 +625,8 @@ FormatStyle getLLVMStyle() {
   LLVMStyle.ReflowComments = true;
   LLVMStyle.SpacesInParentheses = false;
   LLVMStyle.SpacesInSquareBrackets = false;
+  LLVMStyle.SpacesBeforeSquareBrackets = false;
+  LLVMStyle.SpacesBeforeAngleBrackets = false;
   LLVMStyle.SpaceInEmptyParentheses = false;
   LLVMStyle.SpacesInContainerLiterals = true;
   LLVMStyle.SpacesInCStyleCastParentheses = false;
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index 79fa5a7240..b78628a9aa 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -2211,6 +2211,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
                : Style.SpacesInParentheses;
   if (Right.isOneOf(tok::semi, tok::comma))
     return false;
+  if (Right.is(TT_TemplateOpener) && !Left.is(TT_TemplateOpener) &&
+      Style.SpacesBeforeAngleBrackets)
+    return true;
   if (Right.is(tok::less) &&
       Line.Type == LT_ObjCDecl && Style.ObjCSpaceBeforeProtocolList)
     return true;
@@ -2282,6 +2285,10 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
             (Style.SpacesInSquareBrackets &&
              Right.MatchingParen->isOneOf(TT_ArraySubscriptLSquare,
                                           TT_StructuredBindingLSquare)));
+  if (Right.is(tok::l_square) && Style.SpacesBeforeSquareBrackets &&
+      Right.isOneOf(TT_ArraySubscriptLSquare, TT_StructuredBindingLSquare) &&
+	  Right.Next && !Right.Next->is(tok::r_square))
+        return !Left.is(tok::r_square);
   if (Right.is(tok::l_square) &&
       !Right.isOneOf(TT_ObjCMethodExpr, TT_LambdaLSquare,
                      TT_DesignatedInitializerLSquare,
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index e974550f22..4856295cdf 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -9999,6 +9999,8 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
   CHECK_PARSE_BOOL(SpacesInParentheses);
   CHECK_PARSE_BOOL(SpacesInSquareBrackets);
   CHECK_PARSE_BOOL(SpacesInAngles);
+  CHECK_PARSE_BOOL(SpacesBeforeSquareBrackets);
+  CHECK_PARSE_BOOL(SpacesBeforeAngleBrackets);
   CHECK_PARSE_BOOL(SpaceInEmptyParentheses);
   CHECK_PARSE_BOOL(SpacesInContainerLiterals);
   CHECK_PARSE_BOOL(SpacesInCStyleCastParentheses);
@@ -11190,6 +11192,55 @@ TEST_F(FormatTest, SpacesInAngles) {
   verifyFormat("A<A<int>>();", Spaces);
 }
 
+TEST_F(FormatTest, SpacesBeforeAngleBrackets) {
+  FormatStyle Spaces = getLLVMStyle();
+  Spaces.SpacesBeforeAngleBrackets = true;
+
+  verifyFormat("static_cast <int>(arg);", Spaces);
+  verifyFormat("template <typename T0, typename T1> void f() {}", Spaces);
+  verifyFormat("f <int, float>();", Spaces);
+  verifyFormat("template <> g() {}", Spaces);
+  verifyFormat("template <std::vector <int>> f() {}", Spaces);
+  verifyFormat("std::function <void(int, int)> fct;", Spaces);
+  verifyFormat("void inFunction() { std::function <void(int, int)> fct; }",
+               Spaces);
+
+  Spaces.Standard = FormatStyle::LS_Cpp03;
+  Spaces.SpacesBeforeAngleBrackets = true;
+  verifyFormat("A <A <int> >();", Spaces);
+
+  Spaces.SpacesBeforeAngleBrackets = false;
+  verifyFormat("A<A<int> >();", Spaces);
+
+  Spaces.Standard = FormatStyle::LS_Cpp11;
+  Spaces.SpacesBeforeAngleBrackets = true;
+  verifyFormat("A <A <int>>();", Spaces);
+
+  Spaces.SpacesBeforeAngleBrackets = false;
+  verifyFormat("A<A<int>>();", Spaces);
+}
+
+TEST_F(FormatTest, SpacesBeforeSquareBrackets) {
+  verifyFormat("int a[5];");
+  verifyFormat("a[3] += 42;");
+
+  FormatStyle Spaces = getLLVMStyle();
+  Spaces.SpacesBeforeSquareBrackets = true;
+  // Lambdas unchanged.
+  verifyFormat("int c = []() -> int { return 2; }();\n", Spaces);
+  verifyFormat("return [i, args...] {};", Spaces);
+
+  // Not lambdas.
+  verifyFormat("int a [5];", Spaces);
+  verifyFormat("constexpr char hello[]{\"hello\"};", Spaces);
+  verifyFormat("double &operator[](int i) { return 0; }\n"
+               "int i;",
+               Spaces);
+  verifyFormat("std::unique_ptr<int[]> foo() {}", Spaces);
+  verifyFormat("int i = a [a][a]->f();", Spaces);
+  verifyFormat("int i = (*b) [a]->f();", Spaces);
+}
+
 TEST_F(FormatTest, SpaceAfterTemplateKeyword) {
   FormatStyle Style = getLLVMStyle();
   Style.SpaceAfterTemplateKeyword = false;
-- 
2.11.0.windows.1

