From 09db0594445a414fe41ef989534be9f7a333b050 Mon Sep 17 00:00:00 2001
From: Nico Weber <nicolasweber@gmx.de>
Date: Tue, 11 Apr 2017 15:50:04 +0000
Subject: [PATCH] [clang-format] Recognize Java logical shift assignment
 operator

At present, clang-format mangles Java containing logical right shift operators
('>>>=' or '>>>'), splitting them in two, resulting in invalid code:

 public class Minimal {
   public void func(String args) {
     int i = 42;
-    i >>>= 1;
+    i >> >= 1;
     return i;
   }
 }

This adds both forms of logical right shift to the FormatTokenLexer, so
clang-format won't attempt to split them and insert bogus whitespace.

https://reviews.llvm.org/D31652
Patch from Richard Bradfield <bradfier@fstab.me>!


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@299952 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Format/FormatTokenLexer.cpp     | 13 +++++++++++++
 unittests/Format/FormatTestJava.cpp | 12 ++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/lib/Format/FormatTokenLexer.cpp b/lib/Format/FormatTokenLexer.cpp
index 9415dbe9ab3..4ee43d6937e 100644
--- a/lib/Format/FormatTokenLexer.cpp
+++ b/lib/Format/FormatTokenLexer.cpp
@@ -84,6 +84,19 @@ void FormatTokenLexer::tryMergePreviousTokens() {
     if (tryMergeTokens(JSRightArrow, TT_JsFatArrow))
       return;
   }
+
+  if (Style.Language == FormatStyle::LK_Java) {
+    static const tok::TokenKind JavaRightLogicalShift[] = {tok::greater,
+                                                           tok::greater,
+                                                           tok::greater};
+    static const tok::TokenKind JavaRightLogicalShiftAssign[] = {tok::greater,
+                                                                 tok::greater,
+                                                                 tok::greaterequal};
+    if (tryMergeTokens(JavaRightLogicalShift, TT_BinaryOperator))
+      return;
+    if (tryMergeTokens(JavaRightLogicalShiftAssign, TT_BinaryOperator))
+      return;
+  }
 }
 
 bool FormatTokenLexer::tryMergeNSStringLiteral() {
diff --git a/unittests/Format/FormatTestJava.cpp b/unittests/Format/FormatTestJava.cpp
index ee09ca940f1..6e685f6703e 100644
--- a/unittests/Format/FormatTestJava.cpp
+++ b/unittests/Format/FormatTestJava.cpp
@@ -522,5 +522,17 @@ TEST_F(FormatTestJava, AlignsBlockComments) {
                    "  void f() {}"));
 }
 
+TEST_F(FormatTestJava, RetainsLogicalShifts) {
+    verifyFormat("void f() {\n"
+                 "  int a = 1;\n"
+                 "  a >>>= 1;\n"
+                 "}");
+    verifyFormat("void f() {\n"
+                 "  int a = 1;\n"
+                 "  a = a >>> 1;\n"
+                 "}");
+}
+
+
 } // end namespace tooling
 } // end namespace clang
-- 
GitLab