Skip to content

Commit

Permalink
Fixes pmd#1458 Performance degradation scanning large XML files with …
Browse files Browse the repository at this point in the history
…XPath custom rules
  • Loading branch information
adangel committed Apr 1, 2016
1 parent c3f9835 commit 494719d
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
*/
package net.sourceforge.pmd.lang.xml.ast;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand All @@ -21,8 +24,8 @@
*/
class DOMLineNumbers {
private final Document document;
private final String xmlString;
private Map<Integer, Integer> lines;
private String xmlString;
private List<Integer> lines;

public DOMLineNumbers(Document document, String xmlString) {
this.document = document;
Expand Down Expand Up @@ -123,47 +126,62 @@ private String unexpandEntities(Node n, String te) {
}
private void setBeginLocation(Node n, int index) {
if (n != null) {
n.setUserData(XmlNode.BEGIN_LINE, toLine(index), null);
n.setUserData(XmlNode.BEGIN_COLUMN, toColumn(index), null);
int line = toLine(index);
n.setUserData(XmlNode.BEGIN_LINE, line, null);
n.setUserData(XmlNode.BEGIN_COLUMN, toColumn(line, index), null);
}
}
private void setEndLocation(Node n, int index) {
if (n != null) {
n.setUserData(XmlNode.END_LINE, toLine(index), null);
n.setUserData(XmlNode.END_COLUMN, toColumn(index), null);
int line = toLine(index);
n.setUserData(XmlNode.END_LINE, line, null);
n.setUserData(XmlNode.END_COLUMN, toColumn(line, index), null);
}
}

/**
* Calculates a list with the file offsets for each line.
*/
private void calculateLinesMap() {
lines = new TreeMap<Integer, Integer>();
lines = new ArrayList<Integer>();

int index = -1;
int count = StringUtils.countMatches(xmlString, "\n");
for (int line = 1; line <= count; line++) {
lines.put(line, index + 1);
index = xmlString.indexOf("\n", index + 1);
lines.add(index + 1);
index = xmlString.indexOf("\n", index + 1); // fast forward till end of current line
}
lines.put(count + 1, index + 1);
lines.add(index + 1);
}

private int toLine(int index) {
int line = 1;
for (Map.Entry<Integer, Integer> e : lines.entrySet()) {
line = e.getKey();
if (e.getValue() > index) {
line--;
break;
int low = 0;
int high = lines.size() - 1;

// binary search the best match
while (low <= high) {
int middle = (low + high) / 2;
int middleStart = lines.get(middle);
if (middleStart == index) {
return middle + 1; // found
}

if (middleStart > index) {
high = middle - 1;
} else {
low = middle + 1;
}
}
return line;

return low; // not found or last checked line, which is the best match;
}
private int toColumn(int index) {
int line = toLine(index);
Integer lineStart = lines.get(line);

private int toColumn(int line, int index) {
Integer lineStart = lines.get(line - 1);
if (lineStart == null) {
lineStart = lines.get(lines.size() - 1);
}
int column = index - lineStart;
return column + 1;
}

}
1 change: 1 addition & 0 deletions src/site/markdown/overview/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
* [#1456](https://sourceforge.net/p/pmd/bugs/1456/): UnusedFormalParameter should ignore overriding methods
* General
* [#1455](https://sourceforge.net/p/pmd/bugs/1455/): PMD doesn't handle Java 8 explicit receiver parameters
* [#1458](https://sourceforge.net/p/pmd/bugs/1458/): Performance degradation scanning large XML files with XPath custom rules
* [#1461](https://sourceforge.net/p/pmd/bugs/1461/): Possible threading issue due to PR#75

**API Changes:**
Expand Down

0 comments on commit 494719d

Please sign in to comment.