Skip to content

Commit

Permalink
Merge pull request #1591 from ksss/runtime-constants
Browse files Browse the repository at this point in the history
Support cases where `Module#constants` has been redefined
  • Loading branch information
soutaro authored Nov 1, 2023
2 parents ff0f38c + 908c57f commit 3e5c12c
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require: rubocop-rubycw
AllCops:
TargetRubyVersion: 2.7
TargetRubyVersion: 3.0
DisabledByDefault: true
Exclude:
- 'vendor/bundle/**/*'
Expand Down
16 changes: 6 additions & 10 deletions lib/rbs/prototype/runtime.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

require_relative 'runtime/helpers'
require_relative 'runtime/value_object_generator'
require_relative 'runtime/reflection'

module RBS
module Prototype
Expand Down Expand Up @@ -422,7 +423,7 @@ def generate_methods(mod, module_name, members)

def generate_constants(mod, decls)
module_name = const_name!(mod)
mod.constants(false).sort.each do |name|
Reflection.constants_of(mod, false).sort.each do |name|
next if todo_object&.skip_constant?(module_name: module_name, name: name)

begin
Expand All @@ -432,10 +433,10 @@ def generate_constants(mod, decls)
next
end

next if object_class(value).equal?(Class)
next if object_class(value).equal?(Module)
next if Reflection.object_class(value).equal?(Class)
next if Reflection.object_class(value).equal?(Module)

unless object_class(value).name
unless Reflection.object_class(value).name
RBS.logger.warn("Skipping constant #{name} #{value} of #{mod} as an instance of anonymous class")
next
end
Expand All @@ -453,7 +454,7 @@ def generate_constants(mod, decls)
when ENV
Types::ClassInstance.new(name: TypeName("::RBS::Unnamed::ENVClass"), args: [], location: nil)
else
value_type_name = to_type_name(const_name!(object_class(value)), full_name: true).absolute!
value_type_name = to_type_name(const_name!(Reflection.object_class(value)), full_name: true).absolute!
args = type_args(value_type_name)
Types::ClassInstance.new(name: value_type_name, args: args, location: nil)
end
Expand Down Expand Up @@ -631,11 +632,6 @@ def ensure_outer_module_declarations(mod)
destination
end

def object_class(value)
@object_class ||= Object.instance_method(:class)
@object_class.bind_call(value)
end

def type_args(type_name)
if class_decl = env.class_decls.fetch(type_name.absolute!, nil)
class_decl.type_params.size.times.map { Types::Bases::Any.new(location: nil) }
Expand Down
19 changes: 19 additions & 0 deletions lib/rbs/prototype/runtime/reflection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

module RBS
module Prototype
class Runtime
module Reflection
def self.object_class(value)
@object_class ||= Object.instance_method(:class)
@object_class.bind_call(value)
end

def self.constants_of(mod, inherit = true)
@constants_of ||= Module.instance_method(:constants)
@constants_of.bind_call(mod, inherit)
end
end
end
end
end
6 changes: 6 additions & 0 deletions sig/prototype/runtime.rbs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
module RBS
module Prototype
class Runtime
module Reflection
def self.object_class: (Module value) -> Class

def self.constants_of: (Module mod, ?bool inherit) -> Array[Symbol]
end

module Helpers
private

Expand Down
26 changes: 26 additions & 0 deletions test/rbs/runtime_prototype_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -931,4 +931,30 @@ class DataDirectInherit < ::Data
end
end
end

class Redefined
def self.constants = raise
def class = raise
end

def test_reflection
SignatureManager.new do |manager|
manager.build do |env|
p = Runtime.new(patterns: ["RBS::RuntimePrototypeTest::Redefined"], env: env, merge: false)
assert_write p.decls, <<~RBS
module RBS
class RuntimePrototypeTest < ::Test::Unit::TestCase
class Redefined
def self.constants: () -> untyped
public
def class: () -> untyped
end
end
end
RBS
end
end
end
end

0 comments on commit 3e5c12c

Please sign in to comment.