From d364c4bd8e9d4cb974dd23a429cbc30e11fcfa8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aslak=20Helles=C3=B8y?= Date: Wed, 8 Mar 2017 10:08:18 +0000 Subject: [PATCH] API renames, based on feedback in https://github.com/cucumber/cucumber-js/pull/764 --- cucumber-expressions/CHANGELOG.md | 5 + .../AbstractParameter.java | 37 ----- .../AbstractParameterType.java | 37 +++++ .../cucumberexpressions/Argument.java | 8 +- .../cucumberexpressions/ArgumentBuilder.java | 10 +- .../cucumberexpressions/ClassParameter.java | 36 ----- .../ClassParameterType.java | 36 +++++ ...ter.java => ConstructorParameterType.java} | 6 +- .../CucumberExpression.java | 45 +++--- .../CucumberExpressionGenerator.java | 60 +++---- ...mParameter.java => EnumParameterType.java} | 4 +- .../ExpressionFactory.java | 20 +-- .../GeneratedExpression.java | 10 +- .../cucumberexpressions/NumberParser.java | 16 -- .../ParameterRegistry.java | 152 ------------------ .../{Parameter.java => ParameterType.java} | 6 +- ...Matcher.java => ParameterTypeMatcher.java} | 22 +-- .../ParameterTypeRegistry.java | 152 ++++++++++++++++++ .../RegularExpression.java | 28 ++-- .../cucumberexpressions/SimpleParameter.java | 23 --- .../SimpleParameterType.java | 23 +++ .../cucumberexpressions/TypeReference.java | 2 - ...java => ConstructorParameterTypeTest.java} | 10 +- .../CucumberExpressionGeneratorTest.java | 22 +-- .../CucumberExpressionPatternTest.java | 2 +- .../CucumberExpressionTest.java | 12 +- ...Test.java => CustomParameterTypeTest.java} | 42 ++--- .../cucumberexpressions/EnumFormatTest.java | 2 +- .../ExpressionExamplesTest.java | 6 +- .../ExpressionFactoryTest.java | 2 +- ...est.java => GenericParameterTypeTest.java} | 12 +- .../ParameterRegistryTest.java | 15 -- .../ParameterTypeRegistryTest.java | 15 ++ .../RegularExpressionTest.java | 10 +- cucumber-expressions/javascript/package.json | 2 +- .../javascript/src/argument.js | 6 +- .../javascript/src/build_arguments.js | 6 +- .../javascript/src/cucumber_expression.js | 36 ++--- .../src/cucumber_expression_generator.js | 52 +++--- .../javascript/src/generated_expression.js | 10 +- cucumber-expressions/javascript/src/index.js | 8 +- .../javascript/src/parameter.js | 31 ---- .../javascript/src/parameter_registry.js | 92 ----------- .../javascript/src/parameter_type.js | 32 ++++ ...r_matcher.js => parameter_type_matcher.js} | 20 +-- .../javascript/src/parameter_type_registry.js | 92 +++++++++++ .../javascript/src/regular_expression.js | 22 +-- .../cucumber_expression_generator_test.js | 22 +-- .../test/cucumber_expression_regexp_test.js | 4 +- .../test/cucumber_expression_test.js | 24 +-- ..._test.js => custom_parameter_type_test.js} | 58 +++---- .../test/expression_examples_test.js | 14 +- .../test/regular_expression_test.js | 12 +- .../cucumber/cucumber_expressions/argument.rb | 6 +- .../cucumber_expressions/argument_builder.rb | 6 +- .../cucumber_expression.rb | 40 ++--- .../cucumber_expression_generator.rb | 64 ++++---- .../generated_expression.rb | 6 +- .../cucumber_expressions/parameter.rb | 29 ---- .../parameter_registry.rb | 80 --------- .../cucumber_expressions/parameter_type.rb | 29 ++++ ...r_matcher.rb => parameter_type_matcher.rb} | 2 +- .../parameter_type_registry.rb | 80 +++++++++ .../regular_expression.rb | 20 +-- .../cucumber_expression_generator_spec.rb | 16 +- .../cucumber_expression_regexp_spec.rb | 4 +- .../cucumber_expression_spec.rb | 12 +- ..._spec.rb => custom_parameter_type_spec.rb} | 36 ++--- .../expression_examples_spec.rb | 6 +- .../regular_expression_spec.rb | 10 +- 70 files changed, 932 insertions(+), 945 deletions(-) delete mode 100644 cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/AbstractParameter.java create mode 100644 cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/AbstractParameterType.java delete mode 100644 cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ClassParameter.java create mode 100644 cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ClassParameterType.java rename cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/{ConstructorParameter.java => ConstructorParameterType.java} (88%) rename cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/{EnumParameter.java => EnumParameterType.java} (72%) delete mode 100644 cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ParameterRegistry.java rename cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/{Parameter.java => ParameterType.java} (72%) rename cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/{ParameterMatcher.java => ParameterTypeMatcher.java} (59%) create mode 100644 cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ParameterTypeRegistry.java delete mode 100644 cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/SimpleParameter.java create mode 100644 cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/SimpleParameterType.java rename cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/{ConstructorParameterTest.java => ConstructorParameterTypeTest.java} (81%) rename cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/{CustomParameterTest.java => CustomParameterTypeTest.java} (83%) rename cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/{GenericParameterTest.java => GenericParameterTypeTest.java} (65%) delete mode 100644 cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ParameterRegistryTest.java create mode 100644 cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ParameterTypeRegistryTest.java delete mode 100644 cucumber-expressions/javascript/src/parameter.js delete mode 100644 cucumber-expressions/javascript/src/parameter_registry.js create mode 100644 cucumber-expressions/javascript/src/parameter_type.js rename cucumber-expressions/javascript/src/{parameter_matcher.js => parameter_type_matcher.js} (52%) create mode 100644 cucumber-expressions/javascript/src/parameter_type_registry.js rename cucumber-expressions/javascript/test/{custom_parameter_test.js => custom_parameter_type_test.js} (75%) delete mode 100644 cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter.rb delete mode 100644 cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_registry.rb create mode 100644 cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_type.rb rename cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/{parameter_matcher.rb => parameter_type_matcher.rb} (96%) create mode 100644 cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_type_registry.rb rename cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/{custom_parameter_spec.rb => custom_parameter_type_spec.rb} (82%) diff --git a/cucumber-expressions/CHANGELOG.md b/cucumber-expressions/CHANGELOG.md index 86138a884e..711ebb95d4 100644 --- a/cucumber-expressions/CHANGELOG.md +++ b/cucumber-expressions/CHANGELOG.md @@ -15,6 +15,11 @@ N/A (by [aslakhellesoy]) ### Changed +* Renamed API: + * `Parameter -> ParameterType` + * `ParameterRegistry -> ParameterTypeRegistry` + * `addParameter -> defineParameterType` + * Stricter conflict checks when defining parameters ([#121](https://github.com/cucumber/cucumber/pull/121) by [aslakhellesoy]) diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/AbstractParameter.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/AbstractParameter.java deleted file mode 100644 index 349954120f..0000000000 --- a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/AbstractParameter.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.cucumber.cucumberexpressions; - -import java.lang.reflect.Type; -import java.util.List; - -import static java.util.Collections.singletonList; - -public abstract class AbstractParameter implements Parameter { - private final String typeName; - private final Type type; - private final List captureGroupRegexps; - - public AbstractParameter(String typeName, Type type, List captureGroupRegexps) { - this.captureGroupRegexps = captureGroupRegexps; - this.typeName = typeName; - this.type = type; - } - - public AbstractParameter(String typeName, Type type, String captureGroupRegexp) { - this(typeName, type, singletonList(captureGroupRegexp)); - } - - @Override - public String getTypeName() { - return typeName; - } - - @Override - public Type getType() { - return type; - } - - @Override - public List getCaptureGroupRegexps() { - return captureGroupRegexps; - } -} diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/AbstractParameterType.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/AbstractParameterType.java new file mode 100644 index 0000000000..c9fd8cbde5 --- /dev/null +++ b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/AbstractParameterType.java @@ -0,0 +1,37 @@ +package io.cucumber.cucumberexpressions; + +import java.lang.reflect.Type; +import java.util.List; + +import static java.util.Collections.singletonList; + +public abstract class AbstractParameterType implements ParameterType { + private final String typeName; + private final Type type; + private final List regexps; + + public AbstractParameterType(String name, Type type, List regexps) { + this.regexps = regexps; + this.typeName = name; + this.type = type; + } + + public AbstractParameterType(String typeName, Type type, String regexp) { + this(typeName, type, singletonList(regexp)); + } + + @Override + public String getName() { + return typeName; + } + + @Override + public Type getType() { + return type; + } + + @Override + public List getRegexps() { + return regexps; + } +} diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/Argument.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/Argument.java index 0ccb663fcd..b578db0024 100644 --- a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/Argument.java +++ b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/Argument.java @@ -3,12 +3,12 @@ public class Argument { private final int offset; private final String value; - private final Parameter parameter; + private final ParameterType parameterType; - public Argument(Integer offset, String value, Parameter parameter) { + public Argument(Integer offset, String value, ParameterType parameterType) { this.offset = offset; this.value = value; - this.parameter = parameter; + this.parameterType = parameterType; } public int getOffset() { @@ -20,6 +20,6 @@ public String getValue() { } public Object getTransformedValue() { - return parameter.transform(value); + return parameterType.transform(value); } } diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ArgumentBuilder.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ArgumentBuilder.java index 686ebdf759..a67b9fc584 100644 --- a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ArgumentBuilder.java +++ b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ArgumentBuilder.java @@ -6,19 +6,19 @@ import java.util.regex.Pattern; class ArgumentBuilder { - static List buildArguments(Pattern pattern, String text, List> parameters) { + static List buildArguments(Pattern pattern, String text, List> parameterTypes) { Matcher matcher = pattern.matcher(text); if (matcher.lookingAt()) { - if (matcher.groupCount() != parameters.size()) { - throw new RuntimeException(String.format("Expression has %s arguments, but there were %s parameters", matcher.groupCount(), parameters.size())); + if (matcher.groupCount() != parameterTypes.size()) { + throw new RuntimeException(String.format("Expression has %s arguments, but there were %s parameterTypes", matcher.groupCount(), parameterTypes.size())); } List arguments = new ArrayList<>(matcher.groupCount()); for (int i = 0; i < matcher.groupCount(); i++) { int startIndex = matcher.start(i + 1); String value = matcher.group(i + 1); - Parameter parameter = parameters.get(i); + ParameterType parameterType = parameterTypes.get(i); - arguments.add(new Argument(startIndex, value, parameter)); + arguments.add(new Argument(startIndex, value, parameterType)); } return arguments; } else { diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ClassParameter.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ClassParameter.java deleted file mode 100644 index 2bd118a012..0000000000 --- a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ClassParameter.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.cucumber.cucumberexpressions; - -import java.lang.reflect.Type; -import java.util.List; - -public class ClassParameter implements Parameter { - private final Parameter delegate; - - public ClassParameter(Class type) { - if (type.isEnum()) { - delegate = (Parameter) new EnumParameter<>((Class) type); - } else { - delegate = new ConstructorParameter<>(type); - } - } - - @Override - public String getTypeName() { - return delegate.getTypeName(); - } - - @Override - public Type getType() { - return delegate.getType(); - } - - @Override - public List getCaptureGroupRegexps() { - return delegate.getCaptureGroupRegexps(); - } - - @Override - public T transform(String value) { - return delegate.transform(value); - } -} diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ClassParameterType.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ClassParameterType.java new file mode 100644 index 0000000000..fdeaab7a5b --- /dev/null +++ b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ClassParameterType.java @@ -0,0 +1,36 @@ +package io.cucumber.cucumberexpressions; + +import java.lang.reflect.Type; +import java.util.List; + +public class ClassParameterType implements ParameterType { + private final ParameterType delegate; + + public ClassParameterType(Class type) { + if (type.isEnum()) { + delegate = (ParameterType) new EnumParameterType<>((Class) type); + } else { + delegate = new ConstructorParameterType<>(type); + } + } + + @Override + public String getName() { + return delegate.getName(); + } + + @Override + public Type getType() { + return delegate.getType(); + } + + @Override + public List getRegexps() { + return delegate.getRegexps(); + } + + @Override + public T transform(String value) { + return delegate.transform(value); + } +} diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ConstructorParameter.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ConstructorParameterType.java similarity index 88% rename from cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ConstructorParameter.java rename to cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ConstructorParameterType.java index c8f786d093..28b4ca4eaf 100644 --- a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ConstructorParameter.java +++ b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ConstructorParameterType.java @@ -5,11 +5,11 @@ import java.util.Collections; import java.util.List; -public class ConstructorParameter extends AbstractParameter { +public class ConstructorParameterType extends AbstractParameterType { private static final List ANYTHING_GOES = Collections.singletonList(".+"); private final Constructor constructor; - public ConstructorParameter(Class clazz) { + public ConstructorParameterType(Class clazz) { super(null, clazz, ANYTHING_GOES); try { this.constructor = clazz.getConstructor(String.class); @@ -21,7 +21,7 @@ public ConstructorParameter(Class clazz) { @Override public T transform(String value) { if (value == null) { - return (T)null; + return null; } try { return constructor.newInstance(value); diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/CucumberExpression.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/CucumberExpression.java index 39b79c6f78..5672f539cb 100644 --- a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/CucumberExpression.java +++ b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/CucumberExpression.java @@ -12,12 +12,11 @@ public class CucumberExpression implements Expression { private static final Pattern OPTIONAL_PATTERN = Pattern.compile("\\(([^)]+)\\)"); private static final Pattern ALTERNATIVE_WORD_REGEXP = Pattern.compile("([\\p{IsAlphabetic}]+)((/[\\p{IsAlphabetic}]+)+)"); - private final Pattern pattern; - private final List> parameters = new ArrayList<>(); + private final List> parameterTypes = new ArrayList<>(); private final String expression; - public CucumberExpression(String expression, List types, ParameterRegistry parameterRegistry) { + public CucumberExpression(String expression, List types, ParameterTypeRegistry parameterTypeRegistry) { this.expression = expression; expression = ESCAPE_PATTERN.matcher(expression).replaceAll("\\\\$1"); expression = OPTIONAL_PATTERN.matcher(expression).replaceAll("(?:$1)?"); @@ -36,32 +35,32 @@ public CucumberExpression(String expression, List types, Paramet int typeIndex = 0; while (matcher.find()) { String parameterName = matcher.group(1); - String typeName = matcher.group(3); - if (typeName != null) { - System.err.println(String.format("Cucumber expression parameter syntax {%s:%s} is deprecated. Please use {%s} instead.", parameterName, typeName, typeName)); + String parameterTypeName = matcher.group(3); + if (parameterTypeName != null) { + System.err.println(String.format("Cucumber expression parameter type syntax {%s:%s} is deprecated. Please use {%s} instead.", parameterName, parameterTypeName, parameterTypeName)); } Type type = types.size() <= typeIndex ? null : types.get(typeIndex++); - Parameter parameter = null; + ParameterType parameterType = null; if (type != null) { - parameter = parameterRegistry.lookupByType(type); + parameterType = parameterTypeRegistry.lookupByType(type); } - if (parameter == null && typeName != null) { - parameter = parameterRegistry.lookupByTypeName(typeName); + if (parameterType == null && parameterTypeName != null) { + parameterType = parameterTypeRegistry.lookupByTypeName(parameterTypeName); } - if (parameter == null) { - parameter = parameterRegistry.lookupByTypeName(parameterName); + if (parameterType == null) { + parameterType = parameterTypeRegistry.lookupByTypeName(parameterName); } - if (parameter == null && type != null && type instanceof Class) { - parameter = new ClassParameter<>((Class) type); + if (parameterType == null && type != null && type instanceof Class) { + parameterType = new ClassParameterType<>((Class) type); } - if (parameter == null) { - parameter = new ConstructorParameter<>(String.class); + if (parameterType == null) { + parameterType = new ConstructorParameterType<>(String.class); } - parameters.add(parameter); + parameterTypes.add(parameterType); - matcher.appendReplacement(regexp, Matcher.quoteReplacement(getCaptureGroupRegexp(parameter.getCaptureGroupRegexps()))); + matcher.appendReplacement(regexp, Matcher.quoteReplacement(getCaptureGroupRegexp(parameterType.getRegexps()))); } matcher.appendTail(regexp); regexp.append("$"); @@ -69,14 +68,14 @@ public CucumberExpression(String expression, List types, Paramet pattern = Pattern.compile(regexp.toString()); } - private String getCaptureGroupRegexp(List captureGroupRegexps) { + private String getCaptureGroupRegexp(List regexps) { StringBuilder sb = new StringBuilder("("); - if (captureGroupRegexps.size() == 1) { - sb.append(captureGroupRegexps.get(0)); + if (regexps.size() == 1) { + sb.append(regexps.get(0)); } else { boolean bar = false; - for (String captureGroupRegexp : captureGroupRegexps) { + for (String captureGroupRegexp : regexps) { if (bar) sb.append("|"); sb.append("(?:").append(captureGroupRegexp).append(")"); bar = true; @@ -89,7 +88,7 @@ private String getCaptureGroupRegexp(List captureGroupRegexps) { @Override public List match(String text) { - return ArgumentBuilder.buildArguments(pattern, text, parameters); + return ArgumentBuilder.buildArguments(pattern, text, parameterTypes); } @Override diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/CucumberExpressionGenerator.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/CucumberExpressionGenerator.java index c83a9797ac..fa9211063e 100644 --- a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/CucumberExpressionGenerator.java +++ b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/CucumberExpressionGenerator.java @@ -32,45 +32,45 @@ private static boolean isJavaKeyword(String keyword) { return (Arrays.binarySearch(JAVA_KEYWORDS, keyword, ENGLISH_COLLATOR) >= 0); } - private final ParameterRegistry parameterRegistry; + private final ParameterTypeRegistry parameterTypeRegistry; - public CucumberExpressionGenerator(ParameterRegistry parameterRegistry) { - this.parameterRegistry = parameterRegistry; + public CucumberExpressionGenerator(ParameterTypeRegistry parameterTypeRegistry) { + this.parameterTypeRegistry = parameterTypeRegistry; } public GeneratedExpression generateExpression(String text) { List parameterNames = new ArrayList<>(); - List parameterMatchers = createTransformMatchers(text); - List> parameters = new ArrayList<>(); + List parameterTypeMatchers = createParameterTypeMatchers(text); + List> parameterTypes = new ArrayList<>(); Map usageByTypeName = new HashMap<>(); StringBuilder expression = new StringBuilder(); int pos = 0; while (true) { - List matchingParameterMatchers = new ArrayList<>(); + List matchingParameterTypeMatchers = new ArrayList<>(); - for (ParameterMatcher parameterMatcher : parameterMatchers) { - ParameterMatcher advancedParameterMatcher = parameterMatcher.advanceTo(pos); - if (advancedParameterMatcher.find()) { - matchingParameterMatchers.add(advancedParameterMatcher); + for (ParameterTypeMatcher parameterTypeMatcher : parameterTypeMatchers) { + ParameterTypeMatcher advancedParameterTypeMatcher = parameterTypeMatcher.advanceTo(pos); + if (advancedParameterTypeMatcher.find()) { + matchingParameterTypeMatchers.add(advancedParameterTypeMatcher); } } - if (!matchingParameterMatchers.isEmpty()) { - Collections.sort(matchingParameterMatchers); - ParameterMatcher bestParameterMatcher = matchingParameterMatchers.get(0); - Parameter parameter = bestParameterMatcher.getParameter(); - parameters.add(parameter); + if (!matchingParameterTypeMatchers.isEmpty()) { + Collections.sort(matchingParameterTypeMatchers); + ParameterTypeMatcher bestParameterTypeMatcher = matchingParameterTypeMatchers.get(0); + ParameterType parameterType = bestParameterTypeMatcher.getParameterType(); + parameterTypes.add(parameterType); - String parameterName = getParameterName(parameter.getTypeName(), usageByTypeName); + String parameterName = getParameterName(parameterType.getName(), usageByTypeName); parameterNames.add(parameterName); expression - .append(text.substring(pos, bestParameterMatcher.start())) + .append(text.substring(pos, bestParameterTypeMatcher.start())) .append("{") - .append(parameter.getTypeName()) + .append(parameterType.getName()) .append("}"); - pos = bestParameterMatcher.start() + bestParameterMatcher.group().length(); + pos = bestParameterTypeMatcher.start() + bestParameterTypeMatcher.group().length(); } else { break; } @@ -80,7 +80,7 @@ public GeneratedExpression generateExpression(String text) { } } expression.append(text.substring(pos)); - return new GeneratedExpression(expression.toString(), parameterNames, parameters); + return new GeneratedExpression(expression.toString(), parameterNames, parameterTypes); } private String getParameterName(String typeName, Map usageByTypeName) { @@ -91,22 +91,22 @@ private String getParameterName(String typeName, Map usageByTyp return count == 1 && !isJavaKeyword(typeName) ? typeName : typeName + count; } - private List createTransformMatchers(String text) { - Collection> parameters = parameterRegistry.getParameters(); - List parameterMatchers = new ArrayList<>(); - for (Parameter parameter : parameters) { - parameterMatchers.addAll(createTransformMatchers(parameter, text)); + private List createParameterTypeMatchers(String text) { + Collection> parameterTypes = parameterTypeRegistry.getParameters(); + List parameterTypeMatchers = new ArrayList<>(); + for (ParameterType parameterType : parameterTypes) { + parameterTypeMatchers.addAll(createParameterTypeMatchers(parameterType, text)); } - return parameterMatchers; + return parameterTypeMatchers; } - private List createTransformMatchers(Parameter parameter, String text) { - List result = new ArrayList<>(); - List captureGroupRegexps = parameter.getCaptureGroupRegexps(); + private List createParameterTypeMatchers(ParameterType parameterType, String text) { + List result = new ArrayList<>(); + List captureGroupRegexps = parameterType.getRegexps(); for (String captureGroupRegexp : captureGroupRegexps) { Pattern regexp = Pattern.compile("(" + captureGroupRegexp + ")"); Matcher matcher = regexp.matcher(text); - result.add(new ParameterMatcher(parameter, matcher, text.length())); + result.add(new ParameterTypeMatcher(parameterType, matcher, text.length())); } return result; } diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/EnumParameter.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/EnumParameterType.java similarity index 72% rename from cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/EnumParameter.java rename to cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/EnumParameterType.java index 6c8ca01b8d..03535ea45d 100644 --- a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/EnumParameter.java +++ b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/EnumParameterType.java @@ -3,10 +3,10 @@ import java.util.Collections; import java.util.List; -public class EnumParameter> extends AbstractParameter { +public class EnumParameterType> extends AbstractParameterType { private static final List ANYTHING_GOES = Collections.singletonList(".+"); - public EnumParameter(Class enumClass) { + public EnumParameterType(Class enumClass) { super(null, enumClass, ANYTHING_GOES); } diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ExpressionFactory.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ExpressionFactory.java index c92451c09c..cb3ed8eef0 100644 --- a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ExpressionFactory.java +++ b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ExpressionFactory.java @@ -16,35 +16,35 @@ public class ExpressionFactory { private static final Pattern BEGIN_ANCHOR = Pattern.compile("^\\^.*"); private static final Pattern END_ANCHOR = Pattern.compile(".*\\$$"); private static final Pattern SCRIPT_STYLE_REGEXP = Pattern.compile("^/(.*)/$"); - private static final Pattern PARENS = Pattern.compile("\\(([^\\)]+)\\)"); + private static final Pattern PARENS = Pattern.compile("\\(([^)]+)\\)"); private static final Pattern ALPHA = Pattern.compile("[a-zA-Z]+"); - private final ParameterRegistry parameterRegistry; + private final ParameterTypeRegistry parameterTypeRegistry; - public ExpressionFactory(ParameterRegistry parameterRegistry) { - this.parameterRegistry = parameterRegistry; + public ExpressionFactory(ParameterTypeRegistry parameterTypeRegistry) { + this.parameterTypeRegistry = parameterTypeRegistry; } public Expression createExpression(String expressionString, List types) { Matcher m = BEGIN_ANCHOR.matcher(expressionString); if (m.find()) { - return new RegularExpression(Pattern.compile(expressionString), types, parameterRegistry); + return new RegularExpression(Pattern.compile(expressionString), types, parameterTypeRegistry); } m = END_ANCHOR.matcher(expressionString); if (m.find()) { - return new RegularExpression(Pattern.compile(expressionString), types, parameterRegistry); + return new RegularExpression(Pattern.compile(expressionString), types, parameterTypeRegistry); } m = SCRIPT_STYLE_REGEXP.matcher(expressionString); if (m.find()) { - return new RegularExpression(Pattern.compile(m.group(1)), types, parameterRegistry); + return new RegularExpression(Pattern.compile(m.group(1)), types, parameterTypeRegistry); } m = PARENS.matcher(expressionString); if (m.find()) { String insideParens = m.group(1); if (ALPHA.matcher(insideParens).lookingAt()) { - return new CucumberExpression(expressionString, types, parameterRegistry); + return new CucumberExpression(expressionString, types, parameterTypeRegistry); } - return new RegularExpression(Pattern.compile(expressionString), types, parameterRegistry); + return new RegularExpression(Pattern.compile(expressionString), types, parameterTypeRegistry); } - return new CucumberExpression(expressionString, types, parameterRegistry); + return new CucumberExpression(expressionString, types, parameterTypeRegistry); } } diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/GeneratedExpression.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/GeneratedExpression.java index b20aff4b9b..3fb3711b8d 100644 --- a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/GeneratedExpression.java +++ b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/GeneratedExpression.java @@ -5,12 +5,12 @@ public class GeneratedExpression { private final String expression; private final List parameterNames; - private final List> parameters; + private final List> parameterTypes; - public GeneratedExpression(String expression, List parameterNames, List> parameters) { + public GeneratedExpression(String expression, List parameterNames, List> parameterTypes) { this.expression = expression; this.parameterNames = parameterNames; - this.parameters = parameters; + this.parameterTypes = parameterTypes; } public String getSource() { @@ -21,7 +21,7 @@ public List getParameterNames() { return parameterNames; } - public List> getParameters() { - return parameters; + public List> getParameterTypes() { + return parameterTypes; } } diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/NumberParser.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/NumberParser.java index e9d63c1f29..531883911f 100644 --- a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/NumberParser.java +++ b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/NumberParser.java @@ -18,22 +18,6 @@ float parseFloat(String s) { return parse(s).floatValue(); } - byte parseByte(String s) { - return parse(s).byteValue(); - } - - int parseInt(String s) { - return parse(s).intValue(); - } - - long parseLong(String s) { - return parse(s).longValue(); - } - - short parseShort(String s) { - return parse(s).shortValue(); - } - private Number parse(String s) { try { return numberFormat.parse(s); diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ParameterRegistry.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ParameterRegistry.java deleted file mode 100644 index 49c057e98c..0000000000 --- a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ParameterRegistry.java +++ /dev/null @@ -1,152 +0,0 @@ -package io.cucumber.cucumberexpressions; - -import java.lang.reflect.Type; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.text.NumberFormat; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import static java.util.Arrays.asList; - -public class ParameterRegistry { - private static final List INTEGER_REGEXPS = asList("-?\\d+", "\\d+"); - private static final String FLOAT_REGEXP = "-?\\d*[\\.,]\\d+"; - private static final String HEX_REGEXP = "0[xX][0-9a-fA-F]{2}"; - - private Map> parametersByType = new HashMap<>(); - private Map> parametersByTypeName = new HashMap<>(); - private Map> parametersByCaptureGroupRegexp = new HashMap<>(); - - public ParameterRegistry(Locale locale) { - NumberFormat numberFormat = NumberFormat.getNumberInstance(locale); - final NumberParser numberParser = new NumberParser(numberFormat); - - addPredefinedParameter(new SimpleParameter<>("bigint", BigInteger.class, INTEGER_REGEXPS, new Function() { - @Override - public BigInteger apply(String s) { - return new BigInteger(s); - } - })); - addPredefinedParameter(new SimpleParameter<>("bigdecimal", BigDecimal.class, INTEGER_REGEXPS, new Function() { - @Override - public BigDecimal apply(String s) { - return new BigDecimal(s); - } - })); - addPredefinedParameter(new SimpleParameter<>("byte", byte.class, HEX_REGEXP, new Function() { - @Override - public Byte apply(String s) { - return Byte.decode(s); - } - })); - addPredefinedParameter(new SimpleParameter<>("byte", Byte.class, HEX_REGEXP, new Function() { - @Override - public Byte apply(String s) { - return Byte.decode(s); - } - })); - addPredefinedParameter(new SimpleParameter<>("short", short.class, INTEGER_REGEXPS, new Function() { - @Override - public Short apply(String s) { - return Short.decode(s); - } - })); - addPredefinedParameter(new SimpleParameter<>("short", Short.class, INTEGER_REGEXPS, new Function() { - @Override - public Short apply(String s) { - return Short.decode(s); - } - })); - addPredefinedParameter(new SimpleParameter<>("int", int.class, INTEGER_REGEXPS, new Function() { - @Override - public Integer apply(String s) { - return Integer.decode(s); - } - })); - addPredefinedParameter(new SimpleParameter<>("int", Integer.class, INTEGER_REGEXPS, new Function() { - @Override - public Integer apply(String s) { - return Integer.decode(s); - } - })); - addPredefinedParameter(new SimpleParameter<>("long", long.class, INTEGER_REGEXPS, new Function() { - @Override - public Long apply(String s) { - return Long.decode(s); - } - })); - addPredefinedParameter(new SimpleParameter<>("long", Long.class, INTEGER_REGEXPS, new Function() { - @Override - public Long apply(String s) { - return Long.decode(s); - } - })); - addPredefinedParameter(new SimpleParameter<>("float", float.class, FLOAT_REGEXP, new Function() { - @Override - public Float apply(String s) { - return numberParser.parseFloat(s); - } - })); - addPredefinedParameter(new SimpleParameter<>("float", Float.class, FLOAT_REGEXP, new Function() { - @Override - public Float apply(String s) { - return numberParser.parseFloat(s); - } - })); - addPredefinedParameter(new SimpleParameter<>("double", double.class, FLOAT_REGEXP, new Function() { - @Override - public Double apply(String s) { - return numberParser.parseDouble(s); - } - })); - addPredefinedParameter(new SimpleParameter<>("double", Double.class, FLOAT_REGEXP, new Function() { - @Override - public Double apply(String s) { - return numberParser.parseDouble(s); - } - })); - } - - public void addParameter(Parameter parameter) { - addParameter0(parameter, true); - } - - private void addPredefinedParameter(Parameter parameter) { - addParameter0(parameter, false); - } - - private void addParameter0(Parameter parameter, boolean checkConflicts) { - put(parametersByType, parameter.getType(), parameter, "type", parameter.getType().getTypeName(), checkConflicts); - put(parametersByTypeName, parameter.getTypeName(), parameter, "type name", parameter.getTypeName(), checkConflicts); - - for (String captureGroupRegexp : parameter.getCaptureGroupRegexps()) { - put(parametersByCaptureGroupRegexp, captureGroupRegexp, parameter, "regexp", captureGroupRegexp, checkConflicts); - } - } - - private void put(Map> map, K key, Parameter parameter, String prop, String keyName, boolean checkConflicts) { - if (checkConflicts && map.containsKey(key)) - throw new RuntimeException(String.format("There is already a parameter with %s %s", prop, keyName)); - map.put(key, parameter); - } - - public Parameter lookupByType(Type type) { - return (Parameter) parametersByType.get(type); - } - - public Parameter lookupByTypeName(String typeName) { - return (Parameter) parametersByTypeName.get(typeName); - } - - public Parameter lookupByCaptureGroupRegexp(String captureGroupPattern) { - return (Parameter) parametersByCaptureGroupRegexp.get(captureGroupPattern); - } - - public Collection> getParameters() { - return parametersByType.values(); - } -} diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/Parameter.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ParameterType.java similarity index 72% rename from cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/Parameter.java rename to cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ParameterType.java index 53470986eb..4707479a40 100644 --- a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/Parameter.java +++ b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ParameterType.java @@ -3,17 +3,17 @@ import java.lang.reflect.Type; import java.util.List; -public interface Parameter { +public interface ParameterType { /** * This is used in the type name in typed expressions * @return human readable type name */ - String getTypeName(); + String getName(); Type getType(); - List getCaptureGroupRegexps(); + List getRegexps(); T transform(String value); } diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ParameterMatcher.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ParameterTypeMatcher.java similarity index 59% rename from cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ParameterMatcher.java rename to cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ParameterTypeMatcher.java index 72bd1f3d20..68ee74e418 100644 --- a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ParameterMatcher.java +++ b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ParameterTypeMatcher.java @@ -2,19 +2,19 @@ import java.util.regex.Matcher; -class ParameterMatcher implements Comparable { - private final Parameter parameter; +class ParameterTypeMatcher implements Comparable { + private final ParameterType parameterType; private final Matcher matcher; private final int textLength; - public ParameterMatcher(Parameter parameter, Matcher matcher, int textLength) { - this.parameter = parameter; + public ParameterTypeMatcher(ParameterType parameterType, Matcher matcher, int textLength) { + this.parameterType = parameterType; this.matcher = matcher; this.textLength = textLength; } - public ParameterMatcher advanceTo(int newMatchPos) { - return new ParameterMatcher(parameter, matcher.region(newMatchPos, textLength), textLength); + public ParameterTypeMatcher advanceTo(int newMatchPos) { + return new ParameterTypeMatcher(parameterType, matcher.region(newMatchPos, textLength), textLength); } public boolean find() { @@ -30,7 +30,7 @@ public String group() { } @Override - public int compareTo(ParameterMatcher o) { + public int compareTo(ParameterTypeMatcher o) { int posComparison = Integer.compare(start(), o.start()); if (posComparison != 0) return posComparison; int lengthComparison = Integer.compare(o.group().length(), group().length()); @@ -38,16 +38,16 @@ public int compareTo(ParameterMatcher o) { // int and double are more commonly used than other number types. // We give special priority to those types so that the generated expression // will use those types. - if (parameter.getType().equals(int.class)) { + if (parameterType.getType().equals(int.class)) { return -1; } - if (parameter.getType().equals(double.class)) { + if (parameterType.getType().equals(double.class)) { return -1; } return 0; } - public Parameter getParameter() { - return parameter; + public ParameterType getParameterType() { + return parameterType; } } diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ParameterTypeRegistry.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ParameterTypeRegistry.java new file mode 100644 index 0000000000..0bca56b2ce --- /dev/null +++ b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/ParameterTypeRegistry.java @@ -0,0 +1,152 @@ +package io.cucumber.cucumberexpressions; + +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.NumberFormat; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import static java.util.Arrays.asList; + +public class ParameterTypeRegistry { + private static final List INTEGER_REGEXPS = asList("-?\\d+", "\\d+"); + private static final String FLOAT_REGEXP = "-?\\d*[\\.,]\\d+"; + private static final String HEX_REGEXP = "0[xX][0-9a-fA-F]{2}"; + + private final Map> parameterTypesByType = new HashMap<>(); + private final Map> parameterTypesByTypeName = new HashMap<>(); + private final Map> parameterTypesByRegexp = new HashMap<>(); + + public ParameterTypeRegistry(Locale locale) { + NumberFormat numberFormat = NumberFormat.getNumberInstance(locale); + final NumberParser numberParser = new NumberParser(numberFormat); + + definePredefinedParameterType(new SimpleParameterType<>("bigint", BigInteger.class, INTEGER_REGEXPS, new Function() { + @Override + public BigInteger apply(String s) { + return new BigInteger(s); + } + })); + definePredefinedParameterType(new SimpleParameterType<>("bigdecimal", BigDecimal.class, INTEGER_REGEXPS, new Function() { + @Override + public BigDecimal apply(String s) { + return new BigDecimal(s); + } + })); + definePredefinedParameterType(new SimpleParameterType<>("byte", byte.class, HEX_REGEXP, new Function() { + @Override + public Byte apply(String s) { + return Byte.decode(s); + } + })); + definePredefinedParameterType(new SimpleParameterType<>("byte", Byte.class, HEX_REGEXP, new Function() { + @Override + public Byte apply(String s) { + return Byte.decode(s); + } + })); + definePredefinedParameterType(new SimpleParameterType<>("short", short.class, INTEGER_REGEXPS, new Function() { + @Override + public Short apply(String s) { + return Short.decode(s); + } + })); + definePredefinedParameterType(new SimpleParameterType<>("short", Short.class, INTEGER_REGEXPS, new Function() { + @Override + public Short apply(String s) { + return Short.decode(s); + } + })); + definePredefinedParameterType(new SimpleParameterType<>("int", int.class, INTEGER_REGEXPS, new Function() { + @Override + public Integer apply(String s) { + return Integer.decode(s); + } + })); + definePredefinedParameterType(new SimpleParameterType<>("int", Integer.class, INTEGER_REGEXPS, new Function() { + @Override + public Integer apply(String s) { + return Integer.decode(s); + } + })); + definePredefinedParameterType(new SimpleParameterType<>("long", long.class, INTEGER_REGEXPS, new Function() { + @Override + public Long apply(String s) { + return Long.decode(s); + } + })); + definePredefinedParameterType(new SimpleParameterType<>("long", Long.class, INTEGER_REGEXPS, new Function() { + @Override + public Long apply(String s) { + return Long.decode(s); + } + })); + definePredefinedParameterType(new SimpleParameterType<>("float", float.class, FLOAT_REGEXP, new Function() { + @Override + public Float apply(String s) { + return numberParser.parseFloat(s); + } + })); + definePredefinedParameterType(new SimpleParameterType<>("float", Float.class, FLOAT_REGEXP, new Function() { + @Override + public Float apply(String s) { + return numberParser.parseFloat(s); + } + })); + definePredefinedParameterType(new SimpleParameterType<>("double", double.class, FLOAT_REGEXP, new Function() { + @Override + public Double apply(String s) { + return numberParser.parseDouble(s); + } + })); + definePredefinedParameterType(new SimpleParameterType<>("double", Double.class, FLOAT_REGEXP, new Function() { + @Override + public Double apply(String s) { + return numberParser.parseDouble(s); + } + })); + } + + public void defineParameterType(ParameterType parameterType) { + defineParameterType0(parameterType, true); + } + + private void definePredefinedParameterType(ParameterType parameterType) { + defineParameterType0(parameterType, false); + } + + private void defineParameterType0(ParameterType parameterType, boolean checkConflicts) { + put(parameterTypesByType, parameterType.getType(), parameterType, "type", parameterType.getType().getTypeName(), checkConflicts); + put(parameterTypesByTypeName, parameterType.getName(), parameterType, "type name", parameterType.getName(), checkConflicts); + + for (String captureGroupRegexp : parameterType.getRegexps()) { + put(parameterTypesByRegexp, captureGroupRegexp, parameterType, "regexp", captureGroupRegexp, checkConflicts); + } + } + + private void put(Map> map, K key, ParameterType parameterType, String prop, String keyName, boolean checkConflicts) { + if (checkConflicts && map.containsKey(key)) + throw new RuntimeException(String.format("There is already a parameter type with %s %s", prop, keyName)); + map.put(key, parameterType); + } + + public ParameterType lookupByType(Type type) { + return (ParameterType) parameterTypesByType.get(type); + } + + public ParameterType lookupByTypeName(String typeName) { + return (ParameterType) parameterTypesByTypeName.get(typeName); + } + + public ParameterType lookupByRegexp(String regexp) { + return (ParameterType) parameterTypesByRegexp.get(regexp); + } + + public Collection> getParameters() { + return parameterTypesByType.values(); + } +} diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/RegularExpression.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/RegularExpression.java index fb05f33e53..b889dd7f22 100644 --- a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/RegularExpression.java +++ b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/RegularExpression.java @@ -10,7 +10,7 @@ public class RegularExpression implements Expression { private static final Pattern CAPTURE_GROUP_PATTERN = Pattern.compile("\\(([^(]+)\\)"); private final Pattern pattern; - private final List> parameters; + private final List> parameterTypes; /** * Creates a new instance. Use this when the transform types are not known in advance, @@ -19,11 +19,11 @@ public class RegularExpression implements Expression { * * @param pattern the regular expression to use * @param types types to convert capture groups to - * @param parameterRegistry transform lookup + * @param parameterTypeRegistry transform lookup */ - public RegularExpression(Pattern pattern, List types, ParameterRegistry parameterRegistry) { + public RegularExpression(Pattern pattern, List types, ParameterTypeRegistry parameterTypeRegistry) { this.pattern = pattern; - this.parameters = new ArrayList<>(); + this.parameterTypes = new ArrayList<>(); Matcher matcher = CAPTURE_GROUP_PATTERN.matcher(pattern.pattern()); int typeIndex = 0; @@ -31,26 +31,26 @@ public RegularExpression(Pattern pattern, List types, ParameterR Type type = types.size() <= typeIndex ? null : types.get(typeIndex++); String captureGroupPattern = matcher.group(1); - Parameter parameter = null; + ParameterType parameterType = null; if (type != null) { - parameter = parameterRegistry.lookupByType(type); + parameterType = parameterTypeRegistry.lookupByType(type); } - if (parameter == null) { - parameter = parameterRegistry.lookupByCaptureGroupRegexp(captureGroupPattern); + if (parameterType == null) { + parameterType = parameterTypeRegistry.lookupByRegexp(captureGroupPattern); } - if (parameter == null && type != null && type instanceof Class) { - parameter = new ClassParameter<>((Class) type); + if (parameterType == null && type != null && type instanceof Class) { + parameterType = new ClassParameterType<>((Class) type); } - if (parameter == null) { - parameter = new ConstructorParameter<>(String.class); + if (parameterType == null) { + parameterType = new ConstructorParameterType<>(String.class); } - parameters.add(parameter); + parameterTypes.add(parameterType); } } @Override public List match(String text) { - return ArgumentBuilder.buildArguments(pattern, text, parameters); + return ArgumentBuilder.buildArguments(pattern, text, parameterTypes); } @Override diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/SimpleParameter.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/SimpleParameter.java deleted file mode 100644 index 9df360edff..0000000000 --- a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/SimpleParameter.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.cucumber.cucumberexpressions; - -import java.util.List; - -public class SimpleParameter extends AbstractParameter { - private final Function transformer; - - public SimpleParameter(String typeName, Class type, String captureGroupRegexp, Function transformer) { - super(typeName, type, captureGroupRegexp); - this.transformer = transformer; - } - - public SimpleParameter(String typeName, Class type, List captureGroupRegexps, Function transformer) { - super(typeName, type, captureGroupRegexps); - this.transformer = transformer; - } - - @Override - public T transform(String value) { - return transformer.apply(value); - } - -} diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/SimpleParameterType.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/SimpleParameterType.java new file mode 100644 index 0000000000..48a2401da2 --- /dev/null +++ b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/SimpleParameterType.java @@ -0,0 +1,23 @@ +package io.cucumber.cucumberexpressions; + +import java.util.List; + +public class SimpleParameterType extends AbstractParameterType { + private final Function transformer; + + public SimpleParameterType(String name, Class type, String regexp, Function transformer) { + super(name, type, regexp); + this.transformer = transformer; + } + + public SimpleParameterType(String name, Class type, List regexps, Function transformer) { + super(name, type, regexps); + this.transformer = transformer; + } + + @Override + public T transform(String value) { + return transformer.apply(value); + } + +} diff --git a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/TypeReference.java b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/TypeReference.java index 33fe427ce0..fbbfa832ee 100644 --- a/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/TypeReference.java +++ b/cucumber-expressions/java/src/main/java/io/cucumber/cucumberexpressions/TypeReference.java @@ -1,13 +1,11 @@ package io.cucumber.cucumberexpressions; -import java.lang.reflect.Constructor; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; public abstract class TypeReference { private final Type type; - private volatile Constructor constructor; protected TypeReference() { Type superclass = getClass().getGenericSuperclass(); diff --git a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ConstructorParameterTest.java b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ConstructorParameterTypeTest.java similarity index 81% rename from cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ConstructorParameterTest.java rename to cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ConstructorParameterTypeTest.java index 01c179c0ac..9518aa6e19 100644 --- a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ConstructorParameterTest.java +++ b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ConstructorParameterTypeTest.java @@ -6,7 +6,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; -public class ConstructorParameterTest { +public class ConstructorParameterTypeTest { public static class NoStringCtor { } @@ -24,7 +24,7 @@ public Abstract(String s) throws Exception { @Test public void requires_string_ctor() { try { - new ConstructorParameter<>(NoStringCtor.class); + new ConstructorParameterType<>(NoStringCtor.class); fail(); } catch (CucumberExpressionException expected) { assertEquals("Missing constructor: `public NoStringCtor(String)`", expected.getMessage()); @@ -34,7 +34,7 @@ public void requires_string_ctor() { @Test public void reports_ctor_exceptions() { try { - new ConstructorParameter<>(FailingCtor.class).transform("hello"); + new ConstructorParameterType<>(FailingCtor.class).transform("hello"); fail(); } catch (CucumberExpressionException expected) { assertEquals("Failed to invoke `new FailingCtor(\"hello\")`", expected.getMessage()); @@ -45,7 +45,7 @@ public void reports_ctor_exceptions() { @Test public void reports_abstract_exceptions() { try { - new ConstructorParameter<>(Abstract.class).transform("hello"); + new ConstructorParameterType<>(Abstract.class).transform("hello"); fail(); } catch (CucumberExpressionException expected) { assertEquals("Failed to invoke `new Abstract(\"hello\")`", expected.getMessage()); @@ -55,6 +55,6 @@ public void reports_abstract_exceptions() { @Test public void returns_null_for_value_null() { - assertNull(new ConstructorParameter<>(Abstract.class).transform(null)); + assertNull(new ConstructorParameterType<>(Abstract.class).transform(null)); } } diff --git a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CucumberExpressionGeneratorTest.java b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CucumberExpressionGeneratorTest.java index a311964dc6..3fb3cc6ce4 100644 --- a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CucumberExpressionGeneratorTest.java +++ b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CucumberExpressionGeneratorTest.java @@ -14,17 +14,17 @@ public class CucumberExpressionGeneratorTest { - private final ParameterRegistry parameterRegistry = new ParameterRegistry(Locale.ENGLISH); - private final CucumberExpressionGenerator generator = new CucumberExpressionGenerator(parameterRegistry); + private final ParameterTypeRegistry parameterTypeRegistry = new ParameterTypeRegistry(Locale.ENGLISH); + private final CucumberExpressionGenerator generator = new CucumberExpressionGenerator(parameterTypeRegistry); @Test public void documents_expression_generation() { /// [generate-expression] - CucumberExpressionGenerator generator = new CucumberExpressionGenerator(parameterRegistry); + CucumberExpressionGenerator generator = new CucumberExpressionGenerator(parameterTypeRegistry); String undefinedStepText = "I have 2 cucumbers and 1.5 tomato"; GeneratedExpression generatedExpression = generator.generateExpression(undefinedStepText); assertEquals("I have {int} cucumbers and {double} tomato", generatedExpression.getSource()); - assertEquals(Double.TYPE, generatedExpression.getParameters().get(1).getType()); + assertEquals(Double.TYPE, generatedExpression.getParameterTypes().get(1).getType()); /// [generate-expression] } @@ -56,7 +56,7 @@ public void numbers_all_arguments_when_type_is_reserved_keyword() { @Test public void numbers_only_second_argument_when_type_is_not_reserved_keyword() { - parameterRegistry.addParameter(new SimpleParameter<>( + parameterTypeRegistry.defineParameterType(new SimpleParameterType<>( "currency", Currency.class, "[A-Z]{3}", @@ -69,13 +69,13 @@ public void numbers_only_second_argument_when_type_is_not_reserved_keyword() { @Test public void prefers_leftmost_match_when_there_is_overlap() { - parameterRegistry.addParameter(new SimpleParameter<>( + parameterTypeRegistry.defineParameterType(new SimpleParameterType<>( "currency", Currency.class, "cd", null )); - parameterRegistry.addParameter(new SimpleParameter<>( + parameterTypeRegistry.defineParameterType(new SimpleParameterType<>( "date", Date.class, "bc", @@ -88,13 +88,13 @@ public void prefers_leftmost_match_when_there_is_overlap() { @Test public void prefers_widest_match_when_pos_is_same() { - parameterRegistry.addParameter(new SimpleParameter<>( + parameterTypeRegistry.defineParameterType(new SimpleParameterType<>( "currency", Currency.class, "cd", null )); - parameterRegistry.addParameter(new SimpleParameter<>( + parameterTypeRegistry.defineParameterType(new SimpleParameterType<>( "date", Date.class, "cde", @@ -108,8 +108,8 @@ public void prefers_widest_match_when_pos_is_same() { @Test public void exposes_transforms_in_generated_expression() { GeneratedExpression generatedExpression = generator.generateExpression("I have 2 cukes and 1.5 euro"); - assertEquals(int.class, generatedExpression.getParameters().get(0).getType()); - assertEquals(double.class, generatedExpression.getParameters().get(1).getType()); + assertEquals(int.class, generatedExpression.getParameterTypes().get(0).getType()); + assertEquals(double.class, generatedExpression.getParameterTypes().get(1).getType()); } private void assertExpression(String expectedExpression, List expectedArgumentNames, String text) { diff --git a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CucumberExpressionPatternTest.java b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CucumberExpressionPatternTest.java index f78960ab3c..9a48baffa0 100644 --- a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CucumberExpressionPatternTest.java +++ b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CucumberExpressionPatternTest.java @@ -83,7 +83,7 @@ public void translates_parenthesis_to_non_capturing_optional_capture_group() { } private void assertPattern(String expr, String expectedRegexp, List types) { - CucumberExpression cucumberExpression = new CucumberExpression(expr, types, new ParameterRegistry(Locale.ENGLISH)); + CucumberExpression cucumberExpression = new CucumberExpression(expr, types, new ParameterTypeRegistry(Locale.ENGLISH)); assertEquals(expectedRegexp, cucumberExpression.getPattern().pattern()); } } diff --git a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CucumberExpressionTest.java b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CucumberExpressionTest.java index 3b0af88ed7..d441e68fae 100644 --- a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CucumberExpressionTest.java +++ b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CucumberExpressionTest.java @@ -17,12 +17,12 @@ public class CucumberExpressionTest { @Test public void documents_match_arguments() { - ParameterRegistry parameterRegistry = new ParameterRegistry(Locale.ENGLISH); + ParameterTypeRegistry parameterTypeRegistry = new ParameterTypeRegistry(Locale.ENGLISH); /// [capture-buildArguments-arguments] String expr = "I have {n} cuke(s) in my {bodypart} now"; List> types = asList(Integer.class, String.class); - Expression expression = new CucumberExpression(expr, types, parameterRegistry); + Expression expression = new CucumberExpression(expr, types, parameterTypeRegistry); List args = expression.match("I have 7 cukes in my belly now"); assertEquals(7, args.get(0).getTransformedValue()); assertEquals("belly", args.get(1).getTransformedValue()); @@ -74,13 +74,13 @@ public void supports_deprecated_name_colon_type_syntax_for_now() { @Test public void exposes_source() { String expr = "I have {int} cuke(s) in my {bodypart} now"; - assertEquals(expr, new CucumberExpression(expr, Collections.emptyList(), new ParameterRegistry(Locale.ENGLISH)).getSource()); + assertEquals(expr, new CucumberExpression(expr, Collections.emptyList(), new ParameterTypeRegistry(Locale.ENGLISH)).getSource()); } @Test public void exposes_offset_and_value() { String expr = "I have {int} cuke(s) in my {bodypart} now"; - Expression expression = new CucumberExpression(expr, Collections.emptyList(), new ParameterRegistry(Locale.ENGLISH)); + Expression expression = new CucumberExpression(expr, Collections.emptyList(), new ParameterTypeRegistry(Locale.ENGLISH)); Argument arg1 = expression.match("I have 800 cukes in my brain now").get(0); assertEquals(7, arg1.getOffset()); assertEquals("800", arg1.getValue()); @@ -89,7 +89,7 @@ public void exposes_offset_and_value() { @Test public void escapes_special_characters() { String expr = "I have {int} cuke(s) and ^"; - Expression expression = new CucumberExpression(expr, Collections.emptyList(), new ParameterRegistry(Locale.ENGLISH)); + Expression expression = new CucumberExpression(expr, Collections.emptyList(), new ParameterTypeRegistry(Locale.ENGLISH)); Argument arg1 = expression.match("I have 800 cukes and ^").get(0); assertEquals(7, arg1.getOffset()); assertEquals("800", arg1.getValue()); @@ -137,7 +137,7 @@ private List match(String expr, String text, Type type) { } private List match(String expr, String text, List explicitTypes, Locale locale) { - CucumberExpression expression = new CucumberExpression(expr, explicitTypes, new ParameterRegistry(locale)); + CucumberExpression expression = new CucumberExpression(expr, explicitTypes, new ParameterTypeRegistry(locale)); List args = expression.match(text); if (args == null) return null; List transformedValues = new ArrayList<>(); diff --git a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CustomParameterTest.java b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CustomParameterTypeTest.java similarity index 83% rename from cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CustomParameterTest.java rename to cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CustomParameterTypeTest.java index defa1caef8..ddb5d57acf 100644 --- a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CustomParameterTest.java +++ b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/CustomParameterTypeTest.java @@ -13,7 +13,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; -public class CustomParameterTest { +public class CustomParameterTypeTest { public static class Color { public final String name; @@ -34,12 +34,12 @@ public boolean equals(Object obj) { } } - private ParameterRegistry parameterRegistry = new ParameterRegistry(Locale.ENGLISH); + private ParameterTypeRegistry parameterTypeRegistry = new ParameterTypeRegistry(Locale.ENGLISH); @Before public void create_parameter() { /// [add-color-parameter] - parameterRegistry.addParameter(new SimpleParameter<>( + parameterTypeRegistry.defineParameterType(new SimpleParameterType<>( "color", Color.class, "red|blue|yellow", @@ -55,15 +55,15 @@ public Color apply(String name) { @Test public void transforms_CucumberExpression_arguments_with_expression_type() { - Expression expression = new CucumberExpression("I have a {color} ball", Collections.emptyList(), parameterRegistry); + Expression expression = new CucumberExpression("I have a {color} ball", Collections.emptyList(), parameterTypeRegistry); Object transformedArgumentValue = expression.match("I have a red ball").get(0).getTransformedValue(); assertEquals(new Color("red"), transformedArgumentValue); } @Test public void transforms_CucumberExpression_arguments_with_expression_type_using_optional_group() { - parameterRegistry = new ParameterRegistry(Locale.ENGLISH); - parameterRegistry.addParameter(new SimpleParameter<>( + parameterTypeRegistry = new ParameterTypeRegistry(Locale.ENGLISH); + parameterTypeRegistry.defineParameterType(new SimpleParameterType<>( "color", Color.class, asList("red|blue|yellow", "(?:dark|light) (?:red|blue|yellow)"), @@ -74,35 +74,35 @@ public Color apply(String name) { } } )); - Expression expression = new CucumberExpression("I have a {color} ball", Collections.emptyList(), parameterRegistry); + Expression expression = new CucumberExpression("I have a {color} ball", Collections.emptyList(), parameterTypeRegistry); Object transformedArgumentValue = expression.match("I have a dark red ball").get(0).getTransformedValue(); assertEquals(new Color("dark red"), transformedArgumentValue); } @Test public void transforms_CucumberExpression_arguments_with_explicit_type() { - Expression expression = new CucumberExpression("I have a {color} ball", Collections.singletonList(Color.class), parameterRegistry); + Expression expression = new CucumberExpression("I have a {color} ball", Collections.singletonList(Color.class), parameterTypeRegistry); Object transformedArgumentValue = expression.match("I have a red ball").get(0).getTransformedValue(); assertEquals(new Color("red"), transformedArgumentValue); } @Test public void transforms_CucumberExpression_arguments_using_argument_name_as_type() { - Expression expression = new CucumberExpression("I have a {color} ball", Collections.emptyList(), parameterRegistry); + Expression expression = new CucumberExpression("I have a {color} ball", Collections.emptyList(), parameterTypeRegistry); Object transformedArgumentValue = expression.match("I have a red ball").get(0).getTransformedValue(); assertEquals(new Color("red"), transformedArgumentValue); } @Test public void transforms_CucumberExpression_arguments_with_explicit_type_using_constructor_directly() { - Expression expression = new CucumberExpression("I have a {color} ball", Collections.singletonList(Color.class), new ParameterRegistry(Locale.ENGLISH)); + Expression expression = new CucumberExpression("I have a {color} ball", Collections.singletonList(Color.class), new ParameterTypeRegistry(Locale.ENGLISH)); Color transformedArgumentValue = (Color) expression.match("I have a red ball").get(0).getTransformedValue(); assertEquals("red", transformedArgumentValue.name); } @Test public void defers_transformation_until_queried_from_argument() { - parameterRegistry.addParameter(new SimpleParameter<>( + parameterTypeRegistry.defineParameterType(new SimpleParameterType<>( "throwing", String.class, "bad", @@ -112,7 +112,7 @@ public String apply(String name) { throw new RuntimeException(String.format("Can't transform [%s]", name)); } })); - Expression expression = new CucumberExpression("I have a {throwing} parameter", Collections.emptyList(), parameterRegistry); + Expression expression = new CucumberExpression("I have a {throwing} parameter", Collections.emptyList(), parameterTypeRegistry); List arguments = expression.match("I have a bad parameter"); try { arguments.get(0).getTransformedValue(); @@ -127,7 +127,7 @@ public String apply(String name) { @Test public void conflicting_parameter_type_is_detected_for_type() { try { - parameterRegistry.addParameter(new SimpleParameter<>( + parameterTypeRegistry.defineParameterType(new SimpleParameterType<>( "color", String.class, ".*", @@ -139,14 +139,14 @@ public String apply(String s) { })); fail("should have failed"); } catch (RuntimeException expected) { - assertEquals("There is already a parameter with type name color", expected.getMessage()); + assertEquals("There is already a parameter type with type name color", expected.getMessage()); } } @Test public void conflicting_parameter_type_is_detected_for_type_name() { try { - parameterRegistry.addParameter(new SimpleParameter<>( + parameterTypeRegistry.defineParameterType(new SimpleParameterType<>( "whatever", Color.class, ".*", @@ -158,14 +158,14 @@ public Color apply(String s) { })); fail("should have failed"); } catch (RuntimeException expected) { - assertEquals("There is already a parameter with type io.cucumber.cucumberexpressions.CustomParameterTest$Color", expected.getMessage()); + assertEquals("There is already a parameter type with type io.cucumber.cucumberexpressions.CustomParameterTypeTest$Color", expected.getMessage()); } } @Test public void conflicting_parameter_type_is_detected_for_regexp() { try { - parameterRegistry.addParameter(new SimpleParameter<>( + parameterTypeRegistry.defineParameterType(new SimpleParameterType<>( "whatever", String.class, "red|blue|yellow", @@ -177,7 +177,7 @@ public String apply(String s) { })); fail("should have failed"); } catch (RuntimeException expected) { - assertEquals("There is already a parameter with regexp red|blue|yellow", expected.getMessage()); + assertEquals("There is already a parameter type with regexp red|blue|yellow", expected.getMessage()); } } @@ -185,21 +185,21 @@ public String apply(String s) { @Test public void transforms_RegularExpression_arguments_with_explicit_type() { - Expression expression = new RegularExpression(compile("I have a (red|blue|yellow) ball"), Collections.singletonList(Color.class), parameterRegistry); + Expression expression = new RegularExpression(compile("I have a (red|blue|yellow) ball"), Collections.singletonList(Color.class), parameterTypeRegistry); Object transformedArgumentValue = expression.match("I have a red ball").get(0).getTransformedValue(); assertEquals(new Color("red"), transformedArgumentValue); } @Test public void transforms_RegularExpression_arguments_without_explicit_type() { - Expression expression = new RegularExpression(compile("I have a (red|blue|yellow) ball"), Collections.emptyList(), parameterRegistry); + Expression expression = new RegularExpression(compile("I have a (red|blue|yellow) ball"), Collections.emptyList(), parameterTypeRegistry); Object transformedArgumentValue = expression.match("I have a red ball").get(0).getTransformedValue(); assertEquals(new Color("red"), transformedArgumentValue); } @Test public void transforms_RegularExpression_arguments_with_explicit_type_using_constructor_directly() { - Expression expression = new RegularExpression(compile("I have a (red|blue|yellow) ball"), Collections.singletonList(Color.class), new ParameterRegistry(Locale.ENGLISH)); + Expression expression = new RegularExpression(compile("I have a (red|blue|yellow) ball"), Collections.singletonList(Color.class), new ParameterTypeRegistry(Locale.ENGLISH)); Color transformedArgumentValue = (Color) expression.match("I have a red ball").get(0).getTransformedValue(); assertEquals("red", transformedArgumentValue.name); } diff --git a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/EnumFormatTest.java b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/EnumFormatTest.java index b763996428..9199e07d0d 100644 --- a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/EnumFormatTest.java +++ b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/EnumFormatTest.java @@ -11,7 +11,7 @@ public static enum Color { @Test public void constructs_enum() { - Parameter t = new EnumParameter<>(Color.class); + ParameterType t = new EnumParameterType<>(Color.class); assertEquals(Color.BLUE, t.transform("BLUE")); } } diff --git a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ExpressionExamplesTest.java b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ExpressionExamplesTest.java index 409863e517..afb5bc25cb 100644 --- a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ExpressionExamplesTest.java +++ b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ExpressionExamplesTest.java @@ -56,11 +56,11 @@ public void works_with_expression() { private List match(String expressionString, String text) { Expression expression; Matcher matcher = REGEX_PATTERN.matcher(expressionString); - ParameterRegistry parameterRegistry = new ParameterRegistry(Locale.ENGLISH); + ParameterTypeRegistry parameterTypeRegistry = new ParameterTypeRegistry(Locale.ENGLISH); if (matcher.matches()) { - expression = new RegularExpression(Pattern.compile(matcher.group(1)), Collections.emptyList(), parameterRegistry); + expression = new RegularExpression(Pattern.compile(matcher.group(1)), Collections.emptyList(), parameterTypeRegistry); } else { - expression = new CucumberExpression(expressionString, Collections.emptyList(), parameterRegistry); + expression = new CucumberExpression(expressionString, Collections.emptyList(), parameterTypeRegistry); } List arguments = expression.match(text); if (arguments == null) return null; diff --git a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ExpressionFactoryTest.java b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ExpressionFactoryTest.java index 353db86180..e55ae354c3 100644 --- a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ExpressionFactoryTest.java +++ b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ExpressionFactoryTest.java @@ -62,7 +62,7 @@ private void assertCucumberExpression(String expressionSource) { } private void assertExpression(Class expectedClass, String expectedSource, String expressionSource) { - Expression expression = new ExpressionFactory(new ParameterRegistry(Locale.ENGLISH)).createExpression(expressionSource, new ArrayList()); + Expression expression = new ExpressionFactory(new ParameterTypeRegistry(Locale.ENGLISH)).createExpression(expressionSource, new ArrayList()); assertEquals(expectedClass, expression.getClass()); if (expectedSource != null) { assertEquals(expectedSource, expression.getSource()); diff --git a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/GenericParameterTest.java b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/GenericParameterTypeTest.java similarity index 65% rename from cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/GenericParameterTest.java rename to cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/GenericParameterTypeTest.java index 36d8dd830c..79c7afd63e 100644 --- a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/GenericParameterTest.java +++ b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/GenericParameterTypeTest.java @@ -10,9 +10,9 @@ import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; -public class GenericParameterTest { - class ListOfStringParameter extends AbstractParameter> { - public ListOfStringParameter() { +public class GenericParameterTypeTest { + class ListOfStringParameterType extends AbstractParameterType> { + public ListOfStringParameterType() { super("stringlist", new TypeReference>() { }.getType(), ".*"); } @@ -25,9 +25,9 @@ public List transform(String value) { @Test public void transforms_to_a_list_of_string() { - ParameterRegistry parameterRegistry = new ParameterRegistry(Locale.ENGLISH); - parameterRegistry.addParameter(new ListOfStringParameter()); - Expression expression = new CucumberExpression("I have {stringlist} yay", Collections.emptyList(), parameterRegistry); + ParameterTypeRegistry parameterTypeRegistry = new ParameterTypeRegistry(Locale.ENGLISH); + parameterTypeRegistry.defineParameterType(new ListOfStringParameterType()); + Expression expression = new CucumberExpression("I have {stringlist} yay", Collections.emptyList(), parameterTypeRegistry); List args = expression.match("I have three,blind,mice yay"); assertEquals(asList("three", "blind", "mice"), args.get(0).getTransformedValue()); } diff --git a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ParameterRegistryTest.java b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ParameterRegistryTest.java deleted file mode 100644 index 50ea840e93..0000000000 --- a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ParameterRegistryTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.cucumber.cucumberexpressions; - -import org.junit.Test; - -import java.util.Locale; - -import static org.junit.Assert.assertEquals; - -public class ParameterRegistryTest { - @Test - public void looks_up_transform_by_type() { - Parameter parameter = new ParameterRegistry(Locale.ENGLISH).lookupByType(Integer.class); - assertEquals(new Integer(22), parameter.transform("22")); - } -} diff --git a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ParameterTypeRegistryTest.java b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ParameterTypeRegistryTest.java new file mode 100644 index 0000000000..61f879f914 --- /dev/null +++ b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/ParameterTypeRegistryTest.java @@ -0,0 +1,15 @@ +package io.cucumber.cucumberexpressions; + +import org.junit.Test; + +import java.util.Locale; + +import static org.junit.Assert.assertEquals; + +public class ParameterTypeRegistryTest { + @Test + public void looks_up_transform_by_type() { + ParameterType parameterType = new ParameterTypeRegistry(Locale.ENGLISH).lookupByType(Integer.class); + assertEquals(new Integer(22), parameterType.transform("22")); + } +} diff --git a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/RegularExpressionTest.java b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/RegularExpressionTest.java index 902359b035..ac0601eff3 100644 --- a/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/RegularExpressionTest.java +++ b/cucumber-expressions/java/src/test/java/io/cucumber/cucumberexpressions/RegularExpressionTest.java @@ -17,12 +17,12 @@ public class RegularExpressionTest { @Test public void document_match_arguments() { - ParameterRegistry parameterRegistry = new ParameterRegistry(Locale.ENGLISH); + ParameterTypeRegistry parameterTypeRegistry = new ParameterTypeRegistry(Locale.ENGLISH); /// [capture-buildArguments-arguments] Pattern expr = Pattern.compile("I have (\\d+) cukes? in my (\\w+) now"); List> types = asList(Integer.class, String.class); - Expression expression = new RegularExpression(expr, types, parameterRegistry); + Expression expression = new RegularExpression(expr, types, parameterTypeRegistry); List match = expression.match("I have 7 cukes in my belly now"); assertEquals(7, match.get(0).getTransformedValue()); assertEquals("belly", match.get(1).getTransformedValue()); @@ -63,7 +63,7 @@ public void transforms_double_with_sign() { @Test public void exposes_source() { String expr = "I have (\\d+) cukes? in my (.+) now"; - assertEquals(expr, new RegularExpression(Pattern.compile(expr), Collections.emptyList(), new ParameterRegistry(Locale.ENGLISH)).getSource()); + assertEquals(expr, new RegularExpression(Pattern.compile(expr), Collections.emptyList(), new ParameterTypeRegistry(Locale.ENGLISH)).getSource()); } private List match(Pattern pattern, String text) { @@ -75,9 +75,9 @@ private List match(Pattern pattern, String text, List types) { } private List match(Pattern pattern, String text, List types, Locale locale) { - ParameterRegistry parameterRegistry = new ParameterRegistry(locale); + ParameterTypeRegistry parameterTypeRegistry = new ParameterTypeRegistry(locale); RegularExpression regularExpression; - regularExpression = new RegularExpression(pattern, types, parameterRegistry); + regularExpression = new RegularExpression(pattern, types, parameterTypeRegistry); List arguments = regularExpression.match(text); List transformedValues = new ArrayList<>(); for (Argument argument : arguments) { diff --git a/cucumber-expressions/javascript/package.json b/cucumber-expressions/javascript/package.json index 4ebb33c8ca..d5d89d01c0 100644 --- a/cucumber-expressions/javascript/package.json +++ b/cucumber-expressions/javascript/package.json @@ -32,7 +32,7 @@ "babel-cli": "^6.23.0", "babel-preset-es2015": "^6.22.0", "eslint": "^3.15.0", - "eslint-config-eslint": "^3.0.0", + "eslint-config-eslint": "^4.0.0", "istanbul": "1.0.0-alpha.2", "mocha": "^3.2.0" }, diff --git a/cucumber-expressions/javascript/src/argument.js b/cucumber-expressions/javascript/src/argument.js index 0315b5dd0d..54130a299a 100644 --- a/cucumber-expressions/javascript/src/argument.js +++ b/cucumber-expressions/javascript/src/argument.js @@ -1,8 +1,8 @@ class Argument { - constructor(offset, value, parameter) { + constructor(offset, value, parameterType) { this._offset = offset this._value = value - this._parameter = parameter + this._parameterType = parameterType } get offset() { @@ -14,7 +14,7 @@ class Argument { } get transformedValue() { - return this._parameter.transform(this._value) + return this._parameterType.transform(this._value) } } diff --git a/cucumber-expressions/javascript/src/build_arguments.js b/cucumber-expressions/javascript/src/build_arguments.js index 7a10609216..ef4172e678 100644 --- a/cucumber-expressions/javascript/src/build_arguments.js +++ b/cucumber-expressions/javascript/src/build_arguments.js @@ -1,13 +1,13 @@ const Argument = require('./argument') -const buildArguments = (regexp, text, parameters) => { +const buildArguments = (regexp, text, parameterTypes) => { const m = regexp.exec(text) if (!m) return null - let parameterIndex = 0 + let parameterTypeIndex = 0 let offset = 0 return m.slice(1).map(value => { offset = text.indexOf(value, offset) - const parameter = parameters[parameterIndex++] + const parameter = parameterTypes[parameterTypeIndex++] return new Argument(offset, value, parameter) }) } diff --git a/cucumber-expressions/javascript/src/cucumber_expression.js b/cucumber-expressions/javascript/src/cucumber_expression.js index eb6708dc9d..86d2b5710c 100644 --- a/cucumber-expressions/javascript/src/cucumber_expression.js +++ b/cucumber-expressions/javascript/src/cucumber_expression.js @@ -4,15 +4,15 @@ class CucumberExpression { /** * @param expression * @param types Array of type name (String) or types (function). Functions can be a regular function or a constructor - * @param parameterRegistry + * @param parameterTypeRegistry */ - constructor (expression, types, parameterRegistry) { + constructor (expression, types, parameterTypeRegistry) { const PARAMETER_REGEXP = /\{([^}:]+)(:([^}]+))?}/g const OPTIONAL_REGEXP = /\(([^)]+)\)/g const ALTERNATIVE_WORD_REGEXP = /(\w+)((\/\w+)+)/g this._expression = expression - this._parameters = [] + this._parameterTypes = [] let regexp = "^" let typeIndex = 0 let match @@ -28,32 +28,32 @@ class CucumberExpression { while ((match = PARAMETER_REGEXP.exec(expression)) !== null) { const parameterName = match[1] - const typeName = match[3] + const parameterTypeName = match[3] // eslint-disable-next-line no-console - if (typeName && (typeof console !== 'undefined') && (typeof console.error == 'function')) { + if (parameterTypeName && (typeof console !== 'undefined') && (typeof console.error == 'function')) { // eslint-disable-next-line no-console - console.error(`Cucumber expression parameter syntax {${parameterName}:${typeName}} is deprecated. Please use {${typeName}} instead.`) + console.error(`Cucumber expression parameter syntax {${parameterName}:${parameterTypeName}} is deprecated. Please use {${parameterTypeName}} instead.`) } const type = types.length <= typeIndex ? null : types[typeIndex++] let parameter if (type) { - parameter = parameterRegistry.lookupByType(type) + parameter = parameterTypeRegistry.lookupByType(type) } - if (!parameter && typeName) { - parameter = parameterRegistry.lookupByTypeName(typeName) + if (!parameter && parameterTypeName) { + parameter = parameterTypeRegistry.lookupByTypeName(parameterTypeName) } if (!parameter) { - parameter = parameterRegistry.lookupByTypeName(parameterName) + parameter = parameterTypeRegistry.lookupByTypeName(parameterName) } if (!parameter) { - parameter = parameterRegistry.createAnonymousLookup(s => s) + parameter = parameterTypeRegistry.createAnonymousLookup(s => s) } - this._parameters.push(parameter) + this._parameterTypes.push(parameter) const text = expression.slice(matchOffset, match.index) - const captureRegexp = getCaptureRegexp(parameter.captureGroupRegexps) + const captureRegexp = getCaptureRegexp(parameter.regexps) matchOffset = PARAMETER_REGEXP.lastIndex regexp += text regexp += captureRegexp @@ -64,7 +64,7 @@ class CucumberExpression { } match (text) { - return matchPattern(this._regexp, text, this._parameters) + return matchPattern(this._regexp, text, this._parameterTypes) } get source () { @@ -72,12 +72,12 @@ class CucumberExpression { } } -function getCaptureRegexp (captureGroupRegexps) { - if (captureGroupRegexps.length === 1) { - return `(${captureGroupRegexps[0]})` +function getCaptureRegexp (regexps) { + if (regexps.length === 1) { + return `(${regexps[0]})` } - const captureGroups = captureGroupRegexps.map(group => { + const captureGroups = regexps.map(group => { return `(?:${group})` }) diff --git a/cucumber-expressions/javascript/src/cucumber_expression_generator.js b/cucumber-expressions/javascript/src/cucumber_expression_generator.js index ff2a7a4b36..eb04bce825 100644 --- a/cucumber-expressions/javascript/src/cucumber_expression_generator.js +++ b/cucumber-expressions/javascript/src/cucumber_expression_generator.js @@ -1,42 +1,42 @@ -const TransformMatcher = require('./parameter_matcher') +const ParameterTypeMatcher = require('./parameter_type_matcher') const GeneratedExpression = require('./generated_expression') class CucumberExpressionGenerator { - constructor(parameterRegistry) { - this._parameterRegistry = parameterRegistry + constructor(parameterTypeRegistry) { + this._parameterTypeRegistry = parameterTypeRegistry } generateExpression(text) { const parameterNames = [] - const parameterMatchers = this._createTransformMatchers(text) - const parameters = [] + const parameterTypeMatchers = this._createParameterTypeMatchers(text) + const parameterTypes = [] const usageByTypeName = {} let expression = "" let pos = 0 while (true) { // eslint-disable-line no-constant-condition - let matchingTransformMatchers = [] - for (const parameterMatcher of parameterMatchers) { - const advancedTransformMatcher = parameterMatcher.advanceTo(pos) - if (advancedTransformMatcher.find) { - matchingTransformMatchers.push(advancedTransformMatcher) + let matchingParameterTypeMatchers = [] + for (const parameterTypeMatcher of parameterTypeMatchers) { + const advancedParameterTypeMatcher = parameterTypeMatcher.advanceTo(pos) + if (advancedParameterTypeMatcher.find) { + matchingParameterTypeMatchers.push(advancedParameterTypeMatcher) } } - if (matchingTransformMatchers.length > 0) { - matchingTransformMatchers = matchingTransformMatchers.sort(TransformMatcher.compare) - const bestTransformMatcher = matchingTransformMatchers[0] - const parameter = bestTransformMatcher.parameter - parameters.push(parameter) + if (matchingParameterTypeMatchers.length > 0) { + matchingParameterTypeMatchers = matchingParameterTypeMatchers.sort(ParameterTypeMatcher.compare) + const bestParameterTypeMatcher = matchingParameterTypeMatchers[0] + const parameter = bestParameterTypeMatcher.parameterType + parameterTypes.push(parameter) - const parameterName = this._getParameterName(parameter.typeName, usageByTypeName) + const parameterName = this._getParameterName(parameter.name, usageByTypeName) parameterNames.push(parameterName) - expression += text.slice(pos, bestTransformMatcher.start) - expression += `{${parameter.typeName}}` + expression += text.slice(pos, bestParameterTypeMatcher.start) + expression += `{${parameter.name}}` - pos = bestTransformMatcher.start + bestTransformMatcher.group.length + pos = bestParameterTypeMatcher.start + bestParameterTypeMatcher.group.length } else { break } @@ -47,7 +47,7 @@ class CucumberExpressionGenerator { } expression += text.slice(pos) - return new GeneratedExpression(expression, parameterNames, parameters) + return new GeneratedExpression(expression, parameterNames, parameterTypes) } _getParameterName(typeName, usageByTypeName) { @@ -58,18 +58,18 @@ class CucumberExpressionGenerator { return count == 1 ? typeName : `${typeName}${count}` } - _createTransformMatchers(text) { + _createParameterTypeMatchers(text) { let parameterMatchers = [] - for (let parameter of this._parameterRegistry.parameters) { - parameterMatchers = parameterMatchers.concat(this._createTransformMatchers2(parameter, text)) + for (const parameter of this._parameterTypeRegistry.parameterTypes) { + parameterMatchers = parameterMatchers.concat(this._createParameterTypeMatchers2(parameter, text)) } return parameterMatchers } - _createTransformMatchers2(parameter, text) { + _createParameterTypeMatchers2(parameter, text) { const result = [] - for (let captureGroupRegexp of parameter.captureGroupRegexps) { - result.push(new TransformMatcher(parameter, captureGroupRegexp, text)) + for (const regexp of parameter.regexps) { + result.push(new ParameterTypeMatcher(parameter, regexp, text)) } return result } diff --git a/cucumber-expressions/javascript/src/generated_expression.js b/cucumber-expressions/javascript/src/generated_expression.js index 16b98edddd..a8bedc8f34 100644 --- a/cucumber-expressions/javascript/src/generated_expression.js +++ b/cucumber-expressions/javascript/src/generated_expression.js @@ -1,8 +1,8 @@ class GeneratedExpression { - constructor(expression, parameterNames, parameters) { + constructor(expression, parameterNames, parameterTypes) { this._expression = expression this._parameterNames = parameterNames - this._parameters = parameters + this._parameterTypes = parameterTypes } get source() { @@ -19,10 +19,10 @@ class GeneratedExpression { } /** - * @returns {Array.} + * @returns {Array.} */ - get parameters() { - return this._parameters + get parameterTypes() { + return this._parameterTypes } } diff --git a/cucumber-expressions/javascript/src/index.js b/cucumber-expressions/javascript/src/index.js index 9f62faa917..6cc6ecb973 100644 --- a/cucumber-expressions/javascript/src/index.js +++ b/cucumber-expressions/javascript/src/index.js @@ -1,13 +1,13 @@ const CucumberExpression = require("./cucumber_expression") const RegularExpression = require("./regular_expression") const CucumberExpressionGenerator = require("./cucumber_expression_generator") -const ParameterRegistry = require("./parameter_registry") -const Parameter = require("./parameter") +const ParameterTypeRegistry = require("./parameter_type_registry") +const ParameterType = require("./parameter_type") module.exports = { CucumberExpression, RegularExpression, CucumberExpressionGenerator, - ParameterRegistry, - Parameter + ParameterTypeRegistry, + ParameterType } diff --git a/cucumber-expressions/javascript/src/parameter.js b/cucumber-expressions/javascript/src/parameter.js deleted file mode 100644 index 413dcff573..0000000000 --- a/cucumber-expressions/javascript/src/parameter.js +++ /dev/null @@ -1,31 +0,0 @@ -class Parameter { - constructor(typeName, constructorFunction, captureGroupRegexps, transform) { - this._typeName = typeName - this._constructorFunction = constructorFunction - this._captureGroupRegexps = stringArray(captureGroupRegexps) - this._transform = transform - } - - get typeName() { - return this._typeName - } - - get constructorFunction() { - return this._constructorFunction - } - - get captureGroupRegexps() { - return this._captureGroupRegexps - } - - transform(string) { - return this._transform(string) - } -} - -function stringArray(captureGroupRegexps) { - const array = Array.isArray(captureGroupRegexps) ? captureGroupRegexps : [captureGroupRegexps] - return array.map(r => typeof r == 'string' ? r : r.source) -} - -module.exports = Parameter diff --git a/cucumber-expressions/javascript/src/parameter_registry.js b/cucumber-expressions/javascript/src/parameter_registry.js deleted file mode 100644 index 2253f5a574..0000000000 --- a/cucumber-expressions/javascript/src/parameter_registry.js +++ /dev/null @@ -1,92 +0,0 @@ -const Parameter = require('./parameter') - -class ParameterRegistry { - constructor() { - this._parametersByTypeName = new Map() - this._parametersByCaptureGroupRegexp = new Map() - this._parametersByConstructorName = new Map() - - const INTEGER_REGEXPS = [/-?\d+/, /\d+/] - const FLOAT_REGEXP = /-?\d*\.?\d+/ - - this._addPredefinedParameter(new Parameter('int', Number, INTEGER_REGEXPS, parseInt)) - this._addPredefinedParameter(new Parameter('float', Number, FLOAT_REGEXP, parseFloat)) - } - - get parameters() { - return this._parametersByTypeName.values() - } - - lookupByType(type) { - if (typeof type === 'function') { - return this.lookupByFunction(type) - } else if (typeof type === 'string') { - return this.lookupByTypeName(type) - } else { - throw new Error(`Type must be string or function, but was ${type} of type ${typeof type}`) - } - } - - lookupByFunction(fn) { - if (fn.name) { - const prefix = fn.name[0] - const looksLikeConstructor = prefix.toUpperCase() === prefix - - let parameter - if (looksLikeConstructor) { - parameter = this._parametersByConstructorName.get(fn.name) - } - if (!parameter) { - const factory = s => { - if (looksLikeConstructor) { - return new fn(s) - } else { - return fn(s) - } - } - return this.createAnonymousLookup(factory) - } else { - return parameter - } - } else { - return this.createAnonymousLookup(fn) - } - } - - lookupByTypeName(typeName) { - return this._parametersByTypeName.get(typeName) - } - - lookupByCaptureGroupRegexp(captureGroupRegexp) { - return this._parametersByCaptureGroupRegexp.get(captureGroupRegexp) - } - - createAnonymousLookup(fn) { - return new Parameter(null, null, [".+"], fn) - } - - addParameter(parameter) { - this._addParameter(parameter, true) - } - - _addPredefinedParameter(parameter) { - this._addParameter(parameter, false) - } - - _addParameter(parameter, checkConflicts) { - set(this._parametersByConstructorName, parameter.constructorFunction.name, parameter, 'constructor', checkConflicts) - set(this._parametersByTypeName, parameter.typeName, parameter, 'type name', checkConflicts) - - for (let captureGroupRegexp of parameter.captureGroupRegexps) { - set(this._parametersByCaptureGroupRegexp, captureGroupRegexp, parameter, 'regexp', checkConflicts) - } - } -} - -function set(map, key, value, prop, checkConflicts) { - if(checkConflicts && map.has(key)) - throw new Error(`There is already a parameter with ${prop} ${key}`) - map.set(key, value) -} - -module.exports = ParameterRegistry diff --git a/cucumber-expressions/javascript/src/parameter_type.js b/cucumber-expressions/javascript/src/parameter_type.js new file mode 100644 index 0000000000..e0f6ea444e --- /dev/null +++ b/cucumber-expressions/javascript/src/parameter_type.js @@ -0,0 +1,32 @@ +class ParameterType { + constructor(name, constructorFunction, regexps, transform) { + this._name = name + this._constructorFunction = constructorFunction + this._regexps = stringArray(regexps) + // TODO: Check for null transform, don't use Identity elsewhere + this._transform = transform + } + + get name() { + return this._name + } + + get constructorFunction() { + return this._constructorFunction + } + + get regexps() { + return this._regexps + } + + transform(string) { + return this._transform(string) + } +} + +function stringArray(regexps) { + const array = Array.isArray(regexps) ? regexps : [regexps] + return array.map(r => typeof r == 'string' ? r : r.source) +} + +module.exports = ParameterType diff --git a/cucumber-expressions/javascript/src/parameter_matcher.js b/cucumber-expressions/javascript/src/parameter_type_matcher.js similarity index 52% rename from cucumber-expressions/javascript/src/parameter_matcher.js rename to cucumber-expressions/javascript/src/parameter_type_matcher.js index e2dc8b1681..0ced5cbebb 100644 --- a/cucumber-expressions/javascript/src/parameter_matcher.js +++ b/cucumber-expressions/javascript/src/parameter_type_matcher.js @@ -1,21 +1,21 @@ -class ParameterMatcher { +class ParameterTypeMatcher { - constructor(parameter, captureGroupRegexp, text, matchPosition) { - this._parameter = parameter - this._captureGroupRegexp = captureGroupRegexp + constructor(parameter, regexp, text, matchPosition) { + this._parameterType = parameter + this._regexp = regexp this._text = text this._matchPosition = matchPosition || 0 - const regexp = new RegExp(`(${captureGroupRegexp})`) - this._match = regexp.exec(text.slice(this._matchPosition)) + const captureGroupRegexp = new RegExp(`(${regexp})`) + this._match = captureGroupRegexp.exec(text.slice(this._matchPosition)) } - get parameter() { - return this._parameter + get parameterType() { + return this._parameterType } advanceTo(newMatchPosition) { - return new ParameterMatcher(this._parameter, this._captureGroupRegexp, this._text, newMatchPosition) + return new ParameterTypeMatcher(this._parameterType, this._regexp, this._text, newMatchPosition) } get find() { @@ -39,4 +39,4 @@ class ParameterMatcher { } } -module.exports = ParameterMatcher +module.exports = ParameterTypeMatcher diff --git a/cucumber-expressions/javascript/src/parameter_type_registry.js b/cucumber-expressions/javascript/src/parameter_type_registry.js new file mode 100644 index 0000000000..046f562393 --- /dev/null +++ b/cucumber-expressions/javascript/src/parameter_type_registry.js @@ -0,0 +1,92 @@ +const Parameter = require('./parameter_type') + +class ParameterTypeRegistry { + constructor() { + this._parameterTypesByTypeName = new Map() + this._parameterTypesByRegexp = new Map() + this._parameterTypesByConstructorName = new Map() + + const INTEGER_REGEXPS = [/-?\d+/, /\d+/] + const FLOAT_REGEXP = /-?\d*\.?\d+/ + + this._definePredefinedParameterType(new Parameter('int', Number, INTEGER_REGEXPS, parseInt)) + this._definePredefinedParameterType(new Parameter('float', Number, FLOAT_REGEXP, parseFloat)) + } + + get parameterTypes() { + return this._parameterTypesByTypeName.values() + } + + lookupByType(type) { + if (typeof type === 'function') { + return this.lookupByFunction(type) + } else if (typeof type === 'string') { + return this.lookupByTypeName(type) + } else { + throw new Error(`Type must be string or function, but was ${type} of type ${typeof type}`) + } + } + + lookupByFunction(fn) { + if (fn.name) { + const prefix = fn.name[0] + const looksLikeConstructor = prefix.toUpperCase() === prefix + + let parameter + if (looksLikeConstructor) { + parameter = this._parameterTypesByConstructorName.get(fn.name) + } + if (!parameter) { + const factory = s => { + if (looksLikeConstructor) { + return new fn(s) + } else { + return fn(s) + } + } + return this.createAnonymousLookup(factory) + } else { + return parameter + } + } else { + return this.createAnonymousLookup(fn) + } + } + + lookupByTypeName(typeName) { + return this._parameterTypesByTypeName.get(typeName) + } + + lookupByRegexp(regexp) { + return this._parameterTypesByRegexp.get(regexp) + } + + createAnonymousLookup(fn) { + return new Parameter(null, null, [".+"], fn) + } + + defineParameterType(parameterType) { + this._defineParameterType(parameterType, true) + } + + _definePredefinedParameterType(parameterType) { + this._defineParameterType(parameterType, false) + } + + _defineParameterType(parameterType, checkConflicts) { + set(this._parameterTypesByConstructorName, parameterType.constructorFunction.name, parameterType, 'constructor', checkConflicts) + set(this._parameterTypesByTypeName, parameterType.name, parameterType, 'type name', checkConflicts) + + for (const regexp of parameterType.regexps) { + set(this._parameterTypesByRegexp, regexp, parameterType, 'regexp', checkConflicts) + } + } +} + +function set(map, key, value, prop, checkConflicts) { + if(checkConflicts && map.has(key)) + throw new Error(`There is already a parameter with ${prop} ${key}`) + map.set(key, value) +} + +module.exports = ParameterTypeRegistry diff --git a/cucumber-expressions/javascript/src/regular_expression.js b/cucumber-expressions/javascript/src/regular_expression.js index f0d02ea2d2..8e26a85d7f 100644 --- a/cucumber-expressions/javascript/src/regular_expression.js +++ b/cucumber-expressions/javascript/src/regular_expression.js @@ -1,9 +1,9 @@ -const matchPattern = require('./build_arguments') +const buildArguments = require('./build_arguments') class RegularExpression { - constructor(regexp, types, parameterRegistry) { + constructor(regexp, types, parameterTypeRegistry) { this._regexp = regexp - this._parameters = [] + this._parameterTypes = [] const CAPTURE_GROUP_PATTERN = /\(([^(]+)\)/g @@ -13,22 +13,22 @@ class RegularExpression { const captureGroupPattern = match[1] const type = types.length <= typeIndex ? null : types[typeIndex++] - let parameter + let parameterType if (type) { - parameter = parameterRegistry.lookupByType(type) + parameterType = parameterTypeRegistry.lookupByType(type) } - if (!parameter) { - parameter = parameterRegistry.lookupByCaptureGroupRegexp(captureGroupPattern) + if (!parameterType) { + parameterType = parameterTypeRegistry.lookupByRegexp(captureGroupPattern) } - if (!parameter) { - parameter = parameterRegistry.createAnonymousLookup(s => s) + if (!parameterType) { + parameterType = parameterTypeRegistry.createAnonymousLookup(s => s) } - this._parameters.push(parameter) + this._parameterTypes.push(parameterType) } } match(text) { - return matchPattern(this._regexp, text, this._parameters) + return buildArguments(this._regexp, text, this._parameterTypes) } getSource() { diff --git a/cucumber-expressions/javascript/test/cucumber_expression_generator_test.js b/cucumber-expressions/javascript/test/cucumber_expression_generator_test.js index 1d5eba33c1..8894e2ac64 100644 --- a/cucumber-expressions/javascript/test/cucumber_expression_generator_test.js +++ b/cucumber-expressions/javascript/test/cucumber_expression_generator_test.js @@ -1,15 +1,15 @@ /* eslint-env mocha */ const assert = require('assert') const CucumberExpressionGenerator = require('../src/cucumber_expression_generator') -const Parameter = require('../src/parameter') -const ParameterRegistry = require('../src/parameter_registry') +const ParameterType = require('../src/parameter_type') +const ParameterTypeRegistry = require('../src/parameter_type_registry') class Currency { } describe(CucumberExpressionGenerator.name, () => { - let parameterRegistry, generator + let parameterTypeRegistry, generator function assertExpression(expectedExpression, expectedArgumentNames, text) { const generatedExpression = generator.generateExpression(text) @@ -18,19 +18,19 @@ describe(CucumberExpressionGenerator.name, () => { } beforeEach(() => { - parameterRegistry = new ParameterRegistry() - generator = new CucumberExpressionGenerator(parameterRegistry) + parameterTypeRegistry = new ParameterTypeRegistry() + generator = new CucumberExpressionGenerator(parameterTypeRegistry) }) it("documents expression generation", () => { - const parameterRegistry = new ParameterRegistry() + const parameterRegistry = new ParameterTypeRegistry() /// [generate-expression] const generator = new CucumberExpressionGenerator(parameterRegistry) const undefinedStepText = "I have 2 cucumbers and 1.5 tomato" const generatedExpression = generator.generateExpression(undefinedStepText) assert.equal(generatedExpression.source, "I have {int} cucumbers and {float} tomato") assert.equal(generatedExpression.parameterNames[0], 'int') - assert.equal(generatedExpression.parameters[1].typeName, 'float') + assert.equal(generatedExpression.parameterTypes[1].name, 'float') /// [generate-expression] }) @@ -57,7 +57,7 @@ describe(CucumberExpressionGenerator.name, () => { }) it("generates expression for custom type", () => { - parameterRegistry.addParameter(new Parameter( + parameterTypeRegistry.defineParameterType(new ParameterType( 'currency', Currency, '[A-Z]{3}', @@ -70,13 +70,13 @@ describe(CucumberExpressionGenerator.name, () => { }) it("prefers leftmost match when there is overlap", () => { - parameterRegistry.addParameter(new Parameter( + parameterTypeRegistry.defineParameterType(new ParameterType( 'currency', Currency, 'cd', null )) - parameterRegistry.addParameter(new Parameter( + parameterTypeRegistry.defineParameterType(new ParameterType( 'date', Date, 'bc', @@ -90,7 +90,7 @@ describe(CucumberExpressionGenerator.name, () => { it("exposes parameter type names in generated expression", () => { const expression = generator.generateExpression("I have 2 cukes and 1.5 euro") - const typeNames = expression.parameters.map(parameter => parameter.typeName) + const typeNames = expression.parameterTypes.map(parameter => parameter.name) assert.deepEqual(typeNames, ['int', 'float']) }) }) diff --git a/cucumber-expressions/javascript/test/cucumber_expression_regexp_test.js b/cucumber-expressions/javascript/test/cucumber_expression_regexp_test.js index cab69a00e5..f3c677f30c 100644 --- a/cucumber-expressions/javascript/test/cucumber_expression_regexp_test.js +++ b/cucumber-expressions/javascript/test/cucumber_expression_regexp_test.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ const assert = require('assert') const CucumberExpression = require('../src/cucumber_expression') -const TransformLookup = require('../src/parameter_registry') +const ParameterTypeRegistry = require('../src/parameter_type_registry') describe(CucumberExpression.name, () => { describe('RegExp translation', () => { @@ -43,6 +43,6 @@ describe(CucumberExpression.name, () => { }) const assertRegexp = (expression, expectedRegexp) => { - const cucumberExpression = new CucumberExpression(expression, [], new TransformLookup()) + const cucumberExpression = new CucumberExpression(expression, [], new ParameterTypeRegistry()) assert.deepEqual(cucumberExpression._regexp, expectedRegexp) } diff --git a/cucumber-expressions/javascript/test/cucumber_expression_test.js b/cucumber-expressions/javascript/test/cucumber_expression_test.js index 3582219635..6ab5bdf4b7 100644 --- a/cucumber-expressions/javascript/test/cucumber_expression_test.js +++ b/cucumber-expressions/javascript/test/cucumber_expression_test.js @@ -1,15 +1,15 @@ /* eslint-env mocha */ const assert = require('assert') -const { CucumberExpression, ParameterRegistry } = require('../src/index') +const { CucumberExpression, ParameterTypeRegistry } = require('../src/index') describe(CucumberExpression.name, () => { it("documents match arguments", () => { - const parameterRegistry = new ParameterRegistry() + const parameterTypeRegistry = new ParameterTypeRegistry() /// [capture-match-arguments] const expr = "I have {n} cuke(s) in my {bodypart} now" const types = ['int', null] - const expression = new CucumberExpression(expr, types, parameterRegistry) + const expression = new CucumberExpression(expr, types, parameterTypeRegistry) const args = expression.match("I have 7 cukes in my belly now") assert.equal(7, args[0].transformedValue) assert.equal("belly", args[1].transformedValue) @@ -20,7 +20,7 @@ describe(CucumberExpression.name, () => { assert.deepEqual(match("{what}", "22"), ["22"]) }) - it("transforms to int by parameter type", () => { + it("transforms to int by parameterType type", () => { assert.deepEqual(match("{int}", "22"), [22]) }) @@ -28,11 +28,11 @@ describe(CucumberExpression.name, () => { assert.deepEqual(match("{what}", "22", ['int']), [22]) }) - it("doesn't match a float with an int parameter", () => { + it("doesn't match a float with an int parameterType", () => { assert.deepEqual(match("{int}", "1.22"), null) }) - it("transforms to float by parameter type", () => { + it("transforms to float by parameterType type", () => { assert.deepEqual(match("{float}", "0.22"), [0.22]) assert.deepEqual(match("{float}", ".22"), [0.22]) }) @@ -52,12 +52,12 @@ describe(CucumberExpression.name, () => { it("exposes source", () => { const expr = "I have {int} cuke(s) in my {bodypart} now" - assert.equal(new CucumberExpression(expr, [], new ParameterRegistry()).source, expr) + assert.equal(new CucumberExpression(expr, [], new ParameterTypeRegistry()).source, expr) }) it("exposes offset and value", () => { const expr = "I have {int} cuke(s) in my {bodypart} now" - const expression = new CucumberExpression(expr, [], new ParameterRegistry()) + const expression = new CucumberExpression(expr, [], new ParameterTypeRegistry()) const arg1 = expression.match("I have 800 cukes in my brain now")[0] assert.equal(arg1.offset, 7) assert.equal(arg1.value, "800") @@ -67,7 +67,7 @@ describe(CucumberExpression.name, () => { ['\\', '[', ']', '^', '$', '.', '|', '?', '*', '+'].forEach((character) => { it(`escapes ${character}`, () => { const expr = `I have {int} cuke(s) and ${character}` - const expression = new CucumberExpression(expr, [], new ParameterRegistry()) + const expression = new CucumberExpression(expr, [], new ParameterTypeRegistry()) const arg1 = expression.match(`I have 800 cukes and ${character}`)[0] assert.equal(arg1.offset, 7) assert.equal(arg1.value, "800") @@ -76,7 +76,7 @@ describe(CucumberExpression.name, () => { it(`escapes .`, () => { const expr = `I have {int} cuke(s) and .` - const expression = new CucumberExpression(expr, [], new ParameterRegistry()) + const expression = new CucumberExpression(expr, [], new ParameterTypeRegistry()) assert.equal(expression.match(`I have 800 cukes and 3`), null) const arg1 = expression.match(`I have 800 cukes and .`)[0] assert.equal(arg1.offset, 7) @@ -85,7 +85,7 @@ describe(CucumberExpression.name, () => { it(`escapes |`, () => { const expr = `I have {int} cuke(s) and a|b` - const expression = new CucumberExpression(expr, [], new ParameterRegistry()) + const expression = new CucumberExpression(expr, [], new ParameterTypeRegistry()) assert.equal(expression.match(`I have 800 cukes and a`), null) assert.equal(expression.match(`I have 800 cukes and b`), null) const arg1 = expression.match(`I have 800 cukes and a|b`)[0] @@ -96,7 +96,7 @@ describe(CucumberExpression.name, () => { }) const match = (expression, text, types) => { - const cucumberExpression = new CucumberExpression(expression, types || [], new ParameterRegistry()) + const cucumberExpression = new CucumberExpression(expression, types || [], new ParameterTypeRegistry()) const args = cucumberExpression.match(text) if (!args) return null return args.map(arg => arg.transformedValue) diff --git a/cucumber-expressions/javascript/test/custom_parameter_test.js b/cucumber-expressions/javascript/test/custom_parameter_type_test.js similarity index 75% rename from cucumber-expressions/javascript/test/custom_parameter_test.js rename to cucumber-expressions/javascript/test/custom_parameter_type_test.js index 885ff5b679..9343c6cd93 100644 --- a/cucumber-expressions/javascript/test/custom_parameter_test.js +++ b/cucumber-expressions/javascript/test/custom_parameter_type_test.js @@ -5,8 +5,8 @@ const assert = require('assert') const assertThrows = require('./assert_throws') const CucumberExpression = require('../src/cucumber_expression') const RegularExpression = require('../src/regular_expression') -const ParameterRegistry = require('../src/parameter_registry') -const Parameter = require('../src/parameter') +const ParameterTypeRegistry = require('../src/parameter_type_registry') +const ParameterType = require('../src/parameter_type') class Color { /// [color-constructor] @@ -16,69 +16,69 @@ class Color { /// [color-constructor] } -describe('Custom parameter', () => { - let parameterRegistry +describe('Custom parameter type', () => { + let parameterTypeRegistry beforeEach(() => { - parameterRegistry = new ParameterRegistry() - /// [add-color-parameter] - parameterRegistry.addParameter(new Parameter( + parameterTypeRegistry = new ParameterTypeRegistry() + /// [add-color-parameter-type] + parameterTypeRegistry.defineParameterType(new ParameterType( 'color', Color, /red|blue|yellow/, s => new Color(s) )) - /// [add-color-parameter] + /// [add-color-parameter-type] }) describe(CucumberExpression.name, () => { it("matches typed parameters", () => { - const expression = new CucumberExpression("I have a {color} ball", [], parameterRegistry) + const expression = new CucumberExpression("I have a {color} ball", [], parameterTypeRegistry) const transformedValue = expression.match("I have a red ball")[0].transformedValue assert.equal(transformedValue.name, "red") }) it("matches typed parameters with optional group", () => { - parameterRegistry = new ParameterRegistry() - parameterRegistry.addParameter(new Parameter( + parameterTypeRegistry = new ParameterTypeRegistry() + parameterTypeRegistry.defineParameterType(new ParameterType( 'color', Color, [/red|blue|yellow/, /(?:dark|light) (?:red|blue|yellow)/], s => new Color(s) )) - const expression = new CucumberExpression("I have a {color} ball", [], parameterRegistry) + const expression = new CucumberExpression("I have a {color} ball", [], parameterTypeRegistry) const transformedValue = expression.match("I have a dark red ball")[0].transformedValue assert.equal(transformedValue.name, "dark red") }) it("matches untyped parameters with explicit type", () => { - const expression = new CucumberExpression("I have a {color} ball", [Color], parameterRegistry) + const expression = new CucumberExpression("I have a {color} ball", [Color], parameterTypeRegistry) const transformedValue = expression.match("I have a red ball")[0].transformedValue assert.equal(transformedValue.name, "red") }) it("matches untyped parameters with same name as type", () => { - const expression = new CucumberExpression("I have a {color} ball", [], parameterRegistry) + const expression = new CucumberExpression("I have a {color} ball", [], parameterTypeRegistry) const transformedValue = expression.match("I have a red ball")[0].transformedValue assert.equal(transformedValue.name, "red") }) it("defers transformation until queried from argument", () => { - parameterRegistry.addParameter(new Parameter( + parameterTypeRegistry.defineParameterType(new ParameterType( 'throwing', () => null, /bad/, s => { throw new Error(`Can't transform [${s}]`) } )) - const expression = new CucumberExpression("I have a {throwing} parameter", [], parameterRegistry) + const expression = new CucumberExpression("I have a {throwing} parameter", [], parameterTypeRegistry) const args = expression.match("I have a bad parameter") assertThrows(() => args[0].transformedValue, "Can't transform [bad]") }) describe("conflicting parameter type", () => { it("is detected for type name", () => { - assertThrows(() => parameterRegistry.addParameter(new Parameter( + assertThrows(() => parameterTypeRegistry.defineParameterType(new ParameterType( 'color', String, /.*/, @@ -87,7 +87,7 @@ describe('Custom parameter', () => { }) it("is detected for constructor", () => { - assertThrows(() => parameterRegistry.addParameter(new Parameter( + assertThrows(() => parameterTypeRegistry.defineParameterType(new ParameterType( 'color2', Color, /.*/, @@ -96,7 +96,7 @@ describe('Custom parameter', () => { }) it("is detected for regexp", () => { - assertThrows(() => parameterRegistry.addParameter(new Parameter( + assertThrows(() => parameterTypeRegistry.defineParameterType(new ParameterType( 'color2', String, /red|blue|yellow/, @@ -107,24 +107,24 @@ describe('Custom parameter', () => { // JavaScript-specific it("matches untyped parameters with explicit type name", () => { - const expression = new CucumberExpression("I have a {color} ball", ['color'], parameterRegistry) + const expression = new CucumberExpression("I have a {color} ball", ['color'], parameterTypeRegistry) const transformedValue = expression.match("I have a red ball")[0].transformedValue assert.equal(transformedValue.name, "red") }) // JavaScript-specific it("creates arguments using async transform", async () => { - parameterRegistry = new ParameterRegistry() - /// [add-async-parameter] - parameterRegistry.addParameter(new Parameter( + parameterTypeRegistry = new ParameterTypeRegistry() + /// [add-async-parameterType] + parameterTypeRegistry.defineParameterType(new ParameterType( 'asyncColor', Color, /red|blue|yellow/, async s => new Color(s) )) - /// [add-async-parameter] + /// [add-async-parameterType] - const expression = new CucumberExpression("I have a {asyncColor} ball", ['asyncColor'], parameterRegistry) + const expression = new CucumberExpression("I have a {asyncColor} ball", ['asyncColor'], parameterTypeRegistry) const args = await expression.match("I have a red ball") const transformedValue = await args[0].transformedValue assert.equal(transformedValue.name, "red") @@ -133,26 +133,26 @@ describe('Custom parameter', () => { describe(RegularExpression.name, () => { it("matches parameters with explicit constructor", () => { - const expression = new RegularExpression(/I have a (red|blue|yellow) ball/, [Color], parameterRegistry) + const expression = new RegularExpression(/I have a (red|blue|yellow) ball/, [Color], parameterTypeRegistry) const transformedValue = expression.match("I have a red ball")[0].transformedValue assert.equal(transformedValue.name, "red") }) it("matches parameters without explicit constructor", () => { - const expression = new RegularExpression(/I have a (red|blue|yellow) ball/, [], parameterRegistry) + const expression = new RegularExpression(/I have a (red|blue|yellow) ball/, [], parameterTypeRegistry) const transformedValue = expression.match("I have a red ball")[0].transformedValue assert.equal(transformedValue.name, "red") }) it("matches parameters with explicit type that isn't registered", () => { - const expression = new RegularExpression(/I have a (red|blue|yellow) ball/, [Color], new ParameterRegistry()) + const expression = new RegularExpression(/I have a (red|blue|yellow) ball/, [Color], new ParameterTypeRegistry()) const transformedValue = expression.match("I have a red ball")[0].transformedValue assert.equal(transformedValue.name, "red") }) // JavaScript-specific (specifying type as string) it("matches parameters without explicit type name", () => { - const expression = new RegularExpression(/I have a (red|blue|yellow) ball/, ['color'], parameterRegistry) + const expression = new RegularExpression(/I have a (red|blue|yellow) ball/, ['color'], parameterTypeRegistry) const transformedValue = expression.match("I have a red ball")[0].transformedValue assert.equal(transformedValue.name, "red") }) diff --git a/cucumber-expressions/javascript/test/expression_examples_test.js b/cucumber-expressions/javascript/test/expression_examples_test.js index a69ded0f12..437c68d21a 100644 --- a/cucumber-expressions/javascript/test/expression_examples_test.js +++ b/cucumber-expressions/javascript/test/expression_examples_test.js @@ -3,14 +3,14 @@ const fs = require('fs') const assert = require('assert') const CucumberExpression = require('../src/cucumber_expression') const RegularExpression = require('../src/regular_expression') -const TransformLookup = require('../src/parameter_registry') +const ParameterTypeRegistry = require('../src/parameter_type_registry') describe('examples.txt', () => { const match = (expression_text, text) => { const m = /\/(.*)\//.exec(expression_text) const expression = m ? - new RegularExpression(new RegExp(m[1]), [], new TransformLookup()) : - new CucumberExpression(expression_text, [], new TransformLookup()) + new RegularExpression(new RegExp(m[1]), [], new ParameterTypeRegistry()) : + new CucumberExpression(expression_text, [], new ParameterTypeRegistry()) const args = expression.match(text) if (!args) return null return args.map(arg => arg.transformedValue) @@ -18,10 +18,10 @@ describe('examples.txt', () => { const examples = fs.readFileSync("examples.txt", "utf-8") const chunks = examples.split(/^---/m) - for (let chunk of chunks) { - const [expression_text, text, expected_args] = chunk.trim().split(/\n/m) - it(`Works with: ${expression_text}`, () => { - assert.deepEqual(JSON.stringify(match(expression_text, text)), expected_args) + for (const chunk of chunks) { + const [expressionText, text, expectedArgs] = chunk.trim().split(/\n/m) + it(`Works with: ${expressionText}`, () => { + assert.deepEqual(JSON.stringify(match(expressionText, text)), expectedArgs) }) } diff --git a/cucumber-expressions/javascript/test/regular_expression_test.js b/cucumber-expressions/javascript/test/regular_expression_test.js index 5a0820ffa8..acee347b88 100644 --- a/cucumber-expressions/javascript/test/regular_expression_test.js +++ b/cucumber-expressions/javascript/test/regular_expression_test.js @@ -2,11 +2,11 @@ const assert = require('assert') const assertThrows = require('./assert_throws') const RegularExpression = require('../src/regular_expression') -const TransformLookup = require('../src/parameter_registry') +const ParameterTypeRegistry = require('../src/parameter_type_registry') describe(RegularExpression.name, () => { it("documents match arguments", () => { - const parameterRegistry = new TransformLookup() + const parameterRegistry = new ParameterTypeRegistry() /// [capture-match-arguments] const expr = /I have (\d+) cukes? in my (\w+) now/ @@ -30,11 +30,11 @@ describe(RegularExpression.name, () => { assert.deepEqual(match(/(.*)/, "22", [parseFloat]), [22.0]) }) - it("transforms int by parameter pattern", () => { + it("transforms int by parameterType pattern", () => { assert.deepEqual(match(/(-?\d+)/, "22"), [22]) }) - it("transforms int by alternate parameter pattern", () => { + it("transforms int by alternate parameterType pattern", () => { assert.deepEqual(match(/(\d+)/, "22"), [22]) }) @@ -67,12 +67,12 @@ describe(RegularExpression.name, () => { it("exposes source", () => { const expr = /I have (\d+) cukes? in my (.+) now/ - assert.deepEqual(new RegularExpression(expr, [], new TransformLookup()).getSource(), expr.toString()) + assert.deepEqual(new RegularExpression(expr, [], new ParameterTypeRegistry()).getSource(), expr.toString()) }) }) const match = (regexp, text, types) => { - var parameterRegistry = new TransformLookup() + const parameterRegistry = new ParameterTypeRegistry() const regularExpression = new RegularExpression(regexp, types || [], parameterRegistry) const args = regularExpression.match(text) if (!args) return null diff --git a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/argument.rb b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/argument.rb index a062f11a9a..673d1d084a 100644 --- a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/argument.rb +++ b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/argument.rb @@ -3,12 +3,12 @@ module CucumberExpressions class Argument attr_reader :offset, :value - def initialize(offset, value, parameter) - @offset, @value, @parameter = offset, value, parameter + def initialize(offset, value, parameter_type) + @offset, @value, @parameter_type = offset, value, parameter_type end def transformed_value - @parameter.transform(@value) + @parameter_type.transform(@value) end end end diff --git a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/argument_builder.rb b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/argument_builder.rb index a9299b3f77..17e8667ae5 100644 --- a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/argument_builder.rb +++ b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/argument_builder.rb @@ -3,13 +3,13 @@ module Cucumber module CucumberExpressions class ArgumentBuilder - def self.build_arguments(regexp, text, parameters) + def self.build_arguments(regexp, text, parameter_types) m = regexp.match(text) return nil if m.nil? (1...m.length).map do |index| value = m[index] - parameter = parameters[index-1] - Argument.new(m.offset(index)[0], value, parameter) + parameter_type = parameter_types[index-1] + Argument.new(m.offset(index)[0], value, parameter_type) end end end diff --git a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/cucumber_expression.rb b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/cucumber_expression.rb index 7a4ff0b40a..9479f0dc37 100644 --- a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/cucumber_expression.rb +++ b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/cucumber_expression.rb @@ -1,5 +1,5 @@ require 'cucumber/cucumber_expressions/argument_builder' -require 'cucumber/cucumber_expressions/parameter' +require 'cucumber/cucumber_expressions/parameter_type' module Cucumber module CucumberExpressions @@ -10,9 +10,9 @@ class CucumberExpression attr_reader :source - def initialize(expression, types, parameter_registry) + def initialize(expression, types, parameter_type_registry) @source = expression - @parameters = [] + @parameter_types = [] regexp = "^" type_index = 0 match_offset = 0 @@ -32,31 +32,31 @@ def initialize(expression, types, parameter_registry) break if match.nil? parameter_name = match[1] - type_name = match[3] - if type_name - $stderr.puts("Cucumber expression parameter syntax {#{parameter_name}:#{type_name}} is deprecated. Please use {#{type_name}} instead.") + parameter_type_name = match[3] + if parameter_type_name + $stderr.puts("Cucumber expression parameter syntax {#{parameter_name}:#{parameter_type_name}} is deprecated. Please use {#{parameter_type_name}} instead.") end type = types.length <= type_index ? nil : types[type_index] type_index += 1 - parameter = nil + parameter_type = nil if type - parameter = parameter_registry.lookup_by_type(type) + parameter_type = parameter_type_registry.lookup_by_type(type) end - if parameter.nil? && type_name - parameter = parameter_registry.lookup_by_type_name(type_name) + if parameter_type.nil? && parameter_type_name + parameter_type = parameter_type_registry.lookup_by_name(parameter_type_name) end - if parameter.nil? - parameter = parameter_registry.lookup_by_type_name(parameter_name) + if parameter_type.nil? + parameter_type = parameter_type_registry.lookup_by_name(parameter_name) end - if parameter.nil? - parameter = parameter_registry.create_anonymous_lookup(lambda {|s| s}) + if parameter_type.nil? + parameter_type = parameter_type_registry.create_anonymous_lookup(lambda {|s| s}) end - @parameters.push(parameter) + @parameter_types.push(parameter_type) text = expression.slice(match_offset...match.offset(0)[0]) - capture_regexp = capture_group_regexp(parameter.capture_group_regexps) + capture_regexp = regexp(parameter_type.regexps) match_offset = match.offset(0)[1] regexp += text regexp += capture_regexp @@ -67,14 +67,14 @@ def initialize(expression, types, parameter_registry) end def match(text) - ArgumentBuilder.build_arguments(@regexp, text, @parameters) + ArgumentBuilder.build_arguments(@regexp, text, @parameter_types) end private - def capture_group_regexp(capture_group_regexps) - return "(#{capture_group_regexps[0]})" if capture_group_regexps.size == 1 - capture_groups = capture_group_regexps.map { |group| "(?:#{group})" } + def regexp(regexps) + return "(#{regexps[0]})" if regexps.size == 1 + capture_groups = regexps.map { |group| "(?:#{group})" } "(#{capture_groups.join('|')})" end end diff --git a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/cucumber_expression_generator.rb b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/cucumber_expression_generator.rb index dc732cfaf8..8424e8279d 100644 --- a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/cucumber_expression_generator.rb +++ b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/cucumber_expression_generator.rb @@ -1,44 +1,44 @@ -require 'cucumber/cucumber_expressions/parameter_matcher' +require 'cucumber/cucumber_expressions/parameter_type_matcher' require 'cucumber/cucumber_expressions/generated_expression' module Cucumber module CucumberExpressions class CucumberExpressionGenerator - def initialize(parameter_registry) - @parameter_registry = parameter_registry + def initialize(parameter_type_registry) + @parameter_type_registry = parameter_type_registry end def generate_expression(text) parameter_names = [] - parameter_matchers = create_parameter_matchers(text) - parameters = [] - usage_by_type_name = Hash.new(0) + parameter_type_matchers = create_parameter_type_matchers(text) + parameter_types = [] + usage_by_name = Hash.new(0) expression = "" pos = 0 loop do - matching_parameter_matchers = [] - parameter_matchers.each do |parameter_matcher| - advanced_parameter_matcher = parameter_matcher.advance_to(pos) - if advanced_parameter_matcher.find - matching_parameter_matchers.push(advanced_parameter_matcher) + matching_parameter_type_matchers = [] + parameter_type_matchers.each do |parameter_type_matcher| + advanced_parameter_type_matcher = parameter_type_matcher.advance_to(pos) + if advanced_parameter_type_matcher.find + matching_parameter_type_matchers.push(advanced_parameter_type_matcher) end end - if matching_parameter_matchers.any? - matching_parameter_matchers = matching_parameter_matchers.sort - best_parameter_matcher = matching_parameter_matchers[0] - parameter = best_parameter_matcher.parameter - parameters.push(parameter) + if matching_parameter_type_matchers.any? + matching_parameter_type_matchers = matching_parameter_type_matchers.sort + best_parameter_type_matcher = matching_parameter_type_matchers[0] + parameter_type = best_parameter_type_matcher.parameter + parameter_types.push(parameter_type) - parameter_name = get_parameter_name(parameter.type_name, usage_by_type_name) + parameter_name = get_parameter_name(parameter_type.name, usage_by_name) parameter_names.push(parameter_name) - expression += text.slice(pos...best_parameter_matcher.start) - expression += "{#{parameter.type_name}}" + expression += text.slice(pos...best_parameter_type_matcher.start) + expression += "{#{parameter_type.name}}" - pos = best_parameter_matcher.start + best_parameter_matcher.group.length + pos = best_parameter_type_matcher.start + best_parameter_type_matcher.group.length else break end @@ -49,30 +49,30 @@ def generate_expression(text) end expression += text.slice(pos..-1) - GeneratedExpression.new(expression, parameter_names, parameters) + GeneratedExpression.new(expression, parameter_names, parameter_types) end private - def get_parameter_name(type_name, usage_by_type_name) - count = (usage_by_type_name[type_name] += 1) - count == 1 ? type_name : "#{type_name}#{count}" + def get_parameter_name(name, usage_by_name) + count = (usage_by_name[name] += 1) + count == 1 ? name : "#{name}#{count}" end - def create_parameter_matchers(text) + def create_parameter_type_matchers(text) parameter_matchers = [] - @parameter_registry.parameters.each do |parameter| - parameter_matchers += create_parameter_matchers2(parameter, text) + @parameter_type_registry.parameter_types.each do |parameter_type| + parameter_matchers += create_parameter_type_matchers2(parameter_type, text) end parameter_matchers end - def create_parameter_matchers2(parameter, text) + def create_parameter_type_matchers2(parameter_type, text) result = [] - capture_group_regexps = parameter.capture_group_regexps - capture_group_regexps.each do |capture_group_regexp| - regexp = Regexp.new("(#{capture_group_regexp})") - result.push(ParameterMatcher.new(parameter, regexp, text)) + regexps = parameter_type.regexps + regexps.each do |regexp| + regexp = Regexp.new("(#{regexp})") + result.push(ParameterTypeMatcher.new(parameter_type, regexp, text)) end result end diff --git a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/generated_expression.rb b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/generated_expression.rb index 95b39fc871..8950cc02f2 100644 --- a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/generated_expression.rb +++ b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/generated_expression.rb @@ -1,10 +1,10 @@ module Cucumber module CucumberExpressions class GeneratedExpression - attr_reader :source, :parameter_names, :parameters + attr_reader :source, :parameter_names, :parameter_types - def initialize(source, parameter_names, parameters) - @source, @parameter_names, @parameters = source, parameter_names, parameters + def initialize(source, parameter_names, parameters_types) + @source, @parameter_names, @parameter_types = source, parameter_names, parameters_types end end end diff --git a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter.rb b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter.rb deleted file mode 100644 index acd5158f5c..0000000000 --- a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter.rb +++ /dev/null @@ -1,29 +0,0 @@ -module Cucumber - module CucumberExpressions - class Parameter - attr_reader :type_name, :type, :capture_group_regexps - - # Create a new Parameter - # - # @param type_name [Array] array of class or type name to use in {arg:type_name} - # @param capture_group_regexps [Array] list of regexps for capture groups. - # @param transformer lambda that transforms a String to (possibly) another type - # - def initialize(type_name, type, capture_group_regexps, transformer) - @type_name, @type, @transformer = type_name, type, transformer - @capture_group_regexps = string_array(capture_group_regexps) - end - - def transform(value) - @transformer.call(value) - end - - private - - def string_array(capture_group_regexps) - array = capture_group_regexps.is_a?(Array) ? capture_group_regexps : [capture_group_regexps] - array.map { |r| r.is_a?(String) ? r : r.source } - end - end - end -end diff --git a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_registry.rb b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_registry.rb deleted file mode 100644 index c9d00c2d44..0000000000 --- a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_registry.rb +++ /dev/null @@ -1,80 +0,0 @@ -require 'cucumber/cucumber_expressions/parameter' - -module Cucumber - module CucumberExpressions - class ParameterRegistry - INTEGER_REGEXPS = [/-?\d+/, /\d+/] - FLOAT_REGEXP = /-?\d*\.?\d+/ - - def initialize - @parameters_by_type_name = {} - @parameters_by_capture_group_regexp = {} - @parameters_by_class = {} - - add_predefined_parameter(Parameter.new('int', Integer, INTEGER_REGEXPS, lambda { |s| s.to_i })) - add_predefined_parameter(Parameter.new('float', Float, FLOAT_REGEXP, lambda { |s| s.to_f })) - end - - def lookup_by_type(type) - if type.is_a?(Class) - lookup_by_class(type) - elsif type.is_a?(String) - lookup_by_type_name(type) - else - raise Exception.new("Type must be string or class, but was #{type} of type #{type.class}") - end - end - - def lookup_by_class(clazz) - parameter = @parameters_by_class[clazz] - if parameter.nil? - create_anonymous_lookup(lambda { |s| clazz.new(s) }) - else - parameter - end - end - - def lookup_by_type_name(type_name) - @parameters_by_type_name[type_name] - end - - def lookup_by_capture_group_regexp(capture_group_regexp) - @parameters_by_capture_group_regexp[capture_group_regexp] - end - - def create_anonymous_lookup(proc) - Parameter.new(nil, nil, ['.+'], proc) - end - - def parameters - @parameters_by_type_name.values - end - - def add_parameter(parameter) - add_parameter0(parameter, true) - end - - private - - def add_predefined_parameter(parameter) - add_parameter0(parameter, false) - end - - def add_parameter0(parameter, check_conflicts) - put(@parameters_by_type_name, parameter.type_name, parameter, "type name", check_conflicts) - put(@parameters_by_class, parameter.type, parameter, "type", check_conflicts) - - parameter.capture_group_regexps.each do |capture_group_regexp| - put(@parameters_by_capture_group_regexp, capture_group_regexp, parameter, "regexp", check_conflicts) - end - end - - def put(map, key, parameter, prop, check_conflicts) - if check_conflicts && map.has_key?(key) - raise "There is already a parameter with #{prop} #{key}" - end - map[key] = parameter - end - end - end -end diff --git a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_type.rb b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_type.rb new file mode 100644 index 0000000000..380df943d6 --- /dev/null +++ b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_type.rb @@ -0,0 +1,29 @@ +module Cucumber + module CucumberExpressions + class ParameterType + attr_reader :name, :type, :regexps + + # Create a new Parameter + # + # @param name the name of the parameter type + # @param regexps [Array] list of regexps for capture groups. A single regexp can also be used. + # @param transformer lambda that transforms a String to (possibly) another type + # + def initialize(name, type, regexps, transformer) + @name, @type, @transformer = name, type, transformer + @regexps = string_array(regexps) + end + + def transform(value) + @transformer.call(value) + end + + private + + def string_array(regexps) + array = regexps.is_a?(Array) ? regexps : [regexps] + array.map { |r| r.is_a?(String) ? r : r.source } + end + end + end +end diff --git a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_matcher.rb b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_type_matcher.rb similarity index 96% rename from cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_matcher.rb rename to cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_type_matcher.rb index e089616769..4c671de261 100644 --- a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_matcher.rb +++ b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_type_matcher.rb @@ -1,6 +1,6 @@ module Cucumber module CucumberExpressions - class ParameterMatcher + class ParameterTypeMatcher attr_reader :parameter def initialize(parameter, regexp, text, match_position=0) diff --git a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_type_registry.rb b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_type_registry.rb new file mode 100644 index 0000000000..cee85d2e70 --- /dev/null +++ b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/parameter_type_registry.rb @@ -0,0 +1,80 @@ +require 'cucumber/cucumber_expressions/parameter_type' + +module Cucumber + module CucumberExpressions + class ParameterTypeRegistry + INTEGER_REGEXPS = [/-?\d+/, /\d+/] + FLOAT_REGEXP = /-?\d*\.?\d+/ + + def initialize + @parameter_types_by_name = {} + @parameter_types_by_regexp = {} + @parameter_types_by_class = {} + + define_predefined_parameter_type(ParameterType.new('int', Integer, INTEGER_REGEXPS, lambda { |s| s.to_i })) + define_predefined_parameter_type(ParameterType.new('float', Float, FLOAT_REGEXP, lambda { |s| s.to_f })) + end + + def lookup_by_type(type) + if type.is_a?(Class) + lookup_by_class(type) + elsif type.is_a?(String) + lookup_by_name(type) + else + raise Exception.new("Type must be string or class, but was #{type} of type #{type.class}") + end + end + + def lookup_by_class(clazz) + parameter = @parameter_types_by_class[clazz] + if parameter.nil? + create_anonymous_lookup(lambda { |s| clazz.new(s) }) + else + parameter + end + end + + def lookup_by_name(name) + @parameter_types_by_name[name] + end + + def lookup_by_regexp(regexp) + @parameter_types_by_regexp[regexp] + end + + def create_anonymous_lookup(proc) + ParameterType.new(nil, nil, ['.+'], proc) + end + + def parameter_types + @parameter_types_by_name.values + end + + def define_parameter_type(parameter_type) + define_parameter_type0(parameter_type, true) + end + + private + + def define_predefined_parameter_type(parameter_type) + define_parameter_type0(parameter_type, false) + end + + def define_parameter_type0(parameter_type, check_conflicts) + put(@parameter_types_by_name, parameter_type.name, parameter_type, "type name", check_conflicts) + put(@parameter_types_by_class, parameter_type.type, parameter_type, "type", check_conflicts) + + parameter_type.regexps.each do |regexp| + put(@parameter_types_by_regexp, regexp, parameter_type, "regexp", check_conflicts) + end + end + + def put(map, key, parameter, prop, check_conflicts) + if check_conflicts && map.has_key?(key) + raise "There is already a parameter with #{prop} #{key}" + end + map[key] = parameter + end + end + end +end diff --git a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/regular_expression.rb b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/regular_expression.rb index 0b2181439b..c6f9c628d6 100644 --- a/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/regular_expression.rb +++ b/cucumber-expressions/ruby/lib/cucumber/cucumber_expressions/regular_expression.rb @@ -5,9 +5,9 @@ module CucumberExpressions class RegularExpression CAPTURE_GROUP_PATTERN = /\(([^(]+)\)/ - def initialize(regexp, types, parameter_registry) + def initialize(regexp, types, parameter_type_registry) @regexp = regexp - @parameters = [] + @parameter_types = [] type_index = 0 match = nil @@ -21,24 +21,24 @@ def initialize(regexp, types, parameter_registry) type = types.length <= type_index ? nil : types[type_index] type_index += 1 - parameter = nil + parameter_type = nil if (type) - parameter = parameter_registry.lookup_by_type(type) + parameter_type = parameter_type_registry.lookup_by_type(type) end - if (parameter.nil?) - parameter = parameter_registry.lookup_by_capture_group_regexp(capture_group_pattern) + if (parameter_type.nil?) + parameter_type = parameter_type_registry.lookup_by_regexp(capture_group_pattern) end - if (parameter.nil?) - parameter = parameter_registry.create_anonymous_lookup(lambda {|s| s}) + if (parameter_type.nil?) + parameter_type = parameter_type_registry.create_anonymous_lookup(lambda {|s| s}) end - @parameters.push(parameter) + @parameter_types.push(parameter_type) match_offset = match.offset(0)[1] end end def match(text) - ArgumentBuilder.build_arguments(@regexp, text, @parameters) + ArgumentBuilder.build_arguments(@regexp, text, @parameter_types) end def source diff --git a/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/cucumber_expression_generator_spec.rb b/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/cucumber_expression_generator_spec.rb index cd25ac63e0..e9001e3773 100644 --- a/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/cucumber_expression_generator_spec.rb +++ b/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/cucumber_expression_generator_spec.rb @@ -1,6 +1,6 @@ require 'cucumber/cucumber_expressions/cucumber_expression_generator' -require 'cucumber/cucumber_expressions/parameter' -require 'cucumber/cucumber_expressions/parameter_registry' +require 'cucumber/cucumber_expressions/parameter_type' +require 'cucumber/cucumber_expressions/parameter_type_registry' module Cucumber module CucumberExpressions @@ -9,18 +9,18 @@ class Currency end before do - @parameter_registry = ParameterRegistry.new - @generator = CucumberExpressionGenerator.new(@parameter_registry) + @parameter_type_registry = ParameterTypeRegistry.new + @generator = CucumberExpressionGenerator.new(@parameter_type_registry) end it "documents expression generation" do - parameter_registry = ParameterRegistry.new + parameter_registry = ParameterTypeRegistry.new ### [generate-expression] generator = CucumberExpressionGenerator.new(parameter_registry) undefined_step_text = "I have 2 cucumbers and 1.5 tomato" generated_expression = generator.generate_expression(undefined_step_text) expect(generated_expression.source).to eq("I have {int} cucumbers and {float} tomato") - expect(generated_expression.parameters[1].type).to eq(Float) + expect(generated_expression.parameter_types[1].type).to eq(Float) ### [generate-expression] end @@ -47,7 +47,7 @@ class Currency end it "numbers only second argument when type is not reserved keyword" do - @parameter_registry.add_parameter(Parameter.new( + @parameter_type_registry.define_parameter_type(ParameterType.new( 'currency', Currency, '[A-Z]{3}', @@ -61,7 +61,7 @@ class Currency it "exposes parameters in generated expression" do expression = @generator.generate_expression("I have 2 cukes and 1.5 euro") - types = expression.parameters.map(&:type) + types = expression.parameter_types.map(&:type) expect(types).to eq([Integer, Float]) end diff --git a/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/cucumber_expression_regexp_spec.rb b/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/cucumber_expression_regexp_spec.rb index 8d0274771f..e4ef7e88ca 100644 --- a/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/cucumber_expression_regexp_spec.rb +++ b/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/cucumber_expression_regexp_spec.rb @@ -1,12 +1,12 @@ require 'cucumber/cucumber_expressions/cucumber_expression' -require 'cucumber/cucumber_expressions/parameter_registry' +require 'cucumber/cucumber_expressions/parameter_type_registry' module Cucumber module CucumberExpressions describe CucumberExpression do context "Regexp translation" do def assert_regexp(expression, regexp) - cucumber_expression = CucumberExpression.new(expression, [], ParameterRegistry.new) + cucumber_expression = CucumberExpression.new(expression, [], ParameterTypeRegistry.new) expect(regexp).to eq(cucumber_expression.instance_variable_get('@regexp')) end diff --git a/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/cucumber_expression_spec.rb b/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/cucumber_expression_spec.rb index 71c8f2739c..ccdcb1709e 100644 --- a/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/cucumber_expression_spec.rb +++ b/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/cucumber_expression_spec.rb @@ -1,11 +1,11 @@ require 'cucumber/cucumber_expressions/cucumber_expression' -require 'cucumber/cucumber_expressions/parameter_registry' +require 'cucumber/cucumber_expressions/parameter_type_registry' module Cucumber module CucumberExpressions describe CucumberExpression do it "documents match arguments" do - parameter_registry = ParameterRegistry.new + parameter_registry = ParameterTypeRegistry.new ### [capture-match-arguments] expr = "I have {n} cuke(s) in my {bodypart} now" @@ -58,12 +58,12 @@ module CucumberExpressions it "exposes source" do expr = "I have {int} cuke(s) in my {bodypart} now" - expect(CucumberExpression.new(expr, [], ParameterRegistry.new).source).to eq(expr) + expect(CucumberExpression.new(expr, [], ParameterTypeRegistry.new).source).to eq(expr) end it "exposes offset and value" do expr = "I have {int} cuke(s) in my {bodypart} now" - expression = CucumberExpression.new(expr, [], ParameterRegistry.new) + expression = CucumberExpression.new(expr, [], ParameterTypeRegistry.new) arg1 = expression.match("I have 800 cukes in my brain now")[0] expect(arg1.offset).to eq(7) expect(arg1.value).to eq("800") @@ -73,7 +73,7 @@ module CucumberExpressions %w(\\ [ ] ^ $ . | ? * +).each do |character| it "escapes #{character}" do expr = "I have {int} cuke(s) and #{character}" - expression = CucumberExpression.new(expr, [], ParameterRegistry.new) + expression = CucumberExpression.new(expr, [], ParameterTypeRegistry.new) arg1 = expression.match("I have 800 cukes and #{character}")[0] expect(arg1.offset).to eq(7) expect(arg1.value).to eq("800") @@ -82,7 +82,7 @@ module CucumberExpressions end def match(expression, text, types = []) - cucumber_expression = CucumberExpression.new(expression, types, ParameterRegistry.new) + cucumber_expression = CucumberExpression.new(expression, types, ParameterTypeRegistry.new) args = cucumber_expression.match(text) return nil if args.nil? args.map { |arg| arg.transformed_value } diff --git a/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/custom_parameter_spec.rb b/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/custom_parameter_type_spec.rb similarity index 82% rename from cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/custom_parameter_spec.rb rename to cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/custom_parameter_type_spec.rb index 2170f92c47..efbd6ad3de 100644 --- a/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/custom_parameter_spec.rb +++ b/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/custom_parameter_type_spec.rb @@ -1,6 +1,6 @@ require 'cucumber/cucumber_expressions/cucumber_expression' require 'cucumber/cucumber_expressions/regular_expression' -require 'cucumber/cucumber_expressions/parameter_registry' +require 'cucumber/cucumber_expressions/parameter_type_registry' module Cucumber module CucumberExpressions @@ -20,28 +20,28 @@ def ==(other) describe "Custom parameter" do before do - parameter_registry = ParameterRegistry.new + parameter_registry = ParameterTypeRegistry.new ### [add-color-parameter] - parameter_registry.add_parameter(Parameter.new( + parameter_registry.define_parameter_type(ParameterType.new( 'color', Color, /red|blue|yellow/, lambda { |s| Color.new(s) } )) ### [add-color-parameter] - @parameter_registry = parameter_registry + @parameter_type_registry = parameter_registry end describe CucumberExpression do it "matches typed parameters" do - expression = CucumberExpression.new("I have a {color} ball", [], @parameter_registry) + expression = CucumberExpression.new("I have a {color} ball", [], @parameter_type_registry) transformed_argument_value = expression.match("I have a red ball")[0].transformed_value expect( transformed_argument_value ).to eq(Color.new('red')) end it "matches typed parameters with optional group" do - parameter_registry = ParameterRegistry.new - parameter_registry.add_parameter(Parameter.new( + parameter_registry = ParameterTypeRegistry.new + parameter_registry.define_parameter_type(ParameterType.new( 'color', Color, [/red|blue|yellow/, /(?:dark|light) (?:red|blue|yellow)/], @@ -53,31 +53,31 @@ def ==(other) end it "matches untyped parameters with explicit type" do - expression = CucumberExpression.new("I have a {color} ball", [Color], @parameter_registry) + expression = CucumberExpression.new("I have a {color} ball", [Color], @parameter_type_registry) transformed_argument_value = expression.match("I have a red ball")[0].transformed_value expect( transformed_argument_value ).to eq(Color.new('red')) end it "matches untyped parameters with same name as type" do - expression = CucumberExpression.new("I have a {color} ball", [], @parameter_registry) + expression = CucumberExpression.new("I have a {color} ball", [], @parameter_type_registry) transformed_argument_value = expression.match("I have a red ball")[0].transformed_value expect( transformed_argument_value ).to eq(Color.new('red')) end it "matches parameters with explicit type that isn't registered" do - expression = CucumberExpression.new("I have a {color} ball", [Color], ParameterRegistry.new) + expression = CucumberExpression.new("I have a {color} ball", [Color], ParameterTypeRegistry.new) transformed_argument_value = expression.match("I have a red ball")[0].transformed_value expect( transformed_argument_value ).to eq(Color.new('red')) end it "defers transformation until queried from argument" do - @parameter_registry.add_parameter(Parameter.new( + @parameter_type_registry.define_parameter_type(ParameterType.new( 'throwing', String, /bad/, lambda { |s| raise "Can't transform [#{s}]" } )) - expression = CucumberExpression.new("I have a {throwing} parameter", [], @parameter_registry) + expression = CucumberExpression.new("I have a {throwing} parameter", [], @parameter_type_registry) args = expression.match("I have a bad parameter") expect { args[0].transformed_value }.to raise_error("Can't transform [bad]") end @@ -85,7 +85,7 @@ def ==(other) describe "conflicting parameter type" do it "is detected for type name" do expect { - @parameter_registry.add_parameter(Parameter.new( + @parameter_type_registry.define_parameter_type(ParameterType.new( 'color', String, /.*/, @@ -96,7 +96,7 @@ def ==(other) it "is detected for type" do expect { - @parameter_registry.add_parameter(Parameter.new( + @parameter_type_registry.define_parameter_type(ParameterType.new( 'color2', Color, /.*/, @@ -107,7 +107,7 @@ def ==(other) it "is detected for regexp" do expect { - @parameter_registry.add_parameter(Parameter.new( + @parameter_type_registry.define_parameter_type(ParameterType.new( 'color2', String, /red|blue|yellow/, @@ -120,19 +120,19 @@ def ==(other) describe RegularExpression do it "matches parameters with explicit constructor" do - expression = RegularExpression.new(/I have a (red|blue|yellow) ball/, [Color], @parameter_registry) + expression = RegularExpression.new(/I have a (red|blue|yellow) ball/, [Color], @parameter_type_registry) transformed_argument_value = expression.match("I have a red ball")[0].transformed_value expect( transformed_argument_value ).to eq(Color.new('red')) end it "matches parameters without explicit constructor" do - expression = RegularExpression.new(/I have a (red|blue|yellow) ball/, [], @parameter_registry) + expression = RegularExpression.new(/I have a (red|blue|yellow) ball/, [], @parameter_type_registry) transformed_argument_value = expression.match("I have a red ball")[0].transformed_value expect( transformed_argument_value ).to eq(Color.new('red')) end it "matches parameters with explicit type that isn't registered" do - expression = RegularExpression.new(/I have a (red|blue|yellow) ball/, [Color], ParameterRegistry.new) + expression = RegularExpression.new(/I have a (red|blue|yellow) ball/, [Color], ParameterTypeRegistry.new) transformed_argument_value = expression.match("I have a red ball")[0].transformed_value expect( transformed_argument_value ).to eq(Color.new('red')) end diff --git a/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/expression_examples_spec.rb b/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/expression_examples_spec.rb index f63e44fe8f..815899a9ac 100644 --- a/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/expression_examples_spec.rb +++ b/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/expression_examples_spec.rb @@ -1,6 +1,6 @@ require 'cucumber/cucumber_expressions/cucumber_expression' require 'cucumber/cucumber_expressions/regular_expression' -require 'cucumber/cucumber_expressions/parameter_registry' +require 'cucumber/cucumber_expressions/parameter_type_registry' require 'json' module Cucumber @@ -8,8 +8,8 @@ module CucumberExpressions describe 'examples.txt' do def match(expression_text, text) expression = expression_text =~ /\/(.*)\// ? - RegularExpression.new(Regexp.new($1), [], ParameterRegistry.new) : - CucumberExpression.new(expression_text, [], ParameterRegistry.new) + RegularExpression.new(Regexp.new($1), [], ParameterTypeRegistry.new) : + CucumberExpression.new(expression_text, [], ParameterTypeRegistry.new) arguments = expression.match(text) return nil if arguments.nil? diff --git a/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/regular_expression_spec.rb b/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/regular_expression_spec.rb index 923025a70a..d9afbd4419 100644 --- a/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/regular_expression_spec.rb +++ b/cucumber-expressions/ruby/spec/cucumber/cucumber_expressions/regular_expression_spec.rb @@ -1,16 +1,16 @@ require 'cucumber/cucumber_expressions/regular_expression' -require 'cucumber/cucumber_expressions/parameter_registry' +require 'cucumber/cucumber_expressions/parameter_type_registry' module Cucumber module CucumberExpressions describe RegularExpression do it "documents match arguments" do - parameter_registry = ParameterRegistry.new + parameter_type_registry = ParameterTypeRegistry.new ### [capture-match-arguments] expr = /I have (\d+) cukes? in my (\w*) now/ types = ['int', nil] - expression = RegularExpression.new(expr, types, parameter_registry) + expression = RegularExpression.new(expr, types, parameter_type_registry) args = expression.match("I have 7 cukes in my belly now") expect( args[0].transformed_value ).to eq(7) expect( args[1].transformed_value ).to eq("belly") @@ -57,11 +57,11 @@ module CucumberExpressions it "exposes source" do expr = /I have (\d+) cukes? in my (\+) now/ - expect(RegularExpression.new(expr, [], ParameterRegistry.new).source).to eq(expr) + expect(RegularExpression.new(expr, [], ParameterTypeRegistry.new).source).to eq(expr) end def match(expression, text, types = []) - regular_expression = RegularExpression.new(expression, types, ParameterRegistry.new) + regular_expression = RegularExpression.new(expression, types, ParameterTypeRegistry.new) arguments = regular_expression.match(text) return nil if arguments.nil? arguments.map { |arg| arg.transformed_value }