require 'cucumber/cucumber_expressions/ast' module Cucumber module CucumberExpressions class CucumberExpressionError < StandardError def build_message( index, expression, pointer, problem, solution ) m = <<-EOF This Cucumber Expression has a problem at column #{index + 1}: #{expression} #{pointer} #{problem}. #{solution} EOF m.strip end def point_at(index) ' ' * index + '^' end def point_at_located(node) pointer = [point_at(node.start)] if node.start + 1 < node.end for _ in node.start + 1...node.end - 1 pointer.push('-') end pointer.push('^') end pointer.join('') end end class AlternativeMayNotExclusivelyContainOptionals < CucumberExpressionError def initialize(node, expression) super(build_message( node.start, expression, point_at_located(node), 'An alternative may not exclusively contain optionals', "If you did not mean to use an optional you can use '\\(' to escape the the '('" )) end end class AlternativeMayNotBeEmpty < CucumberExpressionError def initialize(node, expression) super(build_message( node.start, expression, point_at_located(node), 'Alternative may not be empty', "If you did not mean to use an alternative you can use '\\/' to escape the the '/'" )) end end class CantEscape < CucumberExpressionError def initialize(expression, index) super(build_message( index, expression, point_at(index), "Only the characters '{', '}', '(', ')', '\\', '/' and whitespace can be escaped", "If you did mean to use an '\\' you can use '\\\\' to escape it" )) end end class OptionalMayNotBeEmpty < CucumberExpressionError def initialize(node, expression) super(build_message( node.start, expression, point_at_located(node), 'An optional must contain some text', "If you did not mean to use an optional you can use '\\(' to escape the the '('" )) end end class ParameterIsNotAllowedInOptional < CucumberExpressionError def initialize(node, expression) super(build_message( node.start, expression, point_at_located(node), 'An optional may not contain a parameter type', "If you did not mean to use an parameter type you can use '\\{' to escape the the '{'" )) end end class OptionalIsNotAllowedInOptional < CucumberExpressionError def initialize(node, expression) super(build_message( node.start, expression, point_at_located(node), 'An optional may not contain an other optional', "If you did not mean to use an optional type you can use '\\(' to escape the the '('. For more complicated expressions consider using a regular expression instead." )) end end class TheEndOfLineCannotBeEscaped < CucumberExpressionError def initialize(expression) index = expression.codepoints.length - 1 super(build_message( index, expression, point_at(index), 'The end of line can not be escaped', "You can use '\\\\' to escape the the '\\'" )) end end class MissingEndToken < CucumberExpressionError def initialize(expression, begin_token, end_token, current) begin_symbol = Token::symbol_of(begin_token) end_symbol = Token::symbol_of(end_token) purpose = Token::purpose_of(begin_token) super(build_message( current.start, expression, point_at_located(current), "The '#{begin_symbol}' does not have a matching '#{end_symbol}'", "If you did not intend to use #{purpose} you can use '\\#{begin_symbol}' to escape the #{purpose}" )) end end class AlternationNotAllowedInOptional < CucumberExpressionError def initialize(expression, current) super(build_message( current.start, expression, point_at_located(current), "An alternation can not be used inside an optional", "You can use '\\/' to escape the the '/'" )) end end class InvalidParameterTypeName < CucumberExpressionError def initialize(type_name) super("Illegal character in parameter name {#{type_name}}. " + "Parameter names may not contain '{', '}', '(', ')', '\\' or '/'") end end class InvalidParameterTypeNameInNode < CucumberExpressionError def initialize(expression, token) super(build_message( token.start, expression, point_at_located(token), "Parameter names may not contain '{', '}', '(', ')', '\\' or '/'", "Did you mean to use a regular expression?" )) end end class UndefinedParameterTypeError < CucumberExpressionError attr_reader :undefined_parameter_type_name def initialize(node, expression, undefined_parameter_type_name) super(build_message(node.start, expression, point_at_located(node), "Undefined parameter type '#{undefined_parameter_type_name}'", "Please register a ParameterType for '#{undefined_parameter_type_name}'")) @undefined_parameter_type_name = undefined_parameter_type_name end end class AmbiguousParameterTypeError < CucumberExpressionError def initialize(parameter_type_regexp, expression_regexp, parameter_types, generated_expressions) super(<<-EOM) Your Regular Expression /#{expression_regexp.source}/ matches multiple parameter types with regexp /#{parameter_type_regexp}/: #{parameter_type_names(parameter_types)} I couldn't decide which one to use. You have two options: 1) Use a Cucumber Expression instead of a Regular Expression. Try one of these: #{expressions(generated_expressions)} 2) Make one of the parameter types preferential and continue to use a Regular Expression. EOM end private def parameter_type_names(parameter_types) parameter_types.map { |p| "{#{p.name}}" }.join("\n ") end def expressions(generated_expressions) generated_expressions.map { |ge| ge.source }.join("\n ") end end end end