From 18df5835ff164c0cdf61e55d0659c62a20c838f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Fri, 8 Jun 2018 20:33:04 +0200 Subject: [PATCH 1/9] Fix Saxon not reading Xml attributes --- .../pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java | 8 ++++++-- .../net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java index 26f98f21d1..e8c8e57b43 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.ast.xpath.saxon; +import java.util.Iterator; + import net.sourceforge.pmd.lang.ast.xpath.Attribute; import net.sf.saxon.om.Navigator; @@ -15,7 +17,7 @@ import net.sf.saxon.om.SequenceIterator; public class AttributeAxisIterator extends Navigator.BaseEnumeration { protected final ElementNode startNodeInfo; - protected final net.sourceforge.pmd.lang.ast.xpath.AttributeAxisIterator iterator; + protected final Iterator iterator; /** * Create an iterator over the Attribute axis for the given ElementNode. @@ -24,7 +26,9 @@ public class AttributeAxisIterator extends Navigator.BaseEnumeration { */ public AttributeAxisIterator(ElementNode startNodeInfo) { this.startNodeInfo = startNodeInfo; - this.iterator = new net.sourceforge.pmd.lang.ast.xpath.AttributeAxisIterator(startNodeInfo.node); + this.iterator = startNodeInfo.node instanceof net.sourceforge.pmd.lang.ast.xpath.AttributeNode + ? ((net.sourceforge.pmd.lang.ast.xpath.AttributeNode) startNodeInfo.node).getAttributeIterator() + : new net.sourceforge.pmd.lang.ast.xpath.AttributeAxisIterator(startNodeInfo.node); } @Override diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java index fef8309a0b..7ae16a7dfb 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java @@ -222,7 +222,7 @@ public class XmlNodeWrapper extends AbstractDomNodeProxy implements XmlNode { @Override public Attribute next() { org.w3c.dom.Node attributeNode = attributes.item(index++); - return new Attribute(parser.wrapDomNode(node), + return new Attribute(XmlNodeWrapper.this, attributeNode.getNodeName(), attributeNode.getNodeValue()); } From cb86f2a4b08ae80c1dc235daaabaeced038e0a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Fri, 8 Jun 2018 21:47:33 +0200 Subject: [PATCH 2/9] Take the chance to display attributes correctly in the designer --- .../pmd/util/fxdesigner/NodeInfoPanelController.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/NodeInfoPanelController.java b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/NodeInfoPanelController.java index f3fddaf9e8..ef594572fc 100644 --- a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/NodeInfoPanelController.java +++ b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/NodeInfoPanelController.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.util.fxdesigner; import java.net.URL; import java.util.Collections; +import java.util.Iterator; import java.util.Objects; import java.util.ResourceBundle; @@ -14,6 +15,7 @@ import org.reactfx.EventStreams; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.xpath.Attribute; import net.sourceforge.pmd.lang.ast.xpath.AttributeAxisIterator; +import net.sourceforge.pmd.lang.ast.xpath.AttributeNode; import net.sourceforge.pmd.lang.java.ast.TypeNode; import net.sourceforge.pmd.lang.symboltable.NameDeclaration; import net.sourceforge.pmd.util.fxdesigner.model.MetricEvaluator; @@ -138,9 +140,10 @@ public class NodeInfoPanelController implements Initializable { */ private static ObservableList getAttributes(Node node) { ObservableList result = FXCollections.observableArrayList(); - AttributeAxisIterator attributeAxisIterator = new AttributeAxisIterator(node); + Iterator attributeAxisIterator = node instanceof AttributeNode ? ((AttributeNode) node).getAttributeIterator() : new AttributeAxisIterator(node); while (attributeAxisIterator.hasNext()) { Attribute attribute = attributeAxisIterator.next(); + // TODO the display should be handled in a ListCell result.add(attribute.getName() + " = " + ((attribute.getValue() != null) ? attribute.getStringValue() : "null")); } From 3a8febb20099b3842c50e66395796fc02ae60ef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 10 Jun 2018 03:00:45 +0200 Subject: [PATCH 3/9] Document AttributeAxisIterator --- .../lang/ast/xpath/AttributeAxisIterator.java | 62 ++++++++++++++----- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIterator.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIterator.java index 2096309099..3a027b1a86 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIterator.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIterator.java @@ -16,17 +16,36 @@ import java.util.concurrent.ConcurrentMap; import net.sourceforge.pmd.lang.ast.Node; + +/** + * Explores an AST node reflectively to iterate over its XPath + * attributes. This is the default way the attributes of a node + * are made accessible to XPath rules, and defines an important + * piece of PMD's XPath support. + */ public class AttributeAxisIterator implements Iterator { + /** + * Associates an attribute accessor with the XPath-accessible + * name of the attribute. This is used to avoid recomputing + * the name of the attribute for each attribute (it's only done + * once and put inside the {@link #METHOD_CACHE}. + */ private static class MethodWrapper { public Method method; public String name; + MethodWrapper(Method m) { this.method = m; this.name = truncateMethodName(m.getName()); } + + /** + * This method produces the actual XPath name of an attribute + * from the name of its accessor. + */ private String truncateMethodName(String n) { // about 70% of the methods start with 'get', so this case goes // first @@ -52,12 +71,15 @@ public class AttributeAxisIterator implements Iterator { private int position; private Node node; - private static ConcurrentMap, MethodWrapper[]> methodCache = - new ConcurrentHashMap, MethodWrapper[]>(); + private static final ConcurrentMap, MethodWrapper[]> METHOD_CACHE = new ConcurrentHashMap<>(); + + /** + * Creates a new iterator that enumerates the attributes of the given node. + */ public AttributeAxisIterator(Node contextNode) { this.node = contextNode; - if (!methodCache.containsKey(contextNode.getClass())) { + if (!METHOD_CACHE.containsKey(contextNode.getClass())) { Method[] preFilter = contextNode.getClass().getMethods(); List postFilter = new ArrayList<>(); for (Method element : preFilter) { @@ -65,17 +87,18 @@ public class AttributeAxisIterator implements Iterator { postFilter.add(new MethodWrapper(element)); } } - methodCache.putIfAbsent(contextNode.getClass(), postFilter.toArray(new MethodWrapper[0])); + METHOD_CACHE.putIfAbsent(contextNode.getClass(), postFilter.toArray(new MethodWrapper[0])); } - this.methodWrappers = methodCache.get(contextNode.getClass()); + this.methodWrappers = METHOD_CACHE.get(contextNode.getClass()); this.position = 0; this.currObj = getNextAttribute(); } + @Override public Attribute next() { - if (currObj == null) { + if (!hasNext()) { throw new IndexOutOfBoundsException(); } Attribute ret = currObj; @@ -83,16 +106,19 @@ public class AttributeAxisIterator implements Iterator { return ret; } + @Override public boolean hasNext() { return currObj != null; } + @Override public void remove() { throw new UnsupportedOperationException(); } + private Attribute getNextAttribute() { if (methodWrappers == null || position == methodWrappers.length) { return null; @@ -102,20 +128,26 @@ public class AttributeAxisIterator implements Iterator { } + private static final Set> CONSIDERED_RETURN_TYPES + = new HashSet<>(Arrays.>asList(Integer.TYPE, Boolean.TYPE, Double.TYPE, String.class, Long.TYPE, Character.TYPE, Float.TYPE)); + + private static final Set FILTERED_OUT_NAMES + = new HashSet<>(Arrays.asList("toString", "getClass", "getXPathNodeName", "getTypeNameNode", "hashCode", "getImportedNameNode", "getScope")); - private static final Set> CONSIDERED_RETURN_TYPES - = new HashSet<>(Arrays.>asList(Integer.TYPE, Boolean.TYPE, Double.TYPE, String.class, Long.TYPE, Character.TYPE, Float.TYPE)); - - private static final Set FILTERED_OUT_NAMES - = new HashSet<>(Arrays.asList("toString", "getClass", "getXPathNodeName", "getTypeNameNode", "hashCode", "getImportedNameNode", "getScope")); - + /** + * Returns whether the given method is an attribute accessor, + * in which case a corresponding Attribute will be added to + * the iterator. + * + * @param method The method to test + */ protected boolean isAttributeAccessor(Method method) { String methodName = method.getName(); return CONSIDERED_RETURN_TYPES.contains(method.getReturnType()) - && method.getParameterTypes().length == 0 - && !methodName.startsWith("jjt") - && !FILTERED_OUT_NAMES.contains(methodName); + && method.getParameterTypes().length == 0 + && !methodName.startsWith("jjt") + && !FILTERED_OUT_NAMES.contains(methodName); } } From 9aacc4d20605037efd34410e886fa42bc6bb6587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 10 Jun 2018 03:03:57 +0200 Subject: [PATCH 4/9] Rearrange code --- .../lang/ast/xpath/AttributeAxisIterator.java | 172 +++++++++--------- 1 file changed, 87 insertions(+), 85 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIterator.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIterator.java index 3a027b1a86..b25ede3e0e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIterator.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIterator.java @@ -25,6 +25,93 @@ import net.sourceforge.pmd.lang.ast.Node; */ public class AttributeAxisIterator implements Iterator { + /** Caches the precomputed attribute accessors of a given class. */ + private static final ConcurrentMap, MethodWrapper[]> METHOD_CACHE = new ConcurrentHashMap<>(); + + /* Constants used to determine which methods are accessors */ + private static final Set> CONSIDERED_RETURN_TYPES + = new HashSet<>(Arrays.>asList(Integer.TYPE, Boolean.TYPE, Double.TYPE, String.class, Long.TYPE, Character.TYPE, Float.TYPE)); + private static final Set FILTERED_OUT_NAMES + = new HashSet<>(Arrays.asList("toString", "getClass", "getXPathNodeName", "getTypeNameNode", "hashCode", "getImportedNameNode", "getScope")); + + /* Iteration variables */ + private Attribute currObj; + private MethodWrapper[] methodWrappers; + private int position; + private Node node; + + + /** + * Creates a new iterator that enumerates the attributes of the given node. + */ + public AttributeAxisIterator(Node contextNode) { + this.node = contextNode; + if (!METHOD_CACHE.containsKey(contextNode.getClass())) { + Method[] preFilter = contextNode.getClass().getMethods(); + List postFilter = new ArrayList<>(); + for (Method element : preFilter) { + if (isAttributeAccessor(element)) { + postFilter.add(new MethodWrapper(element)); + } + } + METHOD_CACHE.putIfAbsent(contextNode.getClass(), postFilter.toArray(new MethodWrapper[0])); + } + this.methodWrappers = METHOD_CACHE.get(contextNode.getClass()); + + this.position = 0; + this.currObj = getNextAttribute(); + } + + + /** + * Returns whether the given method is an attribute accessor, + * in which case a corresponding Attribute will be added to + * the iterator. + * + * @param method The method to test + */ + protected boolean isAttributeAccessor(Method method) { + String methodName = method.getName(); + + return CONSIDERED_RETURN_TYPES.contains(method.getReturnType()) + && method.getParameterTypes().length == 0 + && !methodName.startsWith("jjt") + && !FILTERED_OUT_NAMES.contains(methodName); + } + + + @Override + public Attribute next() { + if (!hasNext()) { + throw new IndexOutOfBoundsException(); + } + Attribute ret = currObj; + currObj = getNextAttribute(); + return ret; + } + + + @Override + public boolean hasNext() { + return currObj != null; + } + + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + + private Attribute getNextAttribute() { + if (methodWrappers == null || position == methodWrappers.length) { + return null; + } + MethodWrapper m = methodWrappers[position++]; + return new Attribute(node, m.name, m.method); + } + + /** * Associates an attribute accessor with the XPath-accessible * name of the attribute. This is used to avoid recomputing @@ -65,89 +152,4 @@ public class AttributeAxisIterator implements Iterator { return n; } } - - private Attribute currObj; - private MethodWrapper[] methodWrappers; - private int position; - private Node node; - - private static final ConcurrentMap, MethodWrapper[]> METHOD_CACHE = new ConcurrentHashMap<>(); - - - /** - * Creates a new iterator that enumerates the attributes of the given node. - */ - public AttributeAxisIterator(Node contextNode) { - this.node = contextNode; - if (!METHOD_CACHE.containsKey(contextNode.getClass())) { - Method[] preFilter = contextNode.getClass().getMethods(); - List postFilter = new ArrayList<>(); - for (Method element : preFilter) { - if (isAttributeAccessor(element)) { - postFilter.add(new MethodWrapper(element)); - } - } - METHOD_CACHE.putIfAbsent(contextNode.getClass(), postFilter.toArray(new MethodWrapper[0])); - } - this.methodWrappers = METHOD_CACHE.get(contextNode.getClass()); - - this.position = 0; - this.currObj = getNextAttribute(); - } - - - @Override - public Attribute next() { - if (!hasNext()) { - throw new IndexOutOfBoundsException(); - } - Attribute ret = currObj; - currObj = getNextAttribute(); - return ret; - } - - - @Override - public boolean hasNext() { - return currObj != null; - } - - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - - private Attribute getNextAttribute() { - if (methodWrappers == null || position == methodWrappers.length) { - return null; - } - MethodWrapper m = methodWrappers[position++]; - return new Attribute(node, m.name, m.method); - } - - - private static final Set> CONSIDERED_RETURN_TYPES - = new HashSet<>(Arrays.>asList(Integer.TYPE, Boolean.TYPE, Double.TYPE, String.class, Long.TYPE, Character.TYPE, Float.TYPE)); - - private static final Set FILTERED_OUT_NAMES - = new HashSet<>(Arrays.asList("toString", "getClass", "getXPathNodeName", "getTypeNameNode", "hashCode", "getImportedNameNode", "getScope")); - - - /** - * Returns whether the given method is an attribute accessor, - * in which case a corresponding Attribute will be added to - * the iterator. - * - * @param method The method to test - */ - protected boolean isAttributeAccessor(Method method) { - String methodName = method.getName(); - - return CONSIDERED_RETURN_TYPES.contains(method.getReturnType()) - && method.getParameterTypes().length == 0 - && !methodName.startsWith("jjt") - && !FILTERED_OUT_NAMES.contains(methodName); - } } From bf466b8b84837500b1342ca7abc48bbb46894a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 10 Jun 2018 03:08:56 +0200 Subject: [PATCH 5/9] Document Attribute --- .../pmd/lang/ast/xpath/Attribute.java | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/Attribute.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/Attribute.java index bbfa026ec5..d419185eff 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/Attribute.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/Attribute.java @@ -14,6 +14,10 @@ import java.util.logging.Logger; import net.sourceforge.pmd.lang.ast.Node; /** + * Represents an XPath attribute of a specific node. + * Attributes know their name, the node they wrap, + * and have access to their value. + * * @author daniels */ public class Attribute { @@ -22,20 +26,23 @@ public class Attribute { private static final Logger LOG = Logger.getLogger(Attribute.class.getName()); private static final ConcurrentMap DETECTED_DEPRECATED_ATTRIBUTES = new ConcurrentHashMap<>(); - private static final Object[] EMPTY_OBJ_ARRAY = new Object[0]; + private Node parent; private String name; private Method method; private Object value; private String stringValue; + /** Creates a new attribute belonging to the given node using its accessor. */ public Attribute(Node parent, String name, Method m) { this.parent = parent; this.name = name; this.method = m; } + + /** Creates a new attribute belonging to the given node using its string value. */ public Attribute(Node parent, String name, String value) { this.parent = parent; this.name = name; @@ -43,6 +50,16 @@ public class Attribute { this.stringValue = value; } + + public String getName() { + return name; + } + + + public Node getParent() { + return parent; + } + public Object getValue() { if (value != null) { return value; @@ -71,11 +88,7 @@ public class Attribute { if (this.value == null) { v = getValue(); } - if (v == null) { - stringValue = ""; - } else { - stringValue = String.valueOf(v); - } + stringValue = v == null ? "" : String.valueOf(v); return stringValue; } @@ -83,14 +96,6 @@ public class Attribute { return parent.getXPathNodeName() + "/@" + name; } - public String getName() { - return name; - } - - public Node getParent() { - return parent; - } - @Override public String toString() { return name + ':' + getValue() + ':' + parent; From 5cf7891d710b5b166d4d47174eea39dcaa491c27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 10 Jun 2018 03:26:28 +0200 Subject: [PATCH 6/9] Add getXPathAttributes() to Node interface Deprecate AttributeNode --- .../net/sourceforge/pmd/lang/ast/AbstractNode.java | 7 +++++++ .../main/java/net/sourceforge/pmd/lang/ast/Node.java | 10 ++++++++++ .../pmd/lang/ast/xpath/AttributeNode.java | 5 +++++ .../pmd/lang/ast/xpath/DocumentNavigator.java | 6 +----- .../sourceforge/pmd/lang/ast/xpath/NodeIterator.java | 5 ++++- .../lang/ast/xpath/saxon/AttributeAxisIterator.java | 7 +++---- .../pmd/lang/ast/xpath/saxon/AttributeNode.java | 8 ++++++++ .../pmd/util/fxdesigner/NodeInfoPanelController.java | 4 +--- .../sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java | 12 +++++++++++- 9 files changed, 50 insertions(+), 14 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AbstractNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AbstractNode.java index 2d2b60012e..f43c03ab64 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AbstractNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AbstractNode.java @@ -21,6 +21,7 @@ import org.w3c.dom.Element; import net.sourceforge.pmd.PMDVersion; import net.sourceforge.pmd.lang.ast.xpath.Attribute; +import net.sourceforge.pmd.lang.ast.xpath.AttributeAxisIterator; import net.sourceforge.pmd.lang.ast.xpath.DocumentNavigator; import net.sourceforge.pmd.lang.dfa.DataFlowNode; @@ -515,4 +516,10 @@ public abstract class AbstractNode implements Node { public String toString() { return getXPathNodeName(); } + + + @Override + public Iterator getXPathAttributes() { + return new AttributeAxisIterator(this); + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java index 204cc3c859..a905195701 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java @@ -5,11 +5,13 @@ package net.sourceforge.pmd.lang.ast; +import java.util.Iterator; import java.util.List; import org.jaxen.JaxenException; import org.w3c.dom.Document; +import net.sourceforge.pmd.lang.ast.xpath.Attribute; import net.sourceforge.pmd.lang.dfa.DataFlowNode; /** @@ -322,4 +324,12 @@ public interface Node { * @return The XPath node name */ String getXPathNodeName(); + + + /** + * Returns an iterator containing all the attributes that are available + * from XPath for this node. + */ + Iterator getXPathAttributes(); + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeNode.java index f34343f133..b08b8e579f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeNode.java @@ -6,11 +6,16 @@ package net.sourceforge.pmd.lang.ast.xpath; import java.util.Iterator; + /** * This interface can be used by an AST node to indicate it can directly provide * access to it's attributes, versus having them be determined via * introspection. + * + * @deprecated See {@link net.sourceforge.pmd.lang.ast.Node#getXPathAttributes()}. + * Will be removed in 7.0.0 */ +@Deprecated public interface AttributeNode { Iterator getAttributeIterator(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/DocumentNavigator.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/DocumentNavigator.java index f56743ddb4..4369e33606 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/DocumentNavigator.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/DocumentNavigator.java @@ -135,11 +135,7 @@ public class DocumentNavigator extends DefaultNavigator { @Override public Iterator getAttributeAxisIterator(Object arg0) { - if (arg0 instanceof AttributeNode) { - return ((AttributeNode) arg0).getAttributeIterator(); - } else { - return new AttributeAxisIterator((Node) arg0); - } + return ((Node) arg0).getXPathAttributes(); } /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/NodeIterator.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/NodeIterator.java index 7f1cb1867a..2d189cfcef 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/NodeIterator.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/NodeIterator.java @@ -10,13 +10,16 @@ import java.util.NoSuchElementException; import net.sourceforge.pmd.lang.ast.Node; /** + * Base class for node iterators used to implement XPath axis + * iterators for Jaxen. + * * @author daniels */ public abstract class NodeIterator implements Iterator { private Node node; - public NodeIterator(Node contextNode) { + protected NodeIterator(Node contextNode) { this.node = getFirstNode(contextNode); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java index e8c8e57b43..db767a8bd3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java @@ -12,7 +12,8 @@ import net.sf.saxon.om.Navigator; import net.sf.saxon.om.SequenceIterator; /** - * This is an Attribute axis iterator. + * An adapter over our {@link net.sourceforge.pmd.lang.ast.xpath.AttributeAxisIterator} + * for the Saxon model. */ public class AttributeAxisIterator extends Navigator.BaseEnumeration { @@ -26,9 +27,7 @@ public class AttributeAxisIterator extends Navigator.BaseEnumeration { */ public AttributeAxisIterator(ElementNode startNodeInfo) { this.startNodeInfo = startNodeInfo; - this.iterator = startNodeInfo.node instanceof net.sourceforge.pmd.lang.ast.xpath.AttributeNode - ? ((net.sourceforge.pmd.lang.ast.xpath.AttributeNode) startNodeInfo.node).getAttributeIterator() - : new net.sourceforge.pmd.lang.ast.xpath.AttributeAxisIterator(startNodeInfo.node); + this.iterator = startNodeInfo.node.getXPathAttributes(); } @Override diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeNode.java index 913f00caec..69e93cddb4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeNode.java @@ -15,12 +15,20 @@ import net.sf.saxon.value.Value; /** * A Saxon OM Attribute node for an AST Node Attribute. + * Belongs to an {@link ElementNode}, and wraps an + * {@link Attribute}. */ public class AttributeNode extends AbstractNodeInfo { protected final Attribute attribute; protected final int id; protected Value value; + + /** + * Creates a new AttributeNode from a PMD Attribute. + * + * @param id The index within the attribute order + */ public AttributeNode(Attribute attribute, int id) { this.attribute = attribute; this.id = id; diff --git a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/NodeInfoPanelController.java b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/NodeInfoPanelController.java index ef594572fc..f939675032 100644 --- a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/NodeInfoPanelController.java +++ b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/NodeInfoPanelController.java @@ -14,8 +14,6 @@ import org.reactfx.EventStreams; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.xpath.Attribute; -import net.sourceforge.pmd.lang.ast.xpath.AttributeAxisIterator; -import net.sourceforge.pmd.lang.ast.xpath.AttributeNode; import net.sourceforge.pmd.lang.java.ast.TypeNode; import net.sourceforge.pmd.lang.symboltable.NameDeclaration; import net.sourceforge.pmd.util.fxdesigner.model.MetricEvaluator; @@ -140,7 +138,7 @@ public class NodeInfoPanelController implements Initializable { */ private static ObservableList getAttributes(Node node) { ObservableList result = FXCollections.observableArrayList(); - Iterator attributeAxisIterator = node instanceof AttributeNode ? ((AttributeNode) node).getAttributeIterator() : new AttributeAxisIterator(node); + Iterator attributeAxisIterator = node.getXPathAttributes(); while (attributeAxisIterator.hasNext()) { Attribute attribute = attributeAxisIterator.next(); // TODO the display should be handled in a ListCell diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java index 7ae16a7dfb..d3436300af 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java @@ -204,7 +204,7 @@ public class XmlNodeWrapper extends AbstractDomNodeProxy implements XmlNode { @Override - public Iterator getAttributeIterator() { + public Iterator getXPathAttributes() { List> iterators = new ArrayList<>(); // Expose DOM Attributes @@ -249,6 +249,16 @@ public class XmlNodeWrapper extends AbstractDomNodeProxy implements XmlNode { } + /** + * @deprecated use {@link #getXPathAttributes()} + */ + @Override + @Deprecated + public Iterator getAttributeIterator() { + return getXPathAttributes(); + } + + @Override public org.w3c.dom.Node getNode() { return node; From b4c492d94ffa911c37cc349cdaa11cf7e0810ef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 10 Jun 2018 03:35:52 +0200 Subject: [PATCH 7/9] More doc --- .../sourceforge/pmd/lang/ast/xpath/AttributeAxisIterator.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIterator.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIterator.java index b25ede3e0e..11a69142b1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIterator.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIterator.java @@ -43,6 +43,8 @@ public class AttributeAxisIterator implements Iterator { /** * Creates a new iterator that enumerates the attributes of the given node. + * Note: if you want to access the attributes of a node, don't use this directly, + * use instead the overridable {@link Node#getXPathAttributes()}. */ public AttributeAxisIterator(Node contextNode) { this.node = contextNode; @@ -116,7 +118,7 @@ public class AttributeAxisIterator implements Iterator { * Associates an attribute accessor with the XPath-accessible * name of the attribute. This is used to avoid recomputing * the name of the attribute for each attribute (it's only done - * once and put inside the {@link #METHOD_CACHE}. + * once and put inside the {@link #METHOD_CACHE}). */ private static class MethodWrapper { public Method method; From 735b8dfe3725f0a94e3f139871a230f3e5bc9f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 10 Jun 2018 03:41:22 +0200 Subject: [PATCH 8/9] Use better name --- .../java/net/sourceforge/pmd/lang/ast/AbstractNode.java | 2 +- .../src/main/java/net/sourceforge/pmd/lang/ast/Node.java | 4 ++-- .../pmd/lang/ast/xpath/AttributeAxisIterator.java | 2 +- .../net/sourceforge/pmd/lang/ast/xpath/AttributeNode.java | 2 +- .../sourceforge/pmd/lang/ast/xpath/DocumentNavigator.java | 2 +- .../pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java | 2 +- .../pmd/util/fxdesigner/NodeInfoPanelController.java | 2 +- .../net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java | 6 +++--- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AbstractNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AbstractNode.java index f43c03ab64..fb0f0512d3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AbstractNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AbstractNode.java @@ -519,7 +519,7 @@ public abstract class AbstractNode implements Node { @Override - public Iterator getXPathAttributes() { + public Iterator getXPathAttributesIterator() { return new AttributeAxisIterator(this); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java index a905195701..f91b4f03a6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java @@ -327,9 +327,9 @@ public interface Node { /** - * Returns an iterator containing all the attributes that are available + * Returns an iterator enumerating all the attributes that are available * from XPath for this node. */ - Iterator getXPathAttributes(); + Iterator getXPathAttributesIterator(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIterator.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIterator.java index 11a69142b1..2a93c13ba5 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIterator.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIterator.java @@ -44,7 +44,7 @@ public class AttributeAxisIterator implements Iterator { /** * Creates a new iterator that enumerates the attributes of the given node. * Note: if you want to access the attributes of a node, don't use this directly, - * use instead the overridable {@link Node#getXPathAttributes()}. + * use instead the overridable {@link Node#getXPathAttributesIterator()}. */ public AttributeAxisIterator(Node contextNode) { this.node = contextNode; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeNode.java index b08b8e579f..6fead63886 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/AttributeNode.java @@ -12,7 +12,7 @@ import java.util.Iterator; * access to it's attributes, versus having them be determined via * introspection. * - * @deprecated See {@link net.sourceforge.pmd.lang.ast.Node#getXPathAttributes()}. + * @deprecated See {@link net.sourceforge.pmd.lang.ast.Node#getXPathAttributesIterator()}. * Will be removed in 7.0.0 */ @Deprecated diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/DocumentNavigator.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/DocumentNavigator.java index 4369e33606..9fcdcf2163 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/DocumentNavigator.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/DocumentNavigator.java @@ -135,7 +135,7 @@ public class DocumentNavigator extends DefaultNavigator { @Override public Iterator getAttributeAxisIterator(Object arg0) { - return ((Node) arg0).getXPathAttributes(); + return ((Node) arg0).getXPathAttributesIterator(); } /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java index db767a8bd3..ada6ed8a78 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java @@ -27,7 +27,7 @@ public class AttributeAxisIterator extends Navigator.BaseEnumeration { */ public AttributeAxisIterator(ElementNode startNodeInfo) { this.startNodeInfo = startNodeInfo; - this.iterator = startNodeInfo.node.getXPathAttributes(); + this.iterator = startNodeInfo.node.getXPathAttributesIterator(); } @Override diff --git a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/NodeInfoPanelController.java b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/NodeInfoPanelController.java index f939675032..2acbff2c9a 100644 --- a/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/NodeInfoPanelController.java +++ b/pmd-ui/src/main/java/net/sourceforge/pmd/util/fxdesigner/NodeInfoPanelController.java @@ -138,7 +138,7 @@ public class NodeInfoPanelController implements Initializable { */ private static ObservableList getAttributes(Node node) { ObservableList result = FXCollections.observableArrayList(); - Iterator attributeAxisIterator = node.getXPathAttributes(); + Iterator attributeAxisIterator = node.getXPathAttributesIterator(); while (attributeAxisIterator.hasNext()) { Attribute attribute = attributeAxisIterator.next(); // TODO the display should be handled in a ListCell diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java index d3436300af..bf9c1cad6e 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlNodeWrapper.java @@ -204,7 +204,7 @@ public class XmlNodeWrapper extends AbstractDomNodeProxy implements XmlNode { @Override - public Iterator getXPathAttributes() { + public Iterator getXPathAttributesIterator() { List> iterators = new ArrayList<>(); // Expose DOM Attributes @@ -250,12 +250,12 @@ public class XmlNodeWrapper extends AbstractDomNodeProxy implements XmlNode { /** - * @deprecated use {@link #getXPathAttributes()} + * @deprecated use {@link #getXPathAttributesIterator()} */ @Override @Deprecated public Iterator getAttributeIterator() { - return getXPathAttributes(); + return getXPathAttributesIterator(); } From 82b4189bc5fc1e5b082ff0b67bffa8f387b30446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 10 Jun 2018 03:58:32 +0200 Subject: [PATCH 9/9] Fix javadoc warning --- pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java index f91b4f03a6..dfac6c1d07 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java @@ -329,6 +329,8 @@ public interface Node { /** * Returns an iterator enumerating all the attributes that are available * from XPath for this node. + * + * @return An attribute iterator for this node */ Iterator getXPathAttributesIterator();