In Objective-C some style guides (including the one at my workplace) use a 
style where assignment operators are aligned, in an effort to increase code 
readability. This patch adds an option to the format library which allows this 
functionality. It is disabled by default for all the included styles, so it 
must be explicitly enabled.

The option will change code such as:

```
- (void)method {
    NSNumber *one = @1;
    NSNumber *twentyFive = @25;
}
```

to:

```
- (void)method {
    NSNumber *one        = @1;
    NSNumber *twentyFive = @25;
}
```

http://reviews.llvm.org/D8821

Files:
  docs/ClangFormatStyleOptions.rst
  include/clang/Format/Format.h
  lib/Format/Format.cpp
  lib/Format/WhitespaceManager.cpp
  lib/Format/WhitespaceManager.h
  unittests/Format/FormatTest.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: docs/ClangFormatStyleOptions.rst
===================================================================
--- docs/ClangFormatStyleOptions.rst
+++ docs/ClangFormatStyleOptions.rst
@@ -160,6 +160,9 @@
   argument2);
   \endcode
 
+**AlignAssignmentOperators** (``bool``)
+  If ``true``, aligns assignment operators.
+
 **AlignEscapedNewlinesLeft** (``bool``)
   If ``true``, aligns escaped newlines as far left as possible.
   Otherwise puts them into the right-most column.
Index: include/clang/Format/Format.h
===================================================================
--- include/clang/Format/Format.h
+++ include/clang/Format/Format.h
@@ -247,6 +247,9 @@
   /// \brief If \c true, aligns trailing comments.
   bool AlignTrailingComments;
 
+  /// \brief If \c true, aligns variable assignments.
+  bool AlignAssignmentOperators;
+
   /// \brief If \c true, aligns escaped newlines as far left as possible.
   /// Otherwise puts them into the right-most column.
   bool AlignEscapedNewlinesLeft;
Index: lib/Format/Format.cpp
===================================================================
--- lib/Format/Format.cpp
+++ lib/Format/Format.cpp
@@ -174,6 +174,7 @@
     IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlinesLeft);
     IO.mapOptional("AlignOperands", Style.AlignOperands);
     IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
+    IO.mapOptional("AlignAssignmentOperators", Style.AlignAssignmentOperators);
     IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
                    Style.AllowAllParametersOfDeclarationOnNextLine);
     IO.mapOptional("AllowShortBlocksOnASingleLine",
@@ -329,6 +330,7 @@
   LLVMStyle.AlignAfterOpenBracket = true;
   LLVMStyle.AlignOperands = true;
   LLVMStyle.AlignTrailingComments = true;
+  LLVMStyle.AlignAssignmentOperators = false;
   LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
   LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
   LLVMStyle.AllowShortBlocksOnASingleLine = false;
@@ -418,6 +420,7 @@
     GoogleStyle.AlignAfterOpenBracket = false;
     GoogleStyle.AlignOperands = false;
     GoogleStyle.AlignTrailingComments = false;
+    GoogleStyle.AlignAssignmentOperators = false;
     GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
     GoogleStyle.AllowShortIfStatementsOnASingleLine = false;
     GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
@@ -477,6 +480,7 @@
   Style.AlignAfterOpenBracket = false;
   Style.AlignOperands = false;
   Style.AlignTrailingComments = false;
+  Style.AlignAssignmentOperators = false;
   Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
   Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup;
   Style.BreakConstructorInitializersBeforeComma = true;
Index: lib/Format/WhitespaceManager.cpp
===================================================================
--- lib/Format/WhitespaceManager.cpp
+++ lib/Format/WhitespaceManager.cpp
@@ -95,6 +95,7 @@
   calculateLineBreakInformation();
   alignTrailingComments();
   alignEscapedNewlines();
+  alignAssignmentOperators();
   generateChanges();
 
   return Replaces;
@@ -263,6 +264,63 @@
   }
 }
 
+void WhitespaceManager::alignAssignmentOperators() {
+  if (!Style.AlignAssignmentOperators)
+    return;
+
+  unsigned MinColumn = 0;
+  unsigned StartOfSequence = 0;
+  bool FoundEqualOnLine = false;
+  unsigned CurrentLine = 0;
+  for (unsigned i = 0, e = Changes.size(); i != e; ++i) {
+    if (Changes[i].NewlinesBefore == 1) {
+      CurrentLine += Changes[i].NewlinesBefore;
+      if (!FoundEqualOnLine && StartOfSequence > 0) {
+        alignAssignmentOperators(StartOfSequence, i, MinColumn);
+        MinColumn = 0;
+        StartOfSequence = 0;
+      }
+      FoundEqualOnLine = false;
+    } else if (Changes[i].NewlinesBefore > 1) {
+      CurrentLine += Changes[i].NewlinesBefore;
+      if (StartOfSequence > 0) {
+        alignAssignmentOperators(StartOfSequence, i, MinColumn);
+        MinColumn = 0;
+        StartOfSequence = 0;
+      }
+      FoundEqualOnLine = false;
+    }
+
+    if (Changes[i].Kind != tok::equal)
+      continue;
+
+    FoundEqualOnLine = true;
+    if (StartOfSequence == 0)
+      StartOfSequence = i;
+
+    unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
+    MinColumn = std::max(MinColumn, ChangeMinColumn);
+  }
+
+  if (StartOfSequence > 0)
+    alignAssignmentOperators(StartOfSequence, Changes.size(), MinColumn);
+}
+
+void WhitespaceManager::alignAssignmentOperators(unsigned Start, unsigned End,
+                                                 unsigned Column) {
+  for (unsigned i = Start; i != End; ++i) {
+    int Shift = 0;
+    if (Changes[i].Kind == tok::equal) {
+      Shift = Column - Changes[i].StartOfTokenColumn;
+    }
+    assert(Shift >= 0);
+    Changes[i].Spaces += Shift;
+    if (i + 1 != Changes.size())
+      Changes[i + 1].PreviousEndOfTokenColumn += Shift;
+    Changes[i].StartOfTokenColumn += Shift;
+  }
+}
+
 void WhitespaceManager::generateChanges() {
   for (unsigned i = 0, e = Changes.size(); i != e; ++i) {
     const Change &C = Changes[i];
Index: lib/Format/WhitespaceManager.h
===================================================================
--- lib/Format/WhitespaceManager.h
+++ lib/Format/WhitespaceManager.h
@@ -178,6 +178,13 @@
   /// the specified \p Column.
   void alignEscapedNewlines(unsigned Start, unsigned End, unsigned Column);
 
+  /// \brief Align assignment operators over all \c Changes.
+  void alignAssignmentOperators();
+
+  /// \brief Align assignment operators from change \p Start to change \p End at
+  /// the specified \p Column.
+  void alignAssignmentOperators(unsigned Start, unsigned End, unsigned Column);
+
   /// \brief Fill \c Replaces with the replacements for all effective changes.
   void generateChanges();
 
Index: unittests/Format/FormatTest.cpp
===================================================================
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -8347,6 +8347,59 @@
   verifyFormat("a or_eq 8;", Spaces);
 }
 
+TEST_F(FormatTest, AlignAssignmentOperators) {
+  FormatStyle Alignment = getLLVMStyle();
+  Alignment.AlignAssignmentOperators = false;
+  verifyFormat("int a = 5;\n"
+               "int oneTwoThree = 123;", Alignment);
+  EXPECT_EQ("int a = 5;\n"
+            "int oneTwoThree = 123;",
+            format("int   a =5;\n"
+                   "int oneTwoThree= 123;", Alignment));
+
+  Alignment.AlignAssignmentOperators = true;
+  verifyFormat("int a           = 5;\n"
+               "int oneTwoThree = 123;", Alignment);
+  EXPECT_EQ("int a           = 5;\n"
+            "int oneTwoThree = 123;",
+            format("int a= 5;\n"
+                   "int oneTwoThree   = 123;", Alignment));
+  EXPECT_EQ("int a = 5;\n"
+            "\n"
+            "int oneTwoThree = 123;",
+            format("int a       = 5;\n"
+                   "\n"
+                   "int oneTwoThree= 123;", Alignment));
+  EXPECT_EQ("int a   = 5;\n"
+            "int one = 1;\n"
+            "\n"
+            "int oneTwoThree = 123;",
+            format("int a = 5;\n"
+                   "int one = 1;\n"
+                   "\n"
+                   "int oneTwoThree = 123;", Alignment));
+  EXPECT_EQ("int a   = 5;\n"
+            "int one = 1;\n"
+            "\n"
+            "int oneTwoThree = 123;\n"
+            "int oneTwo      = 12;",
+            format("int a = 5;\n"
+                   "int one = 1;\n"
+                   "\n"
+                   "int oneTwoThree = 123;\n"
+                   "int oneTwo = 12;", Alignment));
+  EXPECT_EQ("int a   = 5;\n"
+            "int one = 1;\n"
+            "method();\n"
+            "int oneTwoThree = 123;\n"
+            "int oneTwo      = 12;",
+            format("int a = 5;\n"
+                   "int one = 1;\n"
+                   "method();\n"
+                   "int oneTwoThree = 123;\n"
+                   "int oneTwo = 12;", Alignment));
+}
+
 TEST_F(FormatTest, LinuxBraceBreaking) {
   FormatStyle LinuxBraceStyle = getLLVMStyle();
   LinuxBraceStyle.BreakBeforeBraces = FormatStyle::BS_Linux;
@@ -8886,6 +8939,7 @@
   CHECK_PARSE_BOOL(AlignEscapedNewlinesLeft);
   CHECK_PARSE_BOOL(AlignOperands);
   CHECK_PARSE_BOOL(AlignTrailingComments);
+  CHECK_PARSE_BOOL(AlignAssignmentOperators);
   CHECK_PARSE_BOOL(AllowAllParametersOfDeclarationOnNextLine);
   CHECK_PARSE_BOOL(AllowShortBlocksOnASingleLine);
   CHECK_PARSE_BOOL(AllowShortCaseLabelsOnASingleLine);
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to