[core] XPathHandler/XPathFunctionDefintion: Refactoring, javadoc
This commit is contained in:
parent
721661c3f9
commit
304ff2ec25
@ -6,6 +6,8 @@ package net.sourceforge.pmd.lang.rule.xpath.impl;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import net.sourceforge.pmd.lang.Language;
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
|
||||
@ -35,37 +37,90 @@ public abstract class XPathFunctionDefinition {
|
||||
return qname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the types of the function arguments. By default, an empty array is returned, indicating
|
||||
* that the function takes no arguments.
|
||||
*/
|
||||
public Type[] getArgumentTypes() {
|
||||
return new Type[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the return type of the function.
|
||||
*/
|
||||
public abstract Type getResultType();
|
||||
|
||||
/**
|
||||
* If the function depends on the context item or the default XPath namespace, then
|
||||
* If the function depends on the context item, then
|
||||
* this method should return {@code true}.
|
||||
*
|
||||
* <p>Note: Only if this is true, the contextNode parameter will be present in the
|
||||
* {@link FunctionCall#call(Node, Object[])} method.
|
||||
*/
|
||||
public boolean dependsOnContext() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a call on this function. This method is called, when a function call
|
||||
* is found in the XPath expression.
|
||||
*/
|
||||
public abstract FunctionCall makeCallExpression();
|
||||
|
||||
/**
|
||||
* Supported types of a custom XPath function. These can be used as {@link #getResultType() result types}
|
||||
* or {@link #getArgumentTypes() argument types}.
|
||||
*/
|
||||
public enum Type {
|
||||
/** Represents {@link String}. */
|
||||
SINGLE_STRING,
|
||||
/** Represents {@link Boolean}. */
|
||||
SINGLE_BOOLEAN,
|
||||
/** Represents {@link Integer}. */
|
||||
SINGLE_INTEGER,
|
||||
/** Represents any node. Usually used as an argument type. */
|
||||
SINGLE_ELEMENT,
|
||||
/** Represents a {@link java.util.List} of {@link String}, potentially empty. */
|
||||
STRING_SEQUENCE,
|
||||
/** Represents a {@link java.util.Optional} {@link String}. */
|
||||
OPTIONAL_STRING,
|
||||
/** Represents a {@link java.util.Optional} {@link Double}. */
|
||||
OPTIONAL_DECIMAL,
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the actual implementation of a custom XPath function.
|
||||
*/
|
||||
public interface FunctionCall {
|
||||
/**
|
||||
* This method is called at runtime to evaluate the XPath function expression.
|
||||
*
|
||||
* @param contextNode the context node or {@code null}, if this function doesn't depend on the context.
|
||||
* See {@link XPathFunctionDefinition#dependsOnContext()}.
|
||||
* @param arguments The arguments converted as the corresponding java types.
|
||||
* See {@link XPathFunctionDefinition#getArgumentTypes()}.
|
||||
* @return The result of the function. This should be the corresponding java type of
|
||||
* {@link XPathFunctionDefinition#getResultType()}.
|
||||
* @throws XPathFunctionException when any problem during evaluation occurs, like invalid arguments.
|
||||
*/
|
||||
Object call(@Nullable Node contextNode, Object[] arguments) throws XPathFunctionException;
|
||||
|
||||
/**
|
||||
* This is called once before the function is evaluated. It can be used to optimize the
|
||||
* implementation by doing expensive operations only once and cache the result.
|
||||
* This is useful, if the argument of the function is of type {@link String} and is provided
|
||||
* as a String literal in the XPath expression.
|
||||
*
|
||||
* <p>This is an optional step. The default implementation does nothing.
|
||||
*
|
||||
* @param arguments The arguments converted as the corresponding java types.
|
||||
* See {@link XPathFunctionDefinition#getArgumentTypes()}.
|
||||
* Note: This array might contain {@code null} elements, if the values are
|
||||
* not known yet because they are dynamic. Only literal values are available.
|
||||
* @throws XPathFunctionException when any problem during initialization occurs, like invalid arguments.
|
||||
*/
|
||||
default void staticInit(Object[] arguments) throws XPathFunctionException {
|
||||
// default implementation does nothing
|
||||
}
|
||||
|
||||
Object call(Node contextNode, Object[] arguments) throws XPathFunctionException;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,10 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.rule.xpath.impl;
|
||||
|
||||
/**
|
||||
* Indicates a problem during the execution of a custom
|
||||
* XPath function.
|
||||
*/
|
||||
public class XPathFunctionException extends Exception {
|
||||
public XPathFunctionException(String message) {
|
||||
super(message);
|
||||
|
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.rule.xpath.internal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionDefinition;
|
||||
import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionException;
|
||||
|
||||
import net.sf.saxon.expr.Expression;
|
||||
import net.sf.saxon.expr.StaticContext;
|
||||
import net.sf.saxon.expr.StringLiteral;
|
||||
import net.sf.saxon.expr.XPathContext;
|
||||
import net.sf.saxon.lib.ExtensionFunctionCall;
|
||||
import net.sf.saxon.lib.ExtensionFunctionDefinition;
|
||||
import net.sf.saxon.om.EmptyAtomicSequence;
|
||||
import net.sf.saxon.om.Sequence;
|
||||
import net.sf.saxon.om.StructuredQName;
|
||||
import net.sf.saxon.pattern.NodeKindTest;
|
||||
import net.sf.saxon.trans.XPathException;
|
||||
import net.sf.saxon.value.BigDecimalValue;
|
||||
import net.sf.saxon.value.BooleanValue;
|
||||
import net.sf.saxon.value.EmptySequence;
|
||||
import net.sf.saxon.value.Int64Value;
|
||||
import net.sf.saxon.value.SequenceExtent;
|
||||
import net.sf.saxon.value.SequenceType;
|
||||
import net.sf.saxon.value.StringValue;
|
||||
|
||||
/**
|
||||
* Converts PMD's {@link XPathFunctionDefinition} into Saxon's {@link ExtensionFunctionDefinition}.
|
||||
*/
|
||||
public class SaxonExtensionFunctionDefinitionAdapter extends ExtensionFunctionDefinition {
|
||||
private static final SequenceType SINGLE_ELEMENT_SEQUENCE_TYPE = NodeKindTest.ELEMENT.one();
|
||||
|
||||
private final XPathFunctionDefinition definition;
|
||||
|
||||
public SaxonExtensionFunctionDefinitionAdapter(XPathFunctionDefinition definition) {
|
||||
this.definition = definition;
|
||||
}
|
||||
|
||||
private SequenceType convertToSequenceType(XPathFunctionDefinition.Type type) {
|
||||
switch (type) {
|
||||
case SINGLE_STRING: return SequenceType.SINGLE_STRING;
|
||||
case SINGLE_BOOLEAN: return SequenceType.SINGLE_BOOLEAN;
|
||||
case SINGLE_ELEMENT: return SINGLE_ELEMENT_SEQUENCE_TYPE;
|
||||
case SINGLE_INTEGER: return SequenceType.SINGLE_INTEGER;
|
||||
case STRING_SEQUENCE: return SequenceType.STRING_SEQUENCE;
|
||||
case OPTIONAL_STRING: return SequenceType.OPTIONAL_STRING;
|
||||
case OPTIONAL_DECIMAL: return SequenceType.OPTIONAL_DECIMAL;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Type " + type + " is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
private SequenceType[] convertToSequenceTypes(XPathFunctionDefinition.Type[] types) {
|
||||
SequenceType[] result = new SequenceType[types.length];
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
result[i] = convertToSequenceType(types[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructuredQName getFunctionQName() {
|
||||
QName qName = definition.getQName();
|
||||
return new StructuredQName(qName.getPrefix(), qName.getNamespaceURI(), qName.getLocalPart());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SequenceType[] getArgumentTypes() {
|
||||
return convertToSequenceTypes(definition.getArgumentTypes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
|
||||
return convertToSequenceType(definition.getResultType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dependsOnFocus() {
|
||||
return definition.dependsOnContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtensionFunctionCall makeCallExpression() {
|
||||
XPathFunctionDefinition.FunctionCall call = definition.makeCallExpression();
|
||||
return new ExtensionFunctionCall() {
|
||||
@Override
|
||||
public Expression rewrite(StaticContext context, Expression[] arguments) throws XPathException {
|
||||
Object[] convertedArguments = new Object[definition.getArgumentTypes().length];
|
||||
for (int i = 0; i < convertedArguments.length; i++) {
|
||||
if (arguments[i] instanceof StringLiteral) {
|
||||
convertedArguments[i] = ((StringLiteral) arguments[i]).getStringValue();
|
||||
}
|
||||
}
|
||||
try {
|
||||
call.staticInit(convertedArguments);
|
||||
} catch (XPathFunctionException e) {
|
||||
XPathException xPathException = new XPathException(e);
|
||||
xPathException.setIsStaticError(true);
|
||||
throw xPathException;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
|
||||
Node contextNode = null;
|
||||
if (definition.dependsOnContext()) {
|
||||
contextNode = XPathElementToNodeHelper.itemToNode(context.getContextItem());
|
||||
}
|
||||
Object[] convertedArguments = new Object[definition.getArgumentTypes().length];
|
||||
for (int i = 0; i < convertedArguments.length; i++) {
|
||||
switch (definition.getArgumentTypes()[i]) {
|
||||
case SINGLE_STRING:
|
||||
convertedArguments[i] = arguments[i].head().getStringValue();
|
||||
break;
|
||||
case SINGLE_ELEMENT:
|
||||
convertedArguments[i] = arguments[i].head();
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Don't know how to convert argument type " + definition.getArgumentTypes()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Object result = null;
|
||||
try {
|
||||
result = call.call(contextNode, convertedArguments);
|
||||
} catch (XPathFunctionException e) {
|
||||
throw new XPathException(e);
|
||||
}
|
||||
Sequence convertedResult = null;
|
||||
switch (definition.getResultType()) {
|
||||
case SINGLE_BOOLEAN:
|
||||
convertedResult = BooleanValue.get((Boolean) result);
|
||||
break;
|
||||
case SINGLE_INTEGER:
|
||||
convertedResult = Int64Value.makeIntegerValue((Integer) result);
|
||||
break;
|
||||
case SINGLE_STRING:
|
||||
convertedResult = new StringValue((String) result);
|
||||
break;
|
||||
case OPTIONAL_STRING:
|
||||
convertedResult = result instanceof Optional && ((Optional<String>) result).isPresent()
|
||||
? new StringValue(((Optional<String>) result).get())
|
||||
: EmptyAtomicSequence.INSTANCE;
|
||||
break;
|
||||
case STRING_SEQUENCE:
|
||||
convertedResult = result instanceof List
|
||||
? new SequenceExtent(((List<String>) result).stream().map(StringValue::new).collect(Collectors.toList()))
|
||||
: EmptySequence.getInstance();
|
||||
break;
|
||||
case OPTIONAL_DECIMAL:
|
||||
convertedResult = result instanceof Optional && ((Optional<Double>) result).isPresent()
|
||||
? new BigDecimalValue(((Optional<Double>) result).get())
|
||||
: EmptySequence.getInstance();
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Don't know how to convert result type " + definition.getResultType());
|
||||
}
|
||||
return convertedResult;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -5,14 +5,11 @@
|
||||
package net.sourceforge.pmd.lang.rule.xpath.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import org.apache.commons.lang3.exception.ContextedRuntimeException;
|
||||
import org.slf4j.Logger;
|
||||
@ -24,7 +21,6 @@ import net.sourceforge.pmd.lang.rule.xpath.PmdXPathException;
|
||||
import net.sourceforge.pmd.lang.rule.xpath.PmdXPathException.Phase;
|
||||
import net.sourceforge.pmd.lang.rule.xpath.XPathVersion;
|
||||
import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionDefinition;
|
||||
import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionException;
|
||||
import net.sourceforge.pmd.lang.rule.xpath.impl.XPathHandler;
|
||||
import net.sourceforge.pmd.properties.PropertyDescriptor;
|
||||
import net.sourceforge.pmd.util.DataMap;
|
||||
@ -33,33 +29,19 @@ import net.sourceforge.pmd.util.DataMap.SimpleDataKey;
|
||||
import net.sf.saxon.Configuration;
|
||||
import net.sf.saxon.expr.Expression;
|
||||
import net.sf.saxon.expr.LocalVariableReference;
|
||||
import net.sf.saxon.expr.StaticContext;
|
||||
import net.sf.saxon.expr.StringLiteral;
|
||||
import net.sf.saxon.expr.XPathContext;
|
||||
import net.sf.saxon.lib.ExtensionFunctionCall;
|
||||
import net.sf.saxon.lib.ExtensionFunctionDefinition;
|
||||
import net.sf.saxon.lib.NamespaceConstant;
|
||||
import net.sf.saxon.om.AtomicSequence;
|
||||
import net.sf.saxon.om.EmptyAtomicSequence;
|
||||
import net.sf.saxon.om.Item;
|
||||
import net.sf.saxon.om.NamePool;
|
||||
import net.sf.saxon.om.Sequence;
|
||||
import net.sf.saxon.om.SequenceIterator;
|
||||
import net.sf.saxon.om.StructuredQName;
|
||||
import net.sf.saxon.pattern.NodeKindTest;
|
||||
import net.sf.saxon.sxpath.IndependentContext;
|
||||
import net.sf.saxon.sxpath.XPathDynamicContext;
|
||||
import net.sf.saxon.sxpath.XPathEvaluator;
|
||||
import net.sf.saxon.sxpath.XPathExpression;
|
||||
import net.sf.saxon.sxpath.XPathVariable;
|
||||
import net.sf.saxon.trans.XPathException;
|
||||
import net.sf.saxon.value.BigDecimalValue;
|
||||
import net.sf.saxon.value.BooleanValue;
|
||||
import net.sf.saxon.value.EmptySequence;
|
||||
import net.sf.saxon.value.Int64Value;
|
||||
import net.sf.saxon.value.SequenceExtent;
|
||||
import net.sf.saxon.value.SequenceType;
|
||||
import net.sf.saxon.value.StringValue;
|
||||
|
||||
|
||||
/**
|
||||
@ -218,7 +200,7 @@ public class SaxonXPathRuleQuery {
|
||||
}
|
||||
|
||||
for (XPathFunctionDefinition xpathFun : xPathHandler.getRegisteredExtensionFunctions()) {
|
||||
ExtensionFunctionDefinition fun = convertAbstractXPathFunctionDefinition(xpathFun);
|
||||
ExtensionFunctionDefinition fun = new SaxonExtensionFunctionDefinitionAdapter(xpathFun);
|
||||
StructuredQName qname = fun.getFunctionQName();
|
||||
staticCtx.declareNamespace(qname.getPrefix(), qname.getURI());
|
||||
this.configuration.registerExtensionFunction(fun);
|
||||
@ -303,132 +285,4 @@ public class SaxonXPathRuleQuery {
|
||||
return local;
|
||||
}
|
||||
}
|
||||
|
||||
public static ExtensionFunctionDefinition convertAbstractXPathFunctionDefinition(XPathFunctionDefinition definition) {
|
||||
final SequenceType SINGLE_ELEMENT_SEQUENCE_TYPE = NodeKindTest.ELEMENT.one();
|
||||
|
||||
return new ExtensionFunctionDefinition() {
|
||||
private SequenceType convertToSequenceType(XPathFunctionDefinition.Type type) {
|
||||
switch (type) {
|
||||
case SINGLE_STRING: return SequenceType.SINGLE_STRING;
|
||||
case SINGLE_BOOLEAN: return SequenceType.SINGLE_BOOLEAN;
|
||||
case SINGLE_ELEMENT: return SINGLE_ELEMENT_SEQUENCE_TYPE;
|
||||
case SINGLE_INTEGER: return SequenceType.SINGLE_INTEGER;
|
||||
case STRING_SEQUENCE: return SequenceType.STRING_SEQUENCE;
|
||||
case OPTIONAL_STRING: return SequenceType.OPTIONAL_STRING;
|
||||
case OPTIONAL_DECIMAL: return SequenceType.OPTIONAL_DECIMAL;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Type " + type + " is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
private SequenceType[] convertToSequenceTypes(XPathFunctionDefinition.Type[] types) {
|
||||
SequenceType[] result = new SequenceType[types.length];
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
result[i] = convertToSequenceType(types[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructuredQName getFunctionQName() {
|
||||
QName qName = definition.getQName();
|
||||
return new StructuredQName(qName.getPrefix(), qName.getNamespaceURI(), qName.getLocalPart());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SequenceType[] getArgumentTypes() {
|
||||
return convertToSequenceTypes(definition.getArgumentTypes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
|
||||
return convertToSequenceType(definition.getResultType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dependsOnFocus() {
|
||||
return definition.dependsOnContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtensionFunctionCall makeCallExpression() {
|
||||
XPathFunctionDefinition.FunctionCall call = definition.makeCallExpression();
|
||||
return new ExtensionFunctionCall() {
|
||||
@Override
|
||||
public Expression rewrite(StaticContext context, Expression[] arguments) throws XPathException {
|
||||
Object[] convertedArguments = new Object[definition.getArgumentTypes().length];
|
||||
for (int i = 0; i < convertedArguments.length; i++) {
|
||||
if (arguments[i] instanceof StringLiteral) {
|
||||
convertedArguments[i] = ((StringLiteral) arguments[i]).getStringValue();
|
||||
}
|
||||
}
|
||||
try {
|
||||
call.staticInit(convertedArguments);
|
||||
} catch (XPathFunctionException e) {
|
||||
XPathException xPathException = new XPathException(e);
|
||||
xPathException.setIsStaticError(true);
|
||||
throw xPathException;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
|
||||
Node contextNode = null;
|
||||
if (definition.dependsOnContext()) {
|
||||
contextNode = XPathElementToNodeHelper.itemToNode(context.getContextItem());
|
||||
}
|
||||
Object[] convertedArguments = new Object[definition.getArgumentTypes().length];
|
||||
for (int i = 0; i < convertedArguments.length; i++) {
|
||||
switch (definition.getArgumentTypes()[i]) {
|
||||
case SINGLE_STRING:
|
||||
convertedArguments[i] = arguments[i].head().getStringValue();
|
||||
break;
|
||||
case SINGLE_ELEMENT:
|
||||
convertedArguments[i] = arguments[i].head();
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Don't know how to convert argument type " + definition.getArgumentTypes()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Object result = null;
|
||||
try {
|
||||
result = call.call(contextNode, convertedArguments);
|
||||
} catch (XPathFunctionException e) {
|
||||
throw new XPathException(e);
|
||||
}
|
||||
Sequence convertedResult = null;
|
||||
switch (definition.getResultType()) {
|
||||
case SINGLE_BOOLEAN:
|
||||
convertedResult = BooleanValue.get((Boolean) result);
|
||||
break;
|
||||
case SINGLE_INTEGER:
|
||||
convertedResult = Int64Value.makeIntegerValue((Integer) result);
|
||||
break;
|
||||
case SINGLE_STRING:
|
||||
convertedResult = new StringValue((String) result);
|
||||
break;
|
||||
case OPTIONAL_STRING:
|
||||
convertedResult = result != null ? new StringValue((String) result) : EmptyAtomicSequence.INSTANCE;
|
||||
break;
|
||||
case STRING_SEQUENCE:
|
||||
convertedResult = result != null ? new SequenceExtent(Arrays.stream((String[]) result).map(StringValue::new).collect(Collectors.toList()))
|
||||
: EmptySequence.getInstance();
|
||||
break;
|
||||
case OPTIONAL_DECIMAL:
|
||||
convertedResult = result != null && Double.isFinite((Double) result) ? new BigDecimalValue((Double) result)
|
||||
: EmptySequence.getInstance();
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Don't know how to convert result type " + definition.getResultType());
|
||||
}
|
||||
return convertedResult;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
package net.sourceforge.pmd.lang.java.rule.xpath.internal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
|
||||
import net.sourceforge.pmd.lang.java.ast.JavaComment;
|
||||
@ -47,10 +48,10 @@ public class GetCommentOnFunction extends BaseJavaXPathFunction {
|
||||
List<JavaComment> commentList = contextNode.getFirstParentOfType(ASTCompilationUnit.class).getComments();
|
||||
for (JavaComment comment : commentList) {
|
||||
if (comment.getBeginLine() == codeBeginLine || comment.getEndLine() == codeEndLine) {
|
||||
return comment.getText().toString();
|
||||
return Optional.of(comment.getText().toString());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return Optional.<String>empty();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.rule.xpath.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTModifierList;
|
||||
@ -43,9 +44,9 @@ public final class GetModifiersFun extends BaseJavaXPathFunction {
|
||||
ASTModifierList modList = ((AccessNode) contextNode).getModifiers();
|
||||
Set<JModifier> mods = explicit ? modList.getExplicitModifiers()
|
||||
: modList.getEffectiveModifiers();
|
||||
return CollectionUtil.map(mods, JModifier::getToken).toArray(new String[0]);
|
||||
return CollectionUtil.map(mods, JModifier::getToken);
|
||||
}
|
||||
return null;
|
||||
return Collections.<String>emptyList();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.rule.xpath.internal;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider;
|
||||
import net.sourceforge.pmd.lang.metrics.Metric;
|
||||
@ -61,7 +63,7 @@ public final class MetricFunction extends BaseJavaXPathFunction {
|
||||
}
|
||||
|
||||
|
||||
private static double getMetric(Node n, String metricKeyName) throws XPathFunctionException {
|
||||
private static Optional<Double> getMetric(Node n, String metricKeyName) throws XPathFunctionException {
|
||||
LanguageMetricsProvider provider =
|
||||
n.getAstInfo().getLanguageProcessor().services().getLanguageMetricsProvider();
|
||||
Metric<?, ?> metric = provider.getMetricWithName(metricKeyName);
|
||||
@ -70,7 +72,7 @@ public final class MetricFunction extends BaseJavaXPathFunction {
|
||||
}
|
||||
|
||||
Number computed = Metric.compute(metric, n, MetricOptions.emptyOptions());
|
||||
return computed == null ? Double.NaN : computed.doubleValue();
|
||||
return computed == null ? Optional.empty() : Optional.of(computed.doubleValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,8 +4,6 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.xml.rule;
|
||||
|
||||
import static net.sourceforge.pmd.lang.rule.xpath.internal.SaxonXPathRuleQuery.convertAbstractXPathFunctionDefinition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@ -21,6 +19,7 @@ import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.rule.xpath.impl.XPathFunctionDefinition;
|
||||
import net.sourceforge.pmd.lang.rule.xpath.impl.XPathHandler;
|
||||
import net.sourceforge.pmd.lang.rule.xpath.internal.DomainConversion;
|
||||
import net.sourceforge.pmd.lang.rule.xpath.internal.SaxonExtensionFunctionDefinitionAdapter;
|
||||
import net.sourceforge.pmd.lang.xml.ast.XmlNode;
|
||||
import net.sourceforge.pmd.lang.xml.ast.internal.XmlParserImpl.RootXmlNode;
|
||||
import net.sourceforge.pmd.properties.PropertyDescriptor;
|
||||
@ -82,7 +81,7 @@ final class SaxonDomXPathQuery {
|
||||
|
||||
|
||||
for (XPathFunctionDefinition xpathFun : xpathHandler.getRegisteredExtensionFunctions()) {
|
||||
ExtensionFunctionDefinition fun = convertAbstractXPathFunctionDefinition(xpathFun);
|
||||
ExtensionFunctionDefinition fun = new SaxonExtensionFunctionDefinitionAdapter(xpathFun);
|
||||
StructuredQName qname = fun.getFunctionQName();
|
||||
xpathStaticContext.declareNamespace(qname.getPrefix(), qname.getURI());
|
||||
this.configuration.registerExtensionFunction(fun);
|
||||
|
Loading…
x
Reference in New Issue
Block a user