Class: RBS::Test::Tester
Relationships & Source Files | |
Namespace Children | |
Classes:
| |
Exceptions:
| |
Inherits: | Object |
Defined in: | lib/rbs/test/tester.rb |
Class Method Summary
- .new(env:) ⇒ Tester constructor
Instance Attribute Summary
- #env readonly
- #instance_testers readonly
- #singleton_testers readonly
- #targets readonly
Instance Method Summary
Constructor Details
.new(env:) ⇒ Tester
# File 'lib/rbs/test/tester.rb', line 11
def initialize(env:) @env = env @targets = [] @instance_testers = {} @singleton_testers = {} end
Instance Attribute Details
#env (readonly)
[ GitHub ]# File 'lib/rbs/test/tester.rb', line 6
attr_reader :env
#instance_testers (readonly)
[ GitHub ]# File 'lib/rbs/test/tester.rb', line 8
attr_reader :instance_testers
#singleton_testers (readonly)
[ GitHub ]# File 'lib/rbs/test/tester.rb', line 9
attr_reader :singleton_testers
#targets (readonly)
[ GitHub ]# File 'lib/rbs/test/tester.rb', line 7
attr_reader :targets
Instance Method Details
#builder
[ GitHub ]# File 'lib/rbs/test/tester.rb', line 22
def builder @builder ||= DefinitionBuilder.new(env: env) end
#factory
[ GitHub ]#install!(klass, sample_size:, unchecked_classes:)
[ GitHub ]# File 'lib/rbs/test/tester.rb', line 42
def install!(klass, sample_size:, unchecked_classes:) RBS.logger.info { "Installing runtime type checker in #{klass}..." } type_name = factory.type_name(klass.name).absolute! builder.build_instance(type_name).tap do |definition| instance_key = new_key(type_name, "InstanceChecker") tester, set = instance_testers[klass] ||= [ MethodCallTester.new(klass, builder, definition, kind: :instance, sample_size: sample_size, unchecked_classes: unchecked_classes), Set[] ] Observer.register(instance_key, tester) definition.methods.each do |name, method| if reason = skip_method?(type_name, method) unless reason == :implemented_in RBS.logger.info { "Skipping ##{name} because of `#{reason}`..." } end else if !set.include?(name) && ( name == :initialize || klass.instance_methods(false).include?(name) || klass.private_instance_methods(false).include?(name)) RBS.logger.info { "Setting up method hook in ##{name}..." } Hook.hook_instance_method klass, name, key: instance_key set << name end end end end builder.build_singleton(type_name).tap do |definition| singleton_key = new_key(type_name, "SingletonChecker") tester, set = singleton_testers[klass] ||= [ MethodCallTester.new(klass.singleton_class, builder, definition, kind: :singleton, sample_size: sample_size, unchecked_classes: unchecked_classes), Set[] ] Observer.register(singleton_key, tester) definition.methods.each do |name, method| if reason = skip_method?(type_name, method) unless reason == :implemented_in RBS.logger.info { "Skipping .#{name} because of `#{reason}`..." } end else if klass.methods(false).include?(name) && !set.include?(name) RBS.logger.info { "Setting up method hook in .#{name}..." } Hook.hook_singleton_method klass, name, key: singleton_key set << name end end end end targets << klass end
#new_key(type_name, prefix)
[ GitHub ]# File 'lib/rbs/test/tester.rb', line 99
def new_key(type_name, prefix) "#{prefix}__#{type_name}__#{SecureRandom.hex(10)}" end
#skip_method?(type_name, method) ⇒ Boolean
# File 'lib/rbs/test/tester.rb', line 26
def skip_method?(type_name, method) if method.implemented_in == type_name if method.annotations.any? {|a| a.string == "rbs:test:skip" } :skip else false end else if method.annotations.any? {|a| a.string == "rbs:test:target" } false else :implemented_in end end end