Skip to content

Commit 994d158

Browse files
authored
Merge pull request #2701 from Hashim1999164/fix/skip-deprecation-proxies-in-dsl-discovery
Skip ActiveSupport deprecation proxies when gathering DSL constants
2 parents d029cc9 + 276df70 commit 994d158

2 files changed

Lines changed: 36 additions & 1 deletion

File tree

lib/tapioca/dsl/compiler.rb

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,21 @@ def all_modules
7474
@all_modules ||= if @@requested_constants.any?
7575
@@requested_constants.grep(Module)
7676
else
77-
ObjectSpace.each_object(Module).to_a
77+
ObjectSpace.each_object(Module).reject { |mod| deprecated_constant_proxy?(mod) }.to_a
7878
end.freeze #: Enumerable[Module[top]]?
7979
end
80+
81+
# Rails 8.1+ wraps deprecated constants in DeprecatedConstantProxy, which
82+
# undefines most instance methods and warns from method_missing. Inspecting
83+
# those modules during DSL discovery (is_a?, singleton_class, etc.) emits
84+
# deprecation warnings even though Tapioca is only enumerating ObjectSpace.
85+
# class_of uses Kernel#class so we can recognize the proxy without warning.
86+
#: (Module[top] mod) -> bool
87+
def deprecated_constant_proxy?(mod)
88+
proxy_class_name = name_of(class_of(mod))
89+
proxy_class_name == "ActiveSupport::Deprecation::DeprecatedConstantProxy" ||
90+
proxy_class_name == "ActiveSupport::DeprecatedConstantProxy"
91+
end
8092
end
8193

8294
#: (

spec/tapioca/dsl/compilers/active_support_concern_spec.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,29 @@ def before_setup
1414
end
1515

1616
describe "gather_constants" do
17+
it "does not gather ActiveSupport deprecation proxies and does not warn" do
18+
warnings = []
19+
previous_behavior = ActiveSupport.deprecator.behavior
20+
ActiveSupport.deprecator.behavior = ->(message, *) { warnings << message.to_s }
21+
22+
begin
23+
proxy = ActiveSupport::Deprecation::DeprecatedConstantProxy.new(
24+
"FakeDeprecatedConstant",
25+
"Module",
26+
ActiveSupport.deprecator,
27+
)
28+
# Name the proxy so discovery can trigger its warning.
29+
ActiveSupportConcernSpec.const_set(:FakeDeprecatedConstant, proxy)
30+
gathered_constants
31+
all_modules = Tapioca::Dsl::Compilers::ActiveSupportConcern.send(:all_modules)
32+
ensure
33+
ActiveSupport.deprecator.behavior = previous_behavior
34+
end
35+
36+
refute(all_modules.any? { |mod| Tapioca::Runtime::Reflection.are_equal?(mod, proxy) })
37+
assert_empty(warnings.grep(/FakeDeprecatedConstant/))
38+
end
39+
1740
it "does not gather anonymous constants" do
1841
add_ruby_file("test_case.rb", <<~RUBY)
1942
module TestCase

0 commit comments

Comments
 (0)