module ReplTypeCompletor::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 repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 55 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 repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 148 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 repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 26 def self.load_rbs_builder @load_started = true loader = RBS::CLI::LibraryOptions.new.loader sig_path = Pathname('sig') loader.add path: sig_path expanded_sig_path = sig_path.expand_path.to_s unless File.exist?('rbs_collection.yaml') # Load rbs signature from gems. This is a fallback when rbs_collection.yaml is not available. Gem.loaded_specs.values.each do |spec| gem_sig_path = File.expand_path("#{spec.gem_dir}/sig") loader.add(library: spec.name, version: spec.version) if Dir.exist?(gem_sig_path) && expanded_sig_path != gem_sig_path end end # Hack to make this thread priority lower, not to block the main thread. thread_pass_counter = 0 tracepoint = TracePoint.new(:call) do Thread.pass if ((thread_pass_counter += 1) % 10).zero? end tracepoint.enable do env = RBS::Environment.from_loader(loader) @rbs_builder = RBS::DefinitionBuilder.new env: env.resolve_type_names end rescue LoadError, StandardError => e @rbs_load_error = e nil end
method_return_type(type, method_name)
click to toggle source
# File repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 72 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_rbs_builder()
click to toggle source
# File repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 18 def self.preload_rbs_builder return if rbs_load_started? @load_started = true Thread.new do load_rbs_builder end end
rbs_load_started?()
click to toggle source
# File repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 14 def self.rbs_load_started? !!@load_started end
rbs_methods(type, method_name, args_types, kwargs_type, has_block)
click to toggle source
# File repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 91 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.filter_map do |method_type| next unless method_type.type.respond_to?(:required_positionals) 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 repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 60 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 repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 160 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 repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 174 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