package cucumber.runtime.groovy; import cucumber.runtime.JdkPatternArgumentMatcher; import cucumber.runtime.ParameterInfo; import cucumber.runtime.StepDefinition; import cucumber.runtime.Timeout; import gherkin.I18n; import gherkin.formatter.Argument; import gherkin.formatter.model.Step; import groovy.lang.Closure; import org.codehaus.groovy.runtime.StackTraceUtils; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; public class GroovyStepDefinition implements StepDefinition { private final Pattern pattern; private final long timeoutMillis; private final Closure body; private final StackTraceElement location; private final GroovyBackend backend; private final JdkPatternArgumentMatcher argumentMatcher; private final List<ParameterInfo> parameterInfos; public GroovyStepDefinition(Pattern pattern, long timeoutMillis, Closure body, StackTraceElement location, GroovyBackend backend) { this.pattern = pattern; this.timeoutMillis = timeoutMillis; this.backend = backend; this.body = body; this.location = location; this.argumentMatcher = new JdkPatternArgumentMatcher(pattern); this.parameterInfos = getParameterInfos(); } public List<Argument> matchedArguments(Step step) { return argumentMatcher.argumentsFrom(step.getName()); } public String getLocation(boolean detail) { return location.getFileName() + ":" + location.getLineNumber(); } @Override public Integer getParameterCount() { return parameterInfos.size(); } @Override public ParameterInfo getParameterType(int n, Type argumentType) { return parameterInfos.get(n); } private List<ParameterInfo> getParameterInfos() { Class[] parameterTypes = body.getParameterTypes(); return ParameterInfo.fromTypes(parameterTypes); } public void execute(I18n i18n, final Object[] args) throws Throwable { try { Timeout.timeout(new Timeout.Callback<Object>() { @Override public Object call() throws Throwable { backend.invoke(body, args); return null; } }, timeoutMillis); } catch(Throwable e) { throw StackTraceUtils.deepSanitize(e); } } public boolean isDefinedAt(StackTraceElement stackTraceElement) { return location.getFileName().equals(stackTraceElement.getFileName()); } @Override public String getPattern() { return pattern.pattern(); } @Override public boolean isScenarioScoped() { return false; } }