Skip to content

Commit

Permalink
Add support for Groovy-4-style range expressions (spockframework#1958)
Browse files Browse the repository at this point in the history
  • Loading branch information
leonard84 authored May 20, 2024
1 parent aa7651d commit 52f8f9e
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@
import org.spockframework.util.AbstractExpressionConverter;
import org.spockframework.util.Assert;
import org.spockframework.util.Identifiers;
import org.spockframework.util.ReflectionUtil;
import org.spockframework.util.TextUtil;

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

private final IRewriteResources resources;

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

@Override
public void visitRangeExpression(RangeExpression expr) {
RangeExpression conversion =
new RangeExpression(
convert(expr.getFrom()),
convert(expr.getTo()),
expr.isInclusive());
RangeExpression conversion;
if (RANGE_EXPRESSION_CONSTRUCTOR_GROOVY_4 != null) {
conversion = ReflectionUtil.newInstance(RANGE_EXPRESSION_CONSTRUCTOR_GROOVY_4,
convert(expr.getFrom()),
convert(expr.getTo()),
ReflectionUtil.invokeMethod(expr, RANGE_EXPRESSION_IS_EXCLUSIVE_LEFT),
ReflectionUtil.invokeMethod(expr, RANGE_EXPRESSION_IS_EXCLUSIVE_RIGHT)
);
} else {
conversion = new RangeExpression(
convert(expr.getFrom()),
convert(expr.getTo()),
expr.isInclusive());
}

conversion.setSourcePosition(expr);
result = record(conversion);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,24 @@ public static Method getDeclaredMethodBySignature(Class<?> clazz, String name, C
}
}

@Nullable
public static <T> Constructor<T> getConstructorBySignature(Class<T> clazz, Class<?>... parameterTypes) {
try {
return clazz.getConstructor(parameterTypes);
} catch (NoSuchMethodException e) {
return null;
}
}

@Nullable
public static <T> Constructor<T> getDeclaredConstructorBySignature(Class<T> clazz, Class<?>... parameterTypes) {
try {
return clazz.getDeclaredConstructor(parameterTypes);
} catch (NoSuchMethodException e) {
return null;
}
}

/**
* Returns the class file for the given class (which has been verified to exist in the returned location),
* or null if the class file could not be found (e.g. because it is contained in a Jar).
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.spockframework.smoke.condition

import spock.lang.Issue
import spock.lang.Specification

class ConditionG4Spec extends Specification {

@Issue("https://github.com/spockframework/spock/issues/1956")
def "test range"() {
expect:
(0..5) == [0, 1, 2, 3, 4, 5]
(0<..5) == [1, 2, 3, 4, 5]
(0..<5) == [0, 1, 2, 3, 4]
(0<..<5) == [1, 2, 3, 4]
}
}

0 comments on commit 52f8f9e

Please sign in to comment.