module IRB::TypeCompletion::Types
Constants
- OBJECT_TO_TYPE_SAMPLE_SIZE
Attributes
rbs_builder[R]
rbs_load_error[R]
Public Class Methods
class_name_of(klass)
click to toggle source
# File irb/type_completion/types.rb, line 32 def self.class_name_of(klass) klass = klass.superclass if klass.singleton_class? Methods::MODULE_NAME_METHOD.bind_call klass end
intersect?(a, b)
click to toggle source
# File irb/type_completion/types.rb, line 123 def self.intersect?(a, b) atypes = a.types.group_by(&:class) btypes = b.types.group_by(&:class) if atypes[SingletonType] && btypes[SingletonType] aa, bb = [atypes, btypes].map {|types| types[SingletonType].map(&:module_or_class) } return true if (aa & bb).any? end aa, bb = [atypes, btypes].map {|types| (types[InstanceType] || []).map(&:klass) } (aa.flat_map(&:ancestors) & bb).any? end
load_rbs_builder()
click to toggle source
# File irb/type_completion/types.rb, line 21 def self.load_rbs_builder require 'rbs' require 'rbs/cli' loader = RBS::CLI::LibraryOptions.new.loader loader.add path: Pathname('sig') @rbs_builder = RBS::DefinitionBuilder.new env: RBS::Environment.from_loader(loader).resolve_type_names rescue LoadError, StandardError => e @rbs_load_error = e nil end
method_return_type(type, method_name)
click to toggle source
# File irb/type_completion/types.rb, line 49 def self.method_return_type(type, method_name) receivers = type.types.map do |t| case t in SingletonType [t, t.module_or_class, true] in InstanceType [t, t.klass, false] end end types = receivers.flat_map do |receiver_type, klass, singleton| method = rbs_search_method klass, method_name, singleton next [] unless method method.method_types.map do |method| from_rbs_type(method.type.return_type, receiver_type, {}) end end UnionType[*types] end
preload_in_thread()
click to toggle source
# File irb/type_completion/types.rb, line 12 def self.preload_in_thread return if @preload_started @preload_started = true Thread.new do load_rbs_builder end end
rbs_methods(type, method_name, args_types, kwargs_type, has_block)
click to toggle source
# File irb/type_completion/types.rb, line 68 def self.rbs_methods(type, method_name, args_types, kwargs_type, has_block) return [] unless rbs_builder receivers = type.types.map do |t| case t in SingletonType [t, t.module_or_class, true] in InstanceType [t, t.klass, false] end end has_splat = args_types.include?(nil) methods_with_score = receivers.flat_map do |receiver_type, klass, singleton| method = rbs_search_method klass, method_name, singleton next [] unless method method.method_types.map do |method_type| score = 0 score += 2 if !!method_type.block == has_block reqs = method_type.type.required_positionals opts = method_type.type.optional_positionals rest = method_type.type.rest_positionals trailings = method_type.type.trailing_positionals keyreqs = method_type.type.required_keywords keyopts = method_type.type.optional_keywords keyrest = method_type.type.rest_keywords args = args_types if kwargs_type&.any? && keyreqs.empty? && keyopts.empty? && keyrest.nil? kw_value_type = UnionType[*kwargs_type.values] args += [InstanceType.new(Hash, K: SYMBOL, V: kw_value_type)] end if has_splat score += 1 if args.count(&:itself) <= reqs.size + opts.size + trailings.size elsif reqs.size + trailings.size <= args.size && (rest || args.size <= reqs.size + opts.size + trailings.size) score += 2 centers = args[reqs.size...-trailings.size] given = args.first(reqs.size) + centers.take(opts.size) + args.last(trailings.size) expected = (reqs + opts.take(centers.size) + trailings).map(&:type) if rest given << UnionType[*centers.drop(opts.size)] expected << rest.type end if given.any? score += given.zip(expected).count do |t, e| e = from_rbs_type e, receiver_type intersect?(t, e) || (intersect?(STRING, e) && t.methods.include?(:to_str)) || (intersect?(INTEGER, e) && t.methods.include?(:to_int)) || (intersect?(ARRAY, e) && t.methods.include?(:to_ary)) end.fdiv(given.size) end end [[method_type, given || [], expected || []], score] end end max_score = methods_with_score.map(&:last).max methods_with_score.select { _2 == max_score }.map(&:first) end
rbs_search_method(klass, method_name, singleton)
click to toggle source
# File irb/type_completion/types.rb, line 37 def self.rbs_search_method(klass, method_name, singleton) klass.ancestors.each do |ancestor| name = class_name_of ancestor next unless name && rbs_builder type_name = RBS::TypeName(name).absolute! definition = (singleton ? rbs_builder.build_singleton(type_name) : rbs_builder.build_instance(type_name)) rescue nil method = definition.methods[method_name] if definition return method if method end nil end
type_from_object(object)
click to toggle source
# File irb/type_completion/types.rb, line 135 def self.type_from_object(object) case object when Array InstanceType.new Array, { Elem: union_type_from_objects(object) } when Hash InstanceType.new Hash, { K: union_type_from_objects(object.keys), V: union_type_from_objects(object.values) } when Module SingletonType.new object else klass = Methods::OBJECT_SINGLETON_CLASS_METHOD.bind_call(object) rescue Methods::OBJECT_CLASS_METHOD.bind_call(object) InstanceType.new klass end end
union_type_from_objects(objects)
click to toggle source
# File irb/type_completion/types.rb, line 149 def self.union_type_from_objects(objects) values = objects.size <= OBJECT_TO_TYPE_SAMPLE_SIZE ? objects : objects.sample(OBJECT_TO_TYPE_SAMPLE_SIZE) klasses = values.map { Methods::OBJECT_CLASS_METHOD.bind_call(_1) } UnionType[*klasses.uniq.map { InstanceType.new _1 }] end