diff --git a/java/pom.xml b/java/pom.xml index b2abcae776..c8acf99b45 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -17,16 +17,6 @@ io.cucumber cucumber-core - - info.cukes - cucumber-jvm-deps - provided - - - io.cucumber - gherkin - provided - io.cucumber diff --git a/java/src/main/java/cucumber/runtime/java/JavaBackend.java b/java/src/main/java/cucumber/runtime/java/JavaBackend.java index c23e942956..9f7909e611 100644 --- a/java/src/main/java/cucumber/runtime/java/JavaBackend.java +++ b/java/src/main/java/cucumber/runtime/java/JavaBackend.java @@ -1,18 +1,19 @@ package cucumber.runtime.java; +import static cucumber.runtime.io.MultiLoader.packageName; + import cucumber.api.java.After; import cucumber.api.java.Before; import cucumber.api.java.ObjectFactory; import cucumber.api.java8.GlueBase; -import cucumber.api.java8.HookBody; -import cucumber.api.java8.HookNoArgsBody; -import cucumber.api.java8.StepdefBody; import cucumber.runtime.Backend; import cucumber.runtime.ClassFinder; import cucumber.runtime.CucumberException; import cucumber.runtime.DuplicateStepDefinitionException; import cucumber.runtime.Env; import cucumber.runtime.Glue; +import cucumber.runtime.HookDefinition; +import cucumber.runtime.StepDefinition; import cucumber.runtime.UnreportedStepExecutor; import cucumber.runtime.Utils; import cucumber.runtime.io.MultiLoader; @@ -30,8 +31,6 @@ import java.util.List; import java.util.regex.Pattern; -import static cucumber.runtime.io.MultiLoader.packageName; - public class JavaBackend implements Backend { public static final ThreadLocal INSTANCE = new ThreadLocal(); private final SnippetGenerator snippetGenerator = new SnippetGenerator(createSnippet()); @@ -157,14 +156,8 @@ void addStepDefinition(Annotation annotation, Method method) { } } - public void addStepDefinition(String regexp, long timeoutMillis, StepdefBody body, TypeIntrospector typeIntrospector) { - try { - glue.addStepDefinition(new Java8StepDefinition(Pattern.compile(regexp), timeoutMillis, body, typeIntrospector)); - } catch (CucumberException e) { - throw e; - } catch (Exception e) { - throw new CucumberException(e); - } + public void addStepDefinition(StepDefinition stepDefinition) { + glue.addStepDefinition(stepDefinition); } void addHook(Annotation annotation, Method method) { @@ -181,20 +174,12 @@ void addHook(Annotation annotation, Method method) { } } - public void addBeforeHookDefinition(String[] tagExpressions, long timeoutMillis, int order, HookBody body) { - glue.addBeforeHook(new Java8HookDefinition(tagExpressions, order, timeoutMillis, body)); - } - - public void addAfterHookDefinition(String[] tagExpressions, long timeoutMillis, int order, HookBody body) { - glue.addAfterHook(new Java8HookDefinition(tagExpressions, order, timeoutMillis, body)); - } - - public void addBeforeHookDefinition(String[] tagExpressions, long timeoutMillis, int order, HookNoArgsBody body) { - glue.addBeforeHook(new Java8HookDefinition(tagExpressions, order, timeoutMillis, body)); + public void addBeforeHookDefinition(HookDefinition beforeHook) { + glue.addBeforeHook(beforeHook); } - public void addAfterHookDefinition(String[] tagExpressions, long timeoutMillis, int order, HookNoArgsBody body) { - glue.addAfterHook(new Java8HookDefinition(tagExpressions, order, timeoutMillis, body)); + public void addAfterHookDefinition(HookDefinition afterHook) { + glue.addAfterHook(afterHook); } private Pattern pattern(Annotation annotation) throws Throwable { diff --git a/java/src/main/java/cucumber/runtime/java/TypeIntrospector.java b/java/src/main/java/cucumber/runtime/java/TypeIntrospector.java deleted file mode 100644 index 549cf25965..0000000000 --- a/java/src/main/java/cucumber/runtime/java/TypeIntrospector.java +++ /dev/null @@ -1,9 +0,0 @@ -package cucumber.runtime.java; - -import cucumber.api.java8.StepdefBody; - -import java.lang.reflect.Type; - -public interface TypeIntrospector { - Type[] getGenericTypes(Class clazz, Class interfac3) throws Exception; -} diff --git a/java/src/test/java/cucumber/runtime/java/JavaHookTest.java b/java/src/test/java/cucumber/runtime/java/JavaHookTest.java index 64c7d09b76..136b9e682e 100644 --- a/java/src/test/java/cucumber/runtime/java/JavaHookTest.java +++ b/java/src/test/java/cucumber/runtime/java/JavaHookTest.java @@ -7,7 +7,6 @@ import cucumber.runtime.Glue; import cucumber.runtime.HookDefinition; import cucumber.runtime.RuntimeGlue; -import cucumber.runtime.UndefinedStepsTracker; import cucumber.runtime.xstream.LocalizedXStreams; import gherkin.pickles.PickleLocation; import gherkin.pickles.PickleTag; diff --git a/java/src/test/java/cucumber/runtime/java/java8test/AnonInnerClassStepdefs.java b/java/src/test/java/cucumber/runtime/java/java8test/AnonInnerClassStepdefs.java deleted file mode 100644 index f803b9b236..0000000000 --- a/java/src/test/java/cucumber/runtime/java/java8test/AnonInnerClassStepdefs.java +++ /dev/null @@ -1,20 +0,0 @@ -package cucumber.runtime.java.java8test; - -import cucumber.api.java8.GlueBase; -import cucumber.api.java8.StepdefBody; -import cucumber.runtime.java.JavaBackend; - -import static org.junit.Assert.assertEquals; - -public class AnonInnerClassStepdefs implements GlueBase { - - public AnonInnerClassStepdefs() { - JavaBackend.INSTANCE.get().addStepDefinition("^I have (\\d+) cukes in my (.*)", 0, new StepdefBody.A2() { - @Override - public void accept(Integer cukes, String what) throws Throwable { - assertEquals(42, cukes.intValue()); - assertEquals("belly", what); - } - }, null); - } -} diff --git a/java/src/test/java/cucumber/runtime/java/java8test/RunCukesTest.java b/java/src/test/java/cucumber/runtime/java/java8test/RunCukesTest.java deleted file mode 100644 index 2f989726a2..0000000000 --- a/java/src/test/java/cucumber/runtime/java/java8test/RunCukesTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package cucumber.runtime.java.java8test; - -import cucumber.api.CucumberOptions; -import cucumber.api.junit.Cucumber; -import org.junit.runner.RunWith; - -@RunWith(Cucumber.class) -@CucumberOptions(strict = true) -public class RunCukesTest { -} diff --git a/java8/pom.xml b/java8/pom.xml index 88f6b37a20..0175e25f0f 100644 --- a/java8/pom.xml +++ b/java8/pom.xml @@ -17,6 +17,10 @@ io.cucumber cucumber-java + + net.jodah + typetools + io.cucumber @@ -73,7 +77,7 @@ GherkinDialectProvider.DIALECTS.keySet().each { language -> def dialect = dialectProvider.getDialect(language, null) def normalized_language = dialect.language.replaceAll("[\\s-]", "_").toLowerCase() if (!unsupported.contains(normalized_language)) { - def templateSource = new File(project.baseDir, "src${File.separator}main${File.separator}code_generator${File.separator}I18n.java8.txt").getText() + def templateSource = new File(project.baseDir, "src${File.separator}main${File.separator}code_generator${File.separator}I18n.cucumber.runtime.java8.java8.txt").getText() def className = "${normalized_language}".capitalize() def binding = [ "i18n":dialect, "className":className ] def template = engine.createTemplate(templateSource).make(binding) diff --git a/java8/src/main/code_generator/I18n.java8.txt b/java8/src/main/code_generator/I18n.java8.txt index b67377b9db..4bb094fc41 100644 --- a/java8/src/main/code_generator/I18n.java8.txt +++ b/java8/src/main/code_generator/I18n.java8.txt @@ -1,28 +1,37 @@ package cucumber.api.java8; -import cucumber.runtime.java8.ConstantPoolTypeIntrospector; -import cucumber.runtime.java8.LambdaGlueBase; import cucumber.runtime.java.JavaBackend; +import cucumber.runtime.java8.Java8StepDefinition; +import cucumber.runtime.java8.LambdaGlueBase; public interface ${className} extends LambdaGlueBase { <% i18n.stepKeywords.findAll { !it.contains('*') && !it.matches("^\\d.*") }.sort().unique().each { kw -> %> default void ${java.text.Normalizer.normalize(kw.replaceAll("[\\s',!]", ""), java.text.Normalizer.Form.NFC)}(final String regexp, final StepdefBody.A0 body) { - JavaBackend.INSTANCE.get().addStepDefinition(regexp, 0, body, ConstantPoolTypeIntrospector.INSTANCE); + JavaBackend.INSTANCE.get().addStepDefinition( + new Java8StepDefinition(regexp, 0, StepdefBody.A0.class, body) + ); } default void ${java.text.Normalizer.normalize(kw.replaceAll("[\\s',!]", ""), java.text.Normalizer.Form.NFC)}(final String regexp, final long timeoutMillis, final StepdefBody.A0 body) { - JavaBackend.INSTANCE.get().addStepDefinition(regexp, timeoutMillis, body, ConstantPoolTypeIntrospector.INSTANCE); + JavaBackend.INSTANCE.get().addStepDefinition( + new Java8StepDefinition(regexp, timeoutMillis, StepdefBody.A0.class, body) + ); } <% (1..9).each { arity -> def ts = (1..arity).collect { n -> "T"+n } def genericSignature = ts.join(",") %> default <${genericSignature}> void ${java.text.Normalizer.normalize(kw.replaceAll("[\\s',!]", ""), java.text.Normalizer.Form.NFC)}(final String regexp, final StepdefBody.A${arity}<${genericSignature}> body) { - JavaBackend.INSTANCE.get().addStepDefinition(regexp, 0, body, ConstantPoolTypeIntrospector.INSTANCE); + JavaBackend.INSTANCE.get().addStepDefinition( + new Java8StepDefinition(regexp, 0, StepdefBody.A${arity}.class, body) + ); + } default <${genericSignature}> void ${java.text.Normalizer.normalize(kw.replaceAll("[\\s',!]", ""), java.text.Normalizer.Form.NFC)}(final String regexp, final long timeoutMillis, final StepdefBody.A${arity}<${genericSignature}> body) { - JavaBackend.INSTANCE.get().addStepDefinition(regexp, timeoutMillis, body, ConstantPoolTypeIntrospector.INSTANCE); + JavaBackend.INSTANCE.get().addStepDefinition( + new Java8StepDefinition(regexp, timeoutMillis, StepdefBody.A${arity}.class, body) + ); } <% } %> <% } %> diff --git a/java/src/main/java/cucumber/api/java8/HookBody.java b/java8/src/main/java/cucumber/api/java8/HookBody.java similarity index 100% rename from java/src/main/java/cucumber/api/java8/HookBody.java rename to java8/src/main/java/cucumber/api/java8/HookBody.java diff --git a/java/src/main/java/cucumber/api/java8/HookNoArgsBody.java b/java8/src/main/java/cucumber/api/java8/HookNoArgsBody.java similarity index 100% rename from java/src/main/java/cucumber/api/java8/HookNoArgsBody.java rename to java8/src/main/java/cucumber/api/java8/HookNoArgsBody.java diff --git a/java/src/main/java/cucumber/api/java8/StepdefBody.java b/java8/src/main/java/cucumber/api/java8/StepdefBody.java similarity index 100% rename from java/src/main/java/cucumber/api/java8/StepdefBody.java rename to java8/src/main/java/cucumber/api/java8/StepdefBody.java diff --git a/java8/src/main/java/cucumber/runtime/java8/ConstantPoolTypeIntrospector.java b/java8/src/main/java/cucumber/runtime/java8/ConstantPoolTypeIntrospector.java deleted file mode 100644 index 7f8aafc590..0000000000 --- a/java8/src/main/java/cucumber/runtime/java8/ConstantPoolTypeIntrospector.java +++ /dev/null @@ -1,102 +0,0 @@ -package cucumber.runtime.java8; - -import static java.lang.Class.forName; -import static java.lang.System.arraycopy; -import static jdk.internal.org.objectweb.asm.Type.getObjectType; - -import cucumber.api.java8.StepdefBody; -import cucumber.runtime.CucumberException; -import cucumber.runtime.java.TypeIntrospector; -import sun.reflect.ConstantPool; - -import java.lang.reflect.Method; -import java.lang.reflect.Type; - -public class ConstantPoolTypeIntrospector implements TypeIntrospector { - private static final Method Class_getConstantPool; - private static final int REFERENCE_CLASS = 0; - private static final int REFERENCE_METHOD = 1; - private static final int REFERENCE_ARGUMENT_TYPES = 2; - - static { - try { - Class_getConstantPool = Class.class.getDeclaredMethod("getConstantPool"); - Class_getConstantPool.setAccessible(true); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public static final TypeIntrospector INSTANCE = new ConstantPoolTypeIntrospector(); - - @Override - public Type[] getGenericTypes(Class clazz, Class interfac3) throws Exception { - final ConstantPool constantPool = (ConstantPool) Class_getConstantPool.invoke(clazz); - final String[] member = getMemberReference(constantPool); - final int parameterCount = interfac3.getTypeParameters().length; - - // Kotlin lambda expression without arguments or closure variables - if (member[REFERENCE_METHOD].equals("INSTANCE")) { - return handleKotlinInstance(); - } - - final jdk.internal.org.objectweb.asm.Type[] argumentTypes = jdk.internal.org.objectweb.asm.Type.getArgumentTypes(member[REFERENCE_ARGUMENT_TYPES]); - - // If we are one parameter short, this is a - // - Reference to an instance method of an arbitrary object of a particular type - if (parameterCount - 1 == argumentTypes.length) { - return handleMethodReferenceToObjectOfType(member[REFERENCE_CLASS], handleLambda(argumentTypes, parameterCount - 1)); - } - // If we are not short on parameters this either - // - Reference to a static method - // - Reference to an instance method of a particular object - // - Reference to a constructor - // - A lambda expression - // We can all treat these as lambda's for figuring out the types. - return handleLambda(argumentTypes, parameterCount); - } - - private static Type[] handleMethodReferenceToObjectOfType(String containingType, Type[] methodArgumentTypes) throws ClassNotFoundException { - Type[] containingTypeAndMethodArgumentTypes = new Type[methodArgumentTypes.length + 1]; - containingTypeAndMethodArgumentTypes[0] = forName(getObjectType(containingType).getClassName()); - arraycopy(methodArgumentTypes, 0, containingTypeAndMethodArgumentTypes, 1, methodArgumentTypes.length); - return containingTypeAndMethodArgumentTypes; - } - - private static Type[] handleLambda(jdk.internal.org.objectweb.asm.Type[] argumentTypes, int typeParameterCount) throws ClassNotFoundException { - if (argumentTypes.length < typeParameterCount) { - throw new CucumberException(String.format("Expected at least %s arguments but found only %s", typeParameterCount, argumentTypes.length)); - } - - // Only look at the N last arguments to the lambda static method, since the first ones might be variables - // who only pass in the states of closed variables - jdk.internal.org.objectweb.asm.Type[] interestingArgumentTypes = new jdk.internal.org.objectweb.asm.Type[typeParameterCount]; - arraycopy(argumentTypes, argumentTypes.length - typeParameterCount, interestingArgumentTypes, 0, typeParameterCount); - - Type[] typeArguments = new Type[typeParameterCount]; - for (int i = 0; i < typeParameterCount; i++) { - typeArguments[i] = forName(interestingArgumentTypes[i].getClassName()); - } - return typeArguments; - } - - private static Type[] handleKotlinInstance() { - return new Type[0]; - } - - private static String[] getMemberReference(ConstantPool constantPool) { - int size = constantPool.getSize(); - - // find last element in constantPool with valid memberRef - // - previously always at size-2 index but changed with JDK 1.8.0_60 - for (int i = size - 1; i > -1; i--) { - try { - return constantPool.getMemberRefInfoAt(i); - } catch (IllegalArgumentException e) { - // eat error; null entry at ConstantPool index? - } - } - throw new CucumberException("Couldn't find memberRef."); - } - -} diff --git a/java/src/main/java/cucumber/runtime/java/Java8HookDefinition.java b/java8/src/main/java/cucumber/runtime/java8/Java8HookDefinition.java similarity index 98% rename from java/src/main/java/cucumber/runtime/java/Java8HookDefinition.java rename to java8/src/main/java/cucumber/runtime/java8/Java8HookDefinition.java index a922e420f1..29562c9aa1 100644 --- a/java/src/main/java/cucumber/runtime/java/Java8HookDefinition.java +++ b/java8/src/main/java/cucumber/runtime/java8/Java8HookDefinition.java @@ -1,17 +1,17 @@ -package cucumber.runtime.java; +package cucumber.runtime.java8; + +import static java.util.Arrays.asList; import cucumber.api.Scenario; import cucumber.api.java8.HookBody; import cucumber.api.java8.HookNoArgsBody; import cucumber.runtime.HookDefinition; -import cucumber.runtime.Timeout; import cucumber.runtime.TagPredicate; +import cucumber.runtime.Timeout; import gherkin.pickles.PickleTag; import java.util.Collection; -import static java.util.Arrays.asList; - public class Java8HookDefinition implements HookDefinition { private final TagPredicate tagPredicate; private final int order; diff --git a/java/src/main/java/cucumber/runtime/java/Java8StepDefinition.java b/java8/src/main/java/cucumber/runtime/java8/Java8StepDefinition.java similarity index 67% rename from java/src/main/java/cucumber/runtime/java/Java8StepDefinition.java rename to java8/src/main/java/cucumber/runtime/java8/Java8StepDefinition.java index b88a34e90a..b25cc19cc4 100644 --- a/java/src/main/java/cucumber/runtime/java/Java8StepDefinition.java +++ b/java8/src/main/java/cucumber/runtime/java8/Java8StepDefinition.java @@ -1,4 +1,4 @@ -package cucumber.runtime.java; +package cucumber.runtime.java8; import cucumber.api.java8.StepdefBody; import cucumber.runtime.Argument; @@ -8,9 +8,9 @@ import cucumber.runtime.StepDefinition; import cucumber.runtime.Utils; import gherkin.pickles.PickleStep; +import net.jodah.typetools.TypeResolver; import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; @@ -19,7 +19,7 @@ public class Java8StepDefinition implements StepDefinition { - private final Pattern pattern; + private final String pattern; private final long timeoutMillis; private final StepdefBody body; @@ -29,34 +29,21 @@ public class Java8StepDefinition implements StepDefinition { private final List parameterInfos; private final Method method; - public Java8StepDefinition(Pattern pattern, long timeoutMillis, StepdefBody body, TypeIntrospector typeIntrospector) throws Exception { + public Java8StepDefinition(String pattern, long timeoutMillis, Class bodyClass, T body) { this.pattern = pattern; this.timeoutMillis = timeoutMillis; this.body = body; - this.argumentMatcher = new JdkPatternArgumentMatcher(pattern); + this.argumentMatcher = new JdkPatternArgumentMatcher(Pattern.compile(pattern)); this.location = new Exception().getStackTrace()[3]; - - Class bodyClass = body.getClass(); - - this.method = getAcceptMethod(bodyClass); - this.parameterInfos = getParameterInfos(bodyClass, typeIntrospector, method.getParameterTypes().length); - } - - private List getParameterInfos(Class bodyClass, TypeIntrospector typeIntrospector, int parameterCount) throws Exception { - Type genericInterface = bodyClass.getGenericInterfaces()[0]; - Type[] argumentTypes; - if (genericInterface instanceof ParameterizedType) { - argumentTypes = ((ParameterizedType) genericInterface).getActualTypeArguments(); - } else { - Class interfac3 = (Class) bodyClass.getInterfaces()[0]; - argumentTypes = typeIntrospector.getGenericTypes(bodyClass, interfac3); + this.method = getAcceptMethod(body.getClass()); + try { + this.parameterInfos = ParameterInfo.fromTypes(verifyNotListOrMap(TypeResolver.resolveRawArguments(bodyClass, body.getClass()))); + } catch (CucumberException e){ + throw e; + } catch (Exception e) { + throw new CucumberException(e); } - Type[] argumentTypesOfCorrectLength = new Type[parameterCount]; - System.arraycopy(argumentTypes, argumentTypes.length - parameterCount, argumentTypesOfCorrectLength, 0, parameterCount); - verifyNotListOrMap(argumentTypesOfCorrectLength); - - return ParameterInfo.fromTypes(argumentTypesOfCorrectLength); } private Method getAcceptMethod(Class bodyClass) { @@ -73,7 +60,7 @@ private Method getAcceptMethod(Class bodyClass) { return acceptMethods.get(0); } - private void verifyNotListOrMap(Type[] argumentTypes) { + private Type[] verifyNotListOrMap(Type[] argumentTypes) { for (Type argumentType : argumentTypes) { if (argumentType instanceof Class) { Class argumentClass = (Class) argumentType; @@ -82,6 +69,7 @@ private void verifyNotListOrMap(Type[] argumentTypes) { } } } + return argumentTypes; } private CucumberException withLocation(CucumberException exception) { @@ -121,7 +109,7 @@ public boolean isDefinedAt(StackTraceElement stackTraceElement) { @Override public String getPattern() { - return pattern.pattern(); + return pattern; } @Override diff --git a/java8/src/main/java/cucumber/runtime/java8/LambdaGlueBase.java b/java8/src/main/java/cucumber/runtime/java8/LambdaGlueBase.java index 3991307572..0478a3e7c4 100644 --- a/java8/src/main/java/cucumber/runtime/java8/LambdaGlueBase.java +++ b/java8/src/main/java/cucumber/runtime/java8/LambdaGlueBase.java @@ -13,82 +13,82 @@ public interface LambdaGlueBase extends GlueBase { int DEFAULT_AFTER_ORDER = 1000; default void Before(final HookBody body) { - JavaBackend.INSTANCE.get().addBeforeHookDefinition(EMPTY_TAG_EXPRESSIONS, NO_TIMEOUT, DEFAULT_BEFORE_ORDER, body); + JavaBackend.INSTANCE.get().addBeforeHookDefinition(new Java8HookDefinition(EMPTY_TAG_EXPRESSIONS, DEFAULT_BEFORE_ORDER, NO_TIMEOUT, body)); } default void Before(String[] tagExpressions, final HookBody body) { - JavaBackend.INSTANCE.get().addBeforeHookDefinition(tagExpressions, NO_TIMEOUT, DEFAULT_BEFORE_ORDER, body); + JavaBackend.INSTANCE.get().addBeforeHookDefinition(new Java8HookDefinition(tagExpressions, DEFAULT_BEFORE_ORDER, NO_TIMEOUT, body)); } default void Before(long timeoutMillis, final HookBody body) { - JavaBackend.INSTANCE.get().addBeforeHookDefinition(EMPTY_TAG_EXPRESSIONS, timeoutMillis, DEFAULT_BEFORE_ORDER, body); + JavaBackend.INSTANCE.get().addBeforeHookDefinition(new Java8HookDefinition(EMPTY_TAG_EXPRESSIONS, DEFAULT_BEFORE_ORDER, timeoutMillis, body)); } default void Before(int order, final HookBody body) { - JavaBackend.INSTANCE.get().addBeforeHookDefinition(EMPTY_TAG_EXPRESSIONS, NO_TIMEOUT, order, body); + JavaBackend.INSTANCE.get().addBeforeHookDefinition(new Java8HookDefinition(EMPTY_TAG_EXPRESSIONS, order, NO_TIMEOUT, body)); } default void Before(String[] tagExpressions, long timeoutMillis, int order, final HookBody body) { - JavaBackend.INSTANCE.get().addBeforeHookDefinition(tagExpressions, timeoutMillis, order, body); + JavaBackend.INSTANCE.get().addBeforeHookDefinition(new Java8HookDefinition(tagExpressions, order, timeoutMillis, body)); } default void Before(final HookNoArgsBody body) { - JavaBackend.INSTANCE.get().addBeforeHookDefinition(EMPTY_TAG_EXPRESSIONS, NO_TIMEOUT, DEFAULT_BEFORE_ORDER, body); + JavaBackend.INSTANCE.get().addBeforeHookDefinition(new Java8HookDefinition(EMPTY_TAG_EXPRESSIONS, DEFAULT_BEFORE_ORDER, NO_TIMEOUT, body)); } default void Before(String[] tagExpressions, final HookNoArgsBody body) { - JavaBackend.INSTANCE.get().addBeforeHookDefinition(tagExpressions, NO_TIMEOUT, DEFAULT_BEFORE_ORDER, body); + JavaBackend.INSTANCE.get().addBeforeHookDefinition(new Java8HookDefinition(tagExpressions, DEFAULT_BEFORE_ORDER, NO_TIMEOUT, body)); } default void Before(long timeoutMillis, final HookNoArgsBody body) { - JavaBackend.INSTANCE.get().addBeforeHookDefinition(EMPTY_TAG_EXPRESSIONS, timeoutMillis, DEFAULT_BEFORE_ORDER, body); + JavaBackend.INSTANCE.get().addBeforeHookDefinition(new Java8HookDefinition(EMPTY_TAG_EXPRESSIONS, DEFAULT_BEFORE_ORDER, timeoutMillis, body)); } default void Before(int order, final HookNoArgsBody body) { - JavaBackend.INSTANCE.get().addBeforeHookDefinition(EMPTY_TAG_EXPRESSIONS, NO_TIMEOUT, order, body); + JavaBackend.INSTANCE.get().addBeforeHookDefinition(new Java8HookDefinition(EMPTY_TAG_EXPRESSIONS, order, NO_TIMEOUT, body)); } default void Before(String[] tagExpressions, long timeoutMillis, int order, final HookNoArgsBody body) { - JavaBackend.INSTANCE.get().addBeforeHookDefinition(tagExpressions, timeoutMillis, order, body); + JavaBackend.INSTANCE.get().addBeforeHookDefinition(new Java8HookDefinition(tagExpressions, order, timeoutMillis, body)); } default void After(final HookBody body) { - JavaBackend.INSTANCE.get().addAfterHookDefinition(EMPTY_TAG_EXPRESSIONS, NO_TIMEOUT, DEFAULT_AFTER_ORDER, body); + JavaBackend.INSTANCE.get().addAfterHookDefinition(new Java8HookDefinition(EMPTY_TAG_EXPRESSIONS, DEFAULT_AFTER_ORDER, NO_TIMEOUT, body)); } default void After(String[] tagExpressions, final HookBody body) { - JavaBackend.INSTANCE.get().addAfterHookDefinition(tagExpressions, NO_TIMEOUT, DEFAULT_AFTER_ORDER, body); + JavaBackend.INSTANCE.get().addAfterHookDefinition(new Java8HookDefinition(tagExpressions, DEFAULT_AFTER_ORDER, NO_TIMEOUT, body)); } default void After(long timeoutMillis, final HookBody body) { - JavaBackend.INSTANCE.get().addAfterHookDefinition(EMPTY_TAG_EXPRESSIONS, timeoutMillis, DEFAULT_AFTER_ORDER, body); + JavaBackend.INSTANCE.get().addAfterHookDefinition(new Java8HookDefinition(EMPTY_TAG_EXPRESSIONS, DEFAULT_AFTER_ORDER, timeoutMillis, body)); } default void After(int order, final HookBody body) { - JavaBackend.INSTANCE.get().addAfterHookDefinition(EMPTY_TAG_EXPRESSIONS, NO_TIMEOUT, order, body); + JavaBackend.INSTANCE.get().addAfterHookDefinition(new Java8HookDefinition(EMPTY_TAG_EXPRESSIONS, order, NO_TIMEOUT, body)); } default void After(String[] tagExpressions, long timeoutMillis, int order, final HookBody body) { - JavaBackend.INSTANCE.get().addAfterHookDefinition(tagExpressions, timeoutMillis, order, body); + JavaBackend.INSTANCE.get().addAfterHookDefinition(new Java8HookDefinition(tagExpressions, order, timeoutMillis, body)); } default void After(final HookNoArgsBody body) { - JavaBackend.INSTANCE.get().addAfterHookDefinition(EMPTY_TAG_EXPRESSIONS, NO_TIMEOUT, DEFAULT_AFTER_ORDER, body); + JavaBackend.INSTANCE.get().addAfterHookDefinition(new Java8HookDefinition(EMPTY_TAG_EXPRESSIONS, DEFAULT_AFTER_ORDER, NO_TIMEOUT, body)); } default void After(String[] tagExpressions, final HookNoArgsBody body) { - JavaBackend.INSTANCE.get().addAfterHookDefinition(tagExpressions, NO_TIMEOUT, DEFAULT_AFTER_ORDER, body); + JavaBackend.INSTANCE.get().addAfterHookDefinition(new Java8HookDefinition(tagExpressions, DEFAULT_AFTER_ORDER, NO_TIMEOUT, body)); } default void After(long timeoutMillis, final HookNoArgsBody body) { - JavaBackend.INSTANCE.get().addAfterHookDefinition(EMPTY_TAG_EXPRESSIONS, timeoutMillis, DEFAULT_AFTER_ORDER, body); + JavaBackend.INSTANCE.get().addAfterHookDefinition(new Java8HookDefinition(EMPTY_TAG_EXPRESSIONS, DEFAULT_AFTER_ORDER, timeoutMillis, body)); } default void After(int order, final HookNoArgsBody body) { - JavaBackend.INSTANCE.get().addAfterHookDefinition(EMPTY_TAG_EXPRESSIONS, NO_TIMEOUT, order, body); + JavaBackend.INSTANCE.get().addAfterHookDefinition(new Java8HookDefinition(EMPTY_TAG_EXPRESSIONS, order, NO_TIMEOUT, body)); } default void After(String[] tagExpressions, long timeoutMillis, int order, final HookNoArgsBody body) { - JavaBackend.INSTANCE.get().addAfterHookDefinition(tagExpressions, timeoutMillis, order, body); + JavaBackend.INSTANCE.get().addAfterHookDefinition(new Java8HookDefinition(tagExpressions, order, timeoutMillis, body)); } } diff --git a/java/src/test/java/cucumber/runtime/java/Java8StepDefinitionTest.java b/java8/src/test/java/cucumber/runtime/java8/Java8AnonInnerClassStepDefinitionTest.java similarity index 66% rename from java/src/test/java/cucumber/runtime/java/Java8StepDefinitionTest.java rename to java8/src/test/java/cucumber/runtime/java8/Java8AnonInnerClassStepDefinitionTest.java index a56eecee6a..daf9f08308 100644 --- a/java/src/test/java/cucumber/runtime/java/Java8StepDefinitionTest.java +++ b/java8/src/test/java/cucumber/runtime/java8/Java8AnonInnerClassStepDefinitionTest.java @@ -1,33 +1,33 @@ -package cucumber.runtime.java; +package cucumber.runtime.java8; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; import cucumber.api.java8.StepdefBody; import cucumber.runtime.CucumberException; +import org.junit.Ignore; import org.junit.Test; import java.util.List; -import java.util.regex.Pattern; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; -public class Java8StepDefinitionTest { +public class Java8AnonInnerClassStepDefinitionTest { @Test public void should_calculate_parameters_count_from_body_with_one_param() throws Exception { - Java8StepDefinition java8StepDefinition = new Java8StepDefinition(Pattern.compile("^I have (\\d) some step (.*)$"), 0, oneParamStep(), null); - assertEquals(new Integer(1), java8StepDefinition.getParameterCount()); + Java8StepDefinition java8StepDefinition = new Java8StepDefinition("^I have (\\d) some step (.*)$", 0, StepdefBody.A1.class, oneParamStep()); + assertEquals(Integer.valueOf(1), java8StepDefinition.getParameterCount()); } @Test public void should_calculate_parameters_count_from_body_with_two_params() throws Exception { - Java8StepDefinition java8StepDefinition = new Java8StepDefinition(Pattern.compile("^I have some step $"), 0, twoParamStep(), null); - assertEquals(new Integer(2), java8StepDefinition.getParameterCount()); + Java8StepDefinition java8StepDefinition = new Java8StepDefinition("^I have some step $", 0, StepdefBody.A2.class, twoParamStep()); + assertEquals(Integer.valueOf(2), java8StepDefinition.getParameterCount()); } @Test public void should_fail_for_param_with_non_generic_list() throws Exception { try { - new Java8StepDefinition(Pattern.compile("^I have (\\d) some step (.*)$"), 0, nonGenericListStep(), null); + new Java8StepDefinition("^I have (\\d) some step (.*)$", 0, StepdefBody.A1.class, nonGenericListStep()); fail(); } catch (CucumberException expected) { assertEquals("Can't use java.util.List in lambda step definition. Declare a DataTable argument instead and convert manually with asList/asLists/asMap/asMaps", expected.getMessage()); @@ -35,12 +35,13 @@ public void should_fail_for_param_with_non_generic_list() throws Exception { } @Test + @Ignore public void should_pass_for_param_with_generic_list() throws Exception { - Java8StepDefinition java8StepDefinition = new Java8StepDefinition(Pattern.compile("^I have (\\d) some step (.*)$"), 0, genericListStep(), null); - assertEquals(new Integer(1), java8StepDefinition.getParameterCount()); + Java8StepDefinition java8StepDefinition = new Java8StepDefinition("^I have (\\d) some step (.*)$", 0, StepdefBody.A1.class, genericListStep()); + assertEquals(Integer.valueOf(1), java8StepDefinition.getParameterCount()); } - private StepdefBody oneParamStep() { + private StepdefBody.A1 oneParamStep() { return new StepdefBody.A1() { @Override public void accept(String p1) { @@ -48,7 +49,7 @@ public void accept(String p1) { }; } - private StepdefBody twoParamStep() { + private StepdefBody.A2 twoParamStep() { return new StepdefBody.A2() { @Override public void accept(String p1, String p2) { @@ -56,7 +57,7 @@ public void accept(String p1, String p2) { }; } - private StepdefBody genericListStep() { + private StepdefBody.A1 genericListStep() { return new StepdefBody.A1>() { @Override public void accept(List p1) { @@ -65,7 +66,7 @@ public void accept(List p1) { }; } - private StepdefBody nonGenericListStep() { + private StepdefBody.A1 nonGenericListStep() { return new StepdefBody.A1() { @Override public void accept(List p1) { diff --git a/java8/src/test/java/cucumber/runtime/java8/Java8LambdaStepDefinitionTest.java b/java8/src/test/java/cucumber/runtime/java8/Java8LambdaStepDefinitionTest.java new file mode 100644 index 0000000000..fbbf5ec136 --- /dev/null +++ b/java8/src/test/java/cucumber/runtime/java8/Java8LambdaStepDefinitionTest.java @@ -0,0 +1,51 @@ +package cucumber.runtime.java8; + +import cucumber.api.java8.StepdefBody; +import cucumber.runtime.CucumberException; +import org.junit.Test; + +import java.util.List; + +import static org.junit.Assert.assertEquals; + +public class Java8LambdaStepDefinitionTest { + + @Test + public void should_calculate_parameters_count_from_body_with_one_param() throws Exception { + StepdefBody.A1 body = (StepdefBody.A1) p1 -> { + }; + Java8StepDefinition def = new Java8StepDefinition("^I have (\\d) some step (.*)$", 0, StepdefBody.A1.class, body); + assertEquals(Integer.valueOf(1), def.getParameterCount()); + } + + @Test + public void should_calculate_parameters_count_from_body_with_two_params() throws Exception { + StepdefBody.A2 body = (StepdefBody.A2) (p1, p2) -> { + }; + Java8StepDefinition def = new Java8StepDefinition("^I have some step $", 0, StepdefBody.A2.class, body); + assertEquals(Integer.valueOf(2), def.getParameterCount()); + } + + @Test + public void should_fail_for_param_with_non_generic_list() throws Exception { + try { + StepdefBody.A1 body = (StepdefBody.A1) p1 -> { + }; + new Java8StepDefinition("^I have (\\d) some step (.*)$", 0, StepdefBody.A1.class, body); + } catch (CucumberException expected) { + assertEquals("Can't use java.util.List in lambda step definition. Declare a DataTable argument instead and convert manually with asList/asLists/asMap/asMaps", expected.getMessage()); + } + } + + @Test + public void should_pass_for_param_with_generic_list() throws Exception { + try { + StepdefBody.A1 body = (StepdefBody.A1>) p1 -> { + }; + new Java8StepDefinition("^I have (\\d) some step (.*)$", 0, StepdefBody.A1.class, body); + } catch (CucumberException expected) { + assertEquals("Can't use java.util.List in lambda step definition. Declare a DataTable argument instead and convert manually with asList/asLists/asMap/asMaps", expected.getMessage()); + } + } + +} diff --git a/java8/src/test/java/cucumber/runtime/java8/test/AnonInnerClassStepdefs.java b/java8/src/test/java/cucumber/runtime/java8/test/AnonInnerClassStepdefs.java new file mode 100644 index 0000000000..7025c13dfa --- /dev/null +++ b/java8/src/test/java/cucumber/runtime/java8/test/AnonInnerClassStepdefs.java @@ -0,0 +1,24 @@ +package cucumber.runtime.java8.test; + +import static org.junit.Assert.assertEquals; + +import cucumber.api.java8.GlueBase; +import cucumber.api.java8.StepdefBody; +import cucumber.runtime.java.JavaBackend; +import cucumber.runtime.java8.Java8StepDefinition; + +public class AnonInnerClassStepdefs implements GlueBase { + + public AnonInnerClassStepdefs() { + JavaBackend.INSTANCE.get().addStepDefinition( + new Java8StepDefinition( + "^I have (\\d+) java7 beans in my (.*)", 0, StepdefBody.A2.class, + new StepdefBody.A2() { + @Override + public void accept(Integer cukes, String what) throws Throwable { + assertEquals(42, cukes.intValue()); + assertEquals("belly", what); + } + })); + } +} diff --git a/java8/src/test/java/cucumber/runtime/java8/test/Java8StepDefinitionTest.java b/java8/src/test/java/cucumber/runtime/java8/test/Java8StepDefinitionTest.java deleted file mode 100644 index 7616cd6898..0000000000 --- a/java8/src/test/java/cucumber/runtime/java8/test/Java8StepDefinitionTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package cucumber.runtime.java8.test; - -import cucumber.api.java8.StepdefBody; -import cucumber.runtime.CucumberException; -import cucumber.runtime.java.Java8StepDefinition; -import cucumber.runtime.java.TypeIntrospector; -import cucumber.runtime.java8.ConstantPoolTypeIntrospector; -import org.junit.Test; - -import java.util.List; -import java.util.regex.Pattern; - -import static org.junit.Assert.assertEquals; - -public class Java8StepDefinitionTest { - private final TypeIntrospector typeIntrospector = new ConstantPoolTypeIntrospector(); - - @Test - public void should_calculate_parameters_count_from_body_with_one_param() throws Exception { - StepdefBody body = (StepdefBody.A1) p1 -> { - }; - Java8StepDefinition def = new Java8StepDefinition(Pattern.compile("^I have (\\d) some step (.*)$"), 0, body, typeIntrospector); - assertEquals(new Integer(1), def.getParameterCount()); - } - - @Test - public void should_calculate_parameters_count_from_body_with_two_params() throws Exception { - StepdefBody body = (StepdefBody.A2) (p1, p2) -> { - }; - Java8StepDefinition def = new Java8StepDefinition(Pattern.compile("^I have some step $"), 0, body, typeIntrospector); - assertEquals(new Integer(2), def.getParameterCount()); - } - - @Test - public void should_fail_for_param_with_non_generic_list() throws Exception { - try { - StepdefBody body = (StepdefBody.A1) p1 -> { - }; - new Java8StepDefinition(Pattern.compile("^I have (\\d) some step (.*)$"), 0, body, typeIntrospector); - } catch (CucumberException expected) { - assertEquals("Can't use java.util.List in lambda step definition. Declare a DataTable argument instead and convert manually with asList/asLists/asMap/asMaps", expected.getMessage()); - } - } - - @Test - public void should_pass_for_param_with_generic_list() throws Exception { - try { - StepdefBody body = (StepdefBody.A1>) p1 -> { - }; - new Java8StepDefinition(Pattern.compile("^I have (\\d) some step (.*)$"), 0, body, typeIntrospector); - } catch (CucumberException expected) { - assertEquals("Can't use java.util.List in lambda step definition. Declare a DataTable argument instead and convert manually with asList/asLists/asMap/asMaps", expected.getMessage()); - } - } - -} diff --git a/java/src/test/resources/cucumber/runtime/java/java8test/java8.feature b/java8/src/test/resources/cucumber/runtime/java8/test/anon-inner-class-step-definitions.feature similarity index 56% rename from java/src/test/resources/cucumber/runtime/java/java8test/java8.feature rename to java8/src/test/resources/cucumber/runtime/java8/test/anon-inner-class-step-definitions.feature index ab0f99c7d4..a5397dd88c 100644 --- a/java/src/test/resources/cucumber/runtime/java/java8test/java8.feature +++ b/java8/src/test/resources/cucumber/runtime/java8/test/anon-inner-class-step-definitions.feature @@ -1,3 +1,3 @@ Feature: Java8 Scenario: use the API with Java7 style - Given I have 42 cukes in my belly \ No newline at end of file + Given I have 42 java7 beans in my belly \ No newline at end of file diff --git a/java8/src/test/resources/cucumber/runtime/java8/test/java8.feature b/java8/src/test/resources/cucumber/runtime/java8/test/lambda-step-definitions.feature similarity index 100% rename from java8/src/test/resources/cucumber/runtime/java8/test/java8.feature rename to java8/src/test/resources/cucumber/runtime/java8/test/lambda-step-definitions.feature diff --git a/pom.xml b/pom.xml index 3e9e97d271..00d1dbe89c 100644 --- a/pom.xml +++ b/pom.xml @@ -77,6 +77,7 @@ 2.2.0 5.4.0 1.0.1 + 0.5.0 @@ -542,6 +543,11 @@ org.apache.felix.framework ${felix.version} + + net.jodah + typetools + ${typetools.version} +