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

Commit 2d48c87

Browse files
committed
Merge branch 'pr_36'
2 parents d8bbfdc + e2cee0e commit 2d48c87

File tree

3 files changed

+63
-14
lines changed

3 files changed

+63
-14
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ public interface ArgumentConstraint {
3737
*/
3838
int maxArity();
3939

40+
/**
41+
* @param n the number of arguments to check against minArity & maxArity
42+
* @return true if any of the arity constraint failed.
43+
*/
44+
boolean arityViolated(int n);
45+
4046
/**
4147
* @return a string representation of the types accepted. Used to construct
4248
* user friendly error messages.

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

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,38 @@ public final class ArgumentConstraints {
3535
private static final String EXPRESSION_TYPE = "expression";
3636

3737
/**
38-
* Describes a heterogenous list of arguments. Each argument is checked against
38+
* Describes a heterogeneous list of arguments. Each argument is checked against
3939
* the corresponding constraint. An {@link ArityException} will be thrown when
4040
* the number of arguments does not exactly match the number of constraints.
4141
* <p>
4242
* May only be used as a top level constraint – and is already built in to
4343
* {@link Function}, so direct usage of this method should not be needed.
4444
*/
4545
public static ArgumentConstraint listOf(ArgumentConstraint... constraints) {
46-
return new HeterogenousListOf(constraints);
46+
return new HeterogeneousListOf(constraints);
4747
}
4848

4949
/**
50-
* Descripes a homogenous list of arguments, of fixed or variable length.
50+
* Describes a homogeneous list of arguments, of fixed or variable length.
5151
* An {@link ArityException} will be thrown when there are fewer arguments
5252
* than the specified minimum arity, or when there are more arguments than
5353
* the specified maximum arity.
5454
* <p>
5555
* May only be used as a top level constraint.
5656
*/
5757
public static ArgumentConstraint listOf(int min, int max, ArgumentConstraint constraint) {
58-
return new HomogenousListOf(min, max, constraint);
58+
return new HomogeneousListOf(min, max, constraint);
59+
}
60+
61+
/**
62+
* Describes a homogeneous list of arguments without upper limit.
63+
* An {@link ArityException} will be thrown when there are fewer arguments
64+
* than the specified minimum arity.
65+
* <p>
66+
* May only be used as a top level constraint.
67+
*/
68+
public static ArgumentConstraint listOf(int min, ArgumentConstraint constraint) {
69+
return new VariadicListOf(min, constraint);
5970
}
6071

6172
/**
@@ -115,7 +126,7 @@ public BaseArgumentConstraint(int minArity, int maxArity, String expectedTypeDes
115126
this.expectedTypeDescription = expectedTypeDescription;
116127
}
117128

118-
protected <T> Iterator<ArgumentError> checkNoRemaingArguments(Iterator<FunctionArgument<T>> arguments, boolean expectNoRemainingArguments) {
129+
protected <T> Iterator<ArgumentError> checkNoRemainingArguments(Iterator<FunctionArgument<T>> arguments, boolean expectNoRemainingArguments) {
119130
if (expectNoRemainingArguments && arguments.hasNext()) {
120131
return singletonIterator(ArgumentError.createArityError());
121132
} else {
@@ -133,6 +144,9 @@ public int maxArity() {
133144
return maxArity;
134145
}
135146

147+
@Override
148+
public boolean arityViolated(int n) { return (n < minArity || maxArity < n); }
149+
136150
@Override
137151
public String expectedType() {
138152
return expectedTypeDescription;
@@ -147,10 +161,10 @@ protected <U> Iterator<U> emptyIterator() {
147161
}
148162
}
149163

150-
private static class HomogenousListOf extends BaseArgumentConstraint {
164+
private static class HomogeneousListOf extends BaseArgumentConstraint {
151165
private final ArgumentConstraint subConstraint;
152166

153-
public HomogenousListOf(int minArity, int maxArity, ArgumentConstraint subConstraint) {
167+
public HomogeneousListOf(int minArity, int maxArity, ArgumentConstraint subConstraint) {
154168
super(minArity, maxArity, subConstraint.expectedType());
155169
this.subConstraint = subConstraint;
156170
}
@@ -178,14 +192,14 @@ public <T> Iterator<ArgumentError> check(Adapter<T> runtime, Iterator<FunctionAr
178192
break;
179193
}
180194
}
181-
return checkNoRemaingArguments(arguments, expectNoRemainingArguments);
195+
return checkNoRemainingArguments(arguments, expectNoRemainingArguments);
182196
}
183197
}
184198

185-
private static class HeterogenousListOf extends BaseArgumentConstraint {
199+
private static class HeterogeneousListOf extends BaseArgumentConstraint {
186200
private final ArgumentConstraint[] subConstraints;
187201

188-
public HeterogenousListOf(ArgumentConstraint[] subConstraints) {
202+
public HeterogeneousListOf(ArgumentConstraint[] subConstraints) {
189203
super(calculateMinArity(subConstraints), calculateMaxArity(subConstraints), null);
190204
this.subConstraints = subConstraints;
191205
}
@@ -218,10 +232,39 @@ public <T> Iterator<ArgumentError> check(Adapter<T> runtime, Iterator<FunctionAr
218232
return singletonIterator(ArgumentError.createArityError());
219233
}
220234
}
221-
return checkNoRemaingArguments(arguments, expectNoRemainingArguments);
235+
return checkNoRemainingArguments(arguments, expectNoRemainingArguments);
236+
}
237+
}
238+
239+
private static class VariadicListOf extends BaseArgumentConstraint {
240+
private final ArgumentConstraint subConstraint;
241+
242+
public VariadicListOf(int minArity, ArgumentConstraint subConstraint) {
243+
super(minArity, -1, subConstraint.expectedType());
244+
this.subConstraint = subConstraint;
245+
}
246+
247+
@Override
248+
public <T> Iterator<ArgumentError> check(Adapter<T> runtime, Iterator<FunctionArgument<T>> arguments, boolean expectNoRemainingArguments) {
249+
int i = 0;
250+
for ( ;arguments.hasNext(); ++i) {
251+
Iterator<ArgumentError> error = subConstraint.check(runtime, arguments, false);
252+
if (error.hasNext()) {
253+
return error;
254+
}
255+
}
256+
if (i < minArity()) {
257+
return singletonIterator(ArgumentError.createArityError());
258+
} else {
259+
return emptyIterator();
260+
}
222261
}
262+
263+
@Override
264+
public boolean arityViolated(int n) { return n < minArity(); }
223265
}
224266

267+
225268
private static abstract class TypeCheck extends BaseArgumentConstraint {
226269
public TypeCheck(String expectedType) {
227270
super(1, 1, expectedType);
@@ -234,7 +277,7 @@ public <T> Iterator<ArgumentError> check(Adapter<T> runtime, Iterator<FunctionAr
234277
if (error.hasNext()) {
235278
return error;
236279
} else {
237-
return checkNoRemaingArguments(arguments, expectNoRemainingArguments);
280+
return checkNoRemainingArguments(arguments, expectNoRemainingArguments);
238281
}
239282
} else {
240283
return singletonIterator(ArgumentError.createArityError());
@@ -359,7 +402,7 @@ public <T> Iterator<ArgumentError> check(Adapter<T> runtime, Iterator<FunctionAr
359402
return singletonIterator((ArgumentError) ArgumentError.createArgumentTypeError(expectedType(), type.toString()));
360403
}
361404
}
362-
return checkNoRemaingArguments(arguments, expectNoRemainingArguments);
405+
return checkNoRemainingArguments(arguments, expectNoRemainingArguments);
363406
} else {
364407
return singletonIterator(ArgumentError.createArityError());
365408
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ public Node<T> visitFunctionExpression(JmesPathParser.FunctionExpressionContext
300300
errors.parseError(String.format("unknown function \"%s\"", name), token.getStartIndex());
301301
} else {
302302
ArgumentConstraint argumentConstraints = implementation.argumentConstraints();
303-
if (n < argumentConstraints.minArity() || n > argumentConstraints.maxArity()) {
303+
if (argumentConstraints.arityViolated(n)) {
304304
Token token = ctx.NAME().getSymbol();
305305
String message = ArityException.createMessage(implementation, n, false);
306306
errors.parseError(message, token.getStartIndex());

0 commit comments

Comments
 (0)