All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cucumber.runtime.snippets.SnippetGenerator Maven / Gradle / Ivy

There is a newer version: 1.2.6
Show newest version
package cucumber.runtime.snippets;

import cucumber.api.DataTable;
import gherkin.I18n;
import gherkin.formatter.model.Step;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class SnippetGenerator {
    private static final ArgumentPattern[] DEFAULT_ARGUMENT_PATTERNS = new ArgumentPattern[]{
            new ArgumentPattern(Pattern.compile("\"([^\"]*)\""), String.class),
            new ArgumentPattern(Pattern.compile("(\\d+)"), Integer.TYPE)
    };
    private static final Pattern GROUP_PATTERN = Pattern.compile("\\(");
    private static final Pattern[] ESCAPE_PATTERNS = new Pattern[]{
            Pattern.compile("\\$"),
            Pattern.compile("\\("),
            Pattern.compile("\\)"),
            Pattern.compile("\\["),
            Pattern.compile("\\]")
    };

    private static final String REGEXP_HINT = "Express the Regexp above with the code you wish you had";
    private static final Character SUBST = '_';

    private final Snippet snippet;

    public SnippetGenerator(Snippet snippet) {
        this.snippet = snippet;
    }

    public String getSnippet(Step step) {
        return MessageFormat.format(
                snippet.template(),
                I18n.codeKeywordFor(step.getKeyword()),
                snippet.escapePattern(patternFor(step.getName())),
                functionName(step.getName()),
                snippet.arguments(argumentTypes(step)),
                REGEXP_HINT,
                step.getRows() == null ? "" : snippet.tableHint()
        );
    }

    String patternFor(String stepName) {
        String pattern = stepName;
        for (Pattern escapePattern : ESCAPE_PATTERNS) {
            Matcher m = escapePattern.matcher(pattern);
            String replacement = Matcher.quoteReplacement(escapePattern.toString());
            pattern = m.replaceAll(replacement);
        }
        for (ArgumentPattern argumentPattern : argumentPatterns()) {
            pattern = argumentPattern.replaceMatchesWithGroups(pattern);
        }
        if (snippet.namedGroupStart() != null) {
            pattern = withNamedGroups(pattern);
        }

        return "^" + pattern + "$";
    }

    private String functionName(String name) {
        String functionName = name;
        for (ArgumentPattern argumentPattern : argumentPatterns()) {
            functionName = argumentPattern.replaceMatchesWithSpace(functionName);
        }
        functionName = sanitizeFunctionName(functionName);
        return functionName;
    }

    String sanitizeFunctionName(String functionName) {
        StringBuilder sanitized = new StringBuilder();

        String trimmedFunctionName = functionName.trim();

        sanitized.append(Character.isJavaIdentifierStart(trimmedFunctionName.charAt(0)) ? trimmedFunctionName.charAt(0) : SUBST);
        for (int i = 1; i < trimmedFunctionName.length(); i++) {
            if (Character.isJavaIdentifierPart(trimmedFunctionName.charAt(i))) {
                sanitized.append(trimmedFunctionName.charAt(i));
            } else if (sanitized.charAt(sanitized.length() - 1) != SUBST && i != trimmedFunctionName.length() - 1) {
                sanitized.append(SUBST);
            }
        }
        return sanitized.toString();
    }

    private String withNamedGroups(String snippetPattern) {
        Matcher m = GROUP_PATTERN.matcher(snippetPattern);

        StringBuffer sb = new StringBuffer();
        int n = 1;
        while (m.find()) {
            m.appendReplacement(sb, "(" + snippet.namedGroupStart() + n++ + snippet.namedGroupEnd());
        }
        m.appendTail(sb);

        return sb.toString();
    }


    private List> argumentTypes(Step step) {
        String name = step.getName();
        List> argTypes = new ArrayList>();
        Matcher[] matchers = new Matcher[argumentPatterns().length];
        for (int i = 0; i < argumentPatterns().length; i++) {
            matchers[i] = argumentPatterns()[i].pattern().matcher(name);
        }
        int pos = 0;
        while (true) {
            int matchedLength = 1;

            for (int i = 0; i < matchers.length; i++) {
                Matcher m = matchers[i].region(pos, name.length());
                if (m.lookingAt()) {
                    Class typeForSignature = argumentPatterns()[i].type();
                    argTypes.add(typeForSignature);

                    matchedLength = m.group().length();
                    break;
                }
            }

            pos += matchedLength;

            if (pos == name.length()) {
                break;
            }
        }
        if (step.getDocString() != null) {
            argTypes.add(String.class);
        }
        if (step.getRows() != null) {
            argTypes.add(DataTable.class);
        }
        return argTypes;
    }

    ArgumentPattern[] argumentPatterns() {
        return DEFAULT_ARGUMENT_PATTERNS;
    }

    public static String untypedArguments(List> argumentTypes) {
        StringBuilder sb = new StringBuilder();
        for (int n = 0; n < argumentTypes.size(); n++) {
            if (n > 0) {
                sb.append(", ");
            }
            sb.append("arg").append(n + 1);
        }
        return sb.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy