forked from phoedos/pmd
Add TextRange2d
This commit is contained in:
@ -437,7 +437,7 @@ final class ApexTreeBuilder extends AstVisitor<AdditionalPassScope> {
|
||||
Chars trimmed = commentText.subSequence("//".length(), commentText.length()).trimStart();
|
||||
if (trimmed.startsWith(suppressMarker)) {
|
||||
Chars userMessage = trimmed.subSequence(suppressMarker.length(), trimmed.length()).trim();
|
||||
suppressMap.put(source.lineAtOffset(startIdx), userMessage.toString());
|
||||
suppressMap.put(source.lineColumnAtOffset(startIdx).getLine(), userMessage.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import net.sourceforge.pmd.Report.SuppressedViolation;
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.document.FileLocation;
|
||||
import net.sourceforge.pmd.lang.document.TextRange2d;
|
||||
import net.sourceforge.pmd.lang.rule.AbstractRule;
|
||||
import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
|
||||
import net.sourceforge.pmd.processor.AbstractPMDProcessor;
|
||||
@ -131,7 +132,7 @@ public final class RuleContext {
|
||||
|
||||
FileLocation location = node.getReportLocation();
|
||||
if (beginLine != -1 && endLine != -1) {
|
||||
location = FileLocation.location(location.getFileName(), beginLine, 1, endLine, 1);
|
||||
location = FileLocation.location(location.getFileName(), TextRange2d.range2d(beginLine, 1, endLine, 1));
|
||||
}
|
||||
|
||||
RuleViolation violation = fact.createViolation(rule, node, location, makeMessage(message, formatArgs));
|
||||
|
@ -12,6 +12,7 @@ import net.sourceforge.pmd.Rule;
|
||||
import net.sourceforge.pmd.RuleViolation;
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
import net.sourceforge.pmd.lang.document.FileLocation;
|
||||
import net.sourceforge.pmd.lang.document.TextRange2d;
|
||||
|
||||
/**
|
||||
* A {@link RuleViolation} implementation that is immutable, and therefore cache friendly
|
||||
@ -41,7 +42,7 @@ public final class CachedRuleViolation implements RuleViolation {
|
||||
final String className, final String methodName, final String variableName) {
|
||||
this.mapper = mapper;
|
||||
this.description = description;
|
||||
this.location = FileLocation.location(fileName, beginLine, beginColumn, endLine, endColumn);
|
||||
this.location = FileLocation.location(fileName, TextRange2d.range2d(beginLine, beginColumn, endLine, endColumn));
|
||||
this.ruleClassName = ruleClassName;
|
||||
this.ruleName = ruleName;
|
||||
this.ruleTargetLanguage = ruleTargetLanguage;
|
||||
|
@ -153,8 +153,14 @@ public final class FileLocation {
|
||||
* @throws IllegalArgumentException If the line and column are not correctly ordered
|
||||
* @throws IllegalArgumentException If the start offset or length are negative
|
||||
*/
|
||||
public static FileLocation location(String fileName, int beginLine, int beginColumn, int endLine, int endColumn) {
|
||||
return new FileLocation(fileName, beginLine, beginColumn, endLine, endColumn);
|
||||
public static FileLocation location(String fileName, TextRange2d range2d) {
|
||||
TextPos2d start = range2d.getStartPos();
|
||||
TextPos2d end = range2d.getEndPos();
|
||||
return new FileLocation(fileName,
|
||||
start.getLine(),
|
||||
start.getColumn(),
|
||||
end.getLine(),
|
||||
end.getColumn());
|
||||
}
|
||||
|
||||
|
||||
|
@ -64,7 +64,7 @@ final class RootTextDocument extends BaseCloseable implements TextDocument {
|
||||
|
||||
@Override
|
||||
public FileLocation toLocation(TextRegion region) {
|
||||
checkInRange(region);
|
||||
checkInRange(region, this.getLength());
|
||||
SourceCodePositioner positioner = content.getPositioner();
|
||||
|
||||
// We use longs to return both numbers at the same time
|
||||
@ -90,8 +90,18 @@ final class RootTextDocument extends BaseCloseable implements TextDocument {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextPos2d lineColumnAtOffset(int offset) {
|
||||
long longPos = content.getPositioner().lineColFromOffset(offset, true);
|
||||
public boolean isInRange(TextPos2d textPos2d) {
|
||||
if (textPos2d.getLine() <= content.getPositioner().getNumLines()) {
|
||||
int maxColumn = content.getPositioner().offsetOfEndOfLine(textPos2d.getLine());
|
||||
return textPos2d.getColumn()
|
||||
< content.getPositioner().columnFromOffset(textPos2d.getLine(), maxColumn);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextPos2d lineColumnAtOffset(int offset, boolean inclusive) {
|
||||
long longPos = content.getPositioner().lineColFromOffset(offset, inclusive);
|
||||
return TextPos2d.pos2d(
|
||||
SourceCodePositioner.unmaskLine(longPos),
|
||||
SourceCodePositioner.unmaskCol(longPos)
|
||||
@ -113,9 +123,9 @@ final class RootTextDocument extends BaseCloseable implements TextDocument {
|
||||
return TextRegion.fromBothOffsets(first, last);
|
||||
}
|
||||
|
||||
void checkInRange(TextRegion region) {
|
||||
if (region.getEndOffset() > getLength()) {
|
||||
throw regionOutOfBounds(region.getStartOffset(), region.getEndOffset(), getLength());
|
||||
static void checkInRange(TextRegion region, int length) {
|
||||
if (region.getEndOffset() > length) {
|
||||
throw regionOutOfBounds(region.getStartOffset(), region.getEndOffset(), length);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,6 +131,9 @@ final class SourceCodePositioner {
|
||||
*/
|
||||
public int offsetFromLineColumn(final int line, final int column) {
|
||||
if (!isValidLine(line)) {
|
||||
if (line == lineOffsets.length && column == 1) {
|
||||
return sourceCodeLength;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -172,6 +175,10 @@ final class SourceCodePositioner {
|
||||
return lineOffsets.length - 1;
|
||||
}
|
||||
|
||||
public int getNumLines() {
|
||||
return getLastLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last column number of the last line in the document.
|
||||
*/
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.document;
|
||||
|
||||
import static net.sourceforge.pmd.lang.document.RootTextDocument.checkInRange;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
@ -36,6 +38,26 @@ public interface TextDocument extends Closeable {
|
||||
// todo text edition (there are some reverted commits in the branch
|
||||
// with part of this, including a lot of tests)
|
||||
|
||||
/*
|
||||
Summary of different coordinate systems:
|
||||
Coordinate system: Line/column Offset
|
||||
==============================================================
|
||||
Position: TextPos2d int >= 0
|
||||
Range: TextRange2d TextRegion
|
||||
|
||||
(FileLocation is similar to TextRange2d in terms of position info)
|
||||
|
||||
Conversions:
|
||||
line/column -> offset: offsetAtLineColumn
|
||||
offset -> line/column: lineColumnAtOffset
|
||||
Range conversions:
|
||||
TextRegion -> TextRange2d: toRegion
|
||||
TextRange2d -> TextRegion: toRange2d
|
||||
|
||||
TextRegion -> FileLocation: toLocation
|
||||
TextRange2d -> FileLocation: toLocation
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the language version that should be used to parse this file.
|
||||
*/
|
||||
@ -122,16 +144,40 @@ public interface TextDocument extends Closeable {
|
||||
FileLocation toLocation(TextRegion region);
|
||||
|
||||
/**
|
||||
* Create a location from its positions as lines/columns. The file
|
||||
* name is the display name of this document.
|
||||
* Turn a text region into a {@link FileLocation}. The file name is
|
||||
* the display name of this document.
|
||||
*
|
||||
* @param bline Start line
|
||||
* @param bcol Start column
|
||||
* @param eline End line
|
||||
* @param ecol End column
|
||||
* @return A new file position
|
||||
*
|
||||
* @throws IndexOutOfBoundsException If the argument is not a valid region in this document
|
||||
*/
|
||||
default FileLocation createLocation(int bline, int bcol, int eline, int ecol) {
|
||||
return FileLocation.location(getDisplayName(), bline, bcol, eline, ecol);
|
||||
default FileLocation toLocation(TextRange2d range) {
|
||||
int startOffset = offsetAtLineColumn(range.getEndPos());
|
||||
if (startOffset < 0) {
|
||||
throw new IndexOutOfBoundsException("Region out of bounds: " + range.displayString());
|
||||
}
|
||||
TextRegion region = TextRegion.caretAt(startOffset);
|
||||
checkInRange(region, this.getLength());
|
||||
return FileLocation.location(getDisplayName(), range);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a text region to a {@link TextRange2d}.
|
||||
*/
|
||||
default TextRange2d toRange2d(TextRegion region) {
|
||||
TextPos2d start = lineColumnAtOffset(region.getStartOffset(), true);
|
||||
TextPos2d end = lineColumnAtOffset(region.getEndOffset(), false);
|
||||
return TextRange2d.range2d(start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn a {@link TextRange2d} into a {@link TextRegion}.
|
||||
*/
|
||||
default TextRegion toRegion(TextRange2d region) {
|
||||
return TextRegion.fromBothOffsets(
|
||||
offsetAtLineColumn(region.getStartPos()),
|
||||
offsetAtLineColumn(region.getEndPos())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -145,6 +191,11 @@ public interface TextDocument extends Closeable {
|
||||
*/
|
||||
int offsetAtLineColumn(int line, int column);
|
||||
|
||||
/**
|
||||
* Returns true if the position is valid in this document.
|
||||
*/
|
||||
boolean isInRange(TextPos2d textPos2d);
|
||||
|
||||
/**
|
||||
* Returns the offset at the line and number.
|
||||
*/
|
||||
@ -159,35 +210,24 @@ public interface TextDocument extends Closeable {
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if the offset is out of bounds
|
||||
*/
|
||||
TextPos2d lineColumnAtOffset(int offset);
|
||||
|
||||
/**
|
||||
* Determines the line number at the given offset (inclusive).
|
||||
*
|
||||
* @return the line number at the given index
|
||||
*
|
||||
* @throws IndexOutOfBoundsException If the argument is not a valid offset in this document
|
||||
*/
|
||||
default int lineAtOffset(int offset) {
|
||||
return lineColumnAtOffset(offset).getLine();
|
||||
default TextPos2d lineColumnAtOffset(int offset) {
|
||||
return lineColumnAtOffset(offset, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the region that spans from the given position to the other.
|
||||
* Returns the line and column at the given offset (inclusive).
|
||||
*
|
||||
* @throws IllegalArgumentException if start > end
|
||||
* @throws NullPointerException If either argument is null
|
||||
* @param offset A source offset (0-based), can range in {@code [0, length]}.
|
||||
* @param inclusive If the offset falls right after a line terminator,
|
||||
* two behaviours are possible. If the parameter is true,
|
||||
* choose the position at the start of the next line.
|
||||
* Otherwise choose the offset at the end of the line.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if the offset is out of bounds
|
||||
*/
|
||||
default TextRegion rangeBetween(TextPos2d start, TextPos2d end) {
|
||||
if (start.compareTo(end) > 0) {
|
||||
throw new IllegalArgumentException(start.toTupleString() + " comes after " + end.toTupleString());
|
||||
}
|
||||
TextPos2d lineColumnAtOffset(int offset, boolean inclusive);
|
||||
|
||||
int startPos = offsetAtLineColumn(start);
|
||||
int endPos = offsetAtLineColumn(end) + 1;
|
||||
|
||||
return TextRegion.fromBothOffsets(startPos, endPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closing a document closes the underlying {@link TextFile}.
|
||||
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.document;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A place in a text document, represented as line/column information.
|
||||
*/
|
||||
public final class TextRange2d implements Comparable<TextRange2d> {
|
||||
|
||||
private final int startLine;
|
||||
private final int startCol;
|
||||
private final int endLine;
|
||||
private final int endCol;
|
||||
|
||||
public TextRange2d(int startLine, int startCol, int endLine, int endCol) {
|
||||
this.startLine = startLine;
|
||||
this.startCol = startCol;
|
||||
this.endLine = endLine;
|
||||
this.endCol = endCol;
|
||||
}
|
||||
|
||||
|
||||
public TextPos2d getStartPos() {
|
||||
return TextPos2d.pos2d(startLine, startCol);
|
||||
}
|
||||
|
||||
public TextPos2d getEndPos() {
|
||||
return TextPos2d.pos2d(endLine, endCol);
|
||||
}
|
||||
|
||||
public String displayString() {
|
||||
return "(" + startCol + ", " + endCol
|
||||
+ ")-(" + endLine + ", " + endCol + ")";
|
||||
}
|
||||
|
||||
public static TextRange2d range2d(TextPos2d start, TextPos2d end) {
|
||||
return new TextRange2d(start.getLine(), start.getColumn(), end.getLine(), end.getColumn());
|
||||
}
|
||||
|
||||
public static TextRange2d range2d(int bline, int bcol, int eline, int ecol) {
|
||||
return new TextRange2d(bline, bcol, eline, ecol);
|
||||
}
|
||||
|
||||
public static TextRange2d fullLine(int line, int lineLength) {
|
||||
return new TextRange2d(line, 1, line, 1 + lineLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(TextRange2d o) {
|
||||
int cmp = getStartPos().compareTo(o.getStartPos());
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
return getEndPos().compareTo(o.getEndPos());
|
||||
}
|
||||
|
||||
public boolean contains(TextRange2d range) {
|
||||
return getStartPos().compareTo(range.getStartPos()) <= 0 && getEndPos().compareTo(range.getEndPos()) >= 0;
|
||||
}
|
||||
|
||||
public boolean contains(TextPos2d pos) {
|
||||
return getStartPos().compareTo(pos) <= 0 && getEndPos().compareTo(pos) >= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
TextRange2d that = (TextRange2d) o;
|
||||
return this.getStartPos().equals(that.getStartPos())
|
||||
&& this.getEndPos().equals(that.getEndPos());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getStartPos(), getEndPos());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + getStartPos() + " - " + getEndPos() + ']';
|
||||
}
|
||||
|
||||
}
|
@ -14,7 +14,6 @@ import java.util.Collections;
|
||||
import org.junit.Test;
|
||||
|
||||
import net.sourceforge.pmd.Report.SuppressedViolation;
|
||||
import net.sourceforge.pmd.lang.ast.DummyNode;
|
||||
import net.sourceforge.pmd.lang.ast.DummyRoot;
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.rule.AbstractRule;
|
||||
@ -70,8 +69,8 @@ public class AbstractRuleTest {
|
||||
public void testCreateRV() {
|
||||
MyRule r = new MyRule();
|
||||
r.setRuleSetName("foo");
|
||||
DummyNode s = new DummyRoot().withFileName("filename");
|
||||
s.setCoords(5, 5, 5, 10);
|
||||
DummyRoot s = new DummyRoot().withFileName("filename");
|
||||
s.setCoordsReplaceText(5, 5, 5, 10);
|
||||
RuleViolation rv = new ParametricRuleViolation(r, s, r.getMessage());
|
||||
assertEquals("Line number mismatch!", 5, rv.getBeginLine());
|
||||
assertEquals("Filename mismatch!", "filename", rv.getFilename());
|
||||
@ -83,8 +82,8 @@ public class AbstractRuleTest {
|
||||
@Test
|
||||
public void testCreateRV2() {
|
||||
MyRule r = new MyRule();
|
||||
DummyNode s = new DummyRoot().withFileName("filename");
|
||||
s.setCoords(5, 5, 5, 10);
|
||||
DummyRoot s = new DummyRoot().withFileName("filename");
|
||||
s.setCoordsReplaceText(5, 5, 5, 10);
|
||||
RuleViolation rv = new ParametricRuleViolation(r, s, "specificdescription");
|
||||
assertEquals("Line number mismatch!", 5, rv.getBeginLine());
|
||||
assertEquals("Filename mismatch!", "filename", rv.getFilename());
|
||||
@ -103,8 +102,8 @@ public class AbstractRuleTest {
|
||||
r.definePropertyDescriptor(PropertyFactory.intProperty("testInt").desc("description").require(inRange(0, 100)).defaultValue(10).build());
|
||||
r.setMessage("Message ${packageName} ${className} ${methodName} ${variableName} ${testInt} ${noSuchProperty}");
|
||||
|
||||
DummyNode s = new DummyRoot().withFileName("filename");
|
||||
s.setCoords(5, 1, 6, 1);
|
||||
DummyRoot s = new DummyRoot().withFileName("filename");
|
||||
s.setCoordsReplaceText(5, 1, 6, 1);
|
||||
s.setImage("TestImage");
|
||||
|
||||
RuleViolation rv = RuleContextTest.getReportForRuleApply(r, s).getViolations().get(0);
|
||||
@ -114,7 +113,7 @@ public class AbstractRuleTest {
|
||||
@Test
|
||||
public void testRuleSuppress() {
|
||||
DummyRoot n = new DummyRoot().withNoPmdComments(Collections.singletonMap(5, ""));
|
||||
n.setCoords(5, 1, 6, 1);
|
||||
n.setCoordsReplaceText(5, 1, 6, 1);
|
||||
RuleViolation violation = DefaultRuleViolationFactory.defaultInstance().createViolation(new MyRule(), n, n.getReportLocation(), "specificdescription");
|
||||
SuppressedViolation suppressed = DefaultRuleViolationFactory.defaultInstance().suppressOrNull(n, violation);
|
||||
|
||||
|
@ -76,7 +76,8 @@ public class ReportTest {
|
||||
}
|
||||
|
||||
private static DummyNode getNode(int line, int column) {
|
||||
DummyNode parent = new DummyRoot();
|
||||
DummyRoot parent = new DummyRoot();
|
||||
parent.fakeTextWithNLines(line + 10, column);
|
||||
DummyNode s = new DummyNode();
|
||||
parent.setCoords(line, column, line, column + 1);
|
||||
parent.addChild(s, 0);
|
||||
|
@ -475,7 +475,7 @@ public class RuleSetTest {
|
||||
|
||||
private RootNode makeCompilationUnits(String filename) {
|
||||
DummyRoot node = new DummyRoot();
|
||||
node.setCoords(1, 1, 10, 1);
|
||||
node.setCoordsReplaceText(1, 1, 2, 1);
|
||||
node.setImage("Foo");
|
||||
node.withFileName(filename);
|
||||
return node;
|
||||
|
@ -15,7 +15,6 @@ import java.util.Random;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.DummyNode;
|
||||
import net.sourceforge.pmd.lang.ast.DummyRoot;
|
||||
import net.sourceforge.pmd.lang.rule.MockRule;
|
||||
import net.sourceforge.pmd.lang.rule.ParametricRuleViolation;
|
||||
@ -70,8 +69,8 @@ public class RuleViolationComparatorTest {
|
||||
|
||||
private RuleViolation createJavaRuleViolation(Rule rule, String fileName, int beginLine, String description,
|
||||
int beginColumn, int endLine, int endColumn) {
|
||||
DummyNode simpleNode = new DummyRoot().withFileName(fileName);
|
||||
simpleNode.setCoords(beginLine, beginColumn, endLine, endColumn);
|
||||
DummyRoot simpleNode = new DummyRoot().withFileName(fileName);
|
||||
simpleNode.setCoordsReplaceText(beginLine, beginColumn, endLine, endColumn);
|
||||
return new ParametricRuleViolation(rule, simpleNode, description);
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ public class RuleViolationTest {
|
||||
@Test
|
||||
public void testConstructor1() {
|
||||
Rule rule = new MockRule("name", "desc", "msg", "rulesetname");
|
||||
DummyNode s = new DummyRoot().withFileName("filename");
|
||||
s.setCoords(2, 1, 2, 3);
|
||||
DummyRoot s = new DummyRoot().withFileName("filename");
|
||||
s.setCoordsReplaceText(2, 1, 2, 3);
|
||||
RuleViolation r = new ParametricRuleViolation(rule, s, rule.getMessage());
|
||||
assertEquals("object mismatch", rule, r.getRule());
|
||||
assertEquals("line number is wrong", 2, r.getBeginLine());
|
||||
@ -35,8 +35,8 @@ public class RuleViolationTest {
|
||||
@Test
|
||||
public void testConstructor2() {
|
||||
Rule rule = new MockRule("name", "desc", "msg", "rulesetname");
|
||||
DummyNode s = new DummyRoot().withFileName("filename");
|
||||
s.setCoords(2, 1, 2, 3);
|
||||
DummyRoot s = new DummyRoot().withFileName("filename");
|
||||
s.setCoordsReplaceText(2, 1, 2, 3);
|
||||
RuleViolation r = new ParametricRuleViolation(rule, s, "description");
|
||||
assertEquals("object mismatch", rule, r.getRule());
|
||||
assertEquals("line number is wrong", 2, r.getBeginLine());
|
||||
@ -48,11 +48,11 @@ public class RuleViolationTest {
|
||||
public void testComparatorWithDifferentFilenames() {
|
||||
Rule rule = new MockRule("name", "desc", "msg", "rulesetname");
|
||||
Comparator<RuleViolation> comp = RuleViolation.DEFAULT_COMPARATOR;
|
||||
DummyNode s = new DummyRoot().withFileName("filename1");
|
||||
s.setCoords(10, 1, 11, 3);
|
||||
DummyRoot s = new DummyRoot().withFileName("filename1");
|
||||
s.setCoordsReplaceText(10, 1, 11, 3);
|
||||
RuleViolation r1 = new ParametricRuleViolation(rule, s, "description");
|
||||
DummyNode s1 = new DummyRoot().withFileName("filename2");
|
||||
s1.setCoords(10, 1, 11, 3);
|
||||
DummyRoot s1 = new DummyRoot().withFileName("filename2");
|
||||
s1.setCoordsReplaceText(10, 1, 11, 3);
|
||||
RuleViolation r2 = new ParametricRuleViolation(rule, s1, "description");
|
||||
assertEquals(-1, comp.compare(r1, r2));
|
||||
assertEquals(1, comp.compare(r2, r1));
|
||||
@ -62,10 +62,10 @@ public class RuleViolationTest {
|
||||
public void testComparatorWithSameFileDifferentLines() {
|
||||
Rule rule = new MockRule("name", "desc", "msg", "rulesetname");
|
||||
Comparator<RuleViolation> comp = RuleViolation.DEFAULT_COMPARATOR;
|
||||
DummyNode s = new DummyRoot().withFileName("filename1");
|
||||
s.setCoords(10, 1, 15, 10);
|
||||
DummyNode s1 = new DummyRoot().withFileName("filename1");
|
||||
s1.setCoords(20, 1, 25, 10);
|
||||
DummyRoot s = new DummyRoot().withFileName("filename1");
|
||||
s.setCoordsReplaceText(10, 1, 15, 10);
|
||||
DummyRoot s1 = new DummyRoot().withFileName("filename1");
|
||||
s1.setCoordsReplaceText(20, 1, 25, 10);
|
||||
RuleViolation r1 = new ParametricRuleViolation(rule, s, "description");
|
||||
RuleViolation r2 = new ParametricRuleViolation(rule, s1, "description");
|
||||
assertTrue(comp.compare(r1, r2) < 0);
|
||||
|
@ -41,6 +41,7 @@ import net.sourceforge.pmd.lang.document.FileLocation;
|
||||
import net.sourceforge.pmd.lang.document.TextDocument;
|
||||
import net.sourceforge.pmd.lang.document.TextFile;
|
||||
import net.sourceforge.pmd.lang.document.TextFileContent;
|
||||
import net.sourceforge.pmd.lang.document.TextRange2d;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class FileAnalysisCacheTest {
|
||||
@ -116,7 +117,7 @@ public class FileAnalysisCacheTest {
|
||||
|
||||
final RuleViolation rv = mock(RuleViolation.class);
|
||||
when(rv.getFilename()).thenReturn(sourceFile.getDisplayName());
|
||||
when(rv.getLocation()).thenReturn(FileLocation.location(sourceFile.getDisplayName(), 1, 2, 3, 4));
|
||||
when(rv.getLocation()).thenReturn(FileLocation.location(sourceFile.getDisplayName(), TextRange2d.range2d(1, 2, 3, 4)));
|
||||
final net.sourceforge.pmd.Rule rule = mock(net.sourceforge.pmd.Rule.class, Mockito.RETURNS_SMART_NULLS);
|
||||
when(rule.getLanguage()).thenReturn(mock(Language.class));
|
||||
when(rv.getRule()).thenReturn(rule);
|
||||
|
@ -19,6 +19,7 @@ import org.junit.Test;
|
||||
import net.sourceforge.pmd.lang.TokenManager;
|
||||
import net.sourceforge.pmd.lang.ast.GenericToken;
|
||||
import net.sourceforge.pmd.lang.document.FileLocation;
|
||||
import net.sourceforge.pmd.lang.document.TextRange2d;
|
||||
import net.sourceforge.pmd.lang.document.TextRegion;
|
||||
|
||||
public class BaseTokenFilterTest {
|
||||
@ -58,7 +59,7 @@ public class BaseTokenFilterTest {
|
||||
|
||||
@Override
|
||||
public FileLocation getReportLocation() {
|
||||
return FileLocation.location("n/a", 0, 0, 0, 0);
|
||||
return FileLocation.location("n/a", TextRange2d.range2d(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,7 +49,7 @@ public class DummyLanguageModule extends BaseLanguageModule {
|
||||
public Parser getParser() {
|
||||
return task -> {
|
||||
DummyRoot node = new DummyRoot();
|
||||
node.setCoords(1, 1, 2, 10);
|
||||
node.setCoords(1, 1, 1, 1);
|
||||
node.setImage("Foo");
|
||||
node.withFileName(task.getFileDisplayName());
|
||||
node.withLanguage(task.getLanguageVersion());
|
||||
|
@ -10,6 +10,7 @@ import java.util.Map;
|
||||
import net.sourceforge.pmd.lang.ast.impl.AbstractNode;
|
||||
import net.sourceforge.pmd.lang.ast.impl.GenericNode;
|
||||
import net.sourceforge.pmd.lang.document.FileLocation;
|
||||
import net.sourceforge.pmd.lang.document.TextRange2d;
|
||||
|
||||
public class DummyNode extends AbstractNode<DummyNode, DummyNode> implements GenericNode<DummyNode> {
|
||||
private final boolean findBoundary;
|
||||
@ -58,7 +59,7 @@ public class DummyNode extends AbstractNode<DummyNode, DummyNode> implements Gen
|
||||
|
||||
@Override
|
||||
public FileLocation getReportLocation() {
|
||||
return getTextDocument().createLocation(bline, bcol, eline, ecol);
|
||||
return getTextDocument().toLocation(TextRange2d.range2d(bline, bcol, eline, ecol));
|
||||
}
|
||||
|
||||
public void setImage(String image) {
|
||||
|
@ -12,6 +12,7 @@ import net.sourceforge.pmd.lang.LanguageRegistry;
|
||||
import net.sourceforge.pmd.lang.LanguageVersion;
|
||||
import net.sourceforge.pmd.lang.ast.impl.GenericNode;
|
||||
import net.sourceforge.pmd.lang.document.TextDocument;
|
||||
import net.sourceforge.pmd.lang.document.TextPos2d;
|
||||
|
||||
public class DummyRoot extends DummyNode implements GenericNode<DummyNode>, RootNode {
|
||||
|
||||
@ -31,11 +32,42 @@ public class DummyRoot extends DummyNode implements GenericNode<DummyNode>, Root
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public DummyRoot fakeTextWithNLines(int numLines, int lineWidth) {
|
||||
StringBuilder sb = new StringBuilder(numLines * lineWidth);
|
||||
for (int i = 0; i < numLines; i++) {
|
||||
for (int j = 0; j < lineWidth; j++) {
|
||||
sb.append('@');
|
||||
}
|
||||
sb.append('\n');
|
||||
}
|
||||
this.sourceText = sb.toString();
|
||||
return this;
|
||||
}
|
||||
|
||||
public DummyRoot withNoPmdComments(Map<Integer, String> suppressMap) {
|
||||
this.suppressMap = suppressMap;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DummyNode setCoords(int bline, int bcol, int eline, int ecol) {
|
||||
@SuppressWarnings("PMD.CloseResource")
|
||||
TextDocument doc = getAstInfo().getTextDocument();
|
||||
checkInRange(bline, bcol, doc);
|
||||
checkInRange(eline, ecol, doc);
|
||||
return super.setCoords(bline, bcol, eline, ecol);
|
||||
}
|
||||
|
||||
public DummyNode setCoordsReplaceText(int bline, int bcol, int eline, int ecol) {
|
||||
fakeTextWithNLines(eline, Math.max(bcol, ecol));
|
||||
return setCoords(bline, bcol, eline, ecol);
|
||||
}
|
||||
|
||||
private void checkInRange(int line, int col, TextDocument doc) {
|
||||
TextPos2d start = TextPos2d.pos2d(line, col);
|
||||
assert doc.isInRange(start) : "position out of range " + start + ", text:\n" + sourceText;
|
||||
}
|
||||
|
||||
public DummyRoot withFileName(String filename) {
|
||||
this.filename = filename;
|
||||
|
@ -160,6 +160,33 @@ public class TextDocumentTest {
|
||||
assertEquals(11, doc.offsetAtLineColumn(3, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCoordinateRoundTripWithEndOfLine() {
|
||||
TextDocument doc = TextDocument.readOnlyString("bonjour\noa\n", dummyVersion);
|
||||
TextRange2d inputRange = TextRange2d.fullLine(1, "bonjour\n".length());
|
||||
|
||||
TextRegion lineRange = doc.createLineRange(1, 1);
|
||||
TextRegion region = doc.toRegion(inputRange);
|
||||
|
||||
assertEquals(TextRegion.fromOffsetLength(0, "bonjour\n".length()), region);
|
||||
assertEquals(TextRegion.fromOffsetLength(0, "bonjour\n".length()), lineRange);
|
||||
TextRange2d roundTrip = doc.toRange2d(region);
|
||||
assertEquals(inputRange, roundTrip);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCoordinateRoundTripSimple() {
|
||||
TextDocument doc = TextDocument.readOnlyString("bonjour\noa\n", dummyVersion);
|
||||
TextRange2d inputRange = TextRange2d.fullLine(1, "bonjour".length());
|
||||
|
||||
TextRegion region = doc.toRegion(inputRange);
|
||||
assertEquals(TextRegion.fromOffsetLength(0, "bonjour".length()), region);
|
||||
|
||||
TextRange2d roundTrip = doc.toRange2d(region);
|
||||
assertEquals(inputRange, roundTrip);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLineRange() {
|
||||
TextDocument doc = TextDocument.readOnlyString("bonjour\noha\ntristesse", dummyVersion);
|
||||
|
@ -81,8 +81,8 @@ public abstract class AbstractRendererTest {
|
||||
}
|
||||
|
||||
protected DummyNode createNode(int beginLine, int beginColumn, int endLine, int endColumn) {
|
||||
DummyNode node = new DummyRoot().withFileName(getSourceCodeFilename());
|
||||
node.setCoords(beginLine, beginColumn, endLine, endColumn);
|
||||
DummyRoot node = new DummyRoot().withFileName(getSourceCodeFilename());
|
||||
node.setCoordsReplaceText(beginLine, beginColumn, endLine, endColumn);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -144,10 +144,10 @@ public class SummaryHTMLRendererTest extends AbstractRendererTest {
|
||||
assertEquals(getExpectedEmpty(), actual);
|
||||
}
|
||||
|
||||
private Consumer<FileAnalysisListener> createEmptyReportWithSuppression() throws Exception {
|
||||
private Consumer<FileAnalysisListener> createEmptyReportWithSuppression() {
|
||||
return listener -> {
|
||||
DummyRoot root = new DummyRoot().withNoPmdComments(Collections.singletonMap(1, "test")).withFileName(getSourceCodeFilename());
|
||||
root.setCoords(1, 10, 4, 5);
|
||||
root.setCoordsReplaceText(1, 10, 4, 5);
|
||||
|
||||
RuleContext ruleContext = RuleContext.create(listener, new FooRule());
|
||||
ruleContext.addViolationWithPosition(root, 1, 1, "suppress test");
|
||||
|
@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken;
|
||||
import net.sourceforge.pmd.lang.document.FileLocation;
|
||||
import net.sourceforge.pmd.lang.document.TextRange2d;
|
||||
import net.sourceforge.pmd.lang.java.javadoc.JavadocTag;
|
||||
|
||||
public class JavadocElement extends Comment {
|
||||
@ -16,7 +17,7 @@ public class JavadocElement extends Comment {
|
||||
public JavadocElement(JavaccToken t, int theBeginLine, int theEndLine, int theBeginColumn, int theEndColumn, JavadocTag theTag) {
|
||||
super(t);
|
||||
this.tag = theTag;
|
||||
this.reportLoc = FileLocation.location("TODO", theBeginLine, theBeginColumn, theEndLine, theEndColumn);
|
||||
this.reportLoc = FileLocation.location("TODO", TextRange2d.range2d(theBeginLine, theBeginColumn, theEndLine, theEndColumn));
|
||||
}
|
||||
|
||||
public JavadocTag tag() {
|
||||
|
@ -6,6 +6,7 @@ package net.sourceforge.pmd.test.lang.ast;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.impl.AbstractNode;
|
||||
import net.sourceforge.pmd.lang.document.FileLocation;
|
||||
import net.sourceforge.pmd.lang.document.TextRange2d;
|
||||
|
||||
public class DummyNode extends AbstractNode<DummyNode, DummyNode> {
|
||||
|
||||
@ -13,7 +14,7 @@ public class DummyNode extends AbstractNode<DummyNode, DummyNode> {
|
||||
private FileLocation location;
|
||||
|
||||
public void setCoords(int bline, int bcol, int eline, int ecol) {
|
||||
this.location = FileLocation.location(":dummyFile:", bline, bcol, eline, ecol);
|
||||
this.location = FileLocation.location(":dummyFile:", TextRange2d.range2d(bline, bcol, eline, ecol));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Reference in New Issue
Block a user