lib/tspec.rb in tspec-0.1.0 vs lib/tspec.rb in tspec-0.2.0

- old
+ new

@@ -17,15 +17,36 @@ def receive(*type, **types) self end end +class UnboundMethod + def return(*types) + self + end + + def receive(*type, **types) + self + end +end + +class Method + def return(*types) + self + end + + def receive(*type, **types) + self + end +end + module TSpec @method_return_type_table = {} @method_arguments_type_table = {} @before_trace = {} @type_error_flag = false + DEFINE_METHOD_SYMBOLS = %i(method_added singleton_method_added define_method instance_method method) def self.value_type_check(value, *types) types.any? do |type| if type.instance_of?(Array) return false unless value.instance_of?(Array) @@ -42,15 +63,20 @@ end TracePoint.trace do |tp| case tp.event when :call - if %i(return receive).include?(tp.method_id) && %i(method_added singleton_method_added define_method).include?(@before_trace[:method_id]) - klass = (@before_trace[:method_id] == :singleton_method_added) ? @before_trace[:self].singleton_class : @before_trace[:self] + if %i(return receive).include?(tp.method_id) && DEFINE_METHOD_SYMBOLS.include?(@before_trace[:method_id]) ctx = tp.binding - key = "#{klass}::#{ctx.receiver}" + if %i(instance_method method).include?(@before_trace[:method_id]) + key = "#{tp.self.owner}::#{tp.self.name}" + else + klass = (@before_trace[:method_id] == :singleton_method_added) ? @before_trace[:self].singleton_class : @before_trace[:self] + key = "#{klass}::#{ctx.receiver}" + end + case tp.method_id when :return @method_return_type_table[key] = ctx.local_variable_get(:types) when :receive @method_arguments_type_table[key] = ctx.local_variable_get(:types) @@ -64,20 +90,17 @@ if types = @method_arguments_type_table[key] arguments = tp.binding.eval("method(:#{tp.method_id}).parameters.map(&:last)") types.each do |name, type| + name = arguments.first if name == type.__id__ - if name != type.__id__ - unless arguments.include?(name) - @type_error_flag = true - raise NotFoundArgumentNameError, "undefined arguments `#{name}' for #{key}" - end - - value = tp.binding.local_variable_get(name) - else - value = tp.binding.local_variable_get(arguments.first) + unless arguments.include?(name) + @type_error_flag = true + raise NotFoundArgumentNameError, "undefined arguments `#{name}' for #{key}" end + + value = tp.binding.local_variable_get(name) unless value_type_check(value, *type) @type_error_flag = true raise ArgumentTypeError, "##{tp.method_id} '#{name}' variable should be #{type.inspect}, but actual '#{value.inspect}' - #{value.class}" end