From: Daniel Jasper Date: Mon, 15 Sep 2014 11:21:46 +0000 (+0000) Subject: clang-format: Basic support for Java. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=28377e0dad8041ae83c50513206d5e4b5c4c2755;p=clang clang-format: Basic support for Java. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@217759 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index 22a9ef606e..9c33766031 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -47,6 +47,8 @@ struct FormatStyle { LK_None, /// Should be used for C, C++, ObjectiveC, ObjectiveC++. LK_Cpp, + /// Should be used for Java. + LK_Java, /// Should be used for JavaScript. LK_JavaScript, /// Should be used for Protocol Buffers diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 5f9536dac8..2948ec48cd 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -41,6 +41,7 @@ namespace yaml { template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) { IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp); + IO.enumCase(Value, "Java", FormatStyle::LK_Java); IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript); IO.enumCase(Value, "Proto", FormatStyle::LK_Proto); } @@ -405,7 +406,11 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) { GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200; GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1; - if (Language == FormatStyle::LK_JavaScript) { + if (Language == FormatStyle::LK_Java) { + GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; + GoogleStyle.ColumnLimit = 100; + GoogleStyle.SpaceAfterCStyleCast = true; + } else if (Language == FormatStyle::LK_JavaScript) { GoogleStyle.BreakBeforeTernaryOperators = false; GoogleStyle.MaxEmptyLinesToKeep = 3; GoogleStyle.SpacesInContainerLiterals = false; @@ -1031,6 +1036,8 @@ private: /// For example, 'public:' labels in classes are offset by 1 or 2 /// characters to the left from their level. int getIndentOffset(const FormatToken &RootToken) { + if (Style.Language == FormatStyle::LK_Java) + return 0; if (RootToken.isAccessSpecifier(false) || RootToken.isObjCAccessSpecifier()) return Style.AccessModifierOffset; return 0; @@ -1754,6 +1761,8 @@ static StringRef getLanguageName(FormatStyle::LanguageKind Language) { switch (Language) { case FormatStyle::LK_Cpp: return "C++"; + case FormatStyle::LK_Java: + return "Java"; case FormatStyle::LK_JavaScript: return "JavaScript"; case FormatStyle::LK_Proto: @@ -2120,7 +2129,9 @@ const char *StyleOptionHelpDescription = " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""; static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) { - if (FileName.endswith_lower(".js")) { + if (FileName.endswith(".java")) { + return FormatStyle::LK_Java; + } else if (FileName.endswith_lower(".js")) { return FormatStyle::LK_JavaScript; } else if (FileName.endswith_lower(".proto") || FileName.endswith_lower(".protodevel")) { diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index edb68a3d79..2b215fd09f 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -685,7 +685,10 @@ void UnwrappedLineParser::parseStructuralElement() { case tok::kw_public: case tok::kw_protected: case tok::kw_private: - parseAccessSpecifier(); + if (Style.Language == FormatStyle::LK_Java) + nextToken(); + else + parseAccessSpecifier(); return; case tok::kw_if: parseIfThenElse(); @@ -1405,6 +1408,9 @@ void UnwrappedLineParser::parseRecord() { // We fall through to parsing a structural element afterwards, so // class A {} n, m; // will end up in one unwrapped line. + // This does not apply for Java. + if (Style.Language == FormatStyle::LK_Java) + addUnwrappedLine(); } void UnwrappedLineParser::parseObjCProtocolList() { diff --git a/unittests/Format/CMakeLists.txt b/unittests/Format/CMakeLists.txt index 14fc22d05c..700efd5ddb 100644 --- a/unittests/Format/CMakeLists.txt +++ b/unittests/Format/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS add_clang_unittest(FormatTests FormatTest.cpp + FormatTestJava.cpp FormatTestJS.cpp FormatTestProto.cpp ) diff --git a/unittests/Format/FormatTestJava.cpp b/unittests/Format/FormatTestJava.cpp new file mode 100644 index 0000000000..4ae04e6b09 --- /dev/null +++ b/unittests/Format/FormatTestJava.cpp @@ -0,0 +1,69 @@ +//===- unittest/Format/FormatTestJava.cpp - Formatting tests for Java -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "FormatTestUtils.h" +#include "clang/Format/Format.h" +#include "llvm/Support/Debug.h" +#include "gtest/gtest.h" + +#define DEBUG_TYPE "format-test" + +namespace clang { +namespace format { + +class FormatTestJava : public ::testing::Test { +protected: + static std::string format(llvm::StringRef Code, unsigned Offset, + unsigned Length, const FormatStyle &Style) { + DEBUG(llvm::errs() << "---\n"); + DEBUG(llvm::errs() << Code << "\n\n"); + std::vector Ranges(1, tooling::Range(Offset, Length)); + tooling::Replacements Replaces = reformat(Style, Code, Ranges); + std::string Result = applyAllReplacements(Code, Replaces); + EXPECT_NE("", Result); + DEBUG(llvm::errs() << "\n" << Result << "\n\n"); + return Result; + } + + static std::string format( + llvm::StringRef Code, + const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_Java)) { + return format(Code, 0, Code.size(), Style); + } + + static FormatStyle getGoogleJSStyleWithColumns(unsigned ColumnLimit) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_Java); + Style.ColumnLimit = ColumnLimit; + return Style; + } + + static void verifyFormat( + llvm::StringRef Code, + const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_Java)) { + EXPECT_EQ(Code.str(), format(test::messUp(Code), Style)); + } +}; + +TEST_F(FormatTestJava, ClassDeclarations) { + verifyFormat("public class SomeClass {\n" + " private int a;\n" + " private int b;\n" + "}"); + verifyFormat("public class A {\n" + " class B {\n" + " int i;\n" + " }\n" + " class C {\n" + " int j;\n" + " }\n" + "}"); +} + +} // end namespace tooling +} // end namespace clang