From 18af99d30d4775f6cf7e0c521bca8657bf04e008 Mon Sep 17 00:00:00 2001 From: Frank Vennemeyer Date: Tue, 16 May 2017 22:27:37 +0200 Subject: [PATCH] Enhance Import Sorter/Order to cope with multi-line comments and misplaced imports --- .../diffplug/spotless/java/ImportSorter.java | 23 ++++++++++++++++++- .../spotless/java/ImportOrderStepTest.java | 12 ++++++++++ .../importsorter/JavaCodeImportComments.test | 14 +++++++++++ .../JavaCodeSortedMisplacedImports.test | 13 +++++++++++ .../JavaCodeUnsortedMisplacedImports.test | 16 +++++++++++++ 5 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 testlib/src/test/resources/java/importsorter/JavaCodeImportComments.test create mode 100644 testlib/src/test/resources/java/importsorter/JavaCodeSortedMisplacedImports.test create mode 100644 testlib/src/test/resources/java/importsorter/JavaCodeUnsortedMisplacedImports.test diff --git a/lib/src/main/java/com/diffplug/spotless/java/ImportSorter.java b/lib/src/main/java/com/diffplug/spotless/java/ImportSorter.java index 845b6c63da..0fd88bff31 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/ImportSorter.java +++ b/lib/src/main/java/com/diffplug/spotless/java/ImportSorter.java @@ -40,6 +40,7 @@ public String format(String raw) { int firstImportLine = 0; int lastImportLine = 0; int line = 0; + boolean isMultiLineComment = false; List imports = new ArrayList<>(); while (scanner.hasNext()) { line++; @@ -47,6 +48,15 @@ public String format(String raw) { if (next == null) { break; } + //Since we have no AST, we only consider the most common use cases. + isMultiLineComment |= next.contains("/*"); + if (isMultiLineComment && next.contains("*/")) { + isMultiLineComment = false; + if (!next.contains("/*")) { + continue; + } + } + if (next.startsWith("import ")) { int i = next.indexOf("."); if (isNotValidImport(i)) { @@ -59,10 +69,13 @@ public String format(String raw) { int endIndex = next.indexOf(";"); String imprt = next.substring(START_INDEX_OF_IMPORTS_PACKAGE_DECLARATION, endIndex != -1 ? endIndex : next.length()); - if (!imports.contains(imprt)) { + if (!isMultiLineComment && !imports.contains(imprt)) { imports.add(imprt); } } + if (!isMultiLineComment && isBeginningOfScope(next)) { + break; //Don't dare to touch lines after a scope started + } } scanner.close(); @@ -70,6 +83,14 @@ public String format(String raw) { return applyImportsToDocument(raw, firstImportLine, lastImportLine, sortedImports); } + private static boolean isBeginningOfScope(String line) { + int scope = line.indexOf("{"); + if (0 <= scope) { + return !line.substring(0, scope).contains("//"); + } + return false; + } + private static String applyImportsToDocument(final String document, int firstImportLine, int lastImportLine, List strings) { boolean importsAlreadyAppended = false; Scanner scanner = new Scanner(document); diff --git a/testlib/src/test/java/com/diffplug/spotless/java/ImportOrderStepTest.java b/testlib/src/test/java/com/diffplug/spotless/java/ImportOrderStepTest.java index dc174d689f..b06283124f 100644 --- a/testlib/src/test/java/com/diffplug/spotless/java/ImportOrderStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/java/ImportOrderStepTest.java @@ -50,6 +50,18 @@ public void removeDuplicates() throws Throwable { assertOnResources(step, "java/importsorter/JavaCodeSortedDuplicateImportsUnmatched.test", "java/importsorter/JavaCodeSortedImportsUnmatched.test"); } + @Test + public void removeComments() throws Throwable { + FormatterStep step = ImportOrderStep.createFromFile(createTestFile("java/importsorter/import.properties")); + assertOnResources(step, "java/importsorter/JavaCodeImportComments.test", "java/importsorter/JavaCodeSortedImports.test"); + } + + @Test + public void misplacedImports() throws Throwable { + FormatterStep step = ImportOrderStep.createFromFile(createTestFile("java/importsorter/import.properties")); + assertOnResources(step, "java/importsorter/JavaCodeUnsortedMisplacedImports.test", "java/importsorter/JavaCodeSortedMisplacedImports.test"); + } + @Test public void doesntThrowIfImportOrderIsntSerializable() { ImportOrderStep.createFromOrder(NonSerializableList.of("java", "javax", "org", "\\#com")); diff --git a/testlib/src/test/resources/java/importsorter/JavaCodeImportComments.test b/testlib/src/test/resources/java/importsorter/JavaCodeImportComments.test new file mode 100644 index 0000000000..879e4a7e6f --- /dev/null +++ b/testlib/src/test/resources/java/importsorter/JavaCodeImportComments.test @@ -0,0 +1,14 @@ +import static java.lang.Exception.*; +//Will be removed +import org.dooda.Didoo; /* Comment removed, import stays */ +import java.lang.Thread; /* Don't */ /* get */ /* confused */ +import java.lang.Runnable; +/* import org.comments.will +import org.comments.be +import org.comments.removed +*/ +import static java.lang.Runnable.*; +/* +import other.multiline.comments +import will.be.removed.too */ +import static com.foo.Bar diff --git a/testlib/src/test/resources/java/importsorter/JavaCodeSortedMisplacedImports.test b/testlib/src/test/resources/java/importsorter/JavaCodeSortedMisplacedImports.test new file mode 100644 index 0000000000..cf872c9ebc --- /dev/null +++ b/testlib/src/test/resources/java/importsorter/JavaCodeSortedMisplacedImports.test @@ -0,0 +1,13 @@ +import java.lang.Runnable; +import java.lang.Thread; + +import org.dooda.Didoo; + +import static java.lang.Exception.*; +import static java.lang.Runnable.*; + +import static com.foo.Bar; +public class NotDeletedByFormatter { +} +import will.not; +import be.sorted; diff --git a/testlib/src/test/resources/java/importsorter/JavaCodeUnsortedMisplacedImports.test b/testlib/src/test/resources/java/importsorter/JavaCodeUnsortedMisplacedImports.test new file mode 100644 index 0000000000..d6a5e3cc42 --- /dev/null +++ b/testlib/src/test/resources/java/importsorter/JavaCodeUnsortedMisplacedImports.test @@ -0,0 +1,16 @@ +import static java.lang.Exception.*; +import org.dooda.Didoo; +/* +public class IgnoredAndRemoved { +} +*/ +import java.lang.Thread; +// Will be removed {} +import java.lang.Runnable; + +import static java.lang.Runnable.*; +import static com.foo.Bar +public class NotDeletedByFormatter { +} +import will.not; +import be.sorted;