Fix wrong check for location at EOF

This commit is contained in:
Clément Fournier
2020-11-15 22:39:56 +01:00
parent 4cd1fa0a1d
commit 4d018f5a2a
6 changed files with 46 additions and 9 deletions

View File

@ -137,18 +137,37 @@ public final class AssertionUtil {
* @throws IndexOutOfBoundsException If value < 0 || value >= maxValue
*/
public static int requireInNonNegativeRange(String name, int value, int maxValue) {
if (value < 0 || value >= maxValue) {
throw mustBe(name, value, "in range [0," + maxValue + "[", IndexOutOfBoundsException::new);
}
return value;
return requireInExclusiveRange(name, value, 0, maxValue);
}
/**
* @throws IndexOutOfBoundsException If value < 1 || value >= maxValue
*/
public static int requireInPositiveRange(String name, int value, int maxValue) {
if (value < 0 || value >= maxValue) {
throw mustBe(name, value, "in range [1," + maxValue + "[", IndexOutOfBoundsException::new);
return requireInExclusiveRange(name, value, 1, maxValue);
}
// the difference between those two is the message
/**
* @throws IndexOutOfBoundsException If {@code value < minValue || value > maxValue}
*/
public static int requireInInclusiveRange(String name, int value, int minValue, int maxValue) {
return requireInRange(name, value, minValue, maxValue, true);
}
/**
* @throws IndexOutOfBoundsException If {@code value < minValue || value > maxValue}
*/
public static int requireInExclusiveRange(String name, int value, int minValue, int maxValue) {
return requireInRange(name, value, minValue, maxValue, false);
}
public static int requireInRange(String name, int value, int minValue, int maxValue, boolean inclusive) {
if (value < 0 || inclusive && value > maxValue || !inclusive && value >= maxValue) {
String message = "in range [" + minValue + "," + maxValue;
message += inclusive ? "]" : "[";
throw mustBe(name, value, message, IndexOutOfBoundsException::new);
}
return value;
}

View File

@ -67,6 +67,8 @@ final class RootTextDocument extends BaseCloseable implements TextDocument {
checkInRange(region);
SourceCodePositioner positioner = content.getPositioner();
// We use longs to return both numbers at the same time
// This limits us to 2 billion lines or columns, which is FINE
long bpos = positioner.lineColFromOffset(region.getStartOffset(), true);
long epos = region.isEmpty() ? bpos
: positioner.lineColFromOffset(region.getEndOffset(), false);

View File

@ -38,7 +38,7 @@ final class SourceCodePositioner {
}
long lineColFromOffset(int offset, boolean inclusive) {
AssertionUtil.requireInNonNegativeRange("offset", offset, sourceCodeLength);
AssertionUtil.requireInInclusiveRange("offset", offset, 0, sourceCodeLength);
int line = searchLineOffset(offset);

View File

@ -88,6 +88,21 @@ public class TextDocumentTest {
assertEquals(1 + "bonjour\n".length(), withLines.getEndColumn());
}
@Test
public void testRegionAtEndOfFile() {
TextDocument doc = TextDocument.readOnlyString("flemme", dummyVersion);
TextRegion region = TextRegion.fromOffsetLength(0, doc.getLength());
assertEquals(doc.getText(), doc.sliceText(region));
FileLocation withLines = doc.toLocation(region);
assertEquals(1, withLines.getBeginLine());
assertEquals(1, withLines.getEndLine());
assertEquals(1, withLines.getBeginColumn());
assertEquals(1 + doc.getLength(), withLines.getEndColumn());
}
@Test
public void testMultiLineRegion() {
TextDocument doc = TextDocument.readOnlyString("bonjour\noha\ntristesse", dummyVersion);

View File

@ -296,6 +296,8 @@ public abstract class RuleTst {
listener.close();
return reportBuilder.getResult();
}
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}

View File

@ -23,7 +23,6 @@ import net.sourceforge.pmd.lang.ast.Parser.ParserTask;
import net.sourceforge.pmd.lang.ast.RootNode;
import net.sourceforge.pmd.lang.xml.XmlParserOptions;
import net.sourceforge.pmd.lang.xml.ast.XmlNode;
import net.sourceforge.pmd.util.document.TextDocument;
public class XmlParserImpl {
@ -95,7 +94,7 @@ public class XmlParserImpl {
private final AstInfo<RootXmlNode> astInfo;
RootXmlNode(XmlParserImpl parser, Node domNode, TextDocument textDoc) {
RootXmlNode(XmlParserImpl parser, Node domNode, ParserTask task) {
super(parser, domNode);
this.astInfo = new AstInfo<>(task, this);
}