-
Notifications
You must be signed in to change notification settings - Fork 211
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support class redefinitions in runtime for rbs test mode #1636
Comments
@HoneyryderChuck Thank you for reporting the problem. Hmm, I also wonder if @ksss has any idea about this? |
It is possible to hook |
I couldn't find narrow down the smallest possible reproduction, unfortunately. The error can be reproduced with httpx integration, test suite, as |
@HoneyryderChuck When If we can hook into For a makeshift solution, you could do something like the following, which should work for now: diff --git a/lib/rbs/test/observer.rb b/lib/rbs/test/observer.rb
index ff023871..05cc0394 100644
--- a/lib/rbs/test/observer.rb
+++ b/lib/rbs/test/observer.rb
@@ -13,6 +13,10 @@ module RBS
def register(key, object = nil, &block)
@@observers[key] = object || block
end
+
+ def observers
+ @@observers
+ end
end
end
end
diff --git a/lib/rbs/test/setup.rb b/lib/rbs/test/setup.rb
index 1a8041c9..16c30e47 100644
--- a/lib/rbs/test/setup.rb
+++ b/lib/rbs/test/setup.rb
@@ -75,6 +75,21 @@ TracePoint.trace :end do |tp|
end
end
+hook = Module.new{
+ def remove_const(name)
+ super
+ end
+}
+Module.prepend(hook)
+
+TracePoint.new(:call) do |tp|
+ name = tp.binding.local_variable_get(:name)
+ type_name = TypeName("::#{tp.self}::#{name}")
+ RBS::Test::Observer.observers.values.each do |method_call_tester|
+ method_call_tester.check.const_cache.delete(type_name)
+ end
+end.enable(target: hook.instance_method(:remove_const))
+
at_exit do
if $!.nil? || $!.is_a?(SystemExit) && $!.success?
if tester.targets.empty? Alternatively, a very simple fix would be to just stop caching. diff --git a/lib/rbs/test/type_check.rb b/lib/rbs/test/type_check.rb
index ac0edbc3..6ed8d134 100644
--- a/lib/rbs/test/type_check.rb
+++ b/lib/rbs/test/type_check.rb
@@ -208,11 +208,9 @@ module RBS
end
def get_class(type_name)
- const_cache[type_name] ||= begin
- Object.const_get(type_name.to_s)
- rescue NameError
- nil
- end
+ Object.const_get(type_name.to_s)
+ rescue NameError
+ nil
end
def is_double?(value) @soutaro How about this? |
Disable the caching! Seems like there were no strong reason to introduce it... #356 |
I'll send PR soon. |
Thx everyone |
When used in "test mode" (via
rbs/setup
) for runtime type checking,rbs
is not able to verify when a class is redefined, such as whenremove_const
andconst_set
are used. These are used in certain monkey-patching scenarios, and are common enough to warrant specialized support.As an example, webmock uses it to apply monkey-patching to practically all supported http clients (this is for net-http, but everything else works the same way).
When used in such cases, runtime type checking will fail if webmock is disabled-and-enabled-again across tests, where the Net::HTTP class stored in the definition builder will fail to match against a just-redefined instance of Net::HTTP. Given that
rbs/setup
was designed to be used in tests, andwebmock
is the most widely used http client mock library, there should be some level of support for this.I've done my research, and I see that
rbs/setup
uses the Tracepoint API to track class definitions and hooking them up with the type definitions. Sadly, there seems not to have a tracepoint hook for remove_const and const_set. Is this something that needs to be done at the tracepoint level first?The text was updated successfully, but these errors were encountered: