110 lines
3.8 KiB
JavaScript
110 lines
3.8 KiB
JavaScript
"use strict";
|
|
|
|
const util = require('util');
|
|
|
|
const ParameterTypeMatcher = require('./parameter_type_matcher');
|
|
|
|
const ParameterType = require('./parameter_type');
|
|
|
|
const CombinatorialGeneratedExpressionFactory = require('./combinatorial_generated_expression_factory');
|
|
|
|
class CucumberExpressionGenerator {
|
|
constructor(parameterTypeRegistry) {
|
|
this._parameterTypeRegistry = parameterTypeRegistry;
|
|
}
|
|
|
|
generateExpressions(text) {
|
|
const parameterTypeCombinations = [];
|
|
|
|
const parameterTypeMatchers = this._createParameterTypeMatchers(text);
|
|
|
|
let expressionTemplate = '';
|
|
let pos = 0; // eslint-disable-next-line no-constant-condition
|
|
|
|
while (true) {
|
|
let matchingParameterTypeMatchers = [];
|
|
|
|
for (const parameterTypeMatcher of parameterTypeMatchers) {
|
|
const advancedParameterTypeMatcher = parameterTypeMatcher.advanceTo(pos);
|
|
|
|
if (advancedParameterTypeMatcher.find) {
|
|
matchingParameterTypeMatchers.push(advancedParameterTypeMatcher);
|
|
}
|
|
}
|
|
|
|
if (matchingParameterTypeMatchers.length > 0) {
|
|
matchingParameterTypeMatchers = matchingParameterTypeMatchers.sort(ParameterTypeMatcher.compare); // Find all the best parameter type matchers, they are all candidates.
|
|
|
|
const bestParameterTypeMatcher = matchingParameterTypeMatchers[0];
|
|
const bestParameterTypeMatchers = matchingParameterTypeMatchers.filter(m => ParameterTypeMatcher.compare(m, bestParameterTypeMatcher) === 0); // Build a list of parameter types without duplicates. The reason there
|
|
// might be duplicates is that some parameter types have more than one regexp,
|
|
// which means multiple ParameterTypeMatcher objects will have a reference to the
|
|
// same ParameterType.
|
|
// We're sorting the list so preferential parameter types are listed first.
|
|
// Users are most likely to want these, so they should be listed at the top.
|
|
|
|
let parameterTypes = [];
|
|
|
|
for (const parameterTypeMatcher of bestParameterTypeMatchers) {
|
|
if (parameterTypes.indexOf(parameterTypeMatcher.parameterType) === -1) {
|
|
parameterTypes.push(parameterTypeMatcher.parameterType);
|
|
}
|
|
}
|
|
|
|
parameterTypes = parameterTypes.sort(ParameterType.compare);
|
|
parameterTypeCombinations.push(parameterTypes);
|
|
expressionTemplate += escape(text.slice(pos, bestParameterTypeMatcher.start));
|
|
expressionTemplate += '{%s}';
|
|
pos = bestParameterTypeMatcher.start + bestParameterTypeMatcher.group.length;
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
if (pos >= text.length) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
expressionTemplate += escape(text.slice(pos));
|
|
return new CombinatorialGeneratedExpressionFactory(expressionTemplate, parameterTypeCombinations).generateExpressions();
|
|
}
|
|
/**
|
|
* @deprecated
|
|
*/
|
|
|
|
|
|
generateExpression(text) {
|
|
return util.deprecate(() => this.generateExpressions(text)[0], 'CucumberExpressionGenerator.generateExpression: Use CucumberExpressionGenerator.generateExpressions instead')();
|
|
}
|
|
|
|
_createParameterTypeMatchers(text) {
|
|
let parameterMatchers = [];
|
|
|
|
for (const parameterType of this._parameterTypeRegistry.parameterTypes) {
|
|
if (parameterType.useForSnippets) {
|
|
parameterMatchers = parameterMatchers.concat(this._createParameterTypeMatchers2(parameterType, text));
|
|
}
|
|
}
|
|
|
|
return parameterMatchers;
|
|
}
|
|
|
|
_createParameterTypeMatchers2(parameterType, text) {
|
|
// TODO: [].map
|
|
const result = [];
|
|
|
|
for (const regexp of parameterType.regexps) {
|
|
result.push(new ParameterTypeMatcher(parameterType, regexp, text));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
}
|
|
|
|
function escape(s) {
|
|
return s.replace(/%/g, '%%') // for util.format
|
|
.replace(/\(/g, '\\(').replace(/{/g, '\\{').replace(/\//g, '\\/');
|
|
}
|
|
|
|
module.exports = CucumberExpressionGenerator; |