Merge pull request #16505 from Homebrew/dependabot/bundler/Library/Homebrew/sorbet-static-and-runtime-and-sorbet-runtime-0.5.11212
build(deps): bump sorbet-static-and-runtime and sorbet-runtime in /Library/Homebrew
This commit is contained in:
commit
1976ead217
@ -141,14 +141,14 @@ GEM
|
||||
simplecov_json_formatter (0.1.4)
|
||||
simpleidn (0.2.1)
|
||||
unf (~> 0.1.4)
|
||||
sorbet (0.5.11155)
|
||||
sorbet-static (= 0.5.11155)
|
||||
sorbet-runtime (0.5.11155)
|
||||
sorbet-static (0.5.11155-universal-darwin)
|
||||
sorbet-static (0.5.11155-x86_64-linux)
|
||||
sorbet-static-and-runtime (0.5.11155)
|
||||
sorbet (= 0.5.11155)
|
||||
sorbet-runtime (= 0.5.11155)
|
||||
sorbet (0.5.11212)
|
||||
sorbet-static (= 0.5.11212)
|
||||
sorbet-runtime (0.5.11212)
|
||||
sorbet-static (0.5.11212-universal-darwin)
|
||||
sorbet-static (0.5.11212-x86_64-linux)
|
||||
sorbet-static-and-runtime (0.5.11212)
|
||||
sorbet (= 0.5.11212)
|
||||
sorbet-runtime (= 0.5.11212)
|
||||
spoom (1.2.4)
|
||||
erubi (>= 1.10.0)
|
||||
sorbet-static-and-runtime (>= 0.5.10187)
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
class AbstractCoreTap
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
class AbstractDownloadStrategy
|
||||
@ -3209,7 +3208,6 @@ end
|
||||
|
||||
class Cask::Artifact::AbstractArtifact
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
module Cask::Cache
|
||||
@ -3219,12 +3217,10 @@ end
|
||||
|
||||
class Cask::CaskLoader::AbstractContentLoader
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
module Cask::CaskLoader::ILoader
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
extend ::T::Private::Methods::MethodHooks
|
||||
extend ::T::Private::Methods::SingletonMethodHooks
|
||||
end
|
||||
@ -3718,7 +3714,6 @@ end
|
||||
|
||||
class Downloadable
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
class ELFTools::LazyArray
|
||||
@ -6324,6 +6319,8 @@ class Net::HTTP
|
||||
VERSION = ::T.let(nil, ::T.untyped)
|
||||
end
|
||||
|
||||
Net::HTTP::ProxyMod = Net::HTTP::ProxyDelta
|
||||
|
||||
class Net::HTTPAlreadyReported
|
||||
HAS_BODY = ::T.let(nil, ::T.untyped)
|
||||
end
|
||||
@ -6501,7 +6498,6 @@ end
|
||||
|
||||
class OS::Mac::BaseSDKLocator
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
module OS::Mac::CLT
|
||||
@ -7300,7 +7296,6 @@ end
|
||||
class Parlour::Conversion::Converter
|
||||
extend ::T::Helpers
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
module Parlour::Debugging
|
||||
@ -7310,7 +7305,6 @@ end
|
||||
|
||||
module Parlour::Mixin::Searchable
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
extend ::T::Private::Methods::MethodHooks
|
||||
extend ::T::Private::Methods::SingletonMethodHooks
|
||||
end
|
||||
@ -7318,7 +7312,6 @@ end
|
||||
class Parlour::Plugin
|
||||
extend ::T::Helpers
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
module Parlour::TypeLoader
|
||||
@ -7329,13 +7322,11 @@ end
|
||||
class Parlour::TypedObject
|
||||
extend ::T::Helpers
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
class Parlour::Types::Type
|
||||
extend ::T::Helpers
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
class Proc
|
||||
@ -7423,7 +7414,6 @@ end
|
||||
module RBI::Indexable
|
||||
extend ::T::Helpers
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
extend ::T::Private::Methods::MethodHooks
|
||||
extend ::T::Private::Methods::SingletonMethodHooks
|
||||
end
|
||||
@ -7431,13 +7421,11 @@ end
|
||||
class RBI::Node
|
||||
extend ::T::Helpers
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
class RBI::Visitor
|
||||
extend ::T::Helpers
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
class RDoc::Alias
|
||||
@ -9362,7 +9350,6 @@ end
|
||||
|
||||
class RuboCop::Cop::FormulaCop
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
module RuboCop::Cop::HelperFunctions
|
||||
@ -9825,7 +9812,6 @@ end
|
||||
class Spoom::Coverage::D3::Base
|
||||
extend ::T::Helpers
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
module Spoom::Coverage::D3
|
||||
@ -9835,7 +9821,6 @@ end
|
||||
class Spoom::Coverage::Template
|
||||
extend ::T::Helpers
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
module Spoom::Coverage
|
||||
@ -9845,13 +9830,11 @@ end
|
||||
class Spoom::Deadcode::Error
|
||||
extend ::T::Helpers
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
class Spoom::Deadcode::Plugins::Base
|
||||
extend ::T::Helpers
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
module Spoom::Deadcode
|
||||
@ -9861,13 +9844,11 @@ end
|
||||
class Spoom::FileTree::Visitor
|
||||
extend ::T::Helpers
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
module Spoom::LSP::PrintableSymbol
|
||||
extend ::T::Helpers
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
extend ::T::Private::Methods::MethodHooks
|
||||
extend ::T::Private::Methods::SingletonMethodHooks
|
||||
end
|
||||
@ -9979,10 +9960,6 @@ class Test::Helper::OutputAsTTY::Output
|
||||
RUBYGEMS_ACTIVATION_MONITOR = ::T.let(nil, ::T.untyped)
|
||||
end
|
||||
|
||||
class Thread
|
||||
def native_thread_id(); end
|
||||
end
|
||||
|
||||
class Thread::Backtrace
|
||||
def self.limit(); end
|
||||
end
|
||||
@ -10182,7 +10159,6 @@ end
|
||||
|
||||
module UnpackStrategy
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
extend ::T::Private::Methods::MethodHooks
|
||||
extend ::T::Private::Methods::SingletonMethodHooks
|
||||
end
|
||||
@ -10256,12 +10232,10 @@ end
|
||||
|
||||
class Version::Parser
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
class Version::Token
|
||||
extend ::T::Private::Abstract::Hooks
|
||||
extend ::T::InterfaceWrapper::Helpers
|
||||
end
|
||||
|
||||
class WeakRef
|
||||
|
@ -71,7 +71,7 @@ $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/racc-1.7.3/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/parser-3.3.0.4/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/rainbow-3.1.1/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/sorbet-runtime-0.5.11155/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/sorbet-runtime-0.5.11212/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/parlour-8.1.0/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/patchelf-1.4.0/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/plist-3.7.1/lib")
|
||||
@ -112,9 +112,9 @@ $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/simplecov_json_formatter-0.1.4/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/simplecov-0.22.0/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/simplecov-cobertura-2.1.0/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/sorbet-static-0.5.11155-universal-darwin/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/sorbet-0.5.11155/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/sorbet-static-and-runtime-0.5.11155/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/sorbet-static-0.5.11212-universal-darwin/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/sorbet-0.5.11212/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/sorbet-static-and-runtime-0.5.11212/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/syntax_tree-6.2.0/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/thor-1.3.0/lib")
|
||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/spoom-1.2.4/lib")
|
||||
|
@ -1,162 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
# typed: false
|
||||
|
||||
# Wraps an object, exposing only the methods defined on a given class/module. The idea is that, in
|
||||
# the absence of a static type checker that would prevent you from calling non-Bar methods on a
|
||||
# variable of type Bar, we can use these wrappers as a way of enforcing it at runtime.
|
||||
#
|
||||
# Once we ship static type checking, we should get rid of this entirely.
|
||||
class T::InterfaceWrapper
|
||||
extend T::Sig
|
||||
|
||||
module Helpers
|
||||
def wrap_instance(obj)
|
||||
T::InterfaceWrapper.wrap_instance(obj, self)
|
||||
end
|
||||
|
||||
def wrap_instances(arr)
|
||||
T::InterfaceWrapper.wrap_instances(arr, self)
|
||||
end
|
||||
end
|
||||
|
||||
private_class_method :new # use `wrap_instance`
|
||||
|
||||
def self.wrap_instance(obj, interface_mod)
|
||||
wrapper = wrapped_dynamic_cast(obj, interface_mod)
|
||||
if wrapper.nil?
|
||||
raise "#{obj.class} cannot be cast to #{interface_mod}"
|
||||
end
|
||||
wrapper
|
||||
end
|
||||
|
||||
sig do
|
||||
params(
|
||||
arr: Array,
|
||||
interface_mod: T.untyped
|
||||
)
|
||||
.returns(Array)
|
||||
end
|
||||
def self.wrap_instances(arr, interface_mod)
|
||||
arr.map {|instance| self.wrap_instance(instance, interface_mod)}
|
||||
end
|
||||
|
||||
def initialize(target_obj, interface_mod)
|
||||
if target_obj.is_a?(T::InterfaceWrapper)
|
||||
# wrapped_dynamic_cast should guarantee this never happens.
|
||||
raise "Unexpected: wrapping a wrapper. Please report this bug at https://github.com/sorbet/sorbet/issues"
|
||||
end
|
||||
|
||||
if !target_obj.is_a?(interface_mod)
|
||||
# wrapped_dynamic_cast should guarantee this never happens.
|
||||
raise "Unexpected: `is_a?` failed. Please report this bug at https://github.com/sorbet/sorbet/issues"
|
||||
end
|
||||
|
||||
if target_obj.class == interface_mod
|
||||
# wrapped_dynamic_cast should guarantee this never happens.
|
||||
raise "Unexpected: exact class match. Please report this bug at https://github.com/sorbet/sorbet/issues"
|
||||
end
|
||||
|
||||
@target_obj = target_obj
|
||||
@interface_mod = interface_mod
|
||||
self_methods = self.class.self_methods
|
||||
|
||||
# If perf becomes an issue, we can define these on an anonymous subclass, and keep a cache
|
||||
# so we only need to do it once per unique `interface_mod`
|
||||
T::Utils.methods_excluding_object(interface_mod).each do |method_name|
|
||||
if self_methods.include?(method_name)
|
||||
raise "interface_mod has a method that conflicts with #{self.class}: #{method_name}"
|
||||
end
|
||||
|
||||
define_singleton_method(method_name) do |*args, &blk|
|
||||
target_obj.send(method_name, *args, &blk)
|
||||
end
|
||||
|
||||
if singleton_class.respond_to?(:ruby2_keywords, true)
|
||||
singleton_class.send(:ruby2_keywords, method_name)
|
||||
end
|
||||
|
||||
if target_obj.singleton_class.public_method_defined?(method_name)
|
||||
# no-op, it's already public
|
||||
elsif target_obj.singleton_class.protected_method_defined?(method_name)
|
||||
singleton_class.send(:protected, method_name)
|
||||
elsif target_obj.singleton_class.private_method_defined?(method_name)
|
||||
singleton_class.send(:private, method_name)
|
||||
else
|
||||
raise "This should never happen. Report this bug at https://github.com/sorbet/sorbet/issues"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def kind_of?(other)
|
||||
is_a?(other)
|
||||
end
|
||||
|
||||
def is_a?(other)
|
||||
if !other.is_a?(Module)
|
||||
raise TypeError.new("class or module required")
|
||||
end
|
||||
|
||||
# This makes is_a? return true for T::InterfaceWrapper (and its ancestors),
|
||||
# as well as for @interface_mod and its ancestors.
|
||||
self.class <= other || @interface_mod <= other
|
||||
end
|
||||
|
||||
# Prefixed because we're polluting the namespace of the interface we're wrapping, and we don't
|
||||
# want anyone else (besides dynamic_cast) calling it.
|
||||
def __target_obj_DO_NOT_USE # rubocop:disable Naming/MethodName
|
||||
@target_obj
|
||||
end
|
||||
|
||||
# Prefixed because we're polluting the namespace of the interface we're wrapping, and we don't
|
||||
# want anyone else (besides wrapped_dynamic_cast) calling it.
|
||||
def __interface_mod_DO_NOT_USE # rubocop:disable Naming/MethodName
|
||||
@interface_mod
|
||||
end
|
||||
|
||||
# "Cast" an object to another type. If `obj` is an InterfaceWrapper, returns the the wrapped
|
||||
# object if that matches `type`. Otherwise, returns `obj` if it matches `type`. Otherwise,
|
||||
# returns nil.
|
||||
#
|
||||
# @param obj [Object] object to cast
|
||||
# @param mod [Module] type to cast `obj` to
|
||||
#
|
||||
# @example
|
||||
# if (impl = T::InterfaceWrapper.dynamic_cast(iface, MyImplementation))
|
||||
# impl.do_things
|
||||
# end
|
||||
def self.dynamic_cast(obj, mod)
|
||||
if obj.is_a?(T::InterfaceWrapper)
|
||||
target_obj = obj.__target_obj_DO_NOT_USE
|
||||
target_obj.is_a?(mod) ? target_obj : nil
|
||||
elsif obj.is_a?(mod)
|
||||
obj
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Like dynamic_cast, but puts the result in its own wrapper if necessary.
|
||||
#
|
||||
# @param obj [Object] object to cast
|
||||
# @param mod [Module] type to cast `obj` to
|
||||
def self.wrapped_dynamic_cast(obj, mod)
|
||||
# Avoid unwrapping and creating an equivalent wrapper.
|
||||
if obj.is_a?(T::InterfaceWrapper) && obj.__interface_mod_DO_NOT_USE == mod
|
||||
return obj
|
||||
end
|
||||
|
||||
cast_obj = dynamic_cast(obj, mod)
|
||||
if cast_obj.nil?
|
||||
nil
|
||||
elsif cast_obj.class == mod
|
||||
# Nothing to wrap, they want the full class
|
||||
cast_obj
|
||||
else
|
||||
new(cast_obj, mod)
|
||||
end
|
||||
end
|
||||
|
||||
def self.self_methods
|
||||
@self_methods ||= self.instance_methods(false).to_set
|
||||
end
|
||||
end
|
@ -1,197 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
# typed: strict
|
||||
|
||||
module T::Props
|
||||
module Private
|
||||
module SetterFactory
|
||||
extend T::Sig
|
||||
|
||||
SetterProc = T.type_alias {T.proc.params(val: T.untyped).void}
|
||||
ValidateProc = T.type_alias {T.proc.params(prop: Symbol, value: T.untyped).void}
|
||||
|
||||
sig do
|
||||
params(
|
||||
klass: T.all(Module, T::Props::ClassMethods),
|
||||
prop: Symbol,
|
||||
rules: T::Hash[Symbol, T.untyped]
|
||||
)
|
||||
.returns(SetterProc)
|
||||
.checked(:never)
|
||||
end
|
||||
def self.build_setter_proc(klass, prop, rules)
|
||||
# Our nil check works differently than a simple T.nilable for various
|
||||
# reasons (including the `raise_on_nil_write` setting and the existence
|
||||
# of defaults & factories), so unwrap any T.nilable and do a check
|
||||
# manually.
|
||||
non_nil_type = T::Utils::Nilable.get_underlying_type_object(rules.fetch(:type_object))
|
||||
accessor_key = rules.fetch(:accessor_key)
|
||||
validate = rules[:setter_validate]
|
||||
|
||||
# It seems like a bug that this affects the behavior of setters, but
|
||||
# some existing code relies on this behavior
|
||||
has_explicit_nil_default = rules.key?(:default) && rules.fetch(:default).nil?
|
||||
|
||||
# Use separate methods in order to ensure that we only close over necessary
|
||||
# variables
|
||||
if !T::Props::Utils.need_nil_write_check?(rules) || has_explicit_nil_default
|
||||
if validate.nil? && non_nil_type.is_a?(T::Types::Simple)
|
||||
simple_nilable_proc(prop, accessor_key, non_nil_type.raw_type, klass)
|
||||
else
|
||||
nilable_proc(prop, accessor_key, non_nil_type, klass, validate)
|
||||
end
|
||||
else
|
||||
if validate.nil? && non_nil_type.is_a?(T::Types::Simple)
|
||||
simple_non_nil_proc(prop, accessor_key, non_nil_type.raw_type, klass)
|
||||
else
|
||||
non_nil_proc(prop, accessor_key, non_nil_type, klass, validate)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sig do
|
||||
params(
|
||||
prop: Symbol,
|
||||
accessor_key: Symbol,
|
||||
non_nil_type: Module,
|
||||
klass: T.all(Module, T::Props::ClassMethods),
|
||||
)
|
||||
.returns(SetterProc)
|
||||
end
|
||||
private_class_method def self.simple_non_nil_proc(prop, accessor_key, non_nil_type, klass)
|
||||
proc do |val|
|
||||
unless val.is_a?(non_nil_type)
|
||||
T::Props::Private::SetterFactory.raise_pretty_error(
|
||||
klass,
|
||||
prop,
|
||||
T::Utils.coerce(non_nil_type),
|
||||
val,
|
||||
)
|
||||
end
|
||||
instance_variable_set(accessor_key, val)
|
||||
end
|
||||
end
|
||||
|
||||
sig do
|
||||
params(
|
||||
prop: Symbol,
|
||||
accessor_key: Symbol,
|
||||
non_nil_type: T::Types::Base,
|
||||
klass: T.all(Module, T::Props::ClassMethods),
|
||||
validate: T.nilable(ValidateProc)
|
||||
)
|
||||
.returns(SetterProc)
|
||||
end
|
||||
private_class_method def self.non_nil_proc(prop, accessor_key, non_nil_type, klass, validate)
|
||||
proc do |val|
|
||||
# this use of recursively_valid? is intentional: unlike for
|
||||
# methods, we want to make sure data at the 'edge'
|
||||
# (e.g. models that go into databases or structs serialized
|
||||
# from disk) are correct, so we use more thorough runtime
|
||||
# checks there
|
||||
if non_nil_type.recursively_valid?(val)
|
||||
validate&.call(prop, val)
|
||||
else
|
||||
T::Props::Private::SetterFactory.raise_pretty_error(
|
||||
klass,
|
||||
prop,
|
||||
non_nil_type,
|
||||
val,
|
||||
)
|
||||
end
|
||||
instance_variable_set(accessor_key, val)
|
||||
end
|
||||
end
|
||||
|
||||
sig do
|
||||
params(
|
||||
prop: Symbol,
|
||||
accessor_key: Symbol,
|
||||
non_nil_type: Module,
|
||||
klass: T.all(Module, T::Props::ClassMethods),
|
||||
)
|
||||
.returns(SetterProc)
|
||||
end
|
||||
private_class_method def self.simple_nilable_proc(prop, accessor_key, non_nil_type, klass)
|
||||
proc do |val|
|
||||
if val.nil?
|
||||
instance_variable_set(accessor_key, nil)
|
||||
elsif val.is_a?(non_nil_type)
|
||||
instance_variable_set(accessor_key, val)
|
||||
else
|
||||
T::Props::Private::SetterFactory.raise_pretty_error(
|
||||
klass,
|
||||
prop,
|
||||
T::Utils.coerce(non_nil_type),
|
||||
val,
|
||||
)
|
||||
instance_variable_set(accessor_key, val)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sig do
|
||||
params(
|
||||
prop: Symbol,
|
||||
accessor_key: Symbol,
|
||||
non_nil_type: T::Types::Base,
|
||||
klass: T.all(Module, T::Props::ClassMethods),
|
||||
validate: T.nilable(ValidateProc),
|
||||
)
|
||||
.returns(SetterProc)
|
||||
end
|
||||
private_class_method def self.nilable_proc(prop, accessor_key, non_nil_type, klass, validate)
|
||||
proc do |val|
|
||||
if val.nil?
|
||||
instance_variable_set(accessor_key, nil)
|
||||
# this use of recursively_valid? is intentional: unlike for
|
||||
# methods, we want to make sure data at the 'edge'
|
||||
# (e.g. models that go into databases or structs serialized
|
||||
# from disk) are correct, so we use more thorough runtime
|
||||
# checks there
|
||||
elsif non_nil_type.recursively_valid?(val)
|
||||
validate&.call(prop, val)
|
||||
instance_variable_set(accessor_key, val)
|
||||
else
|
||||
T::Props::Private::SetterFactory.raise_pretty_error(
|
||||
klass,
|
||||
prop,
|
||||
non_nil_type,
|
||||
val,
|
||||
)
|
||||
instance_variable_set(accessor_key, val)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sig do
|
||||
params(
|
||||
klass: T.all(Module, T::Props::ClassMethods),
|
||||
prop: Symbol,
|
||||
type: T.any(T::Types::Base, Module),
|
||||
val: T.untyped,
|
||||
)
|
||||
.void
|
||||
end
|
||||
def self.raise_pretty_error(klass, prop, type, val)
|
||||
base_message = "Can't set #{klass.name}.#{prop} to #{val.inspect} (instance of #{val.class}) - need a #{type}"
|
||||
|
||||
pretty_message = "Parameter '#{prop}': #{base_message}\n"
|
||||
caller_loc = caller_locations.find {|l| !l.to_s.include?('sorbet-runtime/lib/types/props')}
|
||||
if caller_loc
|
||||
pretty_message += "Caller: #{caller_loc.path}:#{caller_loc.lineno}\n"
|
||||
end
|
||||
|
||||
T::Configuration.call_validation_error_handler(
|
||||
nil,
|
||||
message: base_message,
|
||||
pretty_message: pretty_message,
|
||||
kind: 'Parameter',
|
||||
name: prop,
|
||||
type: type,
|
||||
value: val,
|
||||
location: caller_loc,
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -73,7 +73,6 @@ require_relative 'types/private/abstract/validate'
|
||||
|
||||
# Catch all. Sort of built by `cd extn; find types -type f | grep -v test | sort`
|
||||
require_relative 'types/generic'
|
||||
require_relative 'types/interface_wrapper'
|
||||
require_relative 'types/private/abstract/declare'
|
||||
require_relative 'types/private/abstract/hooks'
|
||||
require_relative 'types/private/casts'
|
@ -18,7 +18,6 @@ module T::Private::Abstract::Declare
|
||||
Abstract::Data.set(mod, :abstract_type, type)
|
||||
|
||||
mod.extend(Abstract::Hooks)
|
||||
mod.extend(T::InterfaceWrapper::Helpers)
|
||||
|
||||
if mod.is_a?(Class)
|
||||
if type == :interface
|
@ -191,12 +191,11 @@ module T::Private::Methods
|
||||
end
|
||||
end
|
||||
|
||||
def self.add_module_with_final_method(mod, method_name, is_singleton_method)
|
||||
m = is_singleton_method ? mod.singleton_class : mod
|
||||
methods = @modules_with_final[m]
|
||||
def self.add_module_with_final_method(mod, method_name)
|
||||
methods = @modules_with_final[mod]
|
||||
if methods.nil?
|
||||
methods = {}
|
||||
@modules_with_final[m] = methods
|
||||
@modules_with_final[mod] = methods
|
||||
end
|
||||
methods[method_name] = true
|
||||
nil
|
||||
@ -209,13 +208,12 @@ module T::Private::Methods
|
||||
end
|
||||
|
||||
# Only public because it needs to get called below inside the replace_method blocks below.
|
||||
def self._on_method_added(hook_mod, method_name, is_singleton_method: false)
|
||||
def self._on_method_added(hook_mod, mod, method_name)
|
||||
if T::Private::DeclState.current.skip_on_method_added
|
||||
return
|
||||
end
|
||||
|
||||
current_declaration = T::Private::DeclState.current.active_declaration
|
||||
mod = is_singleton_method ? hook_mod.singleton_class : hook_mod
|
||||
|
||||
if T::Private::Final.final_module?(mod) && (current_declaration.nil? || !current_declaration.final)
|
||||
raise "#{mod} was declared as final but its method `#{method_name}` was not declared as final"
|
||||
@ -286,7 +284,7 @@ module T::Private::Methods
|
||||
# use hook_mod, not mod, because for example, we want class C to be marked as having final if we def C.foo as
|
||||
# final. change this to mod to see some final_method tests fail.
|
||||
note_module_deals_with_final(hook_mod)
|
||||
add_module_with_final_method(hook_mod, method_name, is_singleton_method)
|
||||
add_module_with_final_method(mod, method_name)
|
||||
end
|
||||
end
|
||||
|
||||
@ -430,7 +428,7 @@ module T::Private::Methods
|
||||
run_sig_block_for_key(method_to_key(method))
|
||||
end
|
||||
|
||||
private_class_method def self.run_sig_block_for_key(key)
|
||||
private_class_method def self.run_sig_block_for_key(key, force_type_init: false)
|
||||
blk = @sig_wrappers[key]
|
||||
if !blk
|
||||
sig = @signatures_by_method[key]
|
||||
@ -453,14 +451,17 @@ module T::Private::Methods
|
||||
end
|
||||
|
||||
@sig_wrappers.delete(key)
|
||||
|
||||
sig.force_type_init if force_type_init
|
||||
|
||||
sig
|
||||
end
|
||||
|
||||
def self.run_all_sig_blocks
|
||||
def self.run_all_sig_blocks(force_type_init: true)
|
||||
loop do
|
||||
break if @sig_wrappers.empty?
|
||||
key, = @sig_wrappers.first
|
||||
run_sig_block_for_key(key)
|
||||
run_sig_block_for_key(key, force_type_init: force_type_init)
|
||||
end
|
||||
end
|
||||
|
||||
@ -540,14 +541,14 @@ module T::Private::Methods
|
||||
module MethodHooks
|
||||
def method_added(name)
|
||||
super(name)
|
||||
::T::Private::Methods._on_method_added(self, name, is_singleton_method: false)
|
||||
::T::Private::Methods._on_method_added(self, self, name)
|
||||
end
|
||||
end
|
||||
|
||||
module SingletonMethodHooks
|
||||
def singleton_method_added(name)
|
||||
super(name)
|
||||
::T::Private::Methods._on_method_added(self, name, is_singleton_method: true)
|
||||
::T::Private::Methods._on_method_added(self, singleton_class, name)
|
||||
end
|
||||
end
|
||||
|
@ -15,8 +15,6 @@ module T::Private::Methods::CallValidation
|
||||
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, true) 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)
|
||||
@ -67,14 +65,30 @@ module T::Private::Methods::CallValidation
|
||||
simple_method = all_args_are_simple && method_sig.return_type.is_a?(T::Types::Simple)
|
||||
simple_procedure = all_args_are_simple && method_sig.return_type.is_a?(T::Private::Types::Void)
|
||||
|
||||
# All the types for which valid? unconditionally returns `true`
|
||||
return_is_ignorable =
|
||||
(method_sig.return_type.equal?(T::Types::Untyped::Private::INSTANCE) ||
|
||||
method_sig.return_type.equal?(T::Types::Anything::Private::INSTANCE) ||
|
||||
method_sig.return_type.equal?(T::Types::AttachedClassType::Private::INSTANCE) ||
|
||||
method_sig.return_type.equal?(T::Types::SelfType::Private::INSTANCE) ||
|
||||
method_sig.return_type.is_a?(T::Types::TypeParameter) ||
|
||||
method_sig.return_type.is_a?(T::Types::TypeVariable) ||
|
||||
(method_sig.return_type.is_a?(T::Types::Simple) && method_sig.return_type.raw_type.equal?(BasicObject)))
|
||||
|
||||
returns_anything_method = all_args_are_simple && return_is_ignorable
|
||||
|
||||
T::Configuration.without_ruby_warnings do
|
||||
T::Private::DeclState.current.without_on_method_added do
|
||||
if simple_method
|
||||
create_validator_method_fast(mod, original_method, method_sig, original_visibility)
|
||||
elsif returns_anything_method
|
||||
create_validator_method_skip_return_fast(mod, original_method, method_sig, original_visibility)
|
||||
elsif simple_procedure
|
||||
create_validator_procedure_fast(mod, original_method, method_sig, original_visibility)
|
||||
elsif ok_for_fast_path && method_sig.return_type.is_a?(T::Private::Types::Void)
|
||||
create_validator_procedure_medium(mod, original_method, method_sig, original_visibility)
|
||||
elsif ok_for_fast_path && return_is_ignorable
|
||||
create_validator_method_skip_return_medium(mod, original_method, method_sig, original_visibility)
|
||||
elsif ok_for_fast_path
|
||||
create_validator_method_medium(mod, original_method, method_sig, original_visibility)
|
||||
elsif can_skip_block_type
|
@ -343,6 +343,265 @@ module T::Private::Methods::CallValidation
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_fast(mod, original_method, method_sig, original_visibility)
|
||||
# trampoline to reduce stack frame size
|
||||
arg_types = method_sig.arg_types
|
||||
case arg_types.length
|
||||
when 0
|
||||
create_validator_method_skip_return_fast0(mod, original_method, method_sig, original_visibility)
|
||||
when 1
|
||||
create_validator_method_skip_return_fast1(mod, original_method, method_sig, original_visibility,
|
||||
arg_types[0][1].raw_type)
|
||||
when 2
|
||||
create_validator_method_skip_return_fast2(mod, original_method, method_sig, original_visibility,
|
||||
arg_types[0][1].raw_type,
|
||||
arg_types[1][1].raw_type)
|
||||
when 3
|
||||
create_validator_method_skip_return_fast3(mod, original_method, method_sig, original_visibility,
|
||||
arg_types[0][1].raw_type,
|
||||
arg_types[1][1].raw_type,
|
||||
arg_types[2][1].raw_type)
|
||||
when 4
|
||||
create_validator_method_skip_return_fast4(mod, original_method, method_sig, original_visibility,
|
||||
arg_types[0][1].raw_type,
|
||||
arg_types[1][1].raw_type,
|
||||
arg_types[2][1].raw_type,
|
||||
arg_types[3][1].raw_type)
|
||||
else
|
||||
raise 'should not happen'
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_fast0(mod, original_method, method_sig, original_visibility)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |&blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind(self).call(&blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_fast1(mod, original_method, method_sig, original_visibility, arg0_type)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, &blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
unless arg0.is_a?(arg0_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[0][1].error_message_for_obj(arg0),
|
||||
'Parameter',
|
||||
method_sig.arg_types[0][0],
|
||||
arg0_type,
|
||||
arg0,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind(self).call(arg0, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_fast2(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, &blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
unless arg0.is_a?(arg0_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[0][1].error_message_for_obj(arg0),
|
||||
'Parameter',
|
||||
method_sig.arg_types[0][0],
|
||||
arg0_type,
|
||||
arg0,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg1.is_a?(arg1_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[1][1].error_message_for_obj(arg1),
|
||||
'Parameter',
|
||||
method_sig.arg_types[1][0],
|
||||
arg1_type,
|
||||
arg1,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind(self).call(arg0, arg1, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_fast3(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, &blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
unless arg0.is_a?(arg0_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[0][1].error_message_for_obj(arg0),
|
||||
'Parameter',
|
||||
method_sig.arg_types[0][0],
|
||||
arg0_type,
|
||||
arg0,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg1.is_a?(arg1_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[1][1].error_message_for_obj(arg1),
|
||||
'Parameter',
|
||||
method_sig.arg_types[1][0],
|
||||
arg1_type,
|
||||
arg1,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg2.is_a?(arg2_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[2][1].error_message_for_obj(arg2),
|
||||
'Parameter',
|
||||
method_sig.arg_types[2][0],
|
||||
arg2_type,
|
||||
arg2,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind(self).call(arg0, arg1, arg2, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_fast4(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type, arg3_type)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, arg3, &blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
unless arg0.is_a?(arg0_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[0][1].error_message_for_obj(arg0),
|
||||
'Parameter',
|
||||
method_sig.arg_types[0][0],
|
||||
arg0_type,
|
||||
arg0,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg1.is_a?(arg1_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[1][1].error_message_for_obj(arg1),
|
||||
'Parameter',
|
||||
method_sig.arg_types[1][0],
|
||||
arg1_type,
|
||||
arg1,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg2.is_a?(arg2_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[2][1].error_message_for_obj(arg2),
|
||||
'Parameter',
|
||||
method_sig.arg_types[2][0],
|
||||
arg2_type,
|
||||
arg2,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg3.is_a?(arg3_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[3][1].error_message_for_obj(arg3),
|
||||
'Parameter',
|
||||
method_sig.arg_types[3][0],
|
||||
arg3_type,
|
||||
arg3,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind(self).call(arg0, arg1, arg2, arg3, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_procedure_fast(mod, original_method, method_sig, original_visibility)
|
||||
# trampoline to reduce stack frame size
|
||||
arg_types = method_sig.arg_types
|
||||
@ -944,6 +1203,265 @@ module T::Private::Methods::CallValidation
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_medium(mod, original_method, method_sig, original_visibility)
|
||||
# trampoline to reduce stack frame size
|
||||
arg_types = method_sig.arg_types
|
||||
case arg_types.length
|
||||
when 0
|
||||
create_validator_method_skip_return_medium0(mod, original_method, method_sig, original_visibility)
|
||||
when 1
|
||||
create_validator_method_skip_return_medium1(mod, original_method, method_sig, original_visibility,
|
||||
arg_types[0][1])
|
||||
when 2
|
||||
create_validator_method_skip_return_medium2(mod, original_method, method_sig, original_visibility,
|
||||
arg_types[0][1],
|
||||
arg_types[1][1])
|
||||
when 3
|
||||
create_validator_method_skip_return_medium3(mod, original_method, method_sig, original_visibility,
|
||||
arg_types[0][1],
|
||||
arg_types[1][1],
|
||||
arg_types[2][1])
|
||||
when 4
|
||||
create_validator_method_skip_return_medium4(mod, original_method, method_sig, original_visibility,
|
||||
arg_types[0][1],
|
||||
arg_types[1][1],
|
||||
arg_types[2][1],
|
||||
arg_types[3][1])
|
||||
else
|
||||
raise 'should not happen'
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_medium0(mod, original_method, method_sig, original_visibility)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |&blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind(self).call(&blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_medium1(mod, original_method, method_sig, original_visibility, arg0_type)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, &blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
unless arg0_type.valid?(arg0)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[0][1].error_message_for_obj(arg0),
|
||||
'Parameter',
|
||||
method_sig.arg_types[0][0],
|
||||
arg0_type,
|
||||
arg0,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind(self).call(arg0, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_medium2(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, &blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
unless arg0_type.valid?(arg0)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[0][1].error_message_for_obj(arg0),
|
||||
'Parameter',
|
||||
method_sig.arg_types[0][0],
|
||||
arg0_type,
|
||||
arg0,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg1_type.valid?(arg1)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[1][1].error_message_for_obj(arg1),
|
||||
'Parameter',
|
||||
method_sig.arg_types[1][0],
|
||||
arg1_type,
|
||||
arg1,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind(self).call(arg0, arg1, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_medium3(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, &blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
unless arg0_type.valid?(arg0)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[0][1].error_message_for_obj(arg0),
|
||||
'Parameter',
|
||||
method_sig.arg_types[0][0],
|
||||
arg0_type,
|
||||
arg0,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg1_type.valid?(arg1)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[1][1].error_message_for_obj(arg1),
|
||||
'Parameter',
|
||||
method_sig.arg_types[1][0],
|
||||
arg1_type,
|
||||
arg1,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg2_type.valid?(arg2)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[2][1].error_message_for_obj(arg2),
|
||||
'Parameter',
|
||||
method_sig.arg_types[2][0],
|
||||
arg2_type,
|
||||
arg2,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind(self).call(arg0, arg1, arg2, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_medium4(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type, arg3_type)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, arg3, &blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
unless arg0_type.valid?(arg0)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[0][1].error_message_for_obj(arg0),
|
||||
'Parameter',
|
||||
method_sig.arg_types[0][0],
|
||||
arg0_type,
|
||||
arg0,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg1_type.valid?(arg1)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[1][1].error_message_for_obj(arg1),
|
||||
'Parameter',
|
||||
method_sig.arg_types[1][0],
|
||||
arg1_type,
|
||||
arg1,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg2_type.valid?(arg2)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[2][1].error_message_for_obj(arg2),
|
||||
'Parameter',
|
||||
method_sig.arg_types[2][0],
|
||||
arg2_type,
|
||||
arg2,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg3_type.valid?(arg3)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[3][1].error_message_for_obj(arg3),
|
||||
'Parameter',
|
||||
method_sig.arg_types[3][0],
|
||||
arg3_type,
|
||||
arg3,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind(self).call(arg0, arg1, arg2, arg3, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_procedure_medium(mod, original_method, method_sig, original_visibility)
|
||||
# trampoline to reduce stack frame size
|
||||
arg_types = method_sig.arg_types
|
@ -343,6 +343,265 @@ module T::Private::Methods::CallValidation
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_fast(mod, original_method, method_sig, original_visibility)
|
||||
# trampoline to reduce stack frame size
|
||||
arg_types = method_sig.arg_types
|
||||
case arg_types.length
|
||||
when 0
|
||||
create_validator_method_skip_return_fast0(mod, original_method, method_sig, original_visibility)
|
||||
when 1
|
||||
create_validator_method_skip_return_fast1(mod, original_method, method_sig, original_visibility,
|
||||
arg_types[0][1].raw_type)
|
||||
when 2
|
||||
create_validator_method_skip_return_fast2(mod, original_method, method_sig, original_visibility,
|
||||
arg_types[0][1].raw_type,
|
||||
arg_types[1][1].raw_type)
|
||||
when 3
|
||||
create_validator_method_skip_return_fast3(mod, original_method, method_sig, original_visibility,
|
||||
arg_types[0][1].raw_type,
|
||||
arg_types[1][1].raw_type,
|
||||
arg_types[2][1].raw_type)
|
||||
when 4
|
||||
create_validator_method_skip_return_fast4(mod, original_method, method_sig, original_visibility,
|
||||
arg_types[0][1].raw_type,
|
||||
arg_types[1][1].raw_type,
|
||||
arg_types[2][1].raw_type,
|
||||
arg_types[3][1].raw_type)
|
||||
else
|
||||
raise 'should not happen'
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_fast0(mod, original_method, method_sig, original_visibility)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |&blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind_call(self, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_fast1(mod, original_method, method_sig, original_visibility, arg0_type)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, &blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
unless arg0.is_a?(arg0_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[0][1].error_message_for_obj(arg0),
|
||||
'Parameter',
|
||||
method_sig.arg_types[0][0],
|
||||
arg0_type,
|
||||
arg0,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind_call(self, arg0, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_fast2(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, &blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
unless arg0.is_a?(arg0_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[0][1].error_message_for_obj(arg0),
|
||||
'Parameter',
|
||||
method_sig.arg_types[0][0],
|
||||
arg0_type,
|
||||
arg0,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg1.is_a?(arg1_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[1][1].error_message_for_obj(arg1),
|
||||
'Parameter',
|
||||
method_sig.arg_types[1][0],
|
||||
arg1_type,
|
||||
arg1,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind_call(self, arg0, arg1, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_fast3(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, &blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
unless arg0.is_a?(arg0_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[0][1].error_message_for_obj(arg0),
|
||||
'Parameter',
|
||||
method_sig.arg_types[0][0],
|
||||
arg0_type,
|
||||
arg0,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg1.is_a?(arg1_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[1][1].error_message_for_obj(arg1),
|
||||
'Parameter',
|
||||
method_sig.arg_types[1][0],
|
||||
arg1_type,
|
||||
arg1,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg2.is_a?(arg2_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[2][1].error_message_for_obj(arg2),
|
||||
'Parameter',
|
||||
method_sig.arg_types[2][0],
|
||||
arg2_type,
|
||||
arg2,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind_call(self, arg0, arg1, arg2, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_fast4(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type, arg3_type)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, arg3, &blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
unless arg0.is_a?(arg0_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[0][1].error_message_for_obj(arg0),
|
||||
'Parameter',
|
||||
method_sig.arg_types[0][0],
|
||||
arg0_type,
|
||||
arg0,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg1.is_a?(arg1_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[1][1].error_message_for_obj(arg1),
|
||||
'Parameter',
|
||||
method_sig.arg_types[1][0],
|
||||
arg1_type,
|
||||
arg1,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg2.is_a?(arg2_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[2][1].error_message_for_obj(arg2),
|
||||
'Parameter',
|
||||
method_sig.arg_types[2][0],
|
||||
arg2_type,
|
||||
arg2,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg3.is_a?(arg3_type)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[3][1].error_message_for_obj(arg3),
|
||||
'Parameter',
|
||||
method_sig.arg_types[3][0],
|
||||
arg3_type,
|
||||
arg3,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind_call(self, arg0, arg1, arg2, arg3, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_procedure_fast(mod, original_method, method_sig, original_visibility)
|
||||
# trampoline to reduce stack frame size
|
||||
arg_types = method_sig.arg_types
|
||||
@ -944,6 +1203,265 @@ module T::Private::Methods::CallValidation
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_medium(mod, original_method, method_sig, original_visibility)
|
||||
# trampoline to reduce stack frame size
|
||||
arg_types = method_sig.arg_types
|
||||
case arg_types.length
|
||||
when 0
|
||||
create_validator_method_skip_return_medium0(mod, original_method, method_sig, original_visibility)
|
||||
when 1
|
||||
create_validator_method_skip_return_medium1(mod, original_method, method_sig, original_visibility,
|
||||
arg_types[0][1])
|
||||
when 2
|
||||
create_validator_method_skip_return_medium2(mod, original_method, method_sig, original_visibility,
|
||||
arg_types[0][1],
|
||||
arg_types[1][1])
|
||||
when 3
|
||||
create_validator_method_skip_return_medium3(mod, original_method, method_sig, original_visibility,
|
||||
arg_types[0][1],
|
||||
arg_types[1][1],
|
||||
arg_types[2][1])
|
||||
when 4
|
||||
create_validator_method_skip_return_medium4(mod, original_method, method_sig, original_visibility,
|
||||
arg_types[0][1],
|
||||
arg_types[1][1],
|
||||
arg_types[2][1],
|
||||
arg_types[3][1])
|
||||
else
|
||||
raise 'should not happen'
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_medium0(mod, original_method, method_sig, original_visibility)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |&blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind_call(self, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_medium1(mod, original_method, method_sig, original_visibility, arg0_type)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, &blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
unless arg0_type.valid?(arg0)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[0][1].error_message_for_obj(arg0),
|
||||
'Parameter',
|
||||
method_sig.arg_types[0][0],
|
||||
arg0_type,
|
||||
arg0,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind_call(self, arg0, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_medium2(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, &blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
unless arg0_type.valid?(arg0)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[0][1].error_message_for_obj(arg0),
|
||||
'Parameter',
|
||||
method_sig.arg_types[0][0],
|
||||
arg0_type,
|
||||
arg0,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg1_type.valid?(arg1)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[1][1].error_message_for_obj(arg1),
|
||||
'Parameter',
|
||||
method_sig.arg_types[1][0],
|
||||
arg1_type,
|
||||
arg1,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind_call(self, arg0, arg1, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_medium3(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, &blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
unless arg0_type.valid?(arg0)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[0][1].error_message_for_obj(arg0),
|
||||
'Parameter',
|
||||
method_sig.arg_types[0][0],
|
||||
arg0_type,
|
||||
arg0,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg1_type.valid?(arg1)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[1][1].error_message_for_obj(arg1),
|
||||
'Parameter',
|
||||
method_sig.arg_types[1][0],
|
||||
arg1_type,
|
||||
arg1,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg2_type.valid?(arg2)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[2][1].error_message_for_obj(arg2),
|
||||
'Parameter',
|
||||
method_sig.arg_types[2][0],
|
||||
arg2_type,
|
||||
arg2,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind_call(self, arg0, arg1, arg2, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_method_skip_return_medium4(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type, arg3_type)
|
||||
T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, arg3, &blk|
|
||||
# This method is a manually sped-up version of more general code in `validate_call`
|
||||
unless arg0_type.valid?(arg0)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[0][1].error_message_for_obj(arg0),
|
||||
'Parameter',
|
||||
method_sig.arg_types[0][0],
|
||||
arg0_type,
|
||||
arg0,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg1_type.valid?(arg1)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[1][1].error_message_for_obj(arg1),
|
||||
'Parameter',
|
||||
method_sig.arg_types[1][0],
|
||||
arg1_type,
|
||||
arg1,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg2_type.valid?(arg2)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[2][1].error_message_for_obj(arg2),
|
||||
'Parameter',
|
||||
method_sig.arg_types[2][0],
|
||||
arg2_type,
|
||||
arg2,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
unless arg3_type.valid?(arg3)
|
||||
CallValidation.report_error(
|
||||
method_sig,
|
||||
method_sig.arg_types[3][1].error_message_for_obj(arg3),
|
||||
'Parameter',
|
||||
method_sig.arg_types[3][0],
|
||||
arg3_type,
|
||||
arg3,
|
||||
caller_offset: -1
|
||||
)
|
||||
end
|
||||
|
||||
# The following line breaks are intentional to show nice pry message
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PRY note:
|
||||
# this code is sig validation code.
|
||||
# Please issue `finish` to step out of it
|
||||
|
||||
original_method.bind_call(self, arg0, arg1, arg2, arg3, &blk)
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_validator_procedure_medium(mod, original_method, method_sig, original_visibility)
|
||||
# trampoline to reduce stack frame size
|
||||
arg_types = method_sig.arg_types
|
@ -183,7 +183,7 @@ module T::Private::Methods
|
||||
self
|
||||
end
|
||||
|
||||
# Declares valid type paramaters which can be used with `T.type_parameter` in
|
||||
# Declares valid type parameters which can be used with `T.type_parameter` in
|
||||
# this `sig`.
|
||||
#
|
||||
# This is used for generic methods. Example usage:
|
@ -245,6 +245,15 @@ class T::Private::Methods::Signature
|
||||
"#{@method} at #{loc}"
|
||||
end
|
||||
|
||||
def force_type_init
|
||||
@arg_types.each {|_, type| type.build_type}
|
||||
@kwarg_types.each {|_, type| type.build_type}
|
||||
@block_type&.build_type
|
||||
@rest_type&.build_type
|
||||
@keyrest_type&.build_type
|
||||
@return_type.build_type
|
||||
end
|
||||
|
||||
EMPTY_LIST = [].freeze
|
||||
EMPTY_HASH = {}.freeze
|
||||
end
|
@ -262,7 +262,14 @@ module T::Private::Methods::SignatureValidation
|
||||
end
|
||||
|
||||
# return types must be covariant
|
||||
if !signature.return_type.subtype_of?(super_signature.return_type)
|
||||
super_signature_return_type = super_signature.return_type
|
||||
|
||||
if super_signature_return_type == T::Private::Types::Void::Private::INSTANCE
|
||||
# Treat `.void` as `T.anything` (see corresponding comment in definition_valitor for more)
|
||||
super_signature_return_type = T::Types::Anything::Private::INSTANCE
|
||||
end
|
||||
|
||||
if !signature.return_type.subtype_of?(super_signature_return_type)
|
||||
raise "Incompatible return type in signature for #{mode_noun} of method `#{signature.method_name}`:\n" \
|
||||
"* Base: `#{super_signature.return_type}` (in #{method_loc_str(super_signature.method)})\n" \
|
||||
"* #{mode_noun.capitalize}: `#{signature.return_type}` (in #{method_loc_str(signature.method)})\n" \
|
@ -6,6 +6,10 @@
|
||||
class T::Private::Types::NotTyped < T::Types::Base
|
||||
ERROR_MESSAGE = "Validation is being done on a `NotTyped`. Please report this bug at https://github.com/sorbet/sorbet/issues"
|
||||
|
||||
def build_type
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"<NOT-TYPED>"
|
@ -9,6 +9,10 @@ class T::Private::Types::StringHolder < T::Types::Base
|
||||
@string = string
|
||||
end
|
||||
|
||||
def build_type
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
string
|
@ -9,6 +9,10 @@ module T::Private::Types
|
||||
@callable = callable
|
||||
end
|
||||
|
||||
def build_type
|
||||
nil
|
||||
end
|
||||
|
||||
def aliased_type
|
||||
@aliased_type ||= T::Utils.coerce(@callable.call)
|
||||
end
|
@ -18,6 +18,10 @@ module T::Private::Types
|
||||
freeze
|
||||
end
|
||||
|
||||
def build_type
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"<VOID>"
|
@ -139,9 +139,9 @@ module T::Props
|
||||
end
|
||||
|
||||
if cls_or_args.is_a?(Hash)
|
||||
self.prop(name, **cls_or_args.merge(immutable: true))
|
||||
self.prop(name, cls_or_args.merge(immutable: true))
|
||||
else
|
||||
self.prop(name, cls_or_args, **args.merge(immutable: true))
|
||||
self.prop(name, cls_or_args, args.merge(immutable: true))
|
||||
end
|
||||
end
|
||||
|
@ -100,10 +100,7 @@ class T::Props::Decorator
|
||||
# checked(:never) - potentially O(prop accesses) depending on usage pattern
|
||||
sig {params(prop: Symbol, val: T.untyped).void.checked(:never)}
|
||||
def validate_prop_value(prop, val)
|
||||
# We call `setter_proc` here without binding to an instance, so it'll run
|
||||
# `instance_variable_set` if validation passes, but nothing will care.
|
||||
# We only care about the validation.
|
||||
prop_rules(prop).fetch(:setter_proc).call(val)
|
||||
prop_rules(prop).fetch(:value_validate_proc).call(val)
|
||||
end
|
||||
|
||||
# For performance, don't use named params here.
|
||||
@ -335,7 +332,7 @@ class T::Props::Decorator
|
||||
|
||||
prop_validate_definition!(name, cls, rules, type_object)
|
||||
|
||||
# Retrive the possible underlying object with T.nilable.
|
||||
# Retrieve the possible underlying object with T.nilable.
|
||||
type = T::Utils::Nilable.get_underlying_type(type)
|
||||
|
||||
rules_sensitivity = rules[:sensitivity]
|
||||
@ -378,7 +375,11 @@ class T::Props::Decorator
|
||||
end
|
||||
end
|
||||
|
||||
rules[:setter_proc] = T::Props::Private::SetterFactory.build_setter_proc(@class, name, rules).freeze
|
||||
setter_proc, value_validate_proc = T::Props::Private::SetterFactory.build_setter_proc(@class, name, rules)
|
||||
setter_proc.freeze
|
||||
value_validate_proc.freeze
|
||||
rules[:setter_proc] = setter_proc
|
||||
rules[:value_validate_proc] = value_validate_proc
|
||||
|
||||
add_prop_definition(name, rules)
|
||||
|
@ -0,0 +1,257 @@
|
||||
# frozen_string_literal: true
|
||||
# typed: strict
|
||||
|
||||
module T::Props
|
||||
module Private
|
||||
module SetterFactory
|
||||
extend T::Sig
|
||||
|
||||
SetterProc = T.type_alias {T.proc.params(val: T.untyped).void}
|
||||
ValueValidationProc = T.type_alias {T.proc.params(val: T.untyped).void}
|
||||
ValidateProc = T.type_alias {T.proc.params(prop: Symbol, value: T.untyped).void}
|
||||
|
||||
sig do
|
||||
params(
|
||||
klass: T.all(Module, T::Props::ClassMethods),
|
||||
prop: Symbol,
|
||||
rules: T::Hash[Symbol, T.untyped]
|
||||
)
|
||||
.returns([SetterProc, ValueValidationProc])
|
||||
.checked(:never)
|
||||
end
|
||||
def self.build_setter_proc(klass, prop, rules)
|
||||
# Our nil check works differently than a simple T.nilable for various
|
||||
# reasons (including the `raise_on_nil_write` setting and the existence
|
||||
# of defaults & factories), so unwrap any T.nilable and do a check
|
||||
# manually.
|
||||
non_nil_type = T::Utils::Nilable.get_underlying_type_object(rules.fetch(:type_object))
|
||||
accessor_key = rules.fetch(:accessor_key)
|
||||
validate = rules[:setter_validate]
|
||||
|
||||
# It seems like a bug that this affects the behavior of setters, but
|
||||
# some existing code relies on this behavior
|
||||
has_explicit_nil_default = rules.key?(:default) && rules.fetch(:default).nil?
|
||||
|
||||
# Use separate methods in order to ensure that we only close over necessary
|
||||
# variables
|
||||
if !T::Props::Utils.need_nil_write_check?(rules) || has_explicit_nil_default
|
||||
if validate.nil? && non_nil_type.is_a?(T::Types::Simple)
|
||||
simple_nilable_proc(prop, accessor_key, non_nil_type.raw_type, klass)
|
||||
else
|
||||
nilable_proc(prop, accessor_key, non_nil_type, klass, validate)
|
||||
end
|
||||
else
|
||||
if validate.nil? && non_nil_type.is_a?(T::Types::Simple)
|
||||
simple_non_nil_proc(prop, accessor_key, non_nil_type.raw_type, klass)
|
||||
else
|
||||
non_nil_proc(prop, accessor_key, non_nil_type, klass, validate)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sig do
|
||||
params(
|
||||
prop: Symbol,
|
||||
accessor_key: Symbol,
|
||||
non_nil_type: Module,
|
||||
klass: T.all(Module, T::Props::ClassMethods),
|
||||
)
|
||||
.returns([SetterProc, ValueValidationProc])
|
||||
end
|
||||
private_class_method def self.simple_non_nil_proc(prop, accessor_key, non_nil_type, klass)
|
||||
[
|
||||
proc do |val|
|
||||
unless val.is_a?(non_nil_type)
|
||||
T::Props::Private::SetterFactory.raise_pretty_error(
|
||||
klass,
|
||||
prop,
|
||||
T::Utils.coerce(non_nil_type),
|
||||
val,
|
||||
)
|
||||
end
|
||||
instance_variable_set(accessor_key, val)
|
||||
end,
|
||||
proc do |val|
|
||||
unless val.is_a?(non_nil_type)
|
||||
T::Props::Private::SetterFactory.raise_pretty_error(
|
||||
klass,
|
||||
prop,
|
||||
T::Utils.coerce(non_nil_type),
|
||||
val,
|
||||
)
|
||||
end
|
||||
end,
|
||||
]
|
||||
end
|
||||
|
||||
sig do
|
||||
params(
|
||||
prop: Symbol,
|
||||
accessor_key: Symbol,
|
||||
non_nil_type: T::Types::Base,
|
||||
klass: T.all(Module, T::Props::ClassMethods),
|
||||
validate: T.nilable(ValidateProc)
|
||||
)
|
||||
.returns([SetterProc, ValueValidationProc])
|
||||
end
|
||||
private_class_method def self.non_nil_proc(prop, accessor_key, non_nil_type, klass, validate)
|
||||
[
|
||||
proc do |val|
|
||||
# this use of recursively_valid? is intentional: unlike for
|
||||
# methods, we want to make sure data at the 'edge'
|
||||
# (e.g. models that go into databases or structs serialized
|
||||
# from disk) are correct, so we use more thorough runtime
|
||||
# checks there
|
||||
if non_nil_type.recursively_valid?(val)
|
||||
validate&.call(prop, val)
|
||||
else
|
||||
T::Props::Private::SetterFactory.raise_pretty_error(
|
||||
klass,
|
||||
prop,
|
||||
non_nil_type,
|
||||
val,
|
||||
)
|
||||
end
|
||||
instance_variable_set(accessor_key, val)
|
||||
end,
|
||||
proc do |val|
|
||||
# this use of recursively_valid? is intentional: unlike for
|
||||
# methods, we want to make sure data at the 'edge'
|
||||
# (e.g. models that go into databases or structs serialized
|
||||
# from disk) are correct, so we use more thorough runtime
|
||||
# checks there
|
||||
if non_nil_type.recursively_valid?(val)
|
||||
validate&.call(prop, val)
|
||||
else
|
||||
T::Props::Private::SetterFactory.raise_pretty_error(
|
||||
klass,
|
||||
prop,
|
||||
non_nil_type,
|
||||
val,
|
||||
)
|
||||
end
|
||||
end,
|
||||
]
|
||||
end
|
||||
|
||||
sig do
|
||||
params(
|
||||
prop: Symbol,
|
||||
accessor_key: Symbol,
|
||||
non_nil_type: Module,
|
||||
klass: T.all(Module, T::Props::ClassMethods),
|
||||
)
|
||||
.returns([SetterProc, ValueValidationProc])
|
||||
end
|
||||
private_class_method def self.simple_nilable_proc(prop, accessor_key, non_nil_type, klass)
|
||||
[
|
||||
proc do |val|
|
||||
unless val.nil? || val.is_a?(non_nil_type)
|
||||
T::Props::Private::SetterFactory.raise_pretty_error(
|
||||
klass,
|
||||
prop,
|
||||
T::Utils.coerce(non_nil_type),
|
||||
val,
|
||||
)
|
||||
end
|
||||
instance_variable_set(accessor_key, val)
|
||||
end,
|
||||
proc do |val|
|
||||
unless val.nil? || val.is_a?(non_nil_type)
|
||||
T::Props::Private::SetterFactory.raise_pretty_error(
|
||||
klass,
|
||||
prop,
|
||||
T::Utils.coerce(non_nil_type),
|
||||
val,
|
||||
)
|
||||
end
|
||||
end,
|
||||
]
|
||||
end
|
||||
|
||||
sig do
|
||||
params(
|
||||
prop: Symbol,
|
||||
accessor_key: Symbol,
|
||||
non_nil_type: T::Types::Base,
|
||||
klass: T.all(Module, T::Props::ClassMethods),
|
||||
validate: T.nilable(ValidateProc),
|
||||
)
|
||||
.returns([SetterProc, ValueValidationProc])
|
||||
end
|
||||
private_class_method def self.nilable_proc(prop, accessor_key, non_nil_type, klass, validate)
|
||||
[
|
||||
proc do |val|
|
||||
if val.nil?
|
||||
instance_variable_set(accessor_key, nil)
|
||||
# this use of recursively_valid? is intentional: unlike for
|
||||
# methods, we want to make sure data at the 'edge'
|
||||
# (e.g. models that go into databases or structs serialized
|
||||
# from disk) are correct, so we use more thorough runtime
|
||||
# checks there
|
||||
elsif non_nil_type.recursively_valid?(val)
|
||||
validate&.call(prop, val)
|
||||
instance_variable_set(accessor_key, val)
|
||||
else
|
||||
T::Props::Private::SetterFactory.raise_pretty_error(
|
||||
klass,
|
||||
prop,
|
||||
non_nil_type,
|
||||
val,
|
||||
)
|
||||
instance_variable_set(accessor_key, val)
|
||||
end
|
||||
end,
|
||||
proc do |val|
|
||||
if val.nil?
|
||||
# this use of recursively_valid? is intentional: unlike for
|
||||
# methods, we want to make sure data at the 'edge'
|
||||
# (e.g. models that go into databases or structs serialized
|
||||
# from disk) are correct, so we use more thorough runtime
|
||||
# checks there
|
||||
elsif non_nil_type.recursively_valid?(val)
|
||||
validate&.call(prop, val)
|
||||
else
|
||||
T::Props::Private::SetterFactory.raise_pretty_error(
|
||||
klass,
|
||||
prop,
|
||||
non_nil_type,
|
||||
val,
|
||||
)
|
||||
end
|
||||
end,
|
||||
]
|
||||
end
|
||||
|
||||
sig do
|
||||
params(
|
||||
klass: T.all(Module, T::Props::ClassMethods),
|
||||
prop: Symbol,
|
||||
type: T.any(T::Types::Base, Module),
|
||||
val: T.untyped,
|
||||
)
|
||||
.void
|
||||
end
|
||||
def self.raise_pretty_error(klass, prop, type, val)
|
||||
base_message = "Can't set #{klass.name}.#{prop} to #{val.inspect} (instance of #{val.class}) - need a #{type}"
|
||||
|
||||
pretty_message = "Parameter '#{prop}': #{base_message}\n"
|
||||
caller_loc = caller_locations.find {|l| !l.to_s.include?('sorbet-runtime/lib/types/props')}
|
||||
if caller_loc
|
||||
pretty_message += "Caller: #{caller_loc.path}:#{caller_loc.lineno}\n"
|
||||
end
|
||||
|
||||
T::Configuration.call_validation_error_handler(
|
||||
nil,
|
||||
message: base_message,
|
||||
pretty_message: pretty_message,
|
||||
kind: 'Parameter',
|
||||
name: prop,
|
||||
type: type,
|
||||
value: val,
|
||||
location: caller_loc,
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -6,6 +6,10 @@ module T::Types
|
||||
class Anything < Base
|
||||
def initialize; end
|
||||
|
||||
def build_type
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"T.anything"
|
@ -10,6 +10,10 @@ module T::Types
|
||||
|
||||
def initialize(); end
|
||||
|
||||
def build_type
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"T.attached_class"
|
@ -33,6 +33,12 @@ module T::Types
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Force any lazy initialization that this type might need to do
|
||||
# It's unusual to call this directly; you probably want to call it indirectly via `T::Utils.run_all_sig_blocks`.
|
||||
def build_type
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Equality is based on name, so be sure the name reflects all relevant state when implementing.
|
||||
def name
|
||||
raise NotImplementedError
|
@ -10,6 +10,10 @@ module T::Types
|
||||
@type = type
|
||||
end
|
||||
|
||||
def build_type
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"T.class_of(#{@type})"
|
@ -12,6 +12,10 @@ module T::Types
|
||||
@values = values
|
||||
end
|
||||
|
||||
def build_type
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def valid?(obj)
|
||||
@values.member?(obj)
|
@ -6,23 +6,30 @@ module T::Types
|
||||
# Takes a list of types. Validates each item in an array using the type in the same position
|
||||
# in the list.
|
||||
class FixedArray < Base
|
||||
attr_reader :types
|
||||
|
||||
def initialize(types)
|
||||
@types = types.map {|type| T::Utils.coerce(type)}
|
||||
@inner_types = types
|
||||
end
|
||||
|
||||
def types
|
||||
@types ||= @inner_types.map {|type| T::Utils.coerce(type)}
|
||||
end
|
||||
|
||||
def build_type
|
||||
types
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"[#{@types.join(', ')}]"
|
||||
"[#{types.join(', ')}]"
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def recursively_valid?(obj)
|
||||
if obj.is_a?(Array) && obj.length == @types.length
|
||||
if obj.is_a?(Array) && obj.length == types.length
|
||||
i = 0
|
||||
while i < @types.length
|
||||
if !@types[i].recursively_valid?(obj[i])
|
||||
while i < types.length
|
||||
if !types[i].recursively_valid?(obj[i])
|
||||
return false
|
||||
end
|
||||
i += 1
|
||||
@ -35,10 +42,10 @@ module T::Types
|
||||
|
||||
# overrides Base
|
||||
def valid?(obj)
|
||||
if obj.is_a?(Array) && obj.length == @types.length
|
||||
if obj.is_a?(Array) && obj.length == types.length
|
||||
i = 0
|
||||
while i < @types.length
|
||||
if !@types[i].valid?(obj[i])
|
||||
while i < types.length
|
||||
if !types[i].valid?(obj[i])
|
||||
return false
|
||||
end
|
||||
i += 1
|
||||
@ -56,7 +63,7 @@ module T::Types
|
||||
# Properly speaking, covariance here is unsound since arrays
|
||||
# can be mutated, but sorbet implements covariant tuples for
|
||||
# ease of adoption.
|
||||
@types.size == other.types.size && @types.zip(other.types).all? do |t1, t2|
|
||||
types.size == other.types.size && types.zip(other.types).all? do |t1, t2|
|
||||
t1.subtype_of?(t2)
|
||||
end
|
||||
when TypedArray
|
||||
@ -85,7 +92,7 @@ module T::Types
|
||||
# overrides Base
|
||||
def describe_obj(obj)
|
||||
if obj.is_a?(Array)
|
||||
if obj.length == @types.length
|
||||
if obj.length == types.length
|
||||
item_classes = obj.map(&:class).join(', ')
|
||||
"type [#{item_classes}]"
|
||||
else
|
@ -5,30 +5,37 @@ module T::Types
|
||||
# Takes a hash of types. Validates each item in a hash using the type in the same position
|
||||
# in the list.
|
||||
class FixedHash < Base
|
||||
attr_reader :types
|
||||
|
||||
def initialize(types)
|
||||
@types = types.transform_values {|v| T::Utils.coerce(v)}
|
||||
@inner_types = types
|
||||
end
|
||||
|
||||
def types
|
||||
@types ||= @inner_types.transform_values {|v| T::Utils.coerce(v)}
|
||||
end
|
||||
|
||||
def build_type
|
||||
types
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
serialize_hash(@types)
|
||||
serialize_hash(types)
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def recursively_valid?(obj)
|
||||
return false unless obj.is_a?(Hash)
|
||||
return false if @types.any? {|key, type| !type.recursively_valid?(obj[key])}
|
||||
return false if obj.any? {|key, _| !@types[key]}
|
||||
return false if types.any? {|key, type| !type.recursively_valid?(obj[key])}
|
||||
return false if obj.any? {|key, _| !types[key]}
|
||||
true
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def valid?(obj)
|
||||
return false unless obj.is_a?(Hash)
|
||||
return false if @types.any? {|key, type| !type.valid?(obj[key])}
|
||||
return false if obj.any? {|key, _| !@types[key]}
|
||||
return false if types.any? {|key, type| !type.valid?(obj[key])}
|
||||
return false if obj.any? {|key, _| !types[key]}
|
||||
true
|
||||
end
|
||||
|
||||
@ -37,7 +44,7 @@ module T::Types
|
||||
case other
|
||||
when FixedHash
|
||||
# Using `subtype_of?` here instead of == would be unsound
|
||||
@types == other.types
|
||||
types == other.types
|
||||
when TypedHash
|
||||
# warning: covariant hashes
|
||||
|
@ -4,10 +4,12 @@
|
||||
module T::Types
|
||||
# Takes a list of types. Validates that an object matches all of the types.
|
||||
class Intersection < Base
|
||||
attr_reader :types
|
||||
|
||||
def initialize(types)
|
||||
@types = types.flat_map do |type|
|
||||
@inner_types = types
|
||||
end
|
||||
|
||||
def types
|
||||
@types ||= @inner_types.flat_map do |type|
|
||||
type = T::Utils.resolve_alias(type)
|
||||
if type.is_a?(Intersection)
|
||||
# Simplify nested intersections (mostly so `name` returns a nicer value)
|
||||
@ -18,19 +20,24 @@ module T::Types
|
||||
end.uniq
|
||||
end
|
||||
|
||||
def build_type
|
||||
types
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"T.all(#{@types.map(&:name).compact.sort.join(', ')})"
|
||||
"T.all(#{types.map(&:name).compact.sort.join(', ')})"
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def recursively_valid?(obj)
|
||||
@types.all? {|type| type.recursively_valid?(obj)}
|
||||
types.all? {|type| type.recursively_valid?(obj)}
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def valid?(obj)
|
||||
@types.all? {|type| type.valid?(obj)}
|
||||
types.all? {|type| type.valid?(obj)}
|
||||
end
|
||||
|
||||
# overrides Base
|
@ -6,6 +6,10 @@ module T::Types
|
||||
class NoReturn < Base
|
||||
def initialize; end
|
||||
|
||||
def build_type
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"T.noreturn"
|
@ -8,21 +8,31 @@ module T::Types
|
||||
# At present, we only support fixed-arity procs with no optional or
|
||||
# keyword arguments.
|
||||
class Proc < Base
|
||||
attr_reader :arg_types
|
||||
attr_reader :returns
|
||||
|
||||
def initialize(arg_types, returns)
|
||||
@arg_types = {}
|
||||
arg_types.each do |key, raw_type|
|
||||
@arg_types[key] = T::Utils.coerce(raw_type)
|
||||
end
|
||||
@returns = T::Utils.coerce(returns)
|
||||
@inner_arg_types = arg_types
|
||||
@inner_returns = returns
|
||||
end
|
||||
|
||||
def arg_types
|
||||
@arg_types ||= @inner_arg_types.map do |key, raw_type|
|
||||
[key, T::Utils.coerce(raw_type)]
|
||||
end.to_h
|
||||
end
|
||||
|
||||
def returns
|
||||
@returns ||= T::Utils.coerce(@inner_returns)
|
||||
end
|
||||
|
||||
def build_type
|
||||
arg_types
|
||||
returns
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
args = []
|
||||
@arg_types.each do |k, v|
|
||||
arg_types.each do |k, v|
|
||||
args << "#{k}: #{v.name}"
|
||||
end
|
||||
"T.proc.params(#{args.join(', ')}).returns(#{returns})"
|
@ -8,6 +8,10 @@ module T::Types
|
||||
|
||||
def initialize(); end
|
||||
|
||||
def build_type
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"T.self_type"
|
@ -13,6 +13,10 @@ module T::Types
|
||||
@raw_type = raw_type
|
||||
end
|
||||
|
||||
def build_type
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
# Memoize to mitigate pathological performance with anonymous modules (https://bugs.ruby-lang.org/issues/11119)
|
@ -10,6 +10,10 @@ module T::Types
|
||||
@val = val
|
||||
end
|
||||
|
||||
def build_type
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
# Strips the #<...> off, just leaving the ...
|
@ -20,6 +20,10 @@ module T::Types
|
||||
@name = name
|
||||
end
|
||||
|
||||
def build_type
|
||||
nil
|
||||
end
|
||||
|
||||
def self.make(name)
|
||||
cached = Private.cached_entry(name)
|
||||
return cached if cached
|
@ -19,6 +19,10 @@ module T::Types
|
||||
@variance = variance
|
||||
end
|
||||
|
||||
def build_type
|
||||
nil
|
||||
end
|
||||
|
||||
def valid?(obj)
|
||||
true
|
||||
end
|
@ -5,7 +5,7 @@ module T::Types
|
||||
class TypedArray < TypedEnumerable
|
||||
# overrides Base
|
||||
def name
|
||||
"T::Array[#{@type.name}]"
|
||||
"T::Array[#{type.name}]"
|
||||
end
|
||||
|
||||
def underlying_class
|
||||
@ -60,6 +60,11 @@ module T::Types
|
||||
obj.is_a?(Array)
|
||||
end
|
||||
|
||||
def freeze
|
||||
build_type # force lazy initialization before freezing the object
|
||||
super
|
||||
end
|
||||
|
||||
module Private
|
||||
INSTANCE = Untyped.new.freeze
|
||||
end
|
@ -3,15 +3,22 @@
|
||||
|
||||
module T::Types
|
||||
class TypedClass < T::Types::Base
|
||||
attr_reader :type
|
||||
|
||||
def initialize(type)
|
||||
@type = T::Utils.coerce(type)
|
||||
@inner_type = type
|
||||
end
|
||||
|
||||
def type
|
||||
@type ||= T::Utils.coerce(@inner_type)
|
||||
end
|
||||
|
||||
def build_type
|
||||
type
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"T::Class[#{@type.name}]"
|
||||
"T::Class[#{type.name}]"
|
||||
end
|
||||
|
||||
def underlying_class
|
||||
@ -67,6 +74,11 @@ module T::Types
|
||||
super(T.untyped)
|
||||
end
|
||||
|
||||
def freeze
|
||||
build_type # force lazy initialization before freezing the object
|
||||
super
|
||||
end
|
||||
|
||||
module Private
|
||||
INSTANCE = Untyped.new.freeze
|
||||
end
|
||||
@ -77,6 +89,11 @@ module T::Types
|
||||
super(T.anything)
|
||||
end
|
||||
|
||||
def freeze
|
||||
build_type # force lazy initialization before freezing the object
|
||||
super
|
||||
end
|
||||
|
||||
module Private
|
||||
INSTANCE = Anything.new.freeze
|
||||
end
|
@ -6,10 +6,17 @@ module T::Types
|
||||
# `case` statement below in `describe_obj` in order to get better
|
||||
# error messages.
|
||||
class TypedEnumerable < Base
|
||||
attr_reader :type
|
||||
|
||||
def initialize(type)
|
||||
@type = T::Utils.coerce(type)
|
||||
@inner_type = type
|
||||
end
|
||||
|
||||
def type
|
||||
@type ||= T::Utils.coerce(@inner_type)
|
||||
end
|
||||
|
||||
def build_type
|
||||
type
|
||||
nil
|
||||
end
|
||||
|
||||
def underlying_class
|
||||
@ -18,7 +25,7 @@ module T::Types
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"T::Enumerable[#{@type.name}]"
|
||||
"T::Enumerable[#{type.name}]"
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
@ -34,20 +41,20 @@ module T::Types
|
||||
begin
|
||||
it = 0
|
||||
while it < obj.count
|
||||
return false unless @type.recursively_valid?(obj[it])
|
||||
return false unless type.recursively_valid?(obj[it])
|
||||
it += 1
|
||||
end
|
||||
true
|
||||
end
|
||||
when Hash
|
||||
return false unless @type.is_a?(FixedArray)
|
||||
types = @type.types
|
||||
return false unless type.is_a?(FixedArray)
|
||||
types = type.types
|
||||
return false if types.count != 2
|
||||
key_type = types[0]
|
||||
value_type = types[1]
|
||||
obj.each_pair do |key, val|
|
||||
# Some objects (I'm looking at you Rack::Utils::HeaderHash) don't
|
||||
# iterate over a [key, value] array, so we can't juse use the @type.recursively_valid?(v)
|
||||
# iterate over a [key, value] array, so we can't just use the type.recursively_valid?(v)
|
||||
return false if !key_type.recursively_valid?(key) || !value_type.recursively_valid?(val)
|
||||
end
|
||||
true
|
||||
@ -65,10 +72,10 @@ module T::Types
|
||||
# boundlessness, it does not express a type. For example `(nil...nil)` is not a T::Range[NilClass], its a range
|
||||
# of unknown types (T::Range[T.untyped]).
|
||||
# Similarly, `(nil...1)` is not a `T::Range[T.nilable(Integer)]`, it's a boundless range of Integer.
|
||||
(obj.begin.nil? || @type.recursively_valid?(obj.begin)) && (obj.end.nil? || @type.recursively_valid?(obj.end))
|
||||
(obj.begin.nil? || type.recursively_valid?(obj.begin)) && (obj.end.nil? || type.recursively_valid?(obj.end))
|
||||
when Set
|
||||
obj.each do |item|
|
||||
return false unless @type.recursively_valid?(item)
|
||||
return false unless type.recursively_valid?(item)
|
||||
end
|
||||
|
||||
true
|
||||
@ -90,7 +97,7 @@ module T::Types
|
||||
# should be invariant because they are mutable and support
|
||||
# both reading and writing. However, Sorbet treats *all*
|
||||
# Enumerable subclasses as covariant for ease of adoption.
|
||||
@type.subtype_of?(other.type)
|
||||
type.subtype_of?(other.type)
|
||||
elsif other.class <= Simple
|
||||
underlying_class <= other.raw_type
|
||||
else
|
@ -3,15 +3,13 @@
|
||||
|
||||
module T::Types
|
||||
class TypedEnumerator < TypedEnumerable
|
||||
attr_reader :type
|
||||
|
||||
def underlying_class
|
||||
Enumerator
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"T::Enumerator[#{@type.name}]"
|
||||
"T::Enumerator[#{type.name}]"
|
||||
end
|
||||
|
||||
# overrides Base
|
@ -3,15 +3,13 @@
|
||||
|
||||
module T::Types
|
||||
class TypedEnumeratorChain < TypedEnumerable
|
||||
attr_reader :type
|
||||
|
||||
def underlying_class
|
||||
Enumerator::Chain
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"T::Enumerator::Chain[#{@type.name}]"
|
||||
"T::Enumerator::Chain[#{type.name}]"
|
||||
end
|
||||
|
||||
# overrides Base
|
@ -3,15 +3,13 @@
|
||||
|
||||
module T::Types
|
||||
class TypedEnumeratorLazy < TypedEnumerable
|
||||
attr_reader :type
|
||||
|
||||
def underlying_class
|
||||
Enumerator::Lazy
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"T::Enumerator::Lazy[#{@type.name}]"
|
||||
"T::Enumerator::Lazy[#{type.name}]"
|
||||
end
|
||||
|
||||
# overrides Base
|
@ -3,22 +3,32 @@
|
||||
|
||||
module T::Types
|
||||
class TypedHash < TypedEnumerable
|
||||
# Technically we don't need these, but they are a nice api
|
||||
attr_reader :keys, :values
|
||||
|
||||
def underlying_class
|
||||
Hash
|
||||
end
|
||||
|
||||
def initialize(keys:, values:)
|
||||
@keys = T::Utils.coerce(keys)
|
||||
@values = T::Utils.coerce(values)
|
||||
@type = T::Utils.coerce([keys, values])
|
||||
@inner_keys = keys
|
||||
@inner_values = values
|
||||
end
|
||||
|
||||
# Technically we don't need this, but it is a nice api
|
||||
def keys
|
||||
@keys ||= T::Utils.coerce(@inner_keys)
|
||||
end
|
||||
|
||||
# Technically we don't need this, but it is a nice api
|
||||
def values
|
||||
@values ||= T::Utils.coerce(@inner_values)
|
||||
end
|
||||
|
||||
def type
|
||||
@type ||= T::Utils.coerce([keys, values])
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"T::Hash[#{@keys.name}, #{@values.name}]"
|
||||
"T::Hash[#{keys.name}, #{values.name}]"
|
||||
end
|
||||
|
||||
# overrides Base
|
@ -3,15 +3,13 @@
|
||||
|
||||
module T::Types
|
||||
class TypedRange < TypedEnumerable
|
||||
attr_reader :type
|
||||
|
||||
def underlying_class
|
||||
Hash
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"T::Range[#{@type.name}]"
|
||||
"T::Range[#{type.name}]"
|
||||
end
|
||||
|
||||
# overrides Base
|
@ -3,15 +3,13 @@
|
||||
|
||||
module T::Types
|
||||
class TypedSet < TypedEnumerable
|
||||
attr_reader :type
|
||||
|
||||
def underlying_class
|
||||
Hash
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"T::Set[#{@type.name}]"
|
||||
"T::Set[#{type.name}]"
|
||||
end
|
||||
|
||||
# overrides Base
|
@ -4,12 +4,14 @@
|
||||
module T::Types
|
||||
# Takes a list of types. Validates that an object matches at least one of the types.
|
||||
class Union < Base
|
||||
attr_reader :types
|
||||
|
||||
# Don't use Union.new directly, use `Private::Pool.union_of_types`
|
||||
# inside sorbet-runtime and `T.any` elsewhere.
|
||||
def initialize(types)
|
||||
@types = types.flat_map do |type|
|
||||
@inner_types = types
|
||||
end
|
||||
|
||||
def types
|
||||
@types ||= @inner_types.flat_map do |type|
|
||||
type = T::Utils.coerce(type)
|
||||
if type.is_a?(Union)
|
||||
# Simplify nested unions (mostly so `name` returns a nicer value)
|
||||
@ -20,6 +22,11 @@ module T::Types
|
||||
end.uniq
|
||||
end
|
||||
|
||||
def build_type
|
||||
types
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
# Use the attr_reader here so we can override it in SimplePairUnion
|
||||
@ -51,12 +58,12 @@ module T::Types
|
||||
|
||||
# overrides Base
|
||||
def recursively_valid?(obj)
|
||||
@types.any? {|type| type.recursively_valid?(obj)}
|
||||
types.any? {|type| type.recursively_valid?(obj)}
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def valid?(obj)
|
||||
@types.any? {|type| type.valid?(obj)}
|
||||
types.any? {|type| type.valid?(obj)}
|
||||
end
|
||||
|
||||
# overrides Base
|
@ -7,6 +7,10 @@ module T::Types
|
||||
|
||||
def initialize; end
|
||||
|
||||
def build_type
|
||||
nil
|
||||
end
|
||||
|
||||
# overrides Base
|
||||
def name
|
||||
"T.untyped"
|
@ -79,8 +79,8 @@ module T::Utils
|
||||
end
|
||||
|
||||
# Unwraps all the sigs.
|
||||
def self.run_all_sig_blocks
|
||||
T::Private::Methods.run_all_sig_blocks
|
||||
def self.run_all_sig_blocks(force_type_init: true)
|
||||
T::Private::Methods.run_all_sig_blocks(force_type_init: force_type_init)
|
||||
end
|
||||
|
||||
# Return the underlying type for a type alias. Otherwise returns type.
|
Loading…
x
Reference in New Issue
Block a user