File tree Expand file tree Collapse file tree 3 files changed +55
-0
lines changed
Expand file tree Collapse file tree 3 files changed +55
-0
lines changed Original file line number Diff line number Diff line change @@ -86,6 +86,8 @@ def full_name
8686 # The module or class this constant is an alias for
8787
8888 def is_alias_for
89+ @is_alias_for ||= find_alias_for
90+
8991 case @is_alias_for
9092 when String then
9193 found = @store . find_class_or_module @is_alias_for
@@ -96,6 +98,14 @@ def is_alias_for
9698 end
9799 end
98100
101+ # Find alias constant for a value.
102+ # This is used when the constant is parsed before the class or module defined in another file.
103+ # Note that module nesting information is lost, so constant lookup is inaccurate.
104+
105+ def find_alias_for
106+ parent . find_module_named ( value ) if value &.match? ( /\A (::)?([A-Z][A-Za-z0-9_]*)(::[A-Z][A-Za-z0-9_]*)*\z / )
107+ end
108+
99109 def inspect # :nodoc:
100110 "#<%s:0x%x %s::%s>" % [
101111 self . class , object_id ,
Original file line number Diff line number Diff line change @@ -439,6 +439,7 @@ def add_constant(constant)
439439 known . value = constant . value if
440440 known . value . nil? or known . value . strip . empty?
441441
442+ constant . parent = self
442443 known . is_alias_for ||= constant . is_alias_for
443444 else
444445 @constants_hash [ constant . name ] = constant
Original file line number Diff line number Diff line change @@ -1638,6 +1638,50 @@ class Bar; end
16381638 assert_equal 'Foo::C' , klass . find_module_named ( 'C' ) . full_name
16391639 end
16401640
1641+ def test_constant_alias_reverse_order
1642+ util_parser <<~RUBY
1643+ # Parsed first
1644+ class Foo
1645+ A = Bar
1646+ B = Foo::Bar
1647+ C = Baz
1648+ end
1649+
1650+ # Parsed later
1651+ class Foo
1652+ class Bar; end
1653+ end
1654+ class Baz; end
1655+ RUBY
1656+ klass = @top_level . classes . first
1657+ assert_equal 'Foo::Bar' , klass . find_constant_named ( 'A' ) . is_alias_for . full_name
1658+ assert_equal 'Foo::Bar' , klass . find_constant_named ( 'B' ) . is_alias_for . full_name
1659+ assert_equal 'Baz' , klass . find_constant_named ( 'C' ) . is_alias_for . full_name
1660+ end
1661+
1662+ def test_repeated_constant_alias
1663+ util_parser <<~RUBY
1664+ # Parsed first
1665+ class Foo
1666+ if cond
1667+ A = Bar
1668+ B = Baz
1669+ else
1670+ A = Bar
1671+ B = Baz
1672+ end
1673+ end
1674+
1675+ # Parsed later
1676+ class Baz
1677+ end
1678+ RUBY
1679+ klass = @top_level . classes . first
1680+ assert_equal 'Bar' , klass . find_constant_named ( 'A' ) . value
1681+ assert_nil klass . find_constant_named ( 'A' ) . is_alias_for
1682+ assert_equal 'Baz' , klass . find_constant_named ( 'B' ) . is_alias_for . full_name
1683+ end
1684+
16411685 def test_constant_with_singleton_class
16421686 omit if accept_legacy_bug?
16431687 util_parser <<~RUBY
You can’t perform that action at this time.
0 commit comments