diff --git a/java/src/main/java/io/cucumber/java/AbstractGlueDefinition.java b/java/src/main/java/io/cucumber/java/AbstractGlueDefinition.java index c17571d92f..149967421f 100644 --- a/java/src/main/java/io/cucumber/java/AbstractGlueDefinition.java +++ b/java/src/main/java/io/cucumber/java/AbstractGlueDefinition.java @@ -4,13 +4,14 @@ import io.cucumber.core.backend.Lookup; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import static java.util.Objects.requireNonNull; abstract class AbstractGlueDefinition implements Located { protected final Method method; - protected final Lookup lookup; + private final Lookup lookup; private String fullFormat; AbstractGlueDefinition(Method method, Lookup lookup) { @@ -34,4 +35,12 @@ private String getFullLocationLocation() { } return fullFormat; } + + final Object invokeMethod(Object... args) { + if (Modifier.isStatic(method.getModifiers())) { + return Invoker.invokeStatic(this, method, args); + } + return Invoker.invoke(this, lookup.getInstance(method.getDeclaringClass()), method, args); + } + } diff --git a/java/src/main/java/io/cucumber/java/Invoker.java b/java/src/main/java/io/cucumber/java/Invoker.java index f0ee76ad23..ba8d0da2fa 100644 --- a/java/src/main/java/io/cucumber/java/Invoker.java +++ b/java/src/main/java/io/cucumber/java/Invoker.java @@ -19,8 +19,16 @@ static Object invoke(Annotation annotation, Method expressionMethod) { return invoke(null, annotation, expressionMethod); } + static Object invokeStatic(Located located, Method method, Object... args) { + return doInvoke(located, null, method, args); + } + static Object invoke(Located located, Object target, Method method, Object... args) { Method targetMethod = targetMethod(target, method); + return doInvoke(located, target, targetMethod, args); + } + + private static Object doInvoke(Located located, Object target, Method targetMethod, Object[] args) { boolean accessible = targetMethod.isAccessible(); try { targetMethod.setAccessible(true); diff --git a/java/src/main/java/io/cucumber/java/JavaDataTableTypeDefinition.java b/java/src/main/java/io/cucumber/java/JavaDataTableTypeDefinition.java index c5fc8aec36..770f1dae17 100644 --- a/java/src/main/java/io/cucumber/java/JavaDataTableTypeDefinition.java +++ b/java/src/main/java/io/cucumber/java/JavaDataTableTypeDefinition.java @@ -71,28 +71,36 @@ private DataTableType createDataTableType(Method method) { if (DataTable.class.equals(parameterType)) { return new DataTableType( returnType, - (DataTable table) -> execute(replaceEmptyPatternsWithEmptyString(table)) + (DataTable table) -> invokeMethod( + replaceEmptyPatternsWithEmptyString(table) + ) ); } if (List.class.equals(parameterType)) { return new DataTableType( returnType, - (List row) -> execute(replaceEmptyPatternsWithEmptyString(row)) + (List row) -> invokeMethod( + replaceEmptyPatternsWithEmptyString(row) + ) ); } if (Map.class.equals(parameterType)) { return new DataTableType( returnType, - (Map entry) -> execute(replaceEmptyPatternsWithEmptyString(entry)) + (Map entry) -> invokeMethod( + replaceEmptyPatternsWithEmptyString(entry) + ) ); } if (String.class.equals(parameterType)) { return new DataTableType( returnType, - (String cell) -> execute(replaceEmptyPatternsWithEmptyString(cell)) + (String cell) -> invokeMethod( + replaceEmptyPatternsWithEmptyString(cell) + ) ); } @@ -104,8 +112,4 @@ public DataTableType dataTableType() { return dataTableType; } - private Object execute(Object arg) { - return Invoker.invoke(this, lookup.getInstance(method.getDeclaringClass()), method, arg); - } - } diff --git a/java/src/main/java/io/cucumber/java/JavaDefaultDataTableCellTransformerDefinition.java b/java/src/main/java/io/cucumber/java/JavaDefaultDataTableCellTransformerDefinition.java index abe5a28ff6..324c9c491c 100644 --- a/java/src/main/java/io/cucumber/java/JavaDefaultDataTableCellTransformerDefinition.java +++ b/java/src/main/java/io/cucumber/java/JavaDefaultDataTableCellTransformerDefinition.java @@ -16,7 +16,7 @@ class JavaDefaultDataTableCellTransformerDefinition extends AbstractDatatableEle JavaDefaultDataTableCellTransformerDefinition(Method method, Lookup lookup, String[] emptyPatterns) { super(requireValidMethod(method), lookup, emptyPatterns); this.transformer = (cellValue, toValueType) -> - execute(replaceEmptyPatternsWithEmptyString(cellValue), toValueType); + invokeMethod(replaceEmptyPatternsWithEmptyString(cellValue), toValueType); } private static Method requireValidMethod(Method method) { @@ -54,8 +54,4 @@ public TableCellByTypeTransformer tableCellByTypeTransformer() { return transformer; } - private Object execute(String fromValue, Type toValueType) { - return Invoker.invoke(this, lookup.getInstance(method.getDeclaringClass()), method, fromValue, toValueType); - } - } diff --git a/java/src/main/java/io/cucumber/java/JavaDefaultDataTableEntryTransformerDefinition.java b/java/src/main/java/io/cucumber/java/JavaDefaultDataTableEntryTransformerDefinition.java index b8e331a57f..a5004d425f 100644 --- a/java/src/main/java/io/cucumber/java/JavaDefaultDataTableEntryTransformerDefinition.java +++ b/java/src/main/java/io/cucumber/java/JavaDefaultDataTableEntryTransformerDefinition.java @@ -98,7 +98,7 @@ private Object execute(Map fromValue, Type toValueType, TableCel } else { args = new Object[]{fromValue, toValueType}; } - return Invoker.invoke(this, lookup.getInstance(method.getDeclaringClass()), method, args); + return invokeMethod(args); } } diff --git a/java/src/main/java/io/cucumber/java/JavaDocStringTypeDefinition.java b/java/src/main/java/io/cucumber/java/JavaDocStringTypeDefinition.java index a6d9f81f99..89684cf991 100644 --- a/java/src/main/java/io/cucumber/java/JavaDocStringTypeDefinition.java +++ b/java/src/main/java/io/cucumber/java/JavaDocStringTypeDefinition.java @@ -18,7 +18,7 @@ class JavaDocStringTypeDefinition extends AbstractGlueDefinition implements DocS this.docStringType = new DocStringType( this.method.getReturnType(), contentType.isEmpty() ? method.getName() : contentType, - this::execute + this::invokeMethod ); } @@ -50,11 +50,6 @@ private static InvalidMethodSignatureException createInvalidSignatureException(M .build(); } - - private Object execute(String content) { - return Invoker.invoke(this, lookup.getInstance(method.getDeclaringClass()), method, content); - } - @Override public DocStringType docStringType() { return docStringType; diff --git a/java/src/main/java/io/cucumber/java/JavaHookDefinition.java b/java/src/main/java/io/cucumber/java/JavaHookDefinition.java index 16ab34c112..00df4e7b52 100644 --- a/java/src/main/java/io/cucumber/java/JavaHookDefinition.java +++ b/java/src/main/java/io/cucumber/java/JavaHookDefinition.java @@ -13,13 +13,11 @@ final class JavaHookDefinition extends AbstractGlueDefinition implements HookDef private final String tagExpression; private final int order; - private final Lookup lookup; JavaHookDefinition(Method method, String tagExpression, int order, Lookup lookup) { super(requireValidMethod(method), lookup); this.tagExpression = requireNonNull(tagExpression, "tag-expression may not be null"); this.order = order; - this.lookup = lookup; } private static Method requireValidMethod(Method method) { @@ -58,7 +56,7 @@ public void execute(TestCaseState state) { args = new Object[0]; } - Invoker.invoke(this, lookup.getInstance(method.getDeclaringClass()), method, args); + invokeMethod(args); } @Override diff --git a/java/src/main/java/io/cucumber/java/JavaParameterTypeDefinition.java b/java/src/main/java/io/cucumber/java/JavaParameterTypeDefinition.java index c0dcd4b444..30354022f7 100644 --- a/java/src/main/java/io/cucumber/java/JavaParameterTypeDefinition.java +++ b/java/src/main/java/io/cucumber/java/JavaParameterTypeDefinition.java @@ -78,7 +78,7 @@ private Object execute(String[] captureGroups) { args = captureGroups; } - return Invoker.invoke(this, lookup.getInstance(method.getDeclaringClass()), method, args); + return invokeMethod(args); } } diff --git a/java/src/main/java/io/cucumber/java/JavaStepDefinition.java b/java/src/main/java/io/cucumber/java/JavaStepDefinition.java index c68de3599a..283d65467c 100644 --- a/java/src/main/java/io/cucumber/java/JavaStepDefinition.java +++ b/java/src/main/java/io/cucumber/java/JavaStepDefinition.java @@ -10,8 +10,8 @@ import static java.util.Objects.requireNonNull; final class JavaStepDefinition extends AbstractGlueDefinition implements StepDefinition { - private final String expression; + private final String expression; private final List parameterInfos; JavaStepDefinition(Method method, @@ -24,7 +24,7 @@ final class JavaStepDefinition extends AbstractGlueDefinition implements StepDef @Override public void execute(Object[] args) { - Invoker.invoke(this, lookup.getInstance(method.getDeclaringClass()), method, args); + invokeMethod(args); } @Override diff --git a/java/src/test/java/io/cucumber/java/JavaDataTableTypeDefinitionTest.java b/java/src/test/java/io/cucumber/java/JavaDataTableTypeDefinitionTest.java index 70d048ef79..3069dd0257 100644 --- a/java/src/test/java/io/cucumber/java/JavaDataTableTypeDefinitionTest.java +++ b/java/src/test/java/io/cucumber/java/JavaDataTableTypeDefinitionTest.java @@ -25,6 +25,13 @@ public T getInstance(Class glueClass) { } }; + private final Lookup lookupForStaticMethod = new Lookup() { + @Override + public T getInstance(Class glueClass) { + throw new IllegalArgumentException("should not be invoked"); + } + }; + private final DataTable dataTable = DataTable.create(asList( asList("a", "b"), asList("c", "d") @@ -172,4 +179,17 @@ public String converts_map_of_objects_to_string(Map entry) { return "converts_map_of_objects_to_string=" + entry; } + @Test + void static_methods_are_invoked_without_a_body() throws NoSuchMethodException { + Method method = JavaDataTableTypeDefinitionTest.class.getMethod("static_convert_data_table_to_string", DataTable.class); + JavaDataTableTypeDefinition definition = new JavaDataTableTypeDefinition(method, lookupForStaticMethod, new String[0]); + assertThat(definition.dataTableType().transform(dataTable.asLists()), is("static_convert_data_table_to_string=[[a, b], [c, d]]")); + } + + public static String static_convert_data_table_to_string(DataTable table) { + return "static_convert_data_table_to_string=" + table.cells(); + } + + + }