Skip to content
This repository was archived by the owner on Oct 31, 2024. It is now read-only.

Commit 8eeb9c8

Browse files
committed
Merge branch 'arity-error-at-compile-time'
2 parents 16a000c + e92c683 commit 8eeb9c8

File tree

8 files changed

+905
-269
lines changed

8 files changed

+905
-269
lines changed

jmespath-core/src/main/java/io/burt/jmespath/function/ArgumentConstraint.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,21 @@ public interface ArgumentConstraint {
1818
* @throws ArityException when there are not enough arguments left to satisfy the constraint
1919
* @throws ArgumentTypeException when an argument does not satisfy the constraint
2020
*/
21-
public <T> void check(Adapter<T> runtime, Iterator<FunctionArgument<T>> arguments);
21+
<T> void check(Adapter<T> runtime, Iterator<FunctionArgument<T>> arguments);
2222

2323
/**
2424
* @return the minimum number of arguments required.
2525
*/
26-
public int minArity();
26+
int minArity();
2727

2828
/**
2929
* @return the maximum number of arguments accepted.
3030
*/
31-
public int maxArity();
31+
int maxArity();
3232

3333
/**
3434
* @return a string representation of the types accepted. Used to construct
3535
* user friendly error messages.
3636
*/
37-
public String expectedType();
37+
String expectedType();
3838
}

jmespath-core/src/main/java/io/burt/jmespath/function/ArityException.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,31 @@
22

33
@SuppressWarnings("serial")
44
public class ArityException extends FunctionCallException {
5-
public ArityException(String functionName, int minArity, int maxArity, int numArguments) {
6-
this(functionName, minArity, maxArity, numArguments, null);
5+
public ArityException(Function function, int numArguments) {
6+
this(function, numArguments, null);
77
}
88

9-
public ArityException(String functionName, int minArity, int maxArity, int numArguments, Throwable cause) {
10-
super(createMessage(functionName, minArity, maxArity, numArguments), cause);
9+
public ArityException(Function function, int numArguments, Throwable cause) {
10+
super(createMessage(function, numArguments, true), cause);
1111
}
1212

13-
private static String createMessage(String functionName, int minArity, int maxArity, int numArguments) {
13+
public static String createMessage(Function function, int numArguments, boolean initialUppercase) {
14+
int minArity = function.argumentConstraints().minArity();
15+
int maxArity = function.argumentConstraints().maxArity();
16+
StringBuilder buffer = new StringBuilder();
17+
if (initialUppercase) {
18+
buffer.append("Invalid");
19+
} else {
20+
buffer.append("invalid");
21+
}
22+
buffer.append(" arity calling \"").append(function.name()).append("\"");
1423
if (maxArity == minArity) {
15-
return String.format("Invalid arity calling \"%s\": expected %d but was %d", functionName, minArity, numArguments);
24+
buffer.append(String.format(" (expected %d but was %d)", minArity, numArguments));
1625
} else if (numArguments < minArity) {
17-
return String.format("Invalid arity calling \"%s\": expected at least %d but was %d", functionName, minArity, numArguments);
26+
buffer.append(String.format(" (expected at least %d but was %d)", minArity, numArguments));
1827
} else {
19-
return String.format("Invalid arity calling \"%s\": expected at most %d but was %d", functionName, maxArity, numArguments);
28+
buffer.append(String.format(" (expected at most %d but was %d)", maxArity, numArguments));
2029
}
30+
return buffer.toString();
2131
}
2232
}

jmespath-core/src/main/java/io/burt/jmespath/function/BaseFunction.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ public String name() {
9898
return name;
9999
}
100100

101+
@Override
102+
public ArgumentConstraint argumentConstraints() {
103+
return argumentConstraints;
104+
}
105+
101106
/**
102107
* Call this function with a list of arguments.
103108
*
@@ -121,10 +126,10 @@ protected <T> void checkArguments(Adapter<T> runtime, List<FunctionArgument<T>>
121126
Iterator<FunctionArgument<T>> argumentIterator = arguments.iterator();
122127
argumentConstraints.check(runtime, argumentIterator);
123128
if (argumentIterator.hasNext()) {
124-
throw new ArityException(name(), argumentConstraints.minArity(), argumentConstraints.maxArity(), arguments.size());
129+
throw new ArityException(this, arguments.size());
125130
}
126131
} catch (ArgumentConstraints.InternalArityException e) {
127-
throw new ArityException(name(), argumentConstraints.minArity(), argumentConstraints.maxArity(), arguments.size(), e);
132+
throw new ArityException(this, arguments.size(), e);
128133
} catch (ArgumentConstraints.InternalArgumentTypeException e) {
129134
throw new ArgumentTypeException(name(), e.expectedType(), e.actualType(), e);
130135
}

jmespath-core/src/main/java/io/burt/jmespath/function/Function.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@ public interface Function {
1717
* The name is either automatically generated from the class name, or
1818
* explicitly specified in the constructor.
1919
*/
20-
public String name();
20+
String name();
21+
22+
/**
23+
* Returns the constraints to use when checking the list of arguments before
24+
* the function is called.
25+
*/
26+
ArgumentConstraint argumentConstraints();
2127

2228
/**
2329
* Call this function with a list of arguments.
@@ -28,5 +34,5 @@ public interface Function {
2834
* @throws ArgumentTypeException when the function is called with arguments of the wrong type
2935
* @throws ArityException when the function is called with the wrong number of arguments
3036
*/
31-
public <T> T call(Adapter<T> runtime, List<FunctionArgument<T>> arguments);
37+
<T> T call(Adapter<T> runtime, List<FunctionArgument<T>> arguments);
3238
}

jmespath-core/src/main/java/io/burt/jmespath/parser/ExpressionParser.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
import io.burt.jmespath.Expression;
1111
import io.burt.jmespath.Adapter;
1212
import io.burt.jmespath.function.Function;
13+
import io.burt.jmespath.function.ArgumentConstraint;
14+
import io.burt.jmespath.function.ArityException;
1315
import io.burt.jmespath.util.StringEscapeHelper;
1416
import io.burt.jmespath.util.AntlrHelper;
1517
import io.burt.jmespath.node.NodeFactory;
@@ -296,6 +298,13 @@ public Node<T> visitFunctionExpression(JmesPathParser.FunctionExpressionContext
296298
if (implementation == null) {
297299
Token token = ctx.NAME().getSymbol();
298300
errors.parseError(String.format("unknown function \"%s\"", name), token.getStartIndex());
301+
} else {
302+
ArgumentConstraint argumentConstraints = implementation.argumentConstraints();
303+
if (n < argumentConstraints.minArity() || n > argumentConstraints.maxArity()) {
304+
Token token = ctx.NAME().getSymbol();
305+
String message = ArityException.createMessage(implementation, n, false);
306+
errors.parseError(message, token.getStartIndex());
307+
}
299308
}
300309
return createSequenceIfChained(nodeFactory.createFunctionCall(implementation, args));
301310
}

0 commit comments

Comments
 (0)