diff --git a/core/src/main/java/com/google/googlejavaformat/java/Formatter.java b/core/src/main/java/com/google/googlejavaformat/java/Formatter.java index 785a9a344..aca932dda 100644 --- a/core/src/main/java/com/google/googlejavaformat/java/Formatter.java +++ b/core/src/main/java/com/google/googlejavaformat/java/Formatter.java @@ -32,6 +32,7 @@ import com.google.googlejavaformat.Newlines; import com.google.googlejavaformat.Op; import com.google.googlejavaformat.OpsBuilder; +import com.google.googlejavaformat.java.RemoveUnusedImports.JavadocOnlyImports; import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.parser.JavacParser; import com.sun.tools.javac.parser.ParserFactory; @@ -194,6 +195,8 @@ public void formatSource(CharSource input, CharSink output) /** * Format an input string (a Java compilation unit) into an output string. * + *

Leaves import statements untouched. + * * @param input the input string * @return the output string * @throws FormatterException if the input string cannot be parsed @@ -202,6 +205,25 @@ public String formatSource(String input) throws FormatterException { return formatSource(input, Collections.singleton(Range.closedOpen(0, input.length()))); } + /** + * Format an input string (a Java compilation unit) and optimize imports into an output string. + * + *

Optimizing imports includes ordering, spacing and removal of unused import statements. An + * import used only in a Javadoc comment is considered as unused and therefore removed from the + * import statements and its usage within the comment replaced by its fully qualified name. + * + * @param input the input string + * @return the output string + * @throws FormatterException if the input string cannot be parsed + * @see + * Google Java Style Guide - 3.3.3 Import ordering and spacing + */ + public String formatSourceAndOptimizeImports(String input) throws FormatterException { + input = ImportOrderer.reorderImports(input); + input = RemoveUnusedImports.removeUnusedImports(input, JavadocOnlyImports.REMOVE); + return formatSource(input); + } + /** * Format an input string (a Java compilation unit), for only the specified character ranges. * These ranges are extended as necessary (e.g., to encompass whole lines). diff --git a/core/src/test/java/com/google/googlejavaformat/java/FormatterTest.java b/core/src/test/java/com/google/googlejavaformat/java/FormatterTest.java index 1967b6b97..be0a99953 100644 --- a/core/src/test/java/com/google/googlejavaformat/java/FormatterTest.java +++ b/core/src/test/java/com/google/googlejavaformat/java/FormatterTest.java @@ -248,6 +248,15 @@ public void importsNotReorderedByDefault() throws FormatterException { assertThat(output).isEqualTo(expect); } + @Test + public void importsOptimizedIfRequested() throws FormatterException { + String input = + "package com.google.example;\n" + UNORDERED_IMPORTS + "\npublic class ExampleTest {}\n"; + String output = new Formatter().formatSourceAndOptimizeImports(input); + String expect = "package com.google.example;\n\npublic class ExampleTest {}\n"; + assertThat(output).isEqualTo(expect); + } + @Test public void importOrderingWithoutFormatting() throws IOException, UsageException { importOrdering( diff --git a/core/src/test/java/com/google/googlejavaformat/java/MainTest.java b/core/src/test/java/com/google/googlejavaformat/java/MainTest.java index b59f3a50d..cae9abfb7 100644 --- a/core/src/test/java/com/google/googlejavaformat/java/MainTest.java +++ b/core/src/test/java/com/google/googlejavaformat/java/MainTest.java @@ -30,6 +30,7 @@ import java.nio.file.Paths; import java.nio.file.attribute.PosixFilePermission; import java.util.EnumSet; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -204,6 +205,40 @@ public void imports() throws Exception { } } + @Test + @Ignore("FormatFileCallable.call() needs a second format run after fixing imports") + public void optimizeImportsDoesNotLeaveEmptyLines() throws Exception { + String[] input = { + "package abc;", + "", + "import java.util.LinkedList;", + "import java.util.List;", + "import java.util.ArrayList;", + "", + "import static java.nio.charset.StandardCharsets.UTF_8;", + "", + "import java.util.EnumSet;", + "", + "class Test ", + "extends ArrayList {", + "}" + }; + { + String[] expected = { + "package abc;", "", "import java.util.ArrayList;", "", "class Test extends ArrayList {}", "" + }; + // pre-check expectation with local formatter instance + String optimized = new Formatter().formatSourceAndOptimizeImports(joiner.join(input)); + assertThat(optimized).isEqualTo(joiner.join(expected)); + + InputStream in = new ByteArrayInputStream(joiner.join(input).getBytes(UTF_8)); + StringWriter out = new StringWriter(); + Main main = new Main(new PrintWriter(out, true), new PrintWriter(System.err, true), in); + assertThat(main.format("-")).isEqualTo(0); + assertThat(out.toString()).isEqualTo(joiner.join(expected)); + } + } + // test that -lines handling works with import removal @Test public void importRemovalLines() throws Exception {