From: Nico Weber Date: Tue, 11 Apr 2017 15:50:04 +0000 (+0000) Subject: [clang-format] Recognize Java logical shift assignment operator X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=09db0594445a414fe41ef989534be9f7a333b050;p=clang [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 ! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@299952 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/FormatTokenLexer.cpp b/lib/Format/FormatTokenLexer.cpp index 9415dbe9ab..4ee43d6937 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 ee09ca940f..6e685f6703 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