From dc40bc27b8b8c09f7982fd8eafe7bd723feb94d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 24 Apr 2022 17:38:35 +0200 Subject: [PATCH] More tests --- .../pmd/lang/document/NioTextFile.java | 2 +- .../lang/document/ReadOnlyFileException.java | 4 ++ .../pmd/lang/document/TextFile.java | 2 +- .../pmd/lang/document/TextFileContent.java | 19 +++--- .../pmd/lang/document/TextPos2d.java | 6 +- .../pmd/lang/document/TextRange2d.java | 12 ++-- .../document/internal/LanguageDiscoverer.java | 63 ------------------- .../pmd/lang/document/FileLocationTest.java | 7 +++ .../document/SourceCodePositionerTest.java | 4 ++ .../pmd/lang/document/TextFilesTest.java | 26 +++++++- .../pmd/lang/document/TextPos2dTest.java | 22 +++++++ .../pmd/lang/document/TextRange2dTest.java | 20 ++++++ 12 files changed, 102 insertions(+), 85 deletions(-) delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/document/internal/LanguageDiscoverer.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/NioTextFile.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/NioTextFile.java index f362a231cc..c0400e9294 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/NioTextFile.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/NioTextFile.java @@ -69,7 +69,7 @@ class NioTextFile extends BaseCloseable implements TextFile { public void writeContents(TextFileContent content) throws IOException { ensureOpen(); if (isReadOnly()) { - throw new ReadOnlyFileException(); + throw new ReadOnlyFileException(this); } try (BufferedWriter bw = Files.newBufferedWriter(path, charset)) { if (content.getLineTerminator().equals(TextFileContent.NORMALIZED_LINE_TERM)) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/ReadOnlyFileException.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/ReadOnlyFileException.java index 28b739c21c..df27cb13c1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/ReadOnlyFileException.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/ReadOnlyFileException.java @@ -10,4 +10,8 @@ package net.sourceforge.pmd.lang.document; */ public class ReadOnlyFileException extends UnsupportedOperationException { + public ReadOnlyFileException(TextFile textFile) { + super("Read only: " + textFile.getPathId()); + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/TextFile.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/TextFile.java index 6b7ccff057..83ab966a47 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/TextFile.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/TextFile.java @@ -109,7 +109,7 @@ public interface TextFile extends Closeable { * @throws ReadOnlyFileException If this text source is read-only */ default void writeContents(TextFileContent content) throws IOException { - throw new ReadOnlyFileException(); + throw new ReadOnlyFileException(this); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/TextFileContent.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/TextFileContent.java index 0d4234c5ae..cb77db852c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/TextFileContent.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/TextFileContent.java @@ -30,11 +30,16 @@ import org.checkerframework.checker.nullness.qual.Nullable; */ public final class TextFileContent { + // the three line terminators we handle. + private static final String CRLF = "\r\n"; + private static final String LF = "\n"; + private static final String CR = "\r"; + /** * The normalized line ending used to replace platform-specific * line endings in the {@linkplain #getNormalizedText() normalized text}. */ - public static final String NORMALIZED_LINE_TERM = "\n"; + public static final String NORMALIZED_LINE_TERM = LF; /** The normalized line ending as a char. */ public static final char NORMALIZED_LINE_TERM_CHAR = '\n'; @@ -225,10 +230,10 @@ public final class TextFileContent { if (afterCr && c != NORMALIZED_LINE_TERM_CHAR) { // we saw a \r last iteration, but didn't copy it // it's not followed by an \n - newLineTerm = "\r"; + newLineTerm = CR; newLineOffset = bufOffset + i + offsetDiff; if (i > 0) { - cbuf[i - 1] = '\n'; // replace the \r with a \n + cbuf[i - 1] = NORMALIZED_LINE_TERM_CHAR; // replace the \r with a \n } else { // The CR was trailing a buffer, so it's not in the current buffer and wasn't copied. // Append a newline. @@ -236,10 +241,10 @@ public final class TextFileContent { } } else { if (afterCr) { - newLineTerm = "\r\n"; + newLineTerm = CRLF; if (i > 0) { - cbuf[i - 1] = '\n'; // replace the \r with a \n + cbuf[i - 1] = NORMALIZED_LINE_TERM_CHAR; // replace the \r with a \n // copy up to and including the \r, which was replaced result.append(cbuf, nextCharToCopy, i - nextCharToCopy); nextCharToCopy = i + 1; // set the next char to copy to after the \n @@ -249,7 +254,7 @@ public final class TextFileContent { offsetDiff--; } else { // just \n - newLineTerm = "\n"; + newLineTerm = LF; } newLineOffset = bufOffset + i + offsetDiff + 1; } @@ -275,7 +280,7 @@ public final class TextFileContent { if (afterCr) { // we're at EOF, so it's not followed by \n result.append(NORMALIZED_LINE_TERM); positionerBuilder.addLineEndAtOffset(bufOffset); - detectedLineTerm = detectLineTerm(detectedLineTerm, "\r", fallbackLineSep); + detectedLineTerm = detectLineTerm(detectedLineTerm, CR, fallbackLineSep); } if (detectedLineTerm == null) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/TextPos2d.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/TextPos2d.java index bdf767af3b..b554cd3eda 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/TextPos2d.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/TextPos2d.java @@ -18,7 +18,7 @@ public final class TextPos2d implements Comparable { this.line = line; this.column = column; - assert line > 0 && column > 0 : "Invalid position" + parThis(); + assert line > 0 && column > 0 : "Invalid position " + toTupleString(); } /** @@ -44,10 +44,6 @@ public final class TextPos2d implements Comparable { return new TextPos2d(line, column); } - private String parThis() { - return "(" + this + ")"; - } - /** Compares the start offset, then the length of a region. */ @Override diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/TextRange2d.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/TextRange2d.java index 25f6d49dc8..14519896a9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/TextRange2d.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/TextRange2d.java @@ -4,12 +4,18 @@ package net.sourceforge.pmd.lang.document; +import java.util.Comparator; import java.util.Objects; /** * A place in a text document, represented as line/column information. */ public final class TextRange2d implements Comparable { + private static final Comparator COMPARATOR = + Comparator.comparingInt(TextRange2d::getStartLine) + .thenComparingInt(TextRange2d::getStartColumn) + .thenComparingInt(TextRange2d::getEndLine) + .thenComparingInt(TextRange2d::getEndColumn); private final int startLine; private final int startCol; @@ -69,11 +75,7 @@ public final class TextRange2d implements Comparable { @Override public int compareTo(TextRange2d o) { - int cmp = getStartPos().compareTo(o.getStartPos()); - if (cmp != 0) { - return cmp; - } - return getEndPos().compareTo(o.getEndPos()); + return COMPARATOR.compare(this, o); } public boolean contains(TextRange2d range) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/internal/LanguageDiscoverer.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/internal/LanguageDiscoverer.java deleted file mode 100644 index 0544cc175c..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/internal/LanguageDiscoverer.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.document.internal; - -import java.nio.file.Path; -import java.util.Collections; -import java.util.List; - -import org.apache.commons.lang3.StringUtils; - -import net.sourceforge.pmd.lang.Language; -import net.sourceforge.pmd.lang.LanguageRegistry; - -/** - * Discovers the languages applicable to a file. - */ -public class LanguageDiscoverer { - - - private final Language forcedLanguage; - - /** - * Build a new instance. - * - * @param forcedLanguage If non-null, all files will be assigned this language. - */ - public LanguageDiscoverer(Language forcedLanguage) { - this.forcedLanguage = forcedLanguage; - } - - /** - * Get the Languages of a given source file. - * - * @param sourceFile The file. - * - * @return The Languages for the source file, may be empty. - */ - public List getLanguagesForFile(Path sourceFile) { - return getLanguagesForFile(sourceFile.getFileName().toString()); - } - - /** - * Get the Languages of a given source file. - * - * @param fileName The file name. - * - * @return The Languages for the source file, may be empty. - */ - public List getLanguagesForFile(String fileName) { - if (forcedLanguage != null) { - return Collections.singletonList(forcedLanguage); - } - String extension = getExtension(fileName); - return LanguageRegistry.findByExtension(extension); - } - - // Get the extensions from a file - private String getExtension(String fileName) { - return StringUtils.substringAfterLast(fileName, "."); - } -} diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/FileLocationTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/FileLocationTest.java index 5e9c353497..d0fb1e31d2 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/FileLocationTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/FileLocationTest.java @@ -25,6 +25,13 @@ public class FileLocationTest { assertEquals(2, loc.getEndColumn()); } + @Test + public void testToRange() { + TextRange2d range2d = TextRange2d.range2d(1, 1, 1, 2); + FileLocation loc = FileLocation.range("fname", range2d); + assertEquals(range2d, loc.toRange2d()); + } + @Test public void testToString() { FileLocation loc = FileLocation.range("fname", TextRange2d.range2d(1, 1, 1, 2)); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/SourceCodePositionerTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/SourceCodePositionerTest.java index 5436b626bf..26a3c987c2 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/SourceCodePositionerTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/SourceCodePositionerTest.java @@ -63,6 +63,10 @@ public class SourceCodePositionerTest { assertEquals("abcd\ndef".length(), positioner.offsetFromLineColumn(2, 4)); assertEquals("abcd\ndefghi\r\n".length(), positioner.offsetFromLineColumn(3, 1)); + assertEquals(source.length(), positioner.offsetFromLineColumn(4, 4)); + assertEquals(-1, positioner.offsetFromLineColumn(4, 5)); + assertEquals(source.length(), positioner.offsetFromLineColumn(5, 1)); + assertEquals(-1, positioner.offsetFromLineColumn(5, 2)); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/TextFilesTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/TextFilesTest.java index a53ec06ef8..fe807c00cb 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/TextFilesTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/TextFilesTest.java @@ -50,11 +50,22 @@ public class TextFilesTest { assertEquals(Chars.wrap("some content"), tf.readContents().getNormalizedText()); assertFalse("readonly", tf.isReadOnly()); + // write with CRLF tf.writeContents( - TextFileContent.fromCharSeq("new content") + TextFileContent.fromCharSeq("new content\r\n") ); - assertEquals(Chars.wrap("new content"), tf.readContents().getNormalizedText()); + TextFileContent read = tf.readContents(); + // is normalized to LF when rereading + assertEquals(Chars.wrap("new content\n"), read.getNormalizedText()); + // but line terminator is detected as CRLF + assertEquals("\r\n", read.getLineTerminator()); + + tf.writeContents( + TextFileContent.fromCharSeq("new content\n") + ); + + assertEquals(Chars.wrap("new content\n"), tf.readContents().getNormalizedText()); } } @@ -102,13 +113,21 @@ public class TextFilesTest { } @Test - public void testReaderFileEscape() throws IOException { + public void testReaderFile() throws IOException { Path file = makeTmpFile(StandardCharsets.UTF_8, "some\r\ncontent"); try (TextFile tf = TextFile.forReader(Files.newBufferedReader(file, StandardCharsets.UTF_8), "filename", dummyVersion)) { assertEquals("filename", tf.getPathId()); assertEquals("filename", tf.getDisplayName()); assertEquals(dummyVersion, tf.getLanguageVersion()); assertEquals(Chars.wrap("some\ncontent"), tf.readContents().getNormalizedText()); + } + } + + @Test + public void testReaderFileIsReadOnly() throws IOException { + Path file = makeTmpFile(StandardCharsets.UTF_8, "some\r\ncontent"); + try (TextFile tf = TextFile.forReader(Files.newBufferedReader(file, StandardCharsets.UTF_8), "filename", dummyVersion)) { + assertTrue("readonly", tf.isReadOnly()); assertThrows(ReadOnlyFileException.class, () -> tf.writeContents( TextFileContent.fromCharSeq("new content") )); @@ -140,6 +159,7 @@ public class TextFilesTest { @Test public void testStringFileIsReadonly() throws IOException { try (TextFile tf = TextFile.forCharSeq("contents", "filename", dummyVersion)) { + assertTrue("readonly", tf.isReadOnly()); assertThrows(ReadOnlyFileException.class, () -> tf.writeContents( TextFileContent.fromCharSeq("new content") )); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/TextPos2dTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/TextPos2dTest.java index 4546fede17..7b4e6165f9 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/TextPos2dTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/TextPos2dTest.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.document; import static org.hamcrest.CoreMatchers.containsString; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import org.hamcrest.MatcherAssert; import org.junit.Test; @@ -33,4 +34,25 @@ public class TextPos2dTest { MatcherAssert.assertThat(pos.toString(), containsString("!debug only!")); } + @Test + public void testEquals() { + TextPos2d pos = TextPos2d.pos2d(1, 1); + TextPos2d pos2 = TextPos2d.pos2d(1, 2); + assertNotEquals(pos, pos2); + assertEquals(pos, TextPos2d.pos2d(1, 1)); + assertEquals(pos2, pos2); + } + + @Test + public void testCompareTo() { + TextPos2d pos = TextPos2d.pos2d(1, 1); + TextPos2d pos2 = TextPos2d.pos2d(1, 2); + TextPos2d pos3 = TextPos2d.pos2d(2, 1); + + assertEquals(-1, pos.compareTo(pos2)); + assertEquals(-1, pos.compareTo(pos3)); + assertEquals(-1, pos2.compareTo(pos3)); + assertEquals(1, pos2.compareTo(pos)); + assertEquals(0, pos.compareTo(pos)); + } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/TextRange2dTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/TextRange2dTest.java index 188eb1cb7b..ed5f067fd8 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/TextRange2dTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/document/TextRange2dTest.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.document; import static org.hamcrest.CoreMatchers.containsString; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import org.hamcrest.MatcherAssert; import org.junit.Test; @@ -22,6 +23,25 @@ public class TextRange2dTest { assertEquals(pos, pos2); } + @Test + public void testEquals() { + TextRange2d pos = TextRange2d.range2d(1, 1, 1, 1); + TextRange2d pos2 = TextRange2d.range2d(1, 1, 1, 2); + assertNotEquals(pos, pos2); + assertEquals(pos, pos); + assertEquals(pos2, pos2); + } + + @Test + public void testCompareTo() { + TextRange2d pos = TextRange2d.range2d(1, 1, 1, 1); + TextRange2d pos2 = TextRange2d.range2d(1, 1, 1, 2); + + assertEquals(-1, pos.compareTo(pos2)); + assertEquals(1, pos2.compareTo(pos)); + assertEquals(0, pos.compareTo(pos)); + } + @Test public void testToString() { TextRange2d range = TextRange2d.range2d(1, 2, 3, 4);