module Tapioca::Runtime::Reflection
def abstract_type_of(constant)
def abstract_type_of(constant) T::Private::Abstract::Data.get(constant, :abstract_type) || T::Private::Abstract::Data.get(singleton_class_of(constant), :abstract_type) end
def ancestors_of(constant)
def ancestors_of(constant) ANCESTORS_METHOD.bind_call(constant) end
def are_equal?(object, other)
def are_equal?(object, other) EQUAL_METHOD.bind_call(object, other) end
def child_module_for_parent_with_name(parent, name)
def child_module_for_parent_with_name(parent, name) return if parent.autoload?(name) child = constantize(name, inherit: true, namespace: parent) return unless Module === child return unless name_of(child) == "#{name_of(parent)}::#{name}" child end
def class_of(object)
def class_of(object) CLASS_METHOD.bind_call(object) end
def constant_defined?(constant)
def constant_defined?(constant) !UNDEFINED_CONSTANT.eql?(constant) end
def constantize(symbol, inherit: false, namespace: Object)
def constantize(symbol, inherit: false, namespace: Object) namespace.const_get(symbol, inherit) rescue NameError, LoadError, RuntimeError, ArgumentError, TypeError UNDEFINED_CONSTANT end
def constants_of(constant)
def constants_of(constant) CONSTANTS_METHOD.bind_call(constant, false) end
def descendants_of(klass)
def descendants_of(klass) result = ObjectSpace.each_object(klass.singleton_class).reject do |k| k.singleton_class? || k == klass end T.unsafe(result) end
def file_candidates_for(constant)
def file_candidates_for(constant) relevant_methods_for(constant).filter_map do |method| method.source_location&.first end.to_set end
def final_module?(constant)
def final_module?(constant) T::Private::Final.final_module?(constant) end
def has_aliased_namespace?(name)
def has_aliased_namespace?(name) name_parts = name.split("::") name_parts.pop # drop the constant name, leaving just the namespace name_parts.each_with_object([]) do |name_part, namespaces| namespaces << "#{namespaces.last}::#{name_part}".delete_prefix("::") end.any? do |namespace| constant = constantize(namespace) next unless Module === constant # If the constant name doesn't match the namespace, # the namespace must contain an alias name_of(constant) != namespace end end
def inherited_ancestors_of(constant)
def inherited_ancestors_of(constant) if Class === constant ancestors_of(superclass_of(constant) || Object) else Module.new.ancestors end end
def method_defined_by_forwardable_module?(method)
def method_defined_by_forwardable_module?(method) method.source_location&.first == Object.const_source_location(:Forwardable)&.first end
def method_of(constant, method)
def method_of(constant, method) METHOD_METHOD.bind_call(constant, method) end
def methods_for(constant)
def methods_for(constant) modules = [constant, singleton_class_of(constant)] method_list_methods = [ PUBLIC_INSTANCE_METHODS_METHOD, PROTECTED_INSTANCE_METHODS_METHOD, PRIVATE_INSTANCE_METHODS_METHOD, ] modules.product(method_list_methods).flat_map do |mod, method_list_method| method_list_method.bind_call(mod, false).map { |name| mod.instance_method(name) } end end
def name_of(constant)
def name_of(constant) name = NAME_METHOD.bind_call(constant) name&.start_with?("#<") ? nil : name end
def name_of_type(type)
def name_of_type(type) type.to_s end
def object_id_of(object)
def object_id_of(object) OBJECT_ID_METHOD.bind_call(object) end
def private_instance_methods_of(constant)
def private_instance_methods_of(constant) PRIVATE_INSTANCE_METHODS_METHOD.bind_call(constant) end
def protected_instance_methods_of(constant)
def protected_instance_methods_of(constant) PROTECTED_INSTANCE_METHODS_METHOD.bind_call(constant) end
def public_instance_methods_of(constant)
def public_instance_methods_of(constant) PUBLIC_INSTANCE_METHODS_METHOD.bind_call(constant) end
def qualified_name_of(constant)
def qualified_name_of(constant) name = name_of(constant) return if name.nil? if name.start_with?("::") name else "::#{name}" end end
def relevant_methods_for(constant)
def relevant_methods_for(constant) methods = methods_for(constant).select(&:source_location) .reject { |x| method_defined_by_forwardable_module?(x) } return methods unless methods.empty? constants_of(constant).flat_map do |const_name| if (mod = child_module_for_parent_with_name(constant, const_name.to_s)) relevant_methods_for(mod) else [] end end end
def resolve_loc(locations)
def resolve_loc(locations) return "" unless locations resolved_loc = locations.find do |loc| label = loc.label next unless label REQUIRED_FROM_LABELS.include?(label) || label.start_with?("block in <class:") end return "" unless resolved_loc resolved_loc.absolute_path || "" end
def sealed_module?(constant)
def sealed_module?(constant) T::Private::Sealed.sealed_module?(constant) end
def signature_of(method)
def signature_of(method) signature_of!(method) rescue LoadError, StandardError nil end
def signature_of!(method)
def signature_of!(method) T::Utils.signature_for_method(method) end
def singleton_class_of(constant)
def singleton_class_of(constant) SINGLETON_CLASS_METHOD.bind_call(constant) end
def superclass_of(constant)
def superclass_of(constant) SUPERCLASS_METHOD.bind_call(constant) end