From 7f652fecf1ea2f23c9a5ab1721b3348a9601fdd0 Mon Sep 17 00:00:00 2001 From: Christopher Tubbs Date: Thu, 10 Sep 2020 10:45:09 -0400 Subject: [PATCH] Handle empty files and unknown line endings better * Return an empty result if the file is empty to skip the file * Only throw an exception when line ending is unknown, if the line ending configuration is set to KEEP * When reading all lines from the buffer into a list, do not depend on the previously detected line endings, and instead read all lines as-is, regardless of line ending previously detected --- .../java/net/revelc/code/impsort/ImpSort.java | 22 +++++++++---- .../java/net/revelc/code/impsort/Result.java | 4 +++ .../code/impsort/ex/ImpSortException.java | 1 - .../code/impsort/LineEndingEdgeCasesTest.java | 33 +++++++++++++++---- 4 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/main/java/net/revelc/code/impsort/ImpSort.java b/src/main/java/net/revelc/code/impsort/ImpSort.java index 9bd3b39..41144a4 100644 --- a/src/main/java/net/revelc/code/impsort/ImpSort.java +++ b/src/main/java/net/revelc/code/impsort/ImpSort.java @@ -22,7 +22,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.EnumSet; @@ -30,6 +29,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; +import java.util.Scanner; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -75,6 +75,16 @@ public ImpSort(final Charset sourceEncoding, final Grouper grouper, final boolea this.lineEnding = lineEnding; } + private static List readAllLines(String str) { + List result = new ArrayList<>(); + try (Scanner s = new Scanner(str)) { + while (s.hasNextLine()) { + result.add(s.nextLine()); + } + } + return result; + } + /** * Parses the file denoted by this path and returns the result. * @@ -85,20 +95,20 @@ public ImpSort(final Charset sourceEncoding, final Grouper grouper, final boolea public Result parseFile(final Path path) throws IOException { byte[] buf = Files.readAllBytes(path); if (buf.length == 0) { - throw new ImpSortException(path, Reason.EMPTY_FILE); + return Result.EMPTY_FILE; } String file = new String(buf, sourceEncoding); LineEnding fileLineEnding = LineEnding.determineLineEnding(file); - if (fileLineEnding == LineEnding.UNKNOWN) { - throw new ImpSortException(path, Reason.UNKNOWN_LINE_ENDING); - } LineEnding impLineEnding; if (lineEnding == LineEnding.KEEP) { + if (fileLineEnding == LineEnding.UNKNOWN) { + throw new ImpSortException(path, Reason.UNKNOWN_LINE_ENDING); + } impLineEnding = fileLineEnding; } else { impLineEnding = lineEnding; } - List fileLines = Arrays.asList(file.split(fileLineEnding.getChars())); + List fileLines = readAllLines(file); ParseResult parseResult = new JavaParser().parse(file); CompilationUnit unit = parseResult.getResult() .orElseThrow(() -> new ImpSortException(path, Reason.UNABLE_TO_PARSE)); diff --git a/src/main/java/net/revelc/code/impsort/Result.java b/src/main/java/net/revelc/code/impsort/Result.java index 274d232..d8243f5 100644 --- a/src/main/java/net/revelc/code/impsort/Result.java +++ b/src/main/java/net/revelc/code/impsort/Result.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.List; public class Result { @@ -43,6 +44,9 @@ public class Result { private final int stop; private final LineEnding lineEnding; + public static final Result EMPTY_FILE = + new Result(null, null, null, 0, 0, "", "", Collections.emptyList(), null); + Result(Path path, Charset sourceEncoding, List fileLines, int start, int stop, String originalSection, String newSection, Collection allImports, LineEnding lineEnding) { diff --git a/src/main/java/net/revelc/code/impsort/ex/ImpSortException.java b/src/main/java/net/revelc/code/impsort/ex/ImpSortException.java index a1a8ee3..d2f95a7 100644 --- a/src/main/java/net/revelc/code/impsort/ex/ImpSortException.java +++ b/src/main/java/net/revelc/code/impsort/ex/ImpSortException.java @@ -21,7 +21,6 @@ public class ImpSortException extends IOException { public enum Reason { // @formatter:off - EMPTY_FILE("empty file"), UNKNOWN_LINE_ENDING("unknown line ending"), UNABLE_TO_PARSE("unable to successfully parse the Java file"), PARTIAL_PARSE("the Java file contained parse errors") diff --git a/src/test/java/net/revelc/code/impsort/LineEndingEdgeCasesTest.java b/src/test/java/net/revelc/code/impsort/LineEndingEdgeCasesTest.java index e48c68e..74ab744 100644 --- a/src/test/java/net/revelc/code/impsort/LineEndingEdgeCasesTest.java +++ b/src/test/java/net/revelc/code/impsort/LineEndingEdgeCasesTest.java @@ -15,6 +15,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; @@ -50,27 +51,45 @@ public class LineEndingEdgeCasesTest { public void testEmptyFile() throws IOException { Path p = folder.newFile("EmptyFile.java").toPath(); Files.write(p, new byte[0]); - ImpSortException e = assertThrows(ImpSortException.class, - () -> new ImpSort(UTF_8, eclipseDefaults, true, true, LineEnding.AUTO).parseFile(p)); - assertTrue(e.getReason() == Reason.EMPTY_FILE); - assertEquals("file: " + p + "; reason: empty file", e.getMessage()); + Result actual = new ImpSort(UTF_8, eclipseDefaults, true, true, LineEnding.AUTO).parseFile(p); + assertEquals(Result.EMPTY_FILE, actual); + assertTrue(actual.getImports().isEmpty()); + assertTrue(actual.isSorted()); } /** - * Test successfully parsing file without any line ending. + * Test successfully parsing file without any line ending, but line ending config set to KEEP. */ @Test - public void testFileWithoutLineEnding() throws IOException { + public void testFileKeepWithoutLineEnding() throws IOException { String s = "import java.lang.System;public class FileWithoutNewline{public static void main(String[] args){System.out.println(\"Hello, world!\");}}"; Path p = folder.newFile("FileWithoutLineEnding.java").toPath(); Files.write(p, s.getBytes(UTF_8)); ImpSortException e = assertThrows(ImpSortException.class, - () -> new ImpSort(UTF_8, eclipseDefaults, true, true, LineEnding.AUTO).parseFile(p)); + () -> new ImpSort(UTF_8, eclipseDefaults, true, true, LineEnding.KEEP).parseFile(p)); assertTrue(e.getReason() == Reason.UNKNOWN_LINE_ENDING); assertEquals("file: " + p + "; reason: unknown line ending", e.getMessage()); } + /** + * Test successfully parsing file without any line ending, and line ending config set to AUTO. + */ + @Test + public void testFileAutoWithoutLineEnding() throws IOException { + String s = + "import java.lang.System;public class FileWithoutNewline{public static void main(String[] args){System.out.println(\"Hello, world!\");}}"; + Path p = folder.newFile("FileWithoutLineEnding.java").toPath(); + Files.write(p, s.getBytes(UTF_8)); + Result result = new ImpSort(UTF_8, eclipseDefaults, true, true, LineEnding.AUTO).parseFile(p); + assertEquals(1, result.getImports().size()); + assertEquals("java.lang.System", result.getImports().iterator().next().getImport()); + assertTrue(result.getImports().iterator().next().getPrefix().isEmpty()); + assertTrue(result.getImports().iterator().next().getSuffix().isEmpty()); + assertFalse(result.getImports().iterator().next().isStatic()); + assertFalse(result.isSorted()); + } + /** * Test when the parser partially parses the file and creates a partial result. */