Skip to content

Commit

Permalink
Replace inheritance with delegation for #138
Browse files Browse the repository at this point in the history
  • Loading branch information
aslakhellesoy committed Jan 14, 2012
1 parent 9379c6c commit b34455c
Show file tree
Hide file tree
Showing 26 changed files with 297 additions and 199 deletions.
@@ -1,13 +1,14 @@
package cucumber.runtime.clojure;

import clojure.lang.Compiler;
import clojure.lang.IFn;
import clojure.lang.RT;
import clojure.lang.Compiler;
import cucumber.io.Resource;
import cucumber.io.ResourceLoader;
import cucumber.runtime.Backend;
import cucumber.runtime.CucumberException;
import cucumber.runtime.World;
import cucumber.runtime.snippets.SnippetGenerator;
import gherkin.formatter.model.Step;

import java.io.IOException;
Expand All @@ -17,6 +18,7 @@

public class ClojureBackend implements Backend {
private static ClojureBackend instance;
private final SnippetGenerator snippetGenerator = new SnippetGenerator(new ClojureSnippet());
private final ResourceLoader resourceLoader;
private World world;

Expand Down Expand Up @@ -60,7 +62,7 @@ public void disposeWorld() {

@Override
public String getSnippet(Step step) {
return new ClojureSnippetGenerator(step).getSnippet();
return snippetGenerator.getSnippet(step);
}

private StackTraceElement stepDefLocation(String interpreterClassName, String interpreterMethodName) {
Expand Down
37 changes: 37 additions & 0 deletions clojure/src/main/java/cucumber/runtime/clojure/ClojureSnippet.java
@@ -0,0 +1,37 @@
package cucumber.runtime.clojure;

import cucumber.runtime.snippets.Snippet;

import java.util.List;

import static cucumber.runtime.snippets.SnippetGenerator.untypedArguments;

public class ClojureSnippet implements Snippet {
@Override
public String template() {
return "({0} #\"{1}\"\n" +
" (fn [{3}]\n" +
" \" {4}\n" + // TODO: The " should be a ', but that causes a propblem with MessageFormat escaping {4}. Need to read up on MessageFormat docs.
" ))\n";
}

@Override
public String arguments(List<Class<?>> argumentTypes) {
return untypedArguments(argumentTypes);
}

@Override
public String namedGroupStart() {
return null;
}

@Override
public String namedGroupEnd() {
return null;
}

@Override
public String escapePattern(String pattern) {
return pattern;
}
}

This file was deleted.

19 changes: 19 additions & 0 deletions core/src/main/java/cucumber/runtime/snippets/Snippet.java
@@ -0,0 +1,19 @@
package cucumber.runtime.snippets;

import java.util.List;

public interface Snippet {
String template();

String arguments(List<Class<?>> argumentTypes);

/**
* Langauges that don't support named capture groups should return null.
* @return the start of a named group
*/
String namedGroupStart();

String namedGroupEnd();

String escapePattern(String pattern);
}
42 changes: 9 additions & 33 deletions core/src/main/java/cucumber/runtime/snippets/SnippetGenerator.java
Expand Up @@ -21,7 +21,7 @@
* <li>{4} : Hint comment</li>
* </ul>
*/
public abstract class SnippetGenerator {
public final class SnippetGenerator {
private static final ArgumentPattern[] DEFAULT_ARGUMENT_PATTERNS = new ArgumentPattern[]{
new ArgumentPattern(Pattern.compile("\"([^\"]*)\""), String.class),
new ArgumentPattern(Pattern.compile("(\\d+)"), Integer.TYPE)
Expand All @@ -30,46 +30,22 @@ public abstract class SnippetGenerator {
private static final String HINT = "Express the Regexp above with the code you wish you had";
private static final Character SUBST = '_';

private final Step step;
private final String namedGroupStart;
private final String namedGroupEnd;

/**
* Constructor for languages that do not support named capture groups, such as Java.
*
* @param step the step to generate snippet for.
*/
protected SnippetGenerator(Step step) {
this(step, null, null);
}
private final Snippet snippet;

/**
* Constructor for langauges that support named capture groups, such ash Ioke.
*
* @param step the step to generate snippet for.
* @param namedGroupStart beginning of named group, for example "{arg".
* @param namedGroupEnd end of named group, for example "}".
*/
protected SnippetGenerator(Step step, String namedGroupStart, String namedGroupEnd) {
this.step = step;
this.namedGroupStart = namedGroupStart;
this.namedGroupEnd = namedGroupEnd;
public SnippetGenerator(Snippet snippet) {
this.snippet = snippet;
}

public String getSnippet() {
return MessageFormat.format(template(), I18n.codeKeywordFor(step.getKeyword()), patternFor(step.getName()), functionName(step.getName()), arguments(argumentTypes(step.getName())), HINT);
public String getSnippet(Step step) {
return MessageFormat.format(snippet.template(), I18n.codeKeywordFor(step.getKeyword()), snippet.escapePattern(patternFor(step.getName())), functionName(step.getName()), snippet.arguments(argumentTypes(step.getName())), HINT);
}

protected abstract String template();

protected abstract String arguments(List<Class<?>> argumentTypes);

protected String patternFor(String stepName) {
String pattern = stepName;
for (ArgumentPattern argumentPattern : argumentPatterns()) {
pattern = argumentPattern.replaceMatchesWithGroups(pattern);
}
if (namedGroupStart != null) {
if (snippet.namedGroupStart() != null) {
pattern = withNamedGroups(pattern);
}

Expand Down Expand Up @@ -107,7 +83,7 @@ private String withNamedGroups(String snippetPattern) {
StringBuffer sb = new StringBuffer();
int n = 1;
while (m.find()) {
m.appendReplacement(sb, "(" + namedGroupStart + n++ + namedGroupEnd);
m.appendReplacement(sb, "(" + snippet.namedGroupStart() + n++ + snippet.namedGroupEnd());
}
m.appendTail(sb);

Expand Down Expand Up @@ -149,7 +125,7 @@ protected ArgumentPattern[] argumentPatterns() {
return DEFAULT_ARGUMENT_PATTERNS;
}

protected String untypedArguments(List<Class<?>> argumentTypes) {
public static String untypedArguments(List<Class<?>> argumentTypes) {
StringBuilder sb = new StringBuilder();
for (int n = 0; n < argumentTypes.size(); n++) {
if (n > 0) {
Expand Down
28 changes: 20 additions & 8 deletions core/src/test/java/cucumber/runtime/UndefinedStepsTrackerTest.java
@@ -1,5 +1,6 @@
package cucumber.runtime;

import cucumber.runtime.snippets.Snippet;
import cucumber.runtime.snippets.SnippetGenerator;
import gherkin.formatter.model.Step;
import org.junit.Test;
Expand Down Expand Up @@ -62,23 +63,34 @@ public void disposeWorld() {

@Override
public String getSnippet(Step step) {
return new TestSnippetGenerator(step).getSnippet();
return new SnippetGenerator(new TestSnippet()).getSnippet(step);
}
}

private class TestSnippetGenerator extends SnippetGenerator {
protected TestSnippetGenerator(Step step) {
super(step);
}

private class TestSnippet implements Snippet {
@Override
protected String template() {
public String template() {
return "{0} {1}";
}

@Override
protected String arguments(List<Class<?>> argumentTypes) {
public String arguments(List<Class<?>> argumentTypes) {
return argumentTypes.toString();
}

@Override
public String namedGroupStart() {
return null;
}

@Override
public String namedGroupEnd() {
return null;
}

@Override
public String escapePattern(String pattern) {
return pattern;
}
}
}
Expand Up @@ -5,6 +5,7 @@
import cucumber.runtime.Backend;
import cucumber.runtime.CucumberException;
import cucumber.runtime.World;
import cucumber.runtime.snippets.SnippetGenerator;
import gherkin.TagExpression;
import gherkin.formatter.model.Step;
import groovy.lang.Binding;
Expand All @@ -21,6 +22,7 @@

public class GroovyBackend implements Backend {
static GroovyBackend instance;
private final SnippetGenerator snippetGenerator = new SnippetGenerator(new GroovySnippet());
private final ResourceLoader resourceLoader;
private final GroovyShell shell;
private Closure worldClosure;
Expand Down Expand Up @@ -73,7 +75,7 @@ public void disposeWorld() {

@Override
public String getSnippet(Step step) {
return new GroovySnippetGenerator(step).getSnippet();
return snippetGenerator.getSnippet(step);
}

public void addStepDefinition(Pattern regexp, Closure body) {
Expand Down
@@ -1,29 +1,19 @@
package cucumber.runtime.groovy;

import cucumber.runtime.snippets.SnippetGenerator;
import gherkin.formatter.model.Step;
import cucumber.runtime.snippets.Snippet;

import java.util.List;

public class GroovySnippetGenerator extends SnippetGenerator {
public GroovySnippetGenerator(Step step) {
super(step);
}

public class GroovySnippet implements Snippet {
@Override
protected String patternFor(String stepName) {
return super.patternFor(stepName).replaceAll("\"", "\\\\\"");
}

@Override
protected String template() {
public String template() {
return "{0}(~\"{1}\") '{' {3}->\n" +
" // {4}\n" +
"'}'\n";
}

@Override
protected String arguments(List<Class<?>> argumentTypes) {
public String arguments(List<Class<?>> argumentTypes) {
StringBuilder sb = new StringBuilder();
int n = 1;
for (Class<?> argType : argumentTypes) {
Expand All @@ -37,4 +27,19 @@ protected String arguments(List<Class<?>> argumentTypes) {
}
return sb.toString();
}

@Override
public String namedGroupStart() {
return null;
}

@Override
public String namedGroupEnd() {
return null;
}

@Override
public String escapePattern(String pattern) {
return pattern.replaceAll("\"", "\\\\\"");
}
}
4 changes: 3 additions & 1 deletion ioke/src/main/java/cucumber/runtime/ioke/IokeBackend.java
Expand Up @@ -5,6 +5,7 @@
import cucumber.runtime.Backend;
import cucumber.runtime.CucumberException;
import cucumber.runtime.World;
import cucumber.runtime.snippets.SnippetGenerator;
import cucumber.table.DataTable;
import gherkin.formatter.model.Step;
import ioke.lang.IokeObject;
Expand All @@ -17,6 +18,7 @@
import java.util.List;

public class IokeBackend implements Backend {
private final SnippetGenerator snippetGenerator = new SnippetGenerator(new IokeSnippet());
private final ResourceLoader resourceLoader;
private final Runtime ioke;
private final List<Runtime.RescueInfo> failureRescues;
Expand Down Expand Up @@ -65,7 +67,7 @@ public void disposeWorld() {

@Override
public String getSnippet(Step step) {
return new IokeSnippetGenerator(step).getSnippet();
return snippetGenerator.getSnippet(step);
}

public void addStepDefinition(Object iokeStepDefObject) throws Throwable {
Expand Down
35 changes: 35 additions & 0 deletions ioke/src/main/java/cucumber/runtime/ioke/IokeSnippet.java
@@ -0,0 +1,35 @@
package cucumber.runtime.ioke;

import cucumber.runtime.snippets.Snippet;

import java.util.List;

public class IokeSnippet implements Snippet {

@Override
public String template() {
return "{0}(#/{1}/,\n" +
" # {4}\n" +
")\n";
}

@Override
public String arguments(List<Class<?>> argumentTypes) {
return null; // not used
}

@Override
public String namedGroupStart() {
return "{arg";
}

@Override
public String namedGroupEnd() {
return "}";
}

@Override
public String escapePattern(String pattern) {
return pattern;
}
}

0 comments on commit b34455c

Please sign in to comment.