Skip to content

Commit 52f8f9e

Browse files
authored
Add support for Groovy-4-style range expressions (spockframework#1958)
fixes spockframework#1956
1 parent aa7651d commit 52f8f9e

File tree

3 files changed

+54
-5
lines changed

3 files changed

+54
-5
lines changed

spock-core/src/main/java/org/spockframework/compiler/ConditionRewriter.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@
2828
import org.spockframework.util.AbstractExpressionConverter;
2929
import org.spockframework.util.Assert;
3030
import org.spockframework.util.Identifiers;
31+
import org.spockframework.util.ReflectionUtil;
3132
import org.spockframework.util.TextUtil;
3233

34+
import java.lang.reflect.Constructor;
35+
import java.lang.reflect.Method;
3336
import java.util.ArrayList;
3437
import java.util.List;
3538
import java.util.regex.Pattern;
@@ -59,6 +62,9 @@
5962
public class ConditionRewriter extends AbstractExpressionConverter<Expression> implements GroovyCodeVisitorCompat {
6063
private static final Pattern COMMENTS_PATTERN = Pattern.compile("/\\*.*?\\*/|//.*$");
6164
private static final String THROWABLE = "$spock_condition_throwable";
65+
private static final Constructor<RangeExpression> RANGE_EXPRESSION_CONSTRUCTOR_GROOVY_4 = ReflectionUtil.getDeclaredConstructorBySignature(RangeExpression.class, Expression.class, Expression.class, Boolean.TYPE, Boolean.TYPE);
66+
private static final Method RANGE_EXPRESSION_IS_EXCLUSIVE_LEFT = ReflectionUtil.getDeclaredMethodBySignature(RangeExpression.class, "isExclusiveLeft");
67+
private static final Method RANGE_EXPRESSION_IS_EXCLUSIVE_RIGHT = ReflectionUtil.getDeclaredMethodBySignature(RangeExpression.class, "isExclusiveRight");
6268

6369
private final IRewriteResources resources;
6470

@@ -340,11 +346,20 @@ public void visitListExpression(ListExpression expr) {
340346

341347
@Override
342348
public void visitRangeExpression(RangeExpression expr) {
343-
RangeExpression conversion =
344-
new RangeExpression(
345-
convert(expr.getFrom()),
346-
convert(expr.getTo()),
347-
expr.isInclusive());
349+
RangeExpression conversion;
350+
if (RANGE_EXPRESSION_CONSTRUCTOR_GROOVY_4 != null) {
351+
conversion = ReflectionUtil.newInstance(RANGE_EXPRESSION_CONSTRUCTOR_GROOVY_4,
352+
convert(expr.getFrom()),
353+
convert(expr.getTo()),
354+
ReflectionUtil.invokeMethod(expr, RANGE_EXPRESSION_IS_EXCLUSIVE_LEFT),
355+
ReflectionUtil.invokeMethod(expr, RANGE_EXPRESSION_IS_EXCLUSIVE_RIGHT)
356+
);
357+
} else {
358+
conversion = new RangeExpression(
359+
convert(expr.getFrom()),
360+
convert(expr.getTo()),
361+
expr.isInclusive());
362+
}
348363

349364
conversion.setSourcePosition(expr);
350365
result = record(conversion);

spock-core/src/main/java/org/spockframework/util/ReflectionUtil.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,24 @@ public static Method getDeclaredMethodBySignature(Class<?> clazz, String name, C
153153
}
154154
}
155155

156+
@Nullable
157+
public static <T> Constructor<T> getConstructorBySignature(Class<T> clazz, Class<?>... parameterTypes) {
158+
try {
159+
return clazz.getConstructor(parameterTypes);
160+
} catch (NoSuchMethodException e) {
161+
return null;
162+
}
163+
}
164+
165+
@Nullable
166+
public static <T> Constructor<T> getDeclaredConstructorBySignature(Class<T> clazz, Class<?>... parameterTypes) {
167+
try {
168+
return clazz.getDeclaredConstructor(parameterTypes);
169+
} catch (NoSuchMethodException e) {
170+
return null;
171+
}
172+
}
173+
156174
/**
157175
* Returns the class file for the given class (which has been verified to exist in the returned location),
158176
* or null if the class file could not be found (e.g. because it is contained in a Jar).
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.spockframework.smoke.condition
2+
3+
import spock.lang.Issue
4+
import spock.lang.Specification
5+
6+
class ConditionG4Spec extends Specification {
7+
8+
@Issue("https://github.com/spockframework/spock/issues/1956")
9+
def "test range"() {
10+
expect:
11+
(0..5) == [0, 1, 2, 3, 4, 5]
12+
(0<..5) == [1, 2, 3, 4, 5]
13+
(0..<5) == [0, 1, 2, 3, 4]
14+
(0<..<5) == [1, 2, 3, 4]
15+
}
16+
}

0 commit comments

Comments
 (0)