lib/tapioca/runtime/reflection.rb in tapioca-0.8.3 vs lib/tapioca/runtime/reflection.rb in tapioca-0.9.0
- old
+ new
@@ -18,10 +18,12 @@
PUBLIC_INSTANCE_METHODS_METHOD = T.let(Module.instance_method(:public_instance_methods), UnboundMethod)
PROTECTED_INSTANCE_METHODS_METHOD = T.let(Module.instance_method(:protected_instance_methods), UnboundMethod)
PRIVATE_INSTANCE_METHODS_METHOD = T.let(Module.instance_method(:private_instance_methods), UnboundMethod)
METHOD_METHOD = T.let(Kernel.instance_method(:method), UnboundMethod)
+ REQUIRED_FROM_LABELS = T.let(["<top (required)>", "<main>"].freeze, T::Array[String])
+
sig do
params(
symbol: String,
inherit: T::Boolean,
namespace: Module
@@ -149,9 +151,34 @@
result = ObjectSpace.each_object(klass.singleton_class).reject do |k|
T.cast(k, Module).singleton_class? || T.unsafe(k) == klass
end
T.unsafe(result)
+ end
+
+ # Examines the call stack to identify the closest location where a "require" is performed
+ # by searching for the label "<top (required)>". If none is found, it returns the location
+ # labeled "<main>", which is the original call site.
+ sig { returns(String) }
+ def required_from_location
+ locations = Kernel.caller_locations
+ return "" unless locations
+
+ required_location = locations.find { |loc| REQUIRED_FROM_LABELS.include?(loc.label) }
+ return "" unless required_location
+
+ required_location.absolute_path || ""
+ end
+
+ sig { params(constant: Module).returns(T.nilable(String)) }
+ def constant_name_from_singleton_class(constant)
+ constant.to_s.match("#<Class:(.+)>")&.captures&.first
+ end
+
+ sig { params(constant: Module).returns(T.nilable(BasicObject)) }
+ def constant_from_singleton_class(constant)
+ constant_name = constant_name_from_singleton_class(constant)
+ constantize(constant_name) if constant_name
end
end
end
end