Index: include/clang/Basic/LangOptions.def =================================================================== --- include/clang/Basic/LangOptions.def +++ include/clang/Basic/LangOptions.def @@ -92,6 +92,7 @@ LANGOPT(CPlusPlus1z , 1, 0, "C++1z") LANGOPT(ObjC1 , 1, 0, "Objective-C 1") LANGOPT(ObjC2 , 1, 0, "Objective-C 2") +LANGOPT(Java , 1, 0, "Java") BENIGN_LANGOPT(ObjCDefaultSynthProperties , 1, 0, "Objective-C auto-synthesized properties") BENIGN_LANGOPT(EncodeExtendedBlockSig , 1, 0, Index: include/clang/Basic/TokenKinds.def =================================================================== --- include/clang/Basic/TokenKinds.def +++ include/clang/Basic/TokenKinds.def @@ -225,6 +225,10 @@ // CL support PUNCTUATOR(caretcaret, "^^") +// Java support (for clang-format only) +PUNCTUATOR(greatergreatergreaterequal, ">>>=") +PUNCTUATOR(lesslesslessequal, "<<<=") + // C99 6.4.1: Keywords. These turn into kw_* tokens. // Flags allowed: // KEYALL - This is a keyword in all variants of C and C++, or it Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -1902,6 +1902,7 @@ LangOpts.ObjC2 = 1; LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally. LangOpts.DeclSpecKeyword = 1; // To get __declspec. + LangOpts.Java = Style.Language == FormatStyle::LK_Java; return LangOpts; } Index: lib/Lex/Lexer.cpp =================================================================== --- lib/Lex/Lexer.cpp +++ lib/Lex/Lexer.cpp @@ -2967,7 +2967,7 @@ Result.setFlag(Token::LeadingSpace); } - unsigned SizeTmp, SizeTmp2; // Temporaries for use in cases below. + unsigned SizeTmp, SizeTmp2, SizeTmp3; // Temporaries for use in cases below. // Read a character, advancing over it. char Char = getAndAdvanceChar(CurPtr, Result); @@ -3449,6 +3449,14 @@ Kind = tok::lesslessless; CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result), SizeTmp2, Result); + } else if (LangOpts.Java && After == '<') { + char Fourth = getCharAndSize(CurPtr+SizeTmp+SizeTmp2, SizeTmp3); + if (Fourth == '=') { + Kind = tok::lesslesslessequal; + CurPtr = ConsumeChar(ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result), + SizeTmp2, Result), + SizeTmp3, Result); + } } else { CurPtr = ConsumeChar(CurPtr, SizeTmp, Result); Kind = tok::lessless; @@ -3505,6 +3513,14 @@ Kind = tok::greatergreatergreater; CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result), SizeTmp2, Result); + } else if (LangOpts.Java && After == '>') { + char Fourth = getCharAndSize(CurPtr+SizeTmp+SizeTmp2, SizeTmp3); + if (Fourth == '=') { + Kind = tok::greatergreatergreaterequal; + CurPtr = ConsumeChar(ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result), + SizeTmp2, Result), + SizeTmp3, Result); + } } else { CurPtr = ConsumeChar(CurPtr, SizeTmp, Result); Kind = tok::greatergreater; Index: unittests/Format/FormatTestJava.cpp =================================================================== --- unittests/Format/FormatTestJava.cpp +++ unittests/Format/FormatTestJava.cpp @@ -522,5 +522,17 @@ " void f() {}")); } +TEST_F(FormatTestJava, RetainsLogicalShiftAssignments) { + verifyFormat("void f() {\n" + " int a = 1;\n" + " a >>>= 1;\n" + "}"); + verifyFormat("void f() {\n" + " int a = 1;\n" + " a <<<= 1;\n" + "}"); +} + + } // end namespace tooling } // end namespace clang