Check XPath expression result for correct type

Fixes #1939
This commit is contained in:
Clément Fournier
2020-10-26 17:47:48 +01:00
parent 40cc666507
commit c21784843c
2 changed files with 24 additions and 10 deletions

View File

@ -120,25 +120,21 @@ public class SaxonXPathRuleQuery extends AbstractXPathRuleQuery {
assert rootElementNode != null : "Cannot find " + node;
final XPathDynamicContext xpathDynamicContext = createDynamicContext(rootElementNode);
final List<ElementNode> nodes = new LinkedList<>();
final List<Node> results = new LinkedList<>();
List<Expression> expressions = getXPathExpressionForNodeOrDefault(node.getXPathNodeName());
for (Expression expression : expressions) {
SequenceIterator iterator = expression.iterate(xpathDynamicContext.getXPathContextObject());
Item current = iterator.next();
while (current != null) {
nodes.add((ElementNode) current);
if (current instanceof ElementNode) {
results.add((Node) ((ElementNode) current).getUnderlyingNode());
} else {
throw new RuntimeException("XPath rule expression returned a non-node (" + current.getClass() + "): " + current);
}
current = iterator.next();
}
}
/*
Map List of Saxon Nodes -> List of AST Nodes, which were detected to match the XPath expression
(i.e. violation found)
*/
final List<Node> results = new ArrayList<>(nodes.size());
for (final ElementNode elementNode : nodes) {
results.add((Node) elementNode.getUnderlyingNode());
}
Collections.sort(results, RuleChainAnalyzer.documentOrderComparator());
return results;
} catch (final XPathException e) {

View File

@ -9,8 +9,11 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import net.sourceforge.pmd.RuleContext;
import net.sourceforge.pmd.lang.ast.DummyNodeWithListAndEnum;
@ -22,6 +25,9 @@ import net.sf.saxon.expr.Expression;
public class SaxonXPathRuleQueryTest {
@Rule
public final ExpectedException expected = ExpectedException.none();
@Test
public void testListAttribute() {
DummyNodeWithListAndEnum dummy = new DummyNodeWithListAndEnum(1);
@ -37,6 +43,18 @@ public class SaxonXPathRuleQueryTest {
assertQuery(0, "//dummyNode[@EmptyList = (\"A\")]", dummy);
}
@Test
public void testInvalidReturn() {
DummyNodeWithListAndEnum dummy = new DummyNodeWithListAndEnum(1);
expected.expect(RuntimeException.class);
expected.expectMessage(CoreMatchers.containsString("XPath rule expression returned a non-node"));
expected.expectMessage(CoreMatchers.containsString("Int64Value"));
createQuery("1+2").evaluate(dummy, new RuleContext());
}
@Test
public void ruleChainVisits() {
SaxonXPathRuleQuery query = createQuery("//dummyNode[@Image='baz']/foo | //bar[@Public = 'true'] | //dummyNode[@Public = false()] | //dummyNode");