forked from phoedos/pmd
#1308 PMD runs endlessly on some generated files
This commit is contained in:
@ -24,6 +24,7 @@ public abstract class AbstractNode implements Node {
|
||||
|
||||
protected Node parent;
|
||||
protected Node[] children;
|
||||
protected int childIndex;
|
||||
protected int id;
|
||||
|
||||
private String image;
|
||||
@ -76,6 +77,13 @@ public abstract class AbstractNode implements Node {
|
||||
children = newChildren;
|
||||
}
|
||||
children[index] = child;
|
||||
child.jjtSetChildIndex(index);
|
||||
}
|
||||
public void jjtSetChildIndex(int index) {
|
||||
childIndex = index;
|
||||
}
|
||||
public int jjtGetChildIndex() {
|
||||
return childIndex;
|
||||
}
|
||||
|
||||
public Node jjtGetChild(int index) {
|
||||
|
@ -44,6 +44,16 @@ public interface Node {
|
||||
*/
|
||||
void jjtAddChild(Node child, int index);
|
||||
|
||||
/**
|
||||
* Sets the index of this node from the perspective of its parent.
|
||||
* This means: this.jjtGetParent().jjtGetChild(index) == this.
|
||||
*
|
||||
* @param index the child index
|
||||
*/
|
||||
void jjtSetChildIndex(int index);
|
||||
|
||||
int jjtGetChildIndex();
|
||||
|
||||
/**
|
||||
* This method returns a child node. The children are numbered
|
||||
* from zero, left to right.
|
||||
|
@ -43,7 +43,7 @@ public abstract class NodeIterator implements Iterator<Node> {
|
||||
protected Node getPreviousSibling(Node contextNode) {
|
||||
Node parentNode = contextNode.jjtGetParent();
|
||||
if (parentNode != null) {
|
||||
int prevPosition = getPositionFromParent(contextNode) - 1;
|
||||
int prevPosition = contextNode.jjtGetChildIndex() - 1;
|
||||
if (prevPosition >= 0) {
|
||||
return parentNode.jjtGetChild(prevPosition);
|
||||
}
|
||||
@ -51,20 +51,10 @@ public abstract class NodeIterator implements Iterator<Node> {
|
||||
return null;
|
||||
}
|
||||
|
||||
private int getPositionFromParent(Node contextNode) {
|
||||
Node parentNode = contextNode.jjtGetParent();
|
||||
for (int i = 0; i < parentNode.jjtGetNumChildren(); i++) {
|
||||
if (parentNode.jjtGetChild(i) == contextNode) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Node was not a child of it's parent ???");
|
||||
}
|
||||
|
||||
protected Node getNextSibling(Node contextNode) {
|
||||
Node parentNode = contextNode.jjtGetParent();
|
||||
if (parentNode != null) {
|
||||
int nextPosition = getPositionFromParent(contextNode) + 1;
|
||||
int nextPosition = contextNode.jjtGetChildIndex() + 1;
|
||||
if (nextPosition < parentNode.jjtGetNumChildren()) {
|
||||
return parentNode.jjtGetChild(nextPosition);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
package net.sourceforge.pmd.lang.symboltable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -15,7 +16,9 @@ import java.util.Map;
|
||||
public abstract class AbstractScope implements Scope {
|
||||
|
||||
private Scope parent;
|
||||
private Map<NameDeclaration, List<NameOccurrence>> nameDeclarations = new LinkedHashMap<NameDeclaration, List<NameOccurrence>>();
|
||||
/** Stores the name declaration already sorted by class. */
|
||||
private Map<Class<? extends NameDeclaration>, Map<NameDeclaration, List<NameOccurrence>>> nameDeclarations =
|
||||
new LinkedHashMap<Class<? extends NameDeclaration>, Map<NameDeclaration,List<NameOccurrence>>>();
|
||||
|
||||
@Override
|
||||
public Scope getParent() {
|
||||
@ -29,25 +32,26 @@ public abstract class AbstractScope implements Scope {
|
||||
|
||||
@Override
|
||||
public Map<NameDeclaration, List<NameOccurrence>> getDeclarations() {
|
||||
return nameDeclarations;
|
||||
Map<NameDeclaration, List<NameOccurrence>> result = new LinkedHashMap<NameDeclaration, List<NameOccurrence>>();
|
||||
for (Map<NameDeclaration, List<NameOccurrence>> e : nameDeclarations.values()) {
|
||||
result.putAll(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends NameDeclaration> Map<T, List<NameOccurrence>> getDeclarations(Class<T> clazz) {
|
||||
Map<T, List<NameOccurrence>> result = new LinkedHashMap<T, List<NameOccurrence>>();
|
||||
for (Map.Entry<NameDeclaration, List<NameOccurrence>> e : nameDeclarations.entrySet()) {
|
||||
if (clazz.isAssignableFrom(e.getKey().getClass())) {
|
||||
@SuppressWarnings("unchecked") // it's assignable from, so should be ok
|
||||
T cast = (T)e.getKey();
|
||||
result.put(cast, e.getValue());
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<T, List<NameOccurrence>> result = (Map<T, List<NameOccurrence>>)nameDeclarations.get(clazz);
|
||||
if (result == null) {
|
||||
result = new LinkedHashMap<T, List<NameOccurrence>>();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(NameOccurrence occ) {
|
||||
for (NameDeclaration d : nameDeclarations.keySet()) {
|
||||
for (NameDeclaration d : getDeclarations().keySet()) {
|
||||
if (d.getImage().equals(occ.getImage())) {
|
||||
return true;
|
||||
}
|
||||
@ -57,7 +61,12 @@ public abstract class AbstractScope implements Scope {
|
||||
|
||||
@Override
|
||||
public void addDeclaration(NameDeclaration declaration) {
|
||||
nameDeclarations.put(declaration, new ArrayList<NameOccurrence>());
|
||||
Map<NameDeclaration, List<NameOccurrence>> declarationsPerClass = nameDeclarations.get(declaration.getClass());
|
||||
if (declarationsPerClass == null) {
|
||||
declarationsPerClass = new HashMap<NameDeclaration, List<NameOccurrence>>();
|
||||
nameDeclarations.put(declaration.getClass(), declarationsPerClass);
|
||||
}
|
||||
declarationsPerClass.put(declaration, new ArrayList<NameOccurrence>());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -78,7 +87,7 @@ public abstract class AbstractScope implements Scope {
|
||||
@Override
|
||||
public NameDeclaration addNameOccurrence(NameOccurrence occurrence) {
|
||||
NameDeclaration result = null;
|
||||
for (Map.Entry<NameDeclaration, List<NameOccurrence>> e : nameDeclarations.entrySet()) {
|
||||
for (Map.Entry<NameDeclaration, List<NameOccurrence>> e : getDeclarations().entrySet()) {
|
||||
if (e.getKey().getImage().equals(occurrence.getImage())) {
|
||||
result = e.getKey();
|
||||
e.getValue().add(occurrence);
|
||||
|
@ -21,6 +21,7 @@ import net.sourceforge.pmd.util.CompoundIterator;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
public class XmlNodeInvocationHandler implements InvocationHandler {
|
||||
@ -41,6 +42,15 @@ public class XmlNodeInvocationHandler implements InvocationHandler {
|
||||
return node.hasChildNodes() ? node.getChildNodes().getLength() : 0;
|
||||
} else if ("jjtGetChild".equals(method.getName())) {
|
||||
return parser.createProxy(node.getChildNodes().item(((Integer) args[0]).intValue()));
|
||||
} else if ("jjtGetChildIndex".equals(method.getName())) {
|
||||
Node parent = node.getParentNode();
|
||||
NodeList childNodes = parent.getChildNodes();
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
if (node == childNodes.item(i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("This node is not a child of its parent: " + node);
|
||||
} else if ("getImage".equals(method.getName())) {
|
||||
if (node instanceof Text) {
|
||||
return ((Text) node).getData();
|
||||
|
@ -32,3 +32,4 @@
|
||||
* [#1298](https://sourceforge.net/p/pmd/bugs/1298/): Member variable int type with value 0xff000000 causes processing error
|
||||
* [#1299](https://sourceforge.net/p/pmd/bugs/1299/): MethodReturnsInternalArray false positive
|
||||
* [#1306](https://sourceforge.net/p/pmd/bugs/1306/): False positive on duplicate when using static imports
|
||||
* [#1308](https://sourceforge.net/p/pmd/bugs/1308/): PMD runs endlessly on some generated files
|
||||
|
Reference in New Issue
Block a user