module T::Private::Methods::CallValidation
def self.wrap_method_if_needed(mod, method_sig, original_method)
-
(UnboundMethod)
- the new wrapper method (or the original one if we didn't wrap it)
Parameters:
-
method_sig
(T::Private::Methods::Signature
) --
def self.wrap_method_if_needed(mod, method_sig, original_method) original_visibility = visibility_method_name(mod, method_sig.method_name) if method_sig.mode == T::Private::Methods::Modes.abstract T::Private::ClassUtils.replace_method(mod, method_sig.method_name) do |*args, &blk| # TODO: write a cop to ensure that abstract methods have an empty body # # We allow abstract methods to be implemented by things further down the ancestor chain. # So, if a super method exists, call it. if defined?(super) super(*args, &blk) else raise NotImplementedError.new( "The method `#{method_sig.method_name}` on #{mod} is declared as `abstract`. It does not have an implementation." ) end end # Note, this logic is duplicated (intentionally, for micro-perf) at `Methods._on_method_added`, # make sure to keep changes in sync. # This is a trapdoor point for each method: # if a given method is wrapped, it stays wrapped; and if not, it's never wrapped. # (Therefore, we need the `@wrapped_tests_with_validation` check in `T::RuntimeLevels`.) elsif method_sig.check_level == :always || (method_sig.check_level == :tests && T::Private::RuntimeLevels.check_tests?) create_validator_method(mod, original_method, method_sig, original_visibility) else T::Configuration.without_ruby_warnings do # get all the shims out of the way and put back the original method T::Private::DeclState.current.without_on_method_added do mod.send(:define_method, method_sig.method_name, original_method) end mod.send(original_visibility, method_sig.method_name) end end # Return the newly created method (or the original one if we didn't replace it) mod.instance_method(method_sig.method_name) end