lib/raap/method_property.rb in raap-0.3.0 vs lib/raap/method_property.rb in raap-0.4.0

- old
+ new

@@ -1,11 +1,11 @@ # frozen_string_literal: true module RaaP class MethodProperty - class Stats < Struct.new(:success, :skip, :exception) - def initialize(success: 0, skip: 0, exception: 0) + class Stats < Struct.new(:success, :skip, :exception, :break) + def initialize(success: 0, skip: 0, exception: 0, break: false) super end end def initialize(receiver_type:, method_name:, method_type:, size_step:, timeout:, allow_private: false) @@ -21,96 +21,128 @@ stats = Stats.new begin Timeout.timeout(@timeout) do catch(:break) do @size_step.each do |size| - yield call(size: size, stats: stats) + call(size:, stats:).tap do |ret| + case ret + when Result::Success + stats.success += 1 + when Result::Failure + # no count + when Result::Skip + stats.skip += 1 + when Result::Exception + stats.exception += 1 + end + + yield ret + end end end end rescue Timeout::Error => exception - RaaP.logger.warn "Timeout: #{exception}" + stats.break = true + RaaP.logger.info "Timeout: #{exception}" end stats end private def call(size:, stats:) - receiver_value = @receiver_type.pick(size: size, eval: false) - args, kwargs, block = @method_type.pick_arguments(size: size, eval: false) + if @method_type.rbs.each_type.find { |t| t.instance_of?(::RBS::Types::Bases::Any) } + RaaP.logger.info { "Skip type check since `#{@method_type.rbs}` includes `untyped`" } + stats.break = true + throw :break + end + receiver_value = @receiver_type.to_symbolic_call(size:) + args, kwargs, block = @method_type.arguments_to_symbolic_call(size:) # @type var symbolic_call: symbolic_call symbolic_call = [:call, receiver_value, @method_name, args, kwargs, block] symbolic_caller = SymbolicCaller.new(symbolic_call, allow_private: @allow_private) begin # ensure symbolic_call - check = false + check = [:failure] if return_type.instance_of?(::RBS::Types::Bases::Bottom) begin return_value = symbolic_caller.eval rescue StandardError, NotImplementedError - check = true + check = [:success] return_value = Value::Bottom.new + rescue Timeout::ExitException + raise + rescue Exception => e # rubocop:disable Lint/RescueException + RaaP.logger.error("[#{e.class}] class is not supported to check `bot` type") + raise end else return_value = symbolic_caller.eval - check = check_return(receiver_value:, return_value:, method_type: @method_type) + check = check_return(receiver_value:, return_value:) end - if check - stats.success += 1 + case check + in [:success] Result::Success.new(symbolic_call:, return_value:) - else + in [:failure] Result::Failure.new(symbolic_call:, return_value:) + in [:exception, exception] + Result::Exception.new(symbolic_call:, exception:) end rescue TypeError => exception Result::Failure.new(symbolic_call:, return_value:, exception:) end # not ensure symbolic_call - rescue NoMethodError => exception - stats.skip += 1 + rescue NoMethodError, NotImplementedError => exception Result::Skip.new(symbolic_call:, exception:) rescue NameError => e + RaaP.logger.error("[#{e.class}] #{e.detailed_message}") msg = e.name.nil? ? '' : "for `#{BindCall.to_s(e.receiver)}::#{e.name}`" - RaaP.logger.error("Implementation is not found #{msg} maybe.") + RaaP.logger.warn("Implementation is not found #{msg} maybe.") + RaaP.logger.debug(e.backtrace&.join("\n")) + stats.break = true throw :break - rescue NotImplementedError => exception - stats.skip += 1 - Result::Skip.new(symbolic_call:, exception:) rescue SystemStackError => exception - stats.skip += 1 - RaaP.logger.warn "Found recursive type definition." + RaaP.logger.info "Found recursive type definition." Result::Skip.new(symbolic_call:, exception:) rescue => exception - stats.exception += 1 Result::Exception.new(symbolic_call:, exception:) end - def check_return(receiver_value:, return_value:, method_type:) + def check_return(receiver_value:, return_value:) if BindCall.is_a?(receiver_value, Module) if BindCall.is_a?(return_type, ::RBS::Types::ClassSingleton) # ::RBS::Test::TypeCheck cannot support to check singleton class - return receiver_value == return_value + if receiver_value == return_value + [:success] + else + [:failure] + end end + self_class = receiver_value instance_class = receiver_value else self_class = BindCall.class(receiver_value) instance_class = BindCall.class(receiver_value) end type_check = ::RBS::Test::TypeCheck.new( - self_class: self_class, - instance_class: instance_class, + self_class:, + instance_class:, class_class: Module, builder: RBS.builder, sample_size: 100, unchecked_classes: [] ) begin - type_check.value(return_value, return_type) + if type_check.value(return_value, return_type) + [:success] + else + [:failure] + end rescue => e - $stderr.puts "Type check fail by `(#{e.class}) #{e.message}`" - false + RaaP.logger.debug("Type check fail by `(#{e.class}) #{e.message}`") + [:exception, e] end end def return_type @method_type.rbs.type.return_type