Author: mydeveloperday Date: 2020-09-18T18:12:21+01:00 New Revision: 2e7add812eb7bdd90bd0f0fc3b633515edd55f27
URL: https://github.com/llvm/llvm-project/commit/2e7add812eb7bdd90bd0f0fc3b633515edd55f27 DIFF: https://github.com/llvm/llvm-project/commit/2e7add812eb7bdd90bd0f0fc3b633515edd55f27.diff LOG: [clang-format] Add a option for the position of Java static import Some Java style guides and IDEs group Java static imports after non-static imports. This patch allows clang-format to control the location of static imports. Patch by: @bc-lee Reviewed By: MyDeveloperDay, JakeMerdichAMD Differential Revision: https://reviews.llvm.org/D87201 Added: Modified: clang/docs/ClangFormatStyleOptions.rst clang/include/clang/Format/Format.h clang/lib/Format/Format.cpp clang/unittests/Format/FormatTest.cpp clang/unittests/Format/SortImportsTestJava.cpp Removed: ################################################################################ diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 20e829135b33..0c3ed9f4ab84 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1964,10 +1964,12 @@ the configuration (without a prefix: ``Auto``). **JavaImportGroups** (``std::vector<std::string>``) A vector of prefixes ordered by the desired groups for Java imports. - Each group is separated by a newline. Static imports will also follow the - same grouping convention above all non-static imports. One group's prefix - can be a subset of another - the longest prefix is always matched. Within - a group, the imports are ordered lexicographically. + One group's prefix can be a subset of another - the longest prefix is + always matched. Within a group, the imports are ordered lexicographically. + Static imports are grouped separately and follow the same group rules. + By default, static imports are placed before non-static imports, + but this behavior is changed by another option, + ``SortJavaStaticImport``. In the .clang-format configuration file, this can be configured like in the following yaml example. This will result in imports being @@ -2393,6 +2395,33 @@ the configuration (without a prefix: ``Auto``). #include "b.h" vs. #include "a.h" #include "a.h" #include "b.h" +**SortJavaStaticImport** (``SortJavaStaticImportOptions``) + When sorting Java imports, by default static imports are placed before + non-static imports. If ``JavaStaticImportAfterImport`` is ``After``, + static imports are placed after non-static imports. + + Possible values: + + * ``SJSIO_Before`` (in configuration: ``Before``) + Static imports are placed before non-static imports. + + .. code-block:: java + + import static org.example.function1; + + import org.example.ClassA; + + * ``SJSIO_After`` (in configuration: ``After``) + Static imports are placed after non-static imports. + + .. code-block:: java + + import org.example.ClassA; + + import static org.example.function1; + + + **SortUsingDeclarations** (``bool``) If ``true``, clang-format will sort using declarations. diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index c6c182b7bdce..2840a6846018 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -1618,10 +1618,12 @@ struct FormatStyle { /// A vector of prefixes ordered by the desired groups for Java imports. /// - /// Each group is separated by a newline. Static imports will also follow the - /// same grouping convention above all non-static imports. One group's prefix - /// can be a subset of another - the longest prefix is always matched. Within - /// a group, the imports are ordered lexicographically. + /// One group's prefix can be a subset of another - the longest prefix is + /// always matched. Within a group, the imports are ordered lexicographically. + /// Static imports are grouped separately and follow the same group rules. + /// By default, static imports are placed before non-static imports, + /// but this behavior is changed by another option, + /// ``SortJavaStaticImport``. /// /// In the .clang-format configuration file, this can be configured like /// in the following yaml example. This will result in imports being @@ -2016,6 +2018,29 @@ struct FormatStyle { /// \endcode bool SortIncludes; + /// Position for Java Static imports. + enum SortJavaStaticImportOptions { + /// Static imports are placed before non-static imports. + /// \code{.java} + /// import static org.example.function1; + /// + /// import org.example.ClassA; + /// \endcode + SJSIO_Before, + /// Static imports are placed after non-static imports. + /// \code{.java} + /// import org.example.ClassA; + /// + /// import static org.example.function1; + /// \endcode + SJSIO_After, + }; + + /// When sorting Java imports, by default static imports are placed before + /// non-static imports. If ``JavaStaticImportAfterImport`` is ``After``, + /// static imports are placed after non-static imports. + SortJavaStaticImportOptions SortJavaStaticImport; + /// If ``true``, clang-format will sort using declarations. /// /// The order of using declarations is defined as follows: @@ -2435,6 +2460,7 @@ struct FormatStyle { R.PenaltyBreakTemplateDeclaration && PointerAlignment == R.PointerAlignment && RawStringFormats == R.RawStringFormats && + SortJavaStaticImport == R.SortJavaStaticImport && SpaceAfterCStyleCast == R.SpaceAfterCStyleCast && SpaceAfterLogicalNot == R.SpaceAfterLogicalNot && SpaceAfterTemplateKeyword == R.SpaceAfterTemplateKeyword && diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 5dda2bda06b5..03188b46099d 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -377,6 +377,15 @@ struct ScalarEnumerationTraits<FormatStyle::BitFieldColonSpacingStyle> { } }; +template <> +struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> { + static void enumeration(IO &IO, + FormatStyle::SortJavaStaticImportOptions &Value) { + IO.enumCase(Value, "Before", FormatStyle::SJSIO_Before); + IO.enumCase(Value, "After", FormatStyle::SJSIO_After); + } +}; + template <> struct MappingTraits<FormatStyle> { static void mapping(IO &IO, FormatStyle &Style) { // When reading, read the language first, we need it for getPredefinedStyle. @@ -574,6 +583,7 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("RawStringFormats", Style.RawStringFormats); IO.mapOptional("ReflowComments", Style.ReflowComments); IO.mapOptional("SortIncludes", Style.SortIncludes); + IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport); IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations); IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast); IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot); @@ -947,6 +957,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.DisableFormat = false; LLVMStyle.SortIncludes = true; + LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before; LLVMStyle.SortUsingDeclarations = true; LLVMStyle.StatementMacros.push_back("Q_UNUSED"); LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION"); @@ -2312,12 +2323,16 @@ static void sortJavaImports(const FormatStyle &Style, JavaImportGroups.push_back( findJavaImportGroup(Style, Imports[i].Identifier)); } + bool StaticImportAfterNormalImport = + Style.SortJavaStaticImport == FormatStyle::SJSIO_After; llvm::sort(Indices, [&](unsigned LHSI, unsigned RHSI) { // Negating IsStatic to push static imports above non-static imports. - return std::make_tuple(!Imports[LHSI].IsStatic, JavaImportGroups[LHSI], - Imports[LHSI].Identifier) < - std::make_tuple(!Imports[RHSI].IsStatic, JavaImportGroups[RHSI], - Imports[RHSI].Identifier); + return std::make_tuple(!Imports[LHSI].IsStatic ^ + StaticImportAfterNormalImport, + JavaImportGroups[LHSI], Imports[LHSI].Identifier) < + std::make_tuple(!Imports[RHSI].IsStatic ^ + StaticImportAfterNormalImport, + JavaImportGroups[RHSI], Imports[RHSI].Identifier); }); // Deduplicate imports. diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index eae7b24fae7c..eb72a01d3d27 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -14328,6 +14328,12 @@ TEST_F(FormatTest, ParsesConfiguration) { CHECK_PARSE("BitFieldColonSpacing: After", BitFieldColonSpacing, FormatStyle::BFCS_After); + Style.SortJavaStaticImport = FormatStyle::SJSIO_Before; + CHECK_PARSE("SortJavaStaticImport: After", SortJavaStaticImport, + FormatStyle::SJSIO_After); + CHECK_PARSE("SortJavaStaticImport: Before", SortJavaStaticImport, + FormatStyle::SJSIO_Before); + // FIXME: This is required because parsing a configuration simply overwrites // the first N elements of the list instead of resetting it. Style.ForEachMacros.clear(); diff --git a/clang/unittests/Format/SortImportsTestJava.cpp b/clang/unittests/Format/SortImportsTestJava.cpp index 12869eeb54ef..4a3e18abd453 100644 --- a/clang/unittests/Format/SortImportsTestJava.cpp +++ b/clang/unittests/Format/SortImportsTestJava.cpp @@ -250,6 +250,62 @@ TEST_F(SortImportsTestJava, FormatPariallyOnShouldNotReorder) { "import org.c;\n")); } +TEST_F(SortImportsTestJava, SortJavaStaticImport) { + FmtStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before; + EXPECT_EQ("import static com.test.a;\n" + "\n" + "import static org.a;\n" + "\n" + "import static com.a;\n" + "\n" + "import com.test.b;\n" + "\n" + "import org.b;\n" + "\n" + "import com.b;\n", + sort("import static com.test.a;\n" + "import static org.a;\n" + "import static com.a;\n" + "import com.test.b;\n" + "import org.b;\n" + "import com.b;\n")); + + FmtStyle.SortJavaStaticImport = FormatStyle::SJSIO_After; + EXPECT_EQ("import com.test.b;\n" + "import com.test.c;\n" + "\n" + "import org.b;\n" + "\n" + "import com.b;\n" + "\n" + "import static com.test.a;\n" + "\n" + "import static org.a;\n" + "\n" + "import static com.a;\n", + sort("import static com.test.a;\n" + "import static org.a;\n" + "import static com.a;\n" + "import com.test.b;\n" + "import org.b;\n" + "import com.b;\n" + "import com.test.c;\n")); +} + +TEST_F(SortImportsTestJava, SortJavaStaticImportAsGroup) { + FmtStyle.SortJavaStaticImport = FormatStyle::SJSIO_After; + + EXPECT_EQ("import com.test.a;\n" + "import com.test.b;\n" + "\n" + "import static org.a;\n" + "import static org.b;\n", + sort("import com.test.a;\n" + "import static org.a;\n" + "import com.test.b;\n" + "import static org.b;\n")); +} + TEST_F(SortImportsTestJava, DeduplicateImports) { EXPECT_EQ("import org.a;\n", sort("import org.a;\n" "import org.a;\n")); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits