diff --git a/pom.xml b/pom.xml index 402f720..5088bbb 100644 --- a/pom.xml +++ b/pom.xml @@ -380,6 +380,13 @@ org.apache.rat apache-rat-plugin + + + src/test/resources/EmptyFile.java + src/test/resources/FileWithoutNewline.java + src/test/resources/InvalidFile.java + + check-licenses diff --git a/src/main/java/net/revelc/code/impsort/EmptyFileException.java b/src/main/java/net/revelc/code/impsort/EmptyFileException.java new file mode 100644 index 0000000..ddae7b6 --- /dev/null +++ b/src/main/java/net/revelc/code/impsort/EmptyFileException.java @@ -0,0 +1,50 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.revelc.code.impsort; + +import java.io.IOException; +import java.nio.file.Path; + +/** + * Signals that the file denoted by this path is empty. + * + *

+ * This exception will be thrown by the {@link ImpSort#parseFile} when it encounters an empty file. + *

+ */ +public class EmptyFileException extends IOException { + private static final long serialVersionUID = -4202864513494828247L; + + private final Path path; + + /** + * Constructs a {@code EmptyFileException} with {@code null} as its error detail message and the + * specified path. + * + * @param path the path + */ + public EmptyFileException(final Path path) { + this.path = path; + } + + /** + * Returns the path. + * + * @return the path + */ + public Path getPath() { + return path; + } +} diff --git a/src/main/java/net/revelc/code/impsort/ImpSort.java b/src/main/java/net/revelc/code/impsort/ImpSort.java index f1c2e6a..7982d1d 100644 --- a/src/main/java/net/revelc/code/impsort/ImpSort.java +++ b/src/main/java/net/revelc/code/impsort/ImpSort.java @@ -45,7 +45,6 @@ import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.PackageDeclaration; -import com.github.javaparser.ast.body.TypeDeclaration; import com.github.javaparser.ast.comments.Comment; import com.github.javaparser.ast.comments.JavadocComment; import com.github.javaparser.javadoc.Javadoc; @@ -73,9 +72,19 @@ public ImpSort(final Charset sourceEncoding, final Grouper grouper, final boolea this.lineEnding = lineEnding; } - public Result parseFile(final Path path) throws IOException { - String file = new String(Files.readAllBytes(path), sourceEncoding); + public Result parseFile(final Path path) + throws IOException, EmptyFileException, UnknownLineEndingException { + byte[] buf = Files.readAllBytes(path); + + if (buf.length == 0) { + throw new EmptyFileException(path); + } + + String file = new String(buf, sourceEncoding); LineEnding fileLineEnding = LineEnding.determineLineEnding(file); + if (fileLineEnding == LineEnding.UNKNOWN) { + throw new UnknownLineEndingException(path); + } LineEnding impLineEnding; if (lineEnding == LineEnding.KEEP) { impLineEnding = fileLineEnding; @@ -84,8 +93,12 @@ public Result parseFile(final Path path) throws IOException { } List fileLines = Arrays.asList(file.split(fileLineEnding.getChars())); ParseResult parseResult = new JavaParser().parse(file); - CompilationUnit unit = - parseResult.getResult().orElseThrow(() -> new IOException("Unable to parse " + path)); + Optional unitOptional = parseResult.getResult(); + + if (!parseResult.isSuccessful() || !unitOptional.isPresent()) { + throw new IOException("Unable to parse " + path); + } + CompilationUnit unit = unitOptional.get(); Position packagePosition = unit.getPackageDeclaration().map(p -> p.getEnd().get()).orElse(unit.getBegin().get()); NodeList importDeclarations = unit.getImports(); diff --git a/src/main/java/net/revelc/code/impsort/LineEnding.java b/src/main/java/net/revelc/code/impsort/LineEnding.java index 11d5a45..bc8cb40 100644 --- a/src/main/java/net/revelc/code/impsort/LineEnding.java +++ b/src/main/java/net/revelc/code/impsort/LineEnding.java @@ -19,7 +19,7 @@ */ public enum LineEnding { - AUTO(System.lineSeparator()), KEEP(null), LF("\n"), CRLF("\r\n"), CR("\r"), UNKNOWN(null); + AUTO(System.lineSeparator()), KEEP(null), LF("\n"), CRLF("\r\n"), CR("\r"), UNKNOWN(""); private final String chars; @@ -43,10 +43,11 @@ public static LineEnding determineLineEnding(String fileDataString) { int crCount = 0; int crlfCount = 0; - for (int i = 0; i < fileDataString.length(); i++) { - char c = fileDataString.charAt(i); + final int length = fileDataString.length(); + for (int i = 0; i < length; i++) { + final char c = fileDataString.charAt(i); if (c == '\r') { - if ((i + 1) < fileDataString.length() && fileDataString.charAt(i + 1) == '\n') { + if ((i + 1) < length && fileDataString.charAt(i + 1) == '\n') { crlfCount++; i++; } else { diff --git a/src/main/java/net/revelc/code/impsort/Result.java b/src/main/java/net/revelc/code/impsort/Result.java index 274d232..ed17fc2 100644 --- a/src/main/java/net/revelc/code/impsort/Result.java +++ b/src/main/java/net/revelc/code/impsort/Result.java @@ -58,6 +58,10 @@ public class Result { } public boolean isSorted() { + if (lineEnding == LineEnding.UNKNOWN) { + return true; + } + if (isSorted == null) { isSorted = originalSection.contentEquals(newSection); } diff --git a/src/main/java/net/revelc/code/impsort/UnknownLineEndingException.java b/src/main/java/net/revelc/code/impsort/UnknownLineEndingException.java new file mode 100644 index 0000000..cf2d6d0 --- /dev/null +++ b/src/main/java/net/revelc/code/impsort/UnknownLineEndingException.java @@ -0,0 +1,51 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.revelc.code.impsort; + +import java.io.IOException; +import java.nio.file.Path; + +/** + * Signals that the file denoted by this path has an unknown line ending. + * + *

+ * This exception will be thrown by the {@link ImpSort#parseFile} when it encounters a file with an + * unknown line ending. + *

+ */ +public class UnknownLineEndingException extends IOException { + private static final long serialVersionUID = 4417291768648259852L; + + private final Path path; + + /** + * Constructs a {@code UnknownLineEndingException} with {@code null} as its error detail message + * and the specified path. + * + * @param path the path + */ + public UnknownLineEndingException(final Path path) { + this.path = path; + } + + /** + * Returns the path. + * + * @return the path + */ + public Path getPath() { + return path; + } +} diff --git a/src/main/java/net/revelc/code/impsort/maven/plugin/AbstractImpSortMojo.java b/src/main/java/net/revelc/code/impsort/maven/plugin/AbstractImpSortMojo.java index a3a42b7..7c6c73e 100644 --- a/src/main/java/net/revelc/code/impsort/maven/plugin/AbstractImpSortMojo.java +++ b/src/main/java/net/revelc/code/impsort/maven/plugin/AbstractImpSortMojo.java @@ -34,10 +34,12 @@ import org.apache.maven.project.MavenProject; import org.codehaus.plexus.util.DirectoryScanner; +import net.revelc.code.impsort.EmptyFileException; import net.revelc.code.impsort.Grouper; import net.revelc.code.impsort.ImpSort; import net.revelc.code.impsort.LineEnding; import net.revelc.code.impsort.Result; +import net.revelc.code.impsort.UnknownLineEndingException; abstract class AbstractImpSortMojo extends AbstractMojo { @@ -233,6 +235,10 @@ public final void execute() throws MojoExecutionException, MojoFailureException numProcessed.getAndIncrement(); } processResult(path, result); + } catch (EmptyFileException e) { + getLog().warn("Skipping empty file " + e.getPath()); + } catch (UnknownLineEndingException e) { + getLog().warn("Skipping file with unknown line ending " + e.getPath()); } catch (IOException e) { fail("Error reading file " + path, e); } diff --git a/src/test/java/net/revelc/code/impsort/FileTest.java b/src/test/java/net/revelc/code/impsort/FileTest.java new file mode 100644 index 0000000..7919458 --- /dev/null +++ b/src/test/java/net/revelc/code/impsort/FileTest.java @@ -0,0 +1,63 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.revelc.code.impsort; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.junit.Test; + +/** + * Test class for special file cases. + */ +public class FileTest { + + private static Grouper eclipseDefaults = + new Grouper("java.,javax.,org.,com.", "", false, false, true); + + /** + * Test successfully parsing empty (0 byte) file. + */ + @Test(expected = EmptyFileException.class) + public void test_empty_file() throws IOException, EmptyFileException, UnknownLineEndingException { + Path p = + Paths.get(System.getProperty("user.dir"), "src", "test", "resources", "EmptyFile.java"); + new ImpSort(StandardCharsets.UTF_8, eclipseDefaults, true, true, LineEnding.AUTO).parseFile(p); + } + + /** + * Test successfully parsing file without any newline. + */ + @Test(expected = UnknownLineEndingException.class) + public void test_file_without_newline() + throws IOException, EmptyFileException, UnknownLineEndingException { + Path p = Paths.get(System.getProperty("user.dir"), "src", "test", "resources", + "FileWithoutNewline.java"); + new ImpSort(StandardCharsets.UTF_8, eclipseDefaults, true, true, LineEnding.AUTO).parseFile(p); + } + + /** + * Test successfully parsing file without any newline. + */ + @Test(expected = IOException.class) + public void test_invalid_file() + throws IOException, EmptyFileException, UnknownLineEndingException { + Path p = + Paths.get(System.getProperty("user.dir"), "src", "test", "resources", "InvalidFile.java"); + new ImpSort(StandardCharsets.UTF_8, eclipseDefaults, true, true, LineEnding.AUTO).parseFile(p); + } + +} diff --git a/src/test/resources/EmptyFile.java b/src/test/resources/EmptyFile.java new file mode 100644 index 0000000..e69de29 diff --git a/src/test/resources/FileWithoutNewline.java b/src/test/resources/FileWithoutNewline.java new file mode 100644 index 0000000..187002a --- /dev/null +++ b/src/test/resources/FileWithoutNewline.java @@ -0,0 +1 @@ +import java.lang.System;public class FileWithoutNewline{public static void main(String[] args){System.out.println("Hello, world!");}} \ No newline at end of file diff --git a/src/test/resources/InvalidFile.java b/src/test/resources/InvalidFile.java new file mode 100644 index 0000000..f203322 --- /dev/null +++ b/src/test/resources/InvalidFile.java @@ -0,0 +1,5 @@ +public class InvalidFile { + public static void main(String[] args) { + System.out.println("Hello, world!") + } +}